// File: /workspace/github_cpp_makefile_star2_O2/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, %r9
shlq $0x8, %r9
shrq $0x8, %rsi
xorl %r8d, %r8d
testl %edx, %edx
setne %r8b
leaq 0x8224(%rip), %r10      # 0xc020
movq 0x170(%rdi), %rdi
notq %rdi
cmoveq %r9, %rsi
shll $0x4, %r8d
leaq 0x38(%r10), %r9
andq %rdi, %rsi
testl %edx, %edx
cmovneq %r10, %r9
je 0x3e2a
movq 0x28(%r10), %rdi
andq %rsi, %rdi
shrq $0x8, %rdi
jmp 0x3e35
movq 0x10(%r10), %rdi
andq %rsi, %rdi
shlq $0x8, %rdi
pushq %rbp
pushq %rbx
addl $-0x8, %r8d
movq (%r9), %r9
andq %rcx, %rsi
leaq 0x7f98(%rip), %r10      # 0xbde0
testq %rsi, %rsi
je 0x3e7b
bsfq %rsi, %r11
leal (%r8,%r11), %ebx
movl %r11d, %ebp
shll $0x6, %ebp
orl %ebx, %ebp
movl %ebp, %ebx
orl $0xf000, %ebx           # imm = 0xF000
testq %r9, (%r10,%r11,8)
cmovel %ebp, %ebx
movl %ebx, (%rax)
addq $0x8, %rax
leaq -0x1(%rsi), %r11
andq %r11, %rsi
jmp 0x3e48
xorl %esi, %esi
testl %edx, %edx
setne %sil
andq %rcx, %rdi
shll $0x5, %esi
addl $-0x10, %esi
testq %rdi, %rdi
je 0x3eac
bsfq %rdi, %rcx
leal (%rsi,%rcx), %edx
shll $0x6, %ecx
orl %edx, %ecx
movl %ecx, (%rax)
addq $0x8, %rax
leaq -0x1(%rdi), %rcx
andq %rcx, %rdi
jmp 0x3e8c
popq %rbx
popq %rbp
retq