This commit is contained in:
33333-33333 2026-05-21 22:03:14 +09:00
commit 3fe9c31453
12 changed files with 963 additions and 127 deletions

View file

@ -418,29 +418,52 @@ export function generateRegionalPrefectures(seed, sea, elevation, slope, river,
const { compartmentId, compartments } = buildRegionalNaturalCompartments(sea, elevation, slope, river, ridgeField, flowAccum, naturalBarrierScore);
const owner = new Int16Array(compartments.length);
owner.fill(-1);
for (let id = 0; id < seeded.centers.length; id++) {
const center = seeded.centers[id];
if (!center || !inside(center.x, center.y)) continue;
const ci = compartmentId[indexOf(center.x, center.y)];
if (ci >= 0) owner[ci] = id;
}
for (const unit of compartments) {
if (!unit || unit.area === 0) continue;
const counts = new Map();
let anchorCells = 0;
for (const i of unit.cells) {
if (anchorMask[i]) anchorCells++;
const id = beforeRegionId[i];
if (id >= 0) counts.set(id, (counts.get(id) || 0) + 1);
if (unit.cells.some((i) => anchorMask[i])) owner[unit.id] = 0;
}
for (let pass = 0; pass < compartments.length + 6; pass++) {
let changedThisPass = 0;
for (const unit of compartments) {
if (!unit || unit.area === 0 || owner[unit.id] >= 0) continue;
let bestOwner = -1;
let bestScore = -INF;
for (const [neighborId, edge] of unit.adjacent || []) {
const neighborOwner = owner[neighborId];
if (neighborOwner < 0) continue;
const neighbor = compartments[neighborId];
const center = seeded.centers[neighborOwner];
const barrier = edge.target / Math.max(1, edge.count);
const sameClass = neighbor?.classId === unit.classId ? 1.0 : 0;
const d = center ? Math.hypot(unit.x - center.x, unit.y - center.y) : 0;
const score = edge.count * 0.45 + sameClass + neighbor.coastalExposure * 0.08 + neighbor.ridgeExposure * 0.05 - barrier * 2.6 - d * 0.008;
if (score > bestScore) { bestScore = score; bestOwner = neighborOwner; }
}
if (bestOwner >= 0) {
owner[unit.id] = bestOwner;
changedThisPass++;
}
}
if (anchorCells > 0) {
owner[unit.id] = 0;
continue;
}
let bestId = -1;
let best = -1;
for (const [id, count] of counts) {
if (changedThisPass === 0) break;
}
for (const unit of compartments) {
if (!unit || unit.area === 0 || owner[unit.id] >= 0) continue;
let bestId = 0;
let best = -INF;
for (let id = 0; id < seeded.centers.length; id++) {
const center = seeded.centers[id];
const centerFit = center ? -Math.hypot(center.x - unit.x, center.y - unit.y) * 0.012 : 0;
const terrainFit = unit.ridgeExposure * 0.10 + unit.riverExposure * 0.04 + unit.coastalExposure * 0.08;
const score = count + centerFit + terrainFit;
if (!center) continue;
const d = Math.hypot(unit.x - center.x, unit.y - center.y);
const score = -d + (id === 0 ? (unit.cells.some((i) => anchorMask[i]) ? 1000 : -12) : 0);
if (score > best) { best = score; bestId = id; }
}
owner[unit.id] = bestId >= 0 ? bestId : 0;
owner[unit.id] = bestId;
}
const regionId = new Int16Array(beforeRegionId);
@ -472,6 +495,9 @@ export function generateRegionalPrefectures(seed, sea, elevation, slope, river,
regionalNaturalBarrierAverageBefore: beforeNaturalAverage,
regionalNaturalBarrierAverageAfter: afterNaturalAverage,
regionalCompartmentCount: compartments.filter((unit) => unit.area > 0).length,
compartmentCount: compartments.filter((unit) => unit.area > 0).length,
changedAfterCompartmentAssignment: changed,
borderNaturalBarrierAverage: afterNaturalAverage,
},
};
}
@ -635,8 +661,33 @@ function buildRegionalNaturalCompartments(sea, elevation, slope, river, ridgeFie
ridgeExposure: ridgeExposure / Math.max(1, area),
riverExposure: riverExposure / Math.max(1, area),
coastalExposure: coastalExposure / Math.max(1, area),
adjacent: new Map(),
});
}
for (let y = 0; y < MAP_H; y++) {
for (let x = 0; x < MAP_W; x++) {
const i = indexOf(x, y);
if (sea[i]) continue;
const a = compartmentId[i];
if (a < 0 || !compartments[a]) continue;
for (const [nx, ny] of [[x + 1, y], [x, y + 1]]) {
if (!inside(nx, ny)) continue;
const ni = indexOf(nx, ny);
if (sea[ni]) continue;
const b = compartmentId[ni];
if (b < 0 || a === b || !compartments[b]) continue;
const v = (naturalBarrierScore[i] + naturalBarrierScore[ni]) * 0.5;
const edgeA = compartments[a].adjacent.get(b) || { count: 0, target: 0 };
edgeA.count++;
edgeA.target += v;
compartments[a].adjacent.set(b, edgeA);
const edgeB = compartments[b].adjacent.get(a) || { count: 0, target: 0 };
edgeB.count++;
edgeB.target += v;
compartments[b].adjacent.set(a, edgeB);
}
}
}
return { compartmentId, compartments };
}
@ -845,6 +896,15 @@ export function applyOutputOptions(map, options = {}) {
delete slim.flowAccum;
delete slim.erosionField;
delete slim.depositionField;
delete slim.terrainTemplate;
delete slim.ocean;
delete slim.lake;
delete slim.arcSpineField;
delete slim.branchRidgeField;
delete slim.depositionalLowland;
delete slim.alluvialFanField;
delete slim.deltaField;
delete slim.naturalBarrierScore;
return slim;
}