Expand dice contrib readme

This commit is contained in:
Griatch 2023-07-27 12:03:08 +02:00
parent 2e2119d5af
commit b168fbd747
5 changed files with 87 additions and 42 deletions

View file

@ -1,9 +1,9 @@
# Dice roller
Contribution by Griatch, 2012
Contribution by Griatch, 2012, 2023
A dice roller for any number and side of dice. Adds in-game dice rolling
(`roll 2d10 + 1`) as well as conditionals (roll under/over/equal to a target)
(like `roll 2d10 + 1`) as well as conditionals (roll under/over/equal to a target)
and functions for rolling dice in code. Command also supports hidden or secret
rolls for use by a human game master.
@ -44,14 +44,14 @@ unbiased way. For example:
Rolling this will inform all parties if roll was indeed below 8 or not.
> roll/hidden
> roll/hidden 1d100
Informs the room that the roll is being made without telling what the result
was.
> roll/secret
> roll/secret 1d20
Is a hidden roll that does not inform the room it happened.
This a hidden roll that does not inform the room it happened.
## Rolling dice from code
@ -93,9 +93,38 @@ Here's how to roll `2d6 - 1 >= 10` (you'll get back `True`/`False` back):
roll(2, 6, modifier=("-", 1), conditional=(">=", 10))
```
You can only roll one set of dice. If your RPG requires you to roll multiple
### Dice pools and other variations
You can only roll one set of dice at a time. If your RPG requires you to roll multiple
sets of dice and combine them in more advanced ways, you can do so with multiple
`roll()` calls.
`roll()` calls. Depending on what you need, you may just want to express this as
helper functions specific for your game.
Here's how to roll a D&D advantage roll (roll d20 twice, pick highest):
```python
from evennia.contrib.rpg.dice import roll
def roll_d20_with_advantage():
"""Get biggest result of two d20 rolls"""
return max(roll("d20"), roll("d20"))
```
Here's an example of a Free-League style dice pool, where you roll a pile of d6
and want to know how many 1s and sixes you get:
```python
from evennia.contrib.rpg.dice import roll
def roll_dice_pool(poolsize):
"""Return (number_of_ones, number_of_sixes)"""
results = [roll("1d6") for _ in range(poolsize)]
return results.count(1), results.count(6)
```
### Get all roll details

View file

@ -581,10 +581,10 @@ Commands for managing and initiating an in-game character-creation menu.
### `dice`
_Contribution by Griatch, 2012_
_Contribution by Griatch, 2012, 2023_
A dice roller for any number and side of dice. Adds in-game dice rolling
(`roll 2d10 + 1`) as well as conditionals (roll under/over/equal to a target)
(like `roll 2d10 + 1`) as well as conditionals (roll under/over/equal to a target)
and functions for rolling dice in code. Command also supports hidden or secret
rolls for use by a human game master.

View file

@ -1,17 +1,17 @@
# Part 2: What We Want
```{sidebar} Beginner Tutorial Parts
- [Introduction](./Beginner-Tutorial-Overview.md)
- [Introduction](../Beginner-Tutorial-Overview.md)
<br>Getting set up.
- Part 1: [What We Have](Part1/Beginner-Tutorial-Part1-Overview.md)
- Part 1: [What We Have](../Part1/Beginner-Tutorial-Part1-Overview.md)
<br>A tour of Evennia and how to use the tools, including an introduction to Python.
- *Part 2: [What We Want](Part2/Beginner-Tutorial-Part2-Overview.md)*
- *Part 2: [What We Want](./Beginner-Tutorial-Part2-Overview.md)*
<br>Planning our tutorial game and what to consider when planning your own.
- Part 3: [How We Get There](Part3/Beginner-Tutorial-Part3-Overview.md)
- Part 3: [How We Get There](../Part3/Beginner-Tutorial-Part3-Overview.md)
<br>Getting down to the meat of extending Evennia to make your game.
- Part 4: [Using What We Created](Part4/Beginner-Tutorial-Part4-Overview.md)
- Part 4: [Using What We Created](../Part4/Beginner-Tutorial-Part4-Overview.md)
<br>Building a tech-demo and world content to go with our code.
- Part 5: [Showing the World](Part5/Beginner-Tutorial-Part5-Overview.md)
- Part 5: [Showing the World](../Part5/Beginner-Tutorial-Part5-Overview.md)
<br>Taking our new game online and letting players try it out.
```

View file

@ -487,9 +487,7 @@ we check if `maxval` actually has a value `("5",)` or if its empty `()`. The res
### Roll for death
While original Knave suggests hitting 0 HP means insta-death, we will grab the optional "death table"
from the "prettified" Knave's optional rules to make it a little less punishing. We also changed the
result of `2` to 'dead' since we don't simulate 'dismemberment' in this tutorial:
While original Knave suggests hitting 0 HP means insta-death, we will grab the optional "death table" from the "prettified" Knave's optional rules to make it a little less punishing. We also changed the result of `2` to 'dead' since we don't simulate 'dismemberment' in this tutorial:
| Roll | Result | -1d4 Loss of Ability |
|:---: |:--------:|:--------------------:|
@ -501,9 +499,7 @@ result of `2` to 'dead' since we don't simulate 'dismemberment' in this tutorial
| 7 | rattled | WIS |
| 8 | disfigured | CHA |
All the non-dead values map to a loss of 1d4 in one of the six Abilities (but you get HP back).
We need to map back to this from the above table. One also cannot have less than -10 Ability bonus,
if you do, you die too.
All the non-dead values map to a loss of 1d4 in one of the six Abilities (but you get HP back). We need to map back to this from the above table. One also cannot have less than -10 Ability bonus, if you do, you die too.
```python
# in mygame/evadventure/rules.py
@ -557,9 +553,7 @@ dice = EvAdventureRollEngine()
Here we roll on the 'death table' from the rules to see what happens. We give the character
a message if they survive, to let them know what happened.
We don't yet know what 'killing the character' technically means, so we mark this as `TODO` and
return to it in a later lesson. We just know that we need to do _something_ here to kill off the
character!
We don't yet know what 'killing the character' technically means, so we mark this as `TODO` and return to it in a later lesson. We just know that we need to do _something_ here to kill off the character!
## Testing
@ -605,16 +599,11 @@ test method. We use `super().setUp()` to make sure the parent class' version of
always fire. Then we create a fresh `EvAdventureRollEngine` we can test with.
In our test, we import `patch` from the `unittest.mock` library. This is a very useful tool for testing.
Normally the `randint` function we imported in `rules` will return a random value. That's very hard to
test for, since the value will be different every test.
Normally the `randint` function we imported in `rules` will return a random value. That's very hard to test for, since the value will be different every test.
With `@patch` (this is called a _decorator_), we temporarily replace `rules.randint` with a 'mock' - a
dummy entity. This mock is passed into the testing method. We then take this `mock_randint` and set
`.return_value = 4` on it.
With `@patch` (this is called a _decorator_), we temporarily replace `rules.randint` with a 'mock' - a dummy entity. This mock is passed into the testing method. We then take this `mock_randint` and set `.return_value = 4` on it.
Adding `return_value` to the mock means that every time this mock is called, it will return 4. For the
duration of the test we can now check with `self.assertEqual` that our `roll` method always returns a
result as-if the random result was 4.
Adding `return_value` to the mock means that every time this mock is called, it will return 4. For the duration of the test we can now check with `self.assertEqual` that our `roll` method always returns a result as-if the random result was 4.
There are [many resources for understanding mock](https://realpython.com/python-mock-library/), refer to
them for further help.
@ -623,9 +612,7 @@ them for further help.
## Summary
This concludes all the core rule mechanics of _Knave_ - the rules used during play. We noticed here
that we are going to soon need to establish how our _Character_ actually stores data. So we will
address that next.
This concludes all the core rule mechanics of _Knave_ - the rules used during play. We noticed here that we are going to soon need to establish how our _Character_ actually stores data. So we will address that next.