package game import "testing" // Highland Cow banks Trumpets equal to its power on entry. func TestHighlandCowTrumpetsFromPower(t *testing.T) { g, _, _ := testGame(t) res := forceBattle(t, g, []Card{g.goldenPet(t, "Highland Cow")}, // power 3 []Card{g.pet("Foe", 1)}, ) var gain *BattleEvent for i, ev := range res.Events { if ev.Type == "trumpet" && ev.Seat == 0 && ev.Count == 3 { gain = &res.Events[i] } } if gain == nil { t.Fatalf("Highland Cow should bank 3 Trumpets (its power): %+v", eventsOfType(res, "trumpet")) } } // Wildebeest spends 3 Trumpets on entry to shield its first hit. func TestWildebeestSpendsForShield(t *testing.T) { g, _, _ := testGame(t) res := forceBattle(t, g, []Card{g.goldenPet(t, "Highland Cow"), g.goldenPet(t, "Wildebeest")}, // Cow banks 3 []Card{g.pet("Chip", 1), g.pet("Hitter", 6)}, ) // Cow banks 3 Trumpets and trades with Chip, then dies to Hitter; Wildebeest // enters, spends the 3 Trumpets for a shield, and blocks Hitter's blow. spent := false for _, ev := range eventsOfType(res, "trumpet") { if ev.Seat == 0 && ev.Count == -3 { spent = true } } if !spent { t.Fatalf("Wildebeest should spend 3 Trumpets: %+v", eventsOfType(res, "trumpet")) } if len(eventsOfType(res, "shield")) == 0 { t.Fatal("Wildebeest should block a hit with its shield") } if res.WinnerSeat != 0 { t.Fatalf("Wildebeest should survive the block and win, got %d", res.WinnerSeat) } } // Grizzly Bear throws a rock per friendly fainted pet. func TestGrizzlyRocksPerFainted(t *testing.T) { g, _, _ := testGame(t) g.RollDie = func() int { return 2 } res := forceBattle(t, g, []Card{g.pet("F1", 1), g.pet("F2", 1), g.goldenPet(t, "Grizzly Bear")}, []Card{g.pet("K1", 1), g.pet("K2", 1), g.pet("Tank", 2)}, ) rocks := eventsOfType(res, "rock") if len(rocks) != 1 || len(rocks[0].Dice) != 2 || !rocks[0].TargetDied { t.Fatalf("Grizzly should throw 2 rocks (one per friendly faint) and kill Tank: %+v", rocks) } } // Catfish reactivates every pet's Buy ability at battle prep. func TestCatfishReactivatesBuys(t *testing.T) { g, p1, _ := goldenGame(t) p1.Deck = []Card{g.goldenPet(t, "Catfish"), g.realPet(t, "Otter")} // Otter buy: +1 apple g.beginArrange() if countApplesIn(p1.Deck) != 1 { t.Fatalf("Catfish should re-fire Otter's buy for 1 apple, got %d", countApplesIn(p1.Deck)) } } // Komodo shuffles 6 apples into the deck when it is the first pet. func TestKomodoShufflesApplesFirstPet(t *testing.T) { g, _, _ := testGame(t) res := forceBattle(t, g, []Card{g.goldenPet(t, "Komodo")}, // power 6, first pet []Card{g.pet("Foe", 1)}, ) apples := 0 for _, ev := range eventsOfType(res, "summon") { if ev.Card != nil && ev.Card.Name == "Apple" && ev.Seat == 0 { apples++ } } if apples != 6 { t.Fatalf("Komodo should shuffle 6 apples in as the first pet, got %d", apples) } } // Komodo does nothing when it is not the first pet played. func TestKomodoNoShuffleWhenNotFirst(t *testing.T) { g, _, _ := testGame(t) res := forceBattle(t, g, []Card{g.pet("Weak", 1), g.goldenPet(t, "Komodo")}, []Card{g.pet("K", 1), g.pet("Foe", 1)}, ) for _, ev := range eventsOfType(res, "summon") { if ev.Card != nil && ev.Card.Name == "Apple" { t.Fatal("Komodo should not shuffle apples when it isn't the first pet") } } } // Bird of Paradise banks 2 apples-in-play and 2 Trumpets for the next battle. func TestBirdOfParadiseBuy(t *testing.T) { g, p1, _ := goldenGame(t) g.ShopRow[0] = g.goldenPet(t, "Bird of Paradise") g.Turn = 0 if err := g.Buy(p1.ID, 0); err != nil { t.Fatal(err) } if p1.PendingApplesInPlay != 2 || p1.PendingTrumpets != 2 { t.Fatalf("Bird of Paradise should bank 2 apples + 2 Trumpets, got %d/%d", p1.PendingApplesInPlay, p1.PendingTrumpets) } } // The banked Trumpets appear in the pool at battle start, and reset after. func TestPendingTrumpetsSeedBattle(t *testing.T) { g, p1, _ := testGame(t) p1.PendingTrumpets = 2 res := forceBattle(t, g, []Card{g.pet("Hero", 3)}, []Card{g.pet("Foe", 1)}) var seeded *BattleEvent for i, ev := range res.Events { if ev.Type == "trumpet" && ev.Seat == 0 && ev.Count == 2 { seeded = &res.Events[i] } } if seeded == nil { t.Fatalf("the battle should start with 2 Trumpets in the pool: %+v", eventsOfType(res, "trumpet")) } if p1.PendingTrumpets != 0 { t.Fatalf("PendingTrumpets should reset after the battle, got %d", p1.PendingTrumpets) } } // German Shepherd guards the Golden Retriever's first hit. func TestGermanShepherdGuardsRetriever(t *testing.T) { g, _, _ := testGame(t) res := forceBattle(t, g, []Card{g.goldenPet(t, "German Shepherd"), g.goldenPet(t, "Nyala")}, // Nyala banks 2 Trumpets []Card{g.pet("BigA", 5), g.pet("BigB", 9)}, ) // German Shepherd faints (guard aside), Nyala faints (+2 Trumpets), then the // Golden Retriever arrives and its first hit is shaved by 5. var guarded *BattleEvent for i, ev := range res.Events { if ev.Type == "prevent" && ev.Seat == 0 && ev.Count == 5 { guarded = &res.Events[i] } } if guarded == nil { t.Fatalf("the Golden Retriever's first hit should be guarded for 5: %+v", eventsOfType(res, "prevent")) } } // Tomato is a perk that throws 4 rocks on play. func TestTomatoThrowsRocks(t *testing.T) { g, _, _ := testGame(t) g.RollDie = func() int { return 1 } res := forceBattle(t, g, []Card{g.goldenFood(t, "Tomato"), g.pet("Holder", 2)}, []Card{g.pet("Tank", 3)}, ) rocks := eventsOfType(res, "rock") if len(rocks) != 1 || rocks[0].Roll != 4 || !rocks[0].TargetDied { t.Fatalf("Tomato should throw 4 rocks and kill the 3-power Tank: %+v", rocks) } if res.WinnerSeat != 0 { t.Fatalf("seat 0 should win, got %d", res.WinnerSeat) } }