✅ Crystal infection kills ally with no cp
| Category | Ability |
| Status | Passing |
| Test | tests/test_abilities_complex.py::TestVineCrystalInfection::test_crystal_infection_kills_ally_with_no_cp |
Vine uses Crystal Infection on an allied demon. The target
Preconditions
-
P1 Main Phase, P1 has 6 AP, P1 has 0 CP
-
Lane 0: P1's Vine (#085) — READIED
-
Lane 0: P1's Flauros (#013) — READIED, CP=4 (target)
Action
- P1 activates Vine's Crystal Infection (idx=1, 1 AP, exhaust, 1x)
from engine.abilities import execute_ability
vine = make_demon("085", lane=0, owner=Side.PLAYER_1)
flauros = make_demon("013", lane=0, owner=Side.PLAYER_1)
state, placed = _make_state_with_demons(vine, flauros, ap=6)
vine_p, flauros_p = placed
result = execute_ability(state, vine_p, ability_idx=1, targets=[flauros_p])
# Flauros should be removed from the board
Expected Postconditions
-
Flauros: removed from board (fatally wounded → resolved in step 11)
-
Flauros: in P1's graveyard
-
P1 CP: 0 (Flauros's CP=4 is IGNORED due to cp_override_zero status)
-
Vine: EXHAUSTED
-
P1 AP: 5 (6 - 1)
Assertions
assert not any(d.unit_id == "013" for d in result.demons), (
"Flauros should be removed from board (fatally wounded)"
)
# Flauros should be in P1's graveyard
assert "013" in result.players[Side.PLAYER_1].graveyard, (
f"Flauros should be in P1 graveyard. Got {result.players[Side.PLAYER_1].graveyard}"
)
# CRITICAL: P1 gains 0 CP because Crystal Infection applies cp_override_zero
assert result.players[Side.PLAYER_1].cp == 0, (
f"P1 CP should be 0 — Crystal Infection ignores CP. "
f"Got {result.players[Side.PLAYER_1].cp}"
)
# Vine is exhausted, AP spent
vine_after = next(d for d in result.demons if d.unit_id == "085")
assert vine_after.state == DemonState.EXHAUSTED
assert result.players[Side.PLAYER_1].ap == 5