| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- const diceRegex = () => /\b(\d*)[dD](\d+)\b(?:\s?([+-])\s?(\d+))?/g
- class Roll {
- constructor(roll) {
- if (roll) Object.assign(this, roll)
- }
- value() {
- return this.values.reduce((a, b) => a + b, this.bonus || 0)
- }
- toString() {
- let str = this.values.map(val => `[${val}]`).join(' + ')
- if (this.bonus < 0) {
- str += ` - ${Math.abs(this.bonus)}`
- } else if (this.bonus > 0) {
- str += ` + ${this.bonus}`
- }
- if (this.values.length > 1 || this.bonus) {
- str += ` = ${this.value()}`
- }
- return str
- }
- }
- class BadRoll extends Roll {
- constructor(text) {
- super({text})
- }
- toString() {
- return this.text
- }
- }
- class Dice {
- constructor(dice) {
- if (dice) Object.assign(this, dice)
- }
- roll() {
- if (this.count > 100) return new BadRoll(`I lost count rolling ${this}`)
- if (this.sides > 256) return new BadRoll(`The faces are too small to read on ${this}`)
- if (this.count === 0) return new BadRoll(`I finished before I started rolling ${this}`)
- if (this.sides === 0) return new BadRoll(`I lost my grip on ${this}`)
- if (this.sides === 1) return new BadRoll(`The mobius ${this} never stopped rolling`)
- if (this.bonusSign === '-' && this.bonus > this.sides) return new BadRoll(`It doesn't seem fair to roll ${this}`)
- let values = []
- for (let i = 0; i < this.count; i++) {
- values.push(Math.floor(Math.random() * this.sides) + 1)
- }
- let bonus = 0
- switch (this.bonusSign) {
- case '-': bonus = -this.bonus; break
- case '+': bonus = this.bonus; break
- }
- return new Roll({
- values,
- bonus
- })
- }
- toString() {
- let str = `${this.count}d${this.sides}`
- if (this.bonusSign) {
- str += this.bonusSign + this.bonus
- }
- return str
- }
- }
- Dice.parse = str => {
- const regex = diceRegex()
- const ret = []
- let dice
- while (dice = regex.exec(str)) {
- ret.push(new Dice({
- match: dice,
- count: dice[1] === '' ? 1 : parseFloat(dice[1]),
- sides: parseFloat(dice[2]),
- bonusSign: dice[3] || null,
- bonus: dice[4] === undefined ? null : parseFloat(dice[4])
- }))
- }
- return ret
- }
- Dice.chat = chat => {
- const dice = Dice.parse(chat)
- if (dice.length) {
- const diceStrings = dice.map(x => x.toString())
- if (diceStrings.length > 1) {
- diceStrings[diceStrings.length - 1] = `and ${diceStrings[diceStrings.length - 1]}`
- }
- const rollingString = `Rolling ${diceStrings.join(', ')}...`
- const rollsStrings = dice.map(die => die.roll().toString())
- return `${rollingString} ${rollsStrings.join(', ')}.`
- }
- }
- module.exports = {Dice, Roll}
|