Skip to content

Commit

Permalink
♻️ Refactor origami map (#109)
Browse files Browse the repository at this point in the history
  • Loading branch information
bal7hazar authored Oct 8, 2024
1 parent b0777e0 commit 9b881fd
Show file tree
Hide file tree
Showing 11 changed files with 347 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use core::dict::{Felt252Dict, Felt252DictTrait};

// Internal imports

use origami_map::finders::finder::Finder;
use origami_map::helpers::heap::{Heap, HeapTrait};
use origami_map::helpers::bitmap::Bitmap;
use origami_map::helpers::seeder::Seeder;
Expand Down Expand Up @@ -70,7 +71,7 @@ pub impl Astar of AstarTrait {
};

// [Return] The path from the start to the target
Self::path(ref heap, start, target)
Finder::path_with_heap(ref heap, start, target)
}

/// Check if the position can be visited in the specified direction.
Expand Down Expand Up @@ -123,9 +124,9 @@ pub impl Astar of AstarTrait {
fn assess(
width: u8, neighbor_position: u8, current: Node, target: Node, ref heap: Heap<Node>,
) {
let distance = Self::heuristic(current.position, neighbor_position, width);
let distance = Finder::manhattan(current.position, neighbor_position, width);
let neighbor_gcost = current.gcost + distance;
let neighbor_hcost = Self::heuristic(neighbor_position, target.position, width);
let neighbor_hcost = Finder::manhattan(neighbor_position, target.position, width);
let mut neighbor = match heap.get(neighbor_position.into()) {
Option::Some(node) => node,
Option::None => NodeTrait::new(
Expand All @@ -141,58 +142,6 @@ pub impl Astar of AstarTrait {
return heap.update(neighbor);
}
}

/// Compute the heuristic cost between two positions.
/// # Arguments
/// * `position` - The current position
/// * `target` - The target position
/// * `width` - The width of the grid
/// # Returns
/// * The heuristic cost between the two positions
#[inline]
fn heuristic(position: u8, target: u8, width: u8) -> u16 {
let (x1, y1) = (position % width, position / width);
let (x2, y2) = (target % width, target / width);
let dx = if x1 > x2 {
x1 - x2
} else {
x2 - x1
};
let dy = if y1 > y2 {
y1 - y2
} else {
y2 - y1
};
(dx + dy).into()
}

/// Reconstruct the path from the target to the start.
/// # Arguments
/// * `heap` - The heap of nodes
/// * `start` - The starting node
/// * `target` - The target node
/// # Returns
/// * The span of positions from the target to the start
#[inline]
fn path(ref heap: Heap<Node>, start: Node, target: Node) -> Span<u8> {
// [Check] The heap contains the target
let mut path: Array<u8> = array![];
match heap.get(target.position) {
Option::None => { path.span() },
Option::Some(mut current) => {
// [Compute] Reconstruct the path from the target to the start
loop {
if current.position == start.position {
break;
}
path.append(current.position);
current = heap.at(current.source);
};
// [Return] The path from the start to the target
path.span()
},
}
}
}

#[cfg(test)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
use core::dict::{Felt252Dict, Felt252DictTrait};

// Internal imports
use origami_map::helpers::astar::Astar;
use origami_map::finders::finder::Finder;
use origami_map::helpers::bitmap::Bitmap;
use origami_map::helpers::seeder::Seeder;
use origami_map::types::node::{Node, NodeTrait};
use origami_map::types::direction::{Direction, DirectionTrait};


/// BFS implementation for pathfinding
/// BreadthFirstSearch implementation for pathfinding
#[generate_trait]
pub impl BFS of BFSTrait {
/// Searches for a path from 'from' to 'to' on the given grid using BFS
pub impl BreadthFirstSearch of BreadthFirstSearchTrait {
/// Searches for a path from 'from' to 'to' on the given grid using BreadthFirstSearch
///
/// # Arguments
/// * `grid` - The grid represented as a felt252
Expand Down Expand Up @@ -42,7 +42,7 @@ pub impl BFS of BFSTrait {
let mut parents: Felt252Dict<u8> = Default::default();
visited.insert(start.position.into(), true);

// [Compute] BFS until the target is reached or queue is empty
// [Compute] BreadthFirstSearch until the target is reached or queue is empty
let mut path_found = false;
while let Option::Some(current) = queue.pop_front() {
// [Check] Stop if we reached the target
Expand All @@ -55,7 +55,7 @@ pub impl BFS of BFSTrait {
let mut directions = DirectionTrait::compute_shuffled_directions(seed);
while directions != 0 {
let direction = DirectionTrait::pop_front(ref directions);
if Astar::check(grid, width, height, current.position, direction, ref visited) {
if Finder::check(grid, width, height, current.position, direction, ref visited) {
let neighbor_position = direction.next(current.position, width);
parents.insert(neighbor_position.into(), current.position);
let neighbor = NodeTrait::new(neighbor_position, current.position, 0, 0);
Expand All @@ -69,31 +69,14 @@ pub impl BFS of BFSTrait {
if !path_found {
return array![].span();
};
Self::path(parents, start, target)
}

/// Reconstructs the path from start to target using the parents dictionary
#[inline]
fn path(mut parents: Felt252Dict<u8>, start: Node, target: Node) -> Span<u8> {
let mut path: Array<u8> = array![];
let mut current = target.position;

loop {
if current == start.position {
break;
}
path.append(current);
current = parents.get(current.into());
};

path.span()
Finder::path_with_parents(ref parents, start, target)
}
}

#[cfg(test)]
mod test {
// Local imports
use super::BFS;
use super::BreadthFirstSearch;

#[test]
fn test_bfs_search_small() {
Expand All @@ -105,7 +88,7 @@ mod test {
let height = 3;
let from = 0;
let to = 8;
let path = BFS::search(grid, width, height, from, to);
let path = BreadthFirstSearch::search(grid, width, height, from, to);
assert_eq!(path, array![8, 7, 6, 3].span());
}

Expand All @@ -119,7 +102,7 @@ mod test {
let height = 3;
let from = 0;
let to = 8;
let path = BFS::search(grid, width, height, from, to);
let path = BreadthFirstSearch::search(grid, width, height, from, to);
assert_eq!(path, array![].span());
}

Expand All @@ -134,7 +117,7 @@ mod test {
let height = 4;
let from = 0;
let to = 14;
let path = BFS::search(grid, width, height, from, to);
let path = BreadthFirstSearch::search(grid, width, height, from, to);
assert_eq!(path, array![14, 15, 11, 7, 6, 5, 4].span());
}

Expand All @@ -148,7 +131,7 @@ mod test {
let height = 2;
let from = 0;
let to = 1;
let path = BFS::search(grid, width, height, from, to);
let path = BreadthFirstSearch::search(grid, width, height, from, to);
assert_eq!(path, array![1].span());
}

Expand All @@ -164,7 +147,7 @@ mod test {
let height = 4;
let from = 0;
let to = 19;
let path = BFS::search(grid, width, height, from, to);
let path = BreadthFirstSearch::search(grid, width, height, from, to);
assert_eq!(path, array![19, 18, 13, 12, 11, 6, 1].span());
}

Expand All @@ -177,7 +160,7 @@ mod test {
let height = 1;
let from = 0;
let to = 5;
let path = BFS::search(grid, width, height, from, to);
let path = BreadthFirstSearch::search(grid, width, height, from, to);
assert_eq!(path, array![5, 4, 3, 2, 1].span());
}

Expand All @@ -192,7 +175,7 @@ mod test {
let height = 3;
let from = 0;
let to = 8;
let path = BFS::search(grid, width, height, from, to);
let path = BreadthFirstSearch::search(grid, width, height, from, to);
assert_eq!(path, array![].span());
}
}
Loading

0 comments on commit 9b881fd

Please sign in to comment.