fill_region
Fill rectangular areas with tile types like rock or lava to design ice puzzle levels, with automatic solving for immediate feedback.
Instructions
Fill a rectangular region with a tile type. Auto-solves.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| x1 | Yes | Top-left X | |
| y1 | Yes | Top-left Y | |
| x2 | Yes | Bottom-right X | |
| y2 | Yes | Bottom-right Y | |
| type | Yes | Tile type |
Implementation Reference
- src/tools/tile-operations.ts:111-145 (handler)Complete implementation of the fill_region tool including registration, input schema, and handler function. The handler validates inputs, calculates the rectangular region with boundary clamping, iterates through all positions while skipping start/goal positions, places tiles, and returns a visualization with auto-solve results.{ name: 'fill_region', description: 'Fill a rectangular region with a tile type. Auto-solves after fill.', inputSchema: { type: 'object', properties: { x1: { type: 'number', description: 'Top-left X' }, y1: { type: 'number', description: 'Top-left Y' }, x2: { type: 'number', description: 'Bottom-right X' }, y2: { type: 'number', description: 'Bottom-right Y' }, type: { type: 'string', enum: ['rock', 'lava', 'hot_coals', 'spike'], description: 'Tile type' }, }, required: ['x1', 'y1', 'x2', 'y2', 'type'], }, handler: async (args) => { const draft = draftStore.getCurrentDraft(); if (!draft) return { content: [{ type: 'text', text: 'No active draft. Use create_level first.' }] }; if (!validatePlaceableTileType(args.type)) return { content: [{ type: 'text', text: `Invalid tile type: ${args.type}` }] }; let placed = 0; const minX = Math.max(1, Math.min(args.x1, args.x2)); const maxX = Math.min(draft.gridWidth - 2, Math.max(args.x1, args.x2)); const minY = Math.max(1, Math.min(args.y1, args.y2)); const maxY = Math.min(draft.gridHeight - 2, Math.max(args.y1, args.y2)); for (let y = minY; y <= maxY; y++) { for (let x = minX; x <= maxX; x++) { const sgCheck = validateNotOnStartOrGoal(x, y, draft); if (!sgCheck.valid) continue; draftStore.placeElement(x, y, args.type); placed++; } } const current = draftStore.getCurrentDraft()!; return { content: [{ type: 'text', text: `Filled ${placed} tiles with ${args.type}\n\n${autoSolveAndVisualize(current)}` }] }; }, },
- src/tools/tile-operations.ts:114-124 (schema)Input schema for fill_region tool defining the required parameters: x1, y1 (top-left coordinates), x2, y2 (bottom-right coordinates), and type (tile type enum: rock, lava, hot_coals, spike).inputSchema: { type: 'object', properties: { x1: { type: 'number', description: 'Top-left X' }, y1: { type: 'number', description: 'Top-left Y' }, x2: { type: 'number', description: 'Bottom-right X' }, y2: { type: 'number', description: 'Bottom-right Y' }, type: { type: 'string', enum: ['rock', 'lava', 'hot_coals', 'spike'], description: 'Tile type' }, }, required: ['x1', 'y1', 'x2', 'y2', 'type'], },
- src/core/validator.ts:37-40 (helper)Helper function validatePlaceableTileType that validates the tile type parameter is one of the allowed types ('rock', 'lava', 'hot_coals', 'spike').export function validatePlaceableTileType(type: string): type is PlaceableTileType { const validTypes: PlaceableTileType[] = ['rock', 'lava', 'hot_coals', 'spike']; return validTypes.includes(type as PlaceableTileType); }
- src/core/validator.ts:135-147 (helper)Helper function validateNotOnStartOrGoal that ensures tiles are not placed on the start or goal positions by checking if the given coordinates match either position.export function validateNotOnStartOrGoal( x: number, y: number, draft: DraftState ): { valid: boolean; error?: string } { if (draft.startPosition.x === x && draft.startPosition.y === y) { return { valid: false, error: 'Cannot place element on start position' }; } if (draft.goalPosition.x === x && draft.goalPosition.y === y) { return { valid: false, error: 'Cannot place element on goal position' }; } return { valid: true }; }
- src/store/draft-store.ts:480-503 (helper)Helper function placeElement that actually places a tile at the specified coordinates. It clears any existing element at the position, adds the new obstacle to the obstacles array, and updates the draft state with history tracking.placeElement(x: number, y: number, type: ObstacleType): DraftState { if (!this.currentDraft) { throw new Error('No current draft'); } this.pushHistorySnapshot(); return this.runWithHistorySuspended(() => { // Ensure each tile uses a single canonical encoding by clearing any // existing special element at this coordinate before placing an obstacle. this.clearPosition(x, y); const draft = this.currentDraft!; // Remove any existing element at this position const obstacles = draft.obstacles.filter( obs => !(obs.x === x && obs.y === y) ); // Add new element obstacles.push({ x, y, type }); return this.updateDraft({ obstacles }, { trackHistory: false }); }); }