// File: /workspace/github_cpp_makefile_star2_O3/bjohnsonfl[P]Overhead-Chess-Engine-/moveGen.cpp
// Function: pawnPushMoves(position const&, unsigned long, player, unsigned long, candidate*)
candidate* pawnPushMoves (const position& pos, bitboard pawns, player color, bitboard target, candidate* moveList){
    
    direction shift = color == white ? nort : south;
    bitboard rank8Sq = color == white ? rankBitMask[rank_8] : rankBitMask[rank_1];
    
    
    square from = empty, to = empty;
    move mov = none;
    
    bitboard unoccupied = ~(pos.get_pieces());
    
    //BUG!!! Here if a single push target doesnt exist, then a double push is impossible
    //BUT if a double push target exists, it will never occur because the single never happened
   // bitboard singlePush = color == white ? (pawns << nort) & target : (pawns >> -south) & target;
    //bitboard doublePush = color == white ? (singlePush & rankBitMask[rank_3]) << nort
   //                                      : (singlePush & rankBitMask[rank_6]) >> -south;
    
    
    //PROBLEM AGAIN. this allows for double pawn push over an occupied square. fix it
     bitboard singlePush = color == white ? (pawns << nort)  : (pawns >> -south);
    singlePush &= unoccupied;
     bitboard doublePush = color == white ? (singlePush & rankBitMask[rank_3]) << nort
                                        : (singlePush & rankBitMask[rank_6]) >> -south;
    singlePush &= target;
    doublePush &= target;
   // printBitboard(pawns);
   // printBitboard(singlePush);
  //  printBitboard(doublePush);
    
    while(singlePush)
    {
        to = lsb_sq(singlePush);
        from = square(to - shift);
        if ( squareBitMask[to] & rank8Sq ) {
           moveList = makePromotionMoves(from, to, moveList);
        }
        else {
            mov = make_move(from, to);
            (*moveList++).mv = mov;
        }
        
        pop_lsb(&singlePush);
    }
    
    //can never promote
    while(doublePush)
    {
        to = lsb_sq(doublePush);
        from = square(to - shift - shift);
        mov = make_move(from, to);
        (*moveList++).mv = mov;
        
        pop_lsb(&doublePush);
    }

    return moveList;
}

// Assembly:
movq %r8, %rax
movq %rsi, %r10
shlq $0x8, %r10
shrq $0x8, %rsi
xorl %r8d, %r8d
testl %edx, %edx
setne %r9b
leaq 0x8036(%rip), %r11      # 0xc020
movq 0x170(%rdi), %rdi
notq %rdi
cmoveq %r10, %rsi
leaq 0x38(%r11), %r10
andq %rdi, %rsi
testl %edx, %edx
cmovneq %r11, %r10
je 0x4014
movq 0x28(%r11), %rdi
andq %rsi, %rdi
shrq $0x8, %rdi
jmp 0x401f
movq 0x10(%r11), %rdi
andq %rsi, %rdi
shlq $0x8, %rdi
pushq %rbx
andq %rcx, %rdi
andq %rcx, %rsi
je 0x4070
movb %r9b, %r8b
shll $0x4, %r8d
addl $-0x8, %r8d
movq (%r10), %rcx
leaq 0x7da3(%rip), %r9       # 0xbde0
bsfq %rsi, %r10
leal (%r8,%r10), %r11d
movl %r10d, %ebx
shll $0x6, %ebx
orl %r11d, %ebx
movl %ebx, %r11d
orl $0xf000, %r11d          # imm = 0xF000
testq %rcx, (%r9,%r10,8)
cmovel %ebx, %r11d
movl %r11d, (%rax)
addq $0x8, %rax
leaq -0x1(%rsi), %r10
andq %r10, %rsi
jne 0x403d
testq %rdi, %rdi
je 0x409d
xorl %ecx, %ecx
testl %edx, %edx
setne %cl
shll $0x5, %ecx
addl $-0x10, %ecx
bsfq %rdi, %rdx
leal (%rcx,%rdx), %esi
shll $0x6, %edx
orl %esi, %edx
movl %edx, (%rax)
addq $0x8, %rax
leaq -0x1(%rdi), %rdx
andq %rdx, %rdi
jne 0x4082
popq %rbx
retq