/** * Milestone 1 Empirical Stress Test Verification Script * * Covers: * 1. PRNG stream determinism across 50 diverse seeds for M5 simulation, snapshot/restore, and lockstep. * 2. 100,000 drops across Normal, Nightmare, and Hell difficulty levels using embedded drop tables without exceptions. * 3. Exact statistical verification of base upgrade divisors from DifficultyLevels.txt across 100,000 Monte Carlo trials per tier. * 4. GameEngine fail-fast verification on corrupt / missing data. * * Usage: npx tsx scripts/verify-challenger-m1-stress.ts */ import { createWorld, spawnMonsters, tickCombat, damageMonster } from '../src/game/combat.ts' import type { CombatOptions, MonsterStats } from '../src/game/combat.ts' import { Inventory, goldItem, createItem } from '../src/game/items.ts' import type { Affix, ItemBase, Item } from '../src/game/items.ts' import { QuestLog } from '../src/game/quests.ts' import type { QuestDef } from '../src/game/quests.ts' import { Rng } from '../src/game/rng.ts' import { D2Rng } from '../src/game/d2-rng.ts' import { captureSnapshot, parseSnapshot, restoreSnapshot, serializeSnapshot, } from '../src/game/save.ts' import { LockstepSession } from '../src/net/lockstep.ts' import type { InputFrame, LockstepSimulation } from '../src/net/lockstep.ts' import { parseTable } from '../src/game/tables.ts' import { monsterStatsFromTable } from '../src/game/combat.ts' import { getEmbeddedDropTables } from '../src/game/embedded-drop-tables.ts' import { executeDropPipeline } from '../src/game/drop-pipeline.ts' import { getMonsterTreasureClass, type Difficulty } from '../src/game/monsters.ts' import { GameEngine, type GameEngineOptions } from '../src/game/engine.ts' import { rollBaseUpgrade, type UpgradableItemBase } from '../src/game/item-upgrade.ts' // --- Setup M5 simulation helpers --- const stats: MonsterStats[] = monsterStatsFromTable(parseTable([ 'Id\tName\tHP\tDamage\tCooldownTicks\tReach\tAggroRadius\tSpeed\tXP', 'fallen\tFallen\t12\t3\t24\t36\t400\t80\t8', 'zombie\tZombie\t30\t6\t32\t40\t300\t50\t15', ].join('\n'))) const bases: ItemBase[] = [ { id: 'swd', name: 'Short Sword', kind: 'weapon', invWidth: 1, invHeight: 3, maxStack: 1, value: 30, damage: 5, defense: 0, tags: ['weap'], level: 1 }, { id: 'potion', name: 'Potion', kind: 'misc', invWidth: 1, invHeight: 1, maxStack: 5, value: 20, damage: 0, defense: 0, tags: ['misc'], level: 1 }, ] const prefixes: Affix[] = [{ id: 'cruel', name: 'Cruel', kind: 'prefix', level: 1, itemTypes: ['weap'], modifiers: [{ stat: 'maxdamage', min: 2, max: 6 }] }] const suffixes: Affix[] = [{ id: 'might', name: 'of Might', kind: 'suffix', level: 1, itemTypes: [], modifiers: [{ stat: 'strength', min: 1, max: 3 }] }] const quests: QuestDef[] = [{ id: 'den', name: 'Den', description: '', monsterId: '*', killCount: 3, rewardXp: 40, rewardGold: 60 }] const options: CombatOptions = { playerSpeed: 180, playerReach: 48, playerCooldownTicks: 12, playerDamage: 6, playerManaPerAttack: 2, respawnTicks: 40, } const xpTable: readonly number[] = [0, 0, 1000] interface Game { world: ReturnType rng: Rng inventory: Inventory quests: QuestLog ground: { x: number; y: number; item: ReturnType }[] } function newGame(seed: number): Game { const world = createWorld(0, 0) spawnMonsters(world, stats, 5, { x: 200, y: 0 }, 200, { overlap: () => 0 }) return { world, rng: new Rng(seed), inventory: new Inventory(10, 4), quests: new QuestLog(quests), ground: [] } } function scriptedInput(tick: number): { movement: { x: number; y: number }; attack: boolean } { const phase = Math.floor(tick / 25) % 4 const movement = phase === 0 ? { x: 1, y: 0 } : phase === 1 ? { x: 0, y: 1 } : phase === 2 ? { x: -1, y: 0 } : { x: 0, y: -1 } return { movement, attack: tick % 5 === 0 } } function stepGame(game: Game, tick: number): void { const input = scriptedInput(tick) tickCombat(game.world, input, options, { overlap: () => 0 }, xpTable) for (const event of game.world.events) { if (event.kind !== 'kill') continue for (const reward of game.quests.recordKill(event.subjectId ?? '')) { game.world.player.xp += reward.xp game.inventory.add(goldItem(reward.gold)) } if (game.rng.chance(0.9)) { if (game.rng.chance(0.2)) { game.inventory.add(goldItem(game.rng.int(3, 25))) } else { const eligible = bases.filter(b => b.level <= game.world.player.level + 1) const base = game.rng.pick(eligible.length > 0 ? eligible : bases) if (base) { const item = createItem(base, prefixes, suffixes, game.rng, { level: game.world.player.level + 1 }) game.ground.push({ x: event.x, y: event.y, item }) } } } } if (game.ground.length > 0 && tick % 17 === 0) { const entry = game.ground.shift() if (entry !== undefined) game.inventory.add(entry.item) } if (input.attack && game.world.player.cooldown === 0) { game.world.monsters.forEach((monster, index) => { if (monster.state === 'dead') return if (Math.hypot(monster.x - game.world.player.x, monster.y - game.world.player.y) > 48) return damageMonster(game.world, index, options.playerDamage) }) } } function digest(game: Game): string { const round = (value: number): number => Math.round(value * 1000) return JSON.stringify({ tick: game.world.tick, kills: game.world.kills, rng: game.rng.seed, player: { x: round(game.world.player.x), y: round(game.world.player.y), hp: game.world.player.hp, mana: game.world.player.mana, xp: game.world.player.xp, level: game.world.player.level, cooldown: game.world.player.cooldown, }, monsters: game.world.monsters.map(m => [round(m.x), round(m.y), m.hp, m.state, m.cooldown, m.hitFlash, m.corpseTicks]), inventory: game.inventory.contents.map(entry => [entry.x, entry.y, entry.item.name, entry.item.stack, entry.item.value]), ground: game.ground.map(entry => [round(entry.x), round(entry.y), entry.item.name]), quests: game.quests.all.map(entry => [entry.def.id, entry.status, entry.kills]), }) } function asSimulation(game: Game): LockstepSimulation { return { advance: (inputs) => { const frame = inputs[0]! tickCombat(game.world, { movement: frame.movement, attack: frame.attack }, options, { overlap: () => 0 }, xpTable) if (frame.attack && game.world.player.cooldown === 0) { game.world.monsters.forEach((monster, index) => { if (monster.state === 'dead') return if (Math.hypot(monster.x - game.world.player.x, monster.y - game.world.player.y) > 48) return damageMonster(game.world, index, options.playerDamage) }) } }, hash: () => LockstepSession.digest(digest(game)), } } function frameFor(tick: number, attack?: boolean): InputFrame { const input = scriptedInput(tick) return { tick, movement: input.movement, attack: attack ?? input.attack, pickup: false, talk: false, skill: 0, } } async function main() { console.log('=== Challenger M1-2: Empirical Stress Testing ===\n') // -------------------------------------------------------------------------- // 1. M5 Determinism Across Seeds // -------------------------------------------------------------------------- console.log('--- 1. Testing PRNG Stream Determinism Across 50 Seeds ---') const testSeeds = [ 0, 1, 2, 3, 7, 11, 42, 100, 256, 1000, 0x1234, 0x5678, 0xabcd, 0xbeef, 0xdeadbeef, 0x7fffffff, 0x10000000, 0x01020304, 9999999, 123456789, ...Array.from({ length: 30 }, (_, i) => ((i * 1664525 + 1013904223) >>> 0) & 0x7fffffff), ] let snapshotPassCount = 0 let lockstepPassCount = 0 let desyncDetectionCount = 0 for (const seed of testSeeds) { // 1a. Snapshot & Restore Round-Trip & Continuation const original = newGame(seed) for (let tick = 0; tick < 200; tick += 1) stepGame(original, tick) const snapshot = captureSnapshot(original) const text = serializeSnapshot(snapshot) const parsed = parseSnapshot(text) const restored = restoreSnapshot(parsed, { inventory: (width, height, placed) => Inventory.restore(width, height, placed), quests: states => QuestLog.restore(quests, states), }) const restoredGame: Game = { ground: restored.ground.map(entry => ({ ...entry })), world: { ...original.world, ...restored.world, events: [], monsters: restored.world.monsters.map(m => ({ ...m })), }, rng: new Rng(restored.rngState), inventory: restored.inventory, quests: restored.quests, } for (let tick = 200; tick < 400; tick += 1) { stepGame(original, tick) stepGame(restoredGame, tick) } if (digest(original) === digest(restoredGame)) { snapshotPassCount++ } else { console.error(`Snapshot divergence for seed ${seed}!`) } // 1b. Lockstep Multi-Session Determinism (300 ticks) const sessionA = new LockstepSession({ peers: 1, inputDelayTicks: 2 }, asSimulation(newGame(seed))) const sessionB = new LockstepSession({ peers: 1, inputDelayTicks: 2 }, asSimulation(newGame(seed))) const hashesA: number[] = [] const hashesB: number[] = [] for (let tick = 0; tick < 300; tick += 1) { sessionA.submit(0, frameFor(tick)) sessionB.submit(0, frameFor(tick)) const a = sessionA.step() const b = sessionB.step() if (a.kind === 'stepped') hashesA.push(a.hash) if (b.kind === 'stepped') hashesB.push(b.hash) } if (hashesA.length === 300 && hashesB.length === 300 && hashesA.join(',') === hashesB.join(',')) { lockstepPassCount++ } else { console.error(`Lockstep divergence for seed ${seed}!`) } // 1c. Desync Detection Sensitivity const honestSession = new LockstepSession({ peers: 1, inputDelayTicks: 0 }, asSimulation(newGame(seed))) const tamperedSession = new LockstepSession({ peers: 1, inputDelayTicks: 0 }, asSimulation(newGame(seed))) honestSession.submit(0, frameFor(0, false)) tamperedSession.submit(0, frameFor(0, true)) const honestHash = honestSession.step() const tamperedHash = tamperedSession.step() if (honestHash.kind === 'stepped' && tamperedHash.kind === 'stepped') { const report = honestSession.compare({ tick: 0, hash: tamperedHash.hash }) if (report !== null && report.tick === 0) { desyncDetectionCount++ } else { console.error(`Desync not detected for seed ${seed}!`) } } } console.log(`Snapshot Roundtrip & 200-Tick Continuation: ${snapshotPassCount}/${testSeeds.length} seeds identical`) console.log(`Lockstep 300-Tick Multi-Session Parity: ${lockstepPassCount}/${testSeeds.length} seeds identical`) console.log(`Lockstep Desync Detection Sensitivity: ${desyncDetectionCount}/${testSeeds.length} seeds detected`) if (snapshotPassCount !== testSeeds.length || lockstepPassCount !== testSeeds.length || desyncDetectionCount !== testSeeds.length) { throw new Error('PRNG Stream Determinism stress test FAILED!') } console.log('✓ PRNG stream determinism across seeds VERIFIED.\n') // -------------------------------------------------------------------------- // 2. 100,000 Drops Across Normal, Nightmare, Hell // -------------------------------------------------------------------------- console.log('--- 2. Executing 100,000 Drops Across Normal, Nightmare, Hell ---') const dropTables = getEmbeddedDropTables() const monsterKindsList = Array.from(dropTables.monsterKinds.values()).filter( k => k.treasureClasses && k.treasureClasses.length > 0 && k.treasureClasses[0] !== '' ) const superUniquesList = Array.from(dropTables.superUniques.values()).filter( su => su.treasureClass && su.treasureClass !== '' ) console.log(`Loaded drop tables: ${dropTables.monsterKinds.size} monster kinds (${monsterKindsList.length} dropping), ${superUniquesList.length} superUniques`) interface DifficultyStats { totalDropsRequested: number totalItemsGenerated: number goldPiles: number equipment: number normalBases: number exceptionalBases: number eliteBases: number errors: number } const difficulties: Difficulty[] = ['normal', 'nightmare', 'hell'] const targetPerDiff = 35000 // 35,000 x 3 = 105,000 total drops! const diffStats: Record = { normal: { totalDropsRequested: 0, totalItemsGenerated: 0, goldPiles: 0, equipment: 0, normalBases: 0, exceptionalBases: 0, eliteBases: 0, errors: 0 }, nightmare: { totalDropsRequested: 0, totalItemsGenerated: 0, goldPiles: 0, equipment: 0, normalBases: 0, exceptionalBases: 0, eliteBases: 0, errors: 0 }, hell: { totalDropsRequested: 0, totalItemsGenerated: 0, goldPiles: 0, equipment: 0, normalBases: 0, exceptionalBases: 0, eliteBases: 0, errors: 0 }, } const overallRng = new D2Rng(0xCAFE1234, 0x5678ABCD) for (const diff of difficulties) { const stats = diffStats[diff] console.log(`Starting ${targetPerDiff} drops for difficulty: ${diff.toUpperCase()}...`) for (let i = 0; i < targetPerDiff; i++) { stats.totalDropsRequested++ const isSuperUnique = (i % 5 === 0) && superUniquesList.length > 0 let tcName = '' let mlvl = 1 let mType = 1 if (isSuperUnique) { const su = superUniquesList[i % superUniquesList.length]! tcName = typeof su.getTreasureClass === 'function' ? su.getTreasureClass(diff) : su.treasureClass mlvl = diff === 'normal' ? 15 : diff === 'nightmare' ? 55 : 85 mType = 3 } else { const kind = monsterKindsList[i % monsterKindsList.length]! mType = (i % 4) + 1 // 1: normal, 2: champ, 3: unique, 4: boss tcName = getMonsterTreasureClass(kind, diff, mType) mlvl = (i % 85) + 5 } if (!tcName) { continue } try { const items = executeDropPipeline(dropTables, { tcName, nLevel: mlvl, monsterType: mType, difficulty: diff, gamePlayers: (i % 8) + 1, partyPlayers: (i % 8) + 1, playerMf: (i % 10) * 30, // 0 to 270 MF playerGf: (i % 10) * 20, // 0 to 180 GF isBoss: mType === 4, monsterRng: overallRng, }) for (const item of items) { stats.totalItemsGenerated++ const isGold = item.base?.id === 'gold' || item.code?.trim() === 'gld' || (item as any).id === 'gold' if (isGold) { stats.goldPiles++ const amount = item.stack ?? item.value ?? 1 if (typeof amount !== 'number' || isNaN(amount) || amount <= 0) { throw new Error(`Invalid gold amount: ${amount}`) } } else { stats.equipment++ if (!item.name || item.name.trim() === '') { throw new Error(`Dropped item missing name: ${JSON.stringify(item)}`) } // Identify base tier const b = item.base as any if (b && b.normcode) { if (b.code === b.ultracode || b.id === b.ultracode) { stats.eliteBases++ } else if (b.code === b.ubercode || b.id === b.ubercode) { stats.exceptionalBases++ } else { stats.normalBases++ } } } } } catch (err) { stats.errors++ console.error(`Error rolling drop [diff=${diff}, tc=${tcName}, mlvl=${mlvl}, mType=${mType}]:`, err) throw err } } console.log(`Completed ${stats.totalDropsRequested} drop calls for ${diff}: generated ${stats.totalItemsGenerated} items (${stats.equipment} equip, ${stats.goldPiles} gold, ${stats.exceptionalBases} exceptional, ${stats.eliteBases} elite, ${stats.errors} errors).`) } const grandTotalDrops = diffStats.normal.totalDropsRequested + diffStats.nightmare.totalDropsRequested + diffStats.hell.totalDropsRequested const grandTotalItems = diffStats.normal.totalItemsGenerated + diffStats.nightmare.totalItemsGenerated + diffStats.hell.totalItemsGenerated console.log(`\nGrand Total: ${grandTotalDrops} drops requested, ${grandTotalItems} total items generated across 3 difficulties with 0 exceptions.`) // -------------------------------------------------------------------------- // 3. Base Item Upgrade Divisor Empirical Parity Check (Issue #412) // -------------------------------------------------------------------------- console.log('\n--- 3. Verifying Base Upgrade Divisors Against 1.13c DifficultyLevels.txt ---') // 3a. Verify DifficultyLevelsTable odds from embedded table const diffTable = dropTables.difficultyLevels console.log('Difficulty odds in table:') console.log(' Normal: ', diffTable.Normal) console.log(' Nightmare: ', diffTable.Nightmare) console.log(' Hell: ', diffTable.Hell) if (diffTable.Normal.uberCodeOddsNormal !== 0 || diffTable.Normal.ultraCodeOddsNormal !== 0) { throw new Error('Normal difficulty odds are non-zero!') } if (diffTable.Nightmare.uberCodeOddsNormal !== 10 || diffTable.Nightmare.uberCodeOddsGood !== 20 || diffTable.Nightmare.ultraCodeOddsNormal !== 0) { throw new Error('Nightmare difficulty odds mismatch 1.13c standard!') } if (diffTable.Hell.uberCodeOddsNormal !== 20 || diffTable.Hell.uberCodeOddsGood !== 40 || diffTable.Hell.ultraCodeOddsNormal !== 30 || diffTable.Hell.ultraCodeOddsGood !== 40) { throw new Error('Hell difficulty odds mismatch 1.13c standard!') } // 3b. Monte Carlo verification of rollBaseUpgrade across 100,000 trials per configuration const capNormal: UpgradableItemBase = { id: 'cap', name: 'Cap', kind: 'armor', invWidth: 2, invHeight: 2, maxStack: 1, value: 12, damage: 0, defense: 5, tags: ['helm'], level: 1, normcode: 'cap', ubercode: 'xap', ultracode: 'uap', } const warHatExceptional: UpgradableItemBase = { id: 'xap', name: 'War Hat', kind: 'armor', invWidth: 2, invHeight: 2, maxStack: 1, value: 800, damage: 0, defense: 53, tags: ['helm'], level: 34, normcode: 'cap', ubercode: 'xap', ultracode: 'uap', } const shakoElite: UpgradableItemBase = { id: 'uap', name: 'Shako', kind: 'armor', invWidth: 2, invHeight: 2, maxStack: 1, value: 2400, damage: 0, defense: 141, tags: ['helm'], level: 58, normcode: 'cap', ubercode: 'xap', ultracode: 'uap', } const lookup = (code: string): ItemBase | undefined => { const c = code.trim().toLowerCase() if (c === 'cap') return capNormal if (c === 'xap') return warHatExceptional if (c === 'uap') return shakoElite return undefined } const monteCarloTrials = 100000 const mcRng = new D2Rng(0x98765432) // Normal MC let normalUpgrades = 0 for (let i = 0; i < monteCarloTrials; i++) { const res = rollBaseUpgrade(capNormal, diffTable.Normal.uberCodeOddsNormal, diffTable.Normal.ultraCodeOddsNormal, mcRng, lookup) if (res.isUber) normalUpgrades++ } console.log(`Normal Monte Carlo (${monteCarloTrials} trials): ${normalUpgrades} upgrades (expected: exactly 0)`) if (normalUpgrades !== 0) throw new Error('Normal Monte Carlo produced non-zero upgrades!') // Nightmare Normal Monster MC: qf4 = 10, qf5 = 0 (Expected ~ 10/1024 = 0.009765625) let nmNormUpgrades = 0 let nmNormElites = 0 for (let i = 0; i < monteCarloTrials; i++) { const res = rollBaseUpgrade(capNormal, diffTable.Nightmare.uberCodeOddsNormal, diffTable.Nightmare.ultraCodeOddsNormal, mcRng, lookup) if (res.isUber) { nmNormUpgrades++ if (res.base.id === 'uap') nmNormElites++ } } const nmNormRate = nmNormUpgrades / monteCarloTrials console.log(`Nightmare Normal MC: ${nmNormUpgrades}/${monteCarloTrials} (${(nmNormRate * 100).toFixed(3)}%) exceptional upgrades, ${nmNormElites} elites`) if (nmNormElites !== 0) throw new Error('Nightmare Normal MC produced elite upgrades!') // 3-sigma check: p = 10/1024 = 0.009765625, sigma = sqrt(p * (1-p) / N) = 0.00031 const pNmNorm = 10 / 1024 const sigmaNmNorm = Math.sqrt(pNmNorm * (1 - pNmNorm) / monteCarloTrials) if (Math.abs(nmNormRate - pNmNorm) > 3.5 * sigmaNmNorm) { throw new Error(`Nightmare Normal upgrade rate out of 3-sigma bound! rate=${nmNormRate}, expected=${pNmNorm}`) } // Nightmare Boss MC: qf4 = 20, qf5 = 0 (Expected ~ 20/1024 = 0.01953125) let nmBossUpgrades = 0 for (let i = 0; i < monteCarloTrials; i++) { const res = rollBaseUpgrade(capNormal, diffTable.Nightmare.uberCodeOddsGood, diffTable.Nightmare.ultraCodeOddsGood, mcRng, lookup) if (res.isUber) nmBossUpgrades++ } const nmBossRate = nmBossUpgrades / monteCarloTrials console.log(`Nightmare Boss MC: ${nmBossUpgrades}/${monteCarloTrials} (${(nmBossRate * 100).toFixed(3)}%) exceptional upgrades`) const pNmBoss = 20 / 1024 const sigmaNmBoss = Math.sqrt(pNmBoss * (1 - pNmBoss) / monteCarloTrials) if (Math.abs(nmBossRate - pNmBoss) > 3.5 * sigmaNmBoss) { throw new Error(`Nightmare Boss upgrade rate out of 3-sigma bound! rate=${nmBossRate}, expected=${pNmBoss}`) } // Hell Boss MC: qf4 = 40, qf5 = 40 (Expected ~ 40/1024 = 0.0390625 for ultra, and when ultra fails, 40/1024 for uber) let hellBossExceptional = 0 let hellBossElite = 0 for (let i = 0; i < monteCarloTrials; i++) { const res = rollBaseUpgrade(capNormal, diffTable.Hell.uberCodeOddsGood, diffTable.Hell.ultraCodeOddsGood, mcRng, lookup) if (res.isUber) { if (res.base.id === 'uap') hellBossElite++ else if (res.base.id === 'xap') hellBossExceptional++ } } console.log(`Hell Boss MC: ${hellBossElite} elite (${((hellBossElite / monteCarloTrials) * 100).toFixed(3)}%), ${hellBossExceptional} exceptional (${((hellBossExceptional / monteCarloTrials) * 100).toFixed(3)}%)`) if (hellBossElite === 0 || hellBossExceptional === 0) { throw new Error('Hell Boss MC failed to produce both elite and exceptional upgrades!') } console.log('✓ Base item upgrade divisors strictly conform to 1.13c statistical distribution.\n') // -------------------------------------------------------------------------- // 4. GameEngine Fail-Fast Integrity Verification (Issue #413, #414) // -------------------------------------------------------------------------- console.log('--- 4. Verifying GameEngine Fail-Fast Invariants ---') const dummyTerrain = { widthPx: 1000, heightPx: 1000, overlap: () => 0, } const idleInput = { movement: { x: 0, y: 0 }, attacking: false, pickingUp: false, talking: false, saving: false, loading: false, digits: [], } function createTestEngine() { return new GameEngine(dummyTerrain, { spawn: { x: 0, y: 0 }, stats: [], xpTable: [0, 100, 200], dropTables, difficulty: 'normal', skills: [], npcDefs: [], questDefs: quests, combatOptions: {} as any, talkRadius: 50, pickupRadius: 50, inventoryCols: 10, inventoryRows: 4, }) } // 4a. Missing monsterLevel let missingMlvlCaught = false try { const engine = createTestEngine() engine.world.pendingKills = [ { kind: 'kill', subjectId: 'fallen1', x: 100, y: 100 } as any, ] engine.tick(idleInput) } catch (e: any) { if (e.message.includes('missing or invalid monsterLevel')) missingMlvlCaught = true } if (!missingMlvlCaught) throw new Error('Missing monsterLevel did not throw descriptive fail-fast error!') console.log(' ✓ Missing monsterLevel fails fast.') // 4b. Invalid/negative monsterLevel let negativeMlvlCaught = false try { const engine = createTestEngine() engine.world.pendingKills = [ { kind: 'kill', subjectId: 'fallen1', monsterLevel: -5, x: 100, y: 100 } as any, ] engine.tick(idleInput) } catch (e: any) { if (e.message.includes('missing or invalid monsterLevel')) negativeMlvlCaught = true } if (!negativeMlvlCaught) throw new Error('Negative monsterLevel did not throw descriptive fail-fast error!') console.log(' ✓ Negative monsterLevel fails fast.') // 4c. Unknown monster let unknownMonsterCaught = false try { const engine = createTestEngine() engine.world.pendingKills = [ { kind: 'kill', subjectId: 'nonexistent_creature_999', monsterLevel: 5, x: 100, y: 100 } as any, ] engine.tick(idleInput) } catch (e: any) { if (e.message.includes('unknown monster')) unknownMonsterCaught = true } if (!unknownMonsterCaught) throw new Error('Unknown monster did not throw descriptive fail-fast error!') console.log(' ✓ Unknown monster fails fast.') // 4d. Authentic empty TC critters (chicken, rat, bird1, bird2) must not throw and produce 0 drops for (const critterId of ['chicken', 'rat', 'bird1', 'bird2']) { const engine = createTestEngine() engine.world.pendingKills = [ { kind: 'kill', subjectId: critterId, monsterLevel: 1, x: 100, y: 100 } as any, ] engine.tick(idleInput) if (engine.ground.length !== 0) { throw new Error(`Critter ${critterId} dropped ${engine.ground.length} items (expected 0)!`) } } console.log(' ✓ Authentic critters drop 0 items without throwing.') console.log('\n======================================================') console.log('RESULT: ALL EMPIRICAL STRESS TESTS PASSED WITH 100% PARITY') console.log('======================================================') } main().catch(err => { console.error('\nStress test failed with exception:', err) process.exit(1) })