feat: dice roller improved

This commit is contained in:
2026-02-28 16:49:59 +08:00
parent 66aaaa96e1
commit cc10cea31d
12 changed files with 736 additions and 40 deletions
@@ -0,0 +1,129 @@
import { tokenize, parse } from "./parser";
import { rollDicePool, roll } from "./roller";
import type { DicePool } from "./types";
/**
* 骰子引擎测试
* 在浏览器控制台运行:window.testDiceEngine()
*/
export function testDiceEngine() {
console.log("=== 骰子引擎测试 ===\n");
// 测试用例
const testCases: Array<{
name: string;
formula: string;
expected: {
hasPools: number;
hasModifier?: boolean;
};
}> = [
{
name: "标准骰子 3d6",
formula: "3d6",
expected: { hasPools: 1 },
},
{
name: "单个骰子 d20",
formula: "d20",
expected: { hasPools: 1 },
},
{
name: "骰池字面量 {d4,d8}",
formula: "{d4,d8}",
expected: { hasPools: 1 },
},
{
name: "带修饰符 3d6kh2",
formula: "3d6kh2",
expected: { hasPools: 1, hasModifier: true },
},
{
name: "带修饰符 4d6dl1",
formula: "4d6dl1",
expected: { hasPools: 1, hasModifier: true },
},
{
name: "组合骰池 3d6+5",
formula: "3d6+5",
expected: { hasPools: 2 },
},
{
name: "负数组合 3d6-2",
formula: "3d6-2",
expected: { hasPools: 2 },
},
{
name: "复杂公式 3d6+{d4,d8}kh2-5",
formula: "3d6+{d4,d8}kh2-5",
expected: { hasPools: 4, hasModifier: true },
},
{
name: "多个骰池 {d6,d8}+{d10,d12}",
formula: "{d6,d8}+{d10,d12}",
expected: { hasPools: 2 },
},
{
name: "Keep Lowest 5d6kl3",
formula: "5d6kl3",
expected: { hasPools: 1, hasModifier: true },
},
{
name: "Drop Highest 4d6dh1",
formula: "4d6dh1",
expected: { hasPools: 1, hasModifier: true },
},
];
let passed = 0;
let failed = 0;
for (const tc of testCases) {
try {
// 测试词法分析
const tokens = tokenize(tc.formula);
console.log(`\n公式:${tc.formula}`);
console.log(` 令牌:${tokens.length} 个`);
// 测试语法分析
const pools = parse(tokens);
console.log(` 骰池:${pools.length} 个`);
// 测试掷骰
const result = roll(tc.formula);
console.log(` 结果:${result.total}`);
console.log(` 详情:${result.detail}`);
// 验证
if (pools.length >= tc.expected.hasPools) {
console.log(` ✓ 通过`);
passed++;
} else {
console.log(` ✗ 失败:期望至少 ${tc.expected.hasPools} 个骰池,实际 ${pools.length} 个`);
failed++;
}
if (tc.expected.hasModifier) {
const hasMod = pools.some((p) => p.modifier !== undefined);
if (hasMod) {
console.log(` ✓ 修饰符正确`);
} else {
console.log(` ✗ 修饰符缺失`);
failed++;
}
}
} catch (e) {
console.log(` ✗ 错误:${e instanceof Error ? e.message : String(e)}`);
failed++;
}
}
console.log(`\n=== 测试完成:${passed} 通过,${failed} 失败 ===`);
return { passed, failed };
}
// 在浏览器环境下暴露到全局
if (typeof window !== "undefined") {
(window as any).testDiceEngine = testDiceEngine;
}