Si comincia svegliandosi sulla panchina dei vecchietti dopo una notte brava: gli occhi che si aprono a fatica, la piazza sfocata e doppia; e dal Barone il telefonino col sito di San Piero, che si apre a tutto schermo, e il Muro del Sanpierino vero coi messaggi del 2007, «Aggiorna» compreso (Andrea)

- 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
This commit is contained in:
2026-10-31 09:52:34 +01:00
co-authored by Claude Opus 5.5
parent 1ea78161d1
commit c5953f04c0
93 changed files with 1112 additions and 68 deletions
+23 -1
View File
@@ -545,11 +545,33 @@ test('gli amici in giro: l\'Arcu al circolino, il Tozzino al cancello del tennis
ask('Ci si becca da i\' Trappola, ai\' Barrettino!');
assert.equal(g.dialogue, null);
assert.ok(talk('carza', 'tozzino').includes('tozzino: E chi sennò? Ha chiamato ora: s\'è fermato a Pratolino a mettere le catene. A breve arriva.'));
const baron = talk('polisportiva', 'barondeduke');
talk('polisportiva', 'barondeduke');
const baron = ask('Barone! Che ci fai qui?');
assert.ok(baron.includes('barondeduke: Avevo due donne e due jack. Entra la terza donna, e penso: «Male male si divide».'));
assert.equal(baron.at(-1), 'barondeduke: L\'altro aveva colore.');
});
test('il Muro del Sanpierino sul telefonino del Barone: sale, il sito a tutto schermo, il link apre il muro', async () => {
const { RISE, ZOOM, linkBox } = await import('../src/engine/telefono.js');
const g = new Game(story);
settle(g); g.go('polisportiva'); settle(g); g.act('talk', 'barondeduke'); settle(g);
g.choose(g.options().findIndex(o => o.text.includes('muro del Sanpierino'))); settle(g);
assert.equal(g.closeup?.id, 'muro_sanpierino');
const def = story.closeups.muro_sanpierino;
assert.ok(!g.closeupTap(), 'mentre sale, un tocco non conta');
g.update(RISE); assert.ok(g.closeupTap()); assert.equal(g.closeup.step, 'zoom');
for (let i = 0; i < 20; i++) g.update(ZOOM / 10);
assert.equal(g.closeup.step, 'site');
g.closeupAim([600, 340]); assert.ok(!g.closeupTap(), 'fuori dal link non succede niente');
const [x, y, w, h] = linkBox(def, def.siteSize);
g.closeupAim([x + w / 2, y + h / 2]); assert.ok(g.closeupTap()); assert.equal(g.closeup.step, 'wall');
const said = [];
for (let i = 0; i < 400 && (g.speech || !g.closeup.lines || g.closeup.lines.length); i++) { if (g.speech) { said.push(g.speech.text); g.skip(); } g.update(0.05); }
assert.ok(said[0].includes('Firmato: il Regolo'));
g.closeupClose();
assert.ok(settle(g).some(s => s.text.includes('il sito è tuo')), 'chiudendo, il commento');
});
test('i tentativi sbagliati hanno una risposta loro, non quella generica', () => {
const g = new Game(story);
settle(g);