// Composes the told game (src/lib/game/told.ts): its moves are played at // their plies and the drake plays any ply beyond them, so a longer game can // be sketched and steered. Prints the chronicle, and with a ply and a // square, the legal moves of the piece there at that ply. // npx tsx docs/compose-game.ts [plies] [ply square] import { createGame, applyMove, validateMove } from '../src/lib/game/index.ts'; import { chooseMove } from '../src/lib/game/bot.ts'; import { narrate } from '../src/lib/game/chronicle.ts'; import { square, squareName, legalMovesFrom, type Side } from '../src/lib/game/board.ts'; import { TOLD_MOVES } from '../src/lib/game/told.ts'; const FORCED: Record = Object.fromEntries(TOLD_MOVES.map((m, n) => [n + 1, m])); const plies = Number(process.argv[2] ?? 40); const askPly = process.argv[3] ? Number(process.argv[3]) : 0; const askSquare = process.argv[4]; let s = createGame({ A: 'Gold', B: 'Scarlet' }); for (let ply = 1; ply <= plies && !s.over; ply++) { const seat = s.toMove === 'gold' ? 'A' : 'B'; if (ply === askPly && askSquare) { console.log(`ply ${ply}, ${s.toMove} to move, ${askSquare} may go to: ${legalMovesFrom(s.cells, square(askSquare), 'printed').map(squareName).join(' ')}`); process.exit(0); } const forced = FORCED[ply]; let move: { from: number; to: number }; if (forced) { move = { from: square(forced[0]), to: square(forced[1]) }; const why = validateMove(s, seat, move); if (why) { console.log(`ply ${ply}: forced ${forced[0]}-${forced[1]} refused: ${why}`); process.exit(1); } } else move = chooseMove(s.cells, s.toMove as Side, 'printed', 40000)!; s = applyMove(s, move.from, move.to); } for (const t of narrate(s)) console.log(`${t.ply}${FORCED[t.ply] ? '*' : ' '} ${t.lines.map((l) => l.text).join(' ')}`); console.log(s.over ? `over: ${s.over.reason}` : `${s.toMove} to move`);