fix faction disband state and log parity
This commit is contained in:
@@ -70,6 +70,7 @@ export const createMonthlyWanderHandler = (options: {
|
|||||||
belong: 0,
|
belong: 0,
|
||||||
officer_city: 0,
|
officer_city: 0,
|
||||||
officerCity: 0,
|
officerCity: 0,
|
||||||
|
permission: 'normal',
|
||||||
...(general.npcState < 2 ? { max_belong: Math.max(belong, maxBelong) } : {}),
|
...(general.npcState < 2 ? { max_belong: Math.max(belong, maxBelong) } : {}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -150,7 +151,7 @@ export const createMonthlyWanderHandler = (options: {
|
|||||||
});
|
});
|
||||||
world.pushLog({
|
world.pushLog({
|
||||||
scope: LogScope.SYSTEM,
|
scope: LogScope.SYSTEM,
|
||||||
category: LogCategory.ACTION,
|
category: LogCategory.SUMMARY,
|
||||||
text: `<Y>${wanderer.name}</>${wandererNameJosaYi} 세력을 해산했습니다.`,
|
text: `<Y>${wanderer.name}</>${wandererNameJosaYi} 세력을 해산했습니다.`,
|
||||||
format: LogFormat.MONTH,
|
format: LogFormat.MONTH,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const buildGeneral = (options: {
|
|||||||
gold: number;
|
gold: number;
|
||||||
rice: number;
|
rice: number;
|
||||||
belong: number;
|
belong: number;
|
||||||
|
permission?: string;
|
||||||
turnTime: Date;
|
turnTime: Date;
|
||||||
}): TurnGeneral => ({
|
}): TurnGeneral => ({
|
||||||
id: options.id,
|
id: options.id,
|
||||||
@@ -43,7 +44,7 @@ const buildGeneral = (options: {
|
|||||||
age: 20,
|
age: 20,
|
||||||
npcState: options.npcState,
|
npcState: options.npcState,
|
||||||
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
meta: { killturn: 0, makelimit: 0, belong: options.belong },
|
meta: { killturn: 0, makelimit: 0, belong: options.belong, permission: options.permission ?? 'normal' },
|
||||||
turnTime: options.turnTime,
|
turnTime: options.turnTime,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -130,6 +131,7 @@ describe('monthly wandering nation cleanup', () => {
|
|||||||
gold: 2_000,
|
gold: 2_000,
|
||||||
rice: 3_000,
|
rice: 3_000,
|
||||||
belong: 7,
|
belong: 7,
|
||||||
|
permission: 'ambassador',
|
||||||
turnTime: new Date('0195-02-01T12:28:00.000Z'),
|
turnTime: new Date('0195-02-01T12:28:00.000Z'),
|
||||||
}),
|
}),
|
||||||
buildGeneral({
|
buildGeneral({
|
||||||
@@ -142,6 +144,7 @@ describe('monthly wandering nation cleanup', () => {
|
|||||||
gold: 1_500,
|
gold: 1_500,
|
||||||
rice: 4_000,
|
rice: 4_000,
|
||||||
belong: 5,
|
belong: 5,
|
||||||
|
permission: 'auditor',
|
||||||
turnTime: new Date('0195-02-01T12:53:00.000Z'),
|
turnTime: new Date('0195-02-01T12:53:00.000Z'),
|
||||||
}),
|
}),
|
||||||
buildGeneral({
|
buildGeneral({
|
||||||
@@ -180,14 +183,14 @@ describe('monthly wandering nation cleanup', () => {
|
|||||||
gold: 1_000,
|
gold: 1_000,
|
||||||
rice: 1_000,
|
rice: 1_000,
|
||||||
lastTurn: { command: '해산', arg: {} },
|
lastTurn: { command: '해산', arg: {} },
|
||||||
meta: { belong: 0, makelimit: 12 },
|
meta: { belong: 0, makelimit: 12, permission: 'normal' },
|
||||||
});
|
});
|
||||||
expect(world.getGeneralById(2)).toMatchObject({
|
expect(world.getGeneralById(2)).toMatchObject({
|
||||||
nationId: 0,
|
nationId: 0,
|
||||||
officerLevel: 0,
|
officerLevel: 0,
|
||||||
gold: 1_000,
|
gold: 1_000,
|
||||||
rice: 4_000,
|
rice: 4_000,
|
||||||
meta: { belong: 0, max_belong: 5 },
|
meta: { belong: 0, max_belong: 5, permission: 'normal' },
|
||||||
});
|
});
|
||||||
expect(world.getGeneralById(3)).toMatchObject({
|
expect(world.getGeneralById(3)).toMatchObject({
|
||||||
nationId: 1,
|
nationId: 1,
|
||||||
@@ -264,7 +267,7 @@ describe('monthly wandering nation cleanup', () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
scope: LogScope.SYSTEM,
|
scope: LogScope.SYSTEM,
|
||||||
category: LogCategory.ACTION,
|
category: LogCategory.SUMMARY,
|
||||||
text: '<Y>방랑주</>가 세력을 해산했습니다.',
|
text: '<Y>방랑주</>가 세력을 해산했습니다.',
|
||||||
format: LogFormat.MONTH,
|
format: LogFormat.MONTH,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ const buildGeneral = (options: {
|
|||||||
gold: number;
|
gold: number;
|
||||||
rice: number;
|
rice: number;
|
||||||
belong: number;
|
belong: number;
|
||||||
|
permission?: string;
|
||||||
turnTime: Date;
|
turnTime: Date;
|
||||||
}): TurnGeneral => ({
|
}): TurnGeneral => ({
|
||||||
id: options.id,
|
id: options.id,
|
||||||
@@ -53,7 +54,7 @@ const buildGeneral = (options: {
|
|||||||
age: 20,
|
age: 20,
|
||||||
npcState: options.npcState,
|
npcState: options.npcState,
|
||||||
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
meta: { killturn: 0, makelimit: 0, belong: options.belong },
|
meta: { killturn: 0, makelimit: 0, belong: options.belong, permission: options.permission ?? 'normal' },
|
||||||
turnTime: options.turnTime,
|
turnTime: options.turnTime,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -155,6 +156,7 @@ integration('monthly wandering nation persistence', () => {
|
|||||||
gold: 2_000,
|
gold: 2_000,
|
||||||
rice: 3_000,
|
rice: 3_000,
|
||||||
belong: 7,
|
belong: 7,
|
||||||
|
permission: 'ambassador',
|
||||||
turnTime: new Date('0195-02-01T12:28:00.000Z'),
|
turnTime: new Date('0195-02-01T12:28:00.000Z'),
|
||||||
}),
|
}),
|
||||||
buildGeneral({
|
buildGeneral({
|
||||||
@@ -167,6 +169,7 @@ integration('monthly wandering nation persistence', () => {
|
|||||||
gold: 1_500,
|
gold: 1_500,
|
||||||
rice: 4_000,
|
rice: 4_000,
|
||||||
belong: 5,
|
belong: 5,
|
||||||
|
permission: 'auditor',
|
||||||
turnTime: new Date('0195-02-01T12:53:00.000Z'),
|
turnTime: new Date('0195-02-01T12:53:00.000Z'),
|
||||||
}),
|
}),
|
||||||
buildGeneral({
|
buildGeneral({
|
||||||
@@ -336,14 +339,14 @@ integration('monthly wandering nation persistence', () => {
|
|||||||
gold: 1_000,
|
gold: 1_000,
|
||||||
rice: 1_000,
|
rice: 1_000,
|
||||||
lastTurn: { command: '해산', arg: {} },
|
lastTurn: { command: '해산', arg: {} },
|
||||||
meta: expect.objectContaining({ belong: 0, makelimit: 12 }),
|
meta: expect.objectContaining({ belong: 0, makelimit: 12, permission: 'normal' }),
|
||||||
}),
|
}),
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
nationId: 0,
|
nationId: 0,
|
||||||
officerLevel: 0,
|
officerLevel: 0,
|
||||||
gold: 1_000,
|
gold: 1_000,
|
||||||
rice: 4_000,
|
rice: 4_000,
|
||||||
meta: expect.objectContaining({ belong: 0, max_belong: 5 }),
|
meta: expect.objectContaining({ belong: 0, max_belong: 5, permission: 'normal' }),
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
expect(await db.city.findUniqueOrThrow({ where: { id: cityIds[0]! } })).toMatchObject({
|
expect(await db.city.findUniqueOrThrow({ where: { id: cityIds[0]! } })).toMatchObject({
|
||||||
@@ -443,7 +446,7 @@ integration('monthly wandering nation persistence', () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
scope: 'SYSTEM',
|
scope: 'SYSTEM',
|
||||||
category: 'ACTION',
|
category: 'SUMMARY',
|
||||||
generalId: null,
|
generalId: null,
|
||||||
year: 195,
|
year: 195,
|
||||||
month: 2,
|
month: 2,
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ export class ActionResolver<
|
|||||||
// 2. Recruiter Rewards
|
// 2. Recruiter Rewards
|
||||||
const recruiterExperience = destGeneral.experience + 100;
|
const recruiterExperience = destGeneral.experience + 100;
|
||||||
const recruiterDedication = destGeneral.dedication + 100;
|
const recruiterDedication = destGeneral.dedication + 100;
|
||||||
|
const belong = readMetaNumberFromUnknown(general.meta, 'belong') ?? 0;
|
||||||
|
const maxBelong = readMetaNumberFromUnknown(general.meta, 'max_belong') ?? 0;
|
||||||
const recruiterExpLevel = Math.max(
|
const recruiterExpLevel = Math.max(
|
||||||
0,
|
0,
|
||||||
Math.min(
|
Math.min(
|
||||||
@@ -242,6 +244,7 @@ export class ActionResolver<
|
|||||||
...(general.npcState < 2
|
...(general.npcState < 2
|
||||||
? {
|
? {
|
||||||
killturn: context.worldKillturn ?? general.meta.killturn,
|
killturn: context.worldKillturn ?? general.meta.killturn,
|
||||||
|
max_belong: Math.max(belong, maxBelong),
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import type {
|
|||||||
import {
|
import {
|
||||||
createCityPatchEffect,
|
createCityPatchEffect,
|
||||||
createGeneralPatchEffect,
|
createGeneralPatchEffect,
|
||||||
|
createLogEffect,
|
||||||
createNationPatchEffect,
|
createNationPatchEffect,
|
||||||
} from '@sammo-ts/logic/actions/engine.js';
|
} from '@sammo-ts/logic/actions/engine.js';
|
||||||
import { LogCategory, LogFormat, LogScope } from '@sammo-ts/logic/logging/types.js';
|
import { LogCategory, LogFormat, LogScope } from '@sammo-ts/logic/logging/types.js';
|
||||||
@@ -22,6 +23,9 @@ import type { GeneralTurnCommandSpec } from './index.js';
|
|||||||
const ACTION_NAME = '해산';
|
const ACTION_NAME = '해산';
|
||||||
const ACTION_KEY = 'che_해산';
|
const ACTION_KEY = 'che_해산';
|
||||||
|
|
||||||
|
const readMetaNumber = (value: unknown): number =>
|
||||||
|
typeof value === 'number' && Number.isFinite(value) ? value : 0;
|
||||||
|
|
||||||
export interface DisbandFactionArgs {}
|
export interface DisbandFactionArgs {}
|
||||||
|
|
||||||
export interface DisbandFactionResolveContext<
|
export interface DisbandFactionResolveContext<
|
||||||
@@ -76,6 +80,8 @@ export class ActionDefinition<
|
|||||||
const nationGenerals = context.nationGenerals ?? [];
|
const nationGenerals = context.nationGenerals ?? [];
|
||||||
for (const targetGeneral of nationGenerals) {
|
for (const targetGeneral of nationGenerals) {
|
||||||
const isActor = targetGeneral.id === general.id;
|
const isActor = targetGeneral.id === general.id;
|
||||||
|
const belong = readMetaNumber(targetGeneral.meta.belong);
|
||||||
|
const maxBelong = readMetaNumber(targetGeneral.meta.max_belong);
|
||||||
effects.push(
|
effects.push(
|
||||||
createGeneralPatchEffect(
|
createGeneralPatchEffect(
|
||||||
{
|
{
|
||||||
@@ -92,6 +98,8 @@ export class ActionDefinition<
|
|||||||
belong: 0,
|
belong: 0,
|
||||||
officer_city: 0,
|
officer_city: 0,
|
||||||
officerCity: 0,
|
officerCity: 0,
|
||||||
|
permission: 'normal',
|
||||||
|
...(targetGeneral.npcState < 2 ? { max_belong: Math.max(belong, maxBelong) } : {}),
|
||||||
...(isActor ? { makelimit: 12 } : {}),
|
...(isActor ? { makelimit: 12 } : {}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -135,13 +143,39 @@ export class ActionDefinition<
|
|||||||
});
|
});
|
||||||
context.addLog(`<Y>${general.name}</>${josaYi} 세력을 해산했습니다.`, {
|
context.addLog(`<Y>${general.name}</>${josaYi} 세력을 해산했습니다.`, {
|
||||||
scope: LogScope.SYSTEM,
|
scope: LogScope.SYSTEM,
|
||||||
category: LogCategory.ACTION,
|
category: LogCategory.SUMMARY,
|
||||||
});
|
});
|
||||||
context.addLog(`<D><b>${nation.name}</b></>${josaUl} 해산`, {
|
context.addLog(`<D><b>${nation.name}</b></>${josaUl} 해산`, {
|
||||||
scope: LogScope.GENERAL,
|
scope: LogScope.GENERAL,
|
||||||
category: LogCategory.HISTORY,
|
category: LogCategory.HISTORY,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const josaUn = JosaUtil.pick(nation.name, '은');
|
||||||
|
const josaNationYi = JosaUtil.pick(nation.name, '이');
|
||||||
|
effects.push(
|
||||||
|
createLogEffect(`<R><b>【멸망】</b></><D><b>${nation.name}</b></>${josaUn} <R>멸망</>했습니다.`, {
|
||||||
|
scope: LogScope.SYSTEM,
|
||||||
|
category: LogCategory.HISTORY,
|
||||||
|
format: LogFormat.YEAR_MONTH,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
for (const targetGeneral of nationGenerals) {
|
||||||
|
effects.push(
|
||||||
|
createLogEffect(`<D><b>${nation.name}</b></>${josaNationYi} <R>멸망</>했습니다.`, {
|
||||||
|
scope: LogScope.GENERAL,
|
||||||
|
category: LogCategory.ACTION,
|
||||||
|
format: LogFormat.PLAIN,
|
||||||
|
generalId: targetGeneral.id,
|
||||||
|
}),
|
||||||
|
createLogEffect(`<D><b>${nation.name}</b></>${josaNationYi} <R>멸망</>`, {
|
||||||
|
scope: LogScope.GENERAL,
|
||||||
|
category: LogCategory.HISTORY,
|
||||||
|
format: LogFormat.YEAR_MONTH,
|
||||||
|
generalId: targetGeneral.id,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return { effects };
|
return { effects };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ describe('che_등용수락', () => {
|
|||||||
age: 20,
|
age: 20,
|
||||||
npcState: 0,
|
npcState: 0,
|
||||||
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
meta: { killturn: 24 },
|
meta: { killturn: 24, belong: 10, max_belong: 2 },
|
||||||
};
|
};
|
||||||
|
|
||||||
const recruiterGen: General = {
|
const recruiterGen: General = {
|
||||||
@@ -244,6 +244,11 @@ describe('che_등용수락', () => {
|
|||||||
expect(updatedSelf?.cityId).toBe(102); // Capital of Nation2
|
expect(updatedSelf?.cityId).toBe(102); // Capital of Nation2
|
||||||
expect(updatedSelf?.experience).toBe(100);
|
expect(updatedSelf?.experience).toBe(100);
|
||||||
expect(updatedSelf?.dedication).toBe(100);
|
expect(updatedSelf?.dedication).toBe(100);
|
||||||
|
expect(updatedSelf?.meta).toMatchObject({
|
||||||
|
belong: 1,
|
||||||
|
max_belong: 10,
|
||||||
|
permission: 'normal',
|
||||||
|
});
|
||||||
|
|
||||||
expect(updatedRecruiter?.experience).toBe(100);
|
expect(updatedRecruiter?.experience).toBe(100);
|
||||||
expect(updatedRecruiter?.dedication).toBe(100);
|
expect(updatedRecruiter?.dedication).toBe(100);
|
||||||
|
|||||||
@@ -253,8 +253,26 @@ describe('migrated general commands', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('che_해산: 방랑군 해산 시 세력과 소속을 정리한다', async () => {
|
it('che_해산: 방랑군 해산 시 세력과 소속을 정리한다', async () => {
|
||||||
const lord = makeGeneral({ id: 1, nationId: 1, cityId: 1, name: '군주', officerLevel: 12, gold: 1500, rice: 1800 });
|
const lord = makeGeneral({
|
||||||
const member = makeGeneral({ id: 2, nationId: 1, cityId: 2, name: '부하', officerLevel: 1, gold: 2500, rice: 500 });
|
id: 1,
|
||||||
|
nationId: 1,
|
||||||
|
cityId: 1,
|
||||||
|
name: '군주',
|
||||||
|
officerLevel: 12,
|
||||||
|
gold: 1500,
|
||||||
|
rice: 1800,
|
||||||
|
meta: { belong: 5, max_belong: 2, permission: 'ambassador' },
|
||||||
|
});
|
||||||
|
const member = makeGeneral({
|
||||||
|
id: 2,
|
||||||
|
nationId: 1,
|
||||||
|
cityId: 2,
|
||||||
|
name: '부하',
|
||||||
|
officerLevel: 1,
|
||||||
|
gold: 2500,
|
||||||
|
rice: 500,
|
||||||
|
meta: { belong: 7, max_belong: 3, permission: 'auditor' },
|
||||||
|
});
|
||||||
const nation = makeNation({
|
const nation = makeNation({
|
||||||
id: 1,
|
id: 1,
|
||||||
name: '방랑군',
|
name: '방랑군',
|
||||||
@@ -294,6 +312,8 @@ describe('migrated general commands', () => {
|
|||||||
expect(updatedLord.meta.makelimit).toBe(12);
|
expect(updatedLord.meta.makelimit).toBe(12);
|
||||||
expect(updatedLord.gold).toBe(1000);
|
expect(updatedLord.gold).toBe(1000);
|
||||||
expect(updatedMember.gold).toBe(1000);
|
expect(updatedMember.gold).toBe(1000);
|
||||||
|
expect(updatedLord.meta).toMatchObject({ belong: 0, max_belong: 5, permission: 'normal' });
|
||||||
|
expect(updatedMember.meta).toMatchObject({ belong: 0, max_belong: 7, permission: 'normal' });
|
||||||
expect(world.getCity(1)!.nationId).toBe(0);
|
expect(world.getCity(1)!.nationId).toBe(0);
|
||||||
expect(world.getCity(2)!.nationId).toBe(0);
|
expect(world.getCity(2)!.nationId).toBe(0);
|
||||||
expect(world.getNation(1)!.meta.collapsed).toBe(true);
|
expect(world.getNation(1)!.meta.collapsed).toBe(true);
|
||||||
|
|||||||
@@ -124,6 +124,9 @@ export const projectCoreDatabaseSnapshot = (rows: {
|
|||||||
'officerCityId',
|
'officerCityId',
|
||||||
readNumber(meta, 'officer_city', readNumber(meta, 'officerCity', readNumber(meta, 'officerCityId')))
|
readNumber(meta, 'officer_city', readNumber(meta, 'officerCity', readNumber(meta, 'officerCityId')))
|
||||||
),
|
),
|
||||||
|
belong: readNumber(row, 'belong', readNumber(meta, 'belong')),
|
||||||
|
permission: readString(row, 'permission') ?? readString(meta, 'permission') ?? 'normal',
|
||||||
|
maxBelong: readNumber(meta, 'max_belong'),
|
||||||
betray: row.betray,
|
betray: row.betray,
|
||||||
personality: row.personality ?? null,
|
personality: row.personality ?? null,
|
||||||
specialDomestic: row.specialDomestic ?? null,
|
specialDomestic: row.specialDomestic ?? null,
|
||||||
|
|||||||
@@ -281,6 +281,8 @@ const buildGeneral = (row: Record<string, unknown>, fallbackTurnTime: Date): Tur
|
|||||||
'officerCityId',
|
'officerCityId',
|
||||||
readNumber(meta, 'officer_city', readNumber(meta, 'officerCity'))
|
readNumber(meta, 'officer_city', readNumber(meta, 'officerCity'))
|
||||||
),
|
),
|
||||||
|
belong: readNumber(row, 'belong', readNumber(meta, 'belong')),
|
||||||
|
permission: readString(row, 'permission', readString(meta, 'permission', 'normal')),
|
||||||
block: readNumber(row, 'blockState', readNumber(meta, 'block')),
|
block: readNumber(row, 'blockState', readNumber(meta, 'block')),
|
||||||
},
|
},
|
||||||
...(lastTurn ? { lastTurn } : {}),
|
...(lastTurn ? { lastTurn } : {}),
|
||||||
@@ -543,6 +545,9 @@ const projectWorld = (
|
|||||||
'officer_city',
|
'officer_city',
|
||||||
readNumber(general.meta, 'officerCity', readNumber(general.meta, 'officerCityId'))
|
readNumber(general.meta, 'officerCity', readNumber(general.meta, 'officerCityId'))
|
||||||
),
|
),
|
||||||
|
belong: readNumber(general.meta, 'belong'),
|
||||||
|
permission: readString(general.meta, 'permission', 'normal'),
|
||||||
|
maxBelong: readNumber(general.meta, 'max_belong'),
|
||||||
betray: readNumber(general.meta, 'betray'),
|
betray: readNumber(general.meta, 'betray'),
|
||||||
personality: general.role.personality,
|
personality: general.role.personality,
|
||||||
specialDomestic: general.role.specialDomestic,
|
specialDomestic: general.role.specialDomestic,
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ const general = (id: number, nationId: number, cityId: number, officerLevel: num
|
|||||||
killTurn: 24,
|
killTurn: 24,
|
||||||
npcState: 0,
|
npcState: 0,
|
||||||
blockState: 0,
|
blockState: 0,
|
||||||
|
belong: 10,
|
||||||
|
permission: 'normal',
|
||||||
personality: 'None',
|
personality: 'None',
|
||||||
specialDomestic: 'None',
|
specialDomestic: 'None',
|
||||||
specialWar: 'None',
|
specialWar: 'None',
|
||||||
@@ -487,6 +489,112 @@ integration('NPC active command boundary parity', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
interface DisbandFactionBoundaryCase {
|
||||||
|
name: string;
|
||||||
|
actorPatch?: Record<string, unknown>;
|
||||||
|
fixturePatches: FixturePatches;
|
||||||
|
completed: boolean;
|
||||||
|
compareLogs?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const disbandFactionBoundaryCases: DisbandFactionBoundaryCase[] = [
|
||||||
|
{
|
||||||
|
name: 'a non-lord cannot disband the wandering nation',
|
||||||
|
actorPatch: { officerLevel: 11 },
|
||||||
|
fixturePatches: {
|
||||||
|
nations: { 1: { level: 0, capitalCityId: 0, typeCode: 'None' } },
|
||||||
|
cities: { 3: { nationId: 0, supplyState: 0, frontState: 0 } },
|
||||||
|
},
|
||||||
|
completed: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'a settled nation cannot be disbanded',
|
||||||
|
fixturePatches: {
|
||||||
|
nations: { 1: { level: 1 } },
|
||||||
|
},
|
||||||
|
completed: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'disbanding preserves the legacy member state, resources, and destruction logs',
|
||||||
|
actorPatch: {
|
||||||
|
troopId: 3,
|
||||||
|
belong: 5,
|
||||||
|
permission: 'ambassador',
|
||||||
|
gold: 2_000,
|
||||||
|
rice: 3_000,
|
||||||
|
meta: { max_belong: 2 },
|
||||||
|
},
|
||||||
|
fixturePatches: {
|
||||||
|
nations: { 1: { name: '방랑군', level: 0, capitalCityId: 0, typeCode: 'None' } },
|
||||||
|
cities: { 3: { nationId: 0, supplyState: 0, frontState: 0 } },
|
||||||
|
generals: {
|
||||||
|
3: {
|
||||||
|
troopId: 3,
|
||||||
|
belong: 7,
|
||||||
|
permission: 'auditor',
|
||||||
|
gold: 2_500,
|
||||||
|
rice: 4_000,
|
||||||
|
meta: { max_belong: 3 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
troops: [{ id: 3, nationId: 1, name: '방랑군 부대' }],
|
||||||
|
},
|
||||||
|
completed: true,
|
||||||
|
compareLogs: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
integration('general faction disband boundary, state, and log parity', () => {
|
||||||
|
it.each(disbandFactionBoundaryCases)(
|
||||||
|
'$name',
|
||||||
|
async ({ name, actorPatch, fixturePatches, completed, compareLogs }) => {
|
||||||
|
const request = buildRequest('che_해산', undefined, actorPatch, fixturePatches);
|
||||||
|
request.setup!.world!.hiddenSeed = `general-disband-${name}`;
|
||||||
|
request.observe!.includeGlobalHistoryLogs = true;
|
||||||
|
const reference = runReferenceTurnCommandTraceRequest(
|
||||||
|
workspaceRoot!,
|
||||||
|
request as unknown as Record<string, unknown>
|
||||||
|
);
|
||||||
|
const core = await runCoreTurnCommandTrace(request, reference.before);
|
||||||
|
if (process.env.TURN_DIFFERENTIAL_DEBUG === '1') {
|
||||||
|
process.stderr.write(
|
||||||
|
`${JSON.stringify(
|
||||||
|
{
|
||||||
|
name,
|
||||||
|
referenceGenerals: reference.after.generals,
|
||||||
|
coreGenerals: core.after.generals,
|
||||||
|
referenceLogs: addedReferenceLogs(reference.before, reference.after.logs),
|
||||||
|
coreLogs: core.after.logs,
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)}\n`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(reference.execution.outcome).toMatchObject({ completed });
|
||||||
|
expect(core.execution.outcome).toMatchObject({
|
||||||
|
requestedAction: 'che_해산',
|
||||||
|
actionKey: completed ? 'che_해산' : '휴식',
|
||||||
|
usedFallback: !completed,
|
||||||
|
});
|
||||||
|
expect(core.rng).toEqual(reference.rng);
|
||||||
|
expect(
|
||||||
|
compareTurnSnapshotDeltas(reference.before, reference.after, core.before, core.after, {
|
||||||
|
ignoredPathPatterns: ignoredLifecyclePaths,
|
||||||
|
})
|
||||||
|
).toEqual([]);
|
||||||
|
|
||||||
|
if (compareLogs) {
|
||||||
|
expect(semanticLogSignatures(core.after.logs)).toEqual(
|
||||||
|
semanticLogSignatures(addedReferenceLogs(reference.before, reference.after.logs))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
120_000
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
interface SelfStateBoundaryCase {
|
interface SelfStateBoundaryCase {
|
||||||
name: string;
|
name: string;
|
||||||
action: 'che_단련' | 'che_숙련전환' | 'che_사기진작' | 'che_요양';
|
action: 'che_단련' | 'che_숙련전환' | 'che_사기진작' | 'che_요양';
|
||||||
|
|||||||
Reference in New Issue
Block a user