diff --git a/backend/bang/game.py b/backend/bang/game.py index 4990681..3e3724f 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -290,6 +290,7 @@ class Game: self.started = True self.someone_won = False self.attack_in_progress = False + self.attack_queue = [] self.deck = Deck(self) self.initial_players = len(self.players) self.distribute_roles() @@ -381,13 +382,20 @@ class Game: return not any((True for p in self.get_visible_players(player) if p['name'] == target and p['dist'] > card.range)) return True - def attack(self, attacker: pl.Player, target_username:str, double:bool=False, card_name:str=None): + def attack(self, attacker: pl.Player, target_username:str, double:bool=False, card_name:str=None, skip_queue:bool=False): + if self.attack_in_progress and not skip_queue: + self.attack_queue.append((attacker, target_username, double, card_name)) + print(f'attack in progress, queueing the attack queue len:{len(self.attack_queue)}') + return if self.get_player_named(target_username).get_banged(attacker=attacker, double=double, card_name=card_name): + self.attack_in_progress = True self.ready_count = 0 self.waiting_for = 1 attacker.pending_action = pl.PendingAction.WAIT attacker.notify_self() self.get_player_named(target_username).notify_self() + elif not attacker.is_my_turn: + self.players[self.turn].pending_action = pl.PendingAction.PLAY def rimbalzo(self, attacker: pl.Player, target_username:str, card_index:int): if self.get_player_named(target_username).get_banged(attacker=attacker, no_dmg=True, card_index=card_index): @@ -502,6 +510,10 @@ class Game: self.players[self.turn].pending_action = pl.PendingAction.CHOOSE self.players[self.turn].choose_text = f'choose_from_poker;{min(2, tmp)}' self.players[self.turn].available_cards = self.deck.scrap_pile[-tmp:] + elif self.attack_queue: + print('attack completed, next attack') + atk = self.attack_queue.pop(0) + self.attack(atk[0], atk[1], atk[2], atk[3], skip_queue=True) else: self.players[self.turn].pending_action = pl.PendingAction.PLAY self.poker_on = False diff --git a/backend/bang/players.py b/backend/bang/players.py index 29c2c25..63c9ff0 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -1258,7 +1258,7 @@ class Player: self.pending_action = PendingAction.WAIT if hand_index != -1 and hand_index < (len(self.hand)+len(self.equipment)) and ( ((hand_index < len(self.hand) and self.hand[hand_index].name in self.expected_response) or self.character.check(self.game, chd.ElenaFuente)) or - (hand_index-len(self.hand) < len(self.equipment) and self.equipment[hand_index-len(self.hand)].name in self.expected_response)): + (0 <= hand_index-len(self.hand) < len(self.equipment) and self.equipment[hand_index-len(self.hand)].name in self.expected_response)): card = self.hand.pop(hand_index) if hand_index < len(self.hand) else self.equipment.pop(hand_index-len(self.hand)) #hand_index < len(self.hand) with the '<=' due to the hand.pop if self.character.check(self.game, chd.MollyStark) and hand_index <= len(self.hand) and not self.is_my_turn and self.event_type != 'duel': @@ -1272,6 +1272,8 @@ class Player: self.game.deck.scrap(card, True) self.notify_self() self.mancato_needed -= 1 + if isinstance(card, tvosc.RitornoDiFiamma): + self.game.attack(self, self.attacker.name, card_name=card.name) if self.mancato_needed <= 0: if self.event_type == 'duel': self.game.duel(self, self.attacker.name) @@ -1284,15 +1286,11 @@ class Player: self.molly_discarded_cards = 0 self.notify_self() self.game.responders_did_respond_resume_turn(did_lose=False) - if isinstance(card, tvosc.RitornoDiFiamma): - self.game.attack(self, self.attacker.name, card_name=card.name) self.event_type = '' elif not any(((isinstance(c, cs.Mancato) and c.can_be_used_now) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Bang)) or self.character.check(self.game, chd.ElenaFuente) for c in self.hand)) and not any((c.can_be_used_now and isinstance(c, cs.Mancato) for c in self.equipment)): self.on_failed_response_cb() if self.game: self.game.responders_did_respond_resume_turn(did_lose=True) - if isinstance(card, tvosc.RitornoDiFiamma) and self.attacker: - self.game.attack(self, self.attacker.name, card_name=card.name) else: self.pending_action = PendingAction.RESPOND self.notify_self() diff --git a/backend/tests/valley_of_shadows_test.py b/backend/tests/valley_of_shadows_test.py index 3f6d598..8749dc1 100644 --- a/backend/tests/valley_of_shadows_test.py +++ b/backend/tests/valley_of_shadows_test.py @@ -110,7 +110,7 @@ def test_ritorno_di_fiamma(): sio = DummySocket() g = Game('test', sio) g.expansions = ['the_valley_of_shadows'] - ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)] + ps = [Player(f'p{i}', f'p{i}', sio) for i in range(2)] for p in ps: g.add_player(p) g.start_game() @@ -129,6 +129,7 @@ def test_ritorno_di_fiamma(): assert len(p1.hand) == 0 assert p.lives == 3 p.end_turn() + assert p1.is_my_turn p1.draw('') p1.hand = [Bang(1, 1)] p.equipment = [cs.Barile(0,0)] @@ -141,6 +142,39 @@ def test_ritorno_di_fiamma(): p.respond(0) assert p1.lives == 3 +# test RitornoDiFiamma with gatling +def test_ritorno_di_fiamma_gatling(): + sio = DummySocket() + g = Game('test', sio) + ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)] + g.expansions = ['the_valley_of_shadows'] + for p in ps: + g.add_player(p) + g.start_game() + for p in ps: + p.available_characters = [Character('test_char', 4)] + p.set_character(p.available_characters[0].name) + p = g.players[g.turn] + p1 = g.players[(g.turn+1)%3] + p2 = g.players[(g.turn+2)%3] + p.draw('') + p.hand = [cs.Gatling(1, 1), Mancato(0,0)] + p1.hand = [RitornoDiFiamma(0,0)] + p2.hand = [Mancato(0,0)] + p.play_card(0) + assert len(p.hand) == 1 + assert p1.pending_action == PendingAction.RESPOND + assert p2.pending_action == PendingAction.RESPOND + p1.respond(0) + assert p2.pending_action == PendingAction.RESPOND + assert p.pending_action == PendingAction.WAIT + p2.respond(0) + # end of gatling + assert p.pending_action == PendingAction.RESPOND + p.respond(0) + assert len(p.hand) == 0 + assert p.pending_action == PendingAction.PLAY + # test Taglia def test_taglia(): sio = DummySocket()