apprentice now wakes in role-appropriate night order
This commit is contained in:
parent
082f0bba38
commit
8b894b4c8c
|
|
@ -195,6 +195,15 @@ impl Default for ActionComplete {
|
|||
}
|
||||
}
|
||||
|
||||
fn night_sort_order(
|
||||
left_prompt: &ActionPrompt,
|
||||
right_prompt: &ActionPrompt,
|
||||
) -> core::cmp::Ordering {
|
||||
left_prompt
|
||||
.partial_cmp(right_prompt)
|
||||
.unwrap_or(core::cmp::Ordering::Equal)
|
||||
}
|
||||
|
||||
enum Unless {
|
||||
TargetBlocked(CharacterId),
|
||||
TargetsBlocked(CharacterId, CharacterId),
|
||||
|
|
@ -279,15 +288,14 @@ impl Night {
|
|||
.flatten()
|
||||
.chain(village.wolf_pack_kill())
|
||||
.collect::<Vec<_>>();
|
||||
action_queue.sort_by(|left_prompt, right_prompt| {
|
||||
left_prompt
|
||||
.partial_cmp(right_prompt)
|
||||
.unwrap_or(core::cmp::Ordering::Equal)
|
||||
});
|
||||
action_queue.sort_by(night_sort_order);
|
||||
|
||||
let mut action_queue = VecDeque::from({
|
||||
// insert actions for role-changed roles
|
||||
let mut expanded_queue = Vec::new();
|
||||
let mut role_changes = Vec::new();
|
||||
// here we replace the role change prompts with the prompt they *would* have gotten
|
||||
// (if any). if they wouldn't get a prompt, just add the role change prompt back in
|
||||
for action in action_queue {
|
||||
match &action {
|
||||
ActionPrompt::RoleChange {
|
||||
|
|
@ -296,8 +304,15 @@ impl Night {
|
|||
} => {
|
||||
let char = village.character_by_id(character_id.character_id)?;
|
||||
let as_role = char.as_role(new_role.title_to_role_excl_apprentice());
|
||||
let prompts = as_role.night_action_prompts(&village)?;
|
||||
if prompts.is_empty() {
|
||||
// they wouldn't get a prompt alongside the role change, so just add
|
||||
// the role change prompt back in
|
||||
expanded_queue.push(action);
|
||||
for prompt in as_role.night_action_prompts(&village)? {
|
||||
continue;
|
||||
}
|
||||
role_changes.push((character_id.character_id, *new_role));
|
||||
for prompt in prompts {
|
||||
expanded_queue.push(prompt);
|
||||
}
|
||||
}
|
||||
|
|
@ -307,7 +322,23 @@ impl Night {
|
|||
}
|
||||
}
|
||||
}
|
||||
expanded_queue
|
||||
expanded_queue.sort_by(night_sort_order);
|
||||
let mut expanded_queue_with_role_changes =
|
||||
Vec::with_capacity(expanded_queue.len() + role_changes.len());
|
||||
for prompt in expanded_queue {
|
||||
if let Some(char) = prompt.character_id()
|
||||
&& let Some((_, role)) = role_changes.iter().find(|(c, _)| *c == char)
|
||||
{
|
||||
expanded_queue_with_role_changes.push(ActionPrompt::RoleChange {
|
||||
character_id: village.character_by_id(char)?.identity(),
|
||||
new_role: *role,
|
||||
});
|
||||
expanded_queue_with_role_changes.push(prompt);
|
||||
} else {
|
||||
expanded_queue_with_role_changes.push(prompt);
|
||||
}
|
||||
}
|
||||
expanded_queue_with_role_changes
|
||||
});
|
||||
|
||||
if night == 0 {
|
||||
|
|
|
|||
|
|
@ -699,18 +699,7 @@ fn yes_wolf_kill_n2() {
|
|||
.unwrap(),
|
||||
ServerToHostMessage::ActionResult(None, ActionResult::Continue)
|
||||
);
|
||||
|
||||
assert!(matches!(
|
||||
game.process(HostGameMessage::Night(HostNightMessage::Next))
|
||||
.unwrap(),
|
||||
ServerToHostMessage::ActionPrompt(
|
||||
ActionPrompt::WolfPackKill {
|
||||
living_villagers: _,
|
||||
marked: _,
|
||||
},
|
||||
0
|
||||
)
|
||||
));
|
||||
game.next().title().wolf_pack_kill();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright (C) 2025 Emilis Bliūdžius
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
use core::num::NonZeroU8;
|
||||
#[allow(unused)]
|
||||
use pretty_assertions::{assert_eq, assert_ne, assert_str_eq};
|
||||
|
||||
use crate::{
|
||||
diedto::DiedTo,
|
||||
game::{Game, GameSettings, OrRandom, SetupRole},
|
||||
game_test::{
|
||||
ActionPromptTitleExt, ActionResultExt, AlignmentExt, GameExt, ServerToHostMessageExt,
|
||||
SettingsExt, gen_players,
|
||||
},
|
||||
message::{
|
||||
host::{HostDayMessage, HostGameMessage},
|
||||
night::{ActionPrompt, ActionPromptTitle, ActionResult},
|
||||
},
|
||||
role::{Role, RoleTitle},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn beholder_appropriate_prompt_position() {
|
||||
let players = gen_players(1..10);
|
||||
let apprentice = players[0].player_id;
|
||||
let beholder = players[1].player_id;
|
||||
let wolf_player_id = players[2].player_id;
|
||||
|
||||
let mut settings = GameSettings::empty();
|
||||
settings.add_and_assign(
|
||||
SetupRole::Apprentice {
|
||||
to: Some(RoleTitle::Beholder),
|
||||
},
|
||||
apprentice,
|
||||
);
|
||||
settings.add_and_assign(SetupRole::Beholder, beholder);
|
||||
settings.add_and_assign(SetupRole::Werewolf, wolf_player_id);
|
||||
|
||||
settings.fill_remaining_slots_with_villagers(9);
|
||||
let mut game = Game::new(&players, settings).unwrap();
|
||||
game.r#continue().r#continue();
|
||||
assert_eq!(game.next().title(), ActionPromptTitle::WolvesIntro);
|
||||
game.r#continue().sleep();
|
||||
|
||||
game.next_expect_day();
|
||||
game.execute().title().wolf_pack_kill();
|
||||
game.mark(game.character_by_player_id(beholder).character_id());
|
||||
game.r#continue().sleep();
|
||||
|
||||
game.next().title().beholder();
|
||||
game.mark(game.character_by_player_id(wolf_player_id).character_id());
|
||||
game.r#continue().sleep();
|
||||
|
||||
game.next_expect_day();
|
||||
game.execute().title().wolf_pack_kill();
|
||||
game.mark(game.living_villager().character_id());
|
||||
game.r#continue().sleep();
|
||||
|
||||
assert_eq!(
|
||||
game.next(),
|
||||
ActionPrompt::RoleChange {
|
||||
character_id: game.character_by_player_id(apprentice).identity(),
|
||||
new_role: RoleTitle::Beholder
|
||||
}
|
||||
);
|
||||
game.r#continue().r#continue();
|
||||
game.next().title().beholder();
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
mod apprentice;
|
||||
mod beholder;
|
||||
mod black_knight;
|
||||
mod diseased;
|
||||
|
|
|
|||
|
|
@ -118,8 +118,20 @@ fn redeemed_scapegoat_role_changes() {
|
|||
night: NonZero::new(1).unwrap()
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(game.execute().title(), ActionPromptTitle::WolfPackKill);
|
||||
let wolf_target_2 = game
|
||||
.village()
|
||||
.characters()
|
||||
.iter()
|
||||
.find(|c| c.player_id() == wolf_target_2_player_id)
|
||||
.unwrap()
|
||||
.character_id();
|
||||
game.mark_and_check(wolf_target_2);
|
||||
game.r#continue().sleep();
|
||||
|
||||
assert_eq!(
|
||||
game.execute(),
|
||||
game.next(),
|
||||
ActionPrompt::RoleChange {
|
||||
character_id: game.character_by_player_id(scapegoat_player_id).identity(),
|
||||
new_role: RoleTitle::Seer
|
||||
|
|
@ -131,17 +143,6 @@ fn redeemed_scapegoat_role_changes() {
|
|||
assert_eq!(game.r#continue().seer(), Alignment::Wolves);
|
||||
game.r#continue().sleep();
|
||||
|
||||
assert_eq!(game.next().title(), ActionPromptTitle::WolfPackKill);
|
||||
let wolf_target_2 = game
|
||||
.village()
|
||||
.characters()
|
||||
.iter()
|
||||
.find(|c| c.player_id() == wolf_target_2_player_id)
|
||||
.unwrap()
|
||||
.character_id();
|
||||
game.mark_and_check(wolf_target_2);
|
||||
game.r#continue().sleep();
|
||||
|
||||
game.next_expect_day();
|
||||
|
||||
let scapegoat = game.character_by_player_id(scapegoat_player_id);
|
||||
|
|
|
|||
Loading…
Reference in New Issue