Commit Graph
2 Commits
Author SHA1 Message Date
wuwiandClaude Opus 5 c629ae1108 The ladder has names, the bodies play tennis, and the stats screen splits
THE SPRITES. The match opponent borrowed the turned CPU's art — a body drawn
to SHAMBLE at the camera with its racket hanging at its side, which is what
was playing tennis points against you. It has its own family now, 'r', drawn
off the LIVING opponent's poses: a ready stance, a shuffle pair and a real
forehand, at every wound stage, men's and women's — 20 frames, six batches.
'c' keeps its shamble untouched, because in the gore mode shambling is exactly
what the turned CPU should be doing. The pose comes from racketAI's own
`pose`, so the picture cannot drift from the behaviour, and a one-armed
opponent still plays tennis instead of reverting to a walk.

Two pipeline bugs found doing it, both fixed at the root in assets/:
- _fine.py keyed EVERY magenta pixel, not just the background, and the
  generator paints racket strings in the backdrop colour more often than not —
  so frame after frame installed a man holding an empty hoop. Background is now
  the region connected to the border; magenta left INSIDE a body is repainted
  pale grey rather than punched out.
- the flood fill silently did nothing, because Image.fromarray images are
  read-only and PIL's floodfill swallows the write error. .copy() plus a real
  error if it ever fills zero pixels.

THE LADDER (handoff slice 2). Rung N takes design N's name off the chapter
roster — the club's dead staff play you at tennis here and come for you in
gore, same joke twice — plus a personality that is DIALS, not new mechanics:
pace, width, flub and speed scalings multiplying numbers racketAI already
reads. A rung is a data row. Name plate on the walk-on, and the kill files
under the rung rather than under the generic body.

THE STATS SCREEN follows the mode split: BODY COUNT / THE LADDER / THE RECORD
behind a mode strip, each with its own three figures, its own roster heading
and its own footer. The weapon shelf and the roster hide in the modes that
have neither, rather than printing a line about something the mode cannot do.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 09:34:26 +02:00
wuwiandClaude Opus 5 c89d4a3ff9 Three modes, picked up front — and CLASSIC TENNIS is one of them
The setup screen picks WHAT before WHO and WHERE. Three rows out of a table,
in the court row's own markup:

CLASSIC TENNIS is not the opener with the turn switched off and left there —
it is the mode the other two are built on, so it gets real match scoring: six
games with a two-game lead is a set, best of TUNE.classicSets is the match,
the board shows the sets column (hidden until now outside splatter) and the
bar under it says which set this is. The CPU stops rubber-banding and flubs
less: aiFlubLoss exists to get a new player PAST the opener, and a mode whose
whole promise is a real match cannot be won by an opponent that falls apart
the moment he goes ahead. No tiebreak — 6-6 plays on to 8-6. Marked ponytail.

That needed a second ENDING, the one with no corpse in it: G.done, the same
summary and gated tap as the death screen, its own words (GAME, SET, MATCH. /
BEATEN.) and the man still standing. The three endings now share one block
rather than three copies of it.

Caught by the first classic test: stats banked only the FIRST classic run of a
session. `banked` was cleared by the next KILL, and a classic match has no
kills in it at all — every later match was swallowed by the double-bank guard.
beginRun() is the honest reset and restartRun calls it.

ZOMBIE TENNIS from the menu is one line; the back room keeps its door.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 09:27:49 +02:00