snake-ai-game
Version:
A terminal-based snake game powered by AI.
100 lines (88 loc) • 3.29 kB
text/typescript
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 };
}
})
};