95 lines
3.2 KiB
JavaScript
95 lines
3.2 KiB
JavaScript
import { CELL_SIZE, MAP_H, MAP_W, indexOf } from "./mapUtils.js";
|
|
import { generateTerrainAndRivers } from "./mapTerrain.js";
|
|
import { generateMapFeatures } from "./mapFeaturesV2.js";
|
|
import { finishMapOutput } from "./mapOutput.js";
|
|
import { generateAdminLayout } from "./mapAdminStage.js";
|
|
|
|
export { CELL_SIZE, MAP_H, MAP_W, indexOf } from "./mapUtils.js";
|
|
|
|
function nowMs() {
|
|
return typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
|
|
}
|
|
|
|
function timedStage(timings, options, key, label, fn) {
|
|
options?.onProgress?.({ status: "start", key, label, timings: timings.slice() });
|
|
const t0 = nowMs();
|
|
const value = fn();
|
|
const ms = Math.round((nowMs() - t0) * 10) / 10;
|
|
const entry = { key, label, ms };
|
|
timings.push(entry);
|
|
options?.onProgress?.({ status: "done", key, label, ms, timings: timings.slice() });
|
|
return value;
|
|
}
|
|
|
|
export function generateMap(seedInput = 114514, options = {}) {
|
|
const seed = Number(seedInput) >>> 0;
|
|
if (typeof options.onProgress !== "function") options = { ...options, onProgress: () => {} };
|
|
|
|
const generationTimings = [];
|
|
const stage = (key, label, fn) => timedStage(generationTimings, options, key, label, fn);
|
|
|
|
const terrain = stage("terrain", "Terrain, rivers, and prefecture regions", () => generateTerrainAndRivers(seed));
|
|
const {
|
|
elevation,
|
|
slope,
|
|
sea,
|
|
river,
|
|
plain,
|
|
agriculture,
|
|
ridgeField,
|
|
valleyField,
|
|
basinField,
|
|
coastalLowland,
|
|
flowAccum,
|
|
naturalBarrierScore,
|
|
prefectureMask,
|
|
prefectureRegionId,
|
|
adminPrefectureRegionId,
|
|
} = terrain;
|
|
|
|
const features = stage("human", "Human geography and transport", () => generateMapFeatures(seed, terrain));
|
|
const {
|
|
settlementScore,
|
|
villages,
|
|
markets,
|
|
modernCities,
|
|
populationDensity,
|
|
stations,
|
|
industrialZones,
|
|
logisticsParks,
|
|
satelliteCities,
|
|
newTowns,
|
|
ports,
|
|
landuse,
|
|
stationInfluence,
|
|
roadInfluence,
|
|
railInfluence2,
|
|
villageInfluence,
|
|
} = features;
|
|
|
|
const admin = stage("admin", "Municipal and prefectural administration", () => generateAdminLayout({
|
|
seed, prefectureMask, prefectureRegionId: adminPrefectureRegionId || prefectureRegionId, sea, elevation, slope, river, ridgeField, naturalBarrierScore, valleyField, basinField, coastalLowland, flowAccum, plain, agriculture,
|
|
settlementScore, populationDensity, stationInfluence, roadInfluence, railInfluence2, villageInfluence, landuse, modernCities, satelliteCities, newTowns, markets, villages, ports, stations, industrialZones, logisticsParks,
|
|
adminProgress: (event) => options?.onProgress?.({
|
|
...event,
|
|
key: "admin",
|
|
label: event.status === "region-done"
|
|
? `Admin region ${event.regionId} done`
|
|
: event.status === "admin-step"
|
|
? `Admin region ${event.regionId}: ${event.step}`
|
|
: `Admin region ${event.regionId}`,
|
|
timings: generationTimings.slice(),
|
|
}),
|
|
}));
|
|
|
|
const output = stage("output", "Names, population totals, and final packaging", () => finishMapOutput({
|
|
seed,
|
|
options,
|
|
terrain,
|
|
features,
|
|
admin,
|
|
}));
|
|
output.generationTimings = generationTimings;
|
|
output.generationTotalMs = generationTimings.reduce((sum, row) => sum + row.ms, 0);
|
|
return output;
|
|
}
|