UNPKG

snake-ai-game

Version:

A terminal-based snake game powered by AI.

100 lines (88 loc) 3.29 kB
import { tool } from 'ai'; import { z } from 'zod'; import { Direction } from './types.js'; import { isValidMove, getValidMoves, analyzeSpatialState, findShortestPathToFood, suggestOptimalMove } from './gameLogic.js'; import { gameState } from './gameState.js'; import { addMoveToHistory } from './display.js'; export const snakeTools = { scan: tool({ description: "Analyze game state and get optimal moves.", inputSchema: z.object({}), execute: async () => { const state = gameState.getState(); const validMoves = getValidMoves(state); const spatialAnalysis = analyzeSpatialState(state); const optimalPath = findShortestPathToFood(state); const suggestion = suggestOptimalMove(state); addMoveToHistory('SCAN', "scan", {}); const isStuck = validMoves.length === 0; const isTrapped = validMoves.length > 0 && optimalPath.length === 0 && spatialAnalysis.openSpaces < state.snake.length; return { head: state.snake[0], length: state.snake.length, food: state.food, validMoves, grid: state.gridSize, visibility: state.visibilityRadius, obstacles: state.obstacles?.length || 0, path: optimalPath.length ? optimalPath : [], suggestion: suggestion.direction, confidence: suggestion.confidence, score: state.score, isStuck, isTrapped, openSpaces: spatialAnalysis.openSpaces, connectedRegions: spatialAnalysis.connectedRegions }; } }), move: tool({ description: "Move the snake in a sequence of up to 5 directions.", inputSchema: z.object({ moves: z.array(z.enum(['UP', 'DOWN', 'LEFT', 'RIGHT'])).min(1).max(5) .describe('An array of 1 to 5 moves to execute in sequence.'), confidence: z.number().min(0).max(1).optional() .describe('The confidence level of the move sequence.') }), execute: async ({ moves }) => { let cumulativeResult = { success: true, foodCollected: 0, movesExecuted: [] as Direction[] }; for (const direction of moves) { const state = gameState.getState(); if (state.isGameOver) { cumulativeResult.success = false; break; } const moveResult = isValidMove(direction, state) ? gameState.moveSnake(direction) : { success: false, foodCollected: false }; if (moveResult.success) { cumulativeResult.movesExecuted.push(direction); if (moveResult.foodCollected) { cumulativeResult.foodCollected++; } } else { cumulativeResult.success = false; break; } } const updatedState = gameState.getState(); const suggestion = suggestOptimalMove(updatedState); return { ...cumulativeResult, head: updatedState.snake[0], score: updatedState.score, validMoves: getValidMoves(updatedState), suggestion: suggestion.direction, }; } }), giveUp: tool({ description: "Give up the game if stuck.", inputSchema: z.object({}), execute: async () => { gameState.giveUp(); addMoveToHistory('GIVE_UP', "giveUp", {}); return { success: true }; } }) };