-
Notifications
You must be signed in to change notification settings - Fork 1
/
runner.py
112 lines (97 loc) · 4.05 KB
/
runner.py
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
#!/usr/bin/env python3
"""
This module is intended to run batches of games between clients.
It uses three subprocesses for each game: one for the server, and
two for the clients. Synchronization ensures that the games are
run sequentially (not in parallel).
"""
from subprocess import Popen, PIPE, STDOUT
import threading
import sys
import argparse
import logging
SERVER_PATH = './hexgame_server.py'
CLIENT1 = './random_client.py'
CLIENT2 = './random_client.py'
LOG_LEVEL = logging.INFO
LOG_FILE = None
def run_server(server_evt, winners, hexsize=11):
"""Runs the server as a subprocess."""
winning_client = None
with Popen([SERVER_PATH, str(hexsize)], stdout=PIPE) as proc:
client_peernames = []
while proc.poll() is None:
line = proc.stdout.readline().decode()
logging.debug("[Server] %s", line.rstrip())
if line.startswith('Waiting'):
server_evt.set()
logging.info('Connected')
if line.startswith('New player connected'):
client_peernames.append(line[35:].rstrip())
logging.info('Peernames %s', ' / '.join(client_peernames))
if line.startswith('Starting game'):
players = [s.split('#')[0].strip()
for s in line[15:].split('/')]
logging.info('Player 1 → %s / Player 2 → %s',
players[0], players[1])
if line.startswith('Player'):
winner = players[int(line[7]) - 1]
winning_client = client_peernames.index(winner)
logging.info(
'The winner is %s (client %s)', winner,
winning_client)
winners[winning_client] += 1
sys.stdout.flush()
def run_client(server_evt, client_evt, client, num):
"""Runs a client as a subprocess."""
if num == 1:
server_evt.wait()
else:
client_evt.wait()
connection_success = False
attempts = 10
while not connection_success and attempts:
with Popen([client], stdout=PIPE, stderr=STDOUT) as proc:
while proc.poll() is None:
out = proc.stdout.readline().decode()
if out.startswith('ConnectionRefusedError'):
connection_success = False
if out.startswith('Connected'):
connection_success = True
client_evt.set()
logging.debug("[Client {}] ".format(num) + out.rstrip())
sys.stdout.flush()
attempts -= 1
sys.stdout.flush()
def main():
"""Runs a batch of games."""
if LOG_FILE:
logging.basicConfig(level=LOG_LEVEL,
filename=LOG_FILE)
else:
logging.basicConfig(level=LOG_LEVEL)
parser = argparse.ArgumentParser()
parser.add_argument('--batch', nargs=1, default=[1], type=int)
parser.add_argument('--hexsize', nargs=1, default=[11], type=int)
arguments = vars(parser.parse_args(sys.argv[1:]))
server_evt, client_evt = threading.Event(), threading.Event()
winners = [0, 0]
for batch_number in range(arguments['batch'][0]):
logging.info("### Game number %d", batch_number + 1)
t_server = threading.Thread(target=run_server,
args=(server_evt,
winners,
arguments['hexsize'][0]))
t_client1 = threading.Thread(target=run_client, args=(server_evt,
client_evt,
CLIENT1, 1))
t_client2 = threading.Thread(target=run_client, args=(server_evt,
client_evt,
CLIENT2, 2))
t_server.start()
t_client1.start()
t_client2.start()
t_server.join()
print('Winners {}'.format(str(winners)))
if __name__ == '__main__':
main()