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

    const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : CpuIs64Bit ? CNT64_MAX15 : CNT32_MAX15;

    Bitboard b, b2, blockers, supporters, queeningPath, candidates;
    Square s, blockSq, queeningSquare;
    Color c, winnerSide, loserSide;
    bool pathDefended, opposed;
    int pliesToGo, movesToGo, oppMovesToGo, sacptg, blockersCount, minKingDist, kingptg, d;
    int pliesToQueen[] = { 256, 256 };

    // Step 1. Hunt for unstoppable passed pawns. If we find at least one,
    // record how many plies are required for promotion.
    for (c = WHITE; c <= BLACK; c++)
    {
        // Skip if other side has non-pawn pieces
        if (pos.non_pawn_material(opposite_color(c)))
            continue;

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

        while (b)
        {
            s = pop_1st_bit(&b);
            queeningSquare = relative_square(c, make_square(square_file(s), RANK_8));
            queeningPath = squares_in_front_of(c, s);

            // Compute plies to queening and check direct advancement
            movesToGo = rank_distance(s, queeningSquare) - int(relative_rank(c, s) == RANK_2);
            oppMovesToGo = square_distance(pos.king_square(opposite_color(c)), queeningSquare) - int(c != pos.side_to_move());
            pathDefended = ((ei.attackedBy[c][0] & queeningPath) == queeningPath);

            if (movesToGo >= oppMovesToGo && !pathDefended)
                continue;

            // Opponent king cannot block because path is defended and position
            // is not in check. So only friendly pieces can be blockers.
            NEW // opponent king can block if he is adjacent to enemy king
            
            assert(!pos.in_check());
            OLD assert((queeningPath & pos.occupied_squares()) == (queeningPath & pos.pieces_of_color(c)));
            STARTNEW
            assert(
            	((queeningPath & pos.occupied_squares()) == (queeningPath & pos.pieces_of_color(c)))
              || squares_touch
              	  [pos.king_square(pos.side_to_move())]
              	   [pos.king_square(opposite_color(pos.side_to_move()))]);
            ENDNEW

            // Add moves needed to free the path from friendly pieces and retest condition
            movesToGo += count_1s<Max15>(queeningPath & pos.pieces_of_color(c));

            if (movesToGo >= oppMovesToGo && !pathDefended)
                continue;

            pliesToGo = 2 * movesToGo - int(c == pos.side_to_move());
            pliesToQueen[c] = Min(pliesToQueen[c], pliesToGo);
        }
    }

    // Step 2. If either side cannot promote at least three plies before the other side then situation
    // becomes too complex and we give up. Otherwise we determine the possibly "winning side"
    if (abs(pliesToQueen[WHITE] - pliesToQueen[BLACK]) < 3)
        return SCORE_ZERO;

    winnerSide = (pliesToQueen[WHITE] < pliesToQueen[BLACK] ? WHITE : BLACK);
    loserSide = opposite_color(winnerSide);

    // Step 3. Can the losing side possibly create a new passed pawn and thus prevent the loss?
    b = candidates = pos.pieces(PAWN, loserSide);

    while (b)
    {
        s = pop_1st_bit(&b);

        // Compute plies from queening
        queeningSquare = relative_square(loserSide, make_square(square_file(s), RANK_8));
        movesToGo = rank_distance(s, queeningSquare) - int(relative_rank(loserSide, s) == RANK_2);
        pliesToGo = 2 * movesToGo - int(loserSide == pos.side_to_move());

        // Check if (without even considering any obstacles) we're too far away or doubled
        if (   pliesToQueen[winnerSide] + 3 <= pliesToGo
            || (squares_in_front_of(loserSide, s) & pos.pieces(PAWN, loserSide)))
            clear_bit(&candidates, s);
    }

    // If any candidate is already a passed pawn it _may_ promote in time. We give up.
    if (candidates & ei.pi->passed_pawns(loserSide))
        return SCORE_ZERO;

    // Step 4. Check new passed pawn creation through king capturing and pawn sacrifices
    b = candidates;

    while (b)
    {
        s = pop_1st_bit(&b);
        sacptg = blockersCount = 0;
        minKingDist = kingptg = 256;

        // Compute plies from queening
        queeningSquare = relative_square(loserSide, make_square(square_file(s), RANK_8));
        movesToGo = rank_distance(s, queeningSquare) - int(relative_rank(loserSide, s) == RANK_2);
        pliesToGo = 2 * movesToGo - int(loserSide == pos.side_to_move());

        // Generate list of blocking pawns and supporters
        supporters = neighboring_files_bb(s) & candidates;
        opposed = squares_in_front_of(loserSide, s) & pos.pieces(PAWN, winnerSide);
        blockers = passed_pawn_mask(loserSide, s) & pos.pieces(PAWN, winnerSide);

        assert(blockers);

        // How many plies does it take to remove all the blocking pawns?
        while (blockers)
        {
            blockSq = pop_1st_bit(&blockers);
            movesToGo = 256;

            // Check pawns that can give support to overcome obstacle, for instance
            // black pawns: a4, b4 white: b2 then pawn in b4 is giving support.
            if (!opposed)
            {
                b2 = supporters & in_front_bb(winnerSide, blockSq + pawn_push(winnerSide));

                while (b2) // This while-loop could be replaced with LSB/MSB (depending on color)
                {
                    d = square_distance(blockSq, pop_1st_bit(&b2)) - 2;
                    movesToGo = Min(movesToGo, d);
                }
            }

            // Check pawns that can be sacrificed against the blocking pawn
            b2 = attack_span_mask(winnerSide, blockSq) & candidates & ~(1ULL << s);

            while (b2) // This while-loop could be replaced with LSB/MSB (depending on color)
            {
                d = square_distance(blockSq, pop_1st_bit(&b2)) - 2;
                movesToGo = Min(movesToGo, d);
            }

            // If obstacle can be destroyed with an immediate pawn exchange / sacrifice,
            // it's not a real obstacle and we have nothing to add to pliesToGo.
            if (movesToGo <= 0)
                continue;

            // Plies needed to sacrifice against all the blocking pawns
            sacptg += movesToGo * 2;
            blockersCount++;

            // Plies needed for the king to capture all the blocking pawns
            d = square_distance(pos.king_square(loserSide), blockSq);
            minKingDist = Min(minKingDist, d);
            kingptg = (minKingDist + blockersCount) * 2;
        }

        // Check if pawn sacrifice plan _may_ save the day
        if (pliesToQueen[winnerSide] + 3 > pliesToGo + sacptg)
            return SCORE_ZERO;

        // Check if king capture plan _may_ save the day (contains some false positives)
        if (pliesToQueen[winnerSide] + 3 > pliesToGo + kingptg)
            return SCORE_ZERO;
    }

    // Winning pawn is unstoppable and will promote as first, return big score
    Score score = make_score(0, (Value) 0x500 - 0x20 * pliesToQueen[winnerSide]);
    return winnerSide == WHITE ? score : -score;
  }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xb8, %rsp
