Overwiew
Dice2 is a library designed to allow evaluation of complex expressions
involving dice rolls, and to compute probabilities on those
expressions. It is targetted for role-playing games (both real
pen & paper and CRPG), and can be used in many different ways:
- with the included mean and roll programs, by both players
and game master, to roll dices or compute probabilities;
- the included programs, or the library, with an external front-end
(like an IRC bot or a website) to provide dice-rolling for IRC-based
or mail-based role-playing games;
- as a library, to provide dice-rolling and probability evaluator for
programs designed to help game masters during pen & paper games;
- as a library, included inside a CRPG game engine, to roll the dices.
Of course, it may have different uses, feel free to show your
creativity and to use it as you wish :)
Legal issues
This library, the documentation and the programs are copyrighted by
the original author (Gaƫl Le Mignot) and by contributors. It is freely
available under the terms of the GNU General Public License, version
2, or at your option, any further version, as published by the Free
Software Foundation. The full text of the GNU GPL is included in the
original source distribution, and should be kept with any
distribution.
General concepts
Dice code
A simple dice code is a basic expression describing a set of dice to
roll with some rules. A dice code is an arithmetic operator with
some arguments (from 0 to 3). In future versions, functions-like
syntax may be added to allow dice code with more than 3 parameters.
Many dice codes are based on a specific RPG rules, like World of
Darkness, Rolemaster, Ars Magica, Arkeos or similar
dice codes. Some are more generic, like the classical ''sum them
all'' dice code.
A complex dice code is an arithmetic expression including one or
more simple dice code, like 3d6+2d4. Classic priority is used
for arithmetic operators, dice codes having a higher priority than any
arithmetic operator: 3d6*2 is the same than (3d6)*2.
Dice tree
A dice tree is the result of the parsing of a string representation
of an arithmetic expression containing dice codes (and normal
arithmetic operators) into a tree. This tree can then be evaluated by
the library, much faster than the string itself. Use a dice tree
when you'll have to evaluate (roll) the same expression more than
once.
Fuzzy logic
A fuzzy logic engine is included to allow exact and fast computing of
(some) probability. The idea is simple: instead of evaluating the
dice tree in the space of normal integers, with each dice code
resulting in dice rolls, the dice tree is evaluated in the space of
fuzzy integers, and each dice code becomes a fuzzy integer with the
probability of each result as the weight of each possible value.
Please note that some dice codes, like those who can have infinite
values, do not support fuzzy logic evaluation.
Error system
Since version 0.7.0, libdice2 provides an error queue. Errors have a
type and and a level. Each error occuring inside an operation of
dice2 is pushed at the end of the queue, or discarded, depending of
its level and the current configuration.
You should, after each call (or set of calls) to libdice2, fetch
errors, and process them as you wish.
Thread safety
Since version 0.7.0, libdice2 provides support for thread-safety. You
need to explicit enable it, by giving to libdice2 the functions to use
for several operations (locking/unlocking a mutex, and getting the
current thread id).
Once the thread-safety is on, you can use libdice2 in a multithreaded
program, and the error queue will be local to your current thread.
Pay attention that you still need to provide external locking if more
than one thread access to a any given libdice2 object (tree, fuzzy
set, ...)
API Reference
This API Reference only contains documentation for the functions
designed to be called from a program using libdice2. If you want
documentation about some internal functions, look at the source code
and .h files, there should be enough comments; if not, mail me.
General API
Customization variables
The following variables are available to customize the library
behavior:
- int dice_limit_group_size;
- Limit the size of each dice pool or group. Negative value means
unlimited. You can use this variable to protect from a DoS in case
of a publically available dice roller. Pay attention that no
warranty is made that there is no way to bypass the DoS protection.
- int dice_limit_simulation_iterations;
- Limit the number of iterations of a simulated dice roll. See
comments of dice_limit_group_size.
Customization functions
- void dice_cache_configure (int cachesize, int nbbuckets);
Configure the size of the cache used to store fuzzy logic
intermediate computations. Pay attention that if the cache is too
small compared to what you ask for, the algorithm used will stop to
be polynomial. Changing tne number of buckets or reducing the size
of the cache will flush it.
The cache is an hashtable, the number buckets is the size of the
primary table, and the cachesize the maximal number of items that
can be stored in the cache.
- void dice_srandom ();
- Seed the pseudo-random number generator using /dev/urandom if
available or system time else. You should call this function or seed
the PRNG by yourself at the startup of your program.
Tree API
- dice_tree_t *dice_tree_build (const char *s);
- Parse the string and build a new tree from it.
- void dice_tree_free (dice_tree_t *tree);
- Free the memory allocated by the tree.
Rolling API
- int dice_eval_string (const char *s);
- The simplest function, that takes a string, evaluates it and roll
all needed dice codes.
- int dice_tree_eval (const dice_tree_t *tree);
- Do the same as the previous one, but on a previously parsed tree.
- int dice_roll_* (...);
- For each supported dice code, there is a specific raw dice rolling
function, see the full list and prototypes in dice_code.h
Detailed rolling
How to get detailed results
Each of the previous rolling function (string, tree or specific)
support a _full version, which can return additional informations.
The _full versions take two extra parameters:
dice_detail_level_t level and dice_roll_list_t **list. The
level can be LEVEL_NONE (0), LEVEL_GROUP, LEVEL_SINGLE or
LEVEL_BOTH (binary or of the two previous), specifying which
results to include.
LEVEL_GROUP includes all intermediate results of dice groups, like
in 3d6+2d4, two group results will be returned: the result of
3d6 and the result of 2d4.
LEVEL_SINGLE includes all the individual dice rolled during the
evaluation.
How to use detailed results
The dice_roll_list_t is a NULL-terminated linked list of
dice_roll_t elements. Each dice_roll_t element contains the
string representation of what was rolled in the dice field, the
level (group or single) of the intermediate result, and the
result of the roll.
You can use the following helper functions:
- void dice_roll_list_free (dice_roll_list_t *list);
- Free a list and all its elements.
- int dice_roll_list_size (const dice_roll_list_t *list);
- Count the number of elements of the list (this is O(n) on the number
of elements of the list).
Fuzzy logic
How to get a fuzzy logic evaluation ?
- dice_fuzzy_t *dice_eval_string_fuzzy (const char *s);
- Evaluate a string as a fuzzy integer, set an error if not possible.
- dice_fuzzy_t *dice_tree_eval_fuzzy (const dice_tree_t *tree);
- Evaluate a tree as a fuzzy integer, set an error if not possible.
How to use simulate ?
When a fuzzy-logic evaluation is not possible, or too complex, you can
simulate it using many rolls. The following functions can do it:
- dice_fuzzy_t *dice_simulate_string_fuzzy (const char *s, int nbrolls);
- Roll nbrolls times a given string, and retruns a simulated fuzzy int.
- dice_fuzzy_t *dice_tree_simulate_fuzzy (const dice_tree_t *tree, int nbrolls);
- Roll nbrolls times a given tree, and retruns a simulated fuzzy int.
- void dice_tree_simulate_into (dice_fuzzy_t *fuzzy, const dice_tree_t *tree, int nbrolls);
- Appends results to an already created fuzzy int. This function is
useful to simulate the result small bunch by small bunch, like when
you want to create progress bars, or to still react to use input
without using multithreading.
What to do with a fuzzy int ?
The fuzzy int are handled with the functions in dice_fuzzyint.h.
Here are the most important ones to use a result:
- dice_fuzzy_t *dice_fuzzy_ref (dice_fuzzy_t *src);
- Increase the reference counter on a fuzzy int.
- void dice_fuzzy_unref (dice_fuzzy_t *fuzzy);
- Decrease the reference counter on a fuzzy int. If the reference
counter reaches 0, the fuzzy int is destroyed.
- int dice_fuzzy_get_start (const dice_fuzzy_t *fuzzy);
- This function gets the smallest possible value (lower bound of the
fuzzy set).
- int dice_fuzzy_get_ending (const dice_fuzzy_t *fuzzy);
- This function gets the highest possible value (upper bound of the
fuzzy set).
- number_t dice_fuzzy_get (const dice_fuzzy_t *fuzzy, int what);
- This function gets the specific weight (probability) of a given
result to occur. Pay attention that if the fuzzy int was not
scaled, the weight is not directly a probability.
- number_t dice_fuzzy_get_total (const dice_fuzzy_t *fuzzy);
- Return the sum of all weights; to get a real probability, you need
to divide the weight of a specific item by the total weight of the
set.
- void dice_fuzzy_normalize (dice_fuzzy_t *fuzzy, number_t total);
- Rescale all weights so that the sum will be total. Use 1.0
to have weights being mathematical probabilities, and 100.0 if
you want percentile probabilities.
Error API
As explained in the introduction, since version 0.7.0, libdice2 now
use an error queue (for each thread). Every time an error occured, it
is pushed on the queue.
A full list of function can be found in dice_error.h, only the
most important ones will be explained in this document.
- void dice_error_set_drop_level (dice_error_level_t level);
Configure the minimal level of errors to keep. Levels are:
- DICE_ERROR_INFORMATION: simple information item, useful for debugging
- DICE_ERROR_WARNING: non-fatal warning
- DICE_ERROR_ERROR: real error, making the current operation to fail
- DICE_ERROR_CRITICAL: should-not-happen situation, usually a bug in
the library or in the program using it
- DICE_ERROR_INVALID: invalid error level, if you set the drop level
to it, all errors will be dropped.
- dice_error_t *dice_error_pop ();
- Get the first error of the queue (less recent one), and remove it
from the queue. The dice_error_t structure contains three
fields: the level of the error, the type of the error and
a message.
- void dice_error_free (dice_error_t *error);
- Free an error returned by dice_error_pop
- void dice_error_clear ();
- Clear the error queue (of the current thread).
- const char *dice_error_domain_name (dice_error_type_t type);
- Get the domain name from the record in the dice_error_t structure.
- const char *dice_error_level_name (dice_error_level_t level);
- Get the level name from the record in the dice_error_t structure.
Thread-safety API
To enable thread-safety, you need to call the dice_thread_setup
function, with for parameters:
- lock_callback a function pointer, taking a single argument, that
will lock its argument; for example pthread_mutex_lock.
- unlock_callback a function pointer, taking a single argument,
that will unlock its argument; for example pthread_mutex_unlock.
- lock_data an item to be passed to the two previous functions;
for example an allocated and initialized pthread_mutex_t
- get_id_callback a function pointer, taking no argument, and
returning, as an integer, the current thread id; for example
pthread_self