You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
4.8 KiB
Rust

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<Class> for Standard {
fn sample<R: rand::Rng + ?Sized>(&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())
}
}
}
}