pyremaster role and tests
This commit is contained in:
parent
9fa5843b5a
commit
da580a459e
|
|
@ -49,6 +49,10 @@ pub enum DiedTo {
|
|||
killer: CharacterId,
|
||||
night: NonZeroU8,
|
||||
},
|
||||
PyreMasterLynchMob {
|
||||
source: CharacterId,
|
||||
night: NonZeroU8,
|
||||
},
|
||||
MasonLeaderRecruitFail {
|
||||
tried_recruiting: CharacterId,
|
||||
night: u8,
|
||||
|
|
@ -68,6 +72,7 @@ impl DiedTo {
|
|||
| DiedTo::Shapeshift { night, .. }
|
||||
| DiedTo::Hunter { night, .. }
|
||||
| DiedTo::GuardianProtecting { night, .. }
|
||||
| DiedTo::PyreMasterLynchMob { night, .. }
|
||||
| DiedTo::PyreMaster { night, .. } => *night = NonZeroU8::new(night.get() + 1)?,
|
||||
DiedTo::MasonLeaderRecruitFail { night, .. } => *night = *night + 1,
|
||||
}
|
||||
|
|
@ -95,6 +100,7 @@ impl DiedTo {
|
|||
tried_recruiting: killer,
|
||||
..
|
||||
}
|
||||
| DiedTo::PyreMasterLynchMob { source: killer, .. }
|
||||
| DiedTo::PyreMaster { killer, .. } => Some(*killer),
|
||||
}
|
||||
}
|
||||
|
|
@ -121,6 +127,7 @@ impl DiedTo {
|
|||
}
|
||||
| DiedTo::AlphaWolf { killer: _, night }
|
||||
| DiedTo::Shapeshift { into: _, night }
|
||||
| DiedTo::PyreMasterLynchMob { night, .. }
|
||||
| DiedTo::PyreMaster { night, .. }
|
||||
| DiedTo::Hunter { killer: _, night } => DateTime::Night {
|
||||
number: night.get(),
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use crate::{
|
|||
},
|
||||
message::night::{ActionPrompt, ActionResponse, ActionResult},
|
||||
player::Protection,
|
||||
role::{PreviousGuardianAction, RoleBlock, RoleTitle},
|
||||
role::{PYREMASTER_VILLAGER_KILLS_TO_DIE, PreviousGuardianAction, RoleBlock, RoleTitle},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Extract)]
|
||||
|
|
@ -457,15 +457,44 @@ impl Night {
|
|||
}
|
||||
}
|
||||
}
|
||||
// black knights death
|
||||
for knight in new_village
|
||||
.characters_mut()
|
||||
.into_iter()
|
||||
.filter(|k| k.alive())
|
||||
.filter(|k| k.black_knight().ok().and_then(|t| (*t).clone()).is_some())
|
||||
.filter(|k| changes.killed(k.character_id()).is_none())
|
||||
{
|
||||
knight.black_knight_kill()?.kill();
|
||||
}
|
||||
|
||||
// pyre masters death
|
||||
let village_dead = new_village
|
||||
.characters()
|
||||
.into_iter()
|
||||
.filter(|c| c.is_village())
|
||||
.filter_map(|c| c.died_to().cloned())
|
||||
.filter_map(|c| c.killer().map(|k| (k, c)))
|
||||
.collect::<Box<[_]>>();
|
||||
for pyremaster in new_village
|
||||
.living_characters_by_role_mut(RoleTitle::PyreMaster)
|
||||
.into_iter()
|
||||
.filter(|p| {
|
||||
village_dead
|
||||
.iter()
|
||||
.filter(|(k, _)| *k == p.character_id())
|
||||
.count()
|
||||
>= PYREMASTER_VILLAGER_KILLS_TO_DIE.get() as usize
|
||||
})
|
||||
{
|
||||
if let Some(night) = NonZeroU8::new(self.night) {
|
||||
pyremaster.kill(DiedTo::PyreMasterLynchMob {
|
||||
night,
|
||||
source: pyremaster.character_id(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if new_village.is_game_over().is_none() {
|
||||
new_village.to_day()?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ pub trait GameExt {
|
|||
target: CharacterId,
|
||||
) -> (Box<[CharacterState]>, Box<[CharacterId]>, NonZeroU8);
|
||||
fn living_villager_excl(&self, excl: PlayerId) -> Character;
|
||||
fn living_villager(&self) -> Character;
|
||||
#[allow(unused)]
|
||||
fn get_state(&mut self) -> ServerToHostMessage;
|
||||
}
|
||||
|
|
@ -232,6 +233,13 @@ impl GameExt for Game {
|
|||
fn get_state(&mut self) -> ServerToHostMessage {
|
||||
self.process(HostGameMessage::GetState).unwrap()
|
||||
}
|
||||
fn living_villager(&self) -> Character {
|
||||
self.village()
|
||||
.characters()
|
||||
.into_iter()
|
||||
.find(|c| c.alive() && matches!(c.role_title(), RoleTitle::Villager))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn living_villager_excl(&self, excl: PlayerId) -> Character {
|
||||
self.village()
|
||||
|
|
@ -248,7 +256,8 @@ impl GameExt for Game {
|
|||
.characters()
|
||||
.into_iter()
|
||||
.filter_map(|c| {
|
||||
matches!(c.role_title(), RoleTitle::Villager).then_some(c.character_id())
|
||||
(c.alive() && matches!(c.role_title(), RoleTitle::Villager))
|
||||
.then_some(c.character_id())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,5 +4,6 @@ mod diseased;
|
|||
mod elder;
|
||||
mod empath;
|
||||
mod mason;
|
||||
mod pyremaster;
|
||||
mod scapegoat;
|
||||
mod shapeshifter;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
use core::num::NonZeroU8;
|
||||
#[allow(unused)]
|
||||
use pretty_assertions::{assert_eq, assert_ne, assert_str_eq};
|
||||
|
||||
use crate::{
|
||||
diedto::DiedTo,
|
||||
game::{Game, GameSettings, SetupRole},
|
||||
game_test::{ActionPromptTitleExt, ActionResultExt, GameExt, SettingsExt, gen_players},
|
||||
message::night::ActionPromptTitle,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn burnout() {
|
||||
let players = gen_players(1..21);
|
||||
let pyremaster_player_id = players[0].player_id;
|
||||
let wolf_player_id = players[1].player_id;
|
||||
let mut settings = GameSettings::empty();
|
||||
settings.add_and_assign(SetupRole::PyreMaster, pyremaster_player_id);
|
||||
settings.add_and_assign(SetupRole::Werewolf, wolf_player_id);
|
||||
settings.fill_remaining_slots_with_villagers(20);
|
||||
let mut game = Game::new(&players, settings).unwrap();
|
||||
game.r#continue().r#continue();
|
||||
assert_eq!(game.next().title(), ActionPromptTitle::WolvesIntro);
|
||||
game.r#continue().sleep();
|
||||
|
||||
let mut villagers = game.villager_character_ids().into_iter();
|
||||
game.next_expect_day();
|
||||
game.execute().title().wolf_pack_kill();
|
||||
game.mark(villagers.next().unwrap());
|
||||
game.r#continue().sleep();
|
||||
|
||||
game.next().title().pyremaster();
|
||||
game.mark(villagers.next().unwrap());
|
||||
game.r#continue().sleep();
|
||||
|
||||
game.next_expect_day();
|
||||
|
||||
villagers = game.villager_character_ids().into_iter();
|
||||
|
||||
game.execute().title().wolf_pack_kill();
|
||||
game.mark(villagers.next().unwrap());
|
||||
game.r#continue().sleep();
|
||||
|
||||
game.next().title().pyremaster();
|
||||
game.mark(villagers.next().unwrap());
|
||||
game.r#continue().sleep();
|
||||
|
||||
game.next_expect_day();
|
||||
|
||||
assert_eq!(
|
||||
game.character_by_player_id(pyremaster_player_id)
|
||||
.died_to()
|
||||
.cloned(),
|
||||
Some(DiedTo::PyreMasterLynchMob {
|
||||
source: game
|
||||
.character_by_player_id(pyremaster_player_id)
|
||||
.character_id(),
|
||||
night: NonZeroU8::new(2).unwrap()
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
@ -254,6 +254,7 @@ pub enum ArcanistCheck {
|
|||
}
|
||||
|
||||
pub const MAPLE_WOLF_ABSTAIN_LIMIT: NonZeroU8 = NonZeroU8::new(3).unwrap();
|
||||
pub const PYREMASTER_VILLAGER_KILLS_TO_DIE: NonZeroU8 = NonZeroU8::new(2).unwrap();
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum RoleBlock {
|
||||
|
|
|
|||
Loading…
Reference in New Issue