Credibility pass: the reel's scars sanded, the veil finally hung

Three blind reviews over the first-person arc, every finding verified
against the source. History-narrating comments made timeless or cut;
the stacked BUDDY comment collapsed to one voice. Dead code out: the
orphaned FACE copy, the DIR_ANGLE duplicate, the dead loop-counter
poke, the impossible-state sentinel. The never-produced "warp" hit
kind resolved the right way — warp mouths now hang a translucent veil
of the painted warp texture, so art that never rendered finally does.
Types tightened (SlabStrike named once, ShareData rides CatchUpStep,
botTier loses its casts), the gallery reads MATERIALS instead of a
hand-copied list, the chronicle resets through one helper, a
superseded share mint rejects instead of stranding, and the conjured
safe gains the growth key its siblings had. Tests lose a triple
assignment, a tautology, and two self-swallowing regex alternatives.
The sprite spec — which still told the artist to paint for additive
compositing the renderer no longer uses — now describes the renderer
that exists.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-23 21:41:11 -04:00
co-authored by Claude Fable 5
parent 88994f18a2
commit 7a32370ccb
16 changed files with 111 additions and 105 deletions
+30 -23
View File
@@ -13,7 +13,7 @@ export interface Hit {
/** Distance along the ray (perpendicular-corrected by the caller). */
dist: number;
/** What the ray struck. */
kind: "wall" | "door" | "firewall" | "stone" | "rim" | "warp";
kind: "wall" | "door" | "firewall" | "stone" | "rim";
/** 0..1 across the struck face (texture coordinate). */
u: number;
/** Vertical faces get a different shade than horizontal ones. */
@@ -26,11 +26,13 @@ export interface Hit {
edge?: string;
/** The eye reached this through a warp: haze it other-worldly. */
warped?: boolean;
/** Which warp (index in board.warps) the ray first bent through, and
* how far along the ray that mouth stood — the gate a sprite must be
* beyond (its own warp) or in front of (any) to paint this column. */
/** Which warp (index in board.warps) the ray first bent through, how
* far along the ray that mouth stood, and where across it — the gate a
* sprite must be beyond (its own warp) or in front of (any) to paint
* this column, and the veil the renderer hangs in the opening. */
warpId?: number;
warpDist?: number;
warpU?: number;
/** The first known-illusion edge the ray crossed before its solid hit:
* the eye passes, but a translucent ghost of a wall stands there. */
ghost?: { dist: number; u: number; worldU: number; axis: "x" | "y" };
@@ -62,8 +64,8 @@ export function warpLaneMirrored(from: Side, to: Side): boolean {
const [x, y] = LANE_AXIS[from];
const rx = x * Math.cos(d) - y * Math.sin(d);
const ry = x * Math.sin(d) + y * Math.cos(d);
const [ex2, ey] = LANE_AXIS[to];
return rx * ex2 + ry * ey < 0;
const [ux, uy] = LANE_AXIS[to];
return rx * ux + ry * uy < 0;
}
/** Is this edge passable to the EYE (rays), and if not, what is it?
@@ -77,11 +79,6 @@ function edgeObstacle(view: GameView, key: string): Hit["kind"] | null {
return "wall";
}
/**
* March one ray from (ox, oy) at `angle` and return the first thing that
* stops the eye. Off-board is the maze's rim: a wall, unless the crossing
* is a warp mouth (then a shimmering opening).
*/
/** Half-thickness per material: walls are masonry, doors joinery, fire a
* sheet. The slab gives every wall END a visible cap face, so corners and
* doorways read as three-dimensional stone rather than paper. */
@@ -105,6 +102,14 @@ function slabHit(
return { t: Math.max(tNear, 0), axis: tx1 > ty1 ? "x" : "y" };
}
/** What a slab test found: the strike, and how the door slid under it. */
type SlabStrike = { t: number; axis: "x" | "y"; kind: Hit["kind"]; slide: number; edge: string; frame?: boolean };
/**
* March one ray from (ox, oy) at `angle` and return the first thing that
* stops the eye. Off-board is the maze's rim: a wall, unless the crossing
* is a warp mouth — the ray passes through those, remembering the first.
*/
export function castRay(
view: GameView, ox: number, oy: number, angle: number,
/** Transient door openness (0 shut - 1 wide), keyed by edge; doors the
@@ -121,10 +126,12 @@ export function castRay(
let warped = false;
let warpId: number | undefined;
let warpDist: number | undefined;
let warpU: number | undefined;
let ghost: Hit["ghost"];
let doorway: Hit["doorway"];
let rising: Hit["rising"];
for (let traversal = 0; traversal < 3; traversal++) {
let traversed = false;
const dx = Math.cos(angle);
const dy = Math.sin(angle);
let cx = Math.floor(ox);
@@ -140,7 +147,7 @@ export function castRay(
// Every blocked edge of the current cell stands as a slab; the
// nearest strike inside this cell's span wins.
const exit = Math.min(sideDistX, sideDistY);
let best: { t: number; axis: "x" | "y"; kind: Hit["kind"]; slide: number; edge: string; frame?: boolean } | null = null;
let best: SlabStrike | null = null;
const trySide = (side: Side, minX: number, maxX: number, minY: number, maxY: number) => {
const key = edgeKey({ x: cx, y: cy }, side);
const kind = edgeObstacle(view, key);
@@ -188,13 +195,13 @@ export function castRay(
trySide("S", cx, cx + 1, cy + 1 - hw("S"), cy + 1 + hw("S"));
trySide("N", cx, cx + 1, cy - hw("N"), cy + hw("N"));
if (best !== null) {
const b = best as { t: number; axis: "x" | "y"; kind: Hit["kind"]; slide: number; edge: string; frame?: boolean };
const b = best as SlabStrike;
const along = b.axis === "x" ? oy + b.t * dy : ox + b.t * dx;
const u = along - Math.floor(along);
// A sliding door carries its texture with it: sample past the gap.
return {
dist: baseDist + b.t, kind: b.kind, u: Math.max(0, u - b.slide),
axis: b.axis, worldU: along, edge: b.edge, warped, warpId, warpDist, ghost, doorway, rising,
axis: b.axis, worldU: along, edge: b.edge, warped, warpId, warpDist, warpU, ghost, doorway, rising,
...(b.frame ? { frame: true } : {}),
};
}
@@ -221,8 +228,8 @@ export function castRay(
(w) => cellKey(w.from.cell) === cellKey({ x: cx, y: cy }) && w.from.side === side,
);
const warp = wIdx >= 0 ? view.board.warps[wIdx]! : undefined;
if (!warp) return { dist: baseDist + dist, kind: "rim", u: texU, axis, worldU: along, warped, warpId, warpDist, ghost, doorway, rising };
if (warpId === undefined) { warpId = wIdx; warpDist = baseDist + dist; }
if (!warp) return { dist: baseDist + dist, kind: "rim", u: texU, axis, worldU: along, warped, warpId, warpDist, warpU, ghost, doorway, rising };
if (warpId === undefined) { warpId = wIdx; warpDist = baseDist + dist; warpU = texU; }
// Step through: re-enter at the paired mouth, heading inward, the
// lane carried by the same proper rotation the heading turns by —
// mirrored for the pairings whose axes land head-to-head.
@@ -236,23 +243,23 @@ export function castRay(
else { ox = c.x + lane; oy = c.y + 1e-4; }
baseDist += dist;
warped = true;
i = 64; // restart the DDA from the far mouth
break;
traversed = true;
break; // restart the DDA from the far mouth
}
if (view.squareContents[cellKey({ x: nx, y: ny })]?.kind === "stone") {
const sg = growing?.[cellKey({ x: nx, y: ny })];
if (sg !== undefined && sg < 1) {
if (!rising) rising = { dist: baseDist + dist, u: texU, worldU: along, kind: "stone", g: sg };
} else {
return { dist: baseDist + dist, kind: "stone", u: texU, axis, worldU: along, warped, warpId, warpDist, ghost, doorway, rising };
return { dist: baseDist + dist, kind: "stone", u: texU, axis, worldU: along, warped, warpId, warpDist, warpU, ghost, doorway, rising };
}
}
cx = nx;
cy = ny;
}
if (!warped || traversal === 2) break;
if (!traversed) break;
}
return { dist: baseDist + 64, kind: "rim", u: 0, axis: "x", worldU: 0, warped, warpId, warpDist, ghost, doorway, rising };
return { dist: baseDist + 64, kind: "rim", u: 0, axis: "x", worldU: 0, warped, warpId, warpDist, warpU, ghost, doorway, rising };
}
/** Can a wizard's body (not just their eye) cross this edge? Workshop
@@ -436,8 +443,8 @@ export function billboards(
} else if (content.kind === "safe") {
out.push({
...at, src: "/terrain3d/safe.png", fallback: "safe",
scale: 0.55, aspect: 1, rise: 0, bias: 0.18, label: "safe",
clip: { x: Math.floor(at.x), y: Math.floor(at.y) },
scale: 0.55, aspect: 1, rise: 0, bias: 0.18, label: "safe", key: k,
clip: { x: tx, y: ty },
});
}
}