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
@@ -12,6 +12,9 @@ import { createItemActionModules, createItemModuleRegistry } from '../src/items/
import { getEquippedItemInstance } from '../src/items/inventory.js';
import { itemModule as dogiModule } from '../src/items/che_보물_도기.js';
import { itemModule as strategyItemModule } from '../src/items/che_계략_이추.js';
import { itemModule as leadershipWineModule } from '../src/items/che_능력치_통솔_보령압주.js';
import { itemModule as strengthWineModule } from '../src/items/che_능력치_무력_두강주.js';
import { itemModule as intelligenceWineModule } from '../src/items/che_능력치_지력_이강주.js';
import { LogFormat } from '../src/logging/types.js';
const BASE_ENV: TurnCommandEnv = {
@@ -109,6 +112,31 @@ const dogiCatalog: Record<string, TurnCommandItemCatalogEntry> = {
},
};
const scalingStatItems = [
{ module: leadershipWineModule, statName: 'leadership' as const },
{ module: strengthWineModule, statName: 'strength' as const },
{ module: intelligenceWineModule, statName: 'intelligence' as const },
];
describe('year-scaling stat items', () => {
it.each([
{ year: 180, startYear: 180, maxTechLevel: 12, expected: 75 },
{ year: 200, startYear: 180, maxTechLevel: 12, expected: 80 },
{ year: 260, startYear: 180, maxTechLevel: 12, expected: 87 },
{ year: 260, startYear: 180, maxTechLevel: 15, expected: 90 },
])('applies +5, four-year growth, and the $maxTechLevel cap', ({ year, startYear, maxTechLevel, expected }) => {
const context = {
general: makeGeneral(null),
time: { year, month: 1, startYear },
maxTechLevel,
};
for (const { module, statName } of scalingStatItems) {
expect(module.onCalcStat?.(context, statName, 70)).toBe(expected);
}
});
});
const createItemOnlyStack = (items: ReturnType<typeof createItemActionModules>['general']) => {
const noOp = {};
return createRefOrderedActionStack({