Updating mechanics for OS protocols
This commit is contained in:
@@ -2834,13 +2834,13 @@ describe('mechanic validation and pseudo-script', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('rejects pre-event timing for the derived current Health percentage', () => {
|
||||
const invalid: MechanicProgram = {
|
||||
id: 'invalid-health-percent',
|
||||
name: 'Invalid Health Percent',
|
||||
it('evaluates pre-event timing for the derived current Health percentage', () => {
|
||||
const program: MechanicProgram = {
|
||||
id: 'pre-event-health-percent',
|
||||
name: 'Pre-event Health Percent',
|
||||
clauses: [
|
||||
{
|
||||
id: 'invalid',
|
||||
id: 'full-health-before-event',
|
||||
when: 'tick',
|
||||
if: {
|
||||
kind: 'compare',
|
||||
@@ -2849,25 +2849,32 @@ describe('mechanic validation and pseudo-script', () => {
|
||||
path: 'currentHealthPercent',
|
||||
timing: 'pre_event',
|
||||
},
|
||||
operator: 'lt',
|
||||
right: 50,
|
||||
operator: 'gte',
|
||||
right: 100,
|
||||
},
|
||||
reducer: { kind: 'none' },
|
||||
mutations: [],
|
||||
outcomes: [
|
||||
{
|
||||
id: 'matched',
|
||||
label: 'Matched',
|
||||
phase: 'on_event',
|
||||
kind: 'marker',
|
||||
scope: 'self',
|
||||
basis: 'flat',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const result = validateMechanicProgram(invalid);
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.errors).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.stringContaining(
|
||||
'current Health percentage must use current timing',
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
expect(validateMechanicProgram(program)).toMatchObject({ ok: true });
|
||||
expect(
|
||||
evaluateMechanicProgram(program, [{ kind: 'tick', at: 0 }], custom(1), {
|
||||
maxHealth: 100,
|
||||
currentHealth: 100,
|
||||
}).outcomes.map((outcome) => outcome.outcomeId),
|
||||
).toEqual(['matched']);
|
||||
});
|
||||
|
||||
it('formats nested conditions and state operations deterministically', () => {
|
||||
@@ -3104,6 +3111,42 @@ describe('mechanic validation and pseudo-script', () => {
|
||||
expect(
|
||||
maximum.outcomes.every((outcome) => outcome.probabilityRoll === 0),
|
||||
).toBe(true);
|
||||
|
||||
const skillProgram: MechanicProgram = {
|
||||
...program,
|
||||
id: 'skill-hit-explosion',
|
||||
clauses: program.clauses.map((clause) => ({
|
||||
...clause,
|
||||
when: 'skill_hit',
|
||||
if: undefined,
|
||||
})),
|
||||
};
|
||||
expect(validateMechanicProgram(skillProgram)).toMatchObject({ ok: true });
|
||||
expect(
|
||||
evaluateMechanicProgram(
|
||||
skillProgram,
|
||||
[
|
||||
{
|
||||
kind: 'skill_hit',
|
||||
at: 1,
|
||||
targetId: 'enemy-b',
|
||||
areaTargetSample: {
|
||||
center: 'event_target',
|
||||
validTargets: [
|
||||
{ entityId: 'enemy-b', population: 'enemy', distanceMeters: 0 },
|
||||
{ entityId: 'enemy-a', population: 'enemy', distanceMeters: 5 },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
custom(5),
|
||||
{
|
||||
maxHealth: 1000,
|
||||
currentHealth: 1000,
|
||||
attributes: { firepower: 100 },
|
||||
},
|
||||
).outcomes.map((outcome) => outcome.targetId),
|
||||
).toEqual(['enemy-a', 'enemy-b']);
|
||||
});
|
||||
|
||||
it('requires authoritative area evidence only when an area outcome activates', () => {
|
||||
|
||||
Reference in New Issue
Block a user