Tested and fixed effect computations

This commit is contained in:
Stefan Zermatten
2021-09-23 15:22:01 +02:00
parent 2f893710e2
commit c0a9a1251d
14 changed files with 100 additions and 38 deletions

View File

@@ -1,9 +1,9 @@
export default function computeAction(graph, node, scope){
export default function computeAction(computation, node){
const prop = node.data;
if (prop.uses){
prop.usesLeft = prop.uses.value - (prop.usesUsed || 0);
}
computeResources(graph, node, scope);
computeResources(computation, node);
if (!prop.resources) return;
prop.resources.itemsConsumed.forEach(itemConsumed => {
if (!itemConsumed.itemId) return;
@@ -19,12 +19,12 @@ export default function computeAction(graph, node, scope){
});
}
function computeResources(graph, node, scope){
function computeResources(computation, node){
const resources = node.data?.resources;
if (!resources) return;
resources.attributesConsumed.forEach(attConsumed => {
if (!attConsumed.variableName) return;
const att = scope[attConsumed.variableName];
const att = computation.scope[attConsumed.variableName];
attConsumed.available = att.value;
attConsumed.statId = att._id;
attConsumed.statName = att.name;

View File

@@ -2,7 +2,7 @@
// uses its base value and damage since no effects can target it
// If this attribute does have a variable name, it is recomputed later
// by computeVariableAsAttribute
export default function computeAttribute(graph, node){
export default function computeAttribute(computation, node){
const prop = node.data;
prop.total = prop.baseValue?.value || 0;
prop.value = prop.total - (prop.damage || 0);

View File

@@ -1,12 +1,12 @@
import aggregate from './computeVariable/aggregate/index.js';
export default function computeContainer(graph, node){
export default function computeContainer(computation, node){
if (!node.data) node.data = {};
aggregateLinks(graph, node);
aggregateLinks(computation, node);
}
function aggregateLinks(graph, node){
graph.forEachLinkedNode(
function aggregateLinks(computation, node){
computation.dependencyGraph.forEachLinkedNode(
node.id,
(linkedNode, link) => {
if (!linkedNode.data) linkedNode.data = {};

View File

@@ -1,4 +1,4 @@
export default function computSlot(graph, node){
export default function computSlot(computation, node){
const prop = node.data;
if (prop.quantityExpected){
prop.spaceLeft = prop.quantityExpected - prop.totalFilled;

View File

@@ -5,21 +5,22 @@ import computeVariableAsConstant from './computeVariable/computeVariableAsConsta
import computeVariableAsClass from './computeVariable/computeVariableAsClass.js';
import computeImplicitVariable from './computeVariable/computeImplicitVariable.js';
export default function computeVariable(graph, node, scope){
export default function computeVariable(computation, node){
const scope = computation.scope;
if (!node.data) node.data = {};
aggregateLinks(graph, node);
combineAggregations(node, scope);
aggregateLinks(computation, node);
combineAggregations(computation, node);
if (node.data.definingProp){
// Add the defining variable to the scope
scope[node.id] = node.data.definingProp
} else {
// Otherwise add an implicit variable to the scope
scope[node.id] = computeImplicitVariable(node, scope);
scope[node.id] = computeImplicitVariable(node);
}
}
function aggregateLinks(graph, node){
graph.forEachLinkedNode(
function aggregateLinks(computation, node){
computation.dependencyGraph.forEachLinkedNode(
node.id,
(linkedNode, link) => {
if (!linkedNode.data) linkedNode.data = {};
@@ -38,24 +39,24 @@ function aggregateLinks(graph, node){
);
}
function combineAggregations(node, scope){
function combineAggregations(computation, node){
combineMultiplierAggregator(node);
node.data.overridenProps?.forEach(prop => {
computeVariableProp(node, prop, scope);
computeVariableProp(computation, node, prop);
});
computeVariableProp(node, node.data.definingProp, scope);
computeVariableProp(computation, node, node.data.definingProp);
}
function computeVariableProp(node, prop, scope){
function computeVariableProp(computation, node, prop){
if (!prop) return;
if (prop.type === 'attribute'){
computeVariableAsAttribute(node, prop, scope)
computeVariableAsAttribute(computation, node, prop)
} else if (prop.type === 'skill'){
computeVariableAsSkill(node, prop, scope)
computeVariableAsSkill(computation, node, prop)
} else if (prop.type === 'constant'){
computeVariableAsConstant(node, prop, scope)
computeVariableAsConstant(computation, node, prop)
} else if (prop.type === 'class'){
computeVariableAsClass(node, prop, scope)
computeVariableAsClass(computation, node, prop)
}
}

View File

@@ -1,6 +1,6 @@
import getAggregatorResult from './getAggregatorResult.js';
export default function computeVariableAsAttribute(node, prop, scope){
export default function computeVariableAsAttribute(computation, node, prop){
let result = getAggregatorResult(node, prop) || 0;
prop.total = result;
@@ -16,7 +16,7 @@ export default function computeVariableAsAttribute(node, prop, scope){
// Hit dice denormalise constitution modifier
if (prop.attributeType === 'hitDice') {
prop.constitutionMod = scope['constitution']?.modifier || 0;
prop.constitutionMod = computation.scope['constitution']?.modifier || 0;
}
// Stats that have no effects or base value can be hidden

View File

@@ -1,4 +1,4 @@
export default function computeVariableAsAttribute(node, prop){
export default function computeVariableAsAttribute(computation, node, prop){
let classLevelAgg = node.data.classLevelAggregator;
if (!classLevelAgg) return;
prop.level = classLevelAgg.level;

View File

@@ -1,6 +1,6 @@
import { parse } from '/imports/parser/parser.js';
export default function computeVariableAsConstant(node, prop){
export default function computeVariableAsConstant(computation, node, prop){
let string = prop.calculation;
if (!string) return;
let parseNode;

View File

@@ -2,11 +2,11 @@ import { CompilationContext } from '/imports/parser/parser.js';
import INLINE_CALCULATION_REGEX from '/imports/constants/INLINE_CALCULTION_REGEX.js';
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
export default function computeCalculations(node, scope){
export default function computeCalculations(computation, node){
if (!node.data) return;
// evaluate all the calculations
node.data._computationDetails?.calculations?.forEach(calcObj => {
evaluateCalculation(calcObj, scope)
evaluateCalculation(calcObj, computation.scope)
});
node.data._computationDetails?.inlineCalculations?.forEach(inlineCalcObj => {
embedInlineCalculations(inlineCalcObj);

View File

@@ -1,4 +1,4 @@
export default function evaluateToggles(node){
export default function evaluateToggles(computation, node){
let prop = node.data;
if (!prop) return;
let toggles = prop._computationDetails?.toggleAncestors;

View File

@@ -0,0 +1,59 @@
import { buildComputationFromProps } from '/imports/api/creature/computation/newEngine/buildCreatureComputation.js';
import { assert } from 'chai';
import computeCreatureComputation from '../../computeCreatureComputation.js';
import clean from '../../utility/cleanProp.testFn.js';
export default function(){
const computation = buildComputationFromProps(testProperties);
computeCreatureComputation(computation);
const prop = id => computation.propsById[id];
assert.equal(prop('strengthId').value, 26);
}
var testProperties = [
clean({
_id: 'strengthId',
variableName: 'strength',
type: 'attribute',
attributeType: 'ability',
baseValue: {
calculation: '8'
},
}),
clean({
_id: 'strength2Id',
variableName: 'strength',
type: 'attribute',
attributeType: 'ability',
baseValue: {
calculation: '10'
},
}),
clean({
_id: 'strengthBaseId',
type: 'effect',
operation: 'base',
amount: {
calculation: '10 + 2'
},
stats: ['strength'],
}),
clean({
_id: 'strengthAddId',
type: 'effect',
operation: 'add',
amount: {
calculation: '1'
},
stats: ['strength'],
}),
clean({
_id: 'strengthMulId',
type: 'effect',
operation: 'mul',
amount: {
calculation: '2'
},
stats: ['strength'],
}),
];

View File

@@ -4,6 +4,7 @@ import computeClasses from './computeClasses.testFn.js';
import computeConstants from './computeConstants.testFn.js';
import computeInventory from './computeInventory.testFn.js';
import computeDamageMultipliers from './computeDamageMultipliers.testFn.js';
import computeEffects from './computeEffects.testFn.js';
export default [{
text: 'Computes actions',
@@ -23,4 +24,7 @@ export default [{
},{
text: 'Computes damage multipliers',
fn: computeDamageMultipliers,
},{
text: 'Computes effects',
fn: computeEffects,
}];

View File

@@ -5,7 +5,6 @@ import computeByType from '/imports/api/creature/computation/newEngine/computeCo
export default function computeCreatureComputation(computation){
const stack = [];
// Computation scope of {variableName: prop}
const scope = computation.scope;
const graph = computation.dependencyGraph;
// Add all nodes to the stack
graph.forEachNode(node => {
@@ -24,7 +23,7 @@ export default function computeCreatureComputation(computation){
top._visited = true;
stack.pop();
// Compute the top object of the stack
compute(graph, top, scope);
compute(computation, top);
} else {
top._visitedChildren = true;
// Push dependencies to graph to be computed first
@@ -33,12 +32,12 @@ export default function computeCreatureComputation(computation){
}
}
function compute(graph, node, scope){
function compute(computation, node){
// Determine the prop's active status by its toggles
computeToggles(node);
computeCalculations(node, scope);
computeToggles(computation, node);
computeCalculations(computation, node);
// Compute the property by type
computeByType[node.data?.type || '_variable']?.(graph, node, scope);
computeByType[node.data?.type || '_variable']?.(computation, node);
}
function pushDependenciesToStack(nodeId, graph, stack){

View File

@@ -27,7 +27,6 @@ let EffectSchema = createPropertySchema({
'passiveAdd',
'fail',
'conditional',
'rollBonus',
],
},
amount: {