petergpt/doomql
GitHub: petergpt/doomql
一款完全用 SQLite SQL 驱动游戏逻辑与像素渲染的终端 Doom 风格第一人称射击游戏。
Stars: 32 | Forks: 0
# DOOMQL
### `SELECT * FROM HELL`
**一款可玩的第一人称射击游戏,其帧缓冲区是一个 SQL 查询。**
DOOMQL 源于一个刻意不合常理的问题:如果 SQLite 不只是游戏存储数据的地方,
而是游戏引擎本身,会怎么样?
结果就是一款小型的、原创的 Doom 风格游戏,其中 SQL 掌控了移动、
碰撞、敌人、战斗、进度以及屏幕上的每一个 RGB 像素。这里没有
SVG、浏览器、Canvas 或游戏引擎,且可玩的运行时中不包含任何
Python 图形代码。

## SQL 是如何变成画面的?
对于每一帧,SQL 会读取玩家和地图表,并为每个像素生成一行数据:
```
x y red green blue
40 20 232 240 248
41 20 30 35 45
```
第二个 SQL 视图将这些 RGB 行转换为彩色的 `▀` 终端块。
Python 宿主程序不进行任何绘制:它向 SQLite 提供原始按键、时间和终端大小,
然后原封不动地打印完成的查询结果。
```
player + map tables
↓
SQL simulation and raycasting
↓
frame_pixels(x, y, r, g, b)
↓
render_frame(y, coloured scanline)
↓
terminal
```
完整的可见帧由一条查询返回:
```
SELECT scanline FROM render_frame ORDER BY y;
```
## 游戏玩法
你需要:
- macOS、Linux 或其他类 Unix 环境;Windows 用户可以使用 WSL
- Python 3.11 或更高版本
- SQLite 3.45 或更高版本,且启用了数学函数
- 支持 24 位颜色和 Unicode `▀` 的终端
- 建议至少 80 列 × 33 行
没有任何第三方 Python 依赖。在仓库根目录下,运行:
```
make run
```
游戏会跟随终端的实时大小。放大窗口以获取更多
由 SQL 渲染的像素,或者增大终端字体以使每个像素
在物理上变得更大。
### 操作
| 按键 | 动作 |
|---|---|
| `W` / `S` | 前进 / 后退 |
| `A` / `D` | 向左平移 / 向右平移 |
| `J` / `L` 或方向键 | 向左转 / 向右转 |
| 空格键 | 开火 |
| `E` | 使用 index gate |
| `P` | 暂停 |
| `R` | 死亡或胜利后重启 |
| `Ctrl-C` | 退出 |
### 目标
1. 找到青金相间的 **INDEX TOKEN**。
2. 回到琥珀色的门并按下 `E`。
3. 击败红色的 **DEADLOCK**。
4. 抵达青色的提交传送门。
在此过程中,你会遇到 ORPHAN 敌人、远程 LOCK WAITERS、生命 tuple
和弹药 page。
## 在游玩时观看真实的 SQL
这是展示该项目的最佳方式。在仓库根目录下打开两个
终端。
在第一个终端中,启动游戏:
```
make run
```
在第二个终端中,启动只读的 SQL 审计:
```
make inspect
```

