import { describe, expect, it } from 'vitest' import { getEmbeddedDropTables } from '../src/game/embedded-drop-tables.ts' import { executeDropPipeline } from '../src/game/drop-pipeline.ts' import { expandTreasureClass, computeEffectivePlayers, computeScaledNoDrop, } from '../src/game/treasure-engine.ts' import { D2Rng } from '../src/game/d2-rng.ts' import { Rng } from '../src/game/rng.ts' import { GameEngine, type WorldMapProvider, type GameEngineOptions } from '../src/game/engine.ts' import { createWorld, spawnMonsters, tickCombat, damageMonster, monsterStatsFromTable } from '../src/game/combat.ts' import { parseTable } from '../src/game/tables.ts' import { Inventory, goldItem, ItemQuality } from '../src/game/items.ts' import { QuestLog } from '../src/game/quests.ts' import { LockstepSession, type InputFrame, type LockstepSimulation } from '../src/net/lockstep.ts' const dropTables = getEmbeddedDropTables() const dummyTerrain: WorldMapProvider = { widthPx: 1000, heightPx: 1000, overlap: () => 0, } describe('Milestone 2 Challenger 2: Empirical Stress & Statistical Parity', () => { describe('1. Player Scaling Statistical Monte Carlo (Act 1 H2H A)', () => { it('verifies /players 1 NoDrop rate converges to 62.5% (yield 37.5%)', () => { const trials = 20000 const rng = new D2Rng(1001) let empty = 0 for (let i = 0; i < trials; i++) { const drops = expandTreasureClass('Act 1 H2H A', { rng, tcTable: dropTables.tcTable, autoTcTable: dropTables.autoTcTable, gamePlayers: 1, partyPlayers: 1, }) if (drops.length === 0) empty++ } const noDropRate = empty / trials expect(noDropRate).toBeGreaterThanOrEqual(0.625 - 0.015) expect(noDropRate).toBeLessThanOrEqual(0.625 + 0.015) }) it('verifies /players 3 NoDrop rate converges to 38.78% (yield 61.22%)', () => { const trials = 20000 const rng = new D2Rng(3003) let empty = 0 for (let i = 0; i < trials; i++) { const drops = expandTreasureClass('Act 1 H2H A', { rng, tcTable: dropTables.tcTable, autoTcTable: dropTables.autoTcTable, gamePlayers: 3, partyPlayers: 1, }) if (drops.length === 0) empty++ } const noDropRate = empty / trials const expected = 38 / 98 // ~0.387755 expect(noDropRate).toBeGreaterThanOrEqual(expected - 0.015) expect(noDropRate).toBeLessThanOrEqual(expected + 0.015) }) it('verifies /players 5 NoDrop rate converges to 24.05% (yield 75.95%)', () => { const trials = 20000 const rng = new D2Rng(5005) let empty = 0 for (let i = 0; i < trials; i++) { const drops = expandTreasureClass('Act 1 H2H A', { rng, tcTable: dropTables.tcTable, autoTcTable: dropTables.autoTcTable, gamePlayers: 5, partyPlayers: 1, }) if (drops.length === 0) empty++ } const noDropRate = empty / trials const expected = 19 / 79 // ~0.240506 expect(noDropRate).toBeGreaterThanOrEqual(expected - 0.015) expect(noDropRate).toBeLessThanOrEqual(expected + 0.015) }) it('verifies /players 7 NoDrop rate converges to 14.29% (yield 85.71%)', () => { const trials = 20000 const rng = new D2Rng(7007) let empty = 0 for (let i = 0; i < trials; i++) { const drops = expandTreasureClass('Act 1 H2H A', { rng, tcTable: dropTables.tcTable, autoTcTable: dropTables.autoTcTable, gamePlayers: 7, partyPlayers: 1, }) if (drops.length === 0) empty++ } const noDropRate = empty / trials const expected = 10 / 70 // ~0.142857 expect(noDropRate).toBeGreaterThanOrEqual(expected - 0.015) expect(noDropRate).toBeLessThanOrEqual(expected + 0.015) }) it('verifies /players 8 solo matches /players 7 (14.29%) while /players 8 partied drops to 1.64%', () => { const trials = 20000 // 8 players solo (effective = 4) const rngSolo = new D2Rng(8008) let emptySolo = 0 for (let i = 0; i < trials; i++) { const drops = expandTreasureClass('Act 1 H2H A', { rng: rngSolo, tcTable: dropTables.tcTable, autoTcTable: dropTables.autoTcTable, gamePlayers: 8, partyPlayers: 1, }) if (drops.length === 0) emptySolo++ } const soloNoDrop = emptySolo / trials expect(soloNoDrop).toBeGreaterThanOrEqual(10 / 70 - 0.015) expect(soloNoDrop).toBeLessThanOrEqual(10 / 70 + 0.015) // 8 players partied (effective = 8) const rngParty = new D2Rng(8888) let emptyParty = 0 for (let i = 0; i < trials; i++) { const drops = expandTreasureClass('Act 1 H2H A', { rng: rngParty, tcTable: dropTables.tcTable, autoTcTable: dropTables.autoTcTable, gamePlayers: 8, partyPlayers: 8, }) if (drops.length === 0) emptyParty++ } const partyNoDrop = emptyParty / trials expect(partyNoDrop).toBeGreaterThanOrEqual(1 / 61 - 0.01) expect(partyNoDrop).toBeLessThanOrEqual(1 / 61 + 0.01) }) it('verifies GameEngine.setPlayers() updates drop pipeline yield in end-to-end execution', () => { const engine = new GameEngine(dummyTerrain, { spawn: { x: 100, y: 100 }, stats: [], dropTables, difficulty: 'normal', gamePlayers: 1, partyPlayers: 1, npcDefs: [], questDefs: [], inventoryCols: 10, inventoryRows: 4, xpTable: [0, 0, 1000], itemBases: [], prefixAffixes: [], suffixAffixes: [], skills: [], combatOptions: { playerSpeed: 180, playerReach: 48, playerCooldownTicks: 12, playerDamage: 6, playerManaPerAttack: 2, respawnTicks: 40, }, talkRadius: 80, pickupRadius: 60, }) const trials = 5000 let dropsP1 = 0 for (let i = 0; i < trials; i++) { const items = executeDropPipeline(dropTables, { tcName: 'Act 1 H2H A', nLevel: 1, monsterType: 1, difficulty: 'normal', gamePlayers: engine.gamePlayers, partyPlayers: engine.partyPlayers, monsterRng: new D2Rng(20000 + i), }) if (items.length > 0) dropsP1++ } engine.setPlayers(8) expect(engine.gamePlayers).toBe(8) let dropsP8 = 0 for (let i = 0; i < trials; i++) { const items = executeDropPipeline(dropTables, { tcName: 'Act 1 H2H A', nLevel: 1, monsterType: 1, difficulty: 'normal', gamePlayers: engine.gamePlayers, partyPlayers: engine.partyPlayers, monsterRng: new D2Rng(20000 + i), }) if (items.length > 0) dropsP8++ } const yieldP1 = dropsP1 / trials const yieldP8 = dropsP8 / trials expect(yieldP1).toBeGreaterThanOrEqual(0.375 - 0.02) expect(yieldP1).toBeLessThanOrEqual(0.375 + 0.02) expect(yieldP8).toBeGreaterThanOrEqual(0.857 - 0.02) expect(yieldP8).toBeLessThanOrEqual(0.857 + 0.02) expect(yieldP8).toBeGreaterThan(yieldP1 + 0.40) }) }) describe('2. Multi-Seed PRNG Stream Determinism Across 50 Seeds', () => { const SEEDS = [ 1, 2, 3, 7, 13, 42, 100, 255, 256, 1000, 10007, 104729, 1299709, 0x1234, 0x5678, 0xabcd, 0xbeef, 0x10000000, 0x55555555, 0xAAAAAAAA, 0x7FFFFFFF, 0xFFFFFFFF, 123456789, 987654321, 314159265, 271828182, 161803398, ...Array.from({ length: 23 }, (_, i) => ((i * 1664525 + 1013904223) >>> 0) & 0x7FFFFFFF), ] it('verifies exact bit-for-bit drop pipeline replay across 50 diverse seeds with /players set', () => { const tcs = ['Act 1 H2H A', 'Act 1 Champ A', 'Act 1 Unique A', 'Countess', 'Andariel', 'Mephisto'] for (let sIdx = 0; sIdx < SEEDS.length; sIdx++) { const seed = SEEDS[sIdx]! const players = 1 + (sIdx % 8) // Run 1 const rng1 = new D2Rng(seed) const run1: any[] = [] for (const tc of tcs) { const drops = executeDropPipeline(dropTables, { tcName: tc, nLevel: 30, monsterType: tc === 'Andariel' || tc === 'Mephisto' ? 4 : tc.includes('Unique') ? 3 : tc.includes('Champ') ? 2 : 1, difficulty: 'normal', gamePlayers: players, partyPlayers: 1, playerMf: 120, monsterRng: rng1, }) run1.push(drops.map(d => ({ code: d.code, quality: d.quality, rarity: d.rarity, uniqueId: d.uniqueId, durability: d.durability, stats: d.stats, }))) } // Run 2 const rng2 = new D2Rng(seed) const run2: any[] = [] for (const tc of tcs) { const drops = executeDropPipeline(dropTables, { tcName: tc, nLevel: 30, monsterType: tc === 'Andariel' || tc === 'Mephisto' ? 4 : tc.includes('Unique') ? 3 : tc.includes('Champ') ? 2 : 1, difficulty: 'normal', gamePlayers: players, partyPlayers: 1, playerMf: 120, monsterRng: rng2, }) run2.push(drops.map(d => ({ code: d.code, quality: d.quality, rarity: d.rarity, uniqueId: d.uniqueId, durability: d.durability, stats: d.stats, }))) } expect(run1).toEqual(run2) expect(rng1.getSeed()).toEqual(rng2.getSeed()) } }) }) describe('3. Execution Robustness Under Load (10,000 Drops in Unit Test)', () => { it('executes 10,000 drops across all difficulties, monster ranks, and MF setups with 0 errors', () => { const diffs = ['normal', 'nightmare', 'hell'] as const const ranks = ['normal', 'champion', 'unique', 'minion', 'boss'] as const const mfs = [0, 50, 150, 350, 1000, -50, -100, -250] const rng = new D2Rng(0xdeadc0de) let totalDrops = 0 let totalItems = 0 for (let i = 0; i < 10000; i++) { const diff = diffs[i % diffs.length]! const rank = ranks[i % ranks.length]! const mf = mfs[i % mfs.length]! const pCount = 1 + (i % 8) const isBoss = rank === 'boss' || i % 15 === 0 const tc = isBoss ? 'Andariel' : 'Act 1 H2H A' const monsterType = isBoss ? 4 : (rank === 'unique' || rank === 'minion' ? 3 : (rank === 'champion' ? 2 : 1)) const nLevel = 10 + (i % 80) const items = executeDropPipeline(dropTables, { tcName: tc, nLevel, monsterType, difficulty: diff, gamePlayers: pCount, partyPlayers: 1, playerMf: mf, isBoss, monsterRng: rng, }) totalDrops++ totalItems += items.length for (const item of items) { expect(item.base).toBeDefined() const isGold = item.base?.id === 'gold' || item.code?.trim() === 'gld' if (isGold) { const amt = item.stack ?? item.value ?? 0 expect(amt).toBeGreaterThan(0) continue } expect(item.ilvl).toBeGreaterThanOrEqual(1) expect(item.ilvl).toBeLessThanOrEqual(99) if (item.stats) { for (const [_, val] of Object.entries(item.stats)) { if (typeof val === 'number') { expect(isNaN(val)).toBe(false) } } } if (mf <= -100) { if (item.base.kind === 'weapon' || item.base.kind === 'armor') { expect(['magic', 'rare', 'set', 'unique']).not.toContain(item.rarity) } else { expect(['rare', 'set', 'unique']).not.toContain(item.rarity) } } } } expect(totalDrops).toBe(10000) expect(totalItems).toBeGreaterThan(0) }) }) })