Spaces:
Running on Zero
Running on Zero
| """Run state: the journey between combats. | |
| Phase 0 keeps this minimal β a linear node sequence and the player's | |
| persistent resources. The branching map graph, challenges, and items | |
| arrive in later phases. | |
| """ | |
| from __future__ import annotations | |
| from dataclasses import dataclass, field | |
| from enum import Enum | |
| from .cards import Card | |
| class NodeKind(Enum): | |
| BATTLE = "battle" | |
| SHELL = "shell" # sandbox exploration between fights | |
| ALTAR = "altar" # the Warden's command-for-power deal | |
| CARD_CHOICE = "card_choice" | |
| FORK = "fork" # the path splits; payload is a fork id | |
| class Node: | |
| kind: NodeKind | |
| payload: str = "" # encounter id for battles | |
| class RunState: | |
| deck: list[Card] | |
| nodes: list[Node] | |
| position: int = 0 | |
| cycles: int = 0 | |
| ttys: int = 2 # losses remaining before the run ends | |
| over: bool = False | |
| victorious: bool = False | |
| def current(self) -> Node | None: | |
| return self.nodes[self.position] if self.position < len(self.nodes) else None | |
| def advance(self) -> None: | |
| self.position += 1 | |
| if self.current is None: | |
| self.over = True | |
| self.victorious = True | |
| def lose_tty(self) -> None: | |
| self.ttys -= 1 | |
| if self.ttys <= 0: | |
| self.over = True | |
| self.victorious = False | |
| def resolve_fork(self, encounter_id: str) -> None: | |
| """The player chose a door: the FORK node becomes that battle.""" | |
| node = self.current | |
| if node is None or node.kind is not NodeKind.FORK: | |
| raise ValueError("not standing at a fork") | |
| self.nodes[self.position] = Node(NodeKind.BATTLE, encounter_id) | |
| def new_run( | |
| starter_deck: list[Card], | |
| encounter_ids: list[str], | |
| fork_ids: frozenset[str] = frozenset(), | |
| ) -> RunState: | |
| """battle β shell β altar β draft β battle β β¦ β final battle. | |
| Ids in fork_ids become FORK nodes: the battle is chosen at the door. | |
| """ | |
| nodes: list[Node] = [] | |
| for i, enc in enumerate(encounter_ids): | |
| kind = NodeKind.FORK if enc in fork_ids else NodeKind.BATTLE | |
| nodes.append(Node(kind, enc)) | |
| if i < len(encounter_ids) - 1: | |
| nodes.append(Node(NodeKind.SHELL)) | |
| nodes.append(Node(NodeKind.ALTAR)) | |
| nodes.append(Node(NodeKind.CARD_CHOICE)) | |
| return RunState(deck=list(starter_deck), nodes=nodes) | |