// File: /workspace/github_cpp_makefile_star2_O3/ATOMIC-LICHESS[P]ATOMKRAFT/evaluate.cpp
// Function: Score (anonymous namespace)::evaluate_passed_pawns<(Color)1>(Position const&, (anonymous namespace)::EvalInfo&)
Score evaluate_passed_pawns(const Position& pos, EvalInfo& ei) {

    const Color Them = (Us == WHITE ? BLACK : WHITE);

    Bitboard b, squaresToQueen, defendedSquares, unsafeSquares, supportingPawns;
    Score score = SCORE_ZERO;

    b = ei.pi->passed_pawns(Us);

    if (!b)
        return SCORE_ZERO;
    
    STARTNEW
//    
//    // a passed pawn is at least worth the value of the least valuable piece
//    // so create a table of the least valuable pieces ordered from cheap to valuable
//    const Value midgameScores[]  = {Value(0), PawnValueMidgame, KnightValueMidgame, 
//    		BishopValueMidgame, RookValueMidgame, QueenValueMidgame};
//    const Value endgameScores[]  = {Value(0), PawnValueEndgame, KnightValueEndgame, 
//        		BishopValueEndgame, RookValueEndgame, QueenValueEndgame};
//    
//    Value leastOppValuesMg[8];
//    Value leastOppValuesEg[8];
//    
//    // as we trace the passed pawns we increment this
//    int passedPawnCounter = 0;
//    
//    if (useImprovements) {
//    // king is the least valuable blocker since it cannot attack nor defend
//    leastOppValuesMg[0] = KnightValueMidgame / 2;
//    leastOppValuesEg[0] = KnightValueEndgame / 2;
//    int k = 1;
//    for (int pt = int(KNIGHT); pt < int(KING); ++pt) {
//		for (int j = 0; j < pos.piece_count(Them, PieceType(pt)); ++j) {
//			leastOppValuesMg[k] = midgameScores[pt];
//			leastOppValuesEg[k] = endgameScores[pt];
//			++k;
//		}
//    }
//    
//    // fill with queen values
//    while (k < 8) {
//    	leastOppValuesMg[k] = QueenValueMidgame;
//    	leastOppValuesEg[k] = QueenValueEndgame;
//    	++k;
//    }
//    }
    ENDNEW

    do {
        Square s = pop_1st_bit(&b);

        assert(pos.pawn_is_passed(Us, s));

        int r = int(relative_rank(Us, s) - RANK_2);
        int rr = r * (r - 1);

        // Base bonus based on rank
        Value mbonus = Value(20 * rr);
        Value ebonus = Value(10 * (rr + r + 1));

        if (rr)
        {
            Square blockSq = s + pawn_push(Us);

			STARTOLD
			// Adjust bonus based on kings proximity
            ebonus += Value(square_distance(pos.king_square(Them), blockSq) * 6 * rr);
            ebonus -= Value(square_distance(pos.king_square(Us), blockSq) * 3 * rr);

            // If blockSq is not the queening square then consider also a second push
            if (square_rank(blockSq) != (Us == WHITE ? RANK_8 : RANK_1))
                ebonus -= Value(square_distance(pos.king_square(Us), blockSq + pawn_push(Us)) * rr);
            ENDOLD
            
            NEW // the king fails to support passed pawns in atomic
            NEW ebonus += Value(square_distance(pos.king_square(Them), blockSq) * 6 * rr);
            
            // If the pawn is free to advance, increase bonus
            if (pos.square_is_empty(blockSq))
            {
                squaresToQueen = squares_in_front_of(Us, s);
                defendedSquares = squaresToQueen & ei.attackedBy[Us][0];

                // If there is an enemy rook or queen attacking the pawn from behind,
                // add all X-ray attacks by the rook or queen. Otherwise consider only
                // the squares in the pawn's path attacked or occupied by the enemy.
                NEW // queens/rook which attack from behind are no threats 
                NEW // since they have to capture the pawn to stop it
                
                STARTOLD
//                if (   (squares_in_front_of(Them, s) & pos.pieces(ROOK, QUEEN, Them))
//                    && (squares_in_front_of(Them, s) & pos.pieces(ROOK, QUEEN, Them) & pos.attacks_from<ROOK>(s)))
//                    unsafeSquares = squaresToQueen;
//                else
                ENDOLD
                    unsafeSquares = squaresToQueen & (ei.attackedBy[Them][0] | pos.pieces_of_color(Them));

                // If there aren't enemy attacks or pieces along the path to queen give
                // huge bonus. Even bigger if we protect the pawn's path.
                if (!unsafeSquares)
                    ebonus += Value(rr * (squaresToQueen == defendedSquares ? 17 : 15));
                // OLD else 
                    // OK, there are enemy attacks or pieces (but not pawns). Are those
                    // squares which are attacked by the enemy also attacked by us ?
                    // If yes, big bonus (but smaller than when there are no enemy attacks),
                    // if no, somewhat smaller bonus.
                	NEW // there is no possibility of defending by recapture
                    OLD ebonus += Value(rr * ((unsafeSquares & defendedSquares) == unsafeSquares ? 13 : 8));

                // At last, add a small bonus when there are no *friendly* pieces
                // in the pawn's path.
                if (!(squaresToQueen & pos.pieces_of_color(Us)))
                    ebonus += Value(rr);
            }
        } // rr != 0

        // Increase the bonus if the passed pawn is supported by a friendly pawn
        // on the same rank and a bit smaller if it's on the previous rank.
        supportingPawns = pos.pieces(PAWN, Us) & neighboring_files_bb(s);
        if (supportingPawns & rank_bb(s))
            ebonus += Value(r * 20);
        else if (supportingPawns & rank_bb(s - pawn_push(Us)))
            ebonus += Value(r * 12);

        // Rook pawns are a special case: They are sometimes worse, and
        // sometimes better than other passed pawns. It is difficult to find
        // good rules for determining whether they are good or bad. For now,
        // we try the following: Increase the value for rook pawns if the
        // other side has no pieces apart from a knight, and decrease the
        // value if the other side has a rook or queen.
        if (square_file(s) == FILE_A || square_file(s) == FILE_H)
        {
            if (pos.non_pawn_material(Them) <= KnightValueMidgame)
                ebonus += ebonus / 4;
            else if (pos.pieces(ROOK, QUEEN, Them))
                ebonus -= ebonus / 4;
        }
        
        
        NEW // maybe this needs to be scaled up
        NEW score += make_score(3 * mbonus / 2, 3 * ebonus / 2);
        //score += make_score(mbonus, ebonus);
        
        STARTNEW
//        if (useImprovements) {
//        // score the passed pawns with the least valuable defenders
//        score += make_score(
//        		leastOppValuesMg[passedPawnCounter] - PawnValueMidgame, 
//        		leastOppValuesEg[passedPawnCounter] - PawnValueEndgame);
//        
//        ++passedPawnCounter;
//        }
        ENDNEW

    } while (b);

    // Add the scores to the middle game and endgame eval
    return apply_weight(score, Weights[PassedPawns]);
  }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq 0x8(%rsi), %rax
movq 0x10(%rax), %rax
movq %rax, (%rsp)
testq %rax, %rax
je 0x153a1
movq %rsi, %rbx
movq %rdi, %r14
xorl %r12d, %r12d
movq %rsp, %r15
leaq 0x1044ab(%rip), %r13    # 0x119650
leaq 0x104464(%rip), %rbp    # 0x119610
movq %r15, %rdi
callq 0x827b
movl %eax, %r8d
sarl $0x3, %r8d
movl %r8d, %ecx
xorl $0x7, %ecx
leal -0x1(%rcx), %esi
addl $-0x2, %ecx
imull %esi, %ecx
movl %esi, %edx
imull %edx, %edx
leal (%rdx,%rdx,4), %edx
leal 0xa(,%rdx,2), %edx
testl %ecx, %ecx
je 0x15293
movl 0x310(%r14), %r9d
movl %r9d, %r10d
andl $0x7, %r10d
movl %eax, %edi
andl $0x7, %edi
subl %edi, %r10d
movl %r10d, %r11d
negl %r11d
cmovsl %r10d, %r11d
leal -0x8(%rax), %r10d
sarl $0x3, %r9d
sarl $0x3, %r10d
subl %r10d, %r9d
movl %r9d, %r10d
negl %r10d
cmovsl %r9d, %r10d
cmpl %r10d, %r11d
cmoval %r11d, %r10d
imull %ecx, %r10d
leal (%r10,%r10,2), %r9d
leal (%rdx,%r9,2), %edx
movslq %eax, %r9
cmpl $0x10, -0x20(%r14,%r9,4)
jne 0x15298
leaq 0x10e511(%rip), %r10    # 0x123750
movq 0x200(%r10,%r9,8), %r9
movq 0x140(%r14), %r10
orq 0x10(%rbx), %r10
testq %r9, %r10
jne 0x1527a
movq 0x50(%rbx), %r10
notq %r10
xorl %r11d, %r11d
testq %r10, %r9
sete %r11b
leal 0xf(,%r11,2), %r10d
imull %ecx, %r10d
addl %edx, %r10d
movl %r10d, %edx
testq %r9, 0x148(%r14)
movl $0x0, %r9d
cmovel %ecx, %r9d
addl %edx, %r9d
movl %r9d, %edx
jmp 0x15298
movl %eax, %edi
andl $0x7, %edi
movq 0x148(%r14), %r9
andq 0x108(%r14), %r9
movl %edi, %r10d
andq (%r13,%r10,8), %r9
movslq %r8d, %r8
testq %r9, (%rbp,%r8,8)
je 0x152bd
leal (%rsi,%rsi,4), %eax
jmp 0x152cf
addl $0x8, %eax
sarl $0x3, %eax
cltq
testq %r9, (%rbp,%rax,8)
je 0x152d2
leal (%rsi,%rsi,2), %eax
leal (%rdx,%rax,4), %edx
cmpl $0x7, %edi
je 0x152db
testl %edi, %edi
jne 0x15325
movq 0x1938(%r14), %rax
movl 0x28(%rax), %eax
leaq 0x28164(%rip), %rsi     # 0x3d450
cmpl (%rsi), %eax
jle 0x15316
movq 0x128(%r14), %rax
orq 0x120(%r14), %rax
testq %rax, 0x140(%r14)
je 0x15325
leal 0x3(%rdx), %eax
testl %edx, %edx
cmovnsl %edx, %eax
sarl $0x2, %eax
subl %eax, %edx
jmp 0x15325
leal 0x3(%rdx), %eax
testl %edx, %edx
cmovnsl %edx, %eax
sarl $0x2, %eax
addl %edx, %eax
movl %eax, %edx
leal (%rdx,%rdx,2), %eax
movl %eax, %edx
shrl $0x1f, %edx
addl %eax, %edx
sarl %edx
imull $0x1e0000, %ecx, %eax   # imm = 0x1E0000
addl %eax, %r12d
addl %edx, %r12d
cmpq $0x0, (%rsp)
jne 0x151ac
movl 0x39e5d6(%rip), %edx    # 0x3b3924
movl $0x8000, %esi           # imm = 0x8000
leal (%r12,%rsi), %eax
sarl $0x10, %eax
leal (%rdx,%rsi), %edi
sarl $0x10, %edi
imull %eax, %edi
movl $0xff, %ecx
leal (%rdi,%rcx), %eax
testl %edi, %edi
cmovnsl %edi, %eax
movl $0x7fff, %edi           # imm = 0x7FFF
movl %r12d, %r8d
andl %edi, %r8d
andl %esi, %r12d
subl %r12d, %r8d
andl %edx, %edi
andl %esi, %edx
subl %edx, %edi
imull %r8d, %edi
addl %edi, %ecx
testl %edi, %edi
cmovnsl %edi, %ecx
sarl $0x8, %ecx
shll $0x8, %eax
andl $0xffff0000, %eax       # imm = 0xFFFF0000
addl %ecx, %eax
jmp 0x153a3
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq