Skip to content

Commit 623cdfc

Browse files
committed
.
1 parent e4e1196 commit 623cdfc

File tree

4 files changed

+149
-104
lines changed

4 files changed

+149
-104
lines changed

packages/solver-r/src/exitable.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use std::collections::HashSet;
2+
3+
use crate::grid::{Point, WalkableGrid, DIRECTIONS};
4+
5+
pub fn initiate_exitable_with_border(
6+
exitable_cells: &mut HashSet<Point>,
7+
grid: &WalkableGrid,
8+
) -> () {
9+
for x in 0..(grid.grid.width as i8) {
10+
{
11+
let p = Point { x, y: 0 };
12+
if grid.is_cell_walkable(&p) {
13+
exitable_cells.insert(p);
14+
}
15+
}
16+
{
17+
let p = Point {
18+
x,
19+
y: (grid.grid.height as i8) - 1,
20+
};
21+
if grid.is_cell_walkable(&p) {
22+
exitable_cells.insert(p);
23+
}
24+
}
25+
}
26+
for y in 0..(grid.grid.height as i8) {
27+
{
28+
let p = Point { x: 0, y };
29+
if grid.is_cell_walkable(&p) {
30+
exitable_cells.insert(p);
31+
}
32+
}
33+
{
34+
let p = Point {
35+
x: (grid.grid.width as i8) - 1,
36+
y,
37+
};
38+
if grid.is_cell_walkable(&p) {
39+
exitable_cells.insert(p);
40+
}
41+
}
42+
}
43+
}
44+
45+
pub fn propagate_exitable(exitable_cells: &mut HashSet<Point>, grid: &WalkableGrid) -> () {
46+
let mut open_list: Vec<Point> = exitable_cells.iter().map(|p| p.clone()).collect();
47+
48+
while let Some(p) = open_list.pop() {
49+
for dir in DIRECTIONS {
50+
let u = Point {
51+
x: p.x + dir.x,
52+
y: p.y + dir.y,
53+
};
54+
55+
if !exitable_cells.contains(&u) && grid.is_inside(&u) && grid.is_cell_walkable(&u) {
56+
open_list.push(u);
57+
exitable_cells.insert(u);
58+
}
59+
}
60+
}
61+
}

packages/solver-r/src/grid.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
use std::collections::HashSet;
2+
3+
pub const DIRECTION_RIGHT: Point = Point { x: 1, y: 0 };
4+
pub const DIRECTION_LEFT: Point = Point { x: -1, y: 0 };
5+
pub const DIRECTION_UP: Point = Point { x: 0, y: 1 };
6+
pub const DIRECTION_DOWN: Point = Point { x: 0, y: -1 };
7+
pub const DIRECTIONS: [Point; 4] = [
8+
DIRECTION_RIGHT,
9+
DIRECTION_LEFT,
10+
DIRECTION_UP,
11+
DIRECTION_DOWN,
12+
];
13+
114
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
215
pub struct Point {
316
pub x: i8,
@@ -47,7 +60,10 @@ impl Grid {
4760
self.cells[i] = value;
4861
}
4962
pub fn is_inside(&self, p: &Point) -> bool {
50-
p.x >= 0 && p.x < (self.width as i8) && p.y >= 0 && p.y < (self.height as i8)
63+
0 <= p.x && p.x < (self.width as i8) && 0 <= p.y && p.y < (self.height as i8)
64+
}
65+
pub fn is_inside_margin(&self, p: &Point, m: i8) -> bool {
66+
-m <= p.x && p.x < (self.width as i8) + m && -m <= p.y && p.y < (self.height as i8) + m
5167
}
5268
}
5369

@@ -68,22 +84,14 @@ impl WalkableGrid {
6884
pub fn is_inside(&self, p: &Point) -> bool {
6985
self.grid.is_inside(p)
7086
}
87+
pub fn is_inside_margin(&self, p: &Point, margin: i8) -> bool {
88+
self.grid.is_inside_margin(p, margin)
89+
}
7190
pub fn get_cell(&self, p: &Point) -> Cell {
7291
self.grid.get_cell(p)
7392
}
7493
}
7594

