// File: /workspace/github_cpp_makefile_star2_O1/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
movq %rax, 0x28(%rsp)
movq %rdi, 0x10(%rsp)
leaq 0x190(%rdi), %rax
movq %rax, 0x60(%rsp)
movq %rsi, 0x20(%rsp)
leaq 0x10(%rsi), %rax
movq %rax, 0x58(%rsp)
xorl %ebp, %ebp
movq 0x10(%rsp), %rax
movq 0x1938(%rax), %rcx
movl %ebp, %eax
xorq $0x1, %rax
cmpl $0x0, 0x28(%rcx,%rax,4)
jne 0x15059
movq 0x20(%rsp), %rcx
movq 0x8(%rcx), %rcx
movq 0x8(%rcx,%rbp,8), %rcx
movq %rcx, 0x18(%rsp)
testq %rcx, %rcx
je 0x15059
leal (,%rbp,8), %r14d
subl %ebp, %r14d
movl %r14d, %r12d
xorl $0x7, %r12d
shlq $0x9, %rax
movq 0x60(%rsp), %rcx
leaq (%rcx,%rax), %r15
addq $0x180, %r15            # imm = 0x180
movq %rbp, %rbx
shlq $0x6, %rbx
addq 0x58(%rsp), %rbx
movq %rbp, %r13
shlq $0x9, %r13
movq %rbp, 0x8(%rsp)
leaq 0x18(%rsp), %rdi
callq 0x7d37
movslq %eax, %rsi
andl $0x7, %eax
leaq 0x10d82b(%rip), %rcx    # 0x122750
addq %r13, %rcx
movq (%rcx,%rsi,8), %rcx
sarl $0x3, %esi
movl %esi, %edi
subl %r12d, %edi
movl %edi, %edx
negl %edx
cmovsl %edi, %edx
xorl %r14d, %esi
xorl %edi, %edi
cmpl $0x1, %esi
sete %dil
subl %edi, %edx
movl (%r15), %edi
movl %edi, %esi
andl $0x7, %esi
subl %eax, %esi
movl %esi, %eax
negl %eax
cmovsl %esi, %eax
sarl $0x3, %edi
subl %r12d, %edi
movl %edi, %esi
negl %esi
cmovsl %edi, %esi
cmpl %esi, %eax
cmoval %eax, %esi
movq 0x10(%rsp), %rax
movl 0x1090(%rax), %eax
xorl %edi, %edi
cmpq %rax, %rbp
setne %dil
subl %edi, %esi
movq (%rbx), %rdi
andq %rcx, %rdi
cmpl %esi, %edx
jl 0x14f95
cmpq %rcx, %rdi
jne 0x1504d
movq 0x10(%rsp), %r8
movq 0x140(%r8,%rbp,8), %r9
andq %rcx, %r9
movq %r9, %r8
shrq $0x20, %r8
movl %r9d, %r10d
shrl %r10d
movl %r12d, %ebp
movq %rbx, %r12
movq %r13, %rbx
movl %r14d, %r13d
movq %r15, %r14
movl $0x55555555, %r15d      # imm = 0x55555555
andl %r15d, %r10d
movl %r9d, %r11d
subl %r10d, %r11d
shrq $0x21, %r9
andl %r15d, %r9d
subl %r9d, %r8d
movl %r11d, %r9d
shrl $0x2, %r9d
movl $0x33333333, %r15d      # imm = 0x33333333
andl %r15d, %r9d
andl %r15d, %r11d
movl %r8d, %r10d
shrl $0x2, %r10d
andl %r15d, %r10d
andl %r15d, %r8d
movq %r14, %r15
movl %r13d, %r14d
movq %rbx, %r13
movq %r12, %rbx
movl %ebp, %r12d
movq 0x8(%rsp), %rbp
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 0x1502f
cmpq %rcx, %rdi
jne 0x1504d
addl %r8d, %r8d
xorl %ecx, %ecx
cmpq %rax, %rbp
sete %cl
subl %ecx, %r8d
movl 0x28(%rsp,%rbp,4), %eax
cmpl %r8d, %eax
cmovll %eax, %r8d
movl %r8d, 0x28(%rsp,%rbp,4)
cmpq $0x0, 0x18(%rsp)
jne 0x14f0e
leaq 0x1(%rbp), %rax
testq %rbp, %rbp
movq %rax, %rbp
je 0x14e97
movl 0x28(%rsp), %edx
movl 0x2c(%rsp), %esi
movl %edx, %eax
subl %esi, %eax
movl %eax, %ecx
negl %ecx
cmovsl %eax, %ecx
xorl %r13d, %r13d
cmpl $0x3, %ecx
jb 0x15500
xorl %ecx, %ecx
cmpl %esi, %edx
setl %cl
movq 0x10(%rsp), %rax
movq %rcx, 0x30(%rsp)
movq 0x140(%rax,%rcx,8), %rcx
andq 0x108(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq %rcx, 0x18(%rsp)
movl %edx, 0x3c(%rsp)
movl %esi, 0x38(%rsp)
je 0x15175
xorl %eax, %eax
xorl %ebx, %ebx
cmpl %esi, %edx
setge %bl
movl $0xfffffff9, %r14d      # imm = 0xFFFFFFF9
cmovll %eax, %r14d
movl $0x7, %ebp
cmovgel %eax, %ebp
leaq 0x18(%rsp), %r15
leaq 0x1032c9(%rip), %r12    # 0x1183b0
movq %r15, %rdi
callq 0x7d37
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 0x10(%rsp), %rdx
movq 0x30(%rsp), %rdi
cmpl %edi, 0x1090(%rdx)
sete %al
subl %eax, %esi
movl 0x28(%rsp,%rbx,4), %eax
addl $0x3, %eax
cmpl %esi, %eax
jle 0x1515b
movq 0x30(%rsp), %rdi
movl %edi, %eax
shll $0x9, %eax
addq 0x26e4f(%rip), %rax     # 0x3bf90
movq 0x10(%rsp), %rsi
movq 0x108(%rsi), %rdx
andq (%rax,%rcx,8), %rdx
testq %rdx, 0x140(%rsi,%rdi,8)
je 0x15169
movq 0x8(%rsp), %rax
andq (%r12,%rcx,8), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, 0x18(%rsp)
jne 0x150e7
movq 0x20(%rsp), %rax
movq 0x8(%rax), %rax
movq 0x30(%rsp), %rcx
movq 0x8(%rsp), %rdx
testq %rdx, 0x8(%rax,%rcx,8)
jne 0x15500
xorl %eax, %eax
xorl %edx, %edx
xorl %esi, %esi
movl 0x38(%rsp), %ecx
cmpl %ecx, 0x3c(%rsp)
setl %dl
setge %sil
movq %rsi, 0x20(%rsp)
movl $0xfffffff9, %ecx       # imm = 0xFFFFFFF9
cmovll %eax, %ecx
movq %rcx, 0x90(%rsp)
leaq 0x18(%rsp), %rcx
movl $0x7, %esi
cmovgel %eax, %esi
movl %esi, 0x6c(%rsp)
movq 0x8(%rsp), %rax
movq %rax, (%rcx)
shll $0x4, %edx
addl $-0x8, %edx
movq %rdx, 0xa8(%rsp)
movq 0x30(%rsp), %rax
movl %eax, %ecx
shll $0x9, %ecx
movq 0x10(%rsp), %rax
movq %rcx, 0x88(%rsp)
addq %rcx, %rax
addq $0x310, %rax            # imm = 0x310
movq %rax, 0x80(%rsp)
leaq 0x48(%rsp), %r12
cmpq $0x0, 0x18(%rsp)
je 0x154d7
leaq 0x18(%rsp), %rdi
callq 0x7d37
movl %eax, %edx
movslq %eax, %rcx
andl $0x7, %eax
sarl $0x3, %edx
movq 0x90(%rsp), %rsi
addl %edx, %esi
movl %esi, %edi
negl %edi
cmovsl %esi, %edi
xorl 0x6c(%rsp), %edx
xorl %esi, %esi
cmpl $0x1, %edx
sete %sil
subl %esi, %edi
movq %rdi, 0xa0(%rsp)
xorl %edi, %edi
movq 0x10(%rsp), %rdx
movq 0x30(%rsp), %rsi
cmpl %esi, 0x1090(%rdx)
sete %dil
negl %edi
movq %rdi, 0x98(%rsp)
leaq 0x1033cf(%rip), %rsi    # 0x118650
movq (%rsi,%rax,8), %rax
movq %rax, 0xb0(%rsp)
leaq 0x10d4bc(%rip), %rax    # 0x122750
movq 0x88(%rsp), %rsi
addq %rsi, %rax
movq (%rax,%rcx,8), %rax
movq %rax, 0x60(%rsp)
movq 0x20(%rsp), %rax
movq 0x140(%rdx,%rax,8), %rdi
andq 0x108(%rdx), %rdi
leaq 0x10d88d(%rip), %rax    # 0x122b50
addq %rsi, %rax
movq (%rax,%rcx,8), %rax
movq %rdi, 0x58(%rsp)
andq %rdi, %rax
movq %rax, 0x78(%rsp)
movq $-0x2, %r15
rolq %cl, %r15
movl $0x100, 0x40(%rsp)      # imm = 0x100
movq $0x0, 0x50(%rsp)
movq $0x0, 0x70(%rsp)
movl $0x100, 0x44(%rsp)      # imm = 0x100
cmpq $0x0, 0x78(%rsp)
je 0x1549a
leaq 0x78(%rsp), %rdi
callq 0x7d37
movl %eax, %r13d
movl $0x100, %r14d           # imm = 0x100
movq 0x58(%rsp), %rax
testq %rax, 0x60(%rsp)
jne 0x153b8
movq 0xa8(%rsp), %rax
addl %r13d, %eax
sarl $0x3, %eax
cltq
movq 0x20(%rsp), %rcx
shll $0x6, %ecx
addq 0x26bdf(%rip), %rcx     # 0x3bf30
movq (%rcx,%rax,8), %rax
andq 0xb0(%rsp), %rax
andq 0x8(%rsp), %rax
movq %rax, 0x48(%rsp)
je 0x153b8
movl %r13d, %ebx
andl $0x7, %ebx
movl %r13d, %ebp
sarl $0x3, %ebp
movl $0x100, %r14d           # imm = 0x100
movq %r12, %rdi
callq 0x7d37
movl %eax, %ecx
andl $0x7, %ecx
movl %ebx, %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, %r14d
cmovgel %eax, %r14d
cmpq $0x0, 0x48(%rsp)
jne 0x1537b
movslq %r13d, %rax
movq 0x20(%rsp), %rcx
shll $0x9, %ecx
addq 0x26bf6(%rip), %rcx     # 0x3bfc0
movq (%rcx,%rax,8), %rax
andq %r15, %rax
andq 0x8(%rsp), %rax
movq %rax, 0x48(%rsp)
je 0x15426
movl %r13d, %ebx
andl $0x7, %ebx
movl %r13d, %ebp
sarl $0x3, %ebp
movq %r12, %rdi
callq 0x7d37
movl %eax, %ecx
andl $0x7, %ecx
movl %ebx, %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, %r14d
cmovgel %eax, %r14d
cmpq $0x0, 0x48(%rsp)
jne 0x153e9
testl %r14d, %r14d
jle 0x15303
movq 0x80(%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 0x50(%rsp), %rcx
leal (%rcx,%r14,2), %ecx
movq %rcx, 0x50(%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 0x40(%rsp), %eax
cmpl %ecx, %eax
cmovll %eax, %ecx
movq 0x70(%rsp), %rax
leal (%rcx,%rax), %edx
incl %edx
incl %eax
addl %edx, %edx
movl %edx, 0x44(%rsp)
movq %rax, 0x70(%rsp)
movl %ecx, 0x40(%rsp)
jmp 0x15303
movq 0xa0(%rsp), %rax
movq 0x98(%rsp), %rcx
leal (%rcx,%rax,2), %ecx
movq 0x20(%rsp), %rax
movl 0x28(%rsp,%rax,4), %eax
addl $0x3, %eax
movq 0x50(%rsp), %rdx
addl %ecx, %edx
xorl %r13d, %r13d
cmpl %edx, %eax
jg 0x15500
movl 0x44(%rsp), %edx
addl %ecx, %edx
cmpl %edx, %eax
jle 0x15211
jmp 0x15500
xorl %eax, %eax
movl 0x3c(%rsp), %edx
movl 0x38(%rsp), %esi
cmpl %esi, %edx
setge %al
movl 0x28(%rsp,%rax,4), %eax
shll $0x5, %eax
movl $0x500, %ecx            # imm = 0x500
subl %eax, %ecx
movl %ecx, %r13d
negl %r13d
cmpl %esi, %edx
cmovll %ecx, %r13d
movl %r13d, %eax
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop