Changes

Jump to: navigation, search

CPW King

41,609 bytes added, 15:24, 18 December 2018
Created page with "'''Home * Engines * CPW-Engine * CPW_King''' This is a patch to the CPW-Engine, changing its evaluation function. Modifications include: * getting r..."
'''[[Main Page|Home]] * [[Engines]] * [[CPW-Engine]] * CPW_King'''

This is a patch to the [[CPW-Engine]], changing its evaluation function. Modifications include:
* getting rid of [[Lazy Evaluation|lazy eval]]
* using [[Evaluation Hash Table|eval hash table]] as default
* modifying [[Mobility|mobility]] functions, so that they will count number of attacks on squares near enemy king as well as the number of attackers
* placing those functions in the piece-specific routines, before [[King Safety|king safety]] calculation, so that it can make use of them
* adding functions to count attacks by queens

Resulting program plays at the roughly the same strength as regular CPW-Engine, but is much more entertaining to watch. To obtain optimal results, piece/square values fo bishops and knights should be raised a tiny bit.

The most obvious drawback of the presented code is that it does not see attackers that are lined up, such as rooks doubled on a file. If You consider making this example into a real program, this is the first thing to change.

We need to add the following function to the eval_init.cpp, in order to define squares which are considered worthwhile to attack:

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

}
}


</pre>

The complete eval.cpp looks as follows:

<pre>
#include "stdafx.h"
#include "0x88_math.h"
#include "eval.h"
#include "transposition.h"

#define use_eval_hash

/* 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
#define ROOK_ATT 4
#define QUEEN_ATT 8

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

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;

/* local lists of pieces and pawns and indexes to them */
U8 pieceList[32];
U8 pieceIndex;
U8 pawnList[32];
U8 pawnIndex;

/* global flag used by mobility/attack detection functions to know
if a piece examined currently is a king attacker */

int isAttacker = 0;

/*****************************************************************************
* Fast evaluation (material + pcsq + pawn structure) *
*****************************************************************************/

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


/*****************************************************************************
* 1. Main evaluation function *
*****************************************************************************/

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

/***********************************************************************
* 2. Preparatory routines *
***********************************************************************/

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

/***********************************************************************
* This is a reduced version of the previous function, and it creates *
* only a list of pawns. *
***********************************************************************/

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

/************************************************************************
* 3. King safety evaluation *
************************************************************************/

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

/*********************************************************************************
* 4. 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;
}

/* a clone of getPawnScore, used in fastEval, when the pawn list is not set */

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

/****************************************************************
* The next two procedures are used in passed pawn evaluation, *
* the assumption being that passed pawns that are defended or *
* or whose stop square is protected by a friendly pawn tend *
* to be stronger. *
*****************************************************************/

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

/************************************************************************************
* 5. Evaluation of pieces *
************************************************************************************/

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

/**********************************************************************************
* 6. Mobility and king attack evaluation *
**********************************************************************************/

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

// with queen, currently we look for king attacks, not for mobility

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

/***************************************************************************************
* 7. Pattern detection *
***************************************************************************************/

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

/***************************************************************************************
* 8. Printing eval results *
***************************************************************************************/

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