// File: /workspace/github_cpp_makefile_star2_O2/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rcx, 0x18(%rsp)
movq %rdx, %rbp
movq %rdi, %r8
movslq 0x510(%rdi), %rax
movq %rax, 0x30(%rsp)
addq $0x1d0, %r8             # imm = 0x1D0
movq %rdx, %r9
orq %rsi, %r9
xorl %r10d, %r10d
leaq 0x1055e6(%rip), %rbx    # 0x11bf50
movq %rsi, 0x10(%rsp)
movq %r9, 0x8(%rsp)
movslq (%r8), %r12
cmpq $0x40, %r12
je 0x16b4c
movl %r12d, %eax
movl %eax, %r13d
andl $0x7, %r13d
movq %r12, %rcx
shlq $0x6, %rcx
addq 0x1e5ff(%rip), %rcx     # 0x34f98
movq 0x30(%rsp), %rdx
movsbq (%rdx,%rcx), %rcx
leaq 0x395616(%rip), %rdx    # 0x3abfc0
addl (%rdx,%rcx,4), %r10d
pushq $-0x2
popq %rdx
movl %r13d, %ecx
roll %cl, %edx
movq 0x18(%rsp), %rcx
andl %edx, 0x34(%rcx)
sarl $0x3, %eax
movslq %eax, %r14
movl %r13d, %eax
leaq 0xfac82(%rip), %rcx     # 0x111650
movq (%rcx,%rax,8), %rcx
xorl %r15d, %r15d
leaq 0x105174(%rip), %rax    # 0x11bb50
movq (%rax,%r12,8), %rax
andq %rbp, %rax
je 0x16a27
movq %rcx, %rdx
andq %rsi, %rdx
je 0x16a27
leaq 0xfac1c(%rip), %r11     # 0x111610
movq -0x8(%r11,%r14,8), %rdi
orq (%r11,%r14,8), %rdi
andq %rdx, %rdi
jne 0x16a27
testq %rsi, 0x200(%rbx,%r12,8)
jne 0x16a24
leaq 0xfad3d(%rip), %rdx     # 0x111750
movq 0x200(%rdx,%r12,8), %rdx
testq %rbp, %rdx
je 0x16aa9
xorl %r15d, %r15d
movq %r14, 0x20(%rsp)
leaq 0x104d1d(%rip), %rdx    # 0x11b750
movq (%rdx,%r12,8), %r14
testq %rsi, %rcx
je 0x16ac4
testq %rax, %rax
je 0x16ac4
movq %r14, %rcx
andq %rbp, %rcx
jne 0x16ac4
testb %r15b, %r15b
jne 0x16ac4
movq 0x240(%rbx,%r12,8), %rdi
andq %rsi, %rdi
je 0x16ae3
movq %r8, 0x28(%rsp)
movl %r10d, %ebx
callq 0x122c5
movl %eax, 0x4(%rsp)
leaq 0x1054d5(%rip), %rax    # 0x11bf50
movq (%rax,%r12,8), %rdi
andq %rbp, %rdi
callq 0x122c5
movl %ebx, %r10d
leaq 0x1054bf(%rip), %rbx    # 0x11bf50
movq 0x8(%rsp), %r9
movq 0x28(%rsp), %r8
movq 0x10(%rsp), %rsi
cmpl %eax, 0x4(%rsp)
setge %al
jmp 0x16ae5
movq %rdx, %rdi
shlq $0x8, %rdx
testq %r9, %rdi
je 0x16aa9
orq %rdi, %rdx
testq %rbp, %rdx
setne %r15b
jmp 0x16a27
movq %r14, %rcx
andq %rsi, %rcx
orq %rax, %rcx
jne 0x16ae3
leaq 0xfa6ca(%rip), %rax     # 0x1111a0
movq (%rax,%r12,8), %rax
movq 0x18(%rsp), %rcx
orq %rax, 0x8(%rcx)
xorl %eax, %eax
testb %r15b, %r15b
je 0x16b03
xorl %ecx, %ecx
testq %rbp, %r14
setne %cl
shll $0x5, %ecx
leaq 0x395434(%rip), %rdx    # 0x3abf30
addq %rdx, %rcx
subl (%rcx,%r13,4), %r10d
movq 0x20(%rsp), %rcx
addq $0x4, %r8
testb %al, %al
je 0x16974
leaq 0x395475(%rip), %rax    # 0x3abf90
imull $0x3, (%rax,%rcx,4), %edi
pushq $0x2
popq %rsi
movq %r8, %r14
movl %r10d, %ebx
callq 0x11d88
movl %ebx, %r10d
leaq 0x105419(%rip), %rbx    # 0x11bf50
movq 0x8(%rsp), %r9
movq %r14, %r8
movq 0x10(%rsp), %rsi
addl %eax, %r10d
jmp 0x16974
movl %r10d, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq