from dataclasses import dataclass from typing import Union from effects import DamageEffect from enums import CombatSide from jsonable import JsonableDataclassArgs from model import Action, Target, Effect, Character, Clock, CombatStatus, log_substitute @dataclass(**JsonableDataclassArgs) class RoleplayAction(Action): text: str user: Target | None effects: tuple[Effect, ...] def do(self, combat: "CombatStatus", source: Union["Action", "Effect", None] = None) -> "CombatStatus": for effect in self.effects: combat = effect.do(combat, self) return combat def undo(self, combat: "CombatStatus", source: Union["Action", "Effect", None] = None) -> "CombatStatus": for effect in reversed(self.effects): combat = effect.undo(combat, self) return combat def log_message(self, user: Target | None = None) -> str | None: return "\n ".join( [log_substitute(self.text, user=self.user, target=self.user)] + [log_substitute(t, user=self.user, target=self.user) for t in [v.log_message(self.user) for v in self.effects] if t is not None] ) @dataclass(**JsonableDataclassArgs) class AbilityAction(Action): name: str user: Target | None costs: tuple[DamageEffect, ...] effects: tuple[Effect, ...] @dataclass(**JsonableDataclassArgs) class ModifyCharacterAction(Action): index: int old_character_data: Character | None new_character_data: Character | None def __post_init__(self): if self.old_character_data is None and self.new_character_data is None: raise ValueError("At least one of old_character_data or new_character_data must be non-None") @dataclass(**JsonableDataclassArgs) class ModifyClockAction(Action): index: int old_clock_data: Clock | None new_clock_data: Clock | None def __post_init__(self): if self.old_clock_data is None and self.new_clock_data is None: raise ValueError("At least one of old_clock_data or new_clock_data must be non-None") @dataclass(**JsonableDataclassArgs) class EndTurnAction(Action): turn_ending_index: int activating_side: CombatSide @dataclass(**JsonableDataclassArgs) class StartTurnAction(Action): turn_starting_index: int old_active_side: CombatSide @dataclass(**JsonableDataclassArgs) class StartRoundAction(Action): last_round: int old_active_side: CombatSide old_turns_remaining: tuple[int, ...] next_round: int activating_side: CombatSide @dataclass(**JsonableDataclassArgs) class StartBattleAction(Action): starting_side: CombatSide starting_round: int @dataclass(**JsonableDataclassArgs) class EndBattleAction(Action): old_round_number: int old_active_side: CombatSide old_starting_side: CombatSide old_turns_remaining: tuple[int, ...]