// File: /workspace/github_cpp_makefile_star2_O2/bjohnsonfl[P]Overhead-Chess-Engine-/moveGen.cpp
// Function: generateEvasion(position const&, candidate*)
candidate* generateEvasion (const position& pos, candidate* moveList)
{
    /*If in check, the king has 2-3 options.
     1) Move out of Check
     2) Block Check
     3) Capture Check
     Option 1 is required when more than one piece is checking the king
     
     step 1) determine which pieces are attacking the king.
     step 2) generate attack squares from this piece and AND them with king moveable squares
        step 2.1) Make sure the enemy king squares are not included
        step 2.2) Determine if these squares are attacked, if not, create move
     step 3) calculate how many attackers there are from step 1. if more than 1, Break, else step 4
     step 4) Determine which squares are between the king and the attacker, see if our pieces attack them, are not pinned, and thus can move there to BLOCK the check
        step 4.1) promotions count
     step 5) Determine if our pieces can capture the attacking piece, and are not pinned
        step 5.1) EnPassant counts as well as promotions
    
     */
    candidate *start = moveList;
  //  pos.printBoard();
    square sq = empty, to = empty, from = empty;
    move mov = none;
    player us = pos.get_sideToPlay();
    player them = player(!us);
    
    square kingSq = pos.get_king_sq(us);
    square enemyKingSq = pos.get_king_sq(them);
    
    bitboard kingSquares = openBoardAttacks[p_king][kingSq];
    bitboard enemyKingSquares = openBoardAttacks[p_king][enemyKingSq];
    
    //To Keep kings apart. This bitboard is all possible squares a king can move to now
    kingSquares = kingSquares ^( kingSquares & enemyKingSquares );
    //printBitboard(kingSquares);
    //Step 1/2)
    bitboard checker = pos.squareAttackedBy(kingSq) & pos.get_pieces(them);
    bitboard sliders =( pos.get_pieces(p_queen, p_bishop) | pos.get_pieces(p_rook)) & checker;
    bitboard checkedSquares = 0;
   // printBitboard(checker);
    //printBitboard(sliders);
    while(sliders)
    {
        sq = lsb_sq(sliders);
       // printBitboard(lineSqBitMask[sq][kingSq]);
        checkedSquares |= lineSqBitMask[sq][kingSq] ^ squareBitMask[sq];
        pop_lsb(&sliders);
        
    }
   // printBitboard(checkedSquares);
    kingSquares &= ~checkedSquares;
    //printBitboard(kingSquares);
    bitboard kingCaptures = 0, kingQuiets = 0;
    kingCaptures = kingSquares & pos.get_pieces(them);
   // printBitboard(kingCaptures);
    kingQuiets  = kingSquares & ~(pos.get_pieces());
   // printBitboard(kingQuiets);
    while(kingCaptures)
    {
        to = lsb_sq(kingCaptures);
        mov = make_move(kingSq, to);
        (*moveList++).mv = mov;
        
        pop_lsb(&kingCaptures);
    }
    
    while(kingQuiets)
    {
        to = lsb_sq(kingQuiets);
        mov = make_move(kingSq, to);
        (*moveList++).mv = mov;
        
        pop_lsb(&kingQuiets);
    }
    
    //Step 3)
    //these moves will be checked for legality later
    if( popcount(checker) > 1) return moveList;
    
    //Step 4)
    //Pawn (and promotion), knight, bishop, rook, queen
    square checkerSq = lsb_sq(checker);
    bitboard blockerSq = inBetweenSqBitMask[kingSq][checkerSq];
    //printBitboard(blockerSq);
    moveList = pawnPushMoves(pos, pos.get_pieces(us, p_pawn), us, blockerSq, moveList);
    moveList = knightMoves(pos.get_pieces(us, p_knight), blockerSq, moveList);
    moveList = sliderMoves(pos, blockerSq, moveList);
    
    //Step 5)
    bitboard capture = squareBitMask[checkerSq];
    moveList = pawnAttackMoves(pos.get_pieces(us, p_pawn), us, capture, moveList);
    if(pos.get_enPassent() != empty)
    {
        moveList = generateEnPassent(pos, moveList);
    }
    moveList = knightMoves(pos.get_pieces(us, p_knight), capture, moveList);
    moveList = sliderMoves(pos, capture, moveList);
    
  //  printMoves(start, moveList);
    
    return moveList;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %r14
movq %rdi, %rbx
bsfq 0x128(%rdi), %rax
bsfq 0x158(%rdi), %rcx
movl 0x17c(%rdi), %edx
xorl %r13d, %r13d
movl %edx, 0x4(%rsp)
testl %edx, %edx
sete %r13b
movq %rcx, %r15
cmoveq %rax, %r15
leaq 0x8e6d(%rip), %rdx      # 0xc4e0
movq 0xa00(%rdx,%r15,8), %rbp
cmovel %ecx, %eax
movq 0xa00(%rdx,%rax,8), %rax
movq %rax, 0x8(%rsp)
movl %r15d, %esi
callq 0x525a
movq %rax, %r12
movq 0x160(%rbx,%r13,8), %rax
andq %rax, %r12
movq 0x150(%rbx), %rcx
orq 0x120(%rbx), %rcx
orq 0x110(%rbx), %rcx
orq 0x140(%rbx), %rcx
orq 0x118(%rbx), %rcx
orq 0x148(%rbx), %rcx
andq %r12, %rcx
xorl %edx, %edx
leaq 0x11e09(%rip), %rsi     # 0x154e0
leaq 0x8702(%rip), %r13      # 0xbde0
testq %rcx, %rcx
je 0x3702
bsfq %rcx, %rdi
movq (%r13,%rdi,8), %r8
shll $0x9, %edi
addq %rsi, %rdi
xorq (%rdi,%r15,8), %r8
orq %r8, %rdx
leaq -0x1(%rcx), %rdi
andq %rdi, %rcx
jmp 0x36de
orq 0x8(%rsp), %rdx
notq %rdx
andq %rdx, %rbp
andq %rbp, %rax
movq 0x170(%rbx), %rcx
notq %rcx
testq %rax, %rax
je 0x3739
bsfq %rax, %rdx
shll $0x6, %edx
orl %r15d, %edx
movl %edx, (%r14)
addq $0x8, %r14
leaq -0x1(%rax), %rdx
andq %rdx, %rax
jmp 0x371a
andq %rcx, %rbp
testq %rbp, %rbp
je 0x375b
bsfq %rbp, %rax
shll $0x6, %eax
orl %r15d, %eax
movl %eax, (%r14)
addq $0x8, %r14
leaq -0x1(%rbp), %rax
andq %rax, %rbp
jmp 0x373c
movq %r12, %rdi
callq 0x2801
cmpl $0x1, %eax
jle 0x377a
movq %r14, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
bsfq %r12, %rcx
shll $0x9, %r15d
addq 0x7807(%rip), %r15      # 0xaf90
shll $0x3, %ecx
movq %rcx, 0x10(%rsp)
leaq 0x130(%rbx), %r12
leaq 0x100(%rbx), %rax
movl 0x4(%rsp), %edx
testl %edx, %edx
movq (%rcx,%r15), %r15
cmoveq %rax, %r12
movq (%r12), %rsi
movl $0x108, %eax            # imm = 0x108
movl $0x138, %ebp            # imm = 0x138
cmoveq %rax, %rbp
movq %rbx, %rdi
movq %r15, %rcx
movq %r14, %r8
callq 0x3dde
movq %rbp, 0x8(%rsp)
movq (%rbx,%rbp), %rdi
movq %r15, %rsi
movq %rax, %rdx
callq 0x3f1b
movq %rbx, %rdi
movq %r15, %rsi
movq %rax, %rdx
callq 0x3c8d
movq 0x10(%rsp), %rcx
movq (%r13,%rcx), %r14
movq (%r12), %rdi
movl 0x4(%rsp), %esi
movq %r14, %rdx
movq %rax, %rcx
callq 0x3f63
movq 0x188(%rbx), %rcx
cmpl $0x40, 0x4(%rcx)
je 0x3824
movq %rbx, %rdi
movq %rax, %rsi
callq 0x3b47
movq 0x8(%rsp), %rcx
movq (%rbx,%rcx), %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x3f1b
movq %rbx, %rdi
movq %r14, %rsi
movq %rax, %rdx
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3c8d