// File: ATOMIC-LICHESS[P]ATOMKRAFT/endgame.cpp
// Function: Endgame<Value, (EndgameType)3>::apply(Position const&) const
Value Endgame<Value, KRKP>::apply(const Position& pos) const {

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

  Square wksq, wrsq, bksq, bpsq;
  int tempo = (pos.side_to_move() == strongerSide);

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

  if (strongerSide == BLACK)
  {
      wksq = flip_square(wksq);
      wrsq = flip_square(wrsq);
      bksq = flip_square(bksq);
      bpsq = flip_square(bpsq);
  }

  Square queeningSq = make_square(square_file(bpsq), RANK_1);
  Value result;

  // If the stronger side's king is in front of the pawn, it's a win
  if (wksq < bpsq && square_file(wksq) == square_file(bpsq))
      result = RookValueEndgame - Value(square_distance(wksq, bpsq));

  // If the weaker side's king is too far from the pawn and the rook,
  // it's a win
  else if (   square_distance(bksq, bpsq) - (tempo ^ 1) >= 3
           && square_distance(bksq, wrsq) >= 3)
      result = RookValueEndgame - Value(square_distance(wksq, bpsq));

  // If the pawn is far advanced and supported by the defending king,
  // the position is drawish
  else if (   square_rank(bksq) <= RANK_3
           && square_distance(bksq, bpsq) == 1
           && square_rank(wksq) >= RANK_4
           && square_distance(wksq, bpsq) - tempo > 2)
      result = Value(80 - square_distance(wksq, bpsq) * 8);

  else
      result =  Value(200)
              - Value(square_distance(wksq, bpsq + DELTA_S) * 8)
              + Value(square_distance(bksq, bpsq + DELTA_S) * 8)
              + Value(square_distance(bpsq, queeningSq) * 8);

  return strongerSide == pos.side_to_move() ? result : -result;
}

