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:
1 parent
4f4534e272
commit
a42dc6fc81
5 files changed
+41
-146
No files matched your search
+1
-15
@@ -74,16 +74,6 @@ export const TUNE = {
|
||||
smashBoost: 0.42, // extra pace on a FORWARD flick (aim.az < 0), scaled by timing. It does not
|
||||
// send the ball longer — solveShot still lands it on the same spot — it
|
||||
// gets there flatter and sooner, which is what a smash is.
|
||||
// THE LOB ("lupfen", Oliver 2026-08-22). Same forward flick as the smash — the game picks which
|
||||
// shot that gesture means from WHERE THE OTHER MAN IS STANDING, so there is no second gesture to
|
||||
// learn. He is "in" when he is closer to the net than this, in metres:
|
||||
lobArm: 7.0, // ...and 7.0 is not a taste number. A lob peaking at lobApex passes a man
|
||||
// 7 m from the net at almost exactly CONTACT.maxY (2.3 m), so the shot
|
||||
// arms EXACTLY where it can still go over him. Raise one, raise the other.
|
||||
lobApex: 6.0, // m the lob peaks at, whatever the distance. The pace is DERIVED from this
|
||||
// (see doHit): a fixed speed would be a fine lob from the baseline and a
|
||||
// flat drive from mid-court, because the same speed over half the ground
|
||||
// is half the hang time. Height is the shot; speed is what it costs.
|
||||
aimError: 2.4, // m of scatter at quality 0
|
||||
aimTrust: 0.3, // an aimed rally shot TRUSTS its flick: the scatter may still push the
|
||||
// ball further OUT (the chosen out-risk keeps its exact shape) but only
|
||||
@@ -1409,11 +1399,7 @@ export const P_BOUNDS = { x: 6.5, zMin: COURT.netZ + 1.2, zMax: 26 };
|
||||
export const TOSS = { y0: 1.8, vy: 4.6, dx: -0.44, oDx: 0.42 };
|
||||
|
||||
// shot target depth from the receiving baseline, by aim (up = deep, none = mid, down = short)
|
||||
// `lob` is DEEPER than deep on purpose: a lob that lands where an ordinary drive lands passes only
|
||||
// a metre or two behind the man it is going over, and a ball that close to him is still inside his
|
||||
// 2.3 m reach (measured — at SHOT_DEPTH.deep it cleared him by nothing at the far edge of the arm
|
||||
// band). The shot is defined by where it comes DOWN, not by how high it goes.
|
||||
export const SHOT_DEPTH = { deep: 3.0, mid: 5.4, short: 8.6, lob: 2.0 };
|
||||
export const SHOT_DEPTH = { deep: 3.0, mid: 5.4, short: 8.6 };
|
||||
|
||||
// how long swing/serve poses hold before returning to idle (s)
|
||||
export const POSE_TIME = 0.38;
|
||||
|
||||
Reference in new issue
Block a user