This commit refactors the parsing and rolling for the dice pool system
to prepare for support of user variables. The nom parser was dropped
in favor of the easier-to-understand combine parser in most parts of
the code.
A breaking change was introduced into the dice pool syntax to allow
for proper expressions and variables. The syntax is now
"modifiers:pool-amount", e.g. "n:gnosis+8". The simple single-number
syntax with no modifiers is also still understood.
Dice pool expressions are translated into a Vec of "Amount" objects,
stored by the DicePool struct. They have an operator (+ or -) and
either a number or variable name. When the dice pool is rolled, this
list of Amonuts are is collapsed into a single number that is rolled,
as it was before the refactor.
The following changes were made to the dice rolling code:
- Store Vec<Amount> on DicePool instead of single number to roll.
- New struct RolledDicePool to store result of a dice pool roll.
- Remove Display trait from DicePool, move it over to RolledDicePool.
- Separate extra dice pool info into DicePoolModifiers.
- DicePoolModifiers is shared between DicePool and RolledDicePool.
- Dice parsing and rolling now return standard Result objects.
This commit does NOT enable support of actually using variables. Any
dice pool roll containing a variable will result in an eror.
The command parser was also rewritten to use combine and rely on the
standard Result pattern.
Only expose config settings via methods on the Config struct. This
allows default value handling to live entirely inside the config code,
solves various borrowing issues with the "create default bot config
value" solution, and allows us to avoid cloning the bot config values.
The downside is that the config must now be in an Arc since its
ownership is shared in multiple places and the matrix SDK requires
thread-safe types (perhaps in the future we re-compose traits and use
Rc for config instead).
This commit also further cleans up and splits up the bot code for the
matrix connection, notably making the main message event handler
smaller by splitting out the "should we process the message" checks
into a separate function.
Instead of using an Arc Mutex for state management embedded directly
into the bot, utilize actor pattern, with the idea that this will be
much more useful than simply logging a message once in the future.
This also refactors the bot code so that instead of a single run_bot
function, the DiceBot struct now has a run() method attached to it.
This also necessitated changes and cleanup to the dicebot main, which
is for the better anyhow.
The error and config types are also now in their own files, and
implemented for more in-depth use cases.
This commit lays the groundwork for a stateful dicebot, instead of one
that only responds to commands. It now maintains a simple state
machine, used to store the current state of the bot. Currently, it
only cares about whether or not the message about skipping old
messages was logged.
This makes the oldest message age setting optional, in additon to the
entire bot config (for now). If the oldest message age is not
specified (or if the entire bot config is missing), it will default to
15 minutes.
This behavior became broken again after switching away from the
macro-based command parsing. The bot would return any non !command
message as an error, which would cause it to read more messages, and
return those as errors, until finally the matrix SDK would throw up.
Command parser now more properly handles empty messages and
non-commands, but we also simply abort processing if the incoming
message doesn't start with an exclamation point.
By using the alpha1 function in complete mode, we are able to handle
arbitrary single-word commands (e.g. "!help") and proprly map the
remaining input to an empty string.
This gives us many things for free, like automated state management,
no need to declare special API structs and use HTTP requests directly,
and most importantly: ENCRYPTION!