Compare commits
1 Commits
cypher-rol
...
main
Author | SHA1 | Date | |
---|---|---|---|
43f6b61a72 |
@ -8,6 +8,7 @@ import random
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
DICE_DESCRIPTOR_PATTERN = re.compile(r"^([0-9]*d[0-9]+)([+-]([0-9]+|[0-9]*d[0-9]+))*$")
|
DICE_DESCRIPTOR_PATTERN = re.compile(r"^([0-9]*d[0-9]+)([+-]([0-9]+|[0-9]*d[0-9]+))*$")
|
||||||
|
D666_COMBINATIONS = [(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)]
|
||||||
|
|
||||||
|
|
||||||
class Die:
|
class Die:
|
||||||
@ -96,3 +97,26 @@ class Die:
|
|||||||
result += self.modifier
|
result += self.modifier
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def d666(strict_order: bool = False) -> list[int]:
|
||||||
|
"""Roll three six sided dice and use them as separate digits
|
||||||
|
|
||||||
|
“d666” is a special die type often used in random tables; here you don’t roll one 666 sided die, but three 6-sided
|
||||||
|
ones, then use the three values of the three digits of the final result.
|
||||||
|
|
||||||
|
:param strict_order: if ``True``, use the dics in strict order. Otherwise, return all possible combinations.
|
||||||
|
:returns: the list of all valid combinations
|
||||||
|
"""
|
||||||
|
|
||||||
|
roll_values = [random.randint(1, 6) for _ in range(3)]
|
||||||
|
results = []
|
||||||
|
|
||||||
|
combinations = [(0, 1, 2)] if strict_order else D666_COMBINATIONS
|
||||||
|
|
||||||
|
for a, b, c in combinations:
|
||||||
|
result = roll_values[a] * 100 + roll_values[b] * 10 + roll_values[c]
|
||||||
|
if result not in results:
|
||||||
|
results.append(result)
|
||||||
|
|
||||||
|
return results
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
from gm_assistant.dice import Die
|
from gm_assistant.dice import Die, d666
|
||||||
|
|
||||||
|
|
||||||
def test_parse_empty() -> None:
|
def test_parse_empty() -> None:
|
||||||
@ -143,3 +143,45 @@ def test_roll_complex(mocker: MockerFixture) -> None:
|
|||||||
mocker.call(1, 4),
|
mocker.call(1, 4),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_d666_strict_order(mocker: MockerFixture) -> None:
|
||||||
|
"""Test ``d666()`` with strict dice order"""
|
||||||
|
|
||||||
|
mocked_randint = mocker.patch("gm_assistant.dice.random.randint", side_effect=[2, 4, 6])
|
||||||
|
|
||||||
|
assert d666(strict_order=True) == [246]
|
||||||
|
assert mocked_randint.call_count == 3
|
||||||
|
mocked_randint.assert_has_calls([mocker.call(1, 6), mocker.call(1, 6), mocker.call(1, 6)])
|
||||||
|
|
||||||
|
|
||||||
|
def test_d666_any_order(mocker: MockerFixture) -> None:
|
||||||
|
"""Test ``d666()`` without strict order"""
|
||||||
|
|
||||||
|
mocked_randint = mocker.patch("gm_assistant.dice.random.randint", side_effect=[2, 4, 6])
|
||||||
|
|
||||||
|
assert d666(strict_order=False) == [246, 264, 426, 462, 624, 642]
|
||||||
|
assert mocked_randint.call_count == 3
|
||||||
|
mocked_randint.assert_has_calls([mocker.call(1, 6), mocker.call(1, 6), mocker.call(1, 6)])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("dice_values", [pytest.param((1, 1, 2)), pytest.param((1, 2, 1)), pytest.param((2, 1, 1))])
|
||||||
|
def test_d666_equal_dice(dice_values: tuple[int, int, int], mocker: MockerFixture) -> None:
|
||||||
|
"""Test ``d666()`` when some dice are equal"""
|
||||||
|
|
||||||
|
mocked_randint = mocker.patch("gm_assistant.dice.random.randint", side_effect=dice_values)
|
||||||
|
|
||||||
|
assert set(d666()) == set((112, 121, 211))
|
||||||
|
assert mocked_randint.call_count == 3
|
||||||
|
mocked_randint.assert_has_calls([mocker.call(1, 6), mocker.call(1, 6), mocker.call(1, 6)])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("strict_order", (True, False), ids=("strict", "any"))
|
||||||
|
def test_d666_all_equal(strict_order: bool, mocker: MockerFixture) -> None:
|
||||||
|
"""Test ``d666()`` when all dice are equal"""
|
||||||
|
|
||||||
|
mocked_randint = mocker.patch("gm_assistant.dice.random.randint", return_value=5)
|
||||||
|
|
||||||
|
assert d666(strict_order=strict_order) == [555]
|
||||||
|
assert mocked_randint.call_count == 3
|
||||||
|
mocked_randint.assert_has_calls([mocker.call(1, 6), mocker.call(1, 6), mocker.call(1, 6)])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user