diff --git a/src/solver/solver.rs b/src/solver/solver.rs index 47728a7..4f370cc 100644 --- a/src/solver/solver.rs +++ b/src/solver/solver.rs @@ -16,23 +16,29 @@ use std::time::{Duration, Instant}; #[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)] pub enum Strategy { - /// Find any solution + /// Speed priority Fast, + /// Balanced speed and steps + Mixed, + /// Find move optimal solutions with best pushes // FIXME: 结果非最优解, 可能是由于遇到答案就直接返回忽略剩余状态导致的 OptimalMovePush, /// Find push optimal solutions with best moves OptimalPushMove, - - Mixed, } #[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)] pub enum LowerBoundMethod { + /// Minimum push count to nearest target PushCount, + + /// Minimum move count to nearest target MoveCount, + + /// Manhattan distance to nearest target ManhattanDistance, } @@ -201,18 +207,18 @@ impl Solver { } fn calculate_tunnels(&self) -> HashSet<(Vector2, Direction)> { - let mut tunels = HashSet::new(); + let mut tunnels = HashSet::new(); for x in 1..self.level.dimensions.x - 1 { for y in 1..self.level.dimensions.y - 1 { - let position = Vector2::new(x, y); - if !self.level.get_unchecked(&position).intersects(Tile::Floor) - || self.level.get_unchecked(&position).intersects(Tile::Target) + let player_position = Vector2::new(x, y); + if !self + .level + .get_unchecked(&player_position) + .intersects(Tile::Floor) { continue; } - // #$# - // #@# for (up, right, _down, left) in [ Direction::Up, Direction::Right, @@ -225,83 +231,83 @@ impl Solver { .iter() .tuple_windows::<(_, _, _, _)>() { + // #$# + // #@# if self .level - .get_unchecked(&(position + left.to_vector())) + .get_unchecked(&(player_position + left.to_vector())) .intersects(Tile::Wall) && self .level - .get_unchecked(&(position + right.to_vector())) + .get_unchecked(&(player_position + right.to_vector())) .intersects(Tile::Wall) && self .level - .get_unchecked(&(position + up.to_vector() + left.to_vector())) + .get_unchecked(&(player_position + up.to_vector() + left.to_vector())) .intersects(Tile::Wall) && self .level - .get_unchecked(&(position + up.to_vector() + right.to_vector())) + .get_unchecked(&(player_position + up.to_vector() + right.to_vector())) .intersects(Tile::Wall) && self .level - .get_unchecked(&(position + up.to_vector())) + .get_unchecked(&(player_position + up.to_vector())) .intersects(Tile::Floor) + && !self + .level + .get_unchecked(&(player_position + up.to_vector())) + .intersects(Tile::Target) { - tunels.insert((position, *up)); + tunnels.insert((player_position, *up)); } - } - // #$_ _$# - // #@# #@# - // FIXME: Microban #11 - /* - for (up, right, _down, left) in [ - Direction::Up, - Direction::Right, - Direction::Down, - Direction::Left, - Direction::Up, - Direction::Right, - Direction::Down, - ] - .iter() - .tuple_windows::<(_, _, _, _)>() - { - if self + // #$_ _$# + // #@# #@# + if self + .level + .get_unchecked(&(player_position + left.to_vector())) + .intersects(Tile::Wall) + && self .level - .get_unchecked(&(position + left.to_vector())) + .get_unchecked(&(player_position + right.to_vector())) + .intersects(Tile::Wall) + && (self + .level + .get_unchecked(&(player_position + up.to_vector() + right.to_vector())) .intersects(Tile::Wall) && self .level - .get_unchecked(&(position + right.to_vector())) - .intersects(Tile::Wall) - && ((self + .get_unchecked( + &(player_position + up.to_vector() + left.to_vector()), + ) + .intersects(Tile::Floor) + || self .level - .get_unchecked(&(position + up.to_vector() + left.to_vector())) - .intersects(Tile::Wall) + .get_unchecked( + &(player_position + up.to_vector() + right.to_vector()), + ) + .intersects(Tile::Floor) && self .level - .get_unchecked(&(position + up.to_vector() + right.to_vector())) - .intersects(Tile::Floor)) - || (self - .level - .get_unchecked(&(position + up.to_vector() + left.to_vector())) - .intersects(Tile::Floor) - && self - .level - .get_unchecked(&(position + up.to_vector() + right.to_vector())) - .intersects(Tile::Wall))) - && self - .level - .get_unchecked(&(position + up.to_vector())) - .intersects(Tile::Floor) - { - tunels.insert((position, *up)); - } + .get_unchecked( + &(player_position + up.to_vector() + left.to_vector()), + ) + .intersects(Tile::Wall)) + && self + .level + .get_unchecked(&(player_position + up.to_vector())) + .intersects(Tile::Floor) + && !self + .level + .get_unchecked(&(player_position + up.to_vector())) + .intersects(Tile::Target) + { + tunnels.insert((player_position, *up)); } - */ + } } } - tunels + tunnels } #[allow(dead_code)] diff --git a/src/test.rs b/src/test.rs index 96cd3bd..837b0f8 100644 --- a/src/test.rs +++ b/src/test.rs @@ -61,8 +61,8 @@ mod tests { &levels, 0..155, &[ - 35, 87, 92, 96, 97, 98, 107, 108, 110, 113, 116, 121, 122, 137, 138, 142, 144, - 145, 149, 150, 152, 154 + 35, 92, 97, 107, 108, 110, 113, 116, 121, 138, 142, 144, 145, 149, 150, 152, + 154 ], 15 * 2 ) == 0 @@ -78,7 +78,6 @@ mod tests { &levels, 0..100, &[ - 15, // 17, 20, 22, 23, 25, 26, 27, 29, 32, 33, 35, 37, 38, 39, 41, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 66, 67, 68, 70, 71, 72, 73, 75, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 92, 93, 94, 95, 96, 97, 98, 99,