326 lines
11 KiB
Rust
326 lines
11 KiB
Rust
// 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/>.
|
|
|
|
#[allow(unused)]
|
|
use pretty_assertions::{assert_eq, assert_ne, assert_str_eq};
|
|
|
|
use crate::{
|
|
aura::{Aura, AuraTitle},
|
|
game::{Game, GameSettings, SetupRole},
|
|
game_test::{
|
|
ActionPromptTitleExt, ActionResultExt, GameExt, SettingsExt, gen_players, init_log,
|
|
},
|
|
message::night::{ActionPrompt, ActionPromptTitle},
|
|
player::RoleChange,
|
|
role::{Alignment, Killer, Role, RoleTitle},
|
|
};
|
|
|
|
#[test]
|
|
fn redeemable_scapegoat() {
|
|
init_log();
|
|
let players = gen_players(1..21);
|
|
let mut player_ids = players.iter().map(|p| p.player_id);
|
|
let seer = player_ids.next().unwrap();
|
|
let wolf = player_ids.next().unwrap();
|
|
let scapegoat = player_ids.next().unwrap();
|
|
let mut settings = GameSettings::empty();
|
|
settings.add_and_assign(SetupRole::Werewolf, wolf);
|
|
settings.add_and_assign(SetupRole::Seer, seer);
|
|
let mut scapegoat_slot = settings.add_and_assign(SetupRole::Villager, scapegoat);
|
|
scapegoat_slot.auras.push(AuraTitle::RedeemableScapegoat);
|
|
settings.update_slot(scapegoat_slot);
|
|
|
|
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().title(), ActionPromptTitle::WolvesIntro);
|
|
game.r#continue().sleep();
|
|
|
|
game.next().title().seer();
|
|
game.mark(game.character_by_player_id(scapegoat).character_id());
|
|
assert!(game.r#continue().seer().wolves());
|
|
game.r#continue().sleep();
|
|
|
|
game.next_expect_day();
|
|
|
|
assert_eq!(
|
|
game.character_by_player_id(scapegoat).auras(),
|
|
&[Aura::RedeemableScapegoat]
|
|
);
|
|
|
|
game.mark_for_execution(game.character_by_player_id(seer).character_id());
|
|
game.execute().title().wolf_pack_kill();
|
|
game.mark(game.living_villager_excl(scapegoat).character_id());
|
|
game.r#continue().sleep();
|
|
|
|
game.next_expect_day();
|
|
game.execute().title().wolf_pack_kill();
|
|
game.mark(game.living_villager_excl(scapegoat).character_id());
|
|
game.r#continue().sleep();
|
|
|
|
assert_eq!(
|
|
game.next(),
|
|
ActionPrompt::RoleChange {
|
|
character_id: game.character_by_player_id(scapegoat).identity(),
|
|
new_role: RoleTitle::Seer
|
|
}
|
|
);
|
|
game.r#continue().r#continue();
|
|
|
|
game.next().title().seer();
|
|
game.mark(game.character_by_player_id(wolf).character_id());
|
|
assert!(game.r#continue().seer().wolves());
|
|
game.r#continue().sleep();
|
|
|
|
game.next_expect_day();
|
|
|
|
let scapegoat = game.character_by_player_id(scapegoat);
|
|
assert_eq!(
|
|
scapegoat.role_changes(),
|
|
&[RoleChange {
|
|
role: Role::Villager,
|
|
new_role: RoleTitle::Seer,
|
|
changed_on_night: 2,
|
|
}]
|
|
);
|
|
assert_eq!(scapegoat.auras(), &[Aura::Scapegoat]);
|
|
assert_eq!(scapegoat.role(), &Role::Seer);
|
|
}
|
|
|
|
#[test]
|
|
fn inevitable_scapegoat_targeting_black_knight() {
|
|
init_log();
|
|
let players = gen_players(1..21);
|
|
let mut player_ids = players.iter().map(|p| p.player_id);
|
|
let seer = player_ids.next().unwrap();
|
|
let wolf = player_ids.next().unwrap();
|
|
let black_knight = player_ids.next().unwrap();
|
|
let mut settings = GameSettings::empty();
|
|
settings.add_and_assign(SetupRole::Werewolf, wolf);
|
|
|
|
settings.add_and_assign(SetupRole::BlackKnight, black_knight);
|
|
let mut seer_slot = settings.add_and_assign(SetupRole::Seer, seer);
|
|
seer_slot.auras.push(AuraTitle::InevitableScapegoat);
|
|
settings.update_slot(seer_slot);
|
|
|
|
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().title(), ActionPromptTitle::WolvesIntro);
|
|
game.r#continue().sleep();
|
|
|
|
assert_eq!(
|
|
game.character_by_player_id(seer).auras(),
|
|
&[Aura::InevitableScapegoat]
|
|
);
|
|
|
|
game.next().title().seer();
|
|
game.mark(game.character_by_player_id(black_knight).character_id());
|
|
assert!(game.r#continue().seer().wolves());
|
|
game.r#continue().sleep();
|
|
|
|
game.next_expect_day();
|
|
|
|
assert_eq!(
|
|
game.character_by_player_id(black_knight).auras(),
|
|
&[Aura::Scapegoat]
|
|
);
|
|
|
|
assert_eq!(game.character_by_player_id(seer).auras(), &[]);
|
|
|
|
game.execute().title().wolf_pack_kill();
|
|
let next_target = game.village().characters().into_iter().last().unwrap();
|
|
game.mark(
|
|
game.living_villager_excl(next_target.player_id())
|
|
.character_id(),
|
|
);
|
|
game.r#continue().sleep();
|
|
|
|
game.next().title().seer();
|
|
game.mark(next_target.character_id());
|
|
assert!(game.r#continue().seer().village());
|
|
game.r#continue().sleep();
|
|
game.next_expect_day();
|
|
|
|
assert_eq!(game.character_by_player_id(seer).auras(), &[]);
|
|
assert_eq!(
|
|
game.character_by_player_id(next_target.player_id()).auras(),
|
|
&[]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn vindictive_scapegoat() {
|
|
init_log();
|
|
let players = gen_players(1..21);
|
|
let mut player_ids = players.iter().map(|p| p.player_id);
|
|
let scapegoat = player_ids.next().unwrap();
|
|
let wolf = player_ids.next().unwrap();
|
|
let mut settings = GameSettings::empty();
|
|
settings.add_and_assign(SetupRole::Werewolf, wolf);
|
|
let mut scapegoat_slot = settings.add_and_assign(SetupRole::Villager, scapegoat);
|
|
scapegoat_slot.auras.push(AuraTitle::VindictiveScapegoat);
|
|
settings.update_slot(scapegoat_slot);
|
|
|
|
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().title(), ActionPromptTitle::WolvesIntro);
|
|
game.r#continue().sleep();
|
|
|
|
game.next_expect_day();
|
|
game.mark_for_execution(game.character_by_player_id(scapegoat).character_id());
|
|
game.execute().title().wolf_pack_kill();
|
|
game.mark_villager();
|
|
game.r#continue().sleep();
|
|
|
|
game.next_expect_day();
|
|
|
|
assert_eq!(game.character_by_player_id(scapegoat).auras(), &[]);
|
|
assert!(
|
|
game.village()
|
|
.characters()
|
|
.into_iter()
|
|
.filter(|c| c.alive() && c.is_village())
|
|
.any(|c| c.auras() == [Aura::Scapegoat])
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn spiteful_scapegoat_chosen_by_adjudicator() {
|
|
init_log();
|
|
let players = gen_players(1..21);
|
|
let mut player_ids = players.iter().map(|p| p.player_id);
|
|
let seer = player_ids.next().unwrap();
|
|
let wolf = player_ids.next().unwrap();
|
|
let adjudicator = player_ids.next().unwrap();
|
|
let mut settings = GameSettings::empty();
|
|
settings.add_and_assign(SetupRole::Werewolf, wolf);
|
|
|
|
settings.add_and_assign(SetupRole::Adjudicator, adjudicator);
|
|
let mut seer_slot = settings.add_and_assign(SetupRole::Seer, seer);
|
|
seer_slot.auras.push(AuraTitle::SpitefulScapegoat);
|
|
settings.update_slot(seer_slot);
|
|
|
|
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().title(), ActionPromptTitle::WolvesIntro);
|
|
game.r#continue().sleep();
|
|
|
|
assert_eq!(
|
|
game.character_by_player_id(seer).auras(),
|
|
&[Aura::SpitefulScapegoat]
|
|
);
|
|
|
|
game.next().title().seer();
|
|
game.mark(game.character_by_player_id(adjudicator).character_id());
|
|
assert_eq!(game.r#continue().seer(), Alignment::Village);
|
|
game.r#continue().sleep();
|
|
|
|
game.next().title().adjudicator();
|
|
game.mark(game.character_by_player_id(seer).character_id());
|
|
assert_eq!(game.r#continue().adjudicator(), Killer::NotKiller);
|
|
game.r#continue().sleep();
|
|
|
|
game.next_expect_day();
|
|
|
|
assert_eq!(game.character_by_player_id(seer).auras(), &[]);
|
|
|
|
assert_eq!(
|
|
game.character_by_player_id(adjudicator).auras(),
|
|
&[Aura::Scapegoat]
|
|
);
|
|
|
|
game.execute().title().wolf_pack_kill();
|
|
game.mark_villager();
|
|
game.r#continue().sleep();
|
|
|
|
game.next().title().seer();
|
|
game.mark(game.character_by_player_id(adjudicator).character_id());
|
|
assert_eq!(game.r#continue().seer(), Alignment::Wolves);
|
|
game.r#continue().sleep();
|
|
|
|
game.next().title().adjudicator();
|
|
game.mark(game.character_by_player_id(seer).character_id());
|
|
assert_eq!(game.r#continue().adjudicator(), Killer::NotKiller);
|
|
game.r#continue().sleep();
|
|
|
|
game.next_expect_day();
|
|
}
|
|
|
|
#[test]
|
|
fn inevitable_scapegoat_chosen_by_adjudicator() {
|
|
init_log();
|
|
let players = gen_players(1..21);
|
|
let mut player_ids = players.iter().map(|p| p.player_id);
|
|
let seer = player_ids.next().unwrap();
|
|
let wolf = player_ids.next().unwrap();
|
|
let adjudicator = player_ids.next().unwrap();
|
|
let mut settings = GameSettings::empty();
|
|
settings.add_and_assign(SetupRole::Werewolf, wolf);
|
|
|
|
settings.add_and_assign(SetupRole::Adjudicator, adjudicator);
|
|
let mut seer_slot = settings.add_and_assign(SetupRole::Seer, seer);
|
|
seer_slot.auras.push(AuraTitle::InevitableScapegoat);
|
|
settings.update_slot(seer_slot);
|
|
|
|
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().title(), ActionPromptTitle::WolvesIntro);
|
|
game.r#continue().sleep();
|
|
|
|
assert_eq!(
|
|
game.character_by_player_id(seer).auras(),
|
|
&[Aura::InevitableScapegoat]
|
|
);
|
|
|
|
game.next().title().seer();
|
|
game.mark(game.character_by_player_id(adjudicator).character_id());
|
|
assert_eq!(game.r#continue().seer(), Alignment::Wolves);
|
|
game.r#continue().sleep();
|
|
|
|
game.next().title().adjudicator();
|
|
game.mark(game.character_by_player_id(seer).character_id());
|
|
assert_eq!(game.r#continue().adjudicator(), Killer::NotKiller);
|
|
game.r#continue().sleep();
|
|
|
|
game.next_expect_day();
|
|
|
|
assert_eq!(game.character_by_player_id(seer).auras(), &[]);
|
|
|
|
assert_eq!(
|
|
game.character_by_player_id(adjudicator).auras(),
|
|
&[Aura::Scapegoat]
|
|
);
|
|
|
|
game.execute().title().wolf_pack_kill();
|
|
game.mark_villager();
|
|
game.r#continue().sleep();
|
|
|
|
game.next().title().seer();
|
|
game.mark(game.character_by_player_id(adjudicator).character_id());
|
|
assert_eq!(game.r#continue().seer(), Alignment::Wolves);
|
|
game.r#continue().sleep();
|
|
|
|
game.next().title().adjudicator();
|
|
game.mark(game.character_by_player_id(seer).character_id());
|
|
assert_eq!(game.r#continue().adjudicator(), Killer::NotKiller);
|
|
game.r#continue().sleep();
|
|
|
|
game.next_expect_day();
|
|
}
|