diablo2-web/tests/tile-cache-seed.test.ts

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)
})
})
})