// File: /workspace/github_cpp_makefile_star2_O3/ATOMIC-LICHESS[P]ATOMKRAFT/endgame.cpp
// Function: Endgame<ScaleFactor, (EndgameType)15>::apply(Position const&) const
ScaleFactor Endgame<ScaleFactor, KBPKB>::apply(const Position& pos) const {

  assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
  assert(pos.piece_count(strongerSide, BISHOP) == 1);
  assert(pos.piece_count(strongerSide, PAWN) == 1);
  assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
  assert(pos.piece_count(weakerSide, BISHOP) == 1);
  assert(pos.piece_count(weakerSide, PAWN) == 0);

  Square pawnSq = pos.piece_list(strongerSide, PAWN, 0);
  Square strongerBishopSq = pos.piece_list(strongerSide, BISHOP, 0);
  Square weakerBishopSq = pos.piece_list(weakerSide, BISHOP, 0);
  Square weakerKingSq = pos.king_square(weakerSide);

  // Case 1: Defending king blocks the pawn, and cannot be driven away
  if (   square_file(weakerKingSq) == square_file(pawnSq)
      && relative_rank(strongerSide, pawnSq) < relative_rank(strongerSide, weakerKingSq)
      && (   opposite_color_squares(weakerKingSq, strongerBishopSq)
          || relative_rank(strongerSide, weakerKingSq) <= RANK_6))
      return SCALE_FACTOR_ZERO;

  // Case 2: Opposite colored bishops
  if (opposite_color_squares(strongerBishopSq, weakerBishopSq))
  {
      // We assume that the position is drawn in the following three situations:
      //
      //   a. The pawn is on rank 5 or further back.
      //   b. The defending king is somewhere in the pawn's path.
      //   c. The defending bishop attacks some square along the pawn's path,
      //      and is at least three squares away from the pawn.
      //
      // These rules are probably not perfect, but in practice they work
      // reasonably well.

      if (relative_rank(strongerSide, pawnSq) <= RANK_5)
          return SCALE_FACTOR_ZERO;
      else
      {
          Bitboard path = squares_in_front_of(strongerSide, pawnSq);

          if (path & pos.pieces(KING, weakerSide))
              return SCALE_FACTOR_ZERO;

          if (  (pos.attacks_from<BISHOP>(weakerBishopSq) & path)
              && square_distance(weakerBishopSq, pawnSq) >= 3)
              return SCALE_FACTOR_ZERO;
      }
  }
  return SCALE_FACTOR_NONE;
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
movl 0x8(%rdi), %r10d
movl 0xc(%rdi), %ecx
movq %r10, %r8
shlq $0x9, %r8
movslq 0x1d0(%rsi,%r8), %r9
movl 0x250(%rsi,%r8), %r11d
movq %rcx, %rax
shlq $0x9, %rax
movslq 0x250(%rsi,%rax), %rdx
movl 0x310(%rsi,%rax), %ebx
movl %ebx, %eax
andl $0x7, %eax
movl %r9d, %edi
andl $0x7, %edi
cmpl %edi, %eax
jne 0xcf99
movl %r9d, %eax
sarl $0x3, %eax
leal (,%r10,8), %r14d
subl %r10d, %r14d
xorl %r14d, %eax
movl %ebx, %ebp
sarl $0x3, %ebp
xorl %r14d, %ebp
cmpl %ebp, %eax
jge 0xcf99
xorl %eax, %eax
cmpl $0x6, %ebp
jl 0xd071
xorl %r11d, %ebx
movl %ebx, %ebp
shrl $0x3, %ebp
xorl %ebx, %ebp
andl $0x1, %ebp
jne 0xd071
xorl %edx, %r11d
movl %r11d, %ebx
shrl $0x3, %ebx
xorl %r11d, %ebx
movl $0xff, %eax
testb $0x1, %bl
je 0xd071
movl %r9d, %r11d
sarl $0x3, %r11d
leal (,%r10,8), %ebx
subl %r10d, %ebx
xorl %r11d, %ebx
xorl %eax, %eax
cmpl $0x5, %ebx
jl 0xd071
addq 0x2ffb6(%rip), %r8      # 0x3cf90
movq (%r8,%r9,8), %r8
movq 0x130(%rsi), %r9
andq 0x140(%rsi,%rcx,8), %r9
testq %r8, %r9
jne 0xd071
leaq 0x101aa7(%rip), %rcx    # 0x10eaa0
movq (%rcx,%rdx,8), %rcx
andq 0x100(%rsi), %rcx
leaq 0x223b5(%rip), %rsi     # 0x2f3c0
movq (%rsi,%rdx,8), %rsi
movl %esi, %r9d
imull %ecx, %r9d
shrq $0x20, %rcx
shrq $0x20, %rsi
imull %ecx, %esi
xorl %r9d, %esi
leaq 0x22795(%rip), %rcx     # 0x2f7c0
movb (%rcx,%rdx,4), %cl
shrl %cl, %esi
leaq 0x101c69(%rip), %rcx    # 0x10eca0
addl (%rcx,%rdx,4), %esi
leaq 0x101d5f(%rip), %rcx    # 0x10eda0
testq %r8, (%rcx,%rsi,8)
je 0xd06c
movl %edx, %ecx
andl $0x7, %ecx
subl %edi, %ecx
movl %ecx, %esi
negl %esi
cmovsl %ecx, %esi
sarl $0x3, %edx
subl %r11d, %edx
movl %edx, %ecx
negl %ecx
cmovsl %edx, %ecx
cmpl %ecx, %esi
cmoval %esi, %ecx
cmpl $0x2, %ecx
ja 0xd071
movl $0xff, %eax
popq %rbx
popq %r14
popq %rbp
retq