Combining with "patch" branch (#29)

* Update unobot.po

* Update test_player.py

* Update test_player.py

* Update test_player.py

* Update test_player.py

* Update player.py

* Update player.py

* Update internationalization.py

* Update internationalization.py

* Update test_player.py

* Update test_player.py

* Update test_player.py

* Update player.py

* Update player.py

* Update player.py

* Update test_player.py

* Update test_player.py

* revert play 4 then 4 rule

* Update test_player.py

* Update player.py

* Update player.py

* Update player.py

* Update game.py

* Update game_manager.py

* Update game_manager.py

* Update game_manager.py

* Update player.py

* Update test_player.py

* Update player.py

* Update bot.py

* Update credentials.py

* Update credentials.py

* Update bot.py

* Update game.py

* Update game_manager.py

* Update game_manager.py

* Update player.py
This commit is contained in:
Karho 2017-02-16 18:43:44 +08:00 committed by GitHub
parent 284eb91633
commit 615bb35359
5 changed files with 228 additions and 12 deletions

10
bot.py
View file

@ -694,9 +694,10 @@ def do_call_bluff(bot, player):
if player.prev.bluffing: if player.prev.bluffing:
send_async(bot, chat.id, send_async(bot, chat.id,
text=__("Bluff called! Giving 4 cards to {name}", text=__("Bluff called! Giving {numbers} cards to {name}",
multi=game.translate) multi=game.translate)
.format(name=player.prev.user.first_name)) .format(name=player.prev.user.first_name,
numbers=game.draw_counter))
try: try:
player.prev.draw() player.prev.draw()
@ -708,10 +709,11 @@ def do_call_bluff(bot, player):
else: else:
game.draw_counter += 2 game.draw_counter += 2
send_async(bot, chat.id, send_async(bot, chat.id,
text=__("{name1} didn't bluff! Giving 6 cards to {name2}", text=__("{name1} didn't bluff! Giving {numbers} cards to {name2}",
multi=game.translate) multi=game.translate)
.format(name1=player.prev.user.first_name, .format(name1=player.prev.user.first_name,
name2=player.user.first_name)) name2=player.user.first_name,
numbers=game.draw_counter))
try: try:
player.draw() player.draw()
except DeckEmptyError: except DeckEmptyError:

View file

@ -40,6 +40,7 @@ class Game(object):
def __init__(self, chat): def __init__(self, chat):
self.chat = chat self.chat = chat
self.last_card = None self.last_card = None
self.joined_before = [] #FIXME: Change it as set()
while not self.last_card or self.last_card.special: while not self.last_card or self.last_card.special:
self.deck = Deck() self.deck = Deck()

View file

@ -19,6 +19,7 @@
import logging import logging
import random
from game import Game from game import Game
from player import Player from player import Player
@ -77,7 +78,8 @@ class GameManager(object):
# Don not re-add a player and remove the player from previous games in # Don not re-add a player and remove the player from previous games in
# this chat, if he is in one of them # this chat, if he is in one of them
for player in players: for player in players:
if player in game.players: # Try to pervent someone win or leave then join again.
if player in game.players or user.id in game.joined_before:
raise AlreadyJoinedError() raise AlreadyJoinedError()
else: else:
try: try:
@ -94,7 +96,13 @@ class GameManager(object):
player = Player(game, user) player = Player(game, user)
players.append(player) # Randomize player position.
game.joined_before.append(user.id)
if len(players) > 2:
players.insert(random.randrange(len(players)), player)
else:
players.append(player)
self.userid_current[user.id] = player self.userid_current[user.id] = player
def leave_game(self, user, chat): def leave_game(self, user, chat):

View file

@ -167,17 +167,20 @@ class Player(object):
self.logger.debug("Card's color or value doesn't match") self.logger.debug("Card's color or value doesn't match")
is_playable = False is_playable = False
elif last.value == c.DRAW_TWO and not \ elif last.value == c.DRAW_TWO and not \
card.value == c.DRAW_TWO and self.game.draw_counter: (card.value == c.DRAW_TWO or card.special == c.DRAW_FOUR) and self.game.draw_counter:
self.logger.debug("Player has to draw and can't counter") self.logger.debug("Player has to draw and can't counter")
is_playable = False is_playable = False
elif last.special == c.DRAW_FOUR and self.game.draw_counter: elif last.special == c.DRAW_FOUR and self.game.draw_counter and not card.special == c.DRAW_FOUR:
self.logger.debug("Player has to draw and can't counter") self.logger.debug("Player has to draw and can't counter")
is_playable = False is_playable = False
elif (last.special == c.CHOOSE or last.special == c.DRAW_FOUR) and \ elif (last.special == c.CHOOSE) and \
(card.special == c.CHOOSE or card.special == c.DRAW_FOUR): (card.special == c.CHOOSE or card.special == c.DRAW_FOUR) or \
(last.special == c.DRAW_FOUR and card.special == c.CHOOSE):
self.logger.debug("Can't play colorchooser on another one") self.logger.debug("Can't play colorchooser on another one")
is_playable = False is_playable = False
elif not last.color: # Pervent game locks by choose colors.
# When player is going leave and he didn't selected a color, it cause game locks.
elif not last.color and not (last.special == c.CHOOSE or last.special == c.DRAW_FOUR):
self.logger.debug("Last card has no color") self.logger.debug("Last card has no color")
is_playable = False is_playable = False

202
test_player.py Normal file
View file

@ -0,0 +1,202 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Telegram bot to play UNO in group chats
# Copyright (c) 2016 Jannes Höke <uno@jhoeke.de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
import telegram
from game import Game
from player import Player
import card as c
import logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.DEBUG)
logger = logging.getLogger(__name__)
class Test(unittest.TestCase):
game = None
def setUp(self):
self.game = Game(None)
def test_insert(self):
p0 = Player(self.game, "Player 0")
p1 = Player(self.game, "Player 1")
p2 = Player(self.game, "Player 2")
self.assertEqual(p0, p2.next)
self.assertEqual(p1, p0.next)
self.assertEqual(p2, p1.next)
self.assertEqual(p0.prev, p2)
self.assertEqual(p1.prev, p0)
self.assertEqual(p2.prev, p1)
def test_reverse(self):
p0 = Player(self.game, "Player 0")
p1 = Player(self.game, "Player 1")
p2 = Player(self.game, "Player 2")
self.game.reverse()
p3 = Player(self.game, "Player 3")
self.assertEqual(p0, p3.next)
self.assertEqual(p1, p2.next)
self.assertEqual(p2, p0.next)
self.assertEqual(p3, p1.next)
self.assertEqual(p0, p2.prev)
self.assertEqual(p1, p3.prev)
self.assertEqual(p2, p1.prev)
self.assertEqual(p3, p0.prev)
def test_leave(self):
p0 = Player(self.game, "Player 0")
p1 = Player(self.game, "Player 1")
p2 = Player(self.game, "Player 2")
p1.leave()
self.assertEqual(p0, p2.next)
self.assertEqual(p2, p0.next)
def test_draw(self):
p = Player(self.game, "Player 0")
deck_before = len(self.game.deck.cards)
top_card = self.game.deck.cards[-1]
p.draw()
self.assertEqual(top_card, p.cards[-1])
self.assertEqual(deck_before, len(self.game.deck.cards) + 1)
def test_draw_two(self):
p = Player(self.game, "Player 0")
deck_before = len(self.game.deck.cards)
self.game.draw_counter = 2
p.draw()
self.assertEqual(deck_before, len(self.game.deck.cards) + 2)
def test_playable_cards_simple(self):
p = Player(self.game, "Player 0")
self.game.last_card = c.Card(c.RED, '5')
p.cards = [c.Card(c.RED, '0'), c.Card(c.RED, '5'), c.Card(c.BLUE, '0'),
c.Card(c.GREEN, '5'), c.Card(c.GREEN, '8')]
expected = [c.Card(c.RED, '0'), c.Card(c.RED, '5'),
c.Card(c.GREEN, '5')]
self.assertListEqual(p.playable_cards(), expected)
def test_playable_cards_on_draw_two(self):
p = Player(self.game, "Player 0")
self.game.last_card = c.Card(c.RED, c.DRAW_TWO)
self.game.draw_counter = 2
p.cards = [c.Card(c.RED, c.DRAW_TWO), c.Card(c.RED, '5'),
c.Card(c.BLUE, '0'), c.Card(c.GREEN, '5'),
c.Card(c.GREEN, c.DRAW_TWO)]
expected = [c.Card(c.RED, c.DRAW_TWO), c.Card(c.GREEN, c.DRAW_TWO)]
self.assertListEqual(p.playable_cards(), expected)
def test_playable_cards_on_draw_two_then_four(self):
p = Player(self.game, "Player 0")
self.game.last_card = c.Card(c.RED, c.DRAW_TWO)
self.game.draw_counter = 2
p.cards = [c.Card(c.RED, c.DRAW_TWO), c.Card(c.RED, '5'),
c.Card(c.BLUE, '0'), c.Card(c.GREEN, '5'),
c.Card(c.GREEN, c.DRAW_TWO),
c.Card(None, None, c.DRAW_FOUR)]
expected = [c.Card(c.RED, c.DRAW_TWO), c.Card(c.GREEN, c.DRAW_TWO), c.Card(None, None, c.DRAW_FOUR)]
self.assertListEqual(p.playable_cards(), expected)
def test_playable_cards_on_draw_four(self):
p = Player(self.game, "Player 0")
self.game.last_card = c.Card(c.RED, None, c.DRAW_FOUR)
self.game.draw_counter = 4
p.cards = [c.Card(c.RED, c.DRAW_TWO), c.Card(c.RED, '5'),
c.Card(c.BLUE, '0'), c.Card(c.GREEN, '5'),
c.Card(c.GREEN, c.DRAW_TWO),
c.Card(None, None, c.DRAW_FOUR),
c.Card(None, None, c.CHOOSE)]
expected = [c.Card(None, None, c.DRAW_FOUR)]
self.assertListEqual(p.playable_cards(), expected)
# def test_playable_cards_on_draw_four_then_four(self):
# p = Player(self.game, "Player 0")
# self.game.last_card = c.Card(c.RED, None, c.DRAW_FOUR)
# self.game.draw_counter = 4
# p.cards = [c.Card(c.RED, c.DRAW_TWO), c.Card(c.RED, '5'),
# c.Card(c.BLUE, '0'), c.Card(c.GREEN, '5'),
# c.Card(c.GREEN, c.DRAW_TWO),
# c.Card(None, None, c.DRAW_FOUR)]
# expected = [c.Card(None, None, c.DRAW_FOUR)]
# self.assertListEqual(p.playable_cards(), expected)
def test_bluffing(self):
p = Player(self.game, "Player 0")
Player(self.game, "Player 01")
self.game.last_card = c.Card(c.RED, '1')
p.cards = [c.Card(c.RED, c.DRAW_TWO), c.Card(c.RED, '5'),
c.Card(c.BLUE, '0'), c.Card(c.GREEN, '5'),
c.Card(c.RED, '5'), c.Card(c.GREEN, c.DRAW_TWO),
c.Card(None, None, c.DRAW_FOUR),
c.Card(None, None, c.CHOOSE)]
p.playable_cards()
self.assertTrue(p.bluffing)
p.cards = [c.Card(c.BLUE, '1'), c.Card(c.GREEN, '1'),
c.Card(c.GREEN, c.DRAW_TWO),
c.Card(None, None, c.DRAW_FOUR),
c.Card(None, None, c.CHOOSE)]
p.playable_cards()
p.play(c.Card(None, None, c.DRAW_FOUR))
self.game.choose_color(c.GREEN)
self.assertFalse(self.game.current_player.prev.bluffing)
if __name__ == '__main__':
unittest.main()