Spaces:
Running
Running
Case Zero - initial public release (fully local: Qwen2.5-1.5B via llama.cpp + Supertonic, custom pixel-noir SPA via gradio.Server)
414dc55 | """Evidence discovery via non-interrogation channels (search / forensic / document). | |
| Every clue in the solution's minimal set is reachable here, so solvability never | |
| depends on a suspect choosing to talk - the discoverability guarantee in play. | |
| """ | |
| from __future__ import annotations | |
| from ..schemas.case import CaseFile | |
| from ..schemas.clue import Clue | |
| from ..schemas.enums import DiscoveryMethod | |
| from .game_state import GameState | |
| from .state_update import discover_clues | |
| _NON_INTERROGATION = frozenset( | |
| {DiscoveryMethod.SEARCH, DiscoveryMethod.FORENSIC, DiscoveryMethod.DOCUMENT} | |
| ) | |
| def clues_at(case: CaseFile, loc_id: str) -> tuple[Clue, ...]: | |
| """Clues physically discoverable by examining a location.""" | |
| return tuple( | |
| c | |
| for c in case.clues | |
| if c.discoverable_at_loc_id == loc_id and c.discovery_method in _NON_INTERROGATION | |
| ) | |
| def search_location(state: GameState, case: CaseFile, loc_id: str) -> tuple[GameState, tuple[Clue, ...]]: | |
| found = clues_at(case, loc_id) | |
| newly = tuple(c for c in found if c.clue_id not in state.discovered_clue_ids) | |
| new_state = discover_clues(state, tuple(c.clue_id for c in newly), case) | |
| return new_state, newly | |
| def available_evidence(state: GameState, case: CaseFile) -> tuple[Clue, ...]: | |
| """Discovered clues the player currently holds and may present to suspects.""" | |
| return tuple(c for c in case.clues if c.clue_id in state.discovered_clue_ids) | |