- Il risveglio (src/engine/risveglio.js): primo piano sopra la scena, con le battute mentre le palpebre si aprono e i vecchietti che danno la notizia del palio; «Salta» lo salta. - Il telefonino del Barone (src/engine/telefono.js): sale dal basso come il libro, la home di sanpiero50037.it dalla Wayback Machine nello schermo, il mattone del muro apre il muro. - Il muro (assets/muro, tools/muro.py): la pagina vera rifatta statica dal muro riesumato, coi 24 messaggi del dump (senza email né IP) e quelli del gioco, che arrivano con la storia; «Scrivi» spento. - Il gioco sgancia i service worker di altre app rimasti sul suo indirizzo (la Bussola su localhost:8080). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GiECd9RWGMKV7n3K1mdy8T
46 lines
2.4 KiB
JavaScript
46 lines
2.4 KiB
JavaScript
// Fa avanzare il gioco come farebbe un giocatore impaziente: tempo che scorre e battute saltate.
|
|
export function settle(game, { maxSteps = 20000, explore = false } = {}) {
|
|
const said = [];
|
|
for (let i = 0; i < maxSteps; i++) {
|
|
if (game.speech) {
|
|
said.push(game.speech);
|
|
game.skip();
|
|
}
|
|
// Un primo piano aperto aspetta il giocatore (sfogliare, chiudere): qui ci si ferma e decide il test.
|
|
// Il risveglio dell'inizio no: va avanti da solo, come una battuta.
|
|
if (game.closeup && !game.speech && game.reach <= 0 && game.story.closeups[game.closeup.id].type !== 'risveglio') {
|
|
if (!explore || game.story.closeups[game.closeup.id].type !== 'torch') return said;
|
|
exploreTorch(game);
|
|
}
|
|
// Un ultimo fotogramma, come nel gioco vero: a sequenza finita il motore prende il punto fermo e salva.
|
|
if (!game.busy && !game.walking && !game.queue.length && !game.task) { game.update(0); return said; }
|
|
game.update(0.05);
|
|
}
|
|
throw new Error('Il gioco non si ferma: ' + JSON.stringify(game.snapshot()));
|
|
}
|
|
|
|
// Il collaudo della soluzione compie anche i gesti richiesti dal finale interattivo.
|
|
export function exploreTorch(game) {
|
|
const c = game.closeup, def = c && game.story.closeups[c.id];
|
|
if (def?.type !== 'torch') return;
|
|
if (c.step === 'done') game.closeupClose();
|
|
else if (c.step === 'search') game.closeupAim(def.targets[c.found].at);
|
|
}
|
|
|
|
export function memoryStorage() {
|
|
return { data: {}, getItem(k) { return this.data[k] ?? null; }, setItem(k, v) { this.data[k] = String(v); }, removeItem(k) { delete this.data[k]; } };
|
|
}
|
|
|
|
// Il server statico delle prove nel browser, su una porta libera scelta dal sistema: con una porta a caso poteva
|
|
// capitare la 8080 del gioco in Docker (make up), e la prova girava sul codice vecchio del container.
|
|
export async function staticServer() {
|
|
const { spawn } = await import('node:child_process');
|
|
const server = spawn('python3', ['-u', '-m', 'http.server', '0', '--bind', '127.0.0.1'], { stdio: ['ignore', 'pipe', 'ignore'] });
|
|
const port = await new Promise((resolve, reject) => {
|
|
let out = '';
|
|
server.stdout.on('data', d => { out += d; const m = out.match(/port (\d+)/); if (m) resolve(Number(m[1])); });
|
|
server.on('exit', () => reject(new Error('il server di prova non è partito')));
|
|
});
|
|
return { port, kill: () => server.kill() };
|
|
}
|