Files
HexTrails/labs/airport/README.md
T
toshiocn 79afda0085 feat(airport): draw six equal apron fans instead of strip runways
Sectors are 60-degree wedges from the board centre, tucked against the tray. Radial seams mark the ABCDEF flats. Roll back with git checkout feat/airport-edge-runway.
2026-09-21 17:58:02 +08:00

68 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 六角机场实验室
独立的起降调度原型。前四关是 19 格教学;视觉使用原工程马卡龙方案。不覆盖主线关卡或存档。
## 运行
在项目根目录运行 `npm run dev`,打开 [六角机场](http://localhost:4173/labs/airport/index.html)。静态打包包含本实验目录。设计规则见 [设计文档](../../docs/airport-design.md)。
点击地面飞机起飞,点击场外停机坪上的飞机降落;左右转每次 60°。成功、失败与旋转都消耗一次。灰色轨道不分颜色;来机匹配彩色专用机位。P 标记表示已停好的来机。它再次起飞后,停到实际出口那条边的停机坪,仍需重新停好。
板边轨道一直画到托盘外缘,不伸出棋盘。托盘外是以棋盘中心为焦点的六等分扇形停机坪,对应六条平边;扇形不随底盘旋转。当等待机在当前朝向下接得上同色机位时,提示线从飞机接到盘内通道;旋转时通道会亮灭,据此判断能否进场。
## 关卡证据
所有数据冻结在 `levels.js`。`solution` 是最优免费解,`experience` 是制作意图回放。
| 关卡 | 格子 | 最少操作 | 初始额度 | 体验回放 | 先清全盘再接机最少操作 | 最优解保留原有飞机 |
|---|---:|---:|---:|---:|---:|---:|
| 留一点空间 | 19 | 1 | 3 | 1 | 4 | 3 |
| 同色才停靠 | 19 | 1 | 3 | 1 | 4 | 3 |
| 转一下再接入 | 19 | 2 | 4 | 2 | 5 | 3 |
| 清障再接入 | 19 | 5 | 7 | 5 | 11 | 4 |
| 更大的停机坪 | 37 | 6 | 10 | 6 | 19 | 7 |
| 绕一圈再接入 | 37 | 10 | 14 | 10 | 15 | 5 |
| 空港全景 | 61 | 8 | 12 | 8 | 18 | 10 |
前四关为教学。第 5、6 关是半径 3 的练习关。第 7 关把棋盘放大到半径 4(61 格)。最优性通过统一动作成本 BFS 的完整找到最短路径证明;状态上限或深度上限只返回 unknown。
每关通过空棋盘、六朝向、六边、每色完整结果的无歧义校验。入口侧按端口位置落入的平边扇区归类,名称依次为右上方、右方、右下方、左下方、左方、左上方;角部端口只归一边。来机只能从当前停机坪那条平边进场,画在对应边外侧,不使用正北等罗盘悬停点。
```sh
npm run test:airport
npm run airport:verify
npm run airport:generate
npm run airport:practice
npm run build:airport
```
教学四关生成器使用固定种子 9172026。练习关生成器使用 9172027,追加两个 37 格关与一个 61 格关,不改写前四关。不会在玩家进入页面时随机生成。
## 结构
- `core.js`:纯规则、状态变换、碰撞、原子预占、求解和关卡校验。
- `app.js` / `index.html` / `style.css`:Canvas 棋盘、可访问按钮、六侧等待区和动画。
- `solver-worker.js`:异步检查局面,未完成搜索不冒充已证明死局。
- `rewards.js`:广告适配边界、会话隔离和幂等奖励。
- `levels.js`:冻结关卡、最优解与体验解。
规则层 `transition` 供无动画搜索使用;`AirportGame.begin/finish` 管理动画期间操作锁。降落立即占位,来机起飞立即取消完成状态并更新出口侧,动画完成前该飞机不能再次点击。配置的轨道和机位在运行时固定;编辑它们后须调用 `invalidateCatalogs`,`validateAirportLevel` 已自行刷新缓存。
## 广告与存储边界
尚未接入真实广告 SDK。默认界面明确显示“测试补充”,每次 +5 次,每关最多 3 次,仅用来验证奖励流程。
宿主可在页面模块运行前提供 `window.airportAdProvider = async ({levelId, steps}) => ({id, completed})`。只有真实激励广告完成回调才能返回 `completed: true`;`id` 必须是唯一奖励凭据。取消返回 `completed: false`;失败拒绝 Promise。生产宿主负责验证凭据,本地幂等防重复不替代服务端或 SDK 的奖励校验。
广告期间切关或重来后,旧回调不能给新局加步数;确认死局不提供加步数入口。搜索未知时不保证加步数能解围。
唯一持久化键是 `hex-airport-v1`,保存本实验已完成关卡、上次关卡和音效偏好,不保存正在进行的一局,也不读写原作进度。没有撤销、主动提示、拖动旋转或缩放;原型只保留明确按钮操作。
## 验证范围
自动测试覆盖免费回放、最优与全清成本、六侧唯一性、反向入位、首个阻挡、邻格擦碰、入位末段碰撞、连点抢位、失败扣步、换侧返回、最后一步通关、搜索未知与死局区分、奖励取消/失败/重复/过期回调。
浏览器验证使用真实页面按钮回放三个关卡,另检查短屏布局、失败反馈、补充次数和模态操作。自动测试与模型回放不能证明玩家理解度或广告效果;尚需真人试玩。
完整执行记录与已有仓库问题见 [验收报告](verification.md)。