左侧的终端是游戏。右侧的终端读取同一个实时数据库
并显示:
- 实际显示帧的 tick 和分辨率
- 当游戏状态与显示帧匹配时的 `SAME COMMIT=YES`
- 完成的确切渲染查询
- 移动、开火、伤害和状态变化的真实前后数值
- 游戏执行的源代码中确切的负责 SQL
这不是重播、第二次模拟或动画近似。检查器以 `PRAGMA query_only=ON` 打开 SQLite;它无法更改游戏。
没有虚假的指令指针或移动的高亮显示。审计事件在与游戏玩法更改相同的事务中写入,并随之回滚。
使用 `j` / `k` 或 空格 / `b` 滚动 SQL,并使用 `q` 退出检查器。
## 到底有哪些部分是由 SQL 实现的?
| SQL 掌控 | Python 仅负责传输 |
|---|---|
| 按键绑定和输入解释 | 原始终端按键字节 |
| 玩家移动和碰撞 | 单调时间戳 |
| 敌人 AI、战斗和进度 | 终端列和行 |
| 门、拾取物、死亡和胜利 | 固定的 SQL 执行请求 |
| DDA 光线投射和墙壁投影 | 将完成的 SQL 扫描行输出至 stdout |
| Sprite 缩放、深度和遮挡 | 终端模式设置和恢复 |
| 武器、十字准星、效果和 HUD | 没有任何特定于游戏的内容 |
| 每一个最终的 RGB 值和 ANSI 颜色代码 | |
宿主程序刻意不包含任何按键映射、坐标、游戏常量、
颜色、渲染计算或游戏状态决策。测试强制执行了这一
边界。
## 项目布局
```
doomql/
├── sql/ game state, simulation, AI and renderer
├── host/ minimal SQLite and terminal transport
├── tools/ live audit, source browser and preview utilities
├── tests/ gameplay, rendering, determinism and purity tests
├── docs/ technical specification and images
├── .github/ CI and contributor-facing files
├── Makefile
├── LICENSE
└── README.md
```
最重要的两个文件是:
- [`sql/tick.sql`](sql/tick.sql):输入、移动、AI、战斗和进度
- [`sql/003_render.sql`](sql/003_render.sql):光线投射、像素和 ANSI 输出
如需了解完整的设计和纯粹性契约,请阅读
[`docs/SPEC.md`](docs/SPEC.md)。
## 实用命令
| 命令 | 用途 |
|---|---|
| `make run` | 使用持久的 `.doomql/doomql.sqlite` 数据库进行游玩 |
| `make inspect` | 显示实时事务性 SQL 审计 |
| `make reset` | 重置游戏并打印其第一帧 |
| `make demo` | 打印一个由 SQL 生成的帧 |
| `make benchmark` | 测量 SQL tick 和渲染性能 |
| `make verify` | 运行所有测试和命令行冒烟检查 |
| `make clean-db` | 仅删除生成的本地游戏数据库 |
可以通过 `make inspect-source` 和
`make inspect-overview` 获取更深入的可选诊断。
## 验证
```
make verify
```
包含 36 项测试的套件检查了游戏玩法、碰撞、进度、确定性重播、
帧尺寸、RGB 范围、ANSI 解码、只读检查、事务
回滚、确切的运行时源一致性以及 Python 宿主程序中不存在游戏逻辑。它还包括一个严格的本地渲染器延迟门控。
GitHub Actions 在 macOS 和 Linux 上使用受支持的 Python 版本运行独立于硬件的检查。挂钟时间延迟断言保留在本地运行,因为共享虚拟运行器的计时不构成有意义的性能基准。
## 范围和信任
- DOOMQL 是一款原创的 Doom 风格光线投射器,而不是 Doom 移植版。它不包含
任何 Doom 代码、WAD 数据、地图、美术、音频或标志,且不隶属于或
受 id Software 或其发行商的认可。
- 终端执行最终的物理绘制。SQL 计算每一个 RGB
值并发出每一条终端颜色指令;Python 原封不动地写入这些字节。
- 将自定义数据库视为受信任的输入。修改后的数据库可以替换
存储的运行时 SQL 并注入终端文本,因此不要使用 `--db` 打开不受信任的文件。
- 浮点三角函数在 SQLite 和数学库构建版本之间可能会有细微差异,因此仅承诺在同一环境中进行确定性重播。
## 贡献、安全和许可
欢迎在保持由 SQL 掌控的模拟和
渲染边界的前提下做出贡献。在打开拉取请求或报告之前,请阅读[贡献指南](.github/CONTRIBUTING.md)和
[安全策略](.github/SECURITY.md)。
DOOMQL 采用 [MIT 许可证](LICENSE)发布。
标签:FPS, Python, SQL, SQLite, 创意编程, 多线程, 无后门, 游戏开发, 系统审计, 终端游戏, 逆向工具