From 34d5617f54ac0b4b703ff1e0fac2cc00ce315cbb Mon Sep 17 00:00:00 2001 From: platane Date: Sun, 23 Mar 2025 13:45:30 +0100 Subject: [PATCH] . --- packages/demo/demo.rust.ts | 2 - packages/solver-r/Cargo.lock | 12 +++++ packages/solver-r/Cargo.toml | 2 + packages/solver-r/src/lib.rs | 3 ++ packages/solver-r/src/solver.rs | 85 ++++++++++++++++++++++++--------- 5 files changed, 79 insertions(+), 25 deletions(-) diff --git a/packages/demo/demo.rust.ts b/packages/demo/demo.rust.ts index addbcb9..a42f4e6 100644 --- a/packages/demo/demo.rust.ts +++ b/packages/demo/demo.rust.ts @@ -9,8 +9,6 @@ import { grid } from "./sample"; const freeCells = api.iget_free_cell(g); - console.log(freeCells); - { const { canvas, draw, highlightCell } = createCanvas(g); document.body.appendChild(canvas); diff --git a/packages/solver-r/Cargo.lock b/packages/solver-r/Cargo.lock index 96116fa..6cc47fb 100644 --- a/packages/solver-r/Cargo.lock +++ b/packages/solver-r/Cargo.lock @@ -33,6 +33,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "console_log" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f" +dependencies = [ + "log", + "web-sys", +] + [[package]] name = "js-sys" version = "0.3.77" @@ -109,7 +119,9 @@ name = "snk-solver-rust" version = "1.0.0" dependencies = [ "console_error_panic_hook", + "console_log", "js-sys", + "log", "wasm-bindgen", "wasm-bindgen-test", ] diff --git a/packages/solver-r/Cargo.toml b/packages/solver-r/Cargo.toml index 98ff911..a352258 100644 --- a/packages/solver-r/Cargo.toml +++ b/packages/solver-r/Cargo.toml @@ -13,6 +13,8 @@ default = ["console_error_panic_hook"] [dependencies] wasm-bindgen = "0.2.100" js-sys = "0.3.77" +console_log = "1.0.0" +log = "0.4" # The `console_error_panic_hook` crate provides better debugging of panics by # logging them with `console.error`. This is great for development, but requires diff --git a/packages/solver-r/src/lib.rs b/packages/solver-r/src/lib.rs index 98179bb..3bb6bec 100644 --- a/packages/solver-r/src/lib.rs +++ b/packages/solver-r/src/lib.rs @@ -6,6 +6,9 @@ use js_sys; use solver::get_free_cell; use wasm_bindgen::prelude::*; +use log::info; +use log::Level; + #[wasm_bindgen] extern "C" { fn alert(s: &str); diff --git a/packages/solver-r/src/solver.rs b/packages/solver-r/src/solver.rs index c2e0cc4..7b82049 100644 --- a/packages/solver-r/src/solver.rs +++ b/packages/solver-r/src/solver.rs @@ -6,13 +6,21 @@ pub fn get_free_cell(grid: &Grid, walkable: Cell) -> HashSet { let mut free: HashSet = HashSet::new(); let mut open_list: HashSet = HashSet::new(); - for x in -1..((grid.width as i8) + 1) { + for x in 0..(grid.width as i8) { open_list.insert(Point { x, y: 0 }); open_list.insert(Point { x, y: (grid.height as i8) - 1, }); } + for y in 0..(grid.height as i8) { + open_list.insert(Point { x: 0, y }); + open_list.insert(Point { + x: (grid.width as i8) - 1, + y, + }); + } + open_list.retain(|p| grid.get_cell(&p) <= walkable); let directions = [ Point { x: 1, y: 0 }, @@ -24,25 +32,9 @@ pub fn get_free_cell(grid: &Grid, walkable: Cell) -> HashSet { while let Some(p) = open_list.iter().next().cloned() { open_list.remove(&p); - let exit_count: u8 = directions.iter().fold(0, |sum, dir| { - let neighbour = Point { - x: p.x + dir.x, - y: p.y + dir.y, - }; - - if !grid.is_inside(&neighbour) { - sum + 2 - } else if free.contains(&neighbour) { - sum + 1 - } else { - sum - } - }); - - if exit_count >= 2 { - if grid.is_inside(&p) && grid.get_cell(&p) <= walkable { - free.insert(p); - } + let has_enough_free_exits = { + let mut exit_count = 0; + let mut visited: HashSet = HashSet::new(); for dir in directions { let neighbour = Point { @@ -50,9 +42,56 @@ pub fn get_free_cell(grid: &Grid, walkable: Cell) -> HashSet { y: p.y + dir.y, }; - if grid.is_inside(&neighbour) - && (grid.get_cell(&neighbour) <= walkable) - && !free.contains(&neighbour) + if !visited.contains(&neighbour) + && (free.contains(&neighbour) || !grid.is_inside(&neighbour)) + { + visited.insert(neighbour); + exit_count += 1; + } + + if grid.is_inside(&neighbour) && grid.get_cell(&neighbour) <= walkable { + for alt in [-1, 1] { + let corner = { + if neighbour.x != 0 { + Point { + x: neighbour.x, + y: neighbour.y + alt, + } + } else { + Point { + x: neighbour.x + alt, + y: neighbour.y, + } + } + }; + + if !visited.contains(&neighbour) + && !visited.contains(&corner) + && (free.contains(&corner) || !grid.is_inside(&corner)) + { + visited.insert(neighbour); + visited.insert(corner); + exit_count += 1; + } + } + } + } + + exit_count >= 2 + }; + + if has_enough_free_exits { + free.insert(p); + + for dir in directions { + let neighbour = Point { + x: p.x + dir.x, + y: p.y + dir.y, + }; + + if !free.contains(&neighbour) + && grid.is_inside(&neighbour) + && grid.get_cell(&neighbour) <= walkable { open_list.insert(neighbour); }