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

@ -5,6 +5,7 @@ import { applyOutputOptions, attachIdsAndNames, recalculatePopulationAfterLandus
export function finishMapOutput({
seed,
options,
terrainTemplate,
cityPopulationCap,
stationInfluence,
roadInfluence,
@ -13,6 +14,8 @@ export function finishMapOutput({
moisture,
slope,
sea,
ocean,
lake,
river,
floodplain,
plain,
@ -25,6 +28,12 @@ export function finishMapOutput({
flowAccum,
erosionField,
depositionField,
arcSpineField,
branchRidgeField,
depositionalLowland,
alluvialFanField,
deltaField,
naturalBarrierScore,
villages,
ports,
crossings,
@ -132,6 +141,58 @@ export function finishMapOutput({
castleRuins = attachIdsAndNames(tagInsidePrefecture(castleRuins, prefectureMask), "castleRuin", seed, null, nameFields, usedNames, nameDebug);
externalGateways = attachIdsAndNames(tagInsidePrefecture(externalGateways, prefectureMask), "gateway", seed, "External Gateway", nameFields, usedNames, nameDebug);
const adminCenters = attachIdsAndNames(tagInsidePrefecture(adminCentersRaw, prefectureMask), "admin", seed, "Municipal Center", nameFields, usedNames, nameDebug);
const representativeFeatures = [
...modernCities.map((p) => ({ ...p, representativeWeight: 5.0 + (p.population || 0) / 180000 })),
...markets.map((p) => ({ ...p, representativeWeight: 3.2 })),
...ports.map((p) => ({ ...p, representativeWeight: p.portClass === "major" ? 3.8 : 2.4 })),
...villages.map((p) => ({ ...p, representativeWeight: 1.6 })),
].filter((p) => p.insidePrefecture && p.name);
for (const center of adminCenters) {
const centerAdmin = adminId?.[indexOf(center.x, center.y)];
let best = null;
let bestScore = -INF;
for (const sameAdminOnly of [true, false]) {
for (const feature of representativeFeatures) {
const featureAdmin = adminId?.[indexOf(feature.x, feature.y)];
if (sameAdminOnly && centerAdmin >= 0 && featureAdmin >= 0 && featureAdmin !== centerAdmin) continue;
const d = Math.hypot(center.x - feature.x, center.y - feature.y);
const score = feature.representativeWeight - d * 0.11 - (sameAdminOnly ? 0 : 1.2);
if (score > bestScore) {
bestScore = score;
best = feature;
}
}
if (best) break;
}
if (best) {
center.representativeFeatureId = best.id;
center.representativeFeatureName = best.name;
center.generatedMunicipalityName = center.name;
center.name = best.name;
}
}
const adminNamePrefixes = ["\u6771", "\u897F", "\u5357", "\u5317", "\u4E0A", "\u4E0B", "\u65B0", "\u65E7", "\u4E2D", "\u5916"];
const adminNameCounts = new Map();
for (const center of adminCenters) adminNameCounts.set(center.name, (adminNameCounts.get(center.name) || 0) + 1);
const duplicateOrdinal = new Map();
for (const center of adminCenters) {
if ((adminNameCounts.get(center.name) || 0) <= 1) continue;
const n = duplicateOrdinal.get(center.name) || 0;
duplicateOrdinal.set(center.name, n + 1);
const prefix = adminNamePrefixes[(Math.floor(center.x / Math.max(1, MAP_W / 3)) + Math.floor(center.y / Math.max(1, MAP_H / 3)) * 3 + n) % adminNamePrefixes.length];
if (!String(center.name).startsWith(prefix)) center.name = `${prefix}${center.name}`;
}
const usedAdminNames = new Set();
for (const center of adminCenters) {
let candidate = center.name;
let guard = 0;
while (usedAdminNames.has(candidate) && guard < adminNamePrefixes.length) {
candidate = `${adminNamePrefixes[(guard + Math.floor(center.x / 12) + Math.floor(center.y / 12)) % adminNamePrefixes.length]}${center.name}`;
guard++;
}
center.name = candidate;
usedAdminNames.add(center.name);
}
const entitiesForNames = [
...modernCities,
@ -146,6 +207,7 @@ export function finishMapOutput({
...newTowns,
...passes,
...crossings,
...adminCenters,
...externalGateways,
].filter((p) => p.insidePrefecture || p.kind === "External Gateway");
@ -153,6 +215,7 @@ export function finishMapOutput({
width: MAP_W,
height: MAP_H,
cellSize: CELL_SIZE,
terrainTemplate,
prefectureMask,
prefectureBorder,
prefectureRegionId,
@ -162,6 +225,8 @@ export function finishMapOutput({
moisture,
slope,
sea,
ocean,
lake,
river,
floodplain,
plain,
@ -174,6 +239,12 @@ export function finishMapOutput({
flowAccum,
erosionField,
depositionField,
arcSpineField,
branchRidgeField,
depositionalLowland,
alluvialFanField,
deltaField,
naturalBarrierScore,
villages,
ports,
crossings,