class ScrabbleGame: ''' ScrabbleGame class. Keeps track of the players in the game, the letters and the moves played. ''' def __init__(self, name='', options=None): ''' Initialize a new game. @param name: Game ID ''' if not options: options = {} self.players = [] self.name = name self.started = False self.paused = False self.complete = False self.moves = [] self.words = [] self.usedModifiers = [] self.passedMoves = 0 self.currentPlayer = None self.spectators = [] self.spectatorChatEnabled = True self.log = [] self.pending = [] self.stats = {} # Allow older versions to create games too by setting theese keys self.options = { OPTION_NO_REPEATS: False, OPTION_FINAL_LETTER: True, OPTION_LONG_WORD_BONUS: False } self.options.update(options) self.bag = Bag(rules=options[OPTION_RULES]) self.creator = None self.timer = None self.spectatorsAllowed = True def getDistribution(self): ''' Get Letter distribution @return: dict(Letter,Count) ''' return self.bag.getDistribution() def isBagEmpty(self): ''' Check if the letter bag is empty @return: True if the Bag is empty ''' return self.bag.isEmpty() def addUsedModifier(self, pos): ''' Add a used modifier to the list. These are word or letter modifiers that we have already used. @param pos: (x,y) position ''' self.usedModifiers.append(pos) def hasUsedModifier(self, pos): ''' Check to see if we've used a modifier @param pos: (x,y) position ''' return pos in self.usedModifiers def getLetters(self, numLetters): ''' Get letters from the bag @param numLetters: Number of letters to get @return: List of Letters or [] if there or no letters left @see: L{pyscrabble.game.pieces.Letter} ''' try: return self.bag.getLetters(numLetters) except BagEmptyException: pass return [] def addPlayer(self, player): ''' Add a player to the game @param player: Player to add to the game @see: L{pyscrabble.game.player.Player} ''' self.players.append(player) def getGameId(self): ''' Get the Game ID @return: Game ID of this game ''' return self.name def getNumberOfPlayers(self): ''' Get number of players in the game @return: Number of players in the game ''' return len(self.players) def isStarted(self): ''' Check if the game is started. @return: True if the game is started and unpaused. ''' if (self.isPaused()): return False return self.started def isComplete(self): ''' Check if the game is complete. The game is complete when all players cannot make a move and have to pass. @return: True if the game is complete. ''' return self.complete def start(self): ''' Start the game. ''' self.started = True shuffle(self.players) def getCurrentPlayer(self): ''' Get current player @return: Player who has control of the board. @see: L{pyscrabble.game.player.Player} ''' return self.currentPlayer def getNextPlayer(self): ''' Get the next player who has control of the board. @return: Next Player who has control of the board. @see: L{pyscrabble.game.player.Player} ''' if (len(self.players) == 0): return None self.currentPlayer = self.players.pop(0) self.players.append(self.currentPlayer) return self.currentPlayer def getPlayers(self): ''' Return a copy of the list of Players @return: List of Players @see: L{pyscrabble.game.player.Player} ''' return self.players[:] def hasPlayer(self, player): ''' Check to see if a player is in the game @param player: Player @return: True if player is in the game @see: L{pyscrabble.game.player.Player} ''' return player in self.players def playerLeave(self, player): ''' Remove a player from the game and return his/her Letters to the bag @param player: Player to remove @see: L{pyscrabble.game.player.Player} @see: L{pyscrabble.game.pieces.Letter} ''' self.players.remove(player) self.returnLetters(player.getLetters()) def addMoves(self, moves, player): ''' Add a move to the board @param moves: Moves to add to the board @param player: Player who added the move @see: L{pyscrabble.game.pieces.Move} ''' self.passedMoves = 0 # Rest pass counter score = 0 allDisp = '' for move in moves: word = move.getWord() score = score + move.getScore() self.words.append(word) self.moves.append(move) newdisp = '%s (%s) by %s' % (word, str( move.getScore()), player.getUsername()) if self.stats.has_key(STAT_HIGHEST_SCORING_WORD): data, disp = self.stats[STAT_HIGHEST_SCORING_WORD] if (move.getScore() > data.getScore()): self.stats[STAT_HIGHEST_SCORING_WORD] = move, newdisp else: self.stats[STAT_HIGHEST_SCORING_WORD] = move, newdisp newdisp = '%s (%s) by %s' % (word, str( move.length()), player.getUsername()) if self.stats.has_key(STAT_LONGEST_WORD): data, disp = self.stats[STAT_LONGEST_WORD] if (move.length() > data.length()): self.stats[STAT_LONGEST_WORD] = move, newdisp else: self.stats[STAT_LONGEST_WORD] = move, newdisp allDisp = allDisp + '%s (%s) ' % (word, str(move.getScore())) allDisp = allDisp + 'by %s' % player.getUsername() d = allDisp d = '%s, ' % str(score) + d if self.stats.has_key(STAT_HIGHEST_SCORING_MOVE): data, disp = self.stats[STAT_HIGHEST_SCORING_MOVE] if score > data: self.stats[STAT_HIGHEST_SCORING_MOVE] = score, d else: self.stats[STAT_HIGHEST_SCORING_MOVE] = score, d d = allDisp d = '%s, ' % str(len(moves)) + d if self.stats.has_key(STAT_MOST_WORDS_IN_MOVE): data, disp = self.stats[STAT_MOST_WORDS_IN_MOVE] if len(moves) > data: self.stats[STAT_MOST_WORDS_IN_MOVE] = len(moves), d else: self.stats[STAT_MOST_WORDS_IN_MOVE] = len(moves), d def getMoves(self): ''' Return List of moves on the board @return: List of moves on the board @see: L{pyscrabble.game.pieces.Move} ''' return self.moves def hasWord(self, word): ''' Check to see if a word is on the board @param word: Word to check @return: True if the word is on the board. ''' return word in self.words def resetPassCount(self): ''' Reset the pass counter ''' self.passedMoves = 0 def passMove(self): ''' Pass a move. If the number of passed moves is equal to the number of players, all players have passed their moves and the game is over. @raise GameOverException: If all players have passed their moves and the game is over. ''' self.passedMoves = self.passedMoves + 1 if (self.passedMoves == len(self.players)): raise GameOverException def getWinners(self, exclude=None): ''' Return the player(s) with the highest score @param exclude: Player to exclude from winning (say, if they timed out) @return: List of players with the highest score. @see: L{pyscrabble.game.player.Player} ''' tmp = self.players[:] if exclude is not None: tmp.remove(exclude) maxScore = None for player in tmp: maxScore = max(maxScore, player.getScore()) winners = [] for player in tmp: if player.getScore() == maxScore: winners.append(player) return winners def pause(self): ''' Pause the game. ''' self.paused = True self.players.remove(self.currentPlayer) self.players.insert(0, self.currentPlayer) for player in self.players: if player not in self.pending: self.pending.append(player) def unPause(self): ''' Unpause the game. ''' self.paused = False self.pending = [] def isPaused(self): ''' Check whether the game is paused. @return: True if the game is paused. ''' return self.paused def returnLetters(self, letters): ''' Return letters to the Bag. @param letters: Letters to put back in the back @see: L{pyscrabble.game.pieces.Letter} @see: L{pyscrabble.game.pieces.Bag} ''' self.bag.returnLetters(letters) def isInProgress(self): ''' Check whether the game is started. The game is considered in progress even if it is paused. @return: True if the game has been started. ''' return self.started def getPlayer(self, player): ''' Get a player out of the game @param player: Player @return: Player in the game, or None if player is not in the game. @see: L{pyscrabble.game.player.Player} ''' for _player in self.players: if player.getUsername() == _player.getUsername(): return _player return None def isCurrentPlayer(self, player): ''' Check to see if C{player} is the current player @param player: Player to checl @return: True if C{player} is the current player. ''' return self.currentPlayer == player def addSpectator(self, spectator): ''' Add a spectator to the game @param spectator: Spectator name ''' self.spectators.append(spectator) def getSpectators(self): ''' Return a copy of the list of spectors @return: List of Spectator names ''' return self.spectators[:] def spectatorLeave(self, spectator): ''' Remove a spectator from the game @param spectator: Spectator to remove ''' self.spectators.remove(spectator) def hasSpectator(self, spectator): ''' Check to see if a spectator is in the game @param spectator: Spectator @return: True if spectator is in the game ''' return spectator in self.spectators def isSpectatorChatEnabled(self): ''' Check if Spectator Chat is Enabled @return: True if Spectator Chat is enabled for this game ''' return self.spectatorChatEnabled def setSpectatorChatEnabled(self, flag): ''' Set Spectator Chat Enabled/Disabled @param flag: True to enable Spectator Chat ''' self.spectatorChatEnabled = flag def isSpectatorsAllowed(self): ''' Check if Spectator Chat is Enabled @return: True if Spectator Chat is enabled for this game ''' return self.spectatorsAllowed def setSpectatorsAllowed(self, flag): ''' Set Spectators Allowed @param flag: True to allow spectators ''' self.spectatorsAllowed = flag def setComplete(self): ''' Mark this game as complete ''' self.complete = True def appendLogMessage(self, log): ''' Add logging information Log is a tuple: (level, message) @param log: Log Message tuple ''' self.log.append(log) def getLog(self): ''' Retrieve log Log is a list of tuples: (level, message) @return: Game Log ''' return self.log[:] def getPending(self): ''' Get list of players pending to join the game @return: List of players still pending to re-join a paused game ''' return self.pending def removePending(self, player): ''' Remove a player from the pending list @param player: Player ''' self.pending.remove(player) def addPending(self, player): ''' Add pending player @param player: Player ''' if player not in self.pending: self.pending.append(player) def getStats(self): ''' Retrieve list of game stats @return: List of tuples (stat_name, stat_value) ''' s = [] s.append( (ServerMessage([STAT_LETTERS_LEFT]), str(self.bag.getCount()))) for key, value in self.stats.iteritems(): data, disp = value s.append((ServerMessage([key]), disp)) return s def getOptions(self): ''' Return list of options @return: List of tuples (option_name, option_value) ''' s = [] s.append((ServerMessage([CREATOR]), self.creator)) for key, value in self.options.iteritems(): if key in (OPTION_TIMED_GAME, OPTION_TIMED_LIMIT, OPTION_MOVE_TIME): if value == int(1): s.append( (ServerMessage([key]), ServerMessage([value, MINUTE]))) else: s.append( (ServerMessage([key]), ServerMessage([value, MINUTES]))) else: s.append((ServerMessage([key]), ServerMessage([value]))) return s def getCountLetters(self): ''' Return the number of letters left in the bag @return: Count of letters left in bag ''' return self.bag.getCount()
class ScrabbleGame: ''' ScrabbleGame class. Keeps track of the players in the game, the letters and the moves played. ''' def __init__(self, name='', options=None): ''' Initialize a new game. @param name: Game ID ''' self.players = [] self.name = name self.started = False self.paused = False self.complete = False self.moves = [] self.words = [] self.usedModifiers = [] self.passedMoves = 0 self.currentPlayer = None self.log = [] self.pending = [] self.bag = Bag(rules='en') self.creator = None self.timer = None self.spectatorsAllowed = True def getDistribution(self): ''' Get Letter distribution @return: dict(Letter,Count) ''' return self.bag.getDistribution() def isBagEmpty(self): ''' Check if the letter bag is empty @return: True if the Bag is empty ''' return self.bag.isEmpty() def addUsedModifier(self, pos): ''' Add a used modifier to the list. These are word or letter modifiers that we have already used. @param pos: (x,y) position ''' self.usedModifiers.append(pos) def hasUsedModifier(self, pos): ''' Check to see if we've used a modifier @param pos: (x,y) position ''' return pos in self.usedModifiers def getLetters(self, numLetters): ''' Get letters from the bag @param numLetters: Number of letters to get @return: List of Letters or [] if there or no letters left @see: L{pyscrabble.game.pieces.Letter} ''' try: return self.bag.getLetters(numLetters) except BagEmptyException: pass return [] def addPlayer(self, player): ''' Add a player to the game @param player: Player to add to the game @see: L{pyscrabble.game.player.Player} ''' self.players.append(player) def getGameId(self): ''' Get the Game ID @return: Game ID of this game ''' return self.name def getNumberOfPlayers(self): ''' Get number of players in the game @return: Number of players in the game ''' return len(self.players) def isStarted(self): ''' Check if the game is started. @return: True if the game is started and unpaused. ''' if (self.isPaused()): return False return self.started def isComplete(self): ''' Check if the game is complete. The game is complete when all players cannot make a move and have to pass. @return: True if the game is complete. ''' return self.complete def start(self): ''' Start the game. ''' self.started = True shuffle(self.players) def getCurrentPlayer(self): ''' Get current player @return: Player who has control of the board. @see: L{pyscrabble.game.player.Player} ''' return self.currentPlayer def getNextPlayer(self): ''' Get the next player who has control of the board. @return: Next Player who has control of the board. @see: L{pyscrabble.game.player.Player} ''' if (len(self.players) == 0): return None self.currentPlayer = self.players.pop(0) self.players.append(self.currentPlayer) return self.currentPlayer def getPlayers(self): ''' Return a copy of the list of Players @return: List of Players @see: L{pyscrabble.game.player.Player} ''' return self.players[:] def hasPlayer(self, player): ''' Check to see if a player is in the game @param player: Player @return: True if player is in the game @see: L{pyscrabble.game.player.Player} ''' return player in self.players def playerLeave(self, player): ''' Remove a player from the game and return his/her Letters to the bag @param player: Player to remove @see: L{pyscrabble.game.player.Player} @see: L{pyscrabble.game.pieces.Letter} ''' self.players.remove(player) self.returnLetters(player.getLetters()) def addMoves(self, moves, player): ''' Add a move to the board @param moves: Moves to add to the board @param player: Player who added the move @see: L{pyscrabble.game.pieces.Move} ''' self.passedMoves = 0 # Rest pass counter score = 0 for move in moves: word = move.getWord() score = score + move.getScore() self.words.append(word) self.moves.append(move) def getMoves(self): ''' Return List of moves on the board @return: List of moves on the board @see: L{pyscrabble.game.pieces.Move} ''' return self.moves def hasWord(self, word): ''' Check to see if a word is on the board @param word: Word to check @return: True if the word is on the board. ''' return word in self.words def resetPassCount(self): ''' Reset the pass counter ''' self.passedMoves = 0 def passMove(self): ''' Pass a move. If the number of passed moves is equal to the number of players, all players have passed their moves and the game is over. @raise GameOverException: If all players have passed their moves and the game is over. ''' self.passedMoves = self.passedMoves + 1 if (self.passedMoves == len(self.players)): raise GameOverException def getWinners(self, exclude=None): ''' Return the player(s) with the highest score @param exclude: Player to exclude from winning (say, if they timed out) @return: List of players with the highest score. @see: L{pyscrabble.game.player.Player} ''' tmp = self.players[:] if exclude is not None: tmp.remove(exclude) maxScore = None for player in tmp: maxScore = max(maxScore, player.getScore()) winners = [] for player in tmp: if player.getScore() == maxScore: winners.append(player) return winners def pause(self): ''' Pause the game. ''' self.paused = True self.players.remove(self.currentPlayer) self.players.insert(0, self.currentPlayer) for player in self.players: if player not in self.pending: self.pending.append(player) def unPause(self): ''' Unpause the game. ''' self.paused = False self.pending = [] def isPaused(self): ''' Check whether the game is paused. @return: True if the game is paused. ''' return self.paused def returnLetters(self, letters): ''' Return letters to the Bag. @param letters: Letters to put back in the back @see: L{pyscrabble.game.pieces.Letter} @see: L{pyscrabble.game.pieces.Bag} ''' self.bag.returnLetters(letters) def isInProgress(self): ''' Check whether the game is started. The game is considered in progress even if it is paused. @return: True if the game has been started. ''' return self.started def getPlayer(self, player): ''' Get a player out of the game @param player: Player @return: Player in the game, or None if player is not in the game. @see: L{pyscrabble.game.player.Player} ''' for _player in self.players: if player.getUsername() == _player.getUsername(): return _player return None def isCurrentPlayer(self, player): ''' Check to see if C{player} is the current player @param player: Player to checl @return: True if C{player} is the current player. ''' return self.currentPlayer == player def setComplete(self): ''' Mark this game as complete ''' self.complete = True def appendLogMessage(self, log): ''' Add logging information Log is a tuple: (level, message) @param log: Log Message tuple ''' self.log.append(log) def getLog(self): ''' Retrieve log Log is a list of tuples: (level, message) @return: Game Log ''' return self.log[:] def getPending(self): ''' Get list of players pending to join the game @return: List of players still pending to re-join a paused game ''' return self.pending def removePending(self, player): ''' Remove a player from the pending list @param player: Player ''' self.pending.remove(player) def addPending(self, player): ''' Add pending player @param player: Player ''' if player not in self.pending: self.pending.append(player) def getCountLetters(self): ''' Return the number of letters left in the bag @return: Count of letters left in bag ''' return self.bag.getCount()
class ScrabbleGame: ''' ScrabbleGame class. Keeps track of the players in the game, the letters and the moves played. ''' def __init__(self, name='', options=None): ''' Initialize a new game. @param name: Game ID ''' self.name = name self.players = DStringList() DStringList.Map(self.players, "game:" + name + ":players") self.started = DBoolean() DBoolean.Map(self.started, "game:" + name + ":started") self.complete = DBoolean() DBoolean.Map(self.complete, "game:" + name + ":complete") self.moves = [] self.words = [] self.usedModifiers = [] self.passedMoves = DLong() DLong.Map(self.passedMoves, "game:" + name + ":passedmoves") self.currentPlayer = DString() DString.Map(self.currentPlayer, "game:" + name + ":currentplayer") self.log = [] self.bag = Bag(self.name, rules='en') self.creator = DString() DString.Map(self.creator, "game:" + name + ":creator") self.timer = None self.spectatorsAllowed = True self.onboardLetters = DStringList() DStringList.Map(self.onboardLetters, "game:" + name + ":onboardletters") self.onboardLetterScores = DList() DList.Map(self.onboardLetterScores, "game:" + name + ":onboardletterscores") self.onboardX = DList() DList.Map(self.onboardX, "game:" + name + ":onboardx") self.onboardY = DList() DList.Map(self.onboardY, "game:" + name + ":onboardy") def reset(self): for player in self.getPlayers(): player.reset() self.setCreator("") self.currentPlayer.Set("") self.started.Set(False) self.complete.Set(False) self.players.Clear() self.bag.reset(rules='en') self.passedMoves.Set(0) self.clearOnboardMove() empty = DBoolean() DBoolean.Map(empty, "game:" + self.name + ":board:empty") empty.Set(True) for x in range(0, 15): for y in range(0, 15): letterPresent = DBoolean() DBoolean.Map( letterPresent, "game:" + self.name + ":tile:" + repr(y * BOARD_WIDTH + x) + ":letterPresent") letterPresent.Set(False) def setCreator(self, playerName): self.creator.Set(playerName) def getCreator(self): return self.creator.Value() def getOnboardMove(self): result = Move() for i in range(0, self.onboardLetters.Size()): result.addMove( Letter(self.onboardLetters.Value(i), self.onboardLetterScores.Value(i)), self.onboardX.Value(i), self.onboardY.Value(i)) return result def clearOnboardMove(self): self.onboardLetters.Clear() self.onboardLetterScores.Clear() self.onboardX.Clear() self.onboardY.Clear() def removeFromOnboard(self, letter, x, y): index = -1 for i in range(0, self.onboardLetters.Size()): if self.onboardLetters.Value(i) == letter.getLetter( ) and self.onboardX.Value(i) == x and self.onboardY.Value(i) == y: index = i if index != -1: self.onboardLetters.Erase(index) self.onboardLetterScores.Erase(index) self.onboardX.Erase(index) self.onboardY.Erase(index) def addToOnboard(self, letter, x, y): self.onboardLetters.Append(letter.getLetter()) self.onboardLetterScores.Append(letter.getScore()) self.onboardX.Append(x) self.onboardY.Append(y) def getName(self): return self.name def getStatus(self): if (self.isStarted()): status = ServerMessage([STATUS_STARTED]) else: status = ServerMessage([NOT_STARTED]) if (self.isComplete()): status = ServerMessage([COMPLETE]) return status def getDistribution(self): ''' Get Letter distribution @return: dict(Letter,Count) ''' return self.bag.getDistribution() def isBagEmpty(self): ''' Check if the letter bag is empty @return: True if the Bag is empty ''' return self.bag.isEmpty() def addUsedModifier(self, pos): ''' Add a used modifier to the list. These are word or letter modifiers that we have already used. @param pos: (x,y) position ''' self.usedModifiers.append(pos) def hasUsedModifier(self, pos): ''' Check to see if we've used a modifier @param pos: (x,y) position ''' return pos in self.usedModifiers def getLetters(self, numLetters): ''' Get letters from the bag @param numLetters: Number of letters to get @return: List of Letters or [] if there or no letters left @see: L{pyscrabble.game.pieces.Letter} ''' try: return self.bag.getLetters(numLetters) except BagEmptyException: pass return [] def addPlayer(self, player): ''' Add a player to the game @param player: Player to add to the game @see: L{pyscrabble.game.player.Player} ''' self.players.Append(player.getUsername()) def getGameId(self): ''' Get the Game ID @return: Game ID of this game ''' return self.name def getNumberOfPlayers(self): ''' Get number of players in the game @return: Number of players in the game ''' return self.players.Size() def isStarted(self): ''' Check if the game is started. @return: True if the game is started and unpaused. ''' return self.started.Value() def isComplete(self): ''' Check if the game is complete. The game is complete when all players cannot make a move and have to pass. @return: True if the game is complete. ''' return self.complete.Value() def start(self): ''' Start the game. ''' self.started.Set(True) indices = range(0, self.players.Size()) shuffle(indices) tempPlayers = [] for playerName in self.players.Members(): tempPlayers.append(playerName) self.players.Clear() for index in indices: self.players.Append(tempPlayers[index]) def getCurrentPlayer(self): ''' Get current player @return: Player who has control of the board. @see: L{pyscrabble.game.player.Player} ''' return Player(self.currentPlayer.Value()) def getNextPlayer(self): ''' Get the next player who has control of the board. @return: Next Player who has control of the board. @see: L{pyscrabble.game.player.Player} ''' if (self.players.Size() == 0): return None self.currentPlayer.Set(self.players.Value(0)) self.players.Erase(0) self.players.Append(self.currentPlayer.Value()) return Player(self.currentPlayer.Value()) def getPlayers(self): ''' Return a copy of the list of Players @return: List of Players @see: L{pyscrabble.game.player.Player} ''' #return self.players.Members() result = [] for playerName in self.players.Members(): result.append(Player(playerName, self.name)) return result def hasPlayer(self, player): ''' Check to see if a player is in the game @param player: Player @return: True if player is in the game @see: L{pyscrabble.game.player.Player} ''' return player.getUsername() in self.players.Members() def playerLeave(self, player): ''' Remove a player from the game and return his/her Letters to the bag @param player: Player to remove @see: L{pyscrabble.game.player.Player} @see: L{pyscrabble.game.pieces.Letter} ''' self.players.Remove(player.getUsername()) self.returnLetters(player.getLetters()) if self.getNumberOfPlayers() == 0: self.reset() globalGamesSet = DStringSet() DStringSet.Map(globalGamesSet, "global:games") globalGamesSet.Remove(self.name) def addMoves(self, moves, player): ''' Add a move to the board @param moves: Moves to add to the board @param player: Player who added the move @see: L{pyscrabble.game.pieces.Move} ''' self.passedMoves.Set(0) # Rest pass counter #TODO score = 0 for move in moves: word = move.getWord() score = score + move.getScore() self.words.append(word) self.moves.append(move) def getMoves(self): ''' Return List of moves on the board @return: List of moves on the board @see: L{pyscrabble.game.pieces.Move} ''' return self.moves def hasWord(self, word): ''' Check to see if a word is on the board @param word: Word to check @return: True if the word is on the board. ''' return word in self.words def resetPassCount(self): ''' Reset the pass counter ''' self.passedMoves.Set(0) def passMove(self): ''' Pass a move. If the number of passed moves is equal to the number of players, all players have passed their moves and the game is over. @raise GameOverException: If all players have passed their moves and the game is over. ''' self.passedMoves.Set(self.passedMoves.Value() + 1) if (self.passedMoves.Value() == self.players.Size()): raise GameOverException def getWinners(self, exclude=None): ''' Return the player(s) with the highest score @param exclude: Player to exclude from winning (say, if they timed out) @return: List of players with the highest score. @see: L{pyscrabble.game.player.Player} ''' tmp = self.players[:] if exclude is not None: tmp.remove(exclude) maxScore = None for player in tmp: maxScore = max(maxScore, player.getScore()) winners = [] for player in tmp: if player.getScore() == maxScore: winners.append(player) return winners def returnLetters(self, letters): ''' Return letters to the Bag. @param letters: Letters to put back in the back @see: L{pyscrabble.game.pieces.Letter} @see: L{pyscrabble.game.pieces.Bag} ''' self.bag.returnLetters(letters) def isInProgress(self): ''' Check whether the game is started. The game is considered in progress even if it is paused. @return: True if the game has been started. ''' return self.started def getPlayer(self, player): ''' Get a player out of the game @param player: Player @return: Player in the game, or None if player is not in the game. @see: L{pyscrabble.game.player.Player} ''' for _playerName in self.players.Members(): if player.getUsername() == _playerName: return Player(_playerName, self.name) return None def isCurrentPlayer(self, player): ''' Check to see if C{player} is the current player @param player: Player to checl @return: True if C{player} is the current player. ''' return self.currentPlayer.Value() == player.getUsername() def setComplete(self): ''' Mark this game as complete ''' self.complete.Set(True) def appendLogMessage(self, log): ''' Add logging information Log is a tuple: (level, message) @param log: Log Message tuple ''' self.log.append(log) def getLog(self): ''' Retrieve log Log is a list of tuples: (level, message) @return: Game Log ''' return self.log[:] def getCountLetters(self): ''' Return the number of letters left in the bag @return: Count of letters left in bag ''' return self.bag.getCount()
class ScrabbleGame: """ ScrabbleGame class. Keeps track of the players in the game, the letters and the moves played. """ def __init__(self, name="", options=None): """ Initialize a new game. @param name: Game ID """ if not options: options = {} self.players = [] self.name = name self.started = False self.paused = False self.complete = False self.moves = [] self.words = [] self.usedModifiers = [] self.passedMoves = 0 self.currentPlayer = None self.spectators = [] self.spectatorChatEnabled = True self.log = [] self.pending = [] self.stats = {} # Allow older versions to create games too by setting theese keys self.options = {OPTION_NO_REPEATS: False, OPTION_FINAL_LETTER: True, OPTION_LONG_WORD_BONUS: False} self.options.update(options) self.bag = Bag(rules=options[OPTION_RULES]) self.creator = None self.timer = None self.spectatorsAllowed = True def getDistribution(self): """ Get Letter distribution @return: dict(Letter,Count) """ return self.bag.getDistribution() def isBagEmpty(self): """ Check if the letter bag is empty @return: True if the Bag is empty """ return self.bag.isEmpty() def addUsedModifier(self, pos): """ Add a used modifier to the list. These are word or letter modifiers that we have already used. @param pos: (x,y) position """ self.usedModifiers.append(pos) def hasUsedModifier(self, pos): """ Check to see if we've used a modifier @param pos: (x,y) position """ return pos in self.usedModifiers def getLetters(self, numLetters): """ Get letters from the bag @param numLetters: Number of letters to get @return: List of Letters or [] if there or no letters left @see: L{pyscrabble.game.pieces.Letter} """ try: return self.bag.getLetters(numLetters) except BagEmptyException: pass return [] def addPlayer(self, player): """ Add a player to the game @param player: Player to add to the game @see: L{pyscrabble.game.player.Player} """ self.players.append(player) def getGameId(self): """ Get the Game ID @return: Game ID of this game """ return self.name def getNumberOfPlayers(self): """ Get number of players in the game @return: Number of players in the game """ return len(self.players) def isStarted(self): """ Check if the game is started. @return: True if the game is started and unpaused. """ if self.isPaused(): return False return self.started def isComplete(self): """ Check if the game is complete. The game is complete when all players cannot make a move and have to pass. @return: True if the game is complete. """ return self.complete def start(self): """ Start the game. """ self.started = True shuffle(self.players) def getCurrentPlayer(self): """ Get current player @return: Player who has control of the board. @see: L{pyscrabble.game.player.Player} """ return self.currentPlayer def getNextPlayer(self): """ Get the next player who has control of the board. @return: Next Player who has control of the board. @see: L{pyscrabble.game.player.Player} """ if len(self.players) == 0: return None self.currentPlayer = self.players.pop(0) self.players.append(self.currentPlayer) return self.currentPlayer def getPlayers(self): """ Return a copy of the list of Players @return: List of Players @see: L{pyscrabble.game.player.Player} """ return self.players[:] def hasPlayer(self, player): """ Check to see if a player is in the game @param player: Player @return: True if player is in the game @see: L{pyscrabble.game.player.Player} """ return player in self.players def playerLeave(self, player): """ Remove a player from the game and return his/her Letters to the bag @param player: Player to remove @see: L{pyscrabble.game.player.Player} @see: L{pyscrabble.game.pieces.Letter} """ self.players.remove(player) self.returnLetters(player.getLetters()) def addMoves(self, moves, player): """ Add a move to the board @param moves: Moves to add to the board @param player: Player who added the move @see: L{pyscrabble.game.pieces.Move} """ self.passedMoves = 0 # Rest pass counter score = 0 allDisp = "" for move in moves: word = move.getWord() score = score + move.getScore() self.words.append(word) self.moves.append(move) newdisp = "%s (%s) by %s" % (word, str(move.getScore()), player.getUsername()) if self.stats.has_key(STAT_HIGHEST_SCORING_WORD): data, disp = self.stats[STAT_HIGHEST_SCORING_WORD] if move.getScore() > data.getScore(): self.stats[STAT_HIGHEST_SCORING_WORD] = move, newdisp else: self.stats[STAT_HIGHEST_SCORING_WORD] = move, newdisp newdisp = "%s (%s) by %s" % (word, str(move.length()), player.getUsername()) if self.stats.has_key(STAT_LONGEST_WORD): data, disp = self.stats[STAT_LONGEST_WORD] if move.length() > data.length(): self.stats[STAT_LONGEST_WORD] = move, newdisp else: self.stats[STAT_LONGEST_WORD] = move, newdisp allDisp = allDisp + "%s (%s) " % (word, str(move.getScore())) allDisp = allDisp + "by %s" % player.getUsername() d = allDisp d = "%s, " % str(score) + d if self.stats.has_key(STAT_HIGHEST_SCORING_MOVE): data, disp = self.stats[STAT_HIGHEST_SCORING_MOVE] if score > data: self.stats[STAT_HIGHEST_SCORING_MOVE] = score, d else: self.stats[STAT_HIGHEST_SCORING_MOVE] = score, d d = allDisp d = "%s, " % str(len(moves)) + d if self.stats.has_key(STAT_MOST_WORDS_IN_MOVE): data, disp = self.stats[STAT_MOST_WORDS_IN_MOVE] if len(moves) > data: self.stats[STAT_MOST_WORDS_IN_MOVE] = len(moves), d else: self.stats[STAT_MOST_WORDS_IN_MOVE] = len(moves), d def getMoves(self): """ Return List of moves on the board @return: List of moves on the board @see: L{pyscrabble.game.pieces.Move} """ return self.moves def hasWord(self, word): """ Check to see if a word is on the board @param word: Word to check @return: True if the word is on the board. """ return word in self.words def resetPassCount(self): """ Reset the pass counter """ self.passedMoves = 0 def passMove(self): """ Pass a move. If the number of passed moves is equal to the number of players, all players have passed their moves and the game is over. @raise GameOverException: If all players have passed their moves and the game is over. """ self.passedMoves = self.passedMoves + 1 if self.passedMoves == len(self.players): raise GameOverException def getWinners(self, exclude=None): """ Return the player(s) with the highest score @param exclude: Player to exclude from winning (say, if they timed out) @return: List of players with the highest score. @see: L{pyscrabble.game.player.Player} """ tmp = self.players[:] if exclude is not None: tmp.remove(exclude) maxScore = None for player in tmp: maxScore = max(maxScore, player.getScore()) winners = [] for player in tmp: if player.getScore() == maxScore: winners.append(player) return winners def pause(self): """ Pause the game. """ self.paused = True self.players.remove(self.currentPlayer) self.players.insert(0, self.currentPlayer) for player in self.players: if player not in self.pending: self.pending.append(player) def unPause(self): """ Unpause the game. """ self.paused = False self.pending = [] def isPaused(self): """ Check whether the game is paused. @return: True if the game is paused. """ return self.paused def returnLetters(self, letters): """ Return letters to the Bag. @param letters: Letters to put back in the back @see: L{pyscrabble.game.pieces.Letter} @see: L{pyscrabble.game.pieces.Bag} """ self.bag.returnLetters(letters) def isInProgress(self): """ Check whether the game is started. The game is considered in progress even if it is paused. @return: True if the game has been started. """ return self.started def getPlayer(self, player): """ Get a player out of the game @param player: Player @return: Player in the game, or None if player is not in the game. @see: L{pyscrabble.game.player.Player} """ for _player in self.players: if player.getUsername() == _player.getUsername(): return _player return None def isCurrentPlayer(self, player): """ Check to see if C{player} is the current player @param player: Player to checl @return: True if C{player} is the current player. """ return self.currentPlayer == player def addSpectator(self, spectator): """ Add a spectator to the game @param spectator: Spectator name """ self.spectators.append(spectator) def getSpectators(self): """ Return a copy of the list of spectors @return: List of Spectator names """ return self.spectators[:] def spectatorLeave(self, spectator): """ Remove a spectator from the game @param spectator: Spectator to remove """ self.spectators.remove(spectator) def hasSpectator(self, spectator): """ Check to see if a spectator is in the game @param spectator: Spectator @return: True if spectator is in the game """ return spectator in self.spectators def isSpectatorChatEnabled(self): """ Check if Spectator Chat is Enabled @return: True if Spectator Chat is enabled for this game """ return self.spectatorChatEnabled def setSpectatorChatEnabled(self, flag): """ Set Spectator Chat Enabled/Disabled @param flag: True to enable Spectator Chat """ self.spectatorChatEnabled = flag def isSpectatorsAllowed(self): """ Check if Spectator Chat is Enabled @return: True if Spectator Chat is enabled for this game """ return self.spectatorsAllowed def setSpectatorsAllowed(self, flag): """ Set Spectators Allowed @param flag: True to allow spectators """ self.spectatorsAllowed = flag def setComplete(self): """ Mark this game as complete """ self.complete = True def appendLogMessage(self, log): """ Add logging information Log is a tuple: (level, message) @param log: Log Message tuple """ self.log.append(log) def getLog(self): """ Retrieve log Log is a list of tuples: (level, message) @return: Game Log """ return self.log[:] def getPending(self): """ Get list of players pending to join the game @return: List of players still pending to re-join a paused game """ return self.pending def removePending(self, player): """ Remove a player from the pending list @param player: Player """ self.pending.remove(player) def addPending(self, player): """ Add pending player @param player: Player """ if player not in self.pending: self.pending.append(player) def getStats(self): """ Retrieve list of game stats @return: List of tuples (stat_name, stat_value) """ s = [] s.append((ServerMessage([STAT_LETTERS_LEFT]), str(self.bag.getCount()))) for key, value in self.stats.iteritems(): data, disp = value s.append((ServerMessage([key]), disp)) return s def getOptions(self): """ Return list of options @return: List of tuples (option_name, option_value) """ s = [] s.append((ServerMessage([CREATOR]), self.creator)) for key, value in self.options.iteritems(): if key in (OPTION_TIMED_GAME, OPTION_TIMED_LIMIT, OPTION_MOVE_TIME): if value == int(1): s.append((ServerMessage([key]), ServerMessage([value, MINUTE]))) else: s.append((ServerMessage([key]), ServerMessage([value, MINUTES]))) else: s.append((ServerMessage([key]), ServerMessage([value]))) return s def getCountLetters(self): """ Return the number of letters left in the bag @return: Count of letters left in bag """ return self.bag.getCount()