From 708de5b3d1688c891598c493d6fd0b5787422a5c Mon Sep 17 00:00:00 2001 From: Tianyi Hao Date: Thu, 9 May 2024 00:40:11 +0800 Subject: [PATCH 1/9] support python3 --- .vscode/settings.json | 5 + client/ai_match.py | 523 +++++++++++++---------- client/check_forbid.py | 201 +++++---- client/client.py | 192 +++++---- client/new_protocol.py | 180 ++++---- client/old_protocol.py | 107 +++-- client/utility.py | 34 +- server/server.py | 946 ++++++++++++++++++++++++++--------------- 8 files changed, 1349 insertions(+), 839 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..999cd0b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "python.pythonPath": "C:\\Program Files\\Python\\Python27\\python.exe", + "editor.defaultFormatter": "ms-python.black-formatter", + "editor.formatOnSave": true +} \ No newline at end of file diff --git a/client/ai_match.py b/client/ai_match.py index d4cffc8..ce0d918 100644 --- a/client/ai_match.py +++ b/client/ai_match.py @@ -1,32 +1,36 @@ import sys +import base64 from old_protocol import old_protocol from new_protocol import new_protocol from check_forbid import check_forbid from utility import * + class ai_match(object): - def __init__(self, - board_size, - opening, - cmd_1, - cmd_2, - protocol_1, - protocol_2, - timeout_turn_1 = 30*1000, - timeout_turn_2 = 30*1000, - timeout_match_1 = 180*1000, - timeout_match_2 = 180*1000, - max_memory_1 = 350*1024*1024, - max_memory_2 = 350*1024*1024, - game_type = 1, - rule = 0, - folder_1 = "./", - folder_2 = "./", - working_dir_1 = "./", - working_dir_2 = "./", - tolerance = 1000, - settings = {}, - special_rule = ""): + def __init__( + self, + board_size, + opening, + cmd_1, + cmd_2, + protocol_1, + protocol_2, + timeout_turn_1=30 * 1000, + timeout_turn_2=30 * 1000, + timeout_match_1=180 * 1000, + timeout_match_2=180 * 1000, + max_memory_1=350 * 1024 * 1024, + max_memory_2=350 * 1024 * 1024, + game_type=1, + rule=0, + folder_1="./", + folder_2="./", + working_dir_1="./", + working_dir_2="./", + tolerance=1000, + settings={}, + special_rule="", + ): self.board_size = board_size self.opening = opening self.cmd_1 = cmd_1 @@ -50,59 +54,69 @@ def __init__(self, self.special_rule = special_rule self.engine_1 = None self.engine_2 = None - - self.board = [[0 for i in xrange(self.board_size)] for j in xrange(self.board_size)] - for i in xrange(len(self.opening)): + + self.board = [ + [0 for i in range(self.board_size)] for j in range(self.board_size) + ] + for i in range(len(self.opening)): x, y = self.opening[i] self.board[x][y] = i % 2 + 1 self.move_num = 0 self.last_move = (-1, -1) - self.board_1 = [[(0,0) for i in xrange(self.board_size)] for j in xrange(self.board_size)] - self.board_2 = [[(0,0) for i in xrange(self.board_size)] for j in xrange(self.board_size)] + self.board_1 = [ + [(0, 0) for i in range(self.board_size)] for j in range(self.board_size) + ] + self.board_2 = [ + [(0, 0) for i in range(self.board_size)] for j in range(self.board_size) + ] def next_move(self): - #print self.move_num + # print(self.move_num) if self.move_num == 0: - for i in xrange(len(self.opening)): + for i in range(len(self.opening)): x, y = self.opening[i] if len(self.opening) % 2 == i % 2: - self.board_1[x][y] = (i+1, 1) - self.board_2[x][y] = (i+1, 2) + self.board_1[x][y] = (i + 1, 1) + self.board_2[x][y] = (i + 1, 2) else: - self.board_1[x][y] = (i+1, 2) - self.board_2[x][y] = (i+1, 1) + self.board_1[x][y] = (i + 1, 2) + self.board_2[x][y] = (i + 1, 1) if self.engine_1 is None: - self.engine_1 = self.init_protocol(self.cmd_1, - self.protocol_1, - self.board_1, - self.timeout_turn_1, - self.timeout_match_1, - self.max_memory_1, - self.game_type, - self.rule, - self.folder_1, - self.working_dir_1, - self.tolerance) + self.engine_1 = self.init_protocol( + self.cmd_1, + self.protocol_1, + self.board_1, + self.timeout_turn_1, + self.timeout_match_1, + self.max_memory_1, + self.game_type, + self.rule, + self.folder_1, + self.working_dir_1, + self.tolerance, + ) else: self.engine_1.init_board(self.board_1) - + msg, x, y = self.engine_1.start() t = self.engine_1.timeused elif self.move_num == 1: if self.engine_2 is None: - self.engine_2 = self.init_protocol(self.cmd_2, - self.protocol_2, - self.board_2, - self.timeout_turn_2, - self.timeout_match_2, - self.max_memory_2, - self.game_type, - self.rule, - self.folder_2, - self.working_dir_2, - self.tolerance) + self.engine_2 = self.init_protocol( + self.cmd_2, + self.protocol_2, + self.board_2, + self.timeout_turn_2, + self.timeout_match_2, + self.max_memory_2, + self.game_type, + self.rule, + self.folder_2, + self.working_dir_2, + self.tolerance, + ) else: self.engine_2.init_board(self.board_2) msg, x, y = self.engine_2.start() @@ -116,12 +130,18 @@ def next_move(self): t = self.engine_2.timeused self.move_num += 1 - self.board_1[x][y] = (len(self.opening)+self.move_num, (self.move_num + 1) % 2 + 1) - self.board_2[x][y] = (len(self.opening)+self.move_num, (self.move_num + 0) % 2 + 1) - self.last_move = (x,y) + self.board_1[x][y] = ( + len(self.opening) + self.move_num, + (self.move_num + 1) % 2 + 1, + ) + self.board_2[x][y] = ( + len(self.opening) + self.move_num, + (self.move_num + 0) % 2 + 1, + ) + self.last_move = (x, y) return msg, x, y, t - #return + # return # -4: timeout # -3: crash # -2: foul @@ -134,20 +154,20 @@ def make_move(self, x, y, color): if self.rule == 4 and color == 1 and check_forbid(self.board, x, y): return -2 - + self.board[x][y] = color nx = [0, 1, -1, 1] - ny = [1, 0, 1, 1] + ny = [1, 0, 1, 1] for d in range(4): c = 1 blocked = 0 _x, _y = x, y - for i in range(1,6): + for i in range(1, 6): _x += nx[d] _y += ny[d] - if _x<0 or _x>=self.board_size: + if _x < 0 or _x >= self.board_size: break - if _y<0 or _y>=self.board_size: + if _y < 0 or _y >= self.board_size: break if self.board[_x][_y] != self.board[x][y]: if self.board[_x][_y] != 0: @@ -155,12 +175,12 @@ def make_move(self, x, y, color): break c += 1 _x, _y = x, y - for i in range(1,6): + for i in range(1, 6): _x -= nx[d] _y -= ny[d] - if _x<0 or _x>=self.board_size: + if _x < 0 or _x >= self.board_size: break - if _y<0 or _y>=self.board_size: + if _y < 0 or _y >= self.board_size: break if self.board[_x][_y] != self.board[x][y]: if self.board[_x][_y] != 0: @@ -173,12 +193,12 @@ def make_move(self, x, y, color): return 1 if self.rule == 9 and c == 5 and blocked < 2: return 1 - if self.rule == 8 and (c > 5 or (c==5 and blocked < 2)): + if self.rule == 8 and (c > 5 or (c == 5 and blocked < 2)): return 1 - return 0 + return 0 def play(self): - msg = '' + msg = "" psq = [] status = 0 result = endby = 0 @@ -187,93 +207,104 @@ def play(self): if self.special_rule == "swap2": try: i = 0 - self.engine_1 = self.init_protocol(self.cmd_1, - self.protocol_1, - self.board_1, - self.timeout_turn_1, - self.timeout_match_1, - self.max_memory_1, - self.game_type, - self.rule, - self.folder_1, - self.working_dir_1, - self.tolerance) + self.engine_1 = self.init_protocol( + self.cmd_1, + self.protocol_1, + self.board_1, + self.timeout_turn_1, + self.timeout_match_1, + self.max_memory_1, + self.game_type, + self.rule, + self.folder_1, + self.working_dir_1, + self.tolerance, + ) _msg, x, y = self.engine_1.swap2board() t = self.engine_1.timeused - print x,y,t + print(x, y, t) if len(y) != 3: status = -1 else: for j in range(len(y)): if self.board[y[j][0]][y[j][1]] == 0: - self.board_2[y[j][0]][y[j][1]] = (j+1, (j+1) % 2 + 1) + self.board_2[y[j][0]][y[j][1]] = (j + 1, (j + 1) % 2 + 1) self.board[y[j][0]][y[j][1]] = j % 2 + 1 self.opening += [y[j]] - psq += [(y[j][0],y[j][1],0)] + psq += [(y[j][0], y[j][1], 0)] else: status = -1 - msg += '(1) (2) (3) ' + _msg + str(int(t)) + 'ms\n' - assert(status == 0) - + msg += "(1) (2) (3) " + _msg + str(int(t)) + "ms\n" + assert status == 0 + i = 1 - self.engine_2 = self.init_protocol(self.cmd_2, - self.protocol_2, - self.board_2, - self.timeout_turn_2, - self.timeout_match_2, - self.max_memory_2, - self.game_type, - self.rule, - self.folder_2, - self.working_dir_2, - self.tolerance) + self.engine_2 = self.init_protocol( + self.cmd_2, + self.protocol_2, + self.board_2, + self.timeout_turn_2, + self.timeout_match_2, + self.max_memory_2, + self.game_type, + self.rule, + self.folder_2, + self.working_dir_2, + self.tolerance, + ) _msg, x, y = self.engine_2.swap2board() t = self.engine_1.timeused - print x,y,t - if len(y) == 0: #swap - msg += '(3-swap) ' + _msg + str(int(t)) + 'ms\n' + print(x, y, t) + if len(y) == 0: # swap + msg += "(3-swap) " + _msg + str(int(t)) + "ms\n" posswap = True - elif len(y) == 1: #stay with its color + elif len(y) == 1: # stay with its color if self.board[y[0][0]][y[0][1]] == 0: self.board[y[0][0]][y[0][1]] = 2 self.opening += [y[0]] - msg += '(3-stay with its color) (4) ' + _msg + str(int(t)) + 'ms\n' - psq += [(y[0][0],y[0][1],0)] + msg += ( + "(3-stay with its color) (4) " + _msg + str(int(t)) + "ms\n" + ) + psq += [(y[0][0], y[0][1], 0)] else: status = -1 - elif len(y) == 2: #put two stones + elif len(y) == 2: # put two stones i = 2 for j in range(len(y)): if self.board[y[j][0]][y[j][1]] == 0: - self.board_2[y[j][0]][y[j][1]] = (j+4, j % 2 + 1) - self.board[y[j][0]][y[j][1]] = (j+1) % 2 + 1 + self.board_2[y[j][0]][y[j][1]] = (j + 4, j % 2 + 1) + self.board[y[j][0]][y[j][1]] = (j + 1) % 2 + 1 self.opening += [y[j]] - psq += [(y[j][0],y[j][1],0)] + psq += [(y[j][0], y[j][1], 0)] else: status = -1 - msg += '(3-put two stones) (4) (5) ' + _msg + str(int(t)) + 'ms\n' + msg += "(3-put two stones) (4) (5) " + _msg + str(int(t)) + "ms\n" self.engine_1.init_board(self.board_2) _msg, x, y = self.engine_1.swap2board() t = self.engine_1.timeused - print x,y,t + print(x, y, t) self.engine_1, self.engine_2 = self.engine_2, self.engine_1 - if len(y) == 0: #swap - msg += '(5-swap) ' + _msg + str(int(t)) + 'ms\n' - elif len(y) == 1: #stay with its color + if len(y) == 0: # swap + msg += "(5-swap) " + _msg + str(int(t)) + "ms\n" + elif len(y) == 1: # stay with its color posswap = True if self.board[y[0][0]][y[0][1]] == 0: self.board[y[0][0]][y[0][1]] = 2 self.opening += [y[0]] - msg += '(5-stay with its color) (6) ' + _msg + str(int(t)) + 'ms\n' - psq += [(y[0][0],y[0][1],0)] + msg += ( + "(5-stay with its color) (6) " + + _msg + + str(int(t)) + + "ms\n" + ) + psq += [(y[0][0], y[0][1], 0)] else: status = -1 else: status = -1 else: status = -1 - assert(status == 0) - + assert status == 0 + except Exception("TLE"): status = -4 except Exception("MLE"): @@ -284,76 +315,113 @@ def play(self): status = -3 if status != 0: - result = (i+1) % 2 + 1 + result = (i + 1) % 2 + 1 if status == -1: - endby = 3 #illegal coordinate + endby = 3 # illegal coordinate elif status == -3: - endby = 4 #crash + endby = 4 # crash elif status == -4: - endby = 2 #timeout + endby = 2 # timeout if status == 0: if "real_time_pos" in self.settings and self.settings["real_time_pos"] == 1: - for i in xrange(len(psq)): - self.settings["send"]("pos " + psq_to_psq([psq[i]], self.board_size).encode("base64").replace("\n", "").replace("\r", "")) - self.settings["recv"](16) #received - if "real_time_message" in self.settings and self.settings["real_time_message"] == 1: - self.settings["send"]("message " + msg.encode("base64").replace("\n", "").replace("\r", "")) - self.settings["recv"](16) #received + for i in range(len(psq)): + self.settings["send"]( + "pos " + + base64.b64encode( + psq_to_psq([psq[i]], self.board_size).encode() + ) + .decode() + .replace("\n", "") + .replace("\r", "") + ) + self.settings["recv"](16) # received + if ( + "real_time_message" in self.settings + and self.settings["real_time_message"] == 1 + ): + self.settings["send"]( + "message " + + base64.b64encode(msg.encode()) + .decode() + .replace("\n", "") + .replace("\r", "") + ) + self.settings["recv"](16) # received if posswap: self.settings["send"]("pos swap") - print "pos swap" - self.settings["recv"](16) #received - for i in xrange(len(self.opening), self.board_size**2): + print("pos swap") + self.settings["recv"](16) # received + for i in range(len(self.opening), self.board_size**2): if self.rule == 4 and i >= self.board_size**2 - 25: break try: _msg, x, y, t = self.next_move() - print x,y,t - msgturn = '('+str(i+1)+') ' + _msg + str(int(t)) + 'ms\n' - psqturn = [(x,y,int(t))] + print(x, y, t) + msgturn = "(" + str(i + 1) + ") " + _msg + str(int(t)) + "ms\n" + psqturn = [(x, y, int(t))] msg += msgturn psq += psqturn if len(psq) >= 3: - _psqturn = [(x,y,int(t)-psq[len(psq)-3][2])] + _psqturn = [(x, y, int(t) - psq[len(psq) - 3][2])] else: - _psqturn = [(x,y,int(t))] - status = self.make_move(x, y, i%2+1) + _psqturn = [(x, y, int(t))] + status = self.make_move(x, y, i % 2 + 1) if status == -2: msgturn = msgturn + "Forbidden move!\n" msg += "Forbidden move!\n" psq = psq[:-1] - if status != -2 and "real_time_pos" in self.settings and self.settings["real_time_pos"] == 1: - self.settings["send"]("pos " + psq_to_psq(_psqturn, self.board_size).encode("base64").replace("\n", "").replace("\r", "")) - self.settings["recv"](16) #received - if "real_time_message" in self.settings and self.settings["real_time_message"] == 1: - self.settings["send"]("message " + msgturn.encode("base64").replace("\n", "").replace("\r", "")) - self.settings["recv"](16) #received - except Exception("TLE"): - status = -4 - except Exception("MLE"): - status = -3 - except Exception("FLE"): - status = -3 - except: - status = -3 + if ( + status != -2 + and "real_time_pos" in self.settings + and self.settings["real_time_pos"] == 1 + ): + self.settings["send"]( + "pos " + + base64.b64encode( + psq_to_psq(_psqturn, self.board_size).encode() + ) + .decode() + .replace("\n", "") + .replace("\r", "") + ) + self.settings["recv"](16) # received + if ( + "real_time_message" in self.settings + and self.settings["real_time_message"] == 1 + ): + self.settings["send"]( + "message " + + base64.b64encode(msgturn.encode()) + .decode() + .replace("\n", "") + .replace("\r", "") + ) + self.settings["recv"](16) # received + except RuntimeError as e: + if str(e) == "TLE": + status = -4 + elif str(e) == "MLE" or str(e) == "FLE": + status = -3 + else: + status = -3 if status != 0: if status == 1: result = i % 2 + 1 - endby = 0 #draw/five + endby = 0 # draw/five else: - result = (i+1) % 2 + 1 + result = (i + 1) % 2 + 1 if status == -1: - endby = 3 #illegal coordinate + endby = 3 # illegal coordinate elif status == -2: - endby = 1 #foul + endby = 1 # foul elif status == -3: - endby = 4 #crash + endby = 4 # crash elif status == -4: - endby = 2 #timeout + endby = 2 # timeout break - print endby + print(endby) sys.stdout.flush() try: self.engine_1.clean() @@ -364,76 +432,103 @@ def play(self): except: pass if status == 0: - result = 0 #draw - endby = 0 #draw/five + result = 0 # draw + endby = 0 # draw/five return msg, psq, result, endby - - def init_protocol(self, - cmd, - protocol_type, - board, - timeout_turn = 30*1000, - timeout_match = 180*1000, - max_memory = 350*1024*1024, - game_type = 1, - rule = 0, - folder = "./", - working_dir = "./", - tolerance = 1000): - if protocol_type == 'old': - return old_protocol(cmd, board, timeout_turn, timeout_match, max_memory, game_type, rule, folder, working_dir, tolerance) + + def init_protocol( + self, + cmd, + protocol_type, + board, + timeout_turn=30 * 1000, + timeout_match=180 * 1000, + max_memory=350 * 1024 * 1024, + game_type=1, + rule=0, + folder="./", + working_dir="./", + tolerance=1000, + ): + if protocol_type == "old": + return old_protocol( + cmd, + board, + timeout_turn, + timeout_match, + max_memory, + game_type, + rule, + folder, + working_dir, + tolerance, + ) else: - return new_protocol(cmd, board, timeout_turn, timeout_match, max_memory, game_type, rule, folder, working_dir, tolerance) + return new_protocol( + cmd, + board, + timeout_turn, + timeout_match, + max_memory, + game_type, + rule, + folder, + working_dir, + tolerance, + ) def print_board(self): - for i in xrange(self.board_size): - s = '' - for j in xrange(self.board_size): + for i in range(self.board_size): + s = "" + for j in range(self.board_size): if self.board_1[i][j][1] == 0: - s += '_' + s += "_" elif self.board_1[i][j][1] == 1: - s += 'x' + s += "x" elif self.board_1[i][j][1] == 2: - s += 'o' + s += "o" else: - s += '#' - print s + s += "#" + print(s) + def main(): - #openings - #[(2,3)] - #[(1,10)] + # openings + # [(2,3)] + # [(1,10)] test = ai_match( - board_size = 20, - opening = [(10,10)], - cmd_1 = "C:/GomocupJudge/client/match/2b6d35c3ca7a8ec313373b4a568069f8/pbrain-sWINe2017_64.exe", - cmd_2 = "C:/GomocupJudge/client/match/1b7dbb708ee4c6d9398b9a0a878961c8/QMENTAT6.exe", - protocol_1 = "new", - protocol_2 = "old", - timeout_turn_1 = 5000, - timeout_turn_2 = 5000, - timeout_match_1 = 120000, - timeout_match_2 = 120000, - max_memory_1 = 350*1024*1024, - max_memory_2 = 350*1024*1024, - game_type = 1, - rule = 0, - folder_1 = "C:/GomocupJudge/client/match/folder/2b6d35c3ca7a8ec313373b4a568069f8/", - folder_2 = "C:/GomocupJudge/client/match/folder/1b7dbb708ee4c6d9398b9a0a878961c8/", - working_dir_1 = "C:/GomocupJudge/client/match/2b6d35c3ca7a8ec313373b4a568069f8/", - working_dir_2 = "C:/GomocupJudge/client/match/1b7dbb708ee4c6d9398b9a0a878961c8/", - tolerance = 1000) + board_size=20, + opening=[(10, 10)], + cmd_1="C:/GomocupJudge/client/match/2b6d35c3ca7a8ec313373b4a568069f8/pbrain-sWINe2017_64.exe", + cmd_2="C:/GomocupJudge/client/match/1b7dbb708ee4c6d9398b9a0a878961c8/QMENTAT6.exe", + protocol_1="new", + protocol_2="old", + timeout_turn_1=5000, + timeout_turn_2=5000, + timeout_match_1=120000, + timeout_match_2=120000, + max_memory_1=350 * 1024 * 1024, + max_memory_2=350 * 1024 * 1024, + game_type=1, + rule=0, + folder_1="C:/GomocupJudge/client/match/folder/2b6d35c3ca7a8ec313373b4a568069f8/", + folder_2="C:/GomocupJudge/client/match/folder/1b7dbb708ee4c6d9398b9a0a878961c8/", + working_dir_1="C:/GomocupJudge/client/match/2b6d35c3ca7a8ec313373b4a568069f8/", + working_dir_2="C:/GomocupJudge/client/match/1b7dbb708ee4c6d9398b9a0a878961c8/", + tolerance=1000, + ) - ''' - for i in xrange(20): + """ + for i in range(20): msg, x, y, t = test.next_move() - print '['+str(i)+']', x, y - print msg + print('['+str(i)+']', x, y) + print(msg) test.print_board() - ''' + """ msg, pos, ret, endby = test.play() - print msg, pos, ret, endby - -if __name__ == '__main__': + print(msg, pos, ret, endby) + + +if __name__ == "__main__": main() diff --git a/client/check_forbid.py b/client/check_forbid.py index 0e40470..f8f27de 100644 --- a/client/check_forbid.py +++ b/client/check_forbid.py @@ -1,7 +1,8 @@ -''' +""" Adapted from Piskvork -''' -''' +""" + +""" (C) 2012-2015 Tianyi Hao (C) 2016 Petr Lastovicka (C) 2017 Kai Sun @@ -18,155 +19,193 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -''' +""" import copy + def check_forbid(board, _X, _Y): - #currently only deal with square board + # currently only deal with square board global l1, l2, l3, l4, X, Y X, Y = _X, _Y - if len(board) != len(board[0]): return False + if len(board) != len(board[0]): + return False N = len(board) - x1 = [[0 for i in range(N+4)] for j in range(N)] - x2 = [[0 for i in range(N+4)] for j in range(N)] - x3 = [[0 for i in range(N+4)] for j in range(2*N-1)] - x4 = [[0 for i in range(N+4)] for j in range(2*N-1)] - COMB = lambda x : (0x100 | x) - COMC = lambda x,y : (0x10000 | ((x)<<8) | y) + x1 = [[0 for i in range(N + 4)] for j in range(N)] + x2 = [[0 for i in range(N + 4)] for j in range(N)] + x3 = [[0 for i in range(N + 4)] for j in range(2 * N - 1)] + x4 = [[0 for i in range(N + 4)] for j in range(2 * N - 1)] + COMB = lambda x: (0x100 | x) + COMC = lambda x, y: (0x10000 | ((x) << 8) | y) + class line(object): def setline(self, a, p): - a[2+p] = 1 + a[2 + p] = 1 self.x = a[2:] self.p = p + def A6(self): x = self.x p = self.p - for i in range(max(p-5, 0), min(p, N-6)+1): - if x[i] + x[i+1] + x[i+2] + x[i+3] + x[i+4] + x[i+5] == 6: + for i in range(max(p - 5, 0), min(p, N - 6) + 1): + if x[i] + x[i + 1] + x[i + 2] + x[i + 3] + x[i + 4] + x[i + 5] == 6: return 1 return 0 + def A5(self): x = self.x p = self.p - for i in range(max(p-4, 0), min(p, N-5)+1): - if x[i] + x[i+1] + x[i+2] + x[i+3] + x[i+4] == 5 and \ - x[i-1] != 1 and x[i+5] != 1: #XXXXX + for i in range(max(p - 4, 0), min(p, N - 5) + 1): + if ( + x[i] + x[i + 1] + x[i + 2] + x[i + 3] + x[i + 4] == 5 + and x[i - 1] != 1 + and x[i + 5] != 1 + ): # XXXXX return 1 return 0 + def B4(self): x = self.x p = self.p - for i in range(max(p-4, 0), min(p, N-5)+1): - if x[i] + x[i+1] + x[i+2] + x[i+3] + x[i+4] == 4 and \ - x[i-1] != 1 and x[i+5] != 1: - if x[i+4] == 0: #XXXX_ + for i in range(max(p - 4, 0), min(p, N - 5) + 1): + if ( + x[i] + x[i + 1] + x[i + 2] + x[i + 3] + x[i + 4] == 4 + and x[i - 1] != 1 + and x[i + 5] != 1 + ): + if x[i + 4] == 0: # XXXX_ return 1 - elif x[i+3] == 0: #XXX_X - if p == i+4 and x[i+5] == 0 and x[i+6] == 1 and \ - x[i+7] == 1 and x[i+8] == 1 and x[i+9] != 1: #XXX_X_XXX + elif x[i + 3] == 0: # XXX_X + if ( + p == i + 4 + and x[i + 5] == 0 + and x[i + 6] == 1 + and x[i + 7] == 1 + and x[i + 8] == 1 + and x[i + 9] != 1 + ): # XXX_X_XXX return 2 return 1 - elif x[i+2] == 0: #XX_XX - if (p == i+4 or p == i+3) and x[i+5] == 0 and \ - x[i+6] == 1 and x[i+7] == 1 and x[i+8] != 1: #XX_XX_XX + elif x[i + 2] == 0: # XX_XX + if ( + (p == i + 4 or p == i + 3) + and x[i + 5] == 0 + and x[i + 6] == 1 + and x[i + 7] == 1 + and x[i + 8] != 1 + ): # XX_XX_XX return 2 return 1 - elif x[i+1] == 0: #X_XXX - if (x[i+5] == 0 and x[i+6] == 1 and x[i+7] != 1) and \ - (p==i+4 or p==i+3 or p==i+2): #X_XXX_X + elif x[i + 1] == 0: # X_XXX + if (x[i + 5] == 0 and x[i + 6] == 1 and x[i + 7] != 1) and ( + p == i + 4 or p == i + 3 or p == i + 2 + ): # X_XXX_X return 2 return 1 - else: #_XXXX + else: # _XXXX return 1 return 0 + def A3(self): x = self.x p = self.p - for i in range(max(p-3, 0), min(p, N-4)+1): - if x[i] + x[i+1] + x[i+2] + x[i+3] == 3 and x[i-1] == 0 and x[i-2] != 1: - if x[i+3] == 0: #XXX_ - if x[i+4] != 1: - if x[i-2] == 0 and x[i-3] != 1: #__XXX_ - if x[i+4] == 0 and x[i+5] != 1: #__XXX___ - return COMC(i-1, i+3) - return COMB(i-1) - if x[i+4] == 0 and x[i+5] != 1: #_XXX__ - return COMB(i+3) - elif x[i+2] == 0: #XX_X - if x[i+4] == 0 and x[i+5] != 1: - return COMB(i+2) - elif x[i+1] == 0: #X_XX - if x[i+4] == 0 and x[i+5] != 1: - return COMB(i+1) + for i in range(max(p - 3, 0), min(p, N - 4) + 1): + if ( + x[i] + x[i + 1] + x[i + 2] + x[i + 3] == 3 + and x[i - 1] == 0 + and x[i - 2] != 1 + ): + if x[i + 3] == 0: # XXX_ + if x[i + 4] != 1: + if x[i - 2] == 0 and x[i - 3] != 1: # __XXX_ + if x[i + 4] == 0 and x[i + 5] != 1: # __XXX___ + return COMC(i - 1, i + 3) + return COMB(i - 1) + if x[i + 4] == 0 and x[i + 5] != 1: # _XXX__ + return COMB(i + 3) + elif x[i + 2] == 0: # XX_X + if x[i + 4] == 0 and x[i + 5] != 1: + return COMB(i + 2) + elif x[i + 1] == 0: # X_XX + if x[i + 4] == 0 and x[i + 5] != 1: + return COMB(i + 1) return 0 - + def pad(x, c, l): for i in range(c): x[i][0] = x[i][1] = 20 - for j in range(l, N+2): - x[i][j+2] = 20 + for j in range(l, N + 2): + x[i][j + 2] = 20 + pad(x1, N, N) pad(x2, N, N) - pad(x3, 2*N-1, 0) - pad(x4, 2*N-1, 0) + pad(x3, 2 * N - 1, 0) + pad(x4, 2 * N - 1, 0) for i in range(N): for j in range(N): - x1[i][j+2] = x2[j][i+2] = x3[i+j][j+2] = x4[N-1-j+i][N-1-j+2] = 0 if board[i][j] == 0 else (1 if board[i][j] == 1 else -1) + x1[i][j + 2] = x2[j][i + 2] = x3[i + j][j + 2] = x4[N - 1 - j + i][ + N - 1 - j + 2 + ] = (0 if board[i][j] == 0 else (1 if board[i][j] == 1 else -1)) l1 = line() l2 = line() l3 = line() l4 = line() + def A3(l, f): r = l.A3() - return r and (not f(r & 0xff) or r >= 0x10000 and not f((r>>8) & 0xff)) + return r and (not f(r & 0xFF) or r >= 0x10000 and not f((r >> 8) & 0xFF)) + def foulr(x, y, five): global l1, l2, l3, l4, X, Y result = 0 - if x1[x][y+2] != -1: + if x1[x][y + 2] != -1: m1 = copy.deepcopy(l1) m2 = copy.deepcopy(l2) m3 = copy.deepcopy(l3) m4 = copy.deepcopy(l4) x0, y0 = X, Y X, Y = x, y - sign = x1[x][y+2] + sign = x1[x][y + 2] l1.setline(x1[x], y) l2.setline(x2[y], x) - l3.setline(x3[x+y], y) - l4.setline(x4[N-1-y+x], N-1-y) - f1 = lambda r : foulr(X, r, 1) - f2 = lambda r : foulr(r, Y, 1) - f3 = lambda r : foulr(X+Y-r, r, 1) - f4 = lambda r : foulr(N-1+X-Y-r, N-1-r, 1) + l3.setline(x3[x + y], y) + l4.setline(x4[N - 1 - y + x], N - 1 - y) + f1 = lambda r: foulr(X, r, 1) + f2 = lambda r: foulr(r, Y, 1) + f3 = lambda r: foulr(X + Y - r, r, 1) + f4 = lambda r: foulr(N - 1 + X - Y - r, N - 1 - r, 1) if l1.A5() == 1 or l2.A5() == 1 or l3.A5() == 1 or l4.A5() == 1: - result = five #five in a row + result = five # five in a row elif l1.B4() + l2.B4() + l3.B4() + l4.B4() >= 2: - result = 2 #double-four + result = 2 # double-four elif A3(l1, f1) + A3(l2, f2) + A3(l3, f3) + A3(l4, f4) >= 2: - result = 1 #double-three + result = 1 # double-three elif l1.A6() == 1 or l2.A6() == 1 or l3.A6() == 1 or l4.A6() == 1: - result = 3 #overline - x1[x][y+2] = x2[y][x+2] = x3[x+y][y+2] = x4[N-1-y+x][N-1-y+2] = sign + result = 3 # overline + x1[x][y + 2] = x2[y][x + 2] = x3[x + y][y + 2] = x4[N - 1 - y + x][ + N - 1 - y + 2 + ] = sign l1 = m1 l2 = m2 l3 = m3 l4 = m4 X, Y = x0, y0 return result + return foulr(X, Y, 0) != 0 -if __name__ == '__main__': +if __name__ == "__main__": + def str_to_board(N, s): board = [[0 for i in range(N)] for j in range(N)] i = 0 k = 0 s = s.lower() while i < len(s): - x = ord(s[i]) - ord('a') - y = ord(s[i+1]) - ord('0') - if i+2 < len(s) and s[i+2].isdigit(): - y = y * 10 + ord(s[i+2]) - ord('0') - 1 + x = ord(s[i]) - ord("a") + y = ord(s[i + 1]) - ord("0") + if i + 2 < len(s) and s[i + 2].isdigit(): + y = y * 10 + ord(s[i + 2]) - ord("0") - 1 i += 3 else: y = y - 1 @@ -174,18 +213,18 @@ def str_to_board(N, s): board[x][y] = k % 2 + 1 k += 1 return board - #pos = 'd14e14c13c12d12a9c11e11f12g12f13n13h12n11i11e12' - pos = 'g9a15h10o15i10o1j9n1j8i1i7f1h7c5g8d14' - #pos = 'c13b2d12o15f12o1g13h1h7e1i7k1k7o12l7o10g7a7d3a1e3c1f3o3j3m1k3o6l3l15n14o13m13a15l12o9k13m15k14j15k15a8' + + # pos = 'd14e14c13c12d12a9c11e11f12g12f13n13h12n11i11e12' + pos = "g9a15h10o15i10o1j9n1j8i1i7f1h7c5g8d14" + # pos = 'c13b2d12o15f12o1g13h1h7e1i7k1k7o12l7o10g7a7d3a1e3c1f3o3j3m1k3o6l3l15n14o13m13a15l12o9k13m15k14j15k15a8' board = str_to_board(15, pos) for i in range(15): for j in range(15): if board[i][j] != 0: - print 'X' if board[i][j] == 1 else 'O', + print("X" if board[i][j] == 1 else "O", end="") else: if check_forbid(board, i, j): - print '!', + print("!", end="") else: - print '_', - print - + print("_", end="") + print("") diff --git a/client/client.py b/client/client.py index b8aaa70..b1d3ac6 100644 --- a/client/client.py +++ b/client/client.py @@ -5,12 +5,13 @@ import shutil import platform import argparse -import sys import time +import base64 from ai_match import ai_match from utility import * + class client(object): def __init__(self, host, port, working_dir, debug, special_rule, blacklist): self.host = host @@ -30,26 +31,26 @@ def __init__(self, host, port, working_dir, debug, special_rule, blacklist): os.mkdir(self.match_dir) if not os.path.isdir(self.folder_dir): os.mkdir(self.folder_dir) - + self.engine = [] for fname in os.listdir(self.engine_dir): if fname.lower().endswith(".zip") or fname.lower().endswith(".exe"): self.engine += [(fname, self.md5(os.path.join(self.engine_dir, fname)))] - self.is_os_64bit = platform.machine().endswith('64') - + self.is_os_64bit = platform.machine().endswith("64") + self.settings = {} self.settings["real_time_pos"] = 0 self.settings["real_time_message"] = 0 - #self.settings["allow pondering"] = 0 - #self.settings[""] = 0 + # self.settings["allow pondering"] = 0 + # self.settings[""] = 0 self.settings["send"] = self.send self.settings["recv"] = self.recv self.display_info() def display_info(self): - print 'System is '+ ('64' if self.is_os_64bit else '32') + 'bit' + print("System is " + ("64" if self.is_os_64bit else "32") + "bit") for engine in self.engine: - print engine[0], engine[1] + print(engine[0], engine[1]) def md5(self, fname): hash_md5 = hashlib.md5() @@ -72,7 +73,7 @@ def send(self, msg): msg = msg.replace("\n", "") if self.debug: self.debug_log("send: " + msg + "\n") - self.client_socket.send(msg + "\n") + self.client_socket.send((msg + "\n").encode()) def _recv(self, size): try: @@ -80,17 +81,17 @@ def _recv(self, size): except: self.buf_socket = "" - for i in xrange(len(self.buf_socket)): + for i in range(len(self.buf_socket)): if self.buf_socket[i] == "\n": ret = self.buf_socket[:i] - self.buf_socket = self.buf_socket[i+1:] + self.buf_socket = self.buf_socket[i + 1 :] return ret - - buf = self.client_socket.recv(size) + + buf = self.client_socket.recv(size).decode() if self.debug: - self.debug_log("recv("+str(size)+"): " + buf + "\n") + self.debug_log("recv(" + str(size) + "): " + buf + "\n") self.buf_socket = self.buf_socket + buf - + return None def recv(self, size): @@ -99,12 +100,12 @@ def recv(self, size): if ret is not None: return ret time.sleep(0.01) - + def listen(self): while True: - buf = self.recv(16*1024*1024) - #print '\"' + buf + '\"' - #sys.stdout.flush() + buf = self.recv(16 * 1024 * 1024) + # print('\"' + buf + '\"') + # sys.stdout.flush() if buf.lower().startswith("blacklist"): self.send("blacklist " + self.blacklist) elif buf.lower().startswith("engine exist"): @@ -116,15 +117,15 @@ def listen(self): break self.send("yes" if exist else "no") elif buf.lower().startswith("engine send"): - base64fname, base64engine = buf.strip().split(' ')[-2:] - fname = base64fname.decode('base64') - engine = base64engine.decode('base64') + base64fname, base64engine = buf.strip().split(" ")[-2:] + fname = base64.b64decode(base64fname.encode()).decode() + engine = base64.b64decode(base64engine.encode()) with open(os.path.join(self.engine_dir, fname), "wb") as f: f.write(engine) self.engine += [(fname, self.md5(os.path.join(self.engine_dir, fname)))] self.send("received") elif buf.lower().startswith("match new"): - buf = buf.strip().split(' ')[2:] + buf = buf.strip().split(" ")[2:] md5_1 = buf[0] md5_2 = buf[1] timeout_turn = int(buf[2]) @@ -145,11 +146,18 @@ def listen(self): try: os.mkdir(os.path.join(self.match_dir, engine[1])) if engine[0].lower().endswith(".zip"): - zip_ref = zipfile.ZipFile(os.path.join(self.engine_dir, engine[0]), 'r') - zip_ref.extractall(os.path.join(self.match_dir, engine[1])) + zip_ref = zipfile.ZipFile( + os.path.join(self.engine_dir, engine[0]), "r" + ) + zip_ref.extractall( + os.path.join(self.match_dir, engine[1]) + ) zip_ref.close() else: - shutil.copy(os.path.join(self.engine_dir, engine[0]), os.path.join(self.match_dir, engine[1])) + shutil.copy( + os.path.join(self.engine_dir, engine[0]), + os.path.join(self.match_dir, engine[1]), + ) os.mkdir(os.path.join(self.folder_dir, engine[1])) except: pass @@ -168,54 +176,78 @@ def get_cmd_protocol(md5): else: if not has_pbrain: exe_list += [fname] - + if len(exe_list) > 1: for fname in exe_list: - if (self.is_os_64bit and '64' in fname) or (not self.is_os_64bit and '64' not in fname): - cmd = os.path.join(self.match_dir, md5, fname).replace("\\", "/") - protocol = 'new' if fname.lower().startswith('pbrain') else 'old' + if (self.is_os_64bit and "64" in fname) or ( + not self.is_os_64bit and "64" not in fname + ): + cmd = os.path.join(self.match_dir, md5, fname).replace( + "\\", "/" + ) + protocol = ( + "new" + if fname.lower().startswith("pbrain") + else "old" + ) return cmd, protocol fname = exe_list[0] cmd = os.path.join(self.match_dir, md5, fname).replace("\\", "/") - protocol = 'new' if fname.lower().startswith('pbrain') else 'old' + protocol = "new" if fname.lower().startswith("pbrain") else "old" return cmd, protocol - + cmd_1, protocol_1 = get_cmd_protocol(md5_1) cmd_2, protocol_2 = get_cmd_protocol(md5_2) - print cmd_1, protocol_1 - print cmd_2, protocol_2 - - game = ai_match(board_size = board_size, - opening = str_to_pos(opening), - cmd_1 = cmd_1, - cmd_2 = cmd_2, - protocol_1 = protocol_1, - protocol_2 = protocol_2, - timeout_turn_1 = timeout_turn, - timeout_turn_2 = timeout_turn, - timeout_match_1 = timeout_match, - timeout_match_2 = timeout_match, - max_memory_1 = max_memory, - max_memory_2 = max_memory, - game_type = game_type, - rule = rule, - folder_1 = os.path.join(self.folder_dir, md5_1), - folder_2 = os.path.join(self.folder_dir, md5_2), - working_dir_1 = os.path.join(self.match_dir, md5_1), - working_dir_2 = os.path.join(self.match_dir, md5_2), - tolerance = tolerance, - settings = self.settings, - special_rule = self.special_rule) + print(cmd_1, protocol_1) + print(cmd_2, protocol_2) + + game = ai_match( + board_size=board_size, + opening=str_to_pos(opening), + cmd_1=cmd_1, + cmd_2=cmd_2, + protocol_1=protocol_1, + protocol_2=protocol_2, + timeout_turn_1=timeout_turn, + timeout_turn_2=timeout_turn, + timeout_match_1=timeout_match, + timeout_match_2=timeout_match, + max_memory_1=max_memory, + max_memory_2=max_memory, + game_type=game_type, + rule=rule, + folder_1=os.path.join(self.folder_dir, md5_1), + folder_2=os.path.join(self.folder_dir, md5_2), + working_dir_1=os.path.join(self.match_dir, md5_1), + working_dir_2=os.path.join(self.match_dir, md5_2), + tolerance=tolerance, + settings=self.settings, + special_rule=self.special_rule, + ) msg, psq, result, endby = game.play() - #print msg, psq - print result, endby - - self.send("match finished " + psq_to_psq(psq, board_size).encode("base64").replace("\n", "").replace("\r", "") + \ - " " + msg.encode("base64").replace("\n", "").replace("\r", "") + " " + str(result) + " " + str(endby)) - self.recv(16) #received - + # print(msg, psq) + print(result, endby) + + self.send( + "match finished " + + base64.b64encode(psq_to_psq(psq, board_size).encode()) + .decode() + .replace("\n", "") + .replace("\r", "") + + " " + + base64.b64encode(msg.encode()) + .decode() + .replace("\n", "") + .replace("\r", "") + + " " + + str(result) + + " " + + str(endby) + ) + self.recv(16) # received + elif buf.lower().startswith("set real_time_pos"): self.settings["real_time_pos"] = int(buf.strip().split()[-1]) self.send("ok") @@ -223,32 +255,46 @@ def get_cmd_protocol(md5): self.settings["real_time_message"] = int(buf.strip().split()[-1]) self.send("ok") elif buf.lower().startswith("pause"): - #TODO + # TODO self.send("ok") elif buf.lower().startswith("continue"): - #TODO + # TODO self.send("ok") elif buf.lower().startswith("terminate"): - #TODO + # TODO self.send("ok") else: self.send("unknown command") continue + def main(): - parser = argparse.ArgumentParser(description='GomocupJudge Client') + parser = argparse.ArgumentParser(description="GomocupJudge Client") parser.add_argument("--host", dest="host", action="store", required=True) parser.add_argument("--port", dest="port", action="store", required=True) parser.add_argument("--dir", dest="working_dir", action="store", required=True) - parser.add_argument("--debug", dest="debug", action="store", default=False, required=False) - parser.add_argument("--rule", dest="special_rule", action="store", default="", required=False) - parser.add_argument("--blacklist", dest="blacklist", action="store", default="None", required=False) - + parser.add_argument( + "--debug", dest="debug", action="store", default=False, required=False + ) + parser.add_argument( + "--rule", dest="special_rule", action="store", default="", required=False + ) + parser.add_argument( + "--blacklist", dest="blacklist", action="store", default="None", required=False + ) + args = parser.parse_args() - client(host=args.host, port=int(args.port), working_dir = args.working_dir, debug = args.debug, special_rule = args.special_rule, blacklist = args.blacklist).listen() + client( + host=args.host, + port=int(args.port), + working_dir=args.working_dir, + debug=args.debug, + special_rule=args.special_rule, + blacklist=args.blacklist, + ).listen() -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/client/new_protocol.py b/client/new_protocol.py index eafe541..7dd9564 100644 --- a/client/new_protocol.py +++ b/client/new_protocol.py @@ -4,21 +4,24 @@ import time import sys from utility import * -from Queue import Queue, Empty -from threading import Thread +from queue import Queue, Empty +from threading import Thread + class new_protocol(object): - def __init__(self, - cmd, - board, - timeout_turn = 30*1000, - timeout_match = 180*1000, - max_memory = 350*1024*1024, - game_type = 1, - rule = 0, - folder = "./", - working_dir = "./", - tolerance = 1000): + def __init__( + self, + cmd, + board, + timeout_turn=30 * 1000, + timeout_match=180 * 1000, + max_memory=350 * 1024 * 1024, + game_type=1, + rule=0, + folder="./", + working_dir="./", + tolerance=1000, + ): self.cmd = cmd self.board = copy.deepcopy(board) self.timeout_turn = timeout_turn @@ -36,31 +39,40 @@ def __init__(self, self.color = 1 self.piece = {} - for i in xrange(len(board)): - for j in xrange(len(board[i])): + for i in range(len(board)): + for j in range(len(board[i])): if board[i][j][0] != 0: - self.piece[board[i][j][0]] = (i,j) - - self.process = subprocess.Popen(shlex.split(cmd), - shell=False, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - bufsize=1, - close_fds='posix' in sys.builtin_module_names, - cwd=self.working_dir) + self.piece[board[i][j][0]] = (i, j) + + self.process = subprocess.Popen( + shlex.split(cmd), + shell=False, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + bufsize=1, + close_fds="posix" in sys.builtin_module_names, + cwd=self.working_dir, + universal_newlines=True, + ) + def enqueue_output(out, queue): - for line in iter(out.readline, b''): + for line in iter(out.readline, b""): queue.put(line) out.close() + self.queue = Queue() - queuethread = Thread(target=enqueue_output, args=(self.process.stdout, self.queue)) - queuethread.daemon = True # thread dies with the program + queuethread = Thread( + target=enqueue_output, args=(self.process.stdout, self.queue) + ) + queuethread.daemon = True # thread dies with the program queuethread.start() - + self.pp = psutil.Process(self.process.pid) self.write_to_process("START " + str(len(self.board)) + self.endl) self.write_to_process("INFO timeout_turn " + str(self.timeout_turn) + self.endl) - self.write_to_process("INFO timeout_match " + str(self.timeout_match) + self.endl) + self.write_to_process( + "INFO timeout_match " + str(self.timeout_match) + self.endl + ) self.write_to_process("INFO max_memory " + str(self.max_memory) + self.endl) self.write_to_process("INFO game_type " + str(self.game_type) + self.endl) self.write_to_process("INFO rule " + str(self.rule) + self.endl) @@ -70,14 +82,14 @@ def enqueue_output(out, queue): def init_board(self, board): self.board = copy.deepcopy(board) self.piece = {} - for i in xrange(len(board)): - for j in xrange(len(board[i])): + for i in range(len(board)): + for j in range(len(board[i])): if board[i][j][0] != 0: - self.piece[board[i][j][0]] = (i,j) + self.piece[board[i][j][0]] = (i, j) def write_to_process(self, msg): - #print '===>', msg - #sys.stdout.flush() + # print('===>', msg) + # sys.stdout.flush() self.process.stdin.write(msg) self.process.stdin.flush() @@ -107,22 +119,26 @@ def update_vms(self): except: pass - def wait(self, special_rule = ""): + def wait(self, special_rule=""): self.resume() - - msg = '' + + msg = "" x, y = -1, -1 - timeout_sec = (self.tolerance + min((self.timeout_match - self.timeused), self.timeout_turn)) / 1000. + timeout_sec = ( + self.tolerance + + min((self.timeout_match - self.timeused), self.timeout_turn) + ) / 1000.0 start = time.time() while True: - try: buf = self.queue.get_nowait() + try: + buf = self.queue.get_nowait() except Empty: if time.time() - start > timeout_sec: break time.sleep(0.01) else: - #print '<===', buf - #sys.stdout.flush() + # print('<===', buf) + # sys.stdout.flush() if buf.lower().startswith("message"): msg += buf else: @@ -139,7 +155,7 @@ def wait(self, special_rule = ""): xi, yi = xy.split(",") xi, yi = int(xi), int(yi) y += [(xi, yi)] - assert(len(y) > 0) + assert len(y) > 0 else: x, y = buf.split(",") x, y = int(x), int(y) @@ -147,57 +163,72 @@ def wait(self, special_rule = ""): except: pass end = time.time() - self.timeused += int(max(0, end-start-0.01)*1000) - if end-start >= timeout_sec: - raise Exception("TLE") + self.timeused += int(max(0, end - start - 0.01) * 1000) + if end - start >= timeout_sec: + raise RuntimeError("TLE") self.update_vms() self.suspend() if self.vms_memory > self.max_memory and self.max_memory != 0: - raise Exception("MLE") - if get_dir_size(self.folder) > 70*1024*1024: - raise Exception("FLE") + raise RuntimeError("MLE") + if get_dir_size(self.folder) > 70 * 1024 * 1024: + raise RuntimeError("FLE") if special_rule == "": - self.piece[len(self.piece)+1] = (x,y) + self.piece[len(self.piece) + 1] = (x, y) self.board[x][y] = (len(self.piece), self.color) return msg, x, y - + def turn(self, x, y): - self.piece[len(self.piece)+1] = (x,y) + self.piece[len(self.piece) + 1] = (x, y) self.board[x][y] = (len(self.piece), 3 - self.color) - self.write_to_process("INFO time_left " + str(self.timeout_match - self.timeused) + self.endl) + self.write_to_process( + "INFO time_left " + str(self.timeout_match - self.timeused) + self.endl + ) self.write_to_process("TURN " + str(x) + "," + str(y) + self.endl) return self.wait() def start(self): - self.write_to_process("INFO time_left " + str(self.timeout_match - self.timeused) + self.endl) + self.write_to_process( + "INFO time_left " + str(self.timeout_match - self.timeused) + self.endl + ) self.write_to_process("BOARD" + self.endl) - for i in xrange(1, len(self.piece)+1): - self.process.stdin.write(str(self.piece[i][0]) + "," + str(self.piece[i][1]) + "," + str(self.board[self.piece[i][0]][self.piece[i][1]][1]) + self.endl) + for i in range(1, len(self.piece) + 1): + self.process.stdin.write( + str(self.piece[i][0]) + + "," + + str(self.piece[i][1]) + + "," + + str(self.board[self.piece[i][0]][self.piece[i][1]][1]) + + self.endl + ) self.write_to_process("DONE" + self.endl) return self.wait() def swap2board(self): - self.write_to_process("INFO time_left " + str(self.timeout_match - self.timeused) + self.endl) + self.write_to_process( + "INFO time_left " + str(self.timeout_match - self.timeused) + self.endl + ) self.write_to_process("SWAP2BOARD" + self.endl) - for i in xrange(1, len(self.piece)+1): - self.process.stdin.write(str(self.piece[i][0]) + "," + str(self.piece[i][1]) + self.endl) + for i in range(1, len(self.piece) + 1): + self.process.stdin.write( + str(self.piece[i][0]) + "," + str(self.piece[i][1]) + self.endl + ) self.write_to_process("DONE" + self.endl) - return self.wait(special_rule = "swap2") + return self.wait(special_rule="swap2") def clean(self): self.resume() - + self.write_to_process("END" + self.endl) time.sleep(0.5) if self.process.poll() is None: - #self.process.kill() + # self.process.kill() for pp in self.pp.children(recursive=True): pp.kill() self.pp.kill() @@ -205,23 +236,24 @@ def clean(self): def main(): engine = new_protocol( - cmd = "C:/Kai/git/GomocupJudge/engine/pbrain-yixin15.exe", - board = [[(0,0) for i in xrange(20)] for j in xrange(20)], - timeout_turn = 1000, - timeout_match = 100000, - max_memory = 350*1024*1024, - game_type = 1, - rule = 0, - folder = "C:/Kai/git/GomocupJudge/tmp", - working_dir = "C:/Kai/git/GomocupJudge/engine", - tolerance = 1000) + cmd="C:/Kai/git/GomocupJudge/engine/pbrain-yixin15.exe", + board=[[(0, 0) for i in range(20)] for j in range(20)], + timeout_turn=1000, + timeout_match=100000, + max_memory=350 * 1024 * 1024, + game_type=1, + rule=0, + folder="C:/Kai/git/GomocupJudge/tmp", + working_dir="C:/Kai/git/GomocupJudge/engine", + tolerance=1000, + ) msg, x, y = engine.start() - print msg, x, y + print(msg, x, y) engine.clean() -if __name__ == '__main__': - main() \ No newline at end of file +if __name__ == "__main__": + main() diff --git a/client/old_protocol.py b/client/old_protocol.py index 306c737..33c3c99 100644 --- a/client/old_protocol.py +++ b/client/old_protocol.py @@ -6,18 +6,21 @@ from threading import Timer from utility import * + class old_protocol(object): - def __init__(self, - cmd, - board, - timeout_turn = 30*1000, - timeout_match = 180*1000, - max_memory = 350*1024*1024, - game_type = 1, - rule = 0, - folder = "./", - working_dir = "./", - tolerance = 1000): + def __init__( + self, + cmd, + board, + timeout_turn=30 * 1000, + timeout_match=180 * 1000, + max_memory=350 * 1024 * 1024, + game_type=1, + rule=0, + folder="./", + working_dir="./", + tolerance=1000, + ): self.cmd = cmd self.board = copy.deepcopy(board) self.timeout_turn = timeout_turn @@ -31,18 +34,27 @@ def __init__(self, self.timeused = 0 self.vms_memory = 0 - + self.color = 1 self.piece = {} - for i in xrange(len(board)): - for j in xrange(len(board[i])): + for i in range(len(board)): + for j in range(len(board[i])): if board[i][j][0] != 0: - self.piece[board[i][j][0]] = (i,j) - + self.piece[board[i][j][0]] = (i, j) + def run(self): - timeout_sec = (self.tolerance + min((self.timeout_match - self.timeused), self.timeout_turn)) / 1000. + timeout_sec = ( + self.tolerance + + min((self.timeout_match - self.timeused), self.timeout_turn) + ) / 1000.0 start = time.time() - proc = subprocess.Popen(shlex.split(self.cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.working_dir, shell=False) + proc = subprocess.Popen( + shlex.split(self.cmd), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=self.working_dir, + shell=False, + ) try: pp = psutil.Process(proc.pid) m = 0 @@ -56,12 +68,13 @@ def run(self): self.vms_memory = max(self.vms_memory, m) except: pass + def kill_proc(p): _pp = psutil.Process(p.pid) for pp in _pp.children(recursive=True): pp.kill() _pp.kill() - + timer = Timer(timeout_sec, kill_proc, [proc]) try: timer.start() @@ -69,18 +82,18 @@ def kill_proc(p): finally: timer.cancel() end = time.time() - self.timeused += int(max(0, end-start-0.01)*1000) - if end-start >= timeout_sec: - raise Exception("TLE") + self.timeused += int(max(0, end - start - 0.01) * 1000) + if end - start >= timeout_sec: + raise RuntimeError("TLE") if self.vms_memory > self.max_memory: - raise Exception("MLE") - if get_dir_size(self.folder) > 70*1024*1024: - raise Exception("FLE") + raise RuntimeError("MLE") + if get_dir_size(self.folder) > 70 * 1024 * 1024: + raise RuntimeError("FLE") def write_plocha(self): f = open(os.path.join(self.working_dir, "PLOCHA.DAT"), "w") - for i in xrange(len(self.board)): - for j in xrange(len(self.board[i])): + for i in range(len(self.board)): + for j in range(len(self.board[i])): if self.board[i][j][1] == 0: f.write("-") elif self.board[i][j][1] == 1: @@ -133,10 +146,10 @@ def read_tah(self): return int(l[1]), int(l[0]) def turn(self, x, y): - self.piece[len(self.piece)+1] = (x,y) + self.piece[len(self.piece) + 1] = (x, y) self.board[x][y] = (len(self.piece), 3 - self.color) return self.start() - + def start(self): self.write_plocha() self.write_tah() @@ -145,8 +158,8 @@ def start(self): self.write_msg() self.run() msg = self.read_msg() - x,y = self.read_tah() - self.piece[len(self.piece)+1] = (x,y) + x, y = self.read_tah() + self.piece[len(self.piece) + 1] = (x, y) self.board[x][y] = (len(self.piece), self.color) return msg, x, y @@ -156,26 +169,28 @@ def clean(self): os.remove(os.path.join(self.working_dir, "TIMEOUTS.DAT")) os.remove(os.path.join(self.working_dir, "INFO.DAT")) os.remove(os.path.join(self.working_dir, "PLOCHA.DAT")) - - + + def main(): engine = old_protocol( - cmd = "C:/Kai/git/GomocupJudge/engine/pisq7.exe", - board = [[(0,0) for i in xrange(20)] for j in xrange(20)], - timeout_turn = 1000, - timeout_match = 100000, - max_memory = 350*1024*1024, - game_type = 1, - rule = 0, - folder = "C:/Kai/git/GomocupJudge/tmp", - working_dir = "C:/Kai/git/GomocupJudge/engine", - tolerance = 1000) + cmd="C:/Kai/git/GomocupJudge/engine/pisq7.exe", + board=[[(0, 0) for i in range(20)] for j in range(20)], + timeout_turn=1000, + timeout_match=100000, + max_memory=350 * 1024 * 1024, + game_type=1, + rule=0, + folder="C:/Kai/git/GomocupJudge/tmp", + working_dir="C:/Kai/git/GomocupJudge/engine", + tolerance=1000, + ) msg, x, y = engine.start() - print msg, x, y + print(msg, x, y) engine.clean() - -if __name__ == '__main__': + + +if __name__ == "__main__": main() diff --git a/client/utility.py b/client/utility.py index 45cc962..b73d11c 100644 --- a/client/utility.py +++ b/client/utility.py @@ -1,38 +1,42 @@ import os + def pos_to_str(pos): - s = '' - for i in xrange(len(pos)): + s = "" + for i in range(len(pos)): x, y = pos[i] - s += chr(ord('a')+x) + str(y+1) + s += chr(ord("a") + x) + str(y + 1) return s + def str_to_pos(s): pos = [] i = 0 s = s.lower() while i < len(s): - x = ord(s[i]) - ord('a') - y = ord(s[i+1]) - ord('0') - if i+2 < len(s) and s[i+2].isdigit(): - y = y * 10 + ord(s[i+2]) - ord('0') - 1 + x = ord(s[i]) - ord("a") + y = ord(s[i + 1]) - ord("0") + if i + 2 < len(s) and s[i + 2].isdigit(): + y = y * 10 + ord(s[i + 2]) - ord("0") - 1 i += 3 else: y = y - 1 i += 2 - pos += [(x,y)] + pos += [(x, y)] return pos + def psq_to_psq(_psq, board_size): - psq = '' - #psq += 'Piskvorky ' + str(board_size) + "x" + str(board_size) + "," + " 11:11," + " 0\n" + psq = "" + # psq += 'Piskvorky ' + str(board_size) + "x" + str(board_size) + "," + " 11:11," + " 0\n" tt = [0, 0] for i in range(len(_psq)): - x,y,t = _psq[i] - psq += str(x+1)+","+str(y+1)+","+str(t-tt[i%2])+"\n" - tt[i%2] = t + x, y, t = _psq[i] + psq += str(x + 1) + "," + str(y + 1) + "," + str(t - tt[i % 2]) + "\n" + tt[i % 2] = t return psq + def get_dir_size(start_path): total_size = 0 for dirpath, dirnames, filenames in os.walk(start_path): @@ -42,5 +46,5 @@ def get_dir_size(start_path): return total_size -if __name__ == '__main__': - print psq_to_psq([(18,12,36),(11,11,146), (18,10,72), (10,10,291)], 20) +if __name__ == "__main__": + print(psq_to_psq([(18, 12, 36), (11, 11, 146), (18, 10, 72), (10, 10, 291)], 20)) diff --git a/server/server.py b/server/server.py index b52eba8..1ae22cf 100644 --- a/server/server.py +++ b/server/server.py @@ -8,17 +8,16 @@ import os import hashlib import base64 -import Queue +from queue import Queue import subprocess import random -import ftplib import paramiko def get_md5(curpath, engine): - engine_path = curpath + slash + 'engine' + slash + engine + engine_path = curpath + slash + "engine" + slash + engine if os.path.isfile(engine_path): - fin = open(engine_path, 'rb') + fin = open(engine_path, "rb") reads = fin.read() fin.close() if not reads: @@ -30,23 +29,38 @@ def get_md5(curpath, engine): def get_base64(curpath, engine): - engine_path = curpath + slash + 'engine' + slash + engine + engine_path = curpath + slash + "engine" + slash + engine if os.path.isfile(engine_path): - fin = open(engine_path, 'rb') + fin = open(engine_path, "rb") reads = fin.read() fin.close() if not reads: return None - return re.sub(r'\s+', '', base64.b64encode(reads)) + return re.sub(r"\s+", "", base64.b64encode(reads).decode()) else: return None class Match: - def __init__(self, curpath, tournament, tur_name, matchid, player1, - player2, round, board_size, rule, opening, time_turn, - time_match, tolerance, memory, real_time_pos, - real_time_message): + def __init__( + self, + curpath, + tournament, + tur_name, + matchid, + player1, + player2, + round, + board_size, + rule, + opening, + time_turn, + time_match, + tolerance, + memory, + real_time_pos, + real_time_message, + ): self.curpath = curpath self.tournament = tournament self.tur_name = tur_name @@ -78,8 +92,8 @@ def __init__(self, curpath, tournament, tur_name, matchid, player1, def assign(self, client): self.client = client self.started = True - #print repr(self.player1) - #print repr(self.player2) + # print(repr(self.player1)) + # print(repr(self.player2)) client.assign(self) def reinit(self): @@ -93,13 +107,32 @@ def reinit(self): self.client = None def to_string(self): - return repr(self.group_id) + '\t' + repr(self.result) + '\t' + repr( - self.end_with) + '\t' + repr(self.time1) + '\t' + repr( - self.time2) + '\t' + repr(self.move1) + '\t' + repr(self.move2) + return ( + repr(self.group_id) + + "\t" + + repr(self.result) + + "\t" + + repr(self.end_with) + + "\t" + + repr(self.time1) + + "\t" + + repr(self.time2) + + "\t" + + repr(self.move1) + + "\t" + + repr(self.move2) + ) def read_string(self, cur_str): - cur_group_id, self.result, self.end_with, self.time1, self.time2, self.move1, self.move2 = map( - eval, cur_str.split("\t")) + ( + cur_group_id, + self.result, + self.end_with, + self.time1, + self.time2, + self.move1, + self.move2, + ) = list(map(eval, cur_str.split("\t"))) if self.result != None: self.started = True else: @@ -110,22 +143,36 @@ def soft_div(a, b, un): if b != 0: return str(int(round(a * 1.0 / b))) + un else: - return '-' + return "-" class Tournament: - def __init__(self, curpath, engines, engine_ratings, rating_diff, tur_name, - board_size, rule, openings, is_tournament, time_turn, - time_match, tolerance, memory, real_time_pos, - real_time_message): + def __init__( + self, + curpath, + engines, + engine_ratings, + rating_diff, + tur_name, + board_size, + rule, + openings, + is_tournament, + time_turn, + time_match, + tolerance, + memory, + real_time_pos, + real_time_message, + ): self.curpath = curpath - self.enginepath = curpath + slash + 'engine' + self.enginepath = curpath + slash + "engine" self.engines = engines self.engine_ratings = engine_ratings self.rating_diff = rating_diff self.short_engines = self.get_short_engines(3) - print self.engines - print self.short_engines + print(self.engines) + print(self.short_engines) self.md5s = [] for engine in self.engines: self.md5s.append(get_md5(curpath, engine)) @@ -143,11 +190,11 @@ def __init__(self, curpath, engines, engine_ratings, rating_diff, tur_name, self.real_time_pos = real_time_pos self.real_time_message = real_time_message self.matches = [] - self.ratings = [(i, None, self.engines[i]) - for i in range(self.nengines)] + self.ratings = [(i, None, self.engines[i]) for i in range(self.nengines)] self.lresult = [[0, 0, 0] for i in range(self.nengines)] - self.mresult = [[[0, 0, 0] for i in range(self.nengines)] - for j in range(self.nengines)] + self.mresult = [ + [[0, 0, 0] for i in range(self.nengines)] for j in range(self.nengines) + ] self.times = [0 for i in range(self.nengines)] self.moves = [0 for i in range(self.nengines)] self.games = [0 for i in range(self.nengines)] @@ -166,44 +213,96 @@ def __init__(self, curpath, engines, engine_ratings, rating_diff, tur_name, if self.rating_diff > 0: rating_1 = self.engine_ratings[j] rating_2 = self.engine_ratings[k] - if rating_1 > 0 and rating_2 > 0 and abs( - rating_1 - - rating_2) >= self.rating_diff: + if ( + rating_1 > 0 + and rating_2 > 0 + and abs(rating_1 - rating_2) >= self.rating_diff + ): continue player1 = (j, self.engines[j], self.md5s[j]) player2 = (k, self.engines[k], self.md5s[k]) - cur_match = Match(curpath, self, tur_name, - matchcount, player1, player2, i, - board_size, rule, openings[i], - time_turn, time_match, tolerance, - memory, real_time_pos, - real_time_message) + cur_match = Match( + curpath, + self, + tur_name, + matchcount, + player1, + player2, + i, + board_size, + rule, + openings[i], + time_turn, + time_match, + tolerance, + memory, + real_time_pos, + real_time_message, + ) self.matches.append(cur_match) matchcount += 1 - cur_match = Match(curpath, self, tur_name, - matchcount, player2, player1, i, - board_size, rule, openings[i], - time_turn, time_match, tolerance, - memory, real_time_pos, - real_time_message) + cur_match = Match( + curpath, + self, + tur_name, + matchcount, + player2, + player1, + i, + board_size, + rule, + openings[i], + time_turn, + time_match, + tolerance, + memory, + real_time_pos, + real_time_message, + ) self.matches.append(cur_match) matchcount += 1 else: for k in range(1, self.nengines): player1 = (0, self.engines[0], self.md5s[0]) player2 = (k, self.engines[k], self.md5s[k]) - cur_match = Match(curpath, self, tur_name, matchcount, - player1, player2, i, board_size, rule, - openings[i], time_turn, time_match, - tolerance, memory, real_time_pos, - real_time_message) + cur_match = Match( + curpath, + self, + tur_name, + matchcount, + player1, + player2, + i, + board_size, + rule, + openings[i], + time_turn, + time_match, + tolerance, + memory, + real_time_pos, + real_time_message, + ) self.matches.append(cur_match) matchcount += 1 - cur_match = Match(curpath, self, tur_name, matchcount, - player2, player1, i, board_size, rule, - openings[i], time_turn, time_match, - tolerance, memory, real_time_pos, - real_time_message) + cur_match = Match( + curpath, + self, + tur_name, + matchcount, + player2, + player1, + i, + board_size, + rule, + openings[i], + time_turn, + time_match, + tolerance, + memory, + real_time_pos, + real_time_message, + ) self.matches.append(cur_match) matchcount += 1 self.nmatches = len(self.matches) @@ -217,7 +316,7 @@ def __init__(self, curpath, engines, engine_ratings, rating_diff, tur_name, def get_short_engines(self, len_name): engines = self.engines[:] for i in range(len(engines)): - engines[i] = engines[i].rsplit('.', 1)[0] + engines[i] = engines[i].rsplit(".", 1)[0] short_engines = {} for engine in engines: if len(engine) >= len_name: @@ -226,40 +325,41 @@ def get_short_engines(self, len_name): short_engines[engine] = (engine, len(engine) - 1) while True: revert_map = {} - for engine, short_engine in short_engines.iteritems(): + for engine, short_engine in short_engines.items(): short_engine, pos = short_engine - if not revert_map.has_key(short_engine): + if short_engine not in revert_map.keys(): revert_map[short_engine] = [] revert_map[short_engine].append((engine, pos)) flag = False - for short_engine, engines in revert_map.iteritems(): + for short_engine, engines in revert_map.items(): if len(engines) >= 2: for engine, pos in engines: if pos < len(engine) - 1: flag = True if not flag: break - for short_engine, engines in revert_map.iteritems(): + for short_engine, engines in revert_map.items(): minpos = 1024 maxpos = -1 for engine, pos in engines: minpos = min(minpos, pos) maxpos = max(maxpos, pos) flag = False - for short_engine, engines in revert_map.iteritems(): + for short_engine, engines in revert_map.items(): if len(engines) <= 1: continue for engine, pos in engines: - if pos < len(engine) - 1 and (pos > minpos - or minpos == maxpos): + if pos < len(engine) - 1 and (pos > minpos or minpos == maxpos): pos += 1 - short_engines[engine] = (engine[:len_name - 1] + - engine[pos], pos) + short_engines[engine] = ( + engine[: len_name - 1] + engine[pos], + pos, + ) flag = True if not flag: break ret_short_engines = {} - for engine, short_engine in short_engines.iteritems(): + for engine, short_engine in short_engines.items(): ret_short_engines[engine] = short_engine[0] return ret_short_engines @@ -314,31 +414,45 @@ def statistics(self): self.draws[player1][1] += 1 self.draws[player2][0] += 1 for i in range(self.nengines): - if self.games[i] > 0 and (self.timeouts[i] + self.crashes[i] - ) * 1.0 / self.games[i] > 0.1: + if ( + self.games[i] > 0 + and (self.timeouts[i] + self.crashes[i]) * 1.0 / self.games[i] > 0.1 + ): self.valids[i] = False def generate_pgn(self): - result_path = self.curpath + slash + 'result' + slash + tur_name + result_path = self.curpath + slash + "result" + slash + tur_name pgn_file = result_path + slash + "result.pgn" - fout = open(pgn_file, 'w') + fout = open(pgn_file, "w") nmatches = 0 for match in self.matches: if match.result != None: - if self.valids[match.player1[0]] == False or self.valids[ - match.player2[0]] == False: + if ( + self.valids[match.player1[0]] == False + or self.valids[match.player2[0]] == False + ): continue - fout.write("[White \"" + str(match.player1[0]) + "#" + - match.player1[1].rsplit('.', 1)[0] + "\"]\n") - fout.write("[Black \"" + str(match.player2[0]) + "#" + - match.player2[1].rsplit('.', 1)[0] + "\"]\n") + fout.write( + '[White "' + + str(match.player1[0]) + + "#" + + match.player1[1].rsplit(".", 1)[0] + + '"]\n' + ) + fout.write( + '[Black "' + + str(match.player2[0]) + + "#" + + match.player2[1].rsplit(".", 1)[0] + + '"]\n' + ) if match.result == 1: cur_result = "1-0" elif match.result == 2: cur_result = "0-1" else: cur_result = "1/2-1/2" - fout.write("[Result \"" + cur_result + "\"]\n") + fout.write('[Result "' + cur_result + '"]\n') fout.write("\n") fout.write("1. d4 d5 " + cur_result + "\n") fout.write("\n") @@ -350,14 +464,17 @@ def generate_pgn(self): return False def compute_elo(self): - result_path = self.curpath + slash + 'result' + slash + tur_name + result_path = self.curpath + slash + "result" + slash + tur_name ratings = [] if self.generate_pgn(): bayeselo_exe = self.curpath + slash + "bayeselo.exe" - p = subprocess.Popen([bayeselo_exe], - bufsize=1048576, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE) + p = subprocess.Popen( + [bayeselo_exe], + bufsize=1048576, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + universal_newlines=True, + ) pin, pout = p.stdin, p.stdout pin.write("readpgn " + result_path + slash + "result.pgn\n") pin.flush() @@ -378,38 +495,41 @@ def compute_elo(self): pin.write("x\n") pin.flush() p.wait() - fin = open(result_path + slash + "ratings.txt", 'r') + fin = open(result_path + slash + "ratings.txt", "r") reads = fin.readline() while True: reads = fin.readline() if not reads: break reads = reads.strip() - reads = re.split(r'\s+', reads) + reads = re.split(r"\s+", reads) ratings.append( - (string.atoi(reads[1].split('#', - 1)[0]), string.atoi(reads[2]), - reads[1].split('#', 1)[1], string.atoi(reads[4]))) + ( + int(reads[1].split("#", 1)[0]), + int(reads[2]), + reads[1].split("#", 1)[1], + int(reads[4]), + ) + ) fin.close() inratings = [False for i in range(self.nengines)] for engine_id, rating, engine_name, rating_m in ratings: inratings[engine_id] = True for i in range(self.nengines): if not inratings[i]: - ratings.append((i, None, self.engines[i].rsplit('.', - 1)[0], None)) + ratings.append((i, None, self.engines[i].rsplit(".", 1)[0], None)) self.ratings = ratings def print_table(self): - result_path = self.curpath + slash + 'result' + slash + tur_name + result_path = self.curpath + slash + "result" + slash + tur_name self.compute_elo() - fout = open(result_path + slash + "_table.html", 'w') + fout = open(result_path + slash + "_table.html", "w") fout.write( - "\n\nPiskvork tournament result\n\n\n" + '\n\nPiskvork tournament result\n\n\n' ) fout.write("\n") - fout.write("\n") - #fout.write("\n") + fout.write('
\n') + # fout.write("\n") fout.write("\n") fout.write("") cur_rank = 0 @@ -417,9 +537,14 @@ def print_table(self): cur_rank += 1 cur_name = engine_name short_name = self.short_engines[cur_name] - #short_name = cur_name[:min(3, len(cur_name))] - fout.write("") + # short_name = cur_name[:min(3, len(cur_name))] + fout.write( + "" + ) fout.write("\n") cur_rank = 0 for engine_id, rating, engine_name, rating_m in self.ratings: @@ -430,62 +555,107 @@ def print_table(self): rating_str = "-" else: rating_str = str(rating) - fout.write("") + fout.write( + "" + ) for engine_id_2, rating_2, engine_name_2, rating_m_2 in self.ratings: if engine_id == engine_id_2: - fout.write("") + fout.write('') else: cur_mresult = self.mresult[engine_id][engine_id_2] winf = cur_mresult[0] - cur_mresult[1] if winf > 0: - fout.write("") + fout.write( + '" + ) elif winf == 0: - fout.write("") + fout.write( + '" + ) else: - fout.write("") + fout.write( + '" + ) fout.write("\n") fout.write("\n
#NameEloTotal" + str(cur_rank) + "
" + - short_name + "
" + + str(cur_rank) + + "
" + + short_name + + "
" + str(cur_rank) + - "" + cur_name + - "" + rating_str + "" + - str(cur_lresult[0]) + ":" + str(cur_lresult[1]) + - "
" + + str(cur_rank) + + "" + + cur_name + + "" + + rating_str + + "" + + str(cur_lresult[0]) + + ":" + + str(cur_lresult[1]) + + "--" + str(cur_mresult[0]) + - ":" + str(cur_mresult[1]) + "' + + str(cur_mresult[0]) + + ":" + + str(cur_mresult[1]) + + "" + - str(cur_mresult[0]) + ":" + - str(cur_mresult[1]) + "' + + str(cur_mresult[0]) + + ":" + + str(cur_mresult[1]) + + "" + - str(cur_mresult[0]) + ":" + - str(cur_mresult[1]) + "' + + str(cur_mresult[0]) + + ":" + + str(cur_mresult[1]) + + "
\n\n\n") fout.close() ssh_upload(result_path + slash + "_table.html", False) def print_statistics(self): - result_path = self.curpath + slash + 'result' + slash + tur_name - fout = open(result_path + slash + "_result.txt", 'w') + result_path = self.curpath + slash + "result" + slash + tur_name + fout = open(result_path + slash + "_result.txt", "w") cur_rank = 0 for engine_id, rating, engine_name, rating_m in self.ratings: cur_rank += 1 if not rating: - rating = '-' + rating = "-" + fout.write(str(cur_rank) + ". " + engine_name + " " + str(rating) + "\n") + fout.write( + " wins: " + + str(self.wins[engine_id][0]) + + "+" + + str(self.wins[engine_id][1]) + + ", " + ) + fout.write( + "losses: " + + str(self.losses[engine_id][0]) + + "+" + + str(self.losses[engine_id][1]) + + ", " + ) fout.write( - str(cur_rank) + '. ' + engine_name + ' ' + str(rating) + '\n') - fout.write(' wins: ' + str(self.wins[engine_id][0]) + '+' + - str(self.wins[engine_id][1]) + ', ') - fout.write('losses: ' + str(self.losses[engine_id][0]) + '+' + - str(self.losses[engine_id][1]) + ', ') - fout.write('draws: ' + str(self.draws[engine_id][0]) + '+' + - str(self.draws[engine_id][1]) + '\n') - fout.write(' timeouts: ' + str(self.timeouts[engine_id]) + - ', ' + 'errors: ' + str(self.crashes[engine_id]) + - ', ' + 'total games: ' + str(self.games[engine_id]) + - '\n') + "draws: " + + str(self.draws[engine_id][0]) + + "+" + + str(self.draws[engine_id][1]) + + "\n" + ) fout.write( - ' time/game: ' + - soft_div(self.times[engine_id], self.games[engine_id] * - 1000, 's') + ', ' + 'time/turn: ' + - soft_div(self.times[engine_id], self.moves[engine_id], 'ms') + - ', ' + 'move/game: ' + - soft_div(self.moves[engine_id], self.games[engine_id], '') + - '\n') - fout.write('\n') + " timeouts: " + + str(self.timeouts[engine_id]) + + ", " + + "errors: " + + str(self.crashes[engine_id]) + + ", " + + "total games: " + + str(self.games[engine_id]) + + "\n" + ) + fout.write( + " time/game: " + + soft_div(self.times[engine_id], self.games[engine_id] * 1000, "s") + + ", " + + "time/turn: " + + soft_div(self.times[engine_id], self.moves[engine_id], "ms") + + ", " + + "move/game: " + + soft_div(self.moves[engine_id], self.games[engine_id], "") + + "\n" + ) + fout.write("\n") fout.close() ssh_upload(result_path + slash + "_result.txt", False) @@ -506,15 +676,21 @@ def assign_match(self, client): player2 = self.matches[i].player2[0] is_black = False for blacklist_engine in client.blacklist: - if blacklist_engine.lower() in self.matches[i].player1[ - 1].lower() or blacklist_engine.lower( - ) in self.matches[i].player2[1].lower(): + if ( + blacklist_engine.lower() in self.matches[i].player1[1].lower() + or blacklist_engine.lower() + in self.matches[i].player2[1].lower() + ): is_black = True break if is_black: continue - curelo = inv_ratings[player1][0] - inv_ratings[player1][ - 1] + inv_ratings[player2][0] - inv_ratings[player2][1] + curelo = ( + inv_ratings[player1][0] + - inv_ratings[player1][1] + + inv_ratings[player2][0] + - inv_ratings[player2][1] + ) if minelo == None or curelo < minelo: minelo = curelo minind = i @@ -528,18 +704,18 @@ def assign_match(self, client): return 2 def save_state(self): - result_path = self.curpath + slash + 'result' + slash + tur_name + result_path = self.curpath + slash + "result" + slash + tur_name state_path = result_path + slash + "state.txt" - fout = open(state_path, 'w') + fout = open(state_path, "w") for match in self.matches: - fout.write(match.to_string() + '\n') + fout.write(match.to_string() + "\n") fout.close() def load_state(self): - result_path = self.curpath + slash + 'result' + slash + tur_name + result_path = self.curpath + slash + "result" + slash + tur_name state_path = result_path + slash + "state.txt" try: - fin = open(state_path, 'r') + fin = open(state_path, "r") except: return leftmatches = 0 @@ -599,17 +775,28 @@ def cmp_result(result1, result2): def extend_pos(pos, board_size, player1, player2): - return 'Piskvorky ' + str(board_size) + 'x' + str( - board_size - ) + ', 11:11, 0\n' + pos + player1 + '\n' + player2 + '\n' + '-1\n' + return ( + "Piskvorky " + + str(board_size) + + "x" + + str(board_size) + + ", 11:11, 0\n" + + pos + + player1 + + "\n" + + player2 + + "\n" + + "-1\n" + ) def parse_pos(pos, opening): len_opening = opening_length(opening) spos = pos.strip() if spos: - times = map(lambda x: string.atoi(x.split(',')[-1]), - pos.strip().split('\n'))[len_opening:] + times = list( map(lambda x: int(x.split(",")[-1]), pos.strip().split("\n")))[ + len_opening: + ] else: times = [] len_times = len(times) @@ -663,54 +850,74 @@ def assign(self, match): self.cur_pos = None self.tmp_message = None self.cur_message = None - outstr = 'Game ' + str( - self.match.group_id) + ' started on Client ' + self.addr + '.' + outstr = ( + "Game " + str(self.match.group_id) + " started on Client " + self.addr + "." + ) print_log(outstr) def end(self, pos, message, result, end_with): - pos = base64.b64decode(pos) + pos = base64.b64decode(pos).decode() pos = opening_pos2psq(self.match.opening) + pos - message = base64.b64decode(message) - result_raw = string.atoi(result) + message = base64.b64decode(message).decode() + result_raw = int(result) result = result_raw if result > 0: if opening_reverse(self.match.opening) ^ self.match.swapped: result = 3 - result - end_with = string.atoi(end_with) + end_with = int(end_with) round = self.match.round player1 = self.match.player1 player2 = self.match.player2 tur_name = self.match.tur_name - pos_name = str(round) + '_' + str(player1[0]) + '_' + str( - player2[0]) + '_' + str(result_raw) + '.psq' - result_path = self.curpath + slash + 'result' + slash + tur_name + pos_name = ( + str(round) + + "_" + + str(player1[0]) + + "_" + + str(player2[0]) + + "_" + + str(result_raw) + + ".psq" + ) + result_path = self.curpath + slash + "result" + slash + tur_name pos_path = result_path + slash + pos_name - fpos = open(pos_path, 'w') + fpos = open(pos_path, "w") if not (self.match.reverse ^ self.match.swapped): fpos.write( - extend_pos(pos, self.match.board_size, self.match.player1[1], - self.match.player2[1])) + extend_pos( + pos, + self.match.board_size, + self.match.player1[1], + self.match.player2[1], + ) + ) else: fpos.write( - extend_pos(pos, self.match.board_size, self.match.player2[1], - self.match.player1[1])) + extend_pos( + pos, + self.match.board_size, + self.match.player2[1], + self.match.player1[1], + ) + ) if self.match.swapped and result > 0: show_result = 3 - result else: show_result = result - fpos.write(str(show_result) + ',' + self.tournament.tur_name + '\n') + fpos.write(str(show_result) + "," + self.tournament.tur_name + "\n") fpos.close() if upload_offline_result: ssh_upload(pos_path, False) - fmessage = open(result_path + slash + 'message.txt', 'a') + fmessage = open(result_path + slash + "message.txt", "a") fmessage.write(message) - fmessage.write('\n--> ' + pos_path + '\n\n') + fmessage.write("\n--> " + pos_path + "\n\n") fmessage.close() - #ssh_upload(result_path + slash + 'message.txt', False) + # ssh_upload(result_path + slash + 'message.txt', False) self.match.result = result self.match.end_with = end_with - self.match.time1, self.match.time2, self.match.move1, self.match.move2 = parse_pos( - pos, self.match.opening) + self.match.time1, self.match.time2, self.match.move1, self.match.move2 = ( + parse_pos(pos, self.match.opening) + ) cur_tur = self.tournament player1_id = player1[0] player2_id = player2[0] @@ -730,8 +937,13 @@ def end(self, pos, message, result, end_with): cur_tur.mresult[player1_id][player2_id][2] += 1 cur_tur.mresult[player2_id][player1_id][2] += 1 - outstr = 'Game ' + str( - self.match.group_id) + ' finished on Client ' + self.addr + '.' + outstr = ( + "Game " + + str(self.match.group_id) + + " finished on Client " + + self.addr + + "." + ) print_log(outstr) self.active = False @@ -763,14 +975,18 @@ def end(self, pos, message, result, end_with): return False def save_pos(self, pos): - pos = base64.b64decode(pos) + pos = base64.b64decode(pos).decode() if not self.cur_pos: self.cur_pos = opening_pos2psq(self.match.opening) + pos else: self.cur_pos = self.cur_pos + pos - pos_name = self.addr.replace('.', '_').replace( - ':', '_') + '_' + self.match.tur_name + '.psq' - tmp_path = self.curpath + slash + 'result' + slash + 'tmp' + pos_name = ( + self.addr.replace(".", "_").replace(":", "_") + + "_" + + self.match.tur_name + + ".psq" + ) + tmp_path = self.curpath + slash + "result" + slash + "tmp" if os.path.exists(tmp_path): if not os.path.isdir(tmp_path): os.remove(tmp_path) @@ -778,15 +994,25 @@ def save_pos(self, pos): else: os.makedirs(tmp_path) pos_path = tmp_path + slash + pos_name - fpos = open(pos_path, 'w') + fpos = open(pos_path, "w") if not (self.match.reverse ^ self.match.swapped): fpos.write( - extend_pos(self.cur_pos, self.match.board_size, - self.match.player1[1], self.match.player2[1])) + extend_pos( + self.cur_pos, + self.match.board_size, + self.match.player1[1], + self.match.player2[1], + ) + ) else: fpos.write( - extend_pos(self.cur_pos, self.match.board_size, - self.match.player2[1], self.match.player1[1])) + extend_pos( + self.cur_pos, + self.match.board_size, + self.match.player2[1], + self.match.player1[1], + ) + ) fpos.close() if random.random() < upload_ratio: ssh_upload(pos_path, True) @@ -797,8 +1023,8 @@ def save_message(self, message): self.cur_message = message else: self.cur_message = self.cur_message + message - message_name = self.addr.replace('.', '_').replace(':', '_') + '.txt' - tmp_path = self.curpath + slash + 'result' + slash + 'tmp' + message_name = self.addr.replace(".", "_").replace(":", "_") + ".txt" + tmp_path = self.curpath + slash + "result" + slash + "tmp" if os.path.exists(tmp_path): if not os.path.isdir(tmp_path): os.remove(tmp_path) @@ -806,47 +1032,55 @@ def save_message(self, message): else: os.makedirs(tmp_path) message_path = tmp_path + slash + message_name - fmessage = open(message_path, 'w') + fmessage = open(message_path, "w") fmessage.write(self.cur_message) fmessage.close() - #ssh_upload(message_path, True) + # ssh_upload(message_path, True) def process(self, output_queue): if self.active: if self.has_player1 == None: - self.ask = 'player1' - output_queue.put( - (self.addr, "engine exist " + self.match.player1[2])) + self.ask = "player1" + output_queue.put((self.addr, "engine exist " + self.match.player1[2])) elif self.has_player1 == False: - self.ask = 'player1' + self.ask = "player1" output_queue.put( - (self.addr, - "engine send " + base64.b64encode(self.match.player1[1]) + - " " + get_base64(self.curpath, self.match.player1[1]))) + ( + self.addr, + "engine send " + + base64.b64encode(self.match.player1[1].encode()).decode() + + " " + + get_base64(self.curpath, self.match.player1[1]), + ) + ) elif self.has_player2 == None: - self.ask = 'player2' - output_queue.put( - (self.addr, "engine exist " + self.match.player2[2])) + self.ask = "player2" + output_queue.put((self.addr, "engine exist " + self.match.player2[2])) elif self.has_player2 == False: - self.ask = 'player2' + self.ask = "player2" output_queue.put( - (self.addr, - "engine send " + base64.b64encode(self.match.player2[1]) + - " " + get_base64(self.curpath, self.match.player2[1]))) + ( + self.addr, + "engine send " + + base64.b64encode(self.match.player2[1].encode()).decode() + + " " + + get_base64(self.curpath, self.match.player2[1]), + ) + ) elif self.sent_real_time_pos == False: - self.ask = 'real_time_pos' + self.ask = "real_time_pos" if self.match.real_time_pos == True: output_queue.put((self.addr, "set real_time_pos 1")) else: output_queue.put((self.addr, "set real_time_pos 0")) elif self.sent_real_time_message == False: - self.ask = 'real_time_message' + self.ask = "real_time_message" if self.match.real_time_message == True: output_queue.put((self.addr, "set real_time_message 1")) else: output_queue.put((self.addr, "set real_time_message 0")) elif self.tmp_pos != None: - if tmp_pos.strip() == 'swap': + if tmp_pos.strip() == "swap": self.match.swapped = True else: self.save_pos(self.tmp_pos) @@ -857,14 +1091,33 @@ def process(self, output_queue): self.tmp_message = None output_queue.put((self.addr, "received")) elif not self.started: - self.ask = 'match' - output_queue.put((self.addr, "match new " + self.match.player1[2] + ' ' + self.match.player2[2] + \ - ' ' + self.match.time_turn + ' ' + self.match.time_match + ' ' + self.match.rule + \ - ' ' + self.match.tolerance + ' ' + self.match.opening + ' ' + self.match.board_size + \ - ' ' + self.match.memory)) + self.ask = "match" + output_queue.put( + ( + self.addr, + "match new " + + self.match.player1[2] + + " " + + self.match.player2[2] + + " " + + self.match.time_turn + + " " + + self.match.time_match + + " " + + self.match.rule + + " " + + self.match.tolerance + + " " + + self.match.opening + + " " + + self.match.board_size + + " " + + self.match.memory, + ) + ) else: if self.blacklist is None: - self.ask = 'blacklist' + self.ask = "blacklist" output_queue.put((self.addr, "blacklist")) elif self.ended: self.ask = None @@ -881,26 +1134,26 @@ def process(self, output_queue): def print_log(outstr, file=None): curtime = time.time() strdate = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(curtime)) - outstring = '[' + strdate + ']' + ' ' + outstr + outstring = "[" + strdate + "]" + " " + outstr if not file: - print outstring + print(outstring) file = log_file - fout = open(file, 'a') + fout = open(file, "a") fout.write(outstring) - fout.write('\n') + fout.write("\n") fout.close() def connect_addr(addr, trecv, conn): - outstr = 'Client ' + addr + ' connected.' + outstr = "Client " + addr + " connected." print_log(outstr) trecvs[addr] = (trecv, conn) def disconnect_addr(addr): - outstr = 'Client ' + addr + ' disconnected.' + outstr = "Client " + addr + " disconnected." print_log(outstr) - if trecvs.has_key(addr): + if addr in trecvs.keys(): del trecvs[addr] @@ -908,30 +1161,34 @@ def recv_client(conn, addr): global recv_str, recv_mutex while True: try: - data = conn.recv(5242800) + data = conn.recv(5242800).decode() if not data: disconnect_addr(addr) return if recv_mutex.acquire(): - if not recv_str.has_key(addr): - recv_str[addr] = '' + if addr not in recv_str.keys(): + recv_str[addr] = "" recv_str[addr] = recv_str[addr] + data - sdata = recv_str[addr].split('\n') + sdata = recv_str[addr].split("\n") recv_str[addr] = sdata[-1] sdata = sdata[:-1] for edata in sdata: input_queue.put((addr, edata)) - out_str = repr(('input', addr, edata)) + out_str = repr(("input", addr, edata)) print_log(out_str, net_log_file) recv_mutex.release() except: disconnect_addr(addr) - if clients_state.has_key(addr): + if addr in clients_state.keys(): if clients_state[addr].match: if clients_state[addr].match.result == None: - outstr = 'Game ' + repr( - clients_state[addr].match.group_id - ) + ' failed on Client ' + addr + '.' + outstr = ( + "Game " + + repr(clients_state[addr].match.group_id) + + " failed on Client " + + addr + + "." + ) print_log(outstr) clients_state[addr].match.reinit() del clients_state[addr] @@ -939,13 +1196,13 @@ def recv_client(conn, addr): def output_client(): - while (True): + while True: addr, outstr = output_queue.get() - out_str = repr(('output', addr, outstr)) + out_str = repr(("output", addr, outstr)) print_log(out_str, net_log_file) - if trecvs.has_key(addr): + if addr in trecvs.keys(): conn = trecvs[addr][1] - conn.sendall(outstr + '\n') + conn.sendall((outstr + "\n").encode()) if outstr == "end": disconnect_addr(addr) @@ -956,13 +1213,13 @@ def accept_client(host, port): s.listen(1) while True: conn, addr = s.accept() - addr = addr[0] + ':' + str(addr[1]) + addr = addr[0] + ":" + str(addr[1]) trecv = threading.Thread(target=recv_client, args=(conn, addr)) connect_addr(addr, trecv, conn) trecv.start() clients_state[addr] = Client_state(curpath, addr) - input_queue.put((addr, 'connected')) - out_str = repr(('input', addr, 'connected')) + input_queue.put((addr, "connected")) + out_str = repr(("input", addr, "connected")) print_log(out_str, net_log_file) conn.close() @@ -970,7 +1227,7 @@ def accept_client(host, port): def check_end(): while True: end_flag = True - for client_addr, client in clients_state.iteritems(): + for client_addr, client in clients_state.items(): if not client.ended_all: end_flag = False if not output_queue.empty(): @@ -987,12 +1244,12 @@ def check_end(): def parse_line_tournament(line): try: - left, right = line.split('=') + left, right = line.split("=") left = left.strip() right = right.strip() - right = re.sub(r'\s+', ' ', right) - if ' ' in right: - return (left, right.split(' ')) + right = re.sub(r"\s+", " ", right) + if " " in right: + return (left, right.split(" ")) else: return (left, right) except: @@ -1000,7 +1257,7 @@ def parse_line_tournament(line): def read_tournament(tournament_file): - fin = open(tournament_file, 'r') + fin = open(tournament_file, "r") tournament_map = {} while True: reads = fin.readline() @@ -1016,38 +1273,38 @@ def read_tournament(tournament_file): def parse_line_opening(line): try: line = line.strip() - line = re.sub(r'\s+', '', line) + line = re.sub(r"\s+", "", line) return line except: return None def opening2pos(opening, board_size): - opening = opening.split(',') - hboard = board_size / 2 + opening = opening.split(",") + hboard = board_size // 2 pos = "" - for i in range(len(opening) / 2): - curx = hboard + string.atoi(opening[2 * i]) - cury = hboard + string.atoi(opening[2 * i + 1]) - pos = pos + chr(ord('a') + curx) + for i in range(len(opening) // 2): + curx = hboard + int(opening[2 * i]) + cury = hboard + int(opening[2 * i + 1]) + pos = pos + chr(ord("a") + curx) pos = pos + str(1 + cury) return pos def opening_pos2psq(pos): - poses = re.findall(r'[a-z][0-9]{1,2}', pos) - cur_psq = '' + poses = re.findall(r"[a-z][0-9]{1,2}", pos) + cur_psq = "" for p in poses: - px = ord(p[0]) - ord('a') + 1 - py = string.atoi(p[1:]) - cur_psq += str(px) + ',' + str(py) + ',' + '0\n' + px = ord(p[0]) - ord("a") + 1 + py = int(p[1:]) + cur_psq += str(px) + "," + str(py) + "," + "0\n" return cur_psq def opening_reverse(pos): count = 0 for c in pos: - if c >= 'a' and c <= 'z': + if c >= "a" and c <= "z": count += 1 if count % 2 == 1: return True @@ -1058,13 +1315,13 @@ def opening_reverse(pos): def opening_length(pos): count = 0 for c in pos: - if c >= 'a' and c <= 'z': + if c >= "a" and c <= "z": count += 1 return count def read_opening(opening_file, board_size): - fin = open(opening_file, 'r') + fin = open(opening_file, "r") openings_list = [] while True: reads = fin.readline() @@ -1120,9 +1377,9 @@ def empty(self): def ssh_connect(): if remote_info: ssh_server = remote_info[0] - if ':' in ssh_server: - ssh_server, port = remote_info[0].rsplit(':', 1) - port = string.atoi(port) + if ":" in ssh_server: + ssh_server, port = remote_info[0].rsplit(":", 1) + port = int(port) else: port = 22 username = remote_info[1] @@ -1148,8 +1405,8 @@ def ssh_upload_process(): r_path = remote_info[3] else: r_path = remote_info[4] - if not r_path[-1] == '/': - r_path = r_path + '/' + if not r_path[-1] == "/": + r_path = r_path + "/" sftp.put(upfile, r_path + upfile.split(slash)[-1]) except: ftp_queue.put_to_head((upfile, is_online)) @@ -1161,105 +1418,122 @@ def ssh_quit(): if __name__ == "__main__": if len(sys.argv) < 3: - print 'Parameter error!' + print("Parameter error!") exit(-1) trecvs = {} clients_state = {} - input_queue = Queue.Queue(maxsize=0) - output_queue = Queue.Queue(maxsize=0) + input_queue = Queue(maxsize=0) + output_queue = Queue(maxsize=0) curpath = sys.path[0] curos = platform.system() - if curos == 'Windows': - slash = '\\' + if curos == "Windows": + slash = "\\" else: - slash = '/' + slash = "/" recv_str = {} recv_mutex = threading.Lock() tournament_name = sys.argv[1] - tournament_file = curpath + slash + 'tournament' + slash + tournament_name + '.txt' + tournament_file = curpath + slash + "tournament" + slash + tournament_name + ".txt" tournament = read_tournament(tournament_file) - tur_name = tournament['name'] - board_size = tournament['board'] - rule = tournament['rule'] - opening_file = curpath + slash + 'opening' + slash + tournament[ - 'opening'] + '.txt' - engines = tournament['engines'] - if 'engine_ratings' in tournament.keys(): - engine_ratings = list(map(int, tournament['engine_ratings'])) + tur_name = tournament["name"] + board_size = tournament["board"] + rule = tournament["rule"] + opening_file = curpath + slash + "opening" + slash + tournament["opening"] + ".txt" + engines = tournament["engines"] + if "engine_ratings" in tournament.keys(): + engine_ratings = list(map(int, tournament["engine_ratings"])) else: engine_ratings = [0 for i in range(len(engines))] - rating_diff = int(tournament.get('rating_diff', '0')) - is_tournament = tournament['tournament'] - time_turn = tournament['time_turn'] - time_match = tournament['time_match'] - tolerance = tournament['tolerance'] - memory = tournament['memory'] - real_time_pos = string.atoi(tournament['real_time_pos']) + rating_diff = int(tournament.get("rating_diff", "0")) + is_tournament = tournament["tournament"] + time_turn = tournament["time_turn"] + time_match = tournament["time_match"] + tolerance = tournament["tolerance"] + memory = tournament["memory"] + real_time_pos = int(tournament["real_time_pos"]) if real_time_pos > 0: real_time_pos = True else: real_time_pos = False - real_time_message = string.atoi(tournament['real_time_message']) + real_time_message = int(tournament["real_time_message"]) if real_time_message > 0: real_time_message = True else: real_time_message = False try: - upload_ratio = string.atof(tournament['upload_ratio']) + upload_ratio = string.atof(tournament["upload_ratio"]) except: upload_ratio = 1.0 try: - upload_offline_result = string.atoi( - tournament['upload_offline_result']) + upload_offline_result = int(tournament["upload_offline_result"]) if upload_offline_result == 1: upload_offline_result = True else: upload_offline_result = False except: upload_offline_result = True - remote_name = tournament['remote'] + remote_name = tournament["remote"] if remote_name: - remote_file = curpath + slash + 'remote' + slash + remote_name + '.txt' + remote_file = curpath + slash + "remote" + slash + remote_name + ".txt" remote = read_tournament(remote_file) - remote_host = remote['host'] - remote_username = remote['username'] - remote_password = remote['password'] - remote_path = remote['remotepath'] - if not remote_path[-1] == '/': - remote_path = remote_path + '/' - remote_online_path = remote_path + '/' - remote_tur_path = remote_path + tur_name + '/' - remote_info = (remote_host, remote_username, remote_password, - remote_online_path, remote_tur_path) + remote_host = remote["host"] + remote_username = remote["username"] + remote_password = remote["password"] + remote_path = remote["remotepath"] + if not remote_path[-1] == "/": + remote_path = remote_path + "/" + remote_online_path = remote_path + "/" + remote_tur_path = remote_path + tur_name + "/" + remote_info = ( + remote_host, + remote_username, + remote_password, + remote_online_path, + remote_tur_path, + ) else: remote_info = None ftp_queue = Ftp_Queue() - tra, sftp = ssh_connect() - result_dir = curpath + slash + 'result' + slash + tur_name + tra = ssh_connect() + if tra: + tra, sftp = tra + result_dir = curpath + slash + "result" + slash + tur_name if os.path.exists(result_dir): if not os.path.isdir(result_dir): os.remove(result_dir) os.makedirs(result_dir) else: os.makedirs(result_dir) - log_file = result_dir + slash + 'log.txt' - net_log_file = result_dir + slash + 'netlog.txt' - state_file = result_dir + slash + 'state.txt' - result_file = result_dir + slash + 'result.txt' - message_file = result_dir + slash + 'message.txt' - openings = read_opening(opening_file, string.atoi(board_size)) - - tournament_state = Tournament(curpath, engines, engine_ratings, - rating_diff, tur_name, board_size, rule, - openings, is_tournament, time_turn, - time_match, tolerance, memory, real_time_pos, - real_time_message) - - host = '0.0.0.0' - port = string.atoi(sys.argv[2]) + log_file = result_dir + slash + "log.txt" + net_log_file = result_dir + slash + "netlog.txt" + state_file = result_dir + slash + "state.txt" + result_file = result_dir + slash + "result.txt" + message_file = result_dir + slash + "message.txt" + openings = read_opening(opening_file, int(board_size)) + + tournament_state = Tournament( + curpath, + engines, + engine_ratings, + rating_diff, + tur_name, + board_size, + rule, + openings, + is_tournament, + time_turn, + time_match, + tolerance, + memory, + real_time_pos, + real_time_message, + ) + + host = "0.0.0.0" + port = int(sys.argv[2]) taccept = threading.Thread(target=accept_client, args=(host, port)) taccept.start() toutput = threading.Thread(target=output_client) @@ -1271,73 +1545,73 @@ def ssh_quit(): print_log("Server started.") - while (True): + while True: cur_input = input_queue.get() - print cur_input + print(cur_input) inaddr = cur_input[0] instr = cur_input[1].strip() - sinstr = re.split(r'\s', instr) + sinstr = re.split(r"\s", instr) cur_client = clients_state[inaddr] if len(sinstr) == 0: continue - if sinstr[0].lower() == 'connected': + if sinstr[0].lower() == "connected": cur_client.active = False cur_client.blacklist = None cur_client.process(output_queue) - elif sinstr[0].lower() == 'yes': - if cur_client.ask == 'player1': + elif sinstr[0].lower() == "yes": + if cur_client.ask == "player1": cur_client.has_player1 = True cur_client.process(output_queue) - elif cur_client.ask == 'player2': + elif cur_client.ask == "player2": cur_client.has_player2 = True cur_client.process(output_queue) - elif sinstr[0].lower() == 'no': - if cur_client.ask == 'player1': + elif sinstr[0].lower() == "no": + if cur_client.ask == "player1": cur_client.has_player1 = False cur_client.process(output_queue) - elif cur_client.ask == 'player2': + elif cur_client.ask == "player2": cur_client.has_player2 = False cur_client.process(output_queue) - elif sinstr[0].lower() == 'ok': - if cur_client.ask == 'match': + elif sinstr[0].lower() == "ok": + if cur_client.ask == "match": cur_client.started == True - cur_client.save_pos('') - elif cur_client.ask == 'real_time_pos': + cur_client.save_pos("") + elif cur_client.ask == "real_time_pos": cur_client.sent_real_time_pos = True cur_client.process(output_queue) - elif cur_client.ask == 'real_time_message': + elif cur_client.ask == "real_time_message": cur_client.sent_real_time_message = True cur_client.process(output_queue) - elif sinstr[0].lower() == 'received': - if cur_client.ask == 'player1': + elif sinstr[0].lower() == "received": + if cur_client.ask == "player1": cur_client.has_player1 = None cur_client.process(output_queue) - elif cur_client.ask == 'player2': + elif cur_client.ask == "player2": cur_client.has_player2 = None cur_client.process(output_queue) - elif sinstr[0].lower() == 'match': - if sinstr[1].lower() == 'finished': + elif sinstr[0].lower() == "match": + if sinstr[1].lower() == "finished": pos = sinstr[2] message = sinstr[3] result = sinstr[4] end_with = sinstr[5] cur_client.end(pos, message, result, end_with) cur_client.process(output_queue) - elif sinstr[0].lower() == 'pos': + elif sinstr[0].lower() == "pos": if real_time_pos: tmp_pos = sinstr[1] cur_client.tmp_pos = tmp_pos cur_client.process(output_queue) - elif sinstr[0].lower() == 'message': + elif sinstr[0].lower() == "message": if real_time_message: tmp_message = sinstr[1] cur_client.tmp_message = tmp_message cur_client.process(output_queue) - elif sinstr[0].lower() == 'blacklist': - if cur_client.ask == 'blacklist': - if sinstr[1] == 'None': + elif sinstr[0].lower() == "blacklist": + if cur_client.ask == "blacklist": + if sinstr[1] == "None": cur_client.blacklist = [] else: - cur_client.blacklist = sinstr[1].split(';') + cur_client.blacklist = sinstr[1].split(";") tournament_state.assign_match(cur_client) cur_client.process(output_queue) From a8d8ddeea6f53e8a16ca1f6b01bd9a42dc436ee4 Mon Sep 17 00:00:00 2001 From: Tianyi Hao Date: Thu, 9 May 2024 22:56:57 +0800 Subject: [PATCH 2/9] can kill by ctrl+c --- server/server.py | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/server/server.py b/server/server.py index 1ae22cf..4da0db1 100644 --- a/server/server.py +++ b/server/server.py @@ -8,7 +8,7 @@ import os import hashlib import base64 -from queue import Queue +from queue import Queue, Empty import subprocess import random import paramiko @@ -794,7 +794,7 @@ def parse_pos(pos, opening): len_opening = opening_length(opening) spos = pos.strip() if spos: - times = list( map(lambda x: int(x.split(",")[-1]), pos.strip().split("\n")))[ + times = list(map(lambda x: int(x.split(",")[-1]), pos.strip().split("\n")))[ len_opening: ] else: @@ -1197,7 +1197,12 @@ def recv_client(conn, addr): def output_client(): while True: - addr, outstr = output_queue.get() + while True: + try: + addr, outstr = output_queue.get(timeout=1.0) + break + except Empty: + continue out_str = repr(("output", addr, outstr)) print_log(out_str, net_log_file) if addr in trecvs.keys(): @@ -1214,7 +1219,7 @@ def accept_client(host, port): while True: conn, addr = s.accept() addr = addr[0] + ":" + str(addr[1]) - trecv = threading.Thread(target=recv_client, args=(conn, addr)) + trecv = threading.Thread(target=recv_client, args=(conn, addr), daemon=True) connect_addr(addr, trecv, conn) trecv.start() clients_state[addr] = Client_state(curpath, addr) @@ -1399,7 +1404,12 @@ def ssh_upload_process(): global ftp_queue if remote_info: while True: - upfile, is_online = ftp_queue.get() + while True: + try: + upfile, is_online = ftp_queue.get(timeout=1.0) + break + except Empty: + continue try: if is_online: r_path = remote_info[3] @@ -1534,19 +1544,24 @@ def ssh_quit(): host = "0.0.0.0" port = int(sys.argv[2]) - taccept = threading.Thread(target=accept_client, args=(host, port)) + taccept = threading.Thread(target=accept_client, args=(host, port), daemon=True) taccept.start() - toutput = threading.Thread(target=output_client) + toutput = threading.Thread(target=output_client, daemon=True) toutput.start() - tend = threading.Thread(target=check_end) + tend = threading.Thread(target=check_end, daemon=True) tend.start() - tftp = threading.Thread(target=ssh_upload_process) + tftp = threading.Thread(target=ssh_upload_process, daemon=True) tftp.start() print_log("Server started.") while True: - cur_input = input_queue.get() + while True: + try: + cur_input = input_queue.get(timeout=1.0) + break + except Empty: + continue print(cur_input) inaddr = cur_input[0] instr = cur_input[1].strip() From 53a18206c7875a72be5f1a502cf5865afc4809e7 Mon Sep 17 00:00:00 2001 From: Tianyi Hao Date: Fri, 10 May 2024 23:33:54 +0800 Subject: [PATCH 3/9] update --- client/new_protocol.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/client/new_protocol.py b/client/new_protocol.py index 7dd9564..7bf94ee 100644 --- a/client/new_protocol.py +++ b/client/new_protocol.py @@ -49,15 +49,13 @@ def __init__( shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - bufsize=1, close_fds="posix" in sys.builtin_module_names, cwd=self.working_dir, - universal_newlines=True, ) def enqueue_output(out, queue): for line in iter(out.readline, b""): - queue.put(line) + queue.put(line.decode()) out.close() self.queue = Queue() @@ -90,7 +88,7 @@ def init_board(self, board): def write_to_process(self, msg): # print('===>', msg) # sys.stdout.flush() - self.process.stdin.write(msg) + self.process.stdin.write(msg.encode()) self.process.stdin.flush() def suspend(self): @@ -198,12 +196,14 @@ def start(self): self.write_to_process("BOARD" + self.endl) for i in range(1, len(self.piece) + 1): self.process.stdin.write( - str(self.piece[i][0]) - + "," - + str(self.piece[i][1]) - + "," - + str(self.board[self.piece[i][0]][self.piece[i][1]][1]) - + self.endl + ( + str(self.piece[i][0]) + + "," + + str(self.piece[i][1]) + + "," + + str(self.board[self.piece[i][0]][self.piece[i][1]][1]) + + self.endl + ).encode() ) self.write_to_process("DONE" + self.endl) @@ -216,7 +216,9 @@ def swap2board(self): self.write_to_process("SWAP2BOARD" + self.endl) for i in range(1, len(self.piece) + 1): self.process.stdin.write( - str(self.piece[i][0]) + "," + str(self.piece[i][1]) + self.endl + ( + str(self.piece[i][0]) + "," + str(self.piece[i][1]) + self.endl + ).encode() ) self.write_to_process("DONE" + self.endl) From ceebcdbb68960736c0aeec24532349ee8b68893a Mon Sep 17 00:00:00 2001 From: Tianyi Hao Date: Fri, 10 May 2024 23:53:03 +0800 Subject: [PATCH 4/9] fix ftp queue --- server/server.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/server/server.py b/server/server.py index 4da0db1..715d704 100644 --- a/server/server.py +++ b/server/server.py @@ -1404,12 +1404,7 @@ def ssh_upload_process(): global ftp_queue if remote_info: while True: - while True: - try: - upfile, is_online = ftp_queue.get(timeout=1.0) - break - except Empty: - continue + upfile, is_online = ftp_queue.get() try: if is_online: r_path = remote_info[3] From b75dc5ce0639d4ccfdddee2e16f1faf42ef3f4fa Mon Sep 17 00:00:00 2001 From: Tianyi Hao Date: Fri, 10 May 2024 23:58:41 +0800 Subject: [PATCH 5/9] update debug --- client/server_debug.py | 34 ++++++++++++++++++---------------- server/client_debug.py | 12 +++++++----- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/client/server_debug.py b/client/server_debug.py index 0cfd222..d408a0c 100644 --- a/client/server_debug.py +++ b/client/server_debug.py @@ -3,36 +3,38 @@ import socket + def main(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) host = "localhost" port = 6780 s.bind((host, port)) s.listen(5) - + c, addr = s.accept() while True: - x = raw_input() - if x == 'exit': + x = input() + if x == "exit": break - elif x == 'sendengine': + elif x == "sendengine": with open("./tmp/Tito2014.zip", "rb") as f: - engine = f.read().encode('base64') - s = "engine send " + "Tito2014.zip".encode('base64') + " " + engine + engine = f.read().encode("base64") + s = "engine send " + "Tito2014.zip".encode("base64") + " " + engine c.send(s) - print "Tito2014.zip".encode('base64') - elif x == 'newmatch': - c.send("match new c3f044fafd550e01c97cf599f0cd7c31 e7d8817a65c86b9c4b6b675dd021269e "+ - "1000 100000 0 1000 j10 20 350000000 1") - c.recv(16*1024*1024) + print("Tito2014.zip".encode("base64")) + elif x == "newmatch": + c.send( + "match new c3f044fafd550e01c97cf599f0cd7c31 e7d8817a65c86b9c4b6b675dd021269e " + + "1000 100000 0 1000 j10 20 350000000 1" + ) + c.recv(16 * 1024 * 1024) pass else: c.send(x) - buf = c.recv(16*1024*1024) + buf = c.recv(16 * 1024 * 1024) if len(buf) > 0: - print addr, buf - -if __name__ == '__main__': - main() + print(addr, buf) +if __name__ == "__main__": + main() diff --git a/server/client_debug.py b/server/client_debug.py index be2a3a9..8b2e383 100644 --- a/server/client_debug.py +++ b/server/client_debug.py @@ -4,21 +4,23 @@ import string import threading + def recv_server(cur_socket): while True: try: data = cur_socket.recv(5242800) except: os._exit(0) - print data + print(data) + host = sys.argv[1] -port = string.atoi(sys.argv[2]) +port = int(sys.argv[2]) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) -trecv = threading.Thread(target = recv_server, args = (s,)) +trecv = threading.Thread(target=recv_server, args=(s,)) trecv.start() while True: - cmd = raw_input() + cmd = input() s.sendall(cmd) -s.close() \ No newline at end of file +s.close() From 2671bd8849aed4a1828f16d75ad7264bb42c0126 Mon Sep 17 00:00:00 2001 From: Tianyi Hao Date: Sat, 11 May 2024 01:01:23 +0800 Subject: [PATCH 6/9] update exc --- client/client.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/client/client.py b/client/client.py index b1d3ac6..72c9e6d 100644 --- a/client/client.py +++ b/client/client.py @@ -286,14 +286,19 @@ def main(): args = parser.parse_args() - client( - host=args.host, - port=int(args.port), - working_dir=args.working_dir, - debug=args.debug, - special_rule=args.special_rule, - blacklist=args.blacklist, - ).listen() + try: + client( + host=args.host, + port=int(args.port), + working_dir=args.working_dir, + debug=args.debug, + special_rule=args.special_rule, + blacklist=args.blacklist, + ).listen() + except ConnectionResetError: + print("Connection has been reset by the server.") + except ConnectionRefusedError: + print("Connection has been refused by the server.") if __name__ == "__main__": From 4b89ab66bcb85a46a744dd2963a5555de745100c Mon Sep 17 00:00:00 2001 From: Tianyi Hao Date: Sat, 18 May 2024 00:14:52 +0800 Subject: [PATCH 7/9] fix --- client/new_protocol.py | 7 +++++-- client/old_protocol.py | 5 ++++- server/server.py | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/client/new_protocol.py b/client/new_protocol.py index 7bf94ee..c8bb207 100644 --- a/client/new_protocol.py +++ b/client/new_protocol.py @@ -55,7 +55,7 @@ def __init__( def enqueue_output(out, queue): for line in iter(out.readline, b""): - queue.put(line.decode()) + queue.put(line.decode(errors="ignore")) out.close() self.queue = Queue() @@ -175,7 +175,10 @@ def wait(self, special_rule=""): if special_rule == "": self.piece[len(self.piece) + 1] = (x, y) - self.board[x][y] = (len(self.piece), self.color) + if x >= 0 and x < len(self.board) and y >= 0 and y < len(self.board[0]): + self.board[x][y] = (len(self.piece), self.color) + else: + raise RuntimeError("Invalid Move") return msg, x, y def turn(self, x, y): diff --git a/client/old_protocol.py b/client/old_protocol.py index 33c3c99..b71a553 100644 --- a/client/old_protocol.py +++ b/client/old_protocol.py @@ -160,7 +160,10 @@ def start(self): msg = self.read_msg() x, y = self.read_tah() self.piece[len(self.piece) + 1] = (x, y) - self.board[x][y] = (len(self.piece), self.color) + if x >= 0 and x < len(self.board) and y >= 0 and y < len(self.board[0]): + self.board[x][y] = (len(self.piece), self.color) + else: + raise RuntimeError("Invalid Move") return msg, x, y def clean(self): diff --git a/server/server.py b/server/server.py index 715d704..a1fae82 100644 --- a/server/server.py +++ b/server/server.py @@ -908,7 +908,7 @@ def end(self, pos, message, result, end_with): fpos.close() if upload_offline_result: ssh_upload(pos_path, False) - fmessage = open(result_path + slash + "message.txt", "a") + fmessage = open(result_path + slash + "message.txt", "a", encoding="utf-8") fmessage.write(message) fmessage.write("\n--> " + pos_path + "\n\n") fmessage.close() From bec117c465ee152176a55c9fef0e775c5e99cdfe Mon Sep 17 00:00:00 2001 From: Tianyi Hao Date: Sat, 18 May 2024 11:50:31 +0800 Subject: [PATCH 8/9] update dir --- client/client.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/client.py b/client/client.py index 72c9e6d..f8f867c 100644 --- a/client/client.py +++ b/client/client.py @@ -25,6 +25,8 @@ def __init__(self, host, port, working_dir, debug, special_rule, blacklist): self.engine_dir = os.path.join(self.working_dir, "engine") self.match_dir = os.path.join(self.working_dir, "match") self.folder_dir = os.path.join(self.match_dir, "folder") + if not os.path.isdir(self.working_dir): + os.mkdir(self.working_dir) if not os.path.isdir(self.engine_dir): os.mkdir(self.engine_dir) if not os.path.isdir(self.match_dir): From fce26ab8996c2607d62c084cafd9b6be89fd63e7 Mon Sep 17 00:00:00 2001 From: Tianyi Hao Date: Sat, 18 May 2024 19:03:11 +0800 Subject: [PATCH 9/9] python version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 258881f..0581834 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ### Introduction GomocupJudge is a new manager for Gomocup **under development**. -* Tested in Python 2.7 +* Tested in Python 3.8 ### Protocol