Subversion Repositories Games.Chess Giants

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.     Texel - A UCI chess engine.
  3.     Copyright (C) 2012-2014  Peter Ă–sterlund, peterosterlund2@gmail.com
  4.  
  5.     This program is free software: you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation, either version 3 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17. */
  18.  
  19. /*
  20.  * evaluate.hpp
  21.  *
  22.  *  Created on: Feb 25, 2012
  23.  *      Author: petero
  24.  */
  25.  
  26. #ifndef EVALUATE_HPP_
  27. #define EVALUATE_HPP_
  28.  
  29. #include "parameters.hpp"
  30. #include "piece.hpp"
  31. #include "position.hpp"
  32. #include "util/alignedAlloc.hpp"
  33.  
  34. class EvaluateTest;
  35.  
  36. /** Position evaluation routines. */
  37. class Evaluate {
  38.     friend class EvaluateTest;
  39. private:
  40.     struct PawnHashData {
  41.         PawnHashData();
  42.         U64 key;
  43.         S16 current;        // For hash replacement policy
  44.         S16 score;          // Positive score means good for white
  45.         S16 passedBonusW;
  46.         S16 passedBonusB;
  47.         U64 passedPawns;    // The most advanced passed pawns for each file
  48.                             // Contains both white and black pawns
  49.         U64 outPostsW;      // Possible outpost squares for white
  50.         U64 outPostsB;
  51.         U64 stalePawns;     // Pawns that can not be used for "pawn breaks"
  52.     };
  53.  
  54.     struct MaterialHashData {
  55.         MaterialHashData();
  56.         int id;
  57.         int score;
  58.         S16 wPawnIPF, bPawnIPF;
  59.         S16 wKnightIPF, bKnightIPF;
  60.         S16 castleIPF, queenIPF;
  61.         S16 wPassedPawnIPF, bPassedPawnIPF;
  62.         S16 kingSafetyIPF;
  63.         S16 diffColorBishopIPF;
  64.         S16 wKnightOutPostIPF, bKnightOutPostIPF;
  65.         U8 endGame;
  66.     };
  67.  
  68.     struct KingSafetyHashData {
  69.         KingSafetyHashData();
  70.         U64 key;
  71.         int score;
  72.         S16 current;        // For hash replacement policy
  73.     };
  74.  
  75. public:
  76.     struct EvalHashTables {
  77.         EvalHashTables();
  78.         std::vector<PawnHashData> pawnHash;
  79.         std::vector<MaterialHashData> materialHash;
  80.         vector_aligned<KingSafetyHashData> kingSafetyHash;
  81.     };
  82.  
  83.     /** Constructor. */
  84.     Evaluate(EvalHashTables& et);
  85.  
  86.     static int pieceValueOrder[Piece::nPieceTypes];
  87.  
  88.     static const int* psTab1[Piece::nPieceTypes];
  89.     static const int* psTab2[Piece::nPieceTypes];
  90.  
  91.     /** Get evaluation hash tables. */
  92.     static std::shared_ptr<EvalHashTables> getEvalHashTables();
  93.  
  94.     /**
  95.      * Static evaluation of a position.
  96.      * @param pos The position to evaluate.
  97.      * @return The evaluation score, measured in centipawns.
  98.      *         Positive values are good for the side to make the next move.
  99.      */
  100.     int evalPos(const Position& pos);
  101.     int evalPosPrint(const Position& pos);
  102.  
  103.     /** Compute "swindle" score corresponding to an evaluation score when
  104.      * the position is a known TB draw. */
  105.     static int swindleScore(int evalScore);
  106.  
  107.     /**
  108.      * Interpolate between (x1,y1) and (x2,y2).
  109.      * If x < x1, return y1, if x > x2 return y2. Otherwise, use linear interpolation.
  110.      */
  111.     static int interpolate(int x, int x1, int y1, int x2, int y2);
  112.  
  113.     static const int IPOLMAX = 1024;
  114.  
  115.     /** Compute v1 + (v2-v1)*k/IPOLMAX */
  116.     static int interpolate(int v1, int v2, int k);
  117.  
  118.     static void staticInitialize();
  119.     static void updateEvalParams();
  120.  
  121. private:
  122.     template <bool print> int evalPos(const Position& pos);
  123.  
  124.     /** Compute score based on piece square tables. Positive values are good for white. */
  125.     int pieceSquareEval(const Position& pos);
  126.  
  127.     /** Get material score */
  128.     int materialScore(const Position& pos, bool print);
  129.  
  130.     /** Compute material score. */
  131.     void computeMaterialScore(const Position& pos, MaterialHashData& mhd, bool print) const;
  132.  
  133.     /** Implement the "when ahead trade pieces, when behind trade pawns" rule. */
  134.     int tradeBonus(const Position& pos, int wCorr, int bCorr) const;
  135.  
  136.     /** Score castling ability. */
  137.     int castleBonus(const Position& pos);
  138.  
  139.     PawnHashData& getPawnHashEntry(std::vector<PawnHashData>& pawnHash, U64 key);
  140.     int pawnBonus(const Position& pos);
  141.  
  142.     /** Compute set of pawns that can not participate in "pawn breaks". */
  143.     static U64 computeStalePawns(const Position& pos);
  144.  
  145.     /** Compute pawn hash data for pos. */
  146.     void computePawnHashData(const Position& pos, PawnHashData& ph);
  147.  
  148.     /** Compute rook bonus. Rook on open/half-open file. */
  149.     int rookBonus(const Position& pos);
  150.  
  151.     /** Compute bishop evaluation. */
  152.     int bishopEval(const Position& pos, int oldScore);
  153.  
  154.     /** Compute knight evaluation. */
  155.     int knightEval(const Position& pos);
  156.  
  157.     /** Bonus for threatening opponent pieces. */
  158.     int threatBonus(const Position& pos);
  159.  
  160.     /** Bonus for own pieces protected by pawns. */
  161.     int protectBonus(const Position& pos);
  162.  
  163.     /** Compute king safety for both kings. */
  164.     int kingSafety(const Position& pos);
  165.  
  166.     KingSafetyHashData& getKingSafetyHashEntry(vector_aligned<KingSafetyHashData>& ksHash, U64 key);
  167.     int kingSafetyKPPart(const Position& pos);
  168.  
  169.     static int castleMaskFactor[256];
  170.     static int knightMobScoreA[64][9];
  171.     static U64 knightKingProtectPattern[64];
  172.     static U64 bishopKingProtectPattern[64];
  173.  
  174.     std::vector<PawnHashData>& pawnHash;
  175.     const PawnHashData* phd;
  176.  
  177.     std::vector<MaterialHashData>& materialHash;
  178.     const MaterialHashData* mhd;
  179.  
  180.     vector_aligned<KingSafetyHashData>& kingSafetyHash;
  181.  
  182.      // King safety variables
  183.     U64 wKingZone, bKingZone;       // Squares close to king that are worth attacking
  184.     int wKingAttacks, bKingAttacks; // Number of attacks close to white/black king
  185.     U64 wAttacksBB, bAttacksBB;
  186.     U64 wPawnAttacks, bPawnAttacks; // Squares attacked by white/black pawns
  187. };
  188.  
  189.  
  190. inline
  191. Evaluate::PawnHashData::PawnHashData()
  192.     : key((U64)-1), // Non-zero to avoid collision for positions with no pawns
  193.       current(0), score(0),
  194.       passedBonusW(0),
  195.       passedBonusB(0),
  196.       passedPawns(0) {
  197. }
  198.  
  199. inline
  200. Evaluate::MaterialHashData::MaterialHashData()
  201.     : id(-1), score(0) {
  202. }
  203.  
  204. inline
  205. Evaluate::KingSafetyHashData::KingSafetyHashData()
  206.     : key((U64)-1), score(0), current(0) {
  207. }
  208.  
  209. inline
  210. Evaluate::EvalHashTables::EvalHashTables() {
  211.     pawnHash.resize(1<<16);
  212.     kingSafetyHash.resize(1 << 15);
  213.     materialHash.resize(1 << 14);
  214. }
  215.  
  216. inline int
  217. Evaluate::interpolate(int x, int x1, int y1, int x2, int y2) {
  218.     if (x > x2) {
  219.         return y2;
  220.     } else if (x < x1) {
  221.         return y1;
  222.     } else {
  223.         return (x - x1) * (y2 - y1) / (x2 - x1) + y1;
  224.     }
  225. }
  226.  
  227. inline int
  228. Evaluate::interpolate(int v1, int v2, int k) {
  229.     return v1 + (v2 - v1) * k / IPOLMAX;
  230. }
  231.  
  232. inline int
  233. Evaluate::materialScore(const Position& pos, bool print) {
  234.     int mId = pos.materialId();
  235.     int key = (mId >> 16) * 40507 + mId;
  236.     MaterialHashData& newMhd = materialHash[key & (materialHash.size() - 1)];
  237.     if ((newMhd.id != mId) || print)
  238.         computeMaterialScore(pos, newMhd, print);
  239.     mhd = &newMhd;
  240.     return newMhd.score;
  241. }
  242.  
  243. inline Evaluate::PawnHashData&
  244. Evaluate::getPawnHashEntry(std::vector<Evaluate::PawnHashData>& pawnHash, U64 key) {
  245.     int e0 = (int)key & (pawnHash.size() - 2);
  246.     int e1 = e0 + 1;
  247.     if (pawnHash[e0].key == key) {
  248.         pawnHash[e0].current = 1;
  249.         pawnHash[e1].current = 0;
  250.         return pawnHash[e0];
  251.     }
  252.     if (pawnHash[e1].key == key) {
  253.         pawnHash[e1].current = 1;
  254.         pawnHash[e0].current = 0;
  255.         return pawnHash[e1];
  256.     }
  257.     if (pawnHash[e0].current) {
  258.         pawnHash[e1].current = 1;
  259.         pawnHash[e0].current = 0;
  260.         return pawnHash[e1];
  261.     } else {
  262.         pawnHash[e0].current = 1;
  263.         pawnHash[e1].current = 0;
  264.         return pawnHash[e0];
  265.     }
  266. }
  267.  
  268. inline Evaluate::KingSafetyHashData&
  269. Evaluate::getKingSafetyHashEntry(vector_aligned<Evaluate::KingSafetyHashData>& ksHash, U64 key) {
  270.     int e0 = (int)key & (ksHash.size() - 2);
  271.     int e1 = e0 + 1;
  272.     if (ksHash[e0].key == key) {
  273.         ksHash[e0].current = 1;
  274.         ksHash[e1].current = 0;
  275.         return ksHash[e0];
  276.     }
  277.     if (ksHash[e1].key == key) {
  278.         ksHash[e1].current = 1;
  279.         ksHash[e0].current = 0;
  280.         return ksHash[e1];
  281.     }
  282.     if (ksHash[e0].current) {
  283.         ksHash[e1].current = 1;
  284.         ksHash[e0].current = 0;
  285.         return ksHash[e1];
  286.     } else {
  287.         ksHash[e0].current = 1;
  288.         ksHash[e1].current = 0;
  289.         return ksHash[e0];
  290.     }
  291. }
  292.  
  293. #endif /* EVALUATE_HPP_ */
  294.