fix: expand general command differential parity

This commit is contained in:
2026-07-26 00:10:47 +00:00
parent edb971ce5c
commit 03a11c7aac
3 changed files with 28 additions and 5 deletions
@@ -56,8 +56,9 @@ normalized to the core `*Id` spelling before command identity comparison.
canonical projection.
- `trace.ts`: before/execute/after capture boundary.
- `compare.ts`: exact snapshot and delta comparison.
- `turnCommandGeneralMatrix.integration.test.ts`: 21 successful general
command paths, including the four-call `전투태세` completion path.
- `turnCommandGeneralMatrix.integration.test.ts`: 29 successful general
command paths, including the four-call `전투태세` completion path and
movement/return/gift/spy/sabotage commands.
- `turnCommandNationMatrix.integration.test.ts`: 8 successful nation
command paths.
- `turnCommandCoreReference.integration.test.ts`: declaration and live
@@ -162,9 +163,9 @@ Compatibility is established per case only when:
4. live sortie also passes the battle trace comparison;
5. any ignored path is documented in the case evidence.
As of 2026-07-25, 21 general cases, 8 nation cases, declaration and live sortie
As of 2026-07-25, 29 general cases, 8 nation cases, declaration and live sortie
pass this boundary. Live sortie covers battle entry, conquest, defeated-general
neutralization and last-city nation collapse. This is 31 executable comparison
neutralization and last-city nation collapse. This is 39 executable comparison
cases, not a claim that all 55 general and 38 nation command classes have been
dynamically compared.
@@ -17,6 +17,17 @@ const ACTION_KEY = 'che_접경귀환';
export interface BorderReturnArgs {}
type InclusiveRandomGenerator = GeneralActionResolveContext['rng'] & {
nextIntInclusive?: (maxInclusive: number) => number;
};
const legacyChoiceIndex = (rng: GeneralActionResolveContext['rng'], length: number): number => {
const inclusive = rng as InclusiveRandomGenerator;
return inclusive.nextIntInclusive
? inclusive.nextIntInclusive(length - 1)
: rng.nextInt(0, length);
};
export interface BorderReturnResolveContext<
TriggerState extends GeneralTriggerState = GeneralTriggerState,
> extends GeneralActionResolveContext<TriggerState> {
@@ -84,7 +95,7 @@ export class ActionDefinition<
return { effects: [] };
}
const targetCity = nearestCities[context.rng.nextInt(0, nearestCities.length)]!;
const targetCity = nearestCities[legacyChoiceIndex(context.rng, nearestCities.length)]!;
const josaRo = JosaUtil.pick(targetCity.name, '로');
context.addLog(`<G><b>${targetCity.name}</b></>${josaRo} 접경귀환했습니다.`, {
scope: LogScope.GENERAL,
@@ -114,6 +114,7 @@ const buildRequest = (
id: 3,
nationId: 1,
population: 100_000,
populationMax: 200_000,
agriculture: 1_000,
commerce: 1_000,
security: 1_000,
@@ -130,6 +131,7 @@ const buildRequest = (
id: 70,
nationId: 2,
population: 100_000,
populationMax: 200_000,
agriculture: 1_000,
commerce: 1_000,
security: 1_000,
@@ -180,6 +182,14 @@ const cases: Array<[string, Record<string, unknown> | undefined, Record<string,
['che_군량매매', { buyRice: true, amount: 100 }, undefined],
['che_물자조달', undefined, undefined],
['che_헌납', { isGold: true, amount: 100 }, undefined],
['che_이동', { destCityID: 70 }, undefined],
['che_강행', { destCityID: 70 }, undefined],
['che_귀환', undefined, { cityId: 70 }],
['che_접경귀환', undefined, { cityId: 70 }],
['che_증여', { isGold: true, amount: 100, destGeneralID: 3 }, undefined],
['che_첩보', { destCityID: 70 }, undefined],
['che_화계', { destCityID: 70 }, undefined],
['che_파괴', { destCityID: 70 }, undefined],
];
integration('general command success matrix', () => {
@@ -197,6 +207,7 @@ integration('general command success matrix', () => {
`${JSON.stringify(
{
action,
coreOutcome: core.execution.outcome,
referenceRng: reference.rng,
coreRng: core.rng,
referenceGeneralDelta: compareTurnSnapshotDeltas(