Skip to content

Releases: labelle-toolkit/labelle-pathfinding

v2.7.0 - Hook System for Pathfinding Lifecycle Events

25 Dec 21:22

Choose a tag to compare

What's New

Hook System

A comptime-based, zero-overhead hook system for observing pathfinding lifecycle events.

Algorithm Hooks (A*, Floyd-Warshall):

  • path_requested - When pathfinding is initiated
  • path_found - When a valid path is discovered
  • no_path_found - When no path exists between nodes
  • node_visited - When a node is visited during search (for debugging/visualization)
  • search_complete - When the search algorithm finishes

Stair/Movement Hooks (PathfindingEngine):

  • stair_enter - When an entity enters a stair
  • stair_exit - When an entity exits a stair
  • stair_wait - When an entity starts waiting for a stair (blocked by traffic)

Usage Example

const MyHooks = struct {
    pub fn path_found(payload: pathfinding.hooks.HookPayload) void {
        const info = payload.path_found;
        std.log.info("Path found! Cost: {d}", .{info.cost});
    }
};

const Dispatcher = pathfinding.hooks.HookDispatcher(MyHooks);
var astar = pathfinding.AStarWithHooks(Dispatcher).init(allocator);

Other Changes

  • MergePathfindingHooks for combining multiple hook handlers
  • EmptyDispatcher as default when no hooks are needed
  • Hooks emit entity IDs (not internal indices) when using mapping methods

v2.6.0 - Module rename and ECS Components export

22 Dec 14:14

Choose a tag to compare

Breaking Changes

  • Module renamed: pathfindinglabelle_pathfinding

    Update your imports from:

    const pathfinding = @import("pathfinding");

    to:

    const pathfinding = @import("labelle_pathfinding");

