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.