werewolves/werewolves-proto/src/game_test/role/shapeshifter.rs

237 lines
7.2 KiB
Rust

#[allow(unused)]
use pretty_assertions::{assert_eq, assert_ne, assert_str_eq};
use crate::{
character::CharacterId,
game::{Game, GameSettings, SetupRole},
game_test::{
ActionPromptTitleExt, ActionResultExt, GameExt, ServerToHostMessageExt, SettingsExt,
gen_players, init_log,
},
message::{
host::{HostDayMessage, HostGameMessage, HostNightMessage, ServerToHostMessage},
night::{ActionPrompt, ActionPromptTitle, ActionResponse, ActionResult},
},
role::RoleTitle,
};
#[test]
fn protect_stops_shapeshift() {
init_log();
let players = gen_players(1..10);
let mut settings = GameSettings::default();
settings.new_slot(RoleTitle::Shapeshifter);
settings.new_slot(RoleTitle::Protector);
for _ in 0..7 {
settings.new_slot(RoleTitle::Villager);
}
if let Some(slot) = settings
.slots()
.iter()
.find(|s| matches!(s.role, SetupRole::Werewolf))
{
settings.remove_slot(slot.slot_id);
}
let mut game = Game::new(&players, settings).unwrap();
assert_eq!(
game.process(HostGameMessage::Night(HostNightMessage::ActionResponse(
ActionResponse::Continue,
)))
.unwrap(),
ServerToHostMessage::ActionResult(None, ActionResult::Continue)
);
assert!(matches!(
game.process(HostGameMessage::Night(HostNightMessage::Next))
.unwrap(),
ServerToHostMessage::ActionPrompt(ActionPrompt::WolvesIntro { wolves: _ })
));
assert_eq!(
game.process(HostGameMessage::Night(HostNightMessage::ActionResponse(
ActionResponse::Continue
)))
.unwrap(),
ServerToHostMessage::ActionResult(None, ActionResult::GoBackToSleep),
);
assert!(matches!(
game.process(HostGameMessage::Night(HostNightMessage::Next))
.unwrap(),
ServerToHostMessage::Daytime {
characters: _,
marked: _,
day: _,
}
));
let execution_target = game
.village()
.characters()
.into_iter()
.find(|v| v.is_village() && !matches!(v.role().title(), RoleTitle::Protector))
.unwrap()
.character_id();
match game
.process(HostGameMessage::Day(HostDayMessage::MarkForExecution(
execution_target,
)))
.unwrap()
{
ServerToHostMessage::Daytime {
characters: _,
marked,
day: _,
} => assert_eq!(marked.to_vec(), vec![execution_target]),
resp => panic!("unexpected server message: {resp:#?}"),
}
assert_eq!(
game.process(HostGameMessage::Day(HostDayMessage::Execute))
.unwrap()
.prompt()
.title(),
ActionPromptTitle::CoverOfDarkness
);
game.r#continue().r#continue();
let (prot_and_wolf_target, prot_char_id) = match game
.process(HostGameMessage::Night(HostNightMessage::Next))
.unwrap()
{
ServerToHostMessage::ActionPrompt(ActionPrompt::Protector {
character_id: prot_char_id,
targets,
marked: None,
}) => (
targets
.into_iter()
.map(|c| game.village().character_by_id(c.character_id).unwrap())
.find(|c| c.is_village())
.unwrap()
.character_id(),
prot_char_id,
),
_ => panic!("first n2 prompt isn't protector"),
};
let target = game
.village()
.character_by_id(prot_and_wolf_target)
.unwrap()
.clone();
log::info!("target: {target:#?}");
match game
.process(HostGameMessage::Night(HostNightMessage::ActionResponse(
ActionResponse::MarkTarget(prot_and_wolf_target),
)))
.unwrap()
{
ServerToHostMessage::ActionPrompt(ActionPrompt::Protector {
marked: Some(mark), ..
}) => assert_eq!(mark, prot_and_wolf_target, "marked target"),
resp => panic!("unexpected response: {resp:?}"),
}
game.r#continue().sleep();
assert_eq!(game.next().title(), ActionPromptTitle::WolfPackKill);
game.mark_and_check(prot_and_wolf_target);
game.r#continue().r#continue();
assert_eq!(game.next().title(), ActionPromptTitle::Shapeshifter,);
game.response(ActionResponse::Shapeshift);
game.next_expect_day();
let target = game
.village()
.character_by_id(target.character_id())
.unwrap();
assert!(target.is_village());
assert!(target.alive());
let prot = game
.village()
.character_by_id(prot_char_id.character_id)
.unwrap();
assert!(prot.is_village());
assert!(prot.alive());
assert_eq!(prot.role().title(), RoleTitle::Protector);
}
#[test]
fn only_1_shapeshift_prompt_if_first_shifts() {
let players = gen_players(1..10);
let mut settings = GameSettings::default();
settings.new_slot(RoleTitle::Shapeshifter);
settings.new_slot(RoleTitle::Shapeshifter);
for _ in 0..7 {
settings.new_slot(RoleTitle::Villager);
}
if let Some(slot) = settings
.slots()
.iter()
.find(|s| matches!(s.role, SetupRole::Werewolf))
{
settings.remove_slot(slot.slot_id);
}
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();
let target = game
.village()
.characters()
.into_iter()
.find_map(|c| c.is_village().then_some(c.character_id()))
.unwrap();
let (_, marked, _) = game.mark_for_execution(target);
let (marked, target_list): (&[CharacterId], &[CharacterId]) = (&marked, &[target]);
assert_eq!(target_list, marked);
assert_eq!(game.execute().title(), ActionPromptTitle::WolfPackKill);
let target = game
.village()
.characters()
.into_iter()
.find_map(|c| (c.is_village() && c.alive()).then_some(c.character_id()))
.unwrap();
game.mark_and_check(target);
game.r#continue().r#continue();
assert_eq!(game.next().title(), ActionPromptTitle::Shapeshifter);
game.response(ActionResponse::Shapeshift).r#continue();
assert_eq!(game.next().title(), ActionPromptTitle::RoleChange);
game.r#continue().sleep();
game.next_expect_day();
}
#[test]
fn i_would_simply_refuse() {
let players = gen_players(1..21);
let shapeshifter_player_id = players[0].player_id;
let wolf_player_id = players[1].player_id;
let mut settings = GameSettings::empty();
settings.add_and_assign(SetupRole::Shapeshifter, shapeshifter_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();
game.next_expect_day();
game.execute().title().wolf_pack_kill();
let ss_target = game.living_villager();
game.mark(ss_target.character_id());
game.r#continue().r#continue();
game.next().title().shapeshifter();
game.r#continue().sleep();
game.next_expect_day();
}