aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tests/examples/ndice/src/dicer.py
diff options
context:
space:
mode:
authorHsiangNianian <i@jyunko.cn>2025-08-02 11:30:27 +0800
committerHsiangNianian <i@jyunko.cn>2025-08-02 11:30:27 +0800
commitec4566c3d17370c778a1e6cd6b22ed85263731a0 (patch)
tree469258084d3ae0e72db37dd98593731ff20131e4 /tests/examples/ndice/src/dicer.py
parentc68a18ca6440f6460b3b5fce311901229f8f50a9 (diff)
downloadinfini-ec4566c3d17370c778a1e6cd6b22ed85263731a0.tar.gz
infini-ec4566c3d17370c778a1e6cd6b22ed85263731a0.zip
refactor(v3): publish v3 branch
Diffstat (limited to 'tests/examples/ndice/src/dicer.py')
-rw-r--r--tests/examples/ndice/src/dicer.py360
1 files changed, 0 insertions, 360 deletions
diff --git a/tests/examples/ndice/src/dicer.py b/tests/examples/ndice/src/dicer.py
deleted file mode 100644
index 74bb3714..00000000
--- a/tests/examples/ndice/src/dicer.py
+++ /dev/null
@@ -1,360 +0,0 @@
-from multilogging import multilogger
-from typing import List
-
-import abc
-import re
-import random
-
-
-ZERO = 0
-EMPTY_STRING = ""
-EMPTY_LIST = []
-
-logger = multilogger(name="DicerGirl", payload="Dicer")
-
-
-class BaseDice:
- def __init__(self, roll_string: str = EMPTY_STRING) -> None:
- self.roll_string = roll_string
- self.db = EMPTY_STRING
- self.outcome = ZERO
- self.display = EMPTY_LIST
-
- def __repr__(self) -> str:
- return self.db.upper()
-
- @abc.abstractmethod
- def parse(self) -> "BaseDice":
- raise NotImplementedError
-
- @abc.abstractmethod
- def roll(self) -> int:
- """对骰子进行投掷并给出结果"""
- raise NotImplementedError
-
-
-class DigitDice(BaseDice):
- """数字骰"""
-
- def __init__(self, roll_string: str = EMPTY_STRING) -> None:
- super().__init__(roll_string=roll_string)
- if not roll_string.isdigit():
- raise ValueError
-
- self.parse()
-
- def parse(self) -> "DigitDice":
- self.a = int(self.roll_string)
- self.b = 1
- self.db = f"{self.a}"
- return self
-
- def roll(self) -> int:
- self.outcome = self.a
- self.display = [self.a]
- return self.outcome
-
-
-class Dice(BaseDice):
- """多面骰"""
-
- def __init__(self, roll_string: str = "", explode: bool = False) -> None:
- super().__init__(roll_string=roll_string)
- self.dices = EMPTY_LIST
- self.great = False
- self.explode = explode
- self.parse()
-
- def parse(self) -> "Dice":
- self.dices = []
- split = re.split(r"[dD]", self.roll_string)
-
- if split[0]:
- self.a = int(split[0])
- else:
- self.a = 1
-
- if split[1]:
- self.b = int(split[1])
- else:
- self.b = 100
-
- self.db = f"{self.a}D{self.b}"
- self.dices += [f"D{self.b}"] * self.a
- return self
-
- def roll(self) -> int:
- self.results = []
- self.display = []
-
- for _ in range(self.a):
- result = random.randint(1, self.b)
-
- if result == 1 and self.explode:
- result -= 1
-
- if self.explode and self.b == 8:
- self.dices.append("D10")
- result2 = random.randint(1, 10)
- if result2 == 1:
- result -= 1
- result += result2
- if result2 == 10:
- self.dices.append("D12")
- result3 = random.randint(1, 12)
- if result3 == 1:
- result -= 1
- result += result3
- if result3 == 12:
- self.dices.append("D20")
- result4 = random.randint(1, 20)
- if result4 == 1:
- result -= 1
- result += result4
- if result4 == 20:
- self.great = True
-
- self.results.append(result)
- self.display.append(result)
-
- self.outcome = sum(self.results)
- return self.outcome
-
-
-class AwardDice(BaseDice):
- """奖励骰"""
-
- def __init__(self, roll_string: str = "") -> None:
- super().__init__(roll_string=roll_string)
- self.parse()
-
- def parse(self) -> "AwardDice":
- split = re.split(r"[bB]", self.roll_string)
-
- if split[0]:
- self.a = int(split[0])
- else:
- self.a = 1
-
- self.b = int(split[1])
- self.db = f"{self.a}B{self.b}"
- return self
-
- def roll(self) -> int:
- self.results = []
- self.display = []
-
- for _ in range(self.a):
- ten = []
- for _ in range(self.b):
- outcome = Dice("1d10").roll()
- outcome = outcome if outcome != 10 else 0
- ten.append(outcome)
-
- result = Dice("1d100").roll()
- ten.append(result // 10)
- minten = min(ten)
- ten.remove(result // 10)
- outcome = minten * 10 + (result % 10)
- self.results.append(outcome)
- self.display.append([result, ten])
-
- self.outcome = sum(self.results)
- return self.outcome
-
-
-class PunishDice(BaseDice):
- """惩罚骰"""
-
- def __init__(self, roll_string: str = "") -> None:
- super().__init__(roll_string=roll_string)
- self.parse()
-
- def parse(self) -> "PunishDice":
- split = re.split(r"[pP]", self.roll_string)
-
- if split[0]:
- self.a = int(split[0])
- else:
- self.a = 1
-
- self.b = int(split[1])
- self.db = f"{self.a}P{self.b}"
- return self
-
- def roll(self) -> int:
- self.results = []
- self.display = []
-
- for _ in range(self.a):
- ten = []
- for _ in range(self.b):
- outcome = Dice("1d10").roll()
- outcome = outcome if outcome != 10 else 0
- ten.append(outcome)
-
- result = Dice("1d100").roll()
- ten.append(result // 10)
- maxten = max(ten)
- ten.remove(result // 10)
- outcome = maxten * 10 + (result % 10)
- self.results.append(outcome)
- self.display.append([result, ten])
-
- self.outcome = sum(self.results)
- return self.outcome
-
-
-class Dicer:
- """掷骰类
- 参数:
- roll_string: 标准掷骰表达式
- explode: 是否启用爆炸骰
- 示例:
- ```python
- dice = Dice("1d10")
- dice.roll()
- print(dice.outcome) # 输出`1d10`投掷结果
- ```
- """
-
- def __init__(self, roll_string: str = EMPTY_STRING, explode: bool = False) -> None:
- self.roll_string: str = roll_string
- self.explode: bool = explode
- self.calc_list: List[str | Dice | DigitDice | AwardDice | PunishDice] = []
- self.results: List[int] = []
- self.display: List[int | List[int]] = []
- self.outcome: int = ZERO
- self.great: bool = False
- self.dices: List[str] = []
-
- def parse(self, roll_string: str = EMPTY_STRING, explode: bool = False):
- self.roll_string = roll_string if roll_string else self.roll_string
- self.calc_list = []
- self.db = EMPTY_STRING
- matches: List[str] = re.findall(r"\d*[a-zA-Z]\w*|\d+|[-+*/]", self.roll_string)
-
- for match in matches:
- if match in ("+", "-", "*", "/", "(", ")"):
- self.calc_list.append(match)
- self.db += match
- elif re.match(r"\d*[dD]\d*", match):
- self.calc_list.append(Dice(match, explode=explode))
- self.db += match.upper()
- elif re.match(r"\d*[bB]\d+", match):
- self.calc_list.append(AwardDice(match))
- self.db += match.upper()
- elif re.match(r"\d*[pP]\d+", match):
- self.calc_list.append(PunishDice(match))
- self.db += match.upper()
- elif re.match(r"\d+", match):
- self.calc_list.append(DigitDice(match))
- self.db += match.upper()
- else:
- raise ValueError(f"骰 {match} 不符合规范.")
-
- if not matches:
- self.calc_list.append(Dice("1d100"))
- self.db = "1D100"
-
- return self
-
- def roll(self):
- self.parse(roll_string=self.roll_string, explode=self.explode)
- self.dices = []
- self.display = []
- for index, calc in enumerate(self.calc_list):
- if calc in ("+", "-", "*", "/", "(", ")"):
- continue
-
- outcome = calc.roll()
- self.calc_list[index] = outcome
- self.results.append(outcome)
- self.display += calc.display
-
- if isinstance(calc, Dice) and self.explode:
- if calc.great:
- self.great = True
-
- self.dices += calc.dices
-
- self.outcome = eval("".join(map(str, self.calc_list)))
- return self
-
- def description(self):
- def count_integers(lst: list) -> int:
- count = 0
- for item in lst:
- if isinstance(item, int):
- count += 1
- elif isinstance(item, list):
- count += count_integers(item)
- return count
-
- results = self.display
- len_display = count_integers(self.display)
- len_results = count_integers(self.results)
-
- if len_display <= 10:
- results = self.display
- elif len_results <= 10:
- results = self.results
- else:
- results = [...]
-
- return f"{self.db}={results}={self.outcome}"
-
- def get_results(self):
- return self.results
-
- def detail_expr(self):
- return str(self.results)
-
- def calc(self):
- return self.outcome
-
- def __repr__(self):
- return self.db
-
-
-if __name__ == "__main__":
- # text = "-10/d2/1d10+2d2-22/2+3p2+2b10-p4/b2/d2"
- # dice = Dicer(text)
- # print(dice.calc_list)
- # dice.roll()
- # print(dice.calc_list)
- # print(dice.results)
- # print(dice.outcome)
- roll_strings = {
- "1": 1,
- "10": 10,
- "100": 100,
- "-1": -1,
- "-10": -10,
- "-100": -100,
- "1d1": 1,
- "10d1": 10,
- "100d1": 100,
- "10d1+10d1": 20,
- "10d1-10d1": 0,
- "10d1+10d1+10d1": 30,
- "10d1-10d1+10d1": 10,
- "10d1-10d1-10d1": -10,
- }
- for roll_string in roll_strings.keys():
- try:
- dice = Dicer().parse(roll_string).roll().roll()
- if dice.outcome != roll_strings[roll_string]:
- print(dice.description())
- raise ValueError(
- f"对于 {roll_string} dice.toal={dice.outcome} 但期待 {roll_strings[roll_string]}"
- )
- except ValueError as error:
- logger.exception(error)
-
- try:
- roll_string = "d"
- dice = Dicer(roll_string).roll()
- print(dice.description())
- except ValueError as error:
- logger.exception(error)