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

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

  Square wksq = pos.king_square(strongerSide);
  Square wrsq = pos.piece_list(strongerSide, ROOK, 0);
  Square wpsq = pos.piece_list(strongerSide, PAWN, 0);
  Square bksq = pos.king_square(weakerSide);
  Square brsq = pos.piece_list(weakerSide, ROOK, 0);

  // Orient the board in such a way that the stronger side is white, and the
  // pawn is on the left half of the board.
  if (strongerSide == BLACK)
  {
      wksq = flip_square(wksq);
      wrsq = flip_square(wrsq);
      wpsq = flip_square(wpsq);
      bksq = flip_square(bksq);
      brsq = flip_square(brsq);
  }
  if (square_file(wpsq) > FILE_D)
  {
      wksq = flop_square(wksq);
      wrsq = flop_square(wrsq);
      wpsq = flop_square(wpsq);
      bksq = flop_square(bksq);
      brsq = flop_square(brsq);
  }

  File f = square_file(wpsq);
  Rank r = square_rank(wpsq);
  Square queeningSq = make_square(f, RANK_8);
  int tempo = (pos.side_to_move() == strongerSide);

  // If the pawn is not too far advanced and the defending king defends the
  // queening square, use the third-rank defence.
  if (   r <= RANK_5
      && square_distance(bksq, queeningSq) <= 1
      && wksq <= SQ_H5
      && (square_rank(brsq) == RANK_6 || (r <= RANK_3 && square_rank(wrsq) != RANK_6)))
      return SCALE_FACTOR_ZERO;

  // The defending side saves a draw by checking from behind in case the pawn
  // has advanced to the 6th rank with the king behind.
  if (   r == RANK_6
      && square_distance(bksq, queeningSq) <= 1
      && square_rank(wksq) + tempo <= RANK_6
      && (square_rank(brsq) == RANK_1 || (!tempo && abs(square_file(brsq) - f) >= 3)))
      return SCALE_FACTOR_ZERO;

  if (   r >= RANK_6
      && bksq == queeningSq
      && square_rank(brsq) == RANK_1
      && (!tempo || square_distance(wksq, wpsq) >= 2))
      return SCALE_FACTOR_ZERO;

  // White pawn on a7 and rook on a8 is a draw if black's king is on g7 or h7
  // and the black rook is behind the pawn.
  if (   wpsq == SQ_A7
      && wrsq == SQ_A8
      && (bksq == SQ_H7 || bksq == SQ_G7)
      && square_file(brsq) == FILE_A
      && (square_rank(brsq) <= RANK_3 || square_file(wksq) >= FILE_D || square_rank(wksq) <= RANK_5))
      return SCALE_FACTOR_ZERO;

  // If the defending king blocks the pawn and the attacking king is too far
  // away, it's a draw.
  if (   r <= RANK_5
      && bksq == wpsq + DELTA_N
      && square_distance(wksq, wpsq) - tempo >= 2
      && square_distance(wksq, brsq) - tempo >= 2)
      return SCALE_FACTOR_ZERO;

  // Pawn on the 7th rank supported by the rook from behind usually wins if the
  // attacking king is closer to the queening square than the defending king,
  // and the defending king cannot gain tempi by threatening the attacking rook.
  if (   r == RANK_7
      && f != FILE_A
      && square_file(wrsq) == f
      && wrsq != queeningSq
      && (square_distance(wksq, queeningSq) < square_distance(bksq, queeningSq) - 2 + tempo)
      && (square_distance(wksq, queeningSq) < square_distance(bksq, wrsq) + tempo))
      return ScaleFactor(SCALE_FACTOR_MAX - 2 * square_distance(wksq, queeningSq));

  // Similar to the above, but with the pawn further back
  if (   f != FILE_A
      && square_file(wrsq) == f
      && wrsq < wpsq
      && (square_distance(wksq, queeningSq) < square_distance(bksq, queeningSq) - 2 + tempo)
      && (square_distance(wksq, wpsq + DELTA_N) < square_distance(bksq, wpsq + DELTA_N) - 2 + tempo)
      && (  square_distance(bksq, wrsq) + tempo >= 3
          || (    square_distance(wksq, queeningSq) < square_distance(bksq, wrsq) + tempo
              && (square_distance(wksq, wpsq + DELTA_N) < square_distance(bksq, wrsq) + tempo))))
      return ScaleFactor(  SCALE_FACTOR_MAX
                         - 8 * square_distance(wpsq, queeningSq)
                         - 2 * square_distance(wksq, queeningSq));

  // If the pawn is not far advanced, and the defending king is somewhere in
  // the pawn's path, it's probably a draw.
  if (r <= RANK_4 && bksq > wpsq)
  {
      if (square_file(bksq) == square_file(wpsq))
          return ScaleFactor(10);
      if (   abs(square_file(bksq) - square_file(wpsq)) == 1
          && square_distance(wksq, bksq) > 2)
          return ScaleFactor(24 - 2 * square_distance(wksq, bksq));
  }
  return SCALE_FACTOR_NONE;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl 0x8(%rdi), %ebp
