Skip to content

Commit 5edcba9

Browse files
GascaKcmccandless
authored andcommitted
dnd-character: implement exercise v1.0.0 (#1613)
* sum-of-multiples: update tests to v1.5.0 Fixes #1580 * Updated 3 test cases to conform to canonical data (reordered list to fit the ascending order convention) * Updated example to check for ZeroDivisionError * sum-of-multiples: pep8 formatting connotation Small edits to conform to Pep8 standards * sum-of-multiples: pep8 formatting connotation Even smaller updates to conform to pep8 * sum-of_multiples: update import list Change import to link to correct file * sum-of-multiples: update tests to v1.5.0 * Updated test case names to reflect significance of each case. * Updated example.py for brevity * sum-of-multiples: update * Delete blank line * phone-number: update tests to v1.6.1 Fixes #1582 * Version increment. * dnd-character: implement exercise v1.0.0 Closes #1593 * DND exercise implemented with corresponding tests and example * Updated README.md * dnd-character: implement exercise v1.0.0 Update #1613 * Del character{} from dnd_character.py * Modified test cases to fit the exercise implementation in dnd_charact_test.py * Modified example.py to exemplify spirit of exercise and deleted the character{} * Implemented the README.md using the configlet tool * dnd-character: implement exercise v1.0.0 Update config.json to reference this exercise. * Update config.json "unlocked_by" updated to reference "robot-name" Co-Authored-By: GascaK <[email protected]> * Update config.json unlocked_by: null Co-Authored-By: GascaK <[email protected]> * dnd-character: update tests to v1.1.0 Closes #1593 * Update config.json * Update _test.py to correctly reflect the canonical data. * Update _test.py Update to include max roll of 18.
1 parent 68a0ea2 commit 5edcba9

File tree

5 files changed

+197
-0
lines changed

5 files changed

+197
-0
lines changed

config.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,6 +1393,17 @@
13931393
"strings"
13941394
]
13951395
},
1396+
{
1397+
"slug": "dnd-character",
1398+
"uuid": "58625685-b5cf-4e8a-b3aa-bff54da0689d",
1399+
"core": false,
1400+
"unlocked_by": null,
1401+
"difficulty": 1,
1402+
"topics": [
1403+
"randomness",
1404+
"integers"
1405+
]
1406+
},
13961407
{
13971408
"slug": "accumulate",
13981409
"uuid": "e7351e8e-d3ff-4621-b818-cd55cf05bffd",

exercises/dnd-character/README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Dnd Character
2+
3+
For a game of [Dungeons & Dragons][DND], each player starts by generating a
4+
character they can play with. This character has, among other things, six
5+
abilities; strength, dexterity, constitution, intelligence, wisdom and
6+
charisma. These six abilities have scores that are determined randomly. You
7+
do this by rolling four 6-sided dice and record the sum of the largest three
8+
dice. You do this six times, once for each ability.
9+
10+
Your character's initial hitpoints are 10 + your character's constitution
11+
modifier. You find your character's constitution modifier by subtracting 10
12+
from your character's constitution, divide by 2 and round down.
13+
14+
Write a random character generator that follows the rules above.
15+
16+
For example, the six throws of four dice may look like:
17+
18+
* 5, 3, 1, 6: You discard the 1 and sum 5 + 3 + 6 = 14, which you assign to strength.
19+
* 3, 2, 5, 3: You discard the 2 and sum 3 + 5 + 3 = 11, which you assign to dexterity.
20+
* 1, 1, 1, 1: You discard the 1 and sum 1 + 1 + 1 = 3, which you assign to constitution.
21+
* 2, 1, 6, 6: You discard the 1 and sum 2 + 6 + 6 = 14, which you assign to intelligence.
22+
* 3, 5, 3, 4: You discard the 3 and sum 5 + 3 + 4 = 12, which you assign to wisdom.
23+
* 6, 6, 6, 6: You discard the 6 and sum 6 + 6 + 6 = 18, which you assign to charisma.
24+
25+
Because constitution is 3, the constitution modifier is -4 and the hitpoints are 6.
26+
27+
## Notes
28+
29+
Most programming languages feature (pseudo-)random generators, but few
30+
programming languages are designed to roll dice. One such language is [Troll].
31+
32+
[DND]: https://en.wikipedia.org/wiki/Dungeons_%26_Dragons
33+
[Troll]: http://hjemmesider.diku.dk/~torbenm/Troll/
34+
35+
## Exception messages
36+
37+
Sometimes it is necessary to raise an exception. When you do this, you should include a meaningful error message to
38+
indicate what the source of the error is. This makes your code more readable and helps significantly with debugging. Not
39+
every exercise will require you to raise an exception, but for those that do, the tests will only pass if you include
40+
a message.
41+
42+
To raise a message with an exception, just write it as an argument to the exception type. For example, instead of
43+
`raise Exception`, you should write:
44+
45+
```python
46+
raise Exception("Meaningful message indicating the source of the error")
47+
```
48+
49+
## Running the tests
50+
51+
To run the tests, run the appropriate command below ([why they are different](https://github.com/pytest-dev/pytest/issues/1629#issue-161422224)):
52+
53+
- Python 2.7: `py.test dnd_character_test.py`
54+
- Python 3.4+: `pytest dnd_character_test.py`
55+
56+
Alternatively, you can tell Python to run the pytest module (allowing the same command to be used regardless of Python version):
57+
`python -m pytest dnd_character_test.py`
58+
59+
### Common `pytest` options
60+
61+
- `-v` : enable verbose output
62+
- `-x` : stop running tests on first failure
63+
- `--ff` : run failures from previous test before running other test cases
64+
65+
For other options, see `python -m pytest -h`
66+
67+
## Submitting Exercises
68+
69+
Note that, when trying to submit an exercise, make sure the solution is in the `$EXERCISM_WORKSPACE/python/dnd-character` directory.
70+
71+
You can find your Exercism workspace by running `exercism debug` and looking for the line that starts with `Workspace`.
72+
73+
For more detailed information about running tests, code style and linting,
74+
please see [Running the Tests](http://exercism.io/tracks/python/tests).
75+
76+
## Source
77+
78+
Simon Shine, Erik Schierboom [https://github.com/exercism/problem-specifications/issues/616#issuecomment-437358945](https://github.com/exercism/problem-specifications/issues/616#issuecomment-437358945)
79+
80+
## Submitting Incomplete Solutions
81+
82+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class Character:
2+
def __init__(self):
3+
pass
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import unittest
2+
3+
from dnd_character import Character, modifier
4+
5+
6+
# Tests adapted from 'problem-specifications//canonical-data.json' @ v1.1.0
7+
8+
class DnDCharacterTest(unittest.TestCase):
9+
def test_modifier_for_score_3_is_n4(self):
10+
self.assertEqual(modifier(3), -4)
11+
12+
def test_modifier_for_score_4_is_n3(self):
13+
self.assertEqual(modifier(4), -3)
14+
15+
def test_modifier_for_score_5_is_n3(self):
16+
self.assertEqual(modifier(5), -3)
17+
18+
def test_modifier_for_score_6_is_n2(self):
19+
self.assertEqual(modifier(6), -2)
20+
21+
def test_modifier_for_score_7_is_n2(self):
22+
self.assertEqual(modifier(7), -2)
23+
24+
def test_modifier_for_score_8_is_n1(self):
25+
self.assertEqual(modifier(8), -1)
26+
27+
def test_modifier_for_score_9_is_n1(self):
28+
self.assertEqual(modifier(9), -1)
29+
30+
def test_modifier_for_score_10_is_0(self):
31+
self.assertEqual(modifier(10), 0)
32+
33+
def test_modifier_for_score_11_is_0(self):
34+
self.assertEqual(modifier(11), 0)
35+
36+
def test_modifier_for_score_12_is_1(self):
37+
self.assertEqual(modifier(12), 1)
38+
39+
def test_modifier_for_score_13_is_1(self):
40+
self.assertEqual(modifier(13), 1)
41+
42+
def test_modifier_for_score_14_is_2(self):
43+
self.assertEqual(modifier(14), 2)
44+
45+
def test_modifier_for_score_15_is_2(self):
46+
self.assertEqual(modifier(15), 2)
47+
48+
def test_modifier_for_score_16_is_3(self):
49+
self.assertEqual(modifier(16), 3)
50+
51+
def test_modifier_for_score_17_is_3(self):
52+
self.assertEqual(modifier(17), 3)
53+
54+
def test_modifier_for_score_18_is_4(self):
55+
self.assertEqual(modifier(18), 4)
56+
57+
def test_random_ability_is_within_range(self):
58+
self.assertIn(Character().ability(), range(3, 19))
59+
60+
def test_random_character_is_valid(self):
61+
Char = Character()
62+
self.assertIn(Char.strength, range(3, 19))
63+
self.assertIn(Char.dexterity, range(3, 19))
64+
self.assertIn(Char.constitution, range(3, 19))
65+
self.assertIn(Char.intelligence, range(3, 19))
66+
self.assertIn(Char.wisdom, range(3, 19))
67+
self.assertIn(Char.charisma, range(3, 19))
68+
self.assertEqual(
69+
Char.hitpoints,
70+
10 + modifier(Char.constitution))
71+
72+
def test_each_ability_is_only_calculated_once(self):
73+
Char = Character()
74+
self.assertEqual(Char.strength, Char.strength)
75+
76+
77+
if __name__ == '__main__':
78+
unittest.main()

exercises/dnd-character/example.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import random
2+
import math
3+
4+
5+
class Character:
6+
def __init__(self):
7+
self.strength = self.ability()
8+
self.dexterity = self.ability()
9+
self.constitution = self.ability()
10+
self.intelligence = self.ability()
11+
self.wisdom = self.ability()
12+
self.charisma = self.ability()
13+
self.hitpoints = 10 + modifier(self.constitution)
14+
15+
def ability(self):
16+
dice_rolls = sorted(
17+
[random.randint(1, 6)
18+
for _ in range(4)])
19+
return sum(dice_rolls[1:])
20+
21+
22+
def modifier(value):
23+
return math.floor((value-10)/2)

0 commit comments

Comments
 (0)