Skip to content

Commit 694e7e6

Browse files
committed
wip
1 parent 599b723 commit 694e7e6

19 files changed

+1177
-175
lines changed

packages/demo/demo.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[
2-
"interactive",
3-
"getBestRoute",
4-
"getBestTunnel",
5-
"outside",
6-
"getPathToPose",
7-
"getPathTo",
8-
"svg",
9-
"rust",
10-
"rust_astar",
11-
"rust_astar_snake"
2+
"interactive",
3+
"getBestRoute",
4+
"getBestTunnel",
5+
"outside",
6+
"getPathToPose",
7+
"getPathTo",
8+
"svg",
9+
"rust",
10+
"rust_astar",
11+
"rust_astar_snake"
1212
]

packages/demo/demo.rust.ts

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,60 @@ import "./menu";
44
import { grid, snake } from "./sample";
55

66
(async () => {
7-
const api = await import("@snk/solver-r");
8-
9-
const iColorGrid = api.IColorGrid.create(grid.width, grid.height, grid.data);
10-
const iSnake = snakeToCells(snake).map((p) => api.IPoint.create(p.x, p.y));
11-
12-
// const colorGrid = api.get_color_grid_sample(api.SampleGrid.Labyrinthe);
13-
14-
const { canvas, draw, highlightCell } = createCanvas(iColorGrid);
15-
document.body.appendChild(canvas);
16-
draw(iColorGrid, snake, []);
17-
18-
api.greet();
19-
20-
const a = performance.now();
21-
const path = api.solve(iColorGrid, iSnake).reverse();
22-
console.log(performance.now() - a);
23-
24-
{
25-
const snakeLength = snake.length / 2;
26-
27-
const onChange = () => {
28-
const i = +input.value;
29-
const s = createSnakeFromCells(path.slice(i, i + snakeLength).reverse());
30-
31-
draw(iColorGrid, s, []);
32-
33-
for (let j = i + snakeLength; j--; ) {
34-
highlightCell(path[j].x, path[j].y, "#123bde");
35-
}
36-
};
37-
38-
const input = document.createElement("input") as any;
39-
input.type = "range";
40-
input.value = 0;
41-
input.step = 1;
42-
input.min = 0;
43-
input.max = path.length - snakeLength;
44-
input.style.width = "90%";
45-
input.style.padding = "20px 0";
46-
input.addEventListener("input", onChange);
47-
document.body.append(input);
48-
49-
onChange();
50-
}
7+
const {IColorGrid,IPoint,greet,solve} = await import("@snk/solver-r");
8+
greet();
9+
10+
const iColorGrid = IColorGrid.create(grid.width, grid.height, grid.data);
11+
const iSnake = snakeToCells(snake).map((p) => IPoint.create(p.x, p.y));
12+
13+
14+
const { canvas, draw, highlightCell } = createCanvas(iColorGrid);
15+
document.body.appendChild(canvas);
16+
draw(iColorGrid, snake, []);
17+
18+
19+
const a = performance.now();
20+
const path = solve(iColorGrid, iSnake).reverse();
21+
console.log(performance.now() - a);
22+
23+
{
24+
const snakeLength = snake.length / 2;
25+
26+
const onChange = () => {
27+
const i = +input.value;
28+
const s = createSnakeFromCells(path.slice(i, i + snakeLength).reverse());
29+
30+
const g = {
31+
width: iColorGrid.width,
32+
height: iColorGrid.height,
33+
data: new Uint8Array([...iColorGrid.data as any]),
34+
};
35+
for (let j = i; j--; ) {
36+
const { x, y } = path[j];
37+
if (x >= 0 && y >= 0 && x < iColorGrid.width && y < iColorGrid.height) {
38+
const index = x * g.height + y;
39+
g.data[index] = 0;
40+
}
41+
}
42+
43+
draw(g, s, []);
44+
45+
for (let j = i + snakeLength; j--; ) {
46+
highlightCell(path[j].x, path[j].y, "#123bde");
47+
}
48+
};
49+
50+
const input = document.createElement("input") as any;
51+
input.type = "range";
52+
input.value = 0;
53+
input.step = 1;
54+
input.min = 0;
55+
input.max = path.length - snakeLength;
56+
input.style.width = "90%";
57+
input.style.padding = "20px 0";
58+
input.addEventListener("input", onChange);
59+
document.body.append(input);
60+
61+
onChange();
62+
}
5163
})();

packages/demo/demo.rust_astar.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,24 @@ import "./menu";
33
import { grid } from "./sample";
44

55
(async () => {
6-
const api = await import("@snk/solver-r");
6+
const api = await import("@snk/solver-r");
77

8-
const g = api.IGrid.create(grid.width, grid.height, grid.data);
9-
const path = api.iastar(
10-
g,
11-
api.IPoint.create(-1, 0),
12-
api.IPoint.create(47, 4),
13-
);
8+
const g = api.IGrid.create(grid.width, grid.height, grid.data);
9+
const path = api.iastar(
10+
g,
11+
api.IPoint.create(-1, 0),
12+
api.IPoint.create(47, 4),
13+
);
1414

15-
{
16-
const { canvas, draw, highlightCell } = createCanvas(g);
17-
document.body.appendChild(canvas);
15+
{
16+
const { canvas, draw, highlightCell } = createCanvas(g);
17+
document.body.appendChild(canvas);
1818

19-
draw({ width: g.width, height: g.height, data: g.data }, [] as any, []);
19+
draw({ width: g.width, height: g.height, data: g.data }, [] as any, []);
2020

21-
if (path)
22-
for (const p of path) {
23-
highlightCell(p.x, p.y);
24-
}
25-
}
21+
if (path)
22+
for (const p of path) {
23+
highlightCell(p.x, p.y);
24+
}
25+
}
2626
})();

packages/demo/demo.rust_astar_snake.ts

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,44 @@ import "./menu";
44
import { grid, snake } from "./sample";
55

66
(async () => {
7-
const api = await import("@snk/solver-r");
7+
const { IColorGrid, IPoint, get_snake_path,greet } = await import("@snk/solver-r");
88

9-
const g = api.IGrid.create(grid.width, grid.height, grid.data);
10-
const path = api.iastar_snake(
11-
g,
12-
snakeToCells(snake).map((p) => api.IPoint.create(p.x, p.y)),
13-
api.IPoint.create(7, 0),
14-
);
9+
greet();
1510

16-
{
17-
const { canvas, draw, highlightCell } = createCanvas(g);
18-
document.body.appendChild(canvas);
11+
const colorGrid = IColorGrid.create(grid.width, grid.height, grid.data);
1912

20-
draw({ width: g.width, height: g.height, data: g.data }, [] as any, []);
13+
const { canvas, draw, getPointedCell, highlightCell } =
14+
createCanvas(colorGrid);
15+
document.body.appendChild(canvas);
2116

22-
console.log(path);
17+
let end = { x: 5, y: -1 };
18+
const onChange = () => {
19+
const isnake = snakeToCells(snake).map((p) => IPoint.create(p.x, p.y));
2320

24-
if (path)
25-
for (const p of path) {
26-
highlightCell(p.x, p.y);
27-
}
28-
}
21+
const path = get_snake_path(colorGrid, isnake, IPoint.create(end.x, end.y));
22+
23+
24+
draw(
25+
{
26+
width: colorGrid.width,
27+
height: colorGrid.height,
28+
data: colorGrid.data,
29+
},
30+
snake,
31+
[],
32+
);
33+
34+
if (path)
35+
for (const p of path) {
36+
highlightCell(p.x, p.y);
37+
}
38+
};
39+
canvas.addEventListener("mousemove", (e) => {
40+
const p = getPointedCell(e);
41+
if( p.x === end.x && p.y === end.y) return
42+
43+
end = p;
44+
onChange();
45+
});
46+
onChange();
2947
})();

packages/draw/drawSnake.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const drawSnake = (
1616

1717
for (let i = 0; i < cells.length; i++) {
1818
const u = Math.min((i + 1) * 0.6, o.sizeCell * 0.3);
19-
19+
2020
ctx.save();
2121
ctx.fillStyle = o.colorSnake;
2222
ctx.translate(cells[i].x * o.sizeCell + u, cells[i].y * o.sizeCell + u);

packages/solver-r/package.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
2-
"name": "@snk/solver-r",
3-
"version": "1.0.0",
4-
"devDependencies": {
5-
"wasm-pack": "0.13.1"
6-
},
7-
"main": "./pkg/snk_solver_rust.js",
8-
"scripts": {
9-
"build": "wasm-pack build",
10-
"dev": "bunx nodemon --watch src -e rs --exec wasm-pack build"
11-
}
2+
"name": "@snk/solver-r",
3+
"version": "1.0.0",
4+
"devDependencies": {
5+
"wasm-pack": "0.13.1"
6+
},
7+
"main": "./pkg/snk_solver_rust.js",
8+
"scripts": {
9+
"build": "wasm-pack build",
10+
"dev": "bunx nodemon --watch src -e rs --exec wasm-pack build"
11+
}
1212
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use std::collections::{BinaryHeap, HashSet};
2+
3+
use crate::grid::{add, get_distance, Point, DIRECTIONS};
4+
5+
struct Node {
6+
w: usize,
7+
h: usize,
8+
f: usize,
9+
snake: Vec<Point>,
10+
}
11+
12+
impl Eq for Node {}
13+
impl PartialEq for Node {
14+
fn eq(&self, other: &Self) -> bool {
15+
self.snake == other.snake
16+
}
17+
}
18+
impl Ord for Node {
19+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
20+
self.f.cmp(&other.f)
21+
}
22+
}
23+
impl PartialOrd for Node {
24+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
25+
Some(self.cmp(other))
26+
}
27+
}
28+
29+
// the snake is not self locked if it can find a way for this head to reach the current tail position
30+
pub fn is_snake_self_locked<F>(walkable: F, snake: &[Point]) -> bool
31+
where
32+
F: Fn(&Point) -> bool,
33+
{
34+
let end = &snake[snake.len() - 1];
35+
let snake_len = snake.len();
36+
37+
let mut open_list = BinaryHeap::new();
38+
let mut close_list: HashSet<Vec<Point>> = HashSet::new();
39+
40+
open_list.push({
41+
let h = get_distance(&snake[0], &end) as usize;
42+
Node {
43+
snake: snake.to_vec(),
44+
h,
45+
f: h,
46+
w: 0,
47+
}
48+
});
49+
50+
while let Some(node) = open_list.pop() {
51+
for dir in DIRECTIONS {
52+
let next_head = add(&node.snake[0], &dir);
53+
54+
if !walkable(&next_head) {
55+
continue;
56+
}
57+
58+
let head_collide_with_body = (0..snake_len).any(|i| node.snake[i] == next_head);
59+
60+
if head_collide_with_body {
61+
continue;
62+
}
63+
64+
if &next_head == end {
65+
return true;
66+
}
67+
68+
let next_snake = {
69+
let mut snake = node.snake.clone();
70+
snake.insert(0, next_head);
71+
snake.truncate(snake_len);
72+
snake
73+
};
74+
75+
if close_list.contains(&next_snake) {
76+
continue;
77+
}
78+
79+
open_list.push({
80+
let h = get_distance(&next_head, &end) as usize;
81+
let w = node.w + 1;
82+
let f = h + w;
83+
Node {
84+
snake: next_snake,
85+
h,
86+
f,
87+
w,
88+
}
89+
});
90+
}
91+
92+
close_list.insert(node.snake);
93+
}
94+
95+
false
96+
}

packages/solver-r/src/_test_grid_samples.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub enum SampleGrid {
3333
Realistic,
3434
Labyrinthe,
3535
RandomPack,
36+
SolidBlock,
3637
}
3738
pub fn get_grid_sample(g: SampleGrid) -> Grid<Color> {
3839
match g {
@@ -88,5 +89,11 @@ pub fn get_grid_sample(g: SampleGrid) -> Grid<Color> {
8889
);
8990
grid
9091
}
92+
93+
SampleGrid::SolidBlock => {
94+
let mut grid = Grid::<Color>::create(52, 7);
95+
randomly_fill_grid(&mut grid, &[Color::Color1], 92u32);
96+
grid
97+
}
9198
}
9299
}

0 commit comments

Comments
 (0)