CPW-Engine eval init
Home * Engines * CPW-Engine * eval_init
Initialization of the evaluation function.This is used once when the program is started and the values are not changed afterwards.Program supports also reading most of the values from a file.Later version might read piece / square tables in the same way, but that is not strictly necessary.
Code
#include "stdafx.h" #include "0x88_math.h" s_eval_data e; // tables used for translating piece/square tables to internal 0x88 representation int index_white[64] = { A8, B8, C8, D8, E8, F8, G8, H8, A7, B7, C7, D7, E7, F7, G7, H7, A6, B6, C6, D6, E6, F6, G6, H6, A5, B5, C5, D5, E5, F5, G5, H5, A4, B4, C4, D4, E4, F4, G4, H4, A3, B3, C3, D3, E3, F3, G3, H3, A2, B2, C2, D2, E2, F2, G2, H2, A1, B1, C1, D1, E1, F1, G1, H1 }; int index_black[64] = { A1, B1, C1, D1, E1, F1, G1, H1, A2, B2, C2, D2, E2, F2, G2, H2, A3, B3, C3, D3, E3, F3, G3, H3, A4, B4, C4, D4, E4, F4, G4, H4, A5, B5, C5, D5, E5, F5, G5, H5, A6, B6, C6, D6, E6, F6, G6, H6, A7, B7, C7, D7, E7, F7, G7, H7, A8, B8, C8, D8, E8, F8, G8, H8 }; int dist_bonus[64][64]; /***************************************************************** * PAWN PCSQ * * * * Unlike TSCP, CPW generally doesn't want to advance its pawns * * just for the fun of it. It takes into account the following: * * * * - file-dependent component, encouraging program to capture * * towards the center * * - small bonus for staying on the 2nd rank * * - small bonus for standing on a3/h3 * * - penalty for d/e pawns on their initial squares * * - bonus for occupying the center * *****************************************************************/ int pawn_pcsq_mg[64] = { 0, 0, 0, 0, 0, 0, 0, 0, -6, -4, 1, 1, 1, 1, -4, -6, -6, -4, 1, 2, 2, 1, -4, -6, -6, -4, 2, 8, 8, 2, -4, -6, -6, -4, 5, 10, 10, 5, -4, -6, -4, -4, 1, 5, 5, 1, -4, -4, -6, -4, 1, -24, -24, 1, -4, -6, 0, 0, 0, 0, 0, 0, 0, 0 }; int pawn_pcsq_eg[64] = { 0, 0, 0, 0, 0, 0, 0, 0, -6, -4, 1, 1, 1, 1, -4, -6, -6, -4, 1, 2, 2, 1, -4, -6, -6, -4, 2, 8, 8, 2, -4, -6, -6, -4, 5, 10, 10, 5, -4, -6, -4, -4, 1, 5, 5, 1, -4, -4, -6, -4, 1, -24, -24, 1, -4, -6, 0, 0, 0, 0, 0, 0, 0, 0 }; /**************************************************************** * KNIGHT PCSQ * * * * - centralization bonus * * - penalty for not being developed * ****************************************************************/ int knight_pcsq_mg[64] = { -8, -8, -8, -8, -8, -8, -8, -8, -8, 0, 0, 0, 0, 0, 0, -8, -8, 0, 4, 4, 4, 4, 0, -8, -8, 0, 4, 8, 8, 4, 0, -8, -8, 0, 4, 8, 8, 4, 0, -8, -8, 0, 4, 4, 4, 4, 0, -8, -8, 0, 1, 2, 2, 1, 0, -8, -8, -12, -8, -8, -8, -8, -12, -8 }; int knight_pcsq_eg[64] = { -8, -8, -8, -8, -8, -8, -8, -8, -8, 0, 0, 0, 0, 0, 0, -8, -8, 0, 4, 4, 4, 4, 0, -8, -8, 0, 4, 8, 8, 4, 0, -8, -8, 0, 4, 8, 8, 4, 0, -8, -8, 0, 4, 4, 4, 4, 0, -8, -8, 0, 1, 2, 2, 1, 0, -8, -8, -12, -8, -8, -8, -8, -12, -8 }; /**************************************************************** * BISHOP PCSQ * * * * - centralization bonus, smaller than for knight * * - penalty for not being developed * * - good squares on the own half of the board * ****************************************************************/ int bishop_pcsq_mg[64] = { -4, -4, -4, -4, -4, -4, -4, -4, -4, 0, 0, 0, 0, 0, 0, -4, -4, 0, 2, 4, 4, 2, 0, -4, -4, 0, 4, 6, 6, 4, 0, -4, -4, 0, 4, 6, 6, 4, 0, -4, -4, 1, 2, 4, 4, 2, 1, -4, -4, 2, 1, 1, 1, 1, 2, -4, -4, -4, -12, -4, -4, -12, -4, -4 }; int bishop_pcsq_eg[64] = { -4, -4, -4, -4, -4, -4, -4, -4, -4, 0, 0, 0, 0, 0, 0, -4, -4, 0, 2, 4, 4, 2, 0, -4, -4, 0, 4, 6, 6, 4, 0, -4, -4, 0, 4, 6, 6, 4, 0, -4, -4, 1, 2, 4, 4, 2, 1, -4, -4, 2, 1, 1, 1, 1, 2, -4, -4, -4, -12, -4, -4, -12, -4, -4 }; /**************************************************************** * ROOK PCSQ * * * * - bonus for 7th and 8th ranks * * - penalty for a/h columns * * - small centralization bonus * *****************************************************************/ int rook_pcsq_mg[64] = { 5, 5, 5, 5, 5, 5, 5, 5, 20, 20, 20, 20, 20, 20, 20, 20, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0, 2, 2, 0, 0, 0 }; int rook_pcsq_eg[64] = { 5, 5, 5, 5, 5, 5, 5, 5, 20, 20, 20, 20, 20, 20, 20, 20, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0, 2, 2, 0, 0, 0 }; /*************************************************************************** * QUEEN PCSQ * * * * - small bonus for centralization in the endgame * * - penalty for staying on the 1st rank, between rooks in the midgame * ***************************************************************************/ int queen_pcsq_mg[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 2, 3, 3, 2, 0, 0, 0, 0, 2, 3, 3, 2, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, -5, -5, -5, -5, -5, -5, -5, -5 }; int queen_pcsq_eg[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 2, 3, 3, 2, 0, 0, 0, 0, 2, 3, 3, 2, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, -5, -5, -5, -5, -5, -5, -5, -5 }; int king_pcsq_mg[64] = { -40, -30, -50, -70, -70, -50, -30, -40, -30, -20, -40, -60, -60, -40, -20, -30, -20, -10, -30, -50, -50, -30, -10, -20, -10, 0, -20, -40, -40, -20, 0, -10, 0, 10, -10, -30, -30, -10, 10, 0, 10, 20, 0, -20, -20, 0, 20, 10, 30, 40, 20, 0, 0, 20, 40, 30, 40, 50, 30, 10, 10, 30, 50, 40 }; int king_pcsq_eg[64] = { -72, -48, -36, -24, -24, -36, -48, -72, -48, -24, -12, 0, 0, -12, -24, -48, -36, -12, 0, 12, 12, 0, -12, -36, -24, 0, 12, 24, 24, 12, 0, -24, -24, 0, 12, 24, 24, 12, 0, -24, -36, -12, 0, 12, 12, 0, -12, -36, -48, -24, -12, 0, 0, -12, -24, -48, -72, -48, -36, -24, -24, -36, -48, -72 }; /***************************************************************** * WEAK PAWNS PCSQ * * * * Current version of CPW-engine does not differentiate between * * isolated and backward pawns, using one generic cathegory * * of weak pawns. The penalty is bigger in the center, on the * * assumption that weak central pawns can be attacked from * * many directions. If the penalty seems too low, please note * * that being on a semi-open file will come into equation, too. * *****************************************************************/ int weak_pawn_pcsq[64] = { 0, 0, 0, 0, 0, 0, 0, 0, -10, -12, -14, -16, -16, -14, -12, -10, -10, -12, -14, -16, -16, -14, -12, -10, -10, -12, -14, -16, -16, -14, -12, -10, -10, -12, -14, -16, -16, -14, -12, -10, -8, -12, -14, -16, -16, -14, -12, -10, -8, -12, -14, -16, -16, -14, -12, -10, 0, 0, 0, 0, 0, 0, 0, 0 }; int passed_pawn_pcsq[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 100, 100, 100, 100, 100, 100, 100, 100, 80, 80, 80, 80, 80, 80, 80, 80, 60, 60, 60, 60, 60, 60, 60, 60, 40, 40, 40, 40, 40, 40, 40, 40, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0 }; void setDefaultEval() { setBasicValues(); setSquaresNearKing(); setPcsq(); readIniFile(); correctValues(); } void setBasicValues() { /******************************************************************************** * We use material values by IM Larry Kaufman with additional + 10 for a Bishop * * and only +30 for a Bishop pair * ********************************************************************************/ e.PIECE_VALUE[KING] = 0; e.PIECE_VALUE[QUEEN] = 975; e.PIECE_VALUE[ROOK] = 500; e.PIECE_VALUE[BISHOP] = 335; e.PIECE_VALUE[KNIGHT] = 325; e.PIECE_VALUE[PAWN] = 100; e.BISHOP_PAIR = 30; e.P_KNIGHT_PAIR = 8; e.P_ROOK_PAIR = 16; /************************************************* * Calculate the value of piece material * * at the beginning of the game, which is * * used for scaling the king tropism evaluation. * * This way we don't have to update a constant * * every time we change material values. * *************************************************/ e.START_MATERIAL = e.PIECE_VALUE[QUEEN] + 2 * e.PIECE_VALUE[ROOK] + 2 * e.PIECE_VALUE[BISHOP] + 2 * e.PIECE_VALUE[KNIGHT]; /************************************************* * Values used for sorting captures are the same * * as normal piece values, except for a king. * *************************************************/ for (int i = 0; i < 6; ++i) { e.SORT_VALUE[i] = e.PIECE_VALUE[i]; } e.SORT_VALUE[KING] = SORT_KING; /* trapped and blocked pieces */ e.P_KING_BLOCKS_ROOK = 24; e.P_BLOCK_CENTRAL_PAWN = 24; e.P_BISHOP_TRAPPED_A7 = 150; e.P_BISHOP_TRAPPED_A6 = 50; e.P_KNIGHT_TRAPPED_A8 = 150; e.P_KNIGHT_TRAPPED_A7 = 100; /* minor penalties */ e.P_C3_KNIGHT = 5; e.P_NO_FIANCHETTO = 4; /* king's defence */ e.SHIELD_1 = 10; e.SHIELD_2 = 5; e.P_NO_SHIELD = 10; /* minor bonuses */ e.ROOK_OPEN = 10; e.ROOK_HALF = 5; e.RETURNING_BISHOP = 20; e.FIANCHETTO = 4; e.TEMPO = 10; e.ENDGAME_MAT = 1300; } void setSquaresNearKing() { for (int i = 0; i < 128; ++i) for (int j = 0; j < 128; ++j) { e.sqNearK[WHITE][i][j] = 0; e.sqNearK[BLACK][i][j] = 0; if (IS_SQ(i) && IS_SQ(j)) { // squares constituting the ring around both kings if (j == i + NORTH || j == i + SOUTH || j == i + EAST || j == i + WEST || j == i + NW || j == i + NE || j == i + SW || j == i + SE) { e.sqNearK[WHITE][i][j] = 1; e.sqNearK[BLACK][i][j] = 1; } /* squares in front of the white king ring */ if (j == i + NORTH + NORTH || j == i + NORTH + NE || j == i + NORTH + NW) e.sqNearK[WHITE][i][j] = 1; // squares in front og the black king ring if (j == i + SOUTH + SOUTH || j == i + SOUTH + SE || j == i + SOUTH + SW) e.sqNearK[WHITE][i][j] = 1; } } } void setPcsq() { for (int i = 0; i < 64; ++i) { e.weak_pawn[WHITE][index_white[i]] = weak_pawn_pcsq[i]; e.weak_pawn[BLACK][index_black[i]] = weak_pawn_pcsq[i]; e.passed_pawn[WHITE][index_white[i]] = passed_pawn_pcsq[i]; e.passed_pawn[BLACK][index_black[i]] = passed_pawn_pcsq[i]; /* protected passers are considered slightly stronger than ordinary passed pawns */ e.protected_passer[WHITE][index_white[i]] = (passed_pawn_pcsq[i] * 10) / 8; e.protected_passer[BLACK][index_black[i]] = (passed_pawn_pcsq[i] * 10) / 8; /* now set the piece/square tables for each color and piece type */ e.mgPst[PAWN][WHITE][index_white[i]] = pawn_pcsq_mg[i]; e.mgPst[PAWN][BLACK][index_black[i]] = pawn_pcsq_mg[i]; e.mgPst[KNIGHT][WHITE][index_white[i]] = knight_pcsq_mg[i]; e.mgPst[KNIGHT][BLACK][index_black[i]] = knight_pcsq_mg[i]; e.mgPst[BISHOP][WHITE][index_white[i]] = bishop_pcsq_mg[i]; e.mgPst[BISHOP][BLACK][index_black[i]] = bishop_pcsq_mg[i]; e.mgPst[ROOK][WHITE][index_white[i]] = rook_pcsq_mg[i]; e.mgPst[ROOK][BLACK][index_black[i]] = rook_pcsq_mg[i]; e.mgPst[QUEEN][WHITE][index_white[i]] = queen_pcsq_mg[i]; e.mgPst[QUEEN][BLACK][index_black[i]] = queen_pcsq_mg[i]; e.mgPst[KING][WHITE][index_white[i]] = king_pcsq_mg[i]; e.mgPst[KING][BLACK][index_black[i]] = king_pcsq_mg[i]; e.egPst[PAWN][WHITE][index_white[i]] = pawn_pcsq_eg[i]; e.egPst[PAWN][BLACK][index_black[i]] = pawn_pcsq_eg[i]; e.egPst[KNIGHT][WHITE][index_white[i]] = knight_pcsq_eg[i]; e.egPst[KNIGHT][BLACK][index_black[i]] = knight_pcsq_eg[i]; e.egPst[BISHOP][WHITE][index_white[i]] = bishop_pcsq_eg[i]; e.egPst[BISHOP][BLACK][index_black[i]] = bishop_pcsq_eg[i]; e.egPst[ROOK][WHITE][index_white[i]] = rook_pcsq_eg[i]; e.egPst[ROOK][BLACK][index_black[i]] = rook_pcsq_eg[i]; e.egPst[QUEEN][WHITE][index_white[i]] = queen_pcsq_eg[i]; e.egPst[QUEEN][BLACK][index_black[i]] = queen_pcsq_eg[i]; e.egPst[KING][WHITE][index_white[i]] = king_pcsq_eg[i]; e.egPst[KING][BLACK][index_black[i]] = king_pcsq_eg[i]; } } /* This function is meant to be used in conjunction with the *.ini file. Its aim is to make sure that all the assumptions made within the program are met. */ void correctValues() { if (e.PIECE_VALUE[BISHOP] == e.PIECE_VALUE[KNIGHT]) ++e.PIECE_VALUE[BISHOP]; } void readIniFile() { FILE *cpw_init; char line[256]; /* if the cpw.ini file does not exist, then exit */ if ((cpw_init = fopen("cpw.ini", "r")) == NULL) { printf("Cannot open cpw.ini, default settings will be used \n"); return; } /* process cpw.ini file line by line */ while (fgets(line, 250, cpw_init)) { if (line[0] == ';') continue; // don't process comment lines processIniString(line); } } void processIniString(char line[250]) { /* piece values */ if (!strncmp(line, "PAWN_VALUE", 10)) sscanf(line, "PAWN_VALUE %d", &e.PIECE_VALUE[PAWN]); else if (!strncmp(line, "KNIGHT_VALUE", 12)) sscanf(line, "KNIGHT_VALUE %d", &e.PIECE_VALUE[KNIGHT]); else if (!strncmp(line, "BISHOP_VALUE", 12)) sscanf(line, "BISHOP_VALUE %d", &e.PIECE_VALUE[BISHOP]); else if (!strncmp(line, "ROOK_VALUE", 10)) sscanf(line, "ROOK_VALUE %d", &e.PIECE_VALUE[ROOK]); else if (!strncmp(line, "QUEEN_VALUE", 11)) sscanf(line, "QUEEN_VALUE %d", &e.PIECE_VALUE[QUEEN]); /* piece pairs */ else if (!strncmp(line, "BISHOP_PAIR", 11)) sscanf(line, "BISHOP_PAIR %d", &e.BISHOP_PAIR); else if (!strncmp(line, "PENALTY_KNIGHT_PAIR", 19)) sscanf(line, "PENALTY_KNIGHT_PAIR %d", &e.P_KNIGHT_PAIR); else if (!strncmp(line, "PENALTY_ROOK_PAIR", 17)) sscanf(line, "PENALTY_ROOK_PAIR %d", &e.P_KNIGHT_PAIR); /* pawn shield*/ else if (!strncmp(line, "SHIELD_1", 8)) sscanf(line, "SHIELD_1 %d", &e.SHIELD_1); else if (!strncmp(line, "SHIELD_2", 8)) sscanf(line, "SHIELD_2 %d", &e.SHIELD_2); else if (!strncmp(line, "PENALTY_NO_SHIELD", 17)) sscanf(line, "PENALTY_NO_SHIELD %d", &e.P_NO_SHIELD); /* major penalties */ else if (!strncmp(line, "PENALTY_BISHOP_TRAPPED_A7", 25)) sscanf(line, "PENALTY_BISHOP_TRAPPED_A7 %d", &e.P_BISHOP_TRAPPED_A7); else if (!strncmp(line, "PENALTY_BISHOP_TRAPPED_A6", 25)) sscanf(line, "PENALTY_BISHOP_TRAPPED_A6 %d", &e.P_BISHOP_TRAPPED_A6); else if (!strncmp(line, "PENALTY_KNIGHT_TRAPPED_A8", 25)) sscanf(line, "PENALTY_KNIGHT_TRAPPED_A8 %d", &e.P_KNIGHT_TRAPPED_A8); else if (!strncmp(line, "PENALTY_KNIGHT_TRAPPED_A7", 25)) sscanf(line, "PENALTY_KNIGHT_TRAPPED_A7 %d", &e.P_KNIGHT_TRAPPED_A7); else if (!strncmp(line, "PENALTY_KING_BLOCKS_ROOK", 24)) sscanf(line, "PENALTY_KNIGHT_TRAPPED_A7 %d", &e.P_KING_BLOCKS_ROOK); else if (!strncmp(line, "PENALTY_BLOCKED_CENTRAL_PAWN", 28)) sscanf(line, "PENALTY_BLOCKED_CENTRAL_PAWN %d", &e.P_BLOCK_CENTRAL_PAWN); /* minor penalties */ else if (!strncmp(line, "PENALTY_KNIGHT_BLOCKS_C", 23)) sscanf(line, "PENALTY_KNIGHT_BLOCKS_C %d", &e.P_C3_KNIGHT); else if (!strncmp(line, "PENALTY_NO_FIANCHETTO", 21)) sscanf(line, "PENALTY_NO_FIANCHETTO %d", &e.P_NO_FIANCHETTO); /* minor positional bonuses */ else if (!strncmp(line, "ROOK_OPEN", 9)) sscanf(line, "ROOK_OPEN %d", &e.ROOK_OPEN); else if (!strncmp(line, "ROOK_HALF_OPEN", 14)) sscanf(line, "ROOK_HALF_OPEN %d", &e.ROOK_HALF); else if (!strncmp(line, "FIANCHETTO", 10)) sscanf(line, "FIANCHETTO %d", &e.FIANCHETTO); else if (!strncmp(line, "RETURNING_BISHOP", 16)) sscanf(line, "RETURNING_BISHOP %d", &e.RETURNING_BISHOP); else if (!strncmp(line, "TEMPO", 5)) sscanf(line, "TEMPO %d", &e.TEMPO); /* variables deciding about inner workings of evaluation function */ else if (!strncmp(line, "ENDGAME_MATERIAL", 16)) sscanf(line, "ENDGAME_MATERIAL %d", &e.ENDGAME_MAT); }