Skip to content

Commit

Permalink
santa does defense check, and works with retributionist
Browse files Browse the repository at this point in the history
  • Loading branch information
ItsSammyM committed Jan 3, 2025
1 parent dcbdc25 commit 572c2b1
Showing 1 changed file with 63 additions and 91 deletions.
154 changes: 63 additions & 91 deletions server/src/game/role/santa_claus.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
use rand::seq::SliceRandom;
use rand::thread_rng;
use serde::Serialize;

use crate::game::chat::ChatMessageVariant;
use crate::game::components::detained::Detained;
use crate::game::game_conclusion::GameConclusion;
use crate::game::phase::PhaseType;
use crate::game::win_condition::WinCondition;
use crate::game::attack_power::DefensePower;
use crate::game::attack_power::{AttackPower, DefensePower};
use crate::game::player::PlayerReference;

use crate::game::visit::{Visit, VisitTag};
use crate::game::visit::Visit;
use crate::game::Game;
use crate::vec_set::{vec_set, VecSet};

use super::{AbilitySelection, ControllerID, ControllerParametersMap, Priority, Role, RoleStateImpl};

#[derive(Clone, Debug, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SantaClaus {
pub next_ability: SantaListKind,
pub ability_used_last_night: Option<SantaListKind>,
}

Expand All @@ -39,66 +33,65 @@ impl RoleStateImpl for SantaClaus {
fn do_night_action(self, game: &mut Game, actor_ref: PlayerReference, priority: Priority) {
if priority != Priority::Convert { return }

match self.next_ability {
match self.get_next_santa_ability() {
SantaListKind::Nice => {
let actor_visits = actor_ref.untagged_night_visits_cloned(game).into_iter();
let targets = actor_visits.map(|v| v.target);

for target_ref in targets {
let WinCondition::GameConclusionReached { mut win_if_any } = target_ref.win_condition(game).clone() else { continue };
if !get_eligible_players(game, actor_ref).contains(&target_ref) { continue }

match target_ref.win_condition(game).clone() {
WinCondition::GameConclusionReached { mut win_if_any } => {
win_if_any.insert(GameConclusion::NiceList);
target_ref.set_win_condition(game, WinCondition::GameConclusionReached { win_if_any });

target_ref.push_night_message(game, ChatMessageVariant::AddedToNiceList);
actor_ref.set_role_state(game, Self {
ability_used_last_night: Some(SantaListKind::Nice),
..self
});
}
WinCondition::RoleStateWon => {}

if !AttackPower::ArmorPiercing.can_pierce(target_ref.defense(game)) {
actor_ref.push_night_message(game, ChatMessageVariant::YourConvertFailed);
continue;
}

win_if_any.insert(GameConclusion::NiceList);
target_ref.set_win_condition(game, WinCondition::GameConclusionReached { win_if_any });
target_ref.push_night_message(game, ChatMessageVariant::AddedToNiceList);

actor_ref.set_role_state(game, Self {
ability_used_last_night: Some(SantaListKind::Nice),
..self
});
}
}
SantaListKind::Naughty => {
let actor_visits = actor_ref.untagged_night_visits_cloned(game).into_iter();
let targets = actor_visits.map(|v| v.target);

for target_ref in targets {
match target_ref.win_condition(game).clone() {
WinCondition::GameConclusionReached { mut win_if_any } => {
win_if_any.insert(GameConclusion::NaughtyList);
target_ref.set_win_condition(game, WinCondition::GameConclusionReached { win_if_any });


let krampus_list: Vec<PlayerReference> = PlayerReference::all_players(game)
.filter(|player| player.role(game) == Role::Krampus)
.collect();

if !krampus_list.is_empty() {
target_ref.push_night_message(game, ChatMessageVariant::AddedToNaughtyList);
}
for krampus in krampus_list {
krampus.push_night_message(game,
ChatMessageVariant::SantaAddedPlayerToNaughtyList { player: target_ref }
);
}
actor_ref.set_role_state(game, Self {
ability_used_last_night: Some(SantaListKind::Naughty),
..self
});
}
WinCondition::RoleStateWon => {}
let WinCondition::GameConclusionReached { mut win_if_any } = target_ref.win_condition(game).clone() else { continue };
if !get_eligible_players(game, actor_ref).contains(&target_ref) { continue };

if !AttackPower::ArmorPiercing.can_pierce(target_ref.defense(game)) {
actor_ref.push_night_message(game, ChatMessageVariant::YourConvertFailed);
continue;
}

win_if_any.insert(GameConclusion::NaughtyList);
target_ref.set_win_condition(game, WinCondition::GameConclusionReached { win_if_any });
target_ref.push_night_message(game, ChatMessageVariant::AddedToNaughtyList);

actor_ref.set_role_state(game, Self {
ability_used_last_night: Some(SantaListKind::Naughty),
..self
});

for krampus in PlayerReference::all_players(game) {
if krampus.role(game) != Role::Krampus { continue }

krampus.push_night_message(game,
ChatMessageVariant::SantaAddedPlayerToNaughtyList { player: target_ref }
);
}
}
}
}
}

fn controller_parameters_map(self, game: &Game, actor_ref: PlayerReference) -> super::ControllerParametersMap {
match self.next_ability {
match self.get_next_santa_ability() {
SantaListKind::Nice => {
ControllerParametersMap::new_controller_fast(
game,
Expand Down Expand Up @@ -133,71 +126,50 @@ impl RoleStateImpl for SantaClaus {
}
}
}
fn convert_selection_to_visits(self, game: &Game, actor_ref: PlayerReference) -> Vec<Visit> {
// Note: Sam, fix this when you fix jester
if !actor_ref.alive(game) {
return vec![];
}

match self.next_ability {
fn convert_selection_to_visits(self, game: &Game, actor_ref: PlayerReference) -> Vec<Visit> {
match self.get_next_santa_ability() {
SantaListKind::Nice => {
crate::game::role::common_role::convert_controller_selection_to_visits(
game,
actor_ref,
ControllerID::role(actor_ref, Role::SantaClaus, 0),
false,
true,
)
}
SantaListKind::Naughty => {
let visits = crate::game::role::common_role::convert_controller_selection_to_visits(
crate::game::role::common_role::convert_controller_selection_to_visits(
game,
actor_ref,
ControllerID::role(actor_ref, Role::SantaClaus, 1),
false,
);
let eligible_targets: Vec<PlayerReference> = visits.iter()
.map(|v| v.target)
.filter(|t| get_eligible_players(game, actor_ref).contains(t))
.collect();

let mut eligible_options = get_eligible_players(game, actor_ref)
.into_iter()
.filter(|e| !eligible_targets.contains(e))
.collect::<Vec<PlayerReference>>();

eligible_options.shuffle(&mut thread_rng());

let mut targets: Vec<PlayerReference> = eligible_targets.into_iter().chain(eligible_options).collect();

targets.truncate(1);

targets.into_iter()
.map(|target| Visit::new(actor_ref, target, false, VisitTag::Role))
.collect()
true,
)
}
}
}
fn on_phase_start(self, game: &mut Game, actor_ref: PlayerReference, phase: PhaseType){
if phase == PhaseType::Obituary || phase == PhaseType::Night {
let mut new_state = self.clone();

if let Some(ability) = self.ability_used_last_night {
new_state.next_ability = match ability {
SantaListKind::Naughty => SantaListKind::Nice,
SantaListKind::Nice => SantaListKind::Naughty,
};
new_state.ability_used_last_night = None;
}

actor_ref.add_private_chat_message(game, ChatMessageVariant::NextSantaAbility { ability: new_state.next_ability });
actor_ref.set_role_state(game, new_state);
match phase {
PhaseType::Night => {
actor_ref.add_private_chat_message(game,
ChatMessageVariant::NextSantaAbility { ability: self.get_next_santa_ability() }
);
},
_ => {}
}
}
fn default_win_condition(self) -> WinCondition where super::RoleState: From<Self> {
WinCondition::GameConclusionReached { win_if_any: vec![GameConclusion::NiceList].into_iter().collect() }
}
}

impl SantaClaus {
fn get_next_santa_ability(&self)->SantaListKind{
match self.ability_used_last_night {
Some(SantaListKind::Nice) => SantaListKind::Naughty,
_ => SantaListKind::Nice,
}
}
}

fn get_selectable_players(game: &Game, actor_ref: PlayerReference) -> VecSet<PlayerReference> {
PlayerReference::all_players(game)
.filter(|&p|
Expand Down

0 comments on commit 572c2b1

Please sign in to comment.