// File: ATOMIC-LICHESS[P]ATOMKRAFT/evaluate.cpp
// Function: Score (anonymous namespace)::evaluate_passed_pawns<(Color)0>(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:
subq $0xa8, %rsp
movq %rdi, 0x98(%rsp)
movq %rsi, 0x90(%rsp)
movl $0x1, 0x8c(%rsp)
movl $0x0, 0x5c(%rsp)
movq 0x90(%rsp), %rax
movq 0x8(%rax), %rdi
xorl %esi, %esi
callq 0x29bf0
movq %rax, 0x80(%rsp)
cmpq $0x0, 0x80(%rsp)
jne 0x21cd0
movl $0x0, 0xa4(%rsp)
jmp 0x22034
jmp 0x21cd2
leaq 0x80(%rsp), %rdi
callq 0xd940
movl %eax, 0x58(%rsp)
movl 0x58(%rsp), %esi
xorl %edi, %edi
callq 0x1b2c0
movl %eax, %edi
movl $0x1, %esi
callq 0xce20
movl %eax, 0x54(%rsp)
movl 0x54(%rsp), %eax
movl 0x54(%rsp), %ecx
subl $0x1, %ecx
imull %ecx, %eax
movl %eax, 0x50(%rsp)
imull $0x14, 0x50(%rsp), %eax
movl %eax, 0x4c(%rsp)
movl 0x50(%rsp), %eax
addl 0x54(%rsp), %eax
addl $0x1, %eax
imull $0xa, %eax, %eax
movl %eax, 0x48(%rsp)
cmpl $0x0, 0x50(%rsp)
je 0x21e77
movl 0x58(%rsp), %eax
movl %eax, 0x40(%rsp)
xorl %edi, %edi
callq 0x1b580
movl 0x40(%rsp), %edi
movl %eax, %esi
callq 0xd780
movl %eax, 0x44(%rsp)
movq 0x98(%rsp), %rdi
movl $0x1, %esi
callq 0x1b250
movl %eax, %edi
movl 0x44(%rsp), %esi
callq 0xcd00
imull $0x6, %eax, %esi
imull 0x50(%rsp), %esi
leaq 0x48(%rsp), %rdi
callq 0x29dd0
movq 0x98(%rsp), %rdi
movl 0x44(%rsp), %esi
callq 0x29b30
testb $0x1, %al
jne 0x21d9d
jmp 0x21e75
movl 0x58(%rsp), %esi
xorl %edi, %edi
callq 0x1b520
movq %rax, 0x78(%rsp)
movq 0x78(%rsp), %rax
movq 0x90(%rsp), %rcx
andq 0x10(%rcx), %rax
movq %rax, 0x70(%rsp)
movq 0x78(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0x90(%rsp), %rax
movq 0x50(%rax), %rax
movq %rax, 0x30(%rsp)
movq 0x98(%rsp), %rdi
movl $0x1, %esi
callq 0x298c0
movq 0x30(%rsp), %rcx
movq %rax, %rdx
movq 0x38(%rsp), %rax
orq %rdx, %rcx
andq %rcx, %rax
movq %rax, 0x68(%rsp)
cmpq $0x0, 0x68(%rsp)
jne 0x21e3b
movl 0x50(%rsp), %esi
movq 0x78(%rsp), %rdx
movq 0x70(%rsp), %rdi
movl $0xf, %eax
movl $0x11, %ecx
cmpq %rdi, %rdx
cmovel %ecx, %eax
imull %eax, %esi
leaq 0x48(%rsp), %rdi
callq 0x29dd0
movq 0x78(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x98(%rsp), %rdi
xorl %esi, %esi
callq 0x298c0
movq %rax, %rcx
movq 0x28(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
jne 0x21e73
movl 0x50(%rsp), %esi
leaq 0x48(%rsp), %rdi
callq 0x29dd0
jmp 0x21e75
jmp 0x21e77
movq 0x98(%rsp), %rdi
movl $0x1, %esi
xorl %edx, %edx
callq 0x16530
movq %rax, 0x18(%rsp)
movl 0x58(%rsp), %edi
callq 0xe680
movq %rax, %rcx
movq 0x18(%rsp), %rax
andq %rcx, %rax
movq %rax, 0x60(%rsp)
movq 0x60(%rsp), %rax
movq %rax, 0x20(%rsp)
movl 0x58(%rsp), %edi
callq 0x29e60
movq %rax, %rcx
movq 0x20(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x21ede
imull $0x14, 0x54(%rsp), %esi
leaq 0x48(%rsp), %rdi
callq 0x29dd0
jmp 0x21f2b
movq 0x60(%rsp), %rax
movq %rax, 0x10(%rsp)
movl 0x58(%rsp), %eax
movl %eax, 0xc(%rsp)
xorl %edi, %edi
callq 0x1b580
movl 0xc(%rsp), %edi
movl %eax, %esi
callq 0xe9c0
movl %eax, %edi
callq 0x29e60
movq %rax, %rcx
movq 0x10(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x21f29
imull $0xc, 0x54(%rsp), %esi
leaq 0x48(%rsp), %rdi
callq 0x29dd0
jmp 0x21f2b
movl 0x58(%rsp), %edi
callq 0xce10
cmpl $0x0, %eax
je 0x21f47
movl 0x58(%rsp), %edi
callq 0xce10
cmpl $0x7, %eax
jne 0x21fc0
movq 0x98(%rsp), %rdi
movl $0x1, %esi
callq 0x298e0
leaq 0x4a600(%rip), %rcx     # 0x6c560
cmpl (%rcx), %eax
jg 0x21f80
movl 0x48(%rsp), %edi
movl $0x4, %esi
callq 0x281b0
movl %eax, %esi
leaq 0x48(%rsp), %rdi
callq 0x29dd0
jmp 0x21fbe
movq 0x98(%rsp), %rdi
movl $0x4, %esi
movl $0x5, %edx
movl $0x1, %ecx
callq 0x29b80
cmpq $0x0, %rax
je 0x21fbc
movl 0x48(%rsp), %edi
movl $0x4, %esi
callq 0x281b0
movl %eax, %esi
leaq 0x48(%rsp), %rdi
callq 0x29e80
jmp 0x21fbe
jmp 0x21fc0
movl 0x4c(%rsp), %esi
movl $0x3, %edi
callq 0x295b0
movl %eax, %edi
movl $0x2, %esi
callq 0x281b0
movl %eax, 0x8(%rsp)
movl 0x48(%rsp), %esi
movl $0x3, %edi
callq 0x295b0
movl %eax, %edi
movl $0x2, %esi
callq 0x281b0
movl 0x8(%rsp), %edi
movl %eax, %esi
callq 0x27f40
movl %eax, %esi
leaq 0x5c(%rsp), %rdi
callq 0x29810
cmpq $0x0, 0x80(%rsp)
jne 0x21cd2
movl 0x5c(%rsp), %edi
movl 0x3c0a0c(%rip), %esi    # 0x3e2a34
callq 0x20050
movl %eax, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
addq $0xa8, %rsp
retq
nopw %cs:(%rax,%rax)