m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--__tests__/dice.test.js43
-rw-r--r--__tests__/lexer.test.js12
-rw-r--r--__tests__/parser.test.js19
-rw-r--r--index.js2
-rw-r--r--src/dice.js5
-rw-r--r--src/lexer.js2
-rw-r--r--src/parser.js12
7 files changed, 94 insertions, 1 deletions
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 {