def finalize_score(self): """ When game is completed, update scores with the tiles left """ if self._game_resigned: # In case of a resignation, the resigning player has already lost all points return for ix in range(2): # Add the score of the opponent's tiles self._scores[ix] += Alphabet.score(self._racks[1 - ix].contents()) # Subtract the score of the player's own tiles self._scores[ix] -= Alphabet.score(self._racks[ix].contents()) if self._scores[ix] < 0: self._scores[ix] = 0
def _append_final_adjustments(self, movelist): """ Appends final score adjustment transactions to the given movelist """ # Lastplayer is the player who finished the game lastplayer = self.moves[-1].player if self.moves else 0 if not self.state.is_resigned(): # If the game did not end by resignation, check for a timeout overtime = self.overtime() adjustment = list(self.overtime_adjustment()) sc = self.state.scores() if any(overtime[ix] >= Game.MAX_OVERTIME for ix in range(2)): # 10 minutes overtime # Game ended with a loss on overtime ix = 0 if overtime[0] >= Game.MAX_OVERTIME else 1 adjustment[1 - ix] = 0 # Adjust score of losing player down by 100 points adjustment[ix] = - min(100, sc[ix]) # If losing player is still winning on points, add points to the # winning player so that she leads by one point if sc[ix] + adjustment[ix] >= sc[1 - ix]: adjustment[1 - ix] = sc[ix] + adjustment[ix] + 1 - sc[1 - ix] else: # Normal end of game opp_rack = self.state.rack(1 - lastplayer) opp_score = Alphabet.score(opp_rack) last_rack = self.state.rack(lastplayer) last_score = Alphabet.score(last_rack) if not last_rack: # Won with an empty rack: Add double the score of the losing rack movelist.append((1 - lastplayer, (u"", u"--", 0))) movelist.append((lastplayer, (u"", u"2 * " + opp_rack, 2 * opp_score))) else: # The game has ended by passes: each player gets her own rack subtracted movelist.append((1 - lastplayer, (u"", opp_rack, -1 * opp_score))) movelist.append((lastplayer, (u"", last_rack, -1 * last_score))) # If this is a timed game, add eventual overtime adjustment if tuple(adjustment) != (0, 0): movelist.append((1 - lastplayer, (u"", u"TIME", adjustment[1 - lastplayer]))) movelist.append((lastplayer, (u"", u"TIME", adjustment[lastplayer]))) # Add a synthetic "game over" move movelist.append((1 - lastplayer, (u"", u"OVER", 0)))
def client_state(self): """ Create a package of information for the client about the current state """ reply = dict() if self.state.is_game_over(): # The game is now over - one of the players finished it reply["result"] = Error.GAME_OVER # Not really an error num_moves = 1 if self.last_move is not None: # Show the autoplayer move if it was the last move in the game reply["lastmove"] = self.last_move.details() num_moves = 2 # One new move to be added to move list newmoves = [(player, m.summary(self.state.board())) for player, m in self.moves[-num_moves:]] # Lastplayer is the player who finished the game lastplayer = self.moves[-1][0] if not self.resigned: # If the game did not end by resignation, # account for the losing rack rack = self.state._racks[1 - lastplayer].contents() # Subtract the score of the losing rack from the losing player newmoves.append((1 - lastplayer, (u"", rack, -1 * Alphabet.score(rack)))) # Add the score of the losing rack to the winning player newmoves.append((lastplayer, (u"", rack, 1 * Alphabet.score(rack)))) # Add a synthetic "game over" move newmoves.append((1 - lastplayer, (u"", u"OVER", 0))) reply["newmoves"] = newmoves reply["bag"] = "" # Bag is now empty, by definition reply["xchg"] = False # Exchange move not allowed else: # Game is still in progress reply["result"] = 0 # Indicate no error reply["rack"] = self.state.player_rack().details() reply["lastmove"] = self.last_move.details() reply["newmoves"] = [(player, m.summary(self.state.board())) for player, m in self.moves[-2:]] reply["bag"] = self.display_bag() reply["xchg"] = self.state.is_exchange_allowed() reply["scores"] = self.state.scores() return reply
def finalize_score(self, lost_on_overtime = None, overtime_adjustment = None): """ When game is completed, calculate the final score adjustments """ if self._game_resigned: # In case of a resignation, the resigning player has already lost all points return sc = self._scores adj = self._adj_scores if lost_on_overtime is not None: # One of the players lost on overtime player = lost_on_overtime # Subtract 100 points from the player adj[player] = - min(100, sc[player]) # If not enough to make the other player win, add to the other player if sc[player] + adj[player] >= sc[1 - player]: adj[1 - player] = sc[player] + adj[player] + 1 - sc[1 - player] # There is no consideration of rack leave in this case return if any(self._racks[ix].is_empty() for ix in range(2)): # Normal win by one of the players for ix in range(2): # Add double the score of the opponent's tiles (will be zero for the losing player) adj[ix] = 2 * Alphabet.score(self.rack(1 - ix)) else: # Game expired by passes for ix in range(2): # Subtract the score of the player's own tiles adj[ix] = - Alphabet.score(self.rack(ix)) # Apply overtime adjustment, if any if overtime_adjustment is not None: for ix in range(2): adj[ix] += overtime_adjustment[ix]