예제 #1
0
파일: gui.py 프로젝트: willGuimont/chess
    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
예제 #2
0
 def __draw_piece(self, chess: Chess, x: int, y: int):
     piece = chess.get_maybe_piece_at((x, y))
     if piece.is_nothing():
         return
     piece = piece.get()
     str_piece = self.__show_piece(piece)
     self.__draw_label(piece.get_color(), str_piece, self.__half_tile_size, self.__half_tile_size, self.__piece_size)
예제 #3
0
def getNewGame(id):  # Consider just returning a string instead of all these operations
    try:
        chess_dict = pack_chess(Chess())
        result = {"status" : 201, "chess" : chess_dict, 'id' : id}
        return result
    except Exception as e:
        # print(e)
        return {"status" : 500, "chess" : "None", "id" : id, "msg" : "Parsing input caused exception. Server incompetently programmed"}
예제 #4
0
def unpack_chess(chess_json):
    try:
        chess_dict = json.loads(chess_json)
        chess_dict['board'] = np.array(chess_dict['board'], dtype='i1')

        if chess_dict['last_move'] is not None:
            chess_dict['last_move'] = Move(None, None, move_dict=chess_dict['last_move'])

        chess_dict['legal_moves'] = [Move(None, None, move_dict=move_dict) for move_dict in chess_dict['legal_moves']]
        chess = Chess(chess_dict=chess_dict)
        return chess
    except:
        traceback.print_exc()  # For debugging
        # print(e)
        return None
