use core::num::NonZeroU8; use serde::{Deserialize, Serialize}; use werewolves_macros::{ChecksAs, Titles}; use crate::{ game::{DateTime, Village}, message::CharacterIdentity, player::CharacterId, }; #[derive(Debug, Clone, Serialize, Deserialize, ChecksAs, Titles)] pub enum Role { #[checks(Alignment::Village)] Villager, #[checks(Alignment::Wolves)] #[checks("killer")] #[checks("powerful")] Scapegoat, #[checks(Alignment::Village)] #[checks("powerful")] #[checks("is_mentor")] Seer, #[checks(Alignment::Village)] #[checks("powerful")] #[checks("is_mentor")] Arcanist, #[checks(Alignment::Village)] #[checks("powerful")] #[checks("is_mentor")] Gravedigger, #[checks(Alignment::Village)] #[checks("killer")] #[checks("powerful")] #[checks("is_mentor")] #[checks] Hunter { target: Option }, #[checks(Alignment::Village)] #[checks("killer")] #[checks("powerful")] #[checks("is_mentor")] Militia { targeted: Option }, #[checks(Alignment::Wolves)] #[checks("killer")] #[checks("powerful")] #[checks("is_mentor")] MapleWolf { last_kill_on_night: u8 }, #[checks(Alignment::Village)] #[checks("powerful")] #[checks("killer")] #[checks("is_mentor")] Guardian { last_protected: Option, }, #[checks(Alignment::Village)] #[checks("powerful")] #[checks("is_mentor")] Protector { last_protected: Option }, #[checks(Alignment::Village)] #[checks("powerful")] Apprentice(Box), #[checks(Alignment::Village)] #[checks("powerful")] #[checks("is_mentor")] Elder { knows_on_night: NonZeroU8 }, #[checks(Alignment::Wolves)] #[checks("killer")] #[checks("powerful")] #[checks("wolf")] Werewolf, #[checks(Alignment::Wolves)] #[checks("killer")] #[checks("powerful")] #[checks("wolf")] AlphaWolf { killed: Option }, #[checks(Alignment::Village)] #[checks("killer")] #[checks("powerful")] #[checks("wolf")] DireWolf, #[checks(Alignment::Wolves)] #[checks("killer")] #[checks("powerful")] #[checks("wolf")] Shapeshifter { shifted_into: Option }, } impl Role { /// [RoleTitle] as shown to the player on role assignment pub const fn initial_shown_role(&self) -> RoleTitle { match self { Role::Apprentice(_) | Role::Elder { knows_on_night: _ } => RoleTitle::Villager, _ => self.title(), } } pub fn wakes(&self, village: &Village) -> bool { let night_zero = match village.date_time() { DateTime::Day { number: _ } => return false, DateTime::Night { number } => number == 0, }; if night_zero { return match self { Role::DireWolf | Role::Arcanist | Role::Seer => true, Role::Shapeshifter { shifted_into: _ } | Role::Werewolf | Role::AlphaWolf { killed: _ } | Role::Elder { knows_on_night: _ } | Role::Gravedigger | Role::Hunter { target: _ } | Role::Militia { targeted: _ } | Role::MapleWolf { last_kill_on_night: _, } | Role::Guardian { last_protected: _ } | Role::Apprentice(_) | Role::Villager | Role::Scapegoat | Role::Protector { last_protected: _ } => false, }; } match self { Role::AlphaWolf { killed: Some(_) } | Role::Werewolf | Role::Scapegoat | Role::Militia { targeted: Some(_) } | Role::Villager => false, Role::Shapeshifter { shifted_into: _ } | Role::DireWolf | Role::AlphaWolf { killed: None } | Role::Arcanist | Role::Protector { last_protected: _ } | Role::Gravedigger | Role::Hunter { target: _ } | Role::Militia { targeted: None } | Role::MapleWolf { last_kill_on_night: _, } | Role::Guardian { last_protected: _ } | Role::Seer => true, Role::Apprentice(role) => village .characters() .iter() .any(|c| c.role().title() == role.title()), Role::Elder { knows_on_night } => match village.date_time() { DateTime::Night { number } => number == knows_on_night.get(), _ => false, }, } } } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum Alignment { Village, Wolves, } #[derive(Debug, Clone, Serialize, Deserialize, ChecksAs)] pub enum ArcanistCheck { #[checks] Same, #[checks] Different, } pub const MAPLE_WOLF_ABSTAIN_LIMIT: NonZeroU8 = NonZeroU8::new(3).unwrap(); #[derive(Debug, Clone, Serialize, Deserialize)] pub enum RoleBlock { Direwolf, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum PreviousGuardianAction { Protect(CharacterIdentity), Guard(CharacterIdentity), }