// File: /workspace/github_cpp_makefile_star2_O2/cpirc[P]Monochrome/src/search.cpp
// Function: start_search(SearchController&)
void start_search(SearchController& sc) {
    Stats stats;
    SearchStack ss[MAX_PLY];
    std::chrono::time_point<std::chrono::high_resolution_clock> start, end;

    clear_stats(stats);
    clear_ss(ss, MAX_PLY);

    set_stats(ss, stats);

    /* Timing */
    sc.search_start_time = 1000 * clock() / CLOCKS_PER_SEC;

    if (sc.movetime) {
        sc.search_end_time = sc.movetime / 2;
    } else if (sc.moves_per_session) {
        sc.search_end_time =
            (sc.increment * (sc.moves_per_session - 1) + sc.our_clock) /
            sc.moves_per_session;
    } else {
        sc.search_end_time =
            (sc.increment * (GUESSED_LENGTH - 1) + sc.our_clock) /
            GUESSED_LENGTH;
    }

    sc.search_end_time += sc.search_start_time;

    char mstr[6];
    Move best_move;
    int best_score = -INF;
    PV pv;

    /* Iterative deepening */
    for (std::uint32_t depth = 1; depth < sc.max_depth; ++depth) {
        PV depth_pv;
        int beta = INF;
        int alpha = -INF;

        int depth_best_score =
            search(sc, sc.pos, depth, alpha, beta, ss, depth_pv);

        // Check time used
        clock_t time_used =
            clock() * 1000 / CLOCKS_PER_SEC - sc.search_start_time;

        // See if we ran out of time
        if (depth > 1 &&
            time_used >= sc.search_end_time - sc.search_start_time) {
            break;
        }

        // Only update the best pv if we didn't run out of time
        pv = depth_pv;

        // Verify the pv is legal
        assert(pv_verify(sc.pos, pv));
        assert(pv.size() > 0);

        best_score = depth_best_score;

        bool mate = false;
        if (best_score > INF - MAX_PLY) {
            mate = true;
            best_score = INF - best_score;
        }
        if (best_score < -INF + MAX_PLY) {
            mate = true;
            best_score = -INF + best_score;
        }

        // Update info
        if (mate) {
            printf("info score mate %i depth %i nodes %" PRIu64 " time %lu pv ",
                   best_score, depth, stats.node_count, time_used);
        } else {
            printf("info score cp %i depth %i nodes %" PRIu64 " time %lu pv ",
                   best_score, depth, stats.node_count, time_used);
        }
        bool flipped = sc.pos.flipped;
        for (Move move : pv) {
            if (flipped) {
                move = flip_move(move);
            }
            move_to_lan(mstr, move);
            printf("%s ", mstr);
            flipped ^= 1;
        }
        printf("\n");

        // Exit if mate found
        if (mate) {
            break;
        }
    }

    if (pv.size() >= 1) {
        best_move = pv[0];
        if (sc.pos.flipped) {
            best_move = flip_move(best_move);
        }
        move_to_lan(mstr, best_move);

        printf("bestmove %s\n", mstr);
    } else {
        printf("bestmove 0000\n");
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x20678, %rsp          # imm = 0x20678
movq %rdi, %r15
leaq -0x60(%rbp), %rbx
andq $0x0, (%rbx)
leaq -0x20690(%rbp), %r14
pushq $0x40
popq %rsi
movq %r14, %rdi
callq 0x61c7
movq %r14, %rdi
movq %rbx, %rsi
callq 0x6232
callq 0x2120
movl $0x3e8, %ecx            # imm = 0x3E8
cqto
idivq %rcx
movq %rax, %rcx
movq %rax, 0x78(%r15)
movq 0x90(%r15), %rax
testq %rax, %rax
je 0x62ea
pushq $0x2
popq %rsi
jmp 0x6309
movl 0x6c(%r15), %esi
movq 0x70(%r15), %rax
testq %rsi, %rsi
je 0x6515
leal -0x1(%rsi), %edx
imulq %rdx, %rax
addq 0x88(%r15), %rax
cqto
idivq %rsi
addq %rcx, %rax
movq %rax, 0x80(%r15)
xorps %xmm0, %xmm0
leaq -0x50(%rbp), %rax
movaps %xmm0, (%rax)
andq $0x0, 0x10(%rax)
pushq $0x1
popq %rdx
leaq -0x36(%rbp), %r13
leaq 0x4ce5(%rip), %r14      # 0xb01a
movq %r15, -0x88(%rbp)
cmpl 0x68(%r15), %edx
jae 0x64af
xorps %xmm0, %xmm0
movaps %xmm0, -0x80(%rbp)
andq $0x0, -0x70(%rbp)
leaq -0x80(%rbp), %rax
movq %rax, (%rsp)
movq %r15, %rdi
movq %r15, %rsi
movl $0xffff8ad0, %ecx       # imm = 0xFFFF8AD0
movl $0x7530, %r8d           # imm = 0x7530
leaq -0x20690(%rbp), %r9
movl %edx, %r12d
callq 0x658b
movl %eax, %ebx
callq 0x2120
cqto
movl $0x3e8, %ecx            # imm = 0x3E8
idivq %rcx
movq %rax, %rcx
subq 0x78(%r15), %rcx
movq %rcx, -0x58(%rbp)
movl %r12d, -0x30(%rbp)
cmpl $0x2, %r12d
jb 0x63ad
cmpq 0x80(%r15), %rax
jge 0x64a6
leaq -0x50(%rbp), %r12
movq %r12, %rdi
leaq -0x80(%rbp), %rsi
callq 0x69aa
movq %r15, %rdi
movq %r12, %rsi
callq 0x3deb
testb %al, %al
je 0x6546
movq -0x48(%rbp), %rax
cmpq -0x50(%rbp), %rax
je 0x6527
movl $0x7530, %eax           # imm = 0x7530
subl %ebx, %eax
cmpl $0x74f1, %ebx           # imm = 0x74F1
cmovll %ebx, %eax
setl %cl
cmpl $0xffff8b10, %eax       # imm = 0xFFFF8B10
setge %dl
andb %cl, %dl
movb %dl, -0x29(%rbp)
je 0x640f
movq -0x60(%rbp), %rcx
leaq 0x4bde(%rip), %rdi      # 0xafe9
movl %ebx, %esi
jmp 0x6428
leal -0x7530(%rax), %esi
cmpl $0xffff8b10, %eax       # imm = 0xFFFF8B10
cmovgel %eax, %esi
movq -0x60(%rbp), %rcx
leaq 0x4b8e(%rip), %rdi      # 0xafb6
movl -0x30(%rbp), %edx
movq -0x58(%rbp), %r8
xorl %eax, %eax
callq 0x2030
movb 0x41(%r15), %bl
movq -0x50(%rbp), %r12
movq -0x48(%rbp), %r15
cmpq %r15, %r12
je 0x647d
movl (%r12), %eax
movl %eax, %esi
andl $0x3ffff, %esi          # imm = 0x3FFFF
xorl $0xe38, %esi            # imm = 0xE38
testb $0x1, %bl
cmovel %eax, %esi
movq %r13, %rdi
callq 0x3baa
movq %r14, %rdi
movq %r13, %rsi
xorl %eax, %eax
callq 0x2030
xorb $0x1, %bl
addq $0x4, %r12
jmp 0x6442
pushq $0xa
popq %rdi
callq 0x21f0
leaq -0x80(%rbp), %rdi
callq 0x6a76
movl -0x30(%rbp), %edx
incl %edx
cmpb $0x0, -0x29(%rbp)
movq -0x88(%rbp), %r15
jne 0x633c
jmp 0x64af
leaq -0x80(%rbp), %rdi
callq 0x6a76
movq -0x50(%rbp), %rax
cmpq %rax, -0x48(%rbp)
je 0x64ee
movl (%rax), %eax
movl %eax, %esi
andl $0x3ffff, %esi          # imm = 0x3FFFF
xorl $0xe38, %esi            # imm = 0xE38
cmpb $0x0, 0x41(%r15)
cmovel %eax, %esi
leaq -0x36(%rbp), %rdi
callq 0x3baa
leaq 0x4b3d(%rip), %rdi      # 0xb01e
leaq -0x36(%rbp), %rsi
xorl %eax, %eax
callq 0x2030
jmp 0x64fa
leaq 0x4d1a(%rip), %rdi      # 0xb20f
callq 0x2230
leaq -0x50(%rbp), %rdi
callq 0x6a76
addq $0x20678, %rsp          # imm = 0x20678
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
imulq $0x27, %rax, %rax
addq 0x88(%r15), %rax
pushq $0x28
jmp 0x62e7
leaq 0x4a7a(%rip), %rdi      # 0xafa8
leaq 0x492e(%rip), %rsi      # 0xae63
leaq 0x4a46(%rip), %rcx      # 0xaf82
movl $0x181, %edx            # imm = 0x181
callq 0x2110
leaq 0x4a1f(%rip), %rdi      # 0xaf6c
leaq 0x490f(%rip), %rsi      # 0xae63
leaq 0x4a27(%rip), %rcx      # 0xaf82
movl $0x180, %edx            # imm = 0x180
callq 0x2110
movq %rax, %rbx
jmp 0x657a
jmp 0x656e
jmp 0x656e
movq %rax, %rbx
leaq -0x80(%rbp), %rdi
callq 0x6a76
leaq -0x50(%rbp), %rdi
callq 0x6a76
movq %rbx, %rdi
callq 0x2290