// File: /workspace/github_cpp_makefile_star2_O1/ATOMIC-LICHESS[P]ATOMKRAFT/pawns.cpp
// Function: Score PawnInfoTable::evaluate_pawns<(Color)1>(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
movq %rcx, -0x18(%rsp)
movl 0x3d0(%rdi), %ebx
xorl %eax, %eax
cmpl $0x40, %ebx
je 0x1c02b
movslq 0x310(%rdi), %rax
movq %rax, -0x10(%rsp)
addq $0x3d4, %rdi            # imm = 0x3D4
movq %rdx, %rcx
orq %rsi, %rcx
movq -0x18(%rsp), %rax
movl 0x38(%rax), %r10d
xorl %eax, %eax
leaq 0x1071bd(%rip), %rbp    # 0x122f50
movdqa 0x15bf5(%rip), %xmm0    # 0x31990
movdqa 0x15bfd(%rip), %xmm1    # 0x319a0
movdqa 0x15c05(%rip), %xmm2    # 0x319b0
movl %ebx, %r15d
andl $0x7, %r15d
movslq %ebx, %r12
sarl $0x3, %ebx
movq %r12, %r8
shlq $0x6, %r8
addq 0x201d2(%rip), %r8      # 0x3bf98
movq -0x10(%rsp), %r9
movsbq (%r9,%r8), %r8
leaq 0x3971e9(%rip), %r9     # 0x3b2fc0
addl (%r9,%r8,4), %eax
btrl %r15d, %r10d
movq -0x18(%rsp), %r8
movl %r10d, 0x38(%r8)
leaq 0xfc861(%rip), %r8      # 0x118650
movq (%r8,%r15,8), %r9
xorl %r11d, %r11d
leaq 0x106d53(%rip), %r8     # 0x122b50
movq 0x200(%r8,%r12,8), %r13
andq %rdx, %r13
je 0x1be59
movq %r9, %r8
andq %rsi, %r8
je 0x1be59
movslq %ebx, %r14
movq %r9, -0x8(%rsp)
leaq 0xfc7ef(%rip), %r11     # 0x118610
movq 0x8(%r11,%r14,8), %r9
orq (%r11,%r14,8), %r9
xorl %r11d, %r11d
andq %r8, %r9
movq -0x8(%rsp), %r9
jne 0x1be59
testq %rsi, (%rbp,%r12,8)
jne 0x1be56
leaq 0xfc90b(%rip), %r8      # 0x118750
movq 0x1200(%r8,%r12,8), %r8
testq %rdx, %r8
je 0x1bf55
xorl %r11d, %r11d
leaq 0x1068f0(%rip), %r8     # 0x122750
movq 0x200(%r8,%r12,8), %r14
xorl %r8d, %r8d
testq %rsi, %r9
je 0x1bf7a
testq %r13, %r13
je 0x1bf7a
movq %r14, %r9
andq %rdx, %r9
jne 0x1bf7a
testb %r11b, %r11b
jne 0x1bf7a
movq -0x40(%rbp,%r12,8), %r8
andq %rsi, %r8
je 0x1bf77
movq 0x200(%rbp,%r12,8), %r9
andq %rdx, %r9
movq %r9, %xmm3
movq %r8, %xmm4
punpcklqdq %xmm3, %xmm4    # xmm4 = xmm4[0],xmm3[0]
movdqa %xmm4, %xmm3
psrlq $0x20, %xmm3
pshufd $0xe8, %xmm3, %xmm3     # xmm3 = xmm3[0,2,2,3]
pshufd $0xe8, %xmm4, %xmm5     # xmm5 = xmm4[0,2,2,3]
movdqa %xmm5, %xmm6
psrld $0x1, %xmm6
pand %xmm0, %xmm6
psubd %xmm6, %xmm5
psrlq $0x21, %xmm4
pshufd $0xe8, %xmm4, %xmm4     # xmm4 = xmm4[0,2,2,3]
pand %xmm0, %xmm4
psubd %xmm4, %xmm3
movdqa %xmm5, %xmm4
psrld $0x2, %xmm4
pand %xmm1, %xmm4
pand %xmm1, %xmm5
movdqa %xmm3, %xmm6
psrld $0x2, %xmm6
pand %xmm1, %xmm6
pand %xmm1, %xmm3
paddd %xmm5, %xmm3
paddd %xmm4, %xmm3
paddd %xmm6, %xmm3
pshufd $0xf5, %xmm3, %xmm4     # xmm4 = xmm3[1,1,3,3]
pmuludq %xmm2, %xmm3
pshufd $0xe8, %xmm3, %xmm3     # xmm3 = xmm3[0,2,2,3]
pmuludq %xmm2, %xmm4
pshufd $0xe8, %xmm4, %xmm4     # xmm4 = xmm4[0,2,2,3]
punpckldq %xmm4, %xmm3    # xmm3 = xmm3[0],xmm4[0],xmm3[1],xmm4[1]
psrld $0x1c, %xmm3
movd %xmm3, %r8d
pshufd $0x55, %xmm3, %xmm3     # xmm3 = xmm3[1,1,1,1]
movd %xmm3, %r9d
cmpl %r9d, %r8d
setae %r8b
jmp 0x1bf7a
movq %r8, %r14
shrq $0x8, %r8
testq %rcx, %r14
je 0x1bf55
movq %r14, %r8
shrq $0x8, %r8
orq %r14, %r8
testq %rdx, %r8
setne %r11b
jmp 0x1be59
xorl %r8d, %r8d
movq %r14, %r9
andq %rsi, %r9
orq %r13, %r9
jne 0x1bf9f
leaq 0xfc214(%rip), %r9      # 0x1181a0
movq (%r9,%r12,8), %r9
movl %r11d, %r12d
movq -0x18(%rsp), %r11
orq %r9, 0x10(%r11)
movl %r12d, %r11d
testb %r11b, %r11b
je 0x1bfc0
xorl %r9d, %r9d
testq %rdx, %r14
setne %r9b
shll $0x5, %r9d
leaq 0x396f77(%rip), %r11    # 0x3b2f30
addq %r11, %r9
subl (%r9,%r15,4), %eax
testb %r8b, %r8b
je 0x1c01c
xorl $0x7, %ebx
movslq %ebx, %r8
leaq 0x396fbe(%rip), %r9     # 0x3b2f90
movl (%r9,%r8,4), %r8d
leal (%r8,%r8,2), %r8d
movl $0x8000, %ebx           # imm = 0x8000
leal (%r8,%rbx), %r9d
movl %r9d, %r11d
sarl $0x10, %r11d
shrl $0x1f, %r9d
addl %r11d, %r9d
movl %r8d, %r11d
andl $0x7fff, %r11d          # imm = 0x7FFF
andl %ebx, %r8d
subl %r8d, %r11d
movl %r11d, %r8d
shrl $0x1f, %r8d
addl %r11d, %r8d
sarl %r8d
andl $-0x2, %r9d
shll $0xf, %r9d
addl %r8d, %r9d
addl %r9d, %eax
movl (%rdi), %ebx
addq $0x4, %rdi
cmpl $0x40, %ebx
jne 0x1bdab
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq