// File: SethKasmann[P]clever-girl/src/state.cpp
// Function: State::see(unsigned short) const
int State::see(Move m) const
{
    Prop prop;
    Color color;
    Square src, dst, mayAttack;
    PieceType target;
    U64 attackers, from, occupancy, xRay, potential;
    int gain[32] = { 0 };
    int d = 0;

    color = mUs;
    src = getSrc(m);
    dst = getDst(m);
    from = square_bb[src];
    // Check if the move is en passant.
    if (onSquare(src) == pawn && square_bb[dst] & mEnPassant)
        gain[d] = PieceValue[pawn];
    else if (getPiecePromo(m) == queen)
        gain[d] = Queen_wt - Pawn_wt;
    else
        gain[d] = PieceValue[onSquare(dst)];
    occupancy = getOccupancyBB();
    attackers = allAttackers(dst);
    // Get X ray attacks and add in pawns from attackers.
    xRay = getXRayAttacks(dst);

    while (from)
    {
        // Update the target piece and the square it came from.
        src = get_lsb(from);
        target = onSquare(src);

        // Update the depth and color.
        d++;

        // Storing the potential gain, if defended.
        gain[d] = PieceValue[target] - gain[d - 1];

        // Prune if the gain cannot be improved.
        if (std::max(-gain[d - 1], gain[d]) < 0)
            break;

        // Remove the from bit to simulate making the move.
        attackers ^= from;
        occupancy ^= from;

        // If the target is not a night, piece movement could cause a discovered
        // attacker.
        if (target != knight)
        {
            xRay &= occupancy;
            // Create a bitboard of potential discovered attackers.
            potential = coplanar[src][dst] & xRay;
            while (potential)
            {
                mayAttack = pop_lsb(potential);
                // If no bits are between the new square and the dst, there
                // is a new attacker.
                if (!(between[mayAttack][dst] & occupancy))
                {
                    attackers |= square_bb[mayAttack];
                    break;
                }
            }
        }

        // Get the next piece for the opposing player.
        color = !color;
        if (!(attackers & getOccupancyBB(color)))
            break;

        if (attackers & getPieceBB<pawn>(color))
            from = get_lsb_bb(attackers & getPieceBB<pawn>(color));
        else if (attackers & getPieceBB<knight>(color))
            from = get_lsb_bb(attackers & getPieceBB<knight>(color));
        else if (attackers & getPieceBB<bishop>(color))
            from = get_lsb_bb(attackers & getPieceBB<bishop>(color));
        else if (attackers & getPieceBB<rook>(color))
            from = get_lsb_bb(attackers & getPieceBB<rook>(color));
        else if (attackers & getPieceBB<queen>(color))
            from = get_lsb_bb(attackers & getPieceBB<queen>(color));
        else
        {
            from = get_lsb_bb(attackers & getPieceBB<king>(color));
            // Break if the king would be attacked.
            if (attackers & getOccupancyBB(!color))
                break;
        }
    }

    // Negamax the gain array to determine the final SEE value.
    while (--d > 0)
        gain[d - 1] = -std::max(-gain[d - 1], gain[d]);

    return gain[0];
}

// Assembly:
subq $0x158, %rsp            # imm = 0x158
movw %si, %ax
movq %rdi, 0x150(%rsp)
movw %ax, 0x14e(%rsp)
movq 0x150(%rsp), %rax
movq %rax, 0x68(%rsp)
leaq 0x80(%rsp), %rdi
xorl %esi, %esi
movl $0x80, %edx
callq 0x5150
movq 0x68(%rsp), %rax
movl $0x0, 0x7c(%rsp)
movl (%rax), %eax
movl %eax, 0x144(%rsp)
movzwl 0x14e(%rsp), %edi
callq 0x26810
movl %eax, 0x140(%rsp)
movzwl 0x14e(%rsp), %edi
callq 0x26830
movq 0x68(%rsp), %rdi
movl %eax, 0x13c(%rsp)
movl 0x140(%rsp), %eax
movl %eax, %ecx
leaq 0x11cda2(%rip), %rax    # 0x154b10
movq (%rax,%rcx,8), %rax
movq %rax, 0x120(%rsp)
movl 0x140(%rsp), %esi
callq 0x29bd0
cmpl $0x0, %eax
jne 0x37dc2
movq 0x68(%rsp), %rcx
movl 0x13c(%rsp), %eax
movl %eax, %edx
leaq 0x11cd70(%rip), %rax    # 0x154b10
movq (%rax,%rdx,8), %rax
andq 0x30(%rcx), %rax
cmpq $0x0, %rax
je 0x37dc2
movl 0xb6ac(%rip), %ecx      # 0x43460
movslq 0x7c(%rsp), %rax
movl %ecx, 0x80(%rsp,%rax,4)
jmp 0x37e13
movzwl 0x14e(%rsp), %edi
callq 0x268e0
cmpl $0x4, %eax
jne 0x37de6
movslq 0x7c(%rsp), %rax
movl $0x352, 0x80(%rsp,%rax,4) # imm = 0x352
jmp 0x37e11
movq 0x68(%rsp), %rdi
movl 0x13c(%rsp), %esi
callq 0x29bd0
movl %eax, %eax
movl %eax, %ecx
leaq 0xb65e(%rip), %rax      # 0x43460
movl (%rax,%rcx,4), %ecx
movslq 0x7c(%rsp), %rax
movl %ecx, 0x80(%rsp,%rax,4)
jmp 0x37e13
movq 0x68(%rsp), %rdi
callq 0x24bc0
movq 0x68(%rsp), %rdi
movq %rax, 0x118(%rsp)
movl 0x13c(%rsp), %esi
callq 0x3a990
movq 0x68(%rsp), %rdi
movq %rax, 0x128(%rsp)
movl 0x13c(%rsp), %esi
callq 0x3ab30
movq %rax, 0x110(%rsp)
cmpq $0x0, 0x120(%rsp)
je 0x382cb
movq 0x120(%rsp), %rdi
callq 0x25a20
movq 0x68(%rsp), %rdi
movl %eax, 0x140(%rsp)
movl 0x140(%rsp), %esi
callq 0x29bd0
movl %eax, 0x134(%rsp)
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
movl 0x134(%rsp), %eax
movl %eax, %ecx
leaq 0xb5b3(%rip), %rax      # 0x43460
movl (%rax,%rcx,4), %ecx
movl 0x7c(%rsp), %eax
subl $0x1, %eax
cltq
subl 0x80(%rsp,%rax,4), %ecx
movslq 0x7c(%rsp), %rax
movl %ecx, 0x80(%rsp,%rax,4)
movl 0x7c(%rsp), %eax
subl $0x1, %eax
movslq %eax, %rcx
xorl %eax, %eax
subl 0x80(%rsp,%rcx,4), %eax
movl %eax, 0x78(%rsp)
movslq 0x7c(%rsp), %rax
leaq 0x80(%rsp), %rsi
shlq $0x2, %rax
addq %rax, %rsi
leaq 0x78(%rsp), %rdi
callq 0x35600
cmpl $0x0, (%rax)
jge 0x37f0b
jmp 0x382cb
movq 0x120(%rsp), %rax
xorq 0x128(%rsp), %rax
movq %rax, 0x128(%rsp)
movq 0x120(%rsp), %rax
xorq 0x118(%rsp), %rax
movq %rax, 0x118(%rsp)
cmpl $0x1, 0x134(%rsp)
je 0x3800c
movq 0x118(%rsp), %rax
andq 0x110(%rsp), %rax
movq %rax, 0x110(%rsp)
movl 0x140(%rsp), %eax
movl %eax, %ecx
leaq 0x135d9f(%rip), %rax    # 0x16dd10
shlq $0x9, %rcx
addq %rcx, %rax
movl 0x13c(%rsp), %ecx
movq (%rax,%rcx,8), %rax
andq 0x110(%rsp), %rax
movq %rax, 0x108(%rsp)
cmpq $0x0, 0x108(%rsp)
je 0x3800a
leaq 0x108(%rsp), %rdi
callq 0x25770
movl %eax, 0x138(%rsp)
movl 0x138(%rsp), %eax
movl %eax, %ecx
leaq 0x12dd4e(%rip), %rax    # 0x165d10
shlq $0x9, %rcx
addq %rcx, %rax
movl 0x13c(%rsp), %ecx
movq (%rax,%rcx,8), %rax
andq 0x118(%rsp), %rax
cmpq $0x0, %rax
jne 0x38008
movl 0x138(%rsp), %eax
movl %eax, %ecx
leaq 0x11cb1e(%rip), %rax    # 0x154b10
movq (%rax,%rcx,8), %rax
orq 0x128(%rsp), %rax
movq %rax, 0x128(%rsp)
jmp 0x3800a
jmp 0x37f93
jmp 0x3800c
movl 0x144(%rsp), %edi
callq 0x24ce0
movq 0x68(%rsp), %rdi
movl %eax, 0x144(%rsp)
movq 0x128(%rsp), %rax
movq %rax, 0x60(%rsp)
movl 0x144(%rsp), %esi
callq 0x25740
movq %rax, %rcx
movq 0x60(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
jne 0x38053
jmp 0x382cb
movq 0x68(%rsp), %rdi
movq 0x128(%rsp), %rax
movq %rax, 0x58(%rsp)
movl 0x144(%rsp), %esi
callq 0x24b80
movq %rax, %rcx
movq 0x58(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x380ba
movq 0x68(%rsp), %rdi
movq 0x128(%rsp), %rax
movq %rax, 0x50(%rsp)
movl 0x144(%rsp), %esi
callq 0x24b80
movq 0x50(%rsp), %rdi
andq %rax, %rdi
callq 0x3abe0
movq %rax, 0x120(%rsp)
jmp 0x382c6
movq 0x68(%rsp), %rdi
movq 0x128(%rsp), %rax
movq %rax, 0x48(%rsp)
movl 0x144(%rsp), %esi
callq 0x25bb0
movq %rax, %rcx
movq 0x48(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x38121
movq 0x68(%rsp), %rdi
movq 0x128(%rsp), %rax
movq %rax, 0x40(%rsp)
movl 0x144(%rsp), %esi
callq 0x25bb0
movq 0x40(%rsp), %rdi
andq %rax, %rdi
callq 0x3abe0
movq %rax, 0x120(%rsp)
jmp 0x382c4
movq 0x68(%rsp), %rdi
movq 0x128(%rsp), %rax
movq %rax, 0x38(%rsp)
movl 0x144(%rsp), %esi
callq 0x25bf0
movq %rax, %rcx
movq 0x38(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x38188
movq 0x68(%rsp), %rdi
movq 0x128(%rsp), %rax
movq %rax, 0x30(%rsp)
movl 0x144(%rsp), %esi
callq 0x25bf0
movq 0x30(%rsp), %rdi
andq %rax, %rdi
callq 0x3abe0
movq %rax, 0x120(%rsp)
jmp 0x382c2
movq 0x68(%rsp), %rdi
movq 0x128(%rsp), %rax
movq %rax, 0x28(%rsp)
movl 0x144(%rsp), %esi
callq 0x2b410
movq %rax, %rcx
movq 0x28(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x381ef
movq 0x68(%rsp), %rdi
movq 0x128(%rsp), %rax
movq %rax, 0x20(%rsp)
movl 0x144(%rsp), %esi
callq 0x2b410
movq 0x20(%rsp), %rdi
andq %rax, %rdi
callq 0x3abe0
movq %rax, 0x120(%rsp)
jmp 0x382c0
movq 0x68(%rsp), %rdi
movq 0x128(%rsp), %rax
movq %rax, 0x18(%rsp)
movl 0x144(%rsp), %esi
callq 0x2b3d0
movq %rax, %rcx
movq 0x18(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x38253
movq 0x68(%rsp), %rdi
movq 0x128(%rsp), %rax
movq %rax, 0x10(%rsp)
movl 0x144(%rsp), %esi
callq 0x2b3d0
movq 0x10(%rsp), %rdi
andq %rax, %rdi
callq 0x3abe0
movq %rax, 0x120(%rsp)
jmp 0x382be
movq 0x68(%rsp), %rdi
movq 0x128(%rsp), %rax
movq %rax, (%rsp)
movl 0x144(%rsp), %esi
callq 0x25510
movq (%rsp), %rdi
andq %rax, %rdi
callq 0x3abe0
movq %rax, 0x120(%rsp)
movq 0x128(%rsp), %rax
movq %rax, 0x8(%rsp)
movl 0x144(%rsp), %edi
callq 0x24ce0
movq 0x68(%rsp), %rdi
movl %eax, %esi
callq 0x25740
movq %rax, %rcx
movq 0x8(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x382bc
jmp 0x382cb
jmp 0x382be
jmp 0x382c0
jmp 0x382c2
jmp 0x382c4
jmp 0x382c6
jmp 0x37e57
jmp 0x382cd
movl 0x7c(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x7c(%rsp)
cmpl $0x0, %eax
jle 0x38328
movl 0x7c(%rsp), %eax
subl $0x1, %eax
movslq %eax, %rcx
xorl %eax, %eax
subl 0x80(%rsp,%rcx,4), %eax
movl %eax, 0x74(%rsp)
movslq 0x7c(%rsp), %rax
leaq 0x80(%rsp), %rsi
shlq $0x2, %rax
addq %rax, %rsi
leaq 0x74(%rsp), %rdi
callq 0x35600
xorl %ecx, %ecx
subl (%rax), %ecx
movl 0x7c(%rsp), %eax
subl $0x1, %eax
cltq
movl %ecx, 0x80(%rsp,%rax,4)
jmp 0x382cd
movl 0x80(%rsp), %eax
addq $0x158, %rsp            # imm = 0x158
retq
nopw (%rax,%rax)