Files
systemic-game-design-course/course/04-interceptors/tests/rust/test_04.rs
T

178 lines
4.6 KiB
Rust

// Module 4: Interceptors and "trigger twice". Each test matches a heading in scenarios.md.
use engine::harness::*;
fn game_with_deck() -> Game {
new_game(GameOpts {
decks: Some([vec!["Test Filler".to_string(); 5], vec![]]),
})
}
fn damaged(target: Id, amount: i32) -> GameEvent {
GameEvent::Damaged { target, amount }
}
fn triggered(source: Id, trigger: &str) -> GameEvent {
GameEvent::Triggered {
source,
trigger: trigger.to_string(),
}
}
fn spell_cast(card: &str) -> GameEvent {
GameEvent::SpellCast {
card: card.to_string(),
}
}
#[test]
fn test_04_baron_doubles() {
let mut g = game_with_deck();
let b = g.summon("Baron Rivendare", 0);
let h = g.summon("Loot Hoarder", 0);
let golem = g.summon("Harvest Golem", 0);
g.deal_damage(golem, 2);
g.clear_log();
g.cast("Whirlwind", 0, None);
let hand = g.hand(0);
assert_eq!(hand.len(), 2);
let (c1, c2) = (hand[0], hand[1]);
let summoned: Vec<Id> = g
.log()
.into_iter()
.filter_map(|e| match e {
GameEvent::Summoned { id } => Some(id),
_ => None,
})
.collect();
assert_eq!(summoned.len(), 2);
let (d1, d2) = (summoned[0], summoned[1]);
assert_eq!(
g.log(),
vec![
spell_cast("Whirlwind"),
damaged(b, 1),
damaged(h, 1),
damaged(golem, 1),
GameEvent::Destroyed { id: h },
GameEvent::Destroyed { id: golem },
GameEvent::DeathPhase { round: 1 },
triggered(h, "deathrattle"),
GameEvent::Drew { player: 0, id: c1 },
triggered(h, "deathrattle"),
GameEvent::Drew { player: 0, id: c2 },
triggered(golem, "deathrattle"),
GameEvent::Summoned { id: d1 },
triggered(golem, "deathrattle"),
GameEvent::Summoned { id: d2 },
]
);
assert_eq!(g.name_of(d1), "Damaged Golem");
assert_eq!(g.name_of(d2), "Damaged Golem");
let board = g.board(0);
assert_eq!(board.len(), 3);
assert_eq!(board[0], b);
let mut golems = vec![board[1], board[2]];
golems.sort();
let mut expected = vec![d1, d2];
expected.sort();
assert_eq!(golems, expected);
assert_eq!(g.health(b), 6);
}
#[test]
fn test_04_simultaneous_death_not_doubled() {
let mut g = game_with_deck();
let b = g.summon("Baron Rivendare", 0);
let h = g.summon("Loot Hoarder", 0);
g.clear_log();
g.cast("Twisting Nether", 0, None);
assert_eq!(g.hand(0).len(), 1);
let hoarder_triggers = g
.log()
.into_iter()
.filter(|e| *e == triggered(h, "deathrattle"))
.count();
assert_eq!(hoarder_triggers, 1);
assert_eq!(g.zone_of(b), Zone::Graveyard);
assert_eq!(g.zone_of(h), Zone::Graveyard);
}
#[test]
fn test_04_two_barons_do_not_stack() {
let mut g = game_with_deck();
g.summon("Baron Rivendare", 0);
g.summon("Baron Rivendare", 0);
let h = g.summon("Loot Hoarder", 0);
g.clear_log();
g.deal_damage(h, 1);
let hand = g.hand(0);
assert_eq!(hand.len(), 2);
let (c1, c2) = (hand[0], hand[1]);
assert_eq!(
g.log(),
vec![
damaged(h, 1),
GameEvent::Destroyed { id: h },
GameEvent::DeathPhase { round: 1 },
triggered(h, "deathrattle"),
GameEvent::Drew { player: 0, id: c1 },
triggered(h, "deathrattle"),
GameEvent::Drew { player: 0, id: c2 },
]
);
}
#[test]
fn test_04_aura_timing_order() {
let mut g = game_with_deck();
let h = g.summon("Loot Hoarder", 0);
let b = g.summon("Baron Rivendare", 0);
g.clear_log();
g.cast("Twisting Nether", 0, None);
let hand = g.hand(0);
assert_eq!(hand.len(), 1);
let c = hand[0];
assert_eq!(
g.log(),
vec![
spell_cast("Twisting Nether"),
GameEvent::Destroyed { id: h },
GameEvent::Destroyed { id: b },
GameEvent::DeathPhase { round: 1 },
triggered(h, "deathrattle"),
GameEvent::Drew { player: 0, id: c },
]
);
}
#[test]
fn test_04_battlecry_on_play() {
let mut g = game_with_deck();
let e = g.add_to_hand("Novice Engineer", 0);
g.clear_log();
g.play(e);
let hand = g.hand(0);
assert_eq!(hand.len(), 1);
let c = hand[0];
assert_eq!(
g.log(),
vec![
GameEvent::Summoned { id: e },
triggered(e, "battlecry"),
GameEvent::Drew { player: 0, id: c },
]
);
assert_eq!(g.zone_of(e), Zone::Board);
assert_eq!(g.board(0), vec![e]);
}