Files
leggenda-del-regolo/tests/poker.test.mjs
T

102 lines
5.7 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'));
assert.ok(!g.dialogue, 'finito il discorso, si è pronti a partire');
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);
assert.ok(!g.dialogue, 'finito il discorso, si è pronti a partire');
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'));
});