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:
parent
284eb91633
commit
615bb35359
5 changed files with 228 additions and 12 deletions
10
bot.py
10
bot.py
|
@ -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:
|
||||||
|
|
1
game.py
1
game.py
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
# Randomize player position.
|
||||||
|
game.joined_before.append(user.id)
|
||||||
|
if len(players) > 2:
|
||||||
|
players.insert(random.randrange(len(players)), player)
|
||||||
|
else:
|
||||||
players.append(player)
|
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):
|
||||||
|
|
13
player.py
13
player.py
|
@ -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
202
test_player.py
Normal 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()
|
Loading…
Reference in a new issue