import assert from 'node:assert/strict'; import { generateMap } from './mapGenerator.js'; import { createWorldMap } from './worldMap.js'; import { generatePatch } from './mapPatch.js'; import { MAP_W, MAP_H, worldIndexOf } from './mapUtils.js'; const baseSeeds = (process.env.BASE_SEEDS || '24681357,13579246').split(',').map(Number).filter(Number.isFinite); const requestedDirections = new Set((process.env.DIRECTIONS || 'right,left,down,up').split(',').map(s => s.trim())); const results = []; const quiet = process.env.QUIET === '1'; function probeAxis(world, direction, baseOriginX, baseOriginY) { const edgeX = baseOriginX + MAP_W - 1; const edgeY = baseOriginY + MAP_H - 1; if (direction === 'right') return { horizontal: false, fixed: edgeX, start: baseOriginY + Math.floor(MAP_H*.22), end: baseOriginY + Math.floor(MAP_H*.78), oldOffset: 0, newOffset: 1 }; if (direction === 'left') return { horizontal: false, fixed: baseOriginX, start: baseOriginY + Math.floor(MAP_H*.22), end: baseOriginY + Math.floor(MAP_H*.78), oldOffset: 0, newOffset: -1 }; if (direction === 'down') return { horizontal: true, fixed: edgeY, start: baseOriginX + Math.floor(MAP_W*.22), end: baseOriginX + Math.floor(MAP_W*.78), oldOffset: 0, newOffset: 1 }; return { horizontal: true, fixed: baseOriginY, start: baseOriginX + Math.floor(MAP_W*.22), end: baseOriginX + Math.floor(MAP_W*.78), oldOffset: 0, newOffset: -1 }; } function makeRect(direction, ox, oy) { const edgeX = ox + MAP_W - 1, edgeY = oy + MAP_H - 1; const x0 = ox + Math.floor(MAP_W*.22), x1 = ox + Math.floor(MAP_W*.78); const y0 = oy + Math.floor(MAP_H*.22), y1 = oy + Math.floor(MAP_H*.78); if (direction === 'right') return { x0: edgeX - 33, y0, x1: edgeX + 93, y1 }; if (direction === 'left') return { x0: ox - 93, y0, x1: ox + 33, y1 }; if (direction === 'down') return { x0, y0: edgeY - 33, x1, y1: edgeY + 93 }; return { x0, y0: oy - 93, x1, y1: oy + 33 }; } function measureFrontier(world, probe) { let pairs = 0, maxJump = 0, sum = 0; for (let t = probe.start; t < probe.end; t++) { let ax, ay, bx, by; if (!probe.horizontal) { ax = probe.fixed + probe.oldOffset; ay = t; bx = probe.fixed + probe.newOffset; by = t; } else { ax = t; ay = probe.fixed + probe.oldOffset; bx = t; by = probe.fixed + probe.newOffset; } const a = worldIndexOf(world,ax,ay), b = worldIndexOf(world,bx,by); if (a < 0 || b < 0 || world.fields.sea[a] || world.fields.sea[b]) continue; const jump = Math.abs(world.fields.elevation[a] - world.fields.elevation[b]); pairs++; sum += jump; maxJump = Math.max(maxJump,jump); } return { pairs, maxJump, meanJump: pairs ? sum/pairs : 0 }; } for (const baseSeed of baseSeeds) { const initial = generateMap(baseSeed, { terrainType:'auto', onProgress(){} }); for (const direction of ['right','left','down','up']) { if (!requestedDirections.has(direction)) continue; const world = createWorldMap(structuredClone(initial)); const ox = world.originX, oy = world.originY; const rect = makeRect(direction,ox,oy); const patchSeed = (0x13579bdf ^ baseSeed ^ ({right:0x11,left:0x22,down:0x33,up:0x44}[direction])) >>> 0; const result = generatePatch(world,rect,{patchMode:'expansion',terrainType:'auto',seed:patchSeed,variant:1,maxQualityRetries:0,qualityTerrainAttempts:1,acceptBestAvailableQuality:true}); assert.equal(result.ok,true,`${baseSeed}/${direction}: ${result.reason || result.code}`); const probe = measureFrontier(world,probeAxis(world,direction,ox,oy)); assert.ok(probe.pairs >= 12,`${baseSeed}/${direction}: insufficient land frontier pairs (${probe.pairs})`); assert.ok(probe.maxJump <= 0.075,`${baseSeed}/${direction}: frontier max jump ${probe.maxJump}`); assert.equal(result.seamDiagnostics?.hardPass,true,`${baseSeed}/${direction}: seam gate ${JSON.stringify(result.seamDiagnostics?.gateReasons || [])}`); assert.ok((result.seamDiagnostics?.maxEstablishedFrontierElevationJump || 0) <= 0.075,`${baseSeed}/${direction}: diagnostic frontier jump ${result.seamDiagnostics?.maxEstablishedFrontierElevationJump}`); const row={baseSeed,direction,patchSeed,pairs:probe.pairs,maxJump:+probe.maxJump.toFixed(4),meanJump:+probe.meanJump.toFixed(4),diagnosticMax:+(result.seamDiagnostics?.maxEstablishedFrontierElevationJump||0).toFixed(4),seamStatus:result.seamDiagnostics?.status,seamReasons:result.seamDiagnostics?.gateReasons||[],adjusted:result.humanGeography?.establishedFrontierElevationCellsAdjusted||0,gradientAdjusted:result.humanGeography?.establishedFrontierGradientCellsAdjusted||0}; results.push(row); if (!quiet) console.log(JSON.stringify(row)); } } console.log(JSON.stringify({ok:true,cases:results.length,maxObserved:Math.max(...results.map(r=>r.maxJump)),results},null,2));