https://www.chessprogramming.org/index.php?title=CPW-Engine_eval&feed=atom&action=history
CPW-Engine eval - Revision history
2024-03-29T09:16:04Z
Revision history for this page on the wiki
MediaWiki 1.30.1
https://www.chessprogramming.org/index.php?title=CPW-Engine_eval&diff=9310&oldid=prev
GerdIsenberg: Created page with "'''Home * Engines * CPW-Engine * Eval''' =Description= Using this evaluation function CPW-Engine should be aware of the following principles: # develop..."
2018-12-18T14:13:24Z
<p>Created page with "'''<a href="/Main_Page" title="Main Page">Home</a> * <a href="/Engines" title="Engines">Engines</a> * <a href="/CPW-Engine" title="CPW-Engine">CPW-Engine</a> * Eval''' =Description= Using this evaluation function CPW-Engine should be aware of the following principles: # develop..."</p>
<p><b>New page</b></p><div>'''[[Main Page|Home]] * [[Engines]] * [[CPW-Engine]] * Eval'''<br />
<br />
=Description= <br />
Using this evaluation function CPW-Engine should be aware of the following principles:<br />
# develop the pieces<br />
# castle if possible<br />
# need some minimal level of assistance to disrupt its own castling position<br />
# care for doubled, weak and passed pawns<br />
# know a thing or two about the changes of piece values as pawns dissappear<br />
# try to attack squares around enemy king<br />
<br />
For function definitions, see [[CPW-Engine_eval_h]]<br />
<br />
=Code= <br />
<pre><br />
#include "stdafx.h"<br />
#include "0x88_math.h"<br />
#include "eval.h"<br />
#include "transposition.h"<br />
<br />
/* adjustements of piece value based on the number of own pawns */<br />
int knight_adj[9] = { -20, -16, -12, -8, -4, 0, 4, 8, 12 };<br />
int rook_adj[9] = { 15, 12, 9, 6, 3, 0, -3, -6, -9 };<br />
<br />
static const int SafetyTable[100] = {<br />
0, 0, 1, 2, 3, 5, 7, 9, 12, 15,<br />
18, 22, 26, 30, 35, 39, 44, 50, 56, 62,<br />
68, 75, 82, 85, 89, 97, 105, 113, 122, 131,<br />
140, 150, 169, 180, 191, 202, 213, 225, 237, 248,<br />
260, 272, 283, 295, 307, 319, 330, 342, 354, 366,<br />
377, 389, 401, 412, 424, 436, 448, 459, 471, 483,<br />
494, 500, 500, 500, 500, 500, 500, 500, 500, 500,<br />
500, 500, 500, 500, 500, 500, 500, 500, 500, 500,<br />
500, 500, 500, 500, 500, 500, 500, 500, 500, 500,<br />
500, 500, 500, 500, 500, 500, 500, 500, 500, 500<br />
};<br />
<br />
/*******************************************************************<br />
* This struct holds data about certain aspects of evaluation, *<br />
* which allows program to print them if desired. *<br />
*******************************************************************/<br />
<br />
struct eval_vector {<br />
int gamePhase;<br />
int mgMob[2];<br />
int egMob[2];<br />
int attCnt[2];<br />
int attWeight[2];<br />
int kingShield[2];<br />
int MaterialAdjustement[2];<br />
int Blockages[2];<br />
int PositionalThemes[2];<br />
} v;<br />
<br />
int eval(int alpha, int beta, int use_hash) {<br />
int result = 0, mgScore = 0, egScore = 0;<br />
int stronger, weaker;<br />
<br />
/***********************************************************<br />
/ Probe the evaluatinon hashtable, unless we call eval() /<br />
/ only in order to display detailed result /<br />
***********************************************************/<br />
<br />
int probeval = tteval_probe();<br />
if (probeval != INVALID && use_hash)<br />
return probeval;<br />
<br />
/***********************************************************<br />
/ Clear all eval data /<br />
***********************************************************/<br />
<br />
v.gamePhase = 0;<br />
v.mgMob[WHITE] = 0; v.mgMob[BLACK] = 0;<br />
v.egMob[WHITE] = 0; v.egMob[BLACK] = 0;<br />
v.attCnt[WHITE] = 0; v.attCnt[BLACK] = 0;<br />
v.attWeight[WHITE] = 0; v.attWeight[BLACK] = 0;<br />
v.MaterialAdjustement[WHITE] = 0; v.MaterialAdjustement[BLACK] = 0;<br />
v.Blockages[WHITE] = 0; v.Blockages[BLACK] = 0;<br />
v.PositionalThemes[WHITE] = 0; v.PositionalThemes[BLACK] = 0;<br />
v.kingShield[WHITE] = 0; v.kingShield[BLACK] = 0;<br />
<br />
/* sum the incrementally counted material and pcsq values */<br />
mgScore = b.PieceMaterial[WHITE] + b.PawnMaterial[WHITE] + b.PcsqMg[WHITE]<br />
- b.PieceMaterial[BLACK] - b.PawnMaterial[BLACK] - b.PcsqMg[BLACK];<br />
egScore = b.PieceMaterial[WHITE] + b.PawnMaterial[WHITE] + b.PcsqEg[WHITE]<br />
- b.PieceMaterial[BLACK] - b.PawnMaterial[BLACK] - b.PcsqEg[BLACK];<br />
<br />
/* add king's pawn shield score and evaluate part of piece blockage score<br />
(the rest of the latter will be done via piece eval) */<br />
v.kingShield[WHITE] = wKingShield();<br />
v.kingShield[BLACK] = bKingShield();<br />
blockedPieces();<br />
mgScore += (v.kingShield[WHITE] - v.kingShield[BLACK]);<br />
<br />
/* tempo bonus */<br />
if (b.stm == WHITE) result += e.TEMPO;<br />
else result -= e.TEMPO;<br />
<br />
/*******************************************************************<br />
* Adjusting material value for the various combinations of pieces. *<br />
* Currently it scores bishop, knight and rook pairs. The first one *<br />
* gets a bonus, the latter two - a penalty. Please also note that *<br />
* adjustements of knight and rook value based on the number of own *<br />
* pawns on the board are done within the piece-specific routines. *<br />
*******************************************************************/<br />
<br />
if (b.PieceCount[WHITE][BISHOP] > 1) result += e.BISHOP_PAIR;<br />
if (b.PieceCount[BLACK][BISHOP] > 1) result -= e.BISHOP_PAIR;<br />
if (b.PieceCount[WHITE][KNIGHT] > 1) result -= e.P_KNIGHT_PAIR;<br />
if (b.PieceCount[BLACK][KNIGHT] > 1) result += e.P_KNIGHT_PAIR;<br />
if (b.PieceCount[WHITE][ROOK] > 1) result -= e.P_ROOK_PAIR;<br />
if (b.PieceCount[BLACK][ROOK] > 1) result += e.P_ROOK_PAIR;<br />
<br />
result += getPawnScore();<br />
<br />
/*******************************************************************<br />
* Evaluate pieces *<br />
*******************************************************************/<br />
<br />
for (U8 row = 0; row < 8; row++)<br />
for (U8 col = 0; col < 8; col++) {<br />
<br />
S8 sq = SET_SQ(row, col);<br />
<br />
if (b.color[sq] != COLOR_EMPTY) {<br />
switch (b.pieces[sq]) {<br />
case PAWN: // pawns are evaluated separately<br />
break;<br />
case KNIGHT:<br />
EvalKnight(sq, b.color[sq]);<br />
break;<br />
case BISHOP:<br />
EvalBishop(sq, b.color[sq]);<br />
break;<br />
case ROOK:<br />
EvalRook(sq, b.color[sq]);<br />
break;<br />
case QUEEN:<br />
EvalQueen(sq, b.color[sq]);<br />
break;<br />
case KING:<br />
break;<br />
}<br />
}<br />
}<br />
<br />
/********************************************************************<br />
* Merge midgame and endgame score. We interpolate between these *<br />
* two values, using a gamePhase value, based on remaining piece *<br />
* material on both sides. With less pieces, endgame score beco- *<br />
* mes more influential. *<br />
********************************************************************/<br />
<br />
mgScore += (v.mgMob[WHITE] - v.mgMob[BLACK]);<br />
egScore += (v.egMob[WHITE] - v.egMob[BLACK]);<br />
if (v.gamePhase > 24) v.gamePhase = 24;<br />
int mgWeight = v.gamePhase;<br />
int egWeight = 24 - mgWeight;<br />
result += ((mgScore * mgWeight) + (egScore * egWeight)) / 24;<br />
<br />
/********************************************************************<br />
* Add phase-independent score components. *<br />
********************************************************************/<br />
<br />
result += (v.Blockages[WHITE] - v.Blockages[BLACK]);<br />
result += (v.PositionalThemes[WHITE] - v.PositionalThemes[BLACK]);<br />
result += (v.MaterialAdjustement[WHITE] - v.MaterialAdjustement[BLACK]);<br />
<br />
/********************************************************************<br />
* Merge king attack score. We don't apply this value if there are *<br />
* less than two attackers or if the attacker has no queen. *<br />
*******************************************************************/<br />
<br />
if (v.attCnt[WHITE] < 2 || b.PieceCount[WHITE][QUEEN] == 0) v.attWeight[WHITE] = 0;<br />
if (v.attCnt[BLACK] < 2 || b.PieceCount[BLACK][QUEEN] == 0) v.attWeight[BLACK] = 0;<br />
result += SafetyTable[v.attWeight[WHITE]];<br />
result -= SafetyTable[v.attWeight[BLACK]];<br />
<br />
/********************************************************************<br />
* Low material correction - guarding against an illusory material *<br />
* advantage. Full blown program should have more such rules, but *<br />
* the current set ought to be useful enough. Please note that our *<br />
* code assumes different material values for bishop and knight. *<br />
* *<br />
* - a single minor piece cannot win *<br />
* - two knights cannot checkmate bare king *<br />
* - bare rook vs minor piece is drawish *<br />
* - rook and minor vs rook is drawish *<br />
********************************************************************/<br />
<br />
if (result > 0) { stronger = WHITE; weaker = BLACK; }<br />
else { stronger = BLACK; weaker = WHITE; }<br />
<br />
if (b.PawnMaterial[stronger] == 0) {<br />
<br />
if (b.PieceMaterial[stronger] < 400) return 0;<br />
<br />
if (b.PawnMaterial[weaker] == 0<br />
&& (b.PieceMaterial[stronger] == 2 * e.PIECE_VALUE[KNIGHT]))<br />
return 0;<br />
<br />
if (b.PieceMaterial[stronger] == e.PIECE_VALUE[ROOK]<br />
&& b.PieceMaterial[weaker] == e.PIECE_VALUE[BISHOP]) result /= 2;<br />
<br />
if (b.PieceMaterial[stronger] == e.PIECE_VALUE[ROOK]<br />
&& b.PieceMaterial[weaker] == e.PIECE_VALUE[KNIGHT]) result /= 2;<br />
<br />
if (b.PieceMaterial[stronger] == e.PIECE_VALUE[ROOK] + e.PIECE_VALUE[BISHOP]<br />
&& b.PieceMaterial[stronger] == e.PIECE_VALUE[ROOK]) result /= 2;<br />
<br />
if (b.PieceMaterial[stronger] == e.PIECE_VALUE[ROOK] + e.PIECE_VALUE[KNIGHT]<br />
&& b.PieceMaterial[stronger] == e.PIECE_VALUE[ROOK]) result /= 2;<br />
}<br />
<br />
/*******************************************************************<br />
* Finally return the score relative to the side to move. *<br />
*******************************************************************/<br />
<br />
if (b.stm == BLACK) result = -result;<br />
<br />
tteval_save(result);<br />
<br />
return result;<br />
}<br />
<br />
void EvalKnight(S8 sq, S8 side) {<br />
int att = 0;<br />
int mob = 0;<br />
int pos;<br />
v.gamePhase += 1;<br />
<br />
if (side == WHITE) {<br />
switch (sq) {<br />
case A8: if (isPiece(BLACK, PAWN, A7) || isPiece(BLACK, PAWN, C7)) v.Blockages[WHITE] -= e.P_KNIGHT_TRAPPED_A8; break;<br />
case H8: if (isPiece(BLACK, PAWN, H7) || isPiece(BLACK, PAWN, F7)) v.Blockages[WHITE] -= e.P_KNIGHT_TRAPPED_A8; break;<br />
case A7: if (isPiece(BLACK, PAWN, A6) && isPiece(BLACK, PAWN, B7)) v.Blockages[WHITE] -= e.P_KNIGHT_TRAPPED_A7; break;<br />
case H7: if (isPiece(BLACK, PAWN, H6) && isPiece(BLACK, PAWN, G7)) v.Blockages[WHITE] -= e.P_KNIGHT_TRAPPED_A7; break;<br />
case C3: if (isPiece(WHITE, PAWN, C2) && isPiece(WHITE, PAWN, D4) && !isPiece(WHITE, PAWN, E4)) v.Blockages[WHITE] -= e.P_C3_KNIGHT; break;<br />
}<br />
}<br />
else<br />
{<br />
switch (sq) {<br />
case A1: if (isPiece(WHITE, PAWN, A2) || isPiece(WHITE, PAWN, C2)) v.Blockages[BLACK] -= e.P_KNIGHT_TRAPPED_A8; break;<br />
case H1: if (isPiece(WHITE, PAWN, H2) || isPiece(WHITE, PAWN, F2)) v.Blockages[BLACK] -= e.P_KNIGHT_TRAPPED_A8; break;<br />
case A2: if (isPiece(WHITE, PAWN, A3) && isPiece(WHITE, PAWN, B2)) v.Blockages[BLACK] -= e.P_KNIGHT_TRAPPED_A7; break;<br />
case H2: if (isPiece(WHITE, PAWN, H3) && isPiece(WHITE, PAWN, G2)) v.Blockages[BLACK] -= e.P_KNIGHT_TRAPPED_A7; break;<br />
case C6: if (isPiece(BLACK, PAWN, C7) && isPiece(BLACK, PAWN, D5) && !isPiece(BLACK, PAWN, E5)) v.Blockages[BLACK] -= e.P_C3_KNIGHT; break;<br />
}<br />
}<br />
<br />
/***************************************************************<br />
* Material value adjustement based on the no. of own pawns. *<br />
* Knights lose value as pawns disappear. *<br />
***************************************************************/<br />
<br />
v.MaterialAdjustement[side] += knight_adj[b.PieceCount[side][PAWN]];<br />
<br />
/****************************************************************<br />
* Collect data about mobility and king attacks. This resembles *<br />
* move generation code, except that we are just incrementing *<br />
* the counters instead of adding actual moves. *<br />
****************************************************************/<br />
<br />
for (U8 dir = 0; dir<8; dir++) {<br />
pos = sq + vector[KNIGHT][dir];<br />
if (IS_SQ(pos) && b.color[pos] != side) {<br />
++mob;<br />
if (e.sqNearK[!side][b.KingLoc[!side]][pos])<br />
++att; // this knight is attacking zone around enemy king<br />
}<br />
}<br />
<br />
/****************************************************************<br />
* Evaluate mobility. We try to do it in such a way *<br />
* that zero represents average mobility, but our *<br />
* formula of doing so is a puer guess. *<br />
****************************************************************/<br />
<br />
v.mgMob[side] += 4 * (mob - 4);<br />
v.egMob[side] += 4 * (mob - 4);<br />
<br />
/****************************************************************<br />
* Save data about king attacks *<br />
****************************************************************/<br />
<br />
if (att) {<br />
v.attCnt[side]++;<br />
v.attWeight[side] += 2 * att;<br />
}<br />
}<br />
<br />
void EvalBishop(S8 sq, S8 side) {<br />
int att = 0;<br />
int mob = 0;<br />
v.gamePhase += 1;<br />
<br />
if (side == WHITE) {<br />
switch (sq) {<br />
case A7: if (isPiece(BLACK, PAWN, B6)) v.Blockages[WHITE] -= e.P_BISHOP_TRAPPED_A7; break;<br />
case H7: if (isPiece(BLACK, PAWN, G6)) v.Blockages[WHITE] -= e.P_BISHOP_TRAPPED_A7; break;<br />
case B8: if (isPiece(BLACK, PAWN, C7)) v.Blockages[WHITE] -= e.P_BISHOP_TRAPPED_A7; break;<br />
case G8: if (isPiece(BLACK, PAWN, F7)) v.Blockages[WHITE] -= e.P_BISHOP_TRAPPED_A7; break;<br />
case A6: if (isPiece(BLACK, PAWN, B5)) v.Blockages[WHITE] -= e.P_BISHOP_TRAPPED_A6; break;<br />
case H6: if (isPiece(BLACK, PAWN, G5)) v.Blockages[WHITE] -= e.P_BISHOP_TRAPPED_A6; break;<br />
case F1: if (isPiece(WHITE, KING, G1)) v.PositionalThemes[WHITE] += e.RETURNING_BISHOP; break;<br />
case C1: if (isPiece(WHITE, KING, B1)) v.PositionalThemes[WHITE] += e.RETURNING_BISHOP; break;<br />
}<br />
}<br />
else {<br />
switch (sq) {<br />
case A2: if (isPiece(WHITE, PAWN, B3)) v.Blockages[BLACK] -= e.P_BISHOP_TRAPPED_A7; break;<br />
case H2: if (isPiece(WHITE, PAWN, G3)) v.Blockages[BLACK] -= e.P_BISHOP_TRAPPED_A7; break;<br />
case B1: if (isPiece(WHITE, PAWN, C2)) v.Blockages[BLACK] -= e.P_BISHOP_TRAPPED_A7; break;<br />
case G1: if (isPiece(WHITE, PAWN, F2)) v.Blockages[BLACK] -= e.P_BISHOP_TRAPPED_A7; break;<br />
case A3: if (isPiece(WHITE, PAWN, B4)) v.Blockages[BLACK] -= e.P_BISHOP_TRAPPED_A6; break;<br />
case H3: if (isPiece(WHITE, PAWN, G4)) v.Blockages[BLACK] -= e.P_BISHOP_TRAPPED_A6; break;<br />
case F8: if (isPiece(BLACK, KING, G8)) v.PositionalThemes[BLACK] += e.RETURNING_BISHOP; break;<br />
case C8: if (isPiece(BLACK, KING, B8)) v.PositionalThemes[BLACK] += e.RETURNING_BISHOP; break;<br />
}<br />
}<br />
<br />
/****************************************************************<br />
* Collect data about mobility and king attacks *<br />
****************************************************************/<br />
<br />
for (char dir = 0; dir<vectors[BISHOP]; dir++) {<br />
<br />
for (char pos = sq;;) {<br />
<br />
pos = pos + vector[BISHOP][dir];<br />
if (!IS_SQ(pos)) break;<br />
<br />
if (b.pieces[pos] == PIECE_EMPTY) {<br />
mob++;<br />
if (e.sqNearK[!side][b.KingLoc[!side]][pos]) ++att;<br />
}<br />
else if (b.color[pos] != side) {<br />
mob++;<br />
if (e.sqNearK[!side][b.KingLoc[!side]][pos]) ++att;<br />
break;<br />
}<br />
else {<br />
break;<br />
}<br />
<br />
}<br />
}<br />
<br />
v.mgMob[side] += 3 * (mob - 7);<br />
v.egMob[side] += 3 * (mob - 7);<br />
<br />
if (att) {<br />
v.attCnt[side]++;<br />
v.attWeight[side] += 2 * att;<br />
}<br />
<br />
<br />
}<br />
<br />
void EvalRook(S8 sq, S8 side) {<br />
int att = 0;<br />
int mob = 0;<br />
int ownBlockingPawns = 0;<br />
int oppBlockingPawns = 0;<br />
int stepFwd;<br />
int nextSq;<br />
<br />
v.gamePhase += 2;<br />
<br />
/***************************************************************<br />
* Material value adjustement based on the no. of own pawns. *<br />
* Rooks gain value as pawns disappear. *<br />
***************************************************************/<br />
<br />
v.MaterialAdjustement[side] += rook_adj[b.PieceCount[side][PAWN]];<br />
<br />
/***************************************************************<br />
* This is an ugly hack to detect open files. Merging it with *<br />
* mobility eval would have been better, but less readable, *<br />
* and this is educational program fter all. *<br />
/**************************************************************/<br />
<br />
if (side == WHITE) stepFwd = NORTH; else stepFwd = SOUTH;<br />
nextSq = sq + stepFwd;<br />
<br />
while (IS_SQ(nextSq)) {<br />
if (b.pieces[nextSq] == PAWN) {<br />
if (b.color[nextSq] == side) {<br />
ownBlockingPawns++;<br />
break;<br />
}<br />
else<br />
oppBlockingPawns++;<br />
}<br />
nextSq += stepFwd;<br />
}<br />
<br />
/****************************************************************<br />
* Evaluate open and half-open files. We merge this bonus with *<br />
* mobility score. *<br />
/***************************************************************/<br />
<br />
if (!ownBlockingPawns) {<br />
<br />
if (!oppBlockingPawns) {<br />
v.mgMob[side] += e.ROOK_OPEN;<br />
v.egMob[side] += e.ROOK_OPEN;<br />
}<br />
else {<br />
v.mgMob[side] += e.ROOK_HALF;<br />
v.egMob[side] += e.ROOK_HALF;<br />
}<br />
}<br />
<br />
/****************************************************************<br />
* Collect data about mobility and king attacks *<br />
****************************************************************/<br />
<br />
for (char dir = 0; dir<vectors[ROOK]; dir++) {<br />
<br />
for (char pos = sq;;) {<br />
<br />
pos = pos + vector[ROOK][dir];<br />
if (!IS_SQ(pos)) break;<br />
<br />
if (b.pieces[pos] == PIECE_EMPTY) {<br />
mob++;<br />
if (e.sqNearK[!side][b.KingLoc[!side]][pos]) ++att;<br />
}<br />
else if (b.color[pos] != side) {<br />
mob++;<br />
if (e.sqNearK[!side][b.KingLoc[!side]][pos]) ++att;<br />
break;<br />
}<br />
else {<br />
break;<br />
}<br />
<br />
}<br />
}<br />
<br />
v.mgMob[side] += 2 * (mob - 7);<br />
v.egMob[side] += 4 * (mob - 7);<br />
<br />
if (att) {<br />
v.attCnt[side]++;<br />
v.attWeight[side] += 3 * att;<br />
}<br />
<br />
}<br />
<br />
void EvalQueen(S8 sq, S8 side) {<br />
v.gamePhase += 4;<br />
int att = 0;<br />
int mob = 0;<br />
<br />
/****************************************************************<br />
* A queen should not be developed too early *<br />
****************************************************************/<br />
<br />
if (side == WHITE && ROW(sq) > ROW_2) {<br />
if (isPiece(WHITE, KNIGHT, B1)) v.PositionalThemes[WHITE] -= 2;<br />
if (isPiece(WHITE, BISHOP, C1)) v.PositionalThemes[WHITE] -= 2;<br />
if (isPiece(WHITE, BISHOP, F1)) v.PositionalThemes[WHITE] -= 2;<br />
if (isPiece(WHITE, KNIGHT, G1)) v.PositionalThemes[WHITE] -= 2;<br />
}<br />
<br />
if (side == BLACK && ROW(sq) < ROW_7) {<br />
if (isPiece(BLACK, KNIGHT, B8)) v.PositionalThemes[BLACK] -= 2;<br />
if (isPiece(BLACK, BISHOP, C8)) v.PositionalThemes[BLACK] -= 2;<br />
if (isPiece(BLACK, BISHOP, F8)) v.PositionalThemes[BLACK] -= 2;<br />
if (isPiece(BLACK, KNIGHT, G8)) v.PositionalThemes[BLACK] -= 2;<br />
}<br />
<br />
/****************************************************************<br />
* Collect data about mobility and king attacks *<br />
****************************************************************/<br />
<br />
for (char dir = 0; dir<vectors[QUEEN]; dir++) {<br />
<br />
for (char pos = sq;;) {<br />
<br />
pos = pos + vector[QUEEN][dir];<br />
if (!IS_SQ(pos)) break;<br />
<br />
if (b.pieces[pos] == PIECE_EMPTY) {<br />
mob++;<br />
if (e.sqNearK[!side][b.KingLoc[!side]][pos]) ++att;<br />
}<br />
else if (b.color[pos] != side) {<br />
mob++;<br />
if (e.sqNearK[!side][b.KingLoc[!side]][pos]) ++att;<br />
break;<br />
}<br />
else {<br />
break;<br />
}<br />
<br />
}<br />
}<br />
<br />
v.mgMob[side] += 1 * (mob - 14);<br />
v.egMob[side] += 2 * (mob - 14);<br />
<br />
if (att) {<br />
v.attCnt[side]++;<br />
v.attWeight[side] += 4 * att;<br />
}<br />
<br />
}<br />
<br />
int wKingShield() {<br />
<br />
int result = 0;<br />
<br />
/* king on the kingside */<br />
if (COL(b.KingLoc[WHITE]) > COL_E) {<br />
<br />
if (isPiece(WHITE, PAWN, F2)) result += e.SHIELD_1;<br />
else if (isPiece(WHITE, PAWN, F3)) result += e.SHIELD_2;<br />
<br />
if (isPiece(WHITE, PAWN, G2)) result += e.SHIELD_1;<br />
else if (isPiece(WHITE, PAWN, G3)) result += e.SHIELD_2;<br />
<br />
if (isPiece(WHITE, PAWN, H2)) result += e.SHIELD_1;<br />
else if (isPiece(WHITE, PAWN, H3)) result += e.SHIELD_2;<br />
}<br />
<br />
/* king on the queenside */<br />
else if (COL(b.KingLoc[WHITE]) < COL_D) {<br />
<br />
if (isPiece(WHITE, PAWN, A2)) result += e.SHIELD_1;<br />
else if (isPiece(WHITE, PAWN, A3)) result += e.SHIELD_2;<br />
<br />
if (isPiece(WHITE, PAWN, B2)) result += e.SHIELD_1;<br />
else if (isPiece(WHITE, PAWN, B3)) result += e.SHIELD_2;<br />
<br />
if (isPiece(WHITE, PAWN, C2)) result += e.SHIELD_1;<br />
else if (isPiece(WHITE, PAWN, C3)) result += e.SHIELD_2;<br />
}<br />
<br />
return result;<br />
}<br />
<br />
int bKingShield() {<br />
int result = 0;<br />
<br />
/* king on the kingside */<br />
if (COL(b.KingLoc[BLACK]) > COL_E) {<br />
if (isPiece(BLACK, PAWN, F7)) result += e.SHIELD_1;<br />
else if (isPiece(BLACK, PAWN, F6)) result += e.SHIELD_2;<br />
<br />
if (isPiece(BLACK, PAWN, G7)) result += e.SHIELD_1;<br />
else if (isPiece(BLACK, PAWN, G6)) result += e.SHIELD_2;<br />
<br />
if (isPiece(BLACK, PAWN, H7)) result += e.SHIELD_1;<br />
else if (isPiece(BLACK, PAWN, H6)) result += e.SHIELD_2;<br />
}<br />
<br />
/* king on the queenside */<br />
else if (COL(b.KingLoc[BLACK]) < COL_D) {<br />
if (isPiece(BLACK, PAWN, A7)) result += e.SHIELD_1;<br />
else if (isPiece(BLACK, PAWN, A6)) result += e.SHIELD_2;<br />
<br />
if (isPiece(BLACK, PAWN, B7)) result += e.SHIELD_1;<br />
else if (isPiece(BLACK, PAWN, B6)) result += e.SHIELD_2;<br />
<br />
if (isPiece(BLACK, PAWN, C7)) result += e.SHIELD_1;<br />
else if (isPiece(BLACK, PAWN, C6)) result += e.SHIELD_2;<br />
}<br />
return result;<br />
}<br />
<br />
/******************************************************************************<br />
* Pawn structure evaluaton *<br />
******************************************************************************/<br />
<br />
int getPawnScore() {<br />
int result;<br />
<br />
/**************************************************************************<br />
* This function wraps hashing mechanism around evalPawnStructure(). *<br />
* Please note that since we use the pawn hashtable, evalPawnStructure() *<br />
* must not take into account the piece position. In a more elaborate *<br />
* program, pawn hashtable would contain only the characteristics of pawn *<br />
* structure, and scoring them in conjunction with the piece position *<br />
* would have been done elsewhere. *<br />
**************************************************************************/<br />
<br />
int probeval = ttpawn_probe();<br />
if (probeval != INVALID)<br />
return probeval;<br />
<br />
result = evalPawnStructure();<br />
<br />
ttpawn_save(result);<br />
<br />
return result;<br />
}<br />
<br />
int evalPawnStructure() {<br />
int result = 0;<br />
<br />
for (U8 row = 0; row < 8; row++)<br />
for (U8 col = 0; col < 8; col++) {<br />
<br />
S8 sq = SET_SQ(row, col);<br />
<br />
if (b.pieces[sq] == PAWN) {<br />
if (b.color[sq] == WHITE) result += EvalPawn(sq, WHITE);<br />
else result -= EvalPawn(sq, BLACK);<br />
}<br />
}<br />
<br />
return result;<br />
}<br />
<br />
int EvalPawn(S8 sq, S8 side) {<br />
int result = 0;<br />
int flagIsPassed = 1; // we will be trying to disprove that<br />
int flagIsWeak = 1; // we will be trying to disprove that<br />
int flagIsOpposed = 0;<br />
<br />
int stepFwd, stepBck;<br />
if (side == WHITE) stepFwd = NORTH; else stepFwd = SOUTH;<br />
if (side == WHITE) stepBck = SOUTH; else stepBck = NORTH;<br />
S8 nextSq = sq + stepFwd;<br />
<br />
/*************************************************************************<br />
* We have only very basic data structures that do not update informa- *<br />
* tion about pawns incrementally, so we have to calculate everything *<br />
* here. The loop below detects doubled pawns, passed pawns and sets *<br />
* a flag on finding that our pawn is opposed by enemy pawn. *<br />
*************************************************************************/<br />
<br />
while (IS_SQ(nextSq)) {<br />
<br />
if (b.pieces[nextSq] == PAWN) { // either opposed by enemy pawn or doubled<br />
flagIsPassed = 0;<br />
if (b.color[nextSq] == side)<br />
result -= 20; // doubled pawn penalty<br />
else<br />
flagIsOpposed = 1; // flag our pawn as opposed<br />
}<br />
<br />
if (IS_SQ(nextSq + WEST) && isPiece(!side, PAWN, nextSq + WEST))<br />
flagIsPassed = 0;<br />
<br />
if (IS_SQ(nextSq + EAST) && isPiece(!side, PAWN, nextSq + EAST))<br />
flagIsPassed = 0;<br />
<br />
nextSq += stepFwd;<br />
}<br />
<br />
/*************************************************************************<br />
* Another loop, going backwards and checking whether pawn has support. *<br />
* Here we can at least break out of it for speed optimization. *<br />
*************************************************************************/<br />
<br />
nextSq = sq;<br />
while (IS_SQ(nextSq)) {<br />
<br />
if (IS_SQ(nextSq + WEST) && isPiece(side, PAWN, nextSq + WEST)) {<br />
flagIsWeak = 0;<br />
break;<br />
}<br />
<br />
if (IS_SQ(nextSq + EAST) && isPiece(side, PAWN, nextSq + EAST)) {<br />
flagIsWeak = 0;<br />
break;<br />
}<br />
<br />
nextSq += stepBck;<br />
}<br />
<br />
/*************************************************************************<br />
* Evaluate passed pawns, scoring them higher if they are protected *<br />
* or if their advance is supported by friendly pawns *<br />
*************************************************************************/<br />
<br />
if (flagIsPassed) {<br />
if (isPawnSupported(sq, side)) result += e.protected_passer[side][sq];<br />
else result += e.passed_pawn[side][sq];<br />
}<br />
<br />
/*************************************************************************<br />
* Evaluate weak pawns, increasing the penalty if they are situated *<br />
* on a half-open file *<br />
*************************************************************************/<br />
<br />
if (flagIsWeak) {<br />
result += e.weak_pawn[side][sq];<br />
if (!flagIsOpposed)<br />
result -= 4;<br />
}<br />
<br />
return result;<br />
}<br />
<br />
int isPawnSupported(S8 sq, S8 side) {<br />
int step;<br />
if (side == WHITE) step = SOUTH; else step = NORTH;<br />
<br />
if (IS_SQ(sq + WEST) && isPiece(side, PAWN, sq + WEST)) return 1;<br />
if (IS_SQ(sq + EAST) && isPiece(side, PAWN, sq + EAST)) return 1;<br />
if (IS_SQ(sq + step + WEST) && isPiece(side, PAWN, sq + step + WEST)) return 1;<br />
if (IS_SQ(sq + step + EAST) && isPiece(side, PAWN, sq + step + EAST)) return 1;<br />
<br />
return 0;<br />
}<br />
<br />
/******************************************************************************<br />
* Pattern detection *<br />
******************************************************************************/<br />
<br />
void blockedPieces() {<br />
<br />
// central pawn blocked, bishop hard to develop<br />
if (isPiece(WHITE, BISHOP, C1) && isPiece(WHITE, PAWN, D2) && b.color[D3] != COLOR_EMPTY)<br />
v.Blockages[WHITE] -= e.P_BLOCK_CENTRAL_PAWN;<br />
if (isPiece(WHITE, BISHOP, F1) && isPiece(WHITE, PAWN, E2) && b.color[E3] != COLOR_EMPTY)<br />
v.Blockages[WHITE] -= e.P_BLOCK_CENTRAL_PAWN;<br />
if (isPiece(BLACK, BISHOP, C8) && isPiece(BLACK, PAWN, D7) && b.color[D6] != COLOR_EMPTY)<br />
v.Blockages[BLACK] -= e.P_BLOCK_CENTRAL_PAWN;<br />
if (isPiece(BLACK, BISHOP, F8) && isPiece(BLACK, PAWN, E7) && b.color[E6] != COLOR_EMPTY)<br />
v.Blockages[BLACK] -= e.P_BLOCK_CENTRAL_PAWN;<br />
<br />
// uncastled king blocking own rook<br />
if ((isPiece(WHITE, KING, F1) || isPiece(WHITE, KING, G1)) &&<br />
(isPiece(WHITE, ROOK, H1) || isPiece(WHITE, ROOK, G1))<br />
)<br />
v.Blockages[WHITE] -= e.P_KING_BLOCKS_ROOK;<br />
<br />
if ((isPiece(WHITE, KING, C1) || isPiece(WHITE, KING, B1)) &&<br />
(isPiece(WHITE, ROOK, A1) || isPiece(WHITE, ROOK, B1))<br />
)<br />
v.Blockages[WHITE] -= e.P_KING_BLOCKS_ROOK;<br />
<br />
if ((isPiece(BLACK, KING, F8) || isPiece(BLACK, KING, G8)) &&<br />
(isPiece(BLACK, ROOK, H8) || isPiece(BLACK, ROOK, G8))<br />
)<br />
v.Blockages[BLACK] -= e.P_KING_BLOCKS_ROOK;<br />
<br />
if ((isPiece(BLACK, KING, C8) || isPiece(BLACK, KING, B8)) &&<br />
(isPiece(BLACK, ROOK, A8) || isPiece(BLACK, ROOK, B8))<br />
)<br />
v.Blockages[BLACK] -= e.P_KING_BLOCKS_ROOK;<br />
}<br />
<br />
int isPiece(U8 color, U8 piece, S8 sq) {<br />
return ((b.pieces[sq] == piece) && (b.color[sq] == color));<br />
}<br />
<br />
/***************************************************************************************<br />
* Printing eval results *<br />
***************************************************************************************/<br />
<br />
void printEval() {<br />
printf("------------------------------------------\n");<br />
printf("Total value (for side to move): %d \n", eval(-INF, INF, 0));<br />
printf("Material balance : %d \n", b.PieceMaterial[WHITE] + b.PawnMaterial[WHITE] - b.PieceMaterial[BLACK] - b.PawnMaterial[BLACK]);<br />
printf("Material adjustement: "); printEvalFactor(v.MaterialAdjustement[WHITE], v.MaterialAdjustement[BLACK]);<br />
printf("Mg Piece/square tables : "); printEvalFactor(b.PcsqMg[WHITE], b.PcsqMg[BLACK]);<br />
printf("Eg Piece/square tables : "); printEvalFactor(b.PcsqEg[WHITE], b.PcsqEg[BLACK]);<br />
printf("Mg Mobility : "); printEvalFactor(v.mgMob[WHITE], v.mgMob[BLACK]);<br />
printf("Eg Mobility : "); printEvalFactor(v.mgMob[WHITE], v.egMob[BLACK]);<br />
printf("Pawn structure : %d \n", evalPawnStructure());<br />
printf("Blockages : "); printEvalFactor(v.Blockages[WHITE], v.Blockages[BLACK]);<br />
printf("Positional themes : "); printEvalFactor(v.PositionalThemes[WHITE], v.PositionalThemes[BLACK]);<br />
printf("King Shield : "); printEvalFactor(v.kingShield[WHITE], v.kingShield[BLACK]);<br />
printf("Tempo: ");<br />
if (b.stm == WHITE) printf("%d", e.TEMPO); else printf("%d", -e.TEMPO);<br />
printf("\n");<br />
printf("------------------------------------------\n");<br />
}<br />
<br />
void printEvalFactor(int wh, int bl) {<br />
printf("white %4d, black %4d, total: %4d \n", wh, bl, wh - bl);<br />
}<br />
</pre><br />
<br />
'''[[CPW-Engine|Up one Level]]'''</div>
GerdIsenberg