148 lines
4.3 KiB
TypeScript
148 lines
4.3 KiB
TypeScript
import { resolveUnsetSize, UnresolvedLevelSizeError } from '../src/game/wilderness.ts'
|
|
import type { WildernessPiece, WildernessRequest } from '../src/game/wilderness.ts'
|
|
import type { Ds1, Ds1Cell } from '../src/formats/ds1.ts'
|
|
|
|
function makeMockDs1(width: number, height: number): Ds1 {
|
|
const cells: Ds1Cell[][] = []
|
|
for (let y = 0; y < height; y += 1) {
|
|
const row: Ds1Cell[] = []
|
|
for (let x = 0; x < width; x += 1) {
|
|
row.push({
|
|
walls: [],
|
|
floors: [{ prop1: 2, sequence: 0, style: 1, unknown1: 0, unknown2: 0, hidden: false }],
|
|
shadows: [],
|
|
substitutions: [],
|
|
})
|
|
}
|
|
cells.push(row)
|
|
}
|
|
return {
|
|
version: 7,
|
|
width,
|
|
height,
|
|
act: 5,
|
|
substitutionType: 0,
|
|
wallLayers: 1,
|
|
floorLayers: 1,
|
|
cells,
|
|
objects: [],
|
|
npcPathOffset: null,
|
|
}
|
|
}
|
|
|
|
console.log('=== STARTING ADVERSARIAL STRESS TEST FOR resolveUnsetSize ===')
|
|
|
|
let failures = 0
|
|
|
|
function assert(condition: boolean, msg: string) {
|
|
if (!condition) {
|
|
console.error(`FAIL: ${msg}`)
|
|
failures++
|
|
} else {
|
|
console.log(`PASS: ${msg}`)
|
|
}
|
|
}
|
|
|
|
// 1. Anti-silent failure: Empty pieces throws UnresolvedLevelSizeError
|
|
try {
|
|
resolveUnsetSize({
|
|
levelId: 111,
|
|
levelName: 'Act 5 - Barricade 1',
|
|
levelTypeName: 'Act 5 - Barricade',
|
|
sizeX: -1,
|
|
sizeY: -1,
|
|
subType: 10,
|
|
subTheme: 0,
|
|
seed: 12345,
|
|
pieces: [],
|
|
substitutions: [],
|
|
})
|
|
assert(false, 'Expected empty pieces to throw UnresolvedLevelSizeError')
|
|
} catch (err) {
|
|
assert(err instanceof UnresolvedLevelSizeError, 'Empty pieces throws instance of UnresolvedLevelSizeError')
|
|
assert((err as Error).message.includes('Level 111 (Act 5 - Barricade 1)'), 'Error message contains level info')
|
|
}
|
|
|
|
// 2. Anti-silent failure: Non-barricade pieces throw UnresolvedLevelSizeError
|
|
try {
|
|
resolveUnsetSize({
|
|
levelId: 111,
|
|
levelName: 'Act 5 - Barricade 1',
|
|
levelTypeName: 'Act 5 - Barricade',
|
|
sizeX: -1,
|
|
sizeY: -1,
|
|
subType: 10,
|
|
subTheme: 0,
|
|
seed: 12345,
|
|
pieces: [
|
|
{ name: 'Act 5 - Siege 1', border: false, levels: [makeMockDs1(10, 10)] },
|
|
],
|
|
substitutions: [],
|
|
})
|
|
assert(false, 'Expected non-barricade pieces to throw UnresolvedLevelSizeError')
|
|
} catch (err) {
|
|
assert(err instanceof UnresolvedLevelSizeError, 'Non-barricade pieces throw instance of UnresolvedLevelSizeError')
|
|
}
|
|
|
|
// 3. Fuzzing pieces dimensions: 10,000 random dimensions test
|
|
let allBoundsHold = true
|
|
let allAspectRatiosHold = true
|
|
for (let i = 0; i < 10000; i++) {
|
|
const randW1 = Math.floor(Math.random() * 2000) - 500 // -500 to 1500
|
|
const randH1 = Math.floor(Math.random() * 2000) - 500
|
|
const randW2 = Math.floor(Math.random() * 2000) - 500
|
|
const randH2 = Math.floor(Math.random() * 2000) - 500
|
|
|
|
const res = resolveUnsetSize({
|
|
levelId: 111,
|
|
levelName: 'Act 5 - Barricade 1',
|
|
levelTypeName: 'Act 5 - Barricade',
|
|
sizeX: -1,
|
|
sizeY: -1,
|
|
subType: 10,
|
|
subTheme: 0,
|
|
seed: i,
|
|
pieces: [
|
|
{ name: 'Act 5 - Barricade Entrance', border: false, levels: [makeMockDs1(randW1, randH1)] },
|
|
{ name: 'Act 5 - Barricade Exit', border: false, levels: [makeMockDs1(randW2, randH2)] },
|
|
],
|
|
substitutions: [],
|
|
})
|
|
|
|
if (res.sizeX < 48 || res.sizeX > 64 || res.sizeY < 160 || res.sizeY > 192) {
|
|
allBoundsHold = false
|
|
console.error(`Bounds failure at iteration ${i}: sizeX=${res.sizeX}, sizeY=${res.sizeY}`)
|
|
break
|
|
}
|
|
if (res.sizeY <= res.sizeX || (res.sizeY / res.sizeX) < 2.5) {
|
|
allAspectRatiosHold = false
|
|
console.error(`Aspect ratio failure at iteration ${i}: sizeX=${res.sizeX}, sizeY=${res.sizeY}`)
|
|
break
|
|
}
|
|
}
|
|
assert(allBoundsHold, '10,000 random input tests: sizeX in [48..64] and sizeY in [160..192] strictly hold')
|
|
assert(allAspectRatiosHold, '10,000 random input tests: sizeY > sizeX and aspect ratio >= 2.5 strictly hold')
|
|
|
|
// 4. Overrides
|
|
const overrideRes = resolveUnsetSize({
|
|
levelId: 111,
|
|
levelName: 'Act 5 - Barricade 1',
|
|
levelTypeName: 'Act 5 - Barricade',
|
|
sizeX: -1,
|
|
sizeY: -1,
|
|
sizeOverride: { x: 72, y: 144 },
|
|
subType: 10,
|
|
subTheme: 0,
|
|
seed: 999,
|
|
pieces: [],
|
|
substitutions: [],
|
|
})
|
|
assert(overrideRes.sizeX === 72 && overrideRes.sizeY === 144, 'sizeOverride is respected exactly')
|
|
|
|
if (failures > 0) {
|
|
console.error(`\nFAILED: ${failures} assertions failed!`)
|
|
process.exit(1)
|
|
} else {
|
|
console.log('\nSUCCESS: All adversarial checks passed!')
|
|
}
|