diff --git a/blackjackbot/commands/game/functions.py b/blackjackbot/commands/game/functions.py index b7e819f..2309c5a 100644 --- a/blackjackbot/commands/game/functions.py +++ b/blackjackbot/commands/game/functions.py @@ -46,11 +46,11 @@ def players_turn(update, context): if player.has_blackjack(): text = (translator("your_cards_are") + "\n\n" + translator("got_blackjack")).format(user_mention, player.cardvalue, player_cards) update.effective_message.reply_text(text=text, parse_mode=ParseMode.HTML, reply_markup=None) - next_player(update, context) + _advance_turn(update, context) elif player.cardvalue == 21: text = (translator("your_cards_are") + "\n\n" + translator("got_21")).format(user_mention, player.cardvalue, player_cards) update.effective_message.reply_text(text=text, parse_mode=ParseMode.HTML, reply_markup=None) - next_player(update, context) + _advance_turn(update, context) else: text = translator("your_cards_are").format(user_mention, player.cardvalue, player_cards) update.effective_message.reply_text(text=text, parse_mode=ParseMode.HTML, reply_markup=get_game_keyboard(game.id, lang_id)) @@ -65,11 +65,23 @@ def next_player(update, context): game = GameStore().get_game(chat.id) - try: - if user.id != game.get_current_player().user_id: - update.callback_query.answer(translator("mp_not_your_turn_callback").format(user.first_name)) - return + if user.id != game.get_current_player().user_id: + update.callback_query.answer(translator("mp_not_your_turn_callback").format(user.first_name)) + return + + _advance_turn(update, context) + +def _advance_turn(update, context): + """Hand the turn to the next player (or the dealer) without checking who triggered the update. + Used when a player's turn ends automatically, e.g. because they were dealt a blackjack.""" + chat = update.effective_chat + lang_id = Database().get_lang_id(chat.id) + translator = Translator(lang_id=lang_id) + + game = GameStore().get_game(chat.id) + + try: remove_inline_keyboard(update, context) game.next_player() except NoPlayersLeftException: diff --git a/blackjackbot/commands/game/tests/functions_test.py b/blackjackbot/commands/game/tests/functions_test.py index f3647b6..48f7a7a 100644 --- a/blackjackbot/commands/game/tests/functions_test.py +++ b/blackjackbot/commands/game/tests/functions_test.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- import unittest -from unittest.mock import Mock +from unittest.mock import Mock, patch -from blackjackbot.commands.game.functions import is_button_affiliated +from blackjack.game import BlackJackGame, Card +from blackjackbot.commands.game.functions import is_button_affiliated, next_player +from blackjackbot.gamestore import GameStore class GameCommandsFunctionsTest(unittest.TestCase): @@ -32,6 +34,38 @@ def test_is_button_affiliated_negative(self): self.assertFalse(result) update.callback_query.answer.assert_called_once() + @patch("blackjackbot.commands.util.decorators.Database") + @patch("blackjackbot.commands.game.functions.Database") + def test_next_player_skips_player_with_blackjack(self, db_mock, decorator_db_mock): + """When the next player was dealt a blackjack, their turn must be skipped even though another user triggered the update""" + db_mock.return_value.get_lang_id.return_value = "en" + decorator_db_mock.return_value.get_lang_id.return_value = "en" + chat_id = -1001234 + + game = BlackJackGame(gametype=BlackJackGame.Type.MULTIPLAYER_GROUP) + game.add_player(1, "A") + game.add_player(2, "B") + game.add_player(3, "C") + game.running = True + game.players[0]._cards = [Card(0), Card(1)] # 2 + 3 + game.players[1]._cards = [Card(12), Card(9)] # Ace + Jack -> blackjack + game.players[2]._cards = [Card(2), Card(3)] # 4 + 5 + game.dealer._cards = [Card(8), Card(7)] + + game_store = GameStore() + game_store.add_game(chat_id, game) + self.addCleanup(game_store.remove_game, chat_id) + + update = Mock() + update.effective_chat.id = chat_id + update.effective_user.id = 1 # Player A presses "stand" + + next_player(update, Mock()) + + # B was skipped automatically, so it's now C's turn + self.assertEqual(game.players[2], game.get_current_player()) + update.callback_query.answer.assert_not_called() + if __name__ == '__main__': unittest.main()