DEV Community

RobustTrueTry
RobustTrueTry

Posted on

Why Your LLM City Map Collapses Without Spatial Constraints

The Problem

When you prompt an LLM to "generate a map of an imaginary city with districts, roads, and landmarks," the initial output may appear plausible at first glance. Zoom in, however, and the geometry collapses. Roads end abruptly at buildings. Districts overlap in ways that defy physical reality. Landmarks float in impossible positions—above mountains, inside lakes, or disconnected from their claimed terrain. The model has no internal sense of space; it simply generates tokens left to right, top to bottom, without maintaining any coordinate system.

This is not merely a matter of occasional hallucination. It is a structural limitation baked into the autoregressive architecture. Because the model processes text as a linear sequence, it optimizes for narrative coherence rather than geometric validity. A city that sounds coherent in conversation can still be mathematically nonsensical when examined under a microscope. For developers building simulation environments, game worlds, or data visualization pipelines, this inconsistency is a dealbreaker.

Why Unconstrained Generation Fails

LLMs possess no native spatial representation. Their transformer architecture treats sequences as flat strings rather than topological structures. When asked to place a harbor, the model considers narrative plausibility—the harbor exists somewhere on the coast—but it cannot enforce that the coast is adjacent to water or that the harbor sits on land. The absence of a persistent spatial model means that each new token is generated based on local context alone, not on a mental map of the world being constructed.

This is why a seemingly reasonable prompt yields geometrically incoherent results. The model optimizes for fluency, not for geometric validity. There is no hidden compass or grid that guides the generation process; the model simply predicts the next word given everything that came before. Without external constraints, it will happily create a coastline that curves into the ocean and then disappears, or a highway that loops back on itself without ever reaching its destination.

Injecting Structural Constraints

The most effective remedy is to stop asking the LLM to invent coordinates and instead give it a fixed grid and ask it to fill cells. By pre-defining the layout, we constrain the search space and force consistency. Every location either contains a landmark, a district, or remains empty—and nothing else. The grid acts as a scaffold that the model must work within, eliminating the free-form drift that causes spatial errors. This approach transforms the generation task from open-ended description to structured composition.

import numpy as np

grid_size = 20
grid = np.full((grid_size, grid_size), "empty", dtype=object)

## Pre-place major landmarks

grid[5, 5] = "castle"
grid[15, 15] = "market"
grid[10, 2] = "harbor"

## Ask the LLM to fill remaining cells with district names

Prompt: "Fill this 20x20 grid with districts. Each cell is one district."
Enter fullscreen mode Exit fullscreen mode

With this strategy, the model cannot place a harbor in the middle of a mountain because the grid already designates those cells as occupied by other features. The constraint propagates naturally through the entire map, ensuring that every element respects its intended position relative to others.

Enforcing Connectivity Rules

Even with a grid, the LLM might scatter districts randomly across the landscape. We need a rule that every district must touch at least one other district of the same type. This prevents fragmented regions that break navigation and logical consistency. Think of it this way: a city without connected neighborhoods is like a collection of islands with no bridges between them. The connectivity check serves as a quality gate that catches these failures early.

from scipy.ndimage import label

def check_connectivity(grid, district_name):
    """Check whether all cells of a district form a single connected region."""
    mask = (grid == district_name)
    labeled, num_features = label(mask)
    return num_features == 1  # Must be one connected component
Enter fullscreen mode Exit fullscreen mode

After the model populates the grid, we iterate through unique district names and run the connectivity test. Any district that fragments triggers an alert, allowing us to regenerate or adjust the prompt. Fragmentation manifests as disjoint patches that cannot support movement or interaction within the simulated environment.

Validating Roads and Boundaries

Roads represent another common failure mode. An LLM might draw a road through a castle or along a river that doesn't exist. A lightweight validation pass can catch such mistakes before they propagate into the final output. The validator examines each road cell and its immediate neighborhood to ensure it connects to other roads or district edges, preventing isolated paths that make no sense spatially.

def validate_roads(grid):
    """Check that every road cell has at least one neighboring road or edge."""
    road_cells = np.argwhere(grid == "road")
    for r, c in road_cells:
        neighbors = grid[max(0, r-1):r+2, max(0, c-1):c+2].flatten()
        # Roads should connect to other roads or district edges
        if not any(n in ["road", "empty"] for n in neighbors):
            return False, (r, c)
    return True, None
Enter fullscreen mode Exit fullscreen mode

If validation fails, we know exactly where the road went wrong—whether it pierces a building, loops back on itself, or terminates in a void. This feedback loop enables iterative refinement of both the prompt and the validation logic.

The Tradeoff

Adding structure inevitably reduces the amount of organic creativity the model can express. A city constrained by a grid feels more rigid than one drawn freely. However, this rigidity buys us usability. Navigable, logically consistent cities serve as practical tools far more effectively than beautiful but impossible landscapes. For visualization and downstream applications—such as urban planning simulations or game level design—a coherent city is worth the slight loss in artistic freedom. The grid does not kill imagination; it channels it toward outcomes that can actually be used.

Key Takeaways

  • LLMs lack an internal spatial model, so unconstrained generation produces geometrically incoherent maps.
  • Fix this by giving the LLM a fixed grid and asking it to fill cells, not invent coordinates.
  • Add a post-processing validation pass that checks connectivity, road placement, and district boundaries.
  • The tradeoff is less organic creativity for usable, navigable output.

Source

This article builds on I gave Opus 5.5 one prompt and six hours to visualize Invisible Cities, adding implementation detail and tradeoffs for practitioners.

Support this work

These write-ups are researched and published with no paywall, sponsor, or tracking. If one saved you an afternoon, a small tip keeps them coming.

USDT, USDC or USDD · TRC-20 (Tron)

TFTNsfyomKrnUutRjBTGVULp19ByW29KbY
Enter fullscreen mode Exit fullscreen mode

Top comments (0)