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.
496 lines
20 KiB
496 lines
20 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"
|
|
|