use serde::{Deserialize, Serialize}; use werewolves_macros::{ChecksAs, Titles}; use crate::{ message::CharacterIdentity, player::CharacterId, role::{Alignment, PreviousGuardianAction, RoleTitle}, }; #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd)] pub enum ActionType { Cover, WolvesIntro, Protect, WolfPackKill, Direwolf, OtherWolf, Block, Other, RoleChange, } impl ActionType { const fn is_wolfy(&self) -> bool { matches!( self, ActionType::Direwolf | ActionType::OtherWolf | ActionType::WolfPackKill | ActionType::WolvesIntro ) } } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, ChecksAs, Titles)] pub enum ActionPrompt { #[checks(ActionType::Cover)] CoverOfDarkness, #[checks(ActionType::WolfPackKill)] #[checks] WolvesIntro { wolves: Box<[(CharacterIdentity, RoleTitle)]>, }, #[checks(ActionType::RoleChange)] RoleChange { character_id: CharacterIdentity, new_role: RoleTitle, }, #[checks(ActionType::Other)] Seer { character_id: CharacterIdentity, living_players: Box<[CharacterIdentity]>, }, #[checks(ActionType::Protect)] Protector { character_id: CharacterIdentity, targets: Box<[CharacterIdentity]>, }, #[checks(ActionType::Other)] Arcanist { character_id: CharacterIdentity, living_players: Box<[CharacterIdentity]>, }, #[checks(ActionType::Other)] Gravedigger { character_id: CharacterIdentity, dead_players: Box<[CharacterIdentity]>, }, #[checks(ActionType::Other)] Hunter { character_id: CharacterIdentity, current_target: Option, living_players: Box<[CharacterIdentity]>, }, #[checks(ActionType::Other)] Militia { character_id: CharacterIdentity, living_players: Box<[CharacterIdentity]>, }, #[checks(ActionType::Other)] MapleWolf { character_id: CharacterIdentity, kill_or_die: bool, living_players: Box<[CharacterIdentity]>, }, #[checks(ActionType::Protect)] Guardian { character_id: CharacterIdentity, previous: Option, living_players: Box<[CharacterIdentity]>, }, #[checks(ActionType::WolfPackKill)] WolfPackKill { living_villagers: Box<[CharacterIdentity]>, }, #[checks(ActionType::OtherWolf)] Shapeshifter { character_id: CharacterIdentity }, #[checks(ActionType::OtherWolf)] AlphaWolf { character_id: CharacterIdentity, living_villagers: Box<[CharacterIdentity]>, }, #[checks(ActionType::Direwolf)] DireWolf { character_id: CharacterIdentity, living_players: Box<[CharacterIdentity]>, }, } impl ActionPrompt { pub const fn is_wolfy(&self) -> bool { self.action_type().is_wolfy() || match self { ActionPrompt::RoleChange { character_id: _, new_role, } => new_role.wolf(), _ => false, } } } impl PartialOrd for ActionPrompt { fn partial_cmp(&self, other: &Self) -> Option { self.action_type().partial_cmp(&other.action_type()) } } #[derive(Debug, Clone, Serialize, PartialEq, Deserialize, ChecksAs)] pub enum ActionResponse { Seer(CharacterId), Arcanist(CharacterId, CharacterId), Gravedigger(CharacterId), Hunter(CharacterId), Militia(Option), MapleWolf(Option), Guardian(CharacterId), WolfPackKillVote(CharacterId), #[checks] Shapeshifter(bool), AlphaWolf(Option), Direwolf(CharacterId), Protector(CharacterId), #[checks] RoleChangeAck, WolvesIntroAck, ClearCoverOfDarkness, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum ActionResult { RoleBlocked, Seer(Alignment), Arcanist { same: bool }, GraveDigger(Option), GoBackToSleep, Continue, }