Grid Module
A builder for creating graphs from 2D grids.
This module provides convenient ways to convert 2D grids (like heightmaps, mazes, or game boards) into graphs for pathfinding and traversal algorithms.
Key Concepts
- Row-Major Ordering: Node ID = row × cols + col
- Topology: Movement patterns (rook/bishop/queen/knight)
- Predicate: Function that determines if movement is allowed
Movement Topologies
The module provides 4 chess-inspired movement patterns:
Rook (4-way cardinal):
1: 2: 3: |
|
Bishop (4-way diagonal):
1:
|
|
Queen (8-way):
|
Knight (L-shaped):
1: 2: 3: 4: 5: |
|
Example Usage
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: |
|
Use Cases
- Game pathfinding: Character movement on tile-based maps
- Maze solving: Finding paths through grid-based mazes
- Heightmap navigation: Terrain traversal with elevation constraints
- Puzzle solving: Grid-based puzzles like Sokoban, sliding puzzles
<summary> A* (A-Star) search algorithm for optimal pathfinding with heuristic guidance. A* is an informed search algorithm that finds the shortest path from a start node to a goal node using a heuristic function to guide exploration. It combines the completeness of Dijkstra's algorithm with the efficiency of greedy best-first search. ## Algorithm | Algorithm | Function | Complexity | Best For | |-----------|----------|------------|----------| | A* Search | aStar | O((V + E) log V) | Pathfinding with good heuristics | | Implicit A* | implicitAStar | O((V + E) log V) | Large/infinite graphs generated on-demand | ## Key Concepts - **Evaluation Function**: f(n) = g(n) + h(n) - g(n): Actual cost from start to node n - h(n): Heuristic estimate from n to goal - f(n): Estimated total cost through n - **Admissible Heuristic**: h(n) ≤ actual cost (never overestimates) - **Consistent Heuristic**: h(n) ≤ cost(n→n') + h(n') (triangle inequality) ## When to Use A* **Use A* when:** - You have a specific goal node (not single-source to all) - You can provide a good heuristic estimate - The heuristic is admissible (underestimates) **Use Dijkstra when:** - No good heuristic available (h(n) = 0 reduces A* to Dijkstra) - You need shortest paths to all nodes from a source ## Heuristic Examples | Domain | Heuristic | Admissible? | |--------|-----------|-------------| | Grid (4-way) | Manhattan distance | Yes | | Grid (8-way) | Chebyshev distance | Yes | | Geospatial | Haversine/great-circle | Yes | | Road networks | Precomputed landmarks | Yes | ## Use Cases - Video games: NPC pathfinding on game maps - GPS navigation: Route planning with distance estimates - Robotics: Motion planning with obstacle avoidance - Puzzle solving: Sliding puzzles, mazes, labyrinths </summary>
<summary> Finds the shortest path using A* with integer weights. </summary>
Functions and values
| Function or value |
Description
|
||
Full Usage:
always arg1 arg2
Parameters:
'a
arg1 : 'b
Returns: bool
|
Always allows movement between adjacent cells. Every neighbor pair gets an edge regardless of cell data. Useful for fully connected grids or when the cell data is purely informational (e.g., storing coordinates or labels).
Example
val labels: string array2d
val array2D: rows: #('T seq) seq -> 'T array2d
val grid: obj
|
||
Full Usage:
avoiding wallValue from to'
Parameters:
'a
from : 'a
to' : 'a
Returns: bool
|
Allows movement between any cells except the specified wall value. Useful for maze-style grids where "#" or similar marks a wall. Both the source and destination cells must not be the wall value.
Example
val maze: string array2d
val array2D: rows: #('T seq) seq -> 'T array2d
val grid: obj
|
||
Full Usage:
bishop
Returns: (int * int) list
|
Diagonal (4-way) movement: the four diagonal directions. Named after the bishop in chess, which moves along diagonals.
|
||
Full Usage:
coordToId row col cols
Parameters:
int32
col : int32
cols : int
Returns: int32
|
Converts grid coordinates (row, col) to a node ID. Uses row-major ordering: id = row × cols + col
Example
|
||
|
Builds a grid-graph from a 2D array and a custom movement topology. Each cell becomes a node, and edges are added between cells based on the topology and the canMove predicate.
Parameters
Time ComplexityO(rows × cols × |topology|) Example
val maze: string array2d
val array2D: rows: #('T seq) seq -> 'T array2d
val grid: obj
|
||
Full Usage:
getCell row col grid
Parameters:
int
col : int
grid : Grid<'a, 'b>
Returns: 'a option
|
Gets the cell data at the specified grid coordinate. Returns Some(cell_data) if the coordinate is valid, None otherwise.
Example
union case Option.Some: Value: 'T -> Option<'T>
val cell: obj
union case Option.None: Option<'T>
|
||
Full Usage:
idToCoord id cols
Parameters:
int
cols : int
Returns: int * int
|
Converts a node ID back to grid coordinates (row, col).
Example
|
||
Full Usage:
knight
Returns: (int * int) list
|
L-shaped jumps in all 8 orientations. Named after the knight in chess, which jumps in an L-shape (2 squares in one direction, 1 square perpendicular).
|
||
Full Usage:
manhattanDistance fromId toId cols
Parameters:
int
toId : int
cols : int
Returns: int
|
Calculates the Manhattan distance between two node IDs. This is useful as a heuristic for A* pathfinding on grids. Manhattan distance is the sum of absolute differences in coordinates: |x1 - x2| + |y1 - y2|
Example
val start: obj
val goal: obj
val distance: obj
|
||
Full Usage:
queen
Returns: (int * int) list
|
All 8 surrounding directions: cardinal + diagonal. Named after the queen in chess, which combines rook and bishop movement.
|
||
Full Usage:
rook
Returns: (int * int) list
|
Cardinal (4-way) movement: up, down, left, right. Named after the rook in chess, which moves along ranks and files.
|
||
|
|||
Full Usage:
walkable validValue from to'
Parameters:
'a
from : 'a
to' : 'a
Returns: bool
|
Allows movement only between cells matching the specified value. The inverse of
Example
val terrain: string array2d
val array2D: rows: #('T seq) seq -> 'T array2d
val grid: obj
|