fix: typo in test example

This commit is contained in:
Blade Boles 2023-07-05 20:33:24 -06:00
parent 98ce816e39
commit 15b1a287d4

View file

@ -10,35 +10,34 @@ along, you can find a [free fan-version here](http://abominablefancy.blogspot.co
Knave, being inspired by early Dungeons & Dragons, is very simple. Knave, being inspired by early Dungeons & Dragons, is very simple.
- It uses six Ability bonuses - It uses six Ability bonuses
_Strength_ (STR), _Dexterity_ (DEX), _Constitution_ (CON), _Intelligence_ (INT), _Wisdom_ (WIS) _Strength_ (STR), _Dexterity_ (DEX), _Constitution_ (CON), _Intelligence_ (INT), _Wisdom_ (WIS)
and _Charisma_ (CHA). These are rated from `+1` to `+10`. and _Charisma_ (CHA). These are rated from `+1` to `+10`.
- Rolls are made with a twenty-sided die (`1d20`), usually adding a suitable Ability bonus to the roll. - Rolls are made with a twenty-sided die (`1d20`), usually adding a suitable Ability bonus to the roll.
- If you roll _with advantage_, you roll `2d20` and pick the - If you roll _with advantage_, you roll `2d20` and pick the
_highest_ value, If you roll _with disadvantage_, you roll `2d20` and pick the _lowest_. _highest_ value, If you roll _with disadvantage_, you roll `2d20` and pick the _lowest_.
- Rolling a natural `1` is a _critical failure_. A natural `20` is a _critical success_. Rolling such - Rolling a natural `1` is a _critical failure_. A natural `20` is a _critical success_. Rolling such
in combat means your weapon or armor loses quality, which will eventually destroy it. in combat means your weapon or armor loses quality, which will eventually destroy it.
- A _saving throw_ (trying to succeed against the environment) means making a roll to beat `15` (always). - A _saving throw_ (trying to succeed against the environment) means making a roll to beat `15` (always).
So if you are lifting a heavy stone and have `STR +2`, you'd roll `1d20 + 2` and hope the result So if you are lifting a heavy stone and have `STR +2`, you'd roll `1d20 + 2` and hope the result
is higher than `15`. is higher than `15`.
- An _opposed saving throw_ means beating the enemy's suitable Ability 'defense', which is always their - An _opposed saving throw_ means beating the enemy's suitable Ability 'defense', which is always their
`Ability bonus + 10`. So if you have `STR +1` and are arm wrestling someone with `STR +2`, you roll `Ability bonus + 10`. So if you have `STR +1` and are arm wrestling someone with `STR +2`, you roll
`1d20 + 1` and hope to roll higher than `2 + 10 = 12`. `1d20 + 1` and hope to roll higher than `2 + 10 = 12`.
- A special bonus is `Armor`, `+1` is unarmored, additional armor is given by equipment. Melee attacks - A special bonus is `Armor`, `+1` is unarmored, additional armor is given by equipment. Melee attacks
test `STR` versus the `Armor` defense value while ranged attacks uses `WIS` vs `Armor`. test `STR` versus the `Armor` defense value while ranged attacks uses `WIS` vs `Armor`.
- _Knave_ has no skills or classes. Everyone can use all items and using magic means having a special - _Knave_ has no skills or classes. Everyone can use all items and using magic means having a special
'rune stone' in your hands; one spell per stone and day. 'rune stone' in your hands; one spell per stone and day.
- A character has `CON + 10` carry 'slots'. Most normal items uses one slot, armor and large weapons uses - A character has `CON + 10` carry 'slots'. Most normal items uses one slot, armor and large weapons uses
two or three. two or three.
- Healing is random, `1d8 + CON` health healed after food and sleep. - Healing is random, `1d8 + CON` health healed after food and sleep.
- Monster difficulty is listed by hy many 1d8 HP they have; this is called their "hit die" or HD. If - Monster difficulty is listed by hy many 1d8 HP they have; this is called their "hit die" or HD. If
needing to test Abilities, monsters have HD bonus in every Ability. needing to test Abilities, monsters have HD bonus in every Ability.
- Monsters have a _morale rating_. When things go bad, they have a chance to panic and flee if - Monsters have a _morale rating_. When things go bad, they have a chance to panic and flee if
rolling `2d6` over their morale rating. rolling `2d6` over their morale rating.
- All Characters in _Knave_ are mostly randomly generated. HP is `<level>d8` but we give every - All Characters in _Knave_ are mostly randomly generated. HP is `<level>d8` but we give every
new character max HP to start. new character max HP to start.
- _Knave_ also have random tables, such as for starting equipment and to see if dying when - _Knave_ also have random tables, such as for starting equipment and to see if dying when
hitting 0. Death, if it happens, is permanent. hitting 0. Death, if it happens, is permanent.
## Making a rule module ## Making a rule module
@ -48,6 +47,7 @@ hitting 0. Death, if it happens, is permanent.
A complete version of the rule module is found in A complete version of the rule module is found in
[evennia/contrib/tutorials/evadventure/rules.py](../../../api/evennia.contrib.tutorials.evadventure.rules.md). [evennia/contrib/tutorials/evadventure/rules.py](../../../api/evennia.contrib.tutorials.evadventure.rules.md).
``` ```
There are three broad sets of rules for most RPGS: There are three broad sets of rules for most RPGS:
- Character generation rules, often only used during character creation - Character generation rules, often only used during character creation
@ -57,7 +57,6 @@ There are three broad sets of rules for most RPGS:
We want our `rules` module to cover as many aspeects of what we'd otherwise would have to look up We want our `rules` module to cover as many aspeects of what we'd otherwise would have to look up
in a rulebook. in a rulebook.
## Rolling dice ## Rolling dice
We will start by making a dice roller. Let's group all of our dice rolling into a structure like this We will start by making a dice roller. Let's group all of our dice rolling into a structure like this
@ -94,6 +93,7 @@ class EvAdventureRollEngine:
dice = EvAdventureRollEngine() dice = EvAdventureRollEngine()
``` ```
```{sidebar} ```{sidebar}
This groups all dice-related code into one 'container' that is easy to import. But it's mostly a matter This groups all dice-related code into one 'container' that is easy to import. But it's mostly a matter
of taste. You _could_ also break up the class' methods into normal functions at the top-level of the of taste. You _could_ also break up the class' methods into normal functions at the top-level of the
@ -156,6 +156,7 @@ in a specific range. The line
```python ```python
sum(randint(1, diesize) for _ in range(number)) sum(randint(1, diesize) for _ in range(number))
``` ```
works like this: works like this:
- For a certain `number` of times ... - For a certain `number` of times ...
@ -223,6 +224,7 @@ have it figure things out:
```python ```python
result, quality = dice.saving_throw(character, Ability.STR) result, quality = dice.saving_throw(character, Ability.STR)
``` ```
The return will be a boolean `True/False` if they pass, as well as a `quality` that tells us if The return will be a boolean `True/False` if they pass, as well as a `quality` that tells us if
a perfect fail/success was rolled or not. a perfect fail/success was rolled or not.
@ -379,7 +381,6 @@ number of HPs
> Knowing what is available on the character and what rule rolls we need is a bit of a chicken-and-egg > Knowing what is available on the character and what rule rolls we need is a bit of a chicken-and-egg
> problem. We will make sure to implement the matching _Character_ class next lesson. > problem. We will make sure to implement the matching _Character_ class next lesson.
### Rolling on a table ### Rolling on a table
We occasionally need to roll on a 'table' - a selection of choices. There are two main table-types We occasionally need to roll on a 'table' - a selection of choices. There are two main table-types
@ -388,7 +389,7 @@ we need to support:
Simply one element per row of the table (same odds to get each result). Simply one element per row of the table (same odds to get each result).
| Result | | Result |
|:------:| | :----: |
| item1 | | item1 |
| item2 | | item2 |
| item3 | | item3 |
@ -403,7 +404,7 @@ This we will simply represent as a plain list
Ranges per item (varying odds per result): Ranges per item (varying odds per result):
| Range | Result | | Range | Result |
|:-----:|:------:| | :---: | :----: |
| 1-5 | item1 | | 1-5 | item1 |
| 6-15 | item2 | | 6-15 | item2 |
| 16-19 | item3 | | 16-19 | item3 |
@ -461,9 +462,11 @@ class EvAdventureRollEngine:
roll_result = max(1, min(len(table_choices), roll_result)) roll_result = max(1, min(len(table_choices), roll_result))
return table_choices[roll_result - 1] return table_choices[roll_result - 1]
``` ```
Check that you understand what this does. Check that you understand what this does.
This may be confusing: This may be confusing:
```python ```python
minval, *maxval = valrange.split("-", 1) minval, *maxval = valrange.split("-", 1)
minval = abs(int(minval)) minval = abs(int(minval))
@ -484,22 +487,21 @@ maxval = abs(int(maxval[0]) if maxval else minval)
we check if `maxval` actually has a value `("5",)` or if its empty `()`. The result is either we check if `maxval` actually has a value `("5",)` or if its empty `()`. The result is either
`"5"` or the value of `minval`. `"5"` or the value of `minval`.
### Roll for death ### Roll for death
While original Knave suggests hitting 0 HP means insta-death, we will grab the optional "death table" 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 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: result of `2` to 'dead' since we don't simulate 'dismemberment' in this tutorial:
| Roll | Result | -1d4 Loss of Ability | | Roll | Result | -1d4 Loss of Ability |
|:---: |:--------:|:--------------------:| | :--: | :--------: | :------------------: |
| 1-2 | dead | - | 1-2 | dead | - |
| 3 | weakened | STR | | 3 | weakened | STR |
|4 | unsteady | DEX | | 4 | unsteady | DEX |
| 5 | sickly | CON | | 5 | sickly | CON |
| 6 | addled | INT | | 6 | addled | INT |
| 7 | rattled | WIS | | 7 | rattled | WIS |
| 8 | disfigured | CHA | | 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). 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, We need to map back to this from the above table. One also cannot have less than -10 Ability bonus,
@ -584,7 +586,7 @@ class TestEvAdventureRuleEngine(BaseEvenniaTest):
@patch("evadventure.rules.randint") @patch("evadventure.rules.randint")
def test_roll(self, mock_randint): def test_roll(self, mock_randint):
mock_randint.return_value = 4 mock_randint.return_value = 4
self.assertEqual(self.roll_engine.roll("1d6", 4)) self.assertEqual(self.roll_engine.roll("1d6"), 4)
self.assertEqual(self.roll_engine.roll("2d6"), 2 * 4) self.assertEqual(self.roll_engine.roll("2d6"), 2 * 4)
# test of the other rule methods below ... # test of the other rule methods below ...
@ -600,6 +602,7 @@ As before, run the specific test with
In [evennia/contrib/tutorials/evadventure/tests/test_rules.py](../../../api/evennia.contrib.tutorials.evadventure.tests.test_rules.md) In [evennia/contrib/tutorials/evadventure/tests/test_rules.py](../../../api/evennia.contrib.tutorials.evadventure.tests.test_rules.md)
has a complete example of rule testing. has a complete example of rule testing.
``` ```
The `setUp` method is a special method of the testing class. It will be run before every The `setUp` method is a special method of the testing class. It will be run before every
test method. We use `super().setUp()` to make sure the parent class' version of this method test method. We use `super().setUp()` to make sure the parent class' version of this method
always fire. Then we create a fresh `EvAdventureRollEngine` we can test with. always fire. Then we create a fresh `EvAdventureRollEngine` we can test with.
@ -626,8 +629,3 @@ them for further help.
This concludes all the core rule mechanics of _Knave_ - the rules used during play. We noticed here 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 that we are going to soon need to establish how our _Character_ actually stores data. So we will
address that next. address that next.