Changes

Jump to: navigation, search

CPW King

3,143 bytes removed, 15:46, 18 December 2018
no edit summary
/* mobility values for various piece kinds */
int bish_mob[16] = { -10, -4, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8 };int rook_mob[16] = { -4, -2, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4 };int knight_mob[9] = { -6, -4, 0, 2, 4, 5, 6, 7, 8};
/* 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};
#define MINOR_ATT 2
struct eval_vector {
int MaterialAdjustement[2]; int Blockages[2]; int PositionalThemes[2]; int Mobility[2]; int KingAttackers[2]; // no. of pieces attacking enemy king int KingPressure[2]; // value of king pressure
} v;
/* global flag used by mobility/attack detection functions to know
if a piece examined currently is a king attacker */
int isAttacker = 0;
int fast_eval() {
/* fold in incrementally updated values */ int result = p.PieceMaterial[WHITE] + p.PawnMaterial[WHITE] + p.Pcsq[WHITE] - p.PieceMaterial[BLACK] - p.PawnMaterial[BLACK] - p.Pcsq[BLACK];
/* evaluate pawn structure, remembering that a pawn list must be set */ result += getPawnScoreNoList();
/* return score relative to the side to move */ if ( b.stm == BLACK ) return -result; else return result;
}
*****************************************************************************/
int eval( int alpha, int beta ) { int result;
/* probe the evaluatinon hashtable */ int probeval = tteval_probe(); if (probeval != INVALID) return probeval;
/* set internal data of the evaluation function */ eval_setPieceLists(); eval_clearVector();
/* sum the incrementally counted material and pcsq values */ result = p.PieceMaterial[WHITE] + p.PawnMaterial[WHITE] + p.Pcsq[WHITE] - p.PieceMaterial[BLACK] - p.PawnMaterial[BLACK] - p.Pcsq[BLACK];
/* tempo bonus */ if ( b.stm == WHITE ) result += e.TEMPO; else result -= e.TEMPO;
/* add in pawn structure evaluation */ result += getPawnScore();
/******************************************************************* * Low material correction - guarding against an illusory material * * advantage. Program will not not expect to win having only * * a single minor piece and no pawns. * *******************************************************************/
if ( ( p.PawnMaterial[WHITE] == 0 ) && ( p.PieceMaterial[WHITE] < 400 ) && ( result > 0 ) ) return 0;
if ( ( p.PawnMaterial[BLACK] == 0 ) && ( p.PieceMaterial[BLACK] < 400 ) && ( result < 0 ) ) return 0;
/******************************************************************* * Program will not expect to win having only two knights in case * * neither side has pawns. Please note that this code assumes * * different values for bishop and knight, and eval_init() should * * take care of that. * *******************************************************************/
if ( !p.PawnMaterial[WHITE] && !p.PawnMaterial[BLACK] ) { if ( p.PieceMaterial[WHITE] == 2 * e.PIECE_VALUE[KNIGHT] && result > 0 ) result = 0; if ( p.PieceMaterial[BLACK] == 2 * e.PIECE_VALUE[KNIGHT] && result < 0 ) result = 0; }
/******************************************************************* * 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 ( p.PieceCount[WHITE][BISHOP] > 1 ) v.MaterialAdjustement[WHITE] += e.BISHOP_PAIR; if ( p.PieceCount[BLACK][BISHOP] > 1 ) v.MaterialAdjustement[BLACK] += e.BISHOP_PAIR; if ( p.PieceCount[WHITE][KNIGHT] > 1 ) v.MaterialAdjustement[WHITE] -= e.P_KNIGHT_PAIR; if ( p.PieceCount[BLACK][KNIGHT] > 1 ) v.MaterialAdjustement[BLACK] -= e.P_KNIGHT_PAIR; if ( p.PieceCount[WHITE] [ROOK] > 1 ) v.MaterialAdjustement[WHITE] -= e.P_ROOK_PAIR; if ( p.PieceCount[BLACK] [ROOK] > 1 ) v.MaterialAdjustement[BLACK] -= e.P_ROOK_PAIR;
// penalty for the lack of pawns - added 28.07.2008 if ( p.PieceCount[WHITE] [PAWN] == 0 ) v.MaterialAdjustement[WHITE] -= 16; if ( p.PieceCount[BLACK] [PAWN] == 0 ) v.MaterialAdjustement[BLACK] -= 16;
/******************************************************************** * Evaluate piece placement. This giant loop calls piece-specific * * functions which tend to do four things: * * * * (1) they look for the trapped pieces and blockages * * (2) they look for rooks on (half) open files * * (3) they calculate mobility and king safety * * (4) they calculate adjustements of material value based on * * the number of pawns * ********************************************************************/
for (int i=0; i < pieceIndex; i++) {
S8 sq = pieceList[i];
switch ( b.color[sq] ) { case WHITE : { switch ( b.pieces[sq] ) { case KNIGHT : wKnightEval(sq); break; case BISHOP : wBishopEval(sq); break; case ROOK : wRookEval(sq); break; case QUEEN : wQueenEval(sq); break; } } break; case BLACK : { switch ( b.pieces[sq] ) { case KNIGHT : bKnightEval(sq); break; case BISHOP : bBishopEval(sq); break; case ROOK : bRookEval(sq); break; case QUEEN : bQueenEval(sq); break; } } break; }
}
}
/******************************************************************** * After the piece evaluation loop we have the king tropism data * * in order, so it is time to do full king evaluation. For details * * see comments in wKingEval() function. * ********************************************************************/
result += wKingEval( p.KingLoc[WHITE] ); result -= bKingEval( p.KingLoc[BLACK] );
/******************************************************************** * Pattern evaluation - mainly things interrelated with the pawn * * position, not fitting elsewhere. * ********************************************************************/
blockedCentralPawns(); // don't block central pawns on initial squares blockedRooks(); // avoid pseudo-castling which blocks the rook slavMistake(); // don't play c4-c5 against Slav / Stonewall evalFianchetto();
/******************************************************************** * Fold in data gathered in evaluation vector. * ********************************************************************/
result += v.MaterialAdjustement[WHITE]; result -= v.MaterialAdjustement[BLACK]; result += v.Blockages[WHITE]; result -= v.Blockages[BLACK]; result += v.PositionalThemes[WHITE]; result -= v.PositionalThemes[BLACK];
/****************************************************************** * Here mobility score is scaled according to the side to move. * * We give more weight to opponent's mobility to encourage * * playing for restraint. * ******************************************************************/
if ( sd.myside == WHITE ) { v.Mobility[BLACK] *= 4; v.Mobility[BLACK] /= 3; } else { v.Mobility[WHITE] *= 4; v.Mobility[WHITE] /= 3; }
result += v.Mobility[WHITE]; result -= v.Mobility[BLACK];
/******************************************************************* * Finally return the score relative to the side to move. * *******************************************************************/
if ( b.stm == BLACK ) result = -result;
// save value in the eval tt tteval_save(result);
return result;
}
void eval_setPieceLists() {
/*********************************************************************** * Create local lists of pieces and pawns. This is done to avoid * * looping through the entire board three times: for pawns, for pieces * * and again evaluating mobility if lazy eval does not produce a cutoff.* ***********************************************************************/
pieceIndex = 0; pawnIndex = 0;
for (U8 row=0; row < 8; row++) for (U8 col=0; col < 8; col++) {
S8 sq = row * 16 + col;
if ( b.color[sq] != COLOR_EMPTY ) { if ( b.pieces[sq] == PAWN ) { pawnList[pawnIndex] = sq; ++pawnIndex; } else { pieceList[pieceIndex] = sq; ++pieceIndex; }
}
}
}
void eval_setPawnLists() {
pawnIndex = 0;
for ( U8 row=0; row < 8; row++ ) for ( U8 col=0; col < 8; col++ ) {
S8 sq = row * 16 + col;
if ( b.color[sq] != COLOR_EMPTY && b.pieces[sq] == PAWN ) { pawnList[pawnIndex] = sq; ++pawnIndex; }
}
}
void eval_clearVector() {
v.MaterialAdjustement[WHITE] = 0; v.MaterialAdjustement[BLACK] = 0; v.PositionalThemes[WHITE] = 0; v.PositionalThemes[BLACK] = 0; v.KingAttackers[WHITE] = 0; v.KingAttackers[BLACK] = 0; v.KingPressure[WHITE] = 0; v.KingPressure[BLACK] = 0; v.Blockages[WHITE] = 0; v.Blockages[BLACK] = 0; v.Mobility[WHITE] = 0; v.Mobility[BLACK] = 0;
}
int wKingEval(S8 sq) {
int result = 0;
if ( p.PieceMaterial[WHITE] < e.ENDGAME_MAT ) { result += e.endgame_king[sq]; } else { result += e.PIECESQUARE[KING][WHITE][sq]; result += wKingShield(); result -= scaleAttacks( v.KingPressure[BLACK], v.KingAttackers[BLACK] );
/* Scale the middlegame king evaluation against remaining enemy material */ result *= p.PieceMaterial[BLACK]; result /= e.START_MATERIAL; }
return result;
}
int bKingEval(S8 sq) {
int result = 0;
if ( p.PieceMaterial[BLACK] < e.ENDGAME_MAT ) { result += e.endgame_king[sq]; } else { result += e.PIECESQUARE[KING][BLACK][sq]; result += bKingShield(); result -= scaleAttacks( v.KingPressure[WHITE], v.KingAttackers[WHITE] );
/* Scale the middlegame king evaluation against remaining enemy material */ result *= p.PieceMaterial[WHITE]; result /= e.START_MATERIAL; }
return result;
}
int scaleAttacks(int attack_value, int n_of_attackers) {
int result;
switch ( n_of_attackers ) { case 0 : result = 0; case 1 : result = 0; case 2 : result = attack_value; case 3 : result = ( attack_value * 4 ) / 3; case 4 : result = ( attack_value * 3 ) / 2; default: result = attack_value * 2; }
return result;
}
int wKingShield() {
int result = 0;
/* king on the kingside */ if ( COL(p.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; else if ( p.PawnsOnFile [WHITE] [ COL_G ] == 0 ) result -= e.P_NO_SHIELD;
if ( isPiece(WHITE, PAWN, H2) ) result += e.SHIELD_1; else if ( isPiece(WHITE, PAWN, H3) ) result += e.SHIELD_2; else if ( p.PawnsOnFile [WHITE] [ COL_H ] == 0 ) result -= e.P_NO_SHIELD; }
/* king on the queenside */ else if ( COL(p.KingLoc[WHITE]) < COL_D ) {
if ( isPiece(WHITE, PAWN, A2) ) result += e.SHIELD_1; else if ( isPiece(WHITE, PAWN, A3) ) result += e.SHIELD_2; else if ( p.PawnsOnFile [WHITE] [ COL_A ] == 0 ) result -= e.P_NO_SHIELD;
if ( isPiece(WHITE, PAWN, B2) ) result += e.SHIELD_1; else if ( isPiece(WHITE, PAWN, B3) ) result += e.SHIELD_2; else if ( p.PawnsOnFile [WHITE] [ COL_B ] == 0 ) result -= e.P_NO_SHIELD;
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(p.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; else if ( p.PawnsOnFile [BLACK] [ COL_G ] == 0 ) result -= e.P_NO_SHIELD;
if ( isPiece(BLACK, PAWN, H7) ) result += e.SHIELD_1; else if ( isPiece(BLACK, PAWN, H6) ) result += e.SHIELD_2; else if ( p.PawnsOnFile [BLACK] [ COL_H ] == 0 ) result -= e.P_NO_SHIELD; }
/* king on the queenside */ else if ( COL(p.KingLoc[BLACK]) < COL_D ) { if ( isPiece(BLACK, PAWN, A7) ) result += e.SHIELD_1; else if ( isPiece(BLACK, PAWN, A6) ) result += e.SHIELD_2; else if ( p.PawnsOnFile [BLACK] [ COL_A ] == 0 ) result -= e.P_NO_SHIELD;
if ( isPiece(BLACK, PAWN, B7) ) result += e.SHIELD_1; else if ( isPiece(BLACK, PAWN, B6) ) result += e.SHIELD_2; else if ( p.PawnsOnFile [BLACK] [ COL_B ] == 0 ) result -= e.P_NO_SHIELD;
if ( isPiece(BLACK, PAWN, C7) ) result += e.SHIELD_1; else if ( isPiece(BLACK, PAWN, C6) ) result += e.SHIELD_2;
}
return result;
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 getPawnScoreNoList() {
int result;
int probeval = ttpawn_probe(); if (probeval != INVALID) return probeval;
eval_setPawnLists(); result = evalPawnStructure();
ttpawn_save(result);
return result;
}
int evalPawnStructure() {
int result = 0;
/* 1. evaluate pawn center */ result += evalPawnCenter();
/* 2. evaluate doubled/tripled pawns */ for (U8 col=0; col < 8; col++) { result -= e.P_MULTI_PAWN[ p.PawnsOnFile [WHITE] [col] ]; result += e.P_MULTI_PAWN[ p.PawnsOnFile [BLACK] [col] ]; }
/* 3. core procedure: loop through pawn list, evaluating each pawn on the board */ for (U8 i=0; i < pawnIndex; i++) {
S8 sq = pawnList[i];
if (b.color[sq] == WHITE) result += wPawnEval(sq); else result -= bPawnEval(sq); } return result;
}
int evalPawnCenter() {
int result = 0;
if ( isPiece(WHITE, PAWN, D4) ) { if (isPiece(WHITE, PAWN, E4 ) ) result += e.DUO_D4E4; if (isPiece(WHITE, PAWN, C4 ) ) result += e.DUO_D4C4; if (isPiece(WHITE, PAWN, E3 ) ) result += e.DUO_D4E3; }
if ( isPiece(WHITE, PAWN, E4) ) { if (isPiece(WHITE, PAWN, F4 ) ) result += e.DUO_E4F4; if (isPiece(WHITE, PAWN, D3 ) ) result += e.DUO_E4D3; }
if ( isPiece(BLACK, PAWN, D5) ) { if (isPiece(BLACK, PAWN, E5 ) ) result -= e.DUO_D4E4; if (isPiece(BLACK, PAWN, C5 ) ) result -= e.DUO_D4C4; if (isPiece(BLACK, PAWN, E6 ) ) result -= e.DUO_D4E3; }
if ( isPiece(BLACK, PAWN, E5) ) { if (isPiece(BLACK, PAWN, F5 ) ) result -= e.DUO_E4F4; if (isPiece(BLACK, PAWN, D6 ) ) result -= e.DUO_E4D3; }
return result;
}
int wPawnEval(S8 sq) {
int result = 0;
/* 1. Evaluate passed pawns, scoring them higher if they are protected by friendly pawns */
if ( isWPFree(sq) ) { if (isWPSupported(sq) ) result += e.w_protected_passer[sq]; else result += e.w_passed_pawn[sq]; }
/* 2. Evaluate weak pawns */
if ( isWPWeak(sq) ) { result += e.w_weak_pawn[sq]; /* weak pawns on half-open files tend to be even weaker */ if ( p.PawnsOnFile[BLACK] [COL( sq) ] == 0 ) result -= 4; }
return result;
}
int bPawnEval(S8 sq) {
int result = 0;
/* 1. Evaluate passed pawns, scoring them higher if they are protected by friendly pawns */
if ( isBPFree(sq) ) { if ( isBPSupported(sq) ) result += e.b_protected_passer[sq]; else result += e.b_passed_pawn[sq]; }
/* 2. Evaluate weak pawns */
if ( isBPWeak(sq) ) { result += e.b_weak_pawn[sq]; /* weak pawns on half-open files tend to be even weaker */ if ( p.PawnsOnFile[WHITE] [COL( sq) ] == 0 ) result -= 4; }
return result;
}
int isWPFree(S8 sq) {
S8 nextSq = sq + NORTH;
while ( IS_SQ(nextSq) ) {
/* either blocked by enemy pawn or doubled */ if ( b.pieces[nextSq] == PAWN ) return 0;
if ( IS_SQ(nextSq + WEST) && isPiece(BLACK, PAWN, nextSq + WEST) ) return 0;
if ( IS_SQ(nextSq + EAST) && isPiece(BLACK, PAWN, nextSq + EAST) ) return 0;
nextSq += NORTH; }
return 1;
}
int isBPFree(S8 sq) {
S8 nextSq = sq + SOUTH;
while ( IS_SQ(nextSq) ) {
/* either blocked by enemy pawn or doubled */ if ( b.pieces[nextSq] == PAWN ) return 0;
if ( IS_SQ(nextSq + WEST) && isPiece(WHITE, PAWN, nextSq + WEST) ) return 0;
if ( IS_SQ(nextSq + EAST) && isPiece(WHITE, PAWN, nextSq + EAST) ) return 0;
nextSq += SOUTH; }
return 1;
}
int isWPWeak(S8 sq) {
S8 nextSq = sq;
while ( IS_SQ(nextSq) ) {
if ( IS_SQ(nextSq + WEST) && isPiece(WHITE, PAWN, nextSq + WEST) ) return 0;
if ( IS_SQ(nextSq + EAST) && isPiece(WHITE, PAWN, nextSq + EAST) ) return 0;
nextSq += SOUTH; }
return 1;
}
int isBPWeak(S8 sq) {
S8 nextSq = sq;
while ( IS_SQ(nextSq) ) {
if ( IS_SQ(nextSq + WEST) && isPiece(BLACK, PAWN, nextSq + WEST) ) return 0;
if ( IS_SQ(nextSq + EAST) && isPiece(BLACK, PAWN, nextSq + EAST) ) return 0;
nextSq += NORTH; }
return 1;
}
int isWPSupported(S8 sq) {
if ( IS_SQ(sq+WEST) && isPiece(WHITE,PAWN, sq + WEST) ) return 1; if ( IS_SQ(sq+EAST) && isPiece(WHITE,PAWN, sq + EAST) ) return 1; if ( IS_SQ( sq+SE ) && isPiece(WHITE,PAWN, sq + SE ) ) return 1; if ( IS_SQ( sq+SW ) && isPiece(WHITE,PAWN, sq + SW ) ) return 1;
return 0;
}
int isBPSupported(S8 sq) {
if ( IS_SQ(sq+WEST) && isPiece(BLACK,PAWN, sq + WEST) ) return 1; if ( IS_SQ(sq+EAST) && isPiece(BLACK,PAWN, sq + EAST) ) return 1; if ( IS_SQ( sq+NE ) && isPiece(BLACK,PAWN, sq + NE ) ) return 1; if ( IS_SQ( sq+NW ) && isPiece(BLACK,PAWN, sq + NW ) ) return 1;
return 0;
}
void wKnightEval(S8 sq) {
/* material value adjustement based on the no. of own pawns */ v.MaterialAdjustement[WHITE] += knight_adj[ p.PieceCount[WHITE] [PAWN] ];
/* mobility and king attacks calculation */ v.Mobility[WHITE] += wKnightMob(sq);
/* trapped or blocking knight */ 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; }
}
void bKnightEval(S8 sq) {
/* material value adjustement based on the no. of own pawns */ v.MaterialAdjustement[BLACK] += knight_adj[ p.PieceCount[BLACK] [PAWN] ];
/* mobility and king attack calculation */ v.Mobility[BLACK] += bKnightMob(sq);
/* trapped or blocking knight */ 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; }
}
void wBishopEval(S8 sq) {
/* mobility and king attack calculaion */ v.Mobility[WHITE] += wBishopMob(sq);
/* trapped bishop and returning bishop */ 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; }
}
void bBishopEval(S8 sq) {
/* mobility and king attack calculation */ v.Mobility[BLACK] += bBishopMob(sq);
/* trapped bishop and returning bishop */ 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; }
}
void wRookEval(S8 sq) {
/* material value adjustement based on the no. of own pawns */ v.MaterialAdjustement[WHITE] += rook_adj[ p.PieceCount[WHITE] [PAWN] ];
/* mobility and king attack calculation */ v.Mobility[WHITE] += wRookMob(sq);
/* open and half-open files */ if ( p.PawnsOnFile [WHITE] [ COL(sq) ] == 0 ) {
if ( p.PawnsOnFile [BLACK] [ COL(sq) ] == 0 ) v.PositionalThemes[WHITE] += e.ROOK_OPEN; else v.PositionalThemes[WHITE] += e.ROOK_HALF; }
}
void bRookEval(S8 sq) {
/* material value adjustement based on the no. of own pawns */ v.MaterialAdjustement[BLACK] += rook_adj[ p.PieceCount[BLACK] [PAWN] ];
/* mobility and king attack calculation */ v.Mobility[BLACK] += bRookMob(sq);
/* open and half-open files */ if ( p.PawnsOnFile [BLACK] [ COL(sq) ] == 0 ) {
if ( p.PawnsOnFile [WHITE] [ COL(sq) ] == 0 ) v.PositionalThemes[BLACK] += e.ROOK_OPEN; else v.PositionalThemes[BLACK] += e.ROOK_HALF; }
}
void wQueenEval(S8 sq) {
/* mobility and king attack calculation */ v.Mobility[WHITE] += wQueenMob(sq);
/* penalize premature developement */ if ( 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; }
}
void bQueenEval(S8 sq) {
/* mobility and king attack calculation */ v.Mobility[BLACK] += bQueenMob(sq);
/* penalize premature developement */ if ( 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; }
}
int wKnightMob(S8 sq) {
isAttacker = 0; int localMobility = leaperMobility(WHITE, sq, KNIGHT, MINOR_ATT); if ( isAttacker ) ++v.KingAttackers[WHITE];
return knight_mob[localMobility];
}
int bKnightMob(S8 sq) {
isAttacker = 0; int localMobility = leaperMobility(BLACK, sq, KNIGHT, MINOR_ATT); if ( isAttacker ) ++v.KingAttackers[BLACK];
return knight_mob[localMobility];
}
int wBishopMob(S8 sq) {
isAttacker = 0;
int localMobility = sliderMobility(WHITE, sq, NE, MINOR_ATT ) + sliderMobility(WHITE, sq, NW, MINOR_ATT ) + sliderMobility(WHITE, sq, SE, MINOR_ATT ) + sliderMobility(WHITE, sq, SW, MINOR_ATT );
if ( isAttacker ) ++v.KingAttackers[WHITE];
return bish_mob[localMobility];
}
int bBishopMob(S8 sq) {
isAttacker = 0;
int localMobility = sliderMobility(BLACK, sq, NE, MINOR_ATT ) + sliderMobility(BLACK, sq, NW, MINOR_ATT ) + sliderMobility(BLACK, sq, SE, MINOR_ATT ) + sliderMobility(BLACK, sq, SW, MINOR_ATT );
if ( isAttacker ) ++v.KingAttackers[BLACK];
return bish_mob[localMobility];
}
int wRookMob(S8 sq) {
isAttacker = 0;
int localMobility = sliderMobility(WHITE, sq, NORTH, ROOK_ATT ) + sliderMobility(WHITE, sq, SOUTH, ROOK_ATT ) + sliderMobility(WHITE, sq, EAST, ROOK_ATT ) + sliderMobility(WHITE, sq, WEST, ROOK_ATT );
if ( isAttacker ) ++v.KingAttackers[WHITE];
return rook_mob[localMobility];
}
int bRookMob(S8 sq) {
isAttacker = 0;
int localMobility = sliderMobility(BLACK, sq, NORTH, ROOK_ATT ) + sliderMobility(BLACK, sq, SOUTH, ROOK_ATT ) + sliderMobility(BLACK, sq, EAST, ROOK_ATT ) + sliderMobility(BLACK, sq, WEST, ROOK_ATT );
if ( isAttacker ) ++v.KingAttackers[BLACK];
return rook_mob[localMobility];
}
int wQueenMob(S8 sq) {
isAttacker = 0;
int localMobility = sliderMobility(WHITE, sq, NORTH, QUEEN_ATT ) + sliderMobility(WHITE, sq, SOUTH, QUEEN_ATT ) + sliderMobility(WHITE, sq, EAST, QUEEN_ATT ) + sliderMobility(WHITE, sq, WEST, QUEEN_ATT ) + sliderMobility(WHITE, sq, NE, QUEEN_ATT ) + sliderMobility(WHITE, sq, NW, QUEEN_ATT ) + sliderMobility(WHITE, sq, SE, QUEEN_ATT ) + sliderMobility(WHITE, sq, SW, QUEEN_ATT );
if ( isAttacker ) ++v.KingAttackers[WHITE];
return 0;
}
int bQueenMob(S8 sq) {
isAttacker = 0;
int localMobility = sliderMobility(BLACK, sq, NORTH, QUEEN_ATT ) + sliderMobility(BLACK, sq, SOUTH, QUEEN_ATT ) + sliderMobility(BLACK, sq, EAST, QUEEN_ATT ) + sliderMobility(BLACK, sq, WEST, QUEEN_ATT ) + sliderMobility(BLACK, sq, NE, QUEEN_ATT ) + sliderMobility(BLACK, sq, NW, QUEEN_ATT ) + sliderMobility(BLACK, sq, SE, QUEEN_ATT ) + sliderMobility(BLACK, sq, SW, QUEEN_ATT );
if ( isAttacker ) ++v.KingAttackers[BLACK];
return 0;
}
int sliderMobility(U8 color, S8 sq, int vect, int attBonus) {
int nextSq = sq + vect; int result = 0;
while ( IS_SQ(nextSq) ) {
if ( e.sqNearK[!color] [p.KingLoc[!color] ] [nextSq] ) { isAttacker = 1; v.KingPressure[color] += attBonus; }
if (b.color[nextSq] != COLOR_EMPTY ) { if ( b.color[nextSq] != color ) return result + 1; return result; }
++result;
nextSq = nextSq + vect; }
return result;
}
int leaperMobility(U8 color, S8 sq, char byPiece, int attBonus) {
S8 nextSq; int result = 0;
for (U8 dir=0;dir<8;dir++) { nextSq = sq + vector[byPiece][dir];
if ( IS_SQ(nextSq) && b.color[nextSq] != color ) {
/* king attack */ if ( e.sqNearK[!color] [p.KingLoc[!color] ] [nextSq] ) { isAttacker = 1; v.KingPressure[color] += attBonus; } ++result; }
}
}
return result;
}
void blockedCentralPawns() {
if ( isPiece(WHITE,PAWN,D2) && b.color[D3] != COLOR_EMPTY ) v.Blockages[WHITE] -= e.P_BLOCK_CENTRAL_PAWN; if ( isPiece(WHITE,PAWN,E2) && b.color[E3] != COLOR_EMPTY ) v.Blockages[WHITE] -= e.P_BLOCK_CENTRAL_PAWN; if ( isPiece(BLACK,PAWN,D7) && b.color[D6] != COLOR_EMPTY ) v.Blockages[BLACK] -= e.P_BLOCK_CENTRAL_PAWN; if ( isPiece(BLACK,PAWN,E7) && b.color[E6] != COLOR_EMPTY ) v.Blockages[BLACK] -= e.P_BLOCK_CENTRAL_PAWN;
}
void blockedRooks() {
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;
}
void slavMistake() {
if ( isPiece(WHITE, PAWN, D4) && isPiece(WHITE, PAWN, C5) && isPiece(BLACK, PAWN, D5) && isPiece(BLACK, PAWN, C6) ) v.PositionalThemes[WHITE] -= e.P_SLAV_MISTAKE;
if ( isPiece(BLACK, PAWN, D5) && isPiece(BLACK, PAWN, C4) && isPiece(WHITE, PAWN, D4) && isPiece(WHITE, PAWN, C3) ) v.PositionalThemes[BLACK] -= e.P_SLAV_MISTAKE;
}
void evalFianchetto() {
if ( isPiece(WHITE, PAWN, G3) ) { if ( isPiece(WHITE, BISHOP, G2 ) ) v.PositionalThemes[WHITE] += e.FIANCHETTO; else { if ( !isPiece(WHITE, BISHOP, F3 ) && !isPiece(WHITE, BISHOP, H1 ) && !isPiece(WHITE, BISHOP, H3 ) ) v.PositionalThemes[WHITE] -= e.P_NO_FIANCHETTO; }
}
}
if ( isPiece(WHITE, PAWN, B3) ) { if ( isPiece(WHITE, BISHOP, B2 ) ) v.PositionalThemes[WHITE] += e.FIANCHETTO; else { if ( !isPiece(WHITE, BISHOP, C3 ) && !isPiece(WHITE, BISHOP, A1 ) && !isPiece(WHITE, BISHOP, A3 ) )
v.PositionalThemes[WHITE] -= e.P_NO_FIANCHETTO; }
}
}
if ( isPiece(BLACK, PAWN, G6) ) { if ( isPiece(BLACK, BISHOP, G7 ) ) v.PositionalThemes[BLACK] += e.FIANCHETTO; else { if ( !isPiece(BLACK, BISHOP, F6 ) && !isPiece(BLACK, BISHOP, H8 ) && !isPiece(BLACK, BISHOP, H6 ) ) v.PositionalThemes[BLACK] -= e.P_NO_FIANCHETTO; }
}
}
if ( isPiece(BLACK, PAWN, B6) ) { if ( isPiece(BLACK, BISHOP, B7 ) ) v.PositionalThemes[BLACK] += e.P_NO_FIANCHETTO; else { if ( !isPiece(BLACK, BISHOP, C6 ) && !isPiece(BLACK, BISHOP, A8 ) && !isPiece(BLACK, BISHOP, A6 ) ) v.PositionalThemes[BLACK] -= e.P_NO_FIANCHETTO; }
}
}
}
/* determine if two squares lie on the same or neighbouring columns */
int isNearCol(S8 sq1, S8 sq2) {
U8 c1 = COL(sq1); U8 c2 = COL(sq2); U8 hor_dist = (U8) abs(c1 - c2);
if ( hor_dist < 2 ) return 1; else return 0;
}
int isPiece(U8 color, U8 piece, S8 sq) {
return ( (b.pieces[sq] == piece) && (b.color[sq] == color) );
}
void printEval() {
eval(-30000,30000); printf("------------------------------------------\n"); printf("Total value (for side to move): %d \n", eval(-INFINITY,INFINITY) ); printf("Material balance : %d \n", p.PieceMaterial[WHITE] + p.PawnMaterial[WHITE] - p.PieceMaterial[BLACK] - p.PawnMaterial[BLACK] ); printf("Material adjustement: %d \n", v.MaterialAdjustement[WHITE] - v.MaterialAdjustement[BLACK]); printf("Piece/square tables : %d \n", p.Pcsq[WHITE] - p.Pcsq[BLACK]); printf("Pawn structure : %d \n", evalPawnStructure() ); printf("Blockages : %d \n", v.Blockages[WHITE] - v.Blockages[BLACK] ); printf("Positional themes : %d \n", v.PositionalThemes[WHITE] - v.PositionalThemes[BLACK] ); printf("Mobility: white %d, black %d, total %d \n", v.Mobility[WHITE], v.Mobility[BLACK], v.Mobility[WHITE] - v.Mobility[BLACK] ); printf("King pressure: white %d, black %d \n", v.KingPressure[WHITE], v.KingPressure[BLACK] ); printf("King attackers: white %d, black %d \n", v.KingAttackers[WHITE], v.KingAttackers[BLACK] ); printf("Kings: white %d , black %d, total: %d \n", wKingEval(p.KingLoc[WHITE]), bKingEval(p.KingLoc[BLACK] ), wKingEval(p.KingLoc[WHITE])-bKingEval(p.KingLoc[BLACK]) ); printf("Tempo: "); if ( b.stm == WHITE ) printf("%d", e.TEMPO); else printf("%d", -e.TEMPO); printf("\n"); printf("------------------------------------------\n");
}
</pre>
'''[[CPW-Engine|Up one Level]]'''

Navigation menu