멸망 후 등용장에 현재 임관 모드 적용
This commit is contained in:
@@ -2825,6 +2825,7 @@ export const createImmediateGeneralActionExecutor = async (options: {
|
||||
baseContext,
|
||||
{
|
||||
world: state,
|
||||
worldConfig: options.world.getWorldConfig(),
|
||||
scenarioConfig: options.world.getScenarioConfig(),
|
||||
scenarioMeta: options.scenarioMeta,
|
||||
map: options.map,
|
||||
|
||||
@@ -76,6 +76,8 @@ export interface ActionContextWorldRef {
|
||||
|
||||
export interface ActionContextOptions<TArgs extends Record<string, unknown> = Record<string, unknown>> {
|
||||
world: ActionContextWorldState;
|
||||
/** Current game configuration, distinct from the legacy world meta. */
|
||||
worldConfig?: Record<string, unknown>;
|
||||
/** Ref Message::sendRaw stamps the current logical game tick, not the actor turn time. */
|
||||
gameNow?: Date;
|
||||
/** Differential fixtures may point shared message icons at the Ref asset origin. */
|
||||
|
||||
@@ -824,7 +824,11 @@ export const actionContextBuilder: ActionContextBuilder = (base, options) => {
|
||||
const diplomacy = options.worldRef.listDiplomacy();
|
||||
const warConfig = buildWarConfig(options.scenarioConfig, options.unitSet);
|
||||
const aftermathConfig = buildWarAftermathConfig(options.scenarioConfig, warConfig.castleCrewTypeId);
|
||||
const joinModeRaw = options.world.meta?.join_mode ?? options.world.meta?.joinMode;
|
||||
const joinModeRaw =
|
||||
options.worldConfig?.join_mode ??
|
||||
options.worldConfig?.joinMode ??
|
||||
options.world.meta?.join_mode ??
|
||||
options.world.meta?.joinMode;
|
||||
aftermathConfig.joinMode = joinModeRaw === 'onlyRandom' ? 'onlyRandom' : 'full';
|
||||
return {
|
||||
...base,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest';
|
||||
|
||||
import type { City, General, Nation } from '../src/domain/entities.js';
|
||||
import { resolveGeneralAction } from '../src/actions/engine.js';
|
||||
import { ActionDefinition, orderDefenderGenerals } from '../src/actions/turn/general/che_출병.js';
|
||||
import { ActionDefinition, actionContextBuilder, orderDefenderGenerals } from '../src/actions/turn/general/che_출병.js';
|
||||
import type { DispatchResolveContext } from '../src/actions/turn/general/che_출병.js';
|
||||
import type { TurnSchedule } from '../src/turn/calendar.js';
|
||||
import type { WarAftermathConfig, WarEngineConfig } from '../src/war/types.js';
|
||||
@@ -192,6 +192,44 @@ const uniqueItem: ItemModule = {
|
||||
};
|
||||
|
||||
describe('che_출병', () => {
|
||||
it.each(['full', 'onlyRandom'] as const)(
|
||||
'reads %s join mode from current world config for collapse aftermath',
|
||||
(joinMode) => {
|
||||
const general = { ...buildGeneral(1, 1, 1), turnTime: new Date('0200-01-01T00:00:00.000Z') };
|
||||
const destination = buildCity(2, 2);
|
||||
const context = actionContextBuilder(
|
||||
{ general, rng },
|
||||
{
|
||||
world: { currentYear: 200, currentMonth: 1, tickSeconds: 3600, meta: { joinMode: 'full' } },
|
||||
worldConfig: { joinMode },
|
||||
scenarioConfig: {
|
||||
stat: { total: 0, min: 0, max: 0, npcTotal: 0, npcMin: 0, npcMax: 0, chiefMin: 0 },
|
||||
iconPath: '',
|
||||
map: {},
|
||||
const: {},
|
||||
environment: { mapName: 'test', unitSet: 'test' },
|
||||
},
|
||||
map: { id: 'test', name: 'test', cities: [] },
|
||||
unitSet,
|
||||
worldRef: {
|
||||
getCityById: () => destination,
|
||||
getNationById: () => buildNation(2),
|
||||
listCities: () => [destination],
|
||||
listNations: () => [buildNation(2)],
|
||||
listGenerals: () => [general],
|
||||
listDiplomacy: () => [],
|
||||
} as never,
|
||||
actionArgs: { destCityId: destination.id },
|
||||
createGeneralId: () => 3,
|
||||
createNationId: () => 3,
|
||||
seedBase: 'test',
|
||||
}
|
||||
);
|
||||
|
||||
expect(context?.aftermathConfig).toMatchObject({ joinMode });
|
||||
}
|
||||
);
|
||||
|
||||
it('runs war battle and emits patches/logs', () => {
|
||||
const attackerNation = buildNation(1);
|
||||
const defenderNation = buildNation(2);
|
||||
@@ -494,7 +532,7 @@ describe('che_출병', () => {
|
||||
// assignment, so the aftermath alone would not patch it).
|
||||
const defenderPatch = resolution.patches?.generals.find((patch) => patch.id === defender.id);
|
||||
expect(defenderPatch).toBeDefined();
|
||||
expect((defenderPatch?.patch.crew ?? defender.crew)).toBeLessThan(1500);
|
||||
expect(defenderPatch?.patch.crew ?? defender.crew).toBeLessThan(1500);
|
||||
});
|
||||
|
||||
it('orders equal-priority defender inputs by general number before the stable battle sort', () => {
|
||||
|
||||
@@ -726,6 +726,45 @@ describe('war aftermath', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not draw or send collapse recruitment in random-only mode', () => {
|
||||
const attackerNation = buildNation(1);
|
||||
const defenderNation = buildNation(2);
|
||||
defenderNation.chiefGeneralId = 2;
|
||||
const attackerCity = buildCity(1, 1);
|
||||
const defenderCity = buildCity(2, 2);
|
||||
const attacker = buildGeneral(1, 1, 1);
|
||||
const lord = buildGeneral(2, 2, 2);
|
||||
lord.officerLevel = 12;
|
||||
lord.npcState = 2;
|
||||
const rng = {
|
||||
nextRange: vi.fn(() => 0.2),
|
||||
nextBool: vi.fn(() => true),
|
||||
nextRangeInt: vi.fn(() => 1),
|
||||
} as unknown as RandUtil;
|
||||
|
||||
const outcome = resolveWarAftermath({
|
||||
battle: { attacker, defenders: [], defenderCity, logs: [], conquered: true, reports: [] },
|
||||
attackerNation,
|
||||
defenderNation,
|
||||
attackerCity,
|
||||
defenderCity,
|
||||
nations: [attackerNation, defenderNation],
|
||||
cities: [attackerCity, defenderCity],
|
||||
generals: [attacker, lord],
|
||||
unitSet: buildUnitSet(),
|
||||
map: DEFAULT_MAP,
|
||||
config: { ...buildConfig(), joinMode: 'onlyRandom' },
|
||||
time: { year: 186, month: 1, startYear: 179 },
|
||||
messageTime: MESSAGE_TIME,
|
||||
rng,
|
||||
});
|
||||
|
||||
expect(outcome.conquest?.nationCollapsed).toBe(true);
|
||||
expect(outcome.conquest?.messages).toEqual([]);
|
||||
expect(outcome.conquest?.ruinedNpcJoinPlans).toEqual([]);
|
||||
expect(rng.nextBool).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('dispatches city conquest to every stationed defender before collapse RNG', () => {
|
||||
const rng = new RandUtil(new ConstantRNG(0));
|
||||
const draws = [0.01, 0.02, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7];
|
||||
|
||||
Reference in New Issue
Block a user