refactor: enforce package boundaries

This commit is contained in:
2026-08-07 10:13:29 +00:00
parent b1de142440
commit 1a1d0b2d91
64 changed files with 812 additions and 628 deletions
@@ -4,6 +4,7 @@ import type { UnitSetDefinition } from '@sammo-ts/logic/world/types.js';
import type { NationTraitModule } from '@sammo-ts/logic/actionModules/traits/nation/index.js';
import type { RefOrderedActionStack } from '@sammo-ts/logic/actionModules/bundle.js';
import type { ScenarioEffectKey } from '@sammo-ts/logic/scenario/scenarioEffect.js';
import type { TracePort } from '@sammo-ts/logic/ports/trace.js';
export interface TurnCommandItemCatalogEntry {
slot: 'horse' | 'weapon' | 'book' | 'item';
@@ -17,6 +18,7 @@ export interface TurnCommandItemCatalogEntry {
}
export interface TurnCommandEnv {
trace?: TracePort;
unitSet?: UnitSetDefinition;
scenarioEffect?: ScenarioEffectKey | null;
develCost: number;
@@ -124,20 +124,26 @@ export class ActionDefinition<
const generalCount = Math.max(context.nationGeneralCount, this.env.initialNationGenLimit);
if (
(process.env.CORE_AI_TRACE_GENERAL_IDS?.split(',') ?? []).includes(String(context.general.id)) ||
(process.env.CORE_AI_TRACE_NATION_IDS?.split(',') ?? []).includes(String(context.nation.id))
this.env.trace?.isEnabled('AI_ACTION_PATCH_TRACE', {
generalIds: [context.general.id],
nationIds: [context.nation.id],
})
) {
process.stdout.write(
`AI_ACTION_PATCH_TRACE ${JSON.stringify({ engine: 'core-tech', generalId: context.general.id, nationId: context.nation.id, currentTech, techScore, nationGeneralCount: context.nationGeneralCount, generalCount, delta: techScore / generalCount })}\n`
);
this.env.trace.write('AI_ACTION_PATCH_TRACE', {
engine: 'core-tech',
generalId: context.general.id,
nationId: context.nation.id,
currentTech,
techScore,
nationGeneralCount: context.nationGeneralCount,
generalCount,
delta: techScore / generalCount,
});
}
context.nation.meta = {
...context.nation.meta,
tech: addLegacyStoredTech(
currentTech,
techScore / generalCount
),
tech: addLegacyStoredTech(currentTech, techScore / generalCount),
};
context.general.gold = Math.max(0, context.general.gold - result.costGold);
context.general.experience += result.exp;
@@ -39,6 +39,7 @@ import type { MapDefinition, UnitSetDefinition } from '@sammo-ts/logic/world/typ
import type { ActionContextBuilder } from '@sammo-ts/logic/actions/turn/actionContext.js';
import { tryApplyUniqueLottery } from '@sammo-ts/logic/rewards/uniqueLottery.js';
import { buildNationFrontStatePatches } from '../../../diplomacy/frontState.js';
import type { TracePort } from '../../../ports/trace.js';
import { formatDestCityConstraintFailure } from '../constraintFailure.js';
import {
buildWarAftermathConfig,
@@ -380,7 +381,8 @@ export class ActionDefinition<
constructor(
modules: ReadonlyArray<WarActionModule<TriggerState> | null | undefined> = [],
nationTraitModules: NationTraitModule[] = [],
generalModules: ReadonlyArray<GeneralActionModule<TriggerState> | null | undefined> = []
generalModules: ReadonlyArray<GeneralActionModule<TriggerState> | null | undefined> = [],
private readonly trace?: TracePort
) {
this.warModules = modules.filter(Boolean) as ReadonlyArray<WarActionModule<TriggerState>>;
this.nationTraitModules = new Map(nationTraitModules.map((module) => [module.key, module]));
@@ -572,29 +574,25 @@ export class ActionDefinition<
(unitSet.crewTypes?.some((crewType) => crewType.id === general.crewTypeId) ?? false)
)
);
const traceGeneralIds = new Set(process.env.CORE_AI_TRACE_GENERAL_IDS?.split(',') ?? []);
const shouldTraceWar =
traceGeneralIds.has(String(context.general.id)) ||
defenderGenerals.some((general) => traceGeneralIds.has(String(general.id)));
const battleGeneralIds = [context.general.id, ...defenderGenerals.map((general) => general.id)];
const shouldTraceWar = this.trace?.isEnabled('AI_WAR_TRACE', { generalIds: battleGeneralIds }) ?? false;
if (process.env.CORE_BATTLE_FIXTURE_TRACE === '1') {
process.stdout.write(
`AI_WAR_FIXTURE_CORE ${JSON.stringify({
action: 'battle',
seed,
repeatCnt: 1,
year: time.year,
month: time.month,
startYear: time.startYear,
scenarioEffect: null,
attackerGeneral: buildBattleGeneralFixture(context.general),
attackerCity: buildBattleCityFixture(attackerCity),
attackerNation: buildBattleNationFixture(attackerNation),
defenderGenerals: defenderGenerals.map(buildBattleGeneralFixture),
defenderCity: buildBattleCityFixture(defenderCity),
defenderNation: buildBattleNationFixture(defenderNation),
})}\n`
);
if (this.trace?.isEnabled('AI_WAR_FIXTURE_CORE', { generalIds: battleGeneralIds })) {
this.trace.write('AI_WAR_FIXTURE_CORE', {
action: 'battle',
seed,
repeatCnt: 1,
year: time.year,
month: time.month,
startYear: time.startYear,
scenarioEffect: null,
attackerGeneral: buildBattleGeneralFixture(context.general),
attackerCity: buildBattleCityFixture(attackerCity),
attackerNation: buildBattleNationFixture(attackerNation),
defenderGenerals: defenderGenerals.map(buildBattleGeneralFixture),
defenderCity: buildBattleCityFixture(defenderCity),
defenderNation: buildBattleNationFixture(defenderNation),
});
}
const battle = resolveWarBattle({
@@ -619,9 +617,7 @@ export class ActionDefinition<
...(shouldTraceWar
? {
trace: (event) => {
process.stdout.write(
`AI_WAR_TRACE ${JSON.stringify({ generalId: context.general.id, event })}\n`
);
this.trace?.write('AI_WAR_TRACE', { generalId: context.general.id, event });
},
}
: {}),
@@ -648,6 +644,7 @@ export class ActionDefinition<
baseGain
);
},
...(this.trace ? { trace: this.trace } : {}),
});
// Ref ConquerCity() recalculates the fronts of every nation around the
@@ -802,5 +799,10 @@ export const commandSpec: GeneralTurnCommandSpec = {
availabilityArgs: { destCityId: 0 },
argsSchema: ARGS_SCHEMA,
createDefinition: (env: TurnCommandEnv) =>
new ActionDefinition(env.warActionModules ?? [], env.nationTraitModules ?? [], env.generalActionModules ?? []),
new ActionDefinition(
env.warActionModules ?? [],
env.nationTraitModules ?? [],
env.generalActionModules ?? [],
env.trace
),
};