scena3d 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/random.ts","../src/core/palette.ts","../src/core/types.ts","../src/props/tree.ts","../src/props/rock.ts","../src/props/crate.ts","../src/props/fence.ts","../src/props/lamp.ts","../src/props/grass.ts","../src/props/building.ts","../src/environment/terrain.ts","../src/environment/sky.ts","../src/environment/lighting.ts","../src/environment/water.ts","../src/environment/dayCycle.ts","../src/environment/wind.ts","../src/environment/path.ts","../src/generators/village.ts","../src/scatter/scatter.ts"],"sourcesContent":["/**\n * Deterministic seeded randomness — the backbone of SCENA. Same seed,\n * same tree; forests are reproducible, diffable and network-syncable.\n */\nexport class Rng {\n private state: number;\n\n constructor(seed = 1) {\n this.state = seed >>> 0 || 1;\n }\n\n /** Next float in [0, 1) (mulberry32). */\n next(): number {\n this.state = (this.state + 0x6d2b79f5) >>> 0;\n let t = this.state;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n }\n\n /** Float in [min, max). */\n range(min: number, max: number): number {\n return min + this.next() * (max - min);\n }\n\n /** Integer in [min, max] inclusive. */\n int(min: number, max: number): number {\n return min + Math.floor(this.next() * (max - min + 1));\n }\n\n /** Random element of a non-empty array. */\n pick<T>(items: readonly T[]): T {\n return items[Math.floor(this.next() * items.length)];\n }\n\n /** value ± spread (uniform). */\n jitter(value: number, spread: number): number {\n return value + (this.next() * 2 - 1) * spread;\n }\n\n /** A new independent Rng derived from this one. */\n fork(): Rng {\n return new Rng(Math.floor(this.next() * 0xffffffff) || 1);\n }\n}\n\n/** Integer-lattice hash to [0, 1) — the base of the value noise. */\nexport function hash2(ix: number, iz: number, seed: number): number {\n let h = (ix * 374761393 + iz * 668265263 + seed * 2246822519) >>> 0;\n h = Math.imul(h ^ (h >>> 13), 1274126177) >>> 0;\n return ((h ^ (h >>> 16)) >>> 0) / 4294967296;\n}\n\nconst smooth = (t: number): number => t * t * (3 - 2 * t);\n\n/** 2D value noise in [0, 1). Continuous; used by terrain and scatter density. */\nexport function valueNoise2(x: number, z: number, seed: number): number {\n const ix = Math.floor(x);\n const iz = Math.floor(z);\n const fx = smooth(x - ix);\n const fz = smooth(z - iz);\n const a = hash2(ix, iz, seed);\n const b = hash2(ix + 1, iz, seed);\n const c = hash2(ix, iz + 1, seed);\n const d = hash2(ix + 1, iz + 1, seed);\n return a + (b - a) * fx + (c - a) * fz + (a - b - c + d) * fx * fz;\n}\n\n/** Fractal (octaved) value noise in [0, 1). */\nexport function fractalNoise2(\n x: number,\n z: number,\n seed: number,\n octaves = 4,\n lacunarity = 2,\n gain = 0.5\n): number {\n let amplitude = 1;\n let frequency = 1;\n let sum = 0;\n let total = 0;\n for (let i = 0; i < octaves; i++) {\n sum += valueNoise2(x * frequency, z * frequency, seed + i * 101) * amplitude;\n total += amplitude;\n amplitude *= gain;\n frequency *= lacunarity;\n }\n return sum / total;\n}\n","/**\n * Theme palettes: one coherent set of colors shared by every generator,\n * so procedural props look like a matched set rather than a junk drawer.\n * Pass `palette` to any generator to restyle it; whole scenes retheme by\n * building with a different palette.\n */\nexport interface Palette {\n foliage: number[];\n trunk: number;\n rock: number[];\n wood: number;\n woodDark: number;\n metal: number;\n lampGlow: number;\n grassLow: number;\n grassHigh: number;\n cliff: number;\n peak: number;\n skyTop: number;\n skyBottom: number;\n fog: number;\n water: number;\n sand: number;\n path: number;\n /** Building plaster/wall color. */\n wall: number;\n /** Building roof color. */\n roof: number;\n}\n\nexport const PALETTES: Record<'meadow' | 'autumn' | 'dusk' | 'winter', Palette> = {\n meadow: {\n foliage: [0x2f9e57, 0x37b26a, 0x2a8f4f, 0x45b878],\n trunk: 0x6b4a33,\n rock: [0x8a8f98, 0x767c86, 0x9aa0a8],\n wood: 0x8a6642,\n woodDark: 0x6b4a33,\n metal: 0x3d4451,\n lampGlow: 0xffd889,\n grassLow: 0x3f9d5a,\n grassHigh: 0x6fae66,\n cliff: 0x7d7a72,\n peak: 0xe8ecef,\n skyTop: 0x3d70b8,\n skyBottom: 0xbfd9e8,\n fog: 0xb8cfdd,\n water: 0x3f7fae,\n sand: 0xc9b98a,\n path: 0x9a815f,\n wall: 0xd9ccb0,\n roof: 0xa8563e,\n },\n autumn: {\n foliage: [0xc9752f, 0xd98e3a, 0xb35c2a, 0xe0a545],\n trunk: 0x5d4030,\n rock: [0x8d8578, 0x776f63, 0x9c948a],\n wood: 0x7d5a3a,\n woodDark: 0x5d4030,\n metal: 0x463f3a,\n lampGlow: 0xffc571,\n grassLow: 0x9d8a3f,\n grassHigh: 0xb59b4a,\n cliff: 0x82746a,\n peak: 0xe3ded4,\n skyTop: 0x8e6ca8,\n skyBottom: 0xe8c9a8,\n fog: 0xd9c1a8,\n water: 0x4a7a92,\n sand: 0xcbb083,\n path: 0x8d7454,\n wall: 0xccb894,\n roof: 0x8a4a30,\n },\n dusk: {\n foliage: [0x1f5e46, 0x24684f, 0x1a5240, 0x2d7458],\n trunk: 0x413147,\n rock: [0x565672, 0x484861, 0x646484],\n wood: 0x5d4a63,\n woodDark: 0x413147,\n metal: 0x2b2b3d,\n lampGlow: 0xffb35c,\n grassLow: 0x2d6b52,\n grassHigh: 0x3d7a5e,\n cliff: 0x52516b,\n peak: 0xb8b8d9,\n skyTop: 0x1d2145,\n skyBottom: 0xc96a4a,\n fog: 0x6a5a7a,\n water: 0x2d4a68,\n sand: 0x8a7a6a,\n path: 0x6a5a52,\n wall: 0x8d8299,\n roof: 0x453558,\n },\n winter: {\n foliage: [0x2e5c48, 0x38695a, 0x527a68, 0x87a596],\n trunk: 0x4a3a33,\n rock: [0x9aa4ad, 0x848e98, 0xb0b8c0],\n wood: 0x776049,\n woodDark: 0x54453a,\n metal: 0x39404d,\n lampGlow: 0xffd889,\n grassLow: 0xcfd9de,\n grassHigh: 0xe4ebee,\n cliff: 0x76797d,\n peak: 0xf4f7fa,\n skyTop: 0x5a7ba6,\n skyBottom: 0xd8e4ec,\n fog: 0xccd8e0,\n water: 0x4a7086,\n sand: 0xb8c2c6,\n path: 0x8b8378,\n wall: 0xd2c9bb,\n roof: 0x6b4638,\n },\n};\n\nexport const DEFAULT_PALETTE: Palette = PALETTES.meadow;\n","import { Vector3, type Group, type Object3D } from 'three';\n\n/**\n * A steering obstacle in world space — structurally identical to GAMA's\n * `Obstacle`, so SCENA props plug straight into `ObstacleAvoidance`\n * without either library importing the other.\n */\nexport interface Obstacle {\n center: Vector3;\n radius: number;\n}\n\n/** What a prop generator returns: the visual plus gameplay metadata. */\nexport interface Prop {\n object: Group;\n /**\n * Footprint radius for steering/placement, in the prop's local space\n * (centered at its origin). 0 means walk-through (e.g. grass).\n */\n obstacleRadius: number;\n}\n\n/** Collect world-space obstacles from placed props (call after positioning). */\nexport function collectObstacles(props: Iterable<Prop>): Obstacle[] {\n const obstacles: Obstacle[] = [];\n for (const prop of props) {\n if (prop.obstacleRadius <= 0) continue;\n prop.object.updateWorldMatrix(true, false);\n obstacles.push({\n center: prop.object.getWorldPosition(new Vector3()),\n radius: prop.obstacleRadius * maxScale(prop.object),\n });\n }\n return obstacles;\n}\n\nfunction maxScale(object: Object3D): number {\n return Math.max(object.scale.x, object.scale.z);\n}\n","import {\n ConeGeometry,\n CylinderGeometry,\n Group,\n IcosahedronGeometry,\n Mesh,\n MeshStandardMaterial,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface TreeOptions {\n seed?: number;\n /** Overall height in world units. Default ~3.5–5 by seed. */\n height?: number;\n style?: 'pine' | 'oak';\n palette?: Palette;\n}\n\n/**\n * A seeded low-poly tree. `pine` stacks cones; `oak` clusters foliage\n * blobs on a forked trunk. Same seed → identical tree, forever.\n */\nexport function createTree(options: TreeOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const style = options.style ?? (rng.next() < 0.6 ? 'pine' : 'oak');\n const height = options.height ?? rng.range(3.2, 5.2);\n const group = new Group();\n group.name = `tree-${style}`;\n\n const trunkMaterial = new MeshStandardMaterial({ color: palette.trunk, flatShading: true });\n const foliageMaterial = new MeshStandardMaterial({\n color: rng.pick(palette.foliage),\n flatShading: true,\n });\n\n if (style === 'pine') {\n const trunkHeight = height * 0.25;\n const trunk = new Mesh(new CylinderGeometry(0.09, 0.14, trunkHeight, 6), trunkMaterial);\n trunk.position.y = trunkHeight / 2;\n group.add(trunk);\n\n const tiers = rng.int(3, 4);\n let y = trunkHeight;\n let radius = height * rng.range(0.24, 0.3);\n const tierHeight = (height - trunkHeight) / tiers + 0.15;\n for (let i = 0; i < tiers; i++) {\n const cone = new Mesh(new ConeGeometry(radius, tierHeight * 1.35, 7), foliageMaterial);\n cone.position.y = y + tierHeight * 0.55;\n cone.rotation.y = rng.range(0, Math.PI);\n group.add(cone);\n y += tierHeight * 0.8;\n radius *= 0.72;\n }\n } else {\n const trunkHeight = height * 0.45;\n const trunk = new Mesh(new CylinderGeometry(0.12, 0.2, trunkHeight, 6), trunkMaterial);\n trunk.position.y = trunkHeight / 2;\n trunk.rotation.z = rng.range(-0.08, 0.08);\n group.add(trunk);\n\n const blobs = rng.int(2, 4);\n for (let i = 0; i < blobs; i++) {\n const radius = height * rng.range(0.18, 0.28);\n const blob = new Mesh(new IcosahedronGeometry(radius, 0), foliageMaterial);\n blob.position.set(\n rng.jitter(0, height * 0.16),\n trunkHeight + radius * rng.range(0.5, 0.9) + i * radius * 0.35,\n rng.jitter(0, height * 0.16)\n );\n blob.rotation.set(rng.range(0, Math.PI), rng.range(0, Math.PI), 0);\n group.add(blob);\n }\n }\n\n return { object: group, obstacleRadius: style === 'pine' ? 0.5 : 0.6 };\n}\n","import {\n BufferAttribute,\n Group,\n IcosahedronGeometry,\n Mesh,\n MeshStandardMaterial,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface RockOptions {\n seed?: number;\n /** Approximate radius. Default ~0.4–1.1 by seed. */\n size?: number;\n palette?: Palette;\n}\n\n/**\n * A seeded low-poly boulder: an icosahedron with jittered vertices and a\n * flattened underside so it sits on the ground.\n */\nexport function createRock(options: RockOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const size = options.size ?? rng.range(0.4, 1.1);\n\n const geometry = new IcosahedronGeometry(size, 0);\n const positions = geometry.getAttribute('position') as BufferAttribute;\n // Jitter welded-by-value: identical vertex values get identical offsets,\n // so faces stay connected.\n const seen = new Map<string, [number, number, number]>();\n for (let i = 0; i < positions.count; i++) {\n const key = `${positions.getX(i).toFixed(4)},${positions.getY(i).toFixed(4)},${positions.getZ(i).toFixed(4)}`;\n let offset = seen.get(key);\n if (!offset) {\n offset = [rng.jitter(0, size * 0.22), rng.jitter(0, size * 0.16), rng.jitter(0, size * 0.22)];\n seen.set(key, offset);\n }\n positions.setXYZ(\n i,\n positions.getX(i) + offset[0],\n Math.max(positions.getY(i) + offset[1], -size * 0.15), // flatten the bottom\n positions.getZ(i) + offset[2]\n );\n }\n geometry.computeVertexNormals();\n\n const rock = new Mesh(\n geometry,\n new MeshStandardMaterial({ color: rng.pick(palette.rock), flatShading: true })\n );\n rock.position.y = size * 0.15;\n rock.scale.y = rng.range(0.6, 0.9);\n\n const group = new Group();\n group.name = 'rock';\n group.add(rock);\n return { object: group, obstacleRadius: size * 1.05 };\n}\n","import { BoxGeometry, Group, Mesh, MeshStandardMaterial } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface CrateOptions {\n seed?: number;\n size?: number;\n /** 0–1 color wear. Default 0.3. */\n weathering?: number;\n palette?: Palette;\n}\n\n/** A wooden crate: panel box with darker edge framing, seeded wear tint. */\nexport function createCrate(options: CrateOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const size = options.size ?? 1;\n const wear = options.weathering ?? 0.3;\n\n const group = new Group();\n group.name = 'crate';\n\n const panelMaterial = new MeshStandardMaterial({ color: palette.wood, flatShading: true });\n panelMaterial.color.offsetHSL(0, 0, -rng.range(0, wear * 0.18));\n const frameMaterial = new MeshStandardMaterial({ color: palette.woodDark, flatShading: true });\n\n const body = new Mesh(new BoxGeometry(size * 0.92, size * 0.92, size * 0.92), panelMaterial);\n body.position.y = size / 2;\n group.add(body);\n\n const beam = size * 0.12;\n const long = size * 1.0;\n for (const y of [beam / 2, size - beam / 2]) {\n for (const [rx, rz, w, d] of [\n [0, size / 2 - beam / 2, long, beam],\n [0, -(size / 2 - beam / 2), long, beam],\n [size / 2 - beam / 2, 0, beam, long],\n [-(size / 2 - beam / 2), 0, beam, long],\n ] as const) {\n const rail = new Mesh(new BoxGeometry(w, beam, d), frameMaterial);\n rail.position.set(rx, y, rz);\n group.add(rail);\n }\n }\n for (const x of [-1, 1]) {\n for (const z of [-1, 1]) {\n const post = new Mesh(new BoxGeometry(beam, size, beam), frameMaterial);\n post.position.set(x * (size / 2 - beam / 2), size / 2, z * (size / 2 - beam / 2));\n group.add(post);\n }\n }\n group.rotation.y = rng.range(0, Math.PI / 2);\n\n return { object: group, obstacleRadius: size * 0.75 };\n}\n","import { BoxGeometry, CylinderGeometry, Group, Mesh, MeshStandardMaterial } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface FenceOptions {\n seed?: number;\n /** Run length along local +x. Default 6. */\n length?: number;\n postSpacing?: number;\n height?: number;\n palette?: Palette;\n}\n\n/**\n * A rustic fence run along local +x, centered at the origin: posts with\n * two slightly-crooked rails. Chain several and rotate to enclose areas.\n * The obstacle radius covers the whole run (rough but steering-safe);\n * for tight navigation, bake a navmesh — the geometry is authoritative.\n */\nexport function createFence(options: FenceOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const length = options.length ?? 6;\n const spacing = options.postSpacing ?? 1.5;\n const height = options.height ?? 1.1;\n\n const group = new Group();\n group.name = 'fence';\n const postMaterial = new MeshStandardMaterial({ color: palette.woodDark, flatShading: true });\n const railMaterial = new MeshStandardMaterial({ color: palette.wood, flatShading: true });\n\n const posts = Math.max(2, Math.round(length / spacing) + 1);\n const step = length / (posts - 1);\n for (let i = 0; i < posts; i++) {\n const post = new Mesh(new CylinderGeometry(0.06, 0.075, height, 5), postMaterial);\n post.position.set(-length / 2 + i * step, height / 2, rng.jitter(0, 0.03));\n post.rotation.z = rng.range(-0.04, 0.04);\n group.add(post);\n }\n for (const railY of [height * 0.55, height * 0.85]) {\n const rail = new Mesh(new BoxGeometry(length, 0.07, 0.05), railMaterial);\n rail.position.y = rng.jitter(railY, 0.02);\n rail.rotation.x = rng.range(-0.02, 0.02);\n group.add(rail);\n }\n\n return { object: group, obstacleRadius: length / 2 };\n}\n","import {\n BoxGeometry,\n CylinderGeometry,\n Group,\n Mesh,\n MeshStandardMaterial,\n PointLight,\n SphereGeometry,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface LampOptions {\n seed?: number;\n height?: number;\n /** Add a real PointLight. Off by default — lights are a budget. */\n light?: boolean;\n lightIntensity?: number;\n palette?: Palette;\n}\n\n/** A street lamp: post, head, glowing bulb, optional real PointLight. */\nexport function createLamp(options: LampOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const height = options.height ?? rng.range(2.6, 3.1);\n\n const group = new Group();\n group.name = 'lamp';\n const metal = new MeshStandardMaterial({ color: palette.metal, flatShading: true });\n\n const post = new Mesh(new CylinderGeometry(0.05, 0.08, height, 6), metal);\n post.position.y = height / 2;\n group.add(post);\n\n const head = new Mesh(new BoxGeometry(0.34, 0.26, 0.34), metal);\n head.position.y = height + 0.1;\n group.add(head);\n\n const bulb = new Mesh(\n new SphereGeometry(0.11, 8, 6),\n new MeshStandardMaterial({\n color: palette.lampGlow,\n emissive: palette.lampGlow,\n emissiveIntensity: 1.6,\n })\n );\n bulb.position.y = height - 0.03;\n group.add(bulb);\n\n if (options.light) {\n const light = new PointLight(palette.lampGlow, options.lightIntensity ?? 6, 12, 1.8);\n light.position.y = height - 0.05;\n group.add(light);\n }\n\n return { object: group, obstacleRadius: 0.25 };\n}\n","import { ConeGeometry, Group, IcosahedronGeometry, Mesh, MeshStandardMaterial } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface GrassOptions {\n seed?: number;\n /** Blades per tuft. Default 4–6 by seed. */\n blades?: number;\n palette?: Palette;\n}\n\n/**\n * A tuft of grass blades — pure scatter fodder (zero obstacle footprint,\n * walk straight through). Sways beautifully under `applyWind`.\n */\nexport function createGrassTuft(options: GrassOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const blades = options.blades ?? rng.int(4, 6);\n const group = new Group();\n group.name = 'grass';\n const material = new MeshStandardMaterial({\n color: rng.next() < 0.5 ? palette.grassHigh : rng.pick(palette.foliage),\n flatShading: true,\n });\n for (let i = 0; i < blades; i++) {\n const height = rng.range(0.25, 0.5);\n const blade = new Mesh(new ConeGeometry(0.035, height, 3), material);\n blade.position.set(rng.jitter(0, 0.12), height / 2, rng.jitter(0, 0.12));\n blade.rotation.set(rng.range(-0.25, 0.25), rng.range(0, Math.PI), rng.range(-0.25, 0.25));\n group.add(blade);\n }\n return { object: group, obstacleRadius: 0 };\n}\n\nexport interface BushOptions {\n seed?: number;\n size?: number;\n palette?: Palette;\n}\n\n/** A low foliage bush: two or three squashed blobs. Small footprint. */\nexport function createBush(options: BushOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const size = options.size ?? rng.range(0.4, 0.7);\n const group = new Group();\n group.name = 'bush';\n const material = new MeshStandardMaterial({ color: rng.pick(palette.foliage), flatShading: true });\n const blobs = rng.int(2, 3);\n for (let i = 0; i < blobs; i++) {\n const radius = size * rng.range(0.55, 0.85);\n const blob = new Mesh(new IcosahedronGeometry(radius, 0), material);\n blob.position.set(rng.jitter(0, size * 0.4), radius * 0.7, rng.jitter(0, size * 0.4));\n blob.scale.y = rng.range(0.7, 0.85);\n blob.rotation.y = rng.range(0, Math.PI);\n group.add(blob);\n }\n return { object: group, obstacleRadius: size * 0.6 };\n}\n","import {\n BoxGeometry,\n BufferAttribute,\n BufferGeometry,\n CylinderGeometry,\n Group,\n Mesh,\n MeshStandardMaterial,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\n/** A gabled-roof prism: ridge along local z, base resting on y = 0. */\nfunction prismGeometry(width: number, height: number, depth: number): BufferGeometry {\n const w = width / 2;\n const d = depth / 2;\n // prettier-ignore\n const positions = new Float32Array([\n // front gable (z = +d)\n -w, 0, d, w, 0, d, 0, height, d,\n // back gable (z = -d)\n w, 0, -d, -w, 0, -d, 0, height, -d,\n // left slope\n -w, 0, -d, -w, 0, d, 0, height, d,\n -w, 0, -d, 0, height, d, 0, height, -d,\n // right slope\n w, 0, d, w, 0, -d, 0, height, -d,\n w, 0, d, 0, height, -d, 0, height, d,\n // bottom\n -w, 0, -d, w, 0, -d, w, 0, d,\n -w, 0, -d, w, 0, d, -w, 0, d,\n ]);\n const geometry = new BufferGeometry();\n geometry.setAttribute('position', new BufferAttribute(positions, 3));\n geometry.computeVertexNormals();\n return geometry;\n}\n\nexport interface HouseOptions {\n seed?: number;\n /** Footprint width (gable side). Default seeded 3.2–4.2. */\n width?: number;\n depth?: number;\n wallHeight?: number;\n palette?: Palette;\n}\n\n/**\n * A cottage: plastered walls, gabled roof, door, chimney and emissive\n * windows. Pass the house in `createDayCycle`'s `lamps` list and its\n * windows glow at night along with the street lamps. A stone foundation\n * extends below ground so sloped terrain never shows a gap.\n */\nexport function createHouse(options: HouseOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const width = options.width ?? rng.range(3.2, 4.2);\n const depth = options.depth ?? width * rng.range(0.75, 0.9);\n const wallHeight = options.wallHeight ?? rng.range(2.1, 2.4);\n\n const group = new Group();\n group.name = 'house';\n const wall = new MeshStandardMaterial({ color: palette.wall, flatShading: true });\n wall.color.offsetHSL(0, 0, rng.range(-0.03, 0.03));\n const roof = new MeshStandardMaterial({ color: palette.roof, flatShading: true });\n roof.color.offsetHSL(0, 0, rng.range(-0.04, 0.04));\n const stone = new MeshStandardMaterial({ color: palette.rock[0], flatShading: true });\n const wood = new MeshStandardMaterial({ color: palette.woodDark, flatShading: true });\n\n const foundation = new Mesh(new BoxGeometry(width + 0.3, 1.6, depth + 0.3), stone);\n foundation.position.y = -0.55;\n group.add(foundation);\n\n const body = new Mesh(new BoxGeometry(width, wallHeight, depth), wall);\n body.position.y = wallHeight / 2;\n group.add(body);\n\n const ridgeHeight = width * rng.range(0.32, 0.4);\n const roofMesh = new Mesh(prismGeometry(width + 0.5, ridgeHeight, depth + 0.6), roof);\n roofMesh.position.y = wallHeight - 0.02;\n group.add(roofMesh);\n\n const chimney = new Mesh(new BoxGeometry(0.34, ridgeHeight + 0.8, 0.34), stone);\n chimney.position.set(rng.pick([-1, 1]) * width * 0.22, wallHeight + ridgeHeight * 0.45, depth * 0.12);\n group.add(chimney);\n\n // Door on the front face (+z).\n const door = new Mesh(new BoxGeometry(0.85, 1.5, 0.08), wood);\n door.position.set(rng.range(-0.4, 0.4), 0.75, depth / 2 + 0.02);\n group.add(door);\n\n // Emissive windows — createDayCycle treats these like lamp bulbs.\n const glass = new MeshStandardMaterial({\n color: palette.lampGlow,\n emissive: palette.lampGlow,\n emissiveIntensity: 1.0,\n });\n const windowGeometry = new BoxGeometry(0.6, 0.62, 0.08);\n const front = new Mesh(windowGeometry, glass);\n front.position.set(door.position.x < 0 ? width * 0.28 : -width * 0.28, 1.35, depth / 2 + 0.02);\n group.add(front);\n for (const side of [-1, 1]) {\n if (rng.next() < 0.35) continue;\n const pane = new Mesh(windowGeometry, glass);\n pane.position.set(side * (width / 2 + 0.02), 1.35, rng.range(-0.3, 0.3) * depth);\n pane.rotation.y = Math.PI / 2;\n group.add(pane);\n }\n\n return { object: group, obstacleRadius: Math.hypot(width + 0.5, depth + 0.5) / 2 };\n}\n\nexport interface TowerOptions {\n seed?: number;\n height?: number;\n palette?: Palette;\n}\n\n/** A wooden watchtower: splayed legs, platform with railing, pyramid roof. */\nexport function createTower(options: TowerOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const height = options.height ?? rng.range(4.2, 5.2);\n\n const group = new Group();\n group.name = 'tower';\n const wood = new MeshStandardMaterial({ color: palette.wood, flatShading: true });\n const woodDark = new MeshStandardMaterial({ color: palette.woodDark, flatShading: true });\n const roof = new MeshStandardMaterial({ color: palette.roof, flatShading: true });\n\n const spread = 1.0;\n for (const x of [-1, 1]) {\n for (const z of [-1, 1]) {\n const leg = new Mesh(new CylinderGeometry(0.09, 0.12, height, 6), woodDark);\n leg.position.set(x * spread * 0.75, height / 2 - 0.6, z * spread * 0.75);\n leg.rotation.z = -x * 0.1;\n leg.rotation.x = z * 0.1;\n group.add(leg);\n }\n }\n // Cross-braces.\n for (const level of [0.3, 0.62]) {\n const brace = new Mesh(new BoxGeometry(spread * 2.1, 0.09, 0.07), wood);\n brace.position.set(0, height * level, spread * 0.82 * (1 - level * 0.35));\n brace.rotation.z = rng.pick([-0.5, 0.5]);\n group.add(brace);\n const braceSide = new Mesh(new BoxGeometry(0.07, 0.09, spread * 2.1), wood);\n braceSide.position.set(spread * 0.82 * (1 - level * 0.35), height * level, 0);\n braceSide.rotation.x = rng.pick([-0.5, 0.5]);\n group.add(braceSide);\n }\n\n const platform = new Mesh(new BoxGeometry(spread * 2.2, 0.14, spread * 2.2), wood);\n platform.position.y = height - 0.5;\n group.add(platform);\n for (const x of [-1, 1]) {\n for (const z of [-1, 1]) {\n const post = new Mesh(new BoxGeometry(0.08, 0.9, 0.08), woodDark);\n post.position.set(x * spread * 1.0, height - 0.05, z * spread * 1.0);\n group.add(post);\n }\n }\n for (const [rx, rz, w, d] of [\n [0, 1, spread * 2.1, 0.06],\n [0, -1, spread * 2.1, 0.06],\n [1, 0, 0.06, spread * 2.1],\n [-1, 0, 0.06, spread * 2.1],\n ] as const) {\n const rail = new Mesh(new BoxGeometry(w, 0.07, d), wood);\n rail.position.set(rx * spread, height + 0.28, rz * spread);\n group.add(rail);\n }\n\n const cap = new Mesh(new CylinderGeometry(0, spread * 1.55, 1.0, 4), roof);\n cap.position.y = height + 1.15;\n cap.rotation.y = Math.PI / 4;\n group.add(cap);\n\n return { object: group, obstacleRadius: spread * 1.35 };\n}\n\nexport interface WellOptions {\n seed?: number;\n palette?: Palette;\n}\n\n/** A stone well: ring, posts, little gabled roof, hanging bucket. */\nexport function createWell(options: WellOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n\n const group = new Group();\n group.name = 'well';\n const stone = new MeshStandardMaterial({ color: rng.pick(palette.rock), flatShading: true });\n const wood = new MeshStandardMaterial({ color: palette.woodDark, flatShading: true });\n const roof = new MeshStandardMaterial({ color: palette.roof, flatShading: true });\n\n const ring = new Mesh(new CylinderGeometry(0.85, 0.95, 0.75, 10), stone);\n ring.position.y = 0.375;\n group.add(ring);\n const inner = new Mesh(\n new CylinderGeometry(0.62, 0.62, 0.05, 10),\n new MeshStandardMaterial({ color: 0x16222e })\n );\n inner.position.y = 0.76;\n group.add(inner);\n\n for (const side of [-1, 1]) {\n const post = new Mesh(new CylinderGeometry(0.06, 0.075, 1.9, 5), wood);\n post.position.set(side * 0.72, 0.95, 0);\n group.add(post);\n }\n const bar = new Mesh(new CylinderGeometry(0.045, 0.045, 1.5, 5), wood);\n bar.rotation.z = Math.PI / 2;\n bar.position.y = 1.72;\n group.add(bar);\n\n const cap = new Mesh(prismGeometry(2.0, 0.55, 0.65), roof);\n cap.position.y = 1.86;\n cap.rotation.y = Math.PI / 2;\n group.add(cap);\n\n const rope = new Mesh(new CylinderGeometry(0.012, 0.012, 0.6, 4), wood);\n rope.position.y = 1.42;\n group.add(rope);\n const bucket = new Mesh(new CylinderGeometry(0.13, 0.1, 0.2, 7), wood);\n bucket.position.y = 1.05;\n group.add(bucket);\n\n return { object: group, obstacleRadius: 1.0 };\n}\n\nexport interface RuinOptions {\n seed?: number;\n /** Footprint width. Default seeded 3.5–5. */\n size?: number;\n palette?: Palette;\n}\n\n/**\n * A ruined building: a partial rectangle of crumbling wall segments with\n * seeded gaps and heights, and tumbled blocks around the floor.\n */\nexport function createRuin(options: RuinOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const size = options.size ?? rng.range(3.5, 5);\n const depth = size * rng.range(0.7, 0.9);\n\n const group = new Group();\n group.name = 'ruin';\n const stone = new MeshStandardMaterial({ color: rng.pick(palette.rock), flatShading: true });\n stone.color.offsetHSL(0, 0, rng.range(-0.04, 0.02));\n\n const thickness = 0.35;\n // Wall runs: [centerX, centerZ, length, alongX]. Front wall mostly gone.\n const runs: Array<[number, number, number, boolean]> = [\n [0, -depth / 2, size, true],\n [-size / 2, 0, depth, false],\n [size / 2, 0, depth, false],\n [size * 0.3, depth / 2, size * 0.35, true],\n ];\n for (const [cx, cz, length, alongX] of runs) {\n const segments = Math.max(2, Math.round(length / 1.1));\n const step = length / segments;\n for (let i = 0; i < segments; i++) {\n if (rng.next() < 0.22) continue; // collapsed gap\n const height = rng.range(0.5, 2.2);\n const wall = new Mesh(\n new BoxGeometry(alongX ? step * 0.96 : thickness, height, alongX ? thickness : step * 0.96),\n stone\n );\n const offset = -length / 2 + step * (i + 0.5);\n wall.position.set(alongX ? cx + offset : cx, height / 2, alongX ? cz : cz + offset);\n wall.rotation.y = rng.range(-0.03, 0.03);\n group.add(wall);\n }\n }\n // Tumbled blocks.\n const blocks = rng.int(4, 7);\n for (let i = 0; i < blocks; i++) {\n const s = rng.range(0.25, 0.55);\n const block = new Mesh(new BoxGeometry(s, s * rng.range(0.6, 1), s * rng.range(0.7, 1.2)), stone);\n block.position.set(rng.range(-size * 0.6, size * 0.6), s * 0.3, rng.range(-depth * 0.6, depth * 0.7));\n block.rotation.set(rng.range(-0.3, 0.3), rng.range(0, Math.PI), rng.range(-0.3, 0.3));\n group.add(block);\n }\n\n return { object: group, obstacleRadius: Math.hypot(size, depth) / 2 };\n}\n","import {\n BufferAttribute,\n Color,\n Mesh,\n MeshStandardMaterial,\n PlaneGeometry,\n} from 'three';\nimport { fractalNoise2 } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\n\nexport interface TerrainOptions {\n seed?: number;\n /** Square side length. Default 80. */\n size?: number;\n /** Vertices per side. Default 96. */\n resolution?: number;\n /** Peak height. Default 6. */\n amplitude?: number;\n /** Noise feature size in world units. Default 28. */\n noiseScale?: number;\n octaves?: number;\n /** Flatten low areas into meadows (0–1, higher = flatter valleys). Default 0.55. */\n valleyFlatness?: number;\n /** Blend low bands toward sand below (waterLevel + shore margin). */\n waterLevel?: number;\n palette?: Palette;\n}\n\nexport interface Terrain {\n mesh: Mesh;\n /** Exact analytic height at any (x, z) — same function that built the\n * mesh, so agents/navmesh queries never disagree with the visuals. */\n heightAt(x: number, z: number): number;\n size: number;\n seed: number;\n}\n\n/**\n * A seeded low-poly terrain: fractal value noise displacing a plane, with\n * height/slope-banded vertex colors (grass → high grass → cliff → peak).\n * The height function is exported, not just baked into vertices — that's\n * what lets gameplay (spawning, scattering, navmesh baking, agent ground\n * clamping) agree exactly with what's rendered.\n */\nexport function createTerrain(options: TerrainOptions = {}): Terrain {\n const seed = options.seed ?? 1;\n const size = options.size ?? 80;\n const resolution = options.resolution ?? 96;\n const amplitude = options.amplitude ?? 6;\n const noiseScale = options.noiseScale ?? 28;\n const octaves = options.octaves ?? 4;\n const flatness = options.valleyFlatness ?? 0.55;\n const palette = options.palette ?? DEFAULT_PALETTE;\n\n const heightAt = (x: number, z: number): number => {\n const n = fractalNoise2(x / noiseScale, z / noiseScale, seed, octaves);\n // Push valleys down and flatten them; keep peaks.\n const shaped = Math.pow(n, 1 + flatness * 2);\n return shaped * amplitude;\n };\n\n const geometry = new PlaneGeometry(size, size, resolution - 1, resolution - 1);\n geometry.rotateX(-Math.PI / 2);\n const positions = geometry.getAttribute('position') as BufferAttribute;\n for (let i = 0; i < positions.count; i++) {\n positions.setY(i, heightAt(positions.getX(i), positions.getZ(i)));\n }\n geometry.computeVertexNormals();\n\n // Vertex colors by height band + slope.\n const normals = geometry.getAttribute('normal') as BufferAttribute;\n const colors = new Float32Array(positions.count * 3);\n const grassLow = new Color(palette.grassLow);\n const grassHigh = new Color(palette.grassHigh);\n const cliff = new Color(palette.cliff);\n const peak = new Color(palette.peak);\n const sand = new Color(palette.sand);\n const waterLevel = options.waterLevel;\n const scratch = new Color();\n for (let i = 0; i < positions.count; i++) {\n const y = positions.getY(i);\n const h = y / amplitude;\n const slope = 1 - normals.getY(i); // 0 flat … 1 vertical\n scratch.copy(grassLow).lerp(grassHigh, Math.min(1, h * 1.6));\n if (h > 0.75) scratch.lerp(peak, (h - 0.75) * 4);\n if (slope > 0.15) scratch.lerp(cliff, Math.min(1, (slope - 0.15) * 4));\n if (waterLevel !== undefined && y < waterLevel + 0.5) {\n scratch.lerp(sand, Math.min(1, (waterLevel + 0.5 - y) * 1.6));\n }\n colors[i * 3] = scratch.r;\n colors[i * 3 + 1] = scratch.g;\n colors[i * 3 + 2] = scratch.b;\n }\n geometry.setAttribute('color', new BufferAttribute(colors, 3));\n\n const mesh = new Mesh(\n geometry,\n new MeshStandardMaterial({ vertexColors: true, flatShading: true })\n );\n mesh.name = 'terrain';\n\n return { mesh, heightAt, size, seed };\n}\n","import {\n BackSide,\n Color,\n Mesh,\n ShaderMaterial,\n SphereGeometry,\n} from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\n\nexport interface SkyOptions {\n topColor?: number;\n bottomColor?: number;\n radius?: number;\n palette?: Palette;\n}\n\nexport interface Sky {\n mesh: Mesh;\n setColors(top: number, bottom: number): void;\n}\n\n/**\n * A gradient sky dome (vertical color blend on an inverted sphere).\n * Colors default to the palette, so themed scenes get matching skies.\n */\nexport function createSky(options: SkyOptions = {}): Sky {\n const palette = options.palette ?? DEFAULT_PALETTE;\n const material = new ShaderMaterial({\n side: BackSide,\n depthWrite: false,\n uniforms: {\n topColor: { value: new Color(options.topColor ?? palette.skyTop) },\n bottomColor: { value: new Color(options.bottomColor ?? palette.skyBottom) },\n },\n vertexShader: /* glsl */ `\n varying vec3 vWorld;\n void main() {\n vWorld = (modelMatrix * vec4(position, 1.0)).xyz;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }`,\n fragmentShader: /* glsl */ `\n uniform vec3 topColor;\n uniform vec3 bottomColor;\n varying vec3 vWorld;\n void main() {\n float t = clamp(normalize(vWorld).y * 0.5 + 0.5, 0.0, 1.0);\n gl_FragColor = vec4(mix(bottomColor, topColor, pow(t, 0.8)), 1.0);\n }`,\n });\n const mesh = new Mesh(new SphereGeometry(options.radius ?? 400, 16, 12), material);\n mesh.name = 'sky';\n\n return {\n mesh,\n setColors(top, bottom) {\n (material.uniforms.topColor.value as Color).setHex(top);\n (material.uniforms.bottomColor.value as Color).setHex(bottom);\n },\n };\n}\n","import {\n AmbientLight,\n DirectionalLight,\n Fog,\n Group,\n HemisphereLight,\n type Scene,\n} from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\n\nexport type LightingPreset = 'day' | 'golden-hour' | 'overcast' | 'night';\n\nexport interface LightingRig {\n group: Group;\n sun: DirectionalLight;\n ambient: AmbientLight;\n hemisphere: HemisphereLight;\n}\n\nconst PRESETS: Record<\n LightingPreset,\n { sun: number; sunIntensity: number; sunPos: [number, number, number]; ambient: number; ambientIntensity: number; skyTint: number; groundTint: number }\n> = {\n day: {\n sun: 0xfff4e0, sunIntensity: 1.6, sunPos: [30, 45, 20],\n ambient: 0xdfeaff, ambientIntensity: 0.35, skyTint: 0xbcd8ff, groundTint: 0x6a7d66,\n },\n 'golden-hour': {\n sun: 0xffb861, sunIntensity: 1.7, sunPos: [40, 14, -12],\n ambient: 0xffdcc0, ambientIntensity: 0.3, skyTint: 0xffcf9e, groundTint: 0x7a6a58,\n },\n overcast: {\n sun: 0xd8dee8, sunIntensity: 0.7, sunPos: [12, 40, 8],\n ambient: 0xcfd6e0, ambientIntensity: 0.65, skyTint: 0xc8d0dc, groundTint: 0x707a78,\n },\n night: {\n sun: 0x8ea6d8, sunIntensity: 0.35, sunPos: [-20, 30, -25],\n ambient: 0x3a4468, ambientIntensity: 0.35, skyTint: 0x2c3560, groundTint: 0x1e2430,\n },\n};\n\n/**\n * The three lights every scene rebuilds, as a preset: warm directional\n * \"sun\" (position doubles as light direction), ambient fill, and a\n * hemisphere tint. Retune any of them via the returned rig.\n */\nexport function createLightingRig(preset: LightingPreset = 'day'): LightingRig {\n const config = PRESETS[preset];\n const group = new Group();\n group.name = `lighting-${preset}`;\n const sun = new DirectionalLight(config.sun, config.sunIntensity);\n sun.position.set(...config.sunPos);\n const ambient = new AmbientLight(config.ambient, config.ambientIntensity);\n const hemisphere = new HemisphereLight(config.skyTint, config.groundTint, 0.5);\n group.add(sun, ambient, hemisphere);\n return { group, sun, ambient, hemisphere };\n}\n\nexport type FogPreset = 'clear' | 'haze' | 'thick' | 'eerie';\n\nconst FOG: Record<Exclude<FogPreset, 'clear'>, { near: number; far: number }> = {\n haze: { near: 45, far: 160 },\n thick: { near: 12, far: 70 },\n eerie: { near: 6, far: 42 },\n};\n\n/** Distance fog matched to the palette's fog color. 'clear' removes it. */\nexport function applyFog(scene: Scene, preset: FogPreset, palette: Palette = DEFAULT_PALETTE): void {\n if (preset === 'clear') {\n scene.fog = null;\n return;\n }\n const { near, far } = FOG[preset];\n scene.fog = new Fog(palette.fog, near, far);\n}\n","import { BufferAttribute, Mesh, MeshStandardMaterial, PlaneGeometry } from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Terrain } from './terrain';\n\nexport interface WaterOptions {\n /** World-space water surface height. Default 0.8. */\n level?: number;\n size?: number;\n resolution?: number;\n /** Wave height. Default 0.06. */\n amplitude?: number;\n /** Wave speed multiplier. Default 1. */\n speed?: number;\n palette?: Palette;\n}\n\nexport interface Water {\n mesh: Mesh;\n level: number;\n /** Advance the wave animation. Call from your frame loop. */\n update(dt: number): void;\n /** Is ground at this height below the surface? */\n isUnderwater(groundHeight: number): boolean;\n}\n\n/**\n * A low-poly animated water plane at a fixed level. Pair it with a\n * terrain built using the same `waterLevel` so shores blend to sand, and\n * keep scatter/agents ashore with `aboveWater(terrain, water)`.\n */\nexport function createWater(options: WaterOptions = {}): Water {\n const level = options.level ?? 0.8;\n const size = options.size ?? 200;\n const resolution = options.resolution ?? 40;\n const amplitude = options.amplitude ?? 0.06;\n const speed = options.speed ?? 1;\n const palette = options.palette ?? DEFAULT_PALETTE;\n\n const geometry = new PlaneGeometry(size, size, resolution, resolution);\n geometry.rotateX(-Math.PI / 2);\n const positions = geometry.getAttribute('position') as BufferAttribute;\n const mesh = new Mesh(\n geometry,\n new MeshStandardMaterial({\n color: palette.water,\n transparent: true,\n opacity: 0.85,\n flatShading: true,\n metalness: 0.35,\n roughness: 0.4,\n })\n );\n mesh.name = 'water';\n mesh.position.y = level;\n\n let time = 0;\n const update = (dt: number): void => {\n time += dt * speed;\n for (let i = 0; i < positions.count; i++) {\n const x = positions.getX(i);\n const z = positions.getZ(i);\n positions.setY(\n i,\n Math.sin(x * 0.35 + time) * Math.cos(z * 0.3 + time * 0.8) * amplitude\n );\n }\n positions.needsUpdate = true;\n geometry.computeVertexNormals();\n };\n update(0);\n\n return {\n mesh,\n level,\n update,\n isUnderwater: (groundHeight) => groundHeight < level,\n };\n}\n\n/**\n * A scatter mask keeping placements on dry land: true when the terrain\n * at (x, z) sits above the water level plus `margin`.\n */\nexport function aboveWater(\n terrain: Terrain,\n water: Pick<Water, 'level'>,\n margin = 0.25\n): (x: number, z: number) => boolean {\n return (x, z) => terrain.heightAt(x, z) > water.level + margin;\n}\n","import { Color, PointLight, type MeshStandardMaterial, type Mesh, type Object3D, type Scene } from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { LightingRig } from './lighting';\nimport type { Sky } from './sky';\n\ninterface Keyframe {\n t: number;\n skyTop: number;\n skyBottom: number;\n sun: number;\n sunIntensity: number;\n ambientIntensity: number;\n fog: number;\n}\n\nexport interface DayCycleOptions {\n sky?: Sky;\n rig?: LightingRig;\n /** Scene whose fog color should track the cycle. */\n scene?: Scene;\n /** Lamp props/objects whose PointLights + glow bulbs ignite at night. */\n lamps?: Array<{ object: Object3D } | Object3D>;\n palette?: Palette;\n /** Seconds per full day. Default 60. */\n dayLength?: number;\n /** Initial time: 0 = midnight, 0.25 = dawn, 0.5 = noon, 0.75 = dusk. */\n timeOfDay?: number;\n}\n\nexport interface DayCycle {\n timeOfDay: number;\n /** Sun elevation in [-1, 1]; negative = below the horizon. */\n readonly sunElevation: number;\n readonly isNight: boolean;\n /** Advance by dt seconds of real time and re-apply everything. */\n update(dt: number): void;\n /** Jump to a time of day and re-apply everything. */\n set(t: number): void;\n}\n\n/**\n * One `timeOfDay` parameter driving the whole environment in lockstep:\n * sun position/color/intensity, sky gradient, ambient level, fog color,\n * and lamps that ignite as the sun drops below the horizon.\n *\n * ```ts\n * const cycle = createDayCycle({ sky, rig, scene, lamps: [lampA, lampB], dayLength: 120 });\n * game.onUpdate((t) => cycle.update(t.delta));\n * ```\n */\nexport function createDayCycle(options: DayCycleOptions = {}): DayCycle {\n const palette = options.palette ?? DEFAULT_PALETTE;\n const dayLength = options.dayLength ?? 60;\n\n // Universal ramp; noon colors come from the palette so themes carry through.\n const frames: Keyframe[] = [\n { t: 0.0, skyTop: 0x0b1026, skyBottom: 0x1a2340, sun: 0x8ea6d8, sunIntensity: 0.03, ambientIntensity: 0.06, fog: 0x141a2e },\n { t: 0.23, skyTop: 0x27335c, skyBottom: 0x6a5470, sun: 0xcf9a72, sunIntensity: 0.3, ambientIntensity: 0.12, fog: 0x4a4258 },\n { t: 0.3, skyTop: 0x4a6ba0, skyBottom: 0xe8a97a, sun: 0xffb861, sunIntensity: 1.0, ambientIntensity: 0.26, fog: 0xb08a72 },\n { t: 0.5, skyTop: palette.skyTop, skyBottom: palette.skyBottom, sun: 0xfff4e0, sunIntensity: 1.9, ambientIntensity: 0.45, fog: palette.fog },\n { t: 0.7, skyTop: 0x4a5a94, skyBottom: 0xe0955e, sun: 0xffa050, sunIntensity: 1.0, ambientIntensity: 0.26, fog: 0xa07a68 },\n { t: 0.78, skyTop: 0x232a52, skyBottom: 0x8a5560, sun: 0xd88a5a, sunIntensity: 0.25, ambientIntensity: 0.11, fog: 0x463e54 },\n { t: 1.0, skyTop: 0x0b1026, skyBottom: 0x1a2340, sun: 0x8ea6d8, sunIntensity: 0.03, ambientIntensity: 0.06, fog: 0x141a2e },\n ];\n\n // Collect lamp lights and glowing bulb materials once.\n const lampLights: Array<{ light: PointLight; base: number }> = [];\n const lampBulbs: Array<{ material: MeshStandardMaterial; base: number }> = [];\n for (const entry of options.lamps ?? []) {\n const root = (entry as { isObject3D?: boolean }).isObject3D\n ? (entry as Object3D)\n : (entry as { object: Object3D }).object;\n root.traverse((child) => {\n if (child instanceof PointLight) {\n lampLights.push({ light: child, base: child.intensity || 6 });\n }\n const material = (child as Mesh).material as MeshStandardMaterial | undefined;\n if (material?.emissive && material.emissiveIntensity > 0.5) {\n lampBulbs.push({ material, base: material.emissiveIntensity });\n }\n });\n }\n\n const colorA = new Color();\n const colorB = new Color();\n let timeOfDay = options.timeOfDay ?? 0.5;\n let sunElevation = 0;\n\n const sample = (t: number): Keyframe => {\n let a = frames[0];\n let b = frames[frames.length - 1];\n for (let i = 0; i < frames.length - 1; i++) {\n if (t >= frames[i].t && t <= frames[i + 1].t) {\n a = frames[i];\n b = frames[i + 1];\n break;\n }\n }\n const f = b.t === a.t ? 0 : (t - a.t) / (b.t - a.t);\n const lerpHex = (ha: number, hb: number): number =>\n colorA.setHex(ha).lerp(colorB.setHex(hb), f).getHex();\n return {\n t,\n skyTop: lerpHex(a.skyTop, b.skyTop),\n skyBottom: lerpHex(a.skyBottom, b.skyBottom),\n sun: lerpHex(a.sun, b.sun),\n sunIntensity: a.sunIntensity + (b.sunIntensity - a.sunIntensity) * f,\n ambientIntensity: a.ambientIntensity + (b.ambientIntensity - a.ambientIntensity) * f,\n fog: lerpHex(a.fog, b.fog),\n };\n };\n\n const apply = (): void => {\n const t = timeOfDay;\n const frame = sample(t);\n const sunAngle = (t - 0.25) * Math.PI * 2;\n sunElevation = Math.sin(sunAngle);\n\n options.sky?.setColors(frame.skyTop, frame.skyBottom);\n if (options.rig) {\n const { sun, ambient, hemisphere } = options.rig;\n sun.color.setHex(frame.sun);\n sun.intensity = frame.sunIntensity;\n sun.position.set(Math.cos(sunAngle) * 40, Math.max(sunElevation, -0.2) * 45 + 6, 16);\n ambient.intensity = frame.ambientIntensity;\n // Hemisphere fill follows the ambient curve so nights actually darken.\n hemisphere.intensity = frame.ambientIntensity * 1.4;\n }\n if (options.scene?.fog && 'color' in options.scene.fog) {\n options.scene.fog.color.setHex(frame.fog);\n }\n // Lamps fade in as the sun dips below the horizon.\n const night = Math.min(1, Math.max(0, (0.06 - sunElevation) / 0.16));\n for (const { light, base } of lampLights) light.intensity = base * night;\n for (const { material, base } of lampBulbs) {\n material.emissiveIntensity = 0.15 * base + 0.85 * base * night;\n }\n };\n apply();\n\n return {\n get timeOfDay() {\n return timeOfDay;\n },\n set timeOfDay(t: number) {\n timeOfDay = ((t % 1) + 1) % 1;\n apply();\n },\n get sunElevation() {\n return sunElevation;\n },\n get isNight() {\n return sunElevation < 0;\n },\n update(dt) {\n timeOfDay = (timeOfDay + dt / dayLength) % 1;\n apply();\n },\n set(t) {\n timeOfDay = ((t % 1) + 1) % 1;\n apply();\n },\n };\n}\n","import { Mesh, type Material, type Object3D } from 'three';\n\n/** The slice of the shader object onBeforeCompile receives. */\ninterface PatchableShader {\n uniforms: Record<string, { value: unknown }>;\n vertexShader: string;\n}\n\nexport interface WindOptions {\n /** Sway amplitude in world units at the top of a prop. Default 0.06. */\n strength?: number;\n /** Oscillation speed. Default 1.2. */\n frequency?: number;\n /** Local height where sway begins (keeps trunks planted). Default 0.6. */\n anchorHeight?: number;\n}\n\nexport interface Wind {\n /** Advance the animation. Call from your frame loop. */\n update(dt: number): void;\n /** Materials that were patched (for debugging/cleanup). */\n materials: Material[];\n}\n\n/**\n * Vertex-shader wind sway for scattered vegetation: displacement grows\n * with local height (trunk bases stay planted), phase varies per\n * instance so a forest shimmers instead of marching in step. Works on\n * meshes and InstancedMeshes; patches each unique material once via\n * onBeforeCompile.\n *\n * ```ts\n * const wind = applyWind(forest.group, { strength: 0.08 });\n * game.onUpdate((t) => wind.update(t.delta));\n * ```\n */\nexport function applyWind(target: Object3D, options: WindOptions = {}): Wind {\n const strength = options.strength ?? 0.06;\n const frequency = options.frequency ?? 1.2;\n const anchor = options.anchorHeight ?? 0.6;\n const time = { value: 0 };\n const patched = new Set<Material>();\n\n target.traverse((child) => {\n if (!(child instanceof Mesh)) return;\n const materials = Array.isArray(child.material) ? child.material : [child.material];\n for (const material of materials) {\n if (patched.has(material)) continue;\n patched.add(material);\n material.onBeforeCompile = (shader: PatchableShader) => {\n shader.uniforms.uWindTime = time;\n shader.vertexShader = shader.vertexShader\n .replace(\n '#include <common>',\n `#include <common>\n uniform float uWindTime;`\n )\n .replace(\n '#include <begin_vertex>',\n `#include <begin_vertex>\n {\n float sway = max(position.y - ${anchor.toFixed(3)}, 0.0);\n float phase = 0.0;\n #ifdef USE_INSTANCING\n phase = instanceMatrix[3].x * 0.7 + instanceMatrix[3].z * 1.3;\n #endif\n float w = sin(uWindTime * ${(frequency * 2).toFixed(3)} + phase + position.y * 0.8);\n transformed.x += w * sway * ${strength.toFixed(4)} * 4.0;\n transformed.z += cos(uWindTime * ${(frequency * 1.4).toFixed(3)} + phase) * sway * ${strength.toFixed(4)} * 2.0;\n }`\n );\n };\n material.needsUpdate = true;\n }\n });\n\n return {\n update(dt) {\n time.value += dt;\n },\n materials: [...patched],\n };\n}\n","import {\n BufferAttribute,\n BufferGeometry,\n CatmullRomCurve3,\n Mesh,\n MeshStandardMaterial,\n Vector3,\n} from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\n\nexport interface PathOptions {\n /** Ribbon width. Default 1.8. */\n width?: number;\n /** Ground height lookup; a number means flat ground. Default 0. */\n surface?: number | ((x: number, z: number) => number);\n /** Samples per world unit of path length. Default 1. */\n samplesPerUnit?: number;\n /** Close the path into a loop. Default false. */\n loop?: boolean;\n /** Extra clearance added to scatter keep-out circles. Default 0.6. */\n keepOutMargin?: number;\n palette?: Palette;\n}\n\nexport interface WorldPath {\n mesh: Mesh;\n /** Smoothed centerline draped on the surface — feed straight into a\n * GAMA `Path` for patrols, or use as camera dolly points. */\n route: Vector3[];\n /** Keep-out circles for `scatter()` so nothing grows on the road. */\n keepOut: Array<{ center: { x: number; z: number }; radius: number }>;\n /** Is (x, z) on the path surface? (e.g. to exclude grass) */\n contains(x: number, z: number): boolean;\n loop: boolean;\n}\n\n/**\n * A dirt path: a Catmull-Rom-smoothed ribbon draped over the surface.\n * One authored polyline feeds three things at once — the visual ribbon,\n * scatter keep-out, and a patrol route for agents. That's the SCENA\n * handshake applied to level design.\n *\n * ```ts\n * const road = createPath([a, b, c], { surface: terrain.heightAt, loop: true });\n * scene.add(road.mesh);\n * scatter({ ..., keepOut: road.keepOut });\n * agent.addBehavior(new FollowPath(new Path(road.route, road.loop), 1.5));\n * ```\n */\nexport function createPath(\n points: Array<Vector3 | { x: number; z: number }>,\n options: PathOptions = {}\n): WorldPath {\n const width = options.width ?? 1.8;\n const surface = options.surface ?? 0;\n const heightAt =\n typeof surface === 'number' ? () => surface : (x: number, z: number) => surface(x, z);\n const loop = options.loop ?? false;\n const palette = options.palette ?? DEFAULT_PALETTE;\n\n const controls = points.map((p) => new Vector3(p.x, 0, 'z' in p ? p.z : 0));\n const curve = new CatmullRomCurve3(controls, loop, 'centripetal');\n const length = curve.getLength();\n const samples = Math.max(8, Math.ceil(length * (options.samplesPerUnit ?? 1)));\n\n const route: Vector3[] = [];\n for (let i = 0; i <= samples; i++) {\n if (loop && i === samples) break; // avoid duplicate closing point\n const p = curve.getPoint(i / samples);\n route.push(new Vector3(p.x, heightAt(p.x, p.z), p.z));\n }\n\n // Ribbon strip: left/right edge vertices per sample.\n const edgeCount = loop ? route.length + 1 : route.length;\n const positions = new Float32Array(edgeCount * 2 * 3);\n const direction = new Vector3();\n const perp = new Vector3();\n for (let i = 0; i < edgeCount; i++) {\n const current = route[i % route.length];\n const previous = route[(i - 1 + route.length) % route.length];\n const next = route[(i + 1) % route.length];\n if (!loop && i === 0) direction.subVectors(next, current);\n else if (!loop && i === edgeCount - 1) direction.subVectors(current, previous);\n else direction.subVectors(next, previous);\n perp.set(-direction.z, 0, direction.x).normalize().multiplyScalar(width / 2);\n const left = i * 6;\n positions[left] = current.x - perp.x;\n positions[left + 1] = heightAt(current.x - perp.x, current.z - perp.z) + 0.05;\n positions[left + 2] = current.z - perp.z;\n positions[left + 3] = current.x + perp.x;\n positions[left + 4] = heightAt(current.x + perp.x, current.z + perp.z) + 0.05;\n positions[left + 5] = current.z + perp.z;\n }\n const indices: number[] = [];\n for (let i = 0; i < edgeCount - 1; i++) {\n const a = i * 2;\n indices.push(a, a + 1, a + 2, a + 1, a + 3, a + 2);\n }\n const geometry = new BufferGeometry();\n geometry.setAttribute('position', new BufferAttribute(positions, 3));\n geometry.setIndex(indices);\n geometry.computeVertexNormals();\n\n const mesh = new Mesh(\n geometry,\n new MeshStandardMaterial({\n color: palette.path,\n flatShading: true,\n polygonOffset: true,\n polygonOffsetFactor: -1,\n })\n );\n mesh.name = 'path';\n\n const keepOutMargin = options.keepOutMargin ?? 0.6;\n const keepOut = route\n .filter((_p, i) => i % 2 === 0 || i === route.length - 1) // never drop the endpoint\n .map((p) => ({ center: { x: p.x, z: p.z }, radius: width / 2 + keepOutMargin }));\n\n const half = width / 2;\n const contains = (x: number, z: number): boolean => {\n const count = loop ? route.length : route.length - 1;\n for (let i = 0; i < count; i++) {\n const a = route[i];\n const b = route[(i + 1) % route.length];\n const abx = b.x - a.x;\n const abz = b.z - a.z;\n const lengthSq = abx * abx + abz * abz || 1e-9;\n const t = Math.max(0, Math.min(1, ((x - a.x) * abx + (z - a.z) * abz) / lengthSq));\n const dx = x - (a.x + abx * t);\n const dz = z - (a.z + abz * t);\n if (dx * dx + dz * dz <= half * half) return true;\n }\n return false;\n };\n\n return { mesh, route, keepOut, contains, loop };\n}\n","import { Group } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport { collectObstacles, type Obstacle, type Prop } from '../core/types';\nimport { createHouse, createRuin, createTower, createWell } from '../props/building';\nimport { createCrate } from '../props/crate';\nimport { createLamp } from '../props/lamp';\n\nexport interface VillageOptions {\n seed?: number;\n /** Village center in the XZ plane. Default origin. */\n center?: { x: number; z: number };\n /** Ring radius the houses settle on. Default 12. */\n radius?: number;\n /** House count. Default 5. */\n houses?: number;\n /** Ground height lookup; a number means flat ground. Default 0. */\n surface?: number | ((x: number, z: number) => number);\n /** Veto candidate spots (e.g. water, roads). Return false to reject. */\n mask?: (x: number, z: number, y: number) => boolean;\n /** Add real PointLights to this many street lamps. Default 3. */\n lampLights?: number;\n /** Add a watchtower at the edge. Default true. */\n tower?: boolean;\n /** Add a ruin outside the ring. Default true. */\n ruin?: boolean;\n palette?: Palette;\n}\n\nexport interface Village {\n group: Group;\n /** Every placed prop (houses, well, lamps, crates, tower, ruin). */\n props: Prop[];\n /** World-space steering obstacles — feed GAMA's ObstacleAvoidance. */\n obstacles: Obstacle[];\n /**\n * Props with something to ignite at night (street lamps AND house\n * windows). Pass straight to `createDayCycle({ lamps })`.\n */\n lamps: Prop[];\n /** One clearing circle covering the village — feed `scatter`'s keepOut. */\n keepOut: Array<{ center: { x: number; z: number }; radius: number }>;\n center: { x: number; z: number };\n}\n\n/**\n * A seeded hamlet: a well at the center, houses ringed around it facing\n * inward, street lamps between them, crates by the doors, a watchtower on\n * the edge and a ruin beyond. Everything is placed on the given surface\n * (steep or masked spots are rejected and re-rolled), and the result\n * carries the full gameplay handshake: `obstacles` for steering,\n * `keepOut` for scatter, and `lamps` for the day-night cycle — windows\n * and lamps ignite together at dusk.\n *\n * ```ts\n * const village = createVillage({ seed: 5, radius: 10, surface: terrain.heightAt, palette });\n * scene.add(village.group);\n * const cycle = createDayCycle({ sky, rig, scene, lamps: village.lamps, palette });\n * const forest = scatter({ ..., keepOut: village.keepOut });\n * ```\n */\nexport function createVillage(options: VillageOptions = {}): Village {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const center = options.center ?? { x: 0, z: 0 };\n const radius = options.radius ?? 12;\n const houseCount = options.houses ?? 5;\n const surface = options.surface ?? 0;\n const heightAt =\n typeof surface === 'number' ? () => surface : (x: number, z: number) => surface(x, z);\n\n const group = new Group();\n group.name = 'village';\n const props: Prop[] = [];\n const lamps: Prop[] = [];\n\n const place = (prop: Prop, x: number, z: number, rotY: number): Prop => {\n prop.object.position.set(x, heightAt(x, z), z);\n prop.object.rotation.y = rotY;\n group.add(prop.object);\n props.push(prop);\n return prop;\n };\n\n /**\n * Find a buildable spot near (angle, distance): reasonably level across\n * the footprint and not vetoed by the mask. Re-rolls up to 10 times,\n * then falls back to the last candidate so layout never dead-ends.\n */\n const findSpot = (\n angle: number,\n distance: number,\n footprint: number\n ): { x: number; z: number } => {\n let x = center.x;\n let z = center.z;\n for (let attempt = 0; attempt < 10; attempt++) {\n const a = angle + rng.range(-0.25, 0.25) * (attempt > 0 ? 1 : 0.3);\n const d = distance * rng.range(attempt > 0 ? 0.8 : 0.95, 1.1);\n x = center.x + Math.cos(a) * d;\n z = center.z + Math.sin(a) * d;\n const y = heightAt(x, z);\n if (options.mask && !options.mask(x, z, y)) continue;\n let min = y;\n let max = y;\n for (const [dx, dz] of [[footprint, 0], [-footprint, 0], [0, footprint], [0, -footprint]]) {\n const h = heightAt(x + dx, z + dz);\n min = Math.min(min, h);\n max = Math.max(max, h);\n }\n if (max - min <= Math.max(0.9, footprint * 0.35)) break;\n }\n return { x, z };\n };\n\n // The well anchors the plaza.\n const well = createWell({ seed: rng.int(1, 1e9), palette });\n place(well, center.x, center.z, rng.range(0, Math.PI * 2));\n\n // Houses on the ring, facing the well.\n let lightBudget = options.lampLights ?? 3;\n for (let i = 0; i < houseCount; i++) {\n const angle = (i / houseCount) * Math.PI * 2 + rng.range(-0.15, 0.15);\n const house = createHouse({ seed: rng.int(1, 1e9), palette });\n const spot = findSpot(angle, radius * rng.range(0.7, 0.95), house.obstacleRadius);\n const facing = Math.atan2(center.x - spot.x, center.z - spot.z);\n place(house, spot.x, spot.z, facing);\n lamps.push(house);\n\n // A crate by most doors, a lamp partway toward the plaza for some.\n if (rng.next() < 0.7) {\n const crateAngle = angle + rng.range(-0.5, 0.5);\n const crateDistance = Math.hypot(spot.x - center.x, spot.z - center.z) - house.obstacleRadius - 0.7;\n place(\n createCrate({ seed: rng.int(1, 1e9), size: rng.range(0.7, 1), palette }),\n center.x + Math.cos(crateAngle) * crateDistance,\n center.z + Math.sin(crateAngle) * crateDistance,\n rng.range(0, Math.PI)\n );\n }\n if (i % 2 === 0) {\n const lampDistance = Math.hypot(spot.x - center.x, spot.z - center.z) * 0.55;\n const lamp = createLamp({ seed: rng.int(1, 1e9), light: lightBudget > 0, palette });\n lightBudget--;\n place(lamp, center.x + Math.cos(angle) * lampDistance, center.z + Math.sin(angle) * lampDistance, 0);\n lamps.push(lamp);\n }\n }\n\n if (options.tower ?? true) {\n const angle = rng.range(0, Math.PI * 2);\n const tower = createTower({ seed: rng.int(1, 1e9), palette });\n const spot = findSpot(angle, radius * 1.05, tower.obstacleRadius);\n place(tower, spot.x, spot.z, rng.range(0, Math.PI * 2));\n }\n if (options.ruin ?? true) {\n const angle = rng.range(0, Math.PI * 2);\n const ruin = createRuin({ seed: rng.int(1, 1e9), palette });\n const spot = findSpot(angle, radius * 1.35, ruin.obstacleRadius);\n place(ruin, spot.x, spot.z, rng.range(0, Math.PI * 2));\n }\n\n return {\n group,\n props,\n obstacles: collectObstacles(props),\n lamps,\n keepOut: [{ center: { ...center }, radius: radius * 1.5 }],\n center,\n };\n}\n","import {\n DynamicDrawUsage,\n Group,\n InstancedMesh,\n Matrix4,\n Mesh,\n Quaternion,\n Vector3,\n} from 'three';\nimport { Rng, valueNoise2 } from '../core/random';\nimport type { Obstacle, Prop } from '../core/types';\n\nexport interface ScatterItem {\n /** Prop factory, called once per visual variant with a seeded Rng. */\n create(rng: Rng): Prop;\n /** Relative frequency among items. Default 1. */\n weight?: number;\n /** Distinct variants generated per item (visual variety). Default 4. */\n variants?: number;\n /** Per-instance uniform scale range. Default [0.8, 1.25]. */\n scale?: [number, number];\n}\n\nexport interface ScatterOptions {\n seed?: number;\n items: ScatterItem[];\n /** Placement region in the XZ plane. */\n area: { min: { x: number; z: number }; max: { x: number; z: number } };\n /** Ground height lookup; a number means flat ground. Default 0. */\n surface?: number | ((x: number, z: number) => number);\n /** Expected instances per square unit (thinned by density noise). */\n density?: number;\n /** Or an exact target count (before masks/spacing rejections). */\n count?: number;\n /** Veto function: return false to reject a candidate point. */\n mask?: (x: number, z: number, y: number) => boolean;\n /** Minimum distance between any two placements. Default 1.2. */\n minSpacing?: number;\n /** World-space circles to keep clear (paths, spawns, buildings). */\n keepOut?: Obstacle[] | { center: { x: number; z: number }; radius: number }[];\n /** Density-noise feature size in world units. Default 18. */\n clumpScale?: number;\n}\n\nexport interface Placement {\n position: Vector3;\n rotationY: number;\n scale: number;\n itemIndex: number;\n}\n\nexport interface ScatterResult {\n /** One InstancedMesh per template part — a handful of draw calls total. */\n group: Group;\n placements: Placement[];\n /** World-space steering obstacles for everything with a footprint. */\n obstacles: Obstacle[];\n count: number;\n}\n\n/**\n * Populate an area with seeded, instanced props: \"empty plane → forest\"\n * in one call. Placement uses density noise for natural clumping, a\n * spatial hash for minimum spacing, and masks/keep-out circles for\n * exclusion. Rendering merges every placement into InstancedMeshes — a\n * few draw calls for thousands of props.\n *\n * ```ts\n * const forest = scatter({\n * seed: 7,\n * area: { min: { x: -40, z: -40 }, max: { x: 40, z: 40 } },\n * surface: terrain.heightAt,\n * density: 0.04,\n * items: [\n * { create: (rng) => createTree({ seed: rng.int(1, 1e9) }), weight: 3 },\n * { create: (rng) => createRock({ seed: rng.int(1, 1e9) }) },\n * ],\n * mask: (x, z, y) => y > 0.5 && y < 5, // between shore and peaks\n * keepOut: [{ center: village, radius: 12 }],\n * });\n * scene.add(forest.group);\n * agent.addBehavior(new ObstacleAvoidance(() => forest.obstacles));\n * ```\n */\nexport function scatter(options: ScatterOptions): ScatterResult {\n const seed = options.seed ?? 1;\n const rng = new Rng(seed);\n const { area } = options;\n const width = area.max.x - area.min.x;\n const depth = area.max.z - area.min.z;\n const surface = options.surface ?? 0;\n const heightAt =\n typeof surface === 'number' ? () => surface : (x: number, z: number) => surface(x, z);\n const minSpacing = options.minSpacing ?? 1.2;\n const clumpScale = options.clumpScale ?? 18;\n const attempts = options.count ?? Math.round(width * depth * (options.density ?? 0.03));\n\n const keepOut = (options.keepOut ?? []).map((k) => ({\n x: k.center.x,\n z: 'z' in k.center ? k.center.z : (k.center as { z: number }).z,\n radius: k.radius,\n }));\n\n // Weighted item choice.\n const weights = options.items.map((i) => i.weight ?? 1);\n const totalWeight = weights.reduce((a, b) => a + b, 0);\n const pickItem = (): number => {\n let r = rng.next() * totalWeight;\n for (let i = 0; i < weights.length; i++) {\n r -= weights[i];\n if (r <= 0) return i;\n }\n return weights.length - 1;\n };\n\n // Spatial hash for min-spacing rejection.\n const cell = Math.max(minSpacing, 0.001);\n const occupied = new Map<string, Array<{ x: number; z: number }>>();\n const tooClose = (x: number, z: number): boolean => {\n const cx = Math.floor(x / cell);\n const cz = Math.floor(z / cell);\n for (let dx = -1; dx <= 1; dx++) {\n for (let dz = -1; dz <= 1; dz++) {\n const bucket = occupied.get(`${cx + dx},${cz + dz}`);\n if (!bucket) continue;\n for (const p of bucket) {\n if ((p.x - x) ** 2 + (p.z - z) ** 2 < minSpacing * minSpacing) return true;\n }\n }\n }\n return false;\n };\n\n const placements: Placement[] = [];\n for (let i = 0; i < attempts; i++) {\n const x = rng.range(area.min.x, area.max.x);\n const z = rng.range(area.min.z, area.max.z);\n // Density noise: clumps and clearings instead of uniform confetti.\n if (valueNoise2(x / clumpScale, z / clumpScale, seed + 77) < rng.range(0.15, 0.55)) continue;\n if (keepOut.some((k) => (k.x - x) ** 2 + (k.z - z) ** 2 < k.radius * k.radius)) continue;\n if (tooClose(x, z)) continue;\n const y = heightAt(x, z);\n if (options.mask && !options.mask(x, z, y)) continue;\n\n const itemIndex = pickItem();\n const [minScale, maxScale] = options.items[itemIndex].scale ?? [0.8, 1.25];\n placements.push({\n position: new Vector3(x, y, z),\n rotationY: rng.range(0, Math.PI * 2),\n scale: rng.range(minScale, maxScale),\n itemIndex,\n });\n const key = `${Math.floor(x / cell)},${Math.floor(z / cell)}`;\n let bucket = occupied.get(key);\n if (!bucket) occupied.set(key, (bucket = []));\n bucket.push({ x, z });\n }\n\n // Build variants per item, bucket placements per variant, then emit one\n // InstancedMesh per (variant, mesh part).\n const group = new Group();\n group.name = 'scatter';\n const obstacles: Obstacle[] = [];\n const placementMatrix = new Matrix4();\n const composed = new Matrix4();\n const quaternion = new Quaternion();\n const up = new Vector3(0, 1, 0);\n const scaleVector = new Vector3();\n\n options.items.forEach((item, itemIndex) => {\n const variantCount = item.variants ?? 4;\n const variants: Prop[] = [];\n for (let v = 0; v < variantCount; v++) variants.push(item.create(rng.fork()));\n\n const byVariant: Placement[][] = variants.map(() => []);\n for (const placement of placements) {\n if (placement.itemIndex !== itemIndex) continue;\n // Deterministic variant choice from position.\n const v = Math.abs(Math.floor(placement.position.x * 31 + placement.position.z * 17)) % variantCount;\n byVariant[v].push(placement);\n }\n\n variants.forEach((variant, v) => {\n const list = byVariant[v];\n if (list.length === 0) return;\n variant.object.updateMatrixWorld(true);\n variant.object.traverse((child) => {\n if (!(child instanceof Mesh)) return;\n const instanced = new InstancedMesh(child.geometry, child.material, list.length);\n instanced.instanceMatrix.setUsage(DynamicDrawUsage);\n list.forEach((placement, index) => {\n quaternion.setFromAxisAngle(up, placement.rotationY);\n scaleVector.setScalar(placement.scale);\n placementMatrix.compose(placement.position, quaternion, scaleVector);\n composed.multiplyMatrices(placementMatrix, child.matrixWorld);\n instanced.setMatrixAt(index, composed);\n });\n instanced.instanceMatrix.needsUpdate = true;\n group.add(instanced);\n });\n if (variant.obstacleRadius > 0) {\n for (const placement of list) {\n obstacles.push({\n center: placement.position.clone(),\n radius: variant.obstacleRadius * placement.scale,\n });\n }\n }\n });\n });\n\n return { group, placements, obstacles, count: placements.length };\n}\n"],"mappings":"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","names":["Group","IcosahedronGeometry","Mesh","MeshStandardMaterial","IcosahedronGeometry","Mesh","MeshStandardMaterial","Group","Group","Mesh","MeshStandardMaterial","Group","MeshStandardMaterial","Mesh","BoxGeometry","CylinderGeometry","Group","Mesh","MeshStandardMaterial","Group","MeshStandardMaterial","Mesh","CylinderGeometry","BoxGeometry","BoxGeometry","CylinderGeometry","Group","Mesh","MeshStandardMaterial","Group","MeshStandardMaterial","Mesh","CylinderGeometry","BoxGeometry","ConeGeometry","Group","IcosahedronGeometry","Mesh","MeshStandardMaterial","Group","MeshStandardMaterial","Mesh","ConeGeometry","IcosahedronGeometry","BoxGeometry","BufferAttribute","CylinderGeometry","Group","Mesh","MeshStandardMaterial","BufferAttribute","Group","MeshStandardMaterial","Mesh","BoxGeometry","CylinderGeometry","BufferAttribute","Mesh","MeshStandardMaterial","BufferAttribute","Mesh","MeshStandardMaterial","Color","Mesh","SphereGeometry","Color","Mesh","SphereGeometry","Group","Group","Mesh","MeshStandardMaterial","PlaneGeometry","PlaneGeometry","Mesh","MeshStandardMaterial","Color","PointLight","PointLight","Color","Mesh","BufferAttribute","BufferGeometry","Mesh","MeshStandardMaterial","Vector3","Vector3","BufferGeometry","BufferAttribute","Mesh","MeshStandardMaterial","Group","Group","Group","Mesh","Vector3","maxScale","Vector3","Group","Mesh"]}
1
+ {"version":3,"sources":["../src/core/random.ts","../src/core/palette.ts","../src/core/types.ts","../src/props/tree.ts","../src/props/rock.ts","../src/props/crate.ts","../src/props/fence.ts","../src/props/lamp.ts","../src/props/grass.ts","../src/props/building.ts","../src/environment/terrain.ts","../src/environment/sky.ts","../src/environment/lighting.ts","../src/environment/water.ts","../src/environment/dayCycle.ts","../src/environment/wind.ts","../src/environment/path.ts","../src/generators/village.ts","../src/kits/kit.ts","../src/scene/manifest.ts","../src/scatter/scatter.ts","../src/scene/markers.ts"],"sourcesContent":["/**\n * Deterministic seeded randomness — the backbone of SCENA. Same seed,\n * same tree; forests are reproducible, diffable and network-syncable.\n */\nexport class Rng {\n private state: number;\n\n constructor(seed = 1) {\n this.state = seed >>> 0 || 1;\n }\n\n /** Next float in [0, 1) (mulberry32). */\n next(): number {\n this.state = (this.state + 0x6d2b79f5) >>> 0;\n let t = this.state;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n }\n\n /** Float in [min, max). */\n range(min: number, max: number): number {\n return min + this.next() * (max - min);\n }\n\n /** Integer in [min, max] inclusive. */\n int(min: number, max: number): number {\n return min + Math.floor(this.next() * (max - min + 1));\n }\n\n /** Random element of a non-empty array. */\n pick<T>(items: readonly T[]): T {\n return items[Math.floor(this.next() * items.length)];\n }\n\n /** value ± spread (uniform). */\n jitter(value: number, spread: number): number {\n return value + (this.next() * 2 - 1) * spread;\n }\n\n /** A new independent Rng derived from this one. */\n fork(): Rng {\n return new Rng(Math.floor(this.next() * 0xffffffff) || 1);\n }\n}\n\n/** Integer-lattice hash to [0, 1) — the base of the value noise. */\nexport function hash2(ix: number, iz: number, seed: number): number {\n let h = (ix * 374761393 + iz * 668265263 + seed * 2246822519) >>> 0;\n h = Math.imul(h ^ (h >>> 13), 1274126177) >>> 0;\n return ((h ^ (h >>> 16)) >>> 0) / 4294967296;\n}\n\nconst smooth = (t: number): number => t * t * (3 - 2 * t);\n\n/** 2D value noise in [0, 1). Continuous; used by terrain and scatter density. */\nexport function valueNoise2(x: number, z: number, seed: number): number {\n const ix = Math.floor(x);\n const iz = Math.floor(z);\n const fx = smooth(x - ix);\n const fz = smooth(z - iz);\n const a = hash2(ix, iz, seed);\n const b = hash2(ix + 1, iz, seed);\n const c = hash2(ix, iz + 1, seed);\n const d = hash2(ix + 1, iz + 1, seed);\n return a + (b - a) * fx + (c - a) * fz + (a - b - c + d) * fx * fz;\n}\n\n/** Fractal (octaved) value noise in [0, 1). */\nexport function fractalNoise2(\n x: number,\n z: number,\n seed: number,\n octaves = 4,\n lacunarity = 2,\n gain = 0.5\n): number {\n let amplitude = 1;\n let frequency = 1;\n let sum = 0;\n let total = 0;\n for (let i = 0; i < octaves; i++) {\n sum += valueNoise2(x * frequency, z * frequency, seed + i * 101) * amplitude;\n total += amplitude;\n amplitude *= gain;\n frequency *= lacunarity;\n }\n return sum / total;\n}\n","/**\n * Theme palettes: one coherent set of colors shared by every generator,\n * so procedural props look like a matched set rather than a junk drawer.\n * Pass `palette` to any generator to restyle it; whole scenes retheme by\n * building with a different palette.\n */\nexport interface Palette {\n foliage: number[];\n trunk: number;\n rock: number[];\n wood: number;\n woodDark: number;\n metal: number;\n lampGlow: number;\n grassLow: number;\n grassHigh: number;\n cliff: number;\n peak: number;\n skyTop: number;\n skyBottom: number;\n fog: number;\n water: number;\n sand: number;\n path: number;\n /** Building plaster/wall color. */\n wall: number;\n /** Building roof color. */\n roof: number;\n}\n\nexport const PALETTES: Record<'meadow' | 'autumn' | 'dusk' | 'winter', Palette> = {\n meadow: {\n foliage: [0x2f9e57, 0x37b26a, 0x2a8f4f, 0x45b878],\n trunk: 0x6b4a33,\n rock: [0x8a8f98, 0x767c86, 0x9aa0a8],\n wood: 0x8a6642,\n woodDark: 0x6b4a33,\n metal: 0x3d4451,\n lampGlow: 0xffd889,\n grassLow: 0x3f9d5a,\n grassHigh: 0x6fae66,\n cliff: 0x7d7a72,\n peak: 0xe8ecef,\n skyTop: 0x3d70b8,\n skyBottom: 0xbfd9e8,\n fog: 0xb8cfdd,\n water: 0x3f7fae,\n sand: 0xc9b98a,\n path: 0x9a815f,\n wall: 0xd9ccb0,\n roof: 0xa8563e,\n },\n autumn: {\n foliage: [0xc9752f, 0xd98e3a, 0xb35c2a, 0xe0a545],\n trunk: 0x5d4030,\n rock: [0x8d8578, 0x776f63, 0x9c948a],\n wood: 0x7d5a3a,\n woodDark: 0x5d4030,\n metal: 0x463f3a,\n lampGlow: 0xffc571,\n grassLow: 0x9d8a3f,\n grassHigh: 0xb59b4a,\n cliff: 0x82746a,\n peak: 0xe3ded4,\n skyTop: 0x8e6ca8,\n skyBottom: 0xe8c9a8,\n fog: 0xd9c1a8,\n water: 0x4a7a92,\n sand: 0xcbb083,\n path: 0x8d7454,\n wall: 0xccb894,\n roof: 0x8a4a30,\n },\n dusk: {\n foliage: [0x1f5e46, 0x24684f, 0x1a5240, 0x2d7458],\n trunk: 0x413147,\n rock: [0x565672, 0x484861, 0x646484],\n wood: 0x5d4a63,\n woodDark: 0x413147,\n metal: 0x2b2b3d,\n lampGlow: 0xffb35c,\n grassLow: 0x2d6b52,\n grassHigh: 0x3d7a5e,\n cliff: 0x52516b,\n peak: 0xb8b8d9,\n skyTop: 0x1d2145,\n skyBottom: 0xc96a4a,\n fog: 0x6a5a7a,\n water: 0x2d4a68,\n sand: 0x8a7a6a,\n path: 0x6a5a52,\n wall: 0x8d8299,\n roof: 0x453558,\n },\n winter: {\n foliage: [0x2e5c48, 0x38695a, 0x527a68, 0x87a596],\n trunk: 0x4a3a33,\n rock: [0x9aa4ad, 0x848e98, 0xb0b8c0],\n wood: 0x776049,\n woodDark: 0x54453a,\n metal: 0x39404d,\n lampGlow: 0xffd889,\n grassLow: 0xcfd9de,\n grassHigh: 0xe4ebee,\n cliff: 0x76797d,\n peak: 0xf4f7fa,\n skyTop: 0x5a7ba6,\n skyBottom: 0xd8e4ec,\n fog: 0xccd8e0,\n water: 0x4a7086,\n sand: 0xb8c2c6,\n path: 0x8b8378,\n wall: 0xd2c9bb,\n roof: 0x6b4638,\n },\n};\n\nexport const DEFAULT_PALETTE: Palette = PALETTES.meadow;\n","import { Vector3, type Group, type Object3D } from 'three';\n\n/**\n * A steering obstacle in world space — structurally identical to GAMA's\n * `Obstacle`, so SCENA props plug straight into `ObstacleAvoidance`\n * without either library importing the other.\n */\nexport interface Obstacle {\n center: Vector3;\n radius: number;\n}\n\n/** What a prop generator returns: the visual plus gameplay metadata. */\nexport interface Prop {\n object: Group;\n /**\n * Footprint radius for steering/placement, in the prop's local space\n * (centered at its origin). 0 means walk-through (e.g. grass).\n */\n obstacleRadius: number;\n}\n\n/** Collect world-space obstacles from placed props (call after positioning). */\nexport function collectObstacles(props: Iterable<Prop>): Obstacle[] {\n const obstacles: Obstacle[] = [];\n for (const prop of props) {\n if (prop.obstacleRadius <= 0) continue;\n prop.object.updateWorldMatrix(true, false);\n obstacles.push({\n center: prop.object.getWorldPosition(new Vector3()),\n radius: prop.obstacleRadius * maxScale(prop.object),\n });\n }\n return obstacles;\n}\n\nfunction maxScale(object: Object3D): number {\n return Math.max(object.scale.x, object.scale.z);\n}\n","import {\n ConeGeometry,\n CylinderGeometry,\n Group,\n IcosahedronGeometry,\n Mesh,\n MeshStandardMaterial,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface TreeOptions {\n seed?: number;\n /** Overall height in world units. Default ~3.5–5 by seed. */\n height?: number;\n style?: 'pine' | 'oak';\n palette?: Palette;\n}\n\n/**\n * A seeded low-poly tree. `pine` stacks cones; `oak` clusters foliage\n * blobs on a forked trunk. Same seed → identical tree, forever.\n */\nexport function createTree(options: TreeOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const style = options.style ?? (rng.next() < 0.6 ? 'pine' : 'oak');\n const height = options.height ?? rng.range(3.2, 5.2);\n const group = new Group();\n group.name = `tree-${style}`;\n\n const trunkMaterial = new MeshStandardMaterial({ color: palette.trunk, flatShading: true });\n const foliageMaterial = new MeshStandardMaterial({\n color: rng.pick(palette.foliage),\n flatShading: true,\n });\n\n if (style === 'pine') {\n const trunkHeight = height * 0.25;\n const trunk = new Mesh(new CylinderGeometry(0.09, 0.14, trunkHeight, 6), trunkMaterial);\n trunk.position.y = trunkHeight / 2;\n group.add(trunk);\n\n const tiers = rng.int(3, 4);\n let y = trunkHeight;\n let radius = height * rng.range(0.24, 0.3);\n const tierHeight = (height - trunkHeight) / tiers + 0.15;\n for (let i = 0; i < tiers; i++) {\n const cone = new Mesh(new ConeGeometry(radius, tierHeight * 1.35, 7), foliageMaterial);\n cone.position.y = y + tierHeight * 0.55;\n cone.rotation.y = rng.range(0, Math.PI);\n group.add(cone);\n y += tierHeight * 0.8;\n radius *= 0.72;\n }\n } else {\n const trunkHeight = height * 0.45;\n const trunk = new Mesh(new CylinderGeometry(0.12, 0.2, trunkHeight, 6), trunkMaterial);\n trunk.position.y = trunkHeight / 2;\n trunk.rotation.z = rng.range(-0.08, 0.08);\n group.add(trunk);\n\n const blobs = rng.int(2, 4);\n for (let i = 0; i < blobs; i++) {\n const radius = height * rng.range(0.18, 0.28);\n const blob = new Mesh(new IcosahedronGeometry(radius, 0), foliageMaterial);\n blob.position.set(\n rng.jitter(0, height * 0.16),\n trunkHeight + radius * rng.range(0.5, 0.9) + i * radius * 0.35,\n rng.jitter(0, height * 0.16)\n );\n blob.rotation.set(rng.range(0, Math.PI), rng.range(0, Math.PI), 0);\n group.add(blob);\n }\n }\n\n return { object: group, obstacleRadius: style === 'pine' ? 0.5 : 0.6 };\n}\n","import {\n BufferAttribute,\n Group,\n IcosahedronGeometry,\n Mesh,\n MeshStandardMaterial,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface RockOptions {\n seed?: number;\n /** Approximate radius. Default ~0.4–1.1 by seed. */\n size?: number;\n palette?: Palette;\n}\n\n/**\n * A seeded low-poly boulder: an icosahedron with jittered vertices and a\n * flattened underside so it sits on the ground.\n */\nexport function createRock(options: RockOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const size = options.size ?? rng.range(0.4, 1.1);\n\n const geometry = new IcosahedronGeometry(size, 0);\n const positions = geometry.getAttribute('position') as BufferAttribute;\n // Jitter welded-by-value: identical vertex values get identical offsets,\n // so faces stay connected.\n const seen = new Map<string, [number, number, number]>();\n for (let i = 0; i < positions.count; i++) {\n const key = `${positions.getX(i).toFixed(4)},${positions.getY(i).toFixed(4)},${positions.getZ(i).toFixed(4)}`;\n let offset = seen.get(key);\n if (!offset) {\n offset = [rng.jitter(0, size * 0.22), rng.jitter(0, size * 0.16), rng.jitter(0, size * 0.22)];\n seen.set(key, offset);\n }\n positions.setXYZ(\n i,\n positions.getX(i) + offset[0],\n Math.max(positions.getY(i) + offset[1], -size * 0.15), // flatten the bottom\n positions.getZ(i) + offset[2]\n );\n }\n geometry.computeVertexNormals();\n\n const rock = new Mesh(\n geometry,\n new MeshStandardMaterial({ color: rng.pick(palette.rock), flatShading: true })\n );\n rock.position.y = size * 0.15;\n rock.scale.y = rng.range(0.6, 0.9);\n\n const group = new Group();\n group.name = 'rock';\n group.add(rock);\n return { object: group, obstacleRadius: size * 1.05 };\n}\n","import { BoxGeometry, Group, Mesh, MeshStandardMaterial } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface CrateOptions {\n seed?: number;\n size?: number;\n /** 0–1 color wear. Default 0.3. */\n weathering?: number;\n palette?: Palette;\n}\n\n/** A wooden crate: panel box with darker edge framing, seeded wear tint. */\nexport function createCrate(options: CrateOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const size = options.size ?? 1;\n const wear = options.weathering ?? 0.3;\n\n const group = new Group();\n group.name = 'crate';\n\n const panelMaterial = new MeshStandardMaterial({ color: palette.wood, flatShading: true });\n panelMaterial.color.offsetHSL(0, 0, -rng.range(0, wear * 0.18));\n const frameMaterial = new MeshStandardMaterial({ color: palette.woodDark, flatShading: true });\n\n const body = new Mesh(new BoxGeometry(size * 0.92, size * 0.92, size * 0.92), panelMaterial);\n body.position.y = size / 2;\n group.add(body);\n\n const beam = size * 0.12;\n const long = size * 1.0;\n for (const y of [beam / 2, size - beam / 2]) {\n for (const [rx, rz, w, d] of [\n [0, size / 2 - beam / 2, long, beam],\n [0, -(size / 2 - beam / 2), long, beam],\n [size / 2 - beam / 2, 0, beam, long],\n [-(size / 2 - beam / 2), 0, beam, long],\n ] as const) {\n const rail = new Mesh(new BoxGeometry(w, beam, d), frameMaterial);\n rail.position.set(rx, y, rz);\n group.add(rail);\n }\n }\n for (const x of [-1, 1]) {\n for (const z of [-1, 1]) {\n const post = new Mesh(new BoxGeometry(beam, size, beam), frameMaterial);\n post.position.set(x * (size / 2 - beam / 2), size / 2, z * (size / 2 - beam / 2));\n group.add(post);\n }\n }\n group.rotation.y = rng.range(0, Math.PI / 2);\n\n return { object: group, obstacleRadius: size * 0.75 };\n}\n","import { BoxGeometry, CylinderGeometry, Group, Mesh, MeshStandardMaterial } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface FenceOptions {\n seed?: number;\n /** Run length along local +x. Default 6. */\n length?: number;\n postSpacing?: number;\n height?: number;\n palette?: Palette;\n}\n\n/**\n * A rustic fence run along local +x, centered at the origin: posts with\n * two slightly-crooked rails. Chain several and rotate to enclose areas.\n * The obstacle radius covers the whole run (rough but steering-safe);\n * for tight navigation, bake a navmesh — the geometry is authoritative.\n */\nexport function createFence(options: FenceOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const length = options.length ?? 6;\n const spacing = options.postSpacing ?? 1.5;\n const height = options.height ?? 1.1;\n\n const group = new Group();\n group.name = 'fence';\n const postMaterial = new MeshStandardMaterial({ color: palette.woodDark, flatShading: true });\n const railMaterial = new MeshStandardMaterial({ color: palette.wood, flatShading: true });\n\n const posts = Math.max(2, Math.round(length / spacing) + 1);\n const step = length / (posts - 1);\n for (let i = 0; i < posts; i++) {\n const post = new Mesh(new CylinderGeometry(0.06, 0.075, height, 5), postMaterial);\n post.position.set(-length / 2 + i * step, height / 2, rng.jitter(0, 0.03));\n post.rotation.z = rng.range(-0.04, 0.04);\n group.add(post);\n }\n for (const railY of [height * 0.55, height * 0.85]) {\n const rail = new Mesh(new BoxGeometry(length, 0.07, 0.05), railMaterial);\n rail.position.y = rng.jitter(railY, 0.02);\n rail.rotation.x = rng.range(-0.02, 0.02);\n group.add(rail);\n }\n\n return { object: group, obstacleRadius: length / 2 };\n}\n","import {\n BoxGeometry,\n CylinderGeometry,\n Group,\n Mesh,\n MeshStandardMaterial,\n PointLight,\n SphereGeometry,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface LampOptions {\n seed?: number;\n height?: number;\n /** Add a real PointLight. Off by default — lights are a budget. */\n light?: boolean;\n lightIntensity?: number;\n palette?: Palette;\n}\n\n/** A street lamp: post, head, glowing bulb, optional real PointLight. */\nexport function createLamp(options: LampOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const height = options.height ?? rng.range(2.6, 3.1);\n\n const group = new Group();\n group.name = 'lamp';\n const metal = new MeshStandardMaterial({ color: palette.metal, flatShading: true });\n\n const post = new Mesh(new CylinderGeometry(0.05, 0.08, height, 6), metal);\n post.position.y = height / 2;\n group.add(post);\n\n const head = new Mesh(new BoxGeometry(0.34, 0.26, 0.34), metal);\n head.position.y = height + 0.1;\n group.add(head);\n\n const bulb = new Mesh(\n new SphereGeometry(0.11, 8, 6),\n new MeshStandardMaterial({\n color: palette.lampGlow,\n emissive: palette.lampGlow,\n emissiveIntensity: 1.6,\n })\n );\n bulb.position.y = height - 0.03;\n group.add(bulb);\n\n if (options.light) {\n const light = new PointLight(palette.lampGlow, options.lightIntensity ?? 6, 12, 1.8);\n light.position.y = height - 0.05;\n group.add(light);\n }\n\n return { object: group, obstacleRadius: 0.25 };\n}\n","import { ConeGeometry, Group, IcosahedronGeometry, Mesh, MeshStandardMaterial } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface GrassOptions {\n seed?: number;\n /** Blades per tuft. Default 4–6 by seed. */\n blades?: number;\n palette?: Palette;\n}\n\n/**\n * A tuft of grass blades — pure scatter fodder (zero obstacle footprint,\n * walk straight through). Sways beautifully under `applyWind`.\n */\nexport function createGrassTuft(options: GrassOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const blades = options.blades ?? rng.int(4, 6);\n const group = new Group();\n group.name = 'grass';\n const material = new MeshStandardMaterial({\n color: rng.next() < 0.5 ? palette.grassHigh : rng.pick(palette.foliage),\n flatShading: true,\n });\n for (let i = 0; i < blades; i++) {\n const height = rng.range(0.25, 0.5);\n const blade = new Mesh(new ConeGeometry(0.035, height, 3), material);\n blade.position.set(rng.jitter(0, 0.12), height / 2, rng.jitter(0, 0.12));\n blade.rotation.set(rng.range(-0.25, 0.25), rng.range(0, Math.PI), rng.range(-0.25, 0.25));\n group.add(blade);\n }\n return { object: group, obstacleRadius: 0 };\n}\n\nexport interface BushOptions {\n seed?: number;\n size?: number;\n palette?: Palette;\n}\n\n/** A low foliage bush: two or three squashed blobs. Small footprint. */\nexport function createBush(options: BushOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const size = options.size ?? rng.range(0.4, 0.7);\n const group = new Group();\n group.name = 'bush';\n const material = new MeshStandardMaterial({ color: rng.pick(palette.foliage), flatShading: true });\n const blobs = rng.int(2, 3);\n for (let i = 0; i < blobs; i++) {\n const radius = size * rng.range(0.55, 0.85);\n const blob = new Mesh(new IcosahedronGeometry(radius, 0), material);\n blob.position.set(rng.jitter(0, size * 0.4), radius * 0.7, rng.jitter(0, size * 0.4));\n blob.scale.y = rng.range(0.7, 0.85);\n blob.rotation.y = rng.range(0, Math.PI);\n group.add(blob);\n }\n return { object: group, obstacleRadius: size * 0.6 };\n}\n","import {\n BoxGeometry,\n BufferAttribute,\n BufferGeometry,\n CylinderGeometry,\n Group,\n Mesh,\n MeshStandardMaterial,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\n/** A gabled-roof prism: ridge along local z, base resting on y = 0. */\nfunction prismGeometry(width: number, height: number, depth: number): BufferGeometry {\n const w = width / 2;\n const d = depth / 2;\n // prettier-ignore\n const positions = new Float32Array([\n // front gable (z = +d)\n -w, 0, d, w, 0, d, 0, height, d,\n // back gable (z = -d)\n w, 0, -d, -w, 0, -d, 0, height, -d,\n // left slope\n -w, 0, -d, -w, 0, d, 0, height, d,\n -w, 0, -d, 0, height, d, 0, height, -d,\n // right slope\n w, 0, d, w, 0, -d, 0, height, -d,\n w, 0, d, 0, height, -d, 0, height, d,\n // bottom\n -w, 0, -d, w, 0, -d, w, 0, d,\n -w, 0, -d, w, 0, d, -w, 0, d,\n ]);\n const geometry = new BufferGeometry();\n geometry.setAttribute('position', new BufferAttribute(positions, 3));\n geometry.computeVertexNormals();\n return geometry;\n}\n\nexport interface HouseOptions {\n seed?: number;\n /** Footprint width (gable side). Default seeded 3.2–4.2. */\n width?: number;\n depth?: number;\n wallHeight?: number;\n palette?: Palette;\n}\n\n/**\n * A cottage: plastered walls, gabled roof, door, chimney and emissive\n * windows. Pass the house in `createDayCycle`'s `lamps` list and its\n * windows glow at night along with the street lamps. A stone foundation\n * extends below ground so sloped terrain never shows a gap.\n */\nexport function createHouse(options: HouseOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const width = options.width ?? rng.range(3.2, 4.2);\n const depth = options.depth ?? width * rng.range(0.75, 0.9);\n const wallHeight = options.wallHeight ?? rng.range(2.1, 2.4);\n\n const group = new Group();\n group.name = 'house';\n const wall = new MeshStandardMaterial({ color: palette.wall, flatShading: true });\n wall.color.offsetHSL(0, 0, rng.range(-0.03, 0.03));\n const roof = new MeshStandardMaterial({ color: palette.roof, flatShading: true });\n roof.color.offsetHSL(0, 0, rng.range(-0.04, 0.04));\n const stone = new MeshStandardMaterial({ color: palette.rock[0], flatShading: true });\n const wood = new MeshStandardMaterial({ color: palette.woodDark, flatShading: true });\n\n const foundation = new Mesh(new BoxGeometry(width + 0.3, 1.6, depth + 0.3), stone);\n foundation.position.y = -0.55;\n group.add(foundation);\n\n const body = new Mesh(new BoxGeometry(width, wallHeight, depth), wall);\n body.position.y = wallHeight / 2;\n group.add(body);\n\n const ridgeHeight = width * rng.range(0.32, 0.4);\n const roofMesh = new Mesh(prismGeometry(width + 0.5, ridgeHeight, depth + 0.6), roof);\n roofMesh.position.y = wallHeight - 0.02;\n group.add(roofMesh);\n\n const chimney = new Mesh(new BoxGeometry(0.34, ridgeHeight + 0.8, 0.34), stone);\n chimney.position.set(rng.pick([-1, 1]) * width * 0.22, wallHeight + ridgeHeight * 0.45, depth * 0.12);\n group.add(chimney);\n\n // Door on the front face (+z).\n const door = new Mesh(new BoxGeometry(0.85, 1.5, 0.08), wood);\n door.position.set(rng.range(-0.4, 0.4), 0.75, depth / 2 + 0.02);\n group.add(door);\n\n // Emissive windows — createDayCycle treats these like lamp bulbs.\n const glass = new MeshStandardMaterial({\n color: palette.lampGlow,\n emissive: palette.lampGlow,\n emissiveIntensity: 1.0,\n });\n const windowGeometry = new BoxGeometry(0.6, 0.62, 0.08);\n const front = new Mesh(windowGeometry, glass);\n front.position.set(door.position.x < 0 ? width * 0.28 : -width * 0.28, 1.35, depth / 2 + 0.02);\n group.add(front);\n for (const side of [-1, 1]) {\n if (rng.next() < 0.35) continue;\n const pane = new Mesh(windowGeometry, glass);\n pane.position.set(side * (width / 2 + 0.02), 1.35, rng.range(-0.3, 0.3) * depth);\n pane.rotation.y = Math.PI / 2;\n group.add(pane);\n }\n\n return { object: group, obstacleRadius: Math.hypot(width + 0.5, depth + 0.5) / 2 };\n}\n\nexport interface TowerOptions {\n seed?: number;\n height?: number;\n palette?: Palette;\n}\n\n/** A wooden watchtower: splayed legs, platform with railing, pyramid roof. */\nexport function createTower(options: TowerOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const height = options.height ?? rng.range(4.2, 5.2);\n\n const group = new Group();\n group.name = 'tower';\n const wood = new MeshStandardMaterial({ color: palette.wood, flatShading: true });\n const woodDark = new MeshStandardMaterial({ color: palette.woodDark, flatShading: true });\n const roof = new MeshStandardMaterial({ color: palette.roof, flatShading: true });\n\n const spread = 1.0;\n for (const x of [-1, 1]) {\n for (const z of [-1, 1]) {\n const leg = new Mesh(new CylinderGeometry(0.09, 0.12, height, 6), woodDark);\n leg.position.set(x * spread * 0.75, height / 2 - 0.6, z * spread * 0.75);\n leg.rotation.z = -x * 0.1;\n leg.rotation.x = z * 0.1;\n group.add(leg);\n }\n }\n // Cross-braces.\n for (const level of [0.3, 0.62]) {\n const brace = new Mesh(new BoxGeometry(spread * 2.1, 0.09, 0.07), wood);\n brace.position.set(0, height * level, spread * 0.82 * (1 - level * 0.35));\n brace.rotation.z = rng.pick([-0.5, 0.5]);\n group.add(brace);\n const braceSide = new Mesh(new BoxGeometry(0.07, 0.09, spread * 2.1), wood);\n braceSide.position.set(spread * 0.82 * (1 - level * 0.35), height * level, 0);\n braceSide.rotation.x = rng.pick([-0.5, 0.5]);\n group.add(braceSide);\n }\n\n const platform = new Mesh(new BoxGeometry(spread * 2.2, 0.14, spread * 2.2), wood);\n platform.position.y = height - 0.5;\n group.add(platform);\n for (const x of [-1, 1]) {\n for (const z of [-1, 1]) {\n const post = new Mesh(new BoxGeometry(0.08, 0.9, 0.08), woodDark);\n post.position.set(x * spread * 1.0, height - 0.05, z * spread * 1.0);\n group.add(post);\n }\n }\n for (const [rx, rz, w, d] of [\n [0, 1, spread * 2.1, 0.06],\n [0, -1, spread * 2.1, 0.06],\n [1, 0, 0.06, spread * 2.1],\n [-1, 0, 0.06, spread * 2.1],\n ] as const) {\n const rail = new Mesh(new BoxGeometry(w, 0.07, d), wood);\n rail.position.set(rx * spread, height + 0.28, rz * spread);\n group.add(rail);\n }\n\n const cap = new Mesh(new CylinderGeometry(0, spread * 1.55, 1.0, 4), roof);\n cap.position.y = height + 1.15;\n cap.rotation.y = Math.PI / 4;\n group.add(cap);\n\n return { object: group, obstacleRadius: spread * 1.35 };\n}\n\nexport interface WellOptions {\n seed?: number;\n palette?: Palette;\n}\n\n/** A stone well: ring, posts, little gabled roof, hanging bucket. */\nexport function createWell(options: WellOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n\n const group = new Group();\n group.name = 'well';\n const stone = new MeshStandardMaterial({ color: rng.pick(palette.rock), flatShading: true });\n const wood = new MeshStandardMaterial({ color: palette.woodDark, flatShading: true });\n const roof = new MeshStandardMaterial({ color: palette.roof, flatShading: true });\n\n const ring = new Mesh(new CylinderGeometry(0.85, 0.95, 0.75, 10), stone);\n ring.position.y = 0.375;\n group.add(ring);\n const inner = new Mesh(\n new CylinderGeometry(0.62, 0.62, 0.05, 10),\n new MeshStandardMaterial({ color: 0x16222e })\n );\n inner.position.y = 0.76;\n group.add(inner);\n\n for (const side of [-1, 1]) {\n const post = new Mesh(new CylinderGeometry(0.06, 0.075, 1.9, 5), wood);\n post.position.set(side * 0.72, 0.95, 0);\n group.add(post);\n }\n const bar = new Mesh(new CylinderGeometry(0.045, 0.045, 1.5, 5), wood);\n bar.rotation.z = Math.PI / 2;\n bar.position.y = 1.72;\n group.add(bar);\n\n const cap = new Mesh(prismGeometry(2.0, 0.55, 0.65), roof);\n cap.position.y = 1.86;\n cap.rotation.y = Math.PI / 2;\n group.add(cap);\n\n const rope = new Mesh(new CylinderGeometry(0.012, 0.012, 0.6, 4), wood);\n rope.position.y = 1.42;\n group.add(rope);\n const bucket = new Mesh(new CylinderGeometry(0.13, 0.1, 0.2, 7), wood);\n bucket.position.y = 1.05;\n group.add(bucket);\n\n return { object: group, obstacleRadius: 1.0 };\n}\n\nexport interface RuinOptions {\n seed?: number;\n /** Footprint width. Default seeded 3.5–5. */\n size?: number;\n palette?: Palette;\n}\n\n/**\n * A ruined building: a partial rectangle of crumbling wall segments with\n * seeded gaps and heights, and tumbled blocks around the floor.\n */\nexport function createRuin(options: RuinOptions = {}): Prop {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const size = options.size ?? rng.range(3.5, 5);\n const depth = size * rng.range(0.7, 0.9);\n\n const group = new Group();\n group.name = 'ruin';\n const stone = new MeshStandardMaterial({ color: rng.pick(palette.rock), flatShading: true });\n stone.color.offsetHSL(0, 0, rng.range(-0.04, 0.02));\n\n const thickness = 0.35;\n // Wall runs: [centerX, centerZ, length, alongX]. Front wall mostly gone.\n const runs: Array<[number, number, number, boolean]> = [\n [0, -depth / 2, size, true],\n [-size / 2, 0, depth, false],\n [size / 2, 0, depth, false],\n [size * 0.3, depth / 2, size * 0.35, true],\n ];\n for (const [cx, cz, length, alongX] of runs) {\n const segments = Math.max(2, Math.round(length / 1.1));\n const step = length / segments;\n for (let i = 0; i < segments; i++) {\n if (rng.next() < 0.22) continue; // collapsed gap\n const height = rng.range(0.5, 2.2);\n const wall = new Mesh(\n new BoxGeometry(alongX ? step * 0.96 : thickness, height, alongX ? thickness : step * 0.96),\n stone\n );\n const offset = -length / 2 + step * (i + 0.5);\n wall.position.set(alongX ? cx + offset : cx, height / 2, alongX ? cz : cz + offset);\n wall.rotation.y = rng.range(-0.03, 0.03);\n group.add(wall);\n }\n }\n // Tumbled blocks.\n const blocks = rng.int(4, 7);\n for (let i = 0; i < blocks; i++) {\n const s = rng.range(0.25, 0.55);\n const block = new Mesh(new BoxGeometry(s, s * rng.range(0.6, 1), s * rng.range(0.7, 1.2)), stone);\n block.position.set(rng.range(-size * 0.6, size * 0.6), s * 0.3, rng.range(-depth * 0.6, depth * 0.7));\n block.rotation.set(rng.range(-0.3, 0.3), rng.range(0, Math.PI), rng.range(-0.3, 0.3));\n group.add(block);\n }\n\n return { object: group, obstacleRadius: Math.hypot(size, depth) / 2 };\n}\n","import {\n BufferAttribute,\n Color,\n Mesh,\n MeshStandardMaterial,\n PlaneGeometry,\n} from 'three';\nimport { fractalNoise2 } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\n\nexport interface TerrainOptions {\n seed?: number;\n /** Square side length. Default 80. */\n size?: number;\n /** Vertices per side. Default 96. */\n resolution?: number;\n /** Peak height. Default 6. */\n amplitude?: number;\n /** Noise feature size in world units. Default 28. */\n noiseScale?: number;\n octaves?: number;\n /** Flatten low areas into meadows (0–1, higher = flatter valleys). Default 0.55. */\n valleyFlatness?: number;\n /** Blend low bands toward sand below (waterLevel + shore margin). */\n waterLevel?: number;\n palette?: Palette;\n}\n\nexport interface Terrain {\n mesh: Mesh;\n /** Exact analytic height at any (x, z) — same function that built the\n * mesh, so agents/navmesh queries never disagree with the visuals. */\n heightAt(x: number, z: number): number;\n size: number;\n seed: number;\n}\n\n/**\n * A seeded low-poly terrain: fractal value noise displacing a plane, with\n * height/slope-banded vertex colors (grass → high grass → cliff → peak).\n * The height function is exported, not just baked into vertices — that's\n * what lets gameplay (spawning, scattering, navmesh baking, agent ground\n * clamping) agree exactly with what's rendered.\n */\nexport function createTerrain(options: TerrainOptions = {}): Terrain {\n const seed = options.seed ?? 1;\n const size = options.size ?? 80;\n const resolution = options.resolution ?? 96;\n const amplitude = options.amplitude ?? 6;\n const noiseScale = options.noiseScale ?? 28;\n const octaves = options.octaves ?? 4;\n const flatness = options.valleyFlatness ?? 0.55;\n const palette = options.palette ?? DEFAULT_PALETTE;\n\n const heightAt = (x: number, z: number): number => {\n const n = fractalNoise2(x / noiseScale, z / noiseScale, seed, octaves);\n // Push valleys down and flatten them; keep peaks.\n const shaped = Math.pow(n, 1 + flatness * 2);\n return shaped * amplitude;\n };\n\n const geometry = new PlaneGeometry(size, size, resolution - 1, resolution - 1);\n geometry.rotateX(-Math.PI / 2);\n const positions = geometry.getAttribute('position') as BufferAttribute;\n for (let i = 0; i < positions.count; i++) {\n positions.setY(i, heightAt(positions.getX(i), positions.getZ(i)));\n }\n geometry.computeVertexNormals();\n\n // Vertex colors by height band + slope.\n const normals = geometry.getAttribute('normal') as BufferAttribute;\n const colors = new Float32Array(positions.count * 3);\n const grassLow = new Color(palette.grassLow);\n const grassHigh = new Color(palette.grassHigh);\n const cliff = new Color(palette.cliff);\n const peak = new Color(palette.peak);\n const sand = new Color(palette.sand);\n const waterLevel = options.waterLevel;\n const scratch = new Color();\n for (let i = 0; i < positions.count; i++) {\n const y = positions.getY(i);\n const h = y / amplitude;\n const slope = 1 - normals.getY(i); // 0 flat … 1 vertical\n scratch.copy(grassLow).lerp(grassHigh, Math.min(1, h * 1.6));\n if (h > 0.75) scratch.lerp(peak, (h - 0.75) * 4);\n if (slope > 0.15) scratch.lerp(cliff, Math.min(1, (slope - 0.15) * 4));\n if (waterLevel !== undefined && y < waterLevel + 0.5) {\n scratch.lerp(sand, Math.min(1, (waterLevel + 0.5 - y) * 1.6));\n }\n colors[i * 3] = scratch.r;\n colors[i * 3 + 1] = scratch.g;\n colors[i * 3 + 2] = scratch.b;\n }\n geometry.setAttribute('color', new BufferAttribute(colors, 3));\n\n const mesh = new Mesh(\n geometry,\n new MeshStandardMaterial({ vertexColors: true, flatShading: true })\n );\n mesh.name = 'terrain';\n\n return { mesh, heightAt, size, seed };\n}\n","import {\n BackSide,\n Color,\n Mesh,\n ShaderMaterial,\n SphereGeometry,\n} from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\n\nexport interface SkyOptions {\n topColor?: number;\n bottomColor?: number;\n radius?: number;\n palette?: Palette;\n}\n\nexport interface Sky {\n mesh: Mesh;\n setColors(top: number, bottom: number): void;\n}\n\n/**\n * A gradient sky dome (vertical color blend on an inverted sphere).\n * Colors default to the palette, so themed scenes get matching skies.\n */\nexport function createSky(options: SkyOptions = {}): Sky {\n const palette = options.palette ?? DEFAULT_PALETTE;\n const material = new ShaderMaterial({\n side: BackSide,\n depthWrite: false,\n uniforms: {\n topColor: { value: new Color(options.topColor ?? palette.skyTop) },\n bottomColor: { value: new Color(options.bottomColor ?? palette.skyBottom) },\n },\n vertexShader: /* glsl */ `\n varying vec3 vWorld;\n void main() {\n vWorld = (modelMatrix * vec4(position, 1.0)).xyz;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }`,\n fragmentShader: /* glsl */ `\n uniform vec3 topColor;\n uniform vec3 bottomColor;\n varying vec3 vWorld;\n void main() {\n float t = clamp(normalize(vWorld).y * 0.5 + 0.5, 0.0, 1.0);\n gl_FragColor = vec4(mix(bottomColor, topColor, pow(t, 0.8)), 1.0);\n }`,\n });\n const mesh = new Mesh(new SphereGeometry(options.radius ?? 400, 16, 12), material);\n mesh.name = 'sky';\n\n return {\n mesh,\n setColors(top, bottom) {\n (material.uniforms.topColor.value as Color).setHex(top);\n (material.uniforms.bottomColor.value as Color).setHex(bottom);\n },\n };\n}\n","import {\n AmbientLight,\n DirectionalLight,\n Fog,\n Group,\n HemisphereLight,\n type Scene,\n} from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\n\nexport type LightingPreset = 'day' | 'golden-hour' | 'overcast' | 'night';\n\nexport interface LightingRig {\n group: Group;\n sun: DirectionalLight;\n ambient: AmbientLight;\n hemisphere: HemisphereLight;\n}\n\nconst PRESETS: Record<\n LightingPreset,\n { sun: number; sunIntensity: number; sunPos: [number, number, number]; ambient: number; ambientIntensity: number; skyTint: number; groundTint: number }\n> = {\n day: {\n sun: 0xfff4e0, sunIntensity: 1.6, sunPos: [30, 45, 20],\n ambient: 0xdfeaff, ambientIntensity: 0.35, skyTint: 0xbcd8ff, groundTint: 0x6a7d66,\n },\n 'golden-hour': {\n sun: 0xffb861, sunIntensity: 1.7, sunPos: [40, 14, -12],\n ambient: 0xffdcc0, ambientIntensity: 0.3, skyTint: 0xffcf9e, groundTint: 0x7a6a58,\n },\n overcast: {\n sun: 0xd8dee8, sunIntensity: 0.7, sunPos: [12, 40, 8],\n ambient: 0xcfd6e0, ambientIntensity: 0.65, skyTint: 0xc8d0dc, groundTint: 0x707a78,\n },\n night: {\n sun: 0x8ea6d8, sunIntensity: 0.35, sunPos: [-20, 30, -25],\n ambient: 0x3a4468, ambientIntensity: 0.35, skyTint: 0x2c3560, groundTint: 0x1e2430,\n },\n};\n\n/**\n * The three lights every scene rebuilds, as a preset: warm directional\n * \"sun\" (position doubles as light direction), ambient fill, and a\n * hemisphere tint. Retune any of them via the returned rig.\n */\nexport function createLightingRig(preset: LightingPreset = 'day'): LightingRig {\n const config = PRESETS[preset];\n const group = new Group();\n group.name = `lighting-${preset}`;\n const sun = new DirectionalLight(config.sun, config.sunIntensity);\n sun.position.set(...config.sunPos);\n const ambient = new AmbientLight(config.ambient, config.ambientIntensity);\n const hemisphere = new HemisphereLight(config.skyTint, config.groundTint, 0.5);\n group.add(sun, ambient, hemisphere);\n return { group, sun, ambient, hemisphere };\n}\n\nexport type FogPreset = 'clear' | 'haze' | 'thick' | 'eerie';\n\nconst FOG: Record<Exclude<FogPreset, 'clear'>, { near: number; far: number }> = {\n haze: { near: 45, far: 160 },\n thick: { near: 12, far: 70 },\n eerie: { near: 6, far: 42 },\n};\n\n/** Distance fog matched to the palette's fog color. 'clear' removes it. */\nexport function applyFog(scene: Scene, preset: FogPreset, palette: Palette = DEFAULT_PALETTE): void {\n if (preset === 'clear') {\n scene.fog = null;\n return;\n }\n const { near, far } = FOG[preset];\n scene.fog = new Fog(palette.fog, near, far);\n}\n","import { BufferAttribute, Mesh, MeshStandardMaterial, PlaneGeometry } from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Terrain } from './terrain';\n\nexport interface WaterOptions {\n /** World-space water surface height. Default 0.8. */\n level?: number;\n size?: number;\n resolution?: number;\n /** Wave height. Default 0.06. */\n amplitude?: number;\n /** Wave speed multiplier. Default 1. */\n speed?: number;\n palette?: Palette;\n}\n\nexport interface Water {\n mesh: Mesh;\n level: number;\n /** Advance the wave animation. Call from your frame loop. */\n update(dt: number): void;\n /** Is ground at this height below the surface? */\n isUnderwater(groundHeight: number): boolean;\n}\n\n/**\n * A low-poly animated water plane at a fixed level. Pair it with a\n * terrain built using the same `waterLevel` so shores blend to sand, and\n * keep scatter/agents ashore with `aboveWater(terrain, water)`.\n */\nexport function createWater(options: WaterOptions = {}): Water {\n const level = options.level ?? 0.8;\n const size = options.size ?? 200;\n const resolution = options.resolution ?? 40;\n const amplitude = options.amplitude ?? 0.06;\n const speed = options.speed ?? 1;\n const palette = options.palette ?? DEFAULT_PALETTE;\n\n const geometry = new PlaneGeometry(size, size, resolution, resolution);\n geometry.rotateX(-Math.PI / 2);\n const positions = geometry.getAttribute('position') as BufferAttribute;\n const mesh = new Mesh(\n geometry,\n new MeshStandardMaterial({\n color: palette.water,\n transparent: true,\n opacity: 0.85,\n flatShading: true,\n metalness: 0.35,\n roughness: 0.4,\n })\n );\n mesh.name = 'water';\n mesh.position.y = level;\n\n let time = 0;\n const update = (dt: number): void => {\n time += dt * speed;\n for (let i = 0; i < positions.count; i++) {\n const x = positions.getX(i);\n const z = positions.getZ(i);\n positions.setY(\n i,\n Math.sin(x * 0.35 + time) * Math.cos(z * 0.3 + time * 0.8) * amplitude\n );\n }\n positions.needsUpdate = true;\n geometry.computeVertexNormals();\n };\n update(0);\n\n return {\n mesh,\n level,\n update,\n isUnderwater: (groundHeight) => groundHeight < level,\n };\n}\n\n/**\n * A scatter mask keeping placements on dry land: true when the terrain\n * at (x, z) sits above the water level plus `margin`.\n */\nexport function aboveWater(\n terrain: Terrain,\n water: Pick<Water, 'level'>,\n margin = 0.25\n): (x: number, z: number) => boolean {\n return (x, z) => terrain.heightAt(x, z) > water.level + margin;\n}\n","import { Color, PointLight, type MeshStandardMaterial, type Mesh, type Object3D, type Scene } from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { LightingRig } from './lighting';\nimport type { Sky } from './sky';\n\ninterface Keyframe {\n t: number;\n skyTop: number;\n skyBottom: number;\n sun: number;\n sunIntensity: number;\n ambientIntensity: number;\n fog: number;\n}\n\nexport interface DayCycleOptions {\n sky?: Sky;\n rig?: LightingRig;\n /** Scene whose fog color should track the cycle. */\n scene?: Scene;\n /** Lamp props/objects whose PointLights + glow bulbs ignite at night. */\n lamps?: Array<{ object: Object3D } | Object3D>;\n palette?: Palette;\n /** Seconds per full day. Default 60. */\n dayLength?: number;\n /** Initial time: 0 = midnight, 0.25 = dawn, 0.5 = noon, 0.75 = dusk. */\n timeOfDay?: number;\n}\n\nexport interface DayCycle {\n timeOfDay: number;\n /** Sun elevation in [-1, 1]; negative = below the horizon. */\n readonly sunElevation: number;\n readonly isNight: boolean;\n /** Advance by dt seconds of real time and re-apply everything. */\n update(dt: number): void;\n /** Jump to a time of day and re-apply everything. */\n set(t: number): void;\n}\n\n/**\n * One `timeOfDay` parameter driving the whole environment in lockstep:\n * sun position/color/intensity, sky gradient, ambient level, fog color,\n * and lamps that ignite as the sun drops below the horizon.\n *\n * ```ts\n * const cycle = createDayCycle({ sky, rig, scene, lamps: [lampA, lampB], dayLength: 120 });\n * game.onUpdate((t) => cycle.update(t.delta));\n * ```\n */\nexport function createDayCycle(options: DayCycleOptions = {}): DayCycle {\n const palette = options.palette ?? DEFAULT_PALETTE;\n const dayLength = options.dayLength ?? 60;\n\n // Universal ramp; noon colors come from the palette so themes carry through.\n const frames: Keyframe[] = [\n { t: 0.0, skyTop: 0x0b1026, skyBottom: 0x1a2340, sun: 0x8ea6d8, sunIntensity: 0.03, ambientIntensity: 0.06, fog: 0x141a2e },\n { t: 0.23, skyTop: 0x27335c, skyBottom: 0x6a5470, sun: 0xcf9a72, sunIntensity: 0.3, ambientIntensity: 0.12, fog: 0x4a4258 },\n { t: 0.3, skyTop: 0x4a6ba0, skyBottom: 0xe8a97a, sun: 0xffb861, sunIntensity: 1.0, ambientIntensity: 0.26, fog: 0xb08a72 },\n { t: 0.5, skyTop: palette.skyTop, skyBottom: palette.skyBottom, sun: 0xfff4e0, sunIntensity: 1.9, ambientIntensity: 0.45, fog: palette.fog },\n { t: 0.7, skyTop: 0x4a5a94, skyBottom: 0xe0955e, sun: 0xffa050, sunIntensity: 1.0, ambientIntensity: 0.26, fog: 0xa07a68 },\n { t: 0.78, skyTop: 0x232a52, skyBottom: 0x8a5560, sun: 0xd88a5a, sunIntensity: 0.25, ambientIntensity: 0.11, fog: 0x463e54 },\n { t: 1.0, skyTop: 0x0b1026, skyBottom: 0x1a2340, sun: 0x8ea6d8, sunIntensity: 0.03, ambientIntensity: 0.06, fog: 0x141a2e },\n ];\n\n // Collect lamp lights and glowing bulb materials once.\n const lampLights: Array<{ light: PointLight; base: number }> = [];\n const lampBulbs: Array<{ material: MeshStandardMaterial; base: number }> = [];\n for (const entry of options.lamps ?? []) {\n const root = (entry as { isObject3D?: boolean }).isObject3D\n ? (entry as Object3D)\n : (entry as { object: Object3D }).object;\n root.traverse((child) => {\n if (child instanceof PointLight) {\n lampLights.push({ light: child, base: child.intensity || 6 });\n }\n const material = (child as Mesh).material as MeshStandardMaterial | undefined;\n if (material?.emissive && material.emissiveIntensity > 0.5) {\n lampBulbs.push({ material, base: material.emissiveIntensity });\n }\n });\n }\n\n const colorA = new Color();\n const colorB = new Color();\n let timeOfDay = options.timeOfDay ?? 0.5;\n let sunElevation = 0;\n\n const sample = (t: number): Keyframe => {\n let a = frames[0];\n let b = frames[frames.length - 1];\n for (let i = 0; i < frames.length - 1; i++) {\n if (t >= frames[i].t && t <= frames[i + 1].t) {\n a = frames[i];\n b = frames[i + 1];\n break;\n }\n }\n const f = b.t === a.t ? 0 : (t - a.t) / (b.t - a.t);\n const lerpHex = (ha: number, hb: number): number =>\n colorA.setHex(ha).lerp(colorB.setHex(hb), f).getHex();\n return {\n t,\n skyTop: lerpHex(a.skyTop, b.skyTop),\n skyBottom: lerpHex(a.skyBottom, b.skyBottom),\n sun: lerpHex(a.sun, b.sun),\n sunIntensity: a.sunIntensity + (b.sunIntensity - a.sunIntensity) * f,\n ambientIntensity: a.ambientIntensity + (b.ambientIntensity - a.ambientIntensity) * f,\n fog: lerpHex(a.fog, b.fog),\n };\n };\n\n const apply = (): void => {\n const t = timeOfDay;\n const frame = sample(t);\n const sunAngle = (t - 0.25) * Math.PI * 2;\n sunElevation = Math.sin(sunAngle);\n\n options.sky?.setColors(frame.skyTop, frame.skyBottom);\n if (options.rig) {\n const { sun, ambient, hemisphere } = options.rig;\n sun.color.setHex(frame.sun);\n sun.intensity = frame.sunIntensity;\n sun.position.set(Math.cos(sunAngle) * 40, Math.max(sunElevation, -0.2) * 45 + 6, 16);\n ambient.intensity = frame.ambientIntensity;\n // Hemisphere fill follows the ambient curve so nights actually darken.\n hemisphere.intensity = frame.ambientIntensity * 1.4;\n }\n if (options.scene?.fog && 'color' in options.scene.fog) {\n options.scene.fog.color.setHex(frame.fog);\n }\n // Lamps fade in as the sun dips below the horizon.\n const night = Math.min(1, Math.max(0, (0.06 - sunElevation) / 0.16));\n for (const { light, base } of lampLights) light.intensity = base * night;\n for (const { material, base } of lampBulbs) {\n material.emissiveIntensity = 0.15 * base + 0.85 * base * night;\n }\n };\n apply();\n\n return {\n get timeOfDay() {\n return timeOfDay;\n },\n set timeOfDay(t: number) {\n timeOfDay = ((t % 1) + 1) % 1;\n apply();\n },\n get sunElevation() {\n return sunElevation;\n },\n get isNight() {\n return sunElevation < 0;\n },\n update(dt) {\n timeOfDay = (timeOfDay + dt / dayLength) % 1;\n apply();\n },\n set(t) {\n timeOfDay = ((t % 1) + 1) % 1;\n apply();\n },\n };\n}\n","import { Mesh, type Material, type Object3D } from 'three';\n\n/** The slice of the shader object onBeforeCompile receives. */\ninterface PatchableShader {\n uniforms: Record<string, { value: unknown }>;\n vertexShader: string;\n}\n\nexport interface WindOptions {\n /** Sway amplitude in world units at the top of a prop. Default 0.06. */\n strength?: number;\n /** Oscillation speed. Default 1.2. */\n frequency?: number;\n /** Local height where sway begins (keeps trunks planted). Default 0.6. */\n anchorHeight?: number;\n}\n\nexport interface Wind {\n /** Advance the animation. Call from your frame loop. */\n update(dt: number): void;\n /** Materials that were patched (for debugging/cleanup). */\n materials: Material[];\n}\n\n/**\n * Vertex-shader wind sway for scattered vegetation: displacement grows\n * with local height (trunk bases stay planted), phase varies per\n * instance so a forest shimmers instead of marching in step. Works on\n * meshes and InstancedMeshes; patches each unique material once via\n * onBeforeCompile.\n *\n * ```ts\n * const wind = applyWind(forest.group, { strength: 0.08 });\n * game.onUpdate((t) => wind.update(t.delta));\n * ```\n */\nexport function applyWind(target: Object3D, options: WindOptions = {}): Wind {\n const strength = options.strength ?? 0.06;\n const frequency = options.frequency ?? 1.2;\n const anchor = options.anchorHeight ?? 0.6;\n const time = { value: 0 };\n const patched = new Set<Material>();\n\n target.traverse((child) => {\n if (!(child instanceof Mesh)) return;\n const materials = Array.isArray(child.material) ? child.material : [child.material];\n for (const material of materials) {\n if (patched.has(material)) continue;\n patched.add(material);\n material.onBeforeCompile = (shader: PatchableShader) => {\n shader.uniforms.uWindTime = time;\n shader.vertexShader = shader.vertexShader\n .replace(\n '#include <common>',\n `#include <common>\n uniform float uWindTime;`\n )\n .replace(\n '#include <begin_vertex>',\n `#include <begin_vertex>\n {\n float sway = max(position.y - ${anchor.toFixed(3)}, 0.0);\n float phase = 0.0;\n #ifdef USE_INSTANCING\n phase = instanceMatrix[3].x * 0.7 + instanceMatrix[3].z * 1.3;\n #endif\n float w = sin(uWindTime * ${(frequency * 2).toFixed(3)} + phase + position.y * 0.8);\n transformed.x += w * sway * ${strength.toFixed(4)} * 4.0;\n transformed.z += cos(uWindTime * ${(frequency * 1.4).toFixed(3)} + phase) * sway * ${strength.toFixed(4)} * 2.0;\n }`\n );\n };\n material.needsUpdate = true;\n }\n });\n\n return {\n update(dt) {\n time.value += dt;\n },\n materials: [...patched],\n };\n}\n","import {\n BufferAttribute,\n BufferGeometry,\n CatmullRomCurve3,\n Mesh,\n MeshStandardMaterial,\n Vector3,\n} from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\n\nexport interface PathOptions {\n /** Ribbon width. Default 1.8. */\n width?: number;\n /** Ground height lookup; a number means flat ground. Default 0. */\n surface?: number | ((x: number, z: number) => number);\n /** Samples per world unit of path length. Default 1. */\n samplesPerUnit?: number;\n /** Close the path into a loop. Default false. */\n loop?: boolean;\n /** Extra clearance added to scatter keep-out circles. Default 0.6. */\n keepOutMargin?: number;\n palette?: Palette;\n}\n\nexport interface WorldPath {\n mesh: Mesh;\n /** Smoothed centerline draped on the surface — feed straight into a\n * GAMA `Path` for patrols, or use as camera dolly points. */\n route: Vector3[];\n /** Keep-out circles for `scatter()` so nothing grows on the road. */\n keepOut: Array<{ center: { x: number; z: number }; radius: number }>;\n /** Is (x, z) on the path surface? (e.g. to exclude grass) */\n contains(x: number, z: number): boolean;\n loop: boolean;\n}\n\n/**\n * A dirt path: a Catmull-Rom-smoothed ribbon draped over the surface.\n * One authored polyline feeds three things at once — the visual ribbon,\n * scatter keep-out, and a patrol route for agents. That's the SCENA\n * handshake applied to level design.\n *\n * ```ts\n * const road = createPath([a, b, c], { surface: terrain.heightAt, loop: true });\n * scene.add(road.mesh);\n * scatter({ ..., keepOut: road.keepOut });\n * agent.addBehavior(new FollowPath(new Path(road.route, road.loop), 1.5));\n * ```\n */\nexport function createPath(\n points: Array<Vector3 | { x: number; z: number }>,\n options: PathOptions = {}\n): WorldPath {\n const width = options.width ?? 1.8;\n const surface = options.surface ?? 0;\n const heightAt =\n typeof surface === 'number' ? () => surface : (x: number, z: number) => surface(x, z);\n const loop = options.loop ?? false;\n const palette = options.palette ?? DEFAULT_PALETTE;\n\n const controls = points.map((p) => new Vector3(p.x, 0, 'z' in p ? p.z : 0));\n const curve = new CatmullRomCurve3(controls, loop, 'centripetal');\n const length = curve.getLength();\n const samples = Math.max(8, Math.ceil(length * (options.samplesPerUnit ?? 1)));\n\n const route: Vector3[] = [];\n for (let i = 0; i <= samples; i++) {\n if (loop && i === samples) break; // avoid duplicate closing point\n const p = curve.getPoint(i / samples);\n route.push(new Vector3(p.x, heightAt(p.x, p.z), p.z));\n }\n\n // Ribbon strip: left/right edge vertices per sample.\n const edgeCount = loop ? route.length + 1 : route.length;\n const positions = new Float32Array(edgeCount * 2 * 3);\n const direction = new Vector3();\n const perp = new Vector3();\n for (let i = 0; i < edgeCount; i++) {\n const current = route[i % route.length];\n const previous = route[(i - 1 + route.length) % route.length];\n const next = route[(i + 1) % route.length];\n if (!loop && i === 0) direction.subVectors(next, current);\n else if (!loop && i === edgeCount - 1) direction.subVectors(current, previous);\n else direction.subVectors(next, previous);\n perp.set(-direction.z, 0, direction.x).normalize().multiplyScalar(width / 2);\n const left = i * 6;\n positions[left] = current.x - perp.x;\n positions[left + 1] = heightAt(current.x - perp.x, current.z - perp.z) + 0.05;\n positions[left + 2] = current.z - perp.z;\n positions[left + 3] = current.x + perp.x;\n positions[left + 4] = heightAt(current.x + perp.x, current.z + perp.z) + 0.05;\n positions[left + 5] = current.z + perp.z;\n }\n const indices: number[] = [];\n for (let i = 0; i < edgeCount - 1; i++) {\n const a = i * 2;\n indices.push(a, a + 1, a + 2, a + 1, a + 3, a + 2);\n }\n const geometry = new BufferGeometry();\n geometry.setAttribute('position', new BufferAttribute(positions, 3));\n geometry.setIndex(indices);\n geometry.computeVertexNormals();\n\n const mesh = new Mesh(\n geometry,\n new MeshStandardMaterial({\n color: palette.path,\n flatShading: true,\n polygonOffset: true,\n polygonOffsetFactor: -1,\n })\n );\n mesh.name = 'path';\n\n const keepOutMargin = options.keepOutMargin ?? 0.6;\n const keepOut = route\n .filter((_p, i) => i % 2 === 0 || i === route.length - 1) // never drop the endpoint\n .map((p) => ({ center: { x: p.x, z: p.z }, radius: width / 2 + keepOutMargin }));\n\n const half = width / 2;\n const contains = (x: number, z: number): boolean => {\n const count = loop ? route.length : route.length - 1;\n for (let i = 0; i < count; i++) {\n const a = route[i];\n const b = route[(i + 1) % route.length];\n const abx = b.x - a.x;\n const abz = b.z - a.z;\n const lengthSq = abx * abx + abz * abz || 1e-9;\n const t = Math.max(0, Math.min(1, ((x - a.x) * abx + (z - a.z) * abz) / lengthSq));\n const dx = x - (a.x + abx * t);\n const dz = z - (a.z + abz * t);\n if (dx * dx + dz * dz <= half * half) return true;\n }\n return false;\n };\n\n return { mesh, route, keepOut, contains, loop };\n}\n","import { Group } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport { collectObstacles, type Obstacle, type Prop } from '../core/types';\nimport { createHouse, createRuin, createTower, createWell } from '../props/building';\nimport { createCrate } from '../props/crate';\nimport { createLamp } from '../props/lamp';\n\nexport interface VillageOptions {\n seed?: number;\n /** Village center in the XZ plane. Default origin. */\n center?: { x: number; z: number };\n /** Ring radius the houses settle on. Default 12. */\n radius?: number;\n /** House count. Default 5. */\n houses?: number;\n /** Ground height lookup; a number means flat ground. Default 0. */\n surface?: number | ((x: number, z: number) => number);\n /** Veto candidate spots (e.g. water, roads). Return false to reject. */\n mask?: (x: number, z: number, y: number) => boolean;\n /** Add real PointLights to this many street lamps. Default 3. */\n lampLights?: number;\n /** Add a watchtower at the edge. Default true. */\n tower?: boolean;\n /** Add a ruin outside the ring. Default true. */\n ruin?: boolean;\n palette?: Palette;\n}\n\nexport interface Village {\n group: Group;\n /** Every placed prop (houses, well, lamps, crates, tower, ruin). */\n props: Prop[];\n /** World-space steering obstacles — feed GAMA's ObstacleAvoidance. */\n obstacles: Obstacle[];\n /**\n * Props with something to ignite at night (street lamps AND house\n * windows). Pass straight to `createDayCycle({ lamps })`.\n */\n lamps: Prop[];\n /** One clearing circle covering the village — feed `scatter`'s keepOut. */\n keepOut: Array<{ center: { x: number; z: number }; radius: number }>;\n center: { x: number; z: number };\n}\n\n/**\n * A seeded hamlet: a well at the center, houses ringed around it facing\n * inward, street lamps between them, crates by the doors, a watchtower on\n * the edge and a ruin beyond. Everything is placed on the given surface\n * (steep or masked spots are rejected and re-rolled), and the result\n * carries the full gameplay handshake: `obstacles` for steering,\n * `keepOut` for scatter, and `lamps` for the day-night cycle — windows\n * and lamps ignite together at dusk.\n *\n * ```ts\n * const village = createVillage({ seed: 5, radius: 10, surface: terrain.heightAt, palette });\n * scene.add(village.group);\n * const cycle = createDayCycle({ sky, rig, scene, lamps: village.lamps, palette });\n * const forest = scatter({ ..., keepOut: village.keepOut });\n * ```\n */\nexport function createVillage(options: VillageOptions = {}): Village {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const center = options.center ?? { x: 0, z: 0 };\n const radius = options.radius ?? 12;\n const houseCount = options.houses ?? 5;\n const surface = options.surface ?? 0;\n const heightAt =\n typeof surface === 'number' ? () => surface : (x: number, z: number) => surface(x, z);\n\n const group = new Group();\n group.name = 'village';\n const props: Prop[] = [];\n const lamps: Prop[] = [];\n\n const place = (prop: Prop, x: number, z: number, rotY: number): Prop => {\n prop.object.position.set(x, heightAt(x, z), z);\n prop.object.rotation.y = rotY;\n group.add(prop.object);\n props.push(prop);\n return prop;\n };\n\n /**\n * Find a buildable spot near (angle, distance): reasonably level across\n * the footprint and not vetoed by the mask. Re-rolls up to 10 times,\n * then falls back to the last candidate so layout never dead-ends.\n */\n const findSpot = (\n angle: number,\n distance: number,\n footprint: number\n ): { x: number; z: number } => {\n let x = center.x;\n let z = center.z;\n for (let attempt = 0; attempt < 10; attempt++) {\n const a = angle + rng.range(-0.25, 0.25) * (attempt > 0 ? 1 : 0.3);\n const d = distance * rng.range(attempt > 0 ? 0.8 : 0.95, 1.1);\n x = center.x + Math.cos(a) * d;\n z = center.z + Math.sin(a) * d;\n const y = heightAt(x, z);\n if (options.mask && !options.mask(x, z, y)) continue;\n let min = y;\n let max = y;\n for (const [dx, dz] of [[footprint, 0], [-footprint, 0], [0, footprint], [0, -footprint]]) {\n const h = heightAt(x + dx, z + dz);\n min = Math.min(min, h);\n max = Math.max(max, h);\n }\n if (max - min <= Math.max(0.9, footprint * 0.35)) break;\n }\n return { x, z };\n };\n\n // The well anchors the plaza.\n const well = createWell({ seed: rng.int(1, 1e9), palette });\n place(well, center.x, center.z, rng.range(0, Math.PI * 2));\n\n // Houses on the ring, facing the well.\n let lightBudget = options.lampLights ?? 3;\n for (let i = 0; i < houseCount; i++) {\n const angle = (i / houseCount) * Math.PI * 2 + rng.range(-0.15, 0.15);\n const house = createHouse({ seed: rng.int(1, 1e9), palette });\n const spot = findSpot(angle, radius * rng.range(0.7, 0.95), house.obstacleRadius);\n const facing = Math.atan2(center.x - spot.x, center.z - spot.z);\n place(house, spot.x, spot.z, facing);\n lamps.push(house);\n\n // A crate by most doors, a lamp partway toward the plaza for some.\n if (rng.next() < 0.7) {\n const crateAngle = angle + rng.range(-0.5, 0.5);\n const crateDistance = Math.hypot(spot.x - center.x, spot.z - center.z) - house.obstacleRadius - 0.7;\n place(\n createCrate({ seed: rng.int(1, 1e9), size: rng.range(0.7, 1), palette }),\n center.x + Math.cos(crateAngle) * crateDistance,\n center.z + Math.sin(crateAngle) * crateDistance,\n rng.range(0, Math.PI)\n );\n }\n if (i % 2 === 0) {\n const lampDistance = Math.hypot(spot.x - center.x, spot.z - center.z) * 0.55;\n const lamp = createLamp({ seed: rng.int(1, 1e9), light: lightBudget > 0, palette });\n lightBudget--;\n place(lamp, center.x + Math.cos(angle) * lampDistance, center.z + Math.sin(angle) * lampDistance, 0);\n lamps.push(lamp);\n }\n }\n\n if (options.tower ?? true) {\n const angle = rng.range(0, Math.PI * 2);\n const tower = createTower({ seed: rng.int(1, 1e9), palette });\n const spot = findSpot(angle, radius * 1.05, tower.obstacleRadius);\n place(tower, spot.x, spot.z, rng.range(0, Math.PI * 2));\n }\n if (options.ruin ?? true) {\n const angle = rng.range(0, Math.PI * 2);\n const ruin = createRuin({ seed: rng.int(1, 1e9), palette });\n const spot = findSpot(angle, radius * 1.35, ruin.obstacleRadius);\n place(ruin, spot.x, spot.z, rng.range(0, Math.PI * 2));\n }\n\n return {\n group,\n props,\n obstacles: collectObstacles(props),\n lamps,\n keepOut: [{ center: { ...center }, radius: radius * 1.5 }],\n center,\n };\n}\n","import {\n BoxGeometry,\n CylinderGeometry,\n Group,\n InstancedMesh,\n Matrix4,\n Mesh,\n MeshStandardMaterial,\n PointLight,\n SphereGeometry,\n Vector3,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Obstacle } from '../core/types';\n\n/**\n * The kit grid: every kit piece snaps to this cell size (in world units).\n * Shared snap dimensions are what make pieces combinable — a doorway cut\n * in one wall lines up with the corridor on the other side.\n */\nexport const KIT_UNIT = 2;\n\nexport interface KitOptions {\n seed?: number;\n /** Cell size override. Default KIT_UNIT. */\n unit?: number;\n /** Wall height. Default 2.6. */\n wallHeight?: number;\n /** Add real PointLights to this many torches. Default 4. */\n torchLights?: number;\n palette?: Palette;\n}\n\nexport interface Kit {\n group: Group;\n /** One obstacle per wall cell — feed GAMA's ObstacleAvoidance. */\n obstacles: Obstacle[];\n /** World positions of 'S' cells (player/NPC spawn points). */\n spawns: Vector3[];\n /** World positions of 'T' cells (torches), lit in placement order. */\n torches: Vector3[];\n /** Is (x, z) over a walkable floor cell? */\n floorAt(x: number, z: number): boolean;\n /** Footprint in world units: { width, depth } centered on the origin. */\n size: { width: number; depth: number };\n}\n\n/**\n * Assemble a dungeon/compound from an ASCII map — each character is one\n * KIT_UNIT × KIT_UNIT cell, centered on the group origin:\n *\n * - `#` wall block (blocks movement, becomes an obstacle)\n * - `.` floor tile\n * - `D` doorway: floor + lintel spanning the gap overhead\n * - `T` floor + standing torch (emissive flame; `createDayCycle` adopts it)\n * - `S` floor + recorded spawn point\n * - ` ` nothing\n *\n * ```ts\n * const fort = assembleKit([\n * '#######',\n * '#..T..#',\n * '#.....D',\n * '#..S..#',\n * '#######',\n * ], { palette });\n * fort.group.position.set(20, terrain.heightAt(20, 5), 5);\n * ```\n *\n * Walls and floors render as two InstancedMeshes regardless of map size.\n */\nexport function assembleKit(rows: string[], options: KitOptions = {}): Kit {\n const rng = new Rng(options.seed ?? 1);\n const palette = options.palette ?? DEFAULT_PALETTE;\n const unit = options.unit ?? KIT_UNIT;\n const wallHeight = options.wallHeight ?? 2.6;\n let torchLights = options.torchLights ?? 4;\n\n const height = rows.length;\n const width = Math.max(...rows.map((r) => r.length), 0);\n const originX = (-width / 2 + 0.5) * unit;\n const originZ = (-height / 2 + 0.5) * unit;\n const worldOf = (col: number, row: number): { x: number; z: number } => ({\n x: originX + col * unit,\n z: originZ + row * unit,\n });\n\n const group = new Group();\n group.name = 'kit';\n const obstacles: Obstacle[] = [];\n const spawns: Vector3[] = [];\n const torches: Vector3[] = [];\n const floorCells = new Set<string>();\n\n const wallCells: Array<{ x: number; z: number }> = [];\n const floorTiles: Array<{ x: number; z: number }> = [];\n\n for (let row = 0; row < height; row++) {\n for (let col = 0; col < (rows[row] ?? '').length; col++) {\n const cell = rows[row][col];\n if (cell === ' ' || cell === undefined) continue;\n const { x, z } = worldOf(col, row);\n\n if (cell === '#') {\n wallCells.push({ x, z });\n obstacles.push({ center: new Vector3(x, wallHeight / 2, z), radius: unit * 0.71 });\n continue;\n }\n // Everything else stands on a floor tile.\n floorTiles.push({ x, z });\n floorCells.add(`${col},${row}`);\n\n if (cell === 'D') {\n // Lintel over the opening, aligned with whichever axis the walls run.\n const horizontalRun =\n rows[row][col - 1] === '#' || rows[row][col + 1] === '#';\n const lintel = new Mesh(\n new BoxGeometry(\n horizontalRun ? unit : unit * 0.4,\n wallHeight * 0.25,\n horizontalRun ? unit * 0.4 : unit\n ),\n new MeshStandardMaterial({ color: palette.woodDark, flatShading: true })\n );\n lintel.position.set(x, wallHeight * 0.875, z);\n group.add(lintel);\n } else if (cell === 'T') {\n group.add(createTorch(x, z, palette, rng, torchLights > 0));\n torchLights--;\n torches.push(new Vector3(x, 0, z));\n obstacles.push({ center: new Vector3(x, 0, z), radius: 0.3 });\n } else if (cell === 'S') {\n spawns.push(new Vector3(x, 0, z));\n }\n }\n }\n\n // Two draw calls for the architecture: instanced walls + instanced floors.\n const stone = new MeshStandardMaterial({ color: rng.pick(palette.rock), flatShading: true });\n const stoneDark = new MeshStandardMaterial({ color: palette.cliff, flatShading: true });\n const matrix = new Matrix4();\n if (wallCells.length > 0) {\n const walls = new InstancedMesh(\n new BoxGeometry(unit, wallHeight, unit),\n stone,\n wallCells.length\n );\n wallCells.forEach((cell, i) => {\n walls.setMatrixAt(i, matrix.makeTranslation(cell.x, wallHeight / 2, cell.z));\n });\n walls.instanceMatrix.needsUpdate = true;\n group.add(walls);\n }\n if (floorTiles.length > 0) {\n const floors = new InstancedMesh(\n new BoxGeometry(unit, 0.2, unit),\n stoneDark,\n floorTiles.length\n );\n floorTiles.forEach((cell, i) => {\n floors.setMatrixAt(i, matrix.makeTranslation(cell.x, -0.1, cell.z));\n });\n floors.instanceMatrix.needsUpdate = true;\n group.add(floors);\n }\n\n return {\n group,\n obstacles,\n spawns,\n torches,\n floorAt(x, z) {\n const col = Math.round((x - originX) / unit);\n const row = Math.round((z - originZ) / unit);\n return floorCells.has(`${col},${row}`);\n },\n size: { width: width * unit, depth: height * unit },\n };\n}\n\nfunction createTorch(\n x: number,\n z: number,\n palette: Palette,\n rng: Rng,\n light: boolean\n): Group {\n const torch = new Group();\n torch.name = 'torch';\n const pole = new Mesh(\n new CylinderGeometry(0.04, 0.06, 1.5, 5),\n new MeshStandardMaterial({ color: palette.woodDark, flatShading: true })\n );\n pole.position.y = 0.75;\n torch.add(pole);\n const flame = new Mesh(\n new SphereGeometry(0.1, 6, 5),\n new MeshStandardMaterial({\n color: palette.lampGlow,\n emissive: palette.lampGlow,\n emissiveIntensity: 1.8,\n })\n );\n flame.position.y = 1.58;\n flame.scale.y = rng.range(1.2, 1.5);\n torch.add(flame);\n if (light) {\n const point = new PointLight(palette.lampGlow, 5, 9, 1.9);\n point.position.y = 1.6;\n torch.add(point);\n }\n torch.position.set(x, 0, z);\n return torch;\n}\n","import { CylinderGeometry, Group, Mesh, MeshStandardMaterial, type Scene } from 'three';\nimport { Rng } from '../core/random';\nimport { PALETTES, DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Obstacle, Prop } from '../core/types';\nimport { createTerrain, type Terrain } from '../environment/terrain';\nimport { createWater, aboveWater, type Water } from '../environment/water';\nimport { createSky, type Sky } from '../environment/sky';\nimport {\n createLightingRig,\n applyFog,\n type LightingRig,\n type LightingPreset,\n type FogPreset,\n} from '../environment/lighting';\nimport { createDayCycle, type DayCycle } from '../environment/dayCycle';\nimport { applyWind, type Wind } from '../environment/wind';\nimport { createPath, type WorldPath } from '../environment/path';\nimport { createVillage, type Village } from '../generators/village';\nimport { scatter, type ScatterResult, type ScatterItem } from '../scatter/scatter';\nimport { createTree } from '../props/tree';\nimport { createRock } from '../props/rock';\nimport { createCrate } from '../props/crate';\nimport { createFence } from '../props/fence';\nimport { createLamp } from '../props/lamp';\nimport { createGrassTuft, createBush } from '../props/grass';\n\n/** Prop vocabulary available to manifest scatters. */\nexport type ScatterPropType = 'tree' | 'rock' | 'bush' | 'grass' | 'crate' | 'fence' | 'lamp';\n\nexport interface ManifestScatterItem {\n type: ScatterPropType;\n weight?: number;\n variants?: number;\n scale?: [number, number];\n}\n\nexport interface ManifestScatter {\n /** Defaults to the terrain footprint (slightly inset). */\n area?: { min: { x: number; z: number }; max: { x: number; z: number } };\n density?: number;\n count?: number;\n minSpacing?: number;\n clumpScale?: number;\n items: ManifestScatterItem[];\n /** Reject spots above this ground height (keep peaks bare). */\n maxHeight?: number;\n /** Keep placements ashore. Default true when the scene has water. */\n avoidWater?: boolean;\n /** Keep placements off paths and out of the village. Default true. */\n avoidPaths?: boolean;\n /** Opt into tile-based LOD (see ScatterOptions.lod). */\n lod?: { distance: number; tileSize?: number };\n}\n\n/**\n * A whole world as plain JSON — every field is data, so manifests can be\n * stored, diffed, sent over the network, or edited in a tool.\n */\nexport interface SceneManifest {\n seed?: number;\n palette?: keyof typeof PALETTES;\n terrain?: {\n size?: number;\n resolution?: number;\n amplitude?: number;\n noiseScale?: number;\n octaves?: number;\n valleyFlatness?: number;\n };\n water?: { level: number; size?: number };\n /** Sky dome. Default true. */\n sky?: boolean;\n lighting?: LightingPreset;\n /** Fog preset, or false for none. Default 'haze'. */\n fog?: FogPreset | false;\n /** Animated day-night cycle. Off unless specified. */\n dayCycle?: { dayLength?: number; timeOfDay?: number };\n paths?: Array<{\n points: Array<{ x: number; z: number }>;\n width?: number;\n loop?: boolean;\n }>;\n village?: {\n center?: { x: number; z: number };\n radius?: number;\n houses?: number;\n lampLights?: number;\n tower?: boolean;\n ruin?: boolean;\n };\n scatters?: ManifestScatter[];\n /** Vegetation sway. Default on; false disables, or set the strength. */\n wind?: boolean | { strength?: number };\n}\n\nexport interface BuiltScene {\n /** Everything visual, ready to add to a scene (already added if one was passed). */\n group: Group;\n palette: Palette;\n terrain?: Terrain;\n water?: Water;\n sky?: Sky;\n rig: LightingRig;\n cycle?: DayCycle;\n paths: WorldPath[];\n village?: Village;\n scatters: ScatterResult[];\n /** Combined steering obstacles from the village and every scatter. */\n obstacles: Obstacle[];\n /** Ground height (terrain's, or 0 for flat scenes). */\n heightAt(x: number, z: number): number;\n /** Advance water, wind and the day cycle. Call from your frame loop. */\n update(dt: number): void;\n}\n\nconst PROP_FACTORIES: Record<ScatterPropType, (seed: number, palette: Palette) => Prop> = {\n tree: (seed, palette) => createTree({ seed, palette }),\n rock: (seed, palette) => createRock({ seed, palette }),\n bush: (seed, palette) => createBush({ seed, palette }),\n grass: (seed, palette) => createGrassTuft({ seed, palette }),\n crate: (seed, palette) => createCrate({ seed, palette }),\n fence: (seed, palette) => createFence({ seed, palette }),\n lamp: (seed, palette) => createLamp({ seed, palette }),\n};\n\n// Far-distance stand-ins used when a manifest scatter opts into LOD:\n// trees collapse to a single cone, bushes to a squat cone, grass vanishes.\nconst FAR_FACTORIES: Partial<Record<ScatterPropType, (seed: number, palette: Palette) => Prop>> = {\n tree: (seed, palette) => {\n const rng = new Rng(seed);\n const group = new Group();\n const cone = new Mesh(\n new CylinderGeometry(0, rng.range(1.0, 1.4), rng.range(2.6, 3.8), 5),\n new MeshStandardMaterial({ color: rng.pick(palette.foliage), flatShading: true })\n );\n cone.position.y = cone.geometry.parameters.height / 2 + 0.3;\n group.add(cone);\n return { object: group, obstacleRadius: 0 };\n },\n bush: (seed, palette) => {\n const rng = new Rng(seed);\n const group = new Group();\n const cone = new Mesh(\n new CylinderGeometry(0.1, rng.range(0.5, 0.7), rng.range(0.5, 0.8), 5),\n new MeshStandardMaterial({ color: rng.pick(palette.foliage), flatShading: true })\n );\n cone.position.y = 0.3;\n group.add(cone);\n return { object: group, obstacleRadius: 0 };\n },\n grass: () => ({ object: new Group(), obstacleRadius: 0 }),\n};\n\n/**\n * Compile a `SceneManifest` into a live world: terrain, water, sky,\n * lighting, fog, paths, a village, scatters and the day cycle — with all\n * the cross-feature wiring the forest demo does by hand applied\n * automatically (scatters stay ashore, off paths and out of the village;\n * the village avoids water and roads; village lamps and windows feed the\n * day cycle).\n *\n * ```ts\n * const world = buildScene(JSON.parse(manifestJson), scene);\n * game.onUpdate((t) => world.update(t.delta));\n * agent.addBehavior(new ObstacleAvoidance(() => world.obstacles));\n * ```\n */\nexport function buildScene(manifest: SceneManifest, scene?: Scene): BuiltScene {\n const seed = manifest.seed ?? 1;\n const palette = manifest.palette ? PALETTES[manifest.palette] : DEFAULT_PALETTE;\n const group = new Group();\n group.name = 'scena-scene';\n const updates: Array<(dt: number) => void> = [];\n\n // Ground and water.\n let terrain: Terrain | undefined;\n if (manifest.terrain) {\n terrain = createTerrain({\n ...manifest.terrain,\n seed,\n waterLevel: manifest.water?.level,\n palette,\n });\n group.add(terrain.mesh);\n }\n const heightAt = terrain ? terrain.heightAt : () => 0;\n\n let water: Water | undefined;\n if (manifest.water) {\n water = createWater({\n level: manifest.water.level,\n size: manifest.water.size ?? (terrain ? terrain.size * 1.4 : 200),\n palette,\n });\n group.add(water.mesh);\n updates.push((dt) => water!.update(dt));\n }\n const dryLand = terrain && water ? aboveWater(terrain, water, 0.3) : () => true;\n\n // Sky, lights, fog.\n let sky: Sky | undefined;\n if (manifest.sky ?? true) {\n sky = createSky({ palette });\n group.add(sky.mesh);\n }\n const rig = createLightingRig(manifest.lighting ?? 'day');\n group.add(rig.group);\n if (scene && manifest.fog !== false) applyFog(scene, manifest.fog ?? 'haze', palette);\n\n // Paths.\n const paths: WorldPath[] = (manifest.paths ?? []).map((spec) => {\n const path = createPath(spec.points, {\n surface: heightAt,\n width: spec.width,\n loop: spec.loop,\n palette,\n });\n group.add(path.mesh);\n return path;\n });\n const onAnyPath = (x: number, z: number): boolean => paths.some((p) => p.contains(x, z));\n\n // Village.\n let village: Village | undefined;\n if (manifest.village) {\n village = createVillage({\n ...manifest.village,\n seed: seed + 1,\n surface: heightAt,\n mask: (x, z) => dryLand(x, z) && !onAnyPath(x, z),\n palette,\n });\n group.add(village.group);\n }\n\n // Scatters, kept ashore / off roads / out of the village by default.\n const wind = manifest.wind ?? true;\n const scatters: ScatterResult[] = (manifest.scatters ?? []).map((spec, index) => {\n const inset = terrain ? terrain.size * 0.45 : 40;\n const avoidWater = spec.avoidWater ?? true;\n const avoidPaths = spec.avoidPaths ?? true;\n const result = scatter({\n seed: seed + 10 + index,\n area: spec.area ?? { min: { x: -inset, z: -inset }, max: { x: inset, z: inset } },\n surface: heightAt,\n density: spec.density,\n count: spec.count,\n minSpacing: spec.minSpacing,\n clumpScale: spec.clumpScale,\n lod: spec.lod,\n items: spec.items.map((item): ScatterItem => {\n const far = spec.lod ? FAR_FACTORIES[item.type] : undefined;\n return {\n create: (rng) => PROP_FACTORIES[item.type](rng.int(1, 1e9), palette),\n createFar: far && ((rng) => far(rng.int(1, 1e9), palette)),\n weight: item.weight,\n variants: item.variants,\n scale: item.scale,\n };\n }),\n mask: (x, z, y) =>\n (spec.maxHeight === undefined || y < spec.maxHeight) &&\n (!avoidWater || dryLand(x, z)) &&\n (!avoidPaths || !onAnyPath(x, z)),\n keepOut: [\n ...(avoidPaths ? paths.flatMap((p) => p.keepOut) : []),\n ...(village ? village.keepOut : []),\n ],\n });\n group.add(result.group);\n if (wind !== false) {\n const sway: Wind = applyWind(result.group, {\n strength: typeof wind === 'object' ? wind.strength ?? 0.05 : 0.05,\n });\n updates.push((dt) => sway.update(dt));\n }\n return result;\n });\n\n // Day cycle last, so it can adopt the village's lamps and windows.\n let cycle: DayCycle | undefined;\n if (manifest.dayCycle) {\n cycle = createDayCycle({\n sky,\n rig,\n scene,\n lamps: village?.lamps,\n palette,\n dayLength: manifest.dayCycle.dayLength,\n timeOfDay: manifest.dayCycle.timeOfDay,\n });\n updates.push((dt) => cycle!.update(dt));\n }\n\n scene?.add(group);\n\n return {\n group,\n palette,\n terrain,\n water,\n sky,\n rig,\n cycle,\n paths,\n village,\n scatters,\n obstacles: [\n ...(village ? village.obstacles : []),\n ...scatters.flatMap((s) => s.obstacles),\n ],\n heightAt,\n update(dt) {\n for (const fn of updates) fn(dt);\n },\n };\n}\n","import {\n DynamicDrawUsage,\n Group,\n InstancedMesh,\n Matrix4,\n Mesh,\n Quaternion,\n Vector3,\n} from 'three';\nimport { Rng, valueNoise2 } from '../core/random';\nimport type { Obstacle, Prop } from '../core/types';\n\nexport interface ScatterItem {\n /** Prop factory, called once per visual variant with a seeded Rng. */\n create(rng: Rng): Prop;\n /**\n * Simplified far-distance factory for LOD (e.g. a single cone for a\n * tree). Only used when `ScatterOptions.lod` is set; items without one\n * stay full-detail at every distance.\n */\n createFar?(rng: Rng): Prop;\n /** Relative frequency among items. Default 1. */\n weight?: number;\n /** Distinct variants generated per item (visual variety). Default 4. */\n variants?: number;\n /** Per-instance uniform scale range. Default [0.8, 1.25]. */\n scale?: [number, number];\n}\n\nexport interface ScatterOptions {\n seed?: number;\n items: ScatterItem[];\n /** Placement region in the XZ plane. */\n area: { min: { x: number; z: number }; max: { x: number; z: number } };\n /** Ground height lookup; a number means flat ground. Default 0. */\n surface?: number | ((x: number, z: number) => number);\n /** Expected instances per square unit (thinned by density noise). */\n density?: number;\n /** Or an exact target count (before masks/spacing rejections). */\n count?: number;\n /** Veto function: return false to reject a candidate point. */\n mask?: (x: number, z: number, y: number) => boolean;\n /** Minimum distance between any two placements. Default 1.2. */\n minSpacing?: number;\n /** World-space circles to keep clear (paths, spawns, buildings). */\n keepOut?: Obstacle[] | { center: { x: number; z: number }; radius: number }[];\n /** Density-noise feature size in world units. Default 18. */\n clumpScale?: number;\n /**\n * Tile-based LOD: placements are bucketed into square tiles; tiles\n * beyond `distance` from the camera swap full-detail instances for the\n * items' `createFar` variants (with 10% hysteresis so tiles don't\n * flicker at the boundary). Call `result.update(camera)` each frame.\n */\n lod?: {\n /** Camera distance at which tiles switch to far variants. */\n distance: number;\n /** Tile side in world units. Default 16. */\n tileSize?: number;\n };\n}\n\nexport interface Placement {\n position: Vector3;\n rotationY: number;\n scale: number;\n itemIndex: number;\n}\n\nexport interface ScatterTile {\n center: { x: number; z: number };\n near: Group;\n far: Group;\n}\n\nexport interface ScatterResult {\n /** One InstancedMesh per template part — a handful of draw calls total. */\n group: Group;\n placements: Placement[];\n /** World-space steering obstacles for everything with a footprint. */\n obstacles: Obstacle[];\n count: number;\n /** LOD tiles (present when `lod` was requested). */\n tiles?: ScatterTile[];\n /** Re-evaluate tile LOD against the camera (present when `lod` was requested). */\n update?(camera: { position: Vector3 }): void;\n}\n\n/**\n * Populate an area with seeded, instanced props: \"empty plane → forest\"\n * in one call. Placement uses density noise for natural clumping, a\n * spatial hash for minimum spacing, and masks/keep-out circles for\n * exclusion. Rendering merges every placement into InstancedMeshes — a\n * few draw calls for thousands of props.\n *\n * ```ts\n * const forest = scatter({\n * seed: 7,\n * area: { min: { x: -40, z: -40 }, max: { x: 40, z: 40 } },\n * surface: terrain.heightAt,\n * density: 0.04,\n * items: [\n * { create: (rng) => createTree({ seed: rng.int(1, 1e9) }), weight: 3 },\n * { create: (rng) => createRock({ seed: rng.int(1, 1e9) }) },\n * ],\n * mask: (x, z, y) => y > 0.5 && y < 5, // between shore and peaks\n * keepOut: [{ center: village, radius: 12 }],\n * });\n * scene.add(forest.group);\n * agent.addBehavior(new ObstacleAvoidance(() => forest.obstacles));\n * ```\n */\nexport function scatter(options: ScatterOptions): ScatterResult {\n const seed = options.seed ?? 1;\n const rng = new Rng(seed);\n const { area } = options;\n const width = area.max.x - area.min.x;\n const depth = area.max.z - area.min.z;\n const surface = options.surface ?? 0;\n const heightAt =\n typeof surface === 'number' ? () => surface : (x: number, z: number) => surface(x, z);\n const minSpacing = options.minSpacing ?? 1.2;\n const clumpScale = options.clumpScale ?? 18;\n const attempts = options.count ?? Math.round(width * depth * (options.density ?? 0.03));\n\n const keepOut = (options.keepOut ?? []).map((k) => ({\n x: k.center.x,\n z: 'z' in k.center ? k.center.z : (k.center as { z: number }).z,\n radius: k.radius,\n }));\n\n // Weighted item choice.\n const weights = options.items.map((i) => i.weight ?? 1);\n const totalWeight = weights.reduce((a, b) => a + b, 0);\n const pickItem = (): number => {\n let r = rng.next() * totalWeight;\n for (let i = 0; i < weights.length; i++) {\n r -= weights[i];\n if (r <= 0) return i;\n }\n return weights.length - 1;\n };\n\n // Spatial hash for min-spacing rejection.\n const cell = Math.max(minSpacing, 0.001);\n const occupied = new Map<string, Array<{ x: number; z: number }>>();\n const tooClose = (x: number, z: number): boolean => {\n const cx = Math.floor(x / cell);\n const cz = Math.floor(z / cell);\n for (let dx = -1; dx <= 1; dx++) {\n for (let dz = -1; dz <= 1; dz++) {\n const bucket = occupied.get(`${cx + dx},${cz + dz}`);\n if (!bucket) continue;\n for (const p of bucket) {\n if ((p.x - x) ** 2 + (p.z - z) ** 2 < minSpacing * minSpacing) return true;\n }\n }\n }\n return false;\n };\n\n const placements: Placement[] = [];\n for (let i = 0; i < attempts; i++) {\n const x = rng.range(area.min.x, area.max.x);\n const z = rng.range(area.min.z, area.max.z);\n // Density noise: clumps and clearings instead of uniform confetti.\n if (valueNoise2(x / clumpScale, z / clumpScale, seed + 77) < rng.range(0.15, 0.55)) continue;\n if (keepOut.some((k) => (k.x - x) ** 2 + (k.z - z) ** 2 < k.radius * k.radius)) continue;\n if (tooClose(x, z)) continue;\n const y = heightAt(x, z);\n if (options.mask && !options.mask(x, z, y)) continue;\n\n const itemIndex = pickItem();\n const [minScale, maxScale] = options.items[itemIndex].scale ?? [0.8, 1.25];\n placements.push({\n position: new Vector3(x, y, z),\n rotationY: rng.range(0, Math.PI * 2),\n scale: rng.range(minScale, maxScale),\n itemIndex,\n });\n const key = `${Math.floor(x / cell)},${Math.floor(z / cell)}`;\n let bucket = occupied.get(key);\n if (!bucket) occupied.set(key, (bucket = []));\n bucket.push({ x, z });\n }\n\n // Build variants per item, bucket placements per variant, then emit one\n // InstancedMesh per (variant, mesh part).\n const group = new Group();\n group.name = 'scatter';\n const obstacles: Obstacle[] = [];\n const placementMatrix = new Matrix4();\n const composed = new Matrix4();\n const quaternion = new Quaternion();\n const up = new Vector3(0, 1, 0);\n const scaleVector = new Vector3();\n\n const emit = (variant: Prop, list: Placement[], parent: Group): void => {\n variant.object.updateMatrixWorld(true);\n variant.object.traverse((child) => {\n if (!(child instanceof Mesh)) return;\n const instanced = new InstancedMesh(child.geometry, child.material, list.length);\n instanced.instanceMatrix.setUsage(DynamicDrawUsage);\n list.forEach((placement, index) => {\n quaternion.setFromAxisAngle(up, placement.rotationY);\n scaleVector.setScalar(placement.scale);\n placementMatrix.compose(placement.position, quaternion, scaleVector);\n composed.multiplyMatrices(placementMatrix, child.matrixWorld);\n instanced.setMatrixAt(index, composed);\n });\n instanced.instanceMatrix.needsUpdate = true;\n parent.add(instanced);\n });\n };\n\n // LOD tiles: near/far group pairs, lazily created per occupied tile.\n const tileSize = options.lod?.tileSize ?? 16;\n const tileMap = new Map<string, ScatterTile>();\n const tileFor = (x: number, z: number): ScatterTile => {\n const tx = Math.floor(x / tileSize);\n const tz = Math.floor(z / tileSize);\n const key = `${tx},${tz}`;\n let tile = tileMap.get(key);\n if (!tile) {\n tile = {\n center: { x: (tx + 0.5) * tileSize, z: (tz + 0.5) * tileSize },\n near: new Group(),\n far: new Group(),\n };\n tile.far.visible = false;\n group.add(tile.near, tile.far);\n tileMap.set(key, tile);\n }\n return tile;\n };\n\n options.items.forEach((item, itemIndex) => {\n const variantCount = item.variants ?? 4;\n const variants: Prop[] = [];\n for (let v = 0; v < variantCount; v++) variants.push(item.create(rng.fork()));\n const useLod = options.lod !== undefined && item.createFar !== undefined;\n const farVariants: Prop[] = [];\n if (useLod) {\n for (let v = 0; v < variantCount; v++) farVariants.push(item.createFar!(rng.fork()));\n }\n\n const byVariant: Placement[][] = variants.map(() => []);\n for (const placement of placements) {\n if (placement.itemIndex !== itemIndex) continue;\n // Deterministic variant choice from position.\n const v = Math.abs(Math.floor(placement.position.x * 31 + placement.position.z * 17)) % variantCount;\n byVariant[v].push(placement);\n }\n\n variants.forEach((variant, v) => {\n const list = byVariant[v];\n if (list.length === 0) return;\n if (useLod) {\n // Split this variant's placements per tile, emit near + far pairs.\n const byTile = new Map<ScatterTile, Placement[]>();\n for (const placement of list) {\n const tile = tileFor(placement.position.x, placement.position.z);\n let bucket = byTile.get(tile);\n if (!bucket) byTile.set(tile, (bucket = []));\n bucket.push(placement);\n }\n for (const [tile, bucket] of byTile) {\n emit(variant, bucket, tile.near);\n emit(farVariants[v], bucket, tile.far);\n }\n } else {\n emit(variant, list, group);\n }\n if (variant.obstacleRadius > 0) {\n for (const placement of list) {\n obstacles.push({\n center: placement.position.clone(),\n radius: variant.obstacleRadius * placement.scale,\n });\n }\n }\n });\n });\n\n const result: ScatterResult = { group, placements, obstacles, count: placements.length };\n if (options.lod) {\n const tiles = [...tileMap.values()];\n const swapOut = options.lod.distance * 1.1; // hysteresis: no flicker\n const swapIn = options.lod.distance * 0.9;\n result.tiles = tiles;\n result.update = (camera) => {\n for (const tile of tiles) {\n const dx = camera.position.x - tile.center.x;\n const dz = camera.position.z - tile.center.z;\n const distance = Math.hypot(dx, dz);\n if (tile.near.visible && distance > swapOut) {\n tile.near.visible = false;\n tile.far.visible = true;\n } else if (!tile.near.visible && distance < swapIn) {\n tile.near.visible = true;\n tile.far.visible = false;\n }\n }\n };\n }\n return result;\n}\n","import { Vector3, type Object3D } from 'three';\nimport type { Obstacle } from '../core/types';\n\nexport interface Markers {\n /** `spawn_<name>` → world position. */\n spawns: Record<string, Vector3>;\n /** `route_<name>_<index>` → world positions ordered by index. */\n routes: Record<string, Vector3[]>;\n /** `obstacle_<name>` → steering obstacle (radius from the node's scale). */\n obstacles: Obstacle[];\n /** `keepout_<name>` → scatter keep-out circle (radius from scale). */\n keepOut: Array<{ center: { x: number; z: number }; radius: number }>;\n}\n\n/**\n * Extract gameplay markers from an object tree by naming convention — the\n * bridge between a DCC tool (Blender empties, glTF nodes) and SCENA/GAMA:\n *\n * - `spawn_player`, `spawn_boss` → named spawn points\n * - `route_patrol_0`, `route_patrol_1`, … → ordered patrol routes\n * - `obstacle_statue` → steering obstacle; radius = max(scale.x, scale.z)\n * - `keepout_plaza` → scatter keep-out circle; radius = max(scale.x, scale.z)\n *\n * Blender's duplicate suffixes (`.001`) are stripped, so `route_a_0.001`\n * still parses. Positions are world-space (the tree is updated first).\n *\n * ```ts\n * const gltf = await new GLTFLoader().loadAsync('level.glb');\n * const markers = extractMarkers(gltf.scene);\n * player.position.copy(markers.spawns.player);\n * guard.addBehavior(new FollowPath(new Path(markers.routes.patrol, true), 1.5));\n * scatter({ ..., keepOut: markers.keepOut });\n * ```\n */\nexport function extractMarkers(root: Object3D): Markers {\n root.updateWorldMatrix(true, true);\n const spawns: Record<string, Vector3> = {};\n const routePoints: Record<string, Array<{ index: number; position: Vector3 }>> = {};\n const obstacles: Obstacle[] = [];\n const keepOut: Array<{ center: { x: number; z: number }; radius: number }> = [];\n\n root.traverse((node) => {\n const name = node.name.replace(/\\.\\d+$/, ''); // Blender's `.001` suffixes\n const match = /^(spawn|route|obstacle|keepout)_(.+)$/.exec(name);\n if (!match) return;\n const [, kind, rest] = match;\n const position = node.getWorldPosition(new Vector3());\n const radius = Math.max(node.scale.x, node.scale.z);\n\n if (kind === 'spawn') {\n spawns[rest] = position;\n } else if (kind === 'route') {\n const step = /^(.*)_(\\d+)$/.exec(rest);\n const routeName = step ? step[1] : rest;\n const index = step ? parseInt(step[2], 10) : 0;\n (routePoints[routeName] ??= []).push({ index, position });\n } else if (kind === 'obstacle') {\n obstacles.push({ center: position, radius });\n } else {\n keepOut.push({ center: { x: position.x, z: position.z }, radius });\n }\n });\n\n const routes: Record<string, Vector3[]> = {};\n for (const [name, points] of Object.entries(routePoints)) {\n routes[name] = points.sort((a, b) => a.index - b.index).map((p) => p.position);\n }\n return { spawns, routes, obstacles, keepOut };\n}\n"],"mappings":"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","names":["Group","IcosahedronGeometry","Mesh","MeshStandardMaterial","IcosahedronGeometry","Mesh","MeshStandardMaterial","Group","Group","Mesh","MeshStandardMaterial","Group","MeshStandardMaterial","Mesh","BoxGeometry","CylinderGeometry","Group","Mesh","MeshStandardMaterial","Group","MeshStandardMaterial","Mesh","CylinderGeometry","BoxGeometry","BoxGeometry","CylinderGeometry","Group","Mesh","MeshStandardMaterial","Group","MeshStandardMaterial","Mesh","CylinderGeometry","BoxGeometry","ConeGeometry","Group","IcosahedronGeometry","Mesh","MeshStandardMaterial","Group","MeshStandardMaterial","Mesh","ConeGeometry","IcosahedronGeometry","BoxGeometry","BufferAttribute","CylinderGeometry","Group","Mesh","MeshStandardMaterial","BufferAttribute","Group","MeshStandardMaterial","Mesh","BoxGeometry","CylinderGeometry","BufferAttribute","Mesh","MeshStandardMaterial","BufferAttribute","Mesh","MeshStandardMaterial","Color","Mesh","SphereGeometry","Color","Mesh","SphereGeometry","Group","Group","Mesh","MeshStandardMaterial","PlaneGeometry","PlaneGeometry","Mesh","MeshStandardMaterial","Color","PointLight","PointLight","Color","Mesh","BufferAttribute","BufferGeometry","Mesh","MeshStandardMaterial","Vector3","Vector3","BufferGeometry","BufferAttribute","Mesh","MeshStandardMaterial","Group","Group","BoxGeometry","CylinderGeometry","Group","Mesh","MeshStandardMaterial","PointLight","SphereGeometry","Vector3","Group","Vector3","Mesh","BoxGeometry","MeshStandardMaterial","CylinderGeometry","SphereGeometry","PointLight","CylinderGeometry","Group","Mesh","MeshStandardMaterial","Group","InstancedMesh","Matrix4","Mesh","Vector3","maxScale","Vector3","Group","Matrix4","Mesh","InstancedMesh","Group","Mesh","CylinderGeometry","MeshStandardMaterial","Vector3"]}