Diagnose why every rally ends in a net duel
Oliver: every match converges on serve, both at the net, reflex volleys, won by a wrong-foot. Measured headless: rally balls land on the service line by definition, the match CPU stands on the bounce point and volleys 90-100% of everything from opponent 6 up, and the auto-run always picks the earliest contact. Diagnosis, research and a four-step plan go into PROJECT.md (awaiting his go); tools/rally-sim.mjs is the gauge. Fallback tag rally-baseline-v360 marks the shipped feel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
806a739c6f
commit
f33d46366a
2 files changed
+247
No files matched your search
+91
@@ -5127,10 +5127,101 @@ replay button"*. Both are netplay-only by construction, which is why neither had
|
||||
→ both courts come up 0-0 with full blood, the friend standing, no gore, "REMATCH — YOUR SERVE"
|
||||
against "REMATCH — THEIR SERVE". 146 tests.
|
||||
|
||||
## THE RALLY GOES FLAT — diagnosis (2026-10-13, UNDER DISCUSSION, nothing built)
|
||||
|
||||
Oliver: *"jedes Spiel läuft am Ende gleich ab (vor allem in höheren Levels): Aufschlag, dann schnell
|
||||
vor ans Netz (Spieler und Opponent), von wo aus ein sehr schneller Ballwechsel passiert und durch eine
|
||||
Täuschung des Gegners schließlich ein Punkt erzielt werden kann ... so läuft kein echtes Tennismatch
|
||||
ab."* He suspected the late opponents' speed. Both modes, classic and zombie tennis. **Fallback tag
|
||||
before any change: `rally-baseline-v360`** (806a739, pushed).
|
||||
|
||||
**Measured** with `node tools/rally-sim.mjs` (real modules, test.js's autopilot, 240 s per opponent;
|
||||
the service line is 6.4 m from the net, the baseline 11.9 m):
|
||||
|
||||
| zombie tennis | P meets the ball (m from net) | P volleys | O meets the ball | O volleys | time per shot |
|
||||
|---|---|---|---|---|---|
|
||||
| opponent 1 | 4.9 | 87% | 9.3 | 56% | 0.53-0.67 s |
|
||||
| opponent 6 | 7.7 | 52% | 7.6 | 90% | 0.63-0.72 s |
|
||||
| opponent 12 | 7.8 | 50% | 7.7 | 99% | 0.72 s |
|
||||
| opponent 18 | 8.5 | 7% | 6.6 | 100% | 0.72-0.75 s |
|
||||
|
||||
Every rally ball lands at a median **5.4 m from the baseline: on the service line**. Classic tennis
|
||||
is milder but has the same shape (contact 8.5-10.8 m from the net, 0.75-1.0 s per shot, the same
|
||||
5.4 m landings).
|
||||
|
||||
**Four structural causes, none of them a tuning value:**
|
||||
1. **The rally ball lands on the service line by definition.** `SHOT_DEPTH.mid` is 5.4, i.e. the
|
||||
service line itself. In real tennis that is a SHORT ball, an invitation to attack. `deep` (3.0) is
|
||||
the only ball in the back third, and the CPU asks for it 25% of the time.
|
||||
2. **The match opponent runs to the BOUNCE and takes the ball there.** `racketAI` aims at `pred.z`
|
||||
(the first-bounce point, since v352's "approach as far as 1.2 m behind the net"), and is clamped at
|
||||
`>= 1.5`, so it can never stand behind its own baseline. Standing on the bounce point, the ball
|
||||
enters its 1.6 m reach before it lands, so from opponent 6 up it volleys 90-100% of everything
|
||||
from the service line. The speed dials (`matchSpeedPer`, foe `speed`, `leaguePace`) only make it
|
||||
arrive there sooner. That is what "they get very fast" feels like.
|
||||
3. **The player's auto-run picks the EARLIEST reachable waist-high point.** `intercept('P')` walks
|
||||
the flight forward in time and returns the first point that qualifies, which is always the one
|
||||
nearest the net. At opponent 1, 72% of the player's contacts are inside the service line. The
|
||||
classic CPU goes through the same `intercept`, which is why classic has the shape too.
|
||||
4. **Every shot has the same shape.** `solveShot` at pace `s` to one of three depths. No height, no
|
||||
spin family, no lob or drop for the CPU. The lane is the only variable left, so wrong-footing
|
||||
(THE READ) is the only way a point can end. That is exactly his description.
|
||||
|
||||
**Prototype (scratch copy, not committed):** both sides take the ball AFTER the bounce, below 1.5 m
|
||||
and falling, and may stand up to 2.5 m behind their baseline. Homes move behind the baseline (P 24.4,
|
||||
O -0.6). The match CPU waits behind the bounce instead of on it. Rally depth is deep by default, and
|
||||
mistiming lands the ball SHORTER, never longer, so it adds no outs. Result: contact 10-12 m from the
|
||||
net on both sides, volleys 0-2%, 0.8-0.97 s per shot. Rallies at the high rungs then never end for
|
||||
the bot. That is expected: once the geometry is fixed, what is missing is the tools that END a point.
|
||||
|
||||
**What the research says** (real tennis and other tennis games, sources in the session's brief):
|
||||
- Real points are mostly SHORT. 0-4 shots make up ~70% of men's and ~66% of women's points, 5-8 ~20%, 9+ ~10%
|
||||
(AO 2015, Wimbledon 2021). Variety is lots of short points plus a long-rally tail, not long rallies
|
||||
everywhere.
|
||||
- Pros win 66-69% at the net BECAUSE they come in selectively. Controlled for the situation,
|
||||
serve-and-volley is worse than staying back: 66.8% vs 72.2% (Tennis Abstract). They approach "only when
|
||||
the point has developed in an inviting way", i.e. off a short ball. The net is made expensive by the
|
||||
passing shot dipped at the feet, the lob, and needing a good approach first. Our game has none of those
|
||||
three costs.
|
||||
- Even the most minimal arcade tennis games (Super Tennis, Virtua Tennis DC, Mario Tennis) give the lob
|
||||
its own input. Wii Sports rejected reading the swing's direction because "the ball doesn't fly in the
|
||||
direction you expect", which supports our one-gesture rule. Shape-coded swipes (VT Tennis mobile) fight
|
||||
with direction.
|
||||
- AI that is "just fast" is the genre's known failure. Matchpoint's career mode reportedly needs constant
|
||||
net rushing. What works is style dials (TopSpin's baseline/serve-volley/defense/all-round spreads) and
|
||||
believable over/under-hits. Free Tennis's AI "learns whether it is best to take the net or stay back".
|
||||
|
||||
**The plan put to him (smallest root first; every number a TUNE knob, the tag is the fallback):**
|
||||
1. **THE COURT GETS ITS LENGTH BACK.** No new input, both modes. Rally balls land deep, and mistiming lands
|
||||
them SHORT (never long, no new outs). Both sides take the ball after the bounce from behind the
|
||||
baseline. Coming forward happens only onto a short ball: the auto-run runs you in, and you are then
|
||||
visibly at the net, where you can be passed or lobbed. A volley below net height can only be blocked up
|
||||
soft. The suite gets a rally-shape test (contact depth, volley share, shots per point).
|
||||
2. **OPPONENTS WITH A GAME.** The CPU gains shot shapes (heavy topspin that kicks high and pushes you
|
||||
back, low skidding slice, moonball, lob, drop shot) and per-row STYLE dials on `OPPONENTS`: home depth,
|
||||
approach threshold, lob/drop rate, spin. The roster lines already read as styles: pushers at the bottom,
|
||||
ROLLER/BRUTE flat hitters, BALL BOY/RUNNER retrievers, CLUB PRO/DIRECTOR serve-and-volley,
|
||||
MASCOT/PHYSIO touch players, CHAMPION all-court, and he learns whether the net is working. The ladder
|
||||
then climbs through style and consistency rather than legs, and the speed dials are re-tuned
|
||||
afterwards. Context-chosen shots are fine for the CPU: the rule binds the player's gesture, and a lob's
|
||||
arc announces itself.
|
||||
3. **THE PLAYER'S SOFT BALL (Oliver's call).** The down-flick today means "short", which is a fast short
|
||||
ball nobody needs. Proposal: down = SOFT, and its length = how far, so short = drop shot, long = lob.
|
||||
One meaning in every situation, no new gesture. This is NOT the context-armed lob that was cut on
|
||||
2026-08-22. Rejected alternative: coding lob/drive by flick SPEED (AO Tennis Smash, Tennis Clash). A
|
||||
right thumb's left swipe is naturally ~2x slower (measured 2026-08-20), so every left flick would turn
|
||||
into a lob.
|
||||
4. **Retune the escalation** against the new shape, with `tools/rally-sim.mjs` and the step-1 test as the
|
||||
gauge.
|
||||
|
||||
# OPEN — leftovers, in rough priority order
|
||||
|
||||
Nothing here is broken; these are known gaps and unverified risks.
|
||||
|
||||
0. **THE RALLY GOES FLAT (2026-10-13), the top item.** Every match converges on serve, both at the net,
|
||||
reflex volleys, won by a wrong-foot. Diagnosed and measured; a four-step plan is awaiting Oliver's go.
|
||||
See the section of that name just above. Fallback tag `rally-baseline-v360`.
|
||||
|
||||
1. **`RES` 4 is unverified on a real phone under load.** It nearly doubled the fill rate (810 -> 1080
|
||||
device px across). Oliver has not reported stutter, but he also has not played a late horde since.
|
||||
**If the game ever stutters, `RES` back to 3 is the first move** — not reducing zombie counts.
|
||||
|
||||
Reference in new issue
Block a user