Basket: la revisione di Codex, i punti gravi
Dalla mira iniziale (52°) da sotto non entrava con nessuna forza: ora 64°, forza minima più bassa e prima postazione un passo indietro, così da ogni postazione entra in una fascia di forza contigua di almeno l'8% (test). Il palo fermava anche sopra la sua cima e contava come tiro pulito; il tabellone lasciava passare da dietro. Il canestro conta appena entra (anche il risultato all'ultimo pallone), la pausa fra un pallone e l'altro è più corta, la palla entrata non rotola fino in fondo. Andrea resta a braccia alzate finché la palla vola (niente doppio pallone), il rilascio parte sopra la sua testa. La guida si ferma al primo urto e ha un bordo scuro con la punta; il lampo del canestro si spegne; l'obiettivo del livello è sempre in vista; i microurti sul ferro non tintinnano; dietro Andrea non si carica; l'aiuto spiega il clic che fissa la mira e le soglie. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GiECdBYE8csKd4tcFvwntT
This commit is contained in:
+46
-4
@@ -1,7 +1,7 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { newBasket, press, release, cancel, update, shoot, setAngle, setPower, aimScreen, nudge, arc, status, canThrow, releasePoint,
|
||||
powerAt, SWING, BALLS, SPOTS, LEVELS, RIM, BOARD, FLOOR, BALL, ANGLE } from '../src/engine/basket.js';
|
||||
import { newBasket, press, release, cancel, update, shoot, setAngle, setPower, aimScreen, nudge, arc, guide, status, canThrow, releasePoint,
|
||||
powerAt, SWING, BALLS, SPOTS, LEVELS, RIM, BOARD, POLE, FLOOR, BALL, ANGLE } from '../src/engine/basket.js';
|
||||
import { story } from '../src/story/story.js';
|
||||
import { Game } from '../src/engine/game.js';
|
||||
import { settle } from './helpers.mjs';
|
||||
@@ -43,7 +43,7 @@ test('la mira: l\'angolo segue il punto toccato, resta fra i limiti, non si tira
|
||||
});
|
||||
|
||||
test('la parabola della guida comincia dalle mani e scende per la gravità', () => {
|
||||
const c = newBasket(3), r = releasePoint(c), pts = arc(c, 1);
|
||||
const c = newBasket(3), r = releasePoint(c), pts = arc(c, 1.5);
|
||||
assert.deepEqual(pts[0], r);
|
||||
assert.ok(pts[5].y < r.y, 'prima sale');
|
||||
assert.ok(pts.at(-1).y > pts[5].y, 'poi scende');
|
||||
@@ -65,6 +65,48 @@ test('da ogni postazione esiste un tiro che entra, e un tiro entrato conta canes
|
||||
}
|
||||
});
|
||||
|
||||
test('con l\'angolo iniziale, da ogni postazione entra in una fascia di forza contigua di almeno l\'8%', () => {
|
||||
for (const [i, s] of SPOTS.entries()) {
|
||||
const made = [];
|
||||
for (let p = 0; p <= 1.0001; p += 0.005) {
|
||||
const c = newBasket(1); c.spot = i; setPower(c, p); shoot(c);
|
||||
made.push(fly(c).scored);
|
||||
}
|
||||
let best = 0, run = 0;
|
||||
for (const v of made) { run = v ? run + 1 : 0; best = Math.max(best, run); }
|
||||
assert.ok(best >= 16, `${s.name}: la fascia migliore è ${(best - 1) * 0.5}%`);
|
||||
}
|
||||
});
|
||||
|
||||
test('il palo ferma solo dalla cima in giù; il tabellone rimanda anche da dietro; il canestro conta subito', () => {
|
||||
const c = newBasket(11); setAngle(c, 78); setPower(c, 1); shoot(c);
|
||||
let b = fly(c);
|
||||
assert.ok(!c.events.some(e => e.kind === 'basket-swish'), 'sopra il palo la palla vola via: non è un tiro pulito');
|
||||
const d = newBasket(12);
|
||||
d.ball = { x: POLE.x - 30, y: FLOOR - 30, vx: 300, vy: 0, time: 0, bounces: 0, rim: false, board: false, under: false, scored: false, dead: false, spin: 0 };
|
||||
d.step = 'flight'; for (let i = 0; i < 30; i++) update(d, 1 / 120);
|
||||
assert.ok(d.ball.board && d.ball.vx < 0, 'il palo la rimanda indietro come un tabellone');
|
||||
const e = newBasket(13);
|
||||
e.ball = { x: BOARD.x + BOARD.depth + 30, y: (BOARD.top + BOARD.bottom) / 2, vx: -300, vy: 0, time: 0, bounces: 0, rim: false, board: false, under: false, scored: false, dead: false, spin: 0 };
|
||||
e.step = 'flight'; for (let i = 0; i < 30; i++) update(e, 1 / 120);
|
||||
assert.ok(e.ball.board && e.ball.x > BOARD.x, 'da dietro non lo attraversa');
|
||||
const f = newBasket(14); f.thrown = BALLS - 1; f.skill = LEVELS.bona; f.baskets = 2;
|
||||
const shot = goodShot(f); setAngle(f, shot.angle); setPower(f, shot.power); shoot(f);
|
||||
for (let i = 0; i < 2000 && !f.ball.scored; i++) update(f, 1 / 120);
|
||||
assert.equal(f.baskets, 3, 'il canestro conta appena entra');
|
||||
assert.ok(typeof f.ball.scoredAt === 'number');
|
||||
assert.equal(f.result?.winner, 'player', 'all\'ultimo pallone il risultato c\'è già mentre la palla scende');
|
||||
fly(f); rest(f);
|
||||
assert.equal(f.step, 'result'); assert.equal(f.result.baskets, 3);
|
||||
});
|
||||
|
||||
test('la guida si ferma al primo urto', () => {
|
||||
const c = newBasket(15); c.spot = 1; setAngle(c, 30); setPower(c, 1);
|
||||
const g = guide(c, 3), last = g.at(-1);
|
||||
assert.ok(g.length < arc(c, 3).length, 'non arriva in fondo');
|
||||
assert.ok(last.x + BALL > BOARD.x - 2 || last.y + BALL > FLOOR - 2 || Math.hypot(last.x - RIM.x1, last.y - RIM.y) < BALL + 3, 'si ferma su tabellone, campo o ferro');
|
||||
});
|
||||
|
||||
test('un tiro corto batte sul campo e rimbalza; uno lungo prende il tabellone e torna indietro', () => {
|
||||
const c = newBasket(4); c.spot = 3; // da tre, piano: non arriva nemmeno al palo
|
||||
setAngle(c, 45); setPower(c, 0); shoot(c);
|
||||
@@ -73,7 +115,7 @@ test('un tiro corto batte sul campo e rimbalza; uno lungo prende il tabellone e
|
||||
assert.ok(c.events.some(e => e.kind === 'basket-bounce'));
|
||||
assert.ok(b.y + BALL <= FLOOR + 0.01, 'non sprofonda');
|
||||
const d = newBasket(5); d.spot = 1;
|
||||
setAngle(d, 30); setPower(d, 1); shoot(d);
|
||||
setAngle(d, 34); setPower(d, 1); shoot(d);
|
||||
b = fly(d);
|
||||
assert.ok(b.board, 'ha preso il tabellone');
|
||||
assert.ok(c.events.every(e => e.kind !== 'basket-board') && d.events.some(e => e.kind === 'basket-board'));
|
||||
|
||||
Reference in New Issue
Block a user