Began implementing dice rolls in the maths parser
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import evaluateString from '/imports/api/creature/computation/afterComputation/evaluateString.js';
|
import evaluateAndRollString from '/imports/api/creature/computation/afterComputation/evaluateAndRollString.js';
|
||||||
|
|
||||||
export default function applyDamage({
|
export default function applyDamage({
|
||||||
prop,
|
prop,
|
||||||
@@ -11,9 +11,9 @@ export default function applyDamage({
|
|||||||
...creature.variables,
|
...creature.variables,
|
||||||
...actionContext,
|
...actionContext,
|
||||||
};
|
};
|
||||||
let {result, errors} = evaluateString(prop.amount, scope);
|
let {result, errors} = evaluateAndRollString(prop.amount, scope);
|
||||||
if (Meteor.isClient) errors.forEach(e => console.error(e));
|
if (Meteor.isClient){
|
||||||
if (Number.isFinite(result)) {
|
errors.forEach(e => console.error(e));
|
||||||
damageTargets.forEach()
|
console.log(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import applyAction from '/imports/api/creature/actions/applyAction.js';
|
import applyAction from '/imports/api/creature/actions/applyAction.js';
|
||||||
//import applyDamage from '/imports/api/creature/actions/applyDamage.js';
|
import applyDamage from '/imports/api/creature/actions/applyDamage.js';
|
||||||
import applyBuff from '/imports/api/creature/actions/applyBuff.js';
|
import applyBuff from '/imports/api/creature/actions/applyBuff.js';
|
||||||
|
|
||||||
function applyProperty(options){
|
function applyProperty(options){
|
||||||
@@ -19,7 +19,7 @@ function applyProperty(options){
|
|||||||
applyAction(options);
|
applyAction(options);
|
||||||
return true;
|
return true;
|
||||||
case 'damage':
|
case 'damage':
|
||||||
// applyDamage(options);
|
applyDamage(options);
|
||||||
return true;
|
return true;
|
||||||
case 'adjustment':
|
case 'adjustment':
|
||||||
// applyAdjustment(options);
|
// applyAdjustment(options);
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import math from '/imports/math.js';
|
||||||
|
import bareSymbolSubtitutor from '/imports/api/creature/computation/utility/bareSymbolSubtitutor.js';
|
||||||
|
import substituteRollsWithFunctions from '/imports/api/creature/computation/afterComputation/substituteRollsWithFunctions.js'
|
||||||
|
|
||||||
|
export default function evaluateAndRollString(string, scope){
|
||||||
|
let errors = [];
|
||||||
|
if (!string){
|
||||||
|
errors.push('No string provided');
|
||||||
|
return {result: string, errors};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!scope) errors.push('No scope provided');
|
||||||
|
|
||||||
|
// Parse the string using mathjs
|
||||||
|
let calc;
|
||||||
|
try {
|
||||||
|
calc = math.parse(string);
|
||||||
|
} catch (e) {
|
||||||
|
errors.push(e);
|
||||||
|
return {result: string, errors};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace all bare symbols with symbol.value
|
||||||
|
let transformedCalc = calc.transform(bareSymbolSubtitutor(scope));
|
||||||
|
// Replace all rolls with the function to call them
|
||||||
|
transformedCalc = calc.transform(substituteRollsWithFunctions);
|
||||||
|
|
||||||
|
// Evaluate the expression to a number or return with substitutions
|
||||||
|
try {
|
||||||
|
let result = transformedCalc.evaluate(scope);
|
||||||
|
return {result, errors};
|
||||||
|
} catch (e1){
|
||||||
|
errors.push(e1);
|
||||||
|
try {
|
||||||
|
let result = simplifyWithAccessors(transformedCalc, scope).toHTML();
|
||||||
|
return {result, errors};
|
||||||
|
} catch (e2){
|
||||||
|
errors.push(e2);
|
||||||
|
return {result: transformedCalc.toHTML(), errors};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function simplifyWithAccessors(calc, scope){
|
||||||
|
let noAccessorCalc = calc.transform(substituteAccessors(scope));
|
||||||
|
return math.simplify(noAccessorCalc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns a function to replace all accessors with either their resolved value
|
||||||
|
// or a symbol to simplify with
|
||||||
|
function substituteAccessors(scope){
|
||||||
|
return function(node){
|
||||||
|
if (node.isAccessorNode){
|
||||||
|
try {
|
||||||
|
return evaluateAccessor(node, scope);
|
||||||
|
} catch (e) {
|
||||||
|
return replaceAccessorWithSymbol(node);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Throws error if symbol is undefined in scope
|
||||||
|
function evaluateAccessor(node, scope){
|
||||||
|
let value = node.evaluate(scope);
|
||||||
|
if (value === undefined){
|
||||||
|
throw 'Undefined symbol'
|
||||||
|
}
|
||||||
|
return new math.ConstantNode(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function replaceAccessorWithSymbol(node){
|
||||||
|
let symbolNode = new math.SymbolNode(node.toString());
|
||||||
|
return symbolNode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import math from '/imports/math.js';
|
||||||
|
|
||||||
|
const diceRegex = /d\d+/;
|
||||||
|
|
||||||
|
export default function substituteRollsWithFunctions(node){
|
||||||
|
// TODO also replace dx as 1dx
|
||||||
|
if (
|
||||||
|
node.isOperatorNode &&
|
||||||
|
node.fn === 'multiply' &&
|
||||||
|
node.implicit &&
|
||||||
|
node.args[1].isSymbolNode &&
|
||||||
|
diceRegex.test(node.args[1].name)
|
||||||
|
){
|
||||||
|
let diceSize = node.args[1].name.slice(1);
|
||||||
|
let diceSizeNode = new math.ConstantNode(diceSize);
|
||||||
|
return new math.FunctionNode('roll', [node.args[0], diceSizeNode]);
|
||||||
|
} else {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,20 @@
|
|||||||
import { create, all } from 'mathjs';
|
import { create, all } from 'mathjs';
|
||||||
|
import { Random } from 'meteor/random'
|
||||||
|
|
||||||
const math = create(all);
|
const math = create(all);
|
||||||
math.import({
|
math.import({
|
||||||
'if': function(pred, a, b) {
|
'if': function(pred, a, b) {
|
||||||
return pred ? a : b;
|
return pred ? a : b;
|
||||||
|
},
|
||||||
|
'roll': function(number, diceSize){
|
||||||
|
if (number > 100) throw 'Can only roll 100 dice at a time';
|
||||||
|
let rollTotal = 0;
|
||||||
|
let i, roll;
|
||||||
|
for (i = 0; i < number; i++){
|
||||||
|
roll = ~~(Random.fraction() * diceSize) + 1
|
||||||
|
rollTotal += roll;
|
||||||
|
}
|
||||||
|
return rollTotal;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user