1283 lines
65 KiB
JavaScript
1283 lines
65 KiB
JavaScript
import { MAP_H, MAP_W, fbm, valueNoise } from "../src/mapUtils.js";
|
|
import { createExactNoiseMemo } from "../src/mapTerrain.js";
|
|
import {
|
|
capturePatchTransactionSnapshot,
|
|
buildLargeExpansionTiles,
|
|
buildPatchRects,
|
|
buildRawPatchCandidateRequest,
|
|
buildTiledFinalQualityBasis,
|
|
captureStrictMetadataSnapshot,
|
|
captureStrictSelectionFieldSnapshot,
|
|
normalizePatchPrefectureCapitals,
|
|
preparePatchTransactionFields,
|
|
reconcileGeneratedHumanPointsWithFinalTerrain,
|
|
regionalRecalculationProbability,
|
|
restorePatchTransactionSnapshot,
|
|
refreshPatchPrefectureMetadata,
|
|
synchronizePatchAdministrativeMetadata,
|
|
synchronizePatchMunicipalityField,
|
|
} from "../src/mapPatch.js";
|
|
import {
|
|
applyCommittedMirrorDelta,
|
|
buildCommittedMirrorDelta,
|
|
buildCommittedMirrorDeltaFromTransaction,
|
|
buildMainThreadTransferDelta,
|
|
hashCommittedWorld,
|
|
runPatchCandidateSearch,
|
|
runPatchCandidateSearchAsync,
|
|
scheduleRawCandidateSequence,
|
|
shutdownRawCandidateWorkers,
|
|
} from "../src/mapPatchWorker.js";
|
|
import { hashCommittedWorldAsync, materializeCommittedWorldDelta, materializeCommittedWorldDeltaCooperative } from "../src/committedWorldDelta.js";
|
|
import { getViewportMap } from "../src/worldViewport.js";
|
|
import { createWorldMap } from "../src/worldMap.js";
|
|
import { compactRawPatchCandidate, summarizeRawPatchCandidate } from "../src/rawPatchCandidate.js";
|
|
|
|
function assert(condition, message) {
|
|
if (!condition) throw new Error(message);
|
|
console.log(`OK: ${message}`);
|
|
}
|
|
|
|
const recalcAtSelection = regionalRecalculationProbability(0, 100);
|
|
const recalcNear = regionalRecalculationProbability(20, 100);
|
|
const recalcFar = regionalRecalculationProbability(70, 100);
|
|
const recalcOutside = regionalRecalculationProbability(100, 100);
|
|
assert(recalcAtSelection === 1
|
|
&& recalcNear > recalcFar
|
|
&& recalcFar > 0
|
|
&& recalcOutside === 0,
|
|
"regional recalculation probability rises monotonically toward the selected expansion area");
|
|
|
|
function testPointInPolygon(px, py, polygon) {
|
|
let inside = false;
|
|
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
|
const xi = polygon[i].x + 0.5;
|
|
const yi = polygon[i].y + 0.5;
|
|
const xj = polygon[j].x + 0.5;
|
|
const yj = polygon[j].y + 0.5;
|
|
const denomRaw = yj - yi;
|
|
const denom = Math.abs(denomRaw) < 1e-6 ? (denomRaw < 0 ? -1e-6 : 1e-6) : denomRaw;
|
|
if (((yi > py) !== (yj > py)) && px < ((xj - xi) * (py - yi)) / denom + xi) inside = !inside;
|
|
}
|
|
return inside;
|
|
}
|
|
|
|
const base = { fields: { marker: new Uint8Array([1]) } };
|
|
const calls = [];
|
|
const progress = [];
|
|
const search = runPatchCandidateSearch({
|
|
id: 1,
|
|
world: base,
|
|
rect: { x0: 0, y0: 0, x1: 1, y1: 1 },
|
|
options: {},
|
|
search: {
|
|
searchId: "unit-search",
|
|
committedRevision: 1,
|
|
workerEpoch: 1,
|
|
candidatePlan: [{ variant: 5, seed: 105 }, { variant: 6, seed: 106 }],
|
|
},
|
|
}, {
|
|
cloneWorld: structuredClone,
|
|
onProgress: (message) => progress.push(message.progress),
|
|
generateCandidate: (world, rect, options) => {
|
|
calls.push({ variant: options.variant, baseline: world.fields.marker[0] });
|
|
world.fields.marker[0] = options.variant;
|
|
return options.variant === 5
|
|
? { ok: false, code: "patch-quality-gate-failed", reason: "forced reject" }
|
|
: { ok: true, variant: options.variant, seed: options.seed, seamDiagnostics: { hardPass: true } };
|
|
},
|
|
});
|
|
assert(search.result?.ok && search.result.actualVariant === 6, "content rejection advances to the next complete candidate");
|
|
assert(calls.length === 2 && calls.every((call) => call.baseline === 1), "candidate worlds start from one immutable baseline");
|
|
assert(progress.filter((event) => event.boundedWork).every((event) => event.completed <= event.total), "bounded progress remains inside its finite work total");
|
|
|
|
const bestOfThreeCalls = [];
|
|
const bestOfThreeScores = new Map([[12, 0.31], [13, 0.88], [14, 0.57]]);
|
|
const bestOfThree = runPatchCandidateSearch({
|
|
id: 1001,
|
|
world: base,
|
|
rect: { x0: 0, y0: 0, x1: 1, y1: 1 },
|
|
options: { acceptBestAvailableQuality: true },
|
|
search: {
|
|
searchId: "unit-best-of-three",
|
|
selectBestCandidate: true,
|
|
candidatePlan: [12, 13, 14].map((variant, index) => ({ candidateOrdinal: index + 1, candidateId: `best-${variant}`, variant, seed: 100 + variant })),
|
|
},
|
|
}, {
|
|
cloneWorld: structuredClone,
|
|
generateCandidate: (world, rect, options) => {
|
|
bestOfThreeCalls.push(options.variant);
|
|
world.fields.marker[0] = options.variant;
|
|
return {
|
|
ok: true,
|
|
variant: options.variant,
|
|
seed: options.seed,
|
|
candidateQuality: { hardPass: false, score: bestOfThreeScores.get(options.variant) },
|
|
seamDiagnostics: { hardPass: false, gateReasons: ["forced-diagnostic-only-seam"] },
|
|
rects: { writeRect: rect },
|
|
};
|
|
},
|
|
});
|
|
assert(bestOfThree.result?.ok
|
|
&& bestOfThree.result.bestOfCandidates === true
|
|
&& bestOfThree.result.actualVariant === 13
|
|
&& bestOfThree.result.candidateOrdinal === 2
|
|
&& bestOfThreeCalls.join(",") === "12,13,14"
|
|
&& bestOfThree.result.searchAttempts.map((attempt) => attempt.status).join(",") === "evaluated,success,evaluated",
|
|
"best-of-three mode evaluates every complete candidate and publishes the highest quality even when all gates remain diagnostic failures");
|
|
|
|
const asyncBestOfThree = await runPatchCandidateSearchAsync({
|
|
id: 1002,
|
|
world: base,
|
|
rect: { x0: 0, y0: 0, x1: 1, y1: 1 },
|
|
options: { acceptBestAvailableQuality: true },
|
|
search: {
|
|
searchId: "unit-best-of-three-async",
|
|
selectBestCandidate: true,
|
|
candidatePlan: [21, 22, 23].map((variant, index) => ({ candidateOrdinal: index + 1, candidateId: `async-best-${variant}`, variant, seed: 200 + variant })),
|
|
},
|
|
}, {
|
|
cloneWorld: structuredClone,
|
|
generateCandidate: async (world, rect, options) => ({
|
|
ok: true,
|
|
variant: options.variant,
|
|
seed: options.seed,
|
|
candidateQuality: { hardPass: options.variant === 22, score: options.variant === 23 ? 0.93 : options.variant === 22 ? 0.71 : 0.42 },
|
|
seamDiagnostics: { hardPass: options.variant === 22, gateReasons: options.variant === 22 ? [] : ["diagnostic-seam"] },
|
|
rects: { writeRect: rect },
|
|
}),
|
|
});
|
|
assert(asyncBestOfThree.result?.ok && asyncBestOfThree.result.actualVariant === 23
|
|
&& asyncBestOfThree.result.searchAttempts.length === 3,
|
|
"async best-of-three selection uses quality score as the primary ranking signal and evaluates all candidates");
|
|
|
|
const repeatedPipelineProgress = [];
|
|
const repeatedPipelineSearch = runPatchCandidateSearch({
|
|
id: 101,
|
|
world: base,
|
|
rect: { x0: 0, y0: 0, x1: 1, y1: 1 },
|
|
options: {},
|
|
search: {
|
|
searchId: "unit-repeated-pipeline-progress",
|
|
candidatePlan: [{ variant: 11, seed: 111 }, { variant: 12, seed: 112 }],
|
|
},
|
|
}, {
|
|
cloneWorld: structuredClone,
|
|
onProgress: (message) => repeatedPipelineProgress.push(message.progress),
|
|
generateCandidate: (world, rect, options) => {
|
|
// Every complete candidate legitimately reuses the same producer-local
|
|
// work-unit name. The search controller must scope it by candidate rather
|
|
// than treating candidate 2 as a reset of candidate 1.
|
|
options.onProgress({ phase: "terrain", key: "terrain:base", workUnitId: "terrain-production", completed: 0, total: 10 });
|
|
options.onProgress({ phase: "terrain", key: "terrain:base", workUnitId: "terrain-production", completed: 10, total: 10 });
|
|
return options.variant === 11
|
|
? { ok: false, code: "patch-quality-gate-failed", reason: "forced first-candidate reject" }
|
|
: { ok: true, seamDiagnostics: { hardPass: true } };
|
|
},
|
|
});
|
|
const repeatedTerrainUnits = repeatedPipelineProgress
|
|
.filter((event) => event.key === "terrain:base")
|
|
.map((event) => event.workUnitId);
|
|
assert(repeatedPipelineSearch.ok && repeatedPipelineSearch.result?.actualVariant === 12
|
|
&& repeatedTerrainUnits.some((id) => id === "candidate-1/terrain-production")
|
|
&& repeatedTerrainUnits.some((id) => id === "candidate-2/terrain-production"),
|
|
"rejected candidates may restart the same producer-local bounded work under a candidate-scoped workUnitId");
|
|
|
|
|
|
const sequenceForwardSentinel = () => ({ promises: [], done: Promise.resolve(), release() {}, cancel() {} });
|
|
let forwardedSequence = null;
|
|
const asyncForwardSearch = await runPatchCandidateSearchAsync({
|
|
id: 102,
|
|
world: base,
|
|
rect: { x0: 0, y0: 0, x1: 1, y1: 1 },
|
|
options: {},
|
|
search: { searchId: "unit-sequence-forward", candidatePlan: [{ variant: 1, seed: 1 }] },
|
|
}, {
|
|
cloneWorld: structuredClone,
|
|
precomputeRawCandidateSequence: sequenceForwardSentinel,
|
|
generateCandidate: async (world, rect, options) => {
|
|
forwardedSequence = options._precomputeRawCandidateSequence;
|
|
return { ok: true, seamDiagnostics: { hardPass: true } };
|
|
},
|
|
});
|
|
assert(asyncForwardSearch.ok && asyncForwardSearch.result?.ok && forwardedSequence === sequenceForwardSentinel,
|
|
"async candidate search forwards the continuous raw-tile sequence provider into production generation");
|
|
|
|
const invalidProgress = runPatchCandidateSearch({
|
|
id: 2,
|
|
world: base,
|
|
rect: { x0: 0, y0: 0, x1: 1, y1: 1 },
|
|
options: {},
|
|
search: { searchId: "unit-invalid-progress", candidatePlan: [{ variant: 1, seed: 1 }] },
|
|
}, {
|
|
cloneWorld: structuredClone,
|
|
generateCandidate: (world, rect, options) => {
|
|
options.onProgress({ key: "runaway", completed: 4, total: 3 });
|
|
return { ok: true, seamDiagnostics: { hardPass: true } };
|
|
},
|
|
});
|
|
assert(!invalidProgress.ok && invalidProgress.code === "worker-progress-invariant", "runaway bounded work is an invariant failure");
|
|
|
|
const distinctRouteUnits = runPatchCandidateSearch({
|
|
id: 3,
|
|
world: base,
|
|
rect: { x0: 0, y0: 0, x1: 1, y1: 1 },
|
|
options: {},
|
|
search: { searchId: "unit-distinct-route-progress", candidatePlan: [{ variant: 1, seed: 1 }] },
|
|
}, {
|
|
cloneWorld: structuredClone,
|
|
generateCandidate: (world, rect, options) => {
|
|
options.onProgress({ phase: "transport-routing", key: "route:corridor", workUnitId: "corridor-a", completed: 2048, total: 8800 });
|
|
options.onProgress({ phase: "transport-routing", key: "route:corridor", workUnitId: "corridor-b", completed: 2048, total: 6094 });
|
|
options.onProgress({ phase: "transport-routing-detail", key: "route:corridor", workUnitId: "corridor-b", completed: 4096, total: 6094 });
|
|
return { ok: true, seamDiagnostics: { hardPass: true } };
|
|
},
|
|
});
|
|
assert(distinctRouteUnits.ok && distinctRouteUnits.result?.ok, "independent route work units may share a display key and use different finite totals");
|
|
|
|
const changedRouteTotal = runPatchCandidateSearch({
|
|
id: 4,
|
|
world: base,
|
|
rect: { x0: 0, y0: 0, x1: 1, y1: 1 },
|
|
options: {},
|
|
search: { searchId: "unit-changed-route-total", candidatePlan: [{ variant: 1, seed: 1 }] },
|
|
}, {
|
|
cloneWorld: structuredClone,
|
|
generateCandidate: (world, rect, options) => {
|
|
options.onProgress({ phase: "transport-routing", key: "route:corridor", workUnitId: "corridor-one", completed: 1024, total: 8800 });
|
|
options.onProgress({ phase: "transport-routing-detail", key: "route:corridor", workUnitId: "corridor-one", completed: 2048, total: 6094 });
|
|
return { ok: true, seamDiagnostics: { hardPass: true } };
|
|
},
|
|
});
|
|
assert(!changedRouteTotal.ok && changedRouteTotal.code === "worker-progress-invariant", "one finite workUnitId cannot change its total across phase changes");
|
|
|
|
const missingRouteWorkUnit = runPatchCandidateSearch({
|
|
id: 5,
|
|
world: base,
|
|
rect: { x0: 0, y0: 0, x1: 1, y1: 1 },
|
|
options: {},
|
|
search: { searchId: "unit-missing-route-work-unit", candidatePlan: [{ variant: 1, seed: 1 }] },
|
|
}, {
|
|
cloneWorld: structuredClone,
|
|
generateCandidate: (world, rect, options) => {
|
|
options.onProgress({ phase: "transport-routing", key: "route:corridor", completed: 2048, total: 8800 });
|
|
return { ok: true, seamDiagnostics: { hardPass: true } };
|
|
},
|
|
});
|
|
assert(!missingRouteWorkUnit.ok && missingRouteWorkUnit.code === "worker-progress-invariant", "bounded progress requires an explicit machine workUnitId");
|
|
|
|
const recoveredCandidateProgress = [];
|
|
const recoveredCandidateSearch = runPatchCandidateSearch({
|
|
id: 6,
|
|
world: base,
|
|
rect: { x0: 0, y0: 0, x1: 1, y1: 1 },
|
|
options: {},
|
|
search: {
|
|
searchId: "unit-recovered-candidate-progress",
|
|
totalCandidateCount: 3,
|
|
executionAttempt: 2,
|
|
candidatePlan: [
|
|
{ candidateId: "candidate-2", candidateOrdinal: 2, variant: 2, seed: 2 },
|
|
{ candidateId: "candidate-3", candidateOrdinal: 3, variant: 3, seed: 3 },
|
|
],
|
|
},
|
|
}, {
|
|
cloneWorld: structuredClone,
|
|
onProgress: (message) => recoveredCandidateProgress.push(message.progress),
|
|
generateCandidate: (world, rect, options) => options.variant === 2
|
|
? { ok: false, code: "patch-quality-gate-failed", reason: "forced post-restart reject" }
|
|
: { ok: true, seamDiagnostics: { hardPass: true } },
|
|
});
|
|
const recoveredSearchTicks = recoveredCandidateProgress
|
|
.filter((event) => event.workUnitId === "candidate-search" && Number.isFinite(event.completed))
|
|
.map((event) => Number(event.completed));
|
|
assert(recoveredCandidateSearch.ok && recoveredCandidateSearch.result?.actualVariant === 3
|
|
&& recoveredSearchTicks.every((value, index) => index === 0 || value >= recoveredSearchTicks[index - 1]),
|
|
"Worker recovery may resume at candidate ordinal 2 without moving candidate-search progress backward");
|
|
|
|
const recoveredAsyncCandidateProgress = [];
|
|
const recoveredAsyncCandidateSearch = await runPatchCandidateSearchAsync({
|
|
id: 7,
|
|
world: base,
|
|
rect: { x0: 0, y0: 0, x1: 1, y1: 1 },
|
|
options: {},
|
|
search: {
|
|
searchId: "unit-recovered-async-candidate-progress",
|
|
totalCandidateCount: 3,
|
|
executionAttempt: 2,
|
|
candidatePlan: [
|
|
{ candidateId: "candidate-2", candidateOrdinal: 2, variant: 2, seed: 2 },
|
|
{ candidateId: "candidate-3", candidateOrdinal: 3, variant: 3, seed: 3 },
|
|
],
|
|
},
|
|
}, {
|
|
cloneWorld: structuredClone,
|
|
onProgress: (message) => recoveredAsyncCandidateProgress.push(message.progress),
|
|
generateCandidate: async (world, rect, options) => options.variant === 2
|
|
? { ok: false, code: "patch-quality-gate-failed", reason: "forced post-restart reject" }
|
|
: { ok: true, seamDiagnostics: { hardPass: true } },
|
|
});
|
|
const recoveredAsyncTicks = recoveredAsyncCandidateProgress
|
|
.filter((event) => event.workUnitId === "candidate-search" && Number.isFinite(event.completed))
|
|
.map((event) => Number(event.completed));
|
|
assert(recoveredAsyncCandidateSearch.ok && recoveredAsyncCandidateSearch.result?.actualVariant === 3
|
|
&& recoveredAsyncTicks.every((value, index) => index === 0 || value >= recoveredAsyncTicks[index - 1]),
|
|
"async production recovery preserves global candidate ordinals in bounded search progress");
|
|
|
|
|
|
const asyncHashFixture = {
|
|
width: 3, height: 2, originX: -4, originY: 7,
|
|
fields: {
|
|
a: new Float32Array([0, 1.25, -2.5, 3.75, 0, 9]),
|
|
b: new Int16Array([7, -8, 9, -10, 11, -12]),
|
|
},
|
|
generatedMask: new Uint8Array([0, 1, 1, 0, 1, 0]),
|
|
sourceMap: { points: [{ x: 1, y: 2, name: "甲" }], tags: new Set(["b", "a"]) },
|
|
serial: 4,
|
|
};
|
|
let asyncHashYields = 0;
|
|
const exactAsyncHash = await hashCommittedWorldAsync(asyncHashFixture, {
|
|
yieldEvery: 7,
|
|
yieldControl: async () => { asyncHashYields++; },
|
|
});
|
|
assert(exactAsyncHash === hashCommittedWorld(asyncHashFixture) && asyncHashYields > 0,
|
|
"cooperative committed-world hash is bit-identical to the synchronous Worker hash while yielding bounded chunks");
|
|
let abortHash = false;
|
|
try {
|
|
let abortAfterYield = false;
|
|
await hashCommittedWorldAsync(asyncHashFixture, {
|
|
yieldEvery: 4,
|
|
yieldControl: async () => { abortAfterYield = true; },
|
|
shouldAbort: () => abortAfterYield,
|
|
});
|
|
} catch (error) {
|
|
abortHash = error?.name === "AbortError";
|
|
}
|
|
assert(abortHash, "cooperative committed-world hash observes cancellation between chunks");
|
|
|
|
const deltaBase = {
|
|
width: 4, height: 2,
|
|
fields: {
|
|
field: new Int32Array([1, 2, 3, 4, 5, 6, 7, 8]),
|
|
stable: new Uint8Array([9, 9, 9, 9, 9, 9, 9, 9]),
|
|
},
|
|
generatedMask: new Uint8Array(8), sourceMap: { points: [{ x: 1 }] }, serial: 1,
|
|
};
|
|
const deltaTarget = structuredClone(deltaBase);
|
|
deltaBase.sourceMap.unchangedPaths = [[[0, 0], [1, 1]]];
|
|
deltaTarget.sourceMap.unchangedPaths = [[[0, 0], [1, 1]]];
|
|
deltaTarget.fields.field[2] = 30;
|
|
deltaTarget.fields.field[7] = 80;
|
|
deltaTarget.generatedMask[6] = 1;
|
|
deltaTarget.sourceMap.points.push({ x: 2 });
|
|
deltaTarget.serial = 2;
|
|
const committedDelta = buildCommittedMirrorDelta(deltaBase, deltaTarget);
|
|
const deltaApplied = applyCommittedMirrorDelta(structuredClone(deltaBase), committedDelta);
|
|
assert(JSON.stringify(Array.from(deltaApplied.fields.field)) === JSON.stringify(Array.from(deltaTarget.fields.field))
|
|
&& JSON.stringify(Array.from(deltaApplied.generatedMask)) === JSON.stringify(Array.from(deltaTarget.generatedMask))
|
|
&& JSON.stringify(deltaApplied.sourceMap) === JSON.stringify(deltaTarget.sourceMap)
|
|
&& deltaApplied.serial === 2, "transactional Apply delta exactly reproduces the accepted world");
|
|
assert(!("sourceMap" in committedDelta)
|
|
&& !("unchangedPaths" in (committedDelta.sourceMapDelta?.set || {}))
|
|
&& !("points" in (committedDelta.sourceMapDelta?.set || {}))
|
|
&& committedDelta.sourceMapDelta?.arraySplices?.points?.start === 1
|
|
&& committedDelta.sourceMapDelta?.arraySplices?.points?.deleteCount === 0
|
|
&& committedDelta.sourceMapDelta?.arraySplices?.points?.items?.length === 1
|
|
&& !("width" in (committedDelta.metaDelta?.set || {})), "Apply delta retains only changed source and metadata keys");
|
|
const materializeBaseHash = hashCommittedWorld(deltaBase);
|
|
const materializedDelta = buildCommittedMirrorDelta(deltaBase, deltaTarget);
|
|
const materializedPreview = materializeCommittedWorldDelta(deltaBase, materializedDelta, { consumeMetadata: true });
|
|
assert(hashCommittedWorld(materializedPreview) === hashCommittedWorld(deltaTarget)
|
|
&& hashCommittedWorld(deltaBase) === materializeBaseHash
|
|
&& materializedPreview.fields.field !== deltaBase.fields.field
|
|
&& materializedPreview.fields.stable === deltaBase.fields.stable
|
|
&& materializedPreview.sourceMap.points !== deltaBase.sourceMap.points
|
|
&& materializedPreview.sourceMap.unchangedPaths === deltaBase.sourceMap.unchangedPaths,
|
|
"preview materialization clones changed fields/layers only and leaves the committed world immutable");
|
|
let cooperativeYields = 0;
|
|
const cooperativePreview = await materializeCommittedWorldDeltaCooperative(deltaBase, buildCommittedMirrorDelta(deltaBase, deltaTarget), {
|
|
consumeMetadata: true,
|
|
chunkBytes: 8,
|
|
yieldControl: async () => { cooperativeYields++; },
|
|
});
|
|
assert(hashCommittedWorld(cooperativePreview) === hashCommittedWorld(deltaTarget)
|
|
&& hashCommittedWorld(deltaBase) === materializeBaseHash
|
|
&& cooperativeYields > 0,
|
|
"cooperative preview materialization is exact and yields between bounded raster chunks");
|
|
const cancellationBase = {
|
|
width: 4096, height: 1,
|
|
fields: { field: new Uint8Array(4096) },
|
|
generatedMask: new Uint8Array(4096),
|
|
sourceMap: {},
|
|
};
|
|
const cancellationTarget = structuredClone(cancellationBase);
|
|
cancellationTarget.fields.field.fill(7);
|
|
let cancellationYields = 0;
|
|
let materializationCancelled = false;
|
|
try {
|
|
await materializeCommittedWorldDeltaCooperative(cancellationBase, buildCommittedMirrorDelta(cancellationBase, cancellationTarget), {
|
|
consumeMetadata: true,
|
|
chunkBytes: 64,
|
|
yieldControl: async () => { cancellationYields++; },
|
|
shouldCancel: () => cancellationYields >= 2,
|
|
});
|
|
} catch (error) {
|
|
materializationCancelled = error?.name === "AbortError";
|
|
}
|
|
assert(materializationCancelled && cancellationYields >= 2 && cancellationBase.fields.field[0] === 0,
|
|
"cooperative preview materialization observes cancellation without mutating the committed world");
|
|
const transferDelta = buildMainThreadTransferDelta(materializedDelta);
|
|
const transferApplied = applyCommittedMirrorDelta(structuredClone(deltaBase), transferDelta);
|
|
assert(transferDelta.sourceMapDelta === materializedDelta.sourceMapDelta
|
|
&& transferDelta.metaDelta === materializedDelta.metaDelta
|
|
&& transferDelta.fields !== materializedDelta.fields
|
|
&& transferDelta.fields.field.rows[0].values.buffer !== materializedDelta.fields.field.rows[0].values.buffer
|
|
&& transferDelta.generatedMask.rows[0].values.buffer !== materializedDelta.generatedMask.rows[0].values.buffer
|
|
&& hashCommittedWorld(transferApplied) === hashCommittedWorld(deltaTarget),
|
|
"main transfer delta copies detachable raster rows only and leaves metadata for one postMessage clone");
|
|
|
|
const transportDebugWorld = {
|
|
width: 2, height: 2, originX: 0, originY: 0, renderRevision: 1,
|
|
fields: { sea: new Uint8Array(4), slope: new Float32Array(4), plain: new Float32Array(4) },
|
|
generatedRects: [],
|
|
sourceMap: {
|
|
transportDebug: {
|
|
layers: {
|
|
expresswayPotential: new Float32Array([0.5]),
|
|
components: [{ mode: "rail", cells: [[0, 0]] }],
|
|
},
|
|
},
|
|
},
|
|
};
|
|
const transportDebugViewport = getViewportMap(transportDebugWorld, { x: 0, y: 0 }, 2, 2);
|
|
assert(!ArrayBuffer.isView(transportDebugViewport.transportDebug.layers.expresswayPotential)
|
|
&& transportDebugViewport.transportDebug.layers.components.length === 1,
|
|
"viewport drops unused transport potential rasters while preserving vector diagnostics");
|
|
|
|
const edgeViewport = getViewportMap({
|
|
width: 3,
|
|
height: 2,
|
|
originX: 0,
|
|
originY: 0,
|
|
renderRevision: 1,
|
|
fields: { sea: new Uint8Array([1, 2, 3, 4, 5, 6]) },
|
|
sourceMap: {},
|
|
}, { x: -1, y: -1 }, 4, 4);
|
|
assert(Array.from(edgeViewport.sea).join(",") === "1,1,1,1,1,1,2,3,1,4,5,6,1,1,1,1",
|
|
"viewport row copies preserve exact clipping and fallback cells at negative camera edges");
|
|
|
|
const arrayDeltaBase = {
|
|
width: 1, height: 1,
|
|
fields: { marker: new Uint8Array([1]) }, generatedMask: new Uint8Array(1),
|
|
sourceMap: {
|
|
roads: [{ id: "keep-a" }, { id: "replace" }, { id: "keep-b" }],
|
|
annotated: Object.assign([{ id: "old" }], { patchGenerated: true }),
|
|
},
|
|
};
|
|
const arrayDeltaTarget = structuredClone(arrayDeltaBase);
|
|
arrayDeltaTarget.sourceMap.roads.splice(1, 1, { id: "new-1" }, { id: "new-2" });
|
|
arrayDeltaTarget.sourceMap.annotated = Object.assign([{ id: "new" }], { patchGenerated: true });
|
|
const exactArrayDelta = buildCommittedMirrorDelta(arrayDeltaBase, arrayDeltaTarget);
|
|
const exactArrayApplied = applyCommittedMirrorDelta(structuredClone(arrayDeltaBase), exactArrayDelta);
|
|
assert(exactArrayDelta.sourceMapDelta?.arraySplices?.roads?.start === 1
|
|
&& exactArrayDelta.sourceMapDelta?.arraySplices?.roads?.deleteCount === 1
|
|
&& exactArrayDelta.sourceMapDelta?.arraySplices?.roads?.items?.length === 2
|
|
&& Array.isArray(exactArrayDelta.sourceMapDelta?.set?.annotated)
|
|
&& hashCommittedWorld(exactArrayApplied) === hashCommittedWorld(arrayDeltaTarget),
|
|
"metadata delta uses exact middle splices for dense layers and full replacement for annotated arrays");
|
|
const oneShotArrayDelta = buildCommittedMirrorDelta(arrayDeltaBase, arrayDeltaTarget);
|
|
const oneShotInsertedRoad = oneShotArrayDelta.sourceMapDelta.arraySplices.roads.items[0];
|
|
const oneShotArrayApplied = applyCommittedMirrorDelta(structuredClone(arrayDeltaBase), oneShotArrayDelta, { consumeMetadata: true });
|
|
assert(oneShotArrayApplied.sourceMap.roads[1] === oneShotInsertedRoad
|
|
&& hashCommittedWorld(oneShotArrayApplied) === hashCommittedWorld(arrayDeltaTarget),
|
|
"one-shot Worker/main delta application adopts its isolated metadata graph without a second full clone");
|
|
|
|
const transactionBase = {
|
|
seed: 1, width: 8, height: 6, originX: 0, originY: 0, sourceWidth: 8, sourceHeight: 6, seaLevel: 0.3,
|
|
fields: {
|
|
sea: new Uint8Array(48), elevation: new Float32Array(48), municipalityId: new Int32Array(48),
|
|
flowTo: Int32Array.from({ length: 48 }, (_, index) => index - 1),
|
|
},
|
|
generatedMask: new Uint8Array(48), sourceMap: {
|
|
villages: [{ x: 1, y: 1 }],
|
|
adminDebug: { compartmentBorders: [[[0, 0], [1, 1]]] },
|
|
terrainTemplate: { immutableReference: { label: "production terrain" } },
|
|
stable: [1, 2],
|
|
},
|
|
generatedRects: [{
|
|
x0: 0, y0: 0, x1: 8, y1: 6,
|
|
generatedFootprint: { x0: 0, y0: 0, x1: 8, y1: 6, rowRuns: [[0, 8], [0, 8]] },
|
|
}],
|
|
lastPatchResult: { ok: true, seamDiagnostics: { hardPass: true, issuePoints: [] } },
|
|
patchGenerationSerial: 0,
|
|
};
|
|
transactionBase.fields.municipalityId.fill(-1);
|
|
const committedGeneratedRectsRef = transactionBase.generatedRects;
|
|
const committedLastPatchResultRef = transactionBase.lastPatchResult;
|
|
const transactionOriginal = structuredClone(transactionBase);
|
|
const transaction = capturePatchTransactionSnapshot(transactionBase, { lightweight: false });
|
|
assert(transaction.sourceMap.terrainTemplate === transactionBase.sourceMap.terrainTemplate
|
|
&& transaction.sourceMap.stable === transactionBase.sourceMap.stable
|
|
&& transaction.sourceMap.villages !== transactionBase.sourceMap.villages
|
|
&& transaction.sourceMap.villages[0] !== transactionBase.sourceMap.villages[0]
|
|
&& transaction.sourceMap.adminDebug !== transactionBase.sourceMap.adminDebug
|
|
&& transaction.generatedRects === committedGeneratedRectsRef
|
|
&& transaction.lastPatchResult === committedLastPatchResultRef,
|
|
"transaction source snapshots share read-only roots and own every patch-mutable root");
|
|
|
|
const isolatedSourceWorld = structuredClone(transactionOriginal);
|
|
const isolatedCommittedSourceRef = isolatedSourceWorld.sourceMap;
|
|
const isolatedCommittedHash = hashCommittedWorld(isolatedSourceWorld);
|
|
const isolatedSourceTransaction = capturePatchTransactionSnapshot(isolatedSourceWorld, {
|
|
lightweight: false,
|
|
isolateSourceMap: true,
|
|
});
|
|
const isolatedCandidatePoint = { x: 6, y: 4, name: "candidate-only" };
|
|
isolatedSourceWorld.sourceMap.villages.push(isolatedCandidatePoint);
|
|
const isolatedSourceDelta = buildCommittedMirrorDeltaFromTransaction(isolatedSourceTransaction, isolatedSourceWorld);
|
|
restorePatchTransactionSnapshot(isolatedSourceWorld, isolatedSourceTransaction);
|
|
assert(isolatedSourceTransaction.sourceMap === isolatedCommittedSourceRef
|
|
&& isolatedSourceWorld.sourceMap === isolatedCommittedSourceRef
|
|
&& isolatedSourceTransaction.sourceMapIsolated === true
|
|
&& isolatedSourceDelta.sourceMapDelta.arraySplices.villages.items[0] === isolatedCandidatePoint
|
|
&& hashCommittedWorld(isolatedSourceWorld) === isolatedCommittedHash,
|
|
"Worker transactions mutate an isolated sourceMap and rollback by restoring the untouched committed reference");
|
|
preparePatchTransactionFields(transaction, transactionBase, { x0: 2, y0: 1, x1: 6, y1: 5 });
|
|
transactionBase.fields.sea[19] = 1;
|
|
transactionBase.fields.elevation[28] = 0.75;
|
|
transactionBase.fields.municipalityId[10] = 42;
|
|
transactionBase.generatedMask[19] = 1;
|
|
const acceptedVillageRef = { x: 3, y: 2 };
|
|
transactionBase.sourceMap.villages.push(acceptedVillageRef);
|
|
transactionBase.sourceMap.adminDebug.compartmentBorders.push([[2, 2], [3, 3]]);
|
|
const sharedSeamDiagnostic = { hardPass: true, issuePoints: [{ x: 3, y: 2 }] };
|
|
transactionBase.sourceMap.patchSeamDiagnostics = sharedSeamDiagnostic;
|
|
transactionBase.generatedRects = [...transactionBase.generatedRects, { x0: 2, y0: 1, x1: 6, y1: 5 }];
|
|
transactionBase.lastPatchResult = { ok: true, seamDiagnostics: sharedSeamDiagnostic };
|
|
transactionBase.patchGenerationSerial = 1;
|
|
const transactionTarget = structuredClone(transactionBase);
|
|
const transactionDelta = buildCommittedMirrorDeltaFromTransaction(transaction, transactionBase);
|
|
restorePatchTransactionSnapshot(transactionBase, transaction);
|
|
const transactionApplied = applyCommittedMirrorDelta(structuredClone(transactionOriginal), transactionDelta);
|
|
assert(JSON.stringify(transactionBase) === JSON.stringify(transactionOriginal), "transactional candidate restores the committed mirror exactly");
|
|
assert(transactionBase.generatedRects === committedGeneratedRectsRef
|
|
&& transactionBase.lastPatchResult === committedLastPatchResultRef,
|
|
"transaction rollback restores immutable history and prior diagnostics by reference without cloning them");
|
|
|
|
const regenerationMaskWorld = structuredClone(transactionOriginal);
|
|
const regenerationMaskRef = regenerationMaskWorld.generatedMask;
|
|
const regenerationMaskTransaction = capturePatchTransactionSnapshot(regenerationMaskWorld, {
|
|
lightweight: false,
|
|
copyGeneratedMask: false,
|
|
});
|
|
regenerationMaskWorld.generatedMask = new Uint8Array(regenerationMaskWorld.generatedMask.length).fill(1);
|
|
const regenerationMaskDelta = buildCommittedMirrorDeltaFromTransaction(regenerationMaskTransaction, regenerationMaskWorld);
|
|
restorePatchTransactionSnapshot(regenerationMaskWorld, regenerationMaskTransaction);
|
|
assert(regenerationMaskTransaction.generatedMask === null
|
|
&& regenerationMaskTransaction.generatedMaskRef === regenerationMaskRef
|
|
&& regenerationMaskDelta.generatedMask?.rows?.length > 0
|
|
&& regenerationMaskWorld.generatedMask === regenerationMaskRef,
|
|
"Regeneration transactions retain the read-only generated mask by reference and still detect array replacement");
|
|
assert(JSON.stringify(transactionApplied) === JSON.stringify(transactionTarget), "transaction snapshot delta exactly materializes the accepted preview");
|
|
assert(transactionDelta.sourceMapDelta.arraySplices.villages.items[0] === acceptedVillageRef,
|
|
"transaction delta adopts completed candidate metadata directly instead of cloning it before rollback");
|
|
assert(transactionDelta.previewDelta.changedCells === 3
|
|
&& transactionDelta.previewDelta.terrainChangedCells === 2
|
|
&& transactionDelta.previewDelta.adminChangedCells === 1
|
|
&& transactionDelta.previewDelta.featureLayersChanged === 1,
|
|
"transaction delta reuses its field comparison to produce exact preview statistics");
|
|
assert(transactionDelta.sourceMapDelta.set.patchSeamDiagnostics
|
|
=== transactionDelta.metaDelta.set.lastPatchResult.seamDiagnostics
|
|
&& transactionApplied.sourceMap.patchSeamDiagnostics
|
|
=== transactionApplied.lastPatchResult.seamDiagnostics,
|
|
"delta build and apply preserve shared diagnostic objects instead of cloning them per metadata key");
|
|
|
|
const transactionalCalls = [];
|
|
const transactionalSearchBase = structuredClone(transactionOriginal);
|
|
const transactionalSearch = runPatchCandidateSearch({
|
|
id: 3,
|
|
world: transactionalSearchBase,
|
|
rect: { x0: 2, y0: 1, x1: 6, y1: 5 },
|
|
options: {},
|
|
search: { candidatePlan: [{ variant: 8, seed: 108 }, { variant: 9, seed: 109 }] },
|
|
}, {
|
|
transactional: true,
|
|
generateCandidate: (world, rect, options) => {
|
|
transactionalCalls.push([world.fields.sea[19], world.fields.municipalityId[10], world.sourceMap.villages.length]);
|
|
preparePatchTransactionFields(options._externalTransactionSnapshot, world, rect);
|
|
world.fields.sea[19] = options.variant;
|
|
world.fields.municipalityId[10] = options.variant;
|
|
world.sourceMap.villages.push({ x: options.variant, y: 2 });
|
|
world.patchGenerationSerial++;
|
|
return options.variant === 8
|
|
? { ok: false, code: "patch-quality-gate-failed", reason: "forced reject" }
|
|
: { ok: true, seamDiagnostics: { hardPass: true }, rects: { writeRect: rect } };
|
|
},
|
|
});
|
|
assert(transactionalSearch.result?.ok && !transactionalSearch.world && transactionalSearch.transactionDelta,
|
|
"production candidate search returns a bounded delta instead of a second full world");
|
|
assert(transactionalSearch.result.previewDelta?.changedCells === 2
|
|
&& transactionalSearch.result.previewDelta?.featureLayersChanged === 1,
|
|
"transactional search returns precomputed preview statistics without a main-thread field rescan");
|
|
assert(transactionalCalls.every(([sea, municipality, villages]) => sea === 0 && municipality === -1 && villages === 1)
|
|
&& JSON.stringify(transactionalSearchBase) === JSON.stringify(transactionOriginal),
|
|
"rejected and accepted transactional candidates both start from and restore the same committed mirror");
|
|
|
|
const transactionalBestBase = structuredClone(transactionOriginal);
|
|
const transactionalBestScores = new Map([[31, 0.44], [32, 0.91], [33, 0.68]]);
|
|
const transactionalBestSearch = runPatchCandidateSearch({
|
|
id: 303,
|
|
world: transactionalBestBase,
|
|
rect: { x0: 2, y0: 1, x1: 6, y1: 5 },
|
|
options: { acceptBestAvailableQuality: true },
|
|
search: {
|
|
selectBestCandidate: true,
|
|
resolvedPatchMode: "regeneration",
|
|
candidatePlan: [31, 32, 33].map((variant, index) => ({ candidateOrdinal: index + 1, candidateId: `transactional-best-${variant}`, variant, seed: 300 + variant })),
|
|
},
|
|
}, {
|
|
transactional: true,
|
|
generateCandidate: (world, rect, options) => {
|
|
preparePatchTransactionFields(options._externalTransactionSnapshot, world, rect);
|
|
world.fields.sea[19] = options.variant;
|
|
world.fields.municipalityId[10] = options.variant;
|
|
world.sourceMap.villages.push({ x: options.variant, y: 2 });
|
|
world.patchGenerationSerial++;
|
|
return {
|
|
ok: true,
|
|
rects: { writeRect: rect },
|
|
candidateQuality: { hardPass: false, score: transactionalBestScores.get(options.variant) },
|
|
seamDiagnostics: { hardPass: false, gateReasons: ["diagnostic-only"] },
|
|
};
|
|
},
|
|
});
|
|
const transactionalBestApplied = applyCommittedMirrorDelta(structuredClone(transactionOriginal), transactionalBestSearch.transactionDelta);
|
|
assert(transactionalBestSearch.result?.actualVariant === 32
|
|
&& transactionalBestSearch.result?.candidateOrdinal === 2
|
|
&& JSON.stringify(transactionalBestBase) === JSON.stringify(transactionOriginal)
|
|
&& transactionalBestApplied.fields.sea[19] === 32
|
|
&& transactionalBestApplied.fields.municipalityId[10] === 32
|
|
&& transactionalBestApplied.sourceMap.villages.at(-1)?.x === 32,
|
|
"transactional best-of-three keeps only the highest-quality candidate delta and restores the committed mirror after every evaluation");
|
|
|
|
const draftSelectionBase = structuredClone(transactionOriginal);
|
|
const draftSelectionScores = new Map([[41, 0.41], [42, 0.94], [43, 0.63]]);
|
|
const draftSelectionDraftCalls = [];
|
|
const draftSelectionFullCalls = [];
|
|
let draftSelectionDeltaBuilds = 0;
|
|
let draftSelectionHashBuilds = 0;
|
|
const draftSelectionProgress = [];
|
|
const draftSelectionSearch = await runPatchCandidateSearchAsync({
|
|
id: 304,
|
|
world: draftSelectionBase,
|
|
rect: { x0: 2, y0: 1, x1: 6, y1: 5 },
|
|
options: { acceptBestAvailableQuality: true },
|
|
search: {
|
|
searchId: "unit-draft-ranked-production",
|
|
selectBestCandidate: true,
|
|
draftSelection: true,
|
|
resolvedPatchMode: "regeneration",
|
|
candidatePlan: [41, 42, 43].map((variant, index) => ({
|
|
candidateOrdinal: index + 1, candidateId: `draft-ranked-${variant}`, variant, seed: 400 + variant,
|
|
})),
|
|
},
|
|
}, {
|
|
transactional: true,
|
|
onProgress: (message) => draftSelectionProgress.push(message.progress),
|
|
prepareOperationContext: () => ({ ok: true, signature: "unit-shared-context" }),
|
|
evaluateDraftCandidate: async (world, rect, options) => {
|
|
draftSelectionDraftCalls.push(options.variant);
|
|
return {
|
|
ok: true,
|
|
score: draftSelectionScores.get(options.variant),
|
|
qualityUpperBound: draftSelectionScores.get(options.variant),
|
|
candidateQuality: { score: draftSelectionScores.get(options.variant), qualityUpperBound: draftSelectionScores.get(options.variant), terrain: { score: 0.8 }, human: { score: 0.7 } },
|
|
reusableForFull: true,
|
|
precomputedDraft: { terrain: { unitTerrainVariant: options.variant }, baseSeed: (400 + options.variant) >>> 0, effectiveSeed: (400 + options.variant) >>> 0, generationContext: { variant: options.variant }, generationTimings: [{ key: "terrain", ms: 1 }] },
|
|
};
|
|
},
|
|
generateCandidate: async (world, rect, options) => {
|
|
draftSelectionFullCalls.push({ variant: options.variant, reusedFullDraft: options._precomputedDraftCandidate != null, reusedTerrain: options._precomputedTerrainDraftCandidate?.generationContext?.variant ?? null });
|
|
preparePatchTransactionFields(options._externalTransactionSnapshot, world, rect);
|
|
world.fields.sea[19] = options.variant;
|
|
world.fields.municipalityId[10] = options.variant;
|
|
world.sourceMap.villages.push({ x: options.variant, y: 3 });
|
|
world.patchGenerationSerial++;
|
|
return {
|
|
ok: true,
|
|
rects: { writeRect: rect },
|
|
candidateQuality: { hardPass: true, score: 0.9 },
|
|
seamDiagnostics: { hardPass: true },
|
|
};
|
|
},
|
|
buildCommittedDeltaFromTransaction: (transaction, world) => {
|
|
draftSelectionDeltaBuilds++;
|
|
return buildCommittedMirrorDeltaFromTransaction(transaction, world);
|
|
},
|
|
hashCommittedWorld: (world) => {
|
|
draftSelectionHashBuilds++;
|
|
return hashCommittedWorld(world);
|
|
},
|
|
});
|
|
const draftSelectionApplied = applyCommittedMirrorDelta(structuredClone(transactionOriginal), draftSelectionSearch.transactionDelta);
|
|
assert(draftSelectionSearch.result?.ok
|
|
&& draftSelectionSearch.result.actualVariant === 42
|
|
&& draftSelectionSearch.result.draftSelection?.policy === "admissible-terrain-scout-branch-and-bound-two-lane-v2"
|
|
&& draftSelectionSearch.result.draftSelection?.fullCandidateCount === 1
|
|
&& draftSelectionSearch.result.draftSelection?.reusedWinningDraft === false
|
|
&& draftSelectionSearch.result.draftSelection?.reusedTerrainDraft === true
|
|
&& draftSelectionSearch.result.draftSelection?.fullProductionFromTerrainOnly === true
|
|
&& draftSelectionDraftCalls.join(",") === "41,42,43"
|
|
&& draftSelectionFullCalls.length === 1
|
|
&& draftSelectionFullCalls[0].variant === 42
|
|
&& draftSelectionFullCalls[0].reusedFullDraft === false
|
|
&& draftSelectionFullCalls[0].reusedTerrain === 42,
|
|
"terrain-scout production evaluates three cheap terrain candidates, fully finalizes only the viable winner, and never reuses simplified human/transport draft stages");
|
|
assert(draftSelectionDeltaBuilds === 1
|
|
&& draftSelectionHashBuilds === 1
|
|
&& draftSelectionApplied.fields.sea[19] === 42
|
|
&& draftSelectionApplied.fields.municipalityId[10] === 42
|
|
&& JSON.stringify(draftSelectionBase) === JSON.stringify(transactionOriginal),
|
|
"draft-ranked production builds the committed delta and whole-world hash exactly once for the accepted finalist and restores the committed mirror");
|
|
assert(draftSelectionProgress.filter((event) => event.boundedWork).every((event) => event.completed <= event.total)
|
|
&& draftSelectionProgress.filter((event) => event.workUnitId?.startsWith("finalist-") && event.key === "finalist-generation").every((event) => event.total === 1),
|
|
"draft-ranked production keeps finalist progress bounded per full candidate without leaving an incomplete multi-finalist work unit");
|
|
|
|
const nearTieBase = structuredClone(transactionOriginal);
|
|
const nearTieDraftScores = new Map([[51, 0.900], [52, 0.885], [53, 0.61]]);
|
|
const nearTieFullScores = new Map([[51, 0.78], [52, 0.93], [53, 0.64]]);
|
|
const nearTieFullCalls = [];
|
|
let nearTieDeltaBuilds = 0;
|
|
let nearTieHashBuilds = 0;
|
|
const nearTieSearch = await runPatchCandidateSearchAsync({
|
|
id: 305,
|
|
world: nearTieBase,
|
|
rect: { x0: 2, y0: 1, x1: 6, y1: 5 },
|
|
options: { acceptBestAvailableQuality: true },
|
|
search: {
|
|
searchId: "unit-draft-near-tie",
|
|
selectBestCandidate: true,
|
|
draftSelection: true,
|
|
resolvedPatchMode: "regeneration",
|
|
candidatePlan: [51, 52, 53].map((variant, index) => ({
|
|
candidateOrdinal: index + 1, candidateId: `draft-near-${variant}`, variant, seed: 500 + variant,
|
|
})),
|
|
},
|
|
}, {
|
|
transactional: true,
|
|
prepareOperationContext: () => ({ ok: true, signature: "unit-near-tie-context" }),
|
|
evaluateDraftCandidate: async (world, rect, options) => {
|
|
const upper = new Map([[51, 0.95], [52, 0.96], [53, 0.70]]).get(options.variant);
|
|
return {
|
|
ok: true,
|
|
score: nearTieDraftScores.get(options.variant),
|
|
qualityUpperBound: upper,
|
|
candidateQuality: { score: nearTieDraftScores.get(options.variant), qualityUpperBound: upper, hardPass: true, terrain: { score: 0.8 }, human: { score: 0.7 } },
|
|
reusableForFull: true,
|
|
precomputedDraft: { terrain: { unitTerrainVariant: options.variant }, baseSeed: (500 + options.variant) >>> 0, effectiveSeed: (500 + options.variant) >>> 0, generationContext: { variant: options.variant }, generationTimings: [{ key: "terrain", ms: 1 }] },
|
|
};
|
|
},
|
|
generateCandidate: async (world, rect, options) => {
|
|
nearTieFullCalls.push({ variant: options.variant, reusedFullDraft: options._precomputedDraftCandidate != null, reusedTerrain: options._precomputedTerrainDraftCandidate?.generationContext?.variant ?? null });
|
|
preparePatchTransactionFields(options._externalTransactionSnapshot, world, rect);
|
|
world.fields.sea[19] = options.variant;
|
|
world.fields.municipalityId[10] = options.variant;
|
|
world.sourceMap.villages.push({ x: options.variant, y: 7 });
|
|
world.patchGenerationSerial++;
|
|
return {
|
|
ok: true,
|
|
rects: { writeRect: rect },
|
|
candidateQuality: { hardPass: true, score: nearTieFullScores.get(options.variant) },
|
|
seamDiagnostics: { hardPass: true, gateReasons: [] },
|
|
};
|
|
},
|
|
buildCommittedDeltaFromTransaction: (transaction, world) => {
|
|
nearTieDeltaBuilds++;
|
|
return buildCommittedMirrorDeltaFromTransaction(transaction, world);
|
|
},
|
|
hashCommittedWorld: (world) => {
|
|
nearTieHashBuilds++;
|
|
return hashCommittedWorld(world);
|
|
},
|
|
});
|
|
const nearTieApplied = applyCommittedMirrorDelta(structuredClone(transactionOriginal), nearTieSearch.transactionDelta);
|
|
assert(nearTieSearch.result?.ok
|
|
&& nearTieSearch.result.actualVariant === 52
|
|
&& nearTieSearch.result.draftSelection?.policy === "admissible-terrain-scout-branch-and-bound-two-lane-v2"
|
|
&& nearTieSearch.result.draftSelection?.selectionReason === "admissible-bound-winner-live"
|
|
&& nearTieSearch.result.draftSelection?.fullCandidateCount === 2
|
|
&& nearTieSearch.result.draftSelection?.fullGenerationPassCount === 2
|
|
&& nearTieSearch.result.draftSelection?.branchBoundPrunedCandidateOrdinals.includes(3)
|
|
&& nearTieFullCalls.map((row) => row.variant).join(",") === "51,52",
|
|
"admissible Branch-and-Bound fully evaluates only candidates that can still beat the current best and removes the fixed near-tie heuristic");
|
|
assert(nearTieDeltaBuilds === 1
|
|
&& nearTieHashBuilds === 1
|
|
&& nearTieApplied.fields.sea[19] === 52
|
|
&& nearTieApplied.fields.municipalityId[10] === 52
|
|
&& JSON.stringify(nearTieBase) === JSON.stringify(transactionOriginal),
|
|
"near-tie comparison still constructs delta/hash only once for the final selected candidate and restores the committed mirror");
|
|
|
|
const draftFallbackBase = structuredClone(transactionOriginal);
|
|
const draftFallbackCalls = [];
|
|
let draftFallbackDeltaBuilds = 0;
|
|
let draftFallbackHashBuilds = 0;
|
|
const draftFallbackSearch = await runPatchCandidateSearchAsync({
|
|
id: 306,
|
|
world: draftFallbackBase,
|
|
rect: { x0: 2, y0: 1, x1: 6, y1: 5 },
|
|
options: { acceptBestAvailableQuality: true },
|
|
search: {
|
|
searchId: "unit-draft-content-fallback",
|
|
selectBestCandidate: true,
|
|
draftSelection: true,
|
|
resolvedPatchMode: "regeneration",
|
|
candidatePlan: [71, 72, 73].map((variant, index) => ({
|
|
candidateOrdinal: index + 1, candidateId: `draft-fallback-${variant}`, variant, seed: 700 + variant,
|
|
})),
|
|
},
|
|
}, {
|
|
transactional: true,
|
|
prepareOperationContext: () => ({ ok: true, signature: "unit-fallback-context" }),
|
|
evaluateDraftCandidate: async (world, rect, options) => ({
|
|
ok: true,
|
|
score: options.variant === 71 ? 0.91 : options.variant === 72 ? 0.72 : 0.51,
|
|
qualityUpperBound: options.variant === 71 ? 0.96 : options.variant === 72 ? 0.90 : 0.60,
|
|
candidateQuality: { score: options.variant === 71 ? 0.91 : options.variant === 72 ? 0.72 : 0.51, qualityUpperBound: options.variant === 71 ? 0.96 : options.variant === 72 ? 0.90 : 0.60, hardPass: true },
|
|
reusableForFull: true,
|
|
precomputedDraft: { terrain: { unitTerrainVariant: options.variant }, baseSeed: (700 + options.variant) >>> 0, effectiveSeed: (700 + options.variant) >>> 0, generationContext: { variant: options.variant }, generationTimings: [{ key: "terrain", ms: 1 }] },
|
|
}),
|
|
generateCandidate: async (world, rect, options) => {
|
|
draftFallbackCalls.push({ variant: options.variant, reusedFullDraft: options._precomputedDraftCandidate != null, reusedTerrain: options._precomputedTerrainDraftCandidate?.generationContext?.variant ?? null });
|
|
preparePatchTransactionFields(options._externalTransactionSnapshot, world, rect);
|
|
if (options.variant === 71) return { ok: false, code: "patch-quality-gate-failed", reason: "forced full-stage rejection" };
|
|
world.fields.sea[19] = options.variant;
|
|
world.fields.municipalityId[10] = options.variant;
|
|
world.patchGenerationSerial++;
|
|
return { ok: true, rects: { writeRect: rect }, candidateQuality: { hardPass: true, score: 0.82 }, seamDiagnostics: { hardPass: true } };
|
|
},
|
|
buildCommittedDeltaFromTransaction: (transaction, world) => {
|
|
draftFallbackDeltaBuilds++;
|
|
return buildCommittedMirrorDeltaFromTransaction(transaction, world);
|
|
},
|
|
hashCommittedWorld: (world) => {
|
|
draftFallbackHashBuilds++;
|
|
return hashCommittedWorld(world);
|
|
},
|
|
});
|
|
const draftFallbackApplied = applyCommittedMirrorDelta(structuredClone(transactionOriginal), draftFallbackSearch.transactionDelta);
|
|
assert(draftFallbackSearch.result?.ok
|
|
&& draftFallbackSearch.result.actualVariant === 72
|
|
&& draftFallbackSearch.result.draftSelection?.selectionReason?.startsWith("admissible-bound")
|
|
&& draftFallbackSearch.result.draftSelection?.fullCandidateCount === 2
|
|
&& draftFallbackCalls.map((row) => row.variant).join(",") === "71,72"
|
|
&& draftFallbackCalls[0].reusedFullDraft === false
|
|
&& draftFallbackCalls[0].reusedTerrain === 71
|
|
&& draftFallbackCalls[1].reusedFullDraft === false
|
|
&& draftFallbackCalls[1].reusedTerrain === null,
|
|
"clear terrain-scout winner reuses only exact terrain on the fast path and regenerates a discarded runner-up after content rejection");
|
|
assert(draftFallbackDeltaBuilds === 1
|
|
&& draftFallbackHashBuilds === 1
|
|
&& draftFallbackApplied.fields.sea[19] === 72
|
|
&& JSON.stringify(draftFallbackBase) === JSON.stringify(transactionOriginal),
|
|
"content fallback preserves the one-delta/one-hash publication invariant");
|
|
|
|
const municipalityWorld = {
|
|
width: 8, height: 6,
|
|
fields: {
|
|
adminId: Int32Array.from({ length: 48 }, (_, index) => index % 5),
|
|
municipalityId: new Int32Array(48).fill(99),
|
|
sea: new Uint8Array(48),
|
|
},
|
|
};
|
|
const municipalityRects = {
|
|
patchMode: "regeneration",
|
|
coreRect: { x0: 2, y0: 1, x1: 6, y1: 5 },
|
|
writeRect: { x0: 2, y0: 1, x1: 6, y1: 5 },
|
|
repairRect: { x0: 0, y0: 0, x1: 8, y1: 6 },
|
|
writeMargin: 1,
|
|
};
|
|
const municipalityBefore = new Int32Array(municipalityWorld.fields.municipalityId);
|
|
const municipalityWrites = synchronizePatchMunicipalityField(municipalityWorld, municipalityRects, 17);
|
|
let municipalityOutsideChanged = 0;
|
|
for (let y = 0; y < municipalityWorld.height; y++) {
|
|
for (let x = 0; x < municipalityWorld.width; x++) {
|
|
if (x >= 2 && x < 6 && y >= 1 && y < 5) continue;
|
|
const index = y * municipalityWorld.width + x;
|
|
if (municipalityWorld.fields.municipalityId[index] !== municipalityBefore[index]) municipalityOutsideChanged++;
|
|
}
|
|
}
|
|
assert(municipalityWrites > 0 && municipalityOutsideChanged === 0,
|
|
"Regeneration municipality coherence writes only the owned patch alpha instead of rewriting the full world");
|
|
|
|
const adminWorldBase = {
|
|
seed: 3, width: 6, height: 4, originX: 0, originY: 0, sourceWidth: 6, sourceHeight: 4,
|
|
fields: {
|
|
adminId: Int32Array.from({ length: 24 }, (_, index) => index % 6 < 3 ? 0 : 1),
|
|
municipalityId: new Int32Array(24).fill(-1),
|
|
prefectureRegionId: Int32Array.from({ length: 24 }, (_, index) => index % 6 < 3 ? 10 : 11),
|
|
sea: new Uint8Array(24), populationDensity: new Float32Array(24).fill(0.5),
|
|
plain: new Float32Array(24).fill(0.6), agriculture: new Float32Array(24).fill(0.2),
|
|
slope: new Float32Array(24), ridgeField: new Float32Array(24), landuse: new Uint8Array(24),
|
|
},
|
|
generatedMask: new Uint8Array(24), generatedRects: [],
|
|
sourceMap: {
|
|
adminCenters: [], prefectureRegions: [], municipalityToPrefectureId: new Int32Array(2).fill(-1),
|
|
modernCities: [{ x: 1, y: 1, population: 1000 }, { x: 4, y: 1, population: 900 }],
|
|
},
|
|
patchGenerationSerial: 0,
|
|
};
|
|
const adminFullSecond = structuredClone(adminWorldBase);
|
|
const adminOptimizedSecond = structuredClone(adminWorldBase);
|
|
const adminFirstFull = synchronizePatchAdministrativeMetadata(adminFullSecond, adminFullSecond.sourceMap, 3, { writeMunicipalityField: true });
|
|
const adminFirstOptimized = synchronizePatchAdministrativeMetadata(adminOptimizedSecond, adminOptimizedSecond.sourceMap, 3, { writeMunicipalityField: true });
|
|
adminFullSecond.sourceMap.modernCities[0].isPrefecturalCapital = true;
|
|
adminOptimizedSecond.sourceMap.modernCities[0].isPrefecturalCapital = true;
|
|
synchronizePatchAdministrativeMetadata(adminFullSecond, adminFullSecond.sourceMap, 3, { writeMunicipalityField: false });
|
|
refreshPatchPrefectureMetadata(adminOptimizedSecond, adminOptimizedSecond.sourceMap, adminFirstOptimized.municipalCoherence, { afterCapitalNormalization: true });
|
|
assert(hashCommittedWorld(adminOptimizedSecond) === hashCommittedWorld(adminFullSecond)
|
|
&& adminFirstFull.municipalCoherence.debug.activeMunicipalities === adminFirstOptimized.municipalCoherence.debug.activeMunicipalities,
|
|
"post-capital prefecture refresh matches the former second full municipal scan exactly");
|
|
|
|
const capitalWorld = {
|
|
width: 6, height: 2, originX: 0, originY: 0,
|
|
fields: {
|
|
prefectureRegionId: Int32Array.from([0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2]),
|
|
sea: new Uint8Array(12),
|
|
populationDensity: Float32Array.from([1, 3, 1, 4, 1, 5, 2, 2, 3, 2, 4, 3]),
|
|
habitability: new Float32Array(12), slope: new Float32Array(12),
|
|
},
|
|
};
|
|
const capitalSource = { modernCities: [], markets: [], adminCenters: [] };
|
|
const capitalDebug = normalizePatchPrefectureCapitals(capitalWorld, capitalSource);
|
|
assert(capitalDebug.activePrefectures === 3 && capitalDebug.fallbackPrefectureCapitalCitiesAdded === 3
|
|
&& capitalSource.modernCities.map((city) => `${city.worldX},${city.worldY}`).join("|") === "1,0|3,0|5,0",
|
|
"capital fallback collects every prefecture's best cell in one world pass with stable tie order");
|
|
|
|
const tilePlanningWorld = { width: 1000, height: 700, originX: 0, originY: 0 };
|
|
// Expansion implementation tiles are selection-anchored so a maximum visible
|
|
// request does not generate thin world-grid edge candidates. Each tile still
|
|
// maps into one complete MAP_W x MAP_H production candidate; Regeneration keeps
|
|
// its historical full-candidate world-grid assignment.
|
|
const tilePlanningSelection = { x0: 205, y0: 20, x1: 205 + 470, y1: 20 + 333 };
|
|
const expansionTiles = buildLargeExpansionTiles(tilePlanningSelection, tilePlanningWorld);
|
|
const regenerationTiles = buildLargeExpansionTiles(tilePlanningSelection, tilePlanningWorld, {
|
|
_largeSelectionThresholdWidth: MAP_W,
|
|
_largeSelectionThresholdHeight: MAP_H,
|
|
_tileCoreWidth: MAP_W,
|
|
_tileCoreHeight: MAP_H,
|
|
});
|
|
assert(expansionTiles.length === 4
|
|
&& expansionTiles.every((tile) => tile._candidateWindowOverride?.width === MAP_W && tile._candidateWindowOverride?.height === MAP_H)
|
|
&& regenerationTiles.every((tile) => tile.x1 - tile.x0 <= MAP_W && tile.y1 - tile.y0 <= MAP_H),
|
|
"large Expansion packs a maximum visible selection into four full-production candidates while Regeneration retains full-size cores");
|
|
|
|
const standaloneSafeSelection = { x0: 200, y0: 200, x1: 320, y1: 290 };
|
|
const intermediateCoverageSelection = { x0: 200, y0: 200, x1: 360, y1: 310 };
|
|
const standaloneSafeTiles = buildLargeExpansionTiles(standaloneSafeSelection, tilePlanningWorld);
|
|
const intermediateCoverageTiles = buildLargeExpansionTiles(intermediateCoverageSelection, tilePlanningWorld);
|
|
assert(standaloneSafeTiles.length === 0
|
|
&& intermediateCoverageTiles.length === 1
|
|
&& intermediateCoverageTiles[0]._candidateWindowOverride?.width === MAP_W
|
|
&& intermediateCoverageTiles[0]._candidateWindowOverride?.height === MAP_H,
|
|
"Expansion tiling starts when the exact standalone write footprint no longer fits one production candidate, including the former 160x110 coverage hole");
|
|
|
|
let uncoveredStandaloneGeometry = null;
|
|
for (const [width, height] of [[48, 48], [96, 72], [120, 90], [128, 96], [132, 98], [160, 110], [220, 150], [242, 167]]) {
|
|
for (const [x0, y0] of [[0, 0], [200, 180], [1000 - width, 700 - height]]) {
|
|
const selection = { x0, y0, x1: x0 + width, y1: y0 + height };
|
|
if (buildLargeExpansionTiles(selection, tilePlanningWorld).length > 0) continue;
|
|
const rects = buildPatchRects(selection, tilePlanningWorld, { patchMode: "expansion", _geometryOnly: true });
|
|
const cx = (rects.coreRect.x0 + rects.coreRect.x1 - 1) / 2;
|
|
const cy = (rects.coreRect.y0 + rects.coreRect.y1 - 1) / 2;
|
|
const sourceCenterX = (MAP_W - 1) / 2;
|
|
const sourceCenterY = (MAP_H - 1) / 2;
|
|
const corners = [
|
|
[rects.writeRect.x0, rects.writeRect.y0],
|
|
[rects.writeRect.x1 - 1, rects.writeRect.y1 - 1],
|
|
];
|
|
const covered = corners.every(([x, y]) => {
|
|
const sx = Math.round(x - cx + sourceCenterX);
|
|
const sy = Math.round(y - cy + sourceCenterY);
|
|
return sx >= 0 && sx < MAP_W && sy >= 0 && sy < MAP_H;
|
|
});
|
|
if (!covered) uncoveredStandaloneGeometry = { width, height, x0, y0, writeRect: rects.writeRect };
|
|
}
|
|
}
|
|
assert(uncoveredStandaloneGeometry === null,
|
|
"every Expansion that remains on the standalone fast path has complete fixed-candidate coverage, including world-edge placements");
|
|
|
|
const rasterPartitionLasso = {
|
|
kind: "lasso",
|
|
polygon: [
|
|
{ x: 120, y: 40 },
|
|
{ x: 399, y: 60 },
|
|
{ x: 250, y: 140 },
|
|
{ x: 370, y: 239 },
|
|
{ x: 100, y: 210 },
|
|
],
|
|
};
|
|
const rasterPartitionTiles = buildLargeExpansionTiles(rasterPartitionLasso, tilePlanningWorld);
|
|
let partitionMissing = 0;
|
|
let partitionExtra = 0;
|
|
let partitionDuplicate = 0;
|
|
for (let y = 40; y < 240; y++) {
|
|
for (let x = 100; x < 400; x++) {
|
|
const selected = testPointInPolygon(x + 0.5, y + 0.5, rasterPartitionLasso.polygon);
|
|
let tileHits = 0;
|
|
for (const tile of rasterPartitionTiles) {
|
|
if (x < tile.x0 || x >= tile.x1 || y < tile.y0 || y >= tile.y1) continue;
|
|
if (testPointInPolygon(x + 0.5, y + 0.5, tile.polygon)) tileHits++;
|
|
}
|
|
if (selected && tileHits === 0) partitionMissing++;
|
|
if (!selected && tileHits > 0) partitionExtra++;
|
|
if (tileHits > 1) partitionDuplicate++;
|
|
}
|
|
}
|
|
assert(rasterPartitionTiles.length >= 2
|
|
&& partitionMissing === 0
|
|
&& partitionExtra === 0
|
|
&& partitionDuplicate === 0
|
|
&& rasterPartitionTiles.every((tile) => tile.partitionBounds && tile.areaCells > 0),
|
|
"large lasso tiles partition the original even-odd raster exactly without missing, extra, or duplicate seam cells");
|
|
|
|
const strictMetadataWorld = { width: 8, height: 6, originX: 0, originY: 0 };
|
|
const strictMetadataSource = {
|
|
modernCities: [{ x: 0, y: 0, name: "outside" }, { x: 3, y: 2, name: "inside" }],
|
|
adminCenters: [{ x: 0, y: 0, adminId: 1, name: "office" }],
|
|
prefectureRegions: [{ x: 0, y: 0, prefectureRegionId: 2, name: "region" }],
|
|
};
|
|
const strictMetadataBaseline = structuredClone(strictMetadataSource);
|
|
const strictMetadataSnapshot = captureStrictMetadataSnapshot(strictMetadataWorld, strictMetadataSource, municipalityRects, 17, strictMetadataBaseline);
|
|
assert(strictMetadataSnapshot.outsidePointLayers.get("modernCities")[0] === strictMetadataBaseline.modernCities[0]
|
|
&& strictMetadataSnapshot.byLayer.get("adminCenters")[0] === strictMetadataSnapshot.allByLayerId.get("adminCenters").get(1)
|
|
&& strictMetadataSnapshot.byLayer.get("prefectureRegions")[0] === strictMetadataSnapshot.allByLayerId.get("prefectureRegions").get(2),
|
|
"strict metadata snapshots reuse the immutable transaction before-image instead of cloning the same points into multiple stores");
|
|
|
|
const strictFieldWorld = structuredClone(transactionOriginal);
|
|
const strictFieldTransaction = capturePatchTransactionSnapshot(strictFieldWorld, { lightweight: false });
|
|
preparePatchTransactionFields(strictFieldTransaction, strictFieldWorld, municipalityRects.repairRect);
|
|
const strictFieldSnapshot = captureStrictSelectionFieldSnapshot(strictFieldWorld, municipalityRects, 17, {
|
|
deferGlobalSnapshot: true,
|
|
transactionSnapshot: strictFieldTransaction,
|
|
});
|
|
assert(strictFieldSnapshot.transactionSnapshot === strictFieldTransaction
|
|
&& strictFieldSnapshot.fieldNames.size > 0
|
|
&& strictFieldSnapshot.fields.size === 0
|
|
&& !strictFieldTransaction.fields.has("flowTo")
|
|
&& !strictFieldSnapshot.fieldNames.has("flowTo")
|
|
&& !("globalFields" in strictFieldTransaction)
|
|
&& strictFieldSnapshot.protectedIndexLookup === null,
|
|
"strict field restore reuses local transaction before-images without read-only or whole-world duplicates");
|
|
|
|
|
|
const rawFlagWorld = {
|
|
seed: 7, width: 900, height: 700, originX: 0, originY: 0,
|
|
fields: { sea: new Uint8Array(900 * 700), elevation: new Float32Array(900 * 700) },
|
|
sourceMap: {}, generatedMask: new Uint8Array(900 * 700),
|
|
};
|
|
// Half of this internal tile already exists in the committed world. Large
|
|
// Expansion human-density completion must therefore target only the genuinely
|
|
// new fraction rather than treating the entire raw production frame as new.
|
|
for (let y = 0; y < rawFlagWorld.height; y++) {
|
|
for (let x = 0; x < 225; x++) rawFlagWorld.generatedMask[y * rawFlagWorld.width + x] = 1;
|
|
}
|
|
const internalExpansionRaw = buildRawPatchCandidateRequest(rawFlagWorld, { x0: 150, y0: 120, x1: 300, y1: 226 }, {
|
|
patchMode: "expansion", _internalTile: true, seed: 701, variant: 0,
|
|
});
|
|
const ordinaryExpansionRaw = buildRawPatchCandidateRequest(rawFlagWorld, { x0: 150, y0: 120, x1: 300, y1: 226 }, {
|
|
patchMode: "expansion", seed: 701, variant: 0,
|
|
});
|
|
assert(internalExpansionRaw.ok && internalExpansionRaw.mapOptions.largeExpansionTile === true
|
|
&& ordinaryExpansionRaw.ok && ordinaryExpansionRaw.mapOptions.largeExpansionTile === false,
|
|
"canonical internal Expansion tiles activate the bounded large-tile transport policy without affecting ordinary candidates");
|
|
assert(internalExpansionRaw.mapOptions.patchHumanFocusPolygon?.length >= 3
|
|
&& Math.abs(internalExpansionRaw.mapOptions.patchHumanExpansionFraction - 0.5) < 1e-9
|
|
&& ordinaryExpansionRaw.mapOptions.patchHumanExpansionFraction == null,
|
|
"large Expansion raw candidates carry a selection focus and immutable ungenerated fraction without leaking it into ordinary candidates");
|
|
|
|
const savedWorker = globalThis.Worker;
|
|
const fakeStarts = [];
|
|
const fakeFinishes = [];
|
|
let fakeActive = 0;
|
|
let fakePeak = 0;
|
|
class FakeRawCandidateWorker {
|
|
constructor() {
|
|
this.onmessage = null;
|
|
this.onerror = null;
|
|
this.terminated = false;
|
|
}
|
|
postMessage(message) {
|
|
const index = Number(message.mapOptions?.testIndex || 0);
|
|
const delay = Number(message.mapOptions?.testDelay || 0);
|
|
fakeStarts.push({ index, at: performance.now() });
|
|
fakeActive++;
|
|
fakePeak = Math.max(fakePeak, fakeActive);
|
|
setTimeout(() => {
|
|
if (this.terminated) return;
|
|
fakeActive--;
|
|
fakeFinishes.push({ index, at: performance.now() });
|
|
this.onmessage?.({ data: {
|
|
type: "raw-patch-candidate-result",
|
|
id: message.id,
|
|
ok: true,
|
|
candidate: { index },
|
|
} });
|
|
}, delay);
|
|
}
|
|
terminate() {
|
|
this.terminated = true;
|
|
return Promise.resolve();
|
|
}
|
|
}
|
|
globalThis.Worker = FakeRawCandidateWorker;
|
|
try {
|
|
const requests = [70, 5, 5, 5, 5, 5].map((delay, index) => ({
|
|
seed: index + 1,
|
|
taskId: `scheduler-${index}`,
|
|
mapOptions: { testIndex: index, testDelay: delay },
|
|
}));
|
|
const sequence = scheduleRawCandidateSequence(requests, null, { parallelism: 2, windowSize: 3 });
|
|
await sequence.promises[1];
|
|
await new Promise((resolve) => setTimeout(resolve, 15));
|
|
assert(fakeStarts.some((entry) => entry.index === 2) && !fakeFinishes.some((entry) => entry.index === 0),
|
|
"continuous two-worker scheduler lets a free lane start tile 3 while tile 1 is a straggler");
|
|
assert(!fakeStarts.some((entry) => entry.index === 3),
|
|
"raw candidate prefetch is bounded to one lookahead beyond the two active workers before merge-head release");
|
|
const merged = [];
|
|
for (let index = 0; index < sequence.promises.length; index++) {
|
|
const candidate = await sequence.promises[index];
|
|
merged.push(candidate.index);
|
|
sequence.promises[index] = null;
|
|
sequence.release(index);
|
|
}
|
|
await sequence.done;
|
|
assert(merged.join(",") === "0,1,2,3,4,5" && fakePeak <= 2 && fakeStarts.length === 6,
|
|
"raw candidates still merge deterministically in ordinal order with at most two helper workers");
|
|
} finally {
|
|
await shutdownRawCandidateWorkers();
|
|
if (savedWorker === undefined) delete globalThis.Worker;
|
|
else globalThis.Worker = savedWorker;
|
|
}
|
|
|
|
const syntheticRawCandidate = {
|
|
baseSeed: 77,
|
|
width: MAP_W,
|
|
height: MAP_H,
|
|
sea: new Uint8Array([0, 1, 0, 1]),
|
|
municipalityToPrefectureId: new Int32Array([0, 1, 1]),
|
|
villages: [{ x: 2, y: 3 }],
|
|
nationalRoads: [[[0, 0], [1, 1]]],
|
|
generationContext: { width: MAP_W, height: MAP_H },
|
|
terrainTemplate: { terrainType: "test" },
|
|
adminDebug: { compartmentBorders: [] },
|
|
geography: { veryLargeGraph: new Array(500).fill({ id: 1 }) },
|
|
naturalCompartments: [{ id: 1 }],
|
|
unrelatedDebug: { shouldDrop: true },
|
|
};
|
|
const compactedRawCandidate = compactRawPatchCandidate(syntheticRawCandidate);
|
|
const compactedRawSummary = summarizeRawPatchCandidate(compactedRawCandidate);
|
|
assert(compactedRawCandidate.sea === syntheticRawCandidate.sea
|
|
&& compactedRawCandidate.municipalityToPrefectureId === syntheticRawCandidate.municipalityToPrefectureId
|
|
&& compactedRawCandidate.villages === syntheticRawCandidate.villages
|
|
&& compactedRawCandidate.nationalRoads === syntheticRawCandidate.nationalRoads
|
|
&& compactedRawCandidate.generationContext === syntheticRawCandidate.generationContext,
|
|
"raw-candidate compaction preserves dynamically discovered raster fields and merge-required vector metadata");
|
|
assert(!("geography" in compactedRawCandidate)
|
|
&& !("naturalCompartments" in compactedRawCandidate)
|
|
&& !("unrelatedDebug" in compactedRawCandidate)
|
|
&& compactedRawSummary.typedArrayCount === 2
|
|
&& compactedRawSummary.transferableBytes === syntheticRawCandidate.sea.byteLength + syntheticRawCandidate.municipalityToPrefectureId.byteLength,
|
|
"raw-candidate compaction drops full-map-only graphs without hiding transferable-byte accounting");
|
|
|
|
const terrainRehomeWorld = {
|
|
width: 24, height: 24, originX: 0, originY: 0,
|
|
fields: {
|
|
sea: new Uint8Array(24 * 24).fill(1),
|
|
slope: new Float32Array(24 * 24),
|
|
adminId: new Int32Array(24 * 24).fill(-1),
|
|
},
|
|
};
|
|
for (let y = 8; y <= 14; y++) for (let x = 8; x <= 14; x++) {
|
|
terrainRehomeWorld.fields.sea[y * 24 + x] = 0;
|
|
terrainRehomeWorld.fields.adminId[y * 24 + x] = 7;
|
|
}
|
|
const terrainRehomeSource = {
|
|
villages: [
|
|
{ x: 6, y: 10, adminId: 7, patchGenerated: true },
|
|
{ x: 2, y: 2, adminId: 3, patchGenerated: false },
|
|
],
|
|
};
|
|
const terrainRehomeRects = {
|
|
coreRect: { x0: 4, y0: 4, x1: 20, y1: 20 },
|
|
writeRect: { x0: 4, y0: 4, x1: 20, y1: 20 },
|
|
patchMode: "expansion",
|
|
expansionOverlap: 0,
|
|
};
|
|
const terrainRehomeDebug = reconcileGeneratedHumanPointsWithFinalTerrain(
|
|
terrainRehomeWorld, terrainRehomeSource, terrainRehomeRects, 123
|
|
);
|
|
assert(terrainRehomeDebug.relocated === 1 && terrainRehomeDebug.dropped === 0
|
|
&& terrainRehomeSource.villages.length === 2
|
|
&& terrainRehomeWorld.fields.sea[terrainRehomeSource.villages[0].y * 24 + terrainRehomeSource.villages[0].x] === 0
|
|
&& terrainRehomeSource.villages[1].x === 2 && terrainRehomeSource.villages[1].y === 2,
|
|
"final coastline reconciliation relocates only current generated settlements from water to owned land and preserves legacy points");
|
|
|
|
const tiledQualityBasis = buildTiledFinalQualityBasis([
|
|
{ candidateQuality: { terrain: { terrainType: "auto" }, human: {
|
|
minLabels: 30, minSettlements: 18, minAdminCenters: 2, transportRequired: true,
|
|
labelCount: 24, settlementCount: 15, counts: { adminCenters: 2 },
|
|
} } },
|
|
{ candidateQuality: { terrain: { terrainType: "auto" }, human: {
|
|
minLabels: 20, minSettlements: 12, minAdminCenters: 1, transportRequired: false,
|
|
labelCount: 17, settlementCount: 11, counts: { adminCenters: 1 },
|
|
} } },
|
|
], "auto");
|
|
assert(tiledQualityBasis.human.minLabels === 50
|
|
&& tiledQualityBasis.human.minSettlements === 30
|
|
&& tiledQualityBasis.human.preMergeLabelCount === 41
|
|
&& tiledQualityBasis.human.preMergeSettlementCount === 26
|
|
&& tiledQualityBasis.human.minAdminCenters === 3
|
|
&& tiledQualityBasis.human.preMergeAdminCenterCount === 3
|
|
&& tiledQualityBasis.human.transportRequired === true,
|
|
"whole-selection tiled quality basis retains both theoretical floors and actual pre-merge human-geography counts");
|
|
|
|
const sourcePruneInitial = {
|
|
seed: 1,
|
|
sea: new Uint8Array(MAP_W * MAP_H),
|
|
elevation: new Float32Array(MAP_W * MAP_H),
|
|
geography: { cells: [1, 2, 3] },
|
|
naturalCompartments: [{ id: 1 }],
|
|
geographicCompartmentProfiles: [{ id: 1 }],
|
|
watershedProfiles: [{ id: 1 }],
|
|
entitiesForNames: [{ id: 1 }],
|
|
geographyDebug: { heavy: true },
|
|
transportDebug: { keep: true },
|
|
generationTimings: [{ key: "terrain", ms: 1 }],
|
|
villages: [{ x: 1, y: 1 }],
|
|
};
|
|
const sourcePruneWorld = createWorldMap(sourcePruneInitial, { paddingX: 0, paddingY: 0 });
|
|
assert(!("geography" in sourcePruneWorld.sourceMap)
|
|
&& !("naturalCompartments" in sourcePruneWorld.sourceMap)
|
|
&& !("geographicCompartmentProfiles" in sourcePruneWorld.sourceMap)
|
|
&& !("watershedProfiles" in sourcePruneWorld.sourceMap)
|
|
&& !("entitiesForNames" in sourcePruneWorld.sourceMap)
|
|
&& !("geographyDebug" in sourcePruneWorld.sourceMap),
|
|
"committed sourceMap prunes generator-only full-map graphs after world materialization");
|
|
assert(sourcePruneWorld.sourceMap.transportDebug === sourcePruneInitial.transportDebug
|
|
&& sourcePruneWorld.sourceMap.generationTimings === sourcePruneInitial.generationTimings
|
|
&& sourcePruneWorld.sourceMap.villages === sourcePruneInitial.villages,
|
|
"committed sourceMap retains runtime diagnostics and vector layers that viewport/patch logic still consumes");
|
|
|
|
const memo = createExactNoiseMemo();
|
|
let mismatches = 0;
|
|
for (let index = 0; index < 2000; index++) {
|
|
const x = (index * 17 % 997) - 480.25;
|
|
const y = (index * 43 % 1231) - 610.75;
|
|
const seed = (114514 + index * 101) >>> 0;
|
|
const scale = 3.75 + (index % 53);
|
|
if (memo.valueNoise(x, y, seed, scale) !== valueNoise(x, y, seed, scale)) mismatches++;
|
|
if (memo.fbm(x, y, seed) !== fbm(x, y, seed)) mismatches++;
|
|
}
|
|
assert(mismatches === 0, "exact terrain noise memo preserves every sampled value and octave order");
|
|
|
|
console.log("All additional-generation unit tests passed.");
|