Skip to content

Tom-Notch/PoolGameRandomizer

Repository files navigation

PoolGameRandomizer

台球“抽卡”随机器 —— 声明式规则引擎,随时加规则,复杂规则也支持

pre-commit test License: MIT

每杆开球前抽一张“效果牌”,给台球加点花样。原版(poolgamerandomizer.mingfan.uk)把事件、描述、特殊牌写死在几个平行数组里,加规则要改代码。这一版把它换成了声明式规则引擎:规则是数据(JSON),可以在页面里随时增删改、导入导出,并且支持带“持续 / 叠加 / 额外抽牌 / 自定义脚本”等复杂行为的规则。改动只在当前会话生效,不在本地存任何东西,刷新即回到默认。

零构建、纯静态(index.html + styles.css + engine.js + app.js),直接丢到 GitHub Pages / Cloudflare Pages 就能跑,也能本地双击打开。所有游戏逻辑都在 engine.js(不碰 DOM、可单元测试),app.js 只负责把它接到页面上。

玩法

  • 下一杆:按当前概率抽一张牌,展示名称与描述。
  • 概率分布:实时显示每张牌的概率。抽到的普通牌概率会按 decayFactor 衰减(默认 ×0.6),让结果更均匀;特殊牌堆按固定概率触发。
  • 当前生效:持续型效果以“药丸”形式挂在这里,带剩余回合数,可手动移除。
  • 重置概率:恢复初始权重、清空历史与持续效果。
  • 规则编辑器:表单或 JSON 两种方式编辑规则,保存即在当前会话生效(刷新后重置,不写本地存储)。

规则 Schema

一套规则就是一个 JSON 文档,默认内容见 rules.default.json

{
  "version": 1,
  "name": "默认台球规则",
  "settings": {
    "specialDeckProbability": 0.05, // 每次抽牌进入“特殊牌堆”的概率
    "decayFactor": 0.6, // 抽中的普通牌权重 ×= 此值
    "spinCount": 15, // 抽奖动画帧数
    "spinIntervalMs": 80 // 动画帧间隔(ms)
  },
  "rules": [
    {
      "id": "ex-nihilo", // 唯一 id
      "name": "无中生有",
      "description": "抽到时展示给玩家的文字",
      "deck": "normal", // "normal" | "special"
      "weight": 1, // 同一牌堆内的相对权重
      "enabled": true,
      "tags": ["draw"],
      "effect": { "extraDraws": 2, "stackable": true }
    }
  ]
}

effect{} —— 复杂规则

所有字段都可选;不写就是一张“纯展示”的牌。

  • persistent (bool):抽到后作为持续效果挂到“当前生效”区
  • stackable (bool):持续效果是否可叠加(false 时同名只保留一个)
  • maxTurns (int):持续效果最多存在多少个回合(每次顶层抽牌算一回合,到 0 移除)
  • extraDraws (int):抽到后立即追加抽 N 张(实现“无中生有”)
  • repeatLast (bool):重新施加上一张牌的效果(实现“故技重施”)
  • clearAllEffects (bool):立刻清除所有持续效果(实现“无懈可击”)
  • triggers (array):声明式触发器(如犯规打标记),供桌面裁定参考
  • customScript (string):逃生舱,任意 JS 函数体 (ctx) => { ... },见下

customScript —— 任意复杂逻辑

当声明式字段不够用时,直接写一段 JS。它在抽到该牌时执行,ctx 提供:

ctx.rule; // 当前规则对象
ctx.state; // { activeEffects, history, weights, lastDrawn }
ctx.addEffect(rule); // 追加一个持续效果(默认用当前规则)
ctx.removeEffect(uid); // 按 uid 移除
ctx.clearEffects(); // 清空所有持续效果
ctx.drawAgain(n); // 追加抽 n 张
ctx.log(msg); // 在描述区追加一行提示

例:50% 概率再抽一张,否则清场——

if (Math.random() < 0.5) {
  ctx.drawAgain(1);
} else {
  ctx.clearEffects();
  ctx.log("场面清空");
}

⚠️ customScript 会以 new Function 执行,相当于运行你自己写进规则里的代码。仅给可信的人编辑规则;不要导入来路不明的规则文件。

加规则的三种方式

  1. 表单:规则编辑器 → 「+ 新增规则」,填名称/描述/权重,展开「高级效果」勾选行为 → 保存并生效。
  2. JSON:规则编辑器 → 「JSON 编辑」标签,直接改整套 JSON → 应用 JSON。
  3. 文件:导出当前规则为 pool-rules.json,编辑后再导入。

所有改动只在当前会话生效,刷新页面即自动回到默认规则——不写浏览器本地存储(无 cookie / localStorage)。想在会话中重置也可点「恢复默认」。想长期保留自定义规则,用「导出 JSON」存成文件,下次「导入」即可。

本地开发

bash scripts/dev-setup.sh   # 安装并启用 pre-commit 钩子

纯静态、无需构建。本地预览:

python3 -m http.server 8000   # 然后打开 http://localhost:8000

测试

引擎逻辑(engine.js)有一套零依赖单元测试,用 Node 内置 test runner:

node --test        # 或 npm test

CI 在每次 push / PR 上跑测试(.github/workflows/test.yml),Pages 部署以测试通过为前提。

部署

index.html / styles.css / app.js / rules.default.json 作为静态资源发布即可:GitHub Pages(仓库 Settings → Pages → 选分支根目录)、Cloudflare Pages、或任意静态托管。

License

MIT

About

Billiards card-draw randomizer with a declarative rule engine — add rules anytime, complex rules supported. Upgraded fork of poolgamerandomizer.mingfan.uk

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors