phantom-grid / game /state.py
unity4ar's picture
Ship Phantom Grid Docker Space
d2e6f94 verified
Raw
History Blame Contribute Delete
8.76 kB
from __future__ import annotations
from dataclasses import asdict, dataclass, field
from typing import Any
@dataclass
class CulpritMove:
turn_number: int
from_junction: int
to_junction: int
mode: str
route: list[int]
changed_disguise: bool = False
risk_level: str = "unknown"
@dataclass
class CulpritState:
current_junction: int
current_disguise: str
remaining_disguise_changes: int
route_history: list[CulpritMove] = field(default_factory=list)
@dataclass
class CaseLandmark:
venue_id: str
name: str
category: str
junction_id: int
canonical_place_id: str | None = None
description: str = ""
@dataclass
class ObservableFact:
fact_id: str
turn_number: int
junction_id: int
kind: str
text: str
tags: list[str] = field(default_factory=list)
place_id: str | None = None
@dataclass
class StorySegment:
segment_id: str
turn_number: int
from_junction: int
to_junction: int
mode: str
route: list[int]
changed_disguise: bool
previous_disguise: str
new_disguise: str
narrative: str
private_reasoning: str = ""
observable_facts: list[ObservableFact] = field(default_factory=list)
context_profile: dict[str, Any] = field(default_factory=dict)
@dataclass
class StoryMemory:
continuity_synopsis: str = ""
recent_segment_ids: list[str] = field(default_factory=list)
permanent_facts: list[str] = field(default_factory=list)
@dataclass
class PotentialWitness:
potential_id: str
turn_created: int
junction_id: int
observed_fact_ids: list[str]
profile: dict[str, Any]
reliability: float
memory_strength: float
voice_id: str
summary: str
search_tags: list[str] = field(default_factory=list)
surfaced_notice_id: str | None = None
@dataclass
class LookoutNotice:
notice_id: str
turn_number: int
text: str
parsed_location: str | None = None
parsed_description: str | None = None
genericness_score: float = 0.0
false_positive_likelihood: float = 0.0
response_plan: list[dict[str, Any]] = field(default_factory=list)
@dataclass
class WitnessQuestion:
question: str
answer: str
turn_number: int
@dataclass
class WitnessRecord:
witness_id: str
notice_id: str
turn_created: int
junction_id: int
personality: dict[str, Any]
reliability: float
memory_strength: float
corruption_level: float
relevance_score: float
original_summary: str
current_summary: str
stable_facts: list[str] = field(default_factory=list)
fragile_facts: list[str] = field(default_factory=list)
question_history: list[WitnessQuestion] = field(default_factory=list)
name: str = "Unknown witness"
occupation: str = "local resident"
voice_id: str = "voice_01"
observed_fact_ids: list[str] = field(default_factory=list)
conversation_summary: str = ""
is_false_positive: bool = False
@dataclass
class WitnessBatch:
batch_id: str
notice_id: str
turn_number: int
total_witnesses: int
individual_review_allowed: bool
witnesses: list[WitnessRecord] = field(default_factory=list)
@dataclass
class PoliceBlock:
block_id: str
turn_created: int
block_type: str
turns_remaining: int
mode: str | None = None
from_junction: int | None = None
to_junction: int | None = None
junction_id: int | None = None
district: str | None = None
@dataclass
class PlacedTactic:
tactic_id: str
tactic_type: str
turn_created: int
junction_id: int
x: int
y: int
linked_block_id: str | None = None
@dataclass
class JunctionCheck:
check_id: str
turn_number: int
junction_id: int
result: str
@dataclass
class GameState:
game_id: str
turn_number: int
max_turns: int
phase: str
initial_description: str
culprit: CulpritState
last_seen_junction: int | None = None
case_profile: dict[str, Any] = field(default_factory=dict)
case_introduction: dict[str, Any] = field(default_factory=dict)
notices: list[LookoutNotice] = field(default_factory=list)
witness_batches: list[WitnessBatch] = field(default_factory=list)
active_blocks: list[PoliceBlock] = field(default_factory=list)
placed_tactics: list[PlacedTactic] = field(default_factory=list)
viewed_witness_ids: list[str] = field(default_factory=list)
junction_checks: list[JunctionCheck] = field(default_factory=list)
game_log: list[dict[str, Any]] = field(default_factory=list)
result: str | None = None
story_segments: list[StorySegment] = field(default_factory=list)
story_memory: StoryMemory = field(default_factory=StoryMemory)
case_landmarks: list[CaseLandmark] = field(default_factory=list)
potential_witnesses: list[PotentialWitness] = field(default_factory=list)
user_notes: str = ""
last_notice_text: str = ""
finalized_reason: str | None = None
effective_context_length: int = 8192
def to_dict(self) -> dict[str, Any]:
return asdict(self)
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "GameState":
culprit_data = data["culprit"]
route_history = [CulpritMove(**move) for move in culprit_data.get("route_history", [])]
culprit = CulpritState(
current_junction=culprit_data["current_junction"],
current_disguise=culprit_data["current_disguise"],
remaining_disguise_changes=culprit_data["remaining_disguise_changes"],
route_history=route_history,
)
notices = [LookoutNotice(**notice) for notice in data.get("notices", [])]
batches = [_witness_batch_from_dict(batch) for batch in data.get("witness_batches", [])]
blocks = [PoliceBlock(**block) for block in data.get("active_blocks", [])]
placed_tactics = [PlacedTactic(**tactic) for tactic in data.get("placed_tactics", [])]
checks = [JunctionCheck(**check) for check in data.get("junction_checks", [])]
story_segments = [_story_segment_from_dict(item) for item in data.get("story_segments", [])]
story_memory = StoryMemory(**data.get("story_memory", {}))
case_landmarks = [CaseLandmark(**item) for item in data.get("case_landmarks", [])]
potential_witnesses = [PotentialWitness(**item) for item in data.get("potential_witnesses", [])]
return cls(
game_id=data["game_id"],
turn_number=data["turn_number"],
max_turns=data["max_turns"],
phase=data["phase"],
initial_description=data["initial_description"],
culprit=culprit,
last_seen_junction=data.get("last_seen_junction"),
case_profile=data.get("case_profile", {}),
case_introduction=data.get("case_introduction", {}),
notices=notices,
witness_batches=batches,
active_blocks=blocks,
placed_tactics=placed_tactics,
viewed_witness_ids=data.get("viewed_witness_ids", []),
junction_checks=checks,
game_log=data.get("game_log", []),
result=data.get("result"),
story_segments=story_segments,
story_memory=story_memory,
case_landmarks=case_landmarks,
potential_witnesses=potential_witnesses,
user_notes=data.get("user_notes", ""),
last_notice_text=data.get("last_notice_text", ""),
finalized_reason=data.get("finalized_reason"),
effective_context_length=int(data.get("effective_context_length", 8192)),
)
def _witness_batch_from_dict(data: dict[str, Any]) -> WitnessBatch:
witnesses: list[WitnessRecord] = []
for witness in data.get("witnesses", []):
questions = [WitnessQuestion(**question) for question in witness.get("question_history", [])]
witness = {**witness, "question_history": questions}
witnesses.append(WitnessRecord(**witness))
return WitnessBatch(
batch_id=data["batch_id"],
notice_id=data["notice_id"],
turn_number=data["turn_number"],
total_witnesses=data["total_witnesses"],
individual_review_allowed=data["individual_review_allowed"],
witnesses=witnesses,
)
def _story_segment_from_dict(data: dict[str, Any]) -> StorySegment:
facts = [ObservableFact(**fact) for fact in data.get("observable_facts", [])]
return StorySegment(**{**data, "observable_facts": facts})