Stop the auto-run shaking while it chases a ball
Oliver: "wenn der Autoplay den Ball versucht zu bekommen, zittert der Player schnell hin und her". Measured: the run's target flipped by metres every other frame. intercept samples the flight every 10 ms against a 16.7 ms frame, so any candidate on a margin (a low bounce peaking on the 0.45 m floor, a point on the back boundary, a dying drop) passed one frame and failed the next. Frames with no candidate sent him home and back. 9-62 reversals inside 200 ms per five minutes. The chase now latches its plan: the flight is fixed at the strike, so the first point stays the answer while his legs still make it in time, net of any time he stood (split-step, heels). Reach is judged from where the chase began, and the target eases with a start/stop hysteresis. After: no reversals at any rung, timing unchanged. He wastes no steps, so he is a little stronger, mostly at the bottom of the ladder. New test; v375. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
599d5b0506
commit
bb72a01a3e
7 files changed
+145
-19
No files matched your search
@@ -6,6 +6,7 @@
|
||||
// Since step 4: BOT=human (default; JIT, BIAS ms), CLIMB=1, XP, WHY=1, PROBE=1, LOG=1|all, SUMMARY=1,
|
||||
// JSON=1 — see PROJECT.md "Step 4, measured first". Pool 8 seeds before reading a win rate.
|
||||
// ATTACK=0.3 (the long up-flick share), NETX=1 (net/smash tally), KILL=1 (put-aways), T_<knob>=<v> sets TUNE.
|
||||
// JITTER=1 (auto-run shake: reversals, target jumps), =2 prints big jumps, =3 prints fast reversals.
|
||||
// ponytail: the platform stubs are copied from test.js; fold this into a test once the rework lands.
|
||||
let _seed = (Number(process.env.SEED) || 20260811) >>> 0;
|
||||
Math.random = () => { // xorshift32 — small, fast, good enough for jitter
|
||||
@@ -96,6 +97,7 @@ const ATTACK = Number(process.env.ATTACK || 0); // share of baseline shots playe
|
||||
const JIT = Number(process.env.JIT ?? 60) / 1000, LAG = 7;
|
||||
const gauss = () => Math.sqrt(-2 * Math.log(1 - Math.random())) * Math.cos(2 * Math.PI * Math.random());
|
||||
const netx = { attacks: 0, smash: 0, smashWon: 0, lobbed: 0, open: null, p0: 0 };
|
||||
const jit = { shown: 0, rev: 0, fastRev: 0, lastRev: -99, last: 0, jumps: [], frames: 0 };
|
||||
const probe = [], kills = []; let kOpen = null, kpow = 1;
|
||||
const bot = { armed: false, fire: -1, jit: null, swipe: null };
|
||||
const sw = (dx, dy, mag) => { const n = Math.hypot(dx, dy) || 1, fx = dx / n, fy = dy / n;
|
||||
@@ -173,6 +175,7 @@ for (const rung of RUNGS) {
|
||||
}
|
||||
}
|
||||
const lh = ball.lastHit;
|
||||
const px0 = P.x, pz0 = P.z, tg0 = P.tgt;
|
||||
if (process.env.PROBE && lh === 'O' && bot.land && P.swingT >= 0) bot.land.sw = P.swingT, bot.land.d = Math.hypot(ball.x - P.x, (ball.z - P.z) * 0.8), bot.land.y = ball.y, bot.land.bb = ball.bounces;
|
||||
update(DT);
|
||||
if (lh !== 'P' && ball.lastHit === 'P' && ball.active) { if (ball.approach === 'P' && !G.wasServe) netx.attacks++; if (ball.smash) { netx.smash++; netx.open = 'smash'; } }
|
||||
@@ -183,6 +186,15 @@ for (const rung of RUNGS) {
|
||||
if (ball.lastHit !== 'O') G.swipe = null;
|
||||
// KILL=1: every put-away (a q >= .95 CPU ball straight after a player ball under .5) — where it went,
|
||||
// how far the player had to go, how long he had, and whether he got it back
|
||||
// JITTER=1: the auto-run's shake — a direction reversal of the x step inside a chase, and how far the
|
||||
// target jumps between frames (the two things a "zittert hin und her" can be made of)
|
||||
if (process.env.JITTER && G.phase === 'rally' && ball.active && ball.lastHit === 'O' && lh === 'O') {
|
||||
const dx = P.x - px0;
|
||||
if (Math.abs(dx) > 1e-4) { if (jit.last && Math.sign(dx) !== Math.sign(jit.last)) { jit.rev++; if (i - jit.lastRev < 12) { jit.fastRev++; if (process.env.JITTER === '3' && jit.shown++ < 12) console.log('rev', i, 'dx', dx.toFixed(3), 'prev', jit.last.toFixed(3), 'P', P.x.toFixed(2), P.z.toFixed(2), 'tgt', P.tgt && P.tgt.x.toFixed(2), P.tgt && P.tgt.z.toFixed(2), 'swingT', P.swingT.toFixed(2), 'heels', ball.heels.toFixed(2)); } jit.lastRev = i; } jit.last = dx; }
|
||||
if (tg0 && P.tgt) { const j = Math.hypot(P.tgt.x - tg0.x, P.tgt.z - tg0.z); jit.jumps.push(j); }
|
||||
if (process.env.JITTER === '2' && tg0 && P.tgt && Math.hypot(P.tgt.x - tg0.x, P.tgt.z - tg0.z) > 0.5 && jit.shown++ < 25) console.log('jump', i, 'from', tg0.x.toFixed(2), tg0.z.toFixed(2), 'to', P.tgt.x.toFixed(2), P.tgt.z.toFixed(2), 'P', P.x.toFixed(2), P.z.toFixed(2), 'ball', ball.y.toFixed(2), ball.z.toFixed(2), 'b', ball.bounces, JSON.stringify(ball.rx));
|
||||
jit.frames++;
|
||||
} else jit.last = 0;
|
||||
if (process.env.KILL) {
|
||||
if (lh === 'P' && ball.lastHit === 'O' && kpow < 0.5 && ball.pow >= 0.95) {
|
||||
const L = gp.predictLanding(); kills.push({ px: +P.x.toFixed(1), pz: +P.z.toFixed(1), lx: L && +L.x.toFixed(1), lz: L && +L.z.toFixed(1), tl: L && +L.t.toFixed(2), v: +Math.hypot(ball.vx, ball.vz).toFixed(1), got: null }); kOpen = kills[kills.length - 1];
|
||||
@@ -241,6 +253,8 @@ for (const rung of RUNGS) {
|
||||
}
|
||||
if (!process.env.SUMMARY) { console.table(rows); console.table(land); }
|
||||
if (process.env.NETX) console.log(JSON.stringify(netx));
|
||||
if (process.env.JITTER) { const j = jit.jumps.sort((a, b) => a - b), q = f => +(j[Math.floor(j.length * f)] || 0).toFixed(3);
|
||||
console.log(JSON.stringify({ chaseFrames: jit.frames, reversals: jit.rev, fastReversals_lt200ms: jit.fastRev, tgtJump_p50: q(0.5), p90: q(0.9), p99: q(0.99), max: q(0.9999), over20cm: j.filter(x => x > 0.2).length })); }
|
||||
if (process.env.KILL) { console.table(kills.slice(0, 30)); const l = kills.filter(k => k.got === 'LOST').length; console.log('put-aways', kills.length, 'won by CPU', l); }
|
||||
if (process.env.PROBE) { const l = probe.map(p => p.late).sort((a, b) => a - b); console.log("contact after predicted entry, ms: n", l.length, "mean", (l.reduce((a, b) => a + b, 0) / l.length).toFixed(1), "p10", l[l.length * 0.1 | 0], "p50", l[l.length / 2 | 0], "p90", l[l.length * 0.9 | 0]); }
|
||||
if (process.env.JSON) { console.log(JSON.stringify(pts)); process.exit(0); }
|
||||
|
||||
Reference in new issue
Block a user