Skip to content

Strategy search 2026-10-11: five split_shape variants, LeadAndSupport shot fix - #142

Draft
isaac0804 wants to merge 12 commits into
mainfrom
search-20261011
Draft

isaac0804 wants to merge 12 commits into
mainfrom
search-20261011

Conversation

@isaac0804

@isaac0804 isaac0804 commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

One session (2026-10-11/12): an orchestrated strategy search, plus the shared fixes it turned up.

Shared fixes (each with a regression test that fails before, passes after)

  • LeadAndSupportTactic shot-target flip (d7659277): with two near-tied gaps the leader's target flipped every tick, so it never kicked and the match froze. Now uses _pass_and_score's 0.15 m switch margin.
  • turn_on_spot blocked pivot (205ccfeb): when an enemy blocked the pivot, the final override replaced move()'s escape command with the pivot term and pushed into the blocker. A blocked pivot now keeps the escape command.
  • DecoyOverloadTactic finish phase (d3b093b2): never released when the ball stopped making progress. Now releases after 3 s without progress, like its timeout.
  • docs/STRATEGY_DEVELOPMENT.md: leftover merge-conflict markers removed (46e9fa4a).

These touch shared tactics and a shared skill, so check_strategy_branch.py --base main flags them by design.

Strategy search

Haiku subagents researched split_shape and implemented one-idea variants in their own worktrees. Each was reviewed and passed its own tests and test_all_strategy_configs.py. Six kept: ee647a3a, plus split_outlet_wall (bd71d436). split_wall's free-kick wall committed keep-out fouls when the box clamp pulled it within 0.5 m of the ball. Fixed in 47af142b: keep-out fouls fell from 115 to 14 for split_wall and from 58 to 7 for split_outlet_wall.

Round-robin, 18 configs, 153 matches, with all fixes (replays/tournament_20261012_095359):

Strategy Idea W-D-L GF-GA Points per match vs split_shape
split_sticky possession hysteresis 15-0-2 136-83 2.65 8-7
split_block BlockShapeTactic defense 14-1-2 144-82 2.53 8-8
split_wall two-robot wall at the opponent's direct free kicks (first strategy to use referee_overrides) 14-1-2 119-75 2.53 7-6
split_outlet one robot held high on the weak side while defending (new OutletTactic) 14-0-3 127-85 2.47 8-7
split_outlet_wall outlet plus wall 13-1-3 127-74 2.35 7-2
split_press 2-robot press without the ball 12-2-3 138-73 2.24 8-8
split_shape reference 10-3-4 113-76 1.94

Every variant finished above split_shape, but the order among them changed with every shared fix. The screen is one deterministic match per pairing, so it can't rank them.

Head to head with seeded noise (2026-10-12). Each pairing played its 8 deterministic side/kickoff settings and 20 seeded noisy matches: side fixed, kickoff alternating, 3 mm and 1° vision noise, 2% of detections dropped. The noise comes from the existing rsim_noise/rsim_vanishing, injected by a scratch script, so no repo or match-cache change. Goal difference per match for the first-named strategy:

Pairing 8 settings, no noise 20 noisy seeds
split_block vs split_shape 6-2-0, +2.4 ± 0.9 11-1-8, +0.5 ± 0.6
split_outlet vs split_shape 4-0-4, −1.3 ± 1.3 8-4-8, −0.6 ± 0.8
split_sticky vs split_block 3-1-4, +0.0 ± 1.4 8-4-8, −0.3 ± 0.5
split_shape vs counter_flow 7-1-0, +4.0 ± 0.7 17-1-2, +3.1 ± 0.5

No variant is shown better than split_shape, which stays the champion. split_block was picked on its deterministic result, and that edge did not hold over 20 noisy matches. Noise keeps the real gap against counter_flow, a seed replays bit for bit, and each match has about the same spread as a deterministic one. So noise gives as many matches per pairing as needed, without making any single match noisier. That's the basis for the evaluation change (roadmap 2a), in a separate session.

The scenario bench (860 starts, 14 min) found no difference for split_block vs split_shape (t = +0.8). 63% of its starts tied.

Known open

6 of 153 round-robin matches stalled; none of the 80 noisy matches did. In each, two carriers pinned the ball between them until the referee's no-progress stop ended it. The cause of the stuck turn is not found (diagnosis in the session notes); fixing it changes a shared skill, so it is left for its own session.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ECXiwf3VYxBTMmrLaexRQK

isaac0804 and others added 12 commits October 11, 2026 20:26
…ied gaps

find_best_shot was called without prev_best_shot_y, so with two near-equal
gaps (the leader on the centre spot after a goal) the target flipped sign
almost every tick, turn_on_spot chased it, oriented_towards never passed and
kick() never fired: a COMMITTED_FROZEN stall until FORCE_START (split_rest
and split_sticky vs split_shape, 2026-10-11). Uses _pass_and_score's 0.15 m
switch margin.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ECXiwf3VYxBTMmrLaexRQK
Keeps HEAD's wording; the other side still described the status labels
removed on 2026-10-10.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ECXiwf3VYxBTMmrLaexRQK
split_block (BlockShapeTactic defense), split_sticky (possession hysteresis),
split_press (2-robot press without the ball), split_outlet (new OutletTactic:
one robot held high on the weak side while defending) and split_wall (a
two-robot wall at the opponent's direct free kicks, via referee_overrides).
Implemented by Haiku subagents in per-candidate worktrees, reviewed here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ECXiwf3VYxBTMmrLaexRQK
When an enemy or teammate sat on the pivot-push side, the blocked branch
steered move()'s target to an escape point, but the pivot override then
replaced move()'s lateral velocity unconditionally, discarding the escape:
zero net motion, no turn, no kick, a COMMITTED_FROZEN stall (3 of 4 in
tournament_20261011_205245). The override now applies only when not blocked.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ECXiwf3VYxBTMmrLaexRQK
…progress

A decoy pinned body-to-body against a marker held the ball still for the
whole 12 s finish timeout, past the referee's 10 s no-progress stop: a
COMMITTED_FROZEN stall (overload_press_vs_press_trigger_flow,
tournament_20261011_205245). Releases the same way the timeout does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ECXiwf3VYxBTMmrLaexRQK
At the opponent's direct free kick, split_wall and split_outlet_wall placed the
wall 0.9 m out on the ball->goal line. With the ball near our defense-area front
edge that point lies inside the box, and the box clamp pulled it back to the
edge, 0.43-0.46 m from the ball. That is inside the 0.5 m keep-out foul radius,
so the referee called keep_out (115 + 58 fouls in the 2026-10-11 round-robin).

_legal_target now moves any target still inside BALL_KEEP_OUT_DISTANCE to the
nearest legal spot on that circle not already claimed by an earlier target
(WALL_SPACING_M apart). Sliding everything along the edge line stacked robots.

Adds regression tests on the real foul state and on a marker pushed to the circle.

Co-Authored-By: Claude Haiku 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ECXiwf3VYxBTMmrLaexRQK
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant