def run_one_game(nn, randomness, depth, reg, result_counts, count, thread_num, result_list, lr): chess = Chess() states = [] while chess.is_in_progress: val = None if chess.turn_num < 3 or random.random() < randomness: move = random.choice(chess.legal_moves) else: move, val = chess_ai.choose_move_ab( chess, depth=depth, eval_fun=chess_ai.nn_eval, nn=nn, randomize=False ) # Consider saving val for later update (avoid redoing forward pass) chess.move(move) states.append(chess._efficient_copy()) val = nn.predict(chess_ai.chess_to_nn_input(chess))[0] result = 0 if chess.winner is None else chess.winner # result_counts[result + 1] += 1 total = sum(result_counts) # TODO reconsider this entire lr_factor approach # lr_factor = (total - result_counts[result + 1]) / total total_cost = 0 last_cost = None result_ = result avg_dw = [] avg_db = [] for i, state in enumerate(reversed(states)): # if i > 0: # result_ = result_ * .95 # TODO reconsider this nn_input = chess_ai.chess_to_nn_input(state) cost, grad = nn.cost_grad( nn_input, result_, reg=reg ) # TODO reconsider weight decay (and check if it even works (it does not right now. Disabled in neural_net.py)) if last_cost is None: last_cost = cost # lr2 = lr_factor * lr/(i+1) # TODO do this properly. total_cost += cost if not avg_dw: avg_dw = grad["dw"] avg_db = grad["db"] else: for j in range(len(avg_db)): avg_dw[j] += grad["dw"][j] / ((i + 1) * (i + 1)) avg_db[j] += grad["db"][j] / ((i + 1) * (i + 1)) if count < 200: break sum_val = np.sum(chess.board) avg_cost = total_cost / chess.turn_num if count >= 200 else total_cost print_string = ("Game " + str(count) + ", Avg Cost: " + str("{:.3f}".format(avg_cost[0])) + ", Last cost: " + str("{:.3f}".format(last_cost[0])) + ", Turns: " + ((3 - len(str(chess.turn_num))) * " ") + str(chess.turn_num) + ", Randomness: " + str("{:.2f}".format(randomness)) + ", lr: " + str("{:.3f}".format(lr * 1e5)) + "e5" + ", Win: " + (str(result) if result < 0 else (" " + str(result))) + ", Sum: " + ((2 - len(str(abs(sum_val)))) * " ") + (str(sum_val) if sum_val < 0 else (" " + str(sum_val))) + ", Val: " + (str("{:.4f}".format(val)) if val < 0 else (" " + str("{:.4f}".format(val))))) # print(print_string) # with open("logs/detailed_log.txt", "a") as log_file: # log_file.write(print_string + "\n") # if result == 1: # cost_file_name = "logs/win_costs.csv" # elif result == 0: # cost_file_name = "logs/draw_costs.csv" # else: # cost_file_name = "logs/loss_costs.csv" # with open(cost_file_name, "a") as cost_file: cost_string = (str(count) + "," + str(chess.turn_num) + "," + str(total_cost[0]) + "," + str(avg_cost[0]) + "," + str(last_cost[0]) + "\n") # cost_file.write(cost_string) result_list[thread_num] = (avg_db, avg_dw, result, print_string, cost_string)
def test_and_backup(new_nn, best_nn, count, repetitions=4, save_to_files=True): print("test and backup started") t = time.time() string = str(t) save_nn("latest", new_nn) save_nn(string, new_nn) new_wins = 0 best_wins = 0 draws = 0 for i in range(repetitions): chess = Chess() newest_starting = True if i % 2 == 0 else False newest_in_turn = True if newest_starting else False while chess.is_in_progress: nn = new_nn if newest_in_turn else best_nn # Set the nn used in this round newest_in_turn = not newest_in_turn # change bool value of if newest nn is in turn if chess.turn_num < 5: # random opening move = random.choice(chess.legal_moves) else: move, val = chess_ai.choose_move_ab(chess, depth=1, eval_fun=chess_ai.nn_eval, nn=nn, randomize=True) chess.move(move) if (newest_starting and chess.winner == 1) or (not newest_starting and chess.winner == -1): new_wins += 1 win_string = "New" elif (newest_starting and chess.winner == -1) or (not newest_starting and chess.winner == 1): best_wins += 1 win_string = "Best" else: draws += 1 win_string = "None" print("Winner: ", win_string, ", Last value: ", val) print("New wins:", new_wins, ", Best wins:", best_wins, ", Draws:", draws) new_wins_sum = 0 sum_wins = 0 draws = 0 for i in range(repetitions): chess = Chess() newest_starting = True if i % 2 == 0 else False newest_in_turn = True if newest_starting else False while chess.is_in_progress: if chess.turn_num < 5: #Random opening move = random.choice(chess.legal_moves) else: if newest_in_turn: move, val = chess_ai.choose_move_ab( chess, depth=1, eval_fun=chess_ai.nn_eval, nn=nn, randomize=True) # TODO increase depth? else: move, val = chess_ai.choose_move_ab(chess, depth=1, randomize=True) newest_in_turn = not newest_in_turn chess.move(move) if (newest_starting and chess.winner == 1) or (not newest_starting and chess.winner == -1): new_wins_sum += 1 win_string = "New" elif (newest_starting and chess.winner == -1) or (not newest_starting and chess.winner == 1): sum_wins += 1 win_string = "Sum" else: draws += 1 win_string = "None" print("Winner: ", win_string, ", Last value: ", val) print("New wins:", new_wins_sum, ", Sum wins:", sum_wins, ", Draws:", draws) if save_to_files: with open("logs/log.txt", "a") as log_file: log_file.write("\n") log_file.write("Time: " + str(time.time()) + ", Count: " + str(count) + ", Repetitions: " + str(repetitions)) log_file.write("\nNew Wins: " + str(new_wins) + ", Best Wins: " + str(best_wins)) log_file.write("\nNew Wins: " + str(new_wins_sum) + ", Sum Wins: " + str(sum_wins)) log_file.write("\n") # print("new wins: ", new_wins, ", best wins: ", best_wins) # print("new wins: ", new_wins_sum, ", sum wins: ", sum_wins) if new_wins > best_wins: save_nn("best", new_nn) return new_nn else: return copy.deepcopy(best_nn)
class Game(pyglet.window.Window): WHITE_PIECE_COLOR = (255, 255, 255, 255) BLACK_PIECE_COLOR = (0, 0, 0, 255) WHITE_TILE_COLOR = (0, 1, 0, 1) BLACK_TILE_COLOR = (1, 0, 0, 1) TILE_SIZE = 52 PIECE_SIZE = 40 def __init__(self): super().__init__(width=640, height=600, caption='Chess') self.__chess = Chess() self.__ui = UIBoard((self.__chess.BOARD_SIZE, self.__chess.BOARD_SIZE), self.WHITE_PIECE_COLOR, self.BLACK_PIECE_COLOR, self.WHITE_TILE_COLOR, self.BLACK_TILE_COLOR, self.TILE_SIZE, self.PIECE_SIZE, self.width, self.height) self.__selected_piece = Maybe.nothing() self.__winner = None def on_draw(self): self.clear() self.__ui.draw_board(self.__chess) if self.__selected_piece.is_just(): try: p = self.__selected_piece.get() possible_captures = self.__chess.get_possible_captures_for(p) possible_moves = self.__chess.get_possible_moves_for(p) self.__ui.draw_captures(p, possible_captures) self.__ui.draw_moves(p, possible_moves) self.__ui.draw_selected_piece(p) except Exception as e: print(e) print(traceback.print_exc()) if self.__winner is not None: winner = 'White' if self.__winner == Piece.Color.WHITE else 'Black' label = pyglet.text.Label(f'Winner: {winner}', font_size=32, color=(255, 255, 255, 255), x=self.width / 2, y=50, anchor_x='center', anchor_y='center') label.draw() def on_mouse_press(self, x: int, y: int, button: int, modifiers: int): if self.__winner is not None: return i, j = self.__ui.get_cell_index_from_mouse_position(x, y) if 0 <= i < self.__chess.BOARD_SIZE and 0 <= j < self.__chess.BOARD_SIZE: if self.__selected_piece.is_nothing(): maybe_piece = self.__chess.get_maybe_piece_at((i, j)) if maybe_piece.is_just(): p = maybe_piece.get() if p.get_color() == self.__chess.get_player_color(): self.__selected_piece = maybe_piece else: pos = (i, j) if pos == self.__selected_piece.get().get_position(): self.__selected_piece = Maybe.nothing() else: p = self.__selected_piece.get() possible_captures = self.__chess.get_possible_captures_for( p) possible_moves = self.__chess.get_possible_moves_for(p) if pos in possible_captures: self.__chess.capture(p, pos) self.__selected_piece = Maybe.nothing() elif pos in possible_moves: self.__chess.move(p, pos) self.__selected_piece = Maybe.nothing() self.__winner = self.__chess.get_winner()