예제 #5
0
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)
예제 #6
0
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)
예제 #7
0
def train(continu=True,
          depth=1,
          rand_min=0.2,
          rand_max=1.0,
          lr_max=8e-5,
          lr_min=1e-6,
          reg=0.005,
          num_threads=4):  # add more parameters probably.
    if continu:
        nn = load_nn("latest")
        best_nn = load_nn("best")
    else:
        nn = NeuralNet()
        nn.init_net(input_size=386,
                    output_size=1,
                    hidden_size=1000,
                    number_of_hidden=8)
        resets = 0
        while abs(nn.predict(chess_ai.chess_to_nn_input(Chess()))) > .1:
            nn = NeuralNet()
            nn.init_net(input_size=386,
                        output_size=1,
                        hidden_size=1000,
                        number_of_hidden=8)
            resets += 1
        print("nn started. Start predict: ",
              nn.predict(chess_ai.chess_to_nn_input(Chess())), "after", resets,
              "resets")
        best_nn = copy.deepcopy(nn)
    # best_nn = load_nn("best") # crashes if no such nn is saved

    with open("logs/log.txt", "a") as log_file:
        log_file.write("\n=========== New Training Run ================\n")
    bool_dict = {"bool": True}
    ui_thread = threading.Thread(target=shutdown_gui_thread,
                                 args=(bool_dict, ))
    ui_thread.start()
    # thread.start_new_thread(shutdown_gui_thread, (bool_dict, )) # starts thread, which displays gui to allow for easy graceful shutdown.
    lr = lr_max

    result_counts = [1, 1, 1]
    count = 0
    randomness = rand_max

    if continu:
        with open("saved_nns/progress.txt") as f:

            settings_dict = json.loads(f.read())
            result_counts = settings_dict["result_counts"]
            count = settings_dict["count"]
            lr = settings_dict["lr"]
            lr_min = settings_dict["lr_min"]
            randomness = settings_dict["rand"]
            rand_min = settings_dict["rand_min"]

    # else:
    #     result_counts = [1, 1, 1]  # index 0: counts of black wins, index 1: Ties, index 2: white wins
    #     count = 0

    while bool_dict[
            "bool"]:  # This dict is given to the UI thread. This allows for stopping the training via UI

        result_list = [None] * num_threads
        threads = []

        for i in range(num_threads):
            # print("Starting thread", i)
            thread = threading.Thread(target=run_one_game,
                                      args=(nn, randomness, depth, reg,
                                            result_counts, count + i, i,
                                            result_list, lr))
            threads.append(thread)
            thread.daemon = True
            thread.start()

        for thread in threads:
            thread.join()

        # print("All threads done")
        # print("TODO: merge thread results and update")  # TODO!

        avg_db = [
        ]  # Not actually taking the average. Just sum up (maybe reduce learning rate)
        avg_dw = []
        for db, dw, res, print_string, cost_string in result_list:
            lr_factor = 1 - result_counts[res + 1] / sum(result_counts)
            # print(res, lr_factor, result_counts)
            if not avg_db:
                avg_db = db
                avg_dw = dw
            else:
                for i in range(len(avg_db)):
                    avg_db[i] += db[i] * lr_factor
                    avg_dw[i] += dw[i] * lr_factor

            result_counts[res + 1] += 1
            if res == 1:
                cost_file_name = "logs/win_costs.csv"
            elif res == 0:
                cost_file_name = "logs/draw_costs.csv"
            else:
                cost_file_name = "logs/loss_costs.csv"

            print_string += ", lr_factor: " + str("{:.3f}".format(lr_factor))

            with open("logs/detailed_log.txt", "a") as log_file:
                log_file.write(print_string + "\n")
            with open(cost_file_name, "a") as cost_file:
                cost_file.write(cost_string)
            print(print_string)

        for i in range(len(avg_db)):
            avg_db[i] = avg_db[i] * (1 / num_threads)
            avg_dw[i] = avg_dw[i] * (1 / num_threads)

        nn.update_from_gradients(avg_db, avg_dw, lr=lr)

        count += num_threads
        if count > 200:
            randomness = max(
                rand_min, randomness * 0.995
            )  # Reduce randomness a little each run, until it becomes less than rand_min
        if count > 400:
            lr = max(lr_min, lr * 0.995)
        # 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: " + str(chess.turn_num)
        #                  + ", Randomness:" + str("{:.2f}".format(randomness))
        #                  + ", lr:" + str("{:.5f}".format(lr))
        #                  + ", lr factor:" + str("{:.3f}".format(lr_factor))
        #                  + ", Win:" + str(result)
        #                  + ", Sum: " + str(sum_val)
        #                  + ", Val:" + 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)

        # TODO SAVE COSTS FOR GRAPHING LATER
        # print("Game", count, ", Total Cost:", "{:.2f}".format(total_cost[0]), "Last cost: ", cost, "Turns: ", chess.turn_num, ", Randomness:", "{:.2f}".format(randomness), ", lr:", "{:.4f}".format(lr), "lr factor:", "{:.3f}".format(lr_factor), ", Winner:", chess.winner, ", Val:", "{:.5f}".format(val))
        if count % 200 == 0:  # every X games test and backup
            best_nn = test_and_backup(nn, best_nn, count)

    # test_and_backup(nn, best_nn, count)
    save_nn("latest", nn)
    with open("logs/log.txt", "a") as log_file:
        log_file.write("\n=========== Training Run Ended ================\n")
    settings = {
        "count": count,
        "result_counts": result_counts,
        "lr": lr,
        "lr_min": lr_min,
        "rand": randomness,
        "rand_min": rand_min
    }
    with open("saved_nns/progress.txt", "w") as f:
        f.write(json.dumps(settings))
예제 #8
0
파일: gui.py 프로젝트: willGuimont/chess
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()
예제 #9
0
파일: conv_test.py 프로젝트: jon0735/chess
# print(x6)
# print(x7)

# print("cuda available", torch.cuda.is_available())
# print("input cuda: ", x.is_cuda)

# print(type(x1))

# print(conv_nn(x1, x2))

# r1 = conv_nn(x1, x2)
# r2 = conv_nn(x3, x2)
# print("r1:", r1, "r2:", r2)
# print("r1 < r2 ?: ", r1 < r2)

# if r1 < r2:
#     print("true")
# else:
#     print("false")

chess = Chess()

cnn_input, lin_input = chess_ai.chess_to_cnn_input(chess)

# print(cnn_input)
# print(lin_input)

cnn_input = cnn_input.cuda()
lin_input = lin_input.cuda()

print(conv_nn(cnn_input, lin_input))