// Assembly:
subq $0x68, %rsp
movq %rdi, 0x60(%rsp)
movq %rsi, 0x58(%rsp)
movq 0x60(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x58(%rsp), %rdi
callq 0xf5d0
movl %eax, %ecx
movq 0x30(%rsp), %rax
cmpl 0x8(%rax), %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %ecx
movl %ecx, 0x44(%rsp)
movq 0x58(%rsp), %rdi
movl 0x8(%rax), %esi
callq 0x1b250
movl %eax, %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x54(%rsp)
movq 0x58(%rsp), %rdi
movl 0x8(%rax), %esi
movl $0x4, %edx
xorl %ecx, %ecx
callq 0x164f0
movl %eax, %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x50(%rsp)
movq 0x58(%rsp), %rdi
movl 0xc(%rax), %esi
callq 0x1b250
movl %eax, %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x4c(%rsp)
movq 0x58(%rsp), %rdi
movl 0xc(%rax), %esi
movl $0x1, %edx
xorl %ecx, %ecx
callq 0x164f0
movl %eax, %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x48(%rsp)
cmpl $0x1, 0x8(%rax)
jne 0x17741
movl 0x54(%rsp), %edi
callq 0x1b2f0
movl %eax, 0x54(%rsp)
movl 0x50(%rsp), %edi
callq 0x1b2f0
movl %eax, 0x50(%rsp)
movl 0x4c(%rsp), %edi
callq 0x1b2f0
movl %eax, 0x4c(%rsp)
movl 0x48(%rsp), %edi
callq 0x1b2f0
movl %eax, 0x48(%rsp)
movl 0x48(%rsp), %edi
callq 0xce10
movl %eax, %edi
xorl %esi, %esi
callq 0xd740
movl %eax, 0x40(%rsp)
movl 0x54(%rsp), %eax
cmpl 0x48(%rsp), %eax
jge 0x177af
movl 0x54(%rsp), %edi
callq 0xce10
movl %eax, 0x2c(%rsp)
movl 0x48(%rsp), %edi
callq 0xce10
movl %eax, %ecx
movl 0x2c(%rsp), %eax
cmpl %ecx, %eax
jne 0x177af
leaq 0x54dec(%rip), %rax     # 0x6c574
movl (%rax), %eax
movl %eax, 0x28(%rsp)
movl 0x54(%rsp), %edi
movl 0x48(%rsp), %esi
callq 0xcd00
movl 0x28(%rsp), %edi
movl %eax, %esi
callq 0x1b300
movl %eax, 0x3c(%rsp)
jmp 0x178fa
movl 0x4c(%rsp), %edi
movl 0x48(%rsp), %esi
callq 0xcd00
movl 0x44(%rsp), %ecx
xorl $0x1, %ecx
subl %ecx, %eax
cmpl $0x3, %eax
jl 0x1780a
movl 0x4c(%rsp), %edi
movl 0x50(%rsp), %esi
callq 0xcd00
cmpl $0x3, %eax
jl 0x1780a
leaq 0x54d91(%rip), %rax     # 0x6c574
movl (%rax), %eax
movl %eax, 0x24(%rsp)
movl 0x54(%rsp), %edi
movl 0x48(%rsp), %esi
callq 0xcd00
movl 0x24(%rsp), %edi
movl %eax, %esi
callq 0x1b300
movl %eax, 0x3c(%rsp)
jmp 0x178f8
movl 0x4c(%rsp), %edi
callq 0xce40
cmpl $0x2, %eax
jg 0x17870
movl 0x4c(%rsp), %edi
movl 0x48(%rsp), %esi
callq 0xcd00
cmpl $0x1, %eax
jne 0x17870
movl 0x54(%rsp), %edi
callq 0xce40
cmpl $0x3, %eax
jl 0x17870
movl 0x54(%rsp), %edi
movl 0x48(%rsp), %esi
callq 0xcd00
subl 0x44(%rsp), %eax
cmpl $0x2, %eax
jle 0x17870
movl 0x54(%rsp), %edi
movl 0x48(%rsp), %esi
callq 0xcd00
movl %eax, %ecx
shll $0x3, %ecx
movl $0x50, %eax
subl %ecx, %eax
movl %eax, 0x3c(%rsp)
jmp 0x178f6
movl 0x54(%rsp), %eax
movl %eax, 0x14(%rsp)
movl 0x48(%rsp), %edi
movl $0xfffffff8, %esi       # imm = 0xFFFFFFF8
callq 0xd780
movl 0x14(%rsp), %edi
movl %eax, %esi
callq 0xcd00
movl %eax, %esi
shll $0x3, %esi
movl $0xc8, %edi
callq 0x1b300
movl %eax, 0x1c(%rsp)
movl 0x4c(%rsp), %eax
movl %eax, 0x18(%rsp)
movl 0x48(%rsp), %edi
movl $0xfffffff8, %esi       # imm = 0xFFFFFFF8
callq 0xd780
movl 0x18(%rsp), %edi
movl %eax, %esi
callq 0xcd00
movl 0x1c(%rsp), %edi
movl %eax, %esi
shll $0x3, %esi
callq 0x1b320
movl %eax, 0x20(%rsp)
movl 0x48(%rsp), %edi
movl 0x40(%rsp), %esi
callq 0xcd00
movl 0x20(%rsp), %edi
movl %eax, %esi
shll $0x3, %esi
callq 0x1b320
movl %eax, 0x3c(%rsp)
jmp 0x178f8
jmp 0x178fa
movq 0x30(%rsp), %rax
movl 0x8(%rax), %eax
movl %eax, 0x10(%rsp)
movq 0x58(%rsp), %rdi
callq 0xf5d0
movl %eax, %ecx
movl 0x10(%rsp), %eax
cmpl %ecx, %eax
jne 0x17924
movl 0x3c(%rsp), %eax
movl %eax, 0xc(%rsp)
jmp 0x17931
movl 0x3c(%rsp), %edi
callq 0x1b2b0
movl %eax, 0xc(%rsp)
movl 0xc(%rsp), %eax
addq $0x68, %rsp
retq
nopw (%rax,%rax)