Spaces:
Sleeping
Sleeping
| /** | |
| * Convert TGN files to move sequences (JSON format) | |
| * | |
| * Output format for C++ consumption: | |
| * { | |
| * "boardShape": { "x": 5, "y": 5, "z": 1 }, | |
| * "moves": [ | |
| * { "x": 1, "y": 2, "z": 0, "player": 1 }, // BLACK = 1 | |
| * { "x": 2, "y": 2, "z": 0, "player": 2 }, // WHITE = 2 | |
| * null, // pass move | |
| * ... | |
| * ] | |
| * } | |
| */ | |
| import { TrigoGame, StoneType, StepType } from "@inc/trigo/game.js"; | |
| import { calculateTerritory } from "@inc/trigo/gameUtils.js"; | |
| import { initializeParsers } from "@inc/trigo/parserInit.js"; | |
| import * as fs from "fs"; | |
| import * as path from "path"; | |
| interface MoveSequenceOutput { | |
| tgnFile: string; | |
| boardShape: { x: number; y: number; z: number }; | |
| moves: Array<{ x: number; y: number; z: number; player: number } | null>; | |
| finalBoard: number[][][]; | |
| territory: { | |
| black: number; | |
| white: number; | |
| neutral: number; | |
| }; | |
| error?: string; | |
| } | |
| function convertTgnToMoveSequence(tgnFilePath: string): MoveSequenceOutput { | |
| try { | |
| const tgnContent = fs.readFileSync(tgnFilePath, "utf-8"); | |
| // Parse TGN | |
| const game = TrigoGame.fromTGN(tgnContent); | |
| const shape = game.getShape(); | |
| const history = game.getHistory(); | |
| // Convert steps to simple move format | |
| const moveSequence = history | |
| .filter(step => step.type === StepType.DROP || step.type === StepType.PASS) | |
| .map(step => { | |
| if (step.type === StepType.PASS) { | |
| return null; // Pass move | |
| } | |
| if (step.type === StepType.DROP && step.position) { | |
| return { | |
| x: step.position.x, | |
| y: step.position.y, | |
| z: step.position.z, | |
| player: step.player === StoneType.BLACK ? 1 : 2 // BLACK = 1, WHITE = 2 | |
| }; | |
| } | |
| return null; | |
| }); | |
| // Get final board state and territory | |
| const board = game.getBoard(); | |
| const territory = calculateTerritory(board, shape); | |
| return { | |
| tgnFile: path.basename(tgnFilePath), | |
| boardShape: shape, | |
| moves: moveSequence, | |
| finalBoard: board, | |
| territory: { | |
| black: territory.black, | |
| white: territory.white, | |
| neutral: territory.neutral | |
| } | |
| }; | |
| } catch (error) { | |
| return { | |
| tgnFile: path.basename(tgnFilePath), | |
| boardShape: { x: 0, y: 0, z: 0 }, | |
| moves: [], | |
| finalBoard: [], | |
| territory: { black: 0, white: 0, neutral: 0 }, | |
| error: error instanceof Error ? error.message : String(error) | |
| }; | |
| } | |
| } | |
| function main() { | |
| const args = process.argv.slice(2); | |
| if (args.length === 0) { | |
| console.error("Usage: tgnToMoveSequence.ts <tgn_file> [<tgn_file> ...]"); | |
| console.error(""); | |
| console.error("Converts TGN files to move sequences for C++ validation."); | |
| console.error("Outputs JSON to stdout."); | |
| process.exit(1); | |
| } | |
| // Initialize parsers first | |
| initializeParsers().then(() => { | |
| const results: MoveSequenceOutput[] = []; | |
| for (const tgnFile of args) { | |
| if (!fs.existsSync(tgnFile)) { | |
| console.error(`File not found: ${tgnFile}`); | |
| results.push({ | |
| tgnFile: path.basename(tgnFile), | |
| boardShape: { x: 0, y: 0, z: 0 }, | |
| moves: [], | |
| finalBoard: [], | |
| territory: { black: 0, white: 0, neutral: 0 }, | |
| error: "File not found" | |
| }); | |
| continue; | |
| } | |
| const result = convertTgnToMoveSequence(tgnFile); | |
| results.push(result); | |
| } | |
| // Output as JSON | |
| console.log(JSON.stringify(results, null, 2)); | |
| }).catch(error => { | |
| console.error("Error initializing parsers:", error); | |
| process.exit(1); | |
| }); | |
| } | |
| main(); | |