feat(robot): occasional off-strategy deviation, strict in the endgame
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 13s
CI / ui (pull_request) Has been skipped
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m9s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 13s
CI / ui (pull_request) Has been skipped
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m9s
The robot followed its per-game playToWin/lose intent on every move, which made the outcome too predictable. It now flips that intent for a single move on ~20% of opening/midgame turns (a winning robot eases off, a losing one surges ahead), so the chosen strategy may not pan out — which favours the human. The chance tapers linearly to 0 over the last 14 tiles in the bag and is 0 once the bag is empty, so the endgame follows the chosen strategy strictly. The decision is deterministic from the seed (mix(seed,"deviate",moveCount)) and applies to both robot paths via the shared selectMove; the per-game play-to-win intent the admin card shows is unchanged. Adds deviateProb/deviates helpers and unit tests (taper bounds + monotonicity, never-in-endgame, determinism, ~20% distribution); bakes the behaviour into ARCHITECTURE §7, FUNCTIONAL (+_ru), backend/README, PRERELEASE and PLAN Stage 5.
This commit is contained in:
@@ -511,3 +511,11 @@ Then Stage 18.
|
||||
(`GameRow`/`GameDetailView` gain `VsAI`); (4) `games_started_total` / `games_abandoned_total` gain a
|
||||
**`vs_ai`** attribute and the Grafana *Game domain* dashboard splits started/abandoned into **human**
|
||||
and **AI** panels.
|
||||
- **Follow-up (separate PR — strategy deviation):** the robot now plays **≈20%** of opening/midgame moves
|
||||
*against* its per-game `playToWin` intent (toward the opposite margin band — a winning robot eases off, a
|
||||
losing one surges ahead), tapering linearly to **0 over the last 14 bag tiles** and **0 once the bag is
|
||||
empty**, so the endgame follows the chosen strategy strictly while earlier outcomes can swing the human's
|
||||
way. Deterministic from the seed (`mix(seed,"deviate",moveCount)`), applied to **both** robot paths via
|
||||
the shared `selectMove`; the per-game intent (and the admin card) is unchanged. Tests: `robot` unit
|
||||
(taper bounds + monotonicity, never-in-endgame, determinism, ~20% distribution). Bake-back:
|
||||
`docs/ARCHITECTURE.md` §7, `docs/FUNCTIONAL.md` (+`_ru`), `backend/README.md`, `PLAN.md` Stage 5.
|
||||
|
||||
Reference in New Issue
Block a user