Voci: anche le risposte del motore e le scelte dei dialoghi hanno la voce; make ascolta le riascolta con Whisper; rifatte quelle storpiate

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ApqNBvNbNCwXqR2RLo8QJh
This commit is contained in:
2026-10-24 20:49:52 +02:00
co-authored by Claude Opus 5.5
parent bde9a790e5
commit 96b3779ad1
65 changed files with 232 additions and 34 deletions
+26 -1
View File
@@ -2,7 +2,8 @@ import test from 'node:test';
import assert from 'node:assert/strict';
import { existsSync, readFileSync } from 'node:fs';
import { story } from '../src/story/story.js';
import { Game } from '../src/engine/game.js';
import { Game, VERBS } from '../src/engine/game.js';
import { solution } from '../src/story/solution.js';
import { voiceLines, voiceKey, Voices } from '../src/engine/voices.js';
import { settle } from './helpers.mjs';
@@ -29,6 +30,30 @@ test('ogni battuta ha la sua voce (sennò: make voci) e ogni personaggio una voc
}
});
// Quello che si sente davvero giocando: la soluzione completa, e ogni verbo su ogni cosa di ogni scena (anche le
// risposte che il motore dà da sé, e le scelte dei dialoghi ripetute da Andrea). Nessuna battuta resta muta.
test('giocando, ogni battuta pronunciata ha la sua voce', () => {
const mute = new Set(), listen = said => { for (const s of said) if (s.text.trim() && !/^[.…!?\s]+$/.test(s.text) && !index[voiceKey(s.who, s.text)]) mute.add(`${s.who}: ${s.text}`); };
const g = new Game(story);
g.go(story.start.scene, story.start.at);
listen(settle(g));
for (const [verb, target, item] of solution) {
if (verb === 'choose') g.choose(g.options().findIndex(o => o.text === target)); else g.act(verb, target, item);
listen(settle(g));
}
for (const id of Object.keys(story.scenes)) {
const fresh = () => { const t = new Game(story); t.go(id); settle(t); return t; };
for (const h of fresh().hotspots()) for (const verb of VERBS) {
if (h.exit && verb === 'walk') continue;
const t = fresh();
t.act(verb, h.id);
listen(settle(t));
if (t.dialogue) for (let i = 0; i < 6 && t.dialogue && t.options().length; i++) { t.choose(0); listen(settle(t)); }
}
}
assert.deepEqual([...mute], [], 'battute senza voce (make voci)');
});
test('il castello e il leone hanno voci diverse da tutti gli altri', () => {
for (const special of ['castello', 'leone'])
for (const [who, v] of Object.entries(voci))