@mousepox/math
Version:
Math-related objects and utilities
75 lines (74 loc) • 2.01 kB
JavaScript
const M = 0x80000000;
const A = 1103515245;
const C = 12345;
const DiceNotationPattern = /([0-9]+)?d([0-9]+)([+-]{1}[0-9]+)?/;
function parseDiceNotation(notation) {
const matches = notation.match(DiceNotationPattern);
if (matches === null) {
throw new Error(`Invalid dice notation: ${notation}`);
}
return {
bonus: Number(matches[3]),
count: Number(matches[1]),
sides: Number(matches[2]),
};
}
export class Random {
static getDiceNotationRange(notation) {
const { count, sides, bonus } = parseDiceNotation(notation);
return {
max: count * sides + bonus,
min: count * 1 + bonus,
};
}
state = 0;
constructor(seed) {
this.reset(seed);
}
reset(seed) {
if (seed !== undefined) {
this.state = seed;
}
else {
this.state = Math.floor(Math.random() * (M - 1));
}
}
next() {
this.state = (A * this.state + C) % M;
return this.state / M;
}
integer(min, max) {
return Math.floor(this.next() * (max - min + 1)) + min;
}
chance(probability) {
return this.next() <= probability;
}
choice(items, remove = false) {
const index = this.integer(0, items.length - 1);
const pick = items[index];
if (remove) {
items.splice(index, 1);
}
return pick;
}
shuffle(items) {
const len = items.length;
if (len < 2) {
return;
}
for (let i = 0; i < len; ++i) {
const j = this.integer(i, len - 1);
const swap = items[i];
items[i] = items[j];
items[j] = swap;
}
}
rollDiceNotation(notation) {
const { count, sides, bonus } = parseDiceNotation(notation);
let result = bonus;
for (let i = 0; i < count; ++i) {
result += this.integer(1, sides);
}
return result;
}
}