138 lines
4.5 KiB
TypeScript
138 lines
4.5 KiB
TypeScript
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)
|
|
})
|
|
})
|