RulesConfig.exam_failure_loss (bots aware) with the sim axis --exam-loss. Losing 1 or 0 stripes saves 3-5 minutes but weakens comebacks, so the rules keep -3. Default games are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
49 KiB
Il Labirinto del Dojo — board format, rules engine, simulator
Goal and scope
A small tabletop game (1–2 h, target 4 players, playable 3–8), gifted to a friend. Logic and balance first; graphics and cosmetics are out of scope for now.
Deliverables:
RULES.md— the rulebook (English while iterating; Italian final edition produced separately).- A text-based board format, with parser, full-board generator and validator.
- A first playable board.
- A rules engine + bots + Monte Carlo simulator to validate balance and pacing, and in particular to choose between rule variants A and B (B dropped, D28; now the Final Exam options, D29).
Decisions log
| # | Decision | Why |
|---|---|---|
| D1 | Kumite loser loses 1 belt (−3), never below 0 | Developer requirement. |
| D2 | "Punching up": belts change only on equal-belt fights or upsets | Prevents leader farming weak players; built-in catch-up. |
| D3 | Kumite: 1d6 each, higher belt +1 per belt of gap, capped at +2 | Uncapped d6 bonus made fights predetermined (gap 5 = 100%). |
| D4 | Senshu rule: ties go to the attacker | WKF-inspired, one rule without exceptions, makes attacking slightly favourable so fights happen. |
| D5 | Kumite triggers on crossing (entering an occupied square), always forced; winning attacker continues moving; chains allowed | Developer requirement; route choice gives the agency. |
| D6 | Kumite loser is sent to own Start (corner Safe Room) | Developer requirement. |
| D7 | Corner Safe Rooms: 3×3, 2 exits, no Kumite/effects/targeting, stacking allowed | Prevents spawn camping / spawn lock. |
| D8 | Movement 2d6, exact count, orthogonal, no re-entering a square in the same move | Developer requirement + clarity. |
| D9 | Most squares carry an effect from a small vocabulary (7 codes); ~30–40% Tatami | Developer requirement; limits reading load and analysis paralysis. |
| D10 | Effects trigger only when stopping on a square (except Fatica since D36) | Avoids multiple triggers per move. |
| D11 | Nebbia works like Monopoly Chance: the square stays active | Developer requirement. |
| D12 | Progress track 0–17, 3 stripes per belt; squares ±1, Kumite ±3 | Fine-grained board income without breaking pacing. Physical tracking method decided later. |
| D13 | Nebbia deck is mostly movement/interaction/Tecniche, very few flat stripes | Prevents "stripe farming" that would make players avoid fights. |
| D14 | Tecnica cards: hold max 1, played after dice, attacker first | Converts Nebbia luck into a reason to fight. |
| D15 | Passo Falso returns to the start of the current move; skip-turn allowed only if rare (1 card) | Developer requirement. |
| D16 | Tunnel: when stopping on it you may teleport; movement is over; occupied exit starts a Kumite | Developer confirmed. |
| D17 | Meditazione: pass-through; ending on it forces one extra step | Developer rule. |
| D18 | Central Dojo is one logical space, several entrances, Brown only, no exact count to enter | Avoids end-game "need exactly a 3" frustration. |
| D19 | Final Exam: highest opponent defends; challenger wins → game; challenger loses → −3 and Start; defender gains nothing | Avoids the top-two flip-flop. Brown's extra stripes protect against the board, not the exam. |
| D20 | Two rule variants to be decided by simulation: A (no Brown cap, higher-beats-lower 0) vs B (squares/cards cannot move 14→15, higher-beats-lower +1) | Neither is clearly better a priori. Superseded by D28. |
| D21 | Board 16×16, 4×4 Dojo in the centre, authored as one 8×8 quadrant rotated 3× (C4 symmetry) | Fairness by construction. Small asymmetries may be wanted later (see Q2). |
| D22 | Tooling in Python, environment managed with uv | Developer choice. |
| D23 | Rules drafted in English; Italian final edition generated separately | Developer choice. |
| D24 | Board format: see board/FORMAT.md. Tunnel pairing across quadrants via quadrant_offset in board/legend.toml (cell a in quadrant k ↔ cell b in quadrant k+o) |
Every tunnel cell keeps exactly one partner under rotation. |
| D25 | Only the Tunnel square is optional. Sfida (square and card), Irimi and Tunnel Segreto are mandatory; every Nebbia card must be resolved | Sfida prevents stalling; Nebbia cards are chances that can also turn out badly. |
| D26 | Tecnica cards are secret: drawn face down, others only know whether you hold one, a replaced Tecnica is discarded face down, revealed only when played | Hidden information and bluffing. Bots must not see opponents' Tecnica identity (Phase 4). |
| D27 | Edge rules (RULES.md v0.5, inline + FAQ): boxed-in → move as far as possible (safeguard; boards have no dead ends); Uke-saved attacker stops on its previous square, turn ends, no square effect; extra-step rule for ending on any unfightable pawn; tunnel exits with a meditating pawn unusable; meditating players cannot defend the Exam; Tecnica window after both dice, attacker first; relocations never fight or trigger squares; Tsugi-ashi has its own origin; becoming Brown mid-move opens the Dojo | Developer confirmed all ten. |
| D28 | Variant B dropped (developer, after the Phase 5 baseline): no Brown cap; a higher belt beating a lower one gains nothing. Removed from engine, bots, simulator, RULES.md (v0.6) | B made games shorter (13 vs 18 rounds) instead of adding an endgame challenge; the cap barely bit and the +1 applied to every such win. Too complex for what it gave. |
| D29 | Final Exam options under test: a ties go to the defender; c the defender fights as a Black belt (defender +1 vs a Brown challenger); d best of 3. Combinable (--exam ac). Option b (no belt bonus in the Exam) not pursued. Developer favours c |
Baseline pass rate ~80%: the defender is usually 1–2 belts below the Brown challenger, who also gets Senshu. |
| D30 | Simulator reporting: income per source as gains and losses separately (Kumite is zero-sum, so its net hid the flow); standings sampled at the end of every turn; ten one-sidedness measures (see 5.4) | Developer request after the Phase 5 baseline. |
| D31 | Final Exam rule: the defender fights as a Black belt (option c; RULES.md v0.7). Options a (ties to the defender) and d (best of 3) stay as simulator switches only; --exam lists the options in force and defaults to c |
c gave a 44% pass rate, more distinct challengers (1.58/game) and closer endings; d alone raised the pass rate to 91%. |
| D32 | Phase 6 targets confirmed by the developer as a starting point (table in Phase 6) | Q5. |
| D33 | Fatica fix: test option 2 first — a chance square (stop on it, roll 1d6: 1–2 lose a stripe, 3–6 gain one) replacing Fatica and some Allenamento; then option 1 must also be tested — Fatica costs a stripe when walked through as well as when stopped on (breaks D10 for that square only). Options 3 (fewer paths: board rework) and 4 (fewer / once-per-room Allenamento) kept in reserve. The casual bot (6.0.1) is built regardless | Q6. Any on-stop penalty is avoidable when a move reaches ~24 end squares; the chance outcome cannot be dodged. Developer likes 1 and 2. |
| D34 | The "games finished within 200 rounds: 100%" target does not apply to the random lineup (it is a floor, not a player: 94% finished, 115 rounds on average) |
6.1 review. |
| D35 | No Kumite in round 1: opponents are treated like meditating pawns (pass through, extra step if the move would end on one, no Tunnel exit onto them, Sfida has no target; Irimi still works). RulesConfig.first_kumite_round = 2. RULES.md v0.8 |
6.1 review, finding 3: later seats find opponents already outside their Safe Rooms and early equal-belt Kumite are nearly free. |
| D36 | Fatica on crossing is the baseline: every Fatica square stepped onto while walking costs 1 stripe (last step and Meditazione extra step included, before any Kumite on it); stopping adds nothing; teleports and relocations cost nothing. RulesConfig.fatica_on_crossing = True. Supersedes the order in D33 (the chance square, option 2, remains a candidate). Paths to the same end square are offered separately when they cross Fatica differently. RULES.md v0.8 |
6.1 review, finding 4. |
| D37 | Out of contention = more than 3 belts (9 stripes) behind the leader (metrics.CONTENTION_BELTS); the targets (≤ 20% of player-turns, worst player ≤ 35%) now apply to this threshold |
6.1 review, finding 1: one Kumite swings two players 6 stripes apart, so 2 belts was too strict. |
| D38 | Catch-up: only candidate A (Allenamento gives +2 instead of +1 to a player 2+ belts behind the leader) is to be simulated. Rejected: bounty on the leader, belt bonus capped at +1, more Sensei Osserva | 6.1 review, finding 1. |
| D39 | Game length is tuned last; target stays a mean of 60–90 minutes at 4 players | 6.1 review, finding 2. |
| D40 | Bots stay as they are for Phase 6 (casual included, although much weaker than the heuristic bots) | Q7. |
| D41 | Phase 6 order: board and Fatica (6.4 with 6.5) → seat order (6.2) → catch-up (6.9) → style dynamics (6.3) → Kiai (6.6), player counts (6.7), length → consolidation (6.8). Structural fixes before tuning | 6.1 review. |
| D42 | Board draft 2 adopted as board/quadrant.txt (board/board.txt regenerated; draft 1 is in git history, commit 4998931) |
6.4.0 results. |
| D43 | 6.2 seat order suspended: measuring it needs 4,000+ games per scenario for an effect of a few points; D35 (no Kumite in round 1) stays in the rules. Seat rates are still reported by every run and watched in 6.8 | Developer, after the 4,000-game runs were started. |
| D44 | 6.9 catch-up skipped: the v0.8 baseline already has 3–4% of player-turns out of contention (worst player 10–13%), so candidate A has little to fix; dropped from RULES.md "variants under test" (never implemented) | Developer, after the v0.8 baseline metrics. |
| D45 | The random lineup is no longer run in experiments: it never finishes a game and cost ~80% of a run's time. The bot stays in the code and the tests |
Developer, 6.10. |
| D46 | Performance work must leave every game identical (same events for the same seed), so every result recorded in this file stays valid | Developer, 6.10. |
| D47 | Kiai stays +2: +2 and +1 are indistinguishable on every target (6.6); +2 decides more fights (5% vs 3% of Kumite in casual play). kiai_bonus = 1 stays a simulator switch; RULES.md drops the "+1 to be tested" note |
Developer, 6.6 results. |
| D48 | 6+ players start on 3 (Yellow); any player count may start on 3 as a "shorter game" option (saves 15–20% of the time, 6.7). 8 players stays long (107 / 142 min mixed / casual from Yellow) and is accepted: it will rarely be played. Balancing simulations stay at start 0 at every count (developer); --start 3 reproduces the rules' 6+ setup or the shorter game |
Developer, 6.7 results. |
| D49 | Chance square parked (6.4.1 and 6.4.3): Fatica on crossing (D36) on board draft 2 (D42) already makes squares matter; 6.4 closed | Developer. |
| D50 | Length accepted as is; a failed Exam still costs 3 stripes. L1 (Brown floor against Fatica) rejected; L2 (failed Exam −1 / 0) saves only 3–5 min on the mean and weakens comebacks (6.11.4). exam_failure_loss stays a simulator switch. At 4 players mixed and balanced are inside the target; casual (91 / 122) and all-aggressive (90 / 127) stay slightly outside, within the "1–2 h" promise; the shorter-game start on Yellow (D48) is the players' lever |
Developer, 6.11 results. |
Phases
Phase 0 — Rules consolidation
- 0.1 Write
RULES.mdv0.4 with variants A/B marked. - 0.2
RULES.mdv0.5: mandatory effects, Tecnica secrecy, edge rules and FAQ (D25–D27).
Phase 1 — Project scaffold and board format
- 1.1
uv initproject (packagedojo), Python version pinned via uv; dev deps: pytest, ruff. No runtime deps (legend in TOML, parsed with stdlibtomllib). - 1.2
board/FORMAT.md— the format specification:- ASCII grid:
+corners,|vertical walls,---horizontal walls, 3-char cells with a centred code. - Cell codes:
Ssafe room,Ddojo,.AF?PK(Allenamento/Fatica were+/-, changed so no code looks like a wall), digits = tunnel pair ids. - Outer border must be fully walled.
- Dojo entrance = open edge between a
Dcell and a non-Dcell. - Cross-quadrant tunnel links declared in
board/legend.toml.
- ASCII grid:
- 1.3 Parser:
quadrant.txt→ cell grid + wall set. - 1.4 Generator: rotate the quadrant 90°/180°/270° around the board centre → full 16×16 model; write
board/board.txt(generated, never hand-edited). - 1.5 Graph model: cells as nodes, open edges as links. The Dojo is handled as one cell set (impassable, entrances = open D/non-D edges); treating it as a single space for movement lands in the rules engine (3.3).
- 1.6 Validator:
- every non-Dojo square reachable from every Safe Room;
- each Safe Room has exactly 2 exits, on different sides;
- no Safe Room lies on a shortest path between two other points (not a shortcut);
- every tunnel id has exactly one partner;
- Dojo has ≥1 entrance per quadrant;
- report: square-type mix and Tatami %, shortest distance from each start to the Dojo.
- 1.7 CLI:
uv run dojo board validate,uv run dojo board render. - 1.8 Unit tests for parser, rotation, validator.
Phase 2 — First board
- 2.1 Draft the first quadrant (
board/quadrant.txt), following D7, D9, D18. - 2.2 Validate and iterate until clean.
- 2.3 Developer review of the layout (approved as draft 1).
Phase 3 — Rules engine
- 3.1 Game state: pawns, track positions, hands, deck/discard, meditation status, turn order.
- 3.2 Rule configuration object: variant A/B, Kiai value, stripes per belt, starting position, player count.
- 3.3 Movement enumeration: all legal exact-length self-avoiding walks, with Kumite on crossing, chain continuation, Dojo entry with ≥1 step left, Meditazione extra step.
- 3.4 Kumite resolution: gap bonus cap, Senshu, Tecnica timing, consequences table per variant, Uke placement.
- 3.5 Square effects and Nebbia cards (all 13 card types).
- 3.6 Final Exam.
- 3.7 Unit tests covering every edge rule in
RULES.md(tests/test_engine.py,tests/test_movement.py; mutation-checked: breaking Senshu, bonus cap, chain continuation, Meditazione step, variant B cap, Safe Room or meditator immunity each fails tests). - Code:
src/dojo/rules.py(config, variants, deck),movement.py(walks),engine.py(Game, Agent protocol, Randomness),events.py(event log for metrics).
Phase 4 — Bots
- 4.0 Hidden information: agents receive a
GameViewsnapshot (Game.view(player)), never theGame: opponents' Tecnica shows only asholds_tecnica; the event log (which recordsCardDrawn) is not visible to agents (D26). - 4.1 Random bot (baseline):
RandomAgent(rng)insrc/dojo/bots.py. - 4.2 Heuristic bot:
HeuristicAgent(profile). Value = track position; once Brown, plusDOJO_PULL(0.3) per step closer to the Dojo. Scores each offered path as the expected value change over the chain of Kumite (exact 1d6-vs-1d6 odds with belt bonus and Senshu, ±0.1 per Tecnica held), then the stop square's effect (Nebbia worth 0.2, Sfida = best target, Tunnel = better of staying/exit). Exam = 100 × pass chance. Tecnica played only when losing (Kiai only if it turns the fight). Known simplifications: Meditazione extra step, Passo Falso origin after a chain, opponents' replies. - 4.3 Profiles (
PROFILES): losses weighted byrisk, opponents' value changes byrivalry, Tecnica keep order. balanced (1.0, 0.5, Kiai>Kaeshi>Uke), farmer (2.5, 0.2, Uke first), aggressive (0.5, 1.0). - Smoke run (60 seeds, real board, 1 heuristic vs 3 random): heuristic wins 58–60/60 for every profile and both variants; ~20–22 rounds; ~1,300–1,450 turns/s. Four heuristic bots: ~18.7 rounds. Finding to check in Phase 5/6: attacking a higher belt risks nothing for a non-Brown player (losing costs 0 stripes; Start is no worse than elsewhere), so every profile attacks upward.
Phase 5 — Simulator and metrics
-
5.1 Monte Carlo runner over a config matrix; seeded and reproducible.
src/dojo/sim.py:Scenario(variant × players × Kiai bonus × start position × lineup),matrix,run(files, scenarios, games, seed, jobs). Gameiuses seedbase + iin every scenario (same dice across scenarios); the lineup rotates one seat per game; process pool, results independent ofjobs. -
5.2 Metrics (
src/dojo/metrics.py, computed from the event log; Kumite counts exclude the Exam):- game length in rounds and estimated minutes (45 s per turn + 30 s per Kumite);
- Kumite per round, upset rate, higher-beats-lower rate, longest chain per game (Kumite attacked by the active player in one turn);
- win rate by seat and by bot profile (per seat occupied);
- exam attempts per game, exam success rate;
- turns started on 14, longest streak (variant B deadlock check);
- net stripe income per turn: squares vs cards vs Kumite vs Exam; square income in the player's own quadrant vs elsewhere (home farming);
- lead changes per game (strict leader), final spread.
-
5.3 Report output:
uv run dojo simprints a text summary per scenario;--csvwrites one row per game (src/dojo/report.py). Commands inREADME.md. -
Baseline (1,000 games per variant, 4 players, lineup balanced/farmer/aggressive, seed 0), for Phase 6:
Metric A B Rounds mean (p10–p90) 18.4 (14–23) 13.1 (9–17) Minutes mean (p10–p90) 66 (50–85) 46 (33–62) Kumite per round 1.25 1.16 Upsets / higher beats lower 29% / 55% 27% / 52% Exam attempts per game, pass rate 1.26, 79% 1.22, 82% Turns on 14 per game, longest streak 1.26, 4 1.73, 7 Income per turn: square (home / away), card, Kumite +0.52 (0.38 / 0.14), 0.00, +0.04 +0.54 (0.39 / 0.14), 0.00, +0.22 Lead changes, final spread 5.6, 9.3 3.5, 11.5 Wins by seat 23–27% 23–27% -
5.4 Follow-up to the baseline review (D28–D30):
- remove variant B;
--variantreplaced by--exam(Exam options,RulesConfig.exam_ties_to_defender / exam_defender_black / exam_rounds); "turns on 14" metric removed with it; - income per source as gains / losses;
- one-sidedness measures, sampled at turn ends: (1) gap 1st–2nd (mean per game) and winner margin over the best rival at the end; (2) share of turns the winner led; (3) halfway leader wins; (4) point of the game of the last lead change; (5) rivals within one belt of the winner at the end; (6) share of player-turns more than two belts behind the leader, and the worst player's share; (7) rank swaps between any two players; (8) Kumite lost by the leader; (9) distinct Exam challengers; (10) winner's own turns to reach Brown.
- remove variant B;
-
After 5.4 (300 games per option, 4 players, lineup balanced/farmer/aggressive, seed 0):
Metric none a c d Rounds mean (p10–p90) 18.5 (14–23) 19.3 (14–25) 21.9 (16–29) 18.0 (14–22) Minutes mean 67 70 80 66 Exam pass rate, attempts per game 81%, 1.24 67%, 1.50 44%, 2.28 91%, 1.10 Distinct challengers per game 1.13 1.24 1.58 1.06 Winner margin at the end 4.7 4.6 3.9 4.8 Halfway leader wins 40% 41% 40% 41% Rivals within one belt at the end 0.32 0.37 0.62 0.30 Player-turns out of contention 22% 22% 21% 22% Also measured: Kumite moves +0.44 / −0.40 stripes per turn; heuristic bots almost never stop on Fatica (square losses 0.0002 per turn vs 0.08 for random bots): with 2d6 and many paths an Allenamento is nearly always reachable. Seat 3 (last in turn order) won 28–31% in every option.
Phase 6 — Balance experiments
Method (applies to every step):
- Runs use
uv run dojo sim. Default 1,000 games per scenario (a 25% win rate is then known to about ±1.4 pp); 4,000 games where seat effects are measured (about ±0.7 pp). - Compared scenarios share seeds (
--seed 0), so differences come from the rules, not the dice. - Every conclusion is checked on at least two lineups (mixed
balanced,farmer,aggressive, and one same-style lineup), because results depend on bot quality. - One change at a time. When a change is adopted, re-run the 6.1 baseline so later steps start from the current rules, and log the decision (D-number) here and in
RULES.md. - Results go in this file as a table per step (command line, scenario, key measures).
Next action: 6.8 consolidation, when the developer says to continue. 6.2 is suspended (D43), 6.9 skipped (D44); 6.4.1 (chance square) stays optional. Order of the steps: D41. Everything up to D50 is committed; commit only when the developer asks.
Targets (confirmed by the developer as a starting point, D32):
| Measure | Target |
|---|---|
| Minutes, 4 players | mean 60–90, p90 ≤ 110 |
| Exam pass rate | 35–55% |
| Halfway leader wins (4 players) | 35–55% |
| Player-turns out of contention | ≤ 20%; worst player mean ≤ 35% |
| Rivals within one belt of the winner at the end | ≥ 0.5 |
| Win rate by seat, 4 players | each 25% ± 3 pp |
| Win rate by bot style (mixed lineup) | spread ≤ 6 pp |
| Games finished within 200 rounds | 100%, every lineup |
Steps:
-
6.0 Tooling needed by the experiments
- 6.0.1 "Casual" bot: the heuristic bot scoring only a small random sample of the offered moves (sample size is a parameter, default 6), as a stand-in for a human who cannot compare ~24 end squares every move. Added to
BOTSascasual. Done:CasualAgent(rng, profile=BALANCED, sample=CASUAL_SAMPLE)inbots.py; onlychoose_pathis sampled, and the sample is blind (a path into the Dojo is taken only if drawn). - 6.0.2
--summary-csv PATH: one row per scenario with the summary measures, to compare scenarios side by side. Done:report.write_summary_csv; spreads become<name>_mean/_p10/_median/_p90, income<source>_gain/loss_per_turn, seatsseat<i>_<stat>, botswin_rate_<bot>; columns missing in a scenario are empty. - 6.0.3 Seat breakdown in the summary: per seat, mean final track, Exam attempts, and share of games where that seat defended the Exam (for 6.2). Done:
GameMetrics.final_track / exam_attempts_by_seat / exam_defences_by_seat(tuples, comma-joined in the games CSV),Summary.seats(SeatSummary), oneSeat iline per seat in the text report. - 6.0.4 Square reachability measure: share of moves where an Allenamento / Fatica end square is reachable, and mean distinct end squares per move (the Phase 6 probe, made a metric; for 6.4). Done: the engine emits
MoveOptions(player, ends)(square codes of the distinct end squares) before every path choice in_move(first choice, after a won Kumite, Tsugi Ashi; not the Meditazione extra step); report lineMove options.
- 6.0.1 "Casual" bot: the heuristic bot scoring only a small random sample of the offered moves (sample size is a parameter, default 6), as a stand-in for a human who cannot compare ~24 end squares every move. Added to
-
6.1 Baseline on rules v0.7 (Exam c): 4 players, 1,000 games, lineups mixed /
balanced/casual/random. Record the table; check it against the targets.- Command:
uv run dojo sim --games 1000 --seed 0 --lineup balanced,farmer,aggressive balanced casual random --summary-csv ... --csv ...(~2 min on all cores).
Measure (target) mixed balanced casual random Finished within 200 rounds (100%) 100% 100% 100% 94% Rounds mean (p10–p90) 21.8 (15–29) 22.2 (15–30) 24.9 (17–34) 115 (67–179) Minutes mean (60–90), p90 (≤ 110) 79, 108 81, 110.5 83, 114 365, 569 Kumite per round; upsets 1.24; 29% 1.26; 30% 0.66; 28% 0.36; 23% Exam attempts per game; pass rate (35–55%) 2.33; 43% 2.45; 41% 2.39; 42% 2.24; 42% Halfway leader wins (35–55%) 39% 38% 38% 29% Player-turns out of contention (≤ 20%) 21% 21% 17% 19% Worst player's share out, mean (≤ 35%) 44% 43% 40% 39% Rivals within one belt at the end (≥ 0.5) 0.60 0.57 1.22 1.46 Winner margin; lead changes 4.0; 7.0 4.0; 7.4 2.4; 5.3 1.4; 13.2 Win rate by seat 0–3 (25% ± 3 pp) 24 / 23 / 24 / 28 25 / 22 / 26 / 27 26 / 23 / 26 / 26 23 / 23 / 24 / 23 Win rate by style (spread ≤ 6 pp) aggr. 25, bal. 27, farmer 22 (5 pp) — — — Income per turn: square, card, Kumite (gain / loss), Exam loss +0.51/0, +0.01/0, +0.43/−0.40, −0.05 same ±0.01 +0.53/0, +0.01/−0.01, +0.24/−0.23, −0.04 +0.19/−0.08, +0.02/−0.01, +0.12/−0.12, −0.01 Square income home / away +0.38 / +0.14 +0.38 / +0.13 +0.36 / +0.17 +0.07 / +0.05 End squares per move; can end on Allenamento / Fatica 23.9; 78% / 76% 23.9; 78% / 76% 24.5; 83% / 80% 24.0; 81% / 78% Seat 3: Exam attempts per game (others) 0.65 (0.55–0.57) 0.67 (0.58–0.61) 0.62 (0.56–0.63) 0.56 (0.53–0.60) Findings:
- Met: pass rate, halfway leader, rivals within one belt, style spread, seats (mixed seat 3 at the edge, 28%).
- Missed: the worst player's time out of contention (40–44%, target ≤ 35%) on every lineup; overall time out 21% for heuristic lineups; p90 minutes slightly over 110 for
balancedandcasual. randomdoes not finish 6% of games in 200 rounds (115 rounds on average): it is a floor, not a player; the "100% finished" target is read as applying to the other lineups.- Seat 3 makes more Exam attempts in the heuristic lineups (0.65–0.67 vs ≤ 0.61) and not with
random: first lead for 6.2. - Fatica is reachable on 76% of moves but heuristic bots still avoid it (square losses ≈ 0), confirming Q6; the casual bot also avoids it, since 6 sampled moves nearly always include a better one.
- The casual bot fights half as often (0.66 Kumite/round) and gives closer games (winner margin 2.4, 1.22 rivals within one belt).
- Q7 follow-up (1,000 games, seed 0):
casual,balanced→ balanced 36%, casual 14% per seat;casual,casual,casual,balanced→ balanced 46%, casual 18%. The blind sample of 6 is far weaker than the heuristic bot. - Seat probe (4,000 games, scratch script, not in the repo): Kumite attacked in rounds 1–2 per game by seat 0/1/2/3 = 0.25 / 0.40 / 0.54 / 0.67 (mixed lineup), 0.03–0.05 for every seat with
random; mean track after round 3 = 2.04 / 2.04 / 2.35 / 2.50. Later seats find opponents already out of their Safe Rooms, and an early equal-belt Kumite is nearly free for the attacker (Senshu 58%, and a loss at track 0–2 costs at most what is there). Matches the developer's hypothesis; candidate fixes to be proposed in 6.2. - Developer review: D34–D41.
- Re-baseline on rules v0.8 (D35, D36, 3-belt threshold D37), 1,000 games, seed 0, each rule alone against v0.7, after the Dojo-closing fix below (scratch script:
Scenarioconfigs with the two switches replaced; the CLI has no switch for them):
Measure v0.7 + Fatica on crossing + no Kumite in round 1 v0.8 (both) Minutes mean / p90, mixed 79 / 108 83 / 114 78 / 107 83 / 114 Minutes mean / p90, balanced 81 / 111 79 / 109 80 / 110 78 / 108 Minutes mean / p90, casual 83 / 114 126 / 173 83 / 114 127 / 174 Square gain / loss per turn: mixed; casual +0.51 / 0.00; +0.53 / 0.00 +0.52 / −0.05; +0.45 / −0.12 = v0.7 +0.52 / −0.05; +0.45 / −0.12 Kumite per round: mixed; casual 1.24; 0.66 1.03; 0.51 1.23; 0.65 1.02; 0.51 Exam pass rate, mixed 43% 44% 44% 44% Out of contention (3 belts): share; worst player, mixed 5.1%; 15% 5.2%; 16% 5.1%; 15% 5.1%; 15% Win rate by seat 0–3, mixed 24 / 23 / 24 / 29 30 / 21 / 22 / 27 24 / 24 / 25 / 28 29 / 23 / 20 / 28 Win rate by seat 0–3, balanced 25 / 22 / 26 / 27 24 / 23 / 24 / 30 24 / 24 / 26 / 26 25 / 24 / 23 / 29 Win rate by seat 0–3, casual 26 / 23 / 26 / 26 25 / 25 / 24 / 26 26 / 23 / 26 / 24 25 / 25 / 24 / 26 Fix found while planning Dojo tolls: a Brown player (15) walking a Fatica drops to 14 and must not enter the Dojo on that move (the belt changes at once, FAQ).
_path_choicesno longer offers such Dojo paths (_still_brown_at_dojo; a Kumite won on the way re-offers paths). The first run without the fix differed by ≤ 3 minutes and ≤ 2 pp per seat.Findings: (1) at 3 belts the contention targets are met with a wide margin (5% of player-turns, worst player 10–15%). (2) Fatica on crossing on the current board (5 F per quadrant, 20 in all, 10% of the squares) barely touches the heuristic bots (−0.03 to −0.05 per turn) but costs the casual bot −0.12 per turn and adds ~44 minutes (127 mean, p90 174): the board has too many Fatica on ordinary routes for players who do not plan around them. (3) No Kumite in round 1 alone moves seat 3 by about 1 pp (within the ±1.4 pp noise of 1,000 games); 6.2 measures it on 4,000 games. (4) Mixed v0.8 shows seat 0 at 30% and seat 2 at 20%: not seen in the same-bot lineups; to confirm in 6.2 before reading anything into it.
- Command:
-
6.2 Seat order — suspended (D43); runs stopped before any result (monitor; developer concerned): 4,000 games, 4 players, lineups mixed and
random; 2,000 games at 3 and 6 players. If a seat is outside 25% ± 3 pp, diagnose with the 6.0.3 breakdown (hypotheses: moving last means seeing everyone else move first; Exam defender selection; Sensei / Peso cards) and bring candidate fixes to the developer. No fix without agreement. -
6.3 Style dynamics: same-style lineups (
farmer,aggressive,balanced,casual) and one-against-three (aggressive,farmer,farmer,farmer,farmer,aggressive,aggressive,aggressive,balanced,farmer,farmer,farmer). Watch: all-farmer stalling (length, games finished, Kumite per round), a dominant style, time out of contention.-
Run:
uv run dojo sim --games 1000 --seed 0 --lineup farmer aggressive balanced casual aggressive,farmer,farmer,farmer farmer,aggressive,aggressive,aggressive balanced,farmer,farmer,farmer(rules v0.8, board draft 2, 4 players; 17 s on 16 workers).Lineup Minutes mean / p90 Kumite / round Square gain / loss per turn Halfway leader wins Out of contention; worst player Rivals within 1 belt Win rate by bot farmer ×4 63 / 81 0.80 +0.71 / −0.01 34% 1%; 4% 1.47 — aggressive ×4 90 / 127 1.32 +0.56 / −0.13 41% 8%; 21% 0.50 — balanced ×4 68 / 92 1.04 +0.64 / −0.03 39% 3%; 10% 0.81 — casual ×4 91 / 122 0.61 +0.58 / −0.10 39% 4%; 12% 1.42 — aggressive + 3 farmer 68 / 92 0.94 +0.67 / −0.04 43% 3%; 11% 1.14 aggressive 26%, farmer 25% farmer + 3 aggressive 81 / 117 1.20 +0.60 / −0.10 42% 7%; 20% 0.64 farmer 24%, aggressive 26% balanced + 3 farmer 64 / 84 0.87 +0.69 / −0.01 36% 2%; 7% 1.24 balanced 29%, farmer 24% All games finished; Exam pass rate 42–43% everywhere.
-
Reading: no stalling (all-farmer is the shortest game). No dominant style: a lone bot wins 24–26%, except balanced among farmers at 29% (±1.4 pp at 1,000 games, so a real but small edge; the style spread target, ≤ 6 pp, holds). More aggression makes games longer and less close: all-aggressive is the only heuristic lineup over the p90 limit (127 min) and at the edge of the rivals target (0.50); fights cost stripes both ways (+0.45 / −0.43 per turn) and aggressive bots also pay more Fatica (−0.13). Input for the length tuning (D39).
-
-
6.4 Fatica and the square economy (closed: D49) (D33; Fatica on crossing became the baseline, D36; board draft 2 adopted, D42). Each candidate is a board draft in
board/drafts/(new square codes needSquare,board/FORMAT.md, validator stats andRULES.mdentries) and/or aRulesConfigswitch, compared with the 6.1 baseline on square gains / losses per turn, reachability (6.0.4), game length, style win rates, casual vs heuristic gap:-
6.4.0 Board draft 2 (drafted as
board/drafts/quadrant-2.txt, nowboard/quadrant.txt), built for Fatica on crossing. Principles approved by the developer: Fatica as tolls on short routes, fewer Fatica, Allenamento away from the Safe Rooms (covers 6.5), validator / Tatami 30–40% / 11-step walk / tunnels kept; judged on casual minutes (≤ ~93, i.e. v0.7 casual + 10) and heuristic bots paying some tolls.- Method: walls of draft 1 kept (approved layout); only square codes changed. Route analysis showed every square on a shortest Safe Room → Dojo walk has a detour of at most 1 step, so "detour 2–4" is not reachable without wall changes; tolls were placed by measured traffic instead (bots' walks per square, home players vs visitors, on the board without Fatica). Home players load the row-3 corridor and the inner Dojo approach (5,5); visitors load the ring next to the Dojo.
- Variants (1,000 games, seed 0, v0.8; scratch scripts
routes.py,traffic.py,recode.py,rules_compare.py):
Board Fatica (per quadrant) Minutes mean / p90: mixed; casual Square gain / loss per turn: mixed; casual Home share of square income: mixed; casual Seats 0–3, mixed draft 1 (v0.7 rules, reference) 5, on stop 79 / 108; 83 / 114 +0.51 / 0; +0.53 / 0 74%; 69% 24 / 23 / 24 / 28 draft 1 5 83 / 114; 127 / 174 +0.52 / −0.05; +0.45 / −0.12 74%; 76% 29 / 23 / 20 / 28 2a 3: (3,4), (5,5), (7,4) 73 / 99; 110 / 152 +0.66 / −0.09; +0.55 / −0.16 68%; 69% 25 / 24 / 25 / 26 2b 2: (3,4), (5,5) 72 / 98; 89 / 121 +0.62 / −0.05; +0.58 / −0.09 70%; 68% 23 / 28 / 24 / 25 2c 1: (7,4); Allenamento 16 73 / 98; 82 / 112 +0.59 / −0.02; +0.60 / −0.06 68%; 65% 24 / 23 / 26 / 27 2d = draft 2 2: (3,4), (5,5); A moved to the ring 72 / 95; 91 / 122 +0.64 / −0.05; +0.58 / −0.10 67%; 62% 23 / 27 / 27 / 23 Current baseline (rules v0.8, board draft 2) = the draft 2 row above plus the balanced lineup: 68 / 92 minutes, +0.64 / −0.03, home 67%, seats 22 / 23 / 27 / 28. Square mix per quadrant: Tatami 20 (39%), Allenamento 14, Nebbia 8 (16%, up from 6), Fatica 2, Passo Falso 2, Sfida 1, Tunnel 4.
- Reading: casual within the ~93-minute bound (91); heuristic bots pay tolls (−0.03 to −0.05); every lineup 68–72 minutes, inside 60–90. Home share down from 74% to 62–67%, not to 60%: players spend most turns crossing their own quadrant, so placement alone reaches its limit. Seat rates move by ±4 pp between variants at 1,000 games: noise, measured properly in 6.2. Adopted by the developer (D42);
board/drafts/removed.
-
6.4.1 Parked (D49). Option 2, chance square: new code (proposal
C, name to choose with the developer, e.g. "Sorte" / "Randori") — on stop roll 1d6, 1–2 → −1 stripe, 3–6 → +1. Draft: replace every Fatica and some Allenamento with it (start: all F plus about a third of A, keep the square mix inside the validator's Tatami range). Bot: value = expected change (+1/3 stripe, risk-weighted: gain 2/3, loss 1/3). Try variations of the split (e.g. 1–3 / 4–6) if income is off. -
6.4.2 Option 1, Fatica on crossing:
RulesConfig.fatica_on_crossing— each Fatica square entered during a move costs 1 stripe, 1 in total per square whether or not the move stops there (developer, D33); stopping on it adds nothing more. Engine: apply in_walkper square entered (not on teleports / relocations, which never walk). Bot: count Fatica crossed in_path_score. Likely needs fewer Fatica squares; test on the current board and on a draft with fewer F. Done as the baseline rule (D36): engine_step/_path_choices, bot_path_score, tests; measured on the current board in the 6.1 re-baseline. -
6.4.3 Parked (D49). If 6.4.1 is run: compare it with the v0.8 baseline on draft 2 (Fatica on crossing, D36) and bring the table to the developer for a decision (then
RULES.mdand D-number).
-
-
6.5 Home farming: covered by board draft 2 (6.4.0): Allenamento moved from the south training room onto the Dojo ring; own-quadrant share of square income 74% → 62–67%, short of the 60% aim (players cross their own quadrant for most of the game); draft 2 adopted as is (D42). Original step: after 6.4, if the own-quadrant share of square income is still above 60% (baseline: 71%), move Allenamento squares away from the Safe Rooms in a board draft (
dojo sim --quadrant board/drafts/...) and compare. The board must still passdojo board validate. -
6.6 Kiai +2 vs +1: 1,000 games each on two lineups. Watch the Exam pass rate, upset rate and how often a Tecnica turns a fight. Kiai stays +2 (D47).
-
6.6.1 Metric:
GameMetrics.tecnica_kumite,kiai_decided,exam_fights,exam_kiai_decided; report line "Tecnica". A fight is decided by Kiai when the result flips with the Kiai bonus removed, dice and other cards unchanged. The tie rule moved toRulesConfig.attacker_wins, shared by the engine and the metric (fingerprinted games identical). -
6.6.2 Run:
uv run dojo sim --games 1000 --seed 0 --kiai 2 1 --lineup balanced,farmer,aggressive balanced casual.Lineup Kiai Minutes mean / p90 Exam passed Upsets Tecnica played in; Kiai decided (Kumite / Exam) Halfway leader wins Rivals within 1 belt mixed +2 72 / 95 40% 31% 2%; 1% / 1% 40% 0.84 mixed +1 72 / 95 41% 31% 2%; 1% / 1% 41% 0.85 balanced +2 68 / 92 42% 30% 2%; 1% / 1% 39% 0.81 balanced +1 69 / 93 41% 30% 2%; 1% / 1% 39% 0.82 casual +2 91 / 122 43% 27% 12%; 5% / 5% 39% 1.42 casual +1 91 / 121 44% 27% 10%; 3% / 4% 39% 1.38 -
Reading: Kiai +2 and +1 are indistinguishable on every target measure (≤ 1 pp, inside the noise). Tecnica are rare: heuristic bots draw a Nebbia card on 2.3% of turns (0.5 Tecnica per game; Nebbia is worth 0.2 to them, below an Allenamento), casual bots on 9.7% (3.3 Tecnica per game). Even for casual play Kiai decides 5% (+2) vs 3% (+1) of Kumite. Scratch script
tecnica.py(200 games per lineup).
-
-
6.7 Player counts: 3 / 4 / 6 / 8 players, start 0; plus start 3 at 6 and 8 players. Minutes per count; decide whether 6+ players start on Yellow. 6+ players start on Yellow; shorter-game option for any count (D48).
-
Run:
uv run dojo sim --games 1000 --seed 0 --players 3 4 6 8 --start 0 3 --lineup balanced,farmer,aggressive casual(48 s).Players Start Minutes mean / p90: mixed; casual Rounds: mixed; casual Halfway leader wins: mixed; casual Out of contention; worst player (mixed) Rivals within 1 belt: mixed; casual Wins by bot (mixed) 3 0 55 / 75; 71 / 99 20.7; 28.9 49%; 45% 3%; 9% 0.61; 1.05 34 / 34 / 31 3 3 46 / 67; 59 / 84 17.4; 24.2 50%; 46% 3%; 8% 0.65; 1.05 34 / 35 / 31 4 0 72 / 95; 91 / 122 20.4; 27.5 40%; 39% 4%; 13% 0.84; 1.42 24 / 26 / 24 4 3 57 / 80; 77 / 110 16.2; 23.5 42%; 40% 4%; 12% 0.85; 1.47 24 / 25 / 26 6 0 107 / 145; 136 / 182 19.4; 26.4 32%; 27% 9%; 29% 1.19; 1.92 17 / 16 / 17 6 3 86 / 127; 113 / 161 15.8; 22.1 30%; 29% 8%; 28% 1.16; 1.96 15 / 18 / 17 8 0 133 / 181; 170 / 231 17.8; 24.3 26%; 20% 11%; 37% 1.41; 2.16 13 / 14 / 11 8 3 107 / 152; 142 / 200 14.5; 20.5 27%; 24% 10%; 38% 1.53; 2.29 13 / 14 / 11 Wins by bot: aggressive / balanced / farmer. All games finished; Exam pass rate 40–44% everywhere.
-
Reading: rounds stay ~15–29 whatever the count, so table time grows with the number of players (45 s per turn): 6 players take ~1.5x and 8 players ~1.9x the 4-player time. Starting on 3 saves ~3–4 rounds (15–20% of the time) at every count, and changes no other measure by more than a few points. At 6–8 players the worst player is out of contention 28–40% of turns (4-player target ≤ 35%), and the halfway leader wins less (20–32%): more players, more Kumite (2–3 per round), more reshuffling. 8 players on casual stays above 2 hours even from Yellow (142 min).
-
-
6.10 Simulation speed (before 6.3; D46: games unchanged). Profile: ~95% of the time was listing moves (
movement._extend,Board.neighbours, the outcome keys inEngine._path_choices).- 6.10.1 Guard:
agents/scripts/fingerprint_games.pyhashes every event of 210 games (mixed / casual at 4 players, 6 players, Fatica on stop with Kumite in round 1, random bots, 60-round cap);writebefore an engine change,checkafter. A tool for refactoring and speed work, not a test (rule changes are expected to differ). Timings came from a scratch benchmark. - 6.10.2
Board: neighbour table, squares per code and Safe Rooms computed once (cached_property); neighbour order N, E, S, W kept (the random and casual bots pick by position in the offered list).Engine: Fatica squares as a set (_tolls), opponents' squares looked up once per move (_fightable_squares), and paths crossing no opponent keyed by their Fatica count with C-level set operations. - 6.10.3
movement.walks: walks that exclude nothing but the start are cached per (board, start, steps, Dojo open) withfunctools.cache(same pattern asbots.dojo_distance); callers get a fresh list. ~3,200 entries per process, ~80 MB peak. - 6.10.4 Parallel scaling: 8 processes running at once each take ~1.6x their solo time on this machine (8 real cores, clock and cache sharing), so ~5x on 8 workers is the hardware limit; no pool change. 16 workers (hyperthreads) add ~12%.
- Result: 100 games on one process 8–12 s → 1.4–1.7 s; mixed + balanced + casual at 1,000 games on 16 workers 57 s → 8 s. All 210 fingerprinted games identical; the v0.8 baseline run prints the same metrics.
- 6.10.1 Guard:
-
6.11 Length tuning (D39; closed by D50): at 4 players, bring every lineup to a mean of 60–90 minutes with p90 ≤ 110 (v0.8: mixed 72 / 95 and balanced 68 / 92 inside; casual 91 / 122 and all-aggressive 90 / 127 outside). Find where the time goes (climb to Brown vs Exam phase), bring candidate levers to the developer, simulate the chosen ones on at least two lineups.
-
6.11.1 Where the time goes (scratch
phases.py, 400 games per lineup; "endgame" = from the first Brown on the table to the win):Lineup Climb / endgame (min) Winner's stripes gained (15 needed) Drops out of Brown per game Stripes lost per game: square / Kumite / Exam mixed 49 / 22 (31%) 23.3 2.2 3.9 / 27.8 / 4.3 balanced 48 / 21 (30%) 22.6 2.2 2.4 / 26.6 / 4.3 casual 56 / 36 (39%) 24.7 4.0 11.2 / 23.1 / 4.4 aggressive 60 / 32 (35%) 28.6 2.7 12.4 / 42.7 / 4.4 Casual and aggressive are longer in both phases, most of all in the endgame (+11 to +15 min): casual players fall out of Brown twice as often (Fatica tolls, 11 stripes per game), aggressive ones trade stripes in Kumite (43 lost per game).
-
6.11.2 Existing switches (
--start,--exam), 1,000 games, 4 players, minutes mean / p90:Setting mixed balanced casual aggressive v0.8 (start 0) 72 / 95 68 / 92 91 / 122 90 / 127 start 1 68 / 92 65 / 87 88 / 122 88 / 124 start 2 63 / 88 59 / 83 81 / 112 82 / 122 start 3 57 / 80 — 77 / 110 74 / 111 Exam defender not Black ( none)60 / 77 — 79 / 103 74 / 97 The start position shifts every lineup by about the same amount, so it cannot close the ~23-minute gap between balanced and casual: start 2 puts balanced under 60 while aggressive stays at p90 122. The Black-belt defender off pushes the Exam pass rate to 67–80% (target 35–55%) and the rivals at the end to 0.27–0.49: rejected again (as in D31). Other measures barely move with the start position.
-
6.11.3 Candidate levers brought to the developer: L1 Fatica cannot drop a player out of Brown (rejected by the developer); L2 a failed challenger loses 0 or 1 stripe instead of 3 (to test); L3 accept the current length (developer: "satisfied enough").
-
6.11.4 L2 switch:
RulesConfig.exam_failure_loss(default 3; engine and bot_exam_score), sim axisScenario.exam_loss/--exam-loss(scenario names gainfail-N). Fingerprinted games identical at the default. Run:uv run dojo sim --games 1000 --seed 0 --exam-loss 3 1 0 --lineup balanced,farmer,aggressive balanced casual aggressive.Lineup Failed Exam loses Minutes mean / p90 Exam challengers per game Lead changes Halfway leader wins Worst player out Rivals within 1 belt mixed 3 72 / 95 1.68 6.1 40% 13% 0.84 mixed 1 68 / 88 1.48 5.0 44% 15% 0.94 mixed 0 67 / 86 1.45 4.6 44% 16% 0.87 balanced 3 68 / 92 1.69 6.0 39% 10% 0.81 balanced 1 65 / 84 1.50 5.0 43% 12% 0.97 balanced 0 65 / 83 1.46 4.5 43% 13% 0.90 casual 3 91 / 122 1.74 5.7 39% 12% 1.42 casual 1 87 / 116 1.61 4.9 42% 13% 1.47 casual 0 86 / 114 1.55 4.6 41% 14% 1.40 aggressive 3 90 / 127 1.58 7.3 41% 21% 0.50 aggressive 1 85 / 115 1.40 6.2 45% 23% 0.59 aggressive 0 83 / 111 1.32 5.8 49% 25% 0.54 Exam pass rate unchanged (40–44%). Reading: −1 saves 3–5 minutes on the mean and 6–12 on the p90; 0 adds only 1–2 more. The price is the comeback: the first Brown keeps retrying instead of dropping back (fewer different challengers), lead changes fall by ~1 per game, the halfway leader wins 3–8 points more, the worst player is out a little longer. No setting brings casual under p90 110.
-
-
6.9 Catch-up candidate A — skipped (D44). Was:
RulesConfigswitch, Allenamento +2 for a player 2+ belts behind the leader (bot aware of it); compare on the contention, lead and length measures and on the style win rates. -
6.8 Consolidation: the final configuration at 3 / 4 / 6 / 8 players (start 0 as for balancing, plus start 3 at 6 and 8 as in the rules, D48) with all lineups except
random(D45), 2,000 games each; every target checked;RULES.mdupdated to the next version with the decisions; open items moved to Phase 7.
Phase 7 — Finalisation (later)
- 7.1 Freeze rules.
- 7.2 Italian edition.
- 7.3 Physical tracking method and components; printable board.
- Tunnel pairs need unique labels on the printed board (the text format repeats each digit in all 4 quadrants).
Questions
Resolved
- Tie rule → Senshu (attacker wins).
- Several opponents on one square → impossible (loser is teleported); only exception handled by the Meditazione extra-step rule.
- Exam loss → −3 and Start; defender gains nothing.
- Tunnel → teleport optional on stop, movement over.
- Optional vs mandatory effects → D25.
- Engine edge rules → D27.
- Sfida squares → keep, balance via low count.
- Il Peso della Cintura → keep (1 card).
- Player count → focus 4, support 3–8.
- Tests → the agent runs the suite (
uv run pytest), plusruff check,ruff format --check,pyright. - Minutes estimate → 45 s per turn, +30 s per Kumite.
- Q4 Target net income per turn → current pace is fine: A already runs ~66 min (p90 ~85); the winner's pace is measured instead of a table average.
- Variant A vs B → B dropped (D28).
- Final Exam → the defender fights as a Black belt (D31).
- Q5 Phase 6 targets → confirmed as a starting point (D32).
- Q6 Fatica avoidable (bots stop on it once in ~4,000 turns; ~24 distinct end squares per move; Allenamento reachable on 79% of moves, Fatica never forced) → test the chance square first, then Fatica on crossing (D33).
- Q7 Casual bot sample size → the blind sample of 6 is far weaker than the heuristic bot (14–18% vs 36–46% win rate per seat); bots stay as they are (D40).
- Safe Room placement → the owner places the pawn on any square of their room (setup and when sent to Start).
Open
- Q2 Board asymmetry: keep the quadrant as source of truth, or later switch to the full board as source of truth with a symmetry report (warnings) instead of generation? (Deferred by the developer.)
Risks
- Movement enumeration: self-avoiding walks of length up to 12 can explode in open rooms. Keep rooms small; prune by outcome (destination + ordered opponents crossed + Dojo entry).
- Engine speed: after 6.10, ~65 games/s per process (heuristic and casual bots). Further gains would need changing the move enumeration itself (e.g. grouping walks by outcome), not attempted.
- Simulation conclusions depend on bot quality; compare several profiles before trusting a result.
- Home farming: board draft 2 (D42) moved the Allenamento onto the Dojo ring; the own-quadrant share of square income is 62–67% (draft 1: 74%), above the 60% aim because players cross their own quadrant for most of the game. Accepted with draft 2 (6.5).
External documentation
- uv — https://docs.astral.sh/uv/ — project init, dependency and Python version management.
- Python
tomllib— https://docs.python.org/3/library/tomllib.html — stdlib TOML parser forlegend.toml. - pytest — https://docs.pytest.org/ — unit tests.
- Ruff — https://docs.astral.sh/ruff/ — lint and format.
- WKF Kumite competition rules (wkf.net, "Rules") — source of the Senshu concept.