// File: ATOMIC-LICHESS[P]ATOMKRAFT/endgame.cpp
// Function: Endgame<ScaleFactor, (EndgameType)16>::apply(Position const&) const
ScaleFactor Endgame<ScaleFactor, KBPPKB>::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) == 2);
  assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
  assert(pos.piece_count(weakerSide, BISHOP) == 1);
  assert(pos.piece_count(weakerSide, PAWN) == 0);

  Square wbsq = pos.piece_list(strongerSide, BISHOP, 0);
  Square bbsq = pos.piece_list(weakerSide, BISHOP, 0);

  if (!opposite_color_squares(wbsq, bbsq))
      return SCALE_FACTOR_NONE;

  Square ksq = pos.king_square(weakerSide);
  Square psq1 = pos.piece_list(strongerSide, PAWN, 0);
  Square psq2 = pos.piece_list(strongerSide, PAWN, 1);
  Rank r1 = square_rank(psq1);
  Rank r2 = square_rank(psq2);
  Square blockSq1, blockSq2;

  if (relative_rank(strongerSide, psq1) > relative_rank(strongerSide, psq2))
  {
      blockSq1 = psq1 + pawn_push(strongerSide);
      blockSq2 = make_square(square_file(psq2), square_rank(psq1));
  }
  else
  {
      blockSq1 = psq2 + pawn_push(strongerSide);
      blockSq2 = make_square(square_file(psq1), square_rank(psq2));
  }

  switch (file_distance(psq1, psq2))
  {
  case 0:
    // Both pawns are on the same file. Easy draw if defender firmly controls
    // some square in the frontmost pawn's path.
    if (   square_file(ksq) == square_file(blockSq1)
        && relative_rank(strongerSide, ksq) >= relative_rank(strongerSide, blockSq1)
        && opposite_color_squares(ksq, wbsq))
        return SCALE_FACTOR_ZERO;
    else
        return SCALE_FACTOR_NONE;

  case 1:
    // Pawns on neighboring files. Draw if defender firmly controls the square
    // in front of the frontmost pawn's path, and the square diagonally behind
    // this square on the file of the other pawn.
    if (   ksq == blockSq1
        && opposite_color_squares(ksq, wbsq)
        && (   bbsq == blockSq2
            || (pos.attacks_from<BISHOP>(blockSq2) & pos.pieces(BISHOP, weakerSide))
            || abs(r1 - r2) >= 2))
        return SCALE_FACTOR_ZERO;

    else if (   ksq == blockSq2
             && opposite_color_squares(ksq, wbsq)
             && (   bbsq == blockSq1
                 || (pos.attacks_from<BISHOP>(blockSq1) & pos.pieces(BISHOP, weakerSide))))
        return SCALE_FACTOR_ZERO;
    else
        return SCALE_FACTOR_NONE;

  default:
    // The pawns are not on the same file or adjacent files. No scaling.
    return SCALE_FACTOR_NONE;
  }
}

// Assembly:
subq $0x78, %rsp
movq %rdi, 0x68(%rsp)
movq %rsi, 0x60(%rsp)
movq 0x68(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x60(%rsp), %rdi
movl 0x8(%rax), %esi
movl $0x3, %edx
xorl %ecx, %ecx
callq 0x164f0
movl %eax, %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x5c(%rsp)
movq 0x60(%rsp), %rdi
movl 0xc(%rax), %esi
movl $0x3, %edx
xorl %ecx, %ecx
callq 0x164f0
movl %eax, 0x58(%rsp)
movl 0x5c(%rsp), %edi
movl 0x58(%rsp), %esi
callq 0x1b3a0
testb $0x1, %al
jne 0x189ed
movl $0xff, 0x74(%rsp)
jmp 0x18cd4
movq 0x30(%rsp), %rax
movq 0x60(%rsp), %rdi
movl 0xc(%rax), %esi
callq 0x1b250
movl %eax, %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x54(%rsp)
movq 0x60(%rsp), %rdi
movl 0x8(%rax), %esi
movl $0x1, %edx
xorl %ecx, %ecx
callq 0x164f0
movl %eax, %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x50(%rsp)
movq 0x60(%rsp), %rdi
movl 0x8(%rax), %esi
movl $0x1, %ecx
movl %ecx, %edx
callq 0x164f0
movl %eax, 0x4c(%rsp)
movl 0x50(%rsp), %edi
callq 0xce40
movl %eax, 0x48(%rsp)
movl 0x4c(%rsp), %edi
callq 0xce40
movl %eax, %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x44(%rsp)
movl 0x8(%rax), %edi
movl 0x50(%rsp), %esi
callq 0x1b2c0
movl %eax, %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x2c(%rsp)
movl 0x8(%rax), %edi
movl 0x4c(%rsp), %esi
callq 0x1b2c0
movl %eax, %ecx
movl 0x2c(%rsp), %eax
cmpl %ecx, %eax
jle 0x18ada
movq 0x30(%rsp), %rax
movl 0x50(%rsp), %ecx
movl %ecx, 0x24(%rsp)
movl 0x8(%rax), %edi
callq 0x1b580
movl 0x24(%rsp), %edi
movl %eax, %esi
callq 0xd780
movl %eax, 0x40(%rsp)
movl 0x4c(%rsp), %edi
callq 0xce10
movl %eax, 0x28(%rsp)
movl 0x50(%rsp), %edi
callq 0xce40
movl 0x28(%rsp), %edi
movl %eax, %esi
callq 0xd740
movl %eax, 0x3c(%rsp)
jmp 0x18b23
movq 0x30(%rsp), %rax
movl 0x4c(%rsp), %ecx
movl %ecx, 0x1c(%rsp)
movl 0x8(%rax), %edi
callq 0x1b580
movl 0x1c(%rsp), %edi
movl %eax, %esi
callq 0xd780
movl %eax, 0x40(%rsp)
movl 0x50(%rsp), %edi
callq 0xce10
movl %eax, 0x20(%rsp)
movl 0x4c(%rsp), %edi
callq 0xce40
movl 0x20(%rsp), %edi
movl %eax, %esi
callq 0xd740
movl %eax, 0x3c(%rsp)
movl 0x50(%rsp), %edi
movl 0x4c(%rsp), %esi
callq 0xcd70
movl %eax, %ecx
movl %ecx, 0x18(%rsp)
testl %eax, %eax
je 0x18b4e
jmp 0x18b3c
movl 0x18(%rsp), %eax
subl $0x1, %eax
je 0x18bcd
jmp 0x18ccc
movl 0x54(%rsp), %edi
callq 0xce10
movl %eax, 0x14(%rsp)
movl 0x40(%rsp), %edi
callq 0xce10
movl %eax, %ecx
movl 0x14(%rsp), %eax
cmpl %ecx, %eax
jne 0x18bc0
movq 0x30(%rsp), %rax
movl 0x8(%rax), %edi
movl 0x54(%rsp), %esi
callq 0x1b2c0
movl %eax, %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x10(%rsp)
movl 0x8(%rax), %edi
movl 0x40(%rsp), %esi
callq 0x1b2c0
movl %eax, %ecx
movl 0x10(%rsp), %eax
cmpl %ecx, %eax
jl 0x18bc0
movl 0x54(%rsp), %edi
movl 0x5c(%rsp), %esi
callq 0x1b3a0
testb $0x1, %al
jne 0x18bb3
jmp 0x18bc0
movl $0x0, 0x74(%rsp)
jmp 0x18cd4
movl $0xff, 0x74(%rsp)
jmp 0x18cd4
movl 0x54(%rsp), %eax
cmpl 0x40(%rsp), %eax
jne 0x18c55
movl 0x54(%rsp), %edi
movl 0x5c(%rsp), %esi
callq 0x1b3a0
testb $0x1, %al
jne 0x18bea
jmp 0x18c55
movl 0x58(%rsp), %eax
cmpl 0x3c(%rsp), %eax
je 0x18c4b
movq 0x60(%rsp), %rdi
movl 0x3c(%rsp), %esi
callq 0x1b550
movq %rax, %rcx
movq 0x30(%rsp), %rax
movq %rcx, 0x8(%rsp)
movq 0x60(%rsp), %rdi
movl 0xc(%rax), %edx
movl $0x3, %esi
callq 0x16530
movq %rax, %rcx
movq 0x8(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
jne 0x18c4b
movl 0x48(%rsp), %edi
movl 0x44(%rsp), %esi
callq 0xce20
movl %eax, %ecx
negl %ecx
cmovnsl %ecx, %eax
cmpl $0x2, %eax
jl 0x18c55
movl $0x0, 0x74(%rsp)
jmp 0x18cd4
movl 0x54(%rsp), %eax
cmpl 0x3c(%rsp), %eax
jne 0x18cc2
movl 0x54(%rsp), %edi
movl 0x5c(%rsp), %esi
callq 0x1b3a0
testb $0x1, %al
jne 0x18c72
jmp 0x18cc2
movl 0x58(%rsp), %eax
cmpl 0x40(%rsp), %eax
je 0x18cb8
movq 0x60(%rsp), %rdi
movl 0x40(%rsp), %esi
callq 0x1b550
movq %rax, %rcx
movq 0x30(%rsp), %rax
movq %rcx, (%rsp)
movq 0x60(%rsp), %rdi
movl 0xc(%rax), %edx
movl $0x3, %esi
callq 0x16530
movq %rax, %rcx
movq (%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x18cc2
movl $0x0, 0x74(%rsp)
jmp 0x18cd4
movl $0xff, 0x74(%rsp)
jmp 0x18cd4
movl $0xff, 0x74(%rsp)
movl 0x74(%rsp), %eax
addq $0x78, %rsp
retq
nopl (%rax)