// File: /workspace/github_cpp_makefile_star2_O1/SethKasmann[P]clever-girl/src/search.cpp
// Function: qsearch(State&, SearchInfo&, int, int, int)
int qsearch(State& s, SearchInfo& si, int ply, int alpha, int beta)
{
    si.nodes++;
    assert(ply < Max_ply);

    if (history.isThreefoldRepetition(s) ||
        s.insufficientMaterial() ||
        s.getFiftyMoveRule() > 99)
        return Draw;

    Evaluate evaluate(s);

    int qscore = evaluate.getScore();

    // If a beta cutoff is found, return the qscore.
    if (qscore >= beta)
        return beta;

    // Update alpha.
    alpha = std::max(alpha, qscore);

    // Generate moves and create the movelist.
    MoveList mlist(s, nullMove, &history, ply, true);

    int bestScore = Neg_inf;
    int score;
    Move m;

    while (m = mlist.getBestMove())
    {
// -------------------------------------------------------------------------- //
//                                                                            //
// Futility pruning. Do not search subtrees that are unlikely to improve      //
// alpha. To avoid pruning away tactical positions, there are a few things    //
// we need to check:                                                          //
//   1. Side to move is not in check.                                         //
//   2. Move itself doesn't give check.                                       //
//   3. Move is not en passant. I want to be sure to calculate the fScore     //
//      properly, but en passant could throw a wrench by adding a 0 piece     //
//      value. Insead of a separate check to cover en passant moves, I am     //
//      currently just not cosidering them.                                   //
//                                                                            //
// -------------------------------------------------------------------------- //
        if (!s.inCheck() &&
            !s.givesCheck(m) &&
            !s.isEnPassant(m) &&
            !isPromotion(m))
        {
            // TODO:
            // Can I simply include en passant in this calculation?
            // Add a "gives check" function, so I dont have to make the move.
            int fScore = qscore + 100 + PieceValue[s.onSquare(getDst(m))];
            if (fScore <= alpha)
            {
                bestScore = std::max(bestScore, fScore);
                continue;
            }
        }

        State c(s);
        c.make_t(m);

        history.push(std::make_pair(m, c.getKey()));
        score = -qsearch(c, si, ply + 1, -beta, -alpha);
        history.pop();
        if (score >= bestScore)
            bestScore = score;

        alpha = std::max(alpha, bestScore);

        if (alpha >= beta)
            return beta;
    }

    if (bestScore == Neg_inf && s.check())
        return -Checkmate + ply;

    return alpha;                                // Fail-Hard alpha beta score.
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe48, %rsp            # imm = 0xE48
movl %r8d, %ebp
movl %ecx, %ebx
movl %edx, %r12d
movq %rsi, %r13
movq %rdi, %r15
incl 0x1c(%rsi)
movq 0x14542e(%rip), %rax    # 0x15a6a8
movq 0x14541f(%rip), %rcx    # 0x15a6a0
movq %rax, %rdx
subq %rcx, %rdx
cmpq $0x41, %rdx
jb 0x152b3
shlq $0x1c, %rdx
movabsq $-0x500000000, %rsi     # imm = 0xFFFFFFFB00000000
addq %rdx, %rsi
sarq $0x1c, %rsi
movq 0x8(%rcx,%rsi), %rcx
xorl %edx, %edx
cmpq -0x8(%rax), %rcx
je 0x154f5
movq %r15, %rdi
callq 0x187ee
xorl %edx, %edx
testb %al, %al
jne 0x154f5
cmpl $0x63, 0x8(%r15)
jg 0x154f5
leaq 0x38(%rsp), %r14
movq %r14, %rdi
movq %r15, %rsi
callq 0xe024
movq %r14, %rdi
callq 0xef24
cmpl %ebp, %eax
jge 0x154ab
movl %eax, %r14d
movq %r13, 0x20(%rsp)
cmpl %ebx, %eax
cmovgl %eax, %ebx
leaq 0x14539c(%rip), %rcx    # 0x15a6a0
leaq 0x5f0(%rsp), %rdi
movq %r15, %rsi
xorl %edx, %edx
movl %r12d, %r8d
movl $0x1, %r9d
callq 0xfd66
addl $0x64, %r14d
movq %r12, 0x18(%rsp)
leal 0x1(%r12), %eax
movl %eax, 0x14(%rsp)
movl %ebp, %eax
negl %eax
movl %eax, 0x10(%rsp)
movl $0xffff3cb0, %eax       # imm = 0xFFFF3CB0
movl %ebp, 0xc(%rsp)
movl %eax, %r13d
leaq 0x5f0(%rsp), %rdi
callq 0x10030
movl %eax, %ebp
testw %ax, %ax
je 0x154af
cmpq $0x0, 0x28(%r15)
movzwl %bp, %r12d
jne 0x153e4
movq %r15, %rdi
movl %r12d, %esi
callq 0x17442
testb %al, %al
jne 0x153e4
movl %ebp, %eax
andl $0x3f, %eax
cmpl $0x0, 0x188(%r15,%rax,4)
je 0x15391
testl $0x7000, %ebp           # imm = 0x7000
je 0x153b2
jmp 0x153e4
testl $0x7000, %ebp           # imm = 0x7000
jne 0x153e4
movl %ebp, %eax
shrl $0x6, %eax
andl $0x3f, %eax
movq 0x30(%r15), %rcx
leaq 0xe36c4(%rip), %rdx     # 0xf8a70
andq (%rdx,%rax,8), %rcx
jne 0x153e4
movl %ebp, %eax
shrl $0x6, %eax
andl $0x3f, %eax
movl 0x188(%r15,%rax,4), %eax
leaq 0x8fd7(%rip), %rcx      # 0x1e3a0
movl (%rcx,%rax,4), %eax
addl %r14d, %eax
cmpl %eax, %r13d
movl %eax, %ecx
cmovgl %r13d, %ecx
cmpl %ebx, %eax
cmovlel %ecx, %r13d
jle 0x15345
leaq 0xe8(%rsp), %rdi
movq %r15, %rsi
callq 0x16460
leaq 0xe8(%rsp), %rdi
movl %r12d, %esi
callq 0x17b1c
movq 0x100(%rsp), %rax
movw %bp, 0x28(%rsp)
movq %rax, 0x30(%rsp)
movq 0x14528b(%rip), %rsi    # 0x15a6a8
cmpq 0x14528c(%rip), %rsi    # 0x15a6b0
je 0x15438
movups 0x28(%rsp), %xmm0
movups %xmm0, (%rsi)
addq $0x10, 0x145272(%rip)   # 0x15a6a8
jmp 0x15449
leaq 0x145261(%rip), %rdi    # 0x15a6a0
leaq 0x28(%rsp), %rdx
callq 0x14b86
movl %ebx, %r8d
negl %r8d
leaq 0xe8(%rsp), %rdi
movq 0x20(%rsp), %rsi
movl 0x14(%rsp), %edx
movl 0x10(%rsp), %ecx
callq 0x15251
movq 0x145238(%rip), %rcx    # 0x15a6a8
cmpq %rcx, 0x145229(%rip)    # 0x15a6a0
je 0x15484
addq $-0x10, %rcx
movq %rcx, 0x145224(%rip)    # 0x15a6a8
negl %eax
cmpl %eax, %r13d
cmovgl %r13d, %eax
cmpl %eax, %ebx
cmovlel %eax, %ebx
movl 0xc(%rsp), %ebp
cmpl %ebp, %ebx
movl 0x8(%rsp), %ecx
cmovgel %ebp, %ecx
movl %ecx, 0x8(%rsp)
jl 0x15342
jmp 0x154d4
movl %ebp, %edx
jmp 0x154f5
cmpl $0xffff3cb0, %r13d      # imm = 0xFFFF3CB0
jne 0x154d0
movq %r15, %rdi
callq 0x16384
movq 0x18(%rsp), %rcx
addl $0xffff8001, %ecx       # imm = 0xFFFF8001
testb %al, %al
cmovnel %ecx, %ebx
movl %ebx, 0x8(%rsp)
movq 0xe20(%rsp), %rdi
testq %rdi, %rdi
je 0x154f1
movq 0xe30(%rsp), %rsi
subq %rdi, %rsi
callq 0x4250
movl 0x8(%rsp), %edx
movl %edx, %eax
addq $0xe48, %rsp            # imm = 0xE48
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x1550f
jmp 0x1550f
jmp 0x1550f
movq %rax, %rbx
movq 0xe20(%rsp), %rdi
testq %rdi, %rdi
je 0x1552f
movq 0xe30(%rsp), %rsi
subq %rdi, %rsi
callq 0x4250
movq %rbx, %rdi
callq 0x43b0