The opening gate asks for a departure of at least 0.57s, which is how a sparse
board pays: one piece threading a long route while you watch. A packed board
cannot pay that way — the pieces free at the opening are the ones at the rim,
and their routes are short by construction. So the gate rejected 29 of 29
crowded candidates for lacking a payoff they deliver in a different currency:
the cascade of pieces leaving one after another, which is what the brief singles
out as 多个棋子连环出去,非常赏心悦目.
openingRunMs totals every departure available before a turn is needed, and the
gate takes either that or the single long show. Crowded boards come through at
46% density, 0.92 crossings per cell and 14% straight track.
Both thresholds scale with the motion dial the way the first one already did.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
trackShape moves the two drawing measurements into src so the sweep, the pool
build, the selector and the gallery share one definition. They are one property
seen twice: a chord joining opposite ports is a straight line, and two of those
in a cell always cross, which is why the filler that paired leftovers straight
across produced a board that is both all-straight and all-crossings.
Crossings per cell is now a gate at 1.0. Bending the leftover ports alone takes
the median from 2.36 to 0.93, so the gate costs a third of the candidates rather
than most of them, and it is the difference the boards were described by.
Selection gains --plan, an ordered list of segments each naming how many levels
it wants and of what kind. Depth quotas cannot express the shape this campaign
needs, because the two good things pull against each other: a crowded board
clears beautifully and caps at three turns, while a deep lock needs room and so
stays sparse — at five turns and eight pieces per orientation, 16 of 18
candidates fail the release gate. Sorting by depth would file every crowded
level first and every deep one last; segments alternate them deliberately, and a
plan is left in the order it was written rather than re-sorted.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
No level in this project is more than a third pieces — 13% to 28% across the
shipping fifty, and the thousand-level set that preceded it peaks at 32% with
exactly one level above 30%. Clearing a full board is the satisfying part of a
clearing game, and it has never been on offer.
It was not a design choice. deadTurnAudit walks the reachable state space with a
20000-state budget, and the endgame gate read its answer. Past about eleven
pieces that budget is gone long before the walk reaches any state with three
pieces left, so the audit returned `endgameMinOpen: null` — and the gate,
written `endgameMinOpen >= 2`, compared null and got false. Every denser level
was thrown out for a bad endgame that was never looked at. `exhausted` was right
there in the audit's return value and nothing consulted it.
Endgames are now enumerated outright rather than walked to: C(26,3) is 2600
subsets, so it finishes on any board this game will ever have. The statistic is
the SHARE of endgames that are tight, not the minimum over them, because a
minimum over more subsets falls for arithmetic alone — the same confound that
made doubleDead look eight times worse for deep levels when the rate was 2%
against 5%. By share, crowded boards are the better ones: worst 0.33% against
1.73% for sparse.
With the gate measuring something, density inverts. At eight pieces per
orientation: 44% density, 18 of 23 candidates passing the whole chain, and not
one failing the dead-turn gate. At two: 19% density, 9 of 23, with eleven
failing on dead turns. perTurn becomes a swept dial, and the hard piece ceiling
that truncated the placement schedule regardless of it is gone.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>