From 9368b1c33db290d7c80c93db5c867cdb7fcaf14d Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Mon, 11 Sep 2017 15:47:50 -0400 Subject: Implement collecting --- __tests__/dice.test.js | 43 ++++++++++++++++++++++++++++++++++++++++++- __tests__/lexer.test.js | 12 ++++++++++++ __tests__/parser.test.js | 19 +++++++++++++++++++ index.js | 2 ++ src/dice.js | 5 +++++ src/lexer.js | 2 ++ src/parser.js | 12 ++++++++++++ 7 files changed, 94 insertions(+), 1 deletion(-) diff --git a/__tests__/dice.test.js b/__tests__/dice.test.js index 9c03a48..56572d2 100644 --- a/__tests__/dice.test.js +++ b/__tests__/dice.test.js @@ -19,7 +19,8 @@ const { againUnder, thresholdHigh, thresholdLow, - repeat + repeat, + collect } = require('../src/dice.js') const defaultNumberRolls = 500 @@ -817,3 +818,43 @@ describe('repeat', () => { }) }) }) + +describe('collect', () => { + describe('[2d6]', () => { + const die = collect(d(constant(2), constant(6))) + + testDie(die, { + diceCount: 1, + average: { + average: 7 + }, + variance: { + variance: 5.83 + }, + bounds: { + low: 2, + high: 12, + expectLow: true, + expectHigh: true + } + }) + }) + + describe('[1d6 x 1d4]', () => { + const die = + collect(repeat(d(constant(1), constant(6)), d(constant(1), constant(4)))) + + testDie(die, { + diceCount: 1, + average: { + average: 8.75 + }, + bounds: { + low: 1, + high: 24, + expectLow: true, + expectHigh: false + } + }) + }) +}) diff --git a/__tests__/lexer.test.js b/__tests__/lexer.test.js index 7124746..b2cb77e 100644 --- a/__tests__/lexer.test.js +++ b/__tests__/lexer.test.js @@ -171,6 +171,18 @@ describe('lex', () => { { type: 'constant', value: 4 } ]) }) + + it('[2d8]+3', () => { + expect(lex('[2d8]+3')).toEqual([ + { type: '[' }, + { type: 'constant', value: 2 }, + { type: 'd' }, + { type: 'constant', value: 8 }, + { type: ']' }, + { type: 'plus' }, + { type: 'constant', value: 3 } + ]) + }) }) describe('lexes negatives', () => { diff --git a/__tests__/parser.test.js b/__tests__/parser.test.js index 3c9f6ec..cb89ad5 100644 --- a/__tests__/parser.test.js +++ b/__tests__/parser.test.js @@ -325,6 +325,25 @@ describe('parse', () => { }) }) + it('parses dice with collecting', () => { + expect(parse('[2d6] x 1d4')).toEqual({ + type: 'repeat', + left: { + type: 'collect', + value: { + type: 'd', + left: { type: 'constant', value: 2 }, + right: { type: 'constant', value: 6 } + } + }, + right: { + type: 'd', + left: { type: 'constant', value: 1 }, + right: { type: 'constant', value: 4 } + } + }) + }) + describe('parsing parentheses', () => { test('(1d6)d6', () => { expect(parse('(1d6)d6')).toEqual({ diff --git a/index.js b/index.js index 13e6378..db39fd1 100644 --- a/index.js +++ b/index.js @@ -43,6 +43,8 @@ const interpret = tree => { return D.bonusDivide(interpret(tree.left), interpret(tree.right)) case 'repeat': return D.repeat(interpret(tree.left), interpret(tree.right)) + case 'collect': + return D.collect(interpret(tree.value)) } } diff --git a/src/dice.js b/src/dice.js index 0197f25..1e15937 100644 --- a/src/dice.js +++ b/src/dice.js @@ -222,6 +222,10 @@ const repeat = (die1, die2) => { } } +const collect = die => { + return () => [() => roll(die)] +} + exports.pool = pool exports.roll = roll exports.constant = constant @@ -244,3 +248,4 @@ exports.againUnder = againUnder exports.thresholdHigh = thresholdHigh exports.thresholdLow = thresholdLow exports.repeat = repeat +exports.collect = collect diff --git a/src/lexer.js b/src/lexer.js index 6b75129..88bd188 100644 --- a/src/lexer.js +++ b/src/lexer.js @@ -26,6 +26,8 @@ newLexemeType('times', '\\*') newLexemeType('divide', '/') newLexemeType('(', '\\(') newLexemeType(')', '\\)') +newLexemeType('[', '\\[') +newLexemeType(']', '\\]') newLexemeType('E', 'E') newLexemeType('e', 'e') newLexemeType('K', 'K') diff --git a/src/parser.js b/src/parser.js index acae9ad..3cf6d55 100644 --- a/src/parser.js +++ b/src/parser.js @@ -44,6 +44,16 @@ newSymbol('constant', function() { return { type: 'constant', value: this.value } }) +const newBrackets = (openSymbol, closeSymbol, valueWrapper) => { + newSymbol(openSymbol, function(parser) { + const value = parser.expression(1) + parser.match(closeSymbol) + return valueWrapper(value) + }) + + newSymbol(closeSymbol) +} + newSymbol('(', function(parser) { const value = parser.expression(1) parser.match(')') @@ -52,6 +62,8 @@ newSymbol('(', function(parser) { newSymbol(')') +newBrackets('[', ']', value => ({ type: 'collect', value: value })) + newDieOperation('d') newSymbol('d', (parser) => { return { -- cgit v1.2.3