Giochi di carte dopo la revisione di Codex sui tre insieme; player dei video «Come si gioca» e primo copione

Esito che vale e si salva appena deciso, per tutti i minigiochi (anche tornando al titolo dalla schermata del risultato); briscola: uscire durante il conteggio non perde più la vittoria; tressette: si esce ai 21 col primo evento che ci porta, accusa compresa (prima vinceva sempre Andrea se ci arrivavano tutte e due), il carico che fa vincere si dà anche se è il 2, accuse che non escono dal tavolo, convenzioni scritte nell'aiuto; scopa: primiera valutata per quel che migliora, finale esatto a mazzo finito, presa sulla tavola al rilascio con scelta e conferma, frecce e Invio sempre sulla presa scelta. Tastiera: Invio e Spazio giocano sempre la carta scelta. Tavola descritta a parole. Classi CSS comuni ai tre giochi.
Video: player nel gioco (pulsante «Guarda il video» nel «Come si gioca», compare quando il video esiste), video/narra.py per la voce del narratore, pezzi comuni dei copioni e il copione della briscola; scaletta in video/SCALETTA-CARTE.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1dxvtsZx8NE9fwjXUNDBr
This commit is contained in:
2026-10-26 16:39:22 +01:00
co-authored by Claude Opus 5.5
parent 30e324d7e2
commit 7e1e6f6144
24 changed files with 594 additions and 73 deletions
+76
View File
@@ -0,0 +1,76 @@
// Copione del video «Come si gioca: la briscola» (video/SCALETTA-CARTE.md, clip 1).
// Giro: video/narra.py, poi rec.mjs come in video/SCALETTA.md, poi video/monta.py <cartella> --tutorial.
import { c, sleep, setup as base, regista } from "./tutorial-comune.mjs";
export const title = { it: "Come si gioca · la briscola", en: "Come si gioca · la briscola" };
export const cues = [
c("dove", "All'oratorio della Pieve, alle tavolate, c'è il giocatore di carte: per giocare basta parlarci"),
c("mazzo", "Prima si sceglie il mazzo: le carte toscane, con gobbo, donna e regio, oppure le napoletane"),
c("livello", "Poi quanto deve giocare forte: alla bona, seria, o a fassi male"),
c("tavolo", "In basso le tue tre carte, in alto quelle coperte dell'avversario. A sinistra il mazzo, con la briscola girata sotto: quel seme comanda"),
c("presa", "Si gioca una carta per uno. Prende la briscola più alta; se non ce ne sono, la carta più alta del seme di chi è uscito"),
c("punti", "Contano l'Asso, undici punti, il tre, dieci, il regio quattro, la donna tre e il gobbo due. Le altre sono lisci e non valgono niente"),
c("pesca", "Chi prende pesca per primo ed esce alla mano dopo. E non c'è l'obbligo di rispondere al seme"),
c("consiglio", "Un consiglio: su un liscio rispondi con un liscio, e i carichi dell'avversario prendili con una briscola piccola"),
c("tastiera", "Si gioca toccando la carta, oppure coi pulsanti sotto il tavolo, o con le frecce e Invio"),
c("conto", "Finito il mazzo si contano le prese, una carta alla volta. Vince chi arriva a sessantuno punti, e sessanta a sessanta è patta"),
c("fine", "Poi si torna all'oratorio, e si può chiedere la rivincita. Buona briscola!"),
];
export const setup = base;
export async function run(d) {
const p = d.page, r = regista(d, "tutorial-briscola");
await r.ascolta();
await r.vaiA("oratorio", [470, 300]);
await r.cue("dove");
await r.parlaCon("giocatore_carte");
await r.scegli("Una briscola?");
await r.cue("mazzo");
await r.scegli("Con le toscane.");
await r.cue("livello");
await r.scegli("Seria.");
// Una mano fissa, la stessa a ogni ripresa.
await p.evaluate(async () => {
const { newBriscola } = await import("/src/engine/briscola.js");
game.closeup = { id: "briscola", ...newBriscola(91421, { level: "seria", deck: "toscane" }) };
});
await sleep(800);
await r.cue("tavolo");
await r.muovi([150, 160], 1.0); await sleep(600); await r.muovi([320, 280], 1.0);
// Una carta di Andrea: quella che sceglierebbe un giocatore attento, cliccata davvero sul tavolo.
const gioca = async () => {
for (let i = 0; i < 400; i++) {
const s = await p.evaluate(async () => {
const { canPlay } = await import("/src/engine/briscola.js");
return game.closeup?.step === "result" || game.closeup?.step === "count" ? "fine" : canPlay(game.closeup) && !game.speech ? "tocca" : "aspetta";
});
if (s === "fine") return false;
if (s === "tocca") break;
await sleep(150);
}
const i = await p.evaluate(async () => {
const { observation, attentive } = await import("/src/engine/briscola.js");
return attentive(observation(game.closeup, "player"));
});
await r.clicca([176 + i * 102 + 42, 290], 0.7);
return true;
};
const giocane = async (n) => { for (let k = 0; k < n; k++) if (!(await gioca())) return; };
await r.cue("presa"); await giocane(2);
await r.cue("punti"); await giocane(2);
await r.cue("pesca"); await giocane(2);
await r.cue("consiglio"); await giocane(2);
await r.cue("tastiera"); await giocane(20);
await p.waitForFunction(() => game.closeup?.step === "count", null, { timeout: 60000 });
await r.cue("conto");
await p.waitForFunction(() => game.closeup?.step === "result", null, { timeout: 60000 });
await sleep(2500);
await r.cue("fine");
await d.click(p.locator("#closeup-close"), 0.6);
await r.fermi(800);
await r.fine();
await r.salvaAudio();
}