use rand::seq::IteratorRandom; use rand_distr::{Distribution, Standard}; use strum::IntoEnumIterator; use strum_macros::{Display, EnumIter}; use crate::{ skills::{Proficiencies, ToProficiencies}, stats::{StatBlock, ToStatBlock}, }; #[derive(Debug, PartialEq, Eq, EnumIter, Clone, Copy, Display)] pub enum Class { Guard, Knight, Brawler, Thief, Swashbuckler, Survivalist, Hunter, Witch, Wizard, NPC, // Stubbed in for "no class" } impl ToStatBlock for Class { fn stat_block(&self) -> StatBlock { match self { Class::Guard => StatBlock::from((1, 0, 1, 1, 0, 0, 0, 0)), Class::Knight => StatBlock::from((1, 0, 0, 1, 0, 0, 0, 1)), Class::Brawler => StatBlock::from((1, 1, 1, 0, 0, 0, 0, 0)), // ----- Class::Thief => StatBlock::from((0, 1, 0, 0, 1, 0, 1, 0)), Class::Swashbuckler => StatBlock::from((1, 1, 0, 0, 0, 0, 0, 1)), // ----- Class::Survivalist => StatBlock::from((0, 1, 1, 0, 1, 0, 0, 0)), Class::Hunter => StatBlock::from((0, 1, 1, 0, 0, 1, 0, 0)), // ----- Class::Witch => StatBlock::from((0, 0, 0, 0, 1, 1, 1, 0)), Class::Wizard => StatBlock::from((0, 0, 0, 0, 1, 1, 0, 1)), // ----- Class::NPC => StatBlock::from((0, 0, 0, 0, 0, 0, 0, 0)), } } } impl ToProficiencies for Class { fn proficiencies(&self) -> Proficiencies { match self { Class::Guard => Proficiencies { light_armor: true, medium_armor: true, heavy_armor: true, // ----- // bladed_weapons: true, simple_weapons: true, pole_weapons: true, ..Default::default() }, Class::Knight => Proficiencies { light_armor: true, medium_armor: true, heavy_armor: true, // ----- bladed_weapons: true, ..Default::default() }, Class::Brawler => Proficiencies { light_armor: true, medium_armor: true, // ----- simple_weapons: true, blunt_weapons: true, thrown_weapons: true, ..Default::default() }, Class::Thief => Proficiencies { simple_weapons: true, thrown_weapons: true, ranged_weapons: true, ..Default::default() }, Class::Swashbuckler => Proficiencies { light_armor: true, simple_weapons: true, bladed_weapons: true, thrown_weapons: true, ranged_weapons: true, ..Default::default() }, Class::Survivalist => Proficiencies { // ----- simple_weapons: true, thrown_weapons: true, ..Default::default() }, Class::Hunter => Proficiencies { light_armor: true, // ----- simple_weapons: true, pole_weapons: true, ranged_weapons: true, ..Default::default() }, Class::Witch => Proficiencies { simple_weapons: true, ..Default::default() }, Class::Wizard => Proficiencies::default(), Class::NPC => Proficiencies::default(), } } } impl Distribution for Standard { fn sample(&self, rng: &mut R) -> Class { Class::iter().choose(rng).unwrap() } } #[cfg(test)] mod class_tests { use strum::IntoEnumIterator; use crate::{class::Class, stats::ToStatBlock}; #[test] fn stat_sums() { for class in Class::iter() { let stat_block = class.stat_block(); if class != Class::NPC { assert_eq!( 3, stat_block.STR + stat_block.DEX + stat_block.CON + stat_block.STB + stat_block.INT + stat_block.KND + stat_block.CMP + stat_block.CHA ) } } } #[test] fn all_unique() { for class1 in Class::iter() { for class2 in Class::iter() { assert!(class1 == class2 || class1.stat_block() != class2.stat_block()) } } } }