// File: 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
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x20(%rbp)
movl $0x40, -0x24(%rbp)
movl $0x40, -0x28(%rbp)
movl $0x40, -0x2c(%rbp)
movl $0x0, -0x30(%rbp)
movq -0x10(%rbp), %rdi
callq 0x75c0
movl %eax, -0x34(%rbp)
cmpl $0x0, -0x34(%rbp)
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x38(%rbp)
movq -0x10(%rbp), %rdi
movl -0x34(%rbp), %esi
callq 0x7640
movl %eax, -0x3c(%rbp)
movq -0x10(%rbp), %rdi
movl -0x38(%rbp), %esi
callq 0x7640
movl %eax, -0x40(%rbp)
movl -0x3c(%rbp), %eax
movl %eax, %ecx
leaq 0xd802(%rip), %rax      # 0x135a0
movq 0xa00(%rax,%rcx,8), %rax
movq %rax, -0x48(%rbp)
movl -0x40(%rbp), %eax
movl %eax, %ecx
leaq 0xd7ea(%rip), %rax      # 0x135a0
movq 0xa00(%rax,%rcx,8), %rax
movq %rax, -0x50(%rbp)
movq -0x48(%rbp), %rax
movq -0x48(%rbp), %rcx
andq -0x50(%rbp), %rcx
xorq %rcx, %rax
movq %rax, -0x48(%rbp)
movq -0x10(%rbp), %rdi
movl -0x3c(%rbp), %esi
callq 0x98b0
movq %rax, -0xa0(%rbp)
movq -0x10(%rbp), %rdi
movl -0x38(%rbp), %esi
callq 0x7600
movq %rax, %rcx
movq -0xa0(%rbp), %rax
andq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x10(%rbp), %rdi
movl $0x4, %esi
movl $0x2, %edx
callq 0x7700
movq %rax, -0x98(%rbp)
movq -0x10(%rbp), %rdi
movl $0x3, %esi
callq 0x7750
movq %rax, %rcx
movq -0x98(%rbp), %rax
orq %rcx, %rax
andq -0x58(%rbp), %rax
movq %rax, -0x60(%rbp)
movq $0x0, -0x68(%rbp)
cmpq $0x0, -0x60(%rbp)
je 0x5e9a
movq -0x60(%rbp), %rdi
callq 0x7780
movl %eax, -0x24(%rbp)
movl -0x24(%rbp), %eax
movl %eax, %ecx
leaq 0x16737(%rip), %rax     # 0x1c5a0
shlq $0x9, %rcx
addq %rcx, %rax
movl -0x3c(%rbp), %ecx
movq (%rax,%rcx,8), %rax
movl -0x24(%rbp), %ecx
movl %ecx, %edx
leaq 0xd01d(%rip), %rcx      # 0x12ea0
xorq (%rcx,%rdx,8), %rax
orq -0x68(%rbp), %rax
movq %rax, -0x68(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x77a0
jmp 0x5e4a
movq -0x68(%rbp), %rax
xorq $-0x1, %rax
andq -0x48(%rbp), %rax
movq %rax, -0x48(%rbp)
movq $0x0, -0x70(%rbp)
movq $0x0, -0x78(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0x10(%rbp), %rdi
movl -0x38(%rbp), %esi
callq 0x7600
movq %rax, %rcx
movq -0xb0(%rbp), %rax
andq %rcx, %rax
movq %rax, -0x70(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0x10(%rbp), %rdi
callq 0x7690
movq %rax, %rcx
movq -0xa8(%rbp), %rax
xorq $-0x1, %rcx
andq %rcx, %rax
movq %rax, -0x78(%rbp)
cmpq $0x0, -0x70(%rbp)
je 0x5f4b
movq -0x70(%rbp), %rdi
callq 0x7780
movl %eax, -0x28(%rbp)
movl -0x3c(%rbp), %edi
movl -0x28(%rbp), %esi
callq 0x77d0
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %ecx
movq -0x18(%rbp), %rax
movq %rax, %rdx
addq $0x8, %rdx
movq %rdx, -0x18(%rbp)
movl %ecx, (%rax)
leaq -0x70(%rbp), %rdi
callq 0x77a0
jmp 0x5f0b
jmp 0x5f4d
cmpq $0x0, -0x78(%rbp)
je 0x5f8d
movq -0x78(%rbp), %rdi
callq 0x7780
movl %eax, -0x28(%rbp)
movl -0x3c(%rbp), %edi
movl -0x28(%rbp), %esi
callq 0x77d0
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %ecx
movq -0x18(%rbp), %rax
movq %rax, %rdx
addq $0x8, %rdx
movq %rdx, -0x18(%rbp)
movl %ecx, (%rax)
leaq -0x78(%rbp), %rdi
callq 0x77a0
jmp 0x5f4d
movq -0x58(%rbp), %rdi
callq 0x3fa0
cmpl $0x1, %eax
jle 0x5fa8
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x60f5
movq -0x58(%rbp), %rdi
callq 0x7780
movl %eax, -0x7c(%rbp)
movl -0x3c(%rbp), %eax
movl %eax, %ecx
leaq 0xe5e0(%rip), %rax      # 0x145a0
shlq $0x9, %rcx
addq %rcx, %rax
movl -0x7c(%rbp), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, -0x88(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0x10(%rbp), %rdi
movl -0x34(%rbp), %esi
xorl %edx, %edx
callq 0x76b0
movq -0xb8(%rbp), %rdi
movq %rax, %rsi
movl -0x34(%rbp), %edx
movq -0x88(%rbp), %rcx
movq -0x18(%rbp), %r8
callq 0x6a80
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rdi
movl -0x34(%rbp), %esi
movl $0x1, %edx
callq 0x76b0
movq %rax, %rdi
movq -0x88(%rbp), %rsi
movq -0x18(%rbp), %rdx
callq 0x6d80
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rdi
movq -0x88(%rbp), %rsi
movq -0x18(%rbp), %rdx
callq 0x6820
movq %rax, -0x18(%rbp)
movl -0x7c(%rbp), %eax
movl %eax, %ecx
leaq 0xce45(%rip), %rax      # 0x12ea0
movq (%rax,%rcx,8), %rax
movq %rax, -0x90(%rbp)
movq -0x10(%rbp), %rdi
movl -0x34(%rbp), %esi
xorl %edx, %edx
callq 0x76b0
movq %rax, %rdi
movl -0x34(%rbp), %esi
movq -0x90(%rbp), %rdx
movq -0x18(%rbp), %rcx
callq 0x6e40
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rdi
callq 0x75e0
cmpl $0x40, %eax
je 0x60ad
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x65b0
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rdi
movl -0x34(%rbp), %esi
movl $0x1, %edx
callq 0x76b0
movq %rax, %rdi
movq -0x90(%rbp), %rsi
movq -0x18(%rbp), %rdx
callq 0x6d80
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rdi
movq -0x90(%rbp), %rsi
movq -0x18(%rbp), %rdx
callq 0x6820
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0xc0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)