// A game told: twenty-seven moves written to show what a first game should // see, with a callout where there is something to look at. The moves are // replayed through the engine, so the game can never drift from the rules, // and a test says so. import { applyMove, createGame, validateMove, type State } from './index'; import { square } from './board'; /** The moves, from and to, in order. */ export const TOLD_MOVES: [string, string][] = [ ['2f2', '2f3'], ['2g7', '2g6'], ['2b1', '2c3'], ['2k8', '2j6'], ['2c1', '2e3'], ['3g8', '3c4'], ['2c3', '2e4'], ['3c4', '3d4'], ['2e3', '3d4'], ['2c8', '2e6'], ['3d4', '2e5'], ['2h7', '2h6'], ['1c1', '1c2'], ['2e6', '2c4'], ['1c2', '1c3'], ['2i8', '2h7'], ['1c3', '1c4'], ['2d7', '2d6'], ['2b2', '2b3'], ['2j6', '2h5'], ['2b3', '2c4'], ['3c8', '3f6'], ['2e2', '2e3'], ['3f6', '2e5'], ['3g1', '3d4'], ['2a7', '2a6'], ['3d4', '3g7'] ]; /** What to look at, by the ply just played; 0 is before the first move. */ export const CALLOUTS: Record = { 0: 'Both armies stand as Gygax drew them, and Gold moves first. Step through the game a move at a time. Where there is something to see, a word on it appears here.', 1: 'A Warrior steps one square, never two, so the opening is slower than chess. This one clears the f file for the Mage behind it.', 3: 'The Unicorn is the first piece out, because it is the one piece of the land that can leap the wall of Warriors.', 5: 'The Hero leaps two squares along a diagonal, over its own Warrior at 2d2. That leap is how a Hero gets out early.', 6: 'Scarlet’s Dragon leaves its roost, which Gygax warned against. Look at what it threatens now: the five land squares beneath 3c4, and Gold’s Unicorn at 2c3 among them. Then look at what it has left behind. There is no roof over Scarlet’s King.', 7: 'Gold steps the Unicorn out of the Dragon’s shadow.', 8: 'The Dragon follows, hungry, to 3d4, where it threatens the Unicorn again. But it has stepped onto a square a Hero can reach. From 2e3 a Hero rises onto any square diagonally beside 3e3, and 3d4 is one of them.', 9: 'The Hero rises and the Dragon falls. Only five kinds of land piece can touch the air at all, and this is how one of them does it. The Hero is in the air now, where it can do nothing but come down.', 10: 'Scarlet brings a Hero out in answer, leaping its own Warrior at 2d7.', 11: 'Gold’s Hero comes home to the land, onto a square diagonally beside the one beneath it. Off the land, that was its only kind of move.', 13: 'Gold’s Basilisk sets out on a slow walk, one square a move. It wants to be beneath whatever Scarlet sends deep into Gold’s side. Watch where Scarlet’s Hero goes.', 14: 'The Hero digs into Gold’s side at 2c4, two leaps from home. A piece that comes this deep should look beneath its feet.', 17: 'The gaze falls. The Hero at 2c4 is frozen: it cannot move, cannot take, and threatens nothing, until the Basilisk moves or dies. Gold is in no hurry.', 19: 'A Warrior comes to stand diagonally behind the frozen Hero.', 21: 'Taken, in Gygax’s words, more or less at your leisure. The Warrior is safe above Gold’s own Basilisk, since a Basilisk freezes only enemies.', 22: 'Scarlet’s Griffon leaps to 3f6, two squares one way and three the other, over everything. Now look at the four land squares diagonally beside 2f6. One of them is 2e5, where Gold’s Hero stands.', 23: 'Gold does not look up.', 24: 'The swoop. The Griffon drops onto the Hero and takes it. On the land it has lost its wings, and creeps one square at a time until it climbs back.', 25: 'Gold’s Dragon leaves its roost, and this time it is safe to do so: Scarlet’s Dragon is dead, so nothing threatens Gold’s King from the air. Look along the diagonal from 3d4 through e5 and f6 to 3g7, where a Scarlet Sylph hovers above Scarlet’s King.', 26: 'Scarlet does not look up either.', 27: 'The Dragon takes the Sylph at 3g7 and strikes down at every square around the King: 2g7 beneath it, and 2g8, 2f7 and 2h7 beside that. The King cannot step up, because the Dragon stands beside 3g8. It cannot step down, because its own Elemental is at 1g8. Its neighbours on the land are its own pieces or struck squares, and nothing of Scarlet’s can reach 3g7. Checkmate.' }; /** The game at every ply, from the opening to the end. The engine refuses a move that is not legal. */ export function toldStates(): State[] { let s = createGame({ A: 'Gold', B: 'Scarlet' }); const out = [s]; TOLD_MOVES.forEach(([from, to], n) => { const seat = s.toMove === 'gold' ? 'A' : 'B'; const why = validateMove(s, seat, { from: square(from), to: square(to) }); if (why) throw new Error(`told game, ply ${n + 1}, ${from} to ${to}: ${why}`); s = applyMove(s, square(from), square(to)); out.push(s); }); return out; }