Complete instant diplomacy response parity
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import type { City, MapDefinition, Nation } from '@sammo-ts/logic';
|
||||
import { buildNationFrontStatePatches, type City, type MapDefinition, type Nation } from '@sammo-ts/logic';
|
||||
import type { InMemoryTurnWorld, TurnCalendarHandler } from './inMemoryWorld.js';
|
||||
import type { TurnDiplomacy } from './types.js';
|
||||
|
||||
@@ -12,92 +12,6 @@ const buildConnectionMap = (map: MapDefinition): ConnectionMap => {
|
||||
return connectionMap;
|
||||
};
|
||||
|
||||
const collectAdjacentCities = (cityIds: number[], connectionMap: ConnectionMap, bucket: Set<number>): void => {
|
||||
for (const cityId of cityIds) {
|
||||
const neighbors = connectionMap.get(cityId) ?? [];
|
||||
for (const neighborId of neighbors) {
|
||||
bucket.add(neighborId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const collectNationCityIds = (cities: City[]): Map<number, number[]> => {
|
||||
const map = new Map<number, number[]>();
|
||||
for (const city of cities) {
|
||||
const list = map.get(city.nationId) ?? [];
|
||||
list.push(city.id);
|
||||
map.set(city.nationId, list);
|
||||
}
|
||||
return map;
|
||||
};
|
||||
|
||||
const collectDiplomacyTargets = (entries: TurnDiplomacy[], nationId: number): {
|
||||
warTargets: number[];
|
||||
declareTargets: number[];
|
||||
} => {
|
||||
const warTargets: number[] = [];
|
||||
const declareTargets: number[] = [];
|
||||
for (const entry of entries) {
|
||||
if (entry.fromNationId !== nationId) {
|
||||
continue;
|
||||
}
|
||||
if (entry.state === 0) {
|
||||
warTargets.push(entry.toNationId);
|
||||
} else if (entry.state === 1 && entry.term <= 5) {
|
||||
declareTargets.push(entry.toNationId);
|
||||
}
|
||||
}
|
||||
return { warTargets, declareTargets };
|
||||
};
|
||||
|
||||
const resolveNationFrontStates = (
|
||||
nationId: number,
|
||||
connectionMap: ConnectionMap,
|
||||
cityIdsByNation: Map<number, number[]>,
|
||||
diplomacy: TurnDiplomacy[]
|
||||
): Map<number, number> => {
|
||||
const frontStates = new Map<number, number>();
|
||||
if (nationId <= 0) {
|
||||
return frontStates;
|
||||
}
|
||||
|
||||
const { warTargets, declareTargets } = collectDiplomacyTargets(diplomacy, nationId);
|
||||
const adj3 = new Set<number>();
|
||||
const adj2 = new Set<number>();
|
||||
const adj1 = new Set<number>();
|
||||
|
||||
for (const targetNationId of warTargets) {
|
||||
const targetCities = cityIdsByNation.get(targetNationId) ?? [];
|
||||
collectAdjacentCities(targetCities, connectionMap, adj3);
|
||||
}
|
||||
|
||||
for (const targetNationId of declareTargets) {
|
||||
const targetCities = cityIdsByNation.get(targetNationId) ?? [];
|
||||
collectAdjacentCities(targetCities, connectionMap, adj1);
|
||||
}
|
||||
|
||||
if (adj3.size === 0 && adj1.size === 0) {
|
||||
const neutralCities = cityIdsByNation.get(0) ?? [];
|
||||
collectAdjacentCities(neutralCities, connectionMap, adj2);
|
||||
}
|
||||
|
||||
const nationCityIds = cityIdsByNation.get(nationId) ?? [];
|
||||
for (const cityId of nationCityIds) {
|
||||
let nextFrontState = 0;
|
||||
if (adj1.has(cityId)) {
|
||||
nextFrontState = 1;
|
||||
}
|
||||
if (adj2.has(cityId)) {
|
||||
nextFrontState = 2;
|
||||
}
|
||||
if (adj3.has(cityId)) {
|
||||
nextFrontState = 3;
|
||||
}
|
||||
frontStates.set(cityId, nextFrontState);
|
||||
}
|
||||
return frontStates;
|
||||
};
|
||||
|
||||
export const buildFrontStatePatches = (options: {
|
||||
worldView: {
|
||||
listCities(): City[];
|
||||
@@ -114,32 +28,19 @@ export const buildFrontStatePatches = (options: {
|
||||
if (connectionMap.size === 0) {
|
||||
return [];
|
||||
}
|
||||
const cities = options.worldView.listCities();
|
||||
const cityIdsByNation = collectNationCityIds(cities);
|
||||
const diplomacy = options.worldView.listDiplomacy();
|
||||
const cityMap = new Map<number, City>();
|
||||
for (const city of cities) {
|
||||
cityMap.set(city.id, city);
|
||||
}
|
||||
|
||||
const nationList = options.nationIds
|
||||
? options.worldView
|
||||
.listNations()
|
||||
.filter((nation) => options.nationIds?.includes(nation.id))
|
||||
? options.worldView.listNations().filter((nation) => options.nationIds?.includes(nation.id))
|
||||
: options.worldView.listNations();
|
||||
const nations = nationList.filter((nation) => nation.level > 0);
|
||||
const patches: Array<{ id: number; patch: Partial<City> }> = [];
|
||||
for (const nation of nations) {
|
||||
const frontStates = resolveNationFrontStates(nation.id, connectionMap, cityIdsByNation, diplomacy);
|
||||
for (const [cityId, nextFrontState] of frontStates) {
|
||||
const city = cityMap.get(cityId);
|
||||
if (!city || city.frontState === nextFrontState) {
|
||||
continue;
|
||||
}
|
||||
patches.push({ id: cityId, patch: { frontState: nextFrontState } });
|
||||
}
|
||||
}
|
||||
return patches;
|
||||
const nationIds = nationList.filter((nation) => nation.level > 0).map((nation) => nation.id);
|
||||
return buildNationFrontStatePatches({
|
||||
cities: options.worldView.listCities(),
|
||||
diplomacy: options.worldView.listDiplomacy(),
|
||||
connections: connectionMap,
|
||||
nationIds,
|
||||
}).map((patch) => ({
|
||||
id: patch.id,
|
||||
patch: { frontState: patch.frontState },
|
||||
}));
|
||||
};
|
||||
|
||||
export const createFrontStateHandler = (options: {
|
||||
|
||||
Reference in New Issue
Block a user