[go: up one dir, main page]

Menu

Diff of /evaluation.h [000000] .. [r1]  Maximize  Restore

Switch to side-by-side view

--- a
+++ b/evaluation.h
@@ -0,0 +1,355 @@
+/*
+    Protector -- a UCI chess engine
+
+    Copyright (C) 2008 Raimund Heid (Raimund_Heid@yahoo.com)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef _evaluation_h_
+#define _evaluation_h_
+
+#include "position.h"
+#include "bitboard.h"
+#include "keytable.h"
+
+extern const int PAWN_VALUE_OPENING;
+extern const int PAWN_VALUE_ENDGAME;
+
+#define WHITE_BISHOP_LIGHT 0x01
+#define WHITE_BISHOP_DARK  0x02
+#define BLACK_BISHOP_LIGHT 0x04
+#define BLACK_BISHOP_DARK  0x08
+#define WHITE_BISHOP_PAIR  0x03
+#define BLACK_BISHOP_PAIR  0x0C
+
+typedef struct
+{
+   Bitboard upwardRealm[2];
+   Bitboard downwardRealm[2];
+   Bitboard pawnAttackableSquares[2];
+   Bitboard pawnProtectedSquares[2];
+   Bitboard doubledPawns[2];
+   Bitboard passedPawns[2];
+   Bitboard candidatePawns[2];
+
+#ifdef BONUS_HIDDEN_PASSER
+   Bitboard hiddenCandidatePawns[2];
+   bool hasPassersOrCandidates[2];
+#endif
+
+   Bitboard weakPawns[2];
+   Bitboard fixedPawns[2];
+   Bitboard countedSquares[2];
+   Bitboard weakOutpostSquares[2];
+   KingAttacks *kingAttacks[2];
+   Bitboard kingAttackSquares[2];
+
+#ifdef CALCULATE_TARGETS
+   Bitboard pieceAttacks[2];
+#endif
+
+   int numAttackers[2];
+   int attackPoints[2];
+   int spaceAttackPoints[2];
+   int openingPoints[2], endgamePoints[2];
+   bool evaluateKingSafety[2];
+   KingSafetyHashInfo *kingsafetyHashtable;
+}
+EvaluationBase;
+
+extern const int PHASE_MAX;
+
+/**
+ * Calculate the weight of the non-pawn-pieces of the specified color.
+ */
+INLINE int getMaterialValue(const Position * position, const Color color)
+{
+   const int VALUE_SMALL_PIECE = 300;
+   const int ROOK_DIFF = 500 - VALUE_SMALL_PIECE;
+   const int QUEEN_DIFF = 950 - VALUE_SMALL_PIECE;
+   const int numNonPawnPieces = numberOfNonPawnPieces(position, color) - 1;
+   const int numRooks = getPieceCount(position, (Piece) (ROOK | color));
+   const int numQueens = getPieceCount(position, (Piece) (QUEEN | color));
+
+   return numQueens * QUEEN_DIFF + numRooks * ROOK_DIFF +
+      numNonPawnPieces * VALUE_SMALL_PIECE +
+      position->numberOfPawns[color] * 100;
+}
+
+/**
+ * Calculate the weight of the non-pawn-pieces of the specified color.
+ */
+INLINE int getPieceValue(const Position * position, const Color color)
+{
+   const int VALUE_SMALL_PIECE = 300;
+   const int ROOK_DIFF = 500 - VALUE_SMALL_PIECE;
+   const int QUEEN_DIFF = 950 - VALUE_SMALL_PIECE;
+   const int numNonPawnPieces = numberOfNonPawnPieces(position, color) - 1;
+   const int numRooks = getPieceCount(position, (Piece) (ROOK | color));
+   const int numQueens = getPieceCount(position, (Piece) (QUEEN | color));
+
+   return numQueens * QUEEN_DIFF + numRooks * ROOK_DIFF +
+      numNonPawnPieces * VALUE_SMALL_PIECE;
+}
+
+/**
+ * Calculate the weight of the non-pawn-pieces of the specified color.
+ *
+ * @return a value in the range [0-44]
+ */
+INLINE int getPieceWeight(const Position * position, const Color color)
+{
+   const int numNonPawnPieces = numberOfNonPawnPieces(position, color) - 1;
+   const int numRooks = getPieceCount(position, (Piece) (ROOK | color));
+   const int numQueens = getPieceCount(position, (Piece) (QUEEN | color));
+
+   return 3 * numQueens + numRooks + numNonPawnPieces;
+}
+
+/**
+ * Calculate the value of the non-pawn-pieces of the specified color.
+ *
+ * @return a centipawn value
+ */
+INLINE int getOpeningPieceWeight(const Position * position, const Color color)
+{
+   return position->openingValue[color] -
+      PAWN_VALUE_OPENING * position->numberOfPawns[color];
+}
+
+/**
+ * Calculate the phase index of the specified position.
+ *
+ * @return a value in the range [0(initial position)-256(endgame)]
+ */
+INLINE int phaseIndex(const Position * position)
+{
+   const int basicPhase = max(0, PHASE_MAX -
+                              getPieceWeight(position, WHITE) -
+                              getPieceWeight(position, BLACK));
+
+   assert(getPieceWeight(position, WHITE) >= 0);
+   assert(getPieceWeight(position, WHITE) <= 44);
+   assert(getPieceWeight(position, BLACK) >= 0);
+   assert(getPieceWeight(position, BLACK) <= 44);
+   assert(basicPhase >= 0);
+   assert(basicPhase <= PHASE_MAX);
+
+   return (basicPhase * 256 + (PHASE_MAX / 2)) / PHASE_MAX;
+}
+
+INLINE bool hasBishopPair(const Position * position, const Color color)
+{
+   const Bitboard *bishops =
+      &position->piecesOfType[(Piece) (BISHOP | color)];
+
+   return (bool) ((lightSquares & *bishops) != EMPTY_BITBOARD &&
+                  (darkSquares & *bishops) != EMPTY_BITBOARD);
+}
+
+#define VALUE_TEMPO_OPENING 20
+#define VALUE_TEMPO_ENDGAME 10
+
+/**
+ * Calculate a rough value of the specified position,
+ * based on the current pst-values and the specified evaluation base.
+ *
+ * @return the value of the specified position
+ */
+INLINE int positionalBalance(const Position * position, EvaluationBase * base)
+{
+   int openingValue =
+      (base->openingPoints[WHITE] - base->openingPoints[BLACK] +
+       position->openingValue[WHITE] - position->openingValue[BLACK]);
+   int endgameValue =
+      (base->endgamePoints[WHITE] - base->endgamePoints[BLACK] +
+       position->endgameValue[WHITE] - position->endgameValue[BLACK]);
+   const int pi = phaseIndex(position);
+   int value;
+
+   assert(pi >= 0 && pi <= 256);
+
+   if (hasBishopPair(position, WHITE))
+   {
+      openingValue += VALUE_BISHOP_PAIR_OPENING;
+      endgameValue += VALUE_BISHOP_PAIR_ENDGAME;
+   }
+
+   if (hasBishopPair(position, BLACK))
+   {
+      openingValue -= VALUE_BISHOP_PAIR_OPENING;
+      endgameValue -= VALUE_BISHOP_PAIR_ENDGAME;
+   }
+
+   if (position->activeColor == WHITE)
+   {
+      openingValue += VALUE_TEMPO_OPENING;
+      endgameValue += VALUE_TEMPO_ENDGAME;
+   }
+   else
+   {
+      openingValue -= VALUE_TEMPO_OPENING;
+      endgameValue -= VALUE_TEMPO_ENDGAME;
+   }
+
+   value = (openingValue * (256 - pi) + endgameValue * pi) / 256;
+
+   return (position->activeColor == WHITE ? value : -value);
+}
+
+/**
+ * Calculate a rough value of the specified position,
+ * based on the current pst-values.
+ *
+ * @return the value of the specified position
+ */
+INLINE int basicPositionalBalance(Position * position)
+{
+   int openingValue =
+      (position->openingValue[WHITE] - position->openingValue[BLACK]);
+   int endgameValue =
+      (position->endgameValue[WHITE] - position->endgameValue[BLACK]);
+   const int pi = phaseIndex(position);
+   int value;
+
+   assert(pi >= 0 && pi <= 256);
+
+   if (hasBishopPair(position, WHITE))
+   {
+      openingValue += VALUE_BISHOP_PAIR_OPENING;
+      endgameValue += VALUE_BISHOP_PAIR_ENDGAME;
+   }
+
+   if (hasBishopPair(position, BLACK))
+   {
+      openingValue -= VALUE_BISHOP_PAIR_OPENING;
+      endgameValue -= VALUE_BISHOP_PAIR_ENDGAME;
+   }
+
+   if (position->activeColor == WHITE)
+   {
+      openingValue += VALUE_TEMPO_OPENING;
+      endgameValue += VALUE_TEMPO_ENDGAME;
+   }
+   else
+   {
+      openingValue -= VALUE_TEMPO_OPENING;
+      endgameValue -= VALUE_TEMPO_ENDGAME;
+   }
+
+   value = (openingValue * (256 - pi) + endgameValue * pi) / 256;
+
+   return (position->activeColor == WHITE ? value : -value);
+}
+
+/**
+ * Calculate the value of the specified position.
+ *
+ * @return the value of the specified position
+ */
+int getValue(Position * position, const int alpha, const int beta,
+             PawnHashInfo * pawnHashtable,
+             KingSafetyHashInfo * kingsafetyHashtable);
+
+/**
+ * Check if the specified color can win the specified position.
+ *
+ * @return FALSE if the specified color doesn't have sufficient material
+ *         left to win the position
+ */
+INLINE bool hasWinningPotential(Position * position, Color color)
+{
+   return (bool) (position->numberOfPieces[color] > 1);
+}
+
+/**
+ * Check if the pawn at the specified square is a passed pawn.
+ */
+bool pawnIsPassed(const Position * position, const Square pawnSquare);
+
+/**
+ * Reset the pawn hashtable.
+ */
+void resetPawnHashtable(void);
+
+/**
+ * Flip the given position and check if it yields the same result.
+ *
+ * @return FALSE if the flipped position yields a diffent result
+ */
+bool flipTest(Position * position,
+              PawnHashInfo * pawnHashtable,
+              KingSafetyHashInfo * kingsafetyHashtable);
+
+/**
+ * Initialize this module.
+ *
+ * @return 0 if no errors occurred.
+ */
+int initializeModuleEvaluation(void);
+
+/**
+ * Test this module.
+ *
+ * @return 0 if all tests succeed.
+ */
+int testModuleEvaluation(void);
+
+/**
+ * Get the king safety hash value for the given king square.
+ */
+INLINE Bitboard getKingPawnSafetyHashValue(const Position * position,
+                                           const Color color)
+{
+   const int mask[2] =
+      { WHITE_00 | WHITE_000 | 16, BLACK_00 | BLACK_000 | 32 };
+   const int index = (position->castlingRights | 48) & mask[color];
+
+   return position->pawnHashValue ^
+      GENERATED_KEYTABLE[color][position->king[color]] ^
+      GENERATED_KEYTABLE[2][index];
+}
+
+INLINE bool piecesAreBalanced(const Position * position)
+{
+   return (bool) (getPieceCount(position, WHITE_QUEEN) ==
+                  getPieceCount(position, BLACK_QUEEN) &&
+                  getPieceCount(position, WHITE_ROOK) ==
+                  getPieceCount(position, BLACK_ROOK) &&
+                  getPieceCount(position, WHITE_BISHOP) ==
+                  getPieceCount(position, BLACK_BISHOP) &&
+                  getPieceCount(position, WHITE_KNIGHT) ==
+                  getPieceCount(position, BLACK_KNIGHT));
+}
+
+INLINE int getPawnWidth(const Position * position, const Color color)
+{
+   const Bitboard tmp = position->piecesOfType[(Piece) (PAWN | color)] |
+      minValue[position->king[opponent(color)]];
+
+   return getWidth(tmp);
+}
+
+INLINE int getPassedPawnWidth(const Position * position,
+                              const EvaluationBase * base, const Color color)
+{
+   const Bitboard tmp = base->passedPawns[color] |
+      minValue[position->king[opponent(color)]];
+
+   return getWidth(tmp);
+}
+
+#endif