Skip to main content

Leraje

The Unrivaled Archer

Unit #091

HPPWRCPSpeedRangeTier
12 (+6)3 (+1)3 (+2)NormalDistantA

Abilities

Passive

c: If Leraje is Readied when Any Other Demon deals at least 1 damage (after n) to Any Demon, Leraje may perform an Attack basic action targeting the damaged Demon with -1 AP Cost and ignoring a costs. (Range is not ignored.)
Engine Implementation
def _leraje_counter_attack(
state: GameState, event: GameEvent, demon: DemonInstance, depth: int
):
"""#091 Leraje idx=0 — Field Passive: Counter-Attack.

If Leraje is Readied when Any Other Demon deals >= 1 damage to Any Demon,
Leraje may perform an Attack targeting the damaged Demon at -1 AP Cost,
ignoring (exhaust) costs. Range is NOT ignored (Leraje has Distant range).

Fires on DAMAGE_RECEIVED.
Checks: Leraje READIED, source != Leraje, value >= 1, target in Distant range.

Leraje's range is Distant (different lane). The counter-attack is a basic
Attack: deal Leraje's effective PWR as damage (DEF applies) to the target.
AP cost: max(0, ATTACK_AP_COST - 1) = 1 AP deducted from Leraje's owner.
Leraje does NOT exhaust (exhaust cost ignored per card text).
"""
from engine.constants import ATTACK_AP_COST
from engine.operations import deal_damage, get_effective_pwr

# Must have a source and target
if event.source is None or event.target is None:
return None

# Source must not be Leraje itself
if event.source.instance_id == demon.instance_id:
return None

# Damage must be >= 1
if event.value is None or event.value < 1:
return None

# Re-fetch Leraje from current state
leraje_current = next(
(d for d in state.demons if d.instance_id == demon.instance_id), None
)
if leraje_current is None or leraje_current.fatally_wounded:
return None

# Leraje must be READIED
if leraje_current.state != DemonState.READIED:
return None

# Leraje's range is Distant — target must be in a different lane from Leraje
if event.target.lane == leraje_current.lane:
return None # Target is in Leraje's lane — not in Distant range

# Re-fetch target from state (it may have moved due to prior handlers)
target_current = next(
(d for d in state.demons if d.instance_id == event.target.instance_id), None
)
if target_current is None or target_current.fatally_wounded:
return None

# Deduct AP: max(0, ATTACK_AP_COST - 1) = 1
ap_cost = max(0, ATTACK_AP_COST - 1)
new_state = state
owner_player = new_state.players[leraje_current.owner]
if owner_player.ap < ap_cost:
return None # Cannot afford the counter-attack

import copy as _copy
new_state = _copy.deepcopy(state)
new_state.players[leraje_current.owner].ap -= ap_cost

# Leraje does NOT exhaust (card text: ignoring (exhaust) costs)
# Deal PWR damage (regular attack — DEF applies)
leraje_in_new = next(d for d in new_state.demons if d.instance_id == demon.instance_id)
pwr = get_effective_pwr(new_state, leraje_in_new)

return deal_damage(new_state, leraje_in_new, target_current, pwr)

register_trigger("091", 0, _leraje_counter_attack)
Leraje