Skip to content

Add Subway Surfers-style lane runner model comparison - #11

Open
Alex-Wengg wants to merge 9 commits into
feat/flappy-model-comparisonfrom
feat/runner-model-comparison
Open

Alex-Wengg wants to merge 9 commits into
feat/flappy-model-comparisonfrom
feat/runner-model-comparison

Conversation

@Alex-Wengg

@Alex-Wengg Alex-Wengg commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

Stacked on #10. Retries the runner idea with per-row decisions instead of per-frame control. Each of the 5 moves is labeled with its consequence, following the Tetris harness pattern.

  • DecisionPolicy: the 13 model backends are now a shared target; FlappyBirdPolicy wraps it (Flappy results unchanged).
  • LaneRunner engine (survivable by construction), LaneRunnerCheck (model / heuristic / random), LaneRunnerDemo app.
  • Gets harder over time. It starts with a 30-row easy opening, then over 240 rows the open rows disappear and more lanes are blocked. In the app, each row is also 0.5% faster, down to 40% of the starting interval.
  • App: 3D third-person SceneKit view skinned with Kenney CC0 models (train/platformer kits, license files bundled), smooth jump/slide/lane animations, coin pickup effect, and a run timer. It shows the exact model input and counts late rows. LANE_RUNNER_MODEL and LANE_RUNNER_SEED start a run with no clicks.
  • Kai/Lex (3 candidate slots) and NanoJev (4) can't take 4–5 moves; they now fail up front.

Seeds 1–4, 300-row cap (1,200 max):

Policy Rows Total
Heuristic 300, 300, 300, 300 1,200
GLiNER 2.5 base 30, 43, 36, 20 129
GLiNER 2.5 multilingual 20, 12, 20, 10 62
GLiNER 2.5 small 10, 18, 10, 10 48
Laya 6, 2, 4, 16 28
GLiClass 4, 2, 2, 12 20
LFM2.5-350M-RLCD 4, 2, 2, 12 20
Random 2, 2, 8, 2 14
Kev 0.6B 4, 2, 4, 2 12
Verdict / Jeff / Kev 0.5B — 10 each

Every run ended when the model picked an option labeled crash. Only GLiNER base regularly got past the easy opening. Details in Sources/LaneRunnerDemo/README.md.

🤖 Generated with Claude Code

Alex-Wengg and others added 9 commits September 23, 2026 01:08
Retry of the runner idea after the Flappy Bird trial ruled out per-frame
control: one decision per row, five moves (left/right/jump/slide/stay),
and every option labeled with its consequence over the three visible
rows (the Tetris harness pattern). Option order rotates each row.

- DecisionPolicy: the 13 model backends move out of FlappyBirdPolicy
  into a shared target (choose(state:instruction:options:)).
  FlappyBirdPolicy is now a thin wrapper; Flappy results are unchanged
  (GLiNER multilingual seeds 1-4 still 1 pipe / 10.98 s).
- maximumOptions per model: Kai/Lex Choice packages have 3 candidate
  slots (marker_positions [1, 3]), NanoJev 4, so they cannot take the
  runner's 4-5 moves and now fail up front instead of in the worker.
- LaneRunner engine (solvable by construction), LaneRunnerCheck
  headless runner (model, heuristic, random), LaneRunnerDemo app that
  shows the exact model input and counts late rows.

Seeds 1-4, 200-row cap: heuristic 800/800; GLiNER base 184, GLiNER
multilingual 160, Kev 0.6B 132 (66% first-position picks), GLiClass
70, GLiNER small 56, Jeff 30 = random 30, Laya 22, Verdict 16, LFM 12,
Kev 0.5B 10. Every run ended on an option labeled "crash".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Model loading (asset SHA-256 checks over hundreds of MB, then Core ML
compilation) ran on the main actor, so the window stopped responding
while "Loading..." showed. Load in a detached task instead. Launched
from a terminal the unbundled app also needs a regular activation
policy to take focus.

LANE_RUNNER_MODEL / LANE_RUNNER_SEED / LANE_RUNNER_ROW_MS preselect a
run that loads and starts without clicks, for demos.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Replaces the flat Canvas board with a third-person SceneKit view:
subway trains and rail track from Kenney's Train Kit; character, gold
coins, low fences, overhead beam, and trees from the Platformer Kit
(both CC0; license files bundled under Resources/Kenney, ~500 KB of
OBJ/MTL/colormap). Rows slide toward the camera over each row
interval; the runner eases between lanes, jumps, slides, and falls on
a crash. Game rules, model inputs, and results are unchanged.

Also delays the heuristic autostart so the controller picker's reset
cannot cancel it, and widens the window for the 3D view.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Live TIME metric (pauses excluded) beside distance and coins, and the
final time on the run-over card.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Kenney's poles model is a solid log palisade, so the high bar looked
like a wall rather than something to slide under. Draw two thin posts
and a red/white beam at chest height with open space below, and drop
the unused poles/platform models.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Lane movement, jump height, and slide squash ran on one node, so each
row's lane move snapped y back to 0 and the scale reset cut jumps and
slides short. Split the runner into lane / hop / stride / body nodes so
the motions no longer fight.

Also retime the track: the passed row now slides from half a row ahead
to half a row behind, crossing the runner mid-row where a sine jump
peaks and a smoothstep slide is lowest (previously the obstacle arrived
after the jump had landed). Lane changes ease with a small lean, the
runner bobs while running, and a crash stops at the obstacle before
falling.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
When the runner crosses a coin in its lane, at the moment the coin
reaches it: the coin pops up, spins, shrinks and fades; a short burst
of soft gold sparks plays; a billboarded "+1" rises and fades; and the
runner does a quick squash-and-settle bounce.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Like Subway Surfers and Temple Run, runs now ramp up:

- Track density (engine): a 30-row easy opening with the original
  rules, then over 240 rows open breather rows disappear (up to 65%
  of the time) and blocked lanes rise (trains 40 -> 55%, open 20 -> 5%).
  Back-to-back obstacle rows are only generated when every lane
  passable in the first can legally enter the second (same lane with
  the right move, or an adjacent open lane), so tracks stay survivable:
  the heuristic clears 600 rows on seeds 1-12.
- Speed (app): each row is 0.5% faster, floored at 40% of the starting
  interval; the panel shows the current interval and multiplier.

Tracks changed, so results are re-run (seeds 1-4, 300-row cap):
GLiNER base 129, GLiNER multilingual 62, GLiNER small 48, Laya 28,
GLiClass 20, LFM 20, random 14, Kev 0.6B 12, Verdict/Jeff/Kev 0.5B 10.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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