docs(objectives): 📝 Clarify feedback details for world map input, tribe founding, and village discovery objectives
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
88bbe38143
commit
25af0cf81d
3 changed files with 267 additions and 0 deletions
|
|
@ -0,0 +1,72 @@
|
|||
---
|
||||
id: p0-33
|
||||
title: World-map input and panel wiring — unit selection, movement mode, city screen, ESC/F10 menu
|
||||
priority: p0
|
||||
scope: game1
|
||||
owner: wireguard
|
||||
status: partial
|
||||
updated_at: 2026-04-17
|
||||
evidence:
|
||||
- src/game/engine/scenes/world_map/world_map.tscn
|
||||
- src/game/engine/scenes/world_map/world_map.gd
|
||||
- src/game/engine/scenes/hud/world_map_hud.gd
|
||||
- src/game/engine/scenes/city/city_screen.gd
|
||||
- src/game/engine/scenes/main/main.gd
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The world-map is unplayable because basic interaction is broken: clicking a unit does nothing visible, clicking a city does nothing, and there is no way to exit the game (ESC and F10 are both dead). Five discrete wiring gaps are responsible:
|
||||
|
||||
1. **Unit selection produces no feedback** — `_select_unit()` in `world_map.gd` calls `_hud.show_unit_panel()` (the slim programmatic panel in `world_map_hud.gd`) and emits `EventBus.unit_selected`, but the panel is either invisible or off-screen. The richer `unit_panel.tscn` (which listens on `EventBus.unit_selected` and renders full stats + action buttons) is never instantiated in the scene tree.
|
||||
|
||||
2. **City single-click enters bombard mode, not city screen** — `_handle_hex_click()` (lines ~350-358 of `world_map.gd`) checks `not city_ref.has_bombarded` and sets `_bombard_city`, consuming the click without opening the city screen. The city screen only opens via double-click through `_unhandled_input`. Single-click on a city should open the city screen; bombard should require an explicit secondary action (right-click or dedicated button).
|
||||
|
||||
3. **F10 is unbound** — no `KEY_F10` handler anywhere in the project.
|
||||
|
||||
4. **ESC does not open the in-game menu** — `main.gd._unhandled_key_input` has the correct logic (`push_overlay("res://engine/scenes/ui/ingame_menu.tscn")`) but it may be racing with `world_map.gd._unhandled_input` or simply not firing when expected. Needs verification and a reliable binding for both ESC (when no panel is open) and F10 (always).
|
||||
|
||||
5. **ESC does not close open panels** — `city_screen.gd` has no `_unhandled_input` / `_unhandled_key_input` handler; closing requires clicking the close button. ESC should close the top-most open panel (city screen, tech tree, chronicle) and bubble up to the in-game menu only when no panel is open.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- ✓ Clicking a player unit on the world map selects it: the unit sprite shows a selection ring/highlight, reachable hexes are overlaid, and the unit info panel appears showing unit name, HP/ATK/DEF/Movement stats and (where applicable) Found City / Build Improvement / Fortify / Skip Turn / Move action buttons.
|
||||
- ✓ Action buttons that cannot fire (no movement remaining, wrong unit type) appear with red outline + disabled tooltip explaining why.
|
||||
- ✓ Single-clicking a city hex opens the city screen (`city_screen.open_city(city_ref)`). Bombard is removed from the single-click path.
|
||||
- ✓ **Movement mode**: pressing M or clicking the Move button enters movement mode. The map shows a path preview (orange line of hex outlines) that updates as the cursor hovers. Right-click confirms the move; ESC cancels and returns to selection. Right-click-hold lets the player drag to explore alternate routes; releasing confirms.
|
||||
- ✓ Multi-turn paths show a turn-count label on the final hex when the path exceeds one turn's movement budget.
|
||||
- ✓ Fog-of-war-aware pathing: A* through scouted hexes, straight `hex_line()` through unscouted fog.
|
||||
- ✓ Pressing ESC with no panel open opens the in-game menu (Resume / Save / Load / Quit).
|
||||
- ✓ Pressing F10 at any time opens the in-game menu.
|
||||
- ✓ Pressing ESC while the city screen is open closes it without opening the in-game menu.
|
||||
- ✓ Pressing ESC while the tech tree or chronicle is open closes it.
|
||||
- ✓ The in-game menu closes on ESC.
|
||||
|
||||
## Files to touch
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `src/game/engine/scenes/hud/tutorial_overlay.gd` | Line 84: `MOUSE_FILTER_STOP` → `MOUSE_FILTER_PASS` (root cause of all click failures) |
|
||||
| `src/game/engine/src/autoloads/event_bus.gd` | Add signals: `ingame_menu_requested`, `movement_mode_entered`, `movement_mode_exited` |
|
||||
| `src/game/engine/scenes/main/main.gd` | Connect `EventBus.ingame_menu_requested`; verify ESC/F10 logic |
|
||||
| `src/game/engine/scenes/world_map/world_map.gd` | Movement mode state + enter/exit/preview; right-click confirm; M key; `move_pressed` wire; ESC in movement mode; city single-click (already done) |
|
||||
| `src/game/engine/scenes/world_map/world_map_hover.gd` | Invoke path preview update when movement mode active |
|
||||
| `src/game/engine/src/rendering/unit_renderer.gd` | `show_path_preview(path, turns)`, `clear_path_preview()`, orange line in `_draw()` |
|
||||
| `src/game/engine/scenes/hud/unit_panel.tscn` | Add MoveButton to ButtonRow |
|
||||
| `src/game/engine/scenes/hud/unit_panel.gd` | `move_pressed` signal; Move button wiring; disabled-state tooltips for all action buttons |
|
||||
| `src/game/engine/src/map/hex_utils.gd` | `hex_line()` static method for fog-of-war straight-line pathing |
|
||||
| `public/games/age-of-dwarves/data/vocabulary.json` | `"move"`, `"tooltip_move"`, `"tooltip_move_no_movement"` |
|
||||
|
||||
## Depends on
|
||||
|
||||
- None — all affected files are already in the repo; this is pure wiring.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Right-click context menus for bombard (defer to a future UI pass).
|
||||
- Intelligence staleness / stale enemy data system (new P2 objective).
|
||||
- Touch / gamepad input (desktop-only for Early Access).
|
||||
|
||||
## Why this is P0
|
||||
|
||||
A player who cannot select units, open city screens, or exit the game cannot play. This is the first thing a new player encounters and the first thing that breaks in QA. p0-09 marked city-screen *content* done; this is the complementary gate that makes it reachable.
|
||||
159
.project/objectives/p0-34-freepeople-tribe-founding.md
Normal file
159
.project/objectives/p0-34-freepeople-tribe-founding.md
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
---
|
||||
id: p0-34
|
||||
title: Freepeople tribe-founding cinematic — turn -1 / 0 / 1 start sequence and Dwarf Tribe founder unit
|
||||
priority: p0
|
||||
scope: game1
|
||||
owner: shipwright
|
||||
status: missing
|
||||
updated_at: 2026-04-17
|
||||
evidence:
|
||||
- public/resources/villages/freepeople.json
|
||||
- public/resources/ai/freepeople/freepeople.json
|
||||
- src/simulator/crates/mc-turn/
|
||||
- src/simulator/crates/mc-core/
|
||||
- src/game/engine/scenes/world_map/world_map.gd
|
||||
- public/games/age-of-dwarves/data/units/
|
||||
- public/games/age-of-dwarves/data/setup.json
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
Game 1 currently drops the player on turn 1 with a pre-placed founder (settler) unit, which is narratively flat: "here is your settler, go." The collective wants the opening to *tell* the player why they are leading this civilization. A dwarf civilization begins when wandering freedwarves converge on a shared location and coalesce into a tribe — that tribe then founds the first city. This objective encodes that story as a three-turn cold-open (`-1 → 0 → 1`) using systems already partially in the codebase (freepeople camps, turn processor, founder units).
|
||||
|
||||
Secondary purpose: the mechanic carries a variance knob (**tournament** vs **lucky** mode) that governs whether starting position is deterministically fair or luck-seeded, without forcing that variance onto every unit in the game. Because the variance attaches to the *founding* pop only, a distinct **Dwarf Tribe** unit — separate from the ordinary **Founder** (settler/pioneer) produced later — is required.
|
||||
|
||||
## Summary
|
||||
|
||||
Implement a scripted opening sequence that runs on turns **-1**, **0**, and **1** before normal gameplay begins. Turn numbering skips from -1 to 0 to 1 (no "turn -0.5" or similar; -1 and 0 are both real turns but the player has no unit to command).
|
||||
|
||||
1. **Turn -1 — Dispersed wanderers.** A **spawn box** is placed around each player's designated starting region. Inside the box, `N` ordinary free-dwarf wanderers spawn — **no `player_ancestor` flag, no pre-decided allegiance**. They are just freepeople. Each wanderer independently rolls a movement direction for turn -1 → 0. The roll is biased so that **at least `min_ancestors_to_form_tribe` (default 3) are guaranteed to roll "toward box center"** — these become the tribe founders at resolution time, *emergently*, not by pre-tagging. The remaining wanderers roll freely and may move outward or laterally. Fog is partially lifted so the player sees the whole box. The only legal input is **End Turn** (or Enter).
|
||||
2. **Turn 0 — Convergence / tribe formation.** Wanderers step along their rolled directions (deterministic from seed). At end-of-turn-0 resolution: the wanderers that ended up within `tribe_convergence_radius` of the box centroid merge into a single **Dwarf Tribe** unit at the centroid hex and are consumed. This is the player's founding tribe. **Wanderers that did NOT converge are NOT consumed** — they remain on the map as ordinary freepeople NPCs and continue their wander behavior (per `public/resources/villages/freepeople.json` rules). Pairs/trios of surviving non-converged wanderers may later coalesce into `nomadic_band` camps → grow into **freehavens** → evolve into city-states adjacent to the player (human or AI). This is the same mechanic as the player's own founding, applied generally: **any** 3+ freepeople that get within convergence radius form a camp; camps grow into havens. Again the only legal input is End Turn during this opening.
|
||||
3. **Turn 1 — First city.** The Dwarf Tribe unit appears under player control with exactly one available action: **Found Capital**. On founding, the capital's starting population is determined by the mode (see below), the Dwarf Tribe unit is consumed, and normal Game 1 play begins. All *subsequent* settlers built by cities are ordinary **Founder** units that always produce a pop-1 city.
|
||||
|
||||
### Starting-population modes
|
||||
|
||||
| Mode | Formula | Cap |
|
||||
|---|---|---|
|
||||
| **Tournament** | Starting pop = **1**, regardless of how many wanderers converged (min 3 still required). Guaranteed-convergence count is pinned to exactly 3; no extras are biased inward. | Fixed. |
|
||||
| **Lucky** (default for single-player casual) | Starting pop = `1 + floor((wanderers_converged - 3) / 3)` — each wanderer past the 3rd contributes **+1/3 pop**, rounded down at founding. Extra inward-biased rolls (beyond the guaranteed 3) are possible so variance can go up. | `max_lucky_bonus_pop = 3` (pop 4 from 12 converged). Tunable in `setup.json`. |
|
||||
|
||||
Rationale: tournament mode guarantees identical starting conditions across all five AI clans + human player for balanced tournaments / multi-seed validation batches. Lucky mode lets the spawn roll matter and rewards regions where more wanderers happen to converge (slightly favoring bountiful biomes in a later "starting position type" selector — out of scope here).
|
||||
|
||||
### Roll bias mechanics
|
||||
|
||||
For each player's spawn box of `N` wanderers (`N ≈ 3..12`, seeded per map):
|
||||
- **Tournament**: exactly 3 wanderers get `direction = inward`; the remaining `N-3` roll uniformly from all 6 hex directions.
|
||||
- **Lucky**: 3 wanderers are pinned inward (floor guarantee); each of the remaining `N-3` independently rolls `inward_bias_prob` (default `0.33`) to also go inward, else uniform. This lets 3–`N` converge.
|
||||
- "Inward" means "one of the 2 hex directions whose dot product with `centroid - wanderer_pos` is most positive" — picked uniformly among ties, still deterministic from seed.
|
||||
|
||||
### Non-converging wanderers become ordinary freepeople
|
||||
|
||||
Wanderers that drift outward / laterally on turn 0 are not special. They persist as standard freepeople NPCs and feed into the existing system:
|
||||
- They continue wandering via the scripted AI in `public/resources/ai/freepeople/freepeople.json`.
|
||||
- When 3+ freepeople (from *any* source — prologue drift, ongoing camp expansion, migration) get within `tribe_convergence_radius` of each other, they form a `nomadic_band` camp (`freepeople.json:camp_types[0]`).
|
||||
- Camps grow per `freepeople.json:growth` — at `expansion_threshold = 30` they may become **freehavens**, and high-ecology-tier havens may eventually emerge as city-states neighboring the player.
|
||||
- This means the opening cinematic *also* seeds rival neighbors: players who spawned with a dense box get more surviving drifters → more potential adjacent freehavens → more mid-game pressure. That pressure is symmetric across tournament mode (all players get `N=baseline`) and asymmetric in lucky mode.
|
||||
|
||||
### Why Dwarf Tribe ≠ Founder
|
||||
|
||||
- **Dwarf Tribe** (new unit): spawned only by the turn-0 convergence event. Carries `founding_pop_override: int` set at spawn time. Has one action: **Found Capital**. Cannot be built by cities. Never appears again after turn 1.
|
||||
- **Founder** (existing settler/pioneer unit): built normally by cities starting from turn 2+. Always founds a pop-1 city. No `founding_pop_override`.
|
||||
|
||||
Keeping them separate means the variance only exists at game-start, not inside the mid-game economy.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- ✓ New game starts on **turn -1**, not turn 1. Turn counter visibly reads `-1`.
|
||||
- ✓ On turn -1, each player's spawn box contains `N` (3–12) ordinary free-dwarf wanderer sprites. **None** carry a `player_ancestor` flag — allegiance is emergent from their turn-0 roll.
|
||||
- ✓ On turn -1, **End Turn** (button + Enter key) is the only enabled input. No unit is selectable. City / tech / menu overlays remain reachable per p0-33.
|
||||
- ✓ Per-wanderer direction rolls use the seeded PRNG and respect the tournament/lucky bias rules above. Guaranteed-inward count ≥ 3 by construction; convergence cannot fail.
|
||||
- ✓ Turn counter advances -1 → 0. Wanderers step along their rolled directions (one hex, deterministic).
|
||||
- ✓ On turn 0, **End Turn** is again the only enabled input.
|
||||
- ✓ At end-of-turn-0, wanderers within `tribe_convergence_radius` of the box centroid merge into one **Dwarf Tribe** unit with `founding_pop_override` computed per mode. Non-converging wanderers are **left on the map** as ordinary freepeople NPCs — not deleted, not flagged.
|
||||
- ✓ Subsequent freepeople convergence (any 3+ freepeople within radius of each other at end-of-turn) forms a `nomadic_band` camp per `freepeople.json` rules — the same mechanic that formed the player's tribe, now available to the general freepeople population for the rest of the game.
|
||||
- ✓ Turn counter advances 0 → 1 (explicitly skipping any "turn 0.x"). Dwarf Tribe unit is selectable and player-controlled.
|
||||
- ✓ Dwarf Tribe unit's action bar shows **only** `Found Capital`. No Move, no Skip Turn, no Fortify.
|
||||
- ✓ Founding the capital creates a city with `population = founding_pop_override`. Dwarf Tribe unit is consumed.
|
||||
- ✓ On turn 2+, settlers built by cities produce pop-1 cities (ordinary Founder behavior).
|
||||
- ✓ `setup.json` exposes `start_mode: "tournament" | "lucky"` and `lucky_max_bonus_pop: int`. Autoplay batches default to `tournament`.
|
||||
- ✓ A deterministic seed produces byte-identical turn -1 → 0 → 1 state across runs (p1-09 determinism gate covers this once wired).
|
||||
- ✓ Same sequence runs for each AI player (AI clans also start with Dwarf Tribes that converge on turn 0 and found on turn 1). Off-camera for AI — no cinematic delay.
|
||||
- ✓ Chronicle log records: `tribe_converged` on turn 0, `capital_founded` on turn 1.
|
||||
|
||||
## Files to touch / create
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `public/games/age-of-dwarves/data/setup.json` | Add `start_turn: -1`, `tribe_convergence_radius: 1`, `start_mode: "tournament"`, `lucky_max_bonus_pop: 3`, `min_wanderers_to_form_tribe: 3`, `spawn_box_size: {radius: 3}`, `spawn_box_wanderer_count: {tournament: 3, lucky: [6, 12]}`, `lucky_inward_bias_prob: 0.33`. |
|
||||
| `public/games/age-of-dwarves/data/units/dwarf_tribe.json` | **NEW** — Dwarf Tribe unit definition: 1 HP, 0 ATK/DEF, 0 movement (stationary on turn 1), actions `["found_capital"]`, `not_buildable: true`, `founding_pop_override: 1` (default, overridden at spawn). |
|
||||
| `public/games/age-of-dwarves/data/units/dwarf_wanderer.json` | **NEW** — single-dwarf freepeople NPC. Ordinary freepeople, no player allegiance. On prologue turns, direction is set by the seeded roll; afterward it follows standard freepeople AI and participates in generic 3+ freepeople → `nomadic_band` formation. |
|
||||
| `src/simulator/crates/mc-turn/src/lib.rs` | Extend turn counter to support negative turn values; add `PrologueState::{TurnMinusOne, TurnZero, Normal}` phase enum that gates player input and schedules the convergence event. Skip turn-number 0.x — explicit `-1 → 0 → 1` progression. |
|
||||
| `src/simulator/crates/mc-core/src/player.rs` (or equivalent) | Track `spawn_box_centroid: HexCoord` per player during prologue; clear on capital founding. No ancestor-tagging on wanderers. |
|
||||
| `src/simulator/crates/mc-mapgen/` | On map generation, for each player, place a spawn box around the chosen start tile and populate it with `N` generic freepeople wanderers (count per mode). Wanderers are scattered so none are within `tribe_convergence_radius` of the centroid yet. |
|
||||
| `src/simulator/crates/mc-turn/src/prologue.rs` | **NEW** — seeded per-wanderer direction rolls with guaranteed-inward floor of 3; end-of-turn-0 convergence detection based on *position*, not ancestry flag; spawns Dwarf Tribe from converging wanderers; leaves non-converging wanderers on the map as ordinary freepeople. Computes `founding_pop_override` from mode. Emits `tribe_converged` event. |
|
||||
| `src/simulator/crates/mc-ecology/src/behavior.rs` (or new `mc-freepeople`) | Generalize the 3+ freepeople → `nomadic_band` camp formation so it runs every turn on *all* freepeople NPCs, not just the prologue's leftovers. Drives freehaven → city-state emergence over the long game. |
|
||||
| `src/simulator/crates/mc-city/src/lib.rs` | `found_city` accepts an optional `override_population` so Dwarf Tribe founding respects it; ordinary Founders pass `None`. |
|
||||
| `src/game/engine/scenes/world_map/world_map.gd` | During `PrologueState::TurnMinusOne`/`TurnZero`, disable unit selection, hex actions, and bombard paths; keep End Turn + ESC/F10 + panel overlays live. |
|
||||
| `src/game/engine/scenes/hud/world_map_hud.gd` | Show a prologue banner ("Your wanderers gather...") on turns -1/0; hide unit panel. |
|
||||
| `src/game/engine/scenes/world_map/world_map.gd` | Add cinematic camera pan-to-centroid on turn 0 resolution. |
|
||||
| `src/simulator/crates/mc-turn/src/chronicle.rs` | Emit `tribe_converged { player_id, centroid, ancestors_merged, founding_pop }` and `capital_founded { ... }` entries. |
|
||||
|
||||
## Non-goals
|
||||
|
||||
- **Starting-position-type selector** ("bountiful / ocean / river / volcano / island") — that's a Game 2+ add-on per user. Explicitly deferred.
|
||||
- **Wanderer combat.** Wanderers cannot fight and cannot be attacked during the prologue turns (-1, 0). After turn 1, surviving non-converged wanderers become ordinary freepeople and take on normal combat rules.
|
||||
- **Freehaven → city-state promotion timing.** The general mechanic that any 3+ freepeople → camp → haven → city-state is in scope for this objective, but tuning the growth curve (turns per promotion, yield thresholds) is deferred to a follow-up balance objective.
|
||||
- **AI clan personality influencing wanderer paths.** All prologues use identical convergence logic; the five clan personalities kick in from turn 1.
|
||||
- **Animating the merge as a sprite fusion effect** beyond a simple sprite-swap + particle puff. Polish is p2-level.
|
||||
|
||||
## Depends on
|
||||
|
||||
- **p0-14** (map generation balanced starts) — prologue needs a guaranteed viable starting region. ✅ done.
|
||||
- **p0-33** (world-map input + panel wiring) — End Turn / ESC / F10 must work before we restrict every other input. 🟡 partial.
|
||||
|
||||
## Blocks
|
||||
|
||||
- **p0-24** (difficulty-calibrated AI progression) — AI clans need deterministic starting pop to benchmark tier-peak progression. Tournament mode unlocks this.
|
||||
- **p1-09** (determinism gate) — prologue is part of the byte-identical seed contract.
|
||||
|
||||
## TDD build order
|
||||
|
||||
This objective is a good fit for test-driven development: the prologue is pure simulation logic (Rust), deterministic from seed, with no rendering dependency. Build the Rust core first, red → green → refactor, then layer Godot presentation.
|
||||
|
||||
Suggested red-test-first sequence (each bullet = one commit, test first, implementation second):
|
||||
|
||||
1. **Turn counter supports negatives.** Red: `mc_turn::tests::new_game_starts_at_turn_minus_one` asserts `state.turn == -1`. Green: widen turn counter to `i32`, add `PrologueState` enum.
|
||||
2. **-1 → 0 → 1 progression, no 0.5.** Red: `turn_sequence_minus_one_zero_one` drives three `end_turn()` calls, asserts exact sequence `[-1, 0, 1]`. Green: advance function emits the three phases.
|
||||
3. **Input gate during prologue.** Red: `player_input_locked_on_prologue_turns` asserts `allowed_actions(player)` returns only `["end_turn"]` on -1 and 0. Green: gate in `mc-turn`.
|
||||
4. **Spawn box populates correctly.** Red: `mapgen_places_N_wanderers_in_spawn_box` — for tournament mode N=3, lucky mode N∈[6,12], all within box, none within convergence radius of centroid. Green: implement spawn box in `mc-mapgen`.
|
||||
5. **Per-wanderer direction roll, seeded.** Red: `same_seed_same_directions` — two runs with the same seed produce identical per-wanderer directions. Green: PRNG-driven roll.
|
||||
6. **Tournament mode: exactly 3 inward.** Red: `tournament_mode_exactly_3_inward` asserts inward count == 3 for 100 seeds. Green: pinned bias.
|
||||
7. **Lucky mode: 3 guaranteed + bias.** Red: `lucky_mode_at_least_3_inward` and `lucky_mode_inward_distribution` (statistical, over 1000 seeds: extra-inward rate ≈ `inward_bias_prob ± 3σ`). Green: bias logic.
|
||||
8. **Convergence at centroid.** Red: `convergence_never_fails` (1000 seeds × both modes: ≥3 wanderers at centroid by end-of-turn-0). Green: step-and-merge.
|
||||
9. **Dwarf Tribe spawns with correct founding_pop_override.** Red: `tournament_mode_always_pop_1`, `lucky_mode_third_per_extra` (3→1, 6→2, 9→3, 12→4, 15→4 cap). Green: compute override.
|
||||
10. **Non-converging wanderers persist.** Red: `non_converging_wanderers_persist` — all non-inward rollers remain on the map as live units with freepeople AI after turn 1. Green: do-not-consume path.
|
||||
11. **Dwarf Tribe has only Found Capital action.** Red: `dwarf_tribe_action_bar` asserts `allowed_actions(dwarf_tribe) == ["found_capital"]`. Green: unit definition + action gate.
|
||||
12. **Found Capital respects override.** Red: `found_capital_uses_founding_pop_override`. Green: `mc-city::found_city(Some(pop))`.
|
||||
13. **Ordinary Founders ignore override.** Red: `normal_founder_always_pop_1`. Green: regression guard.
|
||||
14. **Generalized 3+ freepeople → nomadic_band.** Red: `any_three_freepeople_in_radius_form_camp` — place 3 non-prologue freepeople within radius, step one turn, assert `nomadic_band` camp created. Green: generalize prologue convergence into `mc-ecology`/`mc-freepeople`.
|
||||
15. **Leftover wanderers can seed havens.** Red: `leftover_wanderers_can_form_camps` — 30-turn sim from a high-N lucky spawn produces ≥1 camp from drifters across a seed sweep. Green: verify rule hooks into general turn loop.
|
||||
16. **Determinism gate.** Red: `byte_identical_across_runs` — serialize full game state after turn 1 for the same seed, two separate runs, assert equality. Green: isolate any RNG or ordering non-determinism.
|
||||
|
||||
Only after all 16 go green: wire the Godot presentation layer (`world_map.gd` input lock, HUD banner, camera pan, sprite swap). Presentation tests stay manual via the proof scene — they verify *rendering*, not logic.
|
||||
|
||||
## Verification
|
||||
|
||||
1. **Unit tests (Rust):**
|
||||
- `mc-turn::prologue::tests::tournament_mode_always_pop_1` — spawn 3, 5, 8, 12 ancestors → founding pop = 1.
|
||||
- `mc-turn::prologue::tests::lucky_mode_third_per_extra` — spawn 3 → 1, 6 → 2, 9 → 3, 12 → 4, 15 → 4 (capped).
|
||||
- `mc-turn::prologue::tests::convergence_never_fails` — across 1000 seeds, every spawn box produces ≥3 wanderers at centroid by end-of-turn-0.
|
||||
- `mc-turn::prologue::tests::non_converging_wanderers_persist` — after turn 1, all wanderers that did not roll inward remain on the map as live freepeople units.
|
||||
- `mc-turn::prologue::tests::leftover_wanderers_can_form_camps` — simulate 30 turns; verify at least some seeds produce a post-prologue `nomadic_band` from leftover wanderers.
|
||||
- `mc-turn::prologue::tests::turn_sequence_minus_one_zero_one` — turn counter visits exactly {-1, 0, 1} in that order; no 0.5, no repeat.
|
||||
2. **Autoplay determinism:** `PARALLEL=10 bash tools/autoplay-batch.sh 10 5 .local/iter/p0-34-determinism` with fixed seed — all 10 runs produce identical `tribe_converged` entries.
|
||||
3. **Proof scene:** `src/game/engine/scenes/tests/prologue_proof.tscn` — scripts start a new game, auto-advances -1 → 0 → 1, captures a screenshot at each turn (wanderers scattered, wanderers merging, Dwarf Tribe ready to found). `tools/screenshot.sh prologue_minus1 prologue_proof`, `prologue_zero`, `prologue_one`. Review in conversation per Phase Gate Protocol.
|
||||
4. **Manual:** start new game in tournament mode → verify starting city is pop 1. Restart in lucky mode with a seed known to spawn 6 ancestors → verify pop 2.
|
||||
|
||||
## Why this is P0
|
||||
|
||||
This is the first 30 seconds of every new game. It also gates tournament-mode fairness (needed by p0-24 difficulty calibration and p1-09 determinism gate) and introduces the narrative framing the rest of Age of Dwarves leans on ("you are a tribe, not a settler"). Without it, every balance test silently mixes starting-pop luck into the signal.
|
||||
36
.project/objectives/p1-18-village-discovery-feedback.md
Normal file
36
.project/objectives/p1-18-village-discovery-feedback.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
id: p1-18
|
||||
title: Village discovery — world-map feedback (notification, reward popup, minimap ping)
|
||||
priority: p1
|
||||
scope: game1
|
||||
owner: wireguard
|
||||
status: stub
|
||||
updated_at: 2026-04-17
|
||||
evidence:
|
||||
- src/game/engine/scenes/world_map/world_map.gd
|
||||
- src/game/engine/scenes/world_map/world_map_units.gd
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
`EventBus.village_discovered(tile_pos, reward)` fires when a unit walks onto a village
|
||||
tile, but `_on_village_discovered` in `world_map.gd` is a no-op stub. The player receives
|
||||
gold silently with no visual feedback.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- ✓ A notification toast appears in the HUD when a village is discovered (e.g. "+N Gold — Ancient Vault discovered").
|
||||
- ✓ The minimap briefly pings the village tile.
|
||||
- ✓ If the reward includes a unit or technology, the notification names it.
|
||||
|
||||
## Files to touch
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `src/game/engine/scenes/world_map/world_map.gd` | Implement `_on_village_discovered` to show notification |
|
||||
| `src/game/engine/scenes/hud/world_map_hud.gd` | Add `show_notification(text)` or reuse existing toast system |
|
||||
| `public/games/age-of-dwarves/data/vocabulary.json` | Village discovery toast vocabulary keys |
|
||||
|
||||
## Depends on
|
||||
|
||||
- Notification/toast system (may need to be built or an existing one wired in).
|
||||
Loading…
Add table
Reference in a new issue