Allow abomination to mimic play abilitites.

This commit is contained in:
Greyson Parrelli
2026-07-25 07:58:02 -04:00
parent a1d57fe1dd
commit 3a7f92b3cb
3 changed files with 48 additions and 3 deletions
+2
View File
@@ -1,7 +1,9 @@
/bin/
/data/
.env
card-captures/
# frontend
web/node_modules/
web/dist/
+17 -3
View File
@@ -1320,7 +1320,10 @@ func (g *Game) runBattle() *BattleResult {
// This runs before the "battle over" check so a parting shot fires even
// when its own side is already out (Crocodile's last-pet volley).
anyDeath := false
for _, q := range plays {
// Index-based so effects queued mid-loop (Abomination mimicking a Play
// ability) are resolved in the same pass.
for i := 0; i < len(plays); i++ {
q := plays[i]
// Effects sourced from a specific unit fizzle if it's gone — unless
// they're posthumous (the Manatee still adds its Apples after rocking
// itself to death).
@@ -1626,8 +1629,9 @@ func (g *Game) runBattle() *BattleResult {
}
case ActionGainAbility:
// Abomination: copy a random pet's effects from the highest tier
// discard pile. Gained abilities fire on their natural triggers going
// forward; a gained Play ability doesn't retro-fire this turn.
// discard pile. The copied effects join Abomination's own (so its
// Faint/Hurt abilities fire later), and any copied Play ability
// resolves right now — it's queued onto this same pass.
bestTier := 0
for tier, pile := range g.Discards {
if tier <= bestTier {
@@ -1652,6 +1656,16 @@ func (g *Game) runBattle() *BattleResult {
q.unit.Card.Effects = append(append([]Effect(nil), q.unit.Card.Effects...), pick.Effects...)
emit(BattleEvent{Type: "eat", Seat: q.seat, Bonus: q.unit.Bonus,
Text: fmt.Sprintf("%s mimics %s's ability.", q.unit.Card.Name, pick.Name)})
// Fire the mimicked Play abilities immediately. Skip another
// gainAbility so mimicking can't chain into an infinite loop,
// and skip the enter-time shields (armed only on reveal).
for _, pe := range pick.Effects {
if pe.Trigger != TriggerPlay || pe.Action == ActionGainAbility ||
pe.Action == ActionShieldSelf || pe.Action == ActionPreventSelf {
continue
}
plays = append(plays, queuedPlay{seat: q.seat, unit: q.unit, effect: pe})
}
}
}
}
+29
View File
@@ -860,6 +860,35 @@ func TestChimeraSummonFromDiscard(t *testing.T) {
}
}
// Abomination mimics a discard pet's ability, firing its Play effect at once.
func TestAbominationMimicsPlayAbility(t *testing.T) {
g, _, _ := unicornGame(t)
// The tier 1 discard pile holds a Barghest (Play → Spook the enemy pet).
g.Discards = map[int][]Card{1: {g.unicornPet(t, "Barghest")}}
res := forceBattle(t, g,
[]Card{g.unicornPet(t, "Abomination"), g.pet("Body", 4)},
[]Card{g.pet("Tank", 10)},
)
if len(eventsOfType(res, "ailment")) == 0 {
t.Fatal("Abomination should immediately fire the mimicked Barghest Play ability")
}
}
// Abomination's mimicked non-Play ability fires on its natural trigger later.
func TestAbominationMimicsFaintAbility(t *testing.T) {
g, _, _ := unicornGame(t)
// Discard holds an Ant (Faint → apple on deck); Abomination gains it and the
// apple appears when Abomination faints.
g.Discards = map[int][]Card{1: {g.tier1(t, "Ant")}}
res := forceBattle(t, g,
[]Card{g.unicornPet(t, "Abomination")},
[]Card{g.pet("Killer", 12)},
)
if seat0Summons(res, "Apple") == 0 {
t.Fatal("Abomination should gain the Ant's Faint ability and drop an apple on faint")
}
}
// Pixiu spends Mana to summon the top of the tier 6 shop deck.
func TestPixiuSummonFromTierDeck(t *testing.T) {
g, _, _ := unicornGame(t)