wolf reverting + fix killing wolf
This commit is contained in:
parent
5c8e33dab1
commit
a424211ab4
|
|
@ -255,7 +255,27 @@ impl Night {
|
|||
.collect(),
|
||||
});
|
||||
}
|
||||
// let current_prompt = action_queue.pop_front().ok_or(GameError::NoNightActions)?;
|
||||
if let Some(prompt) = village.wolf_revert_prompt() {
|
||||
match &prompt {
|
||||
ActionPrompt::RoleChange {
|
||||
character_id,
|
||||
new_role,
|
||||
} => {
|
||||
action_queue = Self::remove_reverted_prompts(
|
||||
action_queue,
|
||||
character_id.character_id,
|
||||
*new_role,
|
||||
)
|
||||
}
|
||||
prompt => {
|
||||
log::error!(
|
||||
"wolf_revert_prompt should have returned a role change, got {prompt:?}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
action_queue.push_front(prompt);
|
||||
}
|
||||
let night_state = NightState::Active {
|
||||
current_prompt: ActionPrompt::CoverOfDarkness,
|
||||
current_changes: Vec::new(),
|
||||
|
|
@ -272,6 +292,84 @@ impl Night {
|
|||
})
|
||||
}
|
||||
|
||||
fn remove_reverted_prompts(
|
||||
mut action_queue: VecDeque<ActionPrompt>,
|
||||
reverting: CharacterId,
|
||||
reverting_into: RoleTitle,
|
||||
) -> VecDeque<ActionPrompt> {
|
||||
let mut new_queue = VecDeque::new();
|
||||
if let Some(wolves) = action_queue.iter_mut().find_map(|q| match q {
|
||||
ActionPrompt::WolvesIntro { wolves } => Some(wolves),
|
||||
_ => None,
|
||||
}) && let Some(w) = wolves.iter_mut().find(|w| w.0.character_id == reverting)
|
||||
{
|
||||
w.1 = reverting_into;
|
||||
}
|
||||
|
||||
// remove prompts by the reverting wolf that are in the queue
|
||||
for prompt in action_queue {
|
||||
let (wolf_id, prompt) = match prompt {
|
||||
ActionPrompt::WolvesIntro { mut wolves } => {
|
||||
if let Some(w) = wolves.iter_mut().find(|w| w.0.character_id == reverting) {
|
||||
w.1 = reverting_into;
|
||||
}
|
||||
new_queue.push_front(ActionPrompt::WolvesIntro { wolves });
|
||||
continue;
|
||||
}
|
||||
|
||||
ActionPrompt::Shapeshifter { character_id } => (
|
||||
character_id.character_id,
|
||||
ActionPrompt::Shapeshifter { character_id },
|
||||
),
|
||||
ActionPrompt::AlphaWolf {
|
||||
character_id,
|
||||
living_villagers,
|
||||
marked,
|
||||
} => (
|
||||
character_id.character_id,
|
||||
ActionPrompt::AlphaWolf {
|
||||
character_id,
|
||||
living_villagers,
|
||||
marked,
|
||||
},
|
||||
),
|
||||
ActionPrompt::DireWolf {
|
||||
character_id,
|
||||
living_players,
|
||||
marked,
|
||||
} => (
|
||||
character_id.character_id,
|
||||
ActionPrompt::DireWolf {
|
||||
character_id,
|
||||
living_players,
|
||||
marked,
|
||||
},
|
||||
),
|
||||
ActionPrompt::LoneWolfKill {
|
||||
character_id,
|
||||
living_players,
|
||||
marked,
|
||||
} => (
|
||||
character_id.character_id,
|
||||
ActionPrompt::LoneWolfKill {
|
||||
character_id,
|
||||
living_players,
|
||||
marked,
|
||||
},
|
||||
),
|
||||
other => {
|
||||
new_queue.push_front(other);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if wolf_id != reverting {
|
||||
new_queue.push_front(prompt);
|
||||
}
|
||||
}
|
||||
|
||||
new_queue
|
||||
}
|
||||
|
||||
/// changes that require no input (such as hunter firing)
|
||||
fn automatic_changes(&self) -> Vec<NightChange> {
|
||||
let mut changes = Vec::new();
|
||||
|
|
|
|||
|
|
@ -49,11 +49,21 @@ impl Village {
|
|||
let mut wolves = self
|
||||
.characters
|
||||
.iter()
|
||||
.filter(|c| c.is_wolf())
|
||||
.filter(|c| c.alive() && c.is_wolf())
|
||||
.collect::<Box<[_]>>();
|
||||
wolves.sort_by_key(|w| w.killing_wolf_order());
|
||||
wolves.first().copied()
|
||||
}
|
||||
|
||||
pub fn wolf_revert_prompt(&self) -> Option<ActionPrompt> {
|
||||
self.killing_wolf()
|
||||
.filter(|killing_wolf| RoleTitle::Werewolf != killing_wolf.role_title())
|
||||
.map(|killing_wolf| ActionPrompt::RoleChange {
|
||||
character_id: killing_wolf.identity(),
|
||||
new_role: RoleTitle::Werewolf,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn wolf_pack_kill(&self) -> Option<ActionPrompt> {
|
||||
let night = match self.time {
|
||||
GameTime::Day { .. } => return None,
|
||||
|
|
@ -162,23 +172,6 @@ impl Village {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub fn killing_wolf_id(&self) -> CharacterId {
|
||||
let wolves = self.living_wolf_pack_players();
|
||||
if let Some(ww) = wolves
|
||||
.iter()
|
||||
.find(|w| matches!(w.role_title(), RoleTitle::Werewolf))
|
||||
{
|
||||
ww.character_id()
|
||||
} else if let Some(non_ss_wolf) = wolves
|
||||
.iter()
|
||||
.find(|w| w.is_wolf() && !matches!(w.role_title(), RoleTitle::Shapeshifter))
|
||||
{
|
||||
non_ss_wolf.character_id()
|
||||
} else {
|
||||
wolves.into_iter().next().unwrap().character_id()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn living_players(&self) -> Box<[CharacterIdentity]> {
|
||||
self.characters
|
||||
.iter()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
mod night_order;
|
||||
mod previous;
|
||||
mod revert;
|
||||
mod role;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -788,19 +789,9 @@ fn wolfpack_kill_all_targets_valid() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn varied_test() {
|
||||
fn big_game_test_based_on_story_test() {
|
||||
init_log();
|
||||
let players = (1..32u8)
|
||||
.filter_map(NonZeroU8::new)
|
||||
.map(|n| Identification {
|
||||
player_id: PlayerId::from_u128(n.get() as _),
|
||||
public: PublicIdentity {
|
||||
name: format!("Player {n}"),
|
||||
pronouns: Some("he/him".into()),
|
||||
number: Some(n),
|
||||
},
|
||||
})
|
||||
.collect::<Box<[_]>>();
|
||||
let players = gen_players(1..32u8);
|
||||
let mut players_iter = players.iter().map(|p| p.player_id);
|
||||
let (
|
||||
werewolf,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
use crate::{
|
||||
game::{Game, GameSettings, SetupRole},
|
||||
game_test::{
|
||||
ActionPromptTitleExt, ActionResultExt, GameExt, SettingsExt, gen_players, init_log,
|
||||
},
|
||||
message::{CharacterIdentity, night::ActionPrompt},
|
||||
role::{Role, RoleTitle},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn sole_non_werewolf_wolves_revert() {
|
||||
const REVERTING_WOLVES: &[SetupRole] = &[
|
||||
SetupRole::DireWolf,
|
||||
SetupRole::LoneWolf,
|
||||
SetupRole::AlphaWolf,
|
||||
SetupRole::Shapeshifter,
|
||||
];
|
||||
init_log();
|
||||
for wolf_role in REVERTING_WOLVES {
|
||||
let role_title = Into::<RoleTitle>::into(wolf_role.clone());
|
||||
log::info!("testing initial reverting for [{role_title}]");
|
||||
|
||||
let players = gen_players(1..32u8);
|
||||
let reverting_wolf = players[0].player_id;
|
||||
let mut settings = GameSettings::empty();
|
||||
settings.add_and_assign(wolf_role.clone(), reverting_wolf);
|
||||
settings.fill_remaining_slots_with_villagers(players.len());
|
||||
let mut game = Game::new(&players, settings).unwrap();
|
||||
game.r#continue().r#continue();
|
||||
|
||||
assert_eq!(
|
||||
game.next(),
|
||||
ActionPrompt::RoleChange {
|
||||
character_id: game.character_by_player_id(reverting_wolf).identity(),
|
||||
new_role: RoleTitle::Werewolf,
|
||||
}
|
||||
);
|
||||
game.r#continue().r#continue();
|
||||
|
||||
assert_eq!(
|
||||
game.next(),
|
||||
ActionPrompt::WolvesIntro {
|
||||
wolves: Box::new([(
|
||||
game.character_by_player_id(reverting_wolf).identity(),
|
||||
RoleTitle::Werewolf
|
||||
)])
|
||||
}
|
||||
);
|
||||
game.r#continue().sleep();
|
||||
|
||||
game.next_expect_day();
|
||||
assert_eq!(
|
||||
*game.character_by_player_id(reverting_wolf).role(),
|
||||
Role::Werewolf
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wolves_revert_on_werewolf_death() {
|
||||
const REVERTING_WOLVES: &[SetupRole] = &[
|
||||
SetupRole::DireWolf,
|
||||
SetupRole::LoneWolf,
|
||||
SetupRole::AlphaWolf,
|
||||
SetupRole::Shapeshifter,
|
||||
];
|
||||
init_log();
|
||||
for wolf_role in REVERTING_WOLVES {
|
||||
let role_title = Into::<RoleTitle>::into(wolf_role.clone());
|
||||
log::info!("testing initial reverting for [{role_title}]");
|
||||
|
||||
let players = gen_players(1..32u8);
|
||||
let wolf = players[0].player_id;
|
||||
let reverting_wolf = players[1].player_id;
|
||||
let mut settings = GameSettings::empty();
|
||||
settings.add_and_assign(SetupRole::Werewolf, wolf);
|
||||
settings.add_and_assign(wolf_role.clone(), reverting_wolf);
|
||||
settings.fill_remaining_slots_with_villagers(players.len());
|
||||
let mut game = Game::new(&players, settings).unwrap();
|
||||
game.r#continue().r#continue();
|
||||
assert_eq!(
|
||||
game.next(),
|
||||
ActionPrompt::WolvesIntro {
|
||||
wolves: Box::new([
|
||||
(
|
||||
game.character_by_player_id(wolf).identity(),
|
||||
RoleTitle::Werewolf
|
||||
),
|
||||
(
|
||||
game.character_by_player_id(reverting_wolf).identity(),
|
||||
role_title
|
||||
)
|
||||
])
|
||||
}
|
||||
);
|
||||
if RoleTitle::DireWolf == role_title {
|
||||
game.r#continue().r#continue();
|
||||
game.next().title().direwolf();
|
||||
game.mark(game.living_villager().character_id());
|
||||
game.r#continue().sleep();
|
||||
} else {
|
||||
game.r#continue().sleep();
|
||||
}
|
||||
|
||||
game.next_expect_day();
|
||||
game.mark_for_execution(game.character_by_player_id(wolf).character_id());
|
||||
|
||||
assert_eq!(
|
||||
game.execute(),
|
||||
ActionPrompt::RoleChange {
|
||||
character_id: game.character_by_player_id(reverting_wolf).identity(),
|
||||
new_role: RoleTitle::Werewolf,
|
||||
}
|
||||
);
|
||||
game.r#continue().r#continue();
|
||||
|
||||
game.next().title().wolf_pack_kill();
|
||||
game.mark(game.living_villager().character_id());
|
||||
game.r#continue().sleep();
|
||||
|
||||
game.next_expect_day();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue