splittintting
This commit is contained in:
parent
b17be0e0d2
commit
d2e7a80e72
11 changed files with 1341 additions and 1349 deletions
191
mapFeatureTransportTools.js
Normal file
191
mapFeatureTransportTools.js
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
import { INF, MAP_H, MAP_W, SIZE, clamp, hash2, indexOf, inside } from "./mapUtils.js";
|
||||
|
||||
export function buildFeatureTransportCostFields(ctx) {
|
||||
const {
|
||||
seed,
|
||||
sea, elevation, slope, river, plain, agriculture, ridgeField, valleyField, basinField, coastalLowland,
|
||||
portSuitability, passSuitability, crossingSuitability, naturalBarrierScore,
|
||||
settlementDemand, urbanEdge, logisticsPreSuitability,
|
||||
preliminaryTownInfluence, preliminaryVillageInfluence,
|
||||
valleySettlement, coastalSettlement, developable,
|
||||
} = ctx;
|
||||
const expressway = new Float32Array(SIZE);
|
||||
const rail = new Float32Array(SIZE);
|
||||
const national = new Float32Array(SIZE);
|
||||
const local = new Float32Array(SIZE);
|
||||
const expresswayPotential = new Float32Array(SIZE);
|
||||
const railPotential = new Float32Array(SIZE);
|
||||
const nationalPotential = new Float32Array(SIZE);
|
||||
const localPotential = new Float32Array(SIZE);
|
||||
|
||||
function seaAdjacency(x, y, radius = 1) {
|
||||
let sum = 0;
|
||||
let total = 0;
|
||||
for (let dy = -radius; dy <= radius; dy++) {
|
||||
for (let dx = -radius; dx <= radius; dx++) {
|
||||
if (!dx && !dy) continue;
|
||||
const nx = x + dx;
|
||||
const ny = y + dy;
|
||||
if (!inside(nx, ny)) continue;
|
||||
total++;
|
||||
if (sea[indexOf(nx, ny)]) sum += 1;
|
||||
}
|
||||
}
|
||||
return total > 0 ? sum / total : 0;
|
||||
}
|
||||
|
||||
function highAltitudeTransportClosed(i) {
|
||||
// Above this contour the generator should treat mountains as no-road
|
||||
// terrain. A strong mapped pass is the exception, so genuine saddle
|
||||
// crossings can still exist without roads drilling through entire ranges.
|
||||
return elevation[i] >= 0.70;
|
||||
}
|
||||
|
||||
for (let y = 0; y < MAP_H; y++) {
|
||||
for (let x = 0; x < MAP_W; x++) {
|
||||
const i = indexOf(x, y);
|
||||
if (sea[i] || highAltitudeTransportClosed(i)) {
|
||||
expressway[i] = rail[i] = national[i] = local[i] = INF;
|
||||
expresswayPotential[i] = railPotential[i] = nationalPotential[i] = localPotential[i] = 0;
|
||||
continue;
|
||||
}
|
||||
const density = settlementDemand[i];
|
||||
const mediumDensity = clamp(1 - Math.abs(density - 0.42) / 0.30);
|
||||
const highDensity = clamp((density - 0.32) / 0.50);
|
||||
const lowland = clamp(plain[i] * 0.48 + basinField[i] * 0.28 + valleyField[i] * 0.24 + coastalLowland[i] * 0.26 + agriculture[i] * 0.16);
|
||||
const pass = passSuitability?.[i] || 0;
|
||||
const crossing = crossingSuitability?.[i] || 0;
|
||||
const waterCrossingPenalty = river[i] > 0.18 ? (1 - crossing) * (0.72 + river[i] * 1.35) : 0;
|
||||
const seaNear = seaAdjacency(x, y, 1);
|
||||
const seaBroad = seaAdjacency(x, y, 3);
|
||||
const seaWide = seaAdjacency(x, y, 5);
|
||||
// Roads should use coastal lowlands when there is a settlement/port reason,
|
||||
// but should not casually trace beaches or hop over small bays.
|
||||
const coastalTraversePenalty = clamp(seaBroad * 1.72 + seaWide * 0.82 - coastalLowland[i] * 0.48 - (portSuitability?.[i] || 0) * 0.30);
|
||||
const highMountain = clamp((elevation[i] - 0.52) * 3.6 + slope[i] * 0.95 + ridgeField[i] * 1.05 - pass * 0.55 - valleyField[i] * 0.12);
|
||||
const extremeMountain = clamp((elevation[i] - 0.64) * 4.8 + slope[i] * 1.55 + ridgeField[i] * 1.45 - pass * 0.80);
|
||||
const denseCorePenalty = clamp((density - 0.66) / 0.28);
|
||||
const openPlainParallelPenalty = clamp(plain[i] * 0.48 + agriculture[i] * 0.26 - density * 0.20 - valleyField[i] * 0.20 - coastalLowland[i] * 0.12);
|
||||
const boundaryRidgePenalty = Math.pow(naturalBarrierScore?.[i] || 0, 2);
|
||||
|
||||
if (extremeMountain > 0.92 && pass < 0.34) {
|
||||
expressway[i] = rail[i] = INF;
|
||||
national[i] = elevation[i] >= 0.68 ? INF : 2.9 + extremeMountain * 2.8 + waterCrossingPenalty;
|
||||
local[i] = elevation[i] >= 0.69 ? INF : 2.2 + extremeMountain * 2.3 + waterCrossingPenalty * 0.55;
|
||||
expresswayPotential[i] = 0;
|
||||
railPotential[i] = 0;
|
||||
nationalPotential[i] = clamp(lowland * 0.18 + pass * 0.24 - extremeMountain * 0.55);
|
||||
localPotential[i] = clamp(valleySettlement[i] * 0.14 + pass * 0.18 - extremeMountain * 0.28);
|
||||
continue;
|
||||
}
|
||||
|
||||
expresswayPotential[i] = clamp(
|
||||
mediumDensity * 0.62 +
|
||||
urbanEdge[i] * 0.38 +
|
||||
logisticsPreSuitability[i] * 0.54 +
|
||||
lowland * 0.36 +
|
||||
agriculture[i] * 0.16 -
|
||||
denseCorePenalty * 0.54 -
|
||||
slope[i] * 0.82 -
|
||||
highMountain * 0.92 -
|
||||
coastalTraversePenalty * 0.32 -
|
||||
river[i] * 0.14
|
||||
);
|
||||
railPotential[i] = clamp(
|
||||
highDensity * 0.80 +
|
||||
preliminaryTownInfluence[i] * 0.22 +
|
||||
lowland * 0.46 +
|
||||
valleyField[i] * 0.22 +
|
||||
coastalLowland[i] * 0.22 -
|
||||
slope[i] * 1.28 -
|
||||
highMountain * 1.10 -
|
||||
coastalTraversePenalty * 0.26 -
|
||||
ridgeField[i] * 0.34
|
||||
);
|
||||
nationalPotential[i] = clamp(
|
||||
density * 0.46 +
|
||||
preliminaryTownInfluence[i] * 0.32 +
|
||||
preliminaryVillageInfluence[i] * 0.20 +
|
||||
agriculture[i] * 0.24 +
|
||||
valleyField[i] * 0.28 +
|
||||
coastalLowland[i] * 0.26 +
|
||||
pass * 0.18 +
|
||||
crossing * 0.18 -
|
||||
slope[i] * 0.48 -
|
||||
highMountain * 0.24 -
|
||||
coastalTraversePenalty * 0.16 -
|
||||
ridgeField[i] * 0.18
|
||||
);
|
||||
localPotential[i] = clamp(
|
||||
preliminaryVillageInfluence[i] * 0.52 +
|
||||
agriculture[i] * 0.38 +
|
||||
coastalSettlement[i] * 0.30 +
|
||||
valleySettlement[i] * 0.30 +
|
||||
developable[i] * 0.18 -
|
||||
slope[i] * 0.34 -
|
||||
coastalTraversePenalty * 0.08 -
|
||||
ridgeField[i] * 0.10
|
||||
);
|
||||
|
||||
expressway[i] = Math.max(0.18,
|
||||
1.62 - expresswayPotential[i] * 0.96 +
|
||||
denseCorePenalty * 1.30 +
|
||||
slope[i] * 5.4 +
|
||||
highMountain * 5.8 +
|
||||
extremeMountain * 4.2 +
|
||||
boundaryRidgePenalty * 4.2 +
|
||||
waterCrossingPenalty * 2.1 +
|
||||
coastalTraversePenalty * 2.65 +
|
||||
seaNear * 2.35 +
|
||||
seaWide * 1.10 +
|
||||
openPlainParallelPenalty * 0.12 +
|
||||
hash2(x, y, seed + 13301) * 0.04
|
||||
);
|
||||
rail[i] = Math.max(0.16,
|
||||
1.48 - railPotential[i] * 1.02 +
|
||||
slope[i] * 7.2 +
|
||||
highMountain * 7.0 +
|
||||
extremeMountain * 4.8 +
|
||||
boundaryRidgePenalty * 2.4 +
|
||||
waterCrossingPenalty * 1.7 +
|
||||
coastalTraversePenalty * 1.75 +
|
||||
seaNear * 1.50 +
|
||||
seaWide * 0.70 +
|
||||
hash2(x, y, seed + 13302) * 0.03
|
||||
);
|
||||
national[i] = Math.max(0.16,
|
||||
1.28 - nationalPotential[i] * 0.84 +
|
||||
slope[i] * 2.8 +
|
||||
ridgeField[i] * 1.18 +
|
||||
Math.max(0, elevation[i] - 0.62) * 3.0 +
|
||||
highMountain * 2.9 +
|
||||
boundaryRidgePenalty * 1.8 +
|
||||
waterCrossingPenalty * 1.25 -
|
||||
valleyField[i] * 0.18 -
|
||||
coastalLowland[i] * 0.08 +
|
||||
coastalTraversePenalty * 1.55 +
|
||||
seaNear * 0.84 +
|
||||
seaWide * 0.48 -
|
||||
pass * 0.42 +
|
||||
hash2(x, y, seed + 13303) * 0.05
|
||||
);
|
||||
local[i] = Math.max(0.14,
|
||||
1.12 - localPotential[i] * 0.86 +
|
||||
slope[i] * 1.72 +
|
||||
ridgeField[i] * 0.82 +
|
||||
Math.max(0, elevation[i] - 0.68) * 1.9 +
|
||||
highMountain * 1.24 +
|
||||
boundaryRidgePenalty * 0.72 +
|
||||
waterCrossingPenalty * 0.65 -
|
||||
valleyField[i] * 0.22 -
|
||||
coastalLowland[i] * 0.10 +
|
||||
coastalTraversePenalty * 0.82 +
|
||||
seaNear * 0.48 +
|
||||
seaWide * 0.26 +
|
||||
hash2(x, y, seed + 13304) * 0.07
|
||||
);
|
||||
}
|
||||
}
|
||||
return { expressway, rail, national, local, expresswayPotential, railPotential, nationalPotential, localPotential };
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue