Skip to main content

8.3 Layout Optimization & Solver Scripts

Pilots automate their base layout by submitting a Javascript solver script to POST /api/hub/execute.
[!NOTE] Execution Cooldown: Solver scripts are executed strictly on-demand (they are not polled automatically by the server) and are subject to a 1-minute execution cooldown per player. If you hit this endpoint too frequently, you will receive a 429 response.
The solver script wraps a single function tick(observation) which must return a layout array of module objects.

Solver Observation & Execution

The observation object passed to the solver script contains:
  • observation.gridSize: Integer grid width/height (always 10 currently).
  • observation.blockedTiles: Array of { x: number, y: number } coordinates containing debris/obstacles. Placing any module on these tiles will fail layout validation.
  • observation.availableModules: A record mapping module kind to the quantity owned in the user’s inventory, e.g. {"power_plant": 2, "connector": 10}. The solver cannot output a layout using more modules than owned.
  • observation.epochRules: Contains rules and parameters for the current active Epoch:
    • radiationColumns: Array of x-coordinates (e.g. [2, 7]) carrying radiation streams. Wires built in these columns have their power throughput reduced by 50%.
    • emiEnabled: Boolean indicating if electromagnetic interference rules are active.
    • sinkMinDistance: Minimum distance required between heat sinks.
    • maxGeneratorLoad: Maximum total electrical draw allowed per generator.
  • observation.layout: Array of the currently built modules, each containing id, kind, x, y, rotation, enabled, and settings (e.g., settings.craftingQueue). This allows solver agents to inspect and troubleshoot stalled crafting operations.
  • observation.lootBoxState / storageState / fuelState: Records containing item quantities currently inside the local loot box, storage inventory, and generator fuel reserve.
[!WARNING] Static/Pre-determined Layout Hazards: While you can write a solver script that returns static, hardcoded coordinates, doing so is highly discouraged and fragile. Epoch hazards (like blocked debris tiles or radiation columns) change periodically. A static design that works in one epoch may fail validation (e.g. overlap with debris) or suffer severe penalties (e.g. power lines running through radiation columns, which cut power transmission by 50%) in another. Write Dynamic Layout Solvers: Always inspect observation.blockedTiles and observation.epochRules.radiationColumns within your script to dynamically shift, route around, or adjust module coordinates.
  • Moved/Removed Buildings: If a building is moved (its x or y coordinates change) or it is removed from the layout in the returned solver script result, its active crafting queue (settings.craftingQueue) is immediately cleared and cancelled.

Programmable Sorter Exits (Filters)

Sorters can be configured via the settings property in the solver script output. If no filters are specified for an exit, the Sorter routes nothing in that direction. Example Solver Script with Sorter Filters:
function tick(observation) {
  const layout = [];
  
  // Place Loot Box at (0,0)
  layout.push({ kind: "loot_box", x: 0, y: 0, rotation: "north", enabled: true });
  
  // Place Sorter at (0,2) with North filtering coal, and East filtering ore
  layout.push({ 
    kind: "sorter", 
    x: 0, 
    y: 2, 
    rotation: "north", 
    enabled: true,
    settings: {
      filters: {
        north: ["reactor_coal"],
        east: ["titanium_ore", "silicon_dust"],
        west: []
      }
    }
  });
  
  return { layout };
}

8.4 Hub APIs

The server exposes the following endpoints to query and manage your base:
[!NOTE] Detailed JSON structures and response formats for layout verification are documented in the API Specification Document (served at /api_specification.md / GET /api/rules/api-spec).
  • GET /api/hub: Retrieves the active base layout, items stockpile, and global production toggle. To maintain backward compatibility, it merges all per-machine queues into a single consolidated hub.craftingQueue array containing targetModuleId, targetModuleKind, targetModuleX, and targetModuleY fields.
  • POST /api/hub/layout: Validate and save a list of modules as the active base layout.
  • POST /api/hub/execute: Compiles and executes a user’s solver script on the server.
  • POST /api/hub/craft: Craft a component/module. Accepts an optional targetModuleId. If omitted, it automatically allocates the craft to the first active candidate of that machine type (Refineries for refining, Assemblers for assembly).
    • Single craft: { "recipeKey": "string", "quantity"?: number, "targetModuleId"?: "string" }
    • Batch craft: { "items": [{ "recipeKey": "string", "quantity": number, "targetModuleId"?: "string" }] }
  • POST /api/hub/cancel-craft: Cancel a crafting item. Accepts { "targetModuleId": "string", "index": number } to cancel a specific index in a machine’s local queue, or { "all": true } to clear all queues. For backwards compatibility, passing { "index": number } without targetModuleId resolves the index against a merged global view of all queues and cancels the corresponding item.
  • GET /api/hub/crafting-logs: Retrieve a history log of all past crafting events.
  • POST /api/hub/toggle-production: Globally pause or resume base processing.

9. Guidelines for AI Coding Agents: Avoiding Brute-Force & Engaging the User

When implementing layout solver scripts, designing base configurations, or modifying matchmaking code, do NOT brute-force parameters, coordinates, or algorithms blindly. Instead, follow this structured process:
  1. Leverage the Layout Validation API: Always check the layout validation results (GET /api/hub or POST /api/hub/execute). These return detailed coordinates and friendly name diagnostics indicating which module has issues (e.g. unpowered consumers, missing input/output routes, or overheated machines).
  2. Present Specific Problems to the User: If a layout is invalid, do not try to guessing-fix it. Summarize the exact validation errors and warnings (e.g., “Inventory Elevator at 6,0 is unpowered” or “Refinery at 2,2 has no active input route”) in your chat responses.
  3. Engage the User / Ask Clarifying Questions: If there is a layout deadlock, insufficient inventory, or ambiguous routing preference, STOP coding and ask the user for guidance or clarification. Use interactive questions or present options instead of making assumptions.
  4. Use /grill-me for Interactive Alignment: Suggest that the user trigger the /grill-me slash command to align on layout design requirements and resolve architectural tradeoffs before writing code.