]> git.sesse.net Git - stockfish/commitdiff
Manual merge
authorMarco Costalba <mcostalba@gmail.com>
Sun, 26 Oct 2008 20:44:58 +0000 (21:44 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Sun, 26 Oct 2008 20:44:58 +0000 (21:44 +0100)
1  2 
src/bitboard.h
src/movegen.cpp
src/movegen.h
src/movepick.cpp
src/movepick.h
src/position.h

diff --combined src/bitboard.h
index eceb845e643112d929c24a8a0b6236ab574fd589,8c6a7007e7263b069ebea469ac687c0e327d7fc6..1222ddfa3f50be9051cf85a0e1aa0504f6707ac8
@@@ -7,12 -7,12 +7,13 @@@
    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.
 -  
 +
++
    Stockfish 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/>.
  */
  // platform macros defined below
  #define AUTO_CONFIGURATION
  
 +// Quiet a warning on Intel compiler
 +#if !defined(__SIZEOF_INT__ )
 +#define __SIZEOF_INT__ 0
 +#endif
  
  // Check for 64 bits for different compilers: Intel, MSVC and gcc
  #if defined(__x86_64) || defined(_WIN64) || (__SIZEOF_INT__ > 4)
@@@ -43,7 -39,7 +44,7 @@@
  #if !defined(AUTO_CONFIGURATION) || defined(IS_64BIT)
  
  //#define USE_COMPACT_ROOK_ATTACKS
 -//#define USE_32BIT_ATTACKS 
 +//#define USE_32BIT_ATTACKS
  #define USE_FOLDED_BITSCAN
  
  #define BITCOUNT_SWAR_64
@@@ -52,7 -48,7 +53,7 @@@
  
  #else
  
 -#define USE_32BIT_ATTACKS 
 +#define USE_32BIT_ATTACKS
  #define USE_FOLDED_BITSCAN
  #define BITCOUNT_SWAR_32
  
@@@ -97,7 -93,7 +98,7 @@@ const Bitboard FileHBB = 0x808080808080
  
  extern const Bitboard FileBB[8];
  extern const Bitboard NeighboringFilesBB[8];
 -extern const Bitboard ThisAndNeighboringFilesBB[8];  
 +extern const Bitboard ThisAndNeighboringFilesBB[8];
  
  const Bitboard Rank1BB = 0xFFULL;
  const Bitboard Rank2BB = 0xFF00ULL;
@@@ -132,7 -128,7 +133,7 @@@ extern int RAttackIndex[64]
  extern Bitboard RAttacks[0x19000];
  #endif // defined(USE_COMPACT_ROOK_ATTACKS)
  
 -extern const uint64_t BMult[64]; 
 +extern const uint64_t BMult[64];
  extern const int BShift[64];
  extern Bitboard BMask[64];
  extern int BAttackIndex[64];
@@@ -147,19 -143,29 +148,19 @@@ extern Bitboard QueenPseudoAttacks[64]
  //// Inline functions
  ////
  
 -/// Functions for testing whether a given bit is set in a bitboard, and for 
 +/// Functions for testing whether a given bit is set in a bitboard, and for
  /// setting and clearing bits.
  
 -inline Bitboard set_mask_bb(Square s) {
 -  //  return 1ULL << s;
 -  return SetMaskBB[s];
 -}
 -
 -inline Bitboard clear_mask_bb(Square s) {
 -  //  return ~set_mask_bb(s);
 -  return ClearMaskBB[s];
 -}
 -
  inline Bitboard bit_is_set(Bitboard b, Square s) {
 -  return b & set_mask_bb(s);
 +  return b & SetMaskBB[s];
  }
  
  inline void set_bit(Bitboard *b, Square s) {
 -  *b |= set_mask_bb(s);
 +  *b |= SetMaskBB[s];
  }
  
  inline void clear_bit(Bitboard *b, Square s) {
 -  *b &= clear_mask_bb(s);
 +  *b &= ClearMaskBB[s];
  }
  
  
@@@ -194,7 -200,7 +195,7 @@@ inline Bitboard neighboring_files_bb(Fi
  inline Bitboard neighboring_files_bb(Square s) {
    return neighboring_files_bb(square_file(s));
  }
 -  
 +
  
  /// this_and_neighboring_files_bb takes a file or a square as input, and
  /// returns a bitboard representing all squares on the given and neighboring
@@@ -269,9 -275,9 +270,9 @@@ inline Bitboard rook_attacks_bb(Square 
  
  inline Bitboard rook_attacks_bb(Square s, Bitboard blockers) {
    Bitboard b = blockers & RMask[s];
 -  return RAttacks[RAttackIndex[s] + 
 +  return RAttacks[RAttackIndex[s] +
                    (unsigned(int(b) * int(RMult[s]) ^
 -                            int(b >> 32) * int(RMult[s] >> 32)) 
 +                            int(b >> 32) * int(RMult[s] >> 32))
                     >> RShift[s])];
  }
  
@@@ -288,9 -294,9 +289,9 @@@ inline Bitboard rook_attacks_bb(Square 
  
  inline Bitboard bishop_attacks_bb(Square s, Bitboard blockers) {
    Bitboard b = blockers & BMask[s];
 -  return BAttacks[BAttackIndex[s] + 
 +  return BAttacks[BAttackIndex[s] +
                    (unsigned(int(b) * int(BMult[s]) ^
 -                            int(b >> 32) * int(BMult[s] >> 32)) 
 +                            int(b >> 32) * int(BMult[s] >> 32))
                     >> BShift[s])];
  }
  
@@@ -318,9 -324,9 +319,9 @@@ inline Bitboard squares_between(Square 
  }
  
  
 -/// squares_in_front_of takes a color and a square as input, and returns a 
 +/// squares_in_front_of takes a color and a square as input, and returns a
  /// bitboard representing all squares along the line in front of the square,
 -/// from the point of view of the given color.  For instance, 
 +/// from the point of view of the given color.  For instance,
  /// squares_in_front_of(BLACK, SQ_E4) returns a bitboard with the squares
  /// e3, e2 and e1 set.
  
@@@ -337,8 -343,8 +338,8 @@@ inline Bitboard squares_behind(Color c
  }
  
  
 -/// passed_pawn_mask takes a color and a square as input, and returns a 
 -/// bitboard mask which can be used to test if a pawn of the given color on 
 +/// passed_pawn_mask takes a color and a square as input, and returns a
 +/// bitboard mask which can be used to test if a pawn of the given color on
  /// the given square is a passed pawn.
  
  inline Bitboard passed_pawn_mask(Color c, Square s) {
@@@ -355,7 -361,7 +356,7 @@@ inline Bitboard outpost_mask(Color c, S
  }
  
  
 -/// isolated_pawn_mask takes a square as input, and returns a bitboard mask 
 +/// isolated_pawn_mask takes a square as input, and returns a bitboard mask
  /// which can be used to test whether a pawn on the given square is isolated.
  
  inline Bitboard isolated_pawn_mask(Square s) {
diff --combined src/movegen.cpp
index 7c59f5e3084f841572b580eaa22d49a486b9f598,50f8b4887ff0f7887378565abca3c674565f50d3..397732b522b8ed96e5bce3a1eb1d578acfb2bc49
@@@ -6,12 -6,12 +6,12 @@@
    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.
 -  
 +
    Stockfish 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/>.
  */
@@@ -25,9 -25,6 +25,9 @@@
  
  #include "movegen.h"
  
 +// Simple macro to wrap a very common while loop, no facny, no flexibility,
 +// hardcoded list name 'mlist' and from square 'from'.
 +#define SERIALIZE_MOVES(b) while (b) (*mlist++).move = make_move(from, pop_1st_bit(&b))
  
  ////
  //// Local definitions
  
  namespace {
  
 -  struct PawnParams {
 -      Bitboard Rank3BB, Rank8BB;
 -      Rank RANK_8;
 -      SquareDelta DELTA_N, DELTA_NE, DELTA_NW;
 -      Color us, them;
 -  };
 -  const PawnParams WhitePawnParams = { Rank3BB, Rank8BB, RANK_8, DELTA_N, DELTA_NE, DELTA_NW, WHITE, BLACK };
 -  const PawnParams BlackPawnParams = { Rank6BB, Rank1BB, RANK_1, DELTA_S, DELTA_SE, DELTA_SW, BLACK, WHITE };
 -  
 -  int generate_castle_moves(const Position&, MoveStack*, Color);
 +  // Function
 +  MoveStack* generate_castle_moves(const Position&, MoveStack*);
 +
 +  // Template generate_pawn_captures() with specializations
 +  template<Color, Color, Bitboard, SquareDelta, SquareDelta, SquareDelta>
 +  MoveStack* do_generate_pawn_captures(const Position& pos, MoveStack* mlist);
  
    template<Color>
 -  int generate_pawn_captures(const Position&, MoveStack*);
 +  inline MoveStack* generate_pawn_captures(const Position& p, MoveStack* m) {
 +      return do_generate_pawn_captures<WHITE, BLACK, Rank8BB, DELTA_NE, DELTA_NW, DELTA_N>(p, m);
 +  }
 +  template<>
 +  inline MoveStack* generate_pawn_captures<BLACK>(const Position& p, MoveStack* m) {
 +      return do_generate_pawn_captures<BLACK, WHITE, Rank1BB, DELTA_SE, DELTA_SW, DELTA_S>(p, m);
 +  }
 +
 +  // Template generate_pawn_noncaptures() with specializations
 +  template<Color, Color, Bitboard, Bitboard, SquareDelta, SquareDelta, SquareDelta>
 +  MoveStack* do_generate_pawn_noncaptures(const Position& pos, MoveStack* mlist);
  
    template<Color>
 -  int generate_pawn_noncaptures(const Position&, MoveStack*);
 -  
 +  inline MoveStack* generate_pawn_noncaptures(const Position& p, MoveStack* m) {
 +      return do_generate_pawn_noncaptures<WHITE, BLACK, Rank8BB, Rank3BB, DELTA_NE, DELTA_NW, DELTA_N>(p, m);
 +  }
 +  template<>
 +  inline MoveStack* generate_pawn_noncaptures<BLACK>(const Position& p, MoveStack* m) {
 +      return do_generate_pawn_noncaptures<BLACK, WHITE, Rank1BB, Rank6BB, DELTA_SE, DELTA_SW, DELTA_S>(p, m);
 +  }
 +
 +  // Template generate_pawn_blocking_evasions() with specializations
 +  template<Color Us, Rank, Bitboard, SquareDelta>
 +  MoveStack* do_generate_pawn_blocking_evasions(const Position& pos, Bitboard not_pinned,
 +                                                Bitboard blockSquares, MoveStack* mlist);
    template<Color>
 -  int generate_pawn_checks(const Position&, Bitboard, Square, MoveStack*, int);
 +  inline MoveStack* generate_pawn_blocking_evasions(const Position& p, Bitboard np, Bitboard bs, MoveStack* m) {
 +      return do_generate_pawn_blocking_evasions<WHITE, RANK_8, Rank3BB, DELTA_N>(p, np, bs, m);
 +  }
 +  template<>
 +  inline MoveStack* generate_pawn_blocking_evasions<BLACK>(const Position& p, Bitboard np, Bitboard bs, MoveStack* m) {
 +      return do_generate_pawn_blocking_evasions<BLACK, RANK_1, Rank6BB, DELTA_S>(p, np, bs, m);
 +  }
 +
 +  // Template generate_pawn_checks() with specializations
 +  template<Color, Color, Bitboard, Bitboard, SquareDelta>
 +  MoveStack* do_generate_pawn_checks(const Position&, Bitboard, Square, MoveStack*);
  
    template<Color>
 -  int generate_pawn_blocking_evasions(const Position&, Bitboard, Bitboard, MoveStack*, int);
 +  inline MoveStack* generate_pawn_checks(const Position& p, Bitboard dc, Square ksq, MoveStack* m) {
 +      return do_generate_pawn_checks<WHITE, BLACK, Rank8BB, Rank3BB, DELTA_N>(p, dc, ksq, m);
 +  }
 +  template<>
 +  inline MoveStack* generate_pawn_checks<BLACK>(const Position& p, Bitboard dc, Square ksq, MoveStack* m) {
 +      return do_generate_pawn_checks<BLACK, WHITE, Rank1BB, Rank6BB, DELTA_S>(p, dc, ksq, m);
 +  }
  
 +  // non-pawn templates
    template<PieceType>
 -  int generate_piece_moves(const Position&, MoveStack*, Color, Bitboard);
 +  MoveStack* generate_piece_moves(const Position&, MoveStack*, Color us, Bitboard);
 +  template<>
 +  MoveStack* generate_piece_moves<KING>(const Position& pos, MoveStack* mlist, Color us, Bitboard target);
  
    template<PieceType>
 -  int generate_piece_checks(const Position&, Bitboard, Bitboard, Square, MoveStack*, int);
 +  MoveStack* generate_piece_checks(const Position&, Bitboard, Bitboard, Square, MoveStack*);
 +  MoveStack* generate_piece_checks_king(const Position&, Square, Bitboard, Square, MoveStack*);
  
    template<PieceType>
 -  int generate_piece_blocking_evasions(const Position&, Bitboard, Bitboard, MoveStack*, int);
 -
 -
 -  /// Templates with specializations are defined here to avoid lookup issues
 -
 -  template<PieceType Piece>
 -  int generate_piece_checks(const Position& pos, Bitboard target, Bitboard dc,
 -                            Square ksq, MoveStack* mlist, int n) {
 -    // Discovered checks
 -    Bitboard b = target & dc;
 -    while (b)
 -    {
 -        Square from = pop_1st_bit(&b);
 -        Bitboard bb = pos.piece_attacks<Piece>(from) & pos.empty_squares();
 -        while (bb)
 -        {
 -            Square to = pop_1st_bit(&bb);
 -            mlist[n++].move = make_move(from, to);
 -        }
 -    }
 -    // Direct checks
 -    b = target & ~dc;
 -    Bitboard checkSqs = pos.piece_attacks<Piece>(ksq) & pos.empty_squares();
 -    while (b)
 -    {
 -        Square from = pop_1st_bit(&b);
 -        Bitboard bb = pos.piece_attacks<Piece>(from) & checkSqs;
 -        while (bb)
 -        {
 -            Square to = pop_1st_bit(&bb);
 -            mlist[n++].move = make_move(from, to);
 -        }
 -    }
 -    return n;
 -  }
 -
 -
 -  template<> // Special case the King
 -  int generate_piece_checks<KING>(const Position& pos, Bitboard, Bitboard dc,
 -                                  Square ksq, MoveStack* mlist, int n) {
 -    if (bit_is_set(dc, ksq))
 -    {
 -        Bitboard bb =   pos.piece_attacks<KING>(ksq)
 -                      & pos.empty_squares()
 -                      & ~QueenPseudoAttacks[ksq];
 -        while (bb)
 -        {
 -            Square to = pop_1st_bit(&bb);
 -            mlist[n++].move = make_move(ksq, to);
 -        }
 -    }
 -    return n;
 -  }
 +  MoveStack* generate_piece_blocking_evasions(const Position&, Bitboard, Bitboard, MoveStack*);
  }
  
  
@@@ -120,95 -133,96 +120,95 @@@ int generate_captures(const Position& p
  
    Color us = pos.side_to_move();
    Bitboard target = pos.pieces_of_color(opposite_color(us));
 -  int n;
 +  MoveStack* mlist_start = mlist;
  
    if (us == WHITE)
 -      n = generate_pawn_captures<WHITE>(pos, mlist);
 +      mlist = generate_pawn_captures<WHITE>(pos, mlist);
    else
 -      n = generate_pawn_captures<BLACK>(pos, mlist);
 -
 -  n += generate_piece_moves<KNIGHT>(pos, mlist+n, us, target);
 -  n += generate_piece_moves<BISHOP>(pos, mlist+n, us, target);
 -  n += generate_piece_moves<ROOK>(pos, mlist+n, us, target);
 -  n += generate_piece_moves<QUEEN>(pos, mlist+n, us, target);
 -  n += generate_piece_moves<KING>(pos, mlist+n, us, target);
 -  return n;
 +      mlist = generate_pawn_captures<BLACK>(pos, mlist);
 +
 +  mlist = generate_piece_moves<KNIGHT>(pos, mlist, us, target);
 +  mlist = generate_piece_moves<BISHOP>(pos, mlist, us, target);
 +  mlist = generate_piece_moves<ROOK>(pos, mlist, us, target);
 +  mlist = generate_piece_moves<QUEEN>(pos, mlist, us, target);
 +  mlist = generate_piece_moves<KING>(pos, mlist, us, target);
 +  return int(mlist - mlist_start);
  }
  
  
 -/// generate_noncaptures() generates all pseudo-legal non-captures and 
 +/// generate_noncaptures() generates all pseudo-legal non-captures and
  /// underpromotions.  The return value is the number of moves generated.
  
 -int generate_noncaptures(const Position& pos, MoveStack *mlist) {
 +int generate_noncaptures(const Position& pos, MoveStackmlist) {
  
    assert(pos.is_ok());
    assert(!pos.is_check());
  
    Color us = pos.side_to_move();
    Bitboard target = pos.empty_squares();
 -  int n;
 +  MoveStack* mlist_start = mlist;
  
    if (us == WHITE)
 -      n = generate_pawn_noncaptures<WHITE>(pos, mlist);
 +      mlist = generate_pawn_noncaptures<WHITE>(pos, mlist);
    else
 -      n = generate_pawn_noncaptures<BLACK>(pos, mlist);
 -
 -  n += generate_piece_moves<KNIGHT>(pos, mlist+n, us, target);
 -  n += generate_piece_moves<BISHOP>(pos, mlist+n, us, target);
 -  n += generate_piece_moves<ROOK>(pos, mlist+n, us, target);
 -  n += generate_piece_moves<QUEEN>(pos, mlist+n, us, target);
 -  n += generate_piece_moves<KING>(pos, mlist+n, us, target);
 -
 -  n += generate_castle_moves(pos, mlist+n, us);
 -  return n;
 +      mlist = generate_pawn_noncaptures<BLACK>(pos, mlist);
 +
 +  mlist = generate_piece_moves<KNIGHT>(pos, mlist, us, target);
 +  mlist = generate_piece_moves<BISHOP>(pos, mlist, us, target);
 +  mlist = generate_piece_moves<ROOK>(pos, mlist, us, target);
 +  mlist = generate_piece_moves<QUEEN>(pos, mlist, us, target);
 +  mlist = generate_piece_moves<KING>(pos, mlist, us, target);
 +  mlist = generate_castle_moves(pos, mlist);
 +  return int(mlist - mlist_start);
  }
  
  
  /// generate_checks() generates all pseudo-legal non-capturing, non-promoting
  /// checks, except castling moves (will add this later).  It returns the
 -/// number of generated moves.  
 +/// number of generated moves.
  
  int generate_checks(const Position& pos, MoveStack* mlist, Bitboard dc) {
  
    assert(pos.is_ok());
    assert(!pos.is_check());
  
 -  int n;
    Color us = pos.side_to_move();
    Square ksq = pos.king_square(opposite_color(us));
 +  MoveStack* mlist_start = mlist;
  
    assert(pos.piece_on(ksq) == king_of_color(opposite_color(us)));
  
    dc = pos.discovered_check_candidates(us);
  
    // Pawn moves
 -  if (us == WHITE)    
 -     n = generate_pawn_checks<WHITE>(pos, dc, ksq, mlist, 0);
 +  if (us == WHITE)
 +     mlist = generate_pawn_checks<WHITE>(pos, dc, ksq, mlist);
    else
 -     n = generate_pawn_checks<BLACK>(pos, dc, ksq, mlist, 0);
 +     mlist = generate_pawn_checks<BLACK>(pos, dc, ksq, mlist);
  
    // Pieces moves
    Bitboard b = pos.knights(us);
    if (b)
 -      n = generate_piece_checks<KNIGHT>(pos, b, dc, ksq, mlist, n);
 +      mlist = generate_piece_checks<KNIGHT>(pos, b, dc, ksq, mlist);
  
    b = pos.bishops(us);
    if (b)
 -      n = generate_piece_checks<BISHOP>(pos, b, dc, ksq, mlist, n);
 +      mlist = generate_piece_checks<BISHOP>(pos, b, dc, ksq, mlist);
  
    b = pos.rooks(us);
    if (b)
 -      n = generate_piece_checks<ROOK>(pos, b, dc, ksq, mlist, n);
 +      mlist = generate_piece_checks<ROOK>(pos, b, dc, ksq, mlist);
  
    b = pos.queens(us);
    if (b)
 -      n = generate_piece_checks<QUEEN>(pos, b, dc, ksq, mlist, n);
 +      mlist = generate_piece_checks<QUEEN>(pos, b, dc, ksq, mlist);
  
    // Hopefully we always have a king ;-)
 -  n = generate_piece_checks<KING>(pos, b, dc, pos.king_square(us), mlist, n);
 +  mlist = generate_piece_checks_king(pos, pos.king_square(us), dc, ksq, mlist);
  
    // TODO: Castling moves!
 -  
 -  return n;
 +
 +  return int(mlist - mlist_start);
  }
  
  
@@@ -222,14 -236,14 +222,14 @@@ int generate_evasions(const Position& p
    assert(pos.is_ok());
    assert(pos.is_check());
  
 +  Square from, to;
    Color us = pos.side_to_move();
    Color them = opposite_color(us);
    Square ksq = pos.king_square(us);
 -  Square from, to;
 -  int n = 0;
 +  MoveStack* mlist_start = mlist;
  
    assert(pos.piece_on(ksq) == king_of_color(us));
 -  
 +
    // Generate evasions for king
    Bitboard b1 = pos.piece_attacks<KING>(ksq) & ~pos.pieces_of_color(us);
    Bitboard b2 = pos.occupied_squares();
  
    while (b1)
    {
 -    Square to = pop_1st_bit(&b1);
 +    to = pop_1st_bit(&b1);
  
 -    // Make sure to is not attacked by the other side. This is a bit ugly,
 +    // Make sure 'to' is not attacked by the other side. This is a bit ugly,
      // because we can't use Position::square_is_attacked. Instead we use
      // the low-level bishop_attacks_bb and rook_attacks_bb with the bitboard
      // b2 (the occupied squares with the king removed) in order to test whether
      // the king will remain in check on the destination square.
 -    if (!(   (bishop_attacks_bb(to, b2)  & pos.bishops_and_queens(them))
 -          || (rook_attacks_bb(to, b2)    & pos.rooks_and_queens(them))
 -          || (pos.piece_attacks<KNIGHT>(to)     & pos.knights(them))
 -          || (pos.pawn_attacks(us, to)   & pos.pawns(them))
 -          || (pos.piece_attacks<KING>(to)       & pos.kings(them))))
 +    if (!(   (pos.piece_attacks<KNIGHT>(to) & pos.knights(them))
 +          || (pos.pawn_attacks(us, to)      & pos.pawns(them))
 +          || (bishop_attacks_bb(to, b2)     & pos.bishops_and_queens(them))
 +          || (rook_attacks_bb(to, b2)       & pos.rooks_and_queens(them))
 +          || (pos.piece_attacks<KING>(to)   & pos.kings(them))))
  
 -        mlist[n++].move = make_move(ksq, to);
 +        (*mlist++).move = make_move(ksq, to);
    }
  
    // Generate evasions for other pieces only if not double check. We use a
            from = pop_1st_bit(&b1);
            if (relative_rank(us, checksq) == RANK_8)
            {
 -              mlist[n++].move = make_promotion_move(from, checksq, QUEEN);
 -              mlist[n++].move = make_promotion_move(from, checksq, ROOK);
 -              mlist[n++].move = make_promotion_move(from, checksq, BISHOP);
 -              mlist[n++].move = make_promotion_move(from, checksq, KNIGHT);
 +              (*mlist++).move = make_promotion_move(from, checksq, QUEEN);
 +              (*mlist++).move = make_promotion_move(from, checksq, ROOK);
 +              (*mlist++).move = make_promotion_move(from, checksq, BISHOP);
 +              (*mlist++).move = make_promotion_move(from, checksq, KNIGHT);
            } else
 -              mlist[n++].move = make_move(from, checksq);
 +              (*mlist++).move = make_move(from, checksq);
        }
  
        // Pieces captures
        while (b1)
        {
            from = pop_1st_bit(&b1);
 -          mlist[n++].move = make_move(from, checksq);
 +          (*mlist++).move = make_move(from, checksq);
        }
  
        // Blocking check evasions are possible only if the checking piece is
            // Pawn moves. Because a blocking evasion can never be a capture, we
            // only generate pawn pushes.
            if (us == WHITE)
 -              n = generate_pawn_blocking_evasions<WHITE>(pos, not_pinned, blockSquares, mlist, n);
 +              generate_pawn_blocking_evasions<WHITE>(pos, not_pinned, blockSquares, mlist);
            else
 -              n = generate_pawn_blocking_evasions<BLACK>(pos, not_pinned, blockSquares, mlist, n);
 +              generate_pawn_blocking_evasions<BLACK>(pos, not_pinned, blockSquares, mlist);
  
            // Pieces moves
            b1 = pos.knights(us) & not_pinned;
            if (b1)
 -              n = generate_piece_blocking_evasions<KNIGHT>(pos, b1, blockSquares, mlist, n);
 +              generate_piece_blocking_evasions<KNIGHT>(pos, b1, blockSquares, mlist);
  
            b1 = pos.bishops(us) & not_pinned;
            if (b1)
 -              n = generate_piece_blocking_evasions<BISHOP>(pos, b1, blockSquares, mlist, n);
 +              generate_piece_blocking_evasions<BISHOP>(pos, b1, blockSquares, mlist);
  
            b1 = pos.rooks(us) & not_pinned;
            if (b1)
 -              n = generate_piece_blocking_evasions<ROOK>(pos, b1, blockSquares, mlist, n);
 +              generate_piece_blocking_evasions<ROOK>(pos, b1, blockSquares, mlist);
  
            b1 = pos.queens(us) & not_pinned;
            if (b1)
 -              n = generate_piece_blocking_evasions<QUEEN>(pos, b1, blockSquares, mlist, n);
 +              generate_piece_blocking_evasions<QUEEN>(pos, b1, blockSquares, mlist);
      }
  
      // Finally, the ugly special case of en passant captures. An en passant
          b1 = pos.pawn_attacks(them, to) & pos.pawns(us);
  
          assert(b1 != EmptyBoardBB);
 -  
 +
          b1 &= not_pinned;
          while (b1)
          {
              clear_bit(&b2, checksq);
              if (!(  (bishop_attacks_bb(ksq, b2) & pos.bishops_and_queens(them))
                    ||(rook_attacks_bb(ksq, b2)   & pos.rooks_and_queens(them))))
 -                
 -                 mlist[n++].move = make_ep_move(from, to);
 +
 +                 (*mlist++).move = make_ep_move(from, to);
          }
      }
    }
 -  return n;
 +  return int(mlist - mlist_start);
  }
  
  
@@@ -377,33 -391,32 +377,33 @@@ int generate_legal_moves(const Position
    if (pos.is_check())
        return generate_evasions(pos, mlist);
  
 -  // Generate pseudo-legal moves:
 +  // Generate pseudo-legal moves
    int n = generate_captures(pos, mlist);
    n += generate_noncaptures(pos, mlist + n);
  
    Bitboard pinned = pos.pinned_pieces(pos.side_to_move());
  
 -  // Remove illegal moves from the list:
 +  // Remove illegal moves from the list
    for (int i = 0; i < n; i++)
 -      if (!pos.move_is_legal(mlist[i].move, pinned))
 +      if (!pos.pl_move_is_legal(mlist[i].move, pinned))
            mlist[i--].move = mlist[--n].move;
  
    return n;
  }
  
  
 -/// generate_move_if_legal() takes a position and a (not necessarily
 -/// pseudo-legal) move and a pinned pieces bitboard as input, and tests
 -/// whether the move is legal.  If the move is legal, the move itself is
 -/// returned.  If not, the function returns MOVE_NONE.  This function must
 +/// move_is_legal() takes a position and a (not necessarily pseudo-legal)
 +/// move and a pinned pieces bitboard as input, and tests whether
 +/// the move is legal.  If the move is legal, the move itself is
 +/// returned. If not, the function returns false.  This function must
  /// only be used when the side to move is not in check.
  
 -Move generate_move_if_legal(const Position &pos, Move m, Bitboard pinned) {
 +bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) {
  
    assert(pos.is_ok());
    assert(!pos.is_check());
    assert(move_is_ok(m));
 +  assert(pinned == pos.pinned_pieces(pos.side_to_move()));
  
    Color us = pos.side_to_move();
    Color them = opposite_color(us);
    // If the from square is not occupied by a piece belonging to the side to
    // move, the move is obviously not legal.
    if (color_of_piece(pc) != us)
 -      return MOVE_NONE;
 +      return false;
  
    Square to = move_to(m);
  
        // en passant square.
        if (   type_of_piece(pc) != PAWN
            || to != pos.ep_square())
 -          return MOVE_NONE;
 +          return false;
  
        assert(pos.square_is_empty(to));
        assert(pos.piece_on(to - pawn_push(us)) == pawn_of_color(them));
  
 -      // The move is pseudo-legal.  If it is legal, return it.
 -      return (pos.move_is_legal(m) ? m : MOVE_NONE);
 +      // The move is pseudo-legal, check if it is also legal
 +      return pos.pl_move_is_legal(m, pinned);
    }
  
    // Castling moves
        // the right to castle kingside.
        if (   type_of_piece(pc) != KING
            ||!pos.can_castle_kingside(us))
 -          return MOVE_NONE;
 +          return false;
  
        assert(from == pos.king_square(us));
        assert(to == pos.initial_kr_square(us));
            if (s != from && s != to && !pos.square_is_empty(s))
                illegal = true;
  
 -      return (!illegal ? m : MOVE_NONE);
 +      return !illegal;
    }
  
    if (move_is_long_castle(m))
        // the right to castle kingside.
        if (   type_of_piece(pc) != KING
            ||!pos.can_castle_queenside(us))
 -          return MOVE_NONE;
 +          return false;
  
        assert(from == pos.king_square(us));
        assert(to == pos.initial_qr_square(us));
                || pos.piece_on(to + DELTA_W) == queen_of_color(them)))
            illegal = true;
  
 -      return (!illegal ? m : MOVE_NONE);
 +      return !illegal;
    }
  
    // Normal moves
  
    // The destination square cannot be occupied by a friendly piece
    if (pos.color_of_piece_on(to) == us)
 -      return MOVE_NONE;
 +      return false;
  
    // Proceed according to the type of the moving piece.
    if (type_of_piece(pc) == PAWN)
 -  {  
 +  {
        // If the destination square is on the 8/1th rank, the move must
        // be a promotion.
        if (   (  (square_rank(to) == RANK_8 && us == WHITE)
                ||(square_rank(to) == RANK_1 && us != WHITE))
             && !move_promotion(m))
 -          return MOVE_NONE;
 +          return false;
  
        // Proceed according to the square delta between the source and
        // destionation squares.
        // Capture. The destination square must be occupied by an enemy
        // piece (en passant captures was handled earlier).
            if (pos.color_of_piece_on(to) != them)
 -              return MOVE_NONE;
 +              return false;
            break;
  
        case DELTA_N:
        case DELTA_S:
        // Pawn push. The destination square must be empty.
            if (!pos.square_is_empty(to))
 -              return MOVE_NONE;
 +              return false;
            break;
  
        case DELTA_NN:
        if (   square_rank(to) != RANK_4
            || !pos.square_is_empty(to)
            || !pos.square_is_empty(from + DELTA_N))
 -          return MOVE_NONE;
 +          return false;
            break;
  
        case DELTA_SS:
            if (   square_rank(to) != RANK_5
                || !pos.square_is_empty(to)
                || !pos.square_is_empty(from + DELTA_S))
 -              return MOVE_NONE;
 +              return false;
            break;
  
        default:
 -          return MOVE_NONE;
 +          return false;
        }
 -      // The move is pseudo-legal.  Return it if it is legal.
 -      return (pos.move_is_legal(m) ? m : MOVE_NONE);
 +      // The move is pseudo-legal, check if it is also legal
 +      return pos.pl_move_is_legal(m, pinned);
    }
  
    // Luckly we can handle all the other pieces in one go
    return (   pos.piece_attacks_square(from, to)
 -          && pos.move_is_legal(m)
 -          && !move_promotion(m) ? m : MOVE_NONE);
 +          && pos.pl_move_is_legal(m, pinned)
 +          && !move_promotion(m));
  }
  
  
  namespace {
  
    template<PieceType Piece>
 -  int generate_piece_moves(const Position &pos, MoveStack *mlist, 
 -                           Color side, Bitboard target) {
 -    int n = 0;
 -    for (int i = 0; i < pos.piece_count(side, Piece); i++)
 +  MoveStack* generate_piece_moves(const Position& pos, MoveStack* mlist, Color us, Bitboard target) {
 +
 +    Square from;
 +    Bitboard b;
 +
 +    for (int i = 0, e = pos.piece_count(us, Piece); i < e; i++)
      {
 -        Square from = pos.piece_list(side, Piece, i);
 -        Bitboard b = pos.piece_attacks<Piece>(from) & target;
 -        while (b)
 -        {
 -            Square to = pop_1st_bit(&b);
 -            mlist[n++].move = make_move(from, to);
 -        }
 +        from = pos.piece_list(us, Piece, i);
 +        b = pos.piece_attacks<Piece>(from) & target;
 +        SERIALIZE_MOVES(b);
      }
 -    return n;
 +    return mlist;
    }
  
 +  template<>
 +  MoveStack* generate_piece_moves<KING>(const Position& pos, MoveStack* mlist, Color us, Bitboard target) {
 +
 +    Bitboard b;
 +    Square from = pos.king_square(us);
 +
 +    b = pos.piece_attacks<KING>(from) & target;
 +    SERIALIZE_MOVES(b);
 +    return mlist;
 +  }
  
    template<PieceType Piece>
 -  int generate_piece_blocking_evasions(const Position& pos, Bitboard b,
 -                                       Bitboard blockSquares, MoveStack* mlist, int n) {
 +  MoveStack* generate_piece_blocking_evasions(const Position& pos, Bitboard b,
 +                                              Bitboard blockSquares, MoveStack* mlist) {
      while (b)
      {
          Square from = pop_1st_bit(&b);
          Bitboard bb = pos.piece_attacks<Piece>(from) & blockSquares;
 -        while (bb)
 -        {
 -            Square to = pop_1st_bit(&bb);
 -            mlist[n++].move = make_move(from, to);
 -        }
 +        SERIALIZE_MOVES(bb);
      }
 -    return n;
 +    return mlist;
    }
  
  
 -  template<Color C>
 -  int generate_pawn_captures(const Position& pos, MoveStack* mlist) {
 +  template<Color Us, Color Them, Bitboard TRank8BB, SquareDelta TDELTA_NE,
 +           SquareDelta TDELTA_NW, SquareDelta TDELTA_N
 +          >
-   MoveStack* do_generate_pawn_captures(const Position& pos, MoveStack* mlist) {    
++  MoveStack* do_generate_pawn_captures(const Position& pos, MoveStack* mlist) {
  
 -    static const PawnParams PP = (C == WHITE ? WhitePawnParams : BlackPawnParams);
 -
 -    Bitboard pawns = pos.pawns(PP.us);
 -    Bitboard enemyPieces = pos.pieces_of_color(PP.them);
 -    Square sq;
 -    int n = 0;
 +    Square to;
 +    Bitboard pawns = pos.pawns(Us);
 +    Bitboard enemyPieces = pos.pieces_of_color(Them);
  
      // Captures in the a1-h8 (a8-h1 for black) direction
 -    Bitboard b1 = (C == WHITE ? pawns << 9 : pawns >> 7) & ~FileABB & enemyPieces;
 +    Bitboard b1 = (Us == WHITE ? pawns << 9 : pawns >> 7) & ~FileABB & enemyPieces;
  
      // Capturing promotions
 -    Bitboard b2 = b1 & PP.Rank8BB;
 +    Bitboard b2 = b1 & TRank8BB;
      while (b2)
      {
 -        sq = pop_1st_bit(&b2);
 -        mlist[n++].move = make_promotion_move(sq - PP.DELTA_NE, sq, QUEEN);
 +        to = pop_1st_bit(&b2);
 +        (*mlist++).move = make_promotion_move(to - TDELTA_NE, to, QUEEN);
      }
  
      // Capturing non-promotions
 -    b2 = b1 & ~PP.Rank8BB;
 +    b2 = b1 & ~TRank8BB;
      while (b2)
      {
 -        sq = pop_1st_bit(&b2);
 -        mlist[n++].move = make_move(sq - PP.DELTA_NE, sq);
 +        to = pop_1st_bit(&b2);
 +        (*mlist++).move = make_move(to - TDELTA_NE, to);
      }
  
      // Captures in the h1-a8 (h8-a1 for black) direction
 -    b1 = (C == WHITE ? pawns << 7 : pawns >> 9) & ~FileHBB & enemyPieces;
 +    b1 = (Us == WHITE ? pawns << 7 : pawns >> 9) & ~FileHBB & enemyPieces;
  
      // Capturing promotions
 -    b2 = b1 & PP.Rank8BB;
 +    b2 = b1 & TRank8BB;
      while (b2)
      {
 -        sq = pop_1st_bit(&b2);
 -        mlist[n++].move = make_promotion_move(sq - PP.DELTA_NW, sq, QUEEN);
 +        to = pop_1st_bit(&b2);
 +        (*mlist++).move = make_promotion_move(to - TDELTA_NW, to, QUEEN);
      }
  
      // Capturing non-promotions
 -    b2 = b1 & ~PP.Rank8BB;
 +    b2 = b1 & ~TRank8BB;
      while (b2)
      {
 -        sq = pop_1st_bit(&b2);
 -        mlist[n++].move = make_move(sq - PP.DELTA_NW, sq);
 +        to = pop_1st_bit(&b2);
 +        (*mlist++).move = make_move(to - TDELTA_NW, to);
      }
  
      // Non-capturing promotions
 -    b1 = (C == WHITE ? pawns << 8 : pawns >> 8) & pos.empty_squares() & Rank8BB;
 +    b1 = (Us == WHITE ? pawns << 8 : pawns >> 8) & pos.empty_squares() & TRank8BB;
      while (b1)
      {
 -        sq = pop_1st_bit(&b1);
 -        mlist[n++].move = make_promotion_move(sq - PP.DELTA_N, sq, QUEEN);
 +        to = pop_1st_bit(&b1);
 +        (*mlist++).move = make_promotion_move(to - TDELTA_N, to, QUEEN);
      }
  
      // En passant captures
      if (pos.ep_square() != SQ_NONE)
      {
 -        assert(PP.us != WHITE || square_rank(pos.ep_square()) == RANK_6);
 -        assert(PP.us != BLACK || square_rank(pos.ep_square()) == RANK_3);
 +        assert(Us != WHITE || square_rank(pos.ep_square()) == RANK_6);
 +        assert(Us != BLACK || square_rank(pos.ep_square()) == RANK_3);
  
 -        b1 = pawns & pos.pawn_attacks(PP.them, pos.ep_square());
 +        b1 = pawns & pos.pawn_attacks(Them, pos.ep_square());
          assert(b1 != EmptyBoardBB);
  
          while (b1)
          {
 -            sq = pop_1st_bit(&b1);
 -            mlist[n++].move = make_ep_move(sq, pos.ep_square());
 +            to = pop_1st_bit(&b1);
 +            (*mlist++).move = make_ep_move(to, pos.ep_square());
          }
      }
 -    return n;
 +    return mlist;
    }
  
-   MoveStack* do_generate_pawn_noncaptures(const Position& pos, MoveStack* mlist) {   
 +  template<Color Us, Color Them, Bitboard TRank8BB, Bitboard TRank3BB,
 +           SquareDelta TDELTA_NE, SquareDelta TDELTA_NW, SquareDelta TDELTA_N
 +          >
++  MoveStack* do_generate_pawn_noncaptures(const Position& pos, MoveStack* mlist) {
  
 -  template<Color C>
 -  int generate_pawn_noncaptures(const Position& pos, MoveStack* mlist) {
 -
 -    static const PawnParams PP = (C == WHITE ? WhitePawnParams : BlackPawnParams);
 -
 -    Bitboard pawns = pos.pawns(PP.us);
 -    Bitboard enemyPieces = pos.pieces_of_color(PP.them);
 +    Bitboard pawns = pos.pawns(Us);
 +    Bitboard enemyPieces = pos.pieces_of_color(Them);
      Bitboard emptySquares = pos.empty_squares();
      Bitboard b1, b2;
 -    Square sq;
 -    int n = 0;
 +    Square to;
  
      // Underpromotion captures in the a1-h8 (a8-h1 for black) direction
 -    b1 = (C == WHITE ? pawns << 9 : pawns >> 7) & ~FileABB & enemyPieces & PP.Rank8BB;
 +    b1 = (Us == WHITE ? pawns << 9 : pawns >> 7) & ~FileABB & enemyPieces & TRank8BB;
      while (b1)
      {
 -        sq = pop_1st_bit(&b1);
 -        mlist[n++].move = make_promotion_move(sq - PP.DELTA_NE, sq, ROOK);
 -        mlist[n++].move = make_promotion_move(sq - PP.DELTA_NE, sq, BISHOP);
 -        mlist[n++].move = make_promotion_move(sq - PP.DELTA_NE, sq, KNIGHT);
 +        to = pop_1st_bit(&b1);
 +        (*mlist++).move = make_promotion_move(to - TDELTA_NE, to, ROOK);
 +        (*mlist++).move = make_promotion_move(to - TDELTA_NE, to, BISHOP);
 +        (*mlist++).move = make_promotion_move(to - TDELTA_NE, to, KNIGHT);
      }
  
      // Underpromotion captures in the h1-a8 (h8-a1 for black) direction
 -    b1 = (C == WHITE ? pawns << 7 : pawns >> 9) & ~FileHBB & enemyPieces & PP.Rank8BB;
 +    b1 = (Us == WHITE ? pawns << 7 : pawns >> 9) & ~FileHBB & enemyPieces & TRank8BB;
      while (b1)
      {
 -        sq = pop_1st_bit(&b1);
 -        mlist[n++].move = make_promotion_move(sq - PP.DELTA_NW, sq, ROOK);
 -        mlist[n++].move = make_promotion_move(sq - PP.DELTA_NW, sq, BISHOP);
 -        mlist[n++].move = make_promotion_move(sq - PP.DELTA_NW, sq, KNIGHT);
 +        to = pop_1st_bit(&b1);
 +        (*mlist++).move = make_promotion_move(to - TDELTA_NW, to, ROOK);
 +        (*mlist++).move = make_promotion_move(to - TDELTA_NW, to, BISHOP);
 +        (*mlist++).move = make_promotion_move(to - TDELTA_NW, to, KNIGHT);
      }
  
      // Single pawn pushes
 -    b1 = (C == WHITE ? pawns << 8 : pawns >> 8) & emptySquares;
 -    b2 = b1 & PP.Rank8BB;
 +    b1 = (Us == WHITE ? pawns << 8 : pawns >> 8) & emptySquares;
 +    b2 = b1 & TRank8BB;
      while (b2)
      {
 -      sq = pop_1st_bit(&b2);
 -      mlist[n++].move = make_promotion_move(sq - PP.DELTA_N, sq, ROOK);
 -      mlist[n++].move = make_promotion_move(sq - PP.DELTA_N, sq, BISHOP);
 -      mlist[n++].move = make_promotion_move(sq - PP.DELTA_N, sq, KNIGHT);
 +      to = pop_1st_bit(&b2);
 +      (*mlist++).move = make_promotion_move(to - TDELTA_N, to, ROOK);
 +      (*mlist++).move = make_promotion_move(to - TDELTA_N, to, BISHOP);
 +      (*mlist++).move = make_promotion_move(to - TDELTA_N, to, KNIGHT);
      }
 -    b2 = b1 & ~PP.Rank8BB;
 +    b2 = b1 & ~TRank8BB;
      while (b2)
      {
 -        sq = pop_1st_bit(&b2);
 -        mlist[n++].move = make_move(sq - PP.DELTA_N, sq);
 +        to = pop_1st_bit(&b2);
 +        (*mlist++).move = make_move(to - TDELTA_N, to);
      }
  
      // Double pawn pushes
 -    b2 = (C == WHITE ? (b1 & PP.Rank3BB) << 8 : (b1 & PP.Rank3BB) >> 8) & emptySquares;
 +    b2 = (Us == WHITE ? (b1 & TRank3BB) << 8 : (b1 & TRank3BB) >> 8) & emptySquares;
      while (b2)
      {
 -      sq = pop_1st_bit(&b2);
 -      mlist[n++].move = make_move(sq - PP.DELTA_N - PP.DELTA_N, sq);
 +      to = pop_1st_bit(&b2);
 +      (*mlist++).move = make_move(to - TDELTA_N - TDELTA_N, to);
      }
 -    return n;
 +    return mlist;
    }
  
  
 -  template<Color C>
 -  int generate_pawn_checks(const Position& pos, Bitboard dc, Square ksq, MoveStack* mlist, int n)
 +  template<Color Us, Color Them, Bitboard TRank8BB, Bitboard TRank3BB, SquareDelta TDELTA_N>
 +  MoveStack* do_generate_pawn_checks(const Position& pos, Bitboard dc, Square ksq, MoveStack* mlist)
    {
 -    static const PawnParams PP = (C == WHITE ? WhitePawnParams : BlackPawnParams);
 -
 -    // Pawn moves which give discovered check. This is possible only if the 
 -    // pawn is not on the same file as the enemy king, because we don't 
 +    // Pawn moves which give discovered check. This is possible only if the
 +    // pawn is not on the same file as the enemy king, because we don't
      // generate captures.
      Bitboard empty = pos.empty_squares();
  
      // Find all friendly pawns not on the enemy king's file
 -    Bitboard b1 = pos.pawns(pos.side_to_move()) & ~file_bb(ksq), b2, b3;
 +    Bitboard b1 = pos.pawns(Us) & ~file_bb(ksq), b2, b3;
  
      // Discovered checks, single pawn pushes
 -    b2 = b3 = (C == WHITE ? (b1 & dc) << 8 : (b1 & dc) >> 8) & ~PP.Rank8BB & empty;
 +    b2 = b3 = (Us == WHITE ? (b1 & dc) << 8 : (b1 & dc) >> 8) & ~TRank8BB & empty;
      while (b3)
      {
          Square to = pop_1st_bit(&b3);
 -        mlist[n++].move = make_move(to - PP.DELTA_N, to);
 +        (*mlist++).move = make_move(to - TDELTA_N, to);
      }
  
      // Discovered checks, double pawn pushes
 -    b3 = (C == WHITE ? (b2 & PP.Rank3BB) << 8 : (b2 & PP.Rank3BB) >> 8) & empty;
 +    b3 = (Us == WHITE ? (b2 & TRank3BB) << 8 : (b2 & TRank3BB) >> 8) & empty;
      while (b3)
      {
          Square to = pop_1st_bit(&b3);
 -        mlist[n++].move = make_move(to - PP.DELTA_N - PP.DELTA_N, to);
 +        (*mlist++).move = make_move(to - TDELTA_N - TDELTA_N, to);
      }
  
      // Direct checks. These are possible only for pawns on neighboring files
      b1 &= (~dc & neighboring_files_bb(ksq)); // FIXME why ~dc ??
  
      // Direct checks, single pawn pushes
 -    b2 = (C == WHITE ? b1 << 8 : b1 >> 8) & empty;
 -    b3 = b2 & pos.pawn_attacks(PP.them, ksq);
 +    b2 = (Us == WHITE ? b1 << 8 : b1 >> 8) & empty;
 +    b3 = b2 & pos.pawn_attacks(Them, ksq);
      while (b3)
      {
          Square to = pop_1st_bit(&b3);
 -        mlist[n++].move = make_move(to - PP.DELTA_N, to);
 +        (*mlist++).move = make_move(to - TDELTA_N, to);
      }
  
      // Direct checks, double pawn pushes
 -    b3 =  (C == WHITE ? (b2 & PP.Rank3BB) << 8 : (b2 & PP.Rank3BB) >> 8)
 +    b3 =  (Us == WHITE ? (b2 & TRank3BB) << 8 : (b2 & TRank3BB) >> 8)
          & empty
 -        & pos.pawn_attacks(PP.them, ksq);
 +        & pos.pawn_attacks(Them, ksq);
  
      while (b3)
      {
          Square to = pop_1st_bit(&b3);
 -        mlist[n++].move = make_move(to - PP.DELTA_N - PP.DELTA_N, to);
 +        (*mlist++).move = make_move(to - TDELTA_N - TDELTA_N, to);
 +    }
 +    return mlist;
 +  }
 +
 +  template<PieceType Piece>
 +  MoveStack* generate_piece_checks(const Position& pos, Bitboard target, Bitboard dc,
 +                                   Square ksq, MoveStack* mlist) {
 +    // Discovered checks
 +    Bitboard b = target & dc;
 +    while (b)
 +    {
 +        Square from = pop_1st_bit(&b);
 +        Bitboard bb = pos.piece_attacks<Piece>(from) & pos.empty_squares();
 +        SERIALIZE_MOVES(bb);
 +    }
 +    // Direct checks
 +    b = target & ~dc;
 +    Bitboard checkSqs = pos.piece_attacks<Piece>(ksq) & pos.empty_squares();
 +    while (b)
 +    {
 +        Square from = pop_1st_bit(&b);
 +        Bitboard bb = pos.piece_attacks<Piece>(from) & checkSqs;
 +        SERIALIZE_MOVES(bb);
      }
 -    return n;
 +    return mlist;
    }
  
 +  MoveStack* generate_piece_checks_king(const Position& pos, Square from, Bitboard dc,
 +                                        Square ksq, MoveStack* mlist) {
 +    if (bit_is_set(dc, from))
 +    {
 +        Bitboard b =   pos.piece_attacks<KING>(from)
 +                     & pos.empty_squares()
 +                     & ~QueenPseudoAttacks[ksq];
 +        SERIALIZE_MOVES(b);
 +    }
 +    return mlist;
 +  }
  
 -  template<Color C>
 -  int generate_pawn_blocking_evasions(const Position& pos, Bitboard not_pinned,
 -                                      Bitboard blockSquares, MoveStack* mlist, int n) {
  
 -    static const PawnParams PP = (C == WHITE ? WhitePawnParams : BlackPawnParams);
 +  template<Color Us, Rank TRANK_8, Bitboard TRank3BB, SquareDelta TDELTA_N>
 +  MoveStack* do_generate_pawn_blocking_evasions(const Position& pos, Bitboard not_pinned,
 +                                                Bitboard blockSquares, MoveStack* mlist) {
 +    Square to;
  
      // Find non-pinned pawns
 -    Bitboard b1 = pos.pawns(PP.us) & not_pinned;
 +    Bitboard b1 = pos.pawns(Us) & not_pinned;
  
      // Single pawn pushes. We don't have to AND with empty squares here,
      // because the blocking squares will always be empty.
 -    Bitboard b2 = (C == WHITE ? b1 << 8 : b1 >> 8) & blockSquares;
 +    Bitboard b2 = (Us == WHITE ? b1 << 8 : b1 >> 8) & blockSquares;
      while (b2)
      {
 -        Square to = pop_1st_bit(&b2);
 +        to = pop_1st_bit(&b2);
  
          assert(pos.piece_on(to) == EMPTY);
  
 -        if (square_rank(to) == PP.RANK_8)
 +        if (square_rank(to) == TRANK_8)
          {
 -            mlist[n++].move = make_promotion_move(to - PP.DELTA_N, to, QUEEN);
 -            mlist[n++].move = make_promotion_move(to - PP.DELTA_N, to, ROOK);
 -            mlist[n++].move = make_promotion_move(to - PP.DELTA_N, to, BISHOP);
 -            mlist[n++].move = make_promotion_move(to - PP.DELTA_N, to, KNIGHT);
 +            (*mlist++).move = make_promotion_move(to - TDELTA_N, to, QUEEN);
 +            (*mlist++).move = make_promotion_move(to - TDELTA_N, to, ROOK);
 +            (*mlist++).move = make_promotion_move(to - TDELTA_N, to, BISHOP);
 +            (*mlist++).move = make_promotion_move(to - TDELTA_N, to, KNIGHT);
          } else
 -            mlist[n++].move = make_move(to - PP.DELTA_N, to);
 +            (*mlist++).move = make_move(to - TDELTA_N, to);
      }
  
      // Double pawn pushes
 -    b2 = (C == WHITE ? b1 << 8 : b1 >> 8) & pos.empty_squares() & PP.Rank3BB;
 -    b2 = (C == WHITE ? b2 << 8 : b2 >> 8) & blockSquares;;
 +    b2 = (Us == WHITE ? b1 << 8 : b1 >> 8) & pos.empty_squares() & TRank3BB;
 +    b2 = (Us == WHITE ? b2 << 8 : b2 >> 8) & blockSquares;;
      while (b2)
      {
 -        Square to = pop_1st_bit(&b2);
 +        to = pop_1st_bit(&b2);
  
          assert(pos.piece_on(to) == EMPTY);
 -        assert(PP.us != WHITE || square_rank(to) == RANK_4);
 -        assert(PP.us != BLACK || square_rank(to) == RANK_5);
 +        assert(Us != WHITE || square_rank(to) == RANK_4);
 +        assert(Us != BLACK || square_rank(to) == RANK_5);
  
 -        mlist[n++].move = make_move(to - PP.DELTA_N - PP.DELTA_N, to);
 +        (*mlist++).move = make_move(to - TDELTA_N - TDELTA_N, to);
      }
 -    return n;
 +    return mlist;
    }
  
  
 -  int generate_castle_moves(const Position &pos, MoveStack *mlist, Color us) {
 +  MoveStack* generate_castle_moves(const Position& pos, MoveStack* mlist) {
  
 -    int n = 0;
 +    Color us = pos.side_to_move();
  
      if (pos.can_castle(us))
      {
          Color them = opposite_color(us);
 -        Square ksq = pos.king_square(us);        
 +        Square ksq = pos.king_square(us);
  
          assert(pos.piece_on(ksq) == king_of_color(us));
  
                      illegal = true;
  
              if (!illegal)
 -                mlist[n++].move = make_castle_move(ksq, rsq);
 +                (*mlist++).move = make_castle_move(ksq, rsq);
        }
  
        if (pos.can_castle_queenside(us))
            Square c1 = relative_square(us, SQ_C1);
            Square d1 = relative_square(us, SQ_D1);
            Square s;
 -          bool illegal = false;        
 +          bool illegal = false;
  
            assert(pos.piece_on(rsq) == rook_of_color(us));
  
              && (   pos.piece_on(relative_square(us, SQ_A1)) == rook_of_color(them)
                  || pos.piece_on(relative_square(us, SQ_A1)) == queen_of_color(them)))
              illegal = true;
 -                         
 +
          if (!illegal)
 -            mlist[n++].move = make_castle_move(ksq, rsq);
 +            (*mlist++).move = make_castle_move(ksq, rsq);
        }
      }
 -    return n;
 +    return mlist;
    }
 +
  }
diff --combined src/movegen.h
index 2f70311db504790c93723efa92b34666c728edf4,94f778ff2e4dd74eb1f958d1e58659c69cab43b3..034dd389250099b9eb7fe46f730bcd4ff8cf1c08
@@@ -7,12 -7,12 +7,12 @@@
    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.
--  
++
    Stockfish 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/>.
  */
@@@ -37,6 -37,6 +37,7 @@@ extern int generate_noncaptures(const P
  extern int generate_checks(const Position &pos, MoveStack *mlist, Bitboard dc);
  extern int generate_evasions(const Position &pos, MoveStack *mlist);
  extern int generate_legal_moves(const Position &pos, MoveStack *mlist);
 -extern Move generate_move_if_legal(const Position &pos, Move m, Bitboard pinned);
 +extern bool move_is_legal(const Position &pos, const Move m, Bitboard pinned);
 +
  #endif // !defined(MOVEGEN_H_INCLUDED)
diff --combined src/movepick.cpp
index b115e8ffb1a9c3b9a6a1c6371ffef62067eea3e3,e1f8e4e77f944bd5831245b81dd16c467c9935f0..187a3c513e0275a112c377919a40d62cbdebf586
@@@ -7,12 -7,12 +7,13 @@@
    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.
 -  
 +
++
    Stockfish 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/>.
  */
@@@ -39,7 -39,7 +40,7 @@@ namespace 
  
    /// Variables
  
 -  MovePicker::MovegenPhase PhaseTable[32];  
 +  MovePicker::MovegenPhase PhaseTable[32];
    int MainSearchPhaseIndex;
    int EvasionsPhaseIndex;
    int QsearchWithChecksPhaseIndex;
@@@ -62,7 -62,7 +63,7 @@@
  /// move ordering is at the current node.
  
  MovePicker::MovePicker(const Position& p, bool pvnode, Move ttm, Move mk,
 -                       Move k1, Move k2, Depth d) : pos(p) {  
 +                       Move k1, Move k2, Depth d) : pos(p) {
    pvNode = pvnode;
    ttMove = ttm;
    mateKiller = (mk == ttm)? MOVE_NONE : mk;
@@@ -116,7 -116,7 +117,7 @@@ Move MovePicker::get_next_move() 
          if (ttMove != MOVE_NONE)
          {
              assert(move_is_ok(ttMove));
 -            if (generate_move_if_legal(pos, ttMove, pinned) != MOVE_NONE)
 +            if (move_is_legal(pos, ttMove, pinned))
                  return ttMove;
          }
          break;
          if (mateKiller != MOVE_NONE)
          {
              assert(move_is_ok(mateKiller));
 -            if (generate_move_if_legal(pos, mateKiller, pinned) != MOVE_NONE)
 +            if (move_is_legal(pos, mateKiller, pinned))
                  return mateKiller;
 -        }
 -        break;
 +       }
 +       break;
  
 -    case PH_GOOD_CAPTURES:      
 +    case PH_GOOD_CAPTURES:
          numOfMoves = generate_captures(pos, moves);
          score_captures();
          movesPicked = 0;
          break;
  
      case PH_EVASIONS:
 -        assert(pos.is_check());      
 +        assert(pos.is_check());
          numOfMoves = generate_evasions(pos, moves);
          score_evasions();
          movesPicked = 0;
          break;
  
 -    case PH_QCAPTURES:      
 +    case PH_QCAPTURES:
          numOfMoves = generate_captures(pos, moves);
          score_qcaptures();
          movesPicked = 0;
          return MOVE_NONE;
      }
    }
 -  assert(false);
 -
 -  return MOVE_NONE;
  }
  
  
  
  Move MovePicker::get_next_move(Lock &lock) {
  
 -  lock_grab(&lock);
 -  if (finished)
 -  {
 -      lock_release(&lock);
 -      return MOVE_NONE;
 -  }
 -  Move m = get_next_move();
 -  if (m == MOVE_NONE)
 -      finished = true;
 -
 -  lock_release(&lock);   
 -  return m;
 +   lock_grab(&lock);
 +   if (finished)
 +   {
 +       lock_release(&lock);
 +       return MOVE_NONE;
 +   }
 +   Move m = get_next_move();
 +   if (m == MOVE_NONE)
 +       finished = true;
 +
 +   lock_release(&lock);
 +   return m;
  }
  
 +
  /// MovePicker::score_captures(), MovePicker::score_noncaptures(),
  /// MovePicker::score_evasions() and MovePicker::score_qcaptures() assign a
  /// numerical move ordering score to each move in a move list.  The moves
  /// with highest scores will be picked first by pick_move_from_list().
  
  void MovePicker::score_captures() {
 -  // Winning and equal captures in the main search are ordered by MVV.
 +  // Winning and equal captures in the main search are ordered by MVV/LVA.
    // Suprisingly, this appears to perform slightly better than SEE based
    // move ordering.  The reason is probably that in a position with a winning
    // capture, capturing a more valuable (but sufficiently defended) piece
    // first usually doesn't hurt.  The opponent will have to recapture, and
    // the hanging piece will still be hanging (except in the unusual cases
 -  // where it is possible to recapture with the hanging piece).  Exchanging
 +  // where it is possible to recapture with the hanging piece). Exchanging
    // big pieces before capturing a hanging piece probably helps to reduce
    // the subtree size.
 +  Move m;
 +  int seeValue;
 +
    for (int i = 0; i < numOfMoves; i++)
    {
 -      Move m = moves[i].move;
 -      moves[i].score = pos.see(m);
 -      if (moves[i].score >= 0)
 -          moves[i].score = move_promotion(m) ? QueenValueMidgame
 -                         : pos.midgame_value_of_piece_on(move_to(m));
 +      m = moves[i].move;
 +      seeValue = pos.see(m);
 +      if (seeValue >= 0)
 +      {
 +          if (move_promotion(m))
 +              moves[i].score = QueenValueMidgame;
 +          else
 +              moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
 +                              -int(pos.type_of_piece_on(move_from(m)));
 +      } else
 +          moves[i].score = seeValue;
    }
  }
  
  void MovePicker::score_noncaptures() {
-   Move m;\r
-   int hs;\r
\r
-   for (int i = 0; i < numOfMoves; i++)\r
-   {\r
-       m = moves[i].move;\r
\r
-       if (m == killer1)\r
-           hs = HistoryMax + 2;\r
-       else if (m == killer2)\r
-           hs = HistoryMax + 1;\r
-       else\r
-           hs = H.move_ordering_score(pos.piece_on(move_from(m)), m);\r
\r
-       // Ensure moves in history are always sorted as first\r
-       if (hs > 0)\r
-           hs += 1000;\r
\r
-       moves[i].score = hs + pos.mg_pst_delta(m);\r
 +  // First score by history, when no history is available then use
 +  // piece/square tables values. This seems to be better then a
 +  // random choice when we don't have an history for any move.
 -      Move m = moves[i].move;
++  Move m;
++  int hs;
+   for (int i = 0; i < numOfMoves; i++)
+   {
 -          moves[i].score = HistoryMax + 2;
++      m = moves[i].move;
++
+       if (m == killer1)
 -          moves[i].score = HistoryMax + 1;
++          hs = HistoryMax + 2;
+       else if (m == killer2)
 -          moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
++          hs = HistoryMax + 1;
+       else
 -      if (moves[i].score > 0)
 -          moves[i].score += 1000;
++          hs = H.move_ordering_score(pos.piece_on(move_from(m)), m);
+       // Ensure moves in history are always sorted as first
 -      moves[i].score += pos.mg_pst_delta(moves[i].move);
++      if (hs > 0)
++          hs += 1000;
++      moves[i].score = hs + pos.mg_pst_delta(m);
    }
  }
  
@@@ -264,9 -251,11 +265,9 @@@ void MovePicker::score_evasions() 
            moves[i].score = 2*HistoryMax;
        else if (!pos.square_is_empty(move_to(m)))
        {
 -          moves[i].score = pos.see(m);
 -          if (moves[i].score >= 0)
 -              moves[i].score += HistoryMax;          
 -      }
 -      else
 +          int seeScore = pos.see(m);
 +          moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore;
 +      } else
            moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
    }
    // FIXME try psqt also here
  
  void MovePicker::score_qcaptures() {
  
 -  // Use MVV ordering
 +  // Use MVV/LVA ordering
    for (int i = 0; i < numOfMoves; i++)
    {
        Move m = moves[i].move;
 -      moves[i].score = move_promotion(m) ? QueenValueMidgame
 -                      : pos.midgame_value_of_piece_on(move_to(m));
 +      if (move_promotion(m))
 +          moves[i].score = QueenValueMidgame;
 +      else
 +          moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
 +                          -int(pos.type_of_piece_on(move_from(m)));
    }
  }
  
@@@ -318,10 -304,10 +319,10 @@@ Move MovePicker::pick_move_from_list() 
    Move move;
  
    switch (PhaseTable[phaseIndex]) {
 -
    case PH_GOOD_CAPTURES:
        assert(!pos.is_check());
        assert(movesPicked >= 0);
 +
        while (movesPicked < numOfMoves)
        {
            int bestScore = -10000000;
                    assert(numOfBadCaptures < 63);
                    badCaptures[numOfBadCaptures++] = moves[i];
                    moves[i--] = moves[--numOfMoves];
 -               }
 -               else if (moves[i].score > bestScore)
 -               {
 -                   bestIndex = i;
 -                   bestScore = moves[i].score;
 -               }
 +              }
 +              else if (moves[i].score > bestScore)
 +              {
 +                  bestIndex = i;
 +                  bestScore = moves[i].score;
 +              }
            }
            if (bestIndex != -1) // Found a good capture
            {
 -              move = moves[bestIndex].move;\r
 +              move = moves[bestIndex].move;
                moves[bestIndex] = moves[movesPicked++];
                if (   move != ttMove
                    && move != mateKiller
 -                  && pos.move_is_legal(move, pinned))
 +                  && pos.pl_move_is_legal(move, pinned))
                    return move;
            }
        }
    case PH_NONCAPTURES:
        assert(!pos.is_check());
        assert(movesPicked >= 0);
 +
        while (movesPicked < numOfMoves)
        {
            // If this is a PV node or we have only picked a few moves, scan
            // the entire move list for the best move.  If many moves have already
            // been searched and it is not a PV node, we are probably failing low
            // anyway, so we just pick the first move from the list.
 -          bestIndex = (movesPicked < 12 || pvNode ? find_best_index() : movesPicked);
 +          bestIndex = (pvNode || movesPicked < 12) ? find_best_index() : movesPicked;
  
            if (bestIndex != -1)
            {
 -              move = moves[bestIndex].move;\r
 +              move = moves[bestIndex].move;
                moves[bestIndex] = moves[movesPicked++];
                if (   move != ttMove
                    && move != mateKiller
 -                  && pos.move_is_legal(move, pinned))
 +                  && pos.pl_move_is_legal(move, pinned))
                    return move;
 -         }
 -    }
 -    break;
 +          }
 +      }
 +      break;
  
    case PH_EVASIONS:
        assert(pos.is_check());
        assert(movesPicked >= 0);
 +
        while (movesPicked < numOfMoves)
        {
            bestIndex = find_best_index();
  
            if (bestIndex != -1)
            {
 -              move = moves[bestIndex].move;\r
 +              move = moves[bestIndex].move;
                moves[bestIndex] = moves[movesPicked++];
                return move;
            }
 -      }
 -      break;
 +    }
 +    break;
  
    case PH_BAD_CAPTURES:
        assert(!pos.is_check());
            move = badCaptures[badCapturesPicked++].move;
            if (   move != ttMove
                && move != mateKiller
 -              && pos.move_is_legal(move, pinned))
 +              && pos.pl_move_is_legal(move, pinned))
                return move;
        }
        break;
        assert(movesPicked >= 0);
        while (movesPicked < numOfMoves)
        {
 -          // FIXME makes sens to score qcaps?
            bestIndex = (movesPicked < 4 ? find_best_index() : movesPicked);
  
            if (bestIndex != -1)
            {
 -              move = moves[bestIndex].move;\r
 +              move = moves[bestIndex].move;
                moves[bestIndex] = moves[movesPicked++];
 -              if (move != ttMove && pos.move_is_legal(move, pinned))
 +              // Remember to change the line below if we decide to hash the qsearch!
 +              // Maybe also postpone the legality check until after futility pruning?
 +              if (/* move != ttMove && */ pos.pl_move_is_legal(move, pinned))
                    return move;
            }
        }
        // move here?  FIXME
        while (movesPicked < numOfMoves)
        {
 -          move = moves[movesPicked++].move;          
 -          if (move != ttMove && pos.move_is_legal(move, pinned))
 +          move = moves[movesPicked++].move;
 +          // Remember to change the line below if we decide to hash the qsearch!
 +          if (/* move != ttMove && */ pos.pl_move_is_legal(move, pinned))
                return move;
        }
        break;
@@@ -460,7 -442,7 +461,7 @@@ MovePicker::MovegenPhase MovePicker::cu
  
  /// MovePicker::init_phase_table() initializes the PhaseTable[],
  /// MainSearchPhaseIndex, EvasionPhaseIndex, QsearchWithChecksPhaseIndex
 -/// and QsearchWithoutChecksPhaseIndex variables.  It is only called once
 +/// and QsearchWithoutChecksPhaseIndex variables. It is only called once
  /// during program startup, and never again while the program is running.
  
  void MovePicker::init_phase_table() {
diff --combined src/movepick.h
index b48bd8b80bd528e8cff46fef072f13965d88524d,a835346db341b62c297c6f999247e561e9e570c6..66518ac76861fff4d34a41078e89fa690631100d
@@@ -7,12 -7,12 +7,16 @@@
    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.
++<<<<<<< HEAD:src/movepick.h
 +
++=======
+   
++>>>>>>> d3600c39a745179ed6b094b305d0645e83a1ee86:src/movepick.h
    Stockfish 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/>.
  */
@@@ -77,7 -77,7 +81,7 @@@ private
    void score_qcaptures();
    Move pick_move_from_list();
    int find_best_index();
 -  
 +
    const Position& pos;
    Move ttMove, mateKiller, killer1, killer2;
    Bitboard pinned, dc;
  /// a single reply to check.
  
  inline int MovePicker::number_of_moves() const {
 +
    return numOfMoves;
  }
  
diff --combined src/position.h
index 8765aac049a9e75520fab73719f43ddbb4c80dd5,48f40dac47e66598b97f1384490861cc6c2ac7aa..a47098a8d61d200284bf0ab6dc0632cc73871594
@@@ -7,12 -7,12 +7,12 @@@
    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.
--  
++
    Stockfish 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/>.
  */
@@@ -25,8 -25,8 +25,8 @@@
  #if defined(_MSC_VER)
  
  // Forcing value to bool 'true' or 'false' (performance warning)
--#pragma warning(disable: 4800) \r
--\r
++#pragma warning(disable: 4800)
++
  #endif
  
  ////
@@@ -48,7 -48,7 +48,7 @@@
  ////
  
  /// FEN string for the initial position:
--const std::string StartPosition = 
++const std::string StartPosition =
    "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
  
  /// Maximum number of plies per game (220 should be enough, because the
@@@ -64,9 -64,9 +64,9 @@@ const int MaxGameLength = 220
  /// Castle rights, encoded as bit fields:
  
  enum CastleRights {
--  NO_CASTLES = 0, 
++  NO_CASTLES = 0,
    WHITE_OO = 1,
--  BLACK_OO = 2, 
++  BLACK_OO = 2,
    WHITE_OOO = 4,
    BLACK_OOO = 8,
    ALL_CASTLES = 15
@@@ -92,7 -92,7 +92,7 @@@ struct UndoInfo 
  
  
  /// The position data structure.  A position consists of the following data:
--///    
++///
  ///    * For each piece type, a bitboard representing the squares occupied
  ///      by pieces of that type.
  ///    * For each color, a bitboard representing the squares occupiecd by
@@@ -217,8 -217,8 +217,8 @@@ public
    bool piece_attacks_square(Square f, Square t) const; // Dispatch at run-time
  
    // Properties of moves
 -  bool move_is_legal(Move m) const;
 -  bool move_is_legal(Move m, Bitboard pinned) const;
 +  bool pl_move_is_legal(Move m) const;
 +  bool pl_move_is_legal(Move m, Bitboard pinned) const;
    bool move_is_check(Move m) const;
    bool move_is_check(Move m, Bitboard dcCandidates) const;
    bool move_is_capture(Move m) const;
  
    // Reset the gamePly variable to 0
    void reset_game_ply();
--  
++
    // Position consistency check, for debugging
    bool is_ok(int* failedStep = NULL) const;
  
@@@ -305,9 -305,6 +305,9 @@@ private
    void undo_ep_move(Move m);
    void find_checkers();
  
 +  template<PieceType Piece, bool FindPinned>
 +  Bitboard hidden_checks(Color c, Square ksq) const;
 +
    // Computing hash keys from scratch (for initialization and debugging)
    Key compute_key() const;
    Key compute_pawn_key() const;
  
    // Piece counts
    int pieceCount[2][8]; // [color][pieceType]
--  
++
    // Piece lists
    Square pieceList[2][8][16]; // [color][pieceType][index]
    int index[64];
@@@ -556,7 -553,7 +556,7 @@@ inline Bitboard Position::checkers() co
  }
  
  inline bool Position::is_check() const {
 -  return checkers() != EmptyBoardBB;
 +  return checkersBB != EmptyBoardBB;
  }
  
  inline bool Position::pawn_attacks_square(Color c, Square f, Square t) const {
@@@ -591,7 -588,7 +591,7 @@@ inline bool Position::file_is_half_open
  inline bool Position::square_is_weak(Square s, Color c) const {
    return !(pawns(c) & outpost_mask(opposite_color(c), s));
  }
--                                
++
  inline Key Position::get_key() const {
    return key;
  }
@@@ -642,7 -639,7 +642,7 @@@ inline Phase Position::game_phase() con
    static const Value EndgameLimit = 4 * RookValueMidgame - Value(325);
  
    Value npm = non_pawn_material(WHITE) + non_pawn_material(BLACK);
--  
++
    if (npm >= MidgameLimit)
        return PHASE_MIDGAME;
    else if(npm <= EndgameLimit)
@@@ -687,7 -684,7 +687,7 @@@ inline int Position::rule_50_counter() 
  inline bool Position::opposite_colored_bishops() const {
  
    return   piece_count(WHITE, BISHOP) == 1
--        && piece_count(BLACK, BISHOP) == 1        
++        && piece_count(BLACK, BISHOP) == 1
          && square_color(piece_list(WHITE, BISHOP, 0)) != square_color(piece_list(BLACK, BISHOP, 0));
  }
  
@@@ -695,6 -692,6 +695,6 @@@ inline bool Position::has_pawn_on_7th(C
  
    return pawns(c) & relative_rank_bb(c, RANK_7);
  }
--                   
++
  
  #endif // !defined(POSITION_H_INCLUDED)