diff --git a/src/characters.rs b/src/characters.rs index 73b66e1..3d6bfee 100644 --- a/src/characters.rs +++ b/src/characters.rs @@ -1,10 +1,48 @@ -#[derive(Debug)] +use rand::distributions::{Distribution, Standard}; + +use crate::Gamemode; + +#[derive(Debug, Clone)] pub struct Character { pub name: &'static str, pub standing: Standing } -#[derive(Debug)] +impl Character { + pub fn build_player(gamemode: Gamemode) -> Character { + Character { + name: "You", + standing: match gamemode { + Gamemode::Abigail => Standing { + society: 10, + court: 10, + friends: vec![], + enemies: vec![] + }, + Gamemode::MaryWarren => Standing { + society: 5, + court: 5, + friends: vec![], + enemies: vec![] + }, + Gamemode::JohnProctor => Standing { + society: 2, + court: 2, + friends: vec![], + enemies: vec![] + }, + Gamemode::GoodyOsborne => Standing { + society: -15, + court: -5, + friends: vec![], + enemies: vec![] + } + } + } + } +} + +#[derive(Debug, Clone)] pub struct Standing { pub society: i8, pub court: i8, @@ -38,7 +76,6 @@ pub enum People { ElizabethProctor(Option), EzekielCheever(Option), FrancisNurse(Option), - RebeccaNurse(Option), GilesCorey(Option), GoodyOsborne(Option), JohnProctor(Option), @@ -47,6 +84,7 @@ pub enum People { MarshalHerrick(Option), MarthaCorey(Option), MercyLewis(Option), + RebeccaNurse(Option), ReverendParris(Option), ReverendJohnHale(Option), SarahGood(Option), @@ -55,8 +93,217 @@ pub enum People { Tituba(Option) } +impl People { + pub fn build_characters() -> Vec { + vec![ + People::AbigailWilliams(Some(Character { + name: "Abigail Williams", + standing: Standing { + society: 10, + court: 10, + friends: vec![ + &People::BettyParris(None), + &People::DeputyGovernorDanforth(None), + &People::ReverendParris(None), + ], + enemies: vec![ + &People::ElizabethProctor(None), + &People::JohnProctor(None), + &People::ReverendJohnHale(None) + ] + } + })), + People::AnnPutnam(Some(Character { + name: "Ann Putnam", + standing: Standing { + society: 10, + court: 7, + friends: vec![ + &People::BettyParris(None), + &People::ThomasPutnam(None), + &People::ReverendParris(None), + &People::MercyLewis(None) + ], + enemies: vec![ + &People::ElizabethProctor(None), + &People::JohnProctor(None), + &People::RebeccaNurse(None) + ] + } + })), + People::BettyParris(Some(Character { + name: "Betty Parris", + standing: Standing { + society: 10, + court: 10, + friends: vec![ + &People::AbigailWilliams(None), + &People::ReverendParris(None) + ], + enemies: vec![ + &People::JohnProctor(None), + &People::ElizabethProctor(None) + ] + } + })), + People::DeputyGovernorDanforth(Some(Character { + name: "Deputy Governor Danforth", + standing: Standing { + society: 10, + court: 100, + friends: vec![ + &People::AbigailWilliams(None), + &People::JudgeHathorne(None), + &People::ReverendParris(None), + &People::EzekielCheever(None), + &People::MarshalHerrick(None) + ], + enemies: vec![ + &People::ElizabethProctor(None), + &People::JohnProctor(None), + &People::ReverendJohnHale(None), + &People::FrancisNurse(None), + &People::GilesCorey(None), + &People::MarthaCorey(None) + ] + } + })), + People::ElizabethProctor(Some(Character{ + name: "Elizabeth Proctor", + standing: Standing { + society: 10, + court: 5, + friends: vec![ + &People::FrancisNurse(None), + &People::GilesCorey(None), + &People::JohnProctor(None), + &People::RebeccaNurse(None), + &People::ReverendJohnHale(None) + ], + enemies: vec![ + &People::AbigailWilliams(None), + &People::DeputyGovernorDanforth(None), + &People::EzekielCheever(None) + ] + } + })), + People::EzekielCheever(Some(Character { + name: "Ezekiel Cheever", + standing: Standing { + society: 12, + court: 50, + friends: vec![ + &People::MarshalHerrick(None), + &People::DeputyGovernorDanforth(None), + &People::ReverendParris(None), + &People::ReverendJohnHale(None), + &People::JudgeHathorne(None) + + ], + enemies: vec![ + &People::ElizabethProctor(None), + &People::JohnProctor(None), + &People::FrancisNurse(None), + &People::GilesCorey(None) + ] + } + })), + People::FrancisNurse(Some(Character { + name: "Francis Nurse", + standing: Standing { + society: 10, + court: 10, + friends: vec![ + &People::RebeccaNurse(None), + &People::JohnProctor(None), + &People::GilesCorey(None), + ], + enemies: vec![ + &People::AnnPutnam(None), + &People::AbigailWilliams(None), + &People::ReverendJohnHale(None), + &People::JudgeHathorne(None), + &People::ThomasPutnam(None) + ] + } + })), + People::RebeccaNurse(Some(Character { + name: "Rebecca Nurse", + standing: Standing { + society: 20, + court: 8, + friends: vec![ + &People::ElizabethProctor(None), + &People::FrancisNurse(None), + &People::JohnProctor(None), + &People::MarthaCorey(None), + &People::GilesCorey(None) + ], + enemies: vec![ + &People::ThomasPutnam(None), + &People::AnnPutnam(None), + &People::ReverendJohnHale(None), + &People::JudgeHathorne(None), + &People::EzekielCheever(None), + &People::MarshalHerrick(None), + &People::AbigailWilliams(None) + ] + } + })), + People::GilesCorey(Some(Character { + name: "Giles Corey", + standing: Standing { + society: 2, + court: 5, + friends: vec![ + &People::JohnProctor(None), + &People::MarthaCorey(None), + &People::FrancisNurse(None), + ], + enemies: vec![ + &People::EzekielCheever(None), + &People::JudgeHathorne(None), + &People::ReverendJohnHale(None), + &People::MarshalHerrick(None) + ] + } + })), + ] + } +} + +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> People { + match rng.gen_range(0..=21) { + 0 => People::AbigailWilliams(None), + 1 => People::AnnPutnam(None), + 2 => People::BettyParris(None), + 3 => People::DeputyGovernorDanforth(None), + 4 => People::ElizabethProctor(None), + 5 => People::EzekielCheever(None), + 6 => People::FrancisNurse(None), + 7 => People::GilesCorey(None), + 8 => People::GoodyOsborne(None), + 9 => People::JohnProctor(None), + 10 => People::JudgeHathorne(None), + 11 => People::MarshalHerrick(None), + 12 => People::MarthaCorey(None), + 13 => People::MaryWarren(None), + 14 => People::RebeccaNurse(None), + 15 => People::ReverendJohnHale(None), + 16 => People::ReverendParris(None), + 18 => People::SarahGood(None), + 19 => People::SusannaWalcott(None), + 20 => People::ThomasPutnam(None), + 21 => People::Tituba(None), + _ => unreachable!() + } + } +} + #[derive(Debug)] pub enum SurvivalStatus { + PlayerMassacred, PlayerLived, PlayerDied } \ No newline at end of file diff --git a/src/events.rs b/src/events.rs index 46306c1..c4613f5 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,16 +1,85 @@ +use std::i8; + +use rand::{ + distributions::{Distribution, Standard}, + rngs::ThreadRng +}; + use crate::characters::{ Character, + People, SurvivalStatus }; -pub fn get_event() {} +pub fn get_event() -> Events { + Events::Trial(Trial) +} -pub struct Trial; - -impl Trial { - pub fn handle(&self, &mut player: &mut Character) -> SurvivalStatus { - let player_status = SurvivalStatus::PlayerDied; - - player_status +#[allow(unused_variables)] +pub trait EventHandle { + fn handle<'main>( + self: &Self, + rng: &'main ThreadRng, + player: &'main mut Character, + characters: &'main mut Vec + ) -> EventReturn { + EventReturn::None } } + +#[derive(Debug)] +pub struct Trial; + +impl EventHandle for Trial { + fn handle<'main>( + self: &Self, + rng: &'main ThreadRng, + player: &'main mut Character, + characters: &'main mut Vec + ) -> EventReturn { + let mut player_status = SurvivalStatus::PlayerDied; + + println!("You have been summoned before the court.\n"); + + if player.standing.clone().calculate() >= {0 as i8} { + player_status = SurvivalStatus::PlayerLived + } + + EventReturn::Survival(player_status) + } +} + +#[derive(Debug)] +pub struct WildAccusation; + +impl EventHandle for WildAccusation { + fn handle<'main>( + self: &Self, + rng: &'main ThreadRng, + player: &'main mut Character, + characters: &'main mut Vec + ) -> EventReturn { + EventReturn::None + } +} + +#[derive(Debug)] +pub enum Events { + Trial(Trial) +} + +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> Events { + match rng.gen_range(0..=0) { + 0 => Events::Trial(Trial), + 1 => Events::Trial(Trial), + _ => unreachable!() + } + } +} + +#[derive(Debug)] +pub enum EventReturn { + Survival(SurvivalStatus), + None + } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 5c5b116..06df7a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,11 +5,15 @@ mod utils; use characters::{ Character, People, - Standing, SurvivalStatus }; -use events::get_event; -use std::vec; +use events::{ + get_event, EventHandle, EventReturn, Events, Trial +}; +use rand::{ + random, + thread_rng +}; use utils::{ fmt_args, ArgType, @@ -21,30 +25,61 @@ const ROUNDS: u8 = 15; fn main() { let cmd_args = dbg!(fmt_args()); - let mut characters = build_characters(); + let mut characters = People::build_characters(); + let mut rng = thread_rng(); // Set player default values based on gamemode. - let mut player = dbg!(build_player(dbg!(get_gamemode(cmd_args)))); - let end_status = SurvivalStatus::PlayerLived; + let mut player: Character = dbg!(Character::build_player(Gamemode::get(&cmd_args))); + let mut end_status = SurvivalStatus::PlayerLived; + + // Game loop. + for r in 0..=ROUNDS { + let random_event: Events = random(); - for _r in 0..=ROUNDS { - get_event().handle(player); - - if player.standing.calculate() <= 0 { - let mut trial = events::Trial; - - match trial.handle(&mut player) { - SurvivalStatus::PlayerDied => { - end_status = SurvivalStatus::PlayerDied - }, - _ => () + match random_event { + Events::Trial(trial) => match trial.handle(&rng, &mut player, &mut characters) { + EventReturn::Survival(state) => match state { + SurvivalStatus::PlayerLived => (), + _ => {end_status = state} + } + _ => unreachable!() } } + + match end_status { + SurvivalStatus::PlayerLived => (), + _ => break + } + + // If player's standing is too low, bring to court. + if player.standing.clone().calculate() <= 0 { + match Trial.handle(&rng, &mut player, &mut characters) { + EventReturn::Survival(state) => match state { + SurvivalStatus::PlayerLived => (), + _ => {end_status = state} + }, + _ => unreachable!() + }; + }; + + if r == ROUNDS { + end_status = SurvivalStatus::PlayerLived + }; + + if characters.len() == 0 { + end_status = SurvivalStatus::PlayerMassacred + }; }; + + match end_status { + SurvivalStatus::PlayerDied => println!("You died. And for what?"), + SurvivalStatus::PlayerLived => println!("You survived, but at what cost? How many died to save you?"), + SurvivalStatus::PlayerMassacred => println!("You killed everyone. I ask, at what end will you yield. Care you not for the life of others?") + } } #[derive(Debug)] -enum Gamemode { +pub enum Gamemode { //Easy Abigail, //Normal @@ -55,120 +90,34 @@ enum Gamemode { GoodyOsborne } -fn build_characters() -> Vec { - vec![ - People::AbigailWilliams(Some(Character { - name: "Abigail Williams", - standing: Standing { - society: 10, - court: 10, - friends: vec![ - &People::BettyParris(None), - &People::DeputyGovernorDanforth(None), - &People::ReverendParris(None), - ], - enemies: vec![ - &People::ElizabethProctor(None), - &People::JohnProctor(None), - &People::ReverendJohnHale(None) - ] - } - })), - People::BettyParris(Some(Character { - name: "Betty Parris", - standing: Standing { - society: 10, - court: 10, - friends: vec![ - &People::AbigailWilliams(None), - &People::ReverendParris(None) - ], - enemies: vec![ - &People::JohnProctor(None), - &People::ElizabethProctor(None) - ] - } - })), - People::ElizabethProctor(Some(Character{ - name: "Elizabeth Proctor", - standing: Standing { - society: 10, - court: 5, - friends: vec![ - &People::FrancisNurse(None), - &People::GilesCorey(None), - &People::JohnProctor(None), - &People::RebeccaNurse(None), - &People::ReverendJohnHale(None) - ], - enemies: vec![ - &People::AbigailWilliams(None), - &People::DeputyGovernorDanforth(None), - &People::EzekielCheever(None) - ] - } - })) - ] -} - -fn build_player(gamemode: Gamemode) -> Character { - Character { - name: "You", - standing: match gamemode { - Gamemode::Abigail => Standing { - society: 10, - court: 10, - friends: vec![], - enemies: vec![] - }, - Gamemode::MaryWarren => Standing { - society: 5, - court: 5, - friends: vec![], - enemies: vec![] - }, - Gamemode::JohnProctor => Standing { - society: 2, - court: 2, - friends: vec![], - enemies: vec![] - }, - Gamemode::GoodyOsborne => Standing { - society: -15, - court: -5, - friends: vec![], - enemies: vec![] - } - } - } -} - -fn get_gamemode(cmd_args: Vec) -> Gamemode { - if cmd_args.len() != 1 { - match &cmd_args[1] { - ArgType::Command(c) => match c.as_str() { - "abigail" => Gamemode::Abigail, - "john_proctor" => Gamemode::JohnProctor, - "goody_osborne" => Gamemode::GoodyOsborne, - _ => Gamemode::MaryWarren - }, - ArgType::Flag(f) => match f { - FlagType::Long(l) => match l.as_str() { +impl Gamemode { + fn get(cmd_args: &Vec) -> Gamemode { + if cmd_args.len() != 1 { + match &cmd_args[1] { + ArgType::Command(c) => match c.as_str() { "abigail" => Gamemode::Abigail, - "john-proctor" => Gamemode::JohnProctor, - "goody-osborne" => Gamemode::GoodyOsborne, + "john_proctor" => Gamemode::JohnProctor, + "goody_osborne" => Gamemode::GoodyOsborne, _ => Gamemode::MaryWarren }, - FlagType::Short(s) => match s.as_str() { - "a" => Gamemode::Abigail, - "j" => Gamemode::JohnProctor, - "o" => Gamemode::GoodyOsborne, - _ => Gamemode::MaryWarren - } - }, - _ => Gamemode::MaryWarren + ArgType::Flag(f) => match f { + FlagType::Long(l) => match l.as_str() { + "abigail" => Gamemode::Abigail, + "john-proctor" => Gamemode::JohnProctor, + "goody-osborne" => Gamemode::GoodyOsborne, + _ => Gamemode::MaryWarren + }, + FlagType::Short(s) => match s.as_str() { + "a" => Gamemode::Abigail, + "j" => Gamemode::JohnProctor, + "o" => Gamemode::GoodyOsborne, + _ => Gamemode::MaryWarren + } + }, + _ => Gamemode::MaryWarren + } + } else { + Gamemode::MaryWarren } - } else { - Gamemode::MaryWarren } -} \ No newline at end of file +}