docs(@projects): 📝 update caravan master capture doc with resolved mechanics

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-05-14 23:08:33 -07:00
parent 1fbc1c310e
commit 61d82362fb
2 changed files with 44 additions and 32 deletions

View file

@ -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`.

View file

@ -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.