use crate::character::{Item, ItemSlot, Rarity};
use rand::Rng;
struct LootEntry {
name: &'static str,
slot: ItemSlot,
power_range: (i32, i32),
}
fn roll_rarity(rng: &mut impl Rng) -> Rarity {
let roll = rng.gen_range(0u32..10000);
match roll {
0..=6999 => Rarity::Common, 7000..=9499 => Rarity::Uncommon, 9500..=9899 => Rarity::Rare, 9900..=9998 => Rarity::Epic, _ => Rarity::Legendary, }
}
const COMMON: &[LootEntry] = &[
LootEntry { name: "Rusty Pipe", slot: ItemSlot::Weapon, power_range: (1, 3) },
LootEntry { name: "Keyboard of Smiting", slot: ItemSlot::Weapon, power_range: (2, 4) },
LootEntry { name: "Mouse of Clicking", slot: ItemSlot::Weapon, power_range: (1, 3) },
LootEntry { name: "Broken USB Stick", slot: ItemSlot::Weapon, power_range: (1, 2) },
LootEntry { name: "Ethernet Whip", slot: ItemSlot::Weapon, power_range: (2, 3) },
LootEntry { name: "Floppy Disk Shuriken", slot: ItemSlot::Weapon, power_range: (1, 4) },
LootEntry { name: "Paperclip of Poking", slot: ItemSlot::Weapon, power_range: (1, 2) },
LootEntry { name: "Sticky Note Dart", slot: ItemSlot::Weapon, power_range: (1, 3) },
LootEntry { name: "VGA Cable Lasso", slot: ItemSlot::Weapon, power_range: (2, 3) },
LootEntry { name: "CD-ROM Frisbee", slot: ItemSlot::Weapon, power_range: (1, 4) },
LootEntry { name: "Bent Antenna", slot: ItemSlot::Weapon, power_range: (1, 2) },
LootEntry { name: "Thermal Paste Spatula", slot: ItemSlot::Weapon, power_range: (1, 3) },
LootEntry { name: "Dead Battery Club", slot: ItemSlot::Weapon, power_range: (2, 4) },
LootEntry { name: "Tangled Earbuds Whip", slot: ItemSlot::Weapon, power_range: (1, 3) },
LootEntry { name: "HDMI Cable Nunchucks", slot: ItemSlot::Weapon, power_range: (2, 4) },
LootEntry { name: "Dust Bunny Launcher", slot: ItemSlot::Weapon, power_range: (1, 3) },
LootEntry { name: "404 Page Scroll", slot: ItemSlot::Weapon, power_range: (1, 2) },
LootEntry { name: "Cracked Screen Shard", slot: ItemSlot::Weapon, power_range: (2, 4) },
LootEntry { name: "Hoodie of Comfort", slot: ItemSlot::Armor, power_range: (1, 3) },
LootEntry { name: "T-Shirt of Localhost", slot: ItemSlot::Armor, power_range: (1, 2) },
LootEntry { name: "Pajama Pants of WFH", slot: ItemSlot::Armor, power_range: (1, 3) },
LootEntry { name: "Flip-Flops of Friday Deploy", slot: ItemSlot::Armor, power_range: (1, 2) },
LootEntry { name: "Beanie of Bluetooth", slot: ItemSlot::Armor, power_range: (2, 3) },
LootEntry { name: "Lanyard of the Intern", slot: ItemSlot::Armor, power_range: (1, 2) },
LootEntry { name: "Cardigan of Code Review", slot: ItemSlot::Armor, power_range: (1, 3) },
LootEntry { name: "Socks of Static", slot: ItemSlot::Armor, power_range: (1, 2) },
LootEntry { name: "Conference Swag Tee", slot: ItemSlot::Armor, power_range: (1, 3) },
LootEntry { name: "Wrinkled Khakis of Standup", slot: ItemSlot::Armor, power_range: (2, 3) },
LootEntry { name: "Baseball Cap of Backwards Compat", slot: ItemSlot::Armor, power_range: (1, 3) },
LootEntry { name: "Crocs of Casual Friday", slot: ItemSlot::Armor, power_range: (1, 2) },
LootEntry { name: "Scarf of Spaghetti Code", slot: ItemSlot::Armor, power_range: (1, 3) },
LootEntry { name: "Wristband of Agile", slot: ItemSlot::Armor, power_range: (1, 2) },
LootEntry { name: "Sunglasses of Screen Glare", slot: ItemSlot::Armor, power_range: (1, 3) },
LootEntry { name: "Ring of Tab Completion", slot: ItemSlot::Ring, power_range: (1, 3) },
LootEntry { name: "Band of Backspace", slot: ItemSlot::Ring, power_range: (1, 2) },
LootEntry { name: "Loop of Localhost", slot: ItemSlot::Ring, power_range: (1, 3) },
LootEntry { name: "Rubber Band of Resilience", slot: ItemSlot::Ring, power_range: (1, 2) },
LootEntry { name: "Twist Tie of Binding", slot: ItemSlot::Ring, power_range: (1, 2) },
LootEntry { name: "Keyring of SSH", slot: ItemSlot::Ring, power_range: (1, 3) },
LootEntry { name: "Washer of the Machine Room", slot: ItemSlot::Ring, power_range: (1, 2) },
LootEntry { name: "Ring Pull of Red Bull", slot: ItemSlot::Ring, power_range: (1, 3) },
LootEntry { name: "Potion of Coffee", slot: ItemSlot::Potion, power_range: (5, 10) },
LootEntry { name: "Vial of Green Tea", slot: ItemSlot::Potion, power_range: (3, 8) },
LootEntry { name: "Flask of Water (Stay Hydrated)", slot: ItemSlot::Potion, power_range: (4, 7) },
LootEntry { name: "Sip of Instant Noodle Broth", slot: ItemSlot::Potion, power_range: (3, 6) },
LootEntry { name: "Half a Granola Bar", slot: ItemSlot::Potion, power_range: (2, 5) },
LootEntry { name: "Stale Donut of the Breakroom", slot: ItemSlot::Potion, power_range: (3, 7) },
LootEntry { name: "Lukewarm La Croix", slot: ItemSlot::Potion, power_range: (2, 6) },
LootEntry { name: "Vending Machine Chips", slot: ItemSlot::Potion, power_range: (3, 6) },
LootEntry { name: "Day-Old Pizza Slice", slot: ItemSlot::Potion, power_range: (4, 8) },
LootEntry { name: "Mug of Decaf (Placebo)", slot: ItemSlot::Potion, power_range: (1, 4) },
];
const UNCOMMON: &[LootEntry] = &[
LootEntry { name: "Sword of Regex", slot: ItemSlot::Weapon, power_range: (4, 7) },
LootEntry { name: "Axe of Grep", slot: ItemSlot::Weapon, power_range: (5, 8) },
LootEntry { name: "Dagger of Sed", slot: ItemSlot::Weapon, power_range: (3, 9) },
LootEntry { name: "Mace of Makefile", slot: ItemSlot::Weapon, power_range: (4, 8) },
LootEntry { name: "Bow of Bash", slot: ItemSlot::Weapon, power_range: (5, 7) },
LootEntry { name: "Halberd of HTTP", slot: ItemSlot::Weapon, power_range: (4, 9) },
LootEntry { name: "Spear of SQL", slot: ItemSlot::Weapon, power_range: (5, 8) },
LootEntry { name: "Crossbow of CORS", slot: ItemSlot::Weapon, power_range: (4, 8) },
LootEntry { name: "Flail of Flexbox", slot: ItemSlot::Weapon, power_range: (5, 7) },
LootEntry { name: "Pike of Ping", slot: ItemSlot::Weapon, power_range: (4, 7) },
LootEntry { name: "Morningstar of Middleware", slot: ItemSlot::Weapon, power_range: (5, 9) },
LootEntry { name: "Rapier of REST", slot: ItemSlot::Weapon, power_range: (5, 8) },
LootEntry { name: "Javelin of JSON", slot: ItemSlot::Weapon, power_range: (4, 8) },
LootEntry { name: "Sling of Svelte", slot: ItemSlot::Weapon, power_range: (4, 7) },
LootEntry { name: "Whip of Webpack", slot: ItemSlot::Weapon, power_range: (5, 9) },
LootEntry { name: "Cloak of Stdout", slot: ItemSlot::Armor, power_range: (3, 6) },
LootEntry { name: "Vest of Version Control", slot: ItemSlot::Armor, power_range: (4, 7) },
LootEntry { name: "Gauntlets of Gzip", slot: ItemSlot::Armor, power_range: (3, 6) },
LootEntry { name: "Helmet of HTTPS", slot: ItemSlot::Armor, power_range: (4, 7) },
LootEntry { name: "Boots of Bootstrap", slot: ItemSlot::Armor, power_range: (3, 5) },
LootEntry { name: "Cape of CI/CD", slot: ItemSlot::Armor, power_range: (5, 7) },
LootEntry { name: "Pauldrons of PostgreSQL", slot: ItemSlot::Armor, power_range: (4, 7) },
LootEntry { name: "Bracers of Brotli", slot: ItemSlot::Armor, power_range: (3, 6) },
LootEntry { name: "Leggings of Linting", slot: ItemSlot::Armor, power_range: (4, 6) },
LootEntry { name: "Visor of Vim Motions", slot: ItemSlot::Armor, power_range: (4, 7) },
LootEntry { name: "Shoulderguards of Scrum", slot: ItemSlot::Armor, power_range: (3, 6) },
LootEntry { name: "Chaps of Caching", slot: ItemSlot::Armor, power_range: (4, 7) },
LootEntry { name: "Ring of Syntax Highlight", slot: ItemSlot::Ring, power_range: (2, 5) },
LootEntry { name: "Signet of SSH", slot: ItemSlot::Ring, power_range: (3, 6) },
LootEntry { name: "Circlet of Cron", slot: ItemSlot::Ring, power_range: (3, 5) },
LootEntry { name: "Band of Base64", slot: ItemSlot::Ring, power_range: (3, 6) },
LootEntry { name: "Ring of Rate Limiting", slot: ItemSlot::Ring, power_range: (2, 5) },
LootEntry { name: "Amulet of Async/Await", slot: ItemSlot::Ring, power_range: (3, 6) },
LootEntry { name: "Pendant of Package.json", slot: ItemSlot::Ring, power_range: (2, 5) },
LootEntry { name: "Elixir of Energy Drink", slot: ItemSlot::Potion, power_range: (10, 20) },
LootEntry { name: "Brew of Debugging", slot: ItemSlot::Potion, power_range: (12, 18) },
LootEntry { name: "Tincture of Focus Mode", slot: ItemSlot::Potion, power_range: (8, 15) },
LootEntry { name: "Smoothie of Sprint Planning", slot: ItemSlot::Potion, power_range: (10, 16) },
LootEntry { name: "Espresso Shot of Urgency", slot: ItemSlot::Potion, power_range: (8, 14) },
LootEntry { name: "Matcha of Mindfulness", slot: ItemSlot::Potion, power_range: (10, 18) },
LootEntry { name: "Cold Brew of All-Nighter", slot: ItemSlot::Potion, power_range: (12, 20) },
];
const RARE: &[LootEntry] = &[
LootEntry { name: "Blade of Sudo", slot: ItemSlot::Weapon, power_range: (8, 12) },
LootEntry { name: "Staff of Stack Overflow", slot: ItemSlot::Weapon, power_range: (7, 13) },
LootEntry { name: "Hammer of Compiler", slot: ItemSlot::Weapon, power_range: (9, 14) },
LootEntry { name: "Trident of TypeScript", slot: ItemSlot::Weapon, power_range: (8, 13) },
LootEntry { name: "Scythe of Segfault", slot: ItemSlot::Weapon, power_range: (10, 15) },
LootEntry { name: "Wand of WebSocket", slot: ItemSlot::Weapon, power_range: (7, 12) },
LootEntry { name: "Claymore of Concurrency", slot: ItemSlot::Weapon, power_range: (9, 14) },
LootEntry { name: "Katana of Kubernetes", slot: ItemSlot::Weapon, power_range: (10, 15) },
LootEntry { name: "Chestplate of Chmod 777", slot: ItemSlot::Armor, power_range: (7, 11) },
LootEntry { name: "Plate of the Firewall", slot: ItemSlot::Armor, power_range: (8, 12) },
LootEntry { name: "Breastplate of Bcrypt", slot: ItemSlot::Armor, power_range: (9, 13) },
LootEntry { name: "Shield of CORS", slot: ItemSlot::Armor, power_range: (7, 11) },
LootEntry { name: "Greaves of GraphQL", slot: ItemSlot::Armor, power_range: (8, 12) },
LootEntry { name: "Crown of CloudFormation", slot: ItemSlot::Armor, power_range: (9, 14) },
LootEntry { name: "Ring of the Daemon", slot: ItemSlot::Ring, power_range: (4, 8) },
LootEntry { name: "Seal of Semaphore", slot: ItemSlot::Ring, power_range: (5, 9) },
LootEntry { name: "Band of the Borrow Checker", slot: ItemSlot::Ring, power_range: (6, 10) },
LootEntry { name: "Talisman of TLS", slot: ItemSlot::Ring, power_range: (5, 9) },
LootEntry { name: "Flask of Liquid Nitrogen", slot: ItemSlot::Potion, power_range: (20, 35) },
LootEntry { name: "Draught of Deep Work", slot: ItemSlot::Potion, power_range: (18, 30) },
LootEntry { name: "Philter of Flow State", slot: ItemSlot::Potion, power_range: (22, 35) },
];
const EPIC: &[LootEntry] = &[
LootEntry { name: "Excalibash", slot: ItemSlot::Weapon, power_range: (13, 18) },
LootEntry { name: "Vorpal Pointer", slot: ItemSlot::Weapon, power_range: (15, 22) },
LootEntry { name: "Mjolnir of Monorepo", slot: ItemSlot::Weapon, power_range: (16, 21) },
LootEntry { name: "Gungnir of Git Rebase", slot: ItemSlot::Weapon, power_range: (14, 23) },
LootEntry { name: "Naginata of Nginx", slot: ItemSlot::Weapon, power_range: (15, 20) },
LootEntry { name: "Armor of the Container", slot: ItemSlot::Armor, power_range: (12, 17) },
LootEntry { name: "Aegis of the Load Balancer", slot: ItemSlot::Armor, power_range: (14, 19) },
LootEntry { name: "Warplate of Kubernetes", slot: ItemSlot::Armor, power_range: (13, 18) },
LootEntry { name: "Ring of Root Access", slot: ItemSlot::Ring, power_range: (8, 14) },
LootEntry { name: "Signet of Zero-Day", slot: ItemSlot::Ring, power_range: (10, 16) },
LootEntry { name: "Phoenix Elixir of Hot Reload", slot: ItemSlot::Potion, power_range: (30, 50) },
];
const LEGENDARY: &[LootEntry] = &[
LootEntry { name: "Mass Migration Sword of Chaos", slot: ItemSlot::Weapon, power_range: (20, 30) },
LootEntry { name: "Mass Migration Blade of the Kernel", slot: ItemSlot::Weapon, power_range: (25, 35) },
LootEntry { name: "The Mass Migration Fork Bomb", slot: ItemSlot::Weapon, power_range: (22, 32) },
LootEntry { name: "Shell of Invulnerability", slot: ItemSlot::Armor, power_range: (18, 25) },
LootEntry { name: "Divine Armor of /dev/null", slot: ItemSlot::Armor, power_range: (20, 28) },
LootEntry { name: "The One Ring (of SSH Keys)", slot: ItemSlot::Ring, power_range: (14, 20) },
LootEntry { name: "Eternal Band of Uptime", slot: ItemSlot::Ring, power_range: (16, 22) },
LootEntry { name: "Elixir of Infinite Context", slot: ItemSlot::Potion, power_range: (50, 99) },
];
fn pick_from(rng: &mut impl Rng, table: &[LootEntry], rarity: Rarity) -> Item {
let entry = &table[rng.gen_range(0..table.len())];
let power = rng.gen_range(entry.power_range.0..=entry.power_range.1);
Item {
name: entry.name.to_string(),
slot: entry.slot,
power,
rarity,
}
}
pub fn roll_loot(_danger_level: u32) -> Item {
let mut rng = rand::thread_rng();
let rarity = roll_rarity(&mut rng);
match rarity {
Rarity::Common => pick_from(&mut rng, COMMON, Rarity::Common),
Rarity::Uncommon => pick_from(&mut rng, UNCOMMON, Rarity::Uncommon),
Rarity::Rare => pick_from(&mut rng, RARE, Rarity::Rare),
Rarity::Epic => pick_from(&mut rng, EPIC, Rarity::Epic),
Rarity::Legendary => pick_from(&mut rng, LEGENDARY, Rarity::Legendary),
}
}