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; } } }
int isPawnSupported(S8 sq, S8 side) { int step; if (side == WHITE) step = SOUTH; else step = NORTH; if ( IS_SQ(sq+WEST) && isPiece(side,PAWN, sq + WEST) ) return 1; if ( IS_SQ(sq+EAST) && isPiece(side,PAWN, sq + EAST) ) return 1; if ( IS_SQ(sq+step+WEST) && isPiece(side,PAWN, sq + step+WEST ) ) return 1; if ( IS_SQ(sq+step+EAST) && isPiece(side,PAWN, sq + step+EAST ) ) return 1; return 0; }
void EvalQueen(S8 sq, S8 side) { v.gamePhase += 4; int att = 0; int mob = 0; /**************************************************************** * A queen should not be developed too early * ****************************************************************/ if (side == WHITE && 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; } if (side == BLACK && 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; } /**************************************************************** * Collect data about mobility and king attacks * ****************************************************************/ for (char dir=0;dir<vectors[QUEEN];dir++) { for (char pos = sq;;) { pos = pos + vector[QUEEN][dir]; if (! IS_SQ(pos)) break; if (b.pieces[pos] == PIECE_EMPTY) { mob++; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; } else if (b.color[pos] != side) { mob++; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; break; } else { break; } } } v.mgMob[side] += 1 * (mob-14); v.egMob[side] += 2 * (mob-14); if (att) { v.attCnt[side]++; v.attWeight[side] += 4*att; } }
int leaperAttack( char byColor, S8 sq, char byPiece ) { S8 nextSq; for ( int dir = 0; dir < 8; dir++ ) { nextSq = sq + vector[byPiece][dir]; if ( IS_SQ(nextSq) && isPiece( byColor, byPiece, nextSq ) ) return 1; } return 0; }
int bishAttack(int byColor, S8 sq, int vect) { int nextSq = sq + vect; while (IS_SQ(nextSq)) { if (b.color[nextSq] != COLOR_EMPTY) { if (b.color[nextSq] == byColor && b.pieces[nextSq] == BISHOP) return 1; return 0; } nextSq = nextSq + vect; } return 0; }
int diagAttack(int byColor, S8 sq, int vect) { int nextSq = sq + vect; while ( IS_SQ( nextSq ) ) { if (b.color[ nextSq ] != COLOR_EMPTY ) { if ( ( b.color[nextSq] == byColor ) && ( b.pieces[nextSq] == BISHOP || b.pieces[nextSq] == QUEEN ) ) return 1; return 0; } nextSq = nextSq + vect; } return 0; }
int straightAttack(char byColor, S8 sq, int vect) { int nextSq = sq + vect; while ( IS_SQ(nextSq) ) { if (b.color[nextSq] != COLOR_EMPTY ) { if ( ( b.color[nextSq] == byColor ) && ( b.pieces[nextSq] == ROOK || b.pieces[nextSq] == QUEEN ) ) return 1; return 0; } nextSq = nextSq + vect; } return 0; }
int EvalPawn(S8 sq, S8 side) { int result = 0; int flagIsPassed = 1; // we will be trying to disprove that int flagIsWeak = 1; // we will be trying to disprove that int flagIsOpposed = 0; int stepFwd, stepBck; if (side == WHITE) stepFwd = NORTH; else stepFwd = SOUTH; if (side == WHITE) stepBck = SOUTH; else stepBck = NORTH; S8 nextSq = sq + stepFwd; /************************************************************************* * We have only very basic data structures that do not update informa- * * tion about pawns incrementally, so we have to calculate everything * * here. The loop below detects doubled pawns, passed pawns and sets * * a flag on finding that our pawn is opposed by enemy pawn. * *************************************************************************/ while (IS_SQ(nextSq)) { if (b.pieces[nextSq] == PAWN) { // either opposed by enemy pawn or doubled flagIsPassed = 0; if (b.color[nextSq] == side) result -= 20; // doubled pawn penalty else flagIsOpposed = 1; // flag our pawn as opposed } if (IS_SQ(nextSq + WEST) && isPiece(!side, PAWN, nextSq + WEST)) flagIsPassed = 0; if (IS_SQ(nextSq + EAST) && isPiece(!side, PAWN, nextSq + EAST)) flagIsPassed = 0; nextSq += stepFwd; } /************************************************************************* * Another loop, going backwards and checking whether pawn has support. * * Here we can at least break out of it for speed optimization. * *************************************************************************/ nextSq = sq; while (IS_SQ(nextSq)) { if (IS_SQ(nextSq + WEST) && isPiece(side, PAWN, nextSq + WEST)) { flagIsWeak = 0; break; } if (IS_SQ(nextSq + EAST) && isPiece(side, PAWN, nextSq + EAST)) { flagIsWeak = 0; break; } nextSq += stepBck; } /************************************************************************* * Evaluate passed pawns, scoring them higher if they are protected * * or if their advance is supported by friendly pawns * *************************************************************************/ if ( flagIsPassed ) { if ( isPawnSupported(sq, side) ) result += e.protected_passer[side][sq]; else result += e.passed_pawn[side][sq]; } /************************************************************************* * Evaluate weak pawns, increasing the penalty if they are situated * * on a half-open file * *************************************************************************/ if ( flagIsWeak ) { result += e.weak_pawn[side][sq]; if (!flagIsOpposed) result -= 4; } return result; }
void EvalRook(S8 sq, S8 side) { int att = 0; int mob = 0; int ownBlockingPawns = 0; int oppBlockingPawns = 0; int stepFwd; int nextSq; v.gamePhase += 2; /*************************************************************** * Material value adjustement based on the no. of own pawns. * * Rooks gain value as pawns disappear. * ***************************************************************/ v.MaterialAdjustement[side] += rook_adj[b.PieceCount[side][PAWN]]; /*************************************************************** * This is an ugly hack to detect open files. Merging it with * * mobility eval would have been better, but less readable, * * and this is educational program fter all. * /**************************************************************/ if (side == WHITE) stepFwd = NORTH; else stepFwd = SOUTH; nextSq = sq + stepFwd; while (IS_SQ(nextSq)) { if (b.pieces[nextSq] == PAWN) { if (b.color[nextSq] == side) { ownBlockingPawns++; break; } else oppBlockingPawns++; } nextSq += stepFwd; } /**************************************************************** * Evaluate open and half-open files. We merge this bonus with * * mobility score. * /***************************************************************/ if ( !ownBlockingPawns ) { if ( !oppBlockingPawns ) { v.mgMob[side] += e.ROOK_OPEN; v.egMob[side] += e.ROOK_OPEN; } else { v.mgMob[side] += e.ROOK_HALF; v.egMob[side] += e.ROOK_HALF; } } /**************************************************************** * Collect data about mobility and king attacks * ****************************************************************/ for (char dir=0; dir<vectors[ROOK]; dir++) { for (char pos = sq;;) { pos = pos + vector[ROOK][dir]; if (! IS_SQ(pos)) break; if (b.pieces[pos] == PIECE_EMPTY) { mob++; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; } else if (b.color[pos] != side) { mob++; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; break; } else { break; } } } v.mgMob[side] += 2 * (mob-7); v.egMob[side] += 4 * (mob-7); if (att) { v.attCnt[side]++; v.attWeight[side] += 3*att; } }
void EvalBishop(S8 sq, S8 side) { int att = 0; int mob = 0; v.gamePhase += 1; if (side == WHITE) { 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; } } else { 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; } } /**************************************************************** * Collect data about mobility and king attacks * ****************************************************************/ for (char dir=0;dir<vectors[BISHOP];dir++) { for (char pos = sq;;) { pos = pos + vector[BISHOP][dir]; if (! IS_SQ(pos)) break; if (b.pieces[pos] == PIECE_EMPTY) { mob++; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; } else if (b.color[pos] != side) { mob++; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; break; } else { break; } } } v.mgMob[side] += 3 * (mob-7); v.egMob[side] += 3 * (mob-7); if (att) { v.attCnt[side]++; v.attWeight[side] += 2*att; } }
void EvalKnight(S8 sq, S8 side) { int att = 0; int mob = 0; int pos; v.gamePhase += 1; if (side == WHITE) { 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; } } else { 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; } } /*************************************************************** * Material value adjustement based on the no. of own pawns. * * Knights lose value as pawns disappear. * ***************************************************************/ v.MaterialAdjustement[side] += knight_adj[b.PieceCount[side][PAWN]]; /**************************************************************** * Collect data about mobility and king attacks. This resembles * * move generation code, except that we are just incrementing * * the counters instead of adding actual moves. * ****************************************************************/ for (U8 dir=0;dir<8;dir++) { pos = sq + vector[KNIGHT][dir]; if ( IS_SQ(pos) && b.color[pos] != side ) { ++mob; if ( e.sqNearK[!side] [b.KingLoc[!side] ] [pos] ) ++att; // this knight is attacking zone around enemy king } } /**************************************************************** * Evaluate mobility. We try to do it in such a way * * that zero represents average mobility, but our * * formula of doing so is a puer guess. * ****************************************************************/ v.mgMob[side] += 4 * (mob-4); v.egMob[side] += 4 * (mob-4); /**************************************************************** * Save data about king attacks * ****************************************************************/ if (att) { v.attCnt[side]++; v.attWeight[side] += 2 * att; } }