diff --git a/plan/README.md b/plan/README.md index 722da43..c26c57d 100644 --- a/plan/README.md +++ b/plan/README.md @@ -57,6 +57,7 @@ frontmatter keys every other epic carries, run the script, stage both. | [training](training.md) | Weights fitted from recorded play | blocked | features, harness | | [observability](observability.md) | Read back what the bot believed and chose | open | beliefs | | [artillery](artillery.md) | A shell fired this round lands next round | open | ev, beliefs | +| [battle-armor](battle-armor.md) | Battle armor plays, mounted and on foot | open | unit-types, candidates | | [bridges](bridges.md) | A bridge is a floor above the ground | open | protocol | | [buildings](buildings.md) | Buildings are terrain the bot can see, enter and destroy | open | los, protocol | | [candidates](candidates.md) | Propose positions, not four verbs | open | los, ev, features | diff --git a/plan/battle-armor.md b/plan/battle-armor.md new file mode 100644 index 0000000..d59751d --- /dev/null +++ b/plan/battle-armor.md @@ -0,0 +1,76 @@ +--- +id: battle-armor +title: Battle armor plays, mounted and on foot +status: open +dependsOn: [unit-types, candidates] +exitCriterion: > + A force with battle armor in it mounts, rides, dismounts and attacks without + any of the four taking an inert default, and `sds spread` shows the mount + decision reading something that moves. +--- + +# battle-armor + +Princess cannot field mounted battle armor at all. That makes this the first +piece of play where "what would MegaMek's bot do" is not even a question, and +the only authority is what the game permits. + +`sds ba-probe` asks it, and `scenarios/ba/observed.txt` is the answer on MegaMek +0.51.00. `tests/test_battle_armor.py` pins it. + +## What the probe settled + +- **`hasBattleArmorHandles()` is not the gate.** Every Mek in the matrix answers + yes, a non-omni Atlas and a quad Goliath included, and every one of them + reports four or five transporters. The accessor whose name is the question is + not the answer to it. +- **`Entity.canLoad` is the gate, and what it turns on is omni.** The Clan + OmniMek accepts all three squads; the two non-omni carriers refuse all three, + with and without the elevation check. Every squad in the matrix answers + `canDoMechanizedBA()` yes, so the squad is not what varies. +- **The refusal is not advisory.** `Entity.load` on a non-omni throws + `IllegalArgumentException`. A candidate that offered that mount would take the + phase down rather than be ignored. +- **`MovePath.isMoveLegal()` does not ask the carrier.** It accepts a `MOUNT` + step onto a carrier whose `canLoad` refuses the squad. The path gate is + checking movement points and terrain and nothing else. +- **The mount step is free, and reaches one hex.** `getMpUsed` for the mount is + the walk's own cost in every cell, and mounting is accepted from the carrier's + hex and from an adjacent one. Every refusal in the matrix is the squad running + out of points before it arrives - the same walk without the mount step is + refused in exactly the same cells. +- **`Entity.load` writes only the carrier's half of the link.** The squad's own + `transportId` is still -1 afterwards; in a game the server sets the other + half. Both halves have to be set before any predicate that reads the squad + means anything. +- **A mounted squad gets no turn of its own.** With both halves set, + `GameTurn.isValidEntity` refuses it and `isSelectableThisTurn` agrees. This is + the one that decides the shape of the work: while a squad is aboard, its + reachable set is the carrier's and only the carrier's, so the two candidate + sets are never crossed. The coupling is a sequence, not a product. +- **And the path gate says otherwise a third time.** `isMoveLegal` still accepts + a `FORWARDS` step for a mounted squad the turn generator will never call on. + +## What it needs + +- Legal movement for a squad on foot, in the observation. Battle armor walks one + or two and jumps three, so its candidate set is small and its terrain column + is not a Mek's. +- The mount as an intent. It is a decision about two units taken on one unit's + turn, and the force is where the pair is known. +- The dismount, which is the carrier's `UNLOAD` step or the squad's `DISCONNECT` + - the probe accepts both and the difference between them has not been + measured under a server. +- Swarm and leg attacks: `getSwarmAttackerId`, `getSwarmTargetId` and + `checkDislodgeSwarmers` are the state, and the attacks themselves are weapons + (`SwarmAttack`, `LegAttack`, `StopSwarmAttack`) rather than physical actions. + Not probed yet. +- Ordinary weapon fire from a squad, which should need nothing new, and has not + been checked. + +## Open questions for jmm + +- Is a non-omni carrier ever legal for mechanised battle armor under a rules + option this probe did not turn on, or is omni the whole of it? +- Swarming is a decision to give up a unit's mobility for a turn or more. Is + that a goal, or a candidate scored like any other?