Skip to main content
Glama

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
NameRequiredDescriptionDefault
x1YesTop-left X
y1YesTop-left Y
x2YesBottom-right X
y2YesBottom-right Y
typeYesTile type

Implementation Reference

  • 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)}` }] };
      },
    },
  • 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'],
    },
  • 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);
    }
  • 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 };
    }
  • 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 });
      });
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wmoten/ice-puzzle-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server