import { draftStore } from '../store/draft-store.js';
import { solve } from '../core/solver.js';
import { renderLevel, formatSolverResult } from '../core/ascii-renderer.js';
import { validateGridSize, validatePuzzleData } from '../core/validator.js';
import { PuzzleData, DraftState } from '../core/types.js';
interface ToolDefinition {
name: string;
description: string;
inputSchema: object;
handler: (args: any) => Promise<{ content: Array<{ type: 'text'; text: string }> }>;
}
function formatDraftSummary(draft: DraftState): string {
const solverInfo = draft.lastSolverResult
? formatSolverResult(draft.lastSolverResult)
: 'Not yet solved';
return [
`Name: ${draft.name}`,
`Grid: ${draft.gridWidth}x${draft.gridHeight}`,
`Par: ${draft.par > 0 ? draft.par : 'not set'}`,
`Start: (${draft.startPosition.x}, ${draft.startPosition.y})`,
`Goal: (${draft.goalPosition.x}, ${draft.goalPosition.y})`,
`Obstacles: ${draft.obstacles.length}`,
`Warps: ${draft.warpPairs.length} pairs`,
`Thin Ice: ${draft.thinIceTiles.length}`,
`Pushable Rocks: ${draft.pushableRocks.length}`,
draft.pressurePlate ? `Pressure Plate: (${draft.pressurePlate.x}, ${draft.pressurePlate.y})` : '',
draft.barrier ? `Barrier: (${draft.barrier.x}, ${draft.barrier.y})` : '',
`Solver: ${solverInfo}`,
].filter(Boolean).join('\n');
}
export function getLevelManagementTools(): ToolDefinition[] {
return [
{
name: 'create_level',
description: 'Create a new empty ice puzzle level. This becomes the current working draft.',
inputSchema: {
type: 'object',
properties: {
name: { type: 'string', description: 'Level name' },
width: { type: 'number', description: 'Grid width (5-25, default 10)', minimum: 5, maximum: 25 },
height: { type: 'number', description: 'Grid height (5-25, default 10)', minimum: 5, maximum: 25 },
},
required: ['name'],
},
handler: async (args) => {
const draft = draftStore.createDraft(args.name, args.width, args.height);
const viz = renderLevel(draft, { showCoords: true });
return { content: [{ type: 'text', text: `Level "${args.name}" created!\n\n${formatDraftSummary(draft)}\n\n${viz}` }] };
},
},
{
name: 'get_level',
description: 'Get the current working draft level state with full details and visualization.',
inputSchema: { type: 'object', properties: {} },
handler: async () => {
const draft = draftStore.getCurrentDraft();
if (!draft) return { content: [{ type: 'text', text: 'No active draft. Use create_level first.' }] };
// Auto-solve if dirty
if (draft.isDirty || !draft.lastSolverResult) {
const puzzleData = draftStore.exportPuzzleData();
if (puzzleData) {
const result = solve(puzzleData);
draftStore.updateDraft({ lastSolverResult: result, isDirty: false });
}
}
const current = draftStore.getCurrentDraft()!;
const viz = renderLevel(current, { showCoords: true, showSolution: true, solution: current.lastSolverResult?.solution });
return { content: [{ type: 'text', text: `${formatDraftSummary(current)}\n\n${viz}` }] };
},
},
{
name: 'list_drafts',
description: 'List all saved draft levels.',
inputSchema: { type: 'object', properties: {} },
handler: async () => {
const drafts = draftStore.listDrafts();
if (drafts.length === 0) return { content: [{ type: 'text', text: 'No saved drafts.' }] };
const list = drafts.map((d, i) => `${i + 1}. ${d.name} (${d.id}) - ${d.description || 'No description'}`).join('\n');
return { content: [{ type: 'text', text: `Saved drafts:\n${list}` }] };
},
},
{
name: 'delete_draft',
description: 'Delete a saved draft level.',
inputSchema: {
type: 'object',
properties: { draftId: { type: 'string', description: 'Draft ID to delete' } },
required: ['draftId'],
},
handler: async (args) => {
const success = draftStore.deleteDraft(args.draftId);
return { content: [{ type: 'text', text: success ? `Draft ${args.draftId} deleted.` : `Draft ${args.draftId} not found.` }] };
},
},
{
name: 'import_level',
description: 'Import a level from PuzzleData JSON. Sets it as the current working draft.',
inputSchema: {
type: 'object',
properties: { puzzleData: { type: 'object', description: 'PuzzleData JSON object' } },
required: ['puzzleData'],
},
handler: async (args) => {
const validation = validatePuzzleData(args.puzzleData);
if (!validation.valid) return { content: [{ type: 'text', text: `Invalid puzzle data: ${validation.error}` }] };
const draft = draftStore.importPuzzleData(validation.data!);
const viz = renderLevel(draft, { showCoords: true });
return { content: [{ type: 'text', text: `Level imported!\n\n${formatDraftSummary(draft)}\n\n${viz}` }] };
},
},
{
name: 'export_level',
description: 'Export the current working draft as PuzzleData JSON.',
inputSchema: { type: 'object', properties: {} },
handler: async () => {
const puzzleData = draftStore.exportPuzzleData();
if (!puzzleData) return { content: [{ type: 'text', text: 'No active draft. Use create_level first.' }] };
return { content: [{ type: 'text', text: JSON.stringify(puzzleData, null, 2) }] };
},
},
];
}