fix tests for new setup + role change fix
This commit is contained in:
parent
d664ff281d
commit
97e1ca8a39
|
|
@ -1,5 +1,5 @@
|
|||
mod kill;
|
||||
mod night;
|
||||
pub(crate) mod night;
|
||||
mod settings;
|
||||
mod village;
|
||||
|
||||
|
|
@ -21,6 +21,7 @@ use crate::{
|
|||
},
|
||||
player::CharacterId,
|
||||
};
|
||||
|
||||
pub use {
|
||||
settings::{Category, GameSettings, OrRandom, SetupRole, SetupSlot, SlotId},
|
||||
village::Village,
|
||||
|
|
|
|||
|
|
@ -565,7 +565,22 @@ impl Night {
|
|||
_ => Err(GameError::InvalidMessageForGameState),
|
||||
};
|
||||
}
|
||||
ActionResponse::Continue => {}
|
||||
ActionResponse::Continue => {
|
||||
if let ActionPrompt::RoleChange {
|
||||
character_id,
|
||||
new_role,
|
||||
} = current_prompt
|
||||
{
|
||||
return Ok(ResponseOutcome::ActionComplete(ActionComplete {
|
||||
result: ActionResult::GoBackToSleep,
|
||||
change: Some(NightChange::RoleChange(
|
||||
character_id.character_id.clone(),
|
||||
*new_role,
|
||||
)),
|
||||
unless: None,
|
||||
}));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match current_prompt {
|
||||
|
|
|
|||
|
|
@ -1,18 +1,23 @@
|
|||
mod night_order;
|
||||
|
||||
use crate::{
|
||||
diedto::DiedTo,
|
||||
error::GameError,
|
||||
game::{Game, GameSettings, SetupRole},
|
||||
game::{Game, GameSettings, OrRandom, SetupRole, night::NightChange},
|
||||
message::{
|
||||
CharacterState, Identification, PublicIdentity,
|
||||
host::{HostDayMessage, HostGameMessage, HostNightMessage, ServerToHostMessage},
|
||||
night::{ActionPrompt, ActionPromptTitle, ActionResponse, ActionResult},
|
||||
},
|
||||
player::{CharacterId, PlayerId},
|
||||
role::RoleTitle,
|
||||
role::{Alignment, Role, RoleTitle},
|
||||
};
|
||||
use colored::Colorize;
|
||||
use core::{num::NonZeroU8, ops::Range};
|
||||
use core::{
|
||||
char,
|
||||
num::{NonZero, NonZeroU8},
|
||||
ops::Range,
|
||||
};
|
||||
#[allow(unused)]
|
||||
use pretty_assertions::{assert_eq, assert_ne, assert_str_eq};
|
||||
use std::io::Write;
|
||||
|
|
@ -20,6 +25,7 @@ use std::io::Write;
|
|||
trait ActionResultExt {
|
||||
fn sleep(&self);
|
||||
fn r#continue(&self);
|
||||
fn seer(&self) -> Alignment;
|
||||
}
|
||||
|
||||
impl ActionResultExt for ActionResult {
|
||||
|
|
@ -30,6 +36,13 @@ impl ActionResultExt for ActionResult {
|
|||
fn r#continue(&self) {
|
||||
assert_eq!(*self, ActionResult::Continue)
|
||||
}
|
||||
|
||||
fn seer(&self) -> Alignment {
|
||||
match self {
|
||||
ActionResult::Seer(a) => a.clone(),
|
||||
_ => panic!("expected a seer result"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait ServerToHostMessageExt {
|
||||
|
|
@ -210,7 +223,10 @@ fn gen_players(range: Range<u8>) -> Box<[Identification]> {
|
|||
#[test]
|
||||
fn starts_with_wolf_intro() {
|
||||
let players = gen_players(1..10);
|
||||
let settings = GameSettings::default();
|
||||
let mut settings = GameSettings::default();
|
||||
for _ in 0..8 {
|
||||
settings.new_slot(RoleTitle::Villager);
|
||||
}
|
||||
let mut game = Game::new(&players, settings).unwrap();
|
||||
let resp = game.process(HostGameMessage::GetState).unwrap();
|
||||
assert_eq!(
|
||||
|
|
@ -225,6 +241,9 @@ fn no_wolf_kill_n1() {
|
|||
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()
|
||||
|
|
@ -266,7 +285,10 @@ fn no_wolf_kill_n1() {
|
|||
#[test]
|
||||
fn yes_wolf_kill_n2() {
|
||||
let players = gen_players(1..10);
|
||||
let settings = GameSettings::default();
|
||||
let mut settings = GameSettings::default();
|
||||
for _ in 0..8 {
|
||||
settings.new_slot(RoleTitle::Villager);
|
||||
}
|
||||
let mut game = Game::new(&players, settings).unwrap();
|
||||
assert_eq!(
|
||||
game.process(HostGameMessage::Night(HostNightMessage::ActionResponse(
|
||||
|
|
@ -350,6 +372,9 @@ fn protect_stops_shapeshift() {
|
|||
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()
|
||||
|
|
@ -496,6 +521,9 @@ fn wolfpack_kill_all_targets_valid() {
|
|||
init_log();
|
||||
let players = gen_players(1..10);
|
||||
let mut settings = GameSettings::default();
|
||||
for _ in 0..8 {
|
||||
settings.new_slot(RoleTitle::Villager);
|
||||
}
|
||||
settings.new_slot(RoleTitle::Shapeshifter);
|
||||
if let Some(slot) = settings
|
||||
.slots()
|
||||
|
|
@ -569,6 +597,9 @@ fn only_1_shapeshift_prompt_if_first_shifts() {
|
|||
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()
|
||||
|
|
@ -614,3 +645,173 @@ fn only_1_shapeshift_prompt_if_first_shifts() {
|
|||
|
||||
game.next_expect_day();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn redeemed_scapegoat_role_changes() {
|
||||
let players = gen_players(1..10);
|
||||
let scapegoat_player_id = players[0].player_id.clone();
|
||||
let seer_player_id = players[1].player_id.clone();
|
||||
let wolf_player_id = players[2].player_id.clone();
|
||||
let wolf_target_2_player_id = players[3].player_id.clone();
|
||||
let mut settings = GameSettings::default();
|
||||
{
|
||||
let scapegoat_slot = settings.new_slot(RoleTitle::Scapegoat);
|
||||
let mut scapegoat_slot = settings
|
||||
.slots()
|
||||
.iter()
|
||||
.find(|s| s.slot_id == scapegoat_slot)
|
||||
.unwrap()
|
||||
.clone();
|
||||
scapegoat_slot.role = SetupRole::Scapegoat {
|
||||
redeemed: OrRandom::Determined(true),
|
||||
};
|
||||
scapegoat_slot.assign_to = Some(scapegoat_player_id.clone());
|
||||
settings.update_slot(scapegoat_slot);
|
||||
}
|
||||
{
|
||||
let mut slot = settings
|
||||
.slots()
|
||||
.iter()
|
||||
.find(|s| matches!(s.role, SetupRole::Werewolf))
|
||||
.unwrap()
|
||||
.clone();
|
||||
slot.assign_to = Some(wolf_player_id.clone());
|
||||
settings.update_slot(slot);
|
||||
}
|
||||
{
|
||||
let slot = settings.new_slot(RoleTitle::Seer);
|
||||
let mut slot = settings
|
||||
.slots()
|
||||
.iter()
|
||||
.find(|s| s.slot_id == slot)
|
||||
.unwrap()
|
||||
.clone();
|
||||
slot.assign_to = Some(seer_player_id.clone());
|
||||
settings.update_slot(slot);
|
||||
}
|
||||
for _ in 0..6 {
|
||||
settings.new_slot(RoleTitle::Villager);
|
||||
}
|
||||
let mut game = Game::new(&players, settings).unwrap();
|
||||
game.r#continue().r#continue();
|
||||
assert_eq!(game.next().title(), ActionPromptTitle::WolvesIntro);
|
||||
game.r#continue().sleep();
|
||||
assert_eq!(game.next().title(), ActionPromptTitle::Seer);
|
||||
let wolf_char_id = game
|
||||
.village()
|
||||
.characters()
|
||||
.into_iter()
|
||||
.find(|c| c.player_id() == &wolf_player_id)
|
||||
.unwrap()
|
||||
.character_id()
|
||||
.clone();
|
||||
game.mark_and_check(&wolf_char_id, |p| match p {
|
||||
ActionPrompt::Seer {
|
||||
marked: Some(marked),
|
||||
..
|
||||
} => marked == &wolf_char_id,
|
||||
_ => false,
|
||||
});
|
||||
assert_eq!(game.r#continue().seer(), Alignment::Wolves);
|
||||
game.next_expect_day();
|
||||
|
||||
assert_eq!(game.execute().title(), ActionPromptTitle::CoverOfDarkness);
|
||||
game.r#continue().r#continue();
|
||||
assert_eq!(game.next().title(), ActionPromptTitle::WolfPackKill);
|
||||
let seer = game
|
||||
.village()
|
||||
.characters()
|
||||
.into_iter()
|
||||
.find(|c| c.player_id() == &seer_player_id)
|
||||
.unwrap()
|
||||
.character_id()
|
||||
.clone();
|
||||
|
||||
game.mark_and_check(&seer, |p| match p {
|
||||
ActionPrompt::WolfPackKill {
|
||||
marked: Some(t), ..
|
||||
} => *t == seer,
|
||||
_ => false,
|
||||
});
|
||||
game.r#continue().sleep();
|
||||
|
||||
assert_eq!(game.next().title(), ActionPromptTitle::Seer);
|
||||
game.mark_and_check(&wolf_char_id, |p| match p {
|
||||
ActionPrompt::Seer {
|
||||
marked: Some(marked),
|
||||
..
|
||||
} => marked == &wolf_char_id,
|
||||
_ => false,
|
||||
});
|
||||
assert_eq!(game.r#continue().seer(), Alignment::Wolves);
|
||||
game.next_expect_day();
|
||||
|
||||
assert_eq!(
|
||||
*game
|
||||
.village()
|
||||
.character_by_id(&seer)
|
||||
.unwrap()
|
||||
.died_to()
|
||||
.unwrap(),
|
||||
DiedTo::Wolfpack {
|
||||
killing_wolf: wolf_char_id.clone(),
|
||||
night: NonZero::new(1).unwrap()
|
||||
}
|
||||
);
|
||||
assert_eq!(game.execute().title(), ActionPromptTitle::CoverOfDarkness);
|
||||
game.r#continue().r#continue();
|
||||
|
||||
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()
|
||||
.clone();
|
||||
game.mark_and_check(&wolf_target_2, |r| match r {
|
||||
ActionPrompt::WolfPackKill {
|
||||
marked: Some(marked),
|
||||
..
|
||||
} => marked == &wolf_target_2,
|
||||
_ => false,
|
||||
});
|
||||
game.r#continue().sleep();
|
||||
let scapegoat = game
|
||||
.village()
|
||||
.characters()
|
||||
.into_iter()
|
||||
.find(|c| c.player_id() == &scapegoat_player_id)
|
||||
.unwrap()
|
||||
.clone();
|
||||
assert_eq!(
|
||||
game.next(),
|
||||
ActionPrompt::RoleChange {
|
||||
character_id: scapegoat.identity(),
|
||||
new_role: RoleTitle::Seer
|
||||
}
|
||||
);
|
||||
game.r#continue().sleep();
|
||||
|
||||
match game.game_state() {
|
||||
crate::game::GameState::Night { night } => night
|
||||
.changes()
|
||||
.iter()
|
||||
.find(|c| match c {
|
||||
NightChange::RoleChange(char, role) => {
|
||||
char == scapegoat.character_id() && role == &RoleTitle::Seer
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
.expect("no role change"),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
game.next_expect_day();
|
||||
let day_scapegoat = game
|
||||
.village()
|
||||
.character_by_id(scapegoat.character_id())
|
||||
.unwrap();
|
||||
assert_eq!(day_scapegoat.role().title(), RoleTitle::Seer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ pub enum ActionPrompt {
|
|||
}
|
||||
|
||||
impl ActionPrompt {
|
||||
pub fn with_mark(&self, mark: CharacterId) -> Result<ActionPrompt> {
|
||||
pub(crate) fn with_mark(&self, mark: CharacterId) -> Result<ActionPrompt> {
|
||||
let mut prompt = self.clone();
|
||||
match &mut prompt {
|
||||
ActionPrompt::WolvesIntro { .. }
|
||||
|
|
|
|||
|
|
@ -1075,4 +1075,6 @@ input {
|
|||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
row-gap: 10px;
|
||||
|
||||
font-size: 2em;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -473,10 +473,36 @@ impl Component for Host {
|
|||
HostMessage::InGame(HostGameMessage::PreviousState),
|
||||
self.send.clone(),
|
||||
);
|
||||
let client_click = Callback::from(|_| {
|
||||
if let Some(loc) = gloo::utils::document().location() {
|
||||
let _ = loc.replace("/");
|
||||
}
|
||||
});
|
||||
let screen = if self.big_screen {
|
||||
let to_normal = Callback::from(|_| {
|
||||
if let Some(loc) = gloo::utils::document().location() {
|
||||
let _ = loc.replace("/host");
|
||||
}
|
||||
});
|
||||
html! {
|
||||
<Button on_click={to_normal}>{"small screen"}</Button>
|
||||
}
|
||||
} else {
|
||||
let to_big = Callback::from(|_| {
|
||||
if let Some(loc) = gloo::utils::document().location() {
|
||||
let _ = loc.replace("/host/big");
|
||||
}
|
||||
});
|
||||
html! {
|
||||
<Button on_click={to_big}>{"big screen 📺"}</Button>
|
||||
}
|
||||
};
|
||||
html! {
|
||||
<nav class="debug-nav" style="z-index: 3;">
|
||||
<Button on_click={on_error_click}>{"error"}</Button>
|
||||
<Button on_click={on_prev_click}>{"previous"}</Button>
|
||||
{screen}
|
||||
<Button on_click={client_click}>{"client"}</Button>
|
||||
</nav>
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ pub fn ClientNav(ClientNavProps { message_callback }: &ClientNavProps) -> Html {
|
|||
</ClickableTextEdit>
|
||||
}
|
||||
};
|
||||
let debug = option_env!("DEBUG").map(|_| {
|
||||
let cb = message_callback.clone();
|
||||
let forgor = move |_| {
|
||||
PlayerId::delete();
|
||||
|
|
@ -147,12 +148,24 @@ pub fn ClientNav(ClientNavProps { message_callback }: &ClientNavProps) -> Html {
|
|||
cb.emit(ClientMessage::Goodbye);
|
||||
let _ = gloo::utils::window().location().reload();
|
||||
};
|
||||
let host_click = Callback::from(|_| {
|
||||
if let Some(loc) = gloo::utils::document().location() {
|
||||
let _ = loc.replace("/host");
|
||||
}
|
||||
});
|
||||
html! {
|
||||
<>
|
||||
<Button on_click={host_click}>{"host"}</Button>
|
||||
<Button on_click={forgor}>{"forgor 💀"}</Button>
|
||||
</>
|
||||
}
|
||||
});
|
||||
html! {
|
||||
<nav class="client-nav">
|
||||
{number}
|
||||
{name}
|
||||
{pronouns}
|
||||
<Button on_click={forgor}>{"forgor 💀"}</Button>
|
||||
{debug}
|
||||
</nav>
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue