Stockfish 1.9 code - evaluation

Discussion of chess software programming and technical issues.

Moderator: Ras

lech
Posts: 1169
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(const Position& pos, EvalInfo& ei) {

   const Color Them = (Us == WHITE ? BLACK : WHITE);

   Bitboard b = ei.attackedBy[Them][KING] = pos.attacks_from<KING>(pos.king_square(Them));
   ei.attackedBy[Us][PAWN] = ei.pi->pawn_attacks(Us);
   
   if ( pos.piece_count(Us, QUEEN)) 
    {
      ei.kingZone[Us] = (b | (Us == WHITE ? b >> 8 : b << 8));
      b &= ei.attackedBy[Us][PAWN];
      ei.kingAttackersCount[Us] = b ? count_1s_max_15<HasPopCnt>(b) / 2 : 0;
    }
   else
   { 
     ei.kingZone[Us] = EmptyBoardBB;
     ei.kingAttackersCount[Us] = 0;
   }
}

template<Color Us, bool HasPopCnt>
  Score evaluate_king(const Position& pos, EvalInfo& ei, Value& margin)

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

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

Code: Select all

MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos)

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

    // Only the two bishops ?
    if (pos.non_pawn_material(WHITE) == BishopValueMidgame
      && pos.non_pawn_material(BLACK) == BishopValueMidgame
      && pos.piece_count(WHITE, PAWN) + pos.piece_count(BLACK, PAWN) == 1) 
      sf = ScaleFactor(8);
    else
    { 
      // the closer only B+B endgame the beter 
      Value sfx = Value( 2 * BishopValueMidgame * 32 
              / int(pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK))); 
      sf = ScaleFactor(SCALE_FACTOR_NORMAL - sfx); 
    }
    mi->factor[WHITE] = sf;
    mi->factor[BLACK] = sf;
 }
// 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 (ei.updateKingTables[Us] && (b & ei.kingZone[Us]))
Seems silly but in 32 bit is faster then just:

Code: Select all

// King attacks
if (b & ei.kingZone[Us])
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: 1169
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(const Position& pos, EvalInfo& ei) {

  memset(&ei, 0, sizeof(EvalInfo)); // added
  
template<Color Us, bool HasPopCnt>
 void init_eval_info(const Position& pos, EvalInfo& ei) {

   const Color Them = (Us == WHITE ? BLACK : WHITE);

   Bitboard b = ei.attackedBy[Them][KING] = pos.attacks_from<KING>(pos.king_square(Them));
   ei.attackedBy[Us][PAWN] = ei.pi->pawn_attacks(Us);
   
   if ( pos.piece_count(Us, QUEEN)) 
    {
      ei.kingZone[Us] = (b | (Us == WHITE ? b >> 8 : b << 8));
      b &= ei.attackedBy[Us][PAWN];
      if (b) 
        ei.kingAttackersCount[Us] = count_1s_max_15<HasPopCnt>(b) / 2;
    }   
}

template<Color Us, bool HasPopCnt>
  Score evaluate_king(const Position& pos, EvalInfo& ei, Value& margin)

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

template<PieceType Piece, Color Us, bool HasPopCnt>
  void evaluate_pieces(const Position& pos, EvalInfo& ei, Bitboard no_mob_area)
  
// King attacks
        if (b & ei.kingZone[Us]) 
// next lines are omitted if  ei.kingZone[Us]  =  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: 1169
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::evaluate_pawns(const Position& pos, Bitboard ourPawns,
                                    Bitboard theirPawns, PawnInfo* pi) const
doubled = ourPawns & squares_in_front_of(Us, s); // changed
// removed :
// if (passed && (ourPawns & squares_in_front_of(Us, s)))
//          passed = false;
if (passed && !doubled) // changed
          set_bit(&(pi->passedPawns[Us]), s);
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::move_attacks_square(Move m, Square s) const

assert(move_is_ok(m));
assert(square_is_ok(s));

Square f = move_from(m), t = move_to(m);
assert(square_is_occupied(f));

Bitboard b;
Bitboard occ = occupied_squares();
Color us = color_of_piece_on(f);

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

// removed useless: set_bit(&occ, t);

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

// If we have attacks we need to verify that are caused by our move
// and are not already existent ones.
return b && (b ^ (b & attacks_from<QUEEN>(s))); 
}
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: 1169
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.