Mastodon Politics, Power, and Science: Design Document: The Blueprint System for Generative Tactical Maps

Monday, December 8, 2025

Design Document: The Blueprint System for Generative Tactical Maps

J. Rogers, SE Ohio

RE: Architecture for Multi-Level, Recipe-Driven Tactical Map Generation

1. Executive Summary

To evolve from single-layer, randomized dungeon layouts to complex, persistent, and shareable multi-level structures (buildings, dungeons), we will implement a Blueprint System. A Blueprint is a declarative JSON file that serves as a "recipe" for the TacticalGenerator. It defines the structural components, room types, and connectivity rules for a given location, such as a "Two-Story Tavern" or a "Crypt Complex."

This system shifts our generation strategy from pure procedural chaos to a structured, template-based assembly. The generator will consume these Blueprints to produce persistent, interconnected tactical grid maps, storing each floor or distinct area as a new node in the database, linked via marker-based portals. This approach ensures modularity, extensibility, and provides a rich structural context for future AI content population.

2. Goals & Requirements

  • Structured Generation: Ensure complex locations are assembled logically. A "Farmstead" Blueprint should generate a farmhouse, a barn, and a field, not a random cluster of rooms.

  • Verticality & Connectivity: Natively support multi-floor buildings and multi-level dungeons with a formal system for "Portals" (stairs, ladders) that link different map nodes.

  • Persistence: The generated grid layouts for each level must be saved to the database (geometry_data) so they are not re-generated on every visit.

  • Modularity & Extensibility: New building or dungeon types can be added by creating new JSON Blueprint files in a designated directory, requiring no changes to the Python generation code. These files can be easily shared.

  • Hierarchical Integrity: The system must integrate seamlessly with our existing three-layer map hierarchy (World -> Local -> Tactical).

3. Core Concept: The Blueprint File System

A Blueprint is a .json file stored in a new data/blueprints/ directory. This directory will be structured to differentiate between location types. The generator will scan these directories to populate UI choices.

Proposed File Structure:

Code

data/
└── blueprints/
    ├── buildings/
    │   ├── tavern_two_story.json
    │   ├── farmhouse_small.json
    │   └── temple_main.json
    └── dungeons/
        ├── crypt_standard.json
        └── goblin_warren.json
  

4. Blueprint Schema Design

We will utilize two types of Blueprints: Simple (a single multi-level structure) and Compound (a collection of structures on a plot of land).

Example 1: farmhouse_small.json (Simple Blueprint)
This defines a single building with multiple floors.

JSON

{
  "id": "farmhouse_small",
  "name": "Small Farmhouse",
  "tags": ["residential", "rural"],
  "layout": {
    "grid_size": {"w": 12, "h": 10},
    "floors": 2,
    "room_rules": [
      { "tag": "kitchen", "floor": 1, "placement_hint": "rear", "min_size": 12 },
      { "tag": "living_area", "floor": 1, "placement_hint": "front", "min_size": 20 },
      { "tag": "bedroom", "floor": 2, "count": 2, "min_size": 9 }
    ],
    "portals": [
      { "type": "stairs", "link": [1, 2], "placement_hint": "central" }
    ]
  }
}
  

Example 2: farmstead_small.json (Compound Blueprint)
This defines a plot of land that uses other blueprints as components.

JSON

{
  "id": "farmstead_small",
  "name": "Small Farmstead",
  "description": "A modest farm with a main house and outbuildings.",
  "plot_size": {"w": 60, "h": 60},
  "main_building": {
    "blueprint_id": "farmhouse_small",
    "name_template": "{owner_name}'s Farmhouse"
  },
  "outbuildings": [
    {
      "blueprint_id": "barn_simple",
      "count": 1,
      "placement_rules": { "min_dist_from_main": 8, "max_dist_from_main": 20 }
    }
  ]
}
  

5. Generation Workflow (Code Logic)

The TacticalGenerator will be refactored to act as a Blueprint interpreter.

  1. Trigger: User Shift+Clicks a "Building" marker on the Local Map (e.g., "Miller's Farm"). The marker's metadata contains {"blueprint_id": "farmstead_small"}.

  2. Check Persistence: The generator first queries the DB for any child nodes linked to the source marker's node_id and coordinates. If they exist, it loads them. If not, it proceeds.

  3. Parse Blueprint: The generator loads farmstead_small.json. It identifies it as a Compound Blueprint because it contains a plot_size key instead of a layout key.

  4. Generate Compound Plot (Recursive Step):

    • A primary "plot" node is created to represent the farmstead's exterior area (this could be a simple grid or even a mini-GeoController map).

    • The generator recursively calls itself to generate the main_building by loading the farmhouse_small.json blueprint.

  5. Generate Simple Structure (Base Step):

    • The generator processes farmhouse_small.json. It sees "floors": 2.

    • It creates a new node record for Floor 1. Its parent_node_id is the Local Map's node ID.

    • It runs a partitioning algorithm (e.g., Binary Space Partitioning) on the grid_size to create rooms satisfying the room_rules for floor: 1.

    • It creates a second node record for Floor 2, with the same parent_node_id.

    • It runs the partitioning algorithm again for floor: 2.

  6. Create Portals:

    • The generator reads the portals array. It sees "link": [1, 2].

    • On the Floor 1 node (e.g., ID 101), it creates a marker of type stairs at a suitable grid location. This marker's metadata will be {"target_node_id": 102} (the ID of the Floor 2 node).

    • On the Floor 2 node (ID 102), it creates a reciprocal stairs marker with metadata {"target_node_id": 101}. This establishes the two-way link.

  7. Save Geometry & Return: The final grid data for each floor [[1,1,0], [0,1,0]] is saved into the geometry_data field of its corresponding node. The generator returns the ID of the primary entry point (Floor 1 of the main house).

6. Database & UI Integration

  • Nodes: Each floor of a building and each level of a dungeon is a separate node record. The existing parent_node_id hierarchy works perfectly for this. The type will be building_interior or dungeon_level.

  • Markers:

    • On the Local Map (Layer 2), a single marker represents the entire compound (the Farmstead).

    • Inside a Tactical Map (Layer 3), markers are used for Portals (linking to other nodes) and interactive objects.

  • User Interaction:

    • When creating a marker on the Local Map, if the type is "Building" or "Lair", a new dropdown will appear, populated by scanning the data/blueprints/ directory.

    • The user selects a blueprint (e.g., "Small Farmstead"), which saves the blueprint_id to the marker's metadata.

    • Shift+Clicking this marker now triggers the generation workflow.

    • Shift+Clicking a "Stairs" marker inside a tactical map will trigger a transition to the target_node_id.

No comments:

Post a Comment

h vs ℏ: A Proof That Planck's Constant Is a Coordinate Choice, Not Physics

J. Rogers, SE Ohio Abstract We prove that the choice between h (Planck's constant) and ℏ (reduced Planck's constant) represents a co...