separate game logic from bot interface,
introduce exceptions instead of boolean returns, remove repetitive code, begin unit tests, improve docstrings, update to python-telegram-bot==4.1.1, add ponyorm settings classes (unused)
This commit is contained in:
115
game_manager.py
115
game_manager.py
@ -21,6 +21,8 @@ import logging
|
||||
|
||||
from game import Game
|
||||
from player import Player
|
||||
from errors import (AlreadyJoinedError, LobbyClosedError, NoGameInChatError,
|
||||
NotEnoughPlayersError)
|
||||
|
||||
|
||||
class GameManager(object):
|
||||
@ -38,7 +40,7 @@ class GameManager(object):
|
||||
"""
|
||||
chat_id = chat.id
|
||||
|
||||
self.logger.info("Creating new game with id " + str(chat_id))
|
||||
self.logger.debug("Creating new game in chat " + str(chat_id))
|
||||
game = Game(chat)
|
||||
|
||||
if chat_id not in self.chatid_games:
|
||||
@ -47,13 +49,17 @@ class GameManager(object):
|
||||
self.chatid_games[chat_id].append(game)
|
||||
return game
|
||||
|
||||
def join_game(self, chat_id, user):
|
||||
def join_game(self, user, chat):
|
||||
""" Create a player from the Telegram user and add it to the game """
|
||||
self.logger.info("Joining game with id " + str(chat_id))
|
||||
self.logger.info("Joining game with id " + str(chat.id))
|
||||
|
||||
try:
|
||||
game = self.chatid_games[chat_id][-1]
|
||||
game = self.chatid_games[chat.id][-1]
|
||||
except (KeyError, IndexError):
|
||||
return None
|
||||
raise NoGameInChatError()
|
||||
|
||||
if not game.open:
|
||||
raise LobbyClosedError()
|
||||
|
||||
if user.id not in self.userid_players:
|
||||
self.userid_players[user.id] = list()
|
||||
@ -61,76 +67,81 @@ class GameManager(object):
|
||||
players = self.userid_players[user.id]
|
||||
|
||||
# Don not re-add a player and remove the player from previous games in
|
||||
# this chat
|
||||
# this chat, if he is in one of them
|
||||
for player in players:
|
||||
if player in game.players:
|
||||
return False
|
||||
raise AlreadyJoinedError()
|
||||
else:
|
||||
self.leave_game(user, chat_id)
|
||||
try:
|
||||
self.leave_game(user, chat)
|
||||
except NoGameInChatError:
|
||||
pass
|
||||
|
||||
player = Player(game, user)
|
||||
|
||||
players.append(player)
|
||||
self.userid_current[user.id] = player
|
||||
return True
|
||||
|
||||
def leave_game(self, user, chat_id):
|
||||
def leave_game(self, user, chat):
|
||||
""" Remove a player from its current game """
|
||||
try:
|
||||
players = self.userid_players[user.id]
|
||||
games = self.chatid_games[chat_id]
|
||||
|
||||
for player in players:
|
||||
for game in games:
|
||||
if player in game.players:
|
||||
if player is game.current_player:
|
||||
game.turn()
|
||||
player = self.player_for_user_in_chat(user, chat)
|
||||
players = self.userid_players.get(user.id, list())
|
||||
|
||||
player.leave()
|
||||
players.remove(player)
|
||||
if not player:
|
||||
raise NoGameInChatError
|
||||
|
||||
# If this is the selected game, switch to another
|
||||
if self.userid_current[user.id] is player:
|
||||
if len(players):
|
||||
self.userid_current[user.id] = players[0]
|
||||
else:
|
||||
del self.userid_current[user.id]
|
||||
return True
|
||||
game = player.game
|
||||
|
||||
if len(game.players) < 3:
|
||||
raise NotEnoughPlayersError()
|
||||
|
||||
if player is game.current_player:
|
||||
game.turn()
|
||||
|
||||
player.leave()
|
||||
players.remove(player)
|
||||
|
||||
# If this is the selected game, switch to another
|
||||
if self.userid_current.get(user.id, None) is player:
|
||||
if players:
|
||||
self.userid_current[user.id] = players[0]
|
||||
else:
|
||||
return False
|
||||
del self.userid_current[user.id]
|
||||
del self.userid_players[user.id]
|
||||
|
||||
except KeyError:
|
||||
return False
|
||||
|
||||
def end_game(self, chat_id, user):
|
||||
def end_game(self, chat, user):
|
||||
"""
|
||||
End a game
|
||||
"""
|
||||
|
||||
self.logger.info("Game in chat " + str(chat_id) + " ended")
|
||||
players = self.userid_players[user.id]
|
||||
games = self.chatid_games[chat_id]
|
||||
the_game = None
|
||||
self.logger.info("Game in chat " + str(chat.id) + " ended")
|
||||
|
||||
# Find the correct game instance to end
|
||||
for player in players:
|
||||
for game in games:
|
||||
if player in game.players:
|
||||
the_game = game
|
||||
break
|
||||
if the_game:
|
||||
break
|
||||
else:
|
||||
return
|
||||
player = self.player_for_user_in_chat(user, chat)
|
||||
|
||||
for player in the_game.players:
|
||||
if not player:
|
||||
raise NoGameInChatError
|
||||
|
||||
game = player.game
|
||||
|
||||
# Clear game
|
||||
for player_in_game in game.players:
|
||||
this_users_players = self.userid_players[player.user.id]
|
||||
this_users_players.remove(player)
|
||||
if len(this_users_players) is 0:
|
||||
this_users_players.remove(player_in_game)
|
||||
|
||||
if this_users_players:
|
||||
self.userid_current[player.user.id] = this_users_players[0]
|
||||
else:
|
||||
del self.userid_players[player.user.id]
|
||||
del self.userid_current[player.user.id]
|
||||
else:
|
||||
self.userid_current[player.user.id] = this_users_players[0]
|
||||
|
||||
self.chatid_games[chat_id].remove(the_game)
|
||||
return
|
||||
self.chatid_games[chat.id].remove(game)
|
||||
|
||||
def player_for_user_in_chat(self, user, chat):
|
||||
players = self.userid_players.get(user.id, list())
|
||||
for player in players:
|
||||
if player.game.chat.id == chat.id:
|
||||
return player
|
||||
else:
|
||||
return None
|
||||
|
Reference in New Issue
Block a user