Playing on a phone, the boards read as a grid of long straight lines crossing
everywhere — "一看到这个画面,我脑袋就大". The cause is one line in the filler.
Each family lays its signature routes over part of the board and leaves the rest
to completePorts, which paired every leftover port with the one straight across.
On a switchback board that made 76% of all track pairs diameters and left 43 of
61 cells containing nothing but diameters. Two diameters in one cell always
cross, so the straightness and the crossings were never two problems.
Preferring a bend halves both, in every family: switchback 76% → 40% straight
and 2.38 → 0.92 crossings per cell, crossing 86% → 10%, weave 37% → 5%.
It was also quietly suppressing 反差, the swing between a piece looking hopeless
and becoming trivial, which the design brief calls the point of the game.
Straight routes barely change between orientations. With bends, petals goes from
4.2 to 14.0 and crossing from 4.8 to 28.8 — both had been failing the ≥12 gate
and were absent from the level pool entirely. Petals is the family the user
singles out as the good-looking one. Generation yield rises with it: four seeds
now grow 24 playable levels against 3, at greater rotation depth.
createRouteBoard keeps 'straight' as its default so nothing already built moves;
the sweep opts in. labs/route-gallery draws both, with the real renderer, so the
choice is made by looking rather than by reading a number.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Pieces still read as slow. Cruising speed goes from 120ms per unit to 85: the
median departure across the shipped fifty drops 970ms → 763ms and a level's
whole animation budget 15.6s → 12.7s, about 18% off. The longest departures do
not move — the cap holds them at 3.46s — so if those still drag, the dial is the
cap, which was settled separately and is left alone.
The gates that guarantee a level opens with something worth watching are stated
in milliseconds, and they were picked while a piece crossed a unit in 120ms.
Held fixed while the speed changes, they stop meaning what they meant: this
change alone made 20 of the 50 shipped levels "fail" an opening gate every one
of them had passed, purely from the unscaled number. Scaled to the dial, none
fail — the set is unchanged, and the alarm was an artifact of the constant. So
the cruise threshold and the opening floor now derive from the speed, naming
the speed they were calibrated at.
exitTiming takes msPerUnit the way it already took knee and maxMs, and the
comparison lab gets a speed slider, reads the levels actually shipping rather
than the prototype sweep they were selected from, and totals every route in the
campaign instead of the four on screen — those four skew long, where the cap
flattens any speed change to 6%.
The test that pins constant cruising speed now reads the dial from the token
instead of hard-coding 120, so tuning motion no longer looks like a broken
guarantee.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
refit-weights regresses the weights select-50 scores with against what agents
actually experienced, so a round of play is a flag on the next selection rather
than an edit. Ridge, because seven collinear features on fifty levels otherwise
hand back large coefficients that cancel.
Most of the work here is in refusing to produce a number. The response averages
the difficulty rating with two continuous measures of the same thing, and a
component with no spread is dropped by name instead of being silently averaged
in as zeros — which is what the first version did, reporting R² = 0.75 for a
fit that never saw a rating. When the rating is flat the script now says so and
says what the remaining fit is really measuring, which is board size.
legibility() asks what it costs to know what you may tap: how far the eye must
follow the cheapest free piece, and how many pieces are held by somebody their
line never touches. It was built to explain why ratings came back flat. It does
not — it correlates -0.02 with them — so it stays a measurement, printed on the
review sheet beside the longest route on the board, and gates nothing.
prototype-d5 takes --seedFrom so a wide sweep shards across cores.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The chain locks all four of its pieces at the opening by construction, and the
pieces grown around it are mostly locked too, so a level built from it hands a
player two rim pieces and a third of a second of animation before any thinking
starts. Measured across the 235-level pool: median two tappable pieces at the
opening, and the best departure available plays for 0.57s.
Growth now reserves a couple of slots for showcase pieces — tappable at the
opening, with a route long enough to read as a journey and short enough to stay
under the animation ceiling. Median opening choices go 2 to 3 and the best
opening show 0.72s to 1.12s, without shortcutting the lock: each candidate is
still put through the solver.
Rotation quota is gone from the board. Turning is free and it is what the game
is about, so depth is grown rather than capped; what is gated is whether each
turn pays out, whether pieces swing between hopeless and trivial, and whether
there is a show up front.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every model that played the D5 set complained about the same moment: two
pieces left, interlocked, and nothing on the board saying which way to turn.
codex-spark took it to the end — it cycled all six orientations on L18 and
gave up on a level that was solvable, with clarity rated 5. Replaying the
position shows exactly one of the six orientations releases anything.
deadTurnAudit now reports endgameMinOpen: across reachable states with three
pieces or fewer left, the fewest orientations that release anything. It is
computed inside the walk that was already happening, so it costs nothing. The
generator requires at least two.
The gate picks out precisely the four levels every model stalled on, with no
false positives — the other fourteen already had two or three. Regenerating
drops the spiral family entirely: its structure produces single-exit endgames
by construction, not by unlucky seed.
Measured on the regenerated set, rule bot first and then grok-4.6 xhigh over
all 18:
blind rotations 1.17 -> 0.29 per level
extra rotations 1.22 -> 0.35
dead taps 2 -> 0
run time 55.5s -> 34.7s
stuck rating 1.89 -> 1.41 (this metric repeats at r = 0.85)
"which way do I turn" complaints 22% -> 12% of levels
The gate is a floor, not a difficulty dial: difficulty also fell, 2.39 -> 2.12,
because the levels it removes are the hard ones. And it treats a symptom — the
t0/t3 interlock is what the four-piece chain in createDeepLock builds by
construction, so the complaint is halved rather than gone.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The shipped 1000 levels have a hole: 568 of them need no rotation at all, and
none needs more than two — the mechanic the game is built on is mostly
decoration. This fills the empty band with levels that need at least three.
createDeepLock builds a four-piece chain where each link only releases at a
later orientation, and growDeepLevel packs the rest of the board around it
without opening a shortcut. Candidate pools are built per orientation and left
untruncated; ranking by bend count first starved the packer and capped levels
at four to six pieces instead of twelve.
deadTurnAudit enumerates every reachable (orientation, remaining-set) state to
prove no dead ends exist, and counts how long a player can be left with
nothing to do — solvable and feeling solvable are different things, which is
what "level 2 is impossible" turned out to be about.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>