Epiales
The Dream Eater
Unit #039
| HP | PWR | CP | Speed | Range | Tier |
|---|---|---|---|---|---|
| 12 (+6) | 3 (+1) | 3 (+2) | Slow | Any | B |
Abilities
Passive
c: While an Evoker has 1 or less AP, their Demons have -2n.
Engine Implementation
def _epiales_aura_def(state: GameState, demon: DemonInstance) -> dict[str, int]:
"""Return -2 DEF to any demon whose owner has ≤1 AP, if Epiales is on the field."""
# Epiales must be on the field for the aura to be active
if not _on_field(state, "039"):
return {}
# Check if the demon's owner has 1 or less AP
owner_ap = state.players[demon.owner].ap
if owner_ap <= 1:
return {"def": -2}
return {}
register_field_aura("039", 0, _epiales_aura_def)
Slumber — X AP
h: Slumber: X AP - a, 1x: e: At the end of this Main Phase, your opponent loses 2X AP.
Engine Implementation
def _epiales_slumber(
state: GameState, demon: DemonInstance, targets, choices, rng
) -> GameState:
"""#039 Epiales — Slumber
Start of Turn, X AP, (exhaust), 1x: Status: At the end of this Main Phase,
your opponent loses 2X AP.
X is read from choices["x"]. The opponent loses 2X AP at end of phase.
We implement this as an immediate AP deduction (floor at 0) since the
engine does not model delayed per-ability end-of-phase callbacks.
The status is cosmetic — the actual AP loss is applied immediately here.
CRITICAL: The AP cost of X is already deducted by execute_ability before
this handler is called. Here we only apply the opponent's AP penalty.
"""
x = choices.get("x", 0) if choices else 0
if x <= 0:
return state
opponent = Side.PLAYER_2 if demon.owner == Side.PLAYER_1 else Side.PLAYER_1
new_state = copy.deepcopy(state)
penalty = 2 * x
new_state.players[opponent].ap = max(0, new_state.players[opponent].ap - penalty)
return new_state
register_ability("039", 1, _epiales_slumber)