Git Product home page Git Product logo

dice-notation-java's Introduction

Dice Notation Tools for Java

This project aims to make the dice notation readable by Java applications, and for this it offers both a model representing it and a parser which can instantiate the model from dice notation expressions.

Created on the late 70s for Dungeons & Dragons, the dice notation has become a standard on tabletop games as it allows generating random values in concrete distributions with the help of simple formulas such as '2d6+5', which means "roll two dice, add their values and then add the number five to the result".

With the pass of years it has evolved, and while it never underwent a formal standardization process a core set of rules is kept among all the variations, mostly representing dice in a format such as '1d6', and the use of algebra operations like addition and subtraction.

Its usefulness is very clear, it allows working with specific random values distributions. And while this is no feat for a machine, which has better tools for it, the aim of the project is not actually handling those distributions, but giving a way for applications to work with the same tools a board game would have.

Maven Central

Release docs Development docs

Release javadocs Development javadocs

Features

  • ANTLR4 grammar
  • Model for dice and dice notation, along classes to generate values from them
  • Parser to create model instances from the notation
  • Allows custom random number generation
  • Arithmetic operations (addition, subtraction, multiplication, integer division)
  • Parenthesis support

Limitations

  • Currently only the most basic operations (dice, numbers and additions or subtractions) are supported

ANTLR4 grammars

The grammar is included among the ANTLR4 sample grammars.

Related projects

Documentation

Documentation is always generated for the latest release, kept in the 'master' branch:

Documentation is also generated from the latest snapshot, taken from the 'develop' branch:

The documentation site sources come along the source code (as it is a Maven site), so it is always possible to generate them using the following Maven command:

mvn verify site

The verify phase is required, as otherwise some of the reports won't be created.

Usage

The application is coded in Java, using Maven to manage the project.

Prerequisites

JDK 8 or higher is required. All other dependencies are handled through Maven, and noted in the included POM file.

Installing

The recommended way to install the project is by setting it up as a dependency. To get the configuration information for this check the Maven Central Repository.

It is always possible installing it by using the usual Maven command:

mvn install

Usage example

The project includes model, BNF grammar and parsers, which allow working with the most common dice notation expressions.

You may parse an expression, and generate a random value, like this:

final DiceParser parser;
final RollHistory rolls;
final DiceInterpreter<RollHistory> roller;

parser = new DefaultDiceParser();
roller = new DiceRoller();

rolls = parser.parse("1d6+12", roller);

// Prints the final result
System.out.println(rolls.getTotalRoll());

For more examples and details check the docs.

Collaborate

Any kind of help with the project will be well received, and there are two main ways to give such help:

  • Reporting errors and asking for extensions through the issues management
  • or forking the repository and extending the project

Issues management

Issues are managed at the GitHub project issues tracker, where any Github user may report bugs or ask for new features.

Getting the code

If you wish to fork or modify the code, visit the GitHub project page, where the latest versions are always kept. Check the 'master' branch for the latest release, and the 'develop' for the current, and stable, development version.

License

The project has been released under version 2.0 of the Apache License.

dice-notation-java's People

Contributors

bernardo-mg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

dice-notation-java's Issues

Handle valid whitespaces

This expression is accepted:

1d20-5+2d6

While this one is rejected:

 1d20- 5  +  2d6

They are both valid, and should parse into the same tree.

Allow chaining dice functions

Dice functions should be able to work with the resulting values from a previous function.

For example: roll 5 dice, take the higher 3, remove the lowest 1.

Allow marking dice

One of the dice groups may be marked. This serves for example for indicating the die that can cause a critical success.

The grammar should offer a way to mark this dice, in such a way that it is possible to know it's exact result (or the result of each die on the group) after the rolling process.

It should be noted that these dice may still be part of an algebraic operation, so for example you can roll a marked dice, along two unmarked one, get the result of the three dice added, and also get the exact result of the marked die.

Take into consideration that in the future it may be interesting having this dice be part of more than one operation.

For example, on one operation you add the marked die to two other dice, in another one you map the results of the marked die.

Apply operator precendence

Currently there is a branch adding additional operators. But it doesn't apply precendence to multiplications and divisions.

This should be fixed at the grammar level.

Add support for single negative numbers

Currently the grammar can't parse an expression like "-1", which contains only a single numeric value.

Note that negative numbers are valid when they are part of an expression such as "1-2".

Rename "final roll" field.

The getFinalResult method is confusing, as it seems to be for the last value in the series.

Instead change it to getFinalResult or something similar.

Float results from divisions

Currently parsed grammars can only return integers. This means that divisions may not return the correct value.

For example '3/2' will return '1', not '1.5'.

Review the lexical rules

The lexical rules on the grammar should be reviewed, as currently some possible lexical rules are mixed with the grammar ones.

Rename default grammar rule

The default rule is called function. This is confusing, and will be more once functions are added to the grammar.

Change it to "expression".

consider allowing multiplication and division

sometimes, though usually its rare, an RPG will ask for multiplication or division. Here is an example from the freely available "Basic Rules" of Dungeons & Dragons 5th Edition:

Starting Wealth

Class Funds
Cleric 5d4 × 10 gp
Fighter 5d4 × 10 gp
Rogue 4d4 × 10 gp
Wizard 4d4 × 10 gp

would you consider allowing multiplication (poss chars: x, *, ×) and division (poss chars: /, ÷) i personally prefer the charcaters * and /.

i would be willing to take a look at adding the necessary operation classes. I wanted to just bounce it off you first in case you have already ruled it out

Review parsed grammar structure

The parser receives the input expression, applies the grammar and outputs the parsed tree.

This tree follows the interpreter pattern.

https://sourcemaking.com/design_patterns/interpreter

Which can be extended to allow the intrepreter to receive a strategy:

public <V> V interpret(Strategy<V> strategy);

This allows returning various values for the parsed result.

To ease this job the parser may returned a wrapper root node, containing the default interpretations, such as rolling the result.

Readable format for roll history

Having this expression: "4d6+5".

  • Rolls: 4, 5, 6, 4

There should be some way to print it neatly, which would look like: "[4 5 6 4] + 5".

Customize the parser return value

The current ways to get values from a dice notation are too restrictive.

The default always returns an integer:

Integer roll = parsed.roll();

While using transformers is a bit clumsy:

Iterable<Dice> dice = parsed.transform(new DiceSetsTransformer());

Maybe the parser can be typed, and the return type can be defined by a transformer:

final DiceNotationExpressionParser<Iterable<Dice>> parser;
final Iterable<Dice> parsed;

parser = new DefaultDiceNotationExpressionParser<>(new DiceSetsTransformer());

parsed = parser.parse("1d6+12");

This would reduce the number of methods used to process the parsed notation.

Currently these are:

  • roll
  • transform
  • parse

And they would be reduced to:

  • parse

Parenthesis

To allow more control over complex operations the grammar should include support for parenthesis.

1+2*3=7
(1+2)*3=9

some erroneous expressions will not emit an error

so the expression 5dz will throw an ANTRL NoViableAltException which is wrapped into a IllegalStateException however an expression like 6d6y will not throw an exception that i can handle. It seems that some error is thrown at some point in ANTLR because the logs contain

line 1:3 token recognition error at: 'y'

however there is no simple way for me to capture that error.

Default package classes

On the reports the grammar classes appear both on their folders and the base folder. Try to find out why this is happening and fix it.

Retrieve parsed portions separately

Functionality of retrieving the number of die, number of sides, operators used, and integers used in operations within the parsed variable would be extraordinarily useful to me. If there is some method in place of retrieving those variables please feel free to show how, as I'd like to use your parser in a discord bot that I am creating (with due credit, of course!)

Detailed view for a roll

Hi,
I try to use this librairy for a little game for my boy, but (maybe it already exists),
i can't find the way to have the detail of rolls
Ex : 1 want a 2D10 , if i to a .roll(), i'll have 15 for example.
But i would like to have a sorted list with 7 and 8 (7 for the first dire, 8 for the second)

How could i help you with this 'feature' ?

The grammar ignores invalid whitespaces

The grammar should reject notation using invalid whitespaces.

This for example should be rejected: "1 d6". But instead it is being parsed as if it were "1d6".

Move dice model to its own project

The dice model may be better placed in its own model. Maybe even separated into an API and its implementation.

Rollers and similar functional classes would be included in the model?

Add a way to indicate success and failure ranges

Dice notation should include success and failure ranges if the chances for these should be calculated.

Some information which would help:

  • Target value (and if the result should be equal, higher or lower)
  • If instead of a target value this is a roll vs roll, then both rolls should be indicated
  • Critical success/failure values (if they matter, as they do on roll vs roll)

Optional quantity of dice

By default the number of sides should be 1, allowing dice without a defined number of sides.

So "d6" would be the same as "1d6".

Make use of fragments for the lexer

Some lexer rules may be better defined as fragments, such as operator symbols.

fragment ADD
:
   '+'
;

fragment SUB
:
   '-'
;

This may help with the token collision which appear sometimes when attempting changes.

Add support for complex value generation rules

For example:

  • Repeat the highest value (every 6 in any d6)
  • Ignore the lowest/highest value
  • Keep the lowest/highest value

These rules are applied to the parsed expression. So they should be applied with transformers.

But maybe they can be activated through special keywords in the grammar, which would require an extension of the basic grammar.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.