// File: /workspace/github_cpp_makefile_star2_O3/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 %ebp, %ebp
movl %edx, 0xc(%rsp)
testl %edx, %edx
sete %bpl
movq %rcx, %r15
cmoveq %rax, %r15
leaq 0x8c91(%rip), %rdx      # 0xc4e0
movq 0xa00(%rdx,%r15,8), %r13
cmovel %ecx, %eax
movq 0xa00(%rdx,%rax,8), %rax
movq %rax, 0x10(%rsp)
movl %r15d, %esi
callq 0x57e6
movq %rax, %r12
movq 0x160(%rbx,%rbp,8), %rax
movq 0x150(%rbx), %rcx
orq 0x120(%rbx), %rcx
orq 0x110(%rbx), %rcx
orq 0x140(%rbx), %rcx
orq 0x118(%rbx), %rcx
andq %rax, %r12
orq 0x148(%rbx), %rcx
xorl %edx, %edx
andq %r12, %rcx
je 0x38db
leaq 0x11c2b(%rip), %rsi     # 0x154e0
leaq 0x8524(%rip), %rdi      # 0xbde0
bsfq %rcx, %r8
movq (%rdi,%r8,8), %r9
shll $0x9, %r8d
addq %rsi, %r8
xorq (%r8,%r15,8), %r9
orq %r9, %rdx
leaq -0x1(%rcx), %r8
andq %r8, %rcx
jne 0x38bc
orq 0x10(%rsp), %rdx
notq %rdx
andq %rdx, %r13
movq 0x170(%rbx), %rcx
notq %rcx
andq %r13, %rcx
andq %rax, %r13
je 0x390f
bsfq %r13, %rax
shll $0x6, %eax
orl %r15d, %eax
movl %eax, (%r14)
addq $0x8, %r14
leaq -0x1(%r13), %rax
jmp 0x38f3
testq %rcx, %rcx
je 0x392e
bsfq %rcx, %rax
shll $0x6, %eax
orl %r15d, %eax
movl %eax, (%r14)
addq $0x8, %r14
leaq -0x1(%rcx), %rax
andq %rax, %rcx
jne 0x3914
movq %r12, %rdi
callq 0x28c9
cmpl $0x1, %eax
jle 0x394d
movq %r14, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
bsfq %r12, %r13
shll $0x9, %r15d
addq 0x7634(%rip), %r15      # 0xaf90
shll $0x3, %r13d
leaq 0x130(%rbx), %rbp
leaq 0x100(%rbx), %rax
movl 0xc(%rsp), %ecx
testl %ecx, %ecx
movl %ecx, %edx
movq (%r13,%r15), %r15
cmoveq %rax, %rbp
movq (%rbp), %rsi
movl $0x108, %eax            # imm = 0x108
movl $0x138, %r12d           # imm = 0x138
cmoveq %rax, %r12
movq %rbx, %rdi
movq %r15, %rcx
movq %r14, %r8
callq 0x3fcc
movq %r12, 0x10(%rsp)
movq (%rbx,%r12), %rdi
movq %r15, %rsi
movq %rax, %rdx
callq 0x4108
movq %rbx, %rdi
movq %r15, %rsi
movq %rax, %rdx
callq 0x3e7a
leaq 0x8417(%rip), %rcx      # 0xbde0
movq (%rcx,%r13), %r14
movq (%rbp), %rdi
movl 0xc(%rsp), %esi
movq %r14, %rdx
movq %rax, %rcx
callq 0x414d
movq 0x188(%rbx), %rcx
cmpl $0x40, 0x4(%rcx)
je 0x39f8
movq %rbx, %rdi
movq %rax, %rsi
callq 0x3d34
movq 0x10(%rsp), %rcx
movq (%rbx,%rcx), %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x4108
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 0x3e7a