4.6 KiB
4.6 KiB
| id | title | priority | status | scope | owner | updated_at | evidence | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| p0-12 | Save / load + autosave on quit | p0 | done | game1 | shipwright | 2026-04-17 |
|
Summary
Save/load UI, autosave-on-quit hook, multi-slot naming, schema version with rejection of mismatches, and GDScript + Rust round-trip tests all shipped. The three serde regressions that reopened this objective on 2026-04-17 are closed:
WonderIdnewtype serialized as an array, not a string — fixed by Testwright via#[serde(transparent)]atmc-core/src/wonder.rs:5.strategic_axes+TechState.progressnon-deterministic key order — fixed by changing both fields fromHashMap<String, _>→BTreeMap<String, _>inmc-turn/src/game_state.rs. BTreeMap iteration is sorted, so JSON output is byte-stable across processes. The three#[ignore]attributes ongame_state_json_roundtrip_is_stable,player_state_json_roundtrip_is_stable, andtech_state_json_roundtrip_is_stablehave been removed; all pass.PlayerState.relationstuple-keyed map fails serde_json — fixed by arelations_as_pairsserde adapter module inmc-turn/src/game_state.rsthat round-trips the map asVec<((u8, u8), RelationState)>. The T2 fixture now populates a(0, 1) → Peacerelation and assertsrelations.is_empty() == falseplus field preservation after round-trip.
Full mc-turn test suite green: 89 passed, 0 failed, 1 ignored (unrelated). All 5 tests in mc-turn/tests/serde_roundtrip.rs pass.
Acceptance
- ✓ Save/load from main menu + in-game pause —
scenes/menus/load_game.gdcallslist_saves()+load_named_slot();scenes/ui/ingame_menu.gdcallssave_to_named_slot(). - ✓ Autosave on quit —
scenes/main/main.gdhandlesNOTIFICATION_WM_CLOSE_REQUEST→SaveManagerScript.autosave()beforequit(). - ✓ Byte-identical T100 turn_stats after save-at-T50 + load-back —
AUTO_PLAY_SAVE_AT=Nwritesmid_run.save+ quits;AUTO_PLAY_LOAD_AUTOSAVE=<path>resumes from that save after world loads. Integration test harness:scripts/autoplay/test_save_resume.sh.SaveManager.load_from_path()added for absolute-path loads. - ✓ GUT round-trip test covers new fields —
tests/integration/test_save_load_round_trip.gd(9 tests incl. traded_luxuries, clan_id, GameState.diplomacy, wonders_built). - ✓
SCHEMA_VERSIONrejection —save_manager.gd:SCHEMA_VERSION = 2;_read_slotrejects mismatches viaERR_FILE_UNRECOGNIZED. Test:test_wrong_schema_version_rejected. - ✓ NEW 2026-04-17: Rust serde round-trip of PlayerState.wonders_built —
WonderId(pub String)was missing#[serde(transparent)]; fixed atmc-core/src/wonder.rs:5. Full workspace cargo test green on apricot after fix (11 crates, ~700 tests). Surfaced + fixed by Testwright. - ✓ 2026-04-17: HashMap → BTreeMap for deterministic save ordering —
PlayerState.strategic_axes: BTreeMap<String, u8>atmc-turn/src/game_state.rs:89andTechState.progress: BTreeMap<String, u32>atmc-turn/src/game_state.rs:202. Call sites inprocessor.rs,snapshot.rs,victory.rs,processor_invariants.rs,gpu/mod.rs,bridge_contract_tests.rs,api-gdext/src/{lib,ai}.rs,mc-sim/src/{lib,bin/*}.rs, and the integration tests updated to match. Previously-#[ignore]'d tests now pass:game_state_json_roundtrip_is_stable,player_state_json_roundtrip_is_stable,tech_state_json_roundtrip_is_stableatmc-turn/tests/serde_roundtrip.rs. - ✓ 2026-04-17: PlayerState.relations diplomacy round-trip —
relations_as_pairsserde adapter atmc-turn/src/game_state.rs:19-35serializesBTreeMap<(u8, u8), RelationState>asVec<((u8, u8), RelationState)>. Annotated via#[serde(default, with = "relations_as_pairs")]atmc-turn/src/game_state.rs:149. Fixture inmc-turn/tests/serde_roundtrip.rs::populated_playernow inserts a(0, 1) → Peacerelation with populatedpeaceful_turns/trade_turns; test asserts!restored.relations.is_empty()and that the round-tripped values match.
Non-goals
- Cloud saves (Game 2).
- Save-file encryption or DRM.