Stockfish 1.9 code - evaluation

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

lech
Posts: 1136
Joined: Sun Feb 14, 2010 10:02 pm

Stockfish 1.9 code - evaluation

Post by lech »

Point 1 - "updateKingTables[]" seems to be useless.
Point 2 - opposite colored bishops seems to be a material question.

1.

Code: Select all

  template<Color Us, bool HasPopCnt>
  void init_eval_info&#40;const Position& pos, EvalInfo& ei&#41; &#123;

   const Color Them = &#40;Us == WHITE ? BLACK &#58; WHITE&#41;;

   Bitboard b = ei.attackedBy&#91;Them&#93;&#91;KING&#93; = pos.attacks_from<KING>&#40;pos.king_square&#40;Them&#41;);
   ei.attackedBy&#91;Us&#93;&#91;PAWN&#93; = ei.pi->pawn_attacks&#40;Us&#41;;
   
   if ( pos.piece_count&#40;Us, QUEEN&#41;) 
    &#123;
      ei.kingZone&#91;Us&#93; = &#40;b | &#40;Us == WHITE ? b >> 8 &#58; b << 8&#41;);
      b &= ei.attackedBy&#91;Us&#93;&#91;PAWN&#93;;
      ei.kingAttackersCount&#91;Us&#93; = b ? count_1s_max_15<HasPopCnt>&#40;b&#41; / 2 &#58; 0;
    &#125;
   else
   &#123; 
     ei.kingZone&#91;Us&#93; = EmptyBoardBB;
     ei.kingAttackersCount&#91;Us&#93; = 0;
   &#125;
&#125;

template<Color Us, bool HasPopCnt>
  Score evaluate_king&#40;const Position& pos, EvalInfo& ei, Value& margin&#41;

  // King safety. This is quite complicated, and is almost certainly far
  // from optimally tuned.
  if (  ei.kingAttackersCount&#91;Them&#93; >= 2
        && pos.non_pawn_material&#40;Us&#41; >= QueenValueMidgame + RookValueMidgame
        && ei.kingAdjacentZoneAttacksCount&#91;Them&#93;)

template<PieceType Piece, Color Us, bool HasPopCnt>
  void evaluate_pieces&#40;const Position& pos, EvalInfo& ei, Bitboard no_mob_area&#41;
  
// King attacks
        if &#40;b & ei.kingZone&#91;Us&#93;) 
// next lines are omitted if  ei.kingZone&#91;Us&#93;  =  EmptyBoardBB;
2.

Code: Select all

MaterialInfo* MaterialInfoTable&#58;&#58;get_material_info&#40;const Position& pos&#41;

// Compute the space weight
--
// Check for opposite colored bishop endgames
if &#40;pos.opposite_colored_bishops&#40;)) // moved from evaluate.cpp and changed
  &#123;
      ScaleFactor sf;

    // Only the two bishops ?
    if &#40;pos.non_pawn_material&#40;WHITE&#41; == BishopValueMidgame
      && pos.non_pawn_material&#40;BLACK&#41; == BishopValueMidgame
      && pos.piece_count&#40;WHITE, PAWN&#41; + pos.piece_count&#40;BLACK, PAWN&#41; == 1&#41; 
      sf = ScaleFactor&#40;8&#41;;
    else
    &#123; 
      // the closer only B+B endgame the beter 
      Value sfx = Value&#40; 2 * BishopValueMidgame * 32 
              / int&#40;pos.non_pawn_material&#40;WHITE&#41; + pos.non_pawn_material&#40;BLACK&#41;)); 
      sf = ScaleFactor&#40;SCALE_FACTOR_NORMAL - sfx&#41;; 
    &#125;
    mi->factor&#91;WHITE&#93; = sf;
    mi->factor&#91;BLACK&#93; = sf;
 &#125;
// Evaluate the material balance
By the way:
Why is ?
// Evaluate space for both sides, only in middle-game.
if (phase > PHASE_ENDGAME && mi->space_weight() > 0)
and not:
// Evaluate space for both sides, only in middle-game.
if (mi->space_weight() > 0)
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Stockfish 1.9 code - evaluation

Post by mcostalba »

lech wrote:Point 1 - "updateKingTables[]" seems to be useless.
It is used by this microptimization:

Code: Select all

// King attacks
if &#40;ei.updateKingTables&#91;Us&#93; && &#40;b & ei.kingZone&#91;Us&#93;))
Seems silly but in 32 bit is faster then just:

Code: Select all

// King attacks
if &#40;b & ei.kingZone&#91;Us&#93;)
Anyhow your code is good because shows that ei.kingZone[] initialization could be skipped when king safety is not later evaluated.
lech wrote: Point 2 - opposite colored bishops seems to be a material question.
Yes, correct. Good catch !

lech wrote: By the way:
Why is ?
// Evaluate space for both sides, only in middle-game.
if (phase > PHASE_ENDGAME && mi->space_weight() > 0)
and not:
// Evaluate space for both sides, only in middle-game.
if (mi->space_weight() > 0)
Another good point ;-) Thanks !
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Stockfish 1.9 code - evaluation

Post by mcostalba »

mcostalba wrote:
lech wrote: Point 2 - opposite colored bishops seems to be a material question.
Yes, correct. Good catch !
After a second thought I realized is not correct.

Currently material evaluation is not able to differentiate between two opposite colored bishops and two same colored bishops: are always counted as 2 and material hash key is always the same.

So currently we need to perform this test in full position evaluation.
lech
Posts: 1136
Joined: Sun Feb 14, 2010 10:02 pm

Re: Stockfish 1.9 code - evaluation

Post by lech »

It is a pity :(

Let me defend or explain the first point.
It is based on version 1.8 for which it was prepared and it was a serious :D optimization.
The correct code is below.
The memset() function is removed in 1.9.

1.

Code: Select all


template<bool HasPopCnt>
 Value do_evaluate&#40;const Position& pos, EvalInfo& ei&#41; &#123;

  memset&#40;&ei, 0, sizeof&#40;EvalInfo&#41;); // added
  
template<Color Us, bool HasPopCnt>
 void init_eval_info&#40;const Position& pos, EvalInfo& ei&#41; &#123;

   const Color Them = &#40;Us == WHITE ? BLACK &#58; WHITE&#41;;

   Bitboard b = ei.attackedBy&#91;Them&#93;&#91;KING&#93; = pos.attacks_from<KING>&#40;pos.king_square&#40;Them&#41;);
   ei.attackedBy&#91;Us&#93;&#91;PAWN&#93; = ei.pi->pawn_attacks&#40;Us&#41;;
   
   if ( pos.piece_count&#40;Us, QUEEN&#41;) 
    &#123;
      ei.kingZone&#91;Us&#93; = &#40;b | &#40;Us == WHITE ? b >> 8 &#58; b << 8&#41;);
      b &= ei.attackedBy&#91;Us&#93;&#91;PAWN&#93;;
      if &#40;b&#41; 
        ei.kingAttackersCount&#91;Us&#93; = count_1s_max_15<HasPopCnt>&#40;b&#41; / 2;
    &#125;   
&#125;

template<Color Us, bool HasPopCnt>
  Score evaluate_king&#40;const Position& pos, EvalInfo& ei, Value& margin&#41;

  // King safety. This is quite complicated, and is almost certainly far
  // from optimally tuned.
  if (  ei.kingAttackersCount&#91;Them&#93; >= 2
        && pos.non_pawn_material&#40;Them&#41; >= QueenValueMidgame + RookValueMidgame
        && ei.kingAdjacentZoneAttacksCount&#91;Them&#93;)

template<PieceType Piece, Color Us, bool HasPopCnt>
  void evaluate_pieces&#40;const Position& pos, EvalInfo& ei, Bitboard no_mob_area&#41;
  
// King attacks
        if &#40;b & ei.kingZone&#91;Us&#93;) 
// next lines are omitted if  ei.kingZone&#91;Us&#93;  =  EmptyBoardBB;
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Stockfish 1.9 code - evaluation

Post by mcostalba »

lech wrote:It is a pity :(

Let me defend or explain the first point.
It is based on version 1.8 for which it was prepared and it was a serious :D optimization.
I think you are right. I have reconsidered the patch and I understood that actually is a good patch because is a semplification, so I have applied it. :-)

Thanks Marek !
benstoker
Posts: 342
Joined: Tue Jan 19, 2010 2:05 am

Re: Stockfish 1.9 code - evaluation

Post by benstoker »

mcostalba wrote:
lech wrote:It is a pity :(

Let me defend or explain the first point.
It is based on version 1.8 for which it was prepared and it was a serious :D optimization.
I think you are right. I have reconsidered the patch and I understood that actually is a good patch because is a semplification, so I have applied it. :-)

Thanks Marek !
Could you please post a diff for this, if not to inconvenient to do so? Thank you.
lech
Posts: 1136
Joined: Sun Feb 14, 2010 10:02 pm

Re: Stockfish 1.9 code - evaluation

Post by lech »

mcostalba wrote: So currently we need to perform this test in full position evaluation.
Let me believe that the long function: opposite_colored_bishops()
is not worth to develop class MaterialInfo.
If true, it seems to be good to change:
if ( phase < PHASE_MIDGAME
&& pos.opposite_colored_bishops()
&& sf == SCALE_FACTOR_NORMAL)
by e.g.:
if ( phase < Phase(64) // clear profit !
&& pos.opposite_colored_bishops()
&& sf == SCALE_FACTOR_NORMAL)

Marco, maybe you will like such a simple thing like this:
3.

Code: Select all

template<Color Us>
Score PawnInfoTable&#58;&#58;evaluate_pawns&#40;const Position& pos, Bitboard ourPawns,
                                    Bitboard theirPawns, PawnInfo* pi&#41; const
doubled = ourPawns & squares_in_front_of&#40;Us, s&#41;; // changed
// removed &#58;
// if &#40;passed && &#40;ourPawns & squares_in_front_of&#40;Us, s&#41;))
//          passed = false;
if &#40;passed && !doubled&#41; // changed
          set_bit&#40;&&#40;pi->passedPawns&#91;Us&#93;), s&#41;;
Or more complex:
The original important function: bool Position::move_attacks_square(Move m, Square s) const
works in that way:
[d]8/8/8/1P4R1/6Q1/8/8/8 w - -
The move Rh5 (square = b5) returns true, and the move Qh5 false.
I hope that 5 corrects it.
5.

Code: Select all

bool Position&#58;&#58;move_attacks_square&#40;Move m, Square s&#41; const

assert&#40;move_is_ok&#40;m&#41;);
assert&#40;square_is_ok&#40;s&#41;);

Square f = move_from&#40;m&#41;, t = move_to&#40;m&#41;;
assert&#40;square_is_occupied&#40;f&#41;);

Bitboard b;
Bitboard occ = occupied_squares&#40;);
Color us = color_of_piece_on&#40;f&#41;;

if &#40;piece_is_slider&#40;piece_on&#40;f&#41;))
&#123;
  PieceType pt = type_of_piece_on&#40;f&#41;;
  if &#40;pt == QUEEN || pt == ROOK&#41;
  &#123;
    b = rook_attacks_bb&#40;s, occ & ~pieces&#40;QUEEN, ROOK, us&#41;); 
    if &#40;bit_is_set&#40;b, t&#41; && !bit_is_set&#40;b, f&#41;) return true;
  &#125;
  if &#40;pt == QUEEN || pt == BISHOP&#41;
  &#123;
    b = bishop_attacks_bb&#40;s, occ & ~pieces&#40;QUEEN, BISHOP, us&#41;); 
    if &#40;bit_is_set&#40;b, t&#41; && !bit_is_set&#40;b, f&#41;) return true;
  &#125;
&#125;
else
&#123;
b = attacks_from&#40;piece_on&#40;f&#41;, s&#41;; 
if &#40;bit_is_set&#40;b, t&#41;) return true;
&#125;
// Move the piece and scan for X-ray attacks behind it
clear_bit&#40;&occ, f&#41;;

// removed useless&#58; set_bit&#40;&occ, t&#41;;

b = ( &#40;rook_attacks_bb&#40;s, occ&#41; &  pieces&#40;ROOK, QUEEN&#41;)
    |&#40;bishop_attacks_bb&#40;s, occ&#41; & pieces&#40;BISHOP, QUEEN&#41;)) & pieces_of_color&#40;us&#41;; 

// If we have attacks we need to verify that are caused by our move
// and are not already existent ones.
return b && &#40;b ^ &#40;b & attacks_from<QUEEN>&#40;s&#41;)); 
&#125;
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Stockfish 1.9 code - evaluation

Post by mcostalba »

lech wrote:
mcostalba wrote: So currently we need to perform this test in full position evaluation.
Let me believe that the long function: opposite_colored_bishops()
is not worth to develop class MaterialInfo.
I have thought about that. The correct solution (no hacks!) would be to introduce another piece type so to have DARK_BISHOP and LIGHT_BISHOP instead of just BISHOP, then all comes naturally including the correct material hash key....but this is a huge change for a not clear advantage....so I am not very inclined to move in that direction.

Regrading the other proposed changes I will analyze more deeply this week end and I think I am going to test some of them ;-)

Thanks
Marco
lech
Posts: 1136
Joined: Sun Feb 14, 2010 10:02 pm

Re: Stockfish 1.9 code - evaluation

Post by lech »

mcostalba wrote: The correct solution (no hacks!)
:wink:
I understand that you reject possibility to add a level (e.g. Phase(64))
and Stockfish will be test opposite bishops on such a high level of material. :?
How to name it? Speculation? :lol:
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Stockfish 1.9 code - evaluation

Post by mcostalba »

lech wrote:
mcostalba wrote: The correct solution (no hacks!)
:wink:
I understand that you reject possibility to add a level (e.g. Phase(64))
and Stockfish will be test opposite bishops on such a high level of material. :?
How to name it? Speculation? :lol:
No, this is a good idea and I will test it.

What I don't plan to do is to move opposite bishops evaluation from evaluate() to material.