Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
ShenMian committed Oct 22, 2024
1 parent 1459bb0 commit 87b8d54
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
- [搜索策略 🚧](solver/solving_strategy.md)
- [启发式函数 🚧](solver/heuristic_function.md)
- [优化](solver/optimization.md)
- [隧道]()
- [隧道](solver/tunnels.md)
- [死锁 🚧](solver/deadlocks.md)
- [割点]()
- [双向搜索]()
Expand Down
Binary file added src/solver/assets/tunnel_pattern_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/solver/assets/tunnel_pattern_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 13 additions & 27 deletions src/solver/tunnels.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,31 @@
# 隧道(Tunnels)

TODO: 图片: 分支后又合并, 说明为何无影响力推动可以被跳过.
TODO: 说明何为隧道.

一般情况下, 箱子的移动将产生一个新的状态, 该状态还会包含其他箱子移动所产生的子状态, 这是因为箱子之间可能存在相互影响.
但在部分关卡中, 存在一种被称为**隧道**的结构, 可以将位于隧道内的箱子与隧道外的箱子**隔绝**, 使它们之间互不影响.

![](assets/tunnel.png)
![隧道](assets/tunnel.png)

如上图所示, 当上方的箱子位于隧道时, 两个箱子之间不会产生影响. 此时推动隧道内的箱子被视作**无影响力推动**(No influence pushes).

在有 $n$ 个箱子的关卡中, 每一个状态最多有 $n$ 个子状态. 但如果当前状态是无影响力推动, 则无需产生子状态, 应该继续推动箱子, 直到产生有影响力的推动(一般是该箱子离开隧道), 并产生 1 个子状态.

TODO: 考虑隧道内存在目标的情况

当玩家推动箱子后产生以下模式, 则应该往同方向继续推一次.
TODO: 说明原因

TODO: 是否满足容许性?

```txt
###########
#. $@$ .#
###########
```

## 停放

将箱子推入隧道内的推动是有影响力的, 这意味这将该箱子停放到隧道内, 并为玩家和其他箱子的移动腾出空间.

TODO: 说明隧道中可以停放一个箱子, 在隧道的入口处, 或出口前. 但应该只停靠在入口处, 因为这样更高效. 说明为何更高效.
单个隧道内**最多能停放一个箱子**. 因为隧道中是不存在目标的, 停放多个箱子会产生[畜栏死锁], 进而导致关卡无解.

为了避免[畜栏死锁], 隧道内**最多能停放一个箱子**.
如果将箱子停放在隧道出口处, 则玩家还需要从隧道入口处离开隧道. 而将箱子停放在隧道入口处, 玩家设置无需进入隧道.
隧道内**停放箱子的最佳位置是隧道入口**, 此处的隧道入口指的是距离箱子最近的隧道口.
因为如果停放在隧道的其他位置, 玩家还需要重新返回隧道入口才能离开封闭的隧道, 这意味着玩家需要原路返回, 增加了不必要的移动步数.

如果箱子停留在隧道出口则玩家需要
## 识别

---
若推动后产生了如下的模式(包括旋转和镜像), 则表示箱子已经被推入隧道, 属于无效推动. 此时应该继续推动箱子, 直到箱子离开隧道, 产生具有有效推动的子状态.

若推动后产生了如下的模式, 包括旋转和镜像.
![隧道模式 1](assets/tunnel_pattern_1.png)
![隧道模式 2](assets/tunnel_pattern_2.png)

```txt
#$ #$#
#@# #@#
```
下面是计算隧道的实现, 通过遍历地图, 识别符合 2 种隧道模式(包括镜像和旋转)的位置并进行标记. 计算结果可以被缓存, 以便在后续求解过程中快速判断隧道.

```rs
impl Solver {
Expand Down Expand Up @@ -111,3 +93,7 @@ impl Solver {
```

[畜栏死锁]: deadlocks.md#畜栏死锁corral-deadlocks

## 参考

- <http://sokobano.de/wiki/index.php?title=Solver#Tunnels>.

0 comments on commit 87b8d54

Please sign in to comment.