fix(turn): 기본 사령턴 목록과 분류를 Ref에 맞춤

Ref 사령부 조작기의 24개 공개 명령을 기본 프로필에 모두 포함하고 카테고리와 내부 순서를 그대로 투영한다.\n\n35개 국가 명령 차등 실행과 조건·로그 비교, 실제 Chromium 목록 검사를 추가한다.
This commit is contained in:
2026-08-16 07:09:03 +00:00
parent 03a8cb02ba
commit cda88738fa
5 changed files with 248 additions and 12 deletions
+70 -1
View File
@@ -10,6 +10,7 @@ import type {
GeneralTurnCommandKey,
MapDefinition,
Nation,
NationTurnCommandKey,
NationTurnCommandSpec,
RequirementKey,
StateView,
@@ -150,6 +151,54 @@ const REF_GENERAL_COMMAND_POSITION = new Map<string, { category: string; index:
)
);
const REF_NATION_COMMAND_GROUPS = [
{
category: '휴식',
commands: ['휴식'],
},
{
category: '인사',
commands: ['che_발령', 'che_포상', 'che_몰수', 'che_부대탈퇴지시'],
},
{
category: '외교',
commands: ['che_물자원조', 'che_불가침제의', 'che_선전포고', 'che_종전제의', 'che_불가침파기제의'],
},
{
category: '특수',
commands: ['che_초토화', 'che_천도', 'che_증축', 'che_감축'],
},
{
category: '전략',
commands: [
'che_필사즉생',
'che_백성동원',
'che_수몰',
'che_허보',
'che_의병모집',
'che_이호경식',
'che_급습',
'che_피장파장',
],
},
{
category: '기타',
commands: ['che_국기변경', 'che_국호변경'],
},
] as const satisfies ReadonlyArray<{
category: string;
commands: ReadonlyArray<NationTurnCommandKey>;
}>;
const REF_NATION_CATEGORY_ORDER = new Map<string, number>(
REF_NATION_COMMAND_GROUPS.map(({ category }, index) => [category, index] as const)
);
const REF_NATION_COMMAND_POSITION = new Map<string, { category: string; index: number }>(
REF_NATION_COMMAND_GROUPS.flatMap(({ category, commands }) =>
commands.map((command, index) => [command, { category, index }] as const)
)
);
const INPUT_REQUIREMENT_KINDS = new Set<RequirementKey['kind']>([
'destGeneral',
'destCity',
@@ -665,6 +714,26 @@ const projectRefGeneralCommandGroups = (entries: CommandEntry[]): CommandEntry[]
)
.map(({ entry }) => entry);
const projectRefNationCommandGroups = (entries: CommandEntry[]): CommandEntry[] =>
entries
.map((entry, profileIndex) => {
const refPosition = REF_NATION_COMMAND_POSITION.get(entry.definition.key as NationTurnCommandKey);
return {
entry: refPosition ? { ...entry, category: refPosition.category } : entry,
categoryIndex:
REF_NATION_CATEGORY_ORDER.get(refPosition?.category ?? entry.category) ?? Number.MAX_SAFE_INTEGER,
commandIndex: refPosition?.index ?? profileIndex,
profileIndex,
};
})
.sort(
(left, right) =>
left.categoryIndex - right.categoryIndex ||
left.commandIndex - right.commandIndex ||
left.profileIndex - right.profileIndex
)
.map(({ entry }) => entry);
export const buildTurnCommandTable = async (options: {
worldState: WorldStateRow;
general: GeneralRow;
@@ -697,7 +766,7 @@ export const buildTurnCommandTable = async (options: {
return {
general: buildGroups(projectRefGeneralCommandGroups(generalEntries), ctx, view),
nation: buildGroups(nationEntries, ctx, view),
nation: buildGroups(projectRefNationCommandGroups(nationEntries), ctx, view),
inputOptions: options.inputOptions ?? {
cities: [],
nations: [],
+31 -1
View File
@@ -100,7 +100,7 @@ const buildNation = (): NationRow =>
}) as unknown as NationRow;
describe('buildTurnCommandTable', () => {
it('projects the main reserved-turn categories and command order from Ref', async () => {
it('projects the general and chief reserved-turn categories and command order from Ref', async () => {
const table = await buildTurnCommandTable({
worldState: buildWorldState(),
general: buildGeneral(),
@@ -140,6 +140,36 @@ describe('buildTurnCommandTable', () => {
: ['che_선동', 'che_탈취', 'che_파괴', 'che_화계'],
: ['che_증여', 'che_헌납', 'che_물자조달', 'che_하야', 'che_거병', 'che_건국', 'che_선양', 'che_해산'],
});
expect(table.nation.map(({ category }) => category)).toEqual(['휴식', '인사', '외교', '특수', '전략', '기타']);
expect(
Object.fromEntries(table.nation.map(({ category, values }) => [category, values.map(({ key }) => key)]))
).toEqual({
: ['휴식'],
: ['che_발령', 'che_포상', 'che_몰수', 'che_부대탈퇴지시'],
: ['che_물자원조', 'che_불가침제의', 'che_선전포고', 'che_종전제의', 'che_불가침파기제의'],
: ['che_초토화', 'che_천도', 'che_증축', 'che_감축'],
: [
'che_필사즉생',
'che_백성동원',
'che_수몰',
'che_허보',
'che_의병모집',
'che_이호경식',
'che_급습',
'che_피장파장',
],
: ['che_국기변경', 'che_국호변경'],
});
expect(
Object.fromEntries(table.nation.map(({ category, values }) => [category, values.map(({ name }) => name)]))
).toEqual({
: ['휴식'],
: ['발령', '포상', '몰수', '부대 탈퇴 지시'],
: ['원조', '불가침 제의', '선전포고', '종전 제의', '불가침 파기 제의'],
: ['초토화', '천도', '증축', '감축'],
: ['필사즉생', '백성동원', '수몰', '허보', '의병모집', '이호경식', '급습', '피장파장'],
: ['국기변경', '국호변경'],
});
});
it('projects the Ref availability boundaries for force move, retirement, and resignation', async () => {