Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GiECd9KMfjthRUnujCGSzZ
102 lines
5.8 KiB
JavaScript
102 lines
5.8 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import * as P from '../src/engine/poker.js';
|
|
import { drawPoker, cardAt, HAND } from '../src/engine/poker-render.js';
|
|
import { Game, MINIGAMES, TRIP } from '../src/engine/game.js';
|
|
import { story } from '../src/story/story.js';
|
|
import { settle } from './helpers.mjs';
|
|
|
|
const card = s => ({ rank: s.slice(0, -1), suit: { c: 'cuori', q: 'quadri', f: 'fiori', p: 'picche' }[s.at(-1)] });
|
|
const hand = s => s.split(' ').map(card);
|
|
|
|
test('i punti del mazzo corto: il colore batte il full, A-7-8-9-10 è la scala più bassa', () => {
|
|
const order = ['Ac Kf 9p 8q 7c', '7c 7f Kp 9q 8c', '7c 7f 9p 9q Ac', 'Jc Jf Jp 9q 8c', 'Ac 7f 8p 9q 10c', '7c 8f 9p 10q Jc',
|
|
'Kc Kf Kp 9q 9c', 'Ac Kc 9c 8c 7c', 'Qc Qf Qp Qq 7c', '7c 8c 9c 10c Jc'];
|
|
const scores = order.map(h => P.evaluate(hand(h)));
|
|
for (let i = 1; i < scores.length; i++) assert.ok(P.compare(scores[i], scores[i - 1]) > 0, `${order[i]} batte ${order[i - 1]}`);
|
|
assert.equal(P.handName(hand('Ac Kc 9c 8c 7c')), 'colore');
|
|
assert.ok(P.compare(P.evaluate(hand('Ac Af 9p 8q 7c')), P.evaluate(hand('Ac Af 9p 8q Kc'))) < 0, 'a parità di coppia contano le carte spaiate');
|
|
});
|
|
|
|
test('una partita intera: le fiches non si perdono, finisce sempre, e chi sa giocare vince più di chi vede sempre', () => {
|
|
const play = (seed, level, brain) => {
|
|
const c = P.newPoker(seed, { level });
|
|
for (let i = 0; i < 20000 && c.step !== 'result'; i++) {
|
|
if (P.myTurn(c)) P.choose(c, brain(c)); else if (P.canDraw(c)) { for (const k of P.cpuDiscards({ ...c, skill: P.LEVELS.male }, 'andrea')) P.play(c, k); P.choose(c, 'cambia'); }
|
|
else if (c.step === 'show') P.advance(c); else P.update(c, 1);
|
|
const sum = P.SEATS.reduce((n, s) => n + c.chips[s], 0) + (c.step === 'show' || c.step === 'result' ? 0 : c.pot);
|
|
assert.equal(sum, P.START * 3);
|
|
}
|
|
assert.equal(c.step, 'result');
|
|
return c.result.chips.andrea;
|
|
};
|
|
const smart = c => { const s = P.strength(c.cards.andrea); return s > 0.5 && P.canRaise(c) ? 'rilancio' : s > 0.15 || !P.toCall(c) ? 'vedo' : 'lascio'; };
|
|
let a = 0, b = 0;
|
|
for (let seed = 1; seed <= 60; seed++) { a += play(seed, 'bona', smart); b += play(seed, 'bona', () => 'vedo'); }
|
|
assert.ok(a > b, `con giudizio ${a}, vedendo sempre ${b}`);
|
|
});
|
|
|
|
test('i comandi di Andrea: il cambio si sceglie toccando (al massimo 4), le puntate coi pulsanti', () => {
|
|
const c = P.newPoker(3);
|
|
while (!P.myTurn(c)) P.update(c, 1);
|
|
const moves = P.moves(c).map(m => m.id);
|
|
assert.deepEqual(moves, ['lascio', 'vedo', 'rilancio']);
|
|
assert.ok(P.choose(c, 'vedo'));
|
|
while (!P.canDraw(c) && c.step !== 'show') P.update(c, 1);
|
|
if (P.canDraw(c)) {
|
|
assert.equal(cardAt(c, [HAND.x + 5, HAND.y + 5]), 0);
|
|
for (const i of [0, 1, 2, 3, 4]) P.play(c, i);
|
|
assert.equal(c.selected.size, 4, 'al massimo quattro');
|
|
assert.ok(P.choose(c, 'cambia'));
|
|
assert.equal(c.changed.andrea, 4);
|
|
}
|
|
});
|
|
|
|
test('il disegno del pokerino non cambia lo stato', () => {
|
|
const calls = [], ctx = new Proxy({}, { get: (o, k) => k in o ? o[k] : (...args) => calls.push([k, ...args]) });
|
|
const c = P.newPoker(9);
|
|
const before = JSON.stringify({ ...c, selected: [...c.selected] });
|
|
drawPoker(ctx, c);
|
|
assert.equal(JSON.stringify({ ...c, selected: [...c.selected] }), before);
|
|
assert.ok(calls.some(([op, t]) => op === 'fillText' && /POKERINO/.test(t)));
|
|
});
|
|
|
|
test('la macchina del tempo: l\'Arcu la fa comparire, il viaggio porta al Barrettino del 1997 e la porta riporta nel 2007', () => {
|
|
assert.ok(MINIGAMES.poker);
|
|
const g = new Game(story); g.go('via_liguri_magelli'); settle(g);
|
|
assert.ok(!g.hotspot('macchina_tempo'));
|
|
g.act('talk', 'arcu'); settle(g);
|
|
g.choose(g.options().findIndex(o => o.text.startsWith('Bei tempi'))); settle(g);
|
|
assert.ok(g.state.flags.macchina_trappola && g.hotspot('macchina_tempo'));
|
|
g.choose(g.options().findIndex(o => o.text.startsWith('Ci si vede'))); settle(g);
|
|
g.act('use', 'macchina_tempo'); settle(g);
|
|
assert.equal(g.closeup?.id, 'viaggio');
|
|
for (let t = 0; t < TRIP.end + 0.5 && g.closeup; t += 0.05) g.update(0.05);
|
|
settle(g);
|
|
assert.equal(g.state.scene, 'barrettino_1997');
|
|
g.act('talk', 'tavola'); settle(g);
|
|
g.choose(g.options().findIndex(o => o.text.startsWith('C\'è posto'))); settle(g);
|
|
g.choose(g.options().findIndex(o => o.text === 'A fassi male.')); settle(g);
|
|
assert.equal(g.closeup?.id, 'poker'); assert.equal(g.closeup.level, 'male');
|
|
g.closeup.step = 'result'; g.closeup.result = { winner: 'player', chips: { andrea: 200, vannino: 60, pierino: 40 }, top: ['andrea'] };
|
|
g.closeupClose(); settle(g);
|
|
assert.ok(g.state.flags.poker_vinto);
|
|
assert.ok(g.hotspot('arcu'), 'l\'Arcu è venuto anche lui');
|
|
g.act('walk', 'porta'); settle(g);
|
|
assert.equal(g.state.scene, 'via_liguri_magelli');
|
|
assert.ok(!g.state.flags.macchina_trappola && !g.hotspot('macchina_tempo'), 'tornati, la macchina sparisce');
|
|
assert.equal(g.goBack(), false, 'nel 2007 il pulsante non c\'è');
|
|
// Per rifare il viaggio si richiede all'Arcu; dal 1997 si torna anche col pulsante «Torna al 2007».
|
|
g.act('talk', 'arcu'); settle(g);
|
|
g.choose(g.options().findIndex(o => o.text.startsWith('Bei tempi'))); settle(g);
|
|
g.choose(g.options().findIndex(o => o.text.startsWith('Ci si vede'))); settle(g);
|
|
g.act('use', 'macchina_tempo'); settle(g);
|
|
for (let t = 0; t < TRIP.end + 0.5 && g.closeup; t += 0.05) g.update(0.05);
|
|
settle(g);
|
|
assert.equal(g.state.scene, 'barrettino_1997');
|
|
assert.equal(g.scene.back.label, 'Torna al 2007');
|
|
assert.ok(g.goBack()); settle(g);
|
|
assert.equal(g.state.scene, 'via_liguri_magelli');
|
|
assert.ok(!g.hotspot('macchina_tempo'));
|
|
});
|