feat: add condition evaluator with full operator support

This commit is contained in:
2026-05-13 03:26:41 +00:00
commit 8ff8e8f522
2 changed files with 267 additions and 0 deletions
+111
View File
@@ -0,0 +1,111 @@
/**
* Condition evaluator for the Rebirth Incremental game.
* Evaluates condition objects against the current game state.
*/
/**
* Operator functions for comparing values.
* All operators perform loose equality/inequality checks where applicable.
*/
export const OPS = {
'==': (a, b) => a == b,
'===': (a, b) => a === b,
'!=': (a, b) => a != b,
'!==': (a, b) => a !== b,
'>': (a, b) => a > b,
'>=': (a, b) => a >= b,
'<': (a, b) => a < b,
'<=': (a, b) => a <= b,
};
/**
* Evaluates a condition object against the game state.
* @param {Object} condition - The condition to evaluate
* @param {Object} state - The current game state
* @returns {boolean} - Whether the condition is satisfied
*/
export function evaluateCondition(condition, state) {
if (!condition || typeof condition !== 'object') {
return false;
}
const { type } = condition;
switch (type) {
case 'age': {
const opFn = OPS[condition.op];
if (!opFn) return false;
return opFn(state.age ?? 0, condition.value);
}
case 'stat': {
const opFn = OPS[condition.op];
if (!opFn) return false;
const statValue = state.stats?.[condition.stat] ?? 0;
return opFn(statValue, condition.value);
}
case 'careerLevel': {
const opFn = OPS[condition.op];
if (!opFn) return false;
const level = state.careers?.[condition.careerId]?.level ?? 0;
return opFn(level, condition.value);
}
case 'money': {
const opFn = OPS[condition.op];
if (!opFn) return false;
return opFn(state.money ?? 0, condition.value);
}
case 'identity': {
return state.identity === condition.value;
}
case 'worldFlag': {
const flagValue = state.worldFlags?.[condition.flag];
if (condition.value !== undefined) {
return flagValue === condition.value;
}
return !!flagValue;
}
case 'hasItem': {
const itemCount = state.shopItems?.[condition.itemId] ?? 0;
return itemCount > 0;
}
case 'hasArtifact': {
const artifactValue = state.artifacts?.[condition.artifactId] ?? 0;
if (condition.op) {
const opFn = OPS[condition.op];
if (!opFn) return false;
return opFn(artifactValue, condition.value);
}
return artifactValue > 0;
}
case 'reincarnation': {
const opFn = OPS[condition.op];
if (!opFn) return false;
return opFn(state.reincarnation ?? 0, condition.value);
}
case 'and': {
if (!Array.isArray(condition.conditions)) return false;
return condition.conditions.every(sub => evaluateCondition(sub, state));
}
case 'or': {
if (!Array.isArray(condition.conditions)) return false;
return condition.conditions.some(sub => evaluateCondition(sub, state));
}
case 'not': {
return !evaluateCondition(condition.condition, state);
}
default:
return false;
}
}