You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

497 lines
19 KiB

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"