Esempio n. 1
0
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
Esempio n. 2
0
def play(con, msg):
    att_play = RE_GTPLAY.match(msg)  # use the RE to check the message
    client = None
    for c in gvals.clientlist:  # see if we can find the client
        if c.equals(con):
            client = c
            break
    if client == None:  # if we did not, close the connection, cannot play if we don't know who you are
        close(con)
        return
    if client in gvals.lobby:  # if you're in the lobby you can't send a play message, strike
        strike(client, 31)
        return
    if not Table.player[Table.curplayer].equals(con):
        strike(client, 15)  # you're not the current player, strike
        server_hand(con)
        return
    if len(msg) > 11:
        strike(client, 33)  # your message was too long, strike
        server_hand(con)
        return

    if att_play:  # if the RE found something
        # build the play (an array of integers)
        play = [
            int(att_play.group("c1")),
            int(att_play.group("c2")),
            int(att_play.group("c3")),
            int(att_play.group("c4"))
        ]
        errcode = Table.checkPlay(
            play)  # check the play, errorcode being what it returns
        thisplayer = Table.curplayer  # set thisplayer to current player int so we can change curplayer later
        cards = 0  # number of cards in play
        for acard in play:  # count the non 52 cards
            if acard != 52:
                cards += 1
        if errcode > 0:  # errocdes > 0 == strikable offenses
            strike(
                client, errcode
            )  # send strikes, then hand, then tell them they can play again
            Table.sendhand(Table.player[Table.curplayer].socket,
                           Table.handof[Table.curplayer])
            Table.Play()
            return
        elif errcode == -1:  #pass situation, they passed, get the next player
            Table.passof[Table.curplayer] = 1
            Table.getNextPlayer()
        elif errcode == -2:  #match situation, they force the next player to pass, then the next player after that gets to play
            Table.getNextPlayer()
            Table.passof[Table.curplayer] = 1
            Table.getNextPlayer()
            Table.numcards = cards
            Table.tablecards = play
            Table.tablecards.sort()
        elif errcode == -3:  #two played, if a two was played, we start a new round
            Table.newround()
        else:  # otherwise the play was a normal play, set status to waiting, get next player, set the table cards to what was played
            Table.passof[Table.curplayer] = 0
            Table.getNextPlayer()
            Table.numcards = cards
            Table.tablecards = play
            Table.tablecards.sort()

        for card in play:  #for each of the cards in the play, remove them from the hand if they were in there
            if card in Table.handof[thisplayer]:
                Table.handof[thisplayer].remove(card)
            elif card != 52:  # if the card wasn't in the hand and wasn't a 52, the card wasn't removed, this should never happen, this means checkPlay failed
                print "Card was not removed..."

        if len(
                Table.handof[thisplayer]
        ) == 0:  # if the player is now out of cards, we add them to the finished list
            Table.finished.appendleft(Table.player[thisplayer])
            print "%s added to finished list." % Table.player[thisplayer].name
            print "----------------------------"

        if gvals.state == 3:  # if we're still in the play state, play again
            Table.Play()
    else:  # this means the RE couldn't match the message
        strike(client, 34)