|
|
|
from PlasmaServer import *
|
|
|
|
|
|
|
|
heekPlayerList = []
|
|
|
|
curtime = 0
|
|
|
|
lastupdate = 0
|
|
|
|
countdownStarted = 0
|
|
|
|
winners = []
|
|
|
|
pot = 0
|
|
|
|
|
|
|
|
agePlayers = [] # a list of all people in the age, tuple where 0 is ID and 1 is Key
|
|
|
|
queueCleanup = 0 # do we need to send a cleanup message to the first person to link in?
|
|
|
|
|
|
|
|
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.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 SendToAll(message):
|
|
|
|
global heekPlayerList
|
|
|
|
for player in heekPlayerList:
|
|
|
|
player.SendMessage(message)
|
|
|
|
|
|
|
|
|
|
|
|
def CalculateRank(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(points):
|
|
|
|
return CalculateRank(points)
|
|
|
|
|
|
|
|
def SendWelcomeMsg(name,points):
|
|
|
|
global heekPlayerList
|
|
|
|
SendToAll("PlrWelcome "+str(points)+' '+str(CalculateAnte(points))+' '+name)
|
|
|
|
|
|
|
|
def SendStatusMsg(player):
|
|
|
|
player.SendMessage("Points "+str(player.points)+' '+str(CalculateAnte(player.points)))
|
|
|
|
|
|
|
|
def RewardRoundWinners():
|
|
|
|
global winners
|
|
|
|
global heekPlayerList
|
|
|
|
for winner in 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 "lightNum is 0 for some reason...len(winners)="+str(len(winners))+", winner.choice="+str(winner.choice)
|
|
|
|
print "len(heekPlayerList)="+str(len(heekPlayerList))+", 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 heekPlayerList if not player in winners]
|
|
|
|
for loser in losers:
|
|
|
|
loser.SendMessage("Lose "+str(loser.choice))
|
|
|
|
|
|
|
|
def CompareRoundScores(player1, player2):
|
|
|
|
if player1.curRoundScore < player2.curRoundScore:
|
|
|
|
return -1
|
|
|
|
if player1.curRoundScore > player2.curRoundScore:
|
|
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
|
|
def ComputeRoundScores():
|
|
|
|
global heekPlayerList
|
|
|
|
cnt = len(heekPlayerList)
|
|
|
|
|
|
|
|
#if cnt == 1: # for single-player only
|
|
|
|
#heekPlayerList[0].curRoundScore = 1
|
|
|
|
|
|
|
|
for i in range(cnt-1):
|
|
|
|
player1 = heekPlayerList[i]
|
|
|
|
for j in range(i+1,cnt):
|
|
|
|
player2 = heekPlayerList[j]
|
|
|
|
player1.curRoundScore += player1.ScoreAgainst(player2)
|
|
|
|
player2.curRoundScore += player2.ScoreAgainst(player1)
|
|
|
|
|
|
|
|
def PickRoundWinners():
|
|
|
|
global heekPlayerList
|
|
|
|
global winners
|
|
|
|
rwCopy = heekPlayerList
|
|
|
|
rwCopy.sort(CompareRoundScores)
|
|
|
|
big=rwCopy[len(rwCopy)-1].curRoundScore
|
|
|
|
if big>0:
|
|
|
|
winners = [winner for winner in rwCopy if winner.curRoundScore == big]
|
|
|
|
|
|
|
|
def CompareRoundsWon(player1, player2):
|
|
|
|
if player1.roundsWon < player2.roundsWon:
|
|
|
|
return -1
|
|
|
|
if player1.roundsWon > player2.roundsWon:
|
|
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
|
|
def PickGameWinners():
|
|
|
|
global winners
|
|
|
|
gameWinners = [winner for winner in 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():
|
|
|
|
global countdownStarted
|
|
|
|
global heekPlayerList
|
|
|
|
if not countdownStarted:
|
|
|
|
print "Starting countdown"
|
|
|
|
SendToAll("StartCountdown")
|
|
|
|
countdownStarted = 1
|
|
|
|
return
|
|
|
|
|
|
|
|
playersReady = [player for player in heekPlayerList if player.choice != kNone]
|
|
|
|
allReady = (len(playersReady) == len(heekPlayerList))
|
|
|
|
|
|
|
|
if allReady and len(playersReady)>1:
|
|
|
|
SendToAll("StopCountdown")
|
|
|
|
|
|
|
|
def ResetGame():
|
|
|
|
global heekPlayerList
|
|
|
|
global winners
|
|
|
|
winners = []
|
|
|
|
for player in heekPlayerList:
|
|
|
|
player.ResetGame()
|
|
|
|
|
|
|
|
def ResetRound():
|
|
|
|
global heekPlayerList
|
|
|
|
global winners
|
|
|
|
winners = []
|
|
|
|
for player in heekPlayerList:
|
|
|
|
player.ResetRound()
|
|
|
|
|
|
|
|
def PlayGame():
|
|
|
|
global countdownStarted
|
|
|
|
global heekPlayerList
|
|
|
|
global pot
|
|
|
|
if not countdownStarted:
|
|
|
|
print "Extra countdown end message received, ignoring"
|
|
|
|
return # extra countdown end message, ignore
|
|
|
|
countdownStarted = 0
|
|
|
|
playersReady = [player for player in heekPlayerList if player.choice != kNone]
|
|
|
|
if len(playersReady) <= 1:
|
|
|
|
print "Only one player was ready, aborting game"
|
|
|
|
ResetRound()
|
|
|
|
SendToAll("ShowIdleAnimation")
|
|
|
|
return
|
|
|
|
print "Disabling player's interfaces"
|
|
|
|
SendToAll("Disable")
|
|
|
|
ComputeRoundScores()
|
|
|
|
PickRoundWinners()
|
|
|
|
RewardRoundWinners()
|
|
|
|
|
|
|
|
def HandleGameWinner():
|
|
|
|
global heekPlayerList
|
|
|
|
global pot
|
|
|
|
gameWinners = PickGameWinners()
|
|
|
|
if len(gameWinners) > 0:
|
|
|
|
print "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"
|
|
|
|
SendToAll("GameWin "+x)
|
|
|
|
pointsToGive = int(pot/len(gameWinners))
|
|
|
|
pot -= pointsToGive*len(gameWinners)
|
|
|
|
for winner in gameWinners:
|
|
|
|
if winner.points != -1:
|
|
|
|
winner.SendMessage("SetPoints "+str(winner.points+pointsToGive))
|
|
|
|
for player in heekPlayerList:
|
|
|
|
if player.ID == winner.ID and player.key == winner.key:
|
|
|
|
player.points += pointsToGive
|
|
|
|
break
|
|
|
|
ResetGame()
|
|
|
|
for player in heekPlayerList:
|
|
|
|
SendStatusMsg(player)
|
|
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
|
|
def SendTableState(ID,key):
|
|
|
|
global heekPlayerList
|
|
|
|
for player in heekPlayerList:
|
|
|
|
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 onInit():
|
|
|
|
global heekPlayerList
|
|
|
|
global lastupdate
|
|
|
|
global countdownStarted
|
|
|
|
global winners
|
|
|
|
global queueCleanup
|
|
|
|
global pot
|
|
|
|
print "Neighborhood.py is initializing"
|
|
|
|
heekPlayerList = []
|
|
|
|
winners = []
|
|
|
|
lastupdate = 0
|
|
|
|
countdownStarted = 0
|
|
|
|
queueCleanup = []
|
|
|
|
pot = 0
|
|
|
|
|
|
|
|
def onShutdown():
|
|
|
|
print "Neighborhood.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 heekPlayerList
|
|
|
|
global agePlayers
|
|
|
|
global queueCleanup
|
|
|
|
position = -1
|
|
|
|
for player in heekPlayerList[:]:
|
|
|
|
if player.ID == ID:
|
|
|
|
position = player.pos
|
|
|
|
heekPlayerList.remove(player)
|
|
|
|
for player in agePlayers[:]:
|
|
|
|
if player[0] == ID:
|
|
|
|
agePlayers.remove(player)
|
|
|
|
if position == -1: # client wasn't playing
|
|
|
|
return
|
|
|
|
print "Client ID# "+str(ID)+" has left, cleaning up after him"
|
|
|
|
if len(heekPlayerList) == 0: # no players left to cleanup the position
|
|
|
|
if len(agePlayers) == 0: # no players in age left to cleanup the table
|
|
|
|
queueCleanup.append(position)
|
|
|
|
else:
|
|
|
|
cleanup = ptPythonMsg()
|
|
|
|
cleanup.setContents("Cleanup "+str(position))
|
|
|
|
cleanup.setKey(agePlayers[0][1])
|
|
|
|
cleanup.send(agePlayers[0][0])
|
|
|
|
cleanup.setContents("ShowIdleAnimation")
|
|
|
|
cleanup.send(agePlayers[0][0])
|
|
|
|
for num in range(len(heekPlayerList)): # let everyone know of their new player numbers
|
|
|
|
numberMsg = ptPythonMsg()
|
|
|
|
numberMsg.setKey(heekPlayerList[num].key)
|
|
|
|
numberMsg.setContents("Number "+str(num+1))
|
|
|
|
numberMsg.send(heekPlayerList[num].ID)
|
|
|
|
if position != -1:
|
|
|
|
SendToAll("Drop "+str(position))
|
|
|
|
|
|
|
|
def onMsgReceived(msg):
|
|
|
|
global heekPlayerList
|
|
|
|
global countdownStarted
|
|
|
|
global agePlayers
|
|
|
|
global queueCleanup
|
|
|
|
global pot
|
|
|
|
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
|
|
|
|
pos = msgContents[4:]
|
|
|
|
for player in heekPlayerList:
|
|
|
|
if player.pos == pos:
|
|
|
|
print "Ignoring client ID# "+str(senderID)+" request to play since someone is already sitting in their requested position: "+str(pos)
|
|
|
|
return
|
|
|
|
print "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
|
|
|
|
heekPlayerList.append(player)
|
|
|
|
reply = ptPythonMsg()
|
|
|
|
reply.setContents("Player "+str(len(heekPlayerList)))
|
|
|
|
reply.setKey(key)
|
|
|
|
reply.send(senderID)
|
|
|
|
reply.setContents("GetPoints")
|
|
|
|
reply.send(senderID)
|
|
|
|
reply.setContents("GetName")
|
|
|
|
reply.send(senderID)
|
|
|
|
elif msgContents == "Remove": # they want to be removed from our player list
|
|
|
|
print "Removing client ID# "+str(senderID)+" from player list."
|
|
|
|
for player in heekPlayerList:
|
|
|
|
if player.ID == senderID and player.key == key:
|
|
|
|
heekPlayerList.remove(player)
|
|
|
|
if len(heekPlayerList) == 0: # last player left
|
|
|
|
print "Last player is requesting a leave, telling him to clean up"
|
|
|
|
if countdownStarted:
|
|
|
|
player.SendMessage("StopCountdown")
|
|
|
|
countdownStarted = 0
|
|
|
|
player.SendMessage("ShowIdleAnimation")
|
|
|
|
if player.points != -1:
|
|
|
|
print "Giving last player the remaining points in the pot: "+str(pot)
|
|
|
|
player.SendMessage("SetPoints "+str(player.points+pot))
|
|
|
|
pot = 0
|
|
|
|
player.SendMessage("Goodbye")
|
|
|
|
#ResetGame()
|
|
|
|
break
|
|
|
|
for num in range(len(heekPlayerList)): # let everyone know of their new player numbers
|
|
|
|
numberMsg = ptPythonMsg()
|
|
|
|
numberMsg.setKey(heekPlayerList[num].key)
|
|
|
|
numberMsg.setContents("Number "+str(num+1))
|
|
|
|
numberMsg.send(heekPlayerList[num].ID)
|
|
|
|
elif msgContents == "Rock":
|
|
|
|
print "Player #"+str(senderID)+" has chosen rock"
|
|
|
|
for player in heekPlayerList:
|
|
|
|
if player.ID == senderID and player.key == key:
|
|
|
|
if player.points != -1 and not player.isPlaying:
|
|
|
|
ante = CalculateAnte(player.points)
|
|
|
|
player.points -= ante
|
|
|
|
pot += ante
|
|
|
|
player.isPlaying = 1
|
|
|
|
player.SendMessage("SetPoints "+str(player.points))
|
|
|
|
player.choice = kRock
|
|
|
|
HandlePlayerReady()
|
|
|
|
return
|
|
|
|
elif msgContents == "Paper":
|
|
|
|
print "Player #"+str(senderID)+" has chosen paper"
|
|
|
|
for player in heekPlayerList:
|
|
|
|
if player.ID == senderID and player.key == key:
|
|
|
|
if player.points != -1 and not player.isPlaying:
|
|
|
|
ante = CalculateAnte(player.points)
|
|
|
|
player.points -= ante
|
|
|
|
pot += ante
|
|
|
|
player.isPlaying = 1
|
|
|
|
player.SendMessage("SetPoints "+str(player.points))
|
|
|
|
player.choice = kPaper
|
|
|
|
HandlePlayerReady()
|
|
|
|
return
|
|
|
|
elif msgContents == "Scissors":
|
|
|
|
print "Player #"+str(senderID)+" has chosen scissors"
|
|
|
|
for player in heekPlayerList:
|
|
|
|
if player.ID == senderID and player.key == key:
|
|
|
|
if player.points != -1 and not player.isPlaying:
|
|
|
|
ante = CalculateAnte(player.points)
|
|
|
|
player.points -= ante
|
|
|
|
pot += ante
|
|
|
|
player.isPlaying = 1
|
|
|
|
player.SendMessage("SetPoints "+str(player.points))
|
|
|
|
player.choice = kScissors
|
|
|
|
HandlePlayerReady()
|
|
|
|
return
|
|
|
|
elif msgContents == "CountdownFinished":
|
|
|
|
print "Countdown has finished"
|
|
|
|
PlayGame()
|
|
|
|
elif msgContents == "ChoiceAnimFinished":
|
|
|
|
print "Choice animation has finished"
|
|
|
|
if not HandleGameWinner():
|
|
|
|
ResetRound()
|
|
|
|
SendToAll("ShowIdleAnimation")
|
|
|
|
SendToAll("Enable")
|
|
|
|
elif msgContents == "GameWinAnimFinished":
|
|
|
|
SendToAll("ShowIdleAnimation")
|
|
|
|
SendToAll("Enable")
|
|
|
|
elif msgContents == "LinkIn": # client telling us it's in the age
|
|
|
|
agePlayers.append((senderID,key))
|
|
|
|
if len(queueCleanup) != 0:
|
|
|
|
for item in queueCleanup:
|
|
|
|
cleanup = ptPythonMsg()
|
|
|
|
cleanup.setContents("Cleanup "+str(item))
|
|
|
|
cleanup.setKey(agePlayers[0][1])
|
|
|
|
cleanup.send(agePlayers[0][0])
|
|
|
|
queueCleanup = []
|
|
|
|
idle = ptPythonMsg()
|
|
|
|
idle.setContents("ShowIdleAnimation")
|
|
|
|
idle.setKey(agePlayers[0][1])
|
|
|
|
idle.send(agePlayers[0][0])
|
|
|
|
SendTableState(senderID,key)
|
|
|
|
elif len(msgContents) > 6 and msgContents[:6] == "Points":
|
|
|
|
points = int(msgContents[7:])
|
|
|
|
print "Player ID# "+str(senderID)+" has "+str(points)+" points"
|
|
|
|
for player in heekPlayerList:
|
|
|
|
if player.ID == senderID and player.key == key:
|
|
|
|
player.points = points
|
|
|
|
if player.name != "":
|
|
|
|
SendWelcomeMsg(player.name,player.points)
|
|
|
|
return
|
|
|
|
elif len(msgContents) > 4 and msgContents[:4] == "Name":
|
|
|
|
name = msgContents[5:]
|
|
|
|
for player in heekPlayerList:
|
|
|
|
if player.ID == senderID and player.key == key:
|
|
|
|
player.name = name
|
|
|
|
if player.points != -1:
|
|
|
|
SendWelcomeMsg(player.name,player.points)
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
print "Unknown message, not handling"
|