Tressette ai 21 all'oratorio: in quattro a coppie, Andrea e il socio contro il giocatore di carte e l'altro. Obbligo di seme, punti in terzi e ultima presa, accuse (napoletana, tre o quattro Assi, 2 o 3), segni onesti di chi esce (busso, striscio, volo) coi loro suoni, si va ai 21 smazzata dopo smazzata. Avversari «Alla bona», «Seria» (gioca a regola ma non conta) e «A fassi male» (conta, legge semi finiti, accuse e busso del socio). Tavolo a quattro, pulsanti dei segni e della mano, tastiera B/S/V; test, taratura e prova nel browser
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A1dxvtsZx8NE9fwjXUNDBr
This commit is contained in:
+61
-6
@@ -12,6 +12,8 @@ import * as bocce from './engine/bocce.js';
|
||||
import * as biliardo from './engine/biliardo.js';
|
||||
import * as briscola from './engine/briscola.js';
|
||||
import { cardAt } from './engine/briscola-render.js';
|
||||
import * as tressette from './engine/tressette.js';
|
||||
import { cardAt as tressetteAt } from './engine/tressette-render.js';
|
||||
import { VERSION, versioned } from './version.js';
|
||||
|
||||
const $ = id => document.getElementById(id);
|
||||
@@ -401,9 +403,12 @@ canvas.addEventListener('pointerdown', e => {
|
||||
if (!running || e.button > 0) return;
|
||||
// Nel primo piano un tocco sfoglia (o salta la battuta): gli oggetti della scena dietro non si toccano.
|
||||
if (game.closeup) {
|
||||
if (story.closeups[game.closeup.id].type === 'briscola') {
|
||||
const deck = CARD_AT[story.closeups[game.closeup.id].type];
|
||||
if (deck) {
|
||||
if (game.skip()) return;
|
||||
press = { card: cardAt(game.closeup, scenePoint(e)), state: game.closeup };
|
||||
// Tressette: fra una smazzata e l'altra un tocco va avanti.
|
||||
if (tressette.advance(game.closeup)) return;
|
||||
press = { card: deck(game.closeup, scenePoint(e)), state: game.closeup, at: deck };
|
||||
canvas.setPointerCapture(e.pointerId);
|
||||
return;
|
||||
}
|
||||
@@ -425,7 +430,7 @@ canvas.addEventListener('pointerup', e => {
|
||||
if (!press) return;
|
||||
if (press.card !== undefined) {
|
||||
const p = press; press = null;
|
||||
if (running && game.closeup === p.state && p.card >= 0 && cardAt(game.closeup, scenePoint(e)) === p.card) game.closeupPlay(p.card);
|
||||
if (running && game.closeup === p.state && p.card >= 0 && p.at(game.closeup, scenePoint(e)) === p.card) game.closeupPlay(p.card);
|
||||
return;
|
||||
}
|
||||
if (press.closeup) { press = null; if (running && !game.closeupRelease() && !game.skip()) game.closeupTap(); return; }
|
||||
@@ -458,6 +463,7 @@ canvas.addEventListener('pointerleave', () => { mouse = null; });
|
||||
|
||||
// Comandi dei minigiochi separati dai verbi: carte oppure mira, forza e lancio.
|
||||
const MINI = {
|
||||
tressette: { ...tressette, back: 'Torna all’oratorio', label: 'Tressette: tocca una carta per giocarla. Frecce scelgono, Invio gioca; B, S, V fanno busso, striscio e volo. Esc esce.' },
|
||||
briscola: { ...briscola, back: 'Torna all’oratorio', label: 'Briscola: tocca una carta per giocarla. Frecce o 1, 2, 3 scelgono; Invio gioca. Esc esce.' },
|
||||
bocce: { ...bocce, nudge: (c, dir) => bocce.aim(c, c.aim.u, c.aim.w + dir * 0.3), back: 'Torna al pallaio', label: 'Bocce: tocca il campo o il dettaglio per mirare. Regola la forza e premi Lancia.' },
|
||||
biliardo: { ...biliardo, back: 'Torna al bar', label: 'Biliardo: clic o tocco fissa la mira. Frecce per affinarla, Maiusc per passi più piccoli. Regola la forza e premi Tira.' },
|
||||
@@ -466,6 +472,15 @@ const miniState = () => running && game?.closeup && MINI[story.closeups[game.clo
|
||||
const mini = () => MINI[story.closeups[game.closeup.id].type];
|
||||
$('bocce-power').addEventListener('input', e => { const c = miniState(); if (c) mini().setPower?.(c, Number(e.target.value) / 100); });
|
||||
$('bocce-throw').addEventListener('click', () => { const c = miniState(); if (c && !game.speech) mini().shoot?.(c); });
|
||||
// Le carte da gioco: dove si tocca la carta sul tavolo, gioco per gioco.
|
||||
const CARD_AT = { briscola: cardAt, tressette: tressetteAt };
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const button = $('tressette-card-' + i);
|
||||
button.addEventListener('click', () => game?.closeupPlay(i));
|
||||
button.addEventListener('focus', () => { if (game?.closeup?.id === 'tressette') tressette.select(game.closeup, i); });
|
||||
}
|
||||
for (const signal of tressette.SIGNALS) $('tressette-' + signal).addEventListener('click', () => { if (game?.closeup?.id === 'tressette') tressette.setSignal(game.closeup, signal); });
|
||||
$('tressette-next').addEventListener('click', () => { if (game?.closeup?.id === 'tressette') tressette.advance(game.closeup); });
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const button = $('briscola-card-' + i);
|
||||
button.addEventListener('click', () => game?.closeupPlay(i));
|
||||
@@ -560,6 +575,25 @@ window.addEventListener('keydown', e => {
|
||||
if (!$('map').hidden) { if (e.key === 'Escape' || e.key === 'p' || e.key === 'P') $('map').hidden = true; return; }
|
||||
// Nel primo piano: Invio, spazio o freccia sfogliano (o saltano la battuta), Esc chiude il libro.
|
||||
if (running && game.closeup) {
|
||||
if (story.closeups[game.closeup.id].type === 'tressette') {
|
||||
const inControls = e.target.closest?.('#tressette-controls'), c = game.closeup;
|
||||
if (e.repeat && ['Enter', ' '].includes(e.key)) { e.preventDefault(); return; }
|
||||
if (inControls && ['BUTTON', 'SUMMARY'].includes(e.target.tagName) && ['Enter', ' '].includes(e.key)) return;
|
||||
const key = e.key.toLowerCase(), signal = { b: 'busso', s: 'striscio', v: 'volo' }[key];
|
||||
if (['arrowleft', 'arrowright', 'arrowup', 'arrowdown', 'enter', ' '].includes(key) || /^[0-9]$/.test(key) || signal) {
|
||||
e.preventDefault();
|
||||
if (e.repeat || game.skip()) return;
|
||||
if (signal) tressette.setSignal(c, signal);
|
||||
else if (/^[0-9]$/.test(key)) tressette.select(c, (Number(key) + 9) % 10);
|
||||
else if (key.startsWith('arrow')) tressette.nudge(c, ['arrowleft', 'arrowup'].includes(key) ? -1 : 1);
|
||||
else if (c.step === 'result') game.closeupClose();
|
||||
else if (!tressette.advance(c) && key === 'enter') game.closeupPlay();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'Escape') game.closeupClose();
|
||||
else if (key === 'm') toggleMute();
|
||||
return;
|
||||
}
|
||||
if (story.closeups[game.closeup.id].type === 'briscola') {
|
||||
const inControls = e.target.closest?.('#briscola-controls');
|
||||
if (e.repeat && ['Enter', ' '].includes(e.key)) { e.preventDefault(); return; }
|
||||
@@ -666,12 +700,33 @@ function updateUi() {
|
||||
updateChoices();
|
||||
updateSpeech();
|
||||
const mg = miniState() && mini(), def = mg && story.closeups[c.id];
|
||||
const cards = def?.type === 'briscola';
|
||||
const cards = def?.type === 'briscola' || def?.type === 'tressette';
|
||||
$('bocce-controls').hidden = !mg || cards;
|
||||
$('bocce-controls').inert = !running;
|
||||
$('briscola-controls').hidden = !cards;
|
||||
$('briscola-controls').hidden = def?.type !== 'briscola';
|
||||
$('briscola-controls').inert = !running;
|
||||
if (cards) {
|
||||
$('tressette-controls').hidden = def?.type !== 'tressette';
|
||||
$('tressette-controls').inert = !running;
|
||||
if (def?.type === 'tressette') {
|
||||
$('panel').hidden = $('choices').hidden = true;
|
||||
const line = tressette.status(c, def.seats);
|
||||
if ($('tressette-status').textContent !== line) $('tressette-status').textContent = line;
|
||||
const mine = tressette.canPlay(c) && !game.speech, ok = mine ? tressette.legal(c.hands[0], c.table) : [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const button = $('tressette-card-' + i), card = c.hands[0][i];
|
||||
const label = card ? `${(i + 1) % 10}. ${tressette.cardName(card)}` : '—';
|
||||
if (button.textContent !== label) button.textContent = label;
|
||||
button.hidden = !card;
|
||||
button.disabled = !ok.includes(i);
|
||||
button.setAttribute('aria-pressed', String(c.selected === i && !!card));
|
||||
}
|
||||
for (const signal of tressette.SIGNALS) {
|
||||
$('tressette-' + signal).disabled = !mine || c.table.length > 0;
|
||||
$('tressette-' + signal).setAttribute('aria-pressed', String(c.signal === signal));
|
||||
}
|
||||
$('tressette-next').hidden = c.step !== 'smazzata';
|
||||
}
|
||||
if (def?.type === 'briscola') {
|
||||
$('panel').hidden = $('choices').hidden = true;
|
||||
const line = briscola.status(c, def.names);
|
||||
if ($('briscola-status').textContent !== line) $('briscola-status').textContent = line;
|
||||
|
||||
Reference in New Issue
Block a user