2025-06-23 09:48:28 +01:00
|
|
|
use serde::{Deserialize, Serialize};
|
2025-09-30 13:07:59 +01:00
|
|
|
use werewolves_macros::{ChecksAs, Titles};
|
2025-06-23 09:48:28 +01:00
|
|
|
|
|
|
|
|
use crate::{
|
2025-09-30 13:07:59 +01:00
|
|
|
message::CharacterIdentity,
|
2025-06-23 09:48:28 +01:00
|
|
|
player::CharacterId,
|
2025-09-30 13:07:59 +01:00
|
|
|
role::{Alignment, PreviousGuardianAction, RoleTitle},
|
2025-06-23 09:48:28 +01:00
|
|
|
};
|
|
|
|
|
|
2025-09-30 13:07:59 +01:00
|
|
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd)]
|
2025-09-28 02:13:34 +01:00
|
|
|
pub enum ActionType {
|
2025-09-30 13:07:59 +01:00
|
|
|
Cover,
|
|
|
|
|
WolvesIntro,
|
|
|
|
|
Protect,
|
|
|
|
|
WolfPackKill,
|
|
|
|
|
Direwolf,
|
|
|
|
|
OtherWolf,
|
|
|
|
|
Block,
|
|
|
|
|
Other,
|
|
|
|
|
RoleChange,
|
2025-09-28 02:13:34 +01:00
|
|
|
}
|
|
|
|
|
|
2025-09-30 13:07:59 +01:00
|
|
|
impl ActionType {
|
|
|
|
|
const fn is_wolfy(&self) -> bool {
|
|
|
|
|
matches!(
|
|
|
|
|
self,
|
|
|
|
|
ActionType::Direwolf
|
|
|
|
|
| ActionType::OtherWolf
|
|
|
|
|
| ActionType::WolfPackKill
|
|
|
|
|
| ActionType::WolvesIntro
|
|
|
|
|
)
|
2025-09-28 02:13:34 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-30 13:07:59 +01:00
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, ChecksAs, Titles)]
|
2025-06-23 09:48:28 +01:00
|
|
|
pub enum ActionPrompt {
|
2025-09-30 13:07:59 +01:00
|
|
|
#[checks(ActionType::Cover)]
|
|
|
|
|
CoverOfDarkness,
|
2025-09-28 02:13:34 +01:00
|
|
|
#[checks(ActionType::WolfPackKill)]
|
2025-09-30 13:07:59 +01:00
|
|
|
#[checks]
|
2025-10-02 17:52:12 +01:00
|
|
|
WolvesIntro {
|
|
|
|
|
wolves: Box<[(CharacterIdentity, RoleTitle)]>,
|
|
|
|
|
},
|
2025-09-28 02:13:34 +01:00
|
|
|
#[checks(ActionType::RoleChange)]
|
2025-09-30 13:07:59 +01:00
|
|
|
RoleChange {
|
|
|
|
|
character_id: CharacterIdentity,
|
|
|
|
|
new_role: RoleTitle,
|
|
|
|
|
},
|
2025-09-28 02:13:34 +01:00
|
|
|
#[checks(ActionType::Other)]
|
2025-09-30 13:07:59 +01:00
|
|
|
Seer {
|
|
|
|
|
character_id: CharacterIdentity,
|
2025-10-02 17:52:12 +01:00
|
|
|
living_players: Box<[CharacterIdentity]>,
|
2025-09-30 13:07:59 +01:00
|
|
|
},
|
2025-09-28 02:13:34 +01:00
|
|
|
#[checks(ActionType::Protect)]
|
2025-09-30 13:07:59 +01:00
|
|
|
Protector {
|
|
|
|
|
character_id: CharacterIdentity,
|
2025-10-02 17:52:12 +01:00
|
|
|
targets: Box<[CharacterIdentity]>,
|
2025-09-30 13:07:59 +01:00
|
|
|
},
|
2025-09-28 02:13:34 +01:00
|
|
|
#[checks(ActionType::Other)]
|
2025-09-30 13:07:59 +01:00
|
|
|
Arcanist {
|
|
|
|
|
character_id: CharacterIdentity,
|
2025-10-02 17:52:12 +01:00
|
|
|
living_players: Box<[CharacterIdentity]>,
|
2025-09-30 13:07:59 +01:00
|
|
|
},
|
2025-09-28 02:13:34 +01:00
|
|
|
#[checks(ActionType::Other)]
|
2025-09-30 13:07:59 +01:00
|
|
|
Gravedigger {
|
|
|
|
|
character_id: CharacterIdentity,
|
2025-10-02 17:52:12 +01:00
|
|
|
dead_players: Box<[CharacterIdentity]>,
|
2025-09-30 13:07:59 +01:00
|
|
|
},
|
2025-09-28 02:13:34 +01:00
|
|
|
#[checks(ActionType::Other)]
|
2025-06-23 09:48:28 +01:00
|
|
|
Hunter {
|
2025-09-30 13:07:59 +01:00
|
|
|
character_id: CharacterIdentity,
|
2025-10-02 17:52:12 +01:00
|
|
|
current_target: Option<CharacterIdentity>,
|
|
|
|
|
living_players: Box<[CharacterIdentity]>,
|
2025-06-23 09:48:28 +01:00
|
|
|
},
|
2025-09-28 02:13:34 +01:00
|
|
|
#[checks(ActionType::Other)]
|
2025-09-30 13:07:59 +01:00
|
|
|
Militia {
|
|
|
|
|
character_id: CharacterIdentity,
|
2025-10-02 17:52:12 +01:00
|
|
|
living_players: Box<[CharacterIdentity]>,
|
2025-09-30 13:07:59 +01:00
|
|
|
},
|
2025-09-28 02:13:34 +01:00
|
|
|
#[checks(ActionType::Other)]
|
2025-06-23 09:48:28 +01:00
|
|
|
MapleWolf {
|
2025-09-30 13:07:59 +01:00
|
|
|
character_id: CharacterIdentity,
|
2025-06-23 09:48:28 +01:00
|
|
|
kill_or_die: bool,
|
2025-10-02 17:52:12 +01:00
|
|
|
living_players: Box<[CharacterIdentity]>,
|
2025-06-23 09:48:28 +01:00
|
|
|
},
|
2025-09-28 02:13:34 +01:00
|
|
|
#[checks(ActionType::Protect)]
|
2025-06-23 09:48:28 +01:00
|
|
|
Guardian {
|
2025-09-30 13:07:59 +01:00
|
|
|
character_id: CharacterIdentity,
|
2025-06-23 09:48:28 +01:00
|
|
|
previous: Option<PreviousGuardianAction>,
|
2025-10-02 17:52:12 +01:00
|
|
|
living_players: Box<[CharacterIdentity]>,
|
2025-06-23 09:48:28 +01:00
|
|
|
},
|
2025-09-30 13:07:59 +01:00
|
|
|
#[checks(ActionType::WolfPackKill)]
|
2025-10-02 17:52:12 +01:00
|
|
|
WolfPackKill {
|
|
|
|
|
living_villagers: Box<[CharacterIdentity]>,
|
|
|
|
|
},
|
2025-09-30 13:07:59 +01:00
|
|
|
#[checks(ActionType::OtherWolf)]
|
|
|
|
|
Shapeshifter { character_id: CharacterIdentity },
|
|
|
|
|
#[checks(ActionType::OtherWolf)]
|
|
|
|
|
AlphaWolf {
|
|
|
|
|
character_id: CharacterIdentity,
|
2025-10-02 17:52:12 +01:00
|
|
|
living_villagers: Box<[CharacterIdentity]>,
|
2025-09-30 13:07:59 +01:00
|
|
|
},
|
2025-09-28 02:13:34 +01:00
|
|
|
#[checks(ActionType::Direwolf)]
|
2025-09-30 13:07:59 +01:00
|
|
|
DireWolf {
|
|
|
|
|
character_id: CharacterIdentity,
|
2025-10-02 17:52:12 +01:00
|
|
|
living_players: Box<[CharacterIdentity]>,
|
2025-09-30 13:07:59 +01:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-06-23 09:48:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PartialOrd for ActionPrompt {
|
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
2025-09-28 02:13:34 +01:00
|
|
|
self.action_type().partial_cmp(&other.action_type())
|
2025-06-23 09:48:28 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Serialize, PartialEq, Deserialize, ChecksAs)]
|
|
|
|
|
pub enum ActionResponse {
|
|
|
|
|
Seer(CharacterId),
|
|
|
|
|
Arcanist(CharacterId, CharacterId),
|
|
|
|
|
Gravedigger(CharacterId),
|
|
|
|
|
Hunter(CharacterId),
|
|
|
|
|
Militia(Option<CharacterId>),
|
|
|
|
|
MapleWolf(Option<CharacterId>),
|
|
|
|
|
Guardian(CharacterId),
|
|
|
|
|
WolfPackKillVote(CharacterId),
|
|
|
|
|
#[checks]
|
|
|
|
|
Shapeshifter(bool),
|
|
|
|
|
AlphaWolf(Option<CharacterId>),
|
|
|
|
|
Direwolf(CharacterId),
|
|
|
|
|
Protector(CharacterId),
|
|
|
|
|
#[checks]
|
|
|
|
|
RoleChangeAck,
|
|
|
|
|
WolvesIntroAck,
|
2025-09-30 13:07:59 +01:00
|
|
|
ClearCoverOfDarkness,
|
2025-06-23 09:48:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
|
|
|
pub enum ActionResult {
|
|
|
|
|
RoleBlocked,
|
|
|
|
|
Seer(Alignment),
|
|
|
|
|
Arcanist { same: bool },
|
|
|
|
|
GraveDigger(Option<RoleTitle>),
|
|
|
|
|
GoBackToSleep,
|
2025-09-30 13:07:59 +01:00
|
|
|
Continue,
|
2025-06-23 09:48:28 +01:00
|
|
|
}
|