fix: dice issue

This commit is contained in:
2026-02-28 17:10:54 +08:00
parent cc10cea31d
commit 91d46dea75
3 changed files with 93 additions and 91 deletions
@@ -13,25 +13,42 @@ export function rollDie(sides: number): number {
* 掷骰池
*/
export function rollDicePool(pool: DicePool): DicePoolResult {
// 掷所有骰子
const rolls: DieResult[] = pool.dice.map((die) => ({
// 分离骰子和固定数字
const diceToRoll = pool.dice.filter((die) => die.sides > 0);
const fixedNumbers = pool.dice.filter((die) => die.sides === 0);
// 只掷真正的骰子
const rolls: DieResult[] = diceToRoll.map((die) => ({
sides: die.sides,
value: rollDie(die.sides),
isNegative: die.isNegative,
}));
// 应用修饰符
// 添加固定数字
const allRolls: DieResult[] = [
...rolls,
...fixedNumbers.map((die) => ({
sides: 0,
value: die.value,
isNegative: die.isNegative,
})),
];
// 应用修饰符(只对有面数的骰子生效)
const { keptRolls, droppedRolls } = applyModifier(rolls, pool.modifier);
// 固定数字总是保留
const finalKeptRolls = [...keptRolls, ...allRolls.filter((r) => r.sides === 0)];
// 计算小计
const subtotal = keptRolls.reduce((sum, roll) => {
const subtotal = finalKeptRolls.reduce((sum, roll) => {
return sum + (roll.isNegative ? -roll.value : roll.value);
}, 0);
return {
pool,
rolls,
keptRolls,
rolls: allRolls,
keptRolls: finalKeptRolls,
droppedRolls,
subtotal,
};
@@ -55,27 +72,23 @@ export function applyModifier(
case "kh": // Keep Highest - 保留最大的 N 个
case "dh": { // Drop Highest - 丢弃最大的 N 个
const count = modifier.count;
const higher = sorted.slice(-count);
const rest = sorted.slice(0, -count);
if (modifier.type === "kh") {
const kept = sorted.slice(-count);
const dropped = sorted.slice(0, -count);
return { keptRolls: kept, droppedRolls: dropped };
return { keptRolls: higher, droppedRolls: rest };
} else {
const kept = sorted.slice(0, -count);
const dropped = sorted.slice(-count);
return { keptRolls: kept, droppedRolls: dropped };
return { keptRolls: rest, droppedRolls: higher };
}
}
case "kl": // Keep Lowest - 保留最小的 N 个
case "dl": { // Drop Lowest - 丢弃最小的 N 个
const count = modifier.count;
const lower = sorted.slice(0, count);
const rest = sorted.slice(count);
if (modifier.type === "kl") {
const kept = sorted.slice(0, count);
const dropped = sorted.slice(count);
return { keptRolls: kept, droppedRolls: dropped };
return { keptRolls: lower, droppedRolls: rest };
} else {
const kept = sorted.slice(count);
const dropped = sorted.slice(0, count);
return { keptRolls: kept, droppedRolls: dropped };
return { keptRolls: rest, droppedRolls: lower };
}
}
}
@@ -93,40 +106,24 @@ export function roll(formula: string): RollResult {
const total = poolResults.reduce((sum, result) => sum + result.subtotal, 0);
// 生成详细表达式 - 使用 HTML 格式
const parts: string[] = [];
const rollSpans: string[] = [];
for (const result of poolResults) {
const diceCount = result.pool.dice.filter((d) => d.sides > 0).length;
const fixedValue = result.pool.dice.find((d) => d.sides === 0)?.value || 0;
const modStr = result.pool.modifier
? `${result.pool.modifier.type}${result.pool.modifier.count}`
: "";
// 骰子部分
let dicePart: string;
if (diceCount > 0) {
const sides = result.pool.dice[0]?.sides || 0;
dicePart = `${diceCount}d${sides}${modStr}`;
} else {
dicePart = `${fixedValue}`;
}
// 构建骰子结果 HTML
const rollSpans = result.rolls.map((roll) => {
const isKept = result.keptRolls.some(
(kept) => kept === roll
);
if (isKept) {
return `<strong>[${roll.value}]</strong>`;
for (const roll of result.rolls) {
const isKept = result.keptRolls.some((kept) => kept === roll);
if (roll.sides === 0) {
// 固定数字,不显示括号
rollSpans.push(`<strong>${roll.isNegative ? '-' : ''}${roll.value}</strong>`);
} else if (isKept) {
rollSpans.push(`<strong>[${roll.value}]</strong>`);
} else {
return `<span class="text-gray-400">[${roll.value}]</span>`;
rollSpans.push(`<span class="text-gray-400">[${roll.value}]</span>`);
}
});
const rollsStr = rollSpans.join(" ");
parts.push(`${dicePart} ${rollsStr} = <strong>${result.subtotal}</strong>`);
}
}
const detail = parts.join(" + ");
const rollsStr = rollSpans.join(" + ");
const detail = `<strong>${total}</strong> = ${rollsStr}`;
return {
pools: poolResults,