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})
Beispiel #5
0
	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)
Beispiel #14
0
	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)