diff options
-rw-r--r-- | __tests__/dice.test.js | 14 | ||||
-rw-r--r-- | index.js | 6 | ||||
-rw-r--r-- | src/dice.js | 121 |
3 files changed, 46 insertions, 95 deletions
diff --git a/__tests__/dice.test.js b/__tests__/dice.test.js index fb8a155..caba0a9 100644 --- a/__tests__/dice.test.js +++ b/__tests__/dice.test.js @@ -7,13 +7,13 @@ const { bonusAdd, bonusSubtract, negative, - explode, + explodeAbove, explodeUnder, keepHigh, keepLow, - again, + againAbove, againUnder, - threshold, + thresholdHigh, thresholdLow } = require('../src/dice.js') @@ -452,7 +452,7 @@ describe('compound dice', () => { describe('exploding dice', () => { describe('6E1d6', () => { - const die = explode(constant(6), d(constant(1), constant(6))) + const die = explodeAbove(constant(6), d(constant(1), constant(6))) testDie(die, { diceCount: 1, average: { @@ -470,7 +470,7 @@ describe('exploding dice', () => { }) describe('6E2d6', () => { - const die = explode(constant(6), d(constant(2), constant(6))) + const die = explodeAbove(constant(6), d(constant(2), constant(6))) testDie(die, { diceCount: 2, average: { @@ -560,7 +560,7 @@ describe('keep', () => { describe('again', () => { describe('10A1d10', () => { - const die = again(constant(10), d(constant(1), constant(10))) + const die = againAbove(constant(10), d(constant(1), constant(10))) testDie(die, { variableDiceCount: { @@ -608,7 +608,7 @@ describe('again', () => { describe('threshold', () => { describe('8T3d10', () => { - const die = threshold(constant(8), d(constant(3), constant(10))) + const die = thresholdHigh(constant(8), d(constant(3), constant(10))) testDie(die, { diceCount: 3, @@ -8,7 +8,7 @@ const interpret = tree => { case 'd': return D.d(interpret(tree.left), interpret(tree.right)) case 'E': - return D.explode(interpret(tree.left), interpret(tree.right)) + return D.explodeAbove(interpret(tree.left), interpret(tree.right)) case 'e': return D.explodeUnder(interpret(tree.left), interpret(tree.right)) case 'K': @@ -16,11 +16,11 @@ const interpret = tree => { case 'k': return D.keepLow(interpret(tree.left), interpret(tree.right)) case 'A': - return D.again(interpret(tree.left), interpret(tree.right)) + return D.againAbove(interpret(tree.left), interpret(tree.right)) case 'a': return D.againUnder(interpret(tree.left), interpret(tree.right)) case 'T': - return D.threshold(interpret(tree.left), interpret(tree.right)) + return D.thresholdHigh(interpret(tree.left), interpret(tree.right)) case 't': return D.thresholdLow(interpret(tree.left), interpret(tree.right)) case 'add': diff --git a/src/dice.js b/src/dice.js index 53d337d..828a772 100644 --- a/src/dice.js +++ b/src/dice.js @@ -1,3 +1,6 @@ +const greaterThanOrEqual = (a, b) => a >= b +const lessThanOrEqual = (a, b) => a <= b + const constant = n => () => [() => n] const pool = (die) => { @@ -58,13 +61,13 @@ const bonusSubtract = (die1, die2) => { } } -const explode = (die1, die2) => { +const explode = (comparison, die1, die2) => { return () => { const explodeOn = roll(die1) return die2().map(die => () => { let lastRoll = die() let total = lastRoll - while (lastRoll >= explodeOn) { + while (comparison(lastRoll, explodeOn)) { lastRoll = die() total += lastRoll } @@ -73,26 +76,21 @@ const explode = (die1, die2) => { } } +const explodeAbove = (die1, die2) => { + return explode(greaterThanOrEqual, die1, die2) +} + const explodeUnder = (die1, die2) => { - return () => { - const explodeOn = roll(die1) - return die2().map(die => () => { - let lastRoll = die() - let total = lastRoll - while (lastRoll <= explodeOn) { - lastRoll = die() - total += lastRoll - } - return total - }) - } + return explode(lessThanOrEqual, die1, die2) } -const keepHigh = (die1, die2) => { + + +const keep = (order, die1, die2) => { return () => { const numberToKeep = roll(die1) let rolls = die2().map(die => [die, die()]) - rolls.sort((a, b) => (a[1] - b[1])).reverse() + rolls.sort(order) return rolls.slice(0, numberToKeep).map(pair => { let returnedOriginal = false return () => { @@ -107,26 +105,15 @@ const keepHigh = (die1, die2) => { } } +const keepHigh = (die1, die2) => { + return keep((a, b) => (b[1] - a[1]), die1, die2) +} + const keepLow = (die1, die2) => { - return () => { - const numberToKeep = roll(die1) - let rolls = die2().map(die => [die, die()]) - rolls.sort((a, b) => (a[1] - b[1])) - return rolls.slice(0, numberToKeep).map(pair => { - let returnedOriginal = false - return () => { - if (!returnedOriginal) { - returnedOriginal = true - return pair[1] - } else { - return pair[0]() - } - } - }) - } + return keep((a, b) => (a[1] - b[1]), die1, die2) } -const again = (die1, die2) => { +const again = (comparison, die1, die2) => { return () => { const againOn = roll(die1) let rolls = [] @@ -135,7 +122,7 @@ const again = (die1, die2) => { const rollDie = (die) => { const roll = die() - if (roll >= againOn) { + if (comparison(roll, againOn)) { rollAgain.push(die) } @@ -162,49 +149,21 @@ const again = (die1, die2) => { } } -const againUnder = (die1, die2) => { - return () => { - const againOn = roll(die1) - let rolls = [] - let rollAgain = [] - - const rollDie = (die) => { - const roll = die() - - if (roll <= againOn) { - rollAgain.push(die) - } - - let returnedOriginal = false - rolls.push(() => { - if (!returnedOriginal) { - returnedOriginal = true - return roll - } else { - return die() - } - }) - } - - die2().forEach(rollDie) - - while (rollAgain.length > 0) { - const oldRollAgain = rollAgain - rollAgain = [] - oldRollAgain.forEach(rollDie) - } +const againAbove = (die1, die2) => { + return again(greaterThanOrEqual, die1, die2) +} - return rolls - } +const againUnder = (die1, die2) => { + return again(lessThanOrEqual, die1, die2) } -const threshold = (die1, die2) => { +const threshold = (comparison, die1, die2) => { return () => { const cutoff = roll(die1) return die2().map(die => { return () => { - if (die() >= cutoff) { + if (comparison(die(), cutoff)) { return 1 } else { return 0 @@ -214,20 +173,12 @@ const threshold = (die1, die2) => { } } -const thresholdLow = (die1, die2) => { - return () => { - const cutoff = roll(die1) +const thresholdHigh = (die1, die2) => { + return threshold(greaterThanOrEqual, die1, die2) +} - return die2().map(die => { - return () => { - if (die() <= cutoff) { - return 1 - } else { - return 0 - } - } - }) - } +const thresholdLow = (die1, die2) => { + return threshold(lessThanOrEqual, die1, die2) } exports.pool = pool @@ -239,11 +190,11 @@ exports.subtract = subtract exports.bonusAdd = bonusAdd exports.bonusSubtract = bonusSubtract exports.negative = negative -exports.explode = explode +exports.explodeAbove = explodeAbove exports.explodeUnder = explodeUnder exports.keepHigh = keepHigh exports.keepLow = keepLow -exports.again = again +exports.againAbove = againAbove exports.againUnder = againUnder -exports.threshold = threshold +exports.thresholdHigh = thresholdHigh exports.thresholdLow = thresholdLow |