def checkPlayerPlaying(self): query = Player.gql("WHERE ANCESTOR IS :1 AND turnNumber = :2", self.game, self.game.turn) result = query.get() if (result == None or result.bankrupt == True): self.game.turn += 1 self.game.put() self.checkPlayerPlaying()
def endPlayerTurn(self, userObj): if self.game.inProgress: if (self.checkPlayerTurn(userObj)): #if user turn player = Player.gql("WHERE ANCESTOR IS :1 AND user = :2", self.game, userObj).get() if self.game.rollRemaining : message = {'error' : 'roll remaining'} self.messagePlayer(userObj, message) elif player.money <= 0: message = {'error' : 'You do not have enough money to continue. Mortgage a property or sell houses'} self.messagePlayer(userObj, message) else : self.game.rollRemaining = True self.game.numRolls = 0 self.game.turn = self.game.turn + 1 if self.game.turn > self.getNumberOfPlayers(): self.game.turn = 1 #Check for bankrupt players self.checkPlayerPlaying() self.game.put() message = {'status' : 'player_ended_turn', 'turn_number' : self.game.turn} self.messageAll(message) else: message = {'error' : 'Not your turn'} self.messagePlayer(userObj, message) else : message = {'error' : 'The game has not started'} self.messagePlayer(userObj, message)
def getCurrentPlayer(self): query = Player.gql("WHERE ANCESTOR IS :1 AND turnNumber = :2", self.game, self.game.turn) result = query.get() if (result == None or result.bankrupt == True): self.messageAll({'error' : 'Player not playing'}) else: return result
def startGame(self): if self.game.inProgress : self.messagePlayer(player.user, {'error' : 'The game has already been started'}) elif self.getNumberOfPlayers() < 2 : self.messagePlayer(player.user, {'error' : 'Not enough players'}) else : #Set game variables so the game can start self.game.inProgress = True self.game.turn = 1 self.game.rollRemaining = True self.game.numRolls = 0 self.game.put() #Create turn numbers query = Player.gql("WHERE ANCESTOR IS :1", self.game) players = query.fetch(4) number = 0 playersString = {} for player in players : number+= 1 player.turnNumber = number playersString[player.piece] = number #Store all players db.put(players) #Message the players with the mappings self.messageAll({'status' : 'game_started', 'turns' : playersString}) self.messageAll({'status' : 'turn', 'turn_number' : 1})
def clientDisconnected(self, clientID) : #Gets the player and the game of which the client just disconnected #The client ID is created from the user id and the game key. (It's pretty hard to recreate confidently, so it's stored with the player) query = Player.gql("WHERE clientID = :1", clientID) player = query.get() #can't import game updater here due to infinite import loop. Return player and the game to request handler return [player, player.parent()]
def chat(self, user, userMessage) : #Get the player from the user query = Player.gql("WHERE ANCESTOR IS :1 AND user = :2", self.game, user) player = query.get() #Escape any html in the message userMessage = cgi.escape(userMessage) message = {'status' : 'chat', 'from' : player.piece, 'message' : userMessage} self.messageAll(message)
def cleanUpDatastore(self): query = Building.gql("WHERE ANCESTOR IS :1", self.game) db.delete(query.fetch(100)) query = Player.gql("WHERE ANCESTOR IS :1", self.game) db.delete(query.fetch(100)) query = EventCard.gql("WHERE ANCESTOR IS :1", self.game) db.delete(query.fetch(100)) self.game.delete()
def addPlayer(self, userObj, userName, game_key): if (not self.game.inProgress): #Check number of players #Escape user name userName = cgi.escape(userName) #Check if name is null if len(userName) < 1 : self.messagePlayer(userObj, {'error' : 'name is empty'}) return numberOfPlayers = self.getNumberOfPlayers() #Check user is not in use already query = Player.gql("WHERE ANCESTOR IS :1", self.game) players = query.fetch(3) for player in players : if player.user == userObj : #user in use, throw an error saying they can't use the user message = {'error' : 'Your account is already being used in this game'} self.messagePlayer(userObj, message) return #add player playerColour = self.game.colours[0] self.game.colours.remove(playerColour) playerPiece = self.game.pieces[0] self.game.pieces.remove(playerPiece) self.game.put() playerArray = [] for play in players: playerArray.append({'name': play.name, 'colour' : play.colour, 'piece' : play.piece, 'money' : play.money, 'position' : play.position}) message = {'status' : 'current_players', 'current_players' : playerArray} self.messagePlayer(userObj, message) player = Player(parent=self.game, user = userObj, name = userName, turnNumber = -1, piece = playerPiece, colour = playerColour, clientID = (str (userObj.user_id()) + str(game_key))) player.put() message = {'status' : 'player_joined', 'name': userName, 'colour' : playerColour, 'piece' : playerPiece, 'money' : 1500, 'position' : 0} self.messageAll(message) message = {'status' : 'you', 'piece' : playerPiece, 'colour' : playerColour} self.messagePlayer(userObj, message) if (numberOfPlayers + 1 == 4): self.startGame() else: message = {'error' : 'The game has already started'} self.messagePlayer(userObj, message)
def actOnPosition(self, player): pos = player.position #Community Chest if ((pos == 2) or (pos == 17) or (pos == 33)): self.drawCard(False, player) #Chance elif((pos == 7) or (pos == 22) or (pos == 36)): self.drawCard(True, player) #Income Tax elif(pos == 4): self.transferMoney(200, player) self.messageAll({'status' : 'tax', 'player_id' : self.game.turn, 'money_change' : '-200', 'money' : player.money}) #Super Tax elif(pos == 38): self.transferMoney(100, player) self.messageAll({'status' : 'tax', 'player_id' : self.game.turn, 'money_change' : '-100', 'money' : player.money}) #Jail elif(pos == 30): self.goToJail(player) self.messageAll({'status' : 'go_to_jail', 'player_id' : self.game.turn, 'position' : 10}) #Free Parking/Just Visiting/Go elif((pos == 0) or ((pos == 10) and (player.inJail == -1)) or (pos == 20)): pass #Property else: query = Building.gql("WHERE ANCESTOR IS :1 AND position = :2", self.game, pos) building = query.get() if(building.mortgaged == False and building.owner != None and building.owner != player.user): query = Player.gql("WHERE ANCESTOR IS :1 AND user = :2", self.game, building.owner) buildingOwner = query.get() rent = self.calculateRent(buildingOwner, building, self.game.lastDiceTotal) self.transferMoney(rent, player, buildingOwner) #Send a message to the clients that rent is to be paid self.messageAll({'status' : 'rent', 'player_id' : player.turnNumber, 'property_owner' : buildingOwner.turnNumber, 'amount' : rent, 'player_money' : player.money, 'owner_money' : buildingOwner.money})
def transferMoney(self, amount, playerFrom, playerTo=None): if(playerFrom.money > amount): playerFrom.money -= amount playerFrom.put() if(playerTo != None): playerTo.money += amount playerTo.put() else: query = Building.gql("WHERE ANCESTOR IS :1 AND owner = :2 AND mortgaged = False", self.game, playerFrom.user) buildings = query.fetch(100) mortgageValue = 0 for building in buildings: mortgageValue += building.houses * (building.buildCost/2) mortgageValue += building.cost/2 playerFrom.money -= amount playerFrom.put() if(mortgageValue > amount): message = {'status' : 'force_mortgage', 'amount' : (-1 * playerFrom.money)+1} self.messagePlayer(playerFrom.user, message) else: playerFrom.bankrupt = True playerFrom.put() message = {'status' : 'bankrupt', 'player' : playerFrom.turnNumber} self.messageAll(message) query = Player.gql("WHERE ANCESTOR IS :1 AND Bankrupt = False", self.game) count = query.count(2) if(count == 1): message = {'status' : 'victory', 'player' : query.get().turnNumber} self.messageAll(message) self.cleanUpDatastore() else: query = Building.gql("WHERE ANCESTOR IS :1 AND owner = :2", self.game, playerFrom.user) buildings = query.fetch(40) for building in buildings: building.owner = playerTo.user building.put()
def leaveGame(self, player) : #Need logic to test if they are not bankrupt and if so return their properties to the bank propertiesMessage = [] if self.game.inProgress : if not player.bankrupt : #In this case they still in the game so their properties still need to be returned to the bank query = Building.gql("WHERE ANCESTOR IS :1 AND owner = :2", self.game, player.user) properties = query.fetch(30) for property in properties : property.owner = None property.houses = 0 property.mortgaged = False property.put() propertiesMessage.append(property.position) #Remove player from the datastore player.delete() #Notify all players that player has left #Check how many players are left (and delete game possibility) if self.game.inProgress : if self.getNumberOfPlayers() < 2 : #Then the remaining player has won message = {'status' : 'victory', 'player_piece' : Player.gql("WHERE ANCESTOR IS :1 AND bankrupt = False", self.game).get().piece} self.messageAll(message) self.cleanUpDatastore() if self.game.turn == player.turnNumber : self.game.rollRemaining = False self.endPlayerTurn(player.user) #End the players turn self.messageAll({'status' : 'player_disconnected', 'player_piece' : player.piece, 'property_positions_returned_to_bank' : propertiesMessage}) else : #Return the colours and pieces to game to use self.game.pieces.append(player.piece) self.game.colours.append(player.colour) self.game.put() self.messageAll({'status' : 'player_disconnected', 'player_piece' : player.piece})
def takeCard(self, card, player, isChance): #Display card.text to player that drew card moneyChange = 0 position = None otherPlayers = [] inJail = False goojf = False if(card.event == 0): #Transfer money self.transferMoney((-1 * card.value),player) moneyChange = card.value elif(card.event == 1): #Move player self.movePlayer(player,card.value) position = player.position elif(card.event == 2): #Move player to stated position self.setPlayerPosition(player, card.value) position = player.position elif(card.event == 3): #Player pays/receives-from all query = Player.gql("WHERE ANCESTOR IS :1",self.game) players = query.fetch(4) for playerX in players: if (player.key() != playerX.key()): #If other player - don't give money to self self.transferMoney(card.value,player,playerX) otherPlayers.append([playerX.turnNumber, card.value, playerX.money]) elif(card.event == 4): #Get out jail free or go to jail if(card.value == 1): #Puts player in jail. No checking for GOOJF cards self.goToJail(player) position = 10 inJail = True else: player.getOutOfJailFree += 1 player.put() goojf = player.getOutOfJailFree elif(card.event == 5): #Move to nearest shop #Currently only moves if player is on a chance/commchest space if (player.position in (2, 7, 33, 36)): #self.setPlayerPosition(player,12) if player.position > 12 : #Will pass go moves = 40 - player.position + card.value self.movePlayer(player, moves) else : self.setPlayerPosition(player, 12) position = 12 elif (player.position in (17, 22)): self.setPlayerPosition(player, 28) position = 28 elif(card.event == 6): #Move to pub #currently only moves if player is on a chance/commchest space if (player.position in (2, 36)): if player.position > 5 : #Will pass go moves = 40 - player.position + card.value self.movePlayer(player, moves) else : self.setPlayerPosition(player, 5) position = 5 if (player.position == 7): self.setPlayerPosition(player,15) position = 15 if (player.position in (17, 22)): self.setPlayerPosition(player,25) position = 25 if (player.position == 33): self.setPlayerPosition(player,35) position = 35 elif(card.event == 7): #NEEDS REVIEW: how does building.houses property work? #also not thoroughly tested. Problem with having hotel/lab #pay per property total_to_pay = 0 #get all buildings with offices/lab query = Building.gql("WHERE ANCESTOR IS :1 AND type = 'building' AND houses > 0",self.game) buildings = query.fetch(40) #find all buildings belonging to player for building in buildings: if (building.owner == player.user): if (building.houses == 5): total_to_pay += card.value2 #pay per hotel/lab else: total_to_pay += (card.value * building.houses) #pay per house/office self.transferMoney(total_to_pay,player) moneyChange = total_to_pay else: message = {'error' : 'Invalid event type. Contact a game admin.'} self.messageAll(message) sys.exit() #Finally send the message regarding the card to all players message = {'status': 'pick_up_card','player': player.turnNumber,'isChance': isChance, 'text': card.text, 'money_change' : moneyChange, 'money' : player.money, 'position' : position, 'otherPlayers' : otherPlayers, 'in_jail' : inJail, 'goojf_card' : goojf} self.messageAll(message)
def getNumberOfPlayers(self): query = Player.gql("WHERE ANCESTOR IS :1", self.game) return query.count(4)
def sendMessageToAll(self, game, message) : #Sends a message to all players in a game query = Player.gql("WHERE ANCESTOR IS :1", game) players = query.fetch(4) for player in players: self.sendMessage(player.user, game, message)