- /* 
-     Texel - A UCI chess engine. 
-     Copyright (C) 2012-2014  Peter Ă–sterlund, peterosterlund2@gmail.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/>. 
- */ 
-   
- /* 
-  * position.hpp 
-  * 
-  *  Created on: Feb 25, 2012 
-  *      Author: petero 
-  */ 
-   
- #ifndef POSITION_HPP_ 
- #define POSITION_HPP_ 
-   
- #include <iosfwd> 
-   
- #include "move.hpp" 
- #include "undoInfo.hpp" 
- #include "bitBoard.hpp" 
- #include "piece.hpp" 
- #include "material.hpp" 
- #include <algorithm> 
- #include <iostream> 
-   
- /** 
-  * Stores the state of a chess position. 
-  * All required state is stored, except for all previous positions 
-  * since the last capture or pawn move. That state is only needed 
-  * for three-fold repetition draw detection, and is better stored 
-  * in a separate hash table. 
-  */ 
- class Position { 
- public: 
-     /** Bit definitions for the castleMask bit mask. */ 
-     static const int A1_CASTLE = 0; /** White long castle. */ 
-     static const int H1_CASTLE = 1; /** White short castle. */ 
-     static const int A8_CASTLE = 2; /** Black long castle. */ 
-     static const int H8_CASTLE = 3; /** Black short castle. */ 
-   
-     /** Initialize board to empty position. */ 
-     Position(); 
-   
-     bool equals(const Position& other) const; 
-   
-     /** 
-      * Return Zobrist hash value for the current position. 
-      * Everything except the move counters are included in the hash value. 
-      */ 
-     U64 zobristHash() const; 
-     U64 pawnZobristHash() const; 
-     U64 kingZobristHash() const; 
-   
-     /** Zobrist hash including the halfMove clock. 
-      *  Only large halfMove clock values affect the hash. */ 
-     U64 historyHash() const; 
-     /** Hash including halfMoveClock, to avoid opening book cycles. */ 
-     U64 bookHash() const; 
-   
-     /** Compute zobrist hash for position after "move" has been made. 
-      * May be incorrect in some cases, intended for prefetch. */ 
-     U64 hashAfterMove(const Move& move) const; 
-   
-     /** Return the material identifier. */ 
-     int materialId() const; 
-   
-     /** 
-      * Decide if two positions are equal in the sense of the draw by repetition rule. 
-      * @return True if positions are equal, false otherwise. 
-      */ 
-     bool drawRuleEquals(Position other) const; 
-   
-     bool isWhiteMove() const; 
-   
-     void setWhiteMove(bool whiteMove); 
-   
-     /** Return piece occupying a square. */ 
-     int getPiece(int square) const; 
-   
-     /** Set a square to a piece value. */ 
-     void setPiece(int square, int piece); 
-   
-     /** 
-      * Set a square to a piece value. 
-      * Special version that only updates enough of the state for the SEE function to be happy. 
-      */ 
-     void setSEEPiece(int square, int piece); 
-   
-     /** Return true if white long castling right has not been lost. */ 
-     bool a1Castle() const; 
-   
-     /** Return true if white short castling right has not been lost. */ 
-     bool h1Castle() const; 
-   
-     /** Return true if black long castling right has not been lost. */ 
-     bool a8Castle() const; 
-   
-     /** Return true if black short castling right has not been lost. */ 
-     bool h8Castle() const; 
-   
-     /** Bitmask describing castling rights. */ 
-     int getCastleMask() const; 
-     void setCastleMask(int castleMask); 
-   
-     /** En passant square, or -1 if no en passant possible. */ 
-     int getEpSquare() const; 
-   
-     void setEpSquare(int epSquare); 
-   
-     int getKingSq(bool white) const; 
-   
-     /** Apply a move to the current position. */ 
-     void makeMove(const Move& move, UndoInfo& ui); 
-   
-     void unMakeMove(const Move& move, const UndoInfo& ui); 
-   
-     /** Special make move functions used by MoveGen::isLegal(). Does not update all data members. */ 
-     void makeMoveB(const Move& move, UndoInfo& ui); 
-     void unMakeMoveB(const Move& move, const UndoInfo& ui); 
-     void setPieceB(int square, int piece); 
-   
-     /** 
-      * Apply a move to the current position. 
-      * Special version that only updates enough of the state for the SEE function to be happy. 
-      */ 
-     void makeSEEMove(const Move& move, UndoInfo& ui); 
-   
-     void unMakeSEEMove(const Move& move, const UndoInfo& ui); 
-   
-     int getFullMoveCounter() const; 
-     void setFullMoveCounter(int fm); 
-     int getHalfMoveClock() const; 
-     void setHalfMoveClock(int hm); 
-   
-     /** Return incrementally updated piece square table score for middle game and endgame. */ 
-     int psScore1(int piece) const; 
-     int psScore2(int piece) const; 
-   
-     /** BitBoard for all squares occupied by a piece type. */ 
-     U64 pieceTypeBB(Piece::Type piece) const; 
-     /** BitBoard for all squares occupied by several piece types. */ 
-     template <typename Piece0, typename... Pieces> U64 pieceTypeBB(Piece0 piece0, Pieces... pieces) const; 
-   
-     /** BitBoard for all squares occupied by white pieces. */ 
-     U64 whiteBB() const; 
-     /** BitBoard for all squares occupied by black pieces. */ 
-     U64 blackBB() const; 
-     /** BitBoard for all squares occupied by white or black pieces. */ 
-     U64 colorBB(int wtm) const; 
-   
-     /** BitBoard for all squares occupied by white and black pieces. */ 
-     U64 occupiedBB() const; 
-   
-     int wKingSq() const; 
-     int bKingSq() const; 
-   
-     /** Total white/black material value. */ 
-     int wMtrl() const; 
-     int bMtrl() const; 
-     /** White/black material value for all pawns. */ 
-     int wMtrlPawns() const; 
-     int bMtrlPawns() const; 
-   
-   
-     /** Return index in squares[] vector corresponding to (x,y). */ 
-     static int getSquare(int x, int y); 
-   
-     /** Return x position (file) corresponding to a square. */ 
-     static int getX(int square); 
-   
-     /** Return y position (rank) corresponding to a square. */ 
-     static int getY(int square); 
-   
-     /** Return getSquare(getX(square),7-getY(square)). */ 
-     static int mirrorY(int square); 
-   
-     /** Return true if (x,y) is a dark square. */ 
-     static bool darkSquare(int x, int y); 
-   
-     /** Compute the Zobrist hash value non-incrementally. Only useful for testing. */ 
-     U64 computeZobristHash(); 
-   
-     /** Initialize static data. */ 
-     static void staticInitialize(); 
-   
-     /** Get hash key for a piece at a square. */ 
-     static U64 getHashKey(int piece, int square); 
-   
-   
-     /** Serialization. Used by tree logging code. */ 
-     struct SerializeData { 
-         U64 v[5]; 
-     }; 
-     void serialize(SerializeData& data) const; 
-     void deSerialize(const SerializeData& data); 
-   
- private: 
-     /** Move a non-pawn piece to an empty square. */ 
-     void movePieceNotPawn(int from, int to); 
-     void movePieceNotPawnB(int from, int to); 
-   
-     void removeCastleRights(int square); 
-   
-     static U64 getRandomHashVal(int rndNo); 
-   
-   
-     int wKingSq_, bKingSq_;  // Cached king positions 
-     int wMtrl_;              // Total value of all white pieces and pawns 
-     int bMtrl_;              // Total value of all black pieces and pawns 
-     int wMtrlPawns_;         // Total value of all white pawns 
-     int bMtrlPawns_;         // Total value of all black pawns 
-   
-     int squares[64]; 
-   
-     // Piece square table scores 
-     short psScore1_[Piece::nPieceTypes]; 
-     short psScore2_[Piece::nPieceTypes]; 
-   
-     // Bitboards 
-     U64 pieceTypeBB_[Piece::nPieceTypes]; 
-     U64 whiteBB_, blackBB_; 
-   
-     bool whiteMove; 
-   
-     /** Number of half-moves since last 50-move reset. */ 
-     int halfMoveClock; 
-   
-     /** Game move number, starting from 1. */ 
-     int fullMoveCounter; 
-   
-     int castleMask; 
-     int epSquare; 
-   
-     U64 hashKey;           // Cached Zobrist hash key 
-     U64 pHashKey;          // Cached Zobrist pawn hash key 
-     MatId matId;           // Cached material identifier 
-   
-     static U64 psHashKeys[Piece::nPieceTypes][64];    // [piece][square] 
-   
-     static U64 whiteHashKey; 
-     static U64 castleHashKeys[16];   // [castleMask] 
-     static U64 epHashKeys[9];        // [epFile + 1] (epFile==-1 for no ep) 
-     static U64 moveCntKeys[101];     // [min(halfMoveClock, 100)] 
-   
-     static const U64 zobristRndKeys[]; 
- }; 
-   
- /** For debugging. */ 
- std::ostream& operator<<(std::ostream& os, const Position& pos); 
-   
- inline bool 
- Position::equals(const Position& other) const { 
-     if (!drawRuleEquals(other)) 
-         return false; 
-     if (halfMoveClock != other.halfMoveClock) 
-         return false; 
-     if (fullMoveCounter != other.fullMoveCounter) 
-         return false; 
-     if (hashKey != other.hashKey) 
-         return false; 
-     if (pHashKey != other.pHashKey) 
-         return false; 
-     if (matId() != other.matId()) 
-         return false; 
-     return true; 
- } 
-   
- inline U64 
- Position::zobristHash() const { 
-     return hashKey; 
- } 
-   
- inline U64 
- Position::pawnZobristHash() const { 
-     return pHashKey; 
- } 
-   
- inline U64 
- Position::kingZobristHash() const { 
-     return psHashKeys[Piece::WKING][wKingSq()] ^ 
-            psHashKeys[Piece::BKING][bKingSq()]; 
- } 
-   
- inline U64 
- Position::historyHash() const { 
-     U64 ret = hashKey; 
-     if (halfMoveClock >= 40) { 
-         if (halfMoveClock < 80) 
-             ret ^= moveCntKeys[halfMoveClock / 10]; 
-         else 
-             ret ^= moveCntKeys[std::min(halfMoveClock, 100)]; 
-     } 
-     return ret; 
- } 
-   
- inline U64 
- Position::bookHash() const { 
-     U64 ret = hashKey; 
-     ret ^= moveCntKeys[std::min(halfMoveClock, 100)]; 
-     return ret; 
- } 
-   
- inline int 
- Position::materialId() const { 
-     return matId(); 
- } 
-   
- inline bool 
- Position::drawRuleEquals(Position other) const { 
-     for (int i = 0; i < 64; i++) 
-         if (squares[i] != other.squares[i]) 
-             return false; 
-     if (whiteMove != other.whiteMove) 
-         return false; 
-     if (castleMask != other.castleMask) 
-         return false; 
-     if (epSquare != other.epSquare) 
-         return false; 
-     return true; 
- } 
-   
- inline bool 
- Position::isWhiteMove() const { 
-     return whiteMove; 
- } 
-   
- inline void 
- Position::setWhiteMove(bool whiteMove) { 
-     if (whiteMove != this->whiteMove) { 
-         hashKey ^= whiteHashKey; 
-         this->whiteMove = whiteMove; 
-     } 
- } 
-   
- inline int 
- Position::getPiece(int square) const { 
-     return squares[square]; 
- } 
-   
- inline void 
- Position::setSEEPiece(int square, int piece) { 
-     int removedPiece = squares[square]; 
-   
-     // Update board 
-     squares[square] = piece; 
-   
-     // Update bitboards 
-     U64 sqMask = 1ULL << square; 
-     pieceTypeBB_[removedPiece] &= ~sqMask; 
-     pieceTypeBB_[piece] |= sqMask; 
-     if (removedPiece != Piece::EMPTY) { 
-         if (Piece::isWhite(removedPiece)) 
-             whiteBB_ &= ~sqMask; 
-         else 
-             blackBB_ &= ~sqMask; 
-     } 
-     if (piece != Piece::EMPTY) { 
-         if (Piece::isWhite(piece)) 
-             whiteBB_ |= sqMask; 
-         else 
-             blackBB_ |= sqMask; 
-     } 
- } 
-   
- inline bool 
- Position::a1Castle() const { 
-     return (castleMask & (1 << A1_CASTLE)) != 0; 
- } 
-   
- inline bool 
- Position::h1Castle() const { 
-     return (castleMask & (1 << H1_CASTLE)) != 0; 
- } 
-   
- inline bool 
- Position::a8Castle() const { 
-     return (castleMask & (1 << A8_CASTLE)) != 0; 
- } 
-   
- inline bool 
- Position::h8Castle() const { 
-     return (castleMask & (1 << H8_CASTLE)) != 0; 
- } 
-   
- inline int 
- Position::getCastleMask() const { 
-     return castleMask; 
- } 
-   
- inline void 
- Position::setCastleMask(int castleMask) { 
-     hashKey ^= castleHashKeys[this->castleMask]; 
-     hashKey ^= castleHashKeys[castleMask]; 
-     this->castleMask = castleMask; 
- } 
-   
- inline int 
- Position::getEpSquare() const { 
-     return epSquare; 
- } 
-   
- inline void 
- Position::setEpSquare(int epSquare) { 
-     if (this->epSquare != epSquare) { 
-         hashKey ^= epHashKeys[(this->epSquare >= 0) ? getX(this->epSquare) + 1 : 0]; 
-         hashKey ^= epHashKeys[(epSquare >= 0) ? getX(epSquare) + 1 : 0]; 
-         this->epSquare = epSquare; 
-     } 
- } 
-   
- inline int 
- Position::getKingSq(bool white) const { 
-     return white ? wKingSq() : bKingSq(); 
- } 
-   
- inline void 
- Position::unMakeMove(const Move& move, const UndoInfo& ui) { 
-     hashKey ^= whiteHashKey; 
-     whiteMove = !whiteMove; 
-     int p = squares[move.to()]; 
-     setPiece(move.from(), p); 
-     setPiece(move.to(), ui.capturedPiece); 
-     setCastleMask(ui.castleMask); 
-     setEpSquare(ui.epSquare); 
-     halfMoveClock = ui.halfMoveClock; 
-     bool wtm = whiteMove; 
-     if (move.promoteTo() != Piece::EMPTY) { 
-         p = wtm ? Piece::WPAWN : Piece::BPAWN; 
-         setPiece(move.from(), p); 
-     } 
-     if (!wtm) 
-         fullMoveCounter--; 
-   
-     // Handle castling 
-     int king = wtm ? Piece::WKING : Piece::BKING; 
-     if (p == king) { 
-         int k0 = move.from(); 
-         if (move.to() == k0 + 2) { // O-O 
-             movePieceNotPawn(k0 + 1, k0 + 3); 
-         } else if (move.to() == k0 - 2) { // O-O-O 
-             movePieceNotPawn(k0 - 1, k0 - 4); 
-         } 
-     } 
-   
-     // Handle en passant 
-     if (move.to() == epSquare) { 
-         if (p == Piece::WPAWN) { 
-             setPiece(move.to() - 8, Piece::BPAWN); 
-         } else if (p == Piece::BPAWN) { 
-             setPiece(move.to() + 8, Piece::WPAWN); 
-         } 
-     } 
- } 
-   
- inline void 
- Position::unMakeMoveB(const Move& move, const UndoInfo& ui) { 
-     int p = squares[move.to()]; 
-     setPieceB(move.from(), p); 
-     setPieceB(move.to(), ui.capturedPiece); 
-     bool wtm = whiteMove; 
-     if (move.promoteTo() != Piece::EMPTY) { 
-         p = wtm ? Piece::WPAWN : Piece::BPAWN; 
-         setPieceB(move.from(), p); 
-     } 
-   
-     // Handle castling 
-     int king = wtm ? Piece::WKING : Piece::BKING; 
-     if (p == king) { 
-         int k0 = move.from(); 
-         if (move.to() == k0 + 2) { // O-O 
-             movePieceNotPawnB(k0 + 1, k0 + 3); 
-         } else if (move.to() == k0 - 2) { // O-O-O 
-             movePieceNotPawnB(k0 - 1, k0 - 4); 
-         } 
-     } 
-   
-     // Handle en passant 
-     if (move.to() == epSquare) { 
-         if (p == Piece::WPAWN) { 
-             setPieceB(move.to() - 8, Piece::BPAWN); 
-         } else if (p == Piece::BPAWN) { 
-             setPieceB(move.to() + 8, Piece::WPAWN); 
-         } 
-     } 
- } 
-   
- inline void 
- Position::setPieceB(int square, int piece) { 
-     int removedPiece = squares[square]; 
-     squares[square] = piece; 
-   
-     // Update bitboards 
-     const U64 sqMask = 1ULL << square; 
-     pieceTypeBB_[removedPiece] &= ~sqMask; 
-     pieceTypeBB_[piece] |= sqMask; 
-   
-     if (removedPiece != Piece::EMPTY) { 
-         if (Piece::isWhite(removedPiece)) 
-             whiteBB_ &= ~sqMask; 
-         else 
-             blackBB_ &= ~sqMask; 
-     } 
-   
-     if (piece != Piece::EMPTY) { 
-         if (Piece::isWhite(piece)) { 
-             whiteBB_ |= sqMask; 
-             if (piece == Piece::WKING) 
-                 wKingSq_ = square; 
-         } else { 
-             blackBB_ |= sqMask; 
-             if (piece == Piece::BKING) 
-                 bKingSq_ = square; 
-         } 
-     } 
- } 
-   
- inline void 
- Position::movePieceNotPawnB(int from, int to) { 
-     const int piece = squares[from]; 
-   
-     squares[from] = Piece::EMPTY; 
-     squares[to] = piece; 
-   
-     const U64 sqMaskF = 1ULL << from; 
-     const U64 sqMaskT = 1ULL << to; 
-     pieceTypeBB_[piece] &= ~sqMaskF; 
-     pieceTypeBB_[piece] |= sqMaskT; 
-     if (Piece::isWhite(piece)) { 
-         whiteBB_ &= ~sqMaskF; 
-         whiteBB_ |= sqMaskT; 
-         if (piece == Piece::WKING) 
-             wKingSq_ = to; 
-     } else { 
-         blackBB_ &= ~sqMaskF; 
-         blackBB_ |= sqMaskT; 
-         if (piece == Piece::BKING) 
-             bKingSq_ = to; 
-     } 
- } 
-   
- inline void 
- Position::makeSEEMove(const Move& move, UndoInfo& ui) { 
-     ui.capturedPiece = squares[move.to()]; 
-     int p = squares[move.from()]; 
-   
-     // Handle en passant 
-     if (move.to() == epSquare) { 
-         if (p == Piece::WPAWN) { 
-             setSEEPiece(move.to() - 8, Piece::EMPTY); 
-         } else if (p == Piece::BPAWN) { 
-             setSEEPiece(move.to() + 8, Piece::EMPTY); 
-         } 
-     } 
-   
-     // Perform move 
-     setSEEPiece(move.from(), Piece::EMPTY); 
-     setSEEPiece(move.to(), p); 
-     whiteMove = !whiteMove; 
- } 
-   
- inline void 
- Position::unMakeSEEMove(const Move& move, const UndoInfo& ui) { 
-     whiteMove = !whiteMove; 
-     int p = squares[move.to()]; 
-     setSEEPiece(move.from(), p); 
-     setSEEPiece(move.to(), ui.capturedPiece); 
-   
-     // Handle en passant 
-     if (move.to() == epSquare) { 
-         if (p == Piece::WPAWN) { 
-             setSEEPiece(move.to() - 8, Piece::BPAWN); 
-         } else if (p == Piece::BPAWN) { 
-             setSEEPiece(move.to() + 8, Piece::WPAWN); 
-         } 
-     } 
- } 
-   
- inline int 
- Position::getSquare(int x, int y) { 
-     return y * 8 + x; 
- } 
-   
- /** Return x position (file) corresponding to a square. */ 
- inline int 
- Position::getX(int square) { 
-     return square & 7; 
- } 
-   
- /** Return y position (rank) corresponding to a square. */ 
- inline int 
- Position::getY(int square) { 
-     return square >> 3; 
- } 
-   
- inline int 
- Position::mirrorY(int square) { 
-     return square ^ 56; 
- } 
-   
- /** Return true if (x,y) is a dark square. */ 
- inline bool 
- Position::darkSquare(int x, int y) { 
-     return (x & 1) == (y & 1); 
- } 
-   
- inline void 
- Position::removeCastleRights(int square) { 
-     if (square == getSquare(0, 0)) { 
-         setCastleMask(castleMask & ~(1 << A1_CASTLE)); 
-     } else if (square == getSquare(7, 0)) { 
-         setCastleMask(castleMask & ~(1 << H1_CASTLE)); 
-     } else if (square == getSquare(0, 7)) { 
-         setCastleMask(castleMask & ~(1 << A8_CASTLE)); 
-     } else if (square == getSquare(7, 7)) { 
-         setCastleMask(castleMask & ~(1 << H8_CASTLE)); 
-     } 
- } 
-   
- inline int Position::getFullMoveCounter() const { 
-     return fullMoveCounter; 
- } 
-   
- inline void Position::setFullMoveCounter(int fm) { 
-     fullMoveCounter = fm; 
- } 
-   
- inline int Position::getHalfMoveClock() const { 
-     return halfMoveClock; 
- } 
-   
- inline void Position::setHalfMoveClock(int hm) { 
-     halfMoveClock = hm; 
- } 
-   
- inline int Position::psScore1(int piece) const { 
-     return psScore1_[piece]; 
- } 
-   
- inline int Position::psScore2(int piece) const { 
-     return psScore2_[piece]; 
- } 
-   
- inline U64 Position::pieceTypeBB(Piece::Type piece) const { 
-     return pieceTypeBB_[piece]; 
- } 
-   
- template <typename Piece0, typename... Pieces> 
- inline U64 Position::pieceTypeBB(Piece0 piece0, Pieces... pieces) const { 
-     return pieceTypeBB(piece0) | pieceTypeBB(pieces...); 
- } 
-   
- inline U64 Position::whiteBB() const { 
-     return whiteBB_; 
- } 
-   
- inline U64 Position::blackBB() const { 
-     return blackBB_; 
- }; 
-   
- inline U64 Position::colorBB(int wtm) const { 
-     return wtm ? whiteBB_ : blackBB_; 
- } 
-   
- inline U64 Position::occupiedBB() const { 
-     return whiteBB() | blackBB(); 
- } 
-   
- inline int Position::wKingSq() const { 
-     return wKingSq_; 
- } 
-   
- inline int Position::bKingSq() const { 
-     return bKingSq_; 
- } 
-   
- inline int Position::wMtrl() const { 
-     return wMtrl_; 
- } 
-   
- inline int Position::bMtrl() const { 
-     return bMtrl_; 
- } 
-   
- inline int Position::wMtrlPawns() const { 
-     return wMtrlPawns_; 
- } 
-   
- inline int Position::bMtrlPawns() const { 
-     return bMtrlPawns_; 
- } 
-   
- inline U64 Position::getHashKey(int piece, int square) { 
-     return psHashKeys[piece][square]; 
- } 
-   
- #endif /* POSITION_HPP_ */ 
-