A link to a message in the main forum

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Lyudmil Tsvetkov
Posts: 6052
Joined: Tue Jun 12, 2012 12:41 pm

A link to a message in the main forum

Post by Lyudmil Tsvetkov »

Hi, I am just posting a link to the message in the main forum
about my humble evaluation project, as Marco suggested : http://www.talkchess.com/forum/viewtopi ... 12&t=44074

Best regards,
Ludmil
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: A link to a message in the main forum

Post by mcostalba »

Lyudmil Tsvetkov wrote:Hi, I am just posting a link to the message in the main forum
about my humble evaluation project, as Marco suggested : http://www.talkchess.com/forum/viewtopi ... 12&t=44074

Best regards,
Ludmil
This is pawn evaluation in SF (it is a very standard one and very common across engines). It is a loop across each pawn, it means each pawn is individually evaluated to get a score and the score summed to the total value.

Even if you are not a programmer perhaps you reconize somthing similar to your ideas. Remember that the lines starting with '//' are so called comments. They are free text written in natural language by the programmer as a kind of note. They are not instructions and are discarded by the computer that ignores them.

Code: Select all

  const Square* pl = pos.piece_list(Us, PAWN);

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

      f = file_of(s);
      r = rank_of(s);

      // This file cannot be half open
      e->halfOpenFiles&#91;Us&#93; &= ~&#40;1 << f&#41;;

      // Our rank plus previous one. Used for chain detection
      b = rank_bb&#40;r&#41; | rank_bb&#40;Us == WHITE ? r - Rank&#40;1&#41; &#58; r + Rank&#40;1&#41;);

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

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

          // 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 (!&#40;b & &#40;ourPawns | theirPawns&#41;))
              Us == WHITE ? b <<= 8 &#58; 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 = &#40;b | &#40;Us == WHITE ? b << 8 &#58; b >> 8&#41;) & theirPawns;
      &#125;

      assert&#40;opposed | passed | &#40;attack_span_mask&#40;Us, s&#41; & theirPawns&#41;);

      // 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 adjacent files is higher or equal than the number of
      // enemy pawns in the forward direction on the adjacent files.
      candidate =   !&#40;opposed | passed | backward | isolated&#41;
                 && &#40;b = attack_span_mask&#40;Them, s + pawn_push&#40;Us&#41;) & ourPawns&#41; != 0
                 &&  popcount<Max15>&#40;b&#41; >= popcount<Max15>&#40;attack_span_mask&#40;Us, s&#41; & theirPawns&#41;;

      // 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 &#40;passed && !doubled&#41;
          e->passedPawns&#91;Us&#93; |= s;

      // Score this pawn
      if &#40;isolated&#41;
          value -= IsolatedPawnPenalty&#91;opposed&#93;&#91;f&#93;;

      if &#40;doubled&#41;
          value -= DoubledPawnPenalty&#91;opposed&#93;&#91;f&#93;;

      if &#40;backward&#41;
          value -= BackwardPawnPenalty&#91;opposed&#93;&#91;f&#93;;

      if &#40;chain&#41;
          value += ChainBonus&#91;f&#93;;

      if &#40;candidate&#41;
          value += CandidateBonus&#91;relative_rank&#40;Us, s&#41;&#93;;
  &#125;
The tables (called arrays) DoubledPawnPenalty...CandidateBonus keep the actual stored scores that depends on file number and if file is half-open. Tables are defined like:

Code: Select all

  // Doubled pawn penalty by opposed flag and file
  const Score DoubledPawnPenalty&#91;2&#93;&#91;8&#93; = &#123;
  &#123; S&#40;13, 43&#41;, S&#40;20, 48&#41;, S&#40;23, 48&#41;, S&#40;23, 48&#41;,
    S&#40;23, 48&#41;, S&#40;23, 48&#41;, S&#40;20, 48&#41;, S&#40;13, 43&#41; &#125;,
  &#123; S&#40;13, 43&#41;, S&#40;20, 48&#41;, S&#40;23, 48&#41;, S&#40;23, 48&#41;,
    S&#40;23, 48&#41;, S&#40;23, 48&#41;, S&#40;20, 48&#41;, S&#40;13, 43&#41; &#125;&#125;;

  // Isolated pawn penalty by opposed flag and file
  const Score IsolatedPawnPenalty&#91;2&#93;&#91;8&#93; = &#123;
  &#123; S&#40;37, 45&#41;, S&#40;54, 52&#41;, S&#40;60, 52&#41;, S&#40;60, 52&#41;,
    S&#40;60, 52&#41;, S&#40;60, 52&#41;, S&#40;54, 52&#41;, S&#40;37, 45&#41; &#125;,
  &#123; S&#40;25, 30&#41;, S&#40;36, 35&#41;, S&#40;40, 35&#41;, S&#40;40, 35&#41;,
    S&#40;40, 35&#41;, S&#40;40, 35&#41;, S&#40;36, 35&#41;, S&#40;25, 30&#41; &#125;&#125;;

  // Backward pawn penalty by opposed flag and file
  const Score BackwardPawnPenalty&#91;2&#93;&#91;8&#93; = &#123;
  &#123; S&#40;30, 42&#41;, S&#40;43, 46&#41;, S&#40;49, 46&#41;, S&#40;49, 46&#41;,
    S&#40;49, 46&#41;, S&#40;49, 46&#41;, S&#40;43, 46&#41;, S&#40;30, 42&#41; &#125;,
  &#123; S&#40;20, 28&#41;, S&#40;29, 31&#41;, S&#40;33, 31&#41;, S&#40;33, 31&#41;,
    S&#40;33, 31&#41;, S&#40;33, 31&#41;, S&#40;29, 31&#41;, S&#40;20, 28&#41; &#125;&#125;;

  // Pawn chain membership bonus by file
  const Score ChainBonus&#91;8&#93; = &#123;
    S&#40;11,-1&#41;, S&#40;13,-1&#41;, S&#40;13,-1&#41;, S&#40;14,-1&#41;,
    S&#40;14,-1&#41;, S&#40;13,-1&#41;, S&#40;13,-1&#41;, S&#40;11,-1&#41;
  &#125;;

  // Candidate passed pawn bonus by rank
  const Score CandidateBonus&#91;8&#93; = &#123;
    S&#40; 0, 0&#41;, S&#40; 6, 13&#41;, S&#40;6,13&#41;, S&#40;14,29&#41;,
    S&#40;34,68&#41;, S&#40;83,166&#41;, S&#40;0, 0&#41;, S&#40; 0, 0&#41;
  &#125;;
The predefined scores like:

Code: Select all

S&#40;83,166&#41;
stores togheter a value used for midgame (83) and a value used for endgame (166). The final value is then found interpolating across the 2 values according to current game phase (interpolating code is not reported).
User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: A link to a message in the main forum

Post by lucasart »

Lyudmil Tsvetkov wrote:Hi, I am just posting a link to the message in the main forum
about my humble evaluation project, as Marco suggested : http://www.talkchess.com/forum/viewtopi ... 12&t=44074

Best regards,
Ludmil
Have you done any testing ?