magicciv/.project/objectives/p3-15-hotseat-multiplayer.md

4.7 KiB
Raw Permalink Blame History

id title priority scope owner status updated_at design evidence
p3-15 Local hotseat multiplayer — multiple humans alternating on one device p3 game1 shipwright done 2026-06-19 .project/designs/p3-15-hotseat-multiplayer-design.md
.project/designs/p3-15-hotseat-multiplayer-design.md
src/game/engine/scenes/menus/game_setup.gd
src/game/engine/scenes/menus/loading_screen.gd
src/game/engine/scenes/world_map/world_map.gd
src/game/engine/scenes/hud/hotseat_handoff.gd
src/game/engine/scenes/tests/hotseat_handoff_proof.gd
src/game/engine/src/autoloads/game_state.gd

Context

Owner scope override (2026-06-19): Game 1 was documented single-human vs AI; the owner promoted local hotseat (2+ humans alternating on one device) into scope. The per-player view substrate already exists (fog keyed on player_index, renderers take a local-player, input routes through get_current_player(), is_human is serialized). The gap is: setup can't mark >1 slot human, the view is locked to slot 0, and there's no pass-the-device hand-off.

Full design: .project/designs/p3-15-hotseat-multiplayer-design.md.

Acceptance

  • ✓ Setup lets a slot be Human ("" controller sentinel); a 2-human duel is constructible; create_player honors it. — game_setup.gd "Human" picker option (HUMAN_CONTROLLER_ID); loading_screen.gd:114 now derives is_human from the controller id (was hardcoded i==0).
  • world_map._set_view_player(idx) re-points fog/units/cities/overlay + recomputes displayed fog; called on each human turn start. — world_map.gd _set_view_player; smoke log alternates view → player 0/1.
  • ✓ Pass-the-device hand-off overlay shown on every human turn in hotseat (board hidden until Ready); input gated until Ready. — hotseat_handoff.gd; _awaiting_handoff gates _handle_hex_click + _on_end_turn_pressed.
  • ✓ Player A never sees player B's view. — Screenshot proof (hotseat_view_proof.tscn, 2026-06-19): the SAME game rendered from each human's view shows two different fogged worlds (Alice = arid region around her start; Bjorn = forested region around his) — switching the view re-fogs the whole map to the other player's knowledge. Plus the hand-off occlusion proof: magenta "secret" board fully hidden by the opaque panel (hotseat_handoff_proof.tscn).
  • ✓ Save/resume of a hotseat roster; is_human round-trips. — mid_run.save holds "is_human":true×2; resume keeps the view alternating 0/1 (both humans survive).
  • ✓ Single-human regression: with 1 human, no hand-off, behaviour identical. — Default auto_play run: 0 hotseat log lines, same progression (2 converged + 2 founded), exit 0.
  • ✓ Runtime-proven on plum. — 2-human auto_play smoke (AUTO_PLAY_HUMANS=2, exit 0, no errors) + hand-off visual proof render.
  • Player names: each slot has a name field in setup (humans editable); player_names flows payload → loading_screenplayer_name. AI slots are named after their clan (PersonalityAssigner, deduped). Proof: AUTO_PLAY_PLAYER_NAMES="Alice,Bob" → view shows player 0 (Alice)/player 1 (Bob); 1-human+AI run named AI "Tinkersmith"/"Deepforge"; setup-screen render shows the name fields + per-slot Human/AI pickers.

Per-player opening + randomized order (2026-06-19)

  • Randomized turn orderGameState.randomize_turn_order() (seeded Fisher-Yates, deterministic per map seed) sets turn_order; next_player() rotates through it for the whole game (sequential fallback when unset). Called from loading_screen after players are created. Proof: 3-player game ordered [0, 2, 1].
  • Per-player opening — the opening is no longer a shared cinematic. turn_manager rotates players during the prologue and advances the start-script to the next display-turn only when the round wraps. Result: turn 1 for each player, then a round of 0, then founding → normal turn 1. AI players auto-advance their opening turns (no dispatch — units/cities don't exist yet, start_turn gates on _is_in_prologue()). Each human sees their own wanderers (view-switch + hotseat hand-off now fire during the opening too), camera framed on their convergence centroid. Proof: 2-/3-player traces + hotseat run (view flips Alice/Bjorn from turn 1).
  • GUT testtests/unit/test_turn_order.gd (5/5): permutation completeness, per-seed determinism, sequential fallback, is_last_in_round position tracking.
  • AI-turn view stays on the last human (brief, overlaid by ai_turn_overlay).
  • Test harness hooks: AUTO_PLAY_HUMANS=N, AUTO_PLAY_PLAYER_NAMES, hand-off auto-passes under AUTO_PLAY, _set_view_player + opening rounds log under AUTO_PLAY.