CPW-Engine_eval

toc
 * Home * Engines * CPW-Engine * Eval**

=Description= Using this evaluation function CPW-Engine should be aware of the following principles: 1) develop the pieces 2) castle if possible 3) need some minimal level of assistance to disrupt its own castling position 4) care for doubled, weak and passed pawns 5) know a thing or two about the changes of piece values as pawns dissappear 6) try to attack squares around enemy king

For function definitions, see CPW-Engine_eval_h

=Code= code format="cpp"
 * 1) include "stdafx.h"
 * 2) include "0x88_math.h"
 * 3) include "eval.h"
 * 4) include "transposition.h"

/* adjustements of piece value based on the number of own pawns */ int knight_adj[9] = { -20, -16, -12, -8, -4, 0,  4,  8, 12}; int rook_adj[9] =  {  15,  12,   9,  6,  3,  0, -3, -6, -9};

static const int SafetyTable[100] = { 0, 0,   1,   2,   3,   5,   7,   9,  12,  15,  18,  22,  26,  30,  35,  39,  44,  50,  56,  62,  68,  75,  82,  85,  89,  97, 105, 113, 122, 131, 140, 150, 169, 180, 191, 202, 213, 225, 237, 248, 260, 272, 283, 295, 307, 319, 330, 342, 354, 366, 377, 389, 401, 412, 424, 436, 448, 459, 471, 483, 494, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500 };

/*******************************************************************
 * This struct holds data about certain aspects of evaluation,    *
 * which allows program to print them if desired.                 *

struct eval_vector { int gamePhase; int mgMob[2]; int egMob[2]; int attCnt[2]; int attWeight[2]; int kingShield[2]; int MaterialAdjustement[2]; int Blockages[2]; int PositionalThemes[2]; } v;

int eval( int alpha, int beta, int use_hash ) { int result = 0, mgScore = 0, egScore = 0; int stronger, weaker;

/***********************************************************   /  Probe the evaluatinon hashtable, unless we call eval  / / only in order to display detailed result                / ***********************************************************/

int probeval = tteval_probe; if (probeval != INVALID && use_hash) return probeval;

/***********************************************************   /  Clear all eval data                                     / ***********************************************************/

v.gamePhase = 0; v.mgMob[WHITE] = 0;     v.mgMob[BLACK] = 0; v.egMob[WHITE] = 0;     v.egMob[BLACK] = 0; v.attCnt[WHITE] = 0;    v.attCnt[BLACK] = 0; v.attWeight[WHITE] = 0; v.attWeight[BLACK] = 0; v.MaterialAdjustement[WHITE] = 0; v.MaterialAdjustement[BLACK] = 0; v.Blockages[WHITE] = 0; v.Blockages[BLACK] = 0; v.PositionalThemes[WHITE] = 0; v.PositionalThemes[BLACK] = 0; v.kingShield[WHITE] = 0; v.kingShield[BLACK] = 0;

/* sum the incrementally counted material and pcsq values */ mgScore = b.PieceMaterial[WHITE] + b.PawnMaterial[WHITE] + b.PcsqMg[WHITE] - b.PieceMaterial[BLACK] - b.PawnMaterial[BLACK] - b.PcsqMg[BLACK]; egScore = b.PieceMaterial[WHITE] + b.PawnMaterial[WHITE] + b.PcsqEg[WHITE] - b.PieceMaterial[BLACK] - b.PawnMaterial[BLACK] - b.PcsqEg[BLACK];

/* add king's pawn shield score and evaluate part of piece blockage score (the rest of the latter will be done via piece eval) */ v.kingShield[WHITE] = wKingShield; v.kingShield[BLACK] = bKingShield; blockedPieces; mgScore += (v.kingShield[WHITE] - v.kingShield[BLACK]);

/* tempo bonus */ if ( b.stm == WHITE ) result += e.TEMPO; else                 result -= e.TEMPO;

/*******************************************************************   * Adjusting material value for the various combinations of pieces. *   * Currently it scores bishop, knight and rook pairs. The first one * * gets a bonus, the latter two - a penalty. Please also note that * * adjustements of knight and rook value based on the number of own * * pawns on the board are done within the piece-specific routines. *   *******************************************************************/

if ( b.PieceCount[WHITE][BISHOP] > 1 ) result += e.BISHOP_PAIR; if ( b.PieceCount[BLACK][BISHOP] > 1 ) result -= e.BISHOP_PAIR; if ( b.PieceCount[WHITE][KNIGHT] > 1 ) result -= e.P_KNIGHT_PAIR; if ( b.PieceCount[BLACK][KNIGHT] > 1 ) result += e.P_KNIGHT_PAIR; if ( b.PieceCount[WHITE] [ROOK] > 1 ) result -= e.P_ROOK_PAIR; if ( b.PieceCount[BLACK] [ROOK] > 1 ) result += e.P_ROOK_PAIR;

result += getPawnScore;

/*******************************************************************   *  Evaluate pieces                                                 * *******************************************************************/

for (U8 row=0; row < 8; row++) for (U8 col=0; col < 8; col++) {

S8 sq = SET_SQ(row, col);

if ( b.color[sq] != COLOR_EMPTY ) { switch (b.pieces[sq]) { case PAWN: // pawns are evaluated separately break; case KNIGHT: EvalKnight(sq, b.color[sq]); break; case BISHOP: EvalBishop(sq, b.color[sq]); break; case ROOK: EvalRook(sq, b.color[sq]); break; case QUEEN: EvalQueen(sq, b.color[sq]); break; case KING: break; }    }   }

/********************************************************************  *  Merge midgame and endgame score. We interpolate between these   * * two values, using a gamePhase value, based on remaining piece    * * material on both sides. With less pieces, endgame score beco-   * * mes more influential. *  ********************************************************************/

mgScore += (v.mgMob[WHITE] - v.mgMob[BLACK]); egScore += (v.egMob[WHITE] - v.egMob[BLACK]); if (v.gamePhase > 24) v.gamePhase = 24; int mgWeight = v.gamePhase; int egWeight = 24 - mgWeight; result += ( (mgScore * mgWeight) + (egScore * egWeight) ) / 24;

/********************************************************************  *  Add phase-independent score components. *  ********************************************************************/

result += (v.Blockages[WHITE] - v.Blockages[BLACK]); result += (v.PositionalThemes[WHITE] - v.PositionalThemes[BLACK]); result += (v.MaterialAdjustement[WHITE] - v.MaterialAdjustement[BLACK]);

/********************************************************************   *  Merge king attack score. We don't apply this value if there are * * less than two attackers or if the attacker has no queen. *   *******************************************************************/

if (v.attCnt[WHITE] < 2 || b.PieceCount[WHITE][QUEEN] == 0) v.attWeight[WHITE] = 0; if (v.attCnt[BLACK] < 2 || b.PieceCount[BLACK][QUEEN] == 0) v.attWeight[BLACK] = 0; result += SafetyTable[v.attWeight[WHITE]]; result -= SafetyTable[v.attWeight[BLACK]];

/********************************************************************  *  Low material correction - guarding against an illusory material  * * advantage. Full blown program should have more such rules, but  * * the current set ought to be useful enough. Please note that our * * code  assumes different material values for bishop and  knight. *  *                                                                   *   *  - a single minor piece cannot win                                * * - two knights cannot checkmate bare king                         * * - bare rook vs minor piece is drawish                            * * - rook and minor vs rook is drawish                              * ********************************************************************/

if (result > 0) { stronger = WHITE; weaker = BLACK; } else              { stronger = BLACK; weaker = WHITE; }

if (b.PawnMaterial[stronger] == 0) {

if (b.PieceMaterial[stronger] < 400) return 0;

if (b.PawnMaterial[weaker] == 0          && (b.PieceMaterial[stronger] == 2 * e.PIECE_VALUE[KNIGHT])) return 0;

if (b.PieceMaterial[stronger] == e.PIECE_VALUE[ROOK]          && b.PieceMaterial[weaker] == e.PIECE_VALUE[BISHOP]) result /= 2;

if (b.PieceMaterial[stronger] == e.PIECE_VALUE[ROOK]          && b.PieceMaterial[weaker] == e.PIECE_VALUE[KNIGHT]) result /= 2;

if (b.PieceMaterial[stronger] == e.PIECE_VALUE[ROOK] + e.PIECE_VALUE[BISHOP]          && b.PieceMaterial[stronger] == e.PIECE_VALUE[ROOK]) result /= 2;

if (b.PieceMaterial[stronger] == e.PIECE_VALUE[ROOK] + e.PIECE_VALUE[KNIGHT]          && b.PieceMaterial[stronger] == e.PIECE_VALUE[ROOK]) result /= 2; }

/*******************************************************************   *  Finally return the score relative to the side to move. *   *******************************************************************/

if ( b.stm == BLACK ) result = -result;

tteval_save(result);

return result; }

void EvalKnight(S8 sq, S8 side) { int att = 0; int mob = 0; int pos; v.gamePhase += 1;

if (side == WHITE) { switch (sq) { case A8: if (isPiece(BLACK, PAWN, A7) || isPiece(BLACK, PAWN, C7)) v.Blockages[WHITE] -= e.P_KNIGHT_TRAPPED_A8; break; case H8: if (isPiece(BLACK, PAWN, H7) || isPiece(BLACK, PAWN, F7)) v.Blockages[WHITE] -= e.P_KNIGHT_TRAPPED_A8; break; case A7: if (isPiece(BLACK, PAWN, A6) && isPiece(BLACK, PAWN, B7)) v.Blockages[WHITE] -= e.P_KNIGHT_TRAPPED_A7; break; case H7: if (isPiece(BLACK, PAWN, H6) && isPiece(BLACK, PAWN, G7)) v.Blockages[WHITE] -= e.P_KNIGHT_TRAPPED_A7; break; case C3: if (isPiece(WHITE, PAWN, C2) && isPiece(WHITE, PAWN, D4) && !isPiece(WHITE, PAWN, E4)) v.Blockages[WHITE] -= e.P_C3_KNIGHT; break; }    }     else {        switch (sq) { case A1: if (isPiece(WHITE, PAWN, A2) || isPiece(WHITE, PAWN, C2)) v.Blockages[BLACK] -= e.P_KNIGHT_TRAPPED_A8; break; case H1: if (isPiece(WHITE, PAWN, H2) || isPiece(WHITE, PAWN, F2)) v.Blockages[BLACK] -= e.P_KNIGHT_TRAPPED_A8; break; case A2: if (isPiece(WHITE, PAWN, A3) && isPiece(WHITE, PAWN, B2)) v.Blockages[BLACK] -= e.P_KNIGHT_TRAPPED_A7; break; case H2: if (isPiece(WHITE, PAWN, H3) && isPiece(WHITE, PAWN, G2)) v.Blockages[BLACK] -= e.P_KNIGHT_TRAPPED_A7; break; case C6: if (isPiece(BLACK, PAWN, C7) && isPiece(BLACK, PAWN, D5) && !isPiece(BLACK, PAWN, E5)) v.Blockages[BLACK] -= e.P_C3_KNIGHT; break; }    }

/***************************************************************    *  Material value adjustement based on the no. of own pawns. *    *  Knights lose value as pawns disappear. *    ***************************************************************/

v.MaterialAdjustement[side] += knight_adj[b.PieceCount[side][PAWN]];

/****************************************************************   *  Collect data about mobility and king attacks. This resembles * * move generation code, except that we are just incrementing   * * the counters instead of adding actual moves. *   ****************************************************************/

for (U8 dir=0;dir<8;dir++) { pos = sq + vector[KNIGHT][dir]; if ( IS_SQ(pos) && b.color[pos] != side ) { ++mob; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; // this knight is attacking zone around enemy king }   }

/****************************************************************   *  Evaluate mobility. We try to do it in such a way            * * that  zero represents average mobility, but  our             * * formula of doing so is a puer guess. *   ****************************************************************/

v.mgMob[side] += 4 * (mob-4); v.egMob[side] += 4 * (mob-4);

/****************************************************************   *  Save data about king attacks                                 * ****************************************************************/

if (att) { v.attCnt[side]++; v.attWeight[side] += 2 * att; } }

void EvalBishop(S8 sq, S8 side) { int att = 0; int mob = 0; v.gamePhase += 1;

if (side == WHITE) { switch (sq) { case A7: if (isPiece(BLACK, PAWN, B6)) v.Blockages[WHITE] -= e.P_BISHOP_TRAPPED_A7; break; case H7: if (isPiece(BLACK, PAWN, G6)) v.Blockages[WHITE] -= e.P_BISHOP_TRAPPED_A7; break; case B8: if (isPiece(BLACK, PAWN, C7)) v.Blockages[WHITE] -= e.P_BISHOP_TRAPPED_A7; break; case G8: if (isPiece(BLACK, PAWN, F7)) v.Blockages[WHITE] -= e.P_BISHOP_TRAPPED_A7; break; case A6: if (isPiece(BLACK, PAWN, B5)) v.Blockages[WHITE] -= e.P_BISHOP_TRAPPED_A6; break; case H6: if (isPiece(BLACK, PAWN, G5)) v.Blockages[WHITE] -= e.P_BISHOP_TRAPPED_A6; break; case F1: if (isPiece(WHITE, KING, G1)) v.PositionalThemes[WHITE] += e.RETURNING_BISHOP; break; case C1: if (isPiece(WHITE, KING, B1)) v.PositionalThemes[WHITE] += e.RETURNING_BISHOP; break; }    }     else { switch (sq) { case A2: if (isPiece(WHITE, PAWN, B3)) v.Blockages[BLACK] -= e.P_BISHOP_TRAPPED_A7; break; case H2: if (isPiece(WHITE, PAWN, G3)) v.Blockages[BLACK] -= e.P_BISHOP_TRAPPED_A7; break; case B1: if (isPiece(WHITE, PAWN, C2)) v.Blockages[BLACK] -= e.P_BISHOP_TRAPPED_A7; break; case G1: if (isPiece(WHITE, PAWN, F2)) v.Blockages[BLACK] -= e.P_BISHOP_TRAPPED_A7; break; case A3: if (isPiece(WHITE, PAWN, B4)) v.Blockages[BLACK] -= e.P_BISHOP_TRAPPED_A6; break; case H3: if (isPiece(WHITE, PAWN, G4)) v.Blockages[BLACK] -= e.P_BISHOP_TRAPPED_A6; break; case F8: if (isPiece(BLACK, KING, G8)) v.PositionalThemes[BLACK] += e.RETURNING_BISHOP; break; case C8: if (isPiece(BLACK, KING, B8)) v.PositionalThemes[BLACK] += e.RETURNING_BISHOP; break; }    }

/****************************************************************   *  Collect data about mobility and king attacks                 * ****************************************************************/

for (char dir=0;dir<vectors[BISHOP];dir++) {

for (char pos = sq;;) {

pos = pos + vector[BISHOP][dir]; if (! IS_SQ(pos)) break;

if (b.pieces[pos] == PIECE_EMPTY) { mob++; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; }             else if (b.color[pos] != side) { mob++; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; break; }             else { break; }

}   }

v.mgMob[side] += 3 * (mob-7); v.egMob[side] += 3 * (mob-7);

if (att) { v.attCnt[side]++; v.attWeight[side] += 2*att; }

}

void EvalRook(S8 sq, S8 side) { int att = 0; int mob = 0; int ownBlockingPawns = 0; int oppBlockingPawns = 0; int stepFwd; int nextSq;

v.gamePhase += 2;

/***************************************************************   *  Material value adjustement based on the no. of own pawns. *   *  Rooks gain value as pawns disappear. *   ***************************************************************/

v.MaterialAdjustement[side] += rook_adj[b.PieceCount[side][PAWN]];

/***************************************************************   *  This is an ugly hack to detect open files. Merging it with * * mobility  eval would have been better, but less  readable,  * * and this is educational program fter all. *   /**************************************************************/

if (side == WHITE) stepFwd = NORTH; else stepFwd = SOUTH; nextSq = sq + stepFwd;

while (IS_SQ(nextSq)) { if (b.pieces[nextSq] == PAWN) { if (b.color[nextSq] == side) { ownBlockingPawns++; break; }           else oppBlockingPawns++; }       nextSq += stepFwd; }

/****************************************************************   *  Evaluate open and half-open files. We merge this bonus with * * mobility  score. *   /***************************************************************/

if ( !ownBlockingPawns ) {

if ( !oppBlockingPawns ) { v.mgMob[side] += e.ROOK_OPEN; v.egMob[side] += e.ROOK_OPEN; } else { v.mgMob[side] += e.ROOK_HALF; v.egMob[side] += e.ROOK_HALF; }   }

/****************************************************************   *  Collect data about mobility and king attacks                 * ****************************************************************/

for (char dir=0; dir<vectors[ROOK]; dir++) {

for (char pos = sq;;) {

pos = pos + vector[ROOK][dir]; if (! IS_SQ(pos)) break;

if (b.pieces[pos] == PIECE_EMPTY) { mob++; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; }             else if (b.color[pos] != side) { mob++; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; break; }             else { break; }

}   }

v.mgMob[side] += 2 * (mob-7); v.egMob[side] += 4 * (mob-7);

if (att) { v.attCnt[side]++; v.attWeight[side] += 3*att; }

}

void EvalQueen(S8 sq, S8 side) { v.gamePhase += 4; int att = 0; int mob = 0;

/****************************************************************   *  A queen should not be developed too early                    * ****************************************************************/

if (side == WHITE && ROW(sq) > ROW_2) { if (isPiece(WHITE, KNIGHT, B1)) v.PositionalThemes[WHITE] -= 2; if (isPiece(WHITE, BISHOP, C1)) v.PositionalThemes[WHITE] -= 2; if (isPiece(WHITE, BISHOP, F1)) v.PositionalThemes[WHITE] -= 2; if (isPiece(WHITE, KNIGHT, G1)) v.PositionalThemes[WHITE] -= 2; }

if (side == BLACK && ROW(sq) < ROW_7) { if (isPiece(BLACK, KNIGHT, B8)) v.PositionalThemes[BLACK] -= 2; if (isPiece(BLACK, BISHOP, C8)) v.PositionalThemes[BLACK] -= 2; if (isPiece(BLACK, BISHOP, F8)) v.PositionalThemes[BLACK] -= 2; if (isPiece(BLACK, KNIGHT, G8)) v.PositionalThemes[BLACK] -= 2; }

/****************************************************************   *  Collect data about mobility and king attacks                 * ****************************************************************/

for (char dir=0;dir<vectors[QUEEN];dir++) {

for (char pos = sq;;) {

pos = pos + vector[QUEEN][dir]; if (! IS_SQ(pos)) break;

if (b.pieces[pos] == PIECE_EMPTY) { mob++; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; }             else if (b.color[pos] != side) { mob++; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; break; }             else { break; }

}   }

v.mgMob[side] += 1 * (mob-14); v.egMob[side] += 2 * (mob-14);

if (att) { v.attCnt[side]++; v.attWeight[side] += 4*att; }

}

int wKingShield {

int result = 0;

/* king on the kingside */ if ( COL(b.KingLoc[WHITE]) > COL_E ) {

if ( isPiece(WHITE, PAWN, F2) ) result += e.SHIELD_1; else if ( isPiece(WHITE, PAWN, F3) ) result += e.SHIELD_2;

if ( isPiece(WHITE, PAWN, G2) ) result += e.SHIELD_1; else if ( isPiece(WHITE, PAWN, G3) ) result += e.SHIELD_2;

if ( isPiece(WHITE, PAWN, H2) ) result += e.SHIELD_1; else if ( isPiece(WHITE, PAWN, H3) ) result += e.SHIELD_2; }

/* king on the queenside */ else if ( COL(b.KingLoc[WHITE]) < COL_D ) {

if ( isPiece(WHITE, PAWN, A2) ) result += e.SHIELD_1; else if ( isPiece(WHITE, PAWN, A3) ) result += e.SHIELD_2;

if ( isPiece(WHITE, PAWN, B2) ) result += e.SHIELD_1; else if ( isPiece(WHITE, PAWN, B3) ) result += e.SHIELD_2;

if ( isPiece(WHITE, PAWN, C2) ) result += e.SHIELD_1; else if ( isPiece(WHITE, PAWN, C3) ) result += e.SHIELD_2; }

return result; }

int bKingShield { int result = 0;

/* king on the kingside */ if ( COL(b.KingLoc[BLACK]) > COL_E ) { if ( isPiece(BLACK, PAWN, F7) ) result += e.SHIELD_1; else if ( isPiece(BLACK, PAWN, F6) ) result += e.SHIELD_2;

if ( isPiece(BLACK, PAWN, G7) ) result += e.SHIELD_1; else if ( isPiece(BLACK, PAWN, G6) ) result += e.SHIELD_2;

if ( isPiece(BLACK, PAWN, H7) ) result += e.SHIELD_1; else if ( isPiece(BLACK, PAWN, H6) ) result += e.SHIELD_2; }

/* king on the queenside */ else if ( COL(b.KingLoc[BLACK]) < COL_D ) { if ( isPiece(BLACK, PAWN, A7) ) result += e.SHIELD_1; else if ( isPiece(BLACK, PAWN, A6) ) result += e.SHIELD_2;

if ( isPiece(BLACK, PAWN, B7) ) result += e.SHIELD_1; else if ( isPiece(BLACK, PAWN, B6) ) result += e.SHIELD_2;

if ( isPiece(BLACK, PAWN, C7) ) result += e.SHIELD_1; else if ( isPiece(BLACK, PAWN, C6) ) result += e.SHIELD_2; } return result; }

/******************************************************************************
 * Pawn structure evaluaton                        *

int getPawnScore { int result;

/**************************************************************************   *  This function wraps hashing mechanism around evalPawnStructure. *   *  Please note  that since we use the pawn hashtable, evalPawnStructure * * must not take into account the piece position. In a more elaborate   * * program, pawn hashtable would contain only the characteristics of pawn * * structure,  and scoring them in conjunction with the piece position    * * would have been done elsewhere. *   **************************************************************************/

int probeval = ttpawn_probe; if (probeval != INVALID) return probeval;

result = evalPawnStructure;

ttpawn_save(result);

return result; }

int evalPawnStructure { int result = 0;

for (U8 row = 0; row < 8; row++) for (U8 col = 0; col < 8; col++) {

S8 sq = SET_SQ(row, col);

if (b.pieces[sq] == PAWN) { if (b.color[sq] == WHITE) result += EvalPawn(sq, WHITE); else                     result -= EvalPawn(sq, BLACK); }  }

return result; }

int EvalPawn(S8 sq, S8 side) { int result = 0; int flagIsPassed = 1; // we will be trying to disprove that int flagIsWeak = 1;  // we will be trying to disprove that int flagIsOpposed = 0;

int stepFwd, stepBck; if (side == WHITE) stepFwd = NORTH; else stepFwd = SOUTH; if (side == WHITE) stepBck = SOUTH; else stepBck = NORTH; S8 nextSq = sq + stepFwd;

/*************************************************************************   *   We have only very basic data structures that do not update informa-  * *  tion about pawns incrementally, so we have to calculate everything   * *  here. The loop below detects doubled pawns, passed pawns and sets  * *  a flag on finding that our pawn is opposed by enemy pawn. *   *************************************************************************/

while (IS_SQ(nextSq)) {

if (b.pieces[nextSq] == PAWN) { // either opposed by enemy pawn or doubled flagIsPassed = 0; if (b.color[nextSq] == side) result -= 20;      // doubled pawn penalty else flagIsOpposed = 1; // flag our pawn as opposed }

if (IS_SQ(nextSq + WEST) && isPiece(!side, PAWN, nextSq + WEST)) flagIsPassed = 0;

if (IS_SQ(nextSq + EAST) && isPiece(!side, PAWN, nextSq + EAST)) flagIsPassed = 0;

nextSq += stepFwd; }

/*************************************************************************   *   Another loop, going backwards and checking whether pawn has support. *   *   Here we can at least break out of it for speed optimization. *   *************************************************************************/

nextSq = sq; while (IS_SQ(nextSq)) {

if (IS_SQ(nextSq + WEST) && isPiece(side, PAWN, nextSq + WEST)) { flagIsWeak = 0; break; }

if (IS_SQ(nextSq + EAST) && isPiece(side, PAWN, nextSq + EAST)) { flagIsWeak = 0; break; }

nextSq += stepBck; }

/*************************************************************************   *  Evaluate passed pawns, scoring them higher if they are protected      * * or if their advance is supported by friendly pawns                    * *************************************************************************/

if ( flagIsPassed ) { if ( isPawnSupported(sq, side) ) result += e.protected_passer[side][sq]; else                            result += e.passed_pawn[side][sq]; }

/*************************************************************************   *  Evaluate weak pawns, increasing the penalty if they are situated      * * on a half-open file                                                   * *************************************************************************/

if ( flagIsWeak ) { result += e.weak_pawn[side][sq]; if (!flagIsOpposed) result -= 4; }

return result; }

int isPawnSupported(S8 sq, S8 side) { int step; if (side == WHITE) step = SOUTH; else step = NORTH;

if ( IS_SQ(sq+WEST) && isPiece(side,PAWN, sq + WEST) ) return 1; if ( IS_SQ(sq+EAST) && isPiece(side,PAWN, sq + EAST) ) return 1; if ( IS_SQ(sq+step+WEST) && isPiece(side,PAWN, sq + step+WEST ) ) return 1; if ( IS_SQ(sq+step+EAST) && isPiece(side,PAWN, sq + step+EAST ) ) return 1;

return 0; }

/******************************************************************************
 * Pattern detection                              *

void blockedPieces {

// central pawn blocked, bishop hard to develop if (isPiece(WHITE, BISHOP, C1) && isPiece(WHITE, PAWN, D2) && b.color[D3] != COLOR_EMPTY) v.Blockages[WHITE] -= e.P_BLOCK_CENTRAL_PAWN; if (isPiece(WHITE, BISHOP, F1) && isPiece(WHITE, PAWN, E2) && b.color[E3] != COLOR_EMPTY) v.Blockages[WHITE] -= e.P_BLOCK_CENTRAL_PAWN; if (isPiece(BLACK, BISHOP, C8) && isPiece(BLACK, PAWN, D7) && b.color[D6] != COLOR_EMPTY) v.Blockages[BLACK] -= e.P_BLOCK_CENTRAL_PAWN; if (isPiece(BLACK, BISHOP, F8) && isPiece(BLACK, PAWN, E7) && b.color[E6] != COLOR_EMPTY) v.Blockages[BLACK] -= e.P_BLOCK_CENTRAL_PAWN;

// uncastled king blocking own rook if ( ( isPiece(WHITE, KING, F1) || isPiece(WHITE, KING, G1 ) )&&        ( isPiece(WHITE, ROOK, H1) || isPiece(WHITE, ROOK, G1 ) )       ) v.Blockages[WHITE] -= e.P_KING_BLOCKS_ROOK;

if ( ( isPiece(WHITE, KING, C1) || isPiece(WHITE, KING, B1 ) )&&        ( isPiece(WHITE, ROOK, A1) || isPiece(WHITE, ROOK, B1 ) )       ) v.Blockages[WHITE] -= e.P_KING_BLOCKS_ROOK;

if ( ( isPiece(BLACK, KING, F8) || isPiece(BLACK, KING, G8 ) )&&        ( isPiece(BLACK, ROOK, H8) || isPiece(BLACK, ROOK, G8 ) )       ) v.Blockages[BLACK] -= e.P_KING_BLOCKS_ROOK;

if ( ( isPiece(BLACK, KING, C8) || isPiece(BLACK, KING, B8 ) )&&        ( isPiece(BLACK, ROOK, A8) || isPiece(BLACK, ROOK, B8 ) )       ) v.Blockages[BLACK] -= e.P_KING_BLOCKS_ROOK; }

int isPiece(U8 color, U8 piece, S8 sq) { return ( (b.pieces[sq] == piece) && (b.color[sq] == color) ); }

/***************************************************************************************
 * Printing eval results                                   *

void printEval { printf("--\n"); printf("Total value (for side to move): %d \n", eval(-INF,INF, 0) ); printf("Material balance   : %d \n", b.PieceMaterial[WHITE] + b.PawnMaterial[WHITE] - b.PieceMaterial[BLACK] - b.PawnMaterial[BLACK] ); printf("Material adjustement: "); printEvalFactor(v.MaterialAdjustement[WHITE], v.MaterialAdjustement[BLACK]); printf("Mg Piece/square tables : "); printEvalFactor(b.PcsqMg[WHITE], b.PcsqMg[BLACK]); printf("Eg Piece/square tables : "); printEvalFactor(b.PcsqEg[WHITE], b.PcsqEg[BLACK]); printf("Mg Mobility           : "); printEvalFactor(v.mgMob[WHITE], v.mgMob[BLACK]); printf("Eg Mobility           : "); printEvalFactor(v.mgMob[WHITE], v.egMob[BLACK]); printf("Pawn structure     : %d \n", evalPawnStructure ); printf("Blockages          : "); printEvalFactor(v.Blockages[WHITE], v.Blockages[BLACK]); printf("Positional themes  : "); printEvalFactor(v.PositionalThemes[WHITE], v.PositionalThemes[BLACK]); printf("King Shield        : "); printEvalFactor(v.kingShield[WHITE], v.kingShield[BLACK]); printf("Tempo: "); if ( b.stm == WHITE ) printf("%d", e.TEMPO); else printf("%d", -e.TEMPO); printf("\n"); printf("--\n"); }

void printEvalFactor(int wh, int bl) { printf("white %4d, black %4d, total: %4d \n", wh, bl, wh - bl); } code

=What links here?= include page="CPW-Engine_eval" component="backlinks" limit="10"
 * Up one Level**