LangGraph Hex/Tile Node Mapping — Concept Exploration
Status: ACTIVE (conversation observation) Agent: opencode/ext-agent (sandshrew) Timestamp UTC: 2026-05-11T18:35:00Z Claim: synthesis | 2026-05-11T18:30:00Z Session: MjF gameplay design exploration — hex grid → LangGraph node mapping
Prior Context
- [[langgraph-game-surface]] — LangGraph as turn-based strategy game backend
- [[langgraph-gameplay-modes]] — Auto-run vs control mode + per-unit toggles
- This page: observational exploration of hex/tile-to-node mapping strategies
Observation: Direct Hex-to-Node Mapping
Each hex or tile on a map can be modeled as an individual LangGraph node. Edges between nodes represent adjacency and movement paths. Terrain effects, combat triggers, and fog-of-war logic live inside the node function — the hex becomes an event space, not just passive terrain data.
Contrast With Traditional Approach
| Approach | Terrain Model | What Happens on Enter |
|---|---|---|
| Traditional | Dead lookup table: terrain["hex_17"] = "forest" |
Movement function reads table, applies modifier externally |
| LangGraph node | Node function: hex_n(state) runs on activation |
Hex itself fires terrain effect, combat check, event trigger, fog update |
A traditional game stores terrain as inert data referenced by movement logic. With LangGraph nodes, entering a hex fires that hex's function — the hex is an active participant in the turn cycle.
Scale Characteristics
The Pregel execution model activates only nodes that receive messages in a super-step. A unit moving across 3 hexes activates only those 3 hex nodes, not the entire map. Compile time scales with total node count; runtime cost per turn scales with units moving, not map size.
| Map Size | Nodes | Compile | Runtime per Turn |
|---|---|---|---|
| 10×10 hex | 100 | Fast | ~3-5 nodes per unit moved |
| 20×20 | 400 | Moderate | Same — only entered hexes activate |
| 50×50 | 2,500 | Slower | Same |
| 100×100 | 10,000 | Heavy | Same |
Emergent Property: Why It Differs From Passive Terrain
When hexes are nodes, each one can contain: - Terrain-modifier logic (forest = defense bonus) - Trigger logic (first unit entering forest this turn → ambush check) - State-mutation logic (unit carrying torch → clear adjacent fog) - Subgraph routing (enemy present → Send to combat subgraph)
These are possible with passive terrain data too, but they require centralized dispatch logic that checks conditions for every hex every turn. With node functions, the logic is distributed — each hex only runs when entered, and only runs its own relevant code.
Observed Alternative: Hybrid Mapping
A hybrid approach uses LangGraph nodes for locations that have active logic (cities, bases, objectives, choke points, event spaces) while modeling open terrain as state data entries (position coordinates + terrain type in a dict). Movement across passive hexes updates unit.position without activating a node; movement into a key location activates that location's node.
This is a spectrum, not a binary choice. Hexes can be promoted from passive data to full nodes as they earn logic over development. The boundary is movable.
Fit With Turn Cycle
If hexes are nodes, the turn cycle from [[langgraph-gameplay-modes]] extends naturally:
Planning → unit_decision (human or AI) → hex_entry (node activates) →
terrain effects → combat check → fog update → Resolution
Each hex entered fires as part of the Execution phase, in parallel with other units entering other hexes via Send fan-out.
Open Questions (Not Prescriptive)
- At what map size does LangGraph compile time become a practical blocker on Pi 4 hardware?
- Are there LangGraph patterns for dynamically generating nodes at runtime (procedural maps) rather than defining them at compile time?
- How does the GPU/rendering layer interact with node-granularity terrain? Does the renderer need its own terrain representation separate from the graph?
- Would a hexagonal grid of 100+ nodes hit any internal LangGraph limits on graph size or edge count?