import { sum } from "./utils/sum"; export class Dice { private count!: number; private sides!: number; private diceString: string; toString() { return this.diceString; } constructor(dice: string) { this.parseDice(dice); this.diceString = dice; } private parseDice(dice: string) { const [c, s] = dice.split(/[dD]/); this.count = Number(c); this.sides = Number(s); } public roll() { let results = []; for (let i = 0; i < this.count; i++) { results.push(this.rollSingle()); } return { total: sum(...results), max: Math.max(...results), min: Math.min(...results), results, }; } public rollMax() { return this.roll().max; } public rollMin() { return this.roll().min; } private rollSingle() { return Math.ceil(Math.random() * this.sides); } public rollAvg() { return this.roll().total / this.count; } public rollTimes(times: number) { let total = 0; for (let i = 0; i < times; i++) { total += this.roll().total; } return total; } public rollTimesAvg(times: number) { return this.rollTimes(times) / times; } public getNormalizedRollDistribution(): Record { const distribution: Record = this.computeDistribution(); // Normalize the distribution const totalOutcomes = Math.pow(this.sides, this.count); for (const sum in distribution) { if (distribution.hasOwnProperty(sum)) { distribution[sum] /= totalOutcomes; } } return distribution; } public getRollDistribution(): Record { return this.computeDistribution(); } public computeDistribution(): Record { const maxSum = this.count * this.sides; const dp: number[][] = Array.from({ length: this.count + 1 }, () => Array(maxSum + 1).fill(0) ); dp[0][0] = 1; for (let dice = 1; dice <= this.count; dice++) { for (let sum = 0; sum <= maxSum; sum++) { for (let face = 1; face <= this.sides; face++) { if (sum >= face) { dp[dice][sum] += dp[dice - 1][sum - face]; } } } } const distribution: Record = {}; for (let sum = this.count; sum <= maxSum; sum++) { distribution[sum] = dp[this.count][sum]; } return distribution; } // STATIC static isDice(d: string) { return /\d+[dD]\d+/.test(d); } } // globalThis.Dice = Dice;