Add sabotage value boundary parity
This commit is contained in:
@@ -554,6 +554,101 @@ integration('general sabotage probability clamp matrix', () => {
|
||||
);
|
||||
});
|
||||
|
||||
type SabotageValueBoundaryCase = {
|
||||
name: string;
|
||||
action: 'che_화계' | 'che_선동' | 'che_파괴' | 'che_탈취';
|
||||
stat: 'leadership' | 'strength' | 'intelligence';
|
||||
fixturePatches: FixturePatches;
|
||||
};
|
||||
|
||||
const sabotageValueBoundaryCases: SabotageValueBoundaryCase[] = [
|
||||
{
|
||||
name: 'fire attack does not reduce agriculture or commerce below zero',
|
||||
action: 'che_화계',
|
||||
stat: 'intelligence',
|
||||
fixturePatches: { cities: { 70: { agriculture: 1, commerce: 1 } } },
|
||||
},
|
||||
{
|
||||
name: 'agitation does not reduce security or trust below zero',
|
||||
action: 'che_선동',
|
||||
stat: 'leadership',
|
||||
fixturePatches: { cities: { 70: { security: 1, trust: 1 } } },
|
||||
},
|
||||
{
|
||||
name: 'destruction does not reduce defence or wall below zero',
|
||||
action: 'che_파괴',
|
||||
stat: 'strength',
|
||||
fixturePatches: { cities: { 70: { defence: 1, wall: 1 } } },
|
||||
},
|
||||
{
|
||||
name: 'seizure does not take more than supplied nation resources',
|
||||
action: 'che_탈취',
|
||||
stat: 'strength',
|
||||
fixturePatches: { nations: { 2: { gold: 1, rice: 1 } } },
|
||||
},
|
||||
{
|
||||
name: 'seizure does not reduce unsupplied city resources below zero',
|
||||
action: 'che_탈취',
|
||||
stat: 'strength',
|
||||
fixturePatches: {
|
||||
cities: { 70: { agriculture: 1, commerce: 1, supplyState: 0 } },
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const hasSuccessfulSabotageLog = (logs: Array<Record<string, unknown>>): boolean =>
|
||||
logs.some((entry) => typeof entry.text === 'string' && entry.text.includes('성공했습니다.'));
|
||||
|
||||
integration('general sabotage value boundary matrix', () => {
|
||||
it.each(sabotageValueBoundaryCases)(
|
||||
'$name matches the legacy clamped state delta',
|
||||
async ({ action, stat, fixturePatches }) => {
|
||||
const request = buildRequest(
|
||||
action,
|
||||
{ destCityID: 70 },
|
||||
{ [stat]: 100 },
|
||||
{
|
||||
...fixturePatches,
|
||||
generals: {
|
||||
...fixturePatches.generals,
|
||||
2: { ...fixturePatches.generals?.[2], [stat]: 10 },
|
||||
},
|
||||
cities: {
|
||||
...fixturePatches.cities,
|
||||
70: {
|
||||
...fixturePatches.cities?.[70],
|
||||
security: 0,
|
||||
securityMax: 2_000,
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
request.setup!.world!.hiddenSeed = 'general-value-0';
|
||||
const reference = runReferenceTurnCommandTraceRequest(
|
||||
workspaceRoot!,
|
||||
request as unknown as Record<string, unknown>
|
||||
);
|
||||
const core = await runCoreTurnCommandTrace(request, reference.before);
|
||||
|
||||
expect(reference.execution.outcome).toMatchObject({ completed: true });
|
||||
expect(core.execution.outcome).toMatchObject({
|
||||
requestedAction: action,
|
||||
actionKey: action,
|
||||
usedFallback: false,
|
||||
});
|
||||
expect(hasSuccessfulSabotageLog(reference.after.logs)).toBe(true);
|
||||
expect(hasSuccessfulSabotageLog(core.after.logs)).toBe(true);
|
||||
expect(core.rng).toEqual(reference.rng);
|
||||
expect(
|
||||
compareTurnSnapshotDeltas(reference.before, reference.after, core.before, core.after, {
|
||||
ignoredPathPatterns: ignoredLifecyclePaths,
|
||||
})
|
||||
).toEqual([]);
|
||||
},
|
||||
120_000
|
||||
);
|
||||
});
|
||||
|
||||
type GeneralConstraintCase = {
|
||||
name: string;
|
||||
action: string;
|
||||
|
||||
Reference in New Issue
Block a user