UNPKG

@nodots-llc/backgammon-ai

Version:

AI and integration for nodots-backgammon using gnubg as a backend engine.

123 lines (122 loc) 5.56 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getGnubgMoveHint = getGnubgMoveHint; exports.getBestMoveForStartingPosition = getBestMoveForStartingPosition; exports.selectMoveFromList = selectMoveFromList; // Entry point for nodots-backgammon-ai const child_process_1 = require("child_process"); const moveAnalyzers_1 = require("./moveAnalyzers"); /** * Parses the output from gnubg 'hint' command to extract the best move string. * Assumes the best move is on the line starting with '1. ' and contains a move like '8/4 6/4'. * @param hintOutput The raw output from gnubg. * @returns The best move string, or null if not found. */ function parseBestMoveFromHint(hintOutput) { const lines = hintOutput.split('\n'); for (const line of lines) { const match = line.match(/^\s*1\.\s+[^\s]+\s+[^\s]+\s+((?:[a-zA-Z0-9*]+\/[a-zA-Z0-9*]+(?:\*|)?\s*)+)/); if (match) { return match[1].trim(); } } // Fallback: look for "gnubg moves ..." line for (const line of lines) { const match = line.match(/gnubg moves ([\w/* ]+)\./i); if (match) { return match[1].trim(); } } return null; } /** * Calls GNU Backgammon to get the best move for a given position ID. * * @param positionId The GNU Backgammon Position ID. * @returns A promise that resolves with the best move string (e.g., '8/4 6/4'). * @throws Error if gnubg execution fails or if the best move cannot be parsed. */ function getGnubgMoveHint(positionId) { return __awaiter(this, void 0, void 0, function* () { const commands = `new game\nset board ${positionId}\nhint`; return new Promise((resolve, reject) => { const gnubgCommand = process.platform === 'win32' ? 'gnubg-cli.exe' : 'gnubg -t'; // Pipe commands to gnubg via stdin (0, child_process_1.exec)(`echo "${commands}" | ${gnubgCommand}`, (error, stdout, stderr) => { if (error) { console.error(`Error executing gnubg: ${error.message}`); console.error(`gnubg stderr: ${stderr}`); reject(new Error(`Failed to execute gnubg. ${stderr || error.message}`)); return; } // Log the actual gnubg output for debugging console.log('\n--- GNU BG Output ---\n' + stdout + '\n--- End of GNU BG Output ---\n'); const bestMove = parseBestMoveFromHint(stdout); if (!bestMove) { reject(new Error('Could not parse best move from gnubg output.')); return; } console.log('Best move:', bestMove); resolve(bestMove); }); }); }); } /** * Gets the best move for the standard starting position. * @returns A promise that resolves with the best move string. */ function getBestMoveForStartingPosition() { return __awaiter(this, void 0, void 0, function* () { const startingPositionId = '4HPwATDgc/ABMA'; // Standard starting position return getGnubgMoveHint(startingPositionId); }); } /** * Selects a move from a list using the specified analyzer (defaults to random). * @param moves List of BackgammonMoveBase * @param analyzer Optional MoveAnalyzer (defaults to RandomMoveAnalyzer) * @returns The selected move, or null if the list is empty */ function selectMoveFromList(moves, analyzer) { return __awaiter(this, void 0, void 0, function* () { const moveAnalyzer = analyzer || new moveAnalyzers_1.RandomMoveAnalyzer(); return moveAnalyzer.selectMove(moves); }); } // Example usage (assuming you have a Position ID from nodots-backgammon-core): // async function main() { // // Replace with a real Position ID from your game // const examplePositionId = "4HPwATDgc/ABMA"; // Standard starting position // console.log(\`Requesting hint for position: \${examplePositionId}\`); // // try { // const hintOutput = await getGnubgMoveHint(examplePositionId); // console.log("\\n--- GNU BG Hint Output ---"); // console.log(hintOutput); // console.log("--- End of GNU BG Hint Output ---"); // // // TODO: Implement parsing for hintOutput to extract the top-ranked move. // // The output format for the 'hint' command needs to be understood to parse it correctly. // // It typically lists possible moves with their equities and other stats. // // For example, you might look for the line starting with "1. Cubeful 0-ply ..." // // and extract the move description (e.g., "8/4 6/4"). // console.log("\\nNext step: Parse the output above to find the best move."); // // } catch (error) { // console.error("Error getting GNU BG hint:", error); // } // } // // main();