https://github.com/nsmryan/zig_astar
Simple implementation of the A-Star algorithm in Zig
https://github.com/nsmryan/zig_astar
astar library zig ziglang
Last synced: 3 months ago
JSON representation
Simple implementation of the A-Star algorithm in Zig
- Host: GitHub
- URL: https://github.com/nsmryan/zig_astar
- Owner: nsmryan
- Created: 2022-09-04T18:07:37.000Z (almost 4 years ago)
- Default Branch: master
- Last Pushed: 2025-06-29T12:56:55.000Z (12 months ago)
- Last Synced: 2025-06-29T13:44:25.426Z (12 months ago)
- Topics: astar, library, zig, ziglang
- Language: Zig
- Homepage:
- Size: 3.91 KB
- Stars: 2
- Watchers: 2
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
I don't recommend using this repository!
There is an updated, less buggy version in my Rust Game on https://codeberg.org/tuplestruct/rrl
I haven't been using GitLab, and I haven't back ported the updated version of this code back to this repo, so please do not trust it!
# Zig AStar
This repository contains a simple implementation of the A-Star algorithm in Zig.
This is not intended to be fancy. However, it does take a user-defined
position type and distance function, and does not assume anything about the
space that the pathfinding takes place in.
Instead the algorithm expects the user to drive it, tracking paths and asking the user
for the neighbors of a particular location. When the algorithm finds a path to the end
location it will report that it is done. This is similar to an iterator, and avoids
requiring any kind of user defined map type or "neighbors" function to be provided.
The implementation uses the std.ArrayList and std.PriorityQueue, and takes an allocator
from the user.
See below for an example use. Notice that the user code drives the search by
calling 'step', and feeding back the requested slice of neighbor positions.
```zig
const SimplePos = struct {
x: isize,
y: isize,
pub fn init(x: isize, y: isize) SimplePos {
return SimplePos{ .x = x, .y = y };
}
};
fn simple_distance(start: SimplePos, end: SimplePos) usize {
const x_dist = std.math.absInt(start.x - end.x) catch unreachable;
const y_dist = std.math.absInt(start.y - end.y) catch unreachable;
return @intCast(usize, std.math.min(x_dist, y_dist));
}
pub main() void {
const allocator = std.heap.page_allocator;
const PathFinder = Astar(SimplePos, simple_distance);
var neighbors = ArrayList(SimplePos).init(allocator);
defer neighbors.deinit();
const start = SimplePos.init(0, 0);
const end = SimplePos.init(4, 4);
var result = try finder.pathFind(start, end);
while (result == .neighbors) {
const pos = result.neighbors;
neighbors.clearRetainingCapacity();
const offsets: [3]isize = .{ -1, 0, 1 };
for (offsets) |offset_x| {
for (offsets) |offset_y| {
const new_x = pos.x + offset_x;
const new_y = pos.y + offset_y;
// User defined validity function 'IsValid' not shown.
if (!IsValid(new_x, new_y)) {
continue;
}
const next_pos = SimplePos.init(new_x, new_y);
try neighbors.append(next_pos);
}
}
result = try finder.step(neighbors.items);
}
// The 'result' variable is now either .done, with the Path structure containing the
// path from start to end, or .no_path indicating that there is no valid path.
switch (result) {
.no_path => {
// Error
},
.done => |path| {
// Path from start to end of type Path(SimplePos).
},
.neighbors => {
unreachable
},
}
}
```