128 lines
4.2 KiB
TypeScript
128 lines
4.2 KiB
TypeScript
import { describe, expect, test } from "vitest"
|
|
import { DRLGROOMTILE_GetTileCache } from "../src/game/wilderness.ts"
|
|
import { Rng } from "../src/game/rng.ts"
|
|
import type { Dt1, Dt1Tile } from "../src/formats/dt1.ts"
|
|
|
|
function makeMockDt1(tiles: (Partial<Dt1Tile> & { rarity?: number; Rarity?: number })[]): Dt1 {
|
|
return {
|
|
warnings: [],
|
|
versionMajor: 7,
|
|
versionMinor: 6,
|
|
tiles: tiles.map(t => ({
|
|
direction: 0,
|
|
height: -80,
|
|
width: 160,
|
|
type: t.type ?? 0,
|
|
style: t.style ?? 0,
|
|
sequence: t.sequence ?? 0,
|
|
materialFlags: 0,
|
|
roofHeight: 0,
|
|
animated: t.animated ?? 0,
|
|
rarityFrameIndex: t.rarityFrameIndex ?? 1,
|
|
subTileFlags: [],
|
|
minBlockY: 0,
|
|
bitmapHeight: 80,
|
|
blocks: [],
|
|
...t,
|
|
})),
|
|
}
|
|
}
|
|
|
|
describe("DRLGROOMTILE_GetTileCache deterministic seed (Issue #78)", () => {
|
|
const dt1 = makeMockDt1([
|
|
{ type: 0, style: 0, sequence: 0, rarityFrameIndex: 20 },
|
|
{ type: 0, style: 0, sequence: 1, rarityFrameIndex: 30 },
|
|
{ type: 0, style: 0, sequence: 2, rarityFrameIndex: 50 },
|
|
])
|
|
|
|
describe("same seed produces identical result", () => {
|
|
test("same integer seed produces identical tile selection across multiple invocations", () => {
|
|
const query1 = { type: 0, seed: 12345 }
|
|
const query2 = { type: 0, seed: 12345 }
|
|
|
|
const res1 = DRLGROOMTILE_GetTileCache([dt1], 1, query1)
|
|
const res2 = DRLGROOMTILE_GetTileCache([dt1], 1, query2)
|
|
|
|
expect(res1).not.toBeNull()
|
|
expect(res2).not.toBeNull()
|
|
expect(res1).toEqual(res2)
|
|
})
|
|
|
|
test("same coordinates and seed produce identical tile selection", () => {
|
|
const resA = DRLGROOMTILE_GetTileCache([dt1], 1, { type: 0, seed: 99999, x: 15, y: 27 })
|
|
const resB = DRLGROOMTILE_GetTileCache([dt1], 1, { type: 0, seed: 99999, x: 15, y: 27 })
|
|
|
|
expect(resA).not.toBeNull()
|
|
expect(resA).toEqual(resB)
|
|
})
|
|
|
|
test("same direct fractional roll produces identical tile selection", () => {
|
|
const resA = DRLGROOMTILE_GetTileCache([dt1], 1, { type: 0, seed: 0.45 })
|
|
const resB = DRLGROOMTILE_GetTileCache([dt1], 1, { type: 0, seed: 0.45 })
|
|
|
|
expect(resA).not.toBeNull()
|
|
expect(resA).toEqual(resB)
|
|
})
|
|
|
|
test("identical Rng seeds produce identical sequences of tile selections", () => {
|
|
const rng1 = new Rng(88888)
|
|
const rng2 = new Rng(88888)
|
|
|
|
const results1 = Array.from({ length: 20 }, () =>
|
|
DRLGROOMTILE_GetTileCache([dt1], 1, { type: 0, seed: rng1 })?.sequence,
|
|
)
|
|
const results2 = Array.from({ length: 20 }, () =>
|
|
DRLGROOMTILE_GetTileCache([dt1], 1, { type: 0, seed: rng2 })?.sequence,
|
|
)
|
|
|
|
expect(results1).toEqual(results2)
|
|
})
|
|
})
|
|
|
|
describe("different seeds produce varying selections over multiple runs", () => {
|
|
test("varying integer seeds select different tiles across runs", () => {
|
|
const seenSequences = new Set<number>()
|
|
|
|
for (let s = 0; s < 50; s += 1) {
|
|
const res = DRLGROOMTILE_GetTileCache([dt1], 1, { type: 0, seed: s * 1000 + 7 })
|
|
if (res !== null) {
|
|
seenSequences.add(res.sequence)
|
|
}
|
|
}
|
|
|
|
// All 3 candidate sequences (0, 1, 2) should be selected across 50 distinct seeds
|
|
expect(seenSequences.size).toBe(3)
|
|
expect(seenSequences.has(0)).toBe(true)
|
|
expect(seenSequences.has(1)).toBe(true)
|
|
expect(seenSequences.has(2)).toBe(true)
|
|
})
|
|
|
|
test("varying coordinates with same seed select different tiles", () => {
|
|
const seenSequences = new Set<number>()
|
|
|
|
for (let x = 0; x < 50; x += 1) {
|
|
const res = DRLGROOMTILE_GetTileCache([dt1], 1, { type: 0, seed: 12345, x, y: 0 })
|
|
if (res !== null) {
|
|
seenSequences.add(res.sequence)
|
|
}
|
|
}
|
|
|
|
expect(seenSequences.size).toBeGreaterThan(1)
|
|
})
|
|
|
|
test("consecutive draws from a single Rng produce varying selections", () => {
|
|
const rng = new Rng(42)
|
|
const seenSequences = new Set<number>()
|
|
|
|
for (let i = 0; i < 50; i += 1) {
|
|
const res = DRLGROOMTILE_GetTileCache([dt1], 1, { type: 0, seed: rng })
|
|
if (res !== null) {
|
|
seenSequences.add(res.sequence)
|
|
}
|
|
}
|
|
|
|
expect(seenSequences.size).toBe(3)
|
|
})
|
|
})
|
|
})
|