// File: 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
subq $0x206e0, %rsp          # imm = 0x206E0
movq %rdi, -0x8(%rbp)
leaq -0x20618(%rbp), %rdi
callq 0xbc90
leaq -0x20620(%rbp), %rdi
callq 0xbc90
leaq -0x10(%rbp), %rdi
callq 0xb520
leaq -0x20610(%rbp), %rdi
movl $0x40, %esi
callq 0xb540
leaq -0x20610(%rbp), %rdi
leaq -0x10(%rbp), %rsi
callq 0xb5f0
callq 0x3160
imulq $0x3e8, %rax, %rax      # imm = 0x3E8
movl $0xf4240, %ecx          # imm = 0xF4240
cqto
idivq %rcx
movq %rax, %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x78(%rax)
movq -0x8(%rbp), %rax
cmpq $0x0, 0x90(%rax)
je 0xb725
movq -0x8(%rbp), %rax
movq 0x90(%rax), %rax
movl $0x2, %ecx
cqto
idivq %rcx
movq %rax, %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x80(%rax)
jmp 0xb79c
movq -0x8(%rbp), %rax
cmpl $0x0, 0x6c(%rax)
je 0xb76e
movq -0x8(%rbp), %rax
movq 0x70(%rax), %rax
movq -0x8(%rbp), %rcx
movl 0x6c(%rcx), %ecx
subl $0x1, %ecx
movl %ecx, %ecx
imulq %rcx, %rax
movq -0x8(%rbp), %rcx
addq 0x88(%rcx), %rax
movq -0x8(%rbp), %rcx
movl 0x6c(%rcx), %ecx
cqto
idivq %rcx
movq %rax, %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x80(%rax)
jmp 0xb79a
movq -0x8(%rbp), %rax
imulq $0x27, 0x70(%rax), %rax
movq -0x8(%rbp), %rcx
addq 0x88(%rcx), %rax
movl $0x28, %ecx
cqto
idivq %rcx
movq %rax, %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x80(%rax)
jmp 0xb79c
movq -0x8(%rbp), %rax
movq 0x78(%rax), %rcx
movq -0x8(%rbp), %rax
addq 0x80(%rax), %rcx
movq %rcx, 0x80(%rax)
movl $0xffff8ad0, -0x20630(%rbp) # imm = 0xFFFF8AD0
leaq -0x20648(%rbp), %rdi
callq 0xbcc0
movl $0x1, -0x2064c(%rbp)
movl -0x2064c(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl 0x68(%rcx), %eax
jae 0xbb6b
leaq -0x20668(%rbp), %rdi
movq %rdi, -0x206c0(%rbp)
callq 0xbcc0
movq -0x206c0(%rbp), %rdi
movl $0x7530, -0x2066c(%rbp) # imm = 0x7530
movl $0xffff8ad0, -0x20670(%rbp) # imm = 0xFFFF8AD0
movq -0x8(%rbp), %rsi
movl -0x2064c(%rbp), %edx
movl -0x20670(%rbp), %ecx
movl -0x2066c(%rbp), %r8d
movq %rsp, %rax
movq %rdi, (%rax)
leaq -0x20610(%rbp), %r9
movq %rsi, %rdi
callq 0xbce0
movl %eax, -0x206b8(%rbp)
jmp 0xb84b
movl -0x206b8(%rbp), %eax
movl %eax, -0x20674(%rbp)
callq 0x3160
imulq $0x3e8, %rax, %rax      # imm = 0x3E8
movl $0xf4240, %ecx          # imm = 0xF4240
cqto
idivq %rcx
movq -0x8(%rbp), %rcx
subq 0x78(%rcx), %rax
movq %rax, -0x20690(%rbp)
cmpl $0x1, -0x2064c(%rbp)
jbe 0xb8d6
movq -0x20690(%rbp), %rax
movq -0x8(%rbp), %rcx
movq 0x80(%rcx), %rcx
movq -0x8(%rbp), %rdx
subq 0x78(%rdx), %rcx
cmpq %rcx, %rax
jl 0xb8d6
movl $0x2, -0x20694(%rbp)
jmp 0xbb3b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20680(%rbp)
movl %eax, -0x20684(%rbp)
leaq -0x20668(%rbp), %rdi
callq 0xc610
jmp 0xbc2c
leaq -0x20648(%rbp), %rdi
leaq -0x20668(%rbp), %rsi
callq 0xc3a0
jmp 0xb8eb
movq -0x8(%rbp), %rdi
leaq -0x20648(%rbp), %rsi
callq 0x60d0
movb %al, -0x206c1(%rbp)
jmp 0xb903
movb -0x206c1(%rbp), %al
testb $0x1, %al
jne 0xb90f
jmp 0xb911
jmp 0xb930
leaq 0x8855(%rip), %rdi      # 0x1416d
leaq 0x8745(%rip), %rsi      # 0x14064
movl $0x180, %edx            # imm = 0x180
leaq 0x8858(%rip), %rcx      # 0x14183
callq 0x3150
leaq -0x20648(%rbp), %rdi
callq 0xc5f0
cmpq $0x0, %rax
jbe 0xb944
jmp 0xb963
leaq 0x885e(%rip), %rdi      # 0x141a9
leaq 0x8712(%rip), %rsi      # 0x14064
movl $0x181, %edx            # imm = 0x181
leaq 0x8825(%rip), %rcx      # 0x14183
callq 0x3150
movl -0x20674(%rbp), %eax
movl %eax, -0x20630(%rbp)
movb $0x0, -0x20695(%rbp)
cmpl $0x74f0, -0x20630(%rbp) # imm = 0x74F0
jle 0xb99a
movb $0x1, -0x20695(%rbp)
movl $0x7530, %eax           # imm = 0x7530
subl -0x20630(%rbp), %eax
movl %eax, -0x20630(%rbp)
cmpl $0xffff8b10, -0x20630(%rbp) # imm = 0xFFFF8B10
jge 0xb9be
movb $0x1, -0x20695(%rbp)
movl -0x20630(%rbp), %eax
addl $0xffff8ad0, %eax       # imm = 0xFFFF8AD0
movl %eax, -0x20630(%rbp)
testb $0x1, -0x20695(%rbp)
je 0xb9f0
movl -0x20630(%rbp), %esi
movl -0x2064c(%rbp), %edx
movq -0x10(%rbp), %rcx
movq -0x20690(%rbp), %r8
leaq 0x87d2(%rip), %rdi      # 0x141b7
xorl %eax, %eax
callq 0x3030
jmp 0xb9ee
jmp 0xba19
movl -0x20630(%rbp), %esi
movl -0x2064c(%rbp), %edx
movq -0x10(%rbp), %rcx
movq -0x20690(%rbp), %r8
leaq 0x87dc(%rip), %rdi      # 0x141ea
xorl %eax, %eax
callq 0x3030
jmp 0xba17
jmp 0xba19
movq -0x8(%rbp), %rax
movb 0x41(%rax), %al
andb $0x1, %al
movb %al, -0x20696(%rbp)
leaq -0x20648(%rbp), %rax
movq %rax, -0x206a0(%rbp)
movq -0x206a0(%rbp), %rdi
callq 0x6a80
movq %rax, -0x206a8(%rbp)
movq -0x206a0(%rbp), %rdi
callq 0x6ab0
movq %rax, -0x206b0(%rbp)
leaq -0x206a8(%rbp), %rdi
leaq -0x206b0(%rbp), %rsi
callq 0x6ae0
testb $0x1, %al
jne 0xba78
jmp 0xbb0c
leaq -0x206a8(%rbp), %rdi
callq 0x6b20
movl (%rax), %eax
movl %eax, -0x206b4(%rbp)
testb $0x1, -0x20696(%rbp)
je 0xbab4
movl -0x206b4(%rbp), %edi
callq 0x69d0
movl %eax, -0x206c8(%rbp)
jmp 0xbaa8
movl -0x206c8(%rbp), %eax
movl %eax, -0x206b4(%rbp)
movl -0x206b4(%rbp), %esi
leaq -0x20626(%rbp), %rdi
callq 0x5ca0
jmp 0xbac8
leaq 0x874c(%rip), %rdi      # 0x1421b
xorl %eax, %eax
leaq -0x20626(%rbp), %rsi
callq 0x3030
jmp 0xbadf
movb -0x20696(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
xorl $0x1, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, -0x20696(%rbp)
leaq -0x206a8(%rbp), %rdi
callq 0x6b40
jmp 0xba5c
leaq 0x7eae(%rip), %rdi      # 0x139c1
xorl %eax, %eax
callq 0x3030
jmp 0xbb1c
testb $0x1, -0x20695(%rbp)
je 0xbb31
movl $0x2, -0x20694(%rbp)
jmp 0xbb3b
movl $0x0, -0x20694(%rbp)
leaq -0x20668(%rbp), %rdi
callq 0xc610
movl -0x20694(%rbp), %eax
testl %eax, %eax
je 0xbb55
jmp 0xbb53
jmp 0xbb6b
jmp 0xbb57
movl -0x2064c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2064c(%rbp)
jmp 0xb7d6
leaq -0x20648(%rbp), %rdi
callq 0xc5f0
cmpq $0x1, %rax
jb 0xbc05
leaq -0x20648(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xc670
movl (%rax), %eax
movl %eax, -0x2062c(%rbp)
movq -0x8(%rbp), %rax
testb $0x1, 0x41(%rax)
je 0xbbd8
movl -0x2062c(%rbp), %edi
callq 0x69d0
movl %eax, -0x206cc(%rbp)
jmp 0xbbb6
movl -0x206cc(%rbp), %eax
movl %eax, -0x2062c(%rbp)
jmp 0xbbd8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20680(%rbp)
movl %eax, -0x20684(%rbp)
jmp 0xbc2c
movl -0x2062c(%rbp), %esi
leaq -0x20626(%rbp), %rdi
callq 0x5ca0
jmp 0xbbec
leaq 0x862c(%rip), %rdi      # 0x1421f
xorl %eax, %eax
leaq -0x20626(%rbp), %rsi
callq 0x3030
jmp 0xbc03
jmp 0xbc17
leaq 0x8620(%rip), %rdi      # 0x1422c
xorl %eax, %eax
callq 0x3030
jmp 0xbc15
jmp 0xbc17
leaq -0x20648(%rbp), %rdi
callq 0xc610
addq $0x206e0, %rsp          # imm = 0x206E0
popq %rbp
retq
leaq -0x20648(%rbp), %rdi
callq 0xc610
movq -0x20680(%rbp), %rdi
callq 0x3350
nopw %cs:(%rax,%rax)
nop