Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/core/game/NationCreation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ export function createNationsForGame(
): Nation[] {
const toNation = (n: ManifestNation): Nation =>
new Nation(
new Cell(n.coordinates[0], n.coordinates[1]),
n.coordinates !== undefined
? new Cell(n.coordinates[0], n.coordinates[1])
: undefined,
new PlayerInfo(n.name, PlayerType.Nation, null, random.nextID()),
);

Expand Down
12 changes: 7 additions & 5 deletions src/core/game/TerrainMapLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export interface MapManifest {
}

export interface Nation {
coordinates: [number, number];
coordinates?: [number, number];
flag?: string;
name: string;
}
Expand Down Expand Up @@ -69,10 +69,12 @@ export async function loadTerrainMap(

if (mapSize === GameMapSize.Compact) {
manifest.nations.forEach((nation) => {
nation.coordinates = [
Math.floor(nation.coordinates[0] / 2),
Math.floor(nation.coordinates[1] / 2),
];
if (nation.coordinates !== undefined) {
nation.coordinates = [
Math.floor(nation.coordinates[0] / 2),
Math.floor(nation.coordinates[1] / 2),
];
}
});
manifest.additionalNations?.forEach((nation) => {
if (nation.coordinates !== undefined) {
Expand Down
85 changes: 57 additions & 28 deletions tests/MapConsistency.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,39 +294,68 @@ describe("Map consistency", () => {
const info = JSON.parse(fs.readFileSync(infoPath, "utf8"));
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));

type NationEntry = { name: string; coordinates: [number, number] };
const infoNations: NationEntry[] = (info.nations ?? []).map(
(n: NationEntry) => ({ name: n.name, coordinates: n.coordinates }),
);
const manifestNations: NationEntry[] = (manifest.nations ?? []).map(
(n: NationEntry) => ({ name: n.name, coordinates: n.coordinates }),
);

if (infoNations.length !== manifestNations.length) {
errors.push(
`${key}: nation count mismatch — info.json has ${infoNations.length}, manifest.json has ${manifestNations.length}`,
);
continue;
}

// Compare nations by index (order must match; names can be duplicated).
for (let i = 0; i < infoNations.length; i++) {
const inf = infoNations[i];
const man = manifestNations[i];
if (inf.name !== man.name) {
// ── Compare nations ──────────────────────────────────────────────
type NationEntry = {
name: string;
coordinates?: [number, number];
};

function compareNationArrays(
label: string,
infoArr: NationEntry[],
manifestArr: NationEntry[],
): void {
if (infoArr.length !== manifestArr.length) {
errors.push(
`${key}: nations[${i}] name mismatch — info.json "${inf.name}" vs manifest.json "${man.name}"`,
`${key}: ${label} count mismatch — info.json has ${infoArr.length}, manifest.json has ${manifestArr.length}`,
);
continue;
return;
}
const [ix, iy] = inf.coordinates;
const [mx, my] = man.coordinates;
if (ix !== mx || iy !== my) {
errors.push(
`${key}: nation "${inf.name}" (index ${i}) coordinates differ — info.json [${ix}, ${iy}] vs manifest.json [${mx}, ${my}]`,
);
for (let i = 0; i < infoArr.length; i++) {
const inf = infoArr[i];
const man = manifestArr[i];
if (inf.name !== man.name) {
errors.push(
`${key}: ${label}[${i}] name mismatch — info.json "${inf.name}" vs manifest.json "${man.name}"`,
);
continue;
}
const infHasCoords = inf.coordinates !== undefined;
const manHasCoords = man.coordinates !== undefined;
if (infHasCoords !== manHasCoords) {
errors.push(
`${key}: ${label} "${inf.name}" (index ${i}) coordinate presence differs — info.json ${infHasCoords ? "has" : "missing"} coordinates, manifest.json ${manHasCoords ? "has" : "missing"} coordinates`,
);
continue;
}
if (inf.coordinates && man.coordinates) {
const [ix, iy] = inf.coordinates;
const [mx, my] = man.coordinates;
if (ix !== mx || iy !== my) {
errors.push(
`${key}: ${label} "${inf.name}" (index ${i}) coordinates differ — info.json [${ix}, ${iy}] vs manifest.json [${mx}, ${my}]`,
);
}
}
}
}

const toEntry = (n: NationEntry) => ({
name: n.name,
coordinates: n.coordinates,
});

compareNationArrays(
"nation",
(info.nations ?? []).map(toEntry),
(manifest.nations ?? []).map(toEntry),
);

compareNationArrays(
"additionalNation",
(info.additionalNations ?? []).map(toEntry),
(manifest.additionalNations ?? []).map(toEntry),
);
} catch (err) {
errors.push(`${key}: failed to parse JSON — ${(err as Error).message}`);
}
Expand Down
28 changes: 28 additions & 0 deletions tests/NationCreation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,34 @@ describe("createNationsForGame: additionalNations pool", () => {
expect(withoutCoords!.spawnCell).toBeUndefined();
});

test("uses coordinates from manifest nations when provided, undefined when omitted", () => {
const manifest: ManifestNation[] = [
{ name: "WithCoords", coordinates: [10, 20] },
{ name: "WithoutCoords" },
];
const random = new PseudoRandom(5);

const nations = createNationsForGame(
makeGameStart(2),
manifest,
[],
0,
random,
);

expect(nations).toHaveLength(2);
const withCoords = nations.find((n) => n.playerInfo.name === "WithCoords");
const withoutCoords = nations.find(
(n) => n.playerInfo.name === "WithoutCoords",
);

expect(withCoords).toBeDefined();
expect(withoutCoords).toBeDefined();
expect(withCoords!.spawnCell?.x).toBe(10);
expect(withCoords!.spawnCell?.y).toBe(20);
expect(withoutCoords!.spawnCell).toBeUndefined();
});

test("produces unique nation names overall", () => {
const manifest = makeManifestNations(3);
const extras = makeAdditionalNations(["Ex1", "Ex2", "Ex3"]);
Expand Down
Loading