Skip to content

Commit

Permalink
feat: initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ShenMian committed Mar 2, 2024
0 parents commit 7b2ef39
Show file tree
Hide file tree
Showing 18 changed files with 924 additions and 0 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Test

on:
push:
branches: [main]

env:
CARGO_TERM_COLOR: always

jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}

steps:
- uses: actions/checkout@v4

- name: Setup mdBook
uses: peaceiris/actions-mdbook@v1
with:
mdbook-version: 'latest'

- run: mdbook build

- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: ${{ github.ref == 'refs/heads/main' }}
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./book
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
book
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Sokoban Tutorial

本文将描述如何实现一个推箱子游戏 📦, 代码示例使用 Rust 语言 🦀 编写.

完整的项目代码位于:

- [ShenMian/soukoban](https://github.com/shenmian/soukoban): 推箱子相关算法实现.
- [ShenMian/sokoban-rs](https://github.com/shenmian/sokoban-rs): 推箱子游戏实现, 使用 [Bevy] 引擎.

[bevy]: https://github.com/bevyengine/bevy
10 changes: 10 additions & 0 deletions book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[book]
title = "Sokoban Tutorial"
authors = ["ShenMian <sms_school@outlook.com>"]
language = "cn"
multilingual = false
src = "src"

[output.html]
git-repository-url = "https://github.com/ShenMian/sokoban-tutorial"
git-repository-icon = "fa-github"
13 changes: 13 additions & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Summary

[介绍](introduction.md)

- [关卡](level/README.md)
- [表示](level/representation.md)
- [行程编码](level/run_length_encoding.md)
- [构造](level/construction.md)
- [标准化](level/normalization.md)
- [动作]()
- [求解器](solver/README.md)
- [资源](resources.md)
- [术语表](glossary.md)
Binary file added src/assets/boxworld_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/assets/no_walls_level.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/assets/sasquatch_41.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/assets/steaming_hot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/glossary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# 术语表

| 中文 | 英文 |
| ----------- | -------- |
| 求解器 | solver |
| 解/解决方案 | solution |
24 changes: 24 additions & 0 deletions src/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# 介绍

本文将描述如何实现一个推箱子游戏 📦, 代码示例使用 Rust 语言 🦀 编写.
推箱子游戏具有以下特点:

- 规则简单. 可以专注于实现功能, 而非理解复杂的游戏规则和机制.
- 基本功能易于实现.
- 有具有挑战的高级功能. 比如纯鼠标控制, 逆推等.
- 有需要深入钻研的求解器, 用于自动求解推箱子关卡.

本文将由浅入深的介绍上面功能并提供实现的思路.

本文不会探讨的内容有:

- 推箱子的其他变种. 感兴趣的读者可以自行了解, 可以作为一种拓展.
- Rust 语言本身. 本文中出现的算法适用于其他编程语言. 因为示例代码使用了 Rust 语言, 可能会探讨 Rust 实现该算法的细节, 但不会专门介绍 Rust 语言的特性.
- 游戏引擎.

完整的项目代码位于:

- [ShenMian/soukoban](https://github.com/shenmian/soukoban): 推箱子相关算法实现.
- [ShenMian/sokoban-rs](https://github.com/shenmian/sokoban-rs): 推箱子游戏实现, 使用 [Bevy] 引擎.

[bevy]: https://github.com/bevyengine/bevy
106 changes: 106 additions & 0 deletions src/level/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# 关卡

推箱子关卡使用最广泛的格式为 XSB, 最初由 XSokoban 所使用. 该格式使用 ASCII 字符来表示地图元素, 并支持注释和附加元数据.
以关卡 `Boxworld #1` 为例:

![Boxworld #1](../assets/boxworld_1.png)

其 XSB 格式关卡的数据如下:

```txt
;Level 1
__###___
__#.#___
__#-####
###$-$.#
#.-$@###
####$#__
___#.#__
___###__
Title: Boxworld 1
Author: Thinking Rabbit
```

- 第 1 行, 以 `;` 开头的单行注释.
- 第 2-9 行, 使用 ASCII 字符表示的地图数据.
- 第 10-11 行, 包括关卡标题和作者的元数据.

| ASCII 符号 | 描述 |
| ----------------- | -------------- |
| `<SPACE>`/`-`/`_` | Floor |
| `#` | Wall |
| `$` | Box |
| `.` | Goal |
| `@` | Player |
| `+` | Player on goal |
| `*` | Box on goal |

除了上面的元数据, 还有一种用于多行注释的特殊元数据. 内容通过 `comment:``comment-end:` 包裹.

关卡可能通过行程编码压缩, 详情请参见[行程编码](run_length.md).

## 特殊关卡

### 玩家不可达区域存在箱子

![Sasquatch #41](../assets/sasquatch_41.png)

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

### 存在只有空元素的行

!["Steaming Hot" by David Buchweitz](../assets/steaming_hot.png)

```txt
# #
# # #
# # #
# # #
# # #
# # #
# # #
-
##########
#........####
# $$$$$$$# #
#.$......# #
# $$$$$$ # #
#......$+# #
#$$$$$$$ # #
# ####
##########
```

### 无完整外墙

部分推箱子程序支持无完整外墙的关卡.
在本文中, 这种关卡属于无效关卡. 但可以通过为其添加外墙的方式来转换为有效关卡.

!["No walls" by Rincewind](../assets/no_walls_level.png)

```txt
* ** *
**
**@$.*
**
* ** *
```

## 参考

- <http://sokobano.de/wiki/index.php?title=Level_format>
Loading

0 comments on commit 7b2ef39

Please sign in to comment.