movl 0xc(%rdi), %eax
movq %rbp, %rcx
shlq $0x9, %rcx
shlq $0x9, %rax
movl 0x310(%rsi,%rcx), %r12d
movl 0x1d0(%rsi,%rcx), %r14d
movl 0x290(%rsi,%rcx), %edi
movl 0x290(%rsi,%rax), %r13d
movl 0x310(%rsi,%rax), %edx
cmpq $0x1, %rbp
jne 0xb819
xorl $0x38, %r12d
xorl $0x38, %edi
xorl $0x38, %r14d
xorl $0x38, %edx
xorl $0x38, %r13d
testb $0x4, %r14b
je 0xb831
xorl $0x7, %r12d
xorl $0x7, %edi
xorl $0x7, %r14d
xorl $0x7, %edx
xorl $0x7, %r13d
movl %r14d, %ebx
andl $0x7, %ebx
movl %r14d, %r15d
sarl $0x3, %r15d
leal 0x38(%rbx), %ecx
movl 0x1090(%rsi), %esi
xorl %eax, %eax
movl %esi, 0x20(%rsp)
cmpl %ebp, %esi
sete %al
movl %eax, 0x1c(%rsp)
cmpl $0x4, %r15d
movl %edi, 0x8(%rsp)
movl %r12d, 0x4(%rsp)
movl %ecx, 0xc(%rsp)
jg 0xb8de
movl %edx, %edi
movl %ecx, %esi
movq %r14, 0x10(%rsp)
movl %r13d, %r14d
movl %r15d, %r13d
movq %rbx, %r15
movq %rbp, %rbx
movl %edx, %ebp
callq 0x75ec
movl 0x8(%rsp), %edi
movl %ebp, %edx
movq %rbx, %rbp
movq %r15, %rbx
movl %r13d, %r15d
movl %r14d, %r13d
movq 0x10(%rsp), %r14
cmpl $0x27, %r12d
jg 0xb9b1
cmpl $0x1, %eax
jg 0xb9b1
movl %r13d, %eax
andl $-0x8, %eax
xorl %r12d, %r12d
cmpl $0x28, %eax
je 0xbbe1
cmpl $0x2, %r15d
jg 0xb9b1
movl %edi, %eax
andl $-0x8, %eax
cmpl $0x28, %eax
jne 0xbbe1
jmp 0xb9b1
cmpl $0x5, %r15d
jne 0xb95b
movl %edx, %edi
movl %ecx, %esi
movq %r14, 0x10(%rsp)
movl %r13d, %r14d
movl %r15d, %r13d
movq %rbx, %r15
movq %rbp, %rbx
movl %edx, %ebp
callq 0x75ec
movl 0x8(%rsp), %edi
movl %ebp, %edx
movq %rbx, %rbp
movq %r15, %rbx
movl %r13d, %r15d
movl %r14d, %r13d
movq 0x10(%rsp), %r14
movl 0xc(%rsp), %ecx
cmpl $0x1, %eax
jg 0xb95b
movl %r12d, %eax
sarl $0x3, %eax
addl 0x1c(%rsp), %eax
cmpl $0x5, %eax
jg 0xb95b
xorl %r12d, %r12d
cmpl $0x8, %r13d
jb 0xbbe1
cmpl %ebp, 0x20(%rsp)
je 0xb9b1
movl %r13d, %eax
andl $0x7, %eax
subl %ebx, %eax
movl %eax, %ecx
negl %ecx
cmovsl %eax, %ecx
cmpl $0x2, %ecx
jbe 0xb9b1
jmp 0xbbe1
cmpl %ecx, %edx
jne 0xb9b1
cmpl $0x7, %r13d
ja 0xb9b1
xorl %r12d, %r12d
cmpl %ebp, 0x20(%rsp)
jne 0xbbe1
movl 0x4(%rsp), %edi
movl %r14d, %esi
movq %r14, 0x10(%rsp)
movl %r13d, %r14d
movl %r15d, %r13d
movq %rbx, %r15
movq %rbp, %rbx
movl %edx, %ebp
callq 0x75ec
movl 0x8(%rsp), %edi
movl %ebp, %edx
movq %rbx, %rbp
movq %r15, %rbx
movl %r13d, %r15d
movl %r14d, %r13d
movq 0x10(%rsp), %r14
cmpl $0x1, %eax
jg 0xbbe1
movl %edx, %eax
andl $-0x2, %eax
cmpl $0x36, %eax
jne 0xb9fb
cmpl $0x30, %r14d
jne 0xb9fb
cmpl $0x38, %edi
jne 0xb9fb
testb $0x7, %r13b
jne 0xbbdb
xorl %r12d, %r12d
cmpl $0x11, %r13d
jl 0xbbe1
movl 0x4(%rsp), %eax
cmpl $0x28, %eax
jl 0xbbe1
andl $0x7, %eax
cmpl $0x2, %eax
jbe 0xbbdb
jmp 0xbbe1
cmpl $0x4, %r15d
jg 0xba58
leal 0x8(%r14), %eax
cmpl %eax, %edx
jne 0xba4b
movl 0x4(%rsp), %edi
movl %r14d, %esi
movl %edx, %r12d
callq 0x75ec
movl 0x8(%rsp), %edi
movl %r12d, %edx
subl 0x1c(%rsp), %eax
cmpl $0x2, %eax
jl 0xba4b
movl 0x4(%rsp), %edi
movl %r13d, %esi
callq 0x75ec
movl 0x8(%rsp), %edi
movl %r12d, %edx
subl 0x1c(%rsp), %eax
xorl %r12d, %r12d
cmpl $0x1, %eax
jg 0xbbe1
testl %ebx, %ebx
jne 0xbb15
jmp 0xbc4f
cmpl $0x6, %r15d
setne %al
testl %ebx, %ebx
sete %cl
orb %al, %cl
jne 0xbb0d
movl %edi, %eax
andl $0x7, %eax
cmpl %ebx, %eax
jne 0xbb15
cmpl 0xc(%rsp), %edi
je 0xbb15
xorl %r13d, %r13d
cmpl %ebp, 0x20(%rsp)
sete %r13b
movl 0x4(%rsp), %edi
movq %rbp, 0x10(%rsp)
movl 0xc(%rsp), %ebp
movl %ebp, %esi
movl %edx, %r12d
callq 0x75ec
movl %eax, 0x24(%rsp)
movl %r12d, %edi
movl %ebp, %esi
movq 0x10(%rsp), %rbp
callq 0x75ec
movl 0x8(%rsp), %edi
movl %r12d, %edx
orl $-0x2, %r13d
addl %eax, %r13d
cmpl %r13d, 0x24(%rsp)
jge 0xbb15
movl 0x4(%rsp), %edi
movl 0xc(%rsp), %esi
callq 0x75ec
movl %eax, %r13d
movl %r12d, %edi
movl 0x8(%rsp), %esi
callq 0x75ec
movl 0x8(%rsp), %edi
movl %r12d, %edx
addl 0x1c(%rsp), %eax
cmpl %eax, %r13d
jge 0xbb15
movl 0x4(%rsp), %edi
movl 0xc(%rsp), %esi
callq 0x75ec
addl %eax, %eax
jmp 0xbbd0
testl %ebx, %ebx
je 0xbbdb
cmpl %r14d, %edi
jge 0xbc4f
movl %edi, %eax
andl $0x7, %eax
cmpl %ebx, %eax
jne 0xbc4f
xorl %r13d, %r13d
cmpl %ebp, 0x20(%rsp)
sete %r13b
movl 0x4(%rsp), %edi
movl 0xc(%rsp), %ebp
movl %ebp, %esi
movl %edx, 0x10(%rsp)
callq 0x75ec
movl %eax, %r12d
movl 0x10(%rsp), %edi
movl %ebp, %esi
callq 0x75ec
movl 0x10(%rsp), %edx
orl $-0x2, %r13d
addl %r13d, %eax
cmpl %eax, %r12d
jge 0xbc4f
leal 0x8(%r14), %ebp
movl 0x4(%rsp), %edi
movl %ebp, %esi
callq 0x75ec
movl %eax, %r12d
movl 0x10(%rsp), %edi
movl %ebp, %esi
callq 0x75ec
movl 0x8(%rsp), %esi
movl 0x10(%rsp), %edx
addl %eax, %r13d
cmpl %r13d, %r12d
jge 0xbc4f
movl %edx, %edi
callq 0x75ec
addl 0x1c(%rsp), %eax
cmpl $0x2, %eax
jle 0xbbf3
movl %r14d, %edi
movl 0xc(%rsp), %ebx
movl %ebx, %esi
callq 0x75ec
movl %eax, %r14d
movl 0x4(%rsp), %edi
movl %ebx, %esi
callq 0x75ec
shll $0x3, %r14d
leal (%r14,%rax,2), %eax
movl $0x80, %r12d
jmp 0xbca6
movl $0xff, %r12d
movl %r12d, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl 0x4(%rsp), %edi
movl 0xc(%rsp), %esi
callq 0x75ec
movl %eax, %r13d
movl 0x10(%rsp), %edi
movl 0x8(%rsp), %esi
callq 0x75ec
movl 0x8(%rsp), %ecx
movl 0x10(%rsp), %edx
addl 0x1c(%rsp), %eax
cmpl %eax, %r13d
jge 0xbc4f
movl 0x4(%rsp), %edi
movl %ebp, %esi
movl %ecx, %r13d
callq 0x75ec
movl %eax, %r12d
movl 0x10(%rsp), %edi
movl %r13d, %esi
callq 0x75ec
movl 0x10(%rsp), %edx
addl 0x1c(%rsp), %eax
cmpl %eax, %r12d
jl 0xbbac
movl $0xff, %r12d
cmpl %r14d, %edx
jle 0xbbe1
cmpl $0x3, %r15d
jg 0xbbe1
movl %edx, %eax
andl $0x7, %eax
subl %ebx, %eax
jne 0xbc72
pushq $0xa
popq %r12
jmp 0xbbe1
incl %eax
testl $0xfffffffd, %eax       # imm = 0xFFFFFFFD
jne 0xbbe1
movl 0x4(%rsp), %edi
movl %edx, %esi
movl %edx, %ebx
callq 0x75ec
cmpl $0x3, %eax
jl 0xbbe1
movl %ebx, %esi
movl 0x4(%rsp), %edi
callq 0x75ec
addl %eax, %eax
pushq $0x18
popq %r12
subl %eax, %r12d
jmp 0xbbe1