from PlasmaServer import * heekTables = [] # an array of heekGames for the tables we have running kNone = 0 kRock = 1 kPaper = 2 kScissors = 3 class heekPlayer: def __init__(self): self.ID = -1 self.key = None self.pos = -1 self.choice = kNone self.rocksWon = 0 self.papersWon = 0 self.scissorsWon = 0 self.roundsWon = 0 self.curRoundScore = 0 self.points = -1 self.isPlaying = 0 self.name = "" self.gamePlaying = None # the heekGame we are currently playing self.scoreDict = { (kRock, kRock): 0, (kRock, kPaper): -1, (kRock, kScissors): 1, (kRock, kNone): 0, (kPaper, kRock): 1, (kPaper, kPaper): 0, (kPaper, kScissors): -1, (kPaper, kNone): 0, (kScissors, kRock): -1, (kScissors, kPaper): 1, (kScissors, kScissors): 0, (kScissors, kNone): 0, (kNone, kNone): 0, (kNone, kRock): 0, (kNone, kPaper): 0, (kNone, kScissors): 0 } def ScoreAgainst(self,other): return self.scoreDict[(self.choice,other.choice)] def ResetGame(self): self.choice = kNone self.rocksWon = 0 self.papersWon = 0 self.scissorsWon = 0 self.curRoundScore = 0 self.isPlaying = 0 def ResetRound(self): self.curRoundScore = 0 self.choice = kNone def SendMessage(self,contents): msg = ptPythonMsg() msg.setKey(self.key) msg.setContents(str(contents)) msg.send(self.ID) def CompareRoundScores(player1, player2): if player1.curRoundScore < player2.curRoundScore: return -1 if player1.curRoundScore > player2.curRoundScore: return 1 return 0 class heekGame: def __init__(self): self.ID = -1 self.playerList = [] self.countdownStarted = 0 self.winners = [] self.pot = 0 self.agePlayers = [] # a list of all people in the age, tuple where 0 is ID and 1 is Key self.queueCleanup = [] # do we need to send a cleanup message to the first person to link in? def PlayerIDInGame(self,ID): for player in self.playerList: if player.ID == ID: return 1 return 0 def PlayerKeyInGame(self,key): for player in self.playerList: if player.key == key: return 1 return 0 def SendToAll(self,message): for player in self.playerList: player.SendMessage(message) def SendWelcomeMsg(self,name,points): self.SendToAll("PlrWelcome "+str(points)+' '+str(self.CalculateAnte(points))+' '+name) def SendStatusMsg(self,player): player.SendMessage("Points "+str(player.points)+' '+str(self.CalculateAnte(player.points))) def CalculateRank(self,points): if points == 0: return 0 gamesWinToRank = 100 # number of 1v1 games against same rank to level rank = 1 curPoints = gamesWinToRank while 1: curPoints += rank*gamesWinToRank if points <= curPoints: return rank rank += 1 def CalculateAnte(self,points): return self.CalculateRank(points) def RewardRoundWinners(self): for winner in self.winners: winner.roundsWon += 1 lightNum = 0 if winner.choice == kRock: winner.rocksWon += 1 lightNum = winner.rocksWon elif winner.choice == kPaper: winner.papersWon += 1 lightNum = winner.papersWon elif winner.choice == kScissors: winner.scissorsWon += 1 lightNum = winner.scissorsWon if lightNum == 0: # shouldn't happen, but just in case print "ID: "+str(self.ID)+" lightNum is 0 for some reason...len(winners)="+str(len(self.winners))+", winner.choice="+str(winner.choice) print "ID: "+str(self.ID)+" len(playerList)="+str(len(self.playerList))+", winner.ID="+str(winner.ID)+", winner.pos="+str(winner.pos) return winner.SendMessage("Win "+str(winner.choice)) if lightNum < 3: light = (winner.choice-1)*2+(lightNum-1) winner.SendMessage("LightOn "+str(light)) elif lightNum == 3: light1 = (winner.choice-1)*2 light2 = light1+1 winner.SendMessage("Flash "+str(light1)) winner.SendMessage("Flash "+str(light2)) losers = [player for player in self.playerList if not player in self.winners] for loser in losers: loser.SendMessage("Lose "+str(loser.choice)) def ComputeRoundScores(self): cnt = len(self.playerList) #if cnt == 1: # for single-player only #self.playerList[0].curRoundScore = 1 for i in range(cnt-1): player1 = self.playerList[i] for j in range(i+1,cnt): player2 = self.playerList[j] player1.curRoundScore += player1.ScoreAgainst(player2) player2.curRoundScore += player2.ScoreAgainst(player1) def PickRoundWinners(self): rwCopy = self.playerList rwCopy.sort(CompareRoundScores) big=rwCopy[len(rwCopy)-1].curRoundScore if big>0: self.winners = [winner for winner in rwCopy if winner.curRoundScore == big] def PickGameWinners(self): gameWinners = [winner for winner in self.winners if winner.rocksWon == 3 or winner.papersWon == 3 or winner.scissorsWon == 3] if (len(gameWinners) <= 1): return gameWinners gwCopy = gameWinners gwCopy.sort(CompareRoundsWon) big=gwCopy[len(gwCopy)-1].roundsWon if big>0: gameWinners = [winner for winner in gwCopy if winner.roundsWon==big] return gameWinners def HandlePlayerReady(self): if not self.countdownStarted: print "ID: "+str(self.ID)+" Starting countdown" self.SendToAll("StartCountdown") self.countdownStarted = 1 return playersReady = [player for player in self.playerList if player.choice != kNone] allReady = (len(playersReady) == len(self.playerList)) if allReady and len(playersReady)>1: self.SendToAll("StopCountdown") def ResetGame(self): self.winners = [] for player in self.playerList: player.ResetGame() def ResetRound(self): self.winners = [] for player in self.playerList: player.ResetRound() def PlayGame(self): if not self.countdownStarted: print "ID: "+str(self.ID)+" Extra countdown end message received, ignoring" return # extra countdown end message, ignore self.countdownStarted = 0 playersReady = [player for player in self.playerList if player.choice != kNone] if len(playersReady) <= 1: print "ID: "+str(self.ID)+" Only one player was ready, aborting game" self.ResetRound() self.SendToAll("ShowIdleAnimation") return print "ID: "+str(self.ID)+" Disabling player's interfaces" self.SendToAll("Disable") self.ComputeRoundScores() self.PickRoundWinners() self.RewardRoundWinners() def HandleGameWinner(self): gameWinners = self.PickGameWinners() if len(gameWinners) > 0: print "ID: "+str(self.ID)+" A player has won, letting admin know about it" x = "init" if (gameWinners[0].choice == kRock): # it might be possible for multiple types to win, will need to check x = "rock" elif (gameWinners[0].choice == kPaper): x = "paper" elif (gameWinners[0].choice == kScissors): x = "scissors" self.SendToAll("GameWin "+x) pointsToGive = int(self.pot/len(gameWinners)) self.pot -= pointsToGive*len(gameWinners) for winner in gameWinners: if winner.points != -1: winner.SendMessage("SetPoints "+str(winner.points+pointsToGive)) for player in self.playerList: if player.ID == winner.ID and player.key == winner.key: player.points += pointsToGive break self.ResetGame() for player in self.playerList: self.SendStatusMsg(player) return 1 return 0 def SendTableState(self,ID,key): for player in self.playerList: setupMsg = ptPythonMsg() setupMsg.setKey(key) setupStr = "SetupP"+str(player.pos) setupMsg.setContents(setupStr+"B") # enable buttons setupMsg.send(ID) if player.rocksWon >= 1: setupMsg.setContents(setupStr+"L0") setupMsg.send(ID) if player.rocksWon >= 2: setupMsg.setContents(setupStr+"L1") setupMsg.send(ID) if player.papersWon >= 1: setupMsg.setContents(setupStr+"L2") setupMsg.send(ID) if player.papersWon >= 2: setupMsg.setContents(setupStr+"L3") setupMsg.send(ID) if player.scissorsWon >= 1: setupMsg.setContents(setupStr+"L4") setupMsg.send(ID) if player.scissorsWon >= 2: setupMsg.setContents(setupStr+"L5") setupMsg.send(ID) def ClientLeft(self,ID): position = -1 for player in self.playerList[:]: if player.ID == ID: position = player.pos self.playerList.remove(player) for player in self.agePlayers[:]: if player[0] == ID: self.agePlayers.remove(player) if position == -1: # client wasn't playing return print "ID: "+str(self.ID)+" Client ID# "+str(ID)+" has left, cleaning up after him" if len(self.playerList) == 0: # no players left to cleanup the position if len(self.agePlayers) == 0: # no players in age left to cleanup the table self.queueCleanup.append(position) else: cleanup = ptPythonMsg() cleanup.setContents("Cleanup "+str(position)) cleanup.setKey(self.agePlayers[0][1]) cleanup.send(self.agePlayers[0][0]) cleanup.setContents("ShowIdleAnimation") cleanup.send(self.agePlayers[0][0]) for num in range(len(self.playerList)): # let everyone know of their new player numbers numberMsg = ptPythonMsg() numberMsg.setKey(self.playerList[num].key) numberMsg.setContents("Number "+str(num+1)) numberMsg.send(self.playerList[num].ID) if position != -1: self.SendToAll("Drop "+str(position)) def HandleAdd(self,senderID,key,pos): for player in self.playerList: if player.pos == pos: print "ID: "+str(self.ID)+" Ignoring client ID# "+str(senderID)+" request to play since someone is already sitting in their requested position: "+str(pos) return print "ID: "+str(self.ID)+" Adding client ID# "+str(senderID)+" to player list. They are playing position "+str(pos) player = heekPlayer() player.ID = senderID player.key = key player.pos = pos self.playerList.append(player) reply = ptPythonMsg() reply.setContents("Player "+str(len(self.playerList))) reply.setKey(key) reply.send(senderID) reply.setContents("GetPoints") reply.send(senderID) reply.setContents("GetName") reply.send(senderID) def HandleRemove(self,senderID,key): print "ID: "+str(self.ID)+" Removing client ID# "+str(senderID)+" from player list." for player in self.playerList: if player.ID == senderID and player.key == key: self.playerList.remove(player) if len(self.playerList) == 0: # last player left print "ID: "+str(self.ID)+" Last player is requesting a leave, telling him to clean up" if self.countdownStarted: player.SendMessage("StopCountdown") self.countdownStarted = 0 player.SendMessage("ShowIdleAnimation") if player.points != -1: print "ID: "+str(self.ID)+" Giving last player the remaining points in the pot: "+str(self.pot) player.SendMessage("SetPoints "+str(player.points+self.pot)) self.pot = 0 player.SendMessage("Goodbye") #self.ResetGame() break for num in range(len(self.playerList)): # let everyone know of their new player numbers numberMsg = ptPythonMsg() numberMsg.setKey(self.playerList[num].key) numberMsg.setContents("Number "+str(num+1)) numberMsg.send(self.playerList[num].ID) def HandleChoice(self,senderID,key,choice): print "ID: "+str(self.ID)+" Player #"+str(senderID)+" has chosen "+str(choice) for player in self.playerList: if player.ID == senderID and player.key == key: if player.points != -1 and not player.isPlaying: ante = self.CalculateAnte(player.points) player.points -= ante self.pot += ante player.isPlaying = 1 player.SendMessage("SetPoints "+str(player.points)) player.choice = choice self.HandlePlayerReady() def HandleCountdownFinished(self): print "ID: "+str(self.ID)+" Countdown has finished" self.PlayGame() def HandleChoiceAnimFinished(self): print "ID: "+str(self.ID)+" Choice animation has finished" if not self.HandleGameWinner(): self.ResetRound() self.SendToAll("ShowIdleAnimation") self.SendToAll("Enable") def HandleWinAnimFinished(self): self.SendToAll("ShowIdleAnimation") self.SendToAll("Enable") def HandleLinkIn(self,senderID,key): self.agePlayers.append((senderID,key)) if len(self.queueCleanup) != 0: for item in self.queueCleanup: cleanup = ptPythonMsg() cleanup.setContents("Cleanup "+str(item)) cleanup.setKey(self.agePlayers[0][1]) cleanup.send(self.agePlayers[0][0]) self.queueCleanup = [] idle = ptPythonMsg() idle.setContents("ShowIdleAnimation") idle.setKey(self.agePlayers[0][1]) idle.send(self.agePlayers[0][0]) self.SendTableState(senderID,key) def HandlePoints(self,senderID,key,points): print "ID: "+str(self.ID)+" Player ID# "+str(senderID)+" has "+str(points)+" points" for player in self.playerList: if player.ID == senderID and player.key == key: player.points = points if player.name != "": self.SendWelcomeMsg(player.name,player.points) def HandleName(self,senderID,key,name): for player in self.playerList: if player.ID == senderID and player.key == key: player.name = name if player.points != -1: self.SendWelcomeMsg(player.name,player.points) return def onInit(): global heekTables print "RestorationGuild.py is initializing" heekTables = [] def onShutdown(): print "RestorationGuild.py is shutting down" #def onUpdate(secs): #global curtime #global lastupdate #global heekPlayerList #if lastupdate == 0: #lastupdate = secs #curtime = secs #if curtime - lastupdate >= 1: # put any code here that wants to be run every second (nothing currently) #lastupdate += 1 def onClientLeft(ID): global heekTables for table in heekTables: table.ClientLeft(ID) def onMsgReceived(msg): global heekTables msgContents = msg.getContents() senderID = msg.getSenderID() key = msg.getKey() print "Message received from client. ID#: "+str(msg.getSenderID())+" Contents: "+msg.getContents() if len(msgContents) > 3 and msgContents[:3] == "Add": # they want to be added to our player list options = msgContents[4:].split(' ') pos = options[0] tableID = options[1] for table in heekTables: if table.ID == tableID: table.HandleAdd(senderID,key,pos) elif msgContents == "Remove": # they want to be removed from our player list for table in heekTables: if table.PlayerIDInGame(senderID): table.HandleRemove(senderID,key) elif msgContents == "Rock": for table in heekTables: if table.PlayerIDInGame(senderID): table.HandleChoice(senderID,key,kRock) elif msgContents == "Paper": for table in heekTables: if table.PlayerIDInGame(senderID): table.HandleChoice(senderID,key,kPaper) elif msgContents == "Scissors": for table in heekTables: if table.PlayerIDInGame(senderID): table.HandleChoice(senderID,key,kScissors) elif msgContents == "CountdownFinished": for table in heekTables: if table.PlayerIDInGame(senderID): table.HandleCountdownFinished() elif msgContents == "ChoiceAnimFinished": for table in heekTables: if table.PlayerIDInGame(senderID): table.HandleChoiceAnimFinished() elif msgContents == "GameWinAnimFinished": for table in heekTables: if table.PlayerIDInGame(senderID): table.HandleWinAnimFinished() elif len(msgContents) > 6 and msgContents[:6] == "LinkIn": # client telling us it's in the age tableID = msgContents[7:] for table in heekTables: if table.ID == tableID: table.HandleLinkIn(senderID,key) return # must be a new table, add it to our list print("Table ID # " + str(tableID) + " isn't in our list of games, adding it") newTable = heekGame() newTable.ID = tableID newTable.HandleLinkIn(senderID,key) heekTables.append(newTable) elif len(msgContents) > 6 and msgContents[:6] == "Points": points = int(msgContents[7:]) for table in heekTables: if table.PlayerIDInGame(senderID): table.HandlePoints(senderID,key,points) elif len(msgContents) > 4 and msgContents[:4] == "Name": name = msgContents[5:] for table in heekTables: if table.PlayerIDInGame(senderID): table.HandleName(senderID,key,name) else: print "Unknown message, not handling"