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 representationint 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 kingsif(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 ringif(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]);elseif(!strncmp(line, "KNIGHT_VALUE", 12))sscanf(line, "KNIGHT_VALUE %d", &e.PIECE_VALUE[KNIGHT]);elseif(!strncmp(line, "BISHOP_VALUE", 12))sscanf(line, "BISHOP_VALUE %d", &e.PIECE_VALUE[BISHOP]);elseif(!strncmp(line, "ROOK_VALUE", 10))sscanf(line, "ROOK_VALUE %d", &e.PIECE_VALUE[ROOK]);elseif(!strncmp(line, "QUEEN_VALUE", 11))sscanf(line, "QUEEN_VALUE %d", &e.PIECE_VALUE[QUEEN]);/* piece pairs */elseif(!strncmp(line, "BISHOP_PAIR", 11))sscanf(line, "BISHOP_PAIR %d", &e.BISHOP_PAIR);elseif(!strncmp(line, "PENALTY_KNIGHT_PAIR", 19))sscanf(line, "PENALTY_KNIGHT_PAIR %d", &e.P_KNIGHT_PAIR);elseif(!strncmp(line, "PENALTY_ROOK_PAIR", 17))sscanf(line, "PENALTY_ROOK_PAIR %d", &e.P_KNIGHT_PAIR);/* pawn shield*/elseif(!strncmp(line, "SHIELD_1", 8))sscanf(line, "SHIELD_1 %d", &e.SHIELD_1);elseif(!strncmp(line, "SHIELD_2", 8))sscanf(line, "SHIELD_2 %d", &e.SHIELD_2);elseif(!strncmp(line, "PENALTY_NO_SHIELD", 17))sscanf(line, "PENALTY_NO_SHIELD %d", &e.P_NO_SHIELD);/* major penalties */elseif(!strncmp(line, "PENALTY_BISHOP_TRAPPED_A7", 25))sscanf(line, "PENALTY_BISHOP_TRAPPED_A7 %d", &e.P_BISHOP_TRAPPED_A7);elseif(!strncmp(line, "PENALTY_BISHOP_TRAPPED_A6", 25))sscanf(line, "PENALTY_BISHOP_TRAPPED_A6 %d", &e.P_BISHOP_TRAPPED_A6);elseif(!strncmp(line, "PENALTY_KNIGHT_TRAPPED_A8", 25))sscanf(line, "PENALTY_KNIGHT_TRAPPED_A8 %d", &e.P_KNIGHT_TRAPPED_A8);elseif(!strncmp(line, "PENALTY_KNIGHT_TRAPPED_A7", 25))sscanf(line, "PENALTY_KNIGHT_TRAPPED_A7 %d", &e.P_KNIGHT_TRAPPED_A7);elseif(!strncmp(line, "PENALTY_KING_BLOCKS_ROOK", 24))sscanf(line, "PENALTY_KNIGHT_TRAPPED_A7 %d", &e.P_KING_BLOCKS_ROOK);elseif(!strncmp(line, "PENALTY_BLOCKED_CENTRAL_PAWN", 28))sscanf(line, "PENALTY_BLOCKED_CENTRAL_PAWN %d", &e.P_BLOCK_CENTRAL_PAWN);/* minor penalties */elseif(!strncmp(line, "PENALTY_KNIGHT_BLOCKS_C", 23))sscanf(line, "PENALTY_KNIGHT_BLOCKS_C %d", &e.P_C3_KNIGHT);elseif(!strncmp(line, "PENALTY_NO_FIANCHETTO", 21))sscanf(line, "PENALTY_NO_FIANCHETTO %d", &e.P_NO_FIANCHETTO);/* minor positional bonuses */elseif(!strncmp(line, "ROOK_OPEN", 9))sscanf(line, "ROOK_OPEN %d", &e.ROOK_OPEN);elseif(!strncmp(line, "ROOK_HALF_OPEN", 14))sscanf(line, "ROOK_HALF_OPEN %d", &e.ROOK_HALF);elseif(!strncmp(line, "FIANCHETTO", 10))sscanf(line, "FIANCHETTO %d", &e.FIANCHETTO);elseif(!strncmp(line, "RETURNING_BISHOP", 16))sscanf(line, "RETURNING_BISHOP %d", &e.RETURNING_BISHOP);elseif(!strncmp(line, "TEMPO", 5))sscanf(line, "TEMPO %d", &e.TEMPO);/* variables deciding about inner workings of evaluation function */elseif(!strncmp(line, "ENDGAME_MATERIAL", 16))sscanf(line, "ENDGAME_MATERIAL %d", &e.ENDGAME_MAT);}
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
Up one Level