From b0bdbe0d0f612e2bd1f0aab1160c295bd4ca4deb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannes=20H=C3=B6ke?= Date: Tue, 1 Mar 2016 01:25:26 +0100 Subject: [PATCH] some refactoring and rule improvements --- bot.py | 247 +++++++++++++++++++++++++++++++++--------------------- card.py | 3 + game.py | 8 +- player.py | 56 +++++++------ 4 files changed, 191 insertions(+), 123 deletions(-) diff --git a/bot.py b/bot.py index 75a8dcc..5b92b6f 100644 --- a/bot.py +++ b/bot.py @@ -22,7 +22,7 @@ def list_subtract(list1, list2): for x in list2: list1.remove(x) - return list1 + return list(sorted(list1)) def new_game(bot, update): @@ -55,105 +55,160 @@ def start(bot, update, args): def inline(bot, update): if update.inline_query: - user_id = update.inline_query.from_user.id - player = gm.userid_player[user_id] - game = gm.userid_game[user_id] - results = list() - playable = list() - - if game.choosing_color: - for color in c.COLORS: - results.append( - InlineQueryResultArticle( - id=color, - title="Choose Color", - message_text=color, - description=color.upper() - ) - ) - else: - playable = player.playable_cards() - - if playable is False: - results.append( - InlineQueryResultArticle( - "not_your_turn", - title="Not your turn", - description="Tap to see the current player", - message_text="Current player: " + - game.current_player.user.first_name - ) - ) - elif playable: - for card in playable: - results.append( - InlineQueryResultArticle(str(card), - title="Play card", - message_text= - ('\xad' - 'Played card ' + repr(card)) - % card.get_image_link(), - thumb_url=card.get_thumb_link(), - description=repr(card), - parse_mode=ParseMode.HTML) - ) - elif not game.choosing_color: - results.append( - InlineQueryResultArticle( - "draw", - title="No suitable cards...", - description="Draw!", - message_text='Drawing %d card(s)' - % (player.game.draw_counter or 1) - ) - ) - - results.append( - InlineQueryResultArticle( - "hand", - title="Other cards:", - description=', '.join([repr(card) for card in - list_subtract(player.cards, playable)]), - message_text='Just checking cards' - ) - ) - - [logger.info(str(result)) for result in results] - - bot.answerInlineQuery(update.inline_query.id, results, cache_time=0) - + reply_to_query(bot, update) else: - user = update.chosen_inline_result.from_user - game = gm.userid_game[user.id] - player = gm.userid_player[user.id] - result_id = update.chosen_inline_result.result_id - chat_id = gm.chatid_gameid[game] + chosen_card(bot, update) - logger.info("Selected result: " + result_id) - if result_id == 'hand': - pass - elif result_id == 'draw': - for n in range(game.draw_counter or 1): - player.cards.append(game.deck.draw()) - game.draw_counter = 0 - elif result_id in c.COLORS: - game.choose_color(result_id) - else: - card = c.from_str(result_id) - game.play_card(card) - player.cards.remove(card) - if game.choosing_color: - bot.sendMessage(chat_id, text="Please choose a color") - elif len(player.cards) == 1: - bot.sendMessage(chat_id, text="Last Card!") - elif len(player.cards) == 0: - gm.leave_game(user) - bot.sendMessage(chat_id, text="Player won!") +def reply_to_query(bot, update): + user_id = update.inline_query.from_user.id + player = gm.userid_player[user_id] + game = gm.userid_game[user_id] + results = list() + playable = list() - bot.sendMessage(chat_id, - text="Next player: " + - game.current_player.user.first_name) + if game.choosing_color: + for color in c.COLORS: + results.append( + InlineQueryResultArticle( + id=color, + title="Choose Color", + message_text=color, + description=color.upper() + ) + ) + else: + playable = list(sorted(player.playable_cards())) + + if playable is False: + not_your_turn(game, results) + elif playable: + for card in playable: + play_card(card, results) + elif not game.choosing_color: + draw(player, results) + + if player.drew: + pass_(results) + + if game.last_card.special == c.DRAW_FOUR and not game.choosing_color: + call_bluff(results) + + other_cards(playable, player, results) + + bot.answerInlineQuery(update.inline_query.id, results, cache_time=0) + + +def other_cards(playable, player, results): + results.append( + InlineQueryResultArticle( + "hand", + title="Other cards:", + description=', '.join([repr(card) for card in + list_subtract(player.cards, playable)]), + message_text='Just checking cards' + ) + ) + + +def draw(player, results): + results.append( + InlineQueryResultArticle( + "draw", + title="No suitable cards...", + description="Draw!", + message_text='Drawing %d card(s)' + % (player.game.draw_counter or 1) + ) + ) + + +def pass_(results): + results.append( + InlineQueryResultArticle( + "pass", + title="Pass", + description="Don't play a card", + message_text='Pass' + ) + ) + + +def call_bluff(results): + results.append( + InlineQueryResultArticle( + "call_bluff", + title="Call their bluff!", + description="Risk it!", + message_text="I'm calling your bluff!" + ) + ) + + +def play_card(card, results): + results.append( + InlineQueryResultArticle(str(card), + title="Play card", + message_text= + ('\xad' + 'Played card ' + repr(card)) + % card.get_image_link(), + thumb_url=card.get_thumb_link(), + description=repr(card), + parse_mode=ParseMode.HTML) + ) + + +def not_your_turn(game, results): + results.append( + InlineQueryResultArticle( + "not_your_turn", + title="Not your turn", + description="Tap to see the current player", + message_text="Current player: " + + game.current_player.user.first_name + ) + ) + + +def chosen_card(bot, update): + user = update.chosen_inline_result.from_user + game = gm.userid_game[user.id] + player = gm.userid_player[user.id] + result_id = update.chosen_inline_result.result_id + chat_id = gm.chatid_gameid[game] + logger.info("Selected result: " + result_id) + + if result_id in ('hand', 'not_your_turn'): + return + elif result_id == 'draw': + for n in range(game.draw_counter or 1): + player.cards.append(game.deck.draw()) + game.draw_counter = 0 + player.drew = True + + if game.last_card.value == c.DRAW_TWO or \ + not player.card_playable(player.cards[-1], list()): + game.turn() + elif result_id == 'pass': + game.turn() + elif result_id in c.COLORS: + game.choose_color(result_id) + else: + card = c.from_str(result_id) + game.play_card(card) + player.cards.remove(card) + if game.choosing_color: + bot.sendMessage(chat_id, text="Please choose a color") + elif len(player.cards) == 1: + bot.sendMessage(chat_id, text="Last Card!") + elif len(player.cards) == 0: + gm.leave_game(user) + bot.sendMessage(chat_id, text="Player won!") + + bot.sendMessage(chat_id, + text="Next player: " + + game.current_player.user.first_name) def error(bot, update, error): diff --git a/card.py b/card.py index c1b293e..8de8079 100644 --- a/card.py +++ b/card.py @@ -56,6 +56,9 @@ class Card(object): def __eq__(self, other): return str(self) == str(other) + def __lt__(self, other): + return str(self) < str(other) + def get_image_link(self): return IMAGE_PATTERN % str(self) diff --git a/game.py b/game.py index dd81843..2faef12 100644 --- a/game.py +++ b/game.py @@ -25,7 +25,9 @@ class Game(object): self.reversed = not self.reversed def turn(self): + self.logger.debug("Next Player") self.current_player = self.current_player.next + self.current_player.drew = False def play_card(self, card): """ @@ -39,7 +41,7 @@ class Game(object): self.logger.info("Playing card " + repr(card)) if card.value == c.SKIP: - self.current_player = self.current_player.next.next + self.turn() elif card.special == c.DRAW_FOUR: self.draw_counter += 4 self.logger.debug("Draw counter increased by 4") @@ -50,12 +52,12 @@ class Game(object): self.reverse() if card.special not in (c.CHOOSE, c.DRAW_FOUR): - self.current_player = self.current_player.next + self.turn() else: self.logger.debug("Choosing Color...") self.choosing_color = True def choose_color(self, color): self.last_card.color = color - self.current_player = self.current_player.next + self.turn() self.choosing_color = False diff --git a/player.py b/player.py index 7519eb7..1441a3b 100644 --- a/player.py +++ b/player.py @@ -27,9 +27,12 @@ class Player(object): self._prev = self game.current_player = self - for i in range(6): + for i in range(7): self.cards.append(self.game.deck.draw()) + self.bluffing = False + self.drew = False + def leave(self): self.next.prev = self.prev self.prev.next = self.next @@ -76,29 +79,34 @@ class Player(object): self.logger.debug("Last card was" + str(last)) for card in self.cards: - self.logger.debug("Checking card " + str(card)) - if (card.color != last.color and card.value != last.value and - not card.special): - self.logger.debug("Card's color or value doesn't match") - continue + if self.card_playable(card, playable): + self.logger.debug("Matching!") + playable.append(card) - if last.value == c.DRAW_TWO and not \ - (card.value == c.DRAW_TWO or - card.special == c.DRAW_FOUR or - not self.game.draw_counter): - self.logger.debug("Player has to draw and can't counter") - continue - - if last.special == c.DRAW_FOUR and self.game.draw_counter: - self.logger.debug("Player has to draw and can't counter") - continue - - if not last.color or card in playable: - self.logger.debug("Last card has no color or the card was " - "already added to the list") - continue - - self.logger.debug("Matching!") - playable.append(card) + self.bluffing = bool(len(playable) - 1) return playable + + def card_playable(self, card, playable): + is_playable = True + last = self.game.last_card + self.logger.debug("Checking card " + str(card)) + if (card.color != last.color and card.value != last.value and + not card.special): + self.logger.debug("Card's color or value doesn't match") + is_playable = False + if last.value == c.DRAW_TWO and not \ + (card.value == c.DRAW_TWO or + card.special == c.DRAW_FOUR or + not self.game.draw_counter): + self.logger.debug("Player has to draw and can't counter") + is_playable = False + if last.special == c.DRAW_FOUR and self.game.draw_counter: + self.logger.debug("Player has to draw and can't counter") + is_playable = False + if not last.color or card in playable: + self.logger.debug("Last card has no color or the card was " + "already added to the list") + is_playable = False + + return is_playable