Prototipo del motore: scena, camminata, verbi, inventario, dialoghi, salvataggio

Motore guidato dai dati con due scene di prova (Piazza e salita alla Fortezza),
percorsi su area concava, clic intelligente e pressione lunga, test della soluzione
completa in node e nel browser con Playwright. Nel documento la leggenda del nonno.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-23 00:08:00 +02:00
co-authored by Claude Opus 5.5
parent 0c5cd240e4
commit 826f5f99ec
22 changed files with 1572 additions and 1 deletions
+64
View File
@@ -0,0 +1,64 @@
// La "frase" in costruzione sotto la scena (Usa squama con…) e cosa fa ogni clic.
// Senza verbo scelto vale il clic intelligente: l'azione più sensata per quel punto.
import { VERB_LABELS } from './game.js';
export class Command {
constructor(game) {
this.game = game;
this.verb = null;
this.item = null;
}
reset() { this.verb = null; this.item = null; }
pickVerb(verb) {
this.verb = this.verb === verb ? null : verb;
this.item = null;
}
// Testo della riga sotto la scena, con l'eventuale bersaglio sotto il puntatore.
sentence(target = null) {
const g = this.game, name = target && g.targetName(target);
if (this.item) return `${VERB_LABELS[this.verb]} ${g.itemName(this.item)} ${this.verb === 'give' ? 'a' : 'con'}${name ? ' ' + name : '…'}`;
if (this.verb) return `${VERB_LABELS[this.verb]}${name ? ' ' + name : '…'}`;
if (!target) return '';
const isItem = !!g.story.items[target];
return isItem ? `Usa ${name} con…` : `${VERB_LABELS[g.defaultVerb(target)]} ${name}`;
}
// Clic sulla scena: `look` per il clic destro o la pressione lunga.
clickScene(point, { look = false } = {}) {
const g = this.game;
if (g.skip()) return 'skip';
if (g.dialogue || g.busy) return null;
const h = g.hotspotAt(point);
let done;
if (look && h) done = g.act('look', h.id);
else if (!h) done = g.walkTo(point);
else if (this.item) done = g.act(this.verb, h.id, this.item);
else if (this.verb) done = g.act(this.verb, h.id);
else done = g.act(g.defaultVerb(h.id), h.id);
this.reset();
return done ? (h ? 'act' : 'walk') : null;
}
clickItem(id, { look = false } = {}) {
const g = this.game;
if (g.skip()) return 'skip';
if (g.dialogue || g.busy) return null;
if (look) { this.reset(); return g.act('look', id) && 'act'; }
if (this.item) {
const ok = this.item !== id && g.act('use', id, this.item);
this.reset();
return ok ? 'act' : null;
}
if (!this.verb || this.verb === 'use' || this.verb === 'give') {
this.verb ??= 'use';
this.item = id;
return 'select';
}
const ok = g.act(this.verb, id);
this.reset();
return ok && 'act';
}
}