// File: /workspace/github_cpp_makefile_star2_O2/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 %r15
pushq %r14
pushq %rbx
pushq %rax
movl 0x8(%rdi), %edx
movl 0xc(%rdi), %eax
movq %rdx, %rcx
shlq $0x9, %rcx
movslq 0x1d0(%rsi,%rcx), %rbx
movl 0x250(%rsi,%rcx), %edi
movq %rax, %r8
shlq $0x9, %r8
movl 0x250(%rsi,%r8), %ebp
movl 0x310(%rsi,%r8), %r8d
movl %r8d, %r9d
xorl %ebx, %r9d
testb $0x7, %r9b
jne 0xbe9d
movl %ebx, %r10d
sarl $0x3, %r10d
imull $0x7, %edx, %r11d
xorl %r11d, %r10d
movl %r8d, %r9d
sarl $0x3, %r9d
xorl %r11d, %r9d
cmpl %r9d, %r10d
jge 0xbe9d
xorl %r14d, %r14d
cmpl $0x6, %r9d
jl 0xbf09
xorl %edi, %r8d
movl %r8d, %r9d
shrl $0x3, %r9d
xorl %r8d, %r9d
andl $0x1, %r9d
jne 0xbf09
xorl %ebp, %edi
movl %edi, %r8d
shrl $0x3, %r8d
xorl %edi, %r8d
movl $0xff, %r14d
testb $0x1, %r8b
je 0xbf09
movl %ebx, %edi
sarl $0x3, %edi
imull $0x7, %edx, %edx
xorl %edi, %edx
xorl %r14d, %r14d
cmpl $0x5, %edx
jl 0xbf09
addq 0x290c2(%rip), %rcx     # 0x34f90
movq (%rcx,%rbx,8), %r15
movq 0x130(%rsi), %rcx
andq 0x140(%rsi,%rax,8), %rcx
testq %r15, %rcx
jne 0xbf09
movq %rsi, %rdi
movl %ebp, %esi
callq 0xcf20
testq %r15, %rax
je 0xbf03
movl %ebp, %edi
movl %ebx, %esi
callq 0x75ec
cmpl $0x2, %eax
jg 0xbf09
movl $0xff, %r14d
movl %r14d, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
nop