// File: /workspace/github_cpp_makefile_star2_O1/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, %r14
movq $0x0, -0x60(%rbp)
leaq -0x20690(%rbp), %rax
xorl %ecx, %ecx
movb %cl, (%rax)
movq $0x0, 0x804(%rax)
incb %cl
addq $0x818, %rax            # imm = 0x818
cmpb $0x40, %cl
jne 0x7fc7
leaq -0x20690(%rbp), %rax
movzbl (%rax), %ecx
negq %rcx
imulq $0x818, %rcx, %rcx      # imm = 0x818
addq %rbp, %rcx
addq $-0x90, %rcx
cmpq %rax, %rcx
jbe 0x801a
leaq -0x60(%rbp), %rdx
movq %rdx, 0x810(%rax)
addq $0x818, %rax            # imm = 0x818
cmpq %rcx, %rax
jb 0x8008
callq 0x3110
movabsq $0x20c49ba5e353f7cf, %rcx # imm = 0x20C49BA5E353F7CF
imulq %rcx
movq %rdx, %rcx
movq %rdx, %rax
shrq $0x3f, %rax
sarq $0x7, %rcx
addq %rax, %rcx
movq %rcx, 0x78(%r14)
movq 0x90(%r14), %rdx
testq %rdx, %rdx
je 0x805c
movq %rdx, %rax
shrq $0x3f, %rax
addq %rdx, %rax
sarq %rax
jmp 0x80a4
movl 0x6c(%r14), %esi
movq 0x70(%r14), %rax
testq %rsi, %rsi
je 0x807e
leal -0x1(%rsi), %edx
imulq %rdx, %rax
addq 0x88(%r14), %rax
cqto
idivq %rsi
jmp 0x80a4
imulq $0x27, %rax, %rax
addq 0x88(%r14), %rax
movabsq $0x6666666666666667, %rdx # imm = 0x6666666666666667
imulq %rdx
movq %rdx, %rax
shrq $0x3f, %rdx
sarq $0x4, %rax
addq %rdx, %rax
addq %rcx, %rax
movq %rax, 0x80(%r14)
xorps %xmm0, %xmm0
movaps %xmm0, -0x50(%rbp)
movq $0x0, -0x40(%rbp)
cmpl $0x2, 0x68(%r14)
jb 0x8270
movl $0x1, %ebx
leaq -0x36(%rbp), %r12
leaq 0x5062(%rip), %r15      # 0xd13a
movq %r14, -0x58(%rbp)
xorps %xmm0, %xmm0
movaps %xmm0, -0x80(%rbp)
movq $0x0, -0x70(%rbp)
leaq -0x80(%rbp), %rax
movq %rax, (%rsp)
movq %r14, %rdi
movq %r14, %rsi
movl %ebx, %edx
movl $0xffff8ad0, %ecx       # imm = 0xFFFF8AD0
movl $0x7530, %r8d           # imm = 0x7530
leaq -0x20690(%rbp), %r9
callq 0x8349
movl %eax, %r13d
callq 0x3110
movabsq $0x20c49ba5e353f7cf, %rcx # imm = 0x20C49BA5E353F7CF
imulq %rcx
movq %rdx, %rax
shrq $0x3f, %rax
sarq $0x7, %rdx
addq %rax, %rdx
movq %rdx, %rax
subq 0x78(%r14), %rax
movq %rax, -0x88(%rbp)
movl %ebx, -0x30(%rbp)
cmpl $0x2, %ebx
jb 0x8158
cmpq 0x80(%r14), %rdx
jge 0x8262
movq %r14, %rbx
leaq -0x50(%rbp), %r14
movq %r14, %rdi
leaq -0x80(%rbp), %rsi
callq 0x8a42
movq %rbx, %rdi
movq %r14, %rsi
callq 0x5156
testb %al, %al
je 0x82db
movq -0x48(%rbp), %rax
cmpq -0x50(%rbp), %rax
je 0x82fa
movl $0x7530, %eax           # imm = 0x7530
subl %r13d, %eax
cmpl $0x74f1, %r13d          # imm = 0x74F1
setl %cl
cmovll %r13d, %eax
leal -0x7530(%rax), %esi
cmpl $0xffff8b10, %eax       # imm = 0xFFFF8B10
setge %dl
cmovgel %eax, %esi
andb %cl, %dl
movb %dl, -0x29(%rbp)
movq -0x60(%rbp), %rcx
leaq 0x4f13(%rip), %rdi      # 0xd0d6
leaq 0x4f3f(%rip), %rax      # 0xd109
cmovneq %rax, %rdi
movl -0x30(%rbp), %edx
movq -0x88(%rbp), %r8
xorl %eax, %eax
callq 0x3040
movq -0x50(%rbp), %r13
movq -0x48(%rbp), %rbx
cmpq %rbx, %r13
je 0x822f
movq -0x58(%rbp), %rax
movb 0x41(%rax), %r14b
movl (%r13), %eax
movl %eax, %esi
andl $0x3ffff, %esi          # imm = 0x3FFFF
xorl $0xe38, %esi            # imm = 0xE38
testb $0x1, %r14b
cmovel %eax, %esi
movq %r12, %rdi
callq 0x4ee6
movq %r15, %rdi
movq %r12, %rsi
xorl %eax, %eax
callq 0x3040
xorb $0x1, %r14b
addq $0x4, %r13
cmpq %rbx, %r13
jne 0x81f4
movl $0xa, %edi
callq 0x3220
movq -0x80(%rbp), %rdi
testq %rdi, %rdi
je 0x8247
callq 0x31a0
cmpb $0x0, -0x29(%rbp)
movq -0x58(%rbp), %r14
movl -0x30(%rbp), %ebx
je 0x8270
incl %ebx
cmpl 0x68(%r14), %ebx
jb 0x80dc
jmp 0x8270
movq -0x80(%rbp), %rdi
testq %rdi, %rdi
je 0x8270
callq 0x31a0
movq -0x50(%rbp), %rax
cmpq %rax, -0x48(%rbp)
je 0x82af
movl (%rax), %eax
movl %eax, %esi
andl $0x3ffff, %esi          # imm = 0x3FFFF
xorl $0xe38, %esi            # imm = 0xE38
cmpb $0x0, 0x41(%r14)
cmovel %eax, %esi
leaq -0x36(%rbp), %rdi
callq 0x4ee6
leaq 0x4e9c(%rip), %rdi      # 0xd13e
leaq -0x36(%rbp), %rsi
xorl %eax, %eax
callq 0x3040
jmp 0x82bb
leaq 0x5079(%rip), %rdi      # 0xd32f
callq 0x3260
movq -0x50(%rbp), %rdi
testq %rdi, %rdi
je 0x82c9
callq 0x31a0
addq $0x20678, %rsp          # imm = 0x20678
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x4daa(%rip), %rdi      # 0xd08c
leaq 0x4c9a(%rip), %rsi      # 0xcf83
leaq 0x4db2(%rip), %rcx      # 0xd0a2
movl $0x180, %edx            # imm = 0x180
callq 0x3100
leaq 0x4dc7(%rip), %rdi      # 0xd0c8
leaq 0x4c7b(%rip), %rsi      # 0xcf83
leaq 0x4d93(%rip), %rcx      # 0xd0a2
movl $0x181, %edx            # imm = 0x181
callq 0x3100
movq %rax, %rbx
jmp 0x8333
jmp 0x8322
jmp 0x8322
movq %rax, %rbx
movq -0x80(%rbp), %rdi
testq %rdi, %rdi
je 0x8333
callq 0x31a0
movq -0x50(%rbp), %rdi
testq %rdi, %rdi
je 0x8341
callq 0x31a0
movq %rbx, %rdi
callq 0x32d0