The lob is out: a gesture the opponent's position redefines is unpredictable

Oliver, on the build: "all good but the lob. please remove it - this is
totally unpredictable."

Reverted in full — oppAtNet, farBody, TUNE.lobArm, TUNE.lobApex,
SHOT_DEPTH.lob, the branch in doHit and its two tests. The forward flick is
the smash it always was. Everything else from that commit stays: the pace
feedback (streak, crack, camera kick) and the death match's blood alignment.

The reason is worth more than the code, and PROJECT.md carries it as a rule:
a gesture whose MEANING depends on where the opponent is standing is
unpredictable however well the shot is tuned. It is the same objection
input.js already states about the slingshot — the direction you moved is the
thing you asked for, no invisible modes — and the written comparison let
option (c) past it on the argument that context cannot mis-fire. It can: you
do not track where the far body is standing while a ball is coming at you, so
one thumb movement produced two shots for reasons you were not watching. The
LOB word at contact explained the surprise; it did not prevent it.

If it comes back it needs a gesture of its own. The ballistics are solved and
are in the history at 4f4534e.

111 tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-22 13:13:56 +02:00
1 parent 4f4534e272
commit a42dc6fc81
5 files changed
+41 -146

No files matched your search

+34 -34
View File
@@ -491,44 +491,41 @@ zombie (now an occasional opponent, `TUNE.racketEvery`, not the every-game fixtu
`RETURNED`, `DOUBLE KILL`) is a footnote to something you already watched happen. Sharing the loud
FACE with the milestone cards is right; sharing their SIZE made every footnote read as a milestone.
## Session log: THE LOB, AND TWO THINGS THE MULTIPLAYER TEST FOUND (2026-08-22, same day)
## Session log: THE LOB (BUILT, THEN CUT) AND TWO THINGS THE MULTIPLAYER TEST FOUND (2026-08-22, same day)
### THE LOB IS THE FLICK YOU ALREADY HAVE — option (c), picked by Oliver after a written comparison
### THE LOB WAS BUILT AND REMOVED THE SAME DAY — and the reason is the useful part
Oliver: *"when you're close to the net in a duel with another player there should be a gesture
allowing to make a ball flying high from below (lupfen)... this likely needs to be discussed."*
Three candidates were put to him — (a) slow drag vs fast flick, (b) a down-then-up hook, (c) context
arms it — and he picked (c): *"i think this is the easiest. no additional gesture to learn."* He also
corrected the premise: *"the opponent should come to the net too — in zombie tennis the zombie often
comes to the net"*, and he is right (racketAI chases up to `COURT.svcFar`, the classic CPU to z 9.5).
Three candidates were put to him — (a) slow drag vs fast flick, (b) a down-then-up hook, (c) let
CONTEXT arm it: the forward flick keeps its one meaning ("put it deep behind him") and the game
picks the trajectory that does that, which with a man at the net is over his head. He picked (c):
*"i think this is the easiest. no additional gesture to learn."*
**The rule: a forward flick means "put it deep behind him", and the game picks the trajectory that
actually does that.** With him on his baseline that is the smash it has always been; with him in, it
is over his head. `oppAtNet()` in gameplay.js is the whole switch. Four things it rests on:
It was built, measured and shipped. It worked exactly as specified — armed at `TUNE.lobArm` 7 m
(the distance at which a lob peaking at `lobApex` still passes over `CONTACT.maxY`), pace derived
from the height so the arc was the same from the baseline and from mid-court, target deeper than
`SHOT_DEPTH.deep`, and the word LOB popped at the contact to say which shot had just been asked for.
1. **It reads the BODY, not O.** In the duel and the match the opponent you play is the racket
zombie; O is the invisible tennis body the serve machinery is driven off and it only moves
between points, so asking O would have answered "on his mark" all rally, in the one mode Oliver
plays most. `farBody()` picks the 'r' zombie whenever there is one and is not netplay.
2. **`TUNE.lobArm` 7.0 m is not taste.** A lob peaking at `lobApex` passes a man 7 m from the net at
almost exactly `CONTACT.maxY` (2.3 m, the height above which nothing can be struck) — so the shot
arms EXACTLY as far out as it can still clear him. Measured, not guessed; the numbers are in the
suite. Move one of the three and re-measure the other two.
3. **The pace is DERIVED from the height, never chosen.** `vy = sqrt(2g(apex - y))` fixes the hang
time and the ground still to cover fixes the speed, so the same arc comes off the baseline (9.5
m/s) and off mid-court (5.8 m/s). A fixed speed was tried on paper first and is a fine lob from
one place and a flat drive from the other. It also carries NO topspin multiplier — the dive that
makes a hard flat ball land in would pull a lob into the net.
4. **`SHOT_DEPTH.lob` is DEEPER than `deep` (2.0 vs 3.0 m).** At the ordinary deep target the ball
passes only a metre or two behind the man it is going over, and at the far edge of the arm band
that was 2.05 m — inside his reach. The shot is defined by where it comes DOWN.
**His verdict, within the hour: *"all good but the lob. please remove it — this is totally
unpredictable."*** It is reverted in full: `oppAtNet`, `farBody`, `TUNE.lobArm`, `TUNE.lobApex`,
`SHOT_DEPTH.lob`, the branch in `doHit` and its two tests are gone, and the forward flick is the
smash it always was.
Measured, nominal (no scatter), from the baseline: over a man at the far service line it passes at
**3.25 m**, lands 2 m inside his baseline, 2.17 s of hang. Over one at z 9.5 (a real net-rusher):
5.4 m. The AI can and does run it down — a lob is not a free point in tennis either — but it pulls
him off the net, which is what the shot is for. The word `LOB` pops at the contact: (c) buys "no
gesture to learn" by letting context change what the flick means, and something has to say which
shot you just asked for.
**THE LESSON, AND IT IS A RULE NOW: a gesture whose MEANING depends on where the opponent is
standing is unpredictable, however well the shot itself is tuned.** This is the same failure the
input layer already names in its own words — *"No timing window and no invisible mode: the direction
you moved is the thing you asked for"* (the slingshot's sidestep-vs-pull comment). The written
comparison put that objection against option (a) and let (c) past on the argument that context can
never mis-fire. It can: the player does not track where the far body is standing while a ball is
coming at him, so the same thumb movement produced two different shots for reasons he was not
watching. The word at the contact told him WHICH shot he got, but a label after the fact does not
make a gesture predictable — it only explains the surprise.
**If the lob is ever asked for again, it needs its own gesture** (option (b), the down-then-up hook,
is the only candidate left that cannot be confused with an existing one) — and the mechanics above
are all still correct and are recorded in the git history at 4f4534e, so the shot itself is a
half-hour's work. The question was never the ballistics.
### "THE OPPONENT SEES THE BALL REALLY FAST — THE PLAYER BARELY SEES THE SPEED INCREASE"
@@ -4033,9 +4030,12 @@ Nothing here is broken; these are known gaps and unverified risks.
from a tin). At 12 rounds/s a per-pellet sample will machine-gun the mixer, not just the wave.
- **boss sounds** — footfall, wind-up, throw, wound, death. Three designs in `BOSS_ART`; decide
whether they share one set or get one each before recording anything.
14. ~~**THE LOB ("lupfen")**~~ SHIPPED 2026-08-22 as option (c) — see the session log. The rest of
this entry is the discussion it came out of, kept because the two rejected options are the
argument for the one that shipped.
14. **THE LOB ("lupfen") — asked for, built and CUT on 2026-08-22. Do not rebuild it as option
(c).** Oliver played the context-armed version and removed it the same hour: *"totally
unpredictable."* See the session log for the rule that came out of it. What is left open is the
shot with a gesture OF ITS OWN — option (b) below is the only candidate that cannot be confused
with something already in the language. The ballistics are solved and are in the history at
4f4534e; do not re-derive them, and do not re-propose (c).
**~~asked for 2026-08-22, UNDER DISCUSSION, do not build it yet.~~** Oliver:
*"when you're close to the net in a duel with another player there should be a gesture allowing
to make a ball flying high from below... I don't know how to implement this gesture wise — this