Compare commits
No commits in common. "a424211ab4aa3c54ffcb3162c278b39d5dc9b6a1" and "00617afe7bb0cdba32a6560c85c48a2900697634" have entirely different histories.
a424211ab4
...
00617afe7b
|
|
@ -255,27 +255,7 @@ impl Night {
|
||||||
.collect(),
|
.collect(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if let Some(prompt) = village.wolf_revert_prompt() {
|
// let current_prompt = action_queue.pop_front().ok_or(GameError::NoNightActions)?;
|
||||||
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 {
|
let night_state = NightState::Active {
|
||||||
current_prompt: ActionPrompt::CoverOfDarkness,
|
current_prompt: ActionPrompt::CoverOfDarkness,
|
||||||
current_changes: Vec::new(),
|
current_changes: Vec::new(),
|
||||||
|
|
@ -292,84 +272,6 @@ 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)
|
/// changes that require no input (such as hunter firing)
|
||||||
fn automatic_changes(&self) -> Vec<NightChange> {
|
fn automatic_changes(&self) -> Vec<NightChange> {
|
||||||
let mut changes = Vec::new();
|
let mut changes = Vec::new();
|
||||||
|
|
|
||||||
|
|
@ -49,21 +49,11 @@ impl Village {
|
||||||
let mut wolves = self
|
let mut wolves = self
|
||||||
.characters
|
.characters
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|c| c.alive() && c.is_wolf())
|
.filter(|c| c.is_wolf())
|
||||||
.collect::<Box<[_]>>();
|
.collect::<Box<[_]>>();
|
||||||
wolves.sort_by_key(|w| w.killing_wolf_order());
|
wolves.sort_by_key(|w| w.killing_wolf_order());
|
||||||
wolves.first().copied()
|
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> {
|
pub fn wolf_pack_kill(&self) -> Option<ActionPrompt> {
|
||||||
let night = match self.time {
|
let night = match self.time {
|
||||||
GameTime::Day { .. } => return None,
|
GameTime::Day { .. } => return None,
|
||||||
|
|
@ -172,6 +162,23 @@ impl Village {
|
||||||
.collect()
|
.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]> {
|
pub fn living_players(&self) -> Box<[CharacterIdentity]> {
|
||||||
self.characters
|
self.characters
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
mod night_order;
|
mod night_order;
|
||||||
mod previous;
|
mod previous;
|
||||||
mod revert;
|
|
||||||
mod role;
|
mod role;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -789,9 +788,19 @@ fn wolfpack_kill_all_targets_valid() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn big_game_test_based_on_story_test() {
|
fn varied_test() {
|
||||||
init_log();
|
init_log();
|
||||||
let players = gen_players(1..32u8);
|
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 mut players_iter = players.iter().map(|p| p.player_id);
|
let mut players_iter = players.iter().map(|p| p.player_id);
|
||||||
let (
|
let (
|
||||||
werewolf,
|
werewolf,
|
||||||
|
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
use core::{fmt::Display, num::NonZeroU8, ops::Not};
|
use core::{
|
||||||
|
fmt::Display,
|
||||||
|
num::NonZeroU8,
|
||||||
|
ops::{Deref, Not},
|
||||||
|
};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use werewolves_macros::{ChecksAs, Titles};
|
use werewolves_macros::{ChecksAs, Titles};
|
||||||
|
|
@ -303,15 +307,15 @@ impl Role {
|
||||||
|
|
||||||
pub const fn wakes_night_zero(&self) -> bool {
|
pub const fn wakes_night_zero(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Role::PowerSeer
|
Role::Insomniac
|
||||||
|
| Role::PowerSeer
|
||||||
|
| Role::Beholder
|
||||||
| Role::Adjudicator
|
| Role::Adjudicator
|
||||||
| Role::DireWolf { .. }
|
| Role::DireWolf { .. }
|
||||||
| Role::Arcanist
|
| Role::Arcanist
|
||||||
| Role::Seer => true,
|
| Role::Seer => true,
|
||||||
|
|
||||||
Role::Insomniac // has to at least get one good night of sleep, right?
|
Role::LoneWolf
|
||||||
| Role::Beholder
|
|
||||||
| Role::LoneWolf
|
|
||||||
| Role::Shapeshifter { .. }
|
| Role::Shapeshifter { .. }
|
||||||
| Role::Werewolf
|
| Role::Werewolf
|
||||||
| Role::AlphaWolf { .. }
|
| Role::AlphaWolf { .. }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue