Skip to content

Commit d3a2a18

Browse files
committed
.
1 parent 16b1d9c commit d3a2a18

File tree

4 files changed

+171
-109
lines changed

4 files changed

+171
-109
lines changed

packages/solver-r/src/astar_snake.rs

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::collections::{BinaryHeap, HashSet};
55

66
struct Node {
77
h: usize,
8+
f: usize,
89
path: Vec<Point>,
910
}
1011

@@ -16,9 +17,7 @@ impl PartialEq for Node {
1617
}
1718
impl Ord for Node {
1819
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
19-
let f1 = self.h + self.path.len();
20-
let f2 = other.h + other.path.len();
21-
f1.cmp(&f2)
20+
self.f.cmp(&other.f)
2221
}
2322
}
2423
impl PartialOrd for Node {
@@ -27,7 +26,12 @@ impl PartialOrd for Node {
2726
}
2827
}
2928

30-
pub fn get_snake_path<F>(mut walkable: F, snake: &Snake, end: &Point) -> Option<Vec<Point>>
29+
pub fn get_snake_path<F>(
30+
mut walkable: F,
31+
snake: &[Point],
32+
end: &Point,
33+
max_weight: usize,
34+
) -> Option<Vec<Point>>
3135
where
3236
F: FnMut(&Point) -> bool,
3337
{
@@ -36,14 +40,22 @@ where
3640
let mut open_list = BinaryHeap::new();
3741
let mut close_list: HashSet<Vec<Point>> = HashSet::new();
3842

39-
open_list.push(Reverse(Node {
40-
path: snake.clone(),
41-
h: get_distance(&snake[0], &end) as usize,
43+
open_list.push(Reverse({
44+
let h = get_distance(&snake[0], &end) as usize;
45+
Node {
46+
path: snake.to_vec(),
47+
h,
48+
f: h,
49+
}
4250
}));
4351

4452
while let Some(n) = open_list.pop() {
4553
let node = n.0;
4654

55+
if node.f > max_weight {
56+
return None;
57+
}
58+
4759
for dir in DIRECTIONS {
4860
let next_head = Point {
4961
x: node.path[0].x + dir.x,
@@ -56,16 +68,16 @@ where
5668
continue;
5769
}
5870

71+
if !walkable(&next_head) {
72+
continue;
73+
}
74+
5975
if &next_head == end {
6076
let mut path = node.path.clone();
6177
path.insert(0, next_head);
6278
return Some(path);
6379
}
6480

65-
if !walkable(&next_head) {
66-
continue;
67-
}
68-
6981
let next_path = {
7082
let mut path = node.path.clone();
7183
path.insert(0, next_head);
@@ -78,9 +90,15 @@ where
7890
continue;
7991
}
8092

81-
let h = get_distance(&next_head, &end) as usize;
82-
83-
open_list.push(Reverse(Node { path: next_path, h }));
93+
open_list.push(Reverse({
94+
let h = get_distance(&next_head, &end) as usize;
95+
let f = h + next_path.len() - snake_length;
96+
Node {
97+
path: next_path,
98+
h,
99+
f,
100+
}
101+
}));
84102
}
85103

86104
let snake = {
@@ -102,6 +120,7 @@ fn it_should_find_path() {
102120
|_| true,
103121
&vec![Point { x: 0, y: 0 }, Point { x: -1, y: 0 }],
104122
&Point { x: 3, y: 0 },
123+
10,
105124
);
106125

107126
assert_eq!(
@@ -123,6 +142,7 @@ fn it_should_180_to_find_path() {
123142
|_| true,
124143
&vec![Point { x: 0, y: 0 }, Point { x: -1, y: 0 }],
125144
&Point { x: -2, y: 0 },
145+
10,
126146
);
127147

128148
assert_eq!(

packages/solver-r/src/grid.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,18 @@ impl Grid {
5252
}
5353

5454
pub struct WalkableGrid {
55-
grid: Grid,
56-
wall: Cell,
55+
pub grid: Grid,
56+
walkable: Cell,
5757
}
5858
impl WalkableGrid {
59-
pub fn create(grid: Grid, wall: Cell) -> WalkableGrid {
60-
WalkableGrid { grid, wall }
59+
pub fn create(grid: Grid, walkable: Cell) -> WalkableGrid {
60+
WalkableGrid { grid, walkable }
6161
}
6262
pub fn is_cell_walkable(&self, p: &Point) -> bool {
63-
!self.grid.is_inside(p) || self.grid.get_cell(p) < self.wall
63+
!self.grid.is_inside(p) || self.grid.get_cell(p) <= self.walkable
6464
}
65-
pub fn set_wall(&mut self, wall: Cell) -> () {
66-
self.wall = wall;
65+
pub fn set_walkable(&mut self, walkable: Cell) -> () {
66+
self.walkable = walkable;
6767
}
6868
pub fn is_inside(&self, p: &Point) -> bool {
6969
self.grid.is_inside(p)

packages/solver-r/src/lib.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ mod solver;
88

99
use astar::get_path;
1010
use astar_snake::get_snake_path;
11-
use grid::{Cell, Grid, Point};
11+
use grid::{Cell, Grid, Point, WalkableGrid};
1212
use js_sys;
13+
use snake_walk::get_path_to_eat_all;
1314
use solver::get_free_cells;
1415
use wasm_bindgen::prelude::*;
1516

@@ -90,6 +91,14 @@ impl From<Point> for IPoint {
9091
}
9192
}
9293
}
94+
impl From<&Point> for IPoint {
95+
fn from(value: &Point) -> Self {
96+
Self {
97+
x: value.x,
98+
y: value.y,
99+
}
100+
}
101+
}
93102
impl From<IPoint> for Point {
94103
fn from(value: IPoint) -> Self {
95104
Self {
@@ -141,6 +150,7 @@ pub fn iastar(grid: &IGrid, start: IPoint, end: IPoint) -> Option<js_sys::Array>
141150
#[wasm_bindgen]
142151
pub fn iastar_snake(grid: &IGrid, start: ISnake, end: IPoint) -> Option<js_sys::Array> {
143152
let g = Grid::from(grid.clone());
153+
let snake: Vec<Point> = start.iter().map(Point::from).collect();
144154
let res = get_snake_path(
145155
|p| {
146156
(!g.is_inside(p) || g.get_cell(p) <= Cell::Color1)
@@ -149,9 +159,22 @@ pub fn iastar_snake(grid: &IGrid, start: ISnake, end: IPoint) -> Option<js_sys::
149159
&& -3 <= p.y
150160
&& p.y <= grid.height as i8 + 4)
151161
},
152-
&start.iter().map(Point::from).collect(),
162+
&snake,
153163
&Point::from(end),
164+
200,
154165
);
155166

156167
res.map(|l| l.into_iter().map(IPoint::from).map(JsValue::from).collect())
157168
}
169+
170+
#[wasm_bindgen]
171+
pub fn ieat_free_cells(grid: &IGrid, snake: ISnake) -> Vec<IPoint> {
172+
let grid = WalkableGrid::create(Grid::from(grid.clone()), Cell::Color1);
173+
let snake: Vec<Point> = snake.iter().map(Point::from).collect();
174+
175+
let (free_cells, out) = get_free_cells(&grid.grid, Cell::Color1);
176+
177+
let path = get_path_to_eat_all(&grid, &snake, free_cells);
178+
179+
path.iter().map(IPoint::from).collect()
180+
}

0 commit comments

Comments
 (0)