// File: ATOMIC-LICHESS[P]ATOMKRAFT/pawns.cpp
// Function: Score PawnInfoTable::evaluate_pawns<(Color)0>(Position const&, unsigned long, unsigned long, PawnInfo*)
Score PawnInfoTable::evaluate_pawns(const Position& pos, Bitboard ourPawns,
                                    Bitboard theirPawns, PawnInfo* pi) {

  const BitCountType Max15 = CpuIs64Bit ? CNT64_MAX15 : CNT32_MAX15;
  const Color Them = (Us == WHITE ? BLACK : WHITE);

  Bitboard b;
  Square s;
  File f;
  Rank r;
  bool passed, isolated, doubled, opposed, chain, backward, candidate;
  Score value = SCORE_ZERO;
  const Square* ptr = pos.piece_list_begin(Us, PAWN);
  
  NEW const Square opp_ksq = pos.king_square(Them);

  // Loop through all pawns of the current color and score each pawn
  while ((s = *ptr++) != SQ_NONE)
  {
      assert(pos.piece_on(s) == make_piece(Us, PAWN));

      f = square_file(s);
      r = square_rank(s);
      
      STARTNEW
      // pawn tropism
      //if (useImprovements) {
	    value += PawnTropism[square_dist(s, opp_ksq)];
      //}
      ENDNEW

      // This file cannot be half open
      pi->halfOpenFiles[Us] &= ~(1 << f);

      // Our rank plus previous one. Used for chain detection
      b = rank_bb(r) | rank_bb(Us == WHITE ? r - Rank(1) : r + Rank(1));

      // Flag the pawn as passed, isolated, doubled or member of a pawn
      // chain (but not the backward one).
      passed   = !(theirPawns & passed_pawn_mask(Us, s));
      doubled  =   ourPawns   & squares_in_front_of(Us, s);
      opposed  =   theirPawns & squares_in_front_of(Us, s);
      isolated = !(ourPawns   & neighboring_files_bb(f));
      chain    =   ourPawns   & neighboring_files_bb(f) & b;

      // Test for backward pawn
      backward = false;

      // If the pawn is passed, isolated, or member of a pawn chain it cannot
      // be backward. If there are friendly pawns behind on neighboring files
      // or if can capture an enemy pawn it cannot be backward either.
      if (   !(passed | isolated | chain)
          && !(ourPawns & attack_span_mask(Them, s))
          && !(pos.attacks_from<PAWN>(s, Us) & theirPawns))
      {
          // We now know that there are no friendly pawns beside or behind this
          // pawn on neighboring files. We now check whether the pawn is
          // backward by looking in the forward direction on the neighboring
          // files, and seeing whether we meet a friendly or an enemy pawn first.
          b = pos.attacks_from<PAWN>(s, Us);

          // Note that we are sure to find something because pawn is not passed
          // nor isolated, so loop is potentially infinite, but it isn't.
          while (!(b & (ourPawns | theirPawns)))
              Us == WHITE ? b <<= 8 : b >>= 8;

          // The friendly pawn needs to be at least two ranks closer than the
          // enemy pawn in order to help the potentially backward pawn advance.
          backward = (b | (Us == WHITE ? b << 8 : b >> 8)) & theirPawns;
      }

      assert(opposed | passed | (attack_span_mask(Us, s) & theirPawns));

      // A not passed pawn is a candidate to become passed if it is free to
      // advance and if the number of friendly pawns beside or behind this
      // pawn on neighboring files is higher or equal than the number of
      // enemy pawns in the forward direction on the neighboring files.
      candidate =   !(opposed | passed | backward | isolated)
                 && (b = attack_span_mask(Them, s + pawn_push(Us)) & ourPawns) != EmptyBoardBB
                 &&  count_1s<Max15>(b) >= count_1s<Max15>(attack_span_mask(Us, s) & theirPawns);

      // Passed pawns will be properly scored in evaluation because we need
      // full attack info to evaluate passed pawns. Only the frontmost passed
      // pawn on each file is considered a true passed pawn.
      if (passed && !doubled)
          set_bit(&(pi->passedPawns[Us]), s);

      // Score this pawn
      OLD if (isolated)
          value -= IsolatedPawnPenalty[opposed][f];

      OLD if (doubled)
          value -= DoubledPawnPenalty[opposed][f];

      if (backward)
          value -= BackwardPawnPenalty[opposed][f];

      OLD if (chain)
          value += ChainBonus[f];

      if (candidate) {
          OLD value += CandidateBonus[relative_rank(Us, s)];
          NEW value += 3 * CandidateBonus[relative_rank(Us, s)] / 2;
      }
  }
  return value;
}

