pyremaster role and tests
This commit is contained in:
parent
9fa5843b5a
commit
da580a459e
|
|
@ -49,6 +49,10 @@ pub enum DiedTo {
|
||||||
killer: CharacterId,
|
killer: CharacterId,
|
||||||
night: NonZeroU8,
|
night: NonZeroU8,
|
||||||
},
|
},
|
||||||
|
PyreMasterLynchMob {
|
||||||
|
source: CharacterId,
|
||||||
|
night: NonZeroU8,
|
||||||
|
},
|
||||||
MasonLeaderRecruitFail {
|
MasonLeaderRecruitFail {
|
||||||
tried_recruiting: CharacterId,
|
tried_recruiting: CharacterId,
|
||||||
night: u8,
|
night: u8,
|
||||||
|
|
@ -68,6 +72,7 @@ impl DiedTo {
|
||||||
| DiedTo::Shapeshift { night, .. }
|
| DiedTo::Shapeshift { night, .. }
|
||||||
| DiedTo::Hunter { night, .. }
|
| DiedTo::Hunter { night, .. }
|
||||||
| DiedTo::GuardianProtecting { night, .. }
|
| DiedTo::GuardianProtecting { night, .. }
|
||||||
|
| DiedTo::PyreMasterLynchMob { night, .. }
|
||||||
| DiedTo::PyreMaster { night, .. } => *night = NonZeroU8::new(night.get() + 1)?,
|
| DiedTo::PyreMaster { night, .. } => *night = NonZeroU8::new(night.get() + 1)?,
|
||||||
DiedTo::MasonLeaderRecruitFail { night, .. } => *night = *night + 1,
|
DiedTo::MasonLeaderRecruitFail { night, .. } => *night = *night + 1,
|
||||||
}
|
}
|
||||||
|
|
@ -95,6 +100,7 @@ impl DiedTo {
|
||||||
tried_recruiting: killer,
|
tried_recruiting: killer,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
| DiedTo::PyreMasterLynchMob { source: killer, .. }
|
||||||
| DiedTo::PyreMaster { killer, .. } => Some(*killer),
|
| DiedTo::PyreMaster { killer, .. } => Some(*killer),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -121,6 +127,7 @@ impl DiedTo {
|
||||||
}
|
}
|
||||||
| DiedTo::AlphaWolf { killer: _, night }
|
| DiedTo::AlphaWolf { killer: _, night }
|
||||||
| DiedTo::Shapeshift { into: _, night }
|
| DiedTo::Shapeshift { into: _, night }
|
||||||
|
| DiedTo::PyreMasterLynchMob { night, .. }
|
||||||
| DiedTo::PyreMaster { night, .. }
|
| DiedTo::PyreMaster { night, .. }
|
||||||
| DiedTo::Hunter { killer: _, night } => DateTime::Night {
|
| DiedTo::Hunter { killer: _, night } => DateTime::Night {
|
||||||
number: night.get(),
|
number: night.get(),
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
message::night::{ActionPrompt, ActionResponse, ActionResult},
|
message::night::{ActionPrompt, ActionResponse, ActionResult},
|
||||||
player::Protection,
|
player::Protection,
|
||||||
role::{PreviousGuardianAction, RoleBlock, RoleTitle},
|
role::{PYREMASTER_VILLAGER_KILLS_TO_DIE, PreviousGuardianAction, RoleBlock, RoleTitle},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Extract)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Extract)]
|
||||||
|
|
@ -457,15 +457,44 @@ impl Night {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// black knights death
|
||||||
for knight in new_village
|
for knight in new_village
|
||||||
.characters_mut()
|
.characters_mut()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
.filter(|k| k.alive())
|
||||||
.filter(|k| k.black_knight().ok().and_then(|t| (*t).clone()).is_some())
|
.filter(|k| k.black_knight().ok().and_then(|t| (*t).clone()).is_some())
|
||||||
.filter(|k| changes.killed(k.character_id()).is_none())
|
.filter(|k| changes.killed(k.character_id()).is_none())
|
||||||
{
|
{
|
||||||
knight.black_knight_kill()?.kill();
|
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() {
|
if new_village.is_game_over().is_none() {
|
||||||
new_village.to_day()?;
|
new_village.to_day()?;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -224,6 +224,7 @@ pub trait GameExt {
|
||||||
target: CharacterId,
|
target: CharacterId,
|
||||||
) -> (Box<[CharacterState]>, Box<[CharacterId]>, NonZeroU8);
|
) -> (Box<[CharacterState]>, Box<[CharacterId]>, NonZeroU8);
|
||||||
fn living_villager_excl(&self, excl: PlayerId) -> Character;
|
fn living_villager_excl(&self, excl: PlayerId) -> Character;
|
||||||
|
fn living_villager(&self) -> Character;
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn get_state(&mut self) -> ServerToHostMessage;
|
fn get_state(&mut self) -> ServerToHostMessage;
|
||||||
}
|
}
|
||||||
|
|
@ -232,6 +233,13 @@ impl GameExt for Game {
|
||||||
fn get_state(&mut self) -> ServerToHostMessage {
|
fn get_state(&mut self) -> ServerToHostMessage {
|
||||||
self.process(HostGameMessage::GetState).unwrap()
|
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 {
|
fn living_villager_excl(&self, excl: PlayerId) -> Character {
|
||||||
self.village()
|
self.village()
|
||||||
|
|
@ -248,7 +256,8 @@ impl GameExt for Game {
|
||||||
.characters()
|
.characters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|c| {
|
.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()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,6 @@ mod diseased;
|
||||||
mod elder;
|
mod elder;
|
||||||
mod empath;
|
mod empath;
|
||||||
mod mason;
|
mod mason;
|
||||||
|
mod pyremaster;
|
||||||
mod scapegoat;
|
mod scapegoat;
|
||||||
mod shapeshifter;
|
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 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)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum RoleBlock {
|
pub enum RoleBlock {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue