-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathXNOP_client.py
More file actions
138 lines (122 loc) · 4.41 KB
/
Copy pathXNOP_client.py
File metadata and controls
138 lines (122 loc) · 4.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Neil Marcellini
# 3/5/21
# COMP 429
# A client for XNOP
import TTTEngine as ttt
import argparse, socket, logging
# Comment out the line below to not print the INFO messages
logging.basicConfig(level=logging.INFO)
def recv_until(sock, suffix):
"""Receive bytes over socket `sock` until we receive the `suffix`."""
message = sock.recv(1024)
if not message:
raise EOFError('socket closed')
while not message.endswith(suffix):
data = sock.recv(1024)
if not data:
raise IOError('received {!r} then socket closed'.format(message))
message += data
return message
def validate_move(move_input, engine):
# insure that a move_input is in the proper format
# and that it is valid with the engine
valid_input = len(move_input) == 1 and move_input.isnumeric()
valid_move = False
if valid_input:
valid_move = engine.is_move_valid(int(move_input))
return valid_move
def client(host,port):
# connect
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host,port))
sock.setblocking(True)
logging.info('Connect to server: ' + host + ' on port: ' + str(port))
msg = recv_until(sock, b"\n").decode('utf-8')
# send Join command
sock.send(b"Join")
join_msg = sock.recv(len("Joined")).decode('utf-8')
print(join_msg)
if join_msg == "ErrorS":
print("Game already started. Try again later.")
# quit
sock.close()
return
# ask user to enter their character
character = input("Please type X or O\n")
while character != "X" and character != "O":
print("Invalid character choice")
character = input("Please type X or O\n")
# send character choice
sock.send(bytes(character, 'utf-8'))
# receive character setup packet
char_setup = sock.recv(len("XS")).decode('utf-8')
my_char = char_setup[0]
if my_char == character:
print(f"Your character is {my_char}")
else:
print(f"The other player is using {character}, your character is {my_char}")
game_state = char_setup[1]
engine = ttt.TicTacToeEngine()
if game_state == "W" or game_state == "S":
print("Waiting for the other player's move.")
# wait for game state message
state = sock.recv(9).decode('utf-8')
# update board state
new_board = [char for char in state]
engine.board = new_board
engine.display_board()
# main gameplay loop
game_over = False
winner = None
final_move = False
while not game_over:
move_input = input("Enter the position between 0 and 8 where you want to play. Top left to bottom right.\n")
valid_move = validate_move(move_input, engine)
while not valid_move:
print("Invalid move!")
move_input = input("Enter the position between 0 and 8 where you want to play. Top left to bottom right.\n")
valid_move = validate_move(move_input, engine)
move = int(move_input)
engine.make_move(move, my_char)
# make the new board into a state packet
board_msg = "".join(engine.board)
sock.send(bytes(board_msg, 'utf-8'))
print("Your move:")
engine.display_board()
if engine.is_game_over() == "-":
# game not over, get the next move
print("Waiting for the other player's move.")
else:
# game will be over
final_move = True
state = sock.recv(9).decode('utf-8')
if state.startswith("End"):
# received an end packet
game_over = True
winner = state[3]
if final_move:
# go straight to results
break
else:
# get end game state if you didn't make the last move
state = sock.recv(9).decode('utf-8')
# convert state into a board
new_board = [char for char in state]
engine.board = new_board
print("The other player's move is:")
engine.display_board()
# show the winner
if winner == my_char:
print("You won!")
elif winner == "T":
print("It's a tie.")
else:
print("Sorry, you lost.")
# quit
sock.close()
if __name__ == '__main__':
port = 9001
parser = argparse.ArgumentParser(description='Client')
parser.add_argument('host', help='IP address of the server.')
args = parser.parse_args()
client(args.host, port)