def swap(con, msg): if len( msg ) > 2: #if length is greater than 2 or less than 2, it wasn't a proper message send_strike(con, 32) return elif len(msg) < 2: send_strike(con, 34) return else: try: # attempt to convert it to an integer returncard = int(msg) except: # if unable to, send a strike send_strike(con, 30) return # if there is no player 1, or this isn't player 1, send strike then the hand if necessary if not Table.player[1] or not Table.player[1].equals(con): send_strike(con, 71) server_hand(con) return # if we don't want to receive a swap message right now, send a strike if gvals.state != 2: send_strike(con, 72) server_hand(con) return # if player 1 doesn't have the card, send strike and update their timeout timer if not returncard in Table.handof[1]: strike(Table.player[1], 70) Table.sendhand(con, Table.handof[1]) gvals.to_time = time.time() return else: # otherwise, remove it from player 1's hand, append it to player 7's hand, sort 7 Table.handof[1].remove(returncard) Table.handof[7].append(returncard) Table.handof[7].sort() try: # send the swap message to the scumbag so they know what they lost and what they received Table.player[7].socket.send("[swaps|%02d|%02d]" % (returncard, Table.wcard)) except socket.error: Table.passof[7] = 2 Table.numplayers -= 1 Table.getNextPlayer() gvals.state = D_STATE.WAITPLAY # state is then put into the waiting for play state Table.StartGame() # and we start the game
def main(): keepalive = 1 # Variable for keeping the server running. HOST = '' # Localhost PORT = 36789 # Port number BLOG = 5 # Number of concurrent listens SIZE = 4096 # Size of data for receiving data # Command line argument parser. parser = argparse.ArgumentParser() parser.add_argument( "-l", dest="l", type=int, default=D_LTIME, help="Sets the lobby timeout value (going from no game -> new game).") parser.add_argument( "-t", dest="t", type=int, default=D_TIMEO, help="Sets the timeout value (for plays/warlord swap).") parser.add_argument( "-m", dest="m", type=int, default=D_MINPL, help="Sets the minimum number of players for a game to run.") parser.add_argument( "-s", dest="s", type=int, default=D_STRIK, help= "Sets the number of strikes given out before disconnecting a client.") parser.add_argument( "-c", dest="c", type=int, default=D_CONNS, help="Sets the maximum number of clients allowed in the lobby.") args = parser.parse_args() # Set values based on command line (or default values if none specified.) gvals.ltimeout = args.l gvals.timeout = args.t if args.m >= 3 and args.m <= 7: gvals.minplay = args.m elif args.m < 3: print "Minimum number of players to start a game must be 3 or greater. Setting value to 3." gvals.minplay = 3 else: print "Maximum number of players for a game is 7. Useless it is to wait for more than 7. Setting to 7." gvals.minplay = 7 if args.l < 35: gvals.maxclients = 35 elif args.l > 90: gvals.maxclients = 90 else: gvals.maxclients = args.l gvals.strikeout = args.s if args.s < 10 else 9 # strikes must be a single digit, i.e. max of 9 try: # attempt to open the socket we need server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # the next line allows us to re-establish the socket immediately after closing server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind((HOST, PORT)) server.listen(BLOG) inlist.append( server) # ensure that we're listening to the socket we opened except socket.error: # unable to establish the socket print "Unable to establish socket. Terminating." server.close() # ensure that we closed the server return print "Server live at " + str(socket.gethostbyname(socket.gethostname())) print "Clients connected: 0" print "----------------------------------" gvals.state = D_STATE.WAITMIN # set default state to waiting for min players # Create queue for reading system in. inputQueue = Queue.Queue() lock = threading.Lock() inThread = threading.Thread(target=input_thread, args=( inputQueue, lock, )) inThread.daemon = True inThread.start() while keepalive: try: # use select statement, don't want it blocking for more than a second at any time inready, outready, exceptready = select.select(inlist, [], [], 1.0) except select.error: print "Unable to use select statement." break lock.acquire() while (not inputQueue.empty()): #check for quit command from terminal line = inputQueue.get().strip() if line == 'quit' or line == 'q': keepalive = 0 lock.release() for s in inready: # loop through all of the sockets with information ready to be read if s == server: # if the socket is our first socket, we're accepting the connection for a new client try: # attempt to accept the connection, then add it input list client, address = server.accept() inlist.append(client) print "Clients connected: " + str(len(inlist) - 1) print "----------------------------------" except socket.error: print "Unable to accept client connection." else: # otherwise we had someone sending us a message! try: data = s.recv(SIZE, socket.MSG_PEEK) # it is christmas! peek! newdata = data.replace('\n', '').replace( '\r', '') # check to see if its just \n or \r if len(data) > 0 and newdata == '': data = s.recv(len(data)) # pull out if so elif newdata: # check newline for correct messages data = data.replace('\n', ' ').replace( '\r', ' ') # replace \n and \r in data peek = RE_CHKMSG.match(data) # peek = proper message throwaway = RE_CHKLEN.match( data) # throwaway = some string before [ if throwaway and throwaway.group( "len"): # if we have something to throwaway data = s.recv( len(throwaway.group("len") )) # pull it from the buffer (and only it) tdata = data.replace('\n', '').replace('\r', '') if tdata: # check to see if it was just \n and \r send_strike( s, 30 ) # if not, send strike to whomever this was elif peek and peek.group( "chk" ): # otherwise, if we had a properly formatted message data = s.recv(len( peek.group("chk"))) # pull it out newdata = data.replace('\n', '').replace('\r', '') parserecv( s, newdata) # throw \n and \r away, then parse it elif len( newdata ) > 512: # if we've gotten 512 characters, and no [], then throw it all away data = s.recv(SIZE) send_strike(s, 30) # and send a strike elif not data: close(s) # if they send us nothing, we close them except socket.error: # on socket error, we close them close(s) continue # Check the state, and do the appropriate action. if gvals.state == D_STATE.WAITMIN: # check if we're waiting for the minimum number of players before starting if len(gvals.lobby ) >= gvals.minplay: # check number of players in lobby gvals.state = D_STATE.LTIMEOUT # set state to lobby timeout state (waiting for set time before starting) gvals.to_time = time.time() # recording current time print "Play starting in " + str(gvals.ltimeout) + " seconds." print "----------------------------------" elif gvals.state == D_STATE.LTIMEOUT: # if we're waiting for a specified time curtime = time.time() # get current time if curtime > gvals.to_time + gvals.ltimeout: # if we're less than the recorded time + timeout value, do nothing print "Let the game begin!" print "----------------------------------" Table.notranked = 1 # make sure when going from lobby timeout to new hand we're doing unranked Table.newhand() # else start a new hand elif gvals.state == D_STATE.WTIMEOUT: # waiting for warlord message Table.checkPlayers() # update the number of players at the table if Table.numplayers == 0: # if everyone left we can go to the waiting for players state gvals.state = D_STATE.WAITMIN print "No players at table. Waiting for players." print "----------------------------------" else: # otherwise check the time rightnow = time.time() if (gvals.timeout > 0 and rightnow > gvals.to_time + gvals.timeout ) or Table.player[1] not in gvals.clientlist: strike( Table.player[1], 20 ) # we haven't received a message yet, strike the player (warlord is default player 1) if Table.passof[ 1] == 2: # if they're dead, we need to get the next player, because they were set as current player Table.getNextPlayer() if Table.wcard in Table.handof[ 1]: # remove wcard if we had it in their hand Table.handof[1].remove(Table.wcard) Table.handof[7].append( Table.wcard ) # put the 'wcard' back in the scumbag's hands Table.handof[7].sort() Table.player[7].socket.send("[swaps|52|52]") Table.StartGame() # start the game elif gvals.state == D_STATE.WAITPLAY: # waiting for current player to send their play message Table.checkPlayers() # check how many players we have if Table.numplayers == 0: # if none, wait for new players print "No players at table. Waiting for players." print "----------------------------------" gvals.state = D_STATE.WAITMIN elif Table.passof[ Table. curplayer] == 2: # if the player died, get the next player and play Table.getNextPlayer() Table.Play() else: # otherwise, check the time and strike if necessary rightnow = time.time() if gvals.timeout > 0 and rightnow > gvals.to_time + gvals.timeout: strike(Table.player[Table.curplayer], 20) Table.passof[Table.curplayer] = 1 if Table.passof[ Table. curplayer] != 2 else 2 # set pass value to pass or dead, whichever applies Table.getNextPlayer() # get next player if gvals.state == D_STATE.WAITPLAY: # if we're still in the waiting for play state, we can play Table.Play() elif gvals.state == D_STATE.NEWGAME: # we need to start a new hand print "A new round is now starting." print "----------------------------------" Table.notranked = 0 # this state is only entered into if we were in a hand already, so by default it is ranked Table.newhand() for c in gvals.clientlist: # send quit message to everyone try: c.socket.send("[squit]\n") except socket.error: # close the socket of anyone who can't have the message sent to them close(c.socket) server.close() # we've exited our run loop, so close the socket