diff --git a/werewolves-proto/src/character.rs b/werewolves-proto/src/character.rs index 2d54a8e..e434fcd 100644 --- a/werewolves-proto/src/character.rs +++ b/werewolves-proto/src/character.rs @@ -504,7 +504,11 @@ impl Character { } => prompts.push(ActionPrompt::Guardian { character_id: self.identity(), previous: Some(PreviousGuardianAction::Protect(prev_target.clone())), - living_players: village.living_players(), + living_players: if prev_target.character_id == self.identity.character_id { + village.living_players_excluding(prev_target.character_id) + } else { + village.living_players() + }, marked: None, }), Role::Guardian { diff --git a/werewolves-proto/src/game_test/role/guardian.rs b/werewolves-proto/src/game_test/role/guardian.rs index 62aa612..51d71c8 100644 --- a/werewolves-proto/src/game_test/role/guardian.rs +++ b/werewolves-proto/src/game_test/role/guardian.rs @@ -26,7 +26,7 @@ use crate::{ }, message::{ host::{HostGameMessage, HostNightMessage}, - night::{ActionPromptTitle, ActionResponse}, + night::{ActionPrompt, ActionPromptTitle, ActionResponse}, }, role::{PreviousGuardianAction, Role, RoleTitle}, }; @@ -271,3 +271,60 @@ fn protects_from_militia() { } ); } + +#[test] +fn cant_self_guard() { + init_log(); + let players = gen_players(1..21); + let mut player_ids = players.iter().map(|p| p.player_id); + let guardian = player_ids.next().unwrap(); + let wolf = player_ids.next().unwrap(); + let mut settings = GameSettings::empty(); + settings.add_and_assign(SetupRole::Guardian, guardian); + settings.add_and_assign(SetupRole::Werewolf, wolf); + settings.fill_remaining_slots_with_villagers(20); + let mut game = Game::new(&players, settings).unwrap(); + game.r#continue().r#continue(); + game.next().title().wolves_intro(); + game.r#continue().sleep(); + game.next_expect_day(); + + game.execute().title().guardian(); + game.mark(game.character_by_player_id(guardian).character_id()); + game.r#continue().sleep(); + + game.next().title().wolf_pack_kill(); + game.mark(game.character_by_player_id(guardian).character_id()); + game.r#continue().sleep(); + + game.next_expect_day(); + + assert_eq!( + game.character_by_player_id(guardian).died_to().cloned(), + None + ); + assert_eq!( + game.character_by_player_id(guardian) + .role() + .guardian_ref() + .unwrap() + .last_protected + .clone(), + Some(PreviousGuardianAction::Protect( + game.character_by_player_id(guardian).identity() + )) + ); + + match game.execute() { + ActionPrompt::Guardian { + character_id, + previous: Some(PreviousGuardianAction::Protect(prev_protect)), + living_players, + .. + } => { + assert_eq!(character_id, prev_protect); + assert!(!living_players.contains(&character_id)); + } + prompt => panic!("expected guardian prompt, got {prompt:?}"), + } +}