/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+ Copyright (C) 2004-2023 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/// | only in 64-bit mode and requires hardware with pext support.
#include <cassert>
-#include <cctype>
#include <cstdint>
-#include <cstdlib>
-#include <algorithm>
#if defined(_MSC_VER)
// Disable some silly and noisy warning from MSVC compiler
/// Predefined macros hell:
///
-/// __GNUC__ Compiler is gcc, Clang or Intel on Linux
-/// __INTEL_COMPILER Compiler is Intel
-/// _MSC_VER Compiler is MSVC or Intel on Windows
-/// _WIN32 Building on Windows (any)
-/// _WIN64 Building on Windows 64 bit
+/// __GNUC__ Compiler is GCC, Clang or ICX
+/// __clang__ Compiler is Clang or ICX
+/// __INTEL_LLVM_COMPILER Compiler is ICX
+/// _MSC_VER Compiler is MSVC
+/// _WIN32 Building on Windows (any)
+/// _WIN64 Building on Windows 64 bit
+
+#if defined(__GNUC__ ) && (__GNUC__ < 9 || (__GNUC__ == 9 && __GNUC_MINOR__ <= 2)) && defined(_WIN32) && !defined(__clang__)
+#define ALIGNAS_ON_STACK_VARIABLES_BROKEN
+#endif
+
+#define ASSERT_ALIGNED(ptr, alignment) assert(reinterpret_cast<uintptr_t>(ptr) % alignment == 0)
#if defined(_WIN64) && defined(_MSC_VER) // No Makefile used
# include <intrin.h> // Microsoft header for _BitScanForward64()
# define IS_64BIT
#endif
-#if defined(USE_POPCNT) && (defined(__INTEL_COMPILER) || defined(_MSC_VER))
-# include <nmmintrin.h> // Intel and Microsoft header for _mm_popcnt_u64()
+#if defined(USE_POPCNT) && defined(_MSC_VER)
+# include <nmmintrin.h> // Microsoft header for _mm_popcnt_u64()
#endif
-#if !defined(NO_PREFETCH) && (defined(__INTEL_COMPILER) || defined(_MSC_VER))
-# include <xmmintrin.h> // Intel and Microsoft header for _mm_prefetch()
+#if !defined(NO_PREFETCH) && defined(_MSC_VER)
+# include <xmmintrin.h> // Microsoft header for _mm_prefetch()
#endif
#if defined(USE_PEXT)
# define pext(b, m) 0
#endif
+namespace Stockfish {
+
#ifdef USE_POPCNT
constexpr bool HasPopCnt = true;
#else
constexpr bool Is64Bit = false;
#endif
-typedef uint64_t Key;
-typedef uint64_t Bitboard;
+using Key = uint64_t;
+using Bitboard = uint64_t;
constexpr int MAX_MOVES = 256;
constexpr int MAX_PLY = 246;
/// bit 6-11: origin square (from 0 to 63)
/// bit 12-13: promotion piece type - 2 (from KNIGHT-2 to QUEEN-2)
/// bit 14-15: special move flag: promotion (1), en passant (2), castling (3)
-/// NOTE: EN-PASSANT bit is set only when a pawn can be captured
+/// NOTE: en passant bit is set only when a pawn can be captured
///
/// Special cases are MOVE_NONE and MOVE_NULL. We can sneak these in because in
/// any normal move destination square is always different from origin square
enum MoveType {
NORMAL,
PROMOTION = 1 << 14,
- ENPASSANT = 2 << 14,
+ EN_PASSANT = 2 << 14,
CASTLING = 3 << 14
};
CASTLING_RIGHT_NB = 16
};
-enum Phase {
- PHASE_ENDGAME,
- PHASE_MIDGAME = 128,
- MG = 0, EG = 1, PHASE_NB = 2
-};
-
-enum ScaleFactor {
- SCALE_FACTOR_DRAW = 0,
- SCALE_FACTOR_NORMAL = 64,
- SCALE_FACTOR_MAX = 128,
- SCALE_FACTOR_NONE = 255
-};
-
enum Bound {
BOUND_NONE,
BOUND_UPPER,
enum Value : int {
VALUE_ZERO = 0,
VALUE_DRAW = 0,
- VALUE_KNOWN_WIN = 10000,
VALUE_MATE = 32000,
VALUE_INFINITE = 32001,
VALUE_NONE = 32002,
VALUE_MATE_IN_MAX_PLY = VALUE_MATE - MAX_PLY,
VALUE_MATED_IN_MAX_PLY = -VALUE_MATE_IN_MAX_PLY,
- PawnValueMg = 126, PawnValueEg = 208,
- KnightValueMg = 781, KnightValueEg = 854,
- BishopValueMg = 825, BishopValueEg = 915,
- RookValueMg = 1276, RookValueEg = 1380,
- QueenValueMg = 2538, QueenValueEg = 2682,
- Tempo = 28,
-
- MidgameLimit = 15258, EndgameLimit = 3915
+ // In the code, we make the assumption that these values
+ // are such that non_pawn_material() can be used to uniquely
+ // identify the material on the board.
+ PawnValue = 208,
+ KnightValue = 781,
+ BishopValue = 825,
+ RookValue = 1276,
+ QueenValue = 2538,
};
enum PieceType {
enum Piece {
NO_PIECE,
- W_PAWN = 1, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
- B_PAWN = 9, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING,
+ W_PAWN = PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
+ B_PAWN = PAWN + 8, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING,
PIECE_NB = 16
};
-// An ID used to track the pieces. Max. 32 pieces on board.
-enum PieceId {
- PIECE_ID_ZERO = 0,
- PIECE_ID_KING = 30,
- PIECE_ID_WKING = 30,
- PIECE_ID_BKING = 31,
- PIECE_ID_NONE = 32
-};
-
-inline PieceId operator++(PieceId& d, int) {
-
- PieceId x = d;
- d = PieceId(int(d) + 1);
- return x;
-}
-
-constexpr Value PieceValue[PHASE_NB][PIECE_NB] = {
- { VALUE_ZERO, PawnValueMg, KnightValueMg, BishopValueMg, RookValueMg, QueenValueMg, VALUE_ZERO, VALUE_ZERO,
- VALUE_ZERO, PawnValueMg, KnightValueMg, BishopValueMg, RookValueMg, QueenValueMg, VALUE_ZERO, VALUE_ZERO },
- { VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg, VALUE_ZERO, VALUE_ZERO,
- VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg, VALUE_ZERO, VALUE_ZERO }
-};
+constexpr Value PieceValue[PIECE_NB] = { VALUE_ZERO, PawnValue, KnightValue, BishopValue, RookValue, QueenValue, VALUE_ZERO, VALUE_ZERO,
+ VALUE_ZERO, PawnValue, KnightValue, BishopValue, RookValue, QueenValue, VALUE_ZERO, VALUE_ZERO };
-typedef int Depth;
+using Depth = int;
enum : int {
DEPTH_QS_CHECKS = 0,
RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8, RANK_NB
};
-// unique number for each piece type on each square
-enum PieceSquare : uint32_t {
- PS_NONE = 0,
- PS_W_PAWN = 1,
- PS_B_PAWN = 1 * SQUARE_NB + 1,
- PS_W_KNIGHT = 2 * SQUARE_NB + 1,
- PS_B_KNIGHT = 3 * SQUARE_NB + 1,
- PS_W_BISHOP = 4 * SQUARE_NB + 1,
- PS_B_BISHOP = 5 * SQUARE_NB + 1,
- PS_W_ROOK = 6 * SQUARE_NB + 1,
- PS_B_ROOK = 7 * SQUARE_NB + 1,
- PS_W_QUEEN = 8 * SQUARE_NB + 1,
- PS_B_QUEEN = 9 * SQUARE_NB + 1,
- PS_W_KING = 10 * SQUARE_NB + 1,
- PS_END = PS_W_KING, // pieces without kings (pawns included)
- PS_B_KING = 11 * SQUARE_NB + 1,
- PS_END2 = 12 * SQUARE_NB + 1
-};
-
-struct ExtPieceSquare {
- PieceSquare from[COLOR_NB];
-};
-
-// Array for finding the PieceSquare corresponding to the piece on the board
-extern ExtPieceSquare kpp_board_index[PIECE_NB];
-
-constexpr bool is_ok(PieceId pid);
-constexpr Square rotate180(Square sq);
-
-// Structure holding which tracked piece (PieceId) is where (PieceSquare)
-class EvalList {
-
-public:
- // Max. number of pieces without kings is 30 but must be a multiple of 4 in AVX2
- static const int MAX_LENGTH = 32;
-
- // Array that holds the piece id for the pieces on the board
- PieceId piece_id_list[SQUARE_NB];
-
- // List of pieces, separate from White and Black POV
- PieceSquare* piece_list_fw() const { return const_cast<PieceSquare*>(pieceListFw); }
- PieceSquare* piece_list_fb() const { return const_cast<PieceSquare*>(pieceListFb); }
-
- // Place the piece pc with piece_id on the square sq on the board
- void put_piece(PieceId piece_id, Square sq, Piece pc)
- {
- assert(is_ok(piece_id));
- if (pc != NO_PIECE)
- {
- pieceListFw[piece_id] = PieceSquare(kpp_board_index[pc].from[WHITE] + sq);
- pieceListFb[piece_id] = PieceSquare(kpp_board_index[pc].from[BLACK] + rotate180(sq));
- piece_id_list[sq] = piece_id;
- }
- else
- {
- pieceListFw[piece_id] = PS_NONE;
- pieceListFb[piece_id] = PS_NONE;
- piece_id_list[sq] = piece_id;
- }
- }
-
- // Convert the specified piece_id piece to ExtPieceSquare type and return it
- ExtPieceSquare piece_with_id(PieceId piece_id) const
- {
- ExtPieceSquare eps;
- eps.from[WHITE] = pieceListFw[piece_id];
- eps.from[BLACK] = pieceListFb[piece_id];
- return eps;
- }
-
-private:
- PieceSquare pieceListFw[MAX_LENGTH];
- PieceSquare pieceListFb[MAX_LENGTH];
-};
-
-// For differential evaluation of pieces that changed since last turn
+// Keep track of what a move changes on the board (used by NNUE)
struct DirtyPiece {
// Number of changed pieces
int dirty_num;
- // The ids of changed pieces, max. 2 pieces can change in one move
- PieceId pieceId[2];
+ // Max 3 pieces can change in one move. A promotion with capture moves
+ // both the pawn and the captured piece to SQ_NONE and the piece promoted
+ // to from SQ_NONE to the capture square.
+ Piece piece[3];
- // What changed from the piece with that piece number
- ExtPieceSquare old_piece[2];
- ExtPieceSquare new_piece[2];
+ // From and to squares, which may be SQ_NONE
+ Square from[3];
+ Square to[3];
};
-/// Score enum stores a middlegame and an endgame value in a single integer (enum).
-/// The least significant 16 bits are used to store the middlegame value and the
-/// upper 16 bits are used to store the endgame value. We have to take care to
-/// avoid left-shifting a signed int to avoid undefined behavior.
-enum Score : int { SCORE_ZERO };
-
-constexpr Score make_score(int mg, int eg) {
- return Score((int)((unsigned int)eg << 16) + mg);
-}
-
-/// Extracting the signed lower and upper 16 bits is not so trivial because
-/// according to the standard a simple cast to short is implementation defined
-/// and so is a right shift of a signed integer.
-inline Value eg_value(Score s) {
- union { uint16_t u; int16_t s; } eg = { uint16_t(unsigned(s + 0x8000) >> 16) };
- return Value(eg.s);
-}
-
-inline Value mg_value(Score s) {
- union { uint16_t u; int16_t s; } mg = { uint16_t(unsigned(s)) };
- return Value(mg.s);
-}
-
#define ENABLE_BASE_OPERATORS_ON(T) \
constexpr T operator+(T d1, int d2) { return T(int(d1) + d2); } \
constexpr T operator-(T d1, int d2) { return T(int(d1) - d2); } \
ENABLE_FULL_OPERATORS_ON(Value)
ENABLE_FULL_OPERATORS_ON(Direction)
-ENABLE_INCR_OPERATORS_ON(Piece)
-ENABLE_INCR_OPERATORS_ON(PieceSquare)
-ENABLE_INCR_OPERATORS_ON(PieceId)
ENABLE_INCR_OPERATORS_ON(PieceType)
ENABLE_INCR_OPERATORS_ON(Square)
ENABLE_INCR_OPERATORS_ON(File)
ENABLE_INCR_OPERATORS_ON(Rank)
-ENABLE_BASE_OPERATORS_ON(Score)
-
#undef ENABLE_FULL_OPERATORS_ON
#undef ENABLE_INCR_OPERATORS_ON
#undef ENABLE_BASE_OPERATORS_ON
inline Square& operator+=(Square& s, Direction d) { return s = s + d; }
inline Square& operator-=(Square& s, Direction d) { return s = s - d; }
-/// Only declared but not defined. We don't want to multiply two scores due to
-/// a very high risk of overflow. So user should explicitly convert to integer.
-Score operator*(Score, Score) = delete;
-
-/// Division of a Score must be handled separately for each term
-inline Score operator/(Score s, int i) {
- return make_score(mg_value(s) / i, eg_value(s) / i);
-}
-
-/// Multiplication of a Score by an integer. We check for overflow in debug mode.
-inline Score operator*(Score s, int i) {
-
- Score result = Score(int(s) * i);
-
- assert(eg_value(result) == (i * eg_value(s)));
- assert(mg_value(result) == (i * mg_value(s)));
- assert((i == 0) || (result / i) == s);
-
- return result;
-}
-
-/// Multiplication of a Score by a boolean
-inline Score operator*(Score s, bool b) {
- return b ? s : SCORE_ZERO;
-}
-
constexpr Color operator~(Color c) {
return Color(c ^ BLACK); // Toggle color
}
return Color(pc >> 3);
}
-constexpr bool is_ok(PieceId pid) {
- return pid < PIECE_ID_NONE;
+constexpr bool is_ok(Move m) {
+ return m != MOVE_NONE && m != MOVE_NULL;
}
constexpr bool is_ok(Square s) {
}
constexpr Square from_sq(Move m) {
+ assert(is_ok(m));
return Square((m >> 6) & 0x3F);
}
constexpr Square to_sq(Move m) {
+ assert(is_ok(m));
return Square(m & 0x3F);
}
-// Return relative square when turning the board 180 degrees
-constexpr Square rotate180(Square sq) {
- return (Square)(sq ^ 0x3F);
-}
-
constexpr int from_to(Move m) {
- return m & 0xFFF;
+ return m & 0xFFF;
}
constexpr MoveType type_of(Move m) {
return Move((from << 6) + to);
}
-constexpr Move reverse_move(Move m) {
- return make_move(to_sq(m), from_sq(m));
-}
-
template<MoveType T>
constexpr Move make(Square from, Square to, PieceType pt = KNIGHT) {
return Move(T + ((pt - KNIGHT) << 12) + (from << 6) + to);
}
-constexpr bool is_ok(Move m) {
- return from_sq(m) != to_sq(m); // Catch MOVE_NULL and MOVE_NONE
-}
-
/// Based on a congruential pseudo random number generator
constexpr Key make_key(uint64_t seed) {
return seed * 6364136223846793005ULL + 1442695040888963407ULL;
}
+} // namespace Stockfish
+
#endif // #ifndef TYPES_H_INCLUDED
#include "tune.h" // Global visibility to tuning setup