// File: 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:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movl -0x14(%rbp), %edx
movl $0xfffffff8, %eax       # imm = 0xFFFFFFF8
movl $0x8, %ecx
cmpl $0x0, %edx
cmovel %ecx, %eax
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x14(%rbp)
jne 0x6acb
leaq 0xc61f(%rip), %rax      # 0x130e0
movq 0x38(%rax), %rax
movq %rax, -0x68(%rbp)
jmp 0x6ad9
leaq 0xc60e(%rip), %rax      # 0x130e0
movq (%rax), %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0x38(%rbp)
movl $0x40, -0x3c(%rbp)
movl $0x40, -0x40(%rbp)
movl $0x0, -0x44(%rbp)
movq -0x8(%rbp), %rdi
callq 0x7690
xorq $-0x1, %rax
movq %rax, -0x50(%rbp)
cmpl $0x0, -0x14(%rbp)
jne 0x6b1b
movq -0x10(%rbp), %rax
shlq $0x8, %rax
movq %rax, -0x70(%rbp)
jmp 0x6b27
movq -0x10(%rbp), %rax
shrq $0x8, %rax
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x50(%rbp), %rax
andq -0x58(%rbp), %rax
movq %rax, -0x58(%rbp)
cmpl $0x0, -0x14(%rbp)
jne 0x6b5a
movq -0x58(%rbp), %rax
leaq 0xc594(%rip), %rcx      # 0x130e0
andq 0x10(%rcx), %rax
shlq $0x8, %rax
movq %rax, -0x78(%rbp)
jmp 0x6b71
movq -0x58(%rbp), %rax
leaq 0xc57b(%rip), %rcx      # 0x130e0
andq 0x28(%rcx), %rax
shrq $0x8, %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x20(%rbp), %rax
andq -0x58(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x20(%rbp), %rax
andq -0x60(%rbp), %rax
movq %rax, -0x60(%rbp)
cmpq $0x0, -0x58(%rbp)
je 0x6c09
movq -0x58(%rbp), %rdi
callq 0x7780
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
subl -0x2c(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x40(%rbp), %eax
movl %eax, %ecx
leaq 0xc2e7(%rip), %rax      # 0x12ea0
movq (%rax,%rcx,8), %rax
andq -0x38(%rbp), %rax
cmpq $0x0, %rax
je 0x6bdc
movl -0x3c(%rbp), %edi
movl -0x40(%rbp), %esi
movq -0x28(%rbp), %rdx
callq 0x6f70
movq %rax, -0x28(%rbp)
jmp 0x6bfe
movl -0x3c(%rbp), %edi
movl -0x40(%rbp), %esi
callq 0x77d0
movl %eax, -0x44(%rbp)
movl -0x44(%rbp), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x8, %rdx
movq %rdx, -0x28(%rbp)
movl %ecx, (%rax)
leaq -0x58(%rbp), %rdi
callq 0x77a0
jmp 0x6b91
jmp 0x6c0b
cmpq $0x0, -0x60(%rbp)
je 0x6c57
movq -0x60(%rbp), %rdi
callq 0x7780
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
subl -0x2c(%rbp), %eax
subl -0x2c(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %edi
movl -0x40(%rbp), %esi
callq 0x77d0
movl %eax, -0x44(%rbp)
movl -0x44(%rbp), %ecx
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0x8, %rdx
movq %rdx, -0x28(%rbp)
movl %ecx, (%rax)
leaq -0x60(%rbp), %rdi
callq 0x77a0
jmp 0x6c0b
movq -0x28(%rbp), %rax
addq $0x80, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)