clone

an endless marble-race generator in the browser; the url is the seed, so every track can be shared

Island wedge law extended: side-flank rule — wedges only where flanked at their own level

Dami committed fcd127d
The first coherence pass still let wedges stand beside lower terraces or
the void, exposing their bare triangular side profile (staircases of
spikes on terraced rims, pyramid slivers on promontories). A slope wedge
now additionally requires BOTH side flanks within a course of its own
level; corner diagonals satisfy this by construction (their side dirs
are the closed backs). Adjacent-open cells without a free corner keep
the cube (their wedge always exposed a side toward the other opening).
commit
fcd127de7b1d89e7160e36fc0696d44650170f93
parent
28d443810e581761da9fb38b07aa116e5afafdde
author
Dami <dami.etoile@gmail.com>
1 file changed, +29 -19
Msrc/gen/endless/islands.ts48++++++++++++++++++------------
M src/gen/endless/islands.ts +29 -19
@@ -351,15 +351,36 @@ export function buildIsland(
351351 352352 // Waterfall column: waterfallTop at the crest, waterfall faces below.353353 const isFall = k === waterfallCell && open.length > 0;354- // Shoulder trim on plain edge tops (never on the waterfall). Support355- // law: a wedge leans against mass, so its high side must be CLOSED —356- // a cell open on two OPPOSITE sides (1-wide ridge) keeps the full357- // cube instead of a wedge with a floating high edge.354+ // Shoulder trim on plain edge tops (never on the waterfall). WFC355+ // wedge laws (USER RULE: triangles must never read jagged):356+ // 1. HIGH side closed — no wedge on opposite-open ridges (its high357+ // edge would float);358+ // 2. SIDE faces flanked at the wedge's own level (side neighbor top359+ // within a course, or higher) — a wedge beside a lower terrace or360+ // the void shows its bare triangular profile, and terraced rims361+ // become staircases of spikes.362+ // A corner diagonal satisfies law 2 by construction: its two side363+ // dirs are exactly the closed backs.358364 const adjacentOpen = open.length === 2 &&359365 open[0][0] !== open[1][0] && open[0][1] !== open[1][1];366+ const dirs = open.map(([dx, dz]) => dirOf(dx, dz));367+ const corner = adjacentOpen &&368+ dropAt(c, open[0][0] + open[1][0], open[0][1] + open[1][1]) >= 0.99;369+ const slopeDir = open.length === 0370+ ? -1371+ : open.length === 1372+ ? dirs[0]373+ : dropAt(c, open[1][0], open[1][1]) > dropAt(c, open[0][0], open[0][1])374+ ? dirs[1]375+ : dirs[0];376+ const flanked = slopeDir >= 0 &&377+ dropAt(c, DIRS[(slopeDir + 1) % 4][0], DIRS[(slopeDir + 1) % 4][1]) <378+ 0.99 &&379+ dropAt(c, DIRS[(slopeDir + 3) % 4][0], DIRS[(slopeDir + 3) % 4][1]) <380+ 0.99;360381 const trim = trimIsland && !isFall && !c.onRun && c.dist >= 1 &&361382 c.depth >= 1 &&362- (open.length === 1 || adjacentOpen);383+ (corner || (open.length === 1 && flanked));363384 364385 // One face per waterfall column — water can't zigzag around the365386 // corner course to course (the old per-course re-pick did).
@@ -389,20 +410,9 @@ export function buildIsland(
389410 role: "support",390411 });391412 } else if (course === 0 && trim) {392- // Slope toward the single open side; diagonal across a corner.393- // USER RULE: the wedge must respect the surrounding surface — the394- // diagonal cut needs the corner cell BETWEEN its two open sides395- // open too (else the cut face jams into that block's corner), and396- // with two open sides the slope descends toward the LOWER one.397- const dirs = open.map(([dx, dz]) => dirOf(dx, dz));398- const corner = adjacentOpen &&399- dropAt(c, open[0][0] + open[1][0], open[0][1] + open[1][1]) >= 0.99;400- const slopeDir = open.length === 1401- ? dirs[0]402- : dropAt(c, open[1][0], open[1][1]) >403- dropAt(c, open[0][0], open[0][1])404- ? dirs[1]405- : dirs[0];413+ // Slope toward the single open side; diagonal across a corner414+ // (the cut needs the cell BETWEEN its two open sides open too,415+ // else the cut face jams into that block's corner).406416 placements.push({407417 pieceId: `${NATURE}:${408418 corner ? "cliff_blockDiagonal" : "cliff_blockSlope"