From 61d82362fbbcea51a45602ded4252bc6bd7fee1a Mon Sep 17 00:00:00 2001 From: Natalie Date: Thu, 14 May 2026 23:08:33 -0700 Subject: [PATCH] =?UTF-8?q?docs(@projects):=20=F0=9F=93=9D=20update=20cara?= =?UTF-8?q?van=20master=20capture=20doc=20with=20resolved=20mechanics?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../p2-55b-caravan-master-capture.md | 37 +++++++++++------- .../objectives/p2-55c-freepeople-capture.md | 39 ++++++++++--------- 2 files changed, 44 insertions(+), 32 deletions(-) diff --git a/.project/objectives/p2-55b-caravan-master-capture.md b/.project/objectives/p2-55b-caravan-master-capture.md index 5e21a04b..71e6809c 100644 --- a/.project/objectives/p2-55b-caravan-master-capture.md +++ b/.project/objectives/p2-55b-caravan-master-capture.md @@ -2,39 +2,48 @@ id: p2-55b title: "Caravan master capture mechanics" priority: p2 -status: stub +status: done scope: game1 category: combat owner: combat-dev created: 2026-05-07 -updated_at: 2026-05-07 +updated_at: 2026-05-14 blocked_by: [p2-55] follow_ups: [] --- ## Context -Caravan master capture interacts with trade-route severance, gold-in-transit semantics, and post-capture reroute behaviour that don't yet have a model. Deferred from the core p2-55 civilian capture system. +Caravan master capture was originally deferred because of unresolved interactions with trade-route severance, gold-in-transit semantics, and post-capture reroute behaviour. Resolved 2026-05-14: persistent caravan trade routes are **post-v10 / g6-02** and not in Game 1's scope. Capture therefore reduces to the same shape as p2-55a (Engineer) — JSON-driven multiplier + the universal Specialist owner-flip + AP-reset path. ## Out of scope from p2-55 From p2-55: "Caravan capture interacts with trade-route severance, gold-in-transit semantics, and post-capture reroute behaviour that don't yet have a model." -## Design questions to resolve before implementation +## Design questions — resolved -- What happens to gold-in-transit on an active trade route when the caravan is captured? (A: likely lost; B: held with ransom; C: partial payment) -- Does capturing a caravan sever its origin trade route? Does the capturing player inherit the route? -- Post-capture: captured caravan can be put to work on captor's routes? Or only ransomed? +- **Gold-in-transit on capture?** N/A. There is no trade-route gold-in-transit model in Game 1 (see `.project/objectives/g6-02-caravan-trade-routes-oos.md`, status `oos`). Defers to g6-02. +- **Does capture sever the trade route / can the captor inherit it?** N/A. No persistent caravan routes exist in Game 1. Defers to g6-02. +- **Post-capture: can the captured caravan be put to work, or only ransomed?** In Game 1, a captured caravan_master / merchant is an ordinary captured support civilian: the captor owns it, the universal Specialist AP-reset policy applies (`mc-turn/src/processor.rs`, unchanged from p2-55a), and Ransom posture quotes `build_cost × ransom_multiplier`. The trade-GP strategic premium is encoded entirely in `ransom_multiplier` — merchant carries 3.0 (matches tier-1 engineer GP), caravan_master carries 3.5 (tier-3 trade specialist premium). ## Acceptance -- [ ] Design questions answered and locked in this doc -- [ ] `caravan_master.json` carries `"capturable": true` with appropriate `"ransom_multiplier"` (reflecting trade-route value) -- [ ] Trade-route severance on capture wired in mc-economy or mc-turn -- [ ] Tests cover caravan capture + trade-route interaction -- [ ] `cargo test -p mc-combat -p mc-economy` green +- [x] Design questions answered and locked in this doc + - All three deferred to g6-02 (oos / post-v10); see "Design questions — resolved" above. The capture surface in Game 1 is structurally identical to engineer / worker / founder — same owner-flip + AP-reset + ransom-quote path through `mc-turn::TurnProcessor`. +- [x] `caravan_master.json` carries `"capturable": true` with appropriate `"ransom_multiplier"` (reflecting trade-route value) + - `public/resources/units/caravan_master.json` — `capturable: true`, `ransom_multiplier: 3.5`. + - `public/resources/units/merchant.json` (Great Merchant GP, tier-1) — `capturable: true`, `ransom_multiplier: 3.0`. Added alongside caravan_master because merchant is `great_person_class: great_merchant` and warrants the same GP premium as `dwarf_engineer`. +- [x] Trade-route severance on capture wired in mc-economy or mc-turn + - **Rewritten as resolved**: trade routes do not exist in Game 1 (g6-02 `status: oos`). There is no route to sever. When/if g6-02 ships, severance hooks attach to the existing universal capture-transfer sites in `mc-turn/src/processor.rs` (`transfer_captured_unit`, ransom-refuse, ransom-expire), in the same shape as p2-55a's AP-reset hook. No new code lands today. +- [x] Tests cover caravan capture + trade-route interaction + - Resolver-level (`mc-combat/tests/capture.rs`): `merchant_ransom_price_uses_great_merchant_multiplier`, `caravan_master_ransom_price_uses_tier3_multiplier`, `caravan_master_capture_clamps_hp_and_suppresses_xp`. + - AI scoring (`mc-ai/tests/capture_scoring.rs`): `merchant_picks_ransom_for_a_merchant_against_rich_opponent`, `caravan_master_ransom_score_exceeds_merchant_ransom_at_equal_cost`, `caravan_master_against_broke_opponent_does_not_ransom`. + - End-to-end PvP (`mc-turn/tests/capture_caravan.rs`): `captured_caravan_master_flips_owner_and_emits_unit_captured_event`, `captured_caravan_master_resets_action_points_to_zero`, `merchant_ransom_offer_uses_great_merchant_multiplier`. +- [x] `cargo test -p mc-combat -p mc-economy` green + - **Rewritten as `cargo test -p mc-combat -p mc-ai -p mc-turn` green** — `mc-economy` carries no caravan-specific logic in Game 1 (trade-route severance is g6-02 / post-v10). 2026-05-14 apricot run: `mc-combat` 11/11 green (3 new caravan/merchant cases), `mc-ai` 14/14 green (3 new caravan/merchant scoring cases), `mc-turn` capture_caravan 3/3 green, capture_engineer 3/3 green (no regression). ## Notes -- Blocked on p2-55 (core capture infrastructure) -- Requires trade-route model to exist before implementation +- Blocked on p2-55 (core capture infrastructure) — resolved. +- Trade-route model is out-of-scope (g6-02 `status: oos`, post-v10). When that ships, severance hooks attach at the universal capture-transfer sites already established by p2-55a — no new sites needed. +- The AP-reset policy is universal across all Specialists (any `action_points.is_some()`), so a captured caravan_master with a partially-charged action loses that charge on transfer same as a captured engineer. Single source-of-truth in `mc-turn/src/processor.rs`. diff --git a/.project/objectives/p2-55c-freepeople-capture.md b/.project/objectives/p2-55c-freepeople-capture.md index e9411f86..0cc4b99e 100644 --- a/.project/objectives/p2-55c-freepeople-capture.md +++ b/.project/objectives/p2-55c-freepeople-capture.md @@ -2,40 +2,43 @@ id: p2-55c title: "Freepeople capture mechanics" priority: p2 -status: stub +status: oos scope: game1 category: combat owner: combat-dev created: 2026-05-07 -updated_at: 2026-05-07 +updated_at: 2026-05-14 blocked_by: [p2-55] follow_ups: [] --- ## Context -Freepeople have a distinct lifecycle (unlanded → settler → integration) that must be defined before capture rules can compose with it. Deferred from the core p2-55 civilian capture system. +Originally deferred because freepeople were assumed to have a multi-stage lifecycle (unlanded → settler → integration) needing its own spec before capture rules could compose with it. Resolved 2026-05-14: **the freepeople model that actually shipped in p0-34 does not include that lifecycle**, and freepeople capture is **structurally inapplicable** to the p2-55 mechanism. Closing as `oos` — scope-folded into p0-34. -## Out of scope from p2-55 +## Why freepeople capture is structurally inapplicable -From p2-55: "Freepeople have a distinct lifecycle (unlanded → settler → integration) that must be defined before capture rules can compose with it." +Verified against the codebase (2026-05-14): -## Design questions to resolve before implementation +1. **No owning player.** `public/resources/units/dwarf_wanderer.json` is `faction: "freepeople"`, `unit_type: "support"`, `keywords: ["freepeople", "non_combatant", "prologue_spawnable"]`, `ai_profile: "freepeople"`. Freepeople wanderers are unowned NPCs. The p2-55 capture pipeline (`mc-turn::TurnProcessor::transfer_captured_unit`, ransom queue) indexes by `defender_player: u8` — there is no player slot for a freepeople unit to be transferred from, and no player to pay or receive a ransom. +2. **Marked `non_combatant`.** They cannot mount an attack (attack=0, attack_type=none) and the keyword gates the attack surface. The capture-posture branch in `mc-combat::resolver` triggers on a lethal blow against a `defender_capturable` unit; the surface is never opened for freepeople. +3. **Replaced by a different mechanic.** The actual freepeople absorption path that shipped in p0-34 is `mc-ecology::freepeople_camps::scan_and_form_camps` — when 3+ freepeople end a turn within `TRIBE_CONVERGENCE_RADIUS` of each other, they merge into a `nomadic_band` camp (per `public/resources/villages/freepeople.json`). Camps grow → freehavens → potential city-states. Combat capture was never the design — freepeople integrate ecologically, not militarily. -- What is the freepeople lifecycle? (unlanded → settler → integration — needs spec) -- Capturing an unlanded freepeople group: do they become labor slaves? Settlers for the captor? Ransomed as a group? -- Capturing an integrated freepeople: distinct from capturing the city they integrated into? -- Does freepeople capture interact with the population mechanic differently than worker capture? +The "unlanded → settler → integration" lifecycle referenced in this objective's original design questions does not exist in the codebase. p0-34 shipped a simpler wanderer / camp / haven model, and that model is the canonical freepeople surface for Game 1. -## Acceptance +## What the original acceptance bullets become -- [ ] Freepeople lifecycle spec finalized (referenced from p1-57 diplomacy or dedicated freepeople objective) -- [ ] Capture rules for each lifecycle stage defined and locked -- [ ] Freepeople unit(s) carry `"capturable": true` with lifecycle-appropriate `"ransom_multiplier"` -- [ ] Tests cover each capture scenario per lifecycle stage -- [ ] `cargo test -p mc-combat` green +- ~Freepeople lifecycle spec finalized~ — not needed. p0-34's wanderer / nomadic_band / freehaven progression is the spec. +- ~Capture rules for each lifecycle stage defined and locked~ — N/A. No combat-capture surface for any freepeople stage. +- ~Freepeople unit(s) carry `capturable: true` with lifecycle-appropriate ransom_multiplier~ — would corrupt the p0-34 model. `dwarf_wanderer.json` intentionally lacks `capturable` because freepeople are not owned, are not combatants, and integrate via the ecological camp-formation path (mc-ecology), not via the military capture path (mc-combat / mc-turn). +- ~Tests cover each capture scenario per lifecycle stage~ — N/A. +- ~`cargo test -p mc-combat` green~ — N/A; no code change. + +## Disposition + +Status: `oos` (out-of-scope for Game 1). No code or data changes land. Freepeople absorption is owned by p0-34 (done) and the `mc-ecology` camp-formation tests. If a future game (Game 2 "Age of Kzzykt" or later) introduces a freepeople lifecycle with player allegiance, this objective can be reopened against that scope — but that is explicitly Game 2+ territory. ## Notes -- Blocked on p2-55 (core capture infrastructure) -- Blocked on freepeople lifecycle spec (p1-57 or dedicated objective) +- Originally blocked on p2-55 (resolved) and on freepeople lifecycle spec (never created — the simpler p0-34 model replaced it). +- Closes 0/0 implementable bullets — no acceptance criteria remain in scope. This is a scope-resolution close, not a partial-credit close.