puradox/tinhorn

GitHub: puradox/tinhorn

一款带物理引擎模拟和实时合成音效的终端骰子滚轮工具,支持丰富的 TTRPG 骰子记法与脚本化单次输出。

Stars: 1 | Forks: 0

tinhorn — a terminal window running tinhorn, an amber die for a cursor, and the reply: a dice cup for your terminal

crates.io downloads CI license: MIT OR Apache-2.0

走过路过不要错过:一个带有真正铁罐摇晃声的终端骰子 roller—— 骰子落在哪儿就是哪儿。朋友,袖子里可没藏猫腻:设置随机种子 (`--seed 42`),就能看着同一次投掷结果出现两次。 ![tinhorn: 输入 2d20kh1 vs 15,摇晃骰盅,在峰值释放,最终掷出一个自然 20 —— 成功高出 5 点](https://raw.githubusercontent.com/puradox/tinhorn/main/docs/demo.gif) 看这一切要花你多少钱?一分钱都不收! - **真实的物理竞技场。** 骰子会被抛掷、弹跳、相互碰撞,并从彼此的背上滚落。 - **你的投掷。** 摇晃骰盅并在峰值时接住进度条。用力掷出去吧! - **设定赌注。** 喊出你的数字——`d20+5 vs 15`——竞技场会给出判定,包括胜负差。在你下注前,统计面板会给你公平的赔率。 - **凭空而生的声音。** 每一声咔哒、碰撞和沉闷的敲击声,都是由产生撞击的瞬间实时合成的。现场没有任何采样音频文件。 - **[花式记法。](#dice-notation)** 优势(Advantage)、丢弃最低值(drop-the-lowest)、爆炸骰子(exploding dice)、乘数——应有尽有。 - **[单次模式](#scripting-one-shot-mode)**,专为快速博彩而生。 ## 安装说明 你需要一个 [Rust 工具链](https://rustup.rs)。在 Linux 上,声音功能需要 ALSA 头文件才能构建(macOS 和 Windows 不需要额外安装): ``` sudo apt install libasound2-dev pkg-config # Debian/Ubuntu sudo dnf install alsa-lib-devel # Fedora ``` 然后从 crates.io 安装: ``` cargo install tinhorn ``` 如果你的手指头偏偏喜欢老办法:`alias roll=tinhorn`。 ## 运行 ``` tinhorn # start empty, type an expression tinhorn 3d6 # roll 3d6 the moment it opens tinhorn "d6+d8" # quote anything with shell-special characters tinhorn --mute # start silent (Ctrl-Q toggles at runtime) ``` ## 快捷键 | 按键 | 动作 | | ---------------------- | ------------------------------------------------- | | `Enter` | 根据模式掷骰(摇晃:再次按下来投掷) | | `Tab` | 切换模式 — 摇晃 → 投掷 → 瞬间 | | 输入 / `Backspace` | 编辑骰子表达式 | | `←` `→` (`Home`/`End`) | 在表达式中移动光标(跳转至首尾) | | `↑` `↓` | 滚动高于屏幕的打开面板 | | `?` | 切换骰子记法帮助覆盖层 | | `Ctrl-H` | 切换掷骰历史面板 | | `Ctrl-S` | 切换统计面板 | | `Ctrl-Q` | 静音 / 取消静音 — Q 代表安静(quiet) | | `Esc` / `Ctrl-C` | 退出(`Esc` 会先关闭面板或停止摇晃) | 三种掷骰模式通过 `Tab` 循环切换:**摇晃**(放入骰盅并接住力量进度条),**投掷**(骰子直接翻滚入场),以及**瞬间**(瞬间落地并计算总和)。 ## 骰子记法 一次掷骰是由**骰子项**和可选的**平坦修正值**按任意组合构成的序列。各项之间可以通过 `+`、`,`、空格分隔,或者直接连在一起书写。 | 输入 | 含义 | | ------------- | --------------------------------- | | `3d6` | 三个六面骰 | | `d%` | 百分比骰 — `d100` 的简写形式 | | `d6+d8` | 一个 d6 和一个 d8 | | `2d20-1` | 两个 d20 带有 −1 修正值 | | `d20+5 vs 15` | 带赌注:总数 ≥ 15 即为成功 | `d6` 表示 `1d6`。数量有上限(≤ 60 个骰子,≤ 1000 个面),这样手滑输入 `999d99999` 也不会卡死渲染器。`vs` 目标必须放在最后面——`d20 vs 4d6` 是一个错误,而不是什么惊喜——而且每次掷骰至多只能有一个目标。 ### 单骰修正值 一个骰子项可以带有写在 `dN` 正后方的修正值。它们按照池子顺序执行——**爆炸 → 保留/丢弃 → 乘以**——并且可以叠加。 | 输入 | 含义 | | ----------- | --------------------------------------------------- | | `2d20kh1` | **优势** — 掷两个 d20,保留最高的 1 个 | | `2d20kl1` | **劣势** — 保留最低的 1 个 | | `4d6dl1` | 丢弃最低的 1 个(经典的能力值掷骰) | | `4d6dh1` | 丢弃最高的 1 个 | | `3d6!` | **爆炸** — 掷出最大面值时再掷一个(可重复) | | `d10!>8` | 在任何 `> 8` 的面值上爆炸(`<` 和 `=` 也适用) | | `4d6*2` | 将_该项的_保留总和乘以 2 | | `4d6!kh3*2` | 叠加使用:先爆炸,保留最好的 3 个,然后翻倍 | `kh`/`kl`/`dh`/`dl` 默认为 1(`2d20kh` = `2d20kh1`)并根据池子大小进行截断。被丢弃的骰子依然会被掷出并四处弹跳——你可以亲眼看着优势(advantage)丢弃掉较低的 d20——但它们在渲染时会变暗,且不计入总数。 爆炸会实时展现:一个_停_在符合条件面值上的骰子会向竞技场中再掉落一个骰子,而这个骰子也可以继续爆炸——每项最多额外增加 40 个骰子,这样 `d2!` 就不会无限制地增长。乘数只绑定其所属的项:在 `3d6*2 + d8` 中,只有 d6 的总和会翻倍。 ## 脚本化(单次模式) 使用输出标志时——或者只要 stdout 不是终端时——`tinhorn` 会跳过动画,仅评估一次掷骰,打印结果并退出,因此可以直接放入脚本和 pipeline 中: ``` tinhorn -p 3d6 # 13 (just the total) tinhorn 3d6 | cat # 13 (piped stdout → one-shot automatically) total=$(tinhorn -p 2d20kh1) # capture it in a variable tinhorn --seed 42 4d6dl1 # reproducible: the same seed always rolls the same dice tinhorn -v 4d6dl1+2 # a full breakdown (dropped dice in [brackets]) tinhorn --json 2d20kh1+3 # machine-readable for jq & friends tinhorn -p d20+4 vs 14 && echo "the potion works" # the exit code IS the check ``` 在 `-p`/`-v` 模式下,带赌注的掷骰在成功时退出码为 0,失败时为 1,这样脚本就可以基于检定结果本身进行分支;`--json` 和管道输出始终以 0 退出,而解析错误会输出到 stderr 并以 2 退出。 `--json` 输出包含每个骰子及其标志、各项的小计、平坦修正值、总和,以及——在带有赌注时——`target`、`success` 和 `margin`。 ## 许可证 根据以下任一许可证授权 - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) 或 ) - MIT license ([LICENSE-MIT](LICENSE-MIT) 或 ) 由你选择。 除非你明确声明,否则根据 Apache-2.0 许可证的定义,你为包含在本作品中而故意提交的任何贡献,均应按上述方式进行双重许可,不附加任何额外的条款或条件。
标签:Rust, 可视化界面, 掷骰子, 桌面游戏, 物理引擎, 终端UI, 网络流量审计, 通知系统, 音频合成