Two refactors that touch the same handlers and should land together.
ExplorationState. GameSession.__init__ sets 41 instance attributes, and the exploration handlers write them directly with ordering that lives only in the handler bodies: end_encounter resets odometer_thirds; _handle_force_door sets noise_since_check before the roll and appends to alerted_areas after; fatigue, provision, and rest counters are separate fields the handlers coordinate by hand. DungeonState, EncounterState, and BattleState already show the better shape. Group the exploration bookkeeping (odometer, noise flag, alerted areas, fatigue and provision clocks, rest credit) into an ExplorationState model on the session with the same serialized layout, so the invariants have one home and the save format stays additive.
Split exploration.py. At about 3,800 lines it is a flat list of thirty-odd private handlers plus helpers, and every hard tracing question during the docstring pass (which events MoveParty can emit, which handler sets which flag) was there. The handlers are private and dispatched by name, so splitting by concern costs nothing at the API surface: movement and doors, searching and traps, provisions and rest, town, with exploration.py keeping HANDLERS and the public constants. Do this after the HANDLERS decision in the handler-registration issue, since the merged table is what the split has to preserve.
Acceptance: goldens unchanged, schema_version unchanged or bumped with a migration if the state grouping changes the save layout, and the generated event and command pages unchanged.
Two refactors that touch the same handlers and should land together.
ExplorationState.
GameSession.__init__sets 41 instance attributes, and the exploration handlers write them directly with ordering that lives only in the handler bodies:end_encounterresetsodometer_thirds;_handle_force_doorsetsnoise_since_checkbefore the roll and appends toalerted_areasafter; fatigue, provision, and rest counters are separate fields the handlers coordinate by hand.DungeonState,EncounterState, andBattleStatealready show the better shape. Group the exploration bookkeeping (odometer, noise flag, alerted areas, fatigue and provision clocks, rest credit) into anExplorationStatemodel on the session with the same serialized layout, so the invariants have one home and the save format stays additive.Split exploration.py. At about 3,800 lines it is a flat list of thirty-odd private handlers plus helpers, and every hard tracing question during the docstring pass (which events
MovePartycan emit, which handler sets which flag) was there. The handlers are private and dispatched by name, so splitting by concern costs nothing at the API surface: movement and doors, searching and traps, provisions and rest, town, withexploration.pykeepingHANDLERSand the public constants. Do this after theHANDLERSdecision in the handler-registration issue, since the merged table is what the split has to preserve.Acceptance: goldens unchanged,
schema_versionunchanged or bumped with a migration if the state grouping changes the save layout, and the generated event and command pages unchanged.