Rules v0.8: Fatica on crossing, no Kumite in round 1, board draft 2
- Fatica costs a stripe for every Fatica walked onto; a route whose Fatica drops a Brown player below 15 no longer enters the Dojo - No Kumite in the first round: opponents are treated like meditating pawns - Board draft 2: two Fatica tolls per quadrant, Allenamento moved to the ring - Casual bot, --summary-csv, per-seat breakdown and move-options metric - Out of contention measured at 3 belts - Plan: Phase 6 baselines, decisions D34-D43 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+16
-4
@@ -10,6 +10,7 @@ from dojo.events import (
|
||||
GameOver,
|
||||
KumiteFought,
|
||||
Moved,
|
||||
MoveOptions,
|
||||
Source,
|
||||
TrackChanged,
|
||||
TurnSkipped,
|
||||
@@ -37,9 +38,11 @@ def test_measure_counts_fights_income_and_exams() -> None:
|
||||
metrics = run(
|
||||
[
|
||||
TurnStarted(1, 0, 7),
|
||||
MoveOptions(0, ("A", "F", ".")),
|
||||
Moved(0, (HOME_0,)),
|
||||
TrackChanged(0, 0, 1, Source.SQUARE),
|
||||
TurnStarted(1, 1, 5),
|
||||
MoveOptions(1, ("A", "?")),
|
||||
Moved(1, (HOME_0,)),
|
||||
TrackChanged(1, 0, 1, Source.SQUARE),
|
||||
fought(1, 0, FightKind.EQUAL),
|
||||
@@ -65,6 +68,10 @@ def test_measure_counts_fights_income_and_exams() -> None:
|
||||
assert (metrics.card_gain, metrics.card_loss) == (5, -1)
|
||||
assert (metrics.square_income_home, metrics.square_income_away) == (1, 1)
|
||||
assert (metrics.winner_seat, metrics.winner_bot, metrics.rounds) == (0, "balanced", 2)
|
||||
assert (metrics.move_choices, metrics.end_squares) == (2, 5)
|
||||
assert (metrics.allenamento_reachable, metrics.fatica_reachable) == (2, 1)
|
||||
assert metrics.final_track == (4, 4)
|
||||
assert (metrics.exam_attempts_by_seat, metrics.exam_defences_by_seat) == ((1, 0), (0, 1))
|
||||
# Both Exam rounds count as fights for the time estimate.
|
||||
assert metrics.minutes == pytest.approx(round((3 * TURN_SECONDS + 5 * KUMITE_SECONDS) / 60, 1))
|
||||
|
||||
@@ -94,9 +101,9 @@ def test_standings_are_sampled_at_turn_ends() -> None:
|
||||
# Halfway is the end of turn 2, led by player 1.
|
||||
assert metrics.halfway_leader_won is False
|
||||
assert metrics.contenders_at_end == 0
|
||||
# Out (more than 6 behind): players 1 and 2 after turn 1, player 2 after turn 2.
|
||||
assert metrics.out_of_contention_share == pytest.approx(3 / 12)
|
||||
assert metrics.worst_out_of_contention_share == pytest.approx(0.5)
|
||||
# Out (more than 9 behind): player 2 after turn 2 only.
|
||||
assert metrics.out_of_contention_share == round(1 / 12, 3)
|
||||
assert metrics.worst_out_of_contention_share == pytest.approx(1 / 4)
|
||||
# 0>1 becomes 1>0; 0>2 becomes 2>0; 1>2 (ties skipped) becomes 2>1.
|
||||
assert metrics.rank_swaps == 3
|
||||
assert metrics.winner_turns_to_brown == 1
|
||||
@@ -127,13 +134,18 @@ def test_summarize_splits_wins_by_seat_and_bot() -> None:
|
||||
replace(base, lineup="balanced,random", winner_seat=0, winner_bot="balanced"),
|
||||
replace(base, lineup="random,balanced", winner_seat=1, winner_bot="balanced"),
|
||||
replace(base, lineup="random,balanced", winner_seat=0, winner_bot="random"),
|
||||
base,
|
||||
replace(
|
||||
base, final_track=(2, 9), exam_attempts_by_seat=(0, 3), exam_defences_by_seat=(2, 0)
|
||||
),
|
||||
]
|
||||
|
||||
summary = summarize("test", rows)
|
||||
|
||||
assert summary.finished == 0.75
|
||||
assert summary.win_rate_by_seat == (0.5, 0.25)
|
||||
assert summary.seats[0].final_track == pytest.approx(0.5)
|
||||
assert summary.seats[1].exam_attempts_per_game == pytest.approx(0.75)
|
||||
assert (summary.seats[0].exam_defended, summary.seats[1].exam_defended) == (0.25, 0.0)
|
||||
assert summary.win_rate_by_bot == {"balanced": 0.5, "random": 0.25}
|
||||
assert summary.rounds.median == 10
|
||||
|
||||
|
||||
Reference in New Issue
Block a user