simple turn-based multiplayer game via TCP server/client

Discussion in 'Python' started by greywine@gmail.com, Jan 4, 2009.

  1. Guest

    Hi everyone,

    I'm learning python to get a multiplayer roleplaying game up and
    running.

    I didn't see any simple examples of multiplayer games on the web so I
    thought I'd post mine here. I choose Rock, Paper, Scissors as a first
    game to experiment with as the game logic/options are easy to
    implement and understand.

    Initially, I tried to get the socketserver.TCPServer example in the
    Python Docs to work, but couldn't get my game variables into the
    handle method of the class MyTCPHandler. And I didn't know how else
    to do it. I ended up creating my own server & client out of simple
    sockets based on the simple echo server & client examples in the
    Python Docs.

    I also wanted to send chat messages OR game variables back & forth,
    but I couldn't figure out how to do the OR, so the basic idea in this
    implementation is to send the dictionary 'game' back and forth. game
    dict contains all the gaming variables as well as any chat messages.
    The program processes results depending on whether the game is
    starting, there's a chat message, or there's a game move.

    Finally, in testing, I ran the server in IDLE, but I had to load a
    command prompt and switch to c:\python30; then type 'python
    rpsmulti.py' for the client every time. Anyone know how to test
    server/client code strictly in IDLE?

    Anyway, try it out and let me know how you would improve it.

    John R.

    # NAME: rpsmulti.py
    # DESCRIPTION: rock, paper, scissors game multiplayer game
    # AUTHOR: John Robinson
    # DATE: 1/3/09
    # VERSION: Python 3.0
    # TO DO:
    # .server_address instead of HOST, PORT?

    import socket
    from random import choice
    from pickle import dumps, loads
    from pprint import pprint

    HOST, PORT = "localhost", 9999 # defined for now
    BUFFSIZE = 1024 # for socket.send & recv commands
    BACKLOG = 2 # number of clients supported by
    server
    SECONDS = 3 # seconds until socket.timeout (not
    implemented)
    # moves dict to translate 'rps' choice
    MOVES = {'r':'Rock',
    'p':'Paper',
    's':'Scissors'}
    # outcome dict stores result for all possible scenarios
    OUTCOME = {('p','r'): 'win',
    ('r','s'): 'win',
    ('s','p'): 'win',
    ('p','p'): 'draw',
    ('r','r'): 'draw',
    ('s','s'): 'draw',
    ('r','p'): 'lose',
    ('s','r'): 'lose',
    ('p','s'): 'lose'}

    def main_menu(game):
    """ initialize game dict variables & opening screen of the game
    """
    game['total'] = 0 # total number of games played
    game['won'] = 0 # total games won by player
    game['lost'] = 0 # total games lost by player
    game['drew'] = 0 # total games drew by player
    game['move'] = '' # player's move (rps)
    game['message'] = '' # player's chat message
    game['sentmessage'] = '' # player's previous message
    game['start'] = True # setting up the game boolean

    print("\tROCK PAPER SCISSORS\n")
    if game['name']=='': # if returning to menu don't display
    the following
    game['name'] = get_name()
    print("Welcome "+game['name']+". Remember...")
    print("Rock smashes scissors! Paper covers Rock! Scissors cuts
    paper!\n")
    print("1. Play single player game")
    print("2. Start two player game")
    print("3. Join two player game")
    print("4. Quit")
    print()
    c = safe_input("Your choice? ", "1234")
    c = int(c)
    if c==1:
    one_player(game)
    elif c==2:
    start_two_player(game)
    elif c==3:
    two_player_join(game)
    else:
    print('Play again soon.')

    def safe_input(prompt, values='abcdefghijklmnopqrstuvwxyz'):
    """ gives prompt, checks first char of input, assures it meets
    given values
    default is anything goes """
    while True:
    i = input(prompt)
    try:
    c = i[0].lower()
    except IndexError: # the only possible error?!
    if c=='':
    print("Try again.")
    else:
    if c not in values: # some other character
    print("Try again.")
    else: # looks good. continue.
    break
    return i

    def get_name():
    """ returns input as name """
    while True:
    name = input("What is your name? ")
    check = input(name + ". Correct (y/n)? ")
    if check[0] in 'yY':
    break
    return name

    def get_result(player, opponent):
    """ reports opponent's choice;
    checks player and opponent dicts ['move'] against OUTCOME
    dict;
    reports result
    returns player dict with updated values """
    print(opponent['name'], 'chose %s.' % (MOVES[opponent['move']]))
    # check lookout dict (OUTCOME dictionary)
    result = OUTCOME[(player['move'], opponent['move'])]
    # update game variables
    player['total'] += 1
    if result=='win':
    print('%s beats %s. You win.' % (MOVES[player['move']], MOVES
    [opponent['move']]))
    player['won'] += 1
    elif result=='draw':
    print('%s - %s: no one wins. You draw.' % (MOVES[player
    ['move']], MOVES[opponent['move']]))
    player['drew'] += 1
    else:
    print('%s loses to %s. You lose.' % (MOVES[player['move']],
    MOVES[opponent['move']]))
    player['lost'] += 1
    return player

    def one_player(game):
    """ implements one player game with minimal opponent dict """
    print("\nType (R)ock, (P)aper or (S)cissors to play. (q)uit to
    return to \
    main menu.")
    opponent = {}
    opponent['name'] = 'Computer'

    # gaming loop
    while True:
    # gets player's choice
    game['move'] = safe_input('1, 2, 3, GO! ','rpsq')
    if game['move']=='q':
    break
    # computer chooses via random.choice
    opponent['move'] = choice('rps')
    # check game outcome dict
    game = get_result(game, opponent)

    # exit loop
    print('\nYou won %s, lost %s, drew %s (%s total)\n' % \
    (game['won'],game['lost'],game['drew'],game['total']))
    main_menu(game)

    def start_two_player(game):
    """ starts tcp server and implements two player game
    game dict = player 1"""
    # Create a socket (SOCK_STREAM means a TCP socket)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind((HOST, PORT))
    sock.listen(BACKLOG)
    serverip, serverport = sock.getsockname()
    print("Running at %s, %s" % (serverip, serverport))
    print("\nType (R)ock, (P)aper or (S)cissors to play. (q)uit to \
    return to main menu.")
    print("Waiting for player...")

    client, address = sock.accept()
    clientip, clientport = address
    # server/game loop
    while True:
    try:
    P2game = loads(client.recv(BUFFSIZE)) # receive other
    game variables
    except EOFError: # if available
    print(P2game['name'], "left the game.")
    break
    client.send(dumps(game)) # send our
    variables
    # it's either the start...
    if P2game['start']:
    print(P2game['name'],"logged on at", clientip, clientport)
    game['start'] = False
    # or there's a message
    if P2game['message']!='' and P2game['message']!=game
    ['sentmessage']:
    print(P2game['name']+': '+P2game['message'])
    game['sentmessage'] = P2game['message'] # to avoid many
    print calls
    game['move'] = '' # message always takes
    priority
    # or there's a move
    if game['move']=='':
    game['move'] = safe_input('1, 2, 3, GO! ')
    if game['move']=='q':
    break
    elif game['move'] not in 'rps':
    game['message'] = game['move']
    game['move'] = ''
    # only check result if P2game also made a move
    if P2game['move']!='':
    # check game outcome dict
    game=get_result(game, P2game)
    game['move']=''
    # exit loop
    client.close()
    print('\nYou won %s, lost %s, drew %s (%s total)\n' % \
    (game['won'],game['lost'],game['drew'],game['total']))
    main_menu(game)

    def two_player_join(game):
    """ joins a tcp server two player game
    game dict = player 2"""
    # Create a socket (SOCK_STREAM means a TCP socket)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((HOST, PORT))

    print("\nType (R)ock, (P)aper or (S)cissors to play. (q)uit to \
    return to main menu.")

    # client/game loop
    while True:
    sock.send(dumps(game))
    try:
    P1game = loads(sock.recv(BUFFSIZE))
    except EOFError:
    print(P1game['name'], "left the game.")
    break
    if P1game['start']:
    print("You're connected to "+P1game['name']+"'s game.")
    game['start'] = False
    if P1game['message']!='' and P1game['message']!=game
    ['sentmessage']:
    print(P1game['name']+': '+P1game['message'])
    game['sentmessage'] = P1game['message']
    game['move'] = ''
    if game['move']=='':
    game['move'] = safe_input('1, 2, 3, GO! ')
    if game['move']=='q':
    break
    elif game['move'] not in 'rps':
    game['message'] = game['move']
    game['move'] = ''
    if P1game['move']!='':
    # check game outcome dict
    game=get_result(game, P1game)
    game['move']=''
    # exit loop
    sock.close()
    print('\nYou won %s, lost %s, drew %s (%s total)\n' % \
    (game['won'],game['lost'],game['drew'],game['total']))
    main_menu(game)

    if __name__=='__main__':
    game = {} # initialize game dict to store all game
    variables
    game['name'] = '' # player's name initially
    main_menu(game)
    , Jan 4, 2009
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Lt
    Replies:
    5
    Views:
    526
  2. Tlo
    Replies:
    5
    Views:
    705
  3. Replies:
    0
    Views:
    921
  4. vish_dude
    Replies:
    1
    Views:
    1,176
    mdtsdca
    Nov 1, 2007
  5. Replies:
    2
    Views:
    134
Loading...

Share This Page