// Assembly:
subq $0xa8, %rsp
movq %rdi, 0xa0(%rsp)
movq %rsi, 0x98(%rsp)
movq %rdx, 0x90(%rsp)
movq %rcx, 0x88(%rsp)
movl $0x3, 0x84(%rsp)
movl $0x1, 0x80(%rsp)
movl $0x0, 0x60(%rsp)
movq 0xa0(%rsp), %rdi
xorl %esi, %esi
movl $0x1, %edx
callq 0x299d0
movq %rax, 0x58(%rsp)
movq 0xa0(%rsp), %rdi
movl $0x1, %esi
callq 0x1b250
movl %eax, 0x54(%rsp)
movq 0x58(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x58(%rsp)
movl (%rax), %eax
movl %eax, 0x74(%rsp)
cmpl $0x40, %eax
je 0x350d1
movl 0x74(%rsp), %edi
callq 0xce10
movl %eax, 0x70(%rsp)
movl 0x74(%rsp), %edi
callq 0xce40
movl %eax, 0x6c(%rsp)
movl 0x74(%rsp), %edi
movl 0x54(%rsp), %esi
callq 0x1b280
movslq %eax, %rcx
leaq 0x3ae43b(%rip), %rax    # 0x3e3170
movl (%rax,%rcx,4), %esi
leaq 0x60(%rsp), %rdi
callq 0x29810
movl 0x70(%rsp), %ecx
movl $0x1, %eax
shll %cl, %eax
movl %eax, %ecx
xorl $-0x1, %ecx
movq 0x88(%rsp), %rax
andl 0x34(%rax), %ecx
movl %ecx, 0x34(%rax)
movl 0x6c(%rsp), %edi
callq 0x1b3d0
movq %rax, 0x20(%rsp)
movl 0x6c(%rsp), %edi
movl $0x1, %esi
callq 0xce20
movl %eax, %edi
callq 0x1b3d0
movq %rax, %rcx
movq 0x20(%rsp), %rax
orq %rcx, %rax
movq %rax, 0x78(%rsp)
movq 0x90(%rsp), %rax
movq %rax, 0x28(%rsp)
movl 0x74(%rsp), %esi
xorl %edi, %edi
callq 0x1bd00
movq %rax, %rcx
movq 0x28(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
setne %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, 0x6b(%rsp)
movq 0x98(%rsp), %rax
movq %rax, 0x30(%rsp)
movl 0x74(%rsp), %esi
xorl %edi, %edi
callq 0x1b520
movq %rax, %rcx
movq 0x30(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
setne %al
andb $0x1, %al
movb %al, 0x69(%rsp)
movq 0x90(%rsp), %rax
movq %rax, 0x38(%rsp)
movl 0x74(%rsp), %esi
xorl %edi, %edi
callq 0x1b520
movq %rax, %rcx
movq 0x38(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
setne %al
andb $0x1, %al
movb %al, 0x68(%rsp)
movq 0x98(%rsp), %rax
movq %rax, 0x40(%rsp)
movl 0x70(%rsp), %edi
callq 0x359d0
movq %rax, %rcx
movq 0x40(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
setne %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, 0x6a(%rsp)
movq 0x98(%rsp), %rax
movq %rax, 0x48(%rsp)
movl 0x70(%rsp), %edi
callq 0x359d0
movq %rax, %rcx
movq 0x48(%rsp), %rax
andq %rcx, %rax
andq 0x78(%rsp), %rax
cmpq $0x0, %rax
setne %al
andb $0x1, %al
movb %al, 0x67(%rsp)
movb $0x0, 0x66(%rsp)
movb 0x6b(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movb 0x6a(%rsp), %cl
andb $0x1, %cl
movzbl %cl, %ecx
orl %ecx, %eax
movb 0x67(%rsp), %cl
andb $0x1, %cl
movzbl %cl, %ecx
orl %ecx, %eax
cmpl $0x0, %eax
jne 0x34f7d
movq 0x98(%rsp), %rax
movq %rax, 0x18(%rsp)
movl 0x74(%rsp), %esi
movl $0x1, %edi
callq 0x29ee0
movq %rax, %rcx
movq 0x18(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
jne 0x34f7d
movq 0xa0(%rsp), %rdi
movl 0x74(%rsp), %esi
xorl %edx, %edx
callq 0x1b460
andq 0x90(%rsp), %rax
cmpq $0x0, %rax
jne 0x34f7d
movq 0xa0(%rsp), %rdi
movl 0x74(%rsp), %esi
xorl %edx, %edx
callq 0x1b460
movq %rax, 0x78(%rsp)
movq 0x78(%rsp), %rax
movq 0x98(%rsp), %rcx
orq 0x90(%rsp), %rcx
andq %rcx, %rax
cmpq $0x0, %rax
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x34f47
jmp 0x34f57
movq 0x78(%rsp), %rax
shlq $0x8, %rax
movq %rax, 0x78(%rsp)
jmp 0x34f20
movq 0x78(%rsp), %rax
movq 0x78(%rsp), %rcx
shlq $0x8, %rcx
orq %rcx, %rax
andq 0x90(%rsp), %rax
cmpq $0x0, %rax
setne %al
andb $0x1, %al
movb %al, 0x66(%rsp)
movb 0x68(%rsp), %al
andb $0x1, %al
movzbl %al, %ecx
movb 0x6b(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
orl %eax, %ecx
movb 0x66(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
orl %eax, %ecx
movb 0x6a(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
orl %eax, %ecx
xorl %eax, %eax
cmpl $0x0, %ecx
movb %al, 0x17(%rsp)
jne 0x3502c
movl 0x74(%rsp), %eax
movl %eax, 0x10(%rsp)
xorl %edi, %edi
callq 0x1b580
movl 0x10(%rsp), %edi
movl %eax, %esi
callq 0xd780
movl %eax, %esi
movl $0x1, %edi
callq 0x29ee0
movq %rax, %rcx
andq 0x98(%rsp), %rcx
movq %rcx, 0x78(%rsp)
xorl %eax, %eax
cmpq $0x0, %rcx
movb %al, 0x17(%rsp)
je 0x3502c
movq 0x78(%rsp), %rdi
callq 0x29a00
movl %eax, 0xc(%rsp)
movl 0x74(%rsp), %esi
xorl %edi, %edi
callq 0x29ee0
movq %rax, %rdi
andq 0x90(%rsp), %rdi
callq 0x29a00
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
setge %al
movb %al, 0x17(%rsp)
movb 0x17(%rsp), %al
andb $0x1, %al
movb %al, 0x65(%rsp)
testb $0x1, 0x6b(%rsp)
je 0x35059
testb $0x1, 0x69(%rsp)
jne 0x35059
movq 0x88(%rsp), %rdi
addq $0x8, %rdi
movl 0x74(%rsp), %esi
callq 0xe7c0
testb $0x1, 0x66(%rsp)
je 0x3508b
movb 0x68(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, %ecx
leaq 0x3ae06e(%rip), %rax    # 0x3e30e0
shlq $0x5, %rcx
addq %rcx, %rax
movslq 0x70(%rsp), %rcx
movl (%rax,%rcx,4), %esi
leaq 0x60(%rsp), %rdi
callq 0x29ae0
testb $0x1, 0x65(%rsp)
je 0x350cc
movl 0x74(%rsp), %esi
xorl %edi, %edi
callq 0x1b2c0
movslq %eax, %rcx
leaq 0x3ae099(%rip), %rax    # 0x3e3140
movl (%rax,%rcx,4), %esi
movl $0x3, %edi
callq 0x29ac0
movl %eax, %edi
movl $0x2, %esi
callq 0x28070
movl %eax, %esi
leaq 0x60(%rsp), %rdi
callq 0x29810
jmp 0x34ce4
movl 0x60(%rsp), %eax
addq $0xa8, %rsp
retq
nopl (%rax)