movabsq $0x10000000100, %rax    # imm = 0x10000000100
leaq 0x40(%rsp), %rcx
movq %rcx, 0x20(%rsp)
movq %rax, (%rcx)
movq %rdi, 0x28(%rsp)
leaq 0x190(%rdi), %rax
movq %rax, 0x48(%rsp)
movq %rsi, 0x50(%rsp)
leaq 0x10(%rsi), %rax
movq %rax, 0x60(%rsp)
movb $0x1, %cl
xorl %r12d, %r12d
movl %ecx, 0x38(%rsp)
movq 0x28(%rsp), %rax
movq 0x1938(%rax), %rcx
movq %r12, %rax
xorq $0x1, %rax
cmpl $0x0, 0x28(%rcx,%rax,4)
jne 0x155c3
movq 0x50(%rsp), %rcx
movq 0x8(%rcx), %rcx
movq 0x8(%rcx,%r12,8), %rcx
movq %rcx, 0x18(%rsp)
testq %rcx, %rcx
je 0x155c3
leal (,%r12,8), %ebp
subl %r12d, %ebp
movl %ebp, %r15d
xorl $0x7, %r15d
shlq $0x9, %rax
movq 0x48(%rsp), %rcx
leaq (%rcx,%rax), %rbx
addq $0x180, %rbx            # imm = 0x180
movq %r12, %r13
shlq $0x6, %r13
addq 0x60(%rsp), %r13
movq %r12, %r14
shlq $0x9, %r14
movl %r15d, 0x10(%rsp)
leaq 0x18(%rsp), %rdi
callq 0x827b
movslq %eax, %rsi
andl $0x7, %eax
leaq 0x10e2bf(%rip), %rcx    # 0x123750
addq %r14, %rcx
movq (%rcx,%rsi,8), %rcx
sarl $0x3, %esi
movl %esi, %edi
subl %r15d, %edi
movl %edi, %edx
negl %edx
cmovsl %edi, %edx
xorl %ebp, %esi
xorl %edi, %edi
cmpl $0x1, %esi
sete %dil
subl %edi, %edx
movl (%rbx), %edi
movl %edi, %esi
andl $0x7, %esi
subl %eax, %esi
movl %esi, %eax
negl %eax
cmovsl %esi, %eax
sarl $0x3, %edi
subl %r15d, %edi
movl %edi, %esi
negl %esi
cmovsl %edi, %esi
cmpl %esi, %eax
cmoval %eax, %esi
movq 0x28(%rsp), %rax
movl 0x1090(%rax), %eax
xorl %edi, %edi
cmpq %rax, %r12
setne %dil
subl %edi, %esi
movq (%r13), %rdi
andq %rcx, %rdi
cmpl %esi, %edx
jl 0x15500
cmpq %rcx, %rdi
jne 0x155b7
movq 0x28(%rsp), %r8
movq 0x140(%r8,%r12,8), %r9
andq %rcx, %r9
movq %r9, %r8
shrq $0x20, %r8
movl %r9d, %r10d
shrl %r10d
movq %r12, %r15
movq %r13, %r12
movq %r14, %r13
movl %ebp, %r14d
movq %rbx, %rbp
movl $0x55555555, %ebx       # imm = 0x55555555
andl %ebx, %r10d
movl %r9d, %r11d
subl %r10d, %r11d
shrq $0x21, %r9
andl %ebx, %r9d
subl %r9d, %r8d
movl %r11d, %r9d
shrl $0x2, %r9d
movl $0x33333333, %ebx       # imm = 0x33333333
andl %ebx, %r9d
andl %ebx, %r11d
movl %r8d, %r10d
shrl $0x2, %r10d
andl %ebx, %r10d
andl %ebx, %r8d
movq %rbp, %rbx
movl %r14d, %ebp
movq %r13, %r14
movq %r12, %r13
movq %r15, %r12
movl 0x10(%rsp), %r15d
addl %r11d, %r8d
addl %r9d, %r8d
addl %r10d, %r8d
imull $0x11111111, %r8d, %r8d # imm = 0x11111111
shrl $0x1c, %r8d
addl %edx, %r8d
cmpl %esi, %r8d
jl 0x15598
cmpq %rcx, %rdi
jne 0x155b7
addl %r8d, %r8d
xorl %ecx, %ecx
cmpq %rax, %r12
sete %cl
subl %ecx, %r8d
movq 0x20(%rsp), %rcx
movl (%rcx), %eax
cmpl %r8d, %eax
cmovll %eax, %r8d
movl %r8d, (%rcx)
cmpq $0x0, 0x18(%rsp)
jne 0x1547a
movl $0x1, %r12d
xorl %eax, %eax
leaq 0x44(%rsp), %rcx
movq %rcx, 0x20(%rsp)
testb $0x1, 0x38(%rsp)
movl $0x0, %ecx
jne 0x153fe
movl 0x40(%rsp), %ecx
movl 0x44(%rsp), %edx
movl %ecx, 0x34(%rsp)
movl %edx, 0x30(%rsp)
subl %edx, %ecx
movl %ecx, %edx
negl %edx
cmovsl %ecx, %edx
cmpl $0x3, %edx
jb 0x15a8a
xorl %r12d, %r12d
movl 0x34(%rsp), %ecx
movl 0x30(%rsp), %edx
cmpl %edx, %ecx
setl %r12b
movq 0x28(%rsp), %rax
movq 0x140(%rax,%r12,8), %rsi
andq 0x108(%rax), %rsi
movq %rsi, 0x10(%rsp)
movq %rsi, 0x18(%rsp)
je 0x15a66
xorl %eax, %eax
xorl %ebx, %ebx
cmpl %edx, %ecx
setge %bl
movl $0xfffffff9, %r14d      # imm = 0xFFFFFFF9
cmovll %eax, %r14d
movl $0x7, %ebp
cmovgel %eax, %ebp
leaq 0x18(%rsp), %r13
leaq 0x103d4d(%rip), %r15    # 0x1193b0
movq %r13, %rdi
callq 0x827b
movslq %eax, %rcx
sarl $0x3, %eax
leal (%rax,%r14), %edx
movl %edx, %esi
negl %esi
cmovsl %edx, %esi
xorl %ebp, %eax
xorl %edx, %edx
cmpl $0x1, %eax
sete %dl
subl %edx, %esi
addl %esi, %esi
xorl %eax, %eax
movq 0x28(%rsp), %rdx
cmpl %r12d, 0x1090(%rdx)
sete %al
subl %eax, %esi
movl 0x40(%rsp,%rbx,4), %eax
addl $0x3, %eax
cmpl %esi, %eax
jle 0x156cf
movl %r12d, %eax
shll $0x9, %eax
addq 0x278db(%rip), %rax     # 0x3cf90
movq 0x28(%rsp), %rsi
movq 0x108(%rsi), %rdx
andq (%rax,%rcx,8), %rdx
testq %rdx, 0x140(%rsi,%r12,8)
je 0x156dd
movq 0x10(%rsp), %rax
andq (%r15,%rcx,8), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, 0x18(%rsp)
jne 0x15663
movq 0x50(%rsp), %rax
movq 0x8(%rax), %rcx
xorl %eax, %eax
movq %r12, 0x70(%rsp)
movq 0x10(%rsp), %rdx
testq %rdx, 0x8(%rcx,%r12,8)
jne 0x15a8a
movq 0x10(%rsp), %rax
movq %rax, 0x18(%rsp)
testq %rax, %rax
movl 0x34(%rsp), %ecx
movl 0x30(%rsp), %edx
movq 0x70(%rsp), %rsi
je 0x15a66
xorl %eax, %eax
xorl %edi, %edi
xorl %r8d, %r8d
cmpl %edx, %ecx
setl %dil
movl $0xfffffff9, %ecx       # imm = 0xFFFFFFF9
cmovll %eax, %ecx
movq %rcx, 0x88(%rsp)
setge %r8b
movq %r8, 0x20(%rsp)
movl $0x7, %ecx
cmovgel %eax, %ecx
movl %ecx, 0x68(%rsp)
shll $0x4, %edi
addl $-0x8, %edi
movq %rdi, 0x90(%rsp)
shll $0x9, %esi
movq 0x48(%rsp), %rax
movq %rsi, 0x80(%rsp)
addq %rsi, %rax
addq $0x180, %rax            # imm = 0x180
movq %rax, 0xa0(%rsp)
leaq 0x58(%rsp), %r12
leaq 0x18(%rsp), %rdi
callq 0x827b
movl %eax, %ecx
andl $0x7, %ecx
movl %eax, %edx
sarl $0x3, %edx
movq 0x88(%rsp), %rsi
addl %edx, %esi
movl %esi, %edi
negl %edi
cmovsl %esi, %edi
movl %edi, 0x6c(%rsp)
xorl 0x68(%rsp), %edx
cmpl $0x1, %edx
sete 0xe(%rsp)
movq 0x28(%rsp), %rsi
movq 0x70(%rsp), %rdx
cmpl %edx, 0x1090(%rsi)
sete 0xf(%rsp)
leaq 0x103e70(%rip), %rdx    # 0x119650
movq (%rdx,%rcx,8), %rcx
movq %rcx, 0x98(%rsp)
movslq %eax, %rcx
leaq 0x10df5a(%rip), %rdx    # 0x123750
movq 0x80(%rsp), %rdi
addq %rdi, %rdx
movq (%rdx,%rcx,8), %rdx
movq %rdx, 0x60(%rsp)
leaq 0x10e33f(%rip), %rdx    # 0x123b50
addq %rdi, %rdx
movq (%rdx,%rcx,8), %rcx
movq 0x20(%rsp), %rdx
movq 0x140(%rsi,%rdx,8), %rdx
andq 0x108(%rsi), %rdx
movq %rdx, 0xb0(%rsp)
andq %rdx, %rcx
movq %rcx, 0x78(%rsp)
je 0x15a0e
movq $-0x2, %rdx
movl %eax, %ecx
rolq %cl, %rdx
movq %rdx, 0xa8(%rsp)
movq $0x0, 0x50(%rsp)
movl $0x100, %r14d           # imm = 0x100
movl $0x100, 0x48(%rsp)      # imm = 0x100
movq $0x0, 0x38(%rsp)
leaq 0x78(%rsp), %rdi
callq 0x827b
movl %eax, %r13d
movl $0x100, %ebx            # imm = 0x100
movq 0xb0(%rsp), %rax
testq %rax, 0x60(%rsp)
jne 0x15925
movq 0x90(%rsp), %rax
addl %r13d, %eax
sarl $0x3, %eax
cltq
movq 0x20(%rsp), %rcx
shll $0x6, %ecx
addq 0x27676(%rip), %rcx     # 0x3cf30
movq (%rcx,%rax,8), %rax
andq 0x98(%rsp), %rax
movl $0x100, %ebx            # imm = 0x100
andq 0x10(%rsp), %rax
movq %rax, 0x58(%rsp)
je 0x15925
movl %r13d, %r15d
andl $0x7, %r15d
movl %r13d, %ebp
sarl $0x3, %ebp
movl $0x100, %ebx            # imm = 0x100
movq %r12, %rdi
callq 0x827b
movl %eax, %ecx
andl $0x7, %ecx
movl %r15d, %edx
subl %ecx, %edx
movl %edx, %ecx
negl %ecx
cmovsl %edx, %ecx
sarl $0x3, %eax
movl %ebp, %edx
subl %eax, %edx
movl %edx, %eax
negl %eax
cmovsl %edx, %eax
cmpl %eax, %ecx
cmoval %ecx, %eax
addl $-0x2, %eax
cmpl %eax, %ebx
cmovgel %eax, %ebx
cmpq $0x0, 0x58(%rsp)
jne 0x158e9
movslq %r13d, %rax
movq 0x20(%rsp), %rcx
shll $0x9, %ecx
addq 0x27689(%rip), %rcx     # 0x3cfc0
movq (%rcx,%rax,8), %rax
andq 0xa8(%rsp), %rax
andq 0x10(%rsp), %rax
movq %rax, 0x58(%rsp)
je 0x15998
movl %r13d, %r15d
andl $0x7, %r15d
movl %r13d, %ebp
sarl $0x3, %ebp
movq %r12, %rdi
callq 0x827b
movl %eax, %ecx
andl $0x7, %ecx
movl %r15d, %edx
subl %ecx, %edx
movl %edx, %ecx
negl %ecx
cmovsl %edx, %ecx
sarl $0x3, %eax
movl %ebp, %edx
subl %eax, %edx
movl %edx, %eax
negl %eax
cmovsl %edx, %eax
cmpl %eax, %ecx
cmoval %ecx, %eax
addl $-0x2, %eax
cmpl %eax, %ebx
cmovgel %eax, %ebx
cmpq $0x0, 0x58(%rsp)
jne 0x1595c
testl %ebx, %ebx
jle 0x15a00
movq 0xa0(%rsp), %rax
movl (%rax), %eax
movl %eax, %ecx
andl $0x7, %ecx
movl %r13d, %edx
andl $0x7, %edx
subl %edx, %ecx
movl %ecx, %edx
negl %edx
cmovsl %ecx, %edx
movq 0x38(%rsp), %rcx
leal (%rcx,%rbx,2), %ecx
movq %rcx, 0x38(%rsp)
sarl $0x3, %eax
sarl $0x3, %r13d
subl %r13d, %eax
movl %eax, %ecx
negl %ecx
cmovsl %eax, %ecx
cmpl %ecx, %edx
cmoval %edx, %ecx
movl 0x48(%rsp), %eax
cmpl %ecx, %eax
cmovll %eax, %ecx
movq 0x50(%rsp), %rax
leal (%rcx,%rax), %r14d
incl %r14d
incl %eax
addl %r14d, %r14d
movq %rax, 0x50(%rsp)
movl %ecx, 0x48(%rsp)
cmpq $0x0, 0x78(%rsp)
jne 0x15876
jmp 0x15a1d
movl $0x100, %r14d           # imm = 0x100
movq $0x0, 0x38(%rsp)
xorl %eax, %eax
movb 0xe(%rsp), %cl
movb %cl, %al
movl 0x6c(%rsp), %esi
subl %eax, %esi
addl %esi, %esi
xorl %eax, %eax
movb 0xf(%rsp), %cl
movb %cl, %al
subl %eax, %esi
movq 0x20(%rsp), %rax
movl 0x40(%rsp,%rax,4), %ecx
leal 0x3(%rcx), %edx
movq 0x38(%rsp), %rdi
addl %esi, %edi
xorl %eax, %eax
cmpl %edi, %edx
jg 0x15a8a
addl %esi, %r14d
cmpl %r14d, %edx
jg 0x15a8a
cmpq $0x0, 0x18(%rsp)
jne 0x1578f
jmp 0x15a71
xorl %eax, %eax
cmpl %edx, %ecx
setge %al
movl 0x40(%rsp,%rax,4), %ecx
shll $0x5, %ecx
movl $0x500, %edx            # imm = 0x500
subl %ecx, %edx
movl %edx, %eax
negl %eax
movl 0x30(%rsp), %ecx
cmpl %ecx, 0x34(%rsp)
cmovll %edx, %eax
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq