Jim's
Tutorials

Fall 2008
course
navigation

RPS Twisted Server

v 3 - Dec 8

#!/usr/bin/env python """ PROGRAM: Rock Paper Scissors... Twisted. - Server version 3. FUNCTION: Receives client connections on port 64800. Client submits a valid move (see Protocol Messages below), and once program receives two moves, returns reslts. ACCEPTED PROTOCOL MESSAGES: Server to Client: "CONNECTED" - Inital connection made; awaiting your move. "REPEAT" - Did not receive valid message. "WIN" - Valid results. "LOSE" "DRAW" Client to server: "REPEAT" - Did not understand message. "ROCK" - Valid moves. "PAPER" "SCISSORS" """ port = 64800 from twisted.internet import protocol, reactor from twisted.protocols import basic CR = "\x0D" LF = "\x0A" EOL = CR + LF machine = { "REPEAT" : (lambda self: self.sendMessage(self.lastSentMessage)), "ROCK" : (lambda self: self.doMove("ROCK")), "PAPER" : (lambda self: self.doMove("PAPER")), "SCISSORS": (lambda self: self.doMove("SCISSORS")), } class rpsProtocol(basic.LineReceiver): def __init__(self): self.lastSentMessage = "" def sendMessage(self, message): self.lastSentMessage = message self.transport.write(message + EOL) def connectionMade(self): self.ipAddress = self.transport.getPeer() print "Connection established with %s" % self.ipAddress self.sendMessage("CONNECTED") def connectionLost(self, reason): print "Connection lost from %s" % self.ipAddress def lineReceived(self, line): """Do the right thing when a line is received from the client.""" if machine.has_key(line): machine[line](self) else: self.sendMessage("REPEAT") def doMove(self, move): """Either adds player and move to self.factory.playerWhoMoved or sends user' move and other player & their move to judgeMoves.""" if self.factory.playerWhoMoved: player2 = self.factory.playerWhoMoved.pop() self.judgeMoves(move, player2) else: self.factory.playerWhoMoved.append([self,move]) def judgeMoves(self, player1move, player2): """This function judges possible results, putting results into a list of two integers, with player1 as [0] and player2 [1], and sends results to both players. Note: Player 2 gets passed as a list: [0] is player's protocol, [1] his-or-her move.""" possibleResults = { "ROCK/PAPER" : [0,1], "PAPER/SCISSORS" : [0,1], "SCISSORS/ROCK" : [0,1], "ROCK/ROCK" : [0,0], "SCISSORS/SCISSORS" : [0,0], "PAPER/PAPER" : [0,0], "PAPER/ROCK" : [1,0], "SCISSORS/PAPER" : [1,0], "ROCK/SCISSORS" : [1,0] } moves = player1move + '/' + player2[1] results = possibleResults[moves] print "Player 1: %s, Player 2: %s." % (player1move, player2[1]), # A '1' is a win, '0' is a loss or draw. if results[0]: player2[0].sendMessage("LOSE") self.sendMessage("WIN") print "Player 1 wins." elif results[1]: player2[0].sendMessage("WIN") self.sendMessage("LOSE") print "Player 2 wins." else: player2[0].sendMessage("DRAW") self.sendMessage("DRAW") print "Draw." class rpsFactory(protocol.ServerFactory): protocol = rpsProtocol def __init__(self): self.playerWhoMoved = [] print "-- starting rps server --" reactor.listenTCP(port, rpsFactory()) reactor.run()

v 2 - Dec 1 in Jim's office

#!/usr/bin/env python """ Dec 1 in Jim's office, continuing work on RPC server. *** This is incomplete *** version 2 """ port = 64800 from twisted.internet import protocol, reactor from twisted.protocols import basic CR = "\x0D" LF = "\x0A" EOL = CR + LF machine = { "REPEAT" : (lambda self: self.sendMessage(self.lastSentMessage)), "ROCK" : (lambda self: self.doMove("ROCK")), "PAPER" : (lambda self: self.doMove("PAPER")), "SCISSORS": (lambda self: self.doMove("SCISSORS")), } class rpsProtocol(basic.LineReceiver): def __init__(self): self.lastSentMessage = "" def sendMessage(self, message): self.lastSentMessage = message self.transport.write(message + EOL) def connectionMade(self): self.ipAddress = self.transport.getPeer() print "Connection established with %s" % self.ipAddress self.factory.registerClient(self) self.sendMessage("CONNECTED") def connectionLost(self, reason): self.factory.deleteClient(self) print "Connection lost from %s" % self.ipAddress def lineReceived(self, line): """Do the right thing when a line is received from the client.""" if machine.has_key(line): machine[line](self) else: self.sendMessage("REPEAT") # print "server got line '%s' from %s" % (line, self.ipAddress) # self.transport.write("You said '%s'.\r\n" % (line)) class rpsFactory(protocol.ServerFactory): protocol = rpsProtocol def __init__(self): self.playersWaiting = [] # [client1, client2, ...] self.playerWhoMoved = '' self.playersMove = '' def registerPlayer(self, player): if self.playersWaiting: self.pairsPlaying.append((self.playersWaiting.pop(), player)) else: self.waitingPlayers.append(client) def moveMade(self, player, move): # if someone else has made a move, pair 'em up, opponent = playing player.sendMessage("WIN") def deletePlayer(self): self.clientList.remove(self) print "-- starting rps server --" reactor.listenTCP(port, rpsFactory()) reactor.run()

v. 1.1 - Dec 1

{0: <twisted.internet.address._ServerFactoryIPv4Address object at 0xb6e3f0>} {0: <twisted.internet.address._ServerFactoryIPv4Address object at 0xb6e690>}
#!/usr/bin/env python """ In tutorial with Jim M on Nov 3, exploring examples at http://twistedmatrix.com/projects/core/documentation/howto/tutorial/intro.html """ port = 64800 from twisted.internet import protocol, reactor from twisted.protocols import basic class rpsProtocol(basic.LineReceiver): def connectionMade(self): print "Connection established." print self.transport.getPeer() self.transport.write("CONNECTED") def connectionLost(self, reason): print "Connection lost." def lineReceived(self, line): """Do something when a line is received from the client.""" print "server got line '%s'" % (line) self.transport.write("You said '%s'.\r\n" % (line)) class rpsFactory(protocol.ServerFactory): protocol = rpsProtocol def __init__(self): self.numClients = 0 self.clientList = {} """ def buildProtocol(self, addr): self.clientList[self.numClients] = addr print self.clientList """ print "-- starting rps server --" reactor.listenTCP(port, rpsFactory()) reactor.run()

v. 1 - Nov 10

Not quite an update on your code, trying to figure out how twisted processes work and then twisted deferreds. Then I can begin adapting my RPS Server Finite State Machine into the twisted server framework.
#!/usr/bin/env python """ In tutorial with Jim M on Nov 3, exploring examples at http://twistedmatrix.com/projects/core/documentation/howto/tutorial/intro.html """ port = 64800 from twisted.internet import protocol, reactor from twisted.protocols import basic class rpsProtocol(basic.LineReceiver): def connectionMade(self): print "Connection established." def connectionLost(self, reason): print "Connection lost." def lineReceived(self, line): """Do something when a line is received from the client.""" print "server got line '%s'" % (line) self.transport.write("You said '%s'.\r\n" % (line)) class rpsFactory(protocol.ServerFactory): protocol = rpsProtocol print "-- starting rps server --" reactor.listenTCP(port, rpsFactory()) reactor.run()
http://cs.marlboro.edu/ courses/ fall2008/tutorials/ rdolan/ RPS_Twisted_Server
last modified Monday January 12 2009 12:14 pm EST