diablo2-web/tests/parity-1.13c.test.ts

161 lines
5.4 KiB
TypeScript

import { describe, it, expect, beforeAll } from 'vitest'
import { ACT_BOSSES, BOSS_LIST, type BossDefinition } from '../src/boss.ts'
import { getEmbeddedDropTables } from '../src/game/embedded-drop-tables.ts'
import { executeDropPipeline, type DropTables } from '../src/game/drop-pipeline.ts'
import type { UpgradableItemBase } from '../src/game/item-upgrade.ts'
import type { Item } from '../src/game/items.ts'
import { runParityAudit } from '../scripts/audit-parity.ts'
export type BaseTier = 'normal' | 'exceptional' | 'elite'
export function classifyItemBaseTier(item: Item): BaseTier | null {
if (item.base.kind !== 'weapon' && item.base.kind !== 'armor') {
return null
}
const b = item.base as UpgradableItemBase
const id = (b.id ?? '').trim().toLowerCase()
const uber = (b.ubercode ?? '').trim().toLowerCase()
const ultra = (b.ultracode ?? '').trim().toLowerCase()
if (ultra && ultra !== 'xxx' && id === ultra) {
return 'elite'
}
if (uber && uber !== 'xxx' && id === uber) {
return 'exceptional'
}
return 'normal'
}
describe('Diablo II 1.13c Parity Baseline & Boss monsterType=4 Upgrade Odds (Issue #126)', () => {
let dropTables: DropTables
beforeAll(() => {
dropTables = getEmbeddedDropTables()
})
it('1. BOSS_LIST and ACT_BOSSES define monsterType === 4 for all 5 Act Bosses', () => {
expect(BOSS_LIST).toBeDefined()
expect(BOSS_LIST).toHaveLength(5)
expect(BOSS_LIST).toBe(ACT_BOSSES)
for (const boss of BOSS_LIST) {
const def: BossDefinition = boss
expect(def.monsterType, `Boss ${def.id} must explicitly set monsterType: 4`).toBe(4)
}
})
it('2. Difficultylevels.txt Good odds (UberCodeOddsGood / UltraCodeOddsGood) exceed Normal odds in Nightmare and Hell', () => {
const nmOdds = dropTables.difficultyLevels.get('Nightmare')!
const hellOdds = dropTables.difficultyLevels.get('Hell')!
expect(nmOdds.uberCodeOddsGood).toBeGreaterThan(nmOdds.uberCodeOddsNormal)
expect(hellOdds.uberCodeOddsGood).toBeGreaterThan(hellOdds.uberCodeOddsNormal)
expect(hellOdds.ultraCodeOddsGood).toBeGreaterThan(hellOdds.ultraCodeOddsNormal)
})
it('3. monsterType=4 (Boss) yields significantly higher Exceptional/Elite base upgrades than monsterType=1 (Normal) over identical seeds', () => {
const sampleKills = 400
let normalMonsterUpgraded = 0
let normalMonsterEquipCount = 0
let bossMonsterUpgraded = 0
let bossMonsterEquipCount = 0
for (let i = 0; i < sampleKills; i++) {
const seed = (0x12600000 + i * 7919) >>> 0
// Run with monsterType = 1 (Normal monster: uses uberCodeOddsNormal=20, ultraCodeOddsNormal=30)
const dropsNormalType = executeDropPipeline({
tcName: 'Mephistoq (H)',
nLevel: 87,
monsterType: 1,
dropTables,
difficulty: 'hell',
playerMf: 250,
gamePlayers: 1,
partyPlayers: 1,
monsterRng: seed,
})
for (const item of dropsNormalType) {
const tier = classifyItemBaseTier(item)
if (tier !== null) {
normalMonsterEquipCount++
if (tier === 'exceptional' || tier === 'elite') {
normalMonsterUpgraded++
}
}
}
// Run with monsterType = 4 (Act Boss: uses uberCodeOddsGood=40, ultraCodeOddsGood=40)
const dropsBossType = executeDropPipeline({
tcName: 'Mephistoq (H)',
nLevel: 87,
monsterType: 4,
dropTables,
difficulty: 'hell',
playerMf: 250,
gamePlayers: 1,
partyPlayers: 1,
monsterRng: seed,
})
for (const item of dropsBossType) {
const tier = classifyItemBaseTier(item)
if (tier !== null) {
bossMonsterEquipCount++
if (tier === 'exceptional' || tier === 'elite') {
bossMonsterUpgraded++
}
}
}
}
expect(normalMonsterEquipCount).toBeGreaterThan(500)
expect(bossMonsterEquipCount).toBe(normalMonsterEquipCount)
const normalUpgradeRate = normalMonsterUpgraded / normalMonsterEquipCount
const bossUpgradeRate = bossMonsterUpgraded / bossMonsterEquipCount
// Boss (Good odds: 40/1024 + 40/1024) must strictly exceed Normal (20/1024 + 30/1024)
expect(bossMonsterUpgraded).toBeGreaterThan(normalMonsterUpgraded)
expect(bossUpgradeRate).toBeGreaterThan(normalUpgradeRate)
})
it('4. executeDropPipeline works properly with monsterType: 4 across all 5 Act Bosses in Hell', () => {
for (const boss of BOSS_LIST) {
const drops = executeDropPipeline({
tcName: boss.questTc.hell,
nLevel: boss.mlvl.hell,
monsterType: boss.monsterType ?? 4,
dropTables,
difficulty: 'hell',
playerMf: 250,
gamePlayers: 1,
partyPlayers: 1,
monsterRng: 1337 + boss.act,
})
expect(drops.length).toBeGreaterThan(0)
for (const item of drops) {
expect(item.ilvl).toBe(boss.mlvl.hell)
}
}
})
it('5. runParityAudit generates structured JSON summary of quality, base upgrade, and affix distributions', () => {
const summary = runParityAudit({
kills: 100,
bossId: 'mephisto',
difficulty: 'hell',
playerMf: 250,
gamePlayers: 1,
})
expect(summary.config.boss).toBe('mephisto')
expect(summary.config.monsterType).toBe(4)
expect(summary.totalItems).toBeGreaterThan(0)
expect(summary.baseTierUpgrade.totalEquipment).toBeGreaterThan(0)
expect(summary.baseTierUpgrade.upgradedRatio).toBeGreaterThan(0)
})
})