Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: To bitboard or not to bitboard?

Author: Uri Blass

Date: 08:23:07 09/01/03

Go up one level in this thread


On September 01, 2003 at 10:37:41, Tord Romstad wrote:

>On September 01, 2003 at 09:56:15, Uri Blass wrote:
>
>>>Yes, that's a good start.  This is how my pawn hash table entries look
>>>at the moment (I am constantly adding new fields).
>>>
>>>typedef struct {
>>>  p_hashkey_t key;
>>>  uint8 isolated_pawns[2][4]; /* Squares of isolated pawns for both sides */
>>
>>number of isolated pawns may be more than 4 for one side because it is possible
>>that one side has more than one isolated pawn in the same file.
>>What do you do in that case?
>
>Only the frontmost isolated pawn on the file is stored in the array.  The
>penalty for this pawn will usually be bigger than for an ordinary isolated
>pawn, because it is an isolated *and* doubled pawn.
>
>>>  uint8 double_pawns[2][4];   /* Squares of doubled pawns for both sides */
>>
>>again what you do in case that white has pawns at e2,e3,e4,a2,a3.
>
>Same answer here, I only store the frontmost pawn.  I am too lazy to
>check my source code now, but if I recall correctly tripled pawns are
>considered to be two doubled pawns.  In your example, the
>double_pawns[WHITE][] array would contain the squares e4, e3 and a3.
>
>>>  uint8 backward_pawns[2][4]; /* Squares of backward pawns for both sides */
>>
>>I do not evaluate backward pawns.
>>What is your definition?
>
>I consider a pawn to be backward if *all* of the following conditions are
>satisfied:
>
>1. It is not an isolated pawn.
>2. The friendly pawns on neighboring files are not beside or behind the
>   pawn.
>3. One or more of the opponent's pawns prevent the pawn from safely
>   advancing until it is beside one of the friendly pawns.
>
>As an example, if black has pawns on e6 and f5 and no pawn on the d file,
>and white has a pawn on d4, the black pawn on e6 is a backward pawn.
>
>>>  uint8 passed_pawns[2][8];   /* Squares of passed pawns for both sides */
>>>  uint8 open_files[2];        /* Bitfields of open files for both sides */
>>
>>Do you define open file for white as file without white pawns?
>
>Yes.
>
>>>  uint8 ks_storm[2];          /* King side pawn storm eval for both sides */
>>>  uint8 qs_storm[2];          /* Queen side pawn storm eval for both sides */
>>
>>How do you evaluate king side pawn storm and queen side pawn storm based on pawn
>>structure?
>
>This is used in positions with opposite castling.  I have four "pawn
>square tables" (piece square tables which are only used with pawns).
>called w_ks_storm_table[], w_qs_storm_table[], b_ks_storm_table[] and
>b_qs_storm_table[].  When white has castled queenside and black kingside,
>I use w_ks_storm_table[] to evaluate the proximity of white's kingside
>pawns to black's king, and (similarly) b_qs_storm_table to evaluate
>black's queenside pawns.
>
>I have a function named analyse_pawn_structure() which computes all the
>stuff in p_hashentry_t and stores it all in the pawn hash table.  Among
>the many computations done, the ks_storm[] and qs_storm[] arrays are
>filled with bonuses calculated from the above-mentioned pawn square tables.
>
>Of course, I never use all the 4 entries in ks_storm[] and qs_storm[]
>simultaneously in my evaluation function.  If the kings are castled to
>the same side, I ignore all the values.  If white has castled queenside
>and black kingside, I use ks_storm[WHITE] and qs_storm[BLACK].

This mean that you may evaluate the same position in a different way because the
same position that happened after castling may happen also when the sides only
moved the king and the rook without castling.

>
>There is great scope for improvement in this part of my program.  It
>is rather primitive to use static pawn square tables for things like this.
>It would be much better to take in consideration the defending side's
>pawns in front of the king when computing ks_storm[] and qs_storm[].
>One of the great things about pawn hash tables is that you can do very
>time-consuming calculations at very little cost, because there are so
>few different pawn structures in the search tree.
>
>The above explanation is somewhat simplified, but I hope you get the idea.
>
>>>  uint8 ks_rook_files[2];     /* Good files for rooks when ks pawn storm */
>>>  uint8 qs_rook_files[2];     /* Good files for rooks when qs pawn storm */
>>>  uint8 bad_bishop_colour[2]; /* Bad bishop colour for both sides */
>>
>>How do you evaluate it?
>
>Basically, a bishop is bad if there are many friendly pawns on the same
>colour.  I use a weighted sum of the number of friendly pawns on the
>bishop's colour (where central squares have the biggest weight), and
>decides that the bishop is bad if this number is bigger than some number.
>
>Note that I do not store a bad bishop penalty in the pawn hash table,
>just the bit of information that a bishop of this colour is bad.  The
>penalty is computed in the evaluation function, where the penalty
>depends on the bishop's mobility, the contents of blocked_pawns_on_b[]
>and similar arrays, and probably something more which I don't remember
>at the moment.
>
>>>  int8 lpf[2];                /* Leftmost pawn file for both sides */
>>>  int8 rpf[2];                /* Rightmost pawn file for both sides */
>>>  int8 pchain_bonus[2];       /* Bonus for pawn chains and phalanxes */
>>
>>How do you evaluate pawn chains and what is phalanx?
>
>I have very primitive definitions of these.  A pawn is member of a "pawn
>chain" if it has a friendly pawn diagonally in front or behind itself.
>It is member of a "phalanx" if it has a friendly pawn on one of the
>neighboring squares.  I give a small bonus for pawns which are members
>of a pawn chain or phalanx.
>
>>>  int8 centre;                /* Type of centre */
>>>  uint8 pawns_on_w[2];        /* Pawns on white squares for both sides */
>>>  uint8 pawns_on_b[2];        /* Pawns on black squares for both sides */
>>>  uint8 central_pawns_on_w[2];/* Central pawns on white squares, both sides */
>>>  uint8 central_pawns_on_b[2];/* Central pawns on black squares, both sides */
>>>  uint8 blocked_pawns_on_w[2];/* Blocked pawns on white squares, both sides */
>>>  uint8 blocked_pawns_on_b[2];/* Blocked pawns on black squares, both sides */
>>>  uint8 blocked_central_pawns_on_w[2];
>>>      /* Blocked central pawns on white squares, both sides */
>>>  uint8 foo[55];  /* This is only here to make the structure 128 bytes big */
>>>} p_hashentry_t;
>>>
>>>The 'centre' field has a value which depends on the central pawn structure.
>>>Possible values are OPEN, HALF_OPEN, HALF_CLOSED, CLOSED, TENSION,
>>>UNRESOLVED, W_STONEWALL and B_STONEWALL.  For each type of centre I evaluate
>>>the position slightly differently (for instance, the penalty for not having
>>>a good pawn shelter in front of the king is much bigger when the centre
>>>is open).  I plan to add many more types of central pawn structures in
>>>the future.
>>
>>It seems that you are a very strong player.
>
>I am not an active chess player at all.  I have no rating, and if I
>started playing actively I think my rating would end up far below 2000.
>
>>My rating is close to 2000 but I never thought about centre in these
>>definitions.
>>
>>I do not consider myself to be good enough to know when to give a bonus and even
>>if I know when to give a bonus I need to test first because even if something is
>>good the bonus may be counter productive if it is too big
>>or if this bonus is already calculated for different reasons.
>
>I'm not saying that anything I do in my program is a good idea.  Unlike
>you, I have no ambitions whatsoever in computer chess.  Rather than trying
>to create the strongest possible program, I just do what I think is fun
>at the moment.  Perhaps all the time and energy I spend on the evaluation
>function is counter-productive for the program's strength, but it gives
>the engine a personality which is different from most others.
>
>>For example you may punish bad bishop not directly for mobility reasons and if
>>you add special evaluation for bad bishop then it may be counter productive
>>because your evaluation is too much when it punishes the bad bishop twice.
>>
>>>
>>>>Should I have some global varaible
>>>>int zobpawns for the key of the position in the board or maybe an array that
>>>>tell me the zobrist key for every ply and local varaible is enough.
>>>
>>>I use an array (for pawn hash keys as well as for normal hash keys).  For
>>>normal hash keys I use 64 bits, for pawn hash keys I use 32.
>>>
>>>Tord
>>
>>I guess that you update your hash key when you make move.
>>How do you do it?
>>
>>Do you use your array or do you define a local varaible?
>>
>>Same question for using your hash key when you probe the hash tables or record
>>position in the hash tables.
>
>No local variables in either case.  But at least in my program, I don't
>think this matters at all.
>
>Tord

I do not think that it can change the speed significantly in my program but I
prefer to do things correctly.

Uri



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.