New Features

  • Components export for ECS integration (#33): Export Components struct containing Vec2, NodeId, and NodePoint types for use with labelle-engine's ComponentRegistryMulti
  • labelle-engine integration example: New example demonstrating how to use pathfinding components in ECS entity definitions

Bug Fixes

  • Module name mismatch (#35): The labelle CLI expects modules with underscored names matching the package name. Module is now correctly named labelle_pathfinding.

🤖 Generated with Claude Code

v2.5.0 - Convenience functions, grid helper, and simplified config

10 Dec 21:13

Choose a tag to compare

What's New

Simplified Configuration

  • PathfindingEngineSimple(Entity, Context) - Quick setup without full Config struct

Grid Helper

  • createGrid(config) - Create grid of nodes with automatic connections in one call
  • Returns a Grid struct with coordinate utilities: toScreen, toNodeId, fromNodeId, nodePosition

Convenience Functions

  • connectAsGrid4(cell_size) - 4-directional movement (up/down/left/right)
  • connectAsGrid8(cell_size) - 8-directional movement (including diagonals)

Vec2 Integration

  • Position queries (getPosition, getNodePosition) return Vec2 from zig-utils
  • New methods: addNodeVec2, registerEntityVec2

Full Changelog

v2.4.0...v2.5.0

v2.4.0

05 Dec 21:32

Choose a tag to compare

What's Changed

  • Removed zig-ecs dependency - The library no longer depends on zig-ecs. The PathfindingEngine is fully self-contained and manages entity positions directly.
  • Removed legacy ECS components (MovementNode, ClosestMovementNode, MovingTowards, WithPath)
  • Removed MovementNodeController

This is a breaking change if you were using the ECS integration. Migrate to using PathfindingEngine directly.

Full Changelog

v2.3.0...v2.4.0

v2.3.0 - Optimized Floyd-Warshall

04 Dec 15:14

Choose a tag to compare

What's New

Optimized Floyd-Warshall Implementations

This release adds high-performance Floyd-Warshall variants with significant speedups:

  • FloydWarshallSimd - SIMD vectorization with flat memory layout (5-8x faster)
  • FloydWarshallParallel - Multi-threaded + SIMD (up to 16x faster for large graphs)

Usage

Direct usage:

// SIMD-only (single-threaded)
var fw = pathfinding.FloydWarshallSimd.init(allocator);

// Parallel + SIMD (multi-threaded, best for 256+ nodes)
var fw = pathfinding.FloydWarshallParallel.init(allocator);

With PathfindingEngine:

const Config = struct {
    pub const Entity = u64;
    pub const Context = *Game;
    pub const floyd_warshall_variant: pathfinding.FloydWarshallVariant = .optimized_parallel;
};

Benchmark

Run zig build run-benchmark to compare performance on your hardware.

Typical results (varies by CPU):

Graph Size Legacy SIMD Parallel
128 nodes 1.5ms 0.2ms (8x) 0.3ms (5x)
256 nodes 12ms 2ms (6x) 1ms (11x)
512 nodes 100ms 15ms (7x) 6ms (16x)

Full Changelog

v2.2.1...v2.3.0

v2.2.1

03 Dec 22:00

Choose a tag to compare

Bug Fixes

Fix stair enter() called every frame (#19)

When an entity traversed a .single mode stair, state.enter() was called every frame, incrementing users_count repeatedly. On the second frame, canEnter() returned false, causing the entity to teleport to a waiting spot.

Fixed by:

  • Check if entity is already using the stair before calling enter()
  • Exit previous stair before entering a new one (multi-floor stairwells)
  • Release stair state on cancelPath() and unregisterEntity()

Improvements

  • Extract releaseStairState() helper to reduce code duplication
  • Add entity ID to debug log messages for better traceability
  • Stricter test assertions for users_count

v2.2.0

03 Dec 21:19

Choose a tag to compare

What's New

Log Level Configuration

Configure logging verbosity via the Config struct:

const Config = struct {
    pub const Entity = u64;
    pub const Context = *Game;
    pub const log_level: pathfinding.LogLevel = .info;  // defaults to .none
};

Available levels: .none, .err, .warning, .info, .debug

Building Example

New run-building example demonstrating multi-floor pathfinding with stairs:

  • Two-floor building layout
  • Entities traversing between floors via stair nodes
  • Uses building connection mode

Changes

  • Add LogLevel enum and comptime configuration
  • Add scoped logging helpers (logErr, logWarn, logInfo, logDebug)
  • Add entity IDs to log messages for debugging
  • Export LogLevel from main pathfinding module
  • Add usage/building_example.zig
  • Add run-building build step

v2.1.0 - Stair Mode for Building Games

03 Dec 20:23

Choose a tag to compare

What's New

Stair Mode for Vertical Connections

This release adds support for 2D building games where vertical movement should only occur at designated stair nodes.

New Features

  • Building Connection Mode - New ConnectionMode.building that creates horizontal connections normally but only creates vertical connections between nodes marked as stairs
  • StairMode Enum - Control traffic on stairs:
    • .none - Not a stair (default, no vertical connections)
    • .all - Multi-lane stair (unlimited concurrent usage)
    • .direction - Directional stair (multiple entities same direction only)
    • .single - Single-file stair (only one entity at a time)
  • Waiting Areas - Define spots where entities wait when stairs are busy, preventing stacking
  • Traffic Management - Runtime stair state tracking with queue-based access control

Example Usage

// Mark nodes as stairs
try engine.setStairMode(stair_bottom, .single);
try engine.setStairMode(stair_top, .single);

// Connect with building mode
try engine.connectNodes(.{
    .building = .{ .horizontal_range = 60, .vertical_range = 120 },
});

// Optional: set waiting areas
try engine.setWaitingArea(stair_bottom, &waiting_spots);

New API Methods

  • setStairMode(node, mode) - Set stair traffic mode
  • getStairMode(node) - Get stair traffic mode
  • setWaitingArea(node, spots) - Define waiting area for stair
  • getStairState(node) - Get runtime stair traffic state

Full Changelog

v2.0.0...v2.1.0

v2.0.0 - PathfindingEngine

03 Dec 18:26

Choose a tag to compare

What's New

This release introduces the PathfindingEngine, a self-contained pathfinding system that owns entity positions internally. This is now the recommended way to use the library.

New Features

  • PathfindingEngine - Complete solution with internal position management

    • Comptime-configurable entity and context types
    • Automatic graph building with connectNodes()
    • Floyd-Warshall precomputed shortest paths
    • Callbacks for path events (node reached, completed, blocked)
  • QuadTree - Spatial partitioning for O(log n) queries

    • getEntitiesInRadius() - Find entities within distance
    • getEntitiesInRect() - Find entities in rectangle
    • getNodesInRadius() - Find nearby waypoints
  • Connection Modes

    • Omnidirectional: For top-down games (connect to N closest neighbors)
    • Directional: For platformers (left/right/up/down connections)

Breaking Changes

  • PathfindingEngine.init() is now fallible (returns !Self)
  • QuadTree.init(), reset(), resetWithBoundaries() are now fallible
  • Old examples replaced with new PathfindingEngine-focused examples

Migration

If you were using Floyd-Warshall or A* directly, they still work unchanged. For new projects, we recommend using PathfindingEngine instead.

const Config = struct {
    pub const Entity = u64;
    pub const Context = *Game;
};

var engine = try pathfinding.PathfindingEngine(Config).init(allocator);

See the README for full documentation.

v1.0.3

30 Nov 04:32

Choose a tag to compare

Full Changelog: v1.0.2...v1.0.3