Oliver's batch, delivered in dependency order. "The opponents look pretty
harsh, almost already pre-zombie" — so BOTH tennis opponents got a new
identity: warm skin, human eyes, an easy near-smile, rolled anchor-first so
every later sheet inherits the face. The male's bounce pair also ADOPTS the
female's palm-out posture (his old crouched receiver stance was the wrong
pose for bouncing a ball — her better one is now the shared convention), and
the pre-serve ball was re-measured onto the drawn palms: BOUNCE_IDLE's oDx
0.45 -> 0.24 / oApex 0.55 -> 0.72 for his close carry, with her wider reach
riding TOURS (oDx 0.48 / oApex 0.73) the same way the player's pair already
does.
"parts of the body as well as the inner of the racket are solid" — the beds
were the cutter's own doing: _fine.key repaints enclosed magenta pale grey
(protection against accidental magenta strings), which defeated the beds we
now draw magenta ON PURPOSE. key()/main() grow a bed=True switch (the
famroll convention, used by _runroll and the refresh cuts); the run cycles'
beds went from ~70% to ~44% opaque — strings, not paddles. Enclosed pockets
of a roll's off-spec background (one sheet came back on blue) are scrubbed
by corner-colour distance too.
Both RUN CYCLES re-rolled off the friendly anchors: his landed 8 clean
frames (racket +0.05..+0.30, one side); hers took four rolls — the gates
caught a white background, a crossing racket, near-dup neighbours — and the
keeper drew a 10-frame cycle, from which the best 8 were chosen by
maximising the minimum adjacent stride (29.7%, smoother than his 22.7).
o_run7/8 return to the SPR list.
AND THE CHASE STOPS DITHERING (Oliver: "switching between a left and right
movement increasingly faster the nearer the ball comes"): intercept()
re-solves every frame and the earliest-reachable point jumps around its
solution as the flight shortens, flipping his run direction each time. The
CPU now commits to its stored target unless a fresh solve moves it by more
than 0.35 m. SPRV 121, main.js v244, 66 tests, every opponent frame verified
200 in the live game.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Her run cycle carried a DETACHED SHOE floating behind her in every frame —
a cut that kept two blobs per figure — spotted while fixing the men's
flicker. Four rolls to a keeper: roll 1 closed on a duplicate (8->1 at
4.4%, gated), roll 2 came back a grid, roll 3's grid was re-laid into one
row locally but its racket flipped sides frame to frame (-0.42..+0.31, the
exact "flashing left and right" the warning exists for), roll 4 landed:
eight frames, racket steady at +0.05..+0.17, one face, no luggage. SPRV 119.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Oliver: 'the motion seems very flashy and unnatural'. Two causes, both
measured: drawChar centres a frame by its total width while the racket's
reach varies across the cycle, so the BODY teleported sideways up to 28
source px on a frame swap (the female player was worst) — every frame is now
padded until its lower-third centroid sits at the frame centre (residuals
±0.2 px, the normalisation lives in _runroll.py's cut). And the hardcoded
4.5 cycles/s was tuned on 2-4 near-duplicate frames; on eight real phases it
was a strobe — rolled sets stride at TUNE.runHz (2.4), old art keeps 4.5.
In-pane: body wobble down from ~36 device px per swap to 3.2.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The old run frames were generated one at a time and it showed: 91/110/92/98 px
of body-width drift, duplicated poses drawn differently, no racket. Each
character (player m/f 6 frames, opponent m/f 8) now comes from ONE 4K call
anchored on a composed identity reference of its settled frames — the broken
run art stayed out of the reference on purpose. Stride-gated, cut with _fine,
judged by eye per roll. drawChar probes run8/run6/run4/run2.
Side effect: the male opponent's old run art faced LEFT against the
art-faces-RIGHT convention — he had been moonwalking right since install.
Fixed by drawing the new rows to the convention.
Pipeline lessons recorded in PROJECT.md (the model negotiates the count; a
back view has no direction; the racket clause goes early and loud).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The court screen picks WHO as well as WHERE now: two tiles above the court
rows, men's or women's singles, remembered like the court is. No new stage —
three rows and a pair of buttons already fill a phone, so the tiles go side by
side and the tap count from splash to play does not change.
Everything downstream is one line: drawChar already built every frame name off
a single prefix, so SK() appends '_f' when the women's tour is picked and falls
straight through to the men's frame for anything without a twin. The horde, the
officials and the ball boys are shared — they are staff, not the draw — but the
turned CPU is not: a male corpse opposite a female player reads as a bug.
Her frames came back as a different woman in every batch — blonde in one,
auburn in the next, greyscale line art in a third — because each was anchored on
the MAN whose pose it was. "newart" repaints the character and "state" is welded
to the corpse palette, so neither could say "the same living woman, a new pose".
That mode now exists, and every batch anchors on her own settled frame.
The death is drawn to frame 3 and recoloured after it. The generator will not
draw a dead woman in any wording worth using; frames 4 and 5 survive that
because by then she is flat and then a heap of cloth, so they are the men's
drawing with the blue shorts painted into her white (see assets/_die_f.py). The
collapse still falls 224/159/117/103/43 straight through the handoff.
Her first bounce frames reached to the shoulder, which is a catching pose, not
patting a ball — redrawn low rather than bending BOUNCE_IDLE to fit a wrong
drawing, so both tours share one apex and the ball meets her palm.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>