fix: Ref 게임 로직과 시나리오 풀 호환을 보정

월 경계, 전투 기술 상한, 연감과 베팅·설문·경매 정산 순서를 Ref 계약에 맞춘다.\n\n시나리오 일반 풀을 ENGINE mutation과 logical tick 기반으로 직렬화하고 914·915 catalog 및 조건부 100기 pool 실행 경계를 추가한다.\n\n경매 worker는 세대별 durable event만 만들고 ENGINE이 row lock 후 상태 전이와 정산을 단일 transaction으로 소유한다.
This commit is contained in:
2026-08-23 16:26:14 +00:00
parent bf6b7be7b0
commit 85591c68ad
114 changed files with 13327 additions and 901 deletions
+39
View File
@@ -166,6 +166,45 @@ const buildGeneral = (strength: number): General => ({
});
describe('war triggers', () => {
it('passes battle time and maximum tech level to year-scaling stat items', async () => {
const general = buildGeneral(80);
const [leadershipWine] = await loadItemModules(['che_능력치_통솔_보령압주']);
expect(leadershipWine).toBeDefined();
const unit = new WarUnitGeneral(
new RandUtil(new ConstantRNG(0)),
{ ...buildConfig(), maxTechLevel: 15 },
general,
buildCity(),
buildNation(),
true,
new WarCrewType(buildUnitSet().crewTypes![0]!),
new ActionLogger({ generalId: 1, nationId: 1 }),
new WarActionPipeline([leadershipWine!]),
{ year: 260, month: 1, startYear: 180 }
);
expect(unit.getComputedStat('leadership', general.stats.leadership, { withInjury: false })).toBe(90);
});
it('uses the battle config maximum tech level for combat ability', () => {
const nation = buildNation();
nation.meta.tech = 15_000;
const unit = new WarUnitGeneral(
new RandUtil(new ConstantRNG(0)),
{ ...buildConfig(), maxTechLevel: 15 },
buildGeneral(80),
buildCity(),
nation,
true,
new WarCrewType(buildUnitSet().crewTypes![0]!),
new ActionLogger({ generalId: 1, nationId: 1 }),
new WarActionPipeline([]),
{ year: 200, month: 1, startYear: 180 }
);
expect(unit.getComputedAttack()).toBeCloseTo(608, 12);
});
it('normalizes accumulated dexterity to the PHP SQL float precision', () => {
const general = buildGeneral(80);
general.meta.dex4 = 14_677.199999999997;