Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ Refactor origami map #109

Merged
merged 2 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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