76-
pub const DIRECTION_RIGHT: Point = Point { x: 1, y: 0 };
77-
pub const DIRECTION_LEFT: Point = Point { x: -1, y: 0 };
78-
pub const DIRECTION_UP: Point = Point { x: 0, y: 1 };
79-
pub const DIRECTION_DOWN: Point = Point { x: 0, y: -1 };
80-
pub const DIRECTIONS: [Point; 4] = [
81-
DIRECTION_RIGHT,
82-
DIRECTION_LEFT,
83-
DIRECTION_UP,
84-
DIRECTION_DOWN,
85-
];
86-
8795
#[test]
8896
fn it_should_sort_cell() {
8997
assert_eq!(Cell::Empty < Cell::Color1, true);

packages/solver-r/src/lib.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod astar;
22
mod astar_snake;
3+
mod exitable;
34
mod grid;
45
mod snake;
56
mod snake_compact;
@@ -10,6 +11,7 @@ use std::collections::HashSet;
1011

1112
use astar::get_path;
1213
use astar_snake::get_snake_path;
14+
use exitable::{initiate_exitable_with_border, propagate_exitable};
1315
use grid::{Cell, Grid, Point, WalkableGrid};
1416
use js_sys;
1517
use log::info;
@@ -161,16 +163,10 @@ pub fn iastar(grid: &IGrid, start: IPoint, end: IPoint) -> Option<js_sys::Array>
161163

162164
#[wasm_bindgen]
163165
pub fn iastar_snake(grid: &IGrid, start: ISnake, end: IPoint) -> Option<js_sys::Array> {
164-
let g = Grid::from(grid.clone());
166+
let grid = WalkableGrid::create(Grid::from(grid.clone()), Cell::Color1);
165167
let snake: Vec<Point> = start.iter().map(Point::from).collect();
166168
let res = get_snake_path(
167-
|p| {
168-
(!g.is_inside(p) || g.get_cell(p) <= Cell::Color1)
169-
&& (-3 <= p.x
170-
&& p.x <= grid.width as i8 + 4
171-
&& -3 <= p.y
172-
&& p.y <= grid.height as i8 + 4)
173-
},
169+
|p| grid.is_cell_walkable(p) && grid.is_inside_margin(p, 4),
174170
&snake,
175171
&Point::from(end),
176172
200,
@@ -184,10 +180,12 @@ pub fn ieat_free_cells(grid: &IGrid, snake: ISnake) -> Vec<IPoint> {
184180
let grid = WalkableGrid::create(Grid::from(grid.clone()), Cell::Color1);
185181
let snake: Vec<Point> = snake.iter().map(Point::from).collect();
186182

187-
let (free_cells, _) = get_free_cells(&grid.grid, Cell::Color1);
183+
let mut exitable_cells = HashSet::new();
184+
initiate_exitable_with_border(&mut exitable_cells, &grid);
185+
propagate_exitable(&mut exitable_cells, &grid);
188186

189187
let cells_to_eat = {
190-
let mut cells = free_cells.clone();
188+
let mut cells = exitable_cells.clone();
191189
cells.retain(|p| grid.get_cell(p) == Cell::Color1);
192190
cells
193191
};
@@ -196,8 +194,9 @@ pub fn ieat_free_cells(grid: &IGrid, snake: ISnake) -> Vec<IPoint> {
196194
// to_eat.insert(Point { x: 6, y: 6 });
197195
// to_eat.insert(Point { x: 5, y: 0 });
198196

199-
// let path = get_path_to_eat_all(&grid, &snake, &to_eat);
200-
let path = get_path_to_eat_all(&grid, &snake, &cells_to_eat);
197+
let (path, unreachable) = get_path_to_eat_all(&grid, &snake, &cells_to_eat);
198+
199+
log::info!("unreachable {:?}", unreachable);
201200

202201
path.iter().map(IPoint::from).collect()
203202
}

0 commit comments

Comments
 (0)