Skip to content

Commit bce2ad2

Browse files
committed
.
1 parent eac4259 commit bce2ad2

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- [优化](solver/optimization.md)
1414
- [隧道]()
1515
- [死锁 🚧](solver/deadlocks.md)
16+
- [死锁 2 🚧](solver/deadlocks_v2.md)
1617
- [割点]()
1718
- [双向搜索 🚧](solver/bidirectional_search.md)
1819
- [特征]()

src/solver/deadlocks_v2.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,48 @@
2626

2727
这类地形变化只会增加墙体, 导致静态死锁区域增加. 因此即使不在地形变化时重新计算也不会导致误报, 但可能导致静态死锁检测不全面.
2828

29+
```rs
30+
pub fn is_static_deadlock(
31+
map: &Map,
32+
box_position: Vector2<i32>,
33+
box_positions: &HashSet<Vector2<i32>>,
34+
visited: &mut HashSet<Vector2<i32>>,
35+
) -> bool {
36+
debug_assert!(box_positions.contains(&box_position));
37+
38+
if !visited.insert(box_position) {
39+
return true;
40+
}
41+
42+
for direction in [
43+
Direction::Up,
44+
Direction::Right,
45+
Direction::Down,
46+
Direction::Left,
47+
]
48+
.windows(3)
49+
{
50+
let neighbors = [
51+
box_position + &direction[0].into(),
52+
box_position + &direction[1].into(),
53+
box_position + &direction[3].into(),
54+
];
55+
for neighbor in &neighbors {
56+
if map[*neighbor].intersects(Tiles::Wall) {
57+
continue;
58+
}
59+
if box_positions.contains(neighbor)
60+
&& is_static_deadlock(map, *neighbor, box_positions, visited)
61+
{
62+
continue;
63+
}
64+
return false;
65+
}
66+
}
67+
true
68+
}
69+
```
70+
2971
## 二分死锁(Bipartite deadlocks)
3072

3173
静态死锁检测的是**指定箱子**能否被推动至目标上, 而二分死锁检测的是箱子能否被推动至**指定目标**上.
@@ -38,6 +80,52 @@
3880

3981
![Freeze deadlock - Sokoban Wiki](assets/freeze_deadlock.png)
4082

83+
```rs
84+
pub fn is_freeze_deadlock(
85+
map: &Map,
86+
box_position: Vector2<i32>,
87+
box_positions: &HashSet<Vector2<i32>>,
88+
visited: &mut HashSet<Vector2<i32>>,
89+
) -> bool {
90+
debug_assert!(box_positions.contains(&box_position));
91+
92+
if !visited.insert(box_position) {
93+
return true;
94+
}
95+
96+
for direction in [
97+
Direction::Up,
98+
Direction::Down,
99+
Direction::Left,
100+
Direction::Right,
101+
]
102+
.chunks(2)
103+
{
104+
let neighbors = [
105+
box_position + &direction[0].into(),
106+
box_position + &direction[1].into(),
107+
];
108+
109+
// Check if any immovable walls on the axis.
110+
if map[neighbors[0]].intersects(Tiles::Wall) || map[neighbors[1]].intersects(Tiles::Wall) {
111+
continue;
112+
}
113+
114+
// Check if any immovable boxes on the axis.
115+
if (box_positions.contains(&neighbors[0])
116+
&& is_freeze_deadlock(map, neighbors[0], box_positions, visited))
117+
|| (box_positions.contains(&neighbors[1])
118+
&& is_freeze_deadlock(map, neighbors[1], box_positions, visited))
119+
{
120+
continue;
121+
}
122+
123+
return false;
124+
}
125+
true
126+
}
127+
```
128+
41129
## 畜栏死锁(Corral deadlocks)
42130

43131
![Corral deadlock - Sokoban Wiki](assets/corral_deadlock.png)

0 commit comments

Comments
 (0)