120 lines
4.1 KiB
JavaScript
120 lines
4.1 KiB
JavaScript
import { TestCase } from "./framework/test_case.js";
|
|
import { MapGenerator } from "../shared/map_generator.js";
|
|
import { MapTopology, key } from "../shared/hex.js";
|
|
import { MAP_CONFIG } from "../shared/data.js";
|
|
import { Random } from "../shared/rng.js";
|
|
|
|
function config(overrides = {}) {
|
|
return {
|
|
...MAP_CONFIG,
|
|
mapSize: { x: 32, y: 24 },
|
|
minCapitalLandmass: 1,
|
|
minCapitalDistance: 2,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function generate(cfg = config()) {
|
|
const topology = new MapTopology(cfg.mapSize, cfg.topology === "cylindrical");
|
|
const generator = new MapGenerator(cfg, topology);
|
|
generator.generate(cfg.terrainSeed);
|
|
return generator;
|
|
}
|
|
|
|
export class MapGeneratorTest extends TestCase {
|
|
test_generate_is_deterministic_for_a_seed() {
|
|
const a = generate();
|
|
const b = generate();
|
|
this.assertEqual(a.landCells, b.landCells);
|
|
this.assertEqual(Object.keys(a.tiles).length, Object.keys(b.tiles).length);
|
|
}
|
|
|
|
test_generate_marks_every_cell_as_land_or_sea() {
|
|
const cfg = config();
|
|
const generator = generate(cfg);
|
|
this.assertNotEmpty(generator.landCells);
|
|
this.assertSize(generator.tiles, cfg.mapSize.x * cfg.mapSize.y);
|
|
for (const coords of generator.landCells) {
|
|
this.assertEqual(generator.tiles[key(coords.x, coords.y)].terrainClass, "Land");
|
|
}
|
|
}
|
|
|
|
test_generate_records_pure_tile_data() {
|
|
const generator = generate();
|
|
for (const coords of generator.landCells) {
|
|
const tile = generator.tiles[key(coords.x, coords.y)];
|
|
this.assertHas(tile, "terrainClass");
|
|
this.assertHas(tile, "movementCostMultiplier");
|
|
this.assertHas(tile, "populationMultiplier");
|
|
this.assertHas(tile, "gdpMultiplier");
|
|
}
|
|
}
|
|
|
|
test_pick_capitals_returns_land_within_count() {
|
|
const generator = generate();
|
|
const capitals = generator.pickCapitals(3, new Random(1));
|
|
this.assertSize(capitals, 3);
|
|
for (const coords of capitals) {
|
|
this.assertTrue(
|
|
generator.landCells.some((c) => c.x === coords.x && c.y === coords.y),
|
|
`capital ${coords.x},${coords.y} is land`
|
|
);
|
|
}
|
|
}
|
|
|
|
test_pick_capitals_respects_distance() {
|
|
const cfg = config({ minCapitalDistance: 3 });
|
|
const generator = generate(cfg);
|
|
const capitals = generator.pickCapitals(2, new Random(1));
|
|
this.assertSize(capitals, 2);
|
|
const distance = generator.topology.tileDistance(capitals[0], capitals[1]);
|
|
this.assertGreaterOrEqual(distance, cfg.minCapitalDistance, "capitals kept apart");
|
|
}
|
|
|
|
test_pick_cities_includes_one_site_per_capital() {
|
|
const cfg = config({ citiesPerCiv: 3, citySpacing: 2 });
|
|
const generator = generate(cfg);
|
|
const capitals = generator.pickCapitals(2, new Random(1));
|
|
const sites = generator.pickCities(capitals, cfg.citiesPerCiv, cfg.citySpacing);
|
|
this.assertNotEmpty(sites);
|
|
const seen = new Set();
|
|
let capitalSites = 0;
|
|
for (const site of sites) {
|
|
if (site.isCapital) capitalSites += 1;
|
|
const k = key(site.coords.x, site.coords.y);
|
|
this.assertFalse(seen.has(k), `duplicate city at ${k}`);
|
|
seen.add(k);
|
|
}
|
|
this.assertEqual(capitalSites, capitals.length);
|
|
}
|
|
|
|
test_poles_are_ice() {
|
|
const cfg = config({ iceLatitude: 0.5 });
|
|
const generator = generate(cfg);
|
|
const half = cfg.mapSize.y / 2;
|
|
for (const k in generator.tiles) {
|
|
const i = k.indexOf(",");
|
|
const y = Number(k.slice(i + 1));
|
|
if (Math.abs(y) / half >= cfg.iceLatitude) {
|
|
this.assertEqual(generator.tiles[k].terrainType, "Ice", `tile ${k}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
test_equator_is_not_ice() {
|
|
const generator = generate();
|
|
for (const k in generator.tiles) {
|
|
const i = k.indexOf(",");
|
|
const y = Number(k.slice(i + 1));
|
|
if (Math.abs(y) < 2) this.assertNotEqual(generator.tiles[k].terrainType, "Ice");
|
|
}
|
|
}
|
|
|
|
test_falloff_lowers_the_edges() {
|
|
const cfg = config({ falloffEnabled: true, falloffStart: 0, falloffStrength: 1 });
|
|
const generator = generate(cfg);
|
|
this.assertApprox(generator._applyFalloff({ x: 0, y: 0 }, 1.0, false), 1.0, 1e-9);
|
|
this.assertApprox(generator._applyFalloff({ x: 16, y: 12 }, 1.0, false), 0.0, 1e-9);
|
|
}
|
|
}
|