pathforge

A MoonBit graph search and grid pathfinding toolkit with BFS, Dijkstra and A*.

pathfinding
graph
astar
dijkstra
bfs
moon add Deviaana/pathforge@0.1.0
Download zip
Author
Version
0.1.0
License
MIT
Last updated
28 days ago
Downloads
2
README

#PathForge

PathForge is a lightweight MoonBit graph search and grid pathfinding toolkit. It packages reusable data structures and algorithms for route planning, game AI, algorithm teaching, and WebAssembly demos.

#Features

  • Directed weighted graph based on adjacency lists
  • BFS for shortest paths by hop count
  • Dijkstra for minimum-cost paths with non-negative edge costs
  • A* with custom heuristics and node reopening for admissible inconsistent heuristics
  • Grid adapter with blocked cells and terrain movement costs
  • Unified PathReport result type with found status, cost, visited count, and path data
  • Unit tests, coverage-ready CI, and a command-line demo

#Project Layout

. |-- graph.mbt # Graph, BFS, Dijkstra, A* |-- grid.mbt # Grid pathfinding adapter |-- priority_queue.mbt # Min-priority queue |-- path_report.mbt # Search result type |-- pathforge_test.mbt # Unit tests |-- cmd/main/main.mbt # Demo entry point |-- docs/api.md # Public API reference |-- docs/application.md # Project application notes |-- moon.mod # MoonBit module metadata `-- moon.pkg # Root package config

#Quick Start

Install MoonBit, then run:

moon check moon test moon run cmd/main

Expected demo output:

PathForge demo found: true cost: 15 visited: 29 path length: 16

#Example

let grid = @pathforge.Grid::new(8, 5)
grid.set_blocked(@pathforge.Point::{ x: 2, y: 0 }, true)
grid.set_blocked(@pathforge.Point::{ x: 2, y: 1 }, true)

let result = grid.astar(
@pathforge.Point::{ x: 0, y: 0 },
@pathforge.Point::{ x: 7, y: 4 },
)
println("found: \{result.found}")
println("cost: \{result.cost}")

#API Documentation

See docs/api.md for the public API reference.

#Publishing

The module metadata in moon.mod includes mooncakes.io fields: license, keywords, repository, description, and homepage.

Before publishing:

moon check --deny-warn moon test moon coverage analyze -- -f summary moon package moon publish

#License

MIT. See LICENSE.

#
Edge

pub(all) struct Edge {
to : Int
cost : Int
}

#
Graph

pub(all) struct Graph {
adj : Array[Array[Edge]]
}

#
Graph::add_edge

fn Graph::add_edge(self : Graph, from : Int, to : Int, cost : Int) -> Unit

#
Graph::add_node

fn Graph::add_node(self : Graph) -> Int

#
Graph::add_undirected_edge

fn Graph::add_undirected_edge(self : Graph, a : Int, b : Int, cost : Int) -> Unit

#
Graph::astar

fn Graph::astar(self : Graph, start : Int, goal : Int, heuristic : (Int, Int) -> Int) -> PathReport

#
Graph::bfs

fn Graph::bfs(self : Graph, start : Int, goal : Int) -> PathReport

#
Graph::dijkstra

fn Graph::dijkstra(self : Graph, start : Int, goal : Int) -> PathReport

#
Graph::has_path

fn Graph::has_path(self : Graph, start : Int, goal : Int) -> Bool

#
Graph::in_bounds

fn Graph::in_bounds(self : Graph, node : Int) -> Bool

#
Graph::neighbors

fn Graph::neighbors(self : Graph, node : Int) -> Array[Edge]

#
Graph::new

fn Graph::new(size : Int) -> Graph

#
Graph::node_count

fn Graph::node_count(self : Graph) -> Int

#
Graph::reachable_count

fn Graph::reachable_count(self : Graph, start : Int) -> Int

#
Grid

pub(all) struct Grid {
width : Int
height : Int
blocked : Array[Bool]
weights : Array[Int]
}

#
Grid::astar

fn Grid::astar(self : Grid, start : Point, goal : Point) -> PathReport

#
Grid::bfs

fn Grid::bfs(self : Grid, start : Point, goal : Point) -> PathReport

#
Grid::bidirectional_bfs

fn Grid::bidirectional_bfs(self : Grid, start : Point, goal : Point) -> PathReport

#
Grid::cost_at

fn Grid::cost_at(self : Grid, p : Point) -> Int

#
Grid::dijkstra

fn Grid::dijkstra(self : Grid, start : Point, goal : Point) -> PathReport

#
Grid::index

fn Grid::index(self : Grid, p : Point) -> Int

#
Grid::inside

fn Grid::inside(self : Grid, p : Point) -> Bool

#
Grid::is_blocked

fn Grid::is_blocked(self : Grid, p : Point) -> Bool

#
Grid::new

fn Grid::new(width : Int, height : Int) -> Grid

#
Grid::point

fn Grid::point(self : Grid, index : Int) -> Point

#
Grid::set_blocked

fn Grid::set_blocked(self : Grid, p : Point, value : Bool) -> Unit

#
Grid::set_cost

fn Grid::set_cost(self : Grid, p : Point, cost : Int) -> Unit

#
Grid::to_graph

fn Grid::to_graph(self : Grid) -> Graph

#
PathReport

pub(all) struct PathReport {
found : Bool
cost : Int
visited : Int
path : Array[Int]
}

#
PathReport::first

fn PathReport::first(self : PathReport) -> Int?

#
PathReport::is_empty

fn PathReport::is_empty(self : PathReport) -> Bool

#
PathReport::last

fn PathReport::last(self : PathReport) -> Int?

#
PathReport::length

fn PathReport::length(self : PathReport) -> Int

#
PathReport::not_found

fn PathReport::not_found(visited : Int) -> PathReport

#
PathReport::single

fn PathReport::single(node : Int) -> PathReport

#
PathReport::success

fn PathReport::success(cost : Int, visited : Int, path : Array[Int]) -> PathReport

#
Point

pub(all) struct Point {
x : Int
y : Int
}

#
PriorityQueue

pub(all) struct PriorityQueue {
data : Array[QueueItem]
}

#
PriorityQueue::is_empty

fn PriorityQueue::is_empty(self : PriorityQueue) -> Bool

#
PriorityQueue::length

fn PriorityQueue::length(self : PriorityQueue) -> Int

#
PriorityQueue::new

#
PriorityQueue::pop

#
PriorityQueue::push

fn PriorityQueue::push(self : PriorityQueue, node : Int, priority : Int) -> Unit

#
QueueItem

pub(all) struct QueueItem {
node : Int
priority : Int
}

Powered by MoonBit

Site sourceReport issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io