CPW-Engine eval init

From Chessprogramming wiki
Jump to: navigation, search

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);
}

Up one Level