fix(game-engine): 중립국을 이민족 종료 집계에서 제외한다
This commit is contained in:
@@ -282,7 +282,12 @@ export const createRaiseInvaderHandler = (options: {
|
||||
world.updateCity(city.id, { nationId: 0, frontState: 0, supplyState: 1 });
|
||||
}
|
||||
|
||||
const existingNationIds = world.listNations().map((nation) => nation.id);
|
||||
// Ref nation table에는 Core의 `id=0 재야` row가 없으므로, 이민족과
|
||||
// 전쟁 관계를 만들 실제 국가만 ID 증가와 외교 생성의 기준으로 삼는다.
|
||||
const existingNationIds = world
|
||||
.listNations()
|
||||
.filter((nation) => nation.id > 0)
|
||||
.map((nation) => nation.id);
|
||||
const currentLastNationId = readNumber(world.getState().meta.lastNationId);
|
||||
const liveNationMaxId = existingNationIds.reduce((maxId, id) => Math.max(maxId, id), 0);
|
||||
let lastNationId = Math.max(currentLastNationId, liveNationMaxId);
|
||||
@@ -499,12 +504,13 @@ export const createInvaderEndingHandler = (options: {
|
||||
if (isUnited === 0 || isUnited === 2) {
|
||||
return;
|
||||
}
|
||||
const nations = world.listNations();
|
||||
// Ref는 국가명 `ⓞ` prefix로 이벤트 승자를 구분한다. 전체 국가 수로
|
||||
// 막으면 서로 불가침 중인 이민족이 여럿 남았을 때 일반국 전멸 뒤에도
|
||||
// 종료할 수 없으므로, 일반국의 부재를 직접 판정한다.
|
||||
const ordinaryNations = nations.filter((nation) => !nation.name.startsWith(INVADER_PREFIX));
|
||||
const invaderNations = nations.filter((nation) => nation.name.startsWith(INVADER_PREFIX));
|
||||
// Ref의 nation table에는 Core가 domain/DB에 유지하는 `id=0 재야` row가
|
||||
// 없다. 실제 승패 국가만 남긴 뒤 `ⓞ` prefix로 이벤트 승자를 구분한다.
|
||||
// 전체 국가 수로 막으면 서로 불가침 중인 이민족이 여럿 남았을 때
|
||||
// 일반국 전멸 뒤에도 종료할 수 없으므로, 일반국의 부재를 직접 판정한다.
|
||||
const activeNations = world.listNations().filter((nation) => nation.id > 0);
|
||||
const ordinaryNations = activeNations.filter((nation) => !nation.name.startsWith(INVADER_PREFIX));
|
||||
const invaderNations = activeNations.filter((nation) => nation.name.startsWith(INVADER_PREFIX));
|
||||
const cities = world.listCities();
|
||||
const neutralCityCount = cities.filter((city) => city.nationId === 0).length;
|
||||
const userWin = ordinaryNations.length === 1 && invaderNations.length === 0 && neutralCityCount === 0;
|
||||
|
||||
@@ -49,6 +49,14 @@ const buildNation = (id: number, capitalCityId = 1, name = `국가${id}`): Natio
|
||||
meta: { tech: 100, war: 1, scout: 1 },
|
||||
});
|
||||
|
||||
const buildNeutralNation = (): Nation => ({
|
||||
...buildNation(0, 0, '재야'),
|
||||
chiefGeneralId: null,
|
||||
level: 0,
|
||||
typeCode: 'che_중립',
|
||||
meta: {},
|
||||
});
|
||||
|
||||
const buildGeneral = (overrides: Partial<TurnGeneral> = {}): TurnGeneral => ({
|
||||
id: 1,
|
||||
userId: null,
|
||||
@@ -347,6 +355,7 @@ describe('invader monthly actions', () => {
|
||||
};
|
||||
const harness = buildHarness({
|
||||
cities: [buildCity(1, 1, 3)],
|
||||
nations: [buildNeutralNation(), buildNation(1)],
|
||||
events: [endingEvent],
|
||||
meta: { isunited: 1, refreshLimit: 3 },
|
||||
});
|
||||
@@ -387,7 +396,7 @@ describe('invader monthly actions', () => {
|
||||
];
|
||||
const harness = buildHarness({
|
||||
cities: [buildCity(1, 2, 4), buildCity(2, 3, 4)],
|
||||
nations: invaderNations,
|
||||
nations: [buildNeutralNation(), ...invaderNations],
|
||||
generals: [],
|
||||
events: [endingEvent],
|
||||
meta: { isunited: 1, refreshLimit: 3 },
|
||||
@@ -427,7 +436,12 @@ describe('invader monthly actions', () => {
|
||||
};
|
||||
const harness = buildHarness({
|
||||
cities: [buildCity(1, 1, 3), buildCity(2, 2, 4), buildCity(3, 3, 4)],
|
||||
nations: [buildNation(1), buildNation(2, 2, 'ⓞ남만족'), buildNation(3, 3, 'ⓞ산월족')],
|
||||
nations: [
|
||||
buildNeutralNation(),
|
||||
buildNation(1),
|
||||
buildNation(2, 2, 'ⓞ남만족'),
|
||||
buildNation(3, 3, 'ⓞ산월족'),
|
||||
],
|
||||
events: [endingEvent],
|
||||
meta: { isunited: 1, refreshLimit: 3 },
|
||||
});
|
||||
|
||||
@@ -109,6 +109,19 @@ const buildCity = (id: number, nationId: number, level: number, name: string): C
|
||||
|
||||
const ordinaryCity = buildCity(ordinaryCityId, existingNationId, 3, '기준도시');
|
||||
const invaderCity = buildCity(invaderCityId, 0, 4, '남만');
|
||||
const neutralNation: Nation = {
|
||||
id: 0,
|
||||
name: '재야',
|
||||
color: '#000000',
|
||||
capitalCityId: null,
|
||||
chiefGeneralId: null,
|
||||
gold: 0,
|
||||
rice: 0,
|
||||
power: 0,
|
||||
level: 0,
|
||||
typeCode: 'che_중립',
|
||||
meta: {},
|
||||
};
|
||||
const existingNation: Nation = {
|
||||
id: existingNationId,
|
||||
name: '기준국',
|
||||
@@ -199,7 +212,9 @@ integration('RaiseInvader database persistence', () => {
|
||||
],
|
||||
},
|
||||
});
|
||||
await db.nation.deleteMany({ where: { id: { in: [existingNationId, createdNationId] } } });
|
||||
await db.nation.deleteMany({
|
||||
where: { id: { in: [neutralNation.id, existingNationId, createdNationId] } },
|
||||
});
|
||||
await db.city.deleteMany({ where: { id: { in: [ordinaryCityId, invaderCityId] } } });
|
||||
await db.event.deleteMany({ where: { id: { in: [sourceEventId, ...createdEventIds] } } });
|
||||
await db.worldState.deleteMany({ where: { scenarioCode: 'monthly-invader-persistence' } });
|
||||
@@ -251,6 +266,21 @@ integration('RaiseInvader database persistence', () => {
|
||||
});
|
||||
await createCity(ordinaryCity);
|
||||
await createCity(invaderCity);
|
||||
await db.nation.create({
|
||||
data: {
|
||||
id: neutralNation.id,
|
||||
name: neutralNation.name,
|
||||
color: neutralNation.color,
|
||||
capitalCityId: neutralNation.capitalCityId,
|
||||
chiefGeneralId: neutralNation.chiefGeneralId,
|
||||
gold: neutralNation.gold,
|
||||
rice: neutralNation.rice,
|
||||
tech: 0,
|
||||
level: neutralNation.level,
|
||||
typeCode: neutralNation.typeCode,
|
||||
meta: neutralNation.meta,
|
||||
},
|
||||
});
|
||||
await db.nation.create({
|
||||
data: {
|
||||
id: existingNationId,
|
||||
@@ -343,7 +373,7 @@ integration('RaiseInvader database persistence', () => {
|
||||
map: { id: 'test', name: 'test', cities: [] },
|
||||
generals: [existingGeneral],
|
||||
cities: [ordinaryCity, invaderCity],
|
||||
nations: [existingNation],
|
||||
nations: [neutralNation, existingNation],
|
||||
troops: [],
|
||||
diplomacy: [],
|
||||
events: [sourceEvent],
|
||||
@@ -406,7 +436,22 @@ integration('RaiseInvader database persistence', () => {
|
||||
OR: [{ srcNationId: createdNationId }, { destNationId: createdNationId }],
|
||||
},
|
||||
})
|
||||
).toBe(2);
|
||||
).toBe(4);
|
||||
expect(
|
||||
await db.diplomacy.findMany({
|
||||
where: {
|
||||
OR: [
|
||||
{ srcNationId: neutralNation.id, destNationId: createdNationId },
|
||||
{ srcNationId: createdNationId, destNationId: neutralNation.id },
|
||||
],
|
||||
},
|
||||
orderBy: [{ srcNationId: 'asc' }, { destNationId: 'asc' }],
|
||||
select: { srcNationId: true, destNationId: true, stateCode: true, term: true },
|
||||
})
|
||||
).toEqual([
|
||||
{ srcNationId: neutralNation.id, destNationId: createdNationId, stateCode: 2, term: 0 },
|
||||
{ srcNationId: createdNationId, destNationId: neutralNation.id, stateCode: 2, term: 0 },
|
||||
]);
|
||||
expect(
|
||||
await db.event.findMany({
|
||||
where: { id: { in: createdEventIds } },
|
||||
|
||||
Reference in New Issue
Block a user