forked from hazelduvall/othello_tourney
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbetter_sio.py
More file actions
202 lines (171 loc) · 7.23 KB
/
better_sio.py
File metadata and controls
202 lines (171 loc) · 7.23 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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
import socketio
from multiprocessing import Process, Value, Pipe
import os
import sys
import importlib
import logging as log
import time
import random
import ctypes
from othello_admin import *
from run_ai import *
ailist_filename = os.getcwd() + '/static/ai_port_info.txt'
human_player_name = 'Yourself'
log.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s', level=log.INFO)
class GameManagerTemplate(socketio.Server):
def __init__(self, *args, **kw):
super().__init__(*args, **kw)
self.possible_names = set()
self.on('connect', self.create_game)
self.on('prequest', self.start_game)
self.on('disconnect', self.delete_game)
self.on('refresh', self.refresh_game)
self.on('movereply', self.send_move)
def create_game(self, sid, environ): pass
def start_game(self, sid, data): pass
def delete_game(self, sid): pass
def refresh_game(self, sid, data): pass
def send_move(self, sid, data): pass
def get_possible_files(self):
folders = os.listdir(os.getcwd()+'/private/Students')
log.debug('Listed Student folders successfully')
return ['private.Students.'+x+'.strategy' for x in folders if x != '__pycache__']
def write_ai(self):
files = self.get_possible_files()
buf = ''
for x in range(len(files)):
name = files[x].split('.')[2]
self.possible_names.add(name)
buf += name +'\n'
log.info('All strategies read')
pfile = open(ailist_filename, 'w')
pfile.write(buf[:-1])
pfile.close()
log.info('Wrote names to webserver file')
log.debug('Filename: '+ailist_filename)
class GameManager(GameManagerTemplate):
def __init__(self, *args, **kw):
super().__init__(*args, **kw)
self.games = dict()
self.pipes = dict()
self.procs = dict()
def create_game(self, sid, environ):
log.info('Client '+sid+' connected')
self.games[sid] = GameRunner(self.possible_names)
def start_game(self, sid, data):
log.info('Client '+sid+' requests game '+str(data))
parent_conn, child_conn = Pipe()
if data['tml'].isdigit():
timelimit = int(data['tml'])
else:
timelimit = 5
self.games[sid].post_init(data['black'].strip(), data['white'].strip(), timelimit)
self.pipes[sid] = parent_conn
self.procs[sid] = Process(target=self.games[sid].run_game, args=(child_conn,))
self.procs[sid].start()
log.debug('Started game for '+sid)
def delete_game(self, sid):
log.info('Client '+sid+' disconnected')
try:
if self.procs[sid].is_alive():
self.procs[sid].terminate()
del self.procs[sid]
del self.pipes[sid]
except:
pass
del self.games[sid]
def refresh_game(self, osid, data):
if 'watching' in data:
sid = data['watching']
else:
sid = osid
log.debug('sid: '+str(sid))
log.debug('Have pipes: '+str(self.pipes))
exists = sid in self.pipes
log.debug('Exists: '+str(exists))
if exists:
log.debug('What is: '+str(self.pipes[sid]))
closed = self.pipes[sid].closed
log.debug('Closed: '+str(closed))
if not closed:
try:
log.debug('Can poll: '+str(self.pipes[sid].poll()))
while self.pipes[sid].poll():
mtype, data = self.pipes[sid].recv()
if mtype == 'board':
self.emit('reply', data=data, room=osid)
elif mtype == 'getmove':
self.emit('moverequest', data=dict(), room=osid)
except BrokenPipeError:
log.debug('Pipe is broken, closing...')
self.pipes[sid].close()
else:
log.debug('Telling client the game has ended...')
self.emit('gameend', data=dict(), room=osid)
def send_move(self, sid, data):
move = int(data['move'])
self.pipes[sid].send(move)
log.info('Recieved move '+str(move)+' from '+sid)
class GameRunner:
def __init__(self, possible_names):
self.core = Strategy()
self.possible_names = possible_names
def post_init(self, nameA, nameB, timelimit):
self.BLACK = nameA if nameA in self.possible_names else None
self.WHITE = nameB if nameB in self.possible_names else None
self.BLACK_STRAT = LocalAI(self.BLACK, self.possible_names, timelimit)
self.WHITE_STRAT = LocalAI(self.WHITE, self.possible_names, timelimit)
log.debug('Set names to '+str(self.BLACK)+' '+str(self.WHITE))
def run_game(self, conn):
log.debug('Game process creation sucessful')
board = self.core.initial_board()
player = core.BLACK
strategy = {core.BLACK: self.BLACK_STRAT, core.WHITE: self.WHITE_STRAT}
names = {core.BLACK: self.BLACK, core.WHITE: self.WHITE}
conn.send((
'board',
{
'bSize':'8',
'board':''.join(board),
'black': self.BLACK if self.BLACK else human_player_name,
'white': self.WHITE if self.WHITE else human_player_name,
'tomove':player
}
))
forfeit = False
while player is not None and not forfeit:
log.debug('Main loop!')
if names[player] is None:
move = 0
# clear out queue from moves sent by rouge client
while conn.poll(): temp=conn.recv()
while not self.core.is_legal(move, player, board):
conn.send(('getmove', 0))
move = conn.recv()
log.debug('Game recieved move '+str(move))
log.debug('Move '+str(move)+' determined legal')
else:
move = strategy[player].get_move(''.join(board), player)
log.debug('Strategy '+names[player]+' returned move '+str(move))
log.debug('Actually got move')
if not self.core.is_legal(move, player, board):
forfeit = True
if player == core.BLACK:
black_score = -100
else:
black_score = 100
continue
board = self.core.make_move(move, player, board)
player = self.core.next_player(board, player)
black_score = self.core.score(core.BLACK, board)
log.debug(self.core.print_board(board))
conn.send(('board', {'bSize':'8',
'board':''.join(board),
'black': self.BLACK if self.BLACK else human_player_name,
'white': self.WHITE if self.WHITE else human_player_name,
'tomove': player if player else core.BLACK
}
))
log.debug('Sent move out to parent')
#self.BLACK_STRAT.kill_remote()
#self.WHITE_STRAT.kill_remote()