from typing import TYPE_CHECKING, Awaitable, Optional from model.card_validator import EffectParser from model.card import Effect, EffectType, CardEffects, EffectTimes, CardType if TYPE_CHECKING: from model import Turn # Effect Types async def effect_type_suicide(effect: Effect, turn: "Turn"): for e in effect.card.effects: if e != effect: while e in turn.effects_availables: turn.effects_availables.remove(e) for se in e.sub_effects: if se != effect: while se in turn.effects_availables: turn.effects_availables.remove(se) if effect.card in turn.player.board: await turn.player.sacrifice_card(str(effect.card.uuid)) return True async def effect_type_faction_combo(effect: Effect, turn: "Turn"): for c in turn.cards_locked: if ( c in turn.cards_locked and c.faction == effect.card.faction and c != effect.card ): return True return False effect_types_all_behaviours = { EffectType.SUICIDE: effect_type_suicide, EffectType.FACTION_COMBO: effect_type_faction_combo, } # Card Effects async def effect_gold(effect: Effect, turn: "Turn", _target: str): turn.gold_reserve += effect.amount return True async def effect_damage(effect: Effect, turn: "Turn", _target: str): turn.damage_reserve += effect.amount return True async def effect_heal(effect: Effect, turn: "Turn", _target: str): turn.heal_reserve += effect.amount return True async def effect_prepare(_effect: Effect, turn: "Turn", target: str): return turn.prepare(target) async def effect_stun(_effect: Effect, turn: "Turn", target: str): return await turn.player.stun(target) async def effect_sacrifice(_effect: Effect, turn: "Turn", target: str): return await turn.sacrifice_card(target) async def effect_draw(_effect: Effect, turn: "Turn", _target: str): return await turn.player.draw(1) async def effect_draw_and_discard(_effect: Effect, turn: "Turn", _target: str): turn.discard_markers += 1 return await turn.player.draw(1) async def effect_discard(_effect: Effect, turn: "Turn", target: str): return await turn.player.make_enemy_discard(target) async def effect_restack_discarded_champion(_effect: Effect, turn: "Turn", target: str): return await turn.restack_discarded_champion(target) async def effect_restack_discarded(_effect: Effect, turn: "Turn", target: str): return await turn.player.put_on_stack_from_discard(target) async def effect_stack_next_action(_effect: Effect, turn: "Turn", target: str): return await turn.buy_card(target, turn.player.buy_on_stack) async def effect_stack_next_card(_effect: Effect, turn: "Turn", target: str): return await turn.buy_card(target, turn.stack_next_card_bought_check) async def effect_play_next_card(_effect: Effect, turn: "Turn", target: str): return await turn.buy_card(target, turn.player.buy_in_hand) card_effect_all_behaviours = { CardEffects.GOLD: effect_gold, CardEffects.DAMAGE: effect_damage, CardEffects.HEAL: effect_heal, CardEffects.PREPARE: effect_prepare, CardEffects.STUN: effect_stun, CardEffects.SACRIFICE: effect_sacrifice, CardEffects.DRAW: effect_draw, CardEffects.DRAW_AND_DISCARD: effect_draw_and_discard, CardEffects.DISCARD: effect_discard, CardEffects.RESTACK_DISCARDED_CHAMPION: effect_restack_discarded_champion, CardEffects.RESTACK_DISCARDED_CARD: effect_restack_discarded, CardEffects.STACK_NEXT_ACTION_BOUGHT: effect_stack_next_action, CardEffects.STACK_NEXT_CARD_BOUGHT: effect_stack_next_card, CardEffects.PLAY_NEXT_CARD_BOUGHT: effect_play_next_card, } # Effect Times def effect_times_same_faction(effect: Effect, turn: "Turn"): times = 0 for c in turn.player.board: if c.faction == effect.card.faction and c in turn.cards_locked: times += 1 return times def effect_times_other_same_faction(effect: Effect, turn: "Turn"): times = 0 for c in turn.player.board: if ( c.faction == effect.card.faction and c != effect.card and c in turn.cards_locked ): times += 1 return times def effect_times_champion(effect: Effect, turn: "Turn"): times = 0 for c in turn.player.board: if c.card_type == CardType.CHAMPION and c in turn.cards_locked: times += 1 return times def effect_times_other_champion(effect: Effect, turn: "Turn"): times = 0 for c in turn.player.board: if ( c.card_type == CardType.CHAMPION and c != effect.card and c in turn.cards_locked ): times += 1 return times def effect_times_other_guard(effect: Effect, turn: "Turn"): times = 0 for c in turn.player.board: if ( c.card_type == CardType.CHAMPION and c.guard is True and c != effect.card and c in turn.cards_locked ): times += 1 return times effect_times_all_behaviours = { EffectTimes.PER_CARD_OF_SAME_FACTION: effect_times_same_faction, EffectTimes.PER_OTHER_CARD_OF_SAME_FACTION: effect_times_other_same_faction, EffectTimes.PER_CHAMPION: effect_times_champion, EffectTimes.PER_OTHER_CHAMPION: effect_times_other_champion, EffectTimes.PER_OTHER_GUARD: effect_times_other_guard, } def create_effect_behaviour(effect: EffectParser) -> Awaitable[None]: async def effect_type_behaviour(_e: Effect, _t: "Turn"): return True if effect.effect_type in effect_types_all_behaviours: effect_type_behaviour = effect_types_all_behaviours[effect.effect_type] if effect.effect not in card_effect_all_behaviours: raise NotImplementedError("CardEffect " + effect.effect + " not implemented") card_effect_behaviour = card_effect_all_behaviours[effect.effect] def effect_times_behaviour(_e: Effect, _t: "Turn"): return 1 if effect.times in effect_times_all_behaviours: effect_times_behaviour = effect_times_all_behaviours[effect.times] async def activate(self: Effect, turn: "Turn", target: Optional[str] = None): effect_type_result = await effect_type_behaviour(self, turn) if not effect_type_result: return False times = effect_times_behaviour(self, turn) for _ in range(times): effect_result = await card_effect_behaviour(self, turn, target) if not effect_result: return False return True return activate