Esempio n. 1
0
 def to_cboard(self):
     cboard = CBoard()
     for x, y in self.board.history:
         move_id = x + 5 * y
         while cboard.cube[move_id] != EMPTY:
             move_id += 25
         cboard.move(move_id)
     return cboard
Esempio n. 2
0
def generator():
    easy = open(easyname, mode='w')
    hard = open(hardname, mode='w')
    counter = 0
    seed = -1
    while counter < 1000:
        seed += 1
        rand = Random(seed)
        board = CBoard()
        gameover = False
        for i in range(rand.randint(8, 18)):
            move_id = rand.choice(list(board.get_valid_moves()))
            if is_win(board, move_id):
                gameover = True
                break
            board.move(move_id)
        if gameover:
            continue
        for _ in range(1):
            move_id = rand.choice(list(board.get_valid_moves()))
            if is_win(board, move_id):
                break
            board.move(move_id)
            results = negamax_full(board, 4)
            file = hard if abs(results[0][1]) < WIN_SCORE else easy
            counter += 1
            line = ",".join([str(x) for x in board.history[0:board.round]])
            print("{} @{}".format(line, counter))
            file.write(line + "\n")
    easy.close()
    hard.close()
Esempio n. 3
0
def test_check_win():
    board = CBoard()
    board.move(1)
    board.move(6)
    board.move(2)
    board.move(7)
    board.move(3)
    board.move(8)
    assert is_win(board, 0)
    assert is_win(board, 4)
Esempio n. 4
0
def test_easy_prevent():
    board = CBoard()
    board.move(7)
    board.move(24)
    board.move(8)
    # must now move to 6 (or 5 or 9) to prevent a direct loss
    result = negamax_full(board)
    assert result[0][0] in [5, 6, 9]
    assert result[1][0] in [5, 6, 9]
    assert result[2][0] in [5, 6, 9]
Esempio n. 5
0
def negamax(board: CBoard, opponent_move_id, depth, alpha, beta):
    board.nodes_counter += 1
    if depth == 0:
        return 0  # not the best estimation :)

    # ok let's do the actual move
    board.move(opponent_move_id)
    possible_moves = board.get_valid_moves()

    # quick lookahead of 1
    for next_move_id in possible_moves:
        if is_win(board, next_move_id):
            board.undo_move()
            return MAX_SCORE - board.round  # we win, yay!

    # quick lookahead of 2
    forced_move_id = -1
    board.current_player ^= 1  # quick zero-move
    for next_move_id in possible_moves:
        if is_win(board, next_move_id):
            if forced_move_id != -1:
                # we will loose next round
                board.current_player ^= 1  # reset to actual player
                board.undo_move()
                return -(MAX_SCORE - board.round - 1)
            forced_move_id = next_move_id
    board.current_player ^= 1

    if forced_move_id != -1:
        sorted_moves = [forced_move_id]
    else:
        # TODO: actual sorting
        sorted_moves = possible_moves

    best_score = -MAX_SCORE
    for next_move_id in sorted_moves:
        current_score = -negamax(board, next_move_id, depth - 1, -beta, -alpha)
        if current_score > best_score:
            best_score = current_score
            if best_score > alpha:
                alpha = best_score
                if alpha >= beta:
                    board.beta_cutoffs += 1
                    break  # cut-off
    board.undo_move()
    return best_score
Esempio n. 6
0
def run_testset(filename):
    counter, solved, nodes, t, cutoff = 0, 0, 0, 0, 0
    with open(filename) as file:
        for line in file:
            board = CBoard()
            for move_id in map(lambda x: int(x), line.split(",")):
                board.move(move_id)
            start = datetime.datetime.now()
            resut = negamax_full(board, depth=4)
            end = datetime.datetime.now()
            micro = (end - start).microseconds

            # stats
            if abs(resut[0][1]) > WIN_SCORE:
                solved += 1
            counter += 1
            nodes += board.nodes_counter
            cutoff += board.beta_cutoffs
            t += micro
            print("{}/{}: nodes={} cutoffs={} ms={}"
                  .format(counter, solved, round(nodes / counter), round(cutoff / counter), round(t / counter / 100)))
Esempio n. 7
0
def test_easy_win():
    board = CBoard()
    board.move(1)
    board.move(6)
    board.move(2)
    board.move(7)
    # must now move to 3 for a win
    assert negamax_full(board)[0][0] == 3
Esempio n. 8
0
def negamax_full(board: CBoard, depth=3):
    """
    :param board:
    :param depth: search depth
    :return:
    """
    sorted_moves = board.get_valid_moves()
    results = []
    for next_move_id in sorted_moves:
        if is_win(board, next_move_id):
            current_score = MAX_SCORE - board.round
        else:
            current_score = -negamax(board, next_move_id, depth, -MAX_SCORE,
                                     MAX_SCORE)
        results.append((next_move_id, current_score))
    return sorted(results, key=lambda x: x[1], reverse=True)
Esempio n. 9
0
def test_undo():
    board = CBoard()
    board.move(1)
    before = deepcopy(board.cube)
    board.move(24)
    board.move(14)
    board.move(5)
    board.undo_move()
    board.undo_move()
    board.undo_move()
    assert before == board.cube
Esempio n. 10
0
def test_check_no_win():
    board = CBoard()
    board.move(1)
    assert not is_win(board, 0)
Esempio n. 11
0
    return best_score


def negamax_full(board: CBoard, depth=3):
    """
    :param board:
    :param depth: search depth
    :return:
    """
    sorted_moves = board.get_valid_moves()
    results = []
    for next_move_id in sorted_moves:
        if is_win(board, next_move_id):
            current_score = MAX_SCORE - board.round
        else:
            current_score = -negamax(board, next_move_id, depth, -MAX_SCORE,
                                     MAX_SCORE)
        results.append((next_move_id, current_score))
    return sorted(results, key=lambda x: x[1], reverse=True)


if __name__ == "__main__":
    test_board = CBoard()
    test_board.move(1)
    test_board.move(6)
    test_board.move(2)
    test_board.move(7)
    print(test_board)
    best_move = negamax_full(test_board)
    print(best_move)