import { describe, expect, test } from "vitest" import { isClosedBorder, selectBorderVariant, getPerimeterOpenings, SPECIAL_PRESETS_BY_LEVEL, generateWilderness, } from "../src/game/wilderness.ts" import type { WildernessPiece } from "../src/game/wilderness.ts" import { Rng } from "../src/game/rng.ts" import type { Ds1, Ds1Cell } from "../src/formats/ds1.ts" function makeMockDs1(width: number, height: number, hasGapInWalls: boolean): Ds1 { const cells: Ds1Cell[][] = [] for (let y = 0; y < height; y += 1) { const row: Ds1Cell[] = [] for (let x = 0; x < width; x += 1) { const isGap = hasGapInWalls && x === Math.floor(width / 2) row.push({ walls: isGap ? [] : [{ prop1: 2, sequence: 0, style: 1, type: 0, unknown1: 0, unknown2: 0, hidden: false }], floors: [{ prop1: 2, sequence: 0, style: 1, unknown1: 0, unknown2: 0, hidden: false }], shadows: [], substitutions: [], }) } cells.push(row) } return { version: 18, width, height, act: 1, substitutionType: 0, wallLayers: 1, floorLayers: 1, cells, objects: [], npcPathOffset: null, } } describe("Wilderness Features & Border Rules", () => { test("isClosedBorder identifies continuous vs open wall presets", () => { const closed = makeMockDs1(8, 8, false) const open = makeMockDs1(8, 8, true) expect(isClosedBorder(closed, "south")).toBe(true) expect(isClosedBorder(closed, "north")).toBe(true) expect(isClosedBorder(open, "south")).toBe(false) expect(isClosedBorder(open, "north")).toBe(false) }) test("getPerimeterOpenings enforces 0 exits for Cow Level and 1 entrance/1 exit for Blood Moor", () => { const cowOpenings = getPerimeterOpenings(39, 10, 10) expect(cowOpenings.size).toBe(0) const bloodMoorOpenings = getPerimeterOpenings(2, 10, 10) expect(bloodMoorOpenings.size).toBe(2) expect(bloodMoorOpenings.has("5,9")).toBe(true) expect(bloodMoorOpenings.has("9,5")).toBe(true) }) test("selectBorderVariant picks open variant for openings and closed variant for closed walls", () => { const closedDs1 = makeMockDs1(8, 8, false) const openDs1 = makeMockDs1(8, 8, true) const piece: WildernessPiece = { name: "Act 1 - Wild Border 1", border: true, levels: [closedDs1, openDs1], } const rng = new Rng(12345) const pickedOpen = selectBorderVariant(piece, "south", true, rng) expect(isClosedBorder(pickedOpen, "south")).toBe(false) const pickedClosed = selectBorderVariant(piece, "south", false, rng) expect(isClosedBorder(pickedClosed, "south")).toBe(true) }) test("SPECIAL_PRESETS_BY_LEVEL contains stone walls and river presets", () => { const bloodMoorPresets = SPECIAL_PRESETS_BY_LEVEL[2] expect(bloodMoorPresets).toBeDefined() expect(bloodMoorPresets).toContain("Act 1 - Corral Fill") expect(bloodMoorPresets).toContain("Act 1 - Fence Fill 4") expect(bloodMoorPresets).toContain("Act 1 - River Upper") expect(bloodMoorPresets).toContain("Act 1 - Bridge") const cowPresets = SPECIAL_PRESETS_BY_LEVEL[39] expect(cowPresets).toBeDefined() expect(cowPresets).toContain("Act 1 - Corral Fill") expect(cowPresets).toContain("Act 1 - Fence Fill 4") expect(cowPresets).toContain("Act 1 - Fence Fill 5") expect(cowPresets).toContain("Act 1 - Bivouac") expect(cowPresets).toContain("Act 1 - Pond") }) test("generateWilderness generates Level 2 with river or pond deterministically by seed", () => { const closedDs1 = makeMockDs1(8, 8, false) const piece: WildernessPiece = { name: "Act 1 - Wild Border 1", border: true, levels: [closedDs1], } const riverPiece: WildernessPiece = { name: "Act 1 - River Upper", border: false, levels: [closedDs1], } const pondPiece: WildernessPiece = { name: "Act 1 - Pond", border: false, levels: [closedDs1], } const corralPiece: WildernessPiece = { name: "Act 1 - Corral Fill", border: false, levels: [closedDs1], } const result = generateWilderness({ levelId: 2, levelName: "Blood Moor", levelTypeName: "Act 1 - Wilderness", sizeX: 80, sizeY: 80, subType: 6, subTheme: 0, seed: 12345, pieces: [piece, riverPiece, pondPiece, corralPiece], substitutions: [], }) expect(result.stats.blockGrid).toEqual({ width: 10, height: 10 }) expect(result.level.width).toBe(80) expect(result.level.height).toBe(80) }) })