feat: add authored mechanic contracts
This commit is contained in:
@@ -1355,6 +1355,104 @@ describe('structured mechanic runtime', () => {
|
||||
expect(maximum.finalState[0].value).toBe(4);
|
||||
});
|
||||
|
||||
it('preserves an explicit zero clause weight', () => {
|
||||
const result = evaluateMechanicProgram(
|
||||
{
|
||||
id: 'zero-weight',
|
||||
name: 'Zero weight',
|
||||
clauses: [
|
||||
{
|
||||
id: 'zero-weight-clause',
|
||||
when: 'agent_hit',
|
||||
reducer: { kind: 'none' },
|
||||
weight: 0,
|
||||
mutations: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
[{ kind: 'agent_hit', at: 0 }],
|
||||
custom(1),
|
||||
);
|
||||
expect(result.emissions).toHaveLength(1);
|
||||
expect(result.emissions[0].weight).toBe(0);
|
||||
expect(result.estimatedActivationCount).toBe(0);
|
||||
});
|
||||
|
||||
it.each([0, 0.5])(
|
||||
'keeps a weighted reload delay intact at weight %s',
|
||||
(weight) => {
|
||||
const result = evaluateMechanicProgram(
|
||||
{
|
||||
id: 'weighted-reload',
|
||||
name: 'Weighted reload',
|
||||
clauses: [
|
||||
{
|
||||
id: 'weighted-reload-clause',
|
||||
when: 'weapon_hit',
|
||||
reducer: { kind: 'none' },
|
||||
weight,
|
||||
mutations: [],
|
||||
outcomes: [
|
||||
{
|
||||
id: 'reload',
|
||||
label: 'Reload',
|
||||
phase: 'on_event',
|
||||
kind: 'weapon_reload',
|
||||
scope: 'equipped_weapon',
|
||||
value: 5,
|
||||
basis: 'flat',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
[{ kind: 'weapon_hit', at: 1 }],
|
||||
custom(10),
|
||||
);
|
||||
expect(result.outcomes).toHaveLength(1);
|
||||
expect(result.outcomes[0]).toMatchObject({
|
||||
at: 6,
|
||||
weight,
|
||||
resolvedValue: 5,
|
||||
appliedValue: 5,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it('preserves a zero weight for maximum-mode passive outcomes', () => {
|
||||
const result = evaluateMechanicProgram(
|
||||
{
|
||||
id: 'zero-weight-maximum',
|
||||
name: 'Zero weight maximum',
|
||||
clauses: [
|
||||
{
|
||||
id: 'zero-weight-maximum-clause',
|
||||
label: 'Maximum passive',
|
||||
when: 'weapon_hit',
|
||||
reducer: { kind: 'none' },
|
||||
weight: 0,
|
||||
mutations: [],
|
||||
outcomes: [
|
||||
{
|
||||
id: 'marker',
|
||||
label: 'Passive marker',
|
||||
phase: 'while_active',
|
||||
kind: 'marker',
|
||||
scope: 'self',
|
||||
value: 1,
|
||||
basis: 'flat',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
[],
|
||||
{ mode: 'maximum', encounterSeconds: 10 },
|
||||
);
|
||||
expect(result.outcomes).toHaveLength(1);
|
||||
expect(result.outcomes[0]).toMatchObject({ weight: 0, appliedValue: 0 });
|
||||
});
|
||||
|
||||
it('derives proximity stacks directly from a builder-controlled snapshot', () => {
|
||||
const program: MechanicProgram = {
|
||||
id: 'nearby-allies',
|
||||
|
||||
Reference in New Issue
Block a user