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