def calculateRent(self, player, building, dice = None): #Rent for buildings if (building.type == "building"): query = Building.gql("WHERE ANCESTOR IS :1 AND colour = :2 AND owner = :3", self.game, building.colour, player.user) count = query.count(3) if (building.houses == 0 and (((building.colour == "954c23" or building.colour == "284ea1") and count == 2) or count == 3)): return building.rent[0] * 2 elif(0 <= building.houses <= 5): return building.rent[building.houses] else: message = {'error' : 'Invalid number of houses. Contact a game admin.'} self.messageAll(message) sys.exit() #Rent for pubs elif (building.type == "pub"): query = Building.gql("WHERE ANCESTOR IS :1 AND type = 'pub' AND owner = :2", self.game, player.user) count = query.count(4) return building.rent[count-1] #Rent for shops elif (building.type == "shop"): query = Building.gql("WHERE ANCESTOR IS :1 AND type = 'shop' AND owner = :2", self.game, player.user) count = query.count(2) if(count == 1): return 4 * (dice) elif(count ==2): return 10 * (dice) else: message = {'error' : 'Property number error. Contact a game admin.'} self.messagePlayer(player.user, message) else: message = {'error' : 'Invalid building type. Contact a game admin.'} self.messagePlayer(player.user, message) sys.exit()
def unmortgageProperty(self, user, property_id) : if self.game.inProgress : if self.checkPlayerTurn(user) : player = self.getCurrentPlayer() query = Building.gql("WHERE ANCESTOR IS :1 AND position = :2", self.game, int(property_id)) property = query.get() #Unmortgage amount is mortgage cost + 10% interest amount = property.cost/2 amount = amount + amount/10 #Validate if player can unmortgage property (Who owns it, if not mortgaged) if property.owner != user : message = {'error' : 'not your property'} self.messagePlayer(user, message) elif property.mortgaged == False : message = {'error' : 'property already unmortgaged'} self.messagePlayer(user, message) elif self.deductMoney(player, amount) : property.mortgaged = False property.put() message = {'status' : 'unmortgaged', 'player_id' : player.turnNumber, 'property_id' : property.position, 'money_change' : amount, 'money' : player.money} self.messageAll(message) else : message = {'error' : 'not enough money'} self.messagePlayer(user, message) else : message = {'error' : 'It is not your turn'} self.messagePlayer(user, message) else : message = {'error' : 'The game has not started'} self.messagePlayer(user, message)
def mortgageProperty(self, user, position) : if self.game.inProgress : if self.checkPlayerTurn(user) : #Mortgage property #Get property player = self.getCurrentPlayer() query = Building.gql("WHERE ANCESTOR IS :1 AND position = :2", self.game, int(position)) property = query.get() #Validate if player can mortgage property (Who owns it, if has houses on block, already mortgaged) if property.owner != user : message = {'error' : 'not your property'} self.messagePlayer(user, message) elif property.mortgaged == True : message = {'error' : 'property already mortgaged'} self.messagePlayer(user, message) elif not self.checkBlockForHouses(property.colour): #no houses so can mortgage property.mortgaged = True property.put() #Now give the player their money amount = property.cost / 2 self.addMoney(player, amount) message = {'status' : 'mortgaged', 'player_id' : player.turnNumber, 'property_id' : property.position, 'money_change' : amount, 'money' : player.money} self.messageAll(message) else : #Block has houses on message = {'error' : 'too many houses on neighbouring properties'} self.messagePlayer(user, message) else : message = {'error' : 'It is not your turn'} self.messagePlayer(user, message) else : message = {'error' : 'The game has not started'} self.messagePlayer(user, message)
def buyProperty(self, user): #Check it is the user's turn if self.game.inProgress : if (self.checkPlayerTurn(user)) : #Action of buying property player = self.getCurrentPlayer() if self.game.numRolls == 0: self.messagePlayer(user, {"error": "You haven't moved yet."}); return #Check if property is available query = Building.gql("WHERE ANCESTOR IS :1 AND owner = NULL AND position = :2" , self.game, player.position) property = query.get() if not property : #property not available message = {'error' : 'property unavailable'} self.messagePlayer(user, message) else : #property is available #Check if the player has the available funds if self.deductMoney(player, property.cost) : property.owner = user property.put() message = {'status' : 'bought', 'player' : player.turnNumber, 'property' : property.position, 'money_change' : -property.cost, 'money' : player.money} self.messageAll(message) else : message = {'error' : 'not enough money'} self.messagePlayer(user, message) else : message = {'error' : 'It is not your turn'} self.messagePlayer(user, message) else : message = {'error' : 'The game has not started'} self.messagePlayer(user, message)
def buyHouse(self, user, propertyPosition): #Check it is the user's turn if self.game.inProgress : if (self.checkPlayerTurn(user)) : #Now time to buy an office/lab player = self.getCurrentPlayer() query = Building.gql("WHERE ANCESTOR IS :1 AND owner = :2 AND position = :3 AND type = 'building' ", self.game, player.user, int(propertyPosition)) property = query.get() #Check if property belongs to player and property is "building" type if property != None : block = self.getBlockDetails(property.colour) #Check if surrounding houses have the minumum number of houses on them #or if one of the properties is mortgaged (as only need to check for one) for houseCheck in block : #Check player owns all in group if houseCheck["owner"] != user: message = {'error' : 'must own all properties'} self.messagePlayer(user, message) return if houseCheck["houses"] < property.houses : message = {'error' : 'not enough houses on neighbouring properties'} self.messagePlayer(user, message) return if houseCheck["mortgaged"] : message = {'error' : 'property in group is mortgaged'} self.messagePlayer(user, message) return if property.houses >= 5 : #Check if the house will exceed the maximum allowed message = {'error' : 'maximum number of houses already'} self.messagePlayer(user, message) return #Check if the player has the available funds if self.deductMoney(player, property.buildCost) : property.houses = property.houses + 1 property.put() message = {'status' : 'addBuilding', 'player' : player.turnNumber, 'property' : property.position, 'money_change' : -property.buildCost, 'money' : player.money} self.messageAll(message) else : message = {'error' : 'not enough money'} self.messageAll(message) else: message = {'error' : 'Cannot build houses here!'} self.messagePlayer(user, message) else : message = {'error' : 'It is not your turn'} self.messagePlayer(user, message) else : message = {'error' : 'The game has not started'} self.messagePlayer(user, message)
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 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 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 getBlockDetails(self, colour) : #Returns a list that contains the properties positions query = Building.gql("WHERE ANCESTOR IS :1 AND colour = :2", self.game, colour) result = query.fetch(3) positions = [] for x in range(0, len(result)) : if colour == 'ffffff' or colour == 'fefefe' : positions.append({ "position": result[x].position, "owner": result[x].owner, "mortgaged": result[x].mortgaged }) else : positions.append({ "position": result[x].position, "houses": result[x].houses, "owner": result[x].owner, "mortgaged": result[x].mortgaged }) return positions
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)