- /* 
-     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/>. 
- */ 
-   
- /* 
-  * moveGen.hpp 
-  * 
-  *  Created on: Feb 25, 2012 
-  *      Author: petero 
-  */ 
-   
- #ifndef MOVEGEN_HPP_ 
- #define MOVEGEN_HPP_ 
-   
- #include "move.hpp" 
- #include "position.hpp" 
- #include "util/util.hpp" 
-   
- #include <cassert> 
-   
- //#define MOVELIST_DEBUG 
-   
- #ifdef MOVELIST_DEBUG 
- # include <set> 
- # include "textio.hpp" 
- #endif 
-   
- /** A stack-allocated move list object. */ 
- class MoveList { 
- public: 
-     MoveList(); 
-   
-     void clear(); 
-   
-           Move& operator[](int i); 
-     const Move& operator[](int i) const; 
-   
-     void addMove(int from, int to, int promoteTo); 
-   
-     /** Remove all moves that are not included in searchMoves. */ 
-     void filter(const std::vector<Move>& searchMoves); 
-   
-     int size; 
-   
- private: 
-     static const int MAX_MOVES = 256; 
-     int buf[sizeof(Move[MAX_MOVES])/sizeof(int)]; 
- }; 
-   
- /** 
-  * Generates move lists (pseudo-legal, legal, check evasions, captures). 
-  */ 
- class MoveGen { 
- public: 
-     MoveGen() = delete; 
-   
-     /** 
-      * Generate and return a list of pseudo-legal moves. 
-      * Pseudo-legal means that the moves don't necessarily defend from check threats. 
-      */ 
-     template <bool wtm> 
-     static void pseudoLegalMoves(const Position& pos, MoveList& moveList); 
-     static void pseudoLegalMoves(const Position& pos, MoveList& moveList); 
-   
-     /** 
-      * Generate and return a list of pseudo-legal check evasion moves. 
-      * Pseudo-legal means that the moves don't necessarily defend from check threats. 
-      */ 
-     template <bool wtm> 
-     static void checkEvasions(const Position& pos, MoveList& moveList); 
-     static void checkEvasions(const Position& pos, MoveList& moveList); 
-   
-     /** Generate captures, checks, and possibly some other moves that are too hard to filter out. */ 
-     template <bool wtm> 
-     static void pseudoLegalCapturesAndChecks(const Position& pos, MoveList& moveList); 
-     static void pseudoLegalCapturesAndChecks(const Position& pos, MoveList& moveList); 
-   
-     /** Generate and return a list of pseudo-legal capture moves. */ 
-     template <bool wtm> 
-     static void pseudoLegalCaptures(const Position& pos, MoveList& moveList); 
-     static void pseudoLegalCaptures(const Position& pos, MoveList& moveList); 
-   
-     /** Return true if the side to move is in check. */ 
-     static bool inCheck(const Position& pos); 
-   
-     /** Return true if making a move delivers check to the opponent */ 
-     static bool givesCheck(const Position& pos, const Move& m); 
-   
-     /** Return true if the side to move can take the opponents king. */ 
-     static bool canTakeKing(Position& pos); 
-   
-     /** Return true if a square is attacked by the opposite side. */ 
-     static bool sqAttacked(const Position& pos, int sq); 
-     static bool sqAttacked(const Position& pos, int sq, U64 occupied); 
-     template <bool wtm> static bool sqAttacked(const Position& pos, int sq, U64 occupied); 
-   
-     /** 
-      * Remove all illegal moves from moveList. 
-      * "moveList" is assumed to be a list of pseudo-legal moves. 
-      * This function removes the moves that don't defend from check threats. 
-      */ 
-     static void removeIllegal(Position& pos, MoveList& moveList); 
-   
-     /** Return true if the pseudo-legal move "move" is legal is position "pos". 
-      * isInCheck must be equal to inCheck(pos). */ 
-     static bool isLegal(Position& pos, const Move& move, bool isInCheck); 
-   
- private: 
-     /** Return the next piece in a given direction, starting from sq. */ 
-     static int nextPiece(const Position& pos, int sq, int delta); 
-   
-     /** Like nextPiece(), but handles board edges. */ 
-     static int nextPieceSafe(const Position& pos, int sq, int delta); 
-   
-     template <bool wtm> 
-     static void addPawnMovesByMask(MoveList& moveList, U64 mask, int delta, bool allPromotions); 
-   
-     static void addPawnDoubleMovesByMask(MoveList& moveList, U64 mask, int delta); 
-   
-     static void addMovesByMask(MoveList& moveList, int sq0, U64 mask); 
- }; 
-   
-   
- inline 
- MoveList::MoveList() 
-     : size(0) { 
- } 
-   
- inline void 
- MoveList::clear() { 
-     size = 0; 
- } 
-   
- inline Move& 
- MoveList::operator[](int i) { 
-     return ((Move*)&buf[0])[i]; 
- } 
- inline const Move& 
- MoveList::operator[](int i) const { 
-     return ((Move*)&buf[0])[i]; 
- } 
-   
- inline void 
- MoveList::addMove(int from, int to, int promoteTo) { 
-     Move& m = (*this)[size++]; 
-     new (&m) Move(from, to, promoteTo, 0); 
- } 
-   
- inline void 
- MoveGen::pseudoLegalMoves(const Position& pos, MoveList& moveList) { 
-     if (pos.isWhiteMove()) 
-         pseudoLegalMoves<true>(pos, moveList); 
-     else 
-         pseudoLegalMoves<false>(pos, moveList); 
- } 
-   
- inline void 
- MoveGen::checkEvasions(const Position& pos, MoveList& moveList) { 
-     if (pos.isWhiteMove()) 
-         checkEvasions<true>(pos, moveList); 
-     else 
-         checkEvasions<false>(pos, moveList); 
- } 
-   
- inline void 
- MoveGen::pseudoLegalCapturesAndChecks(const Position& pos, MoveList& moveList) { 
-     if (pos.isWhiteMove()) 
-         pseudoLegalCapturesAndChecks<true>(pos, moveList); 
-     else 
-         pseudoLegalCapturesAndChecks<false>(pos, moveList); 
- } 
-   
- inline void 
- MoveGen::pseudoLegalCaptures(const Position& pos, MoveList& moveList) { 
-     if (pos.isWhiteMove()) 
-         pseudoLegalCaptures<true>(pos, moveList); 
-     else 
-         pseudoLegalCaptures<false>(pos, moveList); 
- } 
-   
- inline bool 
- MoveGen::inCheck(const Position& pos) { 
-     int kingSq = pos.getKingSq(pos.isWhiteMove()); 
-     return sqAttacked(pos, kingSq); 
- } 
-   
- inline bool 
- MoveGen::canTakeKing(Position& pos) { 
-     pos.setWhiteMove(!pos.isWhiteMove()); 
-     bool ret = inCheck(pos); 
-     pos.setWhiteMove(!pos.isWhiteMove()); 
-     return ret; 
- } 
-   
- inline bool 
- MoveGen::sqAttacked(const Position& pos, int sq) { 
-     const U64 occupied = pos.occupiedBB(); 
-     return sqAttacked(pos, sq, occupied); 
- } 
-   
- inline bool 
- MoveGen::sqAttacked(const Position& pos, int sq, U64 occupied) { 
-     return pos.isWhiteMove() ? sqAttacked<true>(pos, sq, occupied) 
-                              : sqAttacked<false>(pos, sq, occupied); 
- } 
-   
- template <bool wtm> 
- inline bool 
- MoveGen::sqAttacked(const Position& pos, int sq, U64 occupied) { 
-     using OtherColor = ColorTraits<!wtm>; 
-     if ((BitBoard::knightAttacks[sq] & pos.pieceTypeBB(OtherColor::KNIGHT)) != 0) 
-         return true; 
-     if ((BitBoard::kingAttacks[sq] & pos.pieceTypeBB(OtherColor::KING)) != 0) 
-         return true; 
-     if (wtm) { 
-         if ((BitBoard::wPawnAttacks[sq] & pos.pieceTypeBB(OtherColor::PAWN)) != 0) 
-             return true; 
-     } else { 
-         if ((BitBoard::bPawnAttacks[sq] & pos.pieceTypeBB(OtherColor::PAWN)) != 0) 
-             return true; 
-     } 
-     U64 bbQueen = pos.pieceTypeBB(OtherColor::QUEEN); 
-     if ((BitBoard::bishopAttacks(sq, occupied) & (pos.pieceTypeBB(OtherColor::BISHOP) | bbQueen)) != 0) 
-         return true; 
-     if ((BitBoard::rookAttacks(sq, occupied) & (pos.pieceTypeBB(OtherColor::ROOK) | bbQueen)) != 0) 
-         return true; 
-     return false; 
- } 
-   
- inline int 
- MoveGen::nextPiece(const Position& pos, int sq, int delta) { 
-     while (true) { 
-         sq += delta; 
-         int p = pos.getPiece(sq); 
-         if (p != Piece::EMPTY) 
-             return p; 
-     } 
-     assert(false); 
-     return -1; 
- } 
-   
- inline int 
- MoveGen::nextPieceSafe(const Position& pos, int sq, int delta) { 
-     int dx = 0, dy = 0; 
-     switch (delta) { 
-     case 1: dx=1; dy=0; break; 
-     case 9: dx=1; dy=1; break; 
-     case 8: dx=0; dy=1; break; 
-     case 7: dx=-1; dy=1; break; 
-     case -1: dx=-1; dy=0; break; 
-     case -9: dx=-1; dy=-1; break; 
-     case -8: dx=0; dy=-1; break; 
-     case -7: dx=1; dy=-1; break; 
-     } 
-     int x = Position::getX(sq); 
-     int y = Position::getY(sq); 
-     while (true) { 
-         x += dx; 
-         y += dy; 
-         if ((x < 0) || (x > 7) || (y < 0) || (y > 7)) { 
-             return Piece::EMPTY; 
-         } 
-         int p = pos.getPiece(Position::getSquare(x, y)); 
-         if (p != Piece::EMPTY) 
-             return p; 
-     } 
-     assert(false); 
-     return -1; 
- } 
-   
- template <bool wtm> 
- inline void 
- MoveGen::addPawnMovesByMask(MoveList& moveList, U64 mask, int delta, bool allPromotions) { 
-     using MyColor = ColorTraits<wtm>; 
-     if (mask == 0) 
-         return; 
-     U64 promMask = mask & BitBoard::maskRow1Row8; 
-     mask &= ~promMask; 
-     while (promMask != 0) { 
-         int sq = BitBoard::extractSquare(promMask); 
-         int sq0 = sq + delta; 
-         moveList.addMove(sq0, sq, MyColor::QUEEN); 
-         moveList.addMove(sq0, sq, MyColor::KNIGHT); 
-         if (allPromotions) { 
-             moveList.addMove(sq0, sq, MyColor::ROOK); 
-             moveList.addMove(sq0, sq, MyColor::BISHOP); 
-         } 
-     } 
-     while (mask != 0) { 
-         int sq = BitBoard::extractSquare(mask); 
-         moveList.addMove(sq + delta, sq, Piece::EMPTY); 
-     } 
- } 
-   
- inline void 
- MoveGen::addPawnDoubleMovesByMask(MoveList& moveList, U64 mask, int delta) { 
-     while (mask != 0) { 
-         int sq = BitBoard::extractSquare(mask); 
-         moveList.addMove(sq + delta, sq, Piece::EMPTY); 
-     } 
- } 
-   
- inline void 
- MoveGen::addMovesByMask(MoveList& moveList, int sq0, U64 mask) { 
-     while (mask != 0) { 
-         int sq = BitBoard::extractSquare(mask); 
-         moveList.addMove(sq0, sq, Piece::EMPTY); 
-     } 
- } 
-   
- #endif /* MOVEGEN_HPP_ */ 
-