merge: complete general turn compatibility

This commit is contained in:
2026-07-25 08:16:27 +00:00
68 changed files with 2466 additions and 970 deletions
@@ -141,7 +141,8 @@ describe('Domestic Affairs Scenario', () => {
// 4. Verify
const updatedCity = world.getCity(1)!;
expect(updatedCity.agriculture).toBe(600);
// 레거시 che_농지개간: 능력치·경험등급·0.8~1.2 난수·성공 배율을 모두 반영한다.
expect(updatedCity.agriculture).toBe(664);
});
it('should not increase agriculture when city is already maxed', async () => {
@@ -195,6 +195,7 @@ describe('General Commands New Scenario', () => {
// 2. Donate
const donateDef = donateSpec.createDefinition(systemEnv);
const expBeforeDonate = world.getGeneral(1)!.experience;
await runner.runTurn([
{
generalId: 1,
@@ -207,6 +208,8 @@ describe('General Commands New Scenario', () => {
const g1_after_donate = world.getGeneral(1)!;
const n1_after_donate = world.getNation(1)!;
expect(g1_after_donate.gold).toBe(900); // 1000 - 100 (Procure cost 0)
expect(g1_after_donate.experience).toBe(expBeforeDonate + 70);
expect(g1_after_donate.meta.leadership_exp).toBe(1);
expect(n1_after_donate.gold).toBeGreaterThan(10100); // 10000 + Procure + 100
// 3. Move
@@ -270,7 +273,8 @@ describe('General Commands New Scenario', () => {
const g1_after_retire = world.getGeneral(1)!;
expect(g1_after_retire.age).toBe(20);
expect(g1_after_retire.experience).toBe(0);
// General::rebirth()는 앞선 명령으로 누적된 경험을 초기화하지 않고 절반으로 줄인다.
expect(g1_after_retire.experience).toBe(142);
});
it('should execute employ and sabotage commands', async () => {
@@ -414,6 +418,7 @@ describe('General Commands New Scenario', () => {
// 1. Employ (G1 -> G2)
const employDef = employSpec.createDefinition(systemEnv);
const goldBeforeEmploy = world.getGeneral(1)!.gold;
await runner.runTurn([
{
generalId: 1,
@@ -423,6 +428,8 @@ describe('General Commands New Scenario', () => {
context: { destGeneral: gen2, env: systemEnv }, // Manual inject for resolver context
},
]);
// 레거시 비용: round(develcost + (대상 경험 + 공헌) / 1000) * 10.
expect(world.getGeneral(1)!.gold).toBe(goldBeforeEmploy - 1_000);
// Verify Logs? (Runner doesn't expose logs easily, but we checks no throw)
@@ -500,7 +507,22 @@ describe('General Commands New Scenario', () => {
commandKey: 'che_선동',
resolver: agitateDef,
args: { destCityId: 2 },
context: { destCity: city2, env: systemEnv },
context: {
destCity: city2,
destNation: nation2,
destGenerals: [gen2],
env: systemEnv,
rng: {
real: () => 0,
int: (min: number, _max: number) => min,
nextInt: (min: number, _max: number) => min,
next: () => 0,
nextBool: () => true,
nextRange: (min: number, _max: number) => min,
nextRangeInt: (min: number, _max: number) => min,
nextFloat1: () => 0,
},
},
},
]);
@@ -521,7 +543,24 @@ describe('General Commands New Scenario', () => {
commandKey: 'che_탈취',
resolver: seizeDef,
args: { destCityId: 2 },
context: { destCity: city2, destNation: nation2, env: systemEnv },
context: {
destCity: city2,
destNation: nation2,
destGenerals: [gen2],
env: systemEnv,
year: 200,
startYear: 200,
rng: {
real: () => 0,
int: (min: number, _max: number) => min,
nextInt: (min: number, _max: number) => min,
next: () => 0,
nextBool: () => true,
nextRange: (min: number, _max: number) => min,
nextRangeInt: (min: number, _max: number) => min,
nextFloat1: () => 0,
},
},
},
]);
@@ -530,7 +569,8 @@ describe('General Commands New Scenario', () => {
const g1_after_seize = world.getGeneral(1)!;
expect(g1_after_seize.gold).toBeGreaterThan(goldBeforeSeize - systemEnv.develCost);
// 레거시는 개발비의 5배를 먼저 소모한 뒤 탈취량의 30%를 개인 몫으로 지급한다.
expect(g1_after_seize.gold).toBe(goldBeforeSeize - systemEnv.develCost * 5 + 1);
expect(getEquippedItemInstance(g1_after_seize, 'item')).toBeNull();
});
});
+6 -2
View File
@@ -145,6 +145,8 @@ describe('Troop Management Scenario', () => {
const generalAfterDraft = world.getGeneral(1)!;
expect(generalAfterDraft.crew).toBe(1000);
// General::addDex(): 보병(armType 1)은 징병 인원 / 100만큼 숙련도가 오른다.
expect(generalAfterDraft.meta.dex1).toBe(10);
// 3. Train
const trainDef = trainSpec.createDefinition(systemEnv);
@@ -158,7 +160,8 @@ describe('Troop Management Scenario', () => {
]);
const generalAfterTrain = world.getGeneral(1)!;
expect(generalAfterTrain.train).toBe(75);
// 레거시 훈련식: round(통솔 * 100 * trainDelta / 병력), 상한까지 적용.
expect(generalAfterTrain.train).toBe(100);
// 4. Boost Morale
const atmosDef = atmosSpec.createDefinition(systemEnv);
@@ -172,6 +175,7 @@ describe('Troop Management Scenario', () => {
]);
const generalAfterAtmos = world.getGeneral(1)!;
expect(generalAfterAtmos.atmos).toBe(75);
// 레거시 사기진작식: round(통솔 * 100 / 병력 * atmosDelta), 명령 상한까지 적용.
expect(generalAfterAtmos.atmos).toBe(100);
});
});