Skip to content

PendingAction with tests #75

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,34 @@
from ansi_tags import ansiprint
from definitions import CardType, State, TargetType
from message_bus_tools import Card, Effect, Message, Potion, Registerable, Relic, bus
from typing import Callable

ei = helper.ei
view = helper.view

class Action:
def __init__(self, name, action, amount):
class PendingAction:
'''
A pending action is an action that is created before it is executed. It can be cancelled, modified, and executed.

'''
def __init__(self, name: str, action: Callable, amount: int | float):
self.name = name
self.action = action
self.amount = amount
self.executed = False
self.cancelled = False
self.reason = ""

def cancel(self, reason=None):
def cancel(self, reason: str = None):
self.cancelled = True
if not reason:
reason = f"{self.name} was cancelled."
self.reason = reason

def set_amount(self, new_amount):
def set_amount(self, new_amount: int | float):
self.amount = new_amount

def modify_amount(self, change):
def increase_amount(self, change: int | float):
self.amount += change

def execute(self):
Expand All @@ -42,11 +47,12 @@ def execute(self):
if self.cancelled:
ansiprint(self.reason)
return
self.action(self.amount)
result = self.action(self.amount)
self.executed = True
return result

def __str__(self):
return f"Action: {self.name} | Amount: {self.amount}"
return f"PendingAction: {self.name}({self.amount})"

def __repr__(self):
return self.__str__()
Expand Down Expand Up @@ -198,7 +204,7 @@ def draw_cards(self, cards: int = None):
"""Draws [cards] cards."""
if cards is None:
cards = self.draw_strength
action = Action(self, self._draw_cards, cards)
action = PendingAction(self, self._draw_cards, cards)
bus.publish(Message.BEFORE_DRAW, (self, action))
action.execute()
bus.publish(Message.AFTER_DRAW, (self, action))
Expand Down
6 changes: 3 additions & 3 deletions helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from message_bus_tools import Effect, Message, bus

if TYPE_CHECKING:
from entities import Enemy, Player, Action
from entities import Enemy, Player, PendingAction
from items import Card


Expand Down Expand Up @@ -463,7 +463,7 @@ class NoDraw(Effect):
def __init__(self, host, _):
super().__init__(host, "No Draw", StackType.NONE, EffectType.DEBUFF, "You may not draw any more cards this turn.")

def callback(self, message, data: tuple[Player, Action]):
def callback(self, message, data: tuple[Player, PendingAction]):
if message == Message.BEFORE_DRAW:
player, action = data
action.cancel(reason="You cannot draw any cards because of <debuff>No Draw</debuff>.")
Expand Down Expand Up @@ -574,7 +574,7 @@ def __init__(self, host, amount=0):
super().__init__(host, "Barricade", StackType.NONE, EffectType.BUFF, "<keyword>Block</keyword> is not removed at the start of your turn.", amount)
self.end_of_turn_block = None

def callback(self, message, data: tuple[Player, Action] | tuple[Player, list[Enemy]]):
def callback(self, message, data: tuple[Player, PendingAction] | tuple[Player, list[Enemy]]):
if message == Message.END_OF_TURN:
player, enemies = data
self.end_of_turn_block = player.block
Expand Down
53 changes: 53 additions & 0 deletions tests/test_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,56 @@ def test_all_attack_cards_with_all_relics(monkeypatch):
print(f"Playing card {idx} of {initial_size} - {card.name}")
player.use_card(card=card, enemies=[boss], target=boss, exhaust=True, pile=player.draw_pile)


class TestPendingAction():
def test_pending_action_str_and_repl(self):
pa = entities.PendingAction("draw_cards", lambda: None, 100)
assert str(pa) == "PendingAction: draw_cards(100)"
assert repr(pa) == "PendingAction: draw_cards(100)"

def test_pending_action_can_set_argument(self):
def action(arg1):
print(f"Action executed with arg1={arg1}")
return arg1

pa = entities.PendingAction("PendingAction", action, 1)
pa.set_amount(2)
assert pa.amount == 2
assert pa.execute() == 2

def test_pending_action_can_modify_argument(self):
def action(arg1):
print(f"Action executed with arg1={arg1}")
return arg1

pa = entities.PendingAction("PendingAction", action, 1)
pa.increase_amount(2)
assert pa.amount == 3
assert pa.execute() == 3

def test_pending_action_can_be_cancelled(self):
num_times_called = 0
def action(arg1):
nonlocal num_times_called
print(f"Action executed with arg1={arg1}")
num_times_called += 1
return arg1

pa = entities.PendingAction("PendingAction", action, 1)
pa.cancel()
assert pa.execute() is None
assert pa.execute() is None
assert num_times_called == 0

def test_pending_action_can_only_be_executed_once(self):
num_times_called = 0
def action(arg1):
nonlocal num_times_called
print(f"Action executed with arg1={arg1}")
num_times_called += 1
return arg1

pa = entities.PendingAction("PendingAction", action, 1)
assert pa.execute() == 1
assert pa.execute() is None
assert num_times_called == 1
Loading