2008-08-31 23:59:13 -06:00
|
|
|
/*
|
2008-10-19 10:56:28 -06:00
|
|
|
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
|
|
|
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
2016-01-02 02:43:25 -07:00
|
|
|
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
|
2018-01-01 02:33:07 -07:00
|
|
|
Copyright (C) 2015-2018 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
|
2008-08-31 23:59:13 -06:00
|
|
|
|
2008-10-19 10:56:28 -06:00
|
|
|
Stockfish is free software: you can redistribute it and/or modify
|
2008-08-31 23:59:13 -06:00
|
|
|
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.
|
2009-01-07 06:28:04 -07:00
|
|
|
|
2008-10-19 10:56:28 -06:00
|
|
|
Stockfish is distributed in the hope that it will be useful,
|
2008-08-31 23:59:13 -06:00
|
|
|
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.
|
2009-01-07 06:28:04 -07:00
|
|
|
|
2008-08-31 23:59:13 -06:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2013-07-23 07:31:57 -06:00
|
|
|
#ifndef TYPES_H_INCLUDED
|
2008-08-31 23:59:13 -06:00
|
|
|
#define TYPES_H_INCLUDED
|
|
|
|
|
2015-01-09 04:35:44 -07:00
|
|
|
/// When compiling with provided Makefile (e.g. for Linux and OSX), configuration
|
|
|
|
/// is done automatically. To get started type 'make help'.
|
2011-12-30 09:08:07 -07:00
|
|
|
///
|
2015-01-09 04:35:44 -07:00
|
|
|
/// When Makefile is not used (e.g. with Microsoft Visual Studio) some switches
|
|
|
|
/// need to be set manually:
|
2011-12-30 09:08:07 -07:00
|
|
|
///
|
2015-01-09 04:35:44 -07:00
|
|
|
/// -DNDEBUG | Disable debugging mode. Always use this for release.
|
2011-12-30 09:08:07 -07:00
|
|
|
///
|
2015-01-09 04:35:44 -07:00
|
|
|
/// -DNO_PREFETCH | Disable use of prefetch asm-instruction. You may need this to
|
|
|
|
/// | run on some very old machines.
|
2011-12-30 09:08:07 -07:00
|
|
|
///
|
|
|
|
/// -DUSE_POPCNT | Add runtime support for use of popcnt asm-instruction. Works
|
2015-01-09 04:35:44 -07:00
|
|
|
/// | only in 64-bit mode and requires hardware with popcnt support.
|
2015-01-21 11:53:26 -07:00
|
|
|
///
|
|
|
|
/// -DUSE_PEXT | Add runtime support for use of pext asm-instruction. Works
|
|
|
|
/// | only in 64-bit mode and requires hardware with pext support.
|
2011-12-30 09:08:07 -07:00
|
|
|
|
2012-12-05 03:05:32 -07:00
|
|
|
#include <cassert>
|
2012-05-09 01:33:25 -06:00
|
|
|
#include <cctype>
|
2011-02-23 13:27:22 -07:00
|
|
|
#include <climits>
|
2015-01-18 00:00:50 -07:00
|
|
|
#include <cstdint>
|
2011-01-15 02:47:11 -07:00
|
|
|
#include <cstdlib>
|
2008-08-31 23:59:13 -06:00
|
|
|
|
2015-01-18 00:00:50 -07:00
|
|
|
#if defined(_MSC_VER)
|
|
|
|
// Disable some silly and noisy warning from MSVC compiler
|
|
|
|
#pragma warning(disable: 4127) // Conditional expression is constant
|
|
|
|
#pragma warning(disable: 4146) // Unary minus operator applied to unsigned type
|
|
|
|
#pragma warning(disable: 4800) // Forcing value to bool 'true' or 'false'
|
|
|
|
#endif
|
2012-03-03 01:35:56 -07:00
|
|
|
|
2015-01-09 04:35:44 -07:00
|
|
|
/// 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
|
2013-07-15 13:09:06 -06:00
|
|
|
|
2015-06-28 02:24:10 -06:00
|
|
|
#if defined(_WIN64) && defined(_MSC_VER) // No Makefile used
|
2016-05-01 10:18:10 -06:00
|
|
|
# include <intrin.h> // Microsoft header for _BitScanForward64()
|
2011-12-30 09:08:07 -07:00
|
|
|
# define IS_64BIT
|
2010-05-21 13:17:59 -06:00
|
|
|
#endif
|
2009-07-03 01:40:41 -06:00
|
|
|
|
2016-05-01 02:57:50 -06:00
|
|
|
#if defined(USE_POPCNT) && (defined(__INTEL_COMPILER) || defined(_MSC_VER))
|
2016-05-01 10:18:10 -06:00
|
|
|
# include <nmmintrin.h> // Intel and Microsoft header for _mm_popcnt_u64()
|
2011-01-05 03:02:05 -07:00
|
|
|
#endif
|
|
|
|
|
2015-01-09 04:35:44 -07:00
|
|
|
#if !defined(NO_PREFETCH) && (defined(__INTEL_COMPILER) || defined(_MSC_VER))
|
|
|
|
# include <xmmintrin.h> // Intel and Microsoft header for _mm_prefetch()
|
|
|
|
#endif
|
|
|
|
|
2014-04-07 13:04:34 -06:00
|
|
|
#if defined(USE_PEXT)
|
2014-04-10 12:07:40 -06:00
|
|
|
# include <immintrin.h> // Header for _pext_u64() intrinsic
|
2015-01-20 14:17:22 -07:00
|
|
|
# define pext(b, m) _pext_u64(b, m)
|
2014-04-07 13:04:34 -06:00
|
|
|
#else
|
2017-05-07 02:26:09 -06:00
|
|
|
# define pext(b, m) 0
|
2014-04-07 13:04:34 -06:00
|
|
|
#endif
|
|
|
|
|
2013-07-23 07:31:57 -06:00
|
|
|
#ifdef USE_POPCNT
|
2011-12-30 03:30:26 -07:00
|
|
|
const bool HasPopCnt = true;
|
2011-01-29 05:59:23 -07:00
|
|
|
#else
|
2011-12-30 03:30:26 -07:00
|
|
|
const bool HasPopCnt = false;
|
2011-01-29 05:59:23 -07:00
|
|
|
#endif
|
|
|
|
|
2014-04-07 08:27:14 -06:00
|
|
|
#ifdef USE_PEXT
|
|
|
|
const bool HasPext = true;
|
|
|
|
#else
|
|
|
|
const bool HasPext = false;
|
|
|
|
#endif
|
|
|
|
|
2013-07-23 07:31:57 -06:00
|
|
|
#ifdef IS_64BIT
|
2011-12-30 03:30:26 -07:00
|
|
|
const bool Is64Bit = true;
|
2011-01-29 05:59:23 -07:00
|
|
|
#else
|
2011-12-30 03:30:26 -07:00
|
|
|
const bool Is64Bit = false;
|
2011-01-29 05:59:23 -07:00
|
|
|
#endif
|
|
|
|
|
2011-02-23 13:27:22 -07:00
|
|
|
typedef uint64_t Key;
|
|
|
|
typedef uint64_t Bitboard;
|
|
|
|
|
Cleanup MAX_PLY
This area has become obscure and tricky over the course of incremental
changes that did not respect the original's consistency and clarity. Now,
it's not clear why we use MAX_PLY = 120, or why we use MAX_PLY+6, among
other things.
This patch does the following:
* ID loop: depth ranges from 1 to MAX_PLY-1, and due to TT constraint (depth
must fit into an int8_t), MAX_PLY should be 128.
* stack[]: plies now range from 0 to MAX_PLY-1, hence stack[MAX_PLY+4],
because of the extra 2+2 padding elements (for ss-2 and ss+2). Document this
better, while we're at it.
* Enforce 0 <= ply < MAX_PLY:
- stop condition is now ss->ply >= MAX_PLY and not ss->ply > MAX_PLY.
- assert(ss->ply < MAX_PLY), before using ss+1 and ss+2.
- as a result, we don't need the artificial MAX_PLY+6 range. Instead we
can use MAX_PLY+4 and it's clear why (for ss-2 and ss+2).
* fix: extract_pv_from_tt() and insert_pv_in_tt() had no reason to use
MAX_PLY_PLUS_6, because the array is indexed by plies, so the range of
available plies applies (0..MAX_PLY before, and now 0..MAX_PLY-1).
Tested with debug compile, using MAX_PLY=16, and running bench at depth 17,
using 1 and 7 threads. No assert() fired. Feel free to submit to more severe
crash-tests, if you can think of any.
No functional change.
2014-11-03 08:36:24 -07:00
|
|
|
const int MAX_MOVES = 256;
|
|
|
|
const int MAX_PLY = 128;
|
2011-04-01 06:35:39 -06:00
|
|
|
|
2011-12-04 02:53:40 -07:00
|
|
|
/// A move needs 16 bits to be stored
|
|
|
|
///
|
|
|
|
/// bit 0- 5: destination square (from 0 to 63)
|
|
|
|
/// bit 6-11: origin square (from 0 to 63)
|
|
|
|
/// bit 12-13: promotion piece type - 2 (from KNIGHT-2 to QUEEN-2)
|
2013-12-01 02:25:10 -07:00
|
|
|
/// bit 14-15: special move flag: promotion (1), en passant (2), castling (3)
|
2014-02-14 01:42:50 -07:00
|
|
|
/// NOTE: EN-PASSANT bit is set only when a pawn can be captured
|
2011-12-04 02:53:40 -07:00
|
|
|
///
|
|
|
|
/// 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
|
|
|
|
/// while MOVE_NONE and MOVE_NULL have the same origin and destination square.
|
|
|
|
|
2016-10-20 22:48:07 -06:00
|
|
|
enum Move : int {
|
2013-06-23 03:15:58 -06:00
|
|
|
MOVE_NONE,
|
2011-12-04 02:53:40 -07:00
|
|
|
MOVE_NULL = 65
|
|
|
|
};
|
|
|
|
|
2012-06-24 03:08:16 -06:00
|
|
|
enum MoveType {
|
2013-06-23 03:15:58 -06:00
|
|
|
NORMAL,
|
2012-06-24 03:08:16 -06:00
|
|
|
PROMOTION = 1 << 14,
|
|
|
|
ENPASSANT = 2 << 14,
|
2013-12-01 02:25:10 -07:00
|
|
|
CASTLING = 3 << 14
|
2011-12-04 02:53:40 -07:00
|
|
|
};
|
|
|
|
|
2014-03-02 03:53:17 -07:00
|
|
|
enum Color {
|
2017-08-19 06:32:31 -06:00
|
|
|
WHITE, BLACK, COLOR_NB = 2
|
2014-03-02 03:53:17 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
enum CastlingSide {
|
|
|
|
KING_SIDE, QUEEN_SIDE, CASTLING_SIDE_NB = 2
|
|
|
|
};
|
|
|
|
|
2014-06-01 07:29:34 -06:00
|
|
|
enum CastlingRight {
|
2013-12-01 02:25:10 -07:00
|
|
|
NO_CASTLING,
|
2013-06-23 03:15:58 -06:00
|
|
|
WHITE_OO,
|
2015-01-09 04:35:44 -07:00
|
|
|
WHITE_OOO = WHITE_OO << 1,
|
|
|
|
BLACK_OO = WHITE_OO << 2,
|
|
|
|
BLACK_OOO = WHITE_OO << 3,
|
2013-12-01 02:25:10 -07:00
|
|
|
ANY_CASTLING = WHITE_OO | WHITE_OOO | BLACK_OO | BLACK_OOO,
|
2014-03-08 07:08:55 -07:00
|
|
|
CASTLING_RIGHT_NB = 16
|
2011-12-30 09:08:07 -07:00
|
|
|
};
|
|
|
|
|
2014-03-02 03:53:17 -07:00
|
|
|
template<Color C, CastlingSide S> struct MakeCastling {
|
2017-11-25 20:33:34 -07:00
|
|
|
static constexpr CastlingRight
|
2014-03-08 07:08:55 -07:00
|
|
|
right = C == WHITE ? S == QUEEN_SIDE ? WHITE_OOO : WHITE_OO
|
|
|
|
: S == QUEEN_SIDE ? BLACK_OOO : BLACK_OO;
|
2012-04-08 04:32:01 -06:00
|
|
|
};
|
|
|
|
|
2012-10-21 01:12:02 -06:00
|
|
|
enum Phase {
|
2013-06-23 03:15:58 -06:00
|
|
|
PHASE_ENDGAME,
|
2012-10-21 03:49:05 -06:00
|
|
|
PHASE_MIDGAME = 128,
|
|
|
|
MG = 0, EG = 1, PHASE_NB = 2
|
2012-10-21 01:12:02 -06:00
|
|
|
};
|
|
|
|
|
2011-12-30 09:08:07 -07:00
|
|
|
enum ScaleFactor {
|
2013-12-31 13:45:20 -07:00
|
|
|
SCALE_FACTOR_DRAW = 0,
|
|
|
|
SCALE_FACTOR_ONEPAWN = 48,
|
|
|
|
SCALE_FACTOR_NORMAL = 64,
|
|
|
|
SCALE_FACTOR_MAX = 128,
|
|
|
|
SCALE_FACTOR_NONE = 255
|
2011-12-30 09:08:07 -07:00
|
|
|
};
|
|
|
|
|
2012-01-27 11:47:56 -07:00
|
|
|
enum Bound {
|
2013-06-23 03:15:58 -06:00
|
|
|
BOUND_NONE,
|
|
|
|
BOUND_UPPER,
|
|
|
|
BOUND_LOWER,
|
2012-12-15 03:11:38 -07:00
|
|
|
BOUND_EXACT = BOUND_UPPER | BOUND_LOWER
|
2011-02-23 13:27:22 -07:00
|
|
|
};
|
|
|
|
|
2015-01-18 00:00:50 -07:00
|
|
|
enum Value : int {
|
2011-02-23 13:27:22 -07:00
|
|
|
VALUE_ZERO = 0,
|
|
|
|
VALUE_DRAW = 0,
|
2014-01-27 12:08:31 -07:00
|
|
|
VALUE_KNOWN_WIN = 10000,
|
2014-03-29 04:12:37 -06:00
|
|
|
VALUE_MATE = 32000,
|
|
|
|
VALUE_INFINITE = 32001,
|
|
|
|
VALUE_NONE = 32002,
|
2011-04-01 06:35:39 -06:00
|
|
|
|
2015-01-18 00:05:05 -07:00
|
|
|
VALUE_MATE_IN_MAX_PLY = VALUE_MATE - 2 * MAX_PLY,
|
|
|
|
VALUE_MATED_IN_MAX_PLY = -VALUE_MATE + 2 * MAX_PLY,
|
2012-08-19 17:04:42 -06:00
|
|
|
|
Rework the "unsupported" penalty into a "supported" bonus
A pawn (according to all the searched positions of a bench run) is not supported 85% of the time,
(in current master it is either isolated, backward or "unsupported").
So it made sense to try moving the S(17, 8) "unsupported" penalty value into the base pawn value hoping for a more representative pawn value, and accordingly
a) adjust backward and isolated so that they stay more or less the same as master
b) increase the mg connected bonus in the supported case by S(17, 0) and let the Connected formula find a suitable eg value according to rank.
Tested as a simplification SPRT(-3, 1)
Passed STC
http://tests.stockfishchess.org/tests/view/5970dbd30ebc5916ff649dd6
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 19613 W: 3663 L: 3540 D: 12410
Passed LTC
http://tests.stockfishchess.org/tests/view/597137780ebc5916ff649de3
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 24721 W: 3306 L: 3191 D: 18224
Bench: 5581946
Closes #1179
2017-08-01 19:36:33 -06:00
|
|
|
PawnValueMg = 171, PawnValueEg = 240,
|
2017-05-07 22:03:59 -06:00
|
|
|
KnightValueMg = 764, KnightValueEg = 848,
|
|
|
|
BishopValueMg = 826, BishopValueEg = 891,
|
|
|
|
RookValueMg = 1282, RookValueEg = 1373,
|
|
|
|
QueenValueMg = 2526, QueenValueEg = 2646,
|
2014-04-27 01:23:45 -06:00
|
|
|
|
2016-08-30 12:15:51 -06:00
|
|
|
MidgameLimit = 15258, EndgameLimit = 3915
|
2011-02-23 13:27:22 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
enum PieceType {
|
2013-06-23 03:15:58 -06:00
|
|
|
NO_PIECE_TYPE, PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING,
|
|
|
|
ALL_PIECES = 0,
|
2012-10-21 02:41:23 -06:00
|
|
|
PIECE_TYPE_NB = 8
|
2011-02-23 13:27:22 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
enum Piece {
|
2013-06-23 03:15:58 -06:00
|
|
|
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,
|
2012-10-21 02:41:23 -06:00
|
|
|
PIECE_NB = 16
|
2011-02-23 13:27:22 -07:00
|
|
|
};
|
|
|
|
|
2016-09-17 00:19:06 -06:00
|
|
|
extern Value PieceValue[PHASE_NB][PIECE_NB];
|
2016-09-04 07:29:11 -06:00
|
|
|
|
2016-11-26 07:13:58 -07:00
|
|
|
enum Depth : int {
|
2011-02-23 13:27:22 -07:00
|
|
|
|
2014-09-29 06:08:56 -06:00
|
|
|
ONE_PLY = 1,
|
2011-02-23 13:27:22 -07:00
|
|
|
|
2016-08-19 04:17:38 -06:00
|
|
|
DEPTH_ZERO = 0 * ONE_PLY,
|
|
|
|
DEPTH_QS_CHECKS = 0 * ONE_PLY,
|
|
|
|
DEPTH_QS_NO_CHECKS = -1 * ONE_PLY,
|
|
|
|
DEPTH_QS_RECAPTURES = -5 * ONE_PLY,
|
2011-02-23 13:27:22 -07:00
|
|
|
|
2016-08-19 04:17:38 -06:00
|
|
|
DEPTH_NONE = -6 * ONE_PLY,
|
|
|
|
DEPTH_MAX = MAX_PLY * ONE_PLY
|
2011-02-23 13:27:22 -07:00
|
|
|
};
|
|
|
|
|
2016-08-19 04:17:38 -06:00
|
|
|
static_assert(!(ONE_PLY & (ONE_PLY - 1)), "ONE_PLY is not a power of 2");
|
|
|
|
|
2017-12-04 09:52:31 -07:00
|
|
|
enum Square : int {
|
2011-02-23 13:27:22 -07:00
|
|
|
SQ_A1, SQ_B1, SQ_C1, SQ_D1, SQ_E1, SQ_F1, SQ_G1, SQ_H1,
|
|
|
|
SQ_A2, SQ_B2, SQ_C2, SQ_D2, SQ_E2, SQ_F2, SQ_G2, SQ_H2,
|
|
|
|
SQ_A3, SQ_B3, SQ_C3, SQ_D3, SQ_E3, SQ_F3, SQ_G3, SQ_H3,
|
|
|
|
SQ_A4, SQ_B4, SQ_C4, SQ_D4, SQ_E4, SQ_F4, SQ_G4, SQ_H4,
|
|
|
|
SQ_A5, SQ_B5, SQ_C5, SQ_D5, SQ_E5, SQ_F5, SQ_G5, SQ_H5,
|
|
|
|
SQ_A6, SQ_B6, SQ_C6, SQ_D6, SQ_E6, SQ_F6, SQ_G6, SQ_H6,
|
|
|
|
SQ_A7, SQ_B7, SQ_C7, SQ_D7, SQ_E7, SQ_F7, SQ_G7, SQ_H7,
|
|
|
|
SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8,
|
|
|
|
SQ_NONE,
|
|
|
|
|
2017-12-04 09:52:31 -07:00
|
|
|
SQUARE_NB = 64
|
|
|
|
};
|
2012-10-21 02:41:23 -06:00
|
|
|
|
2017-12-04 09:52:31 -07:00
|
|
|
enum Direction : int {
|
2016-09-23 11:28:34 -06:00
|
|
|
NORTH = 8,
|
|
|
|
EAST = 1,
|
2017-05-07 02:26:09 -06:00
|
|
|
SOUTH = -NORTH,
|
|
|
|
WEST = -EAST,
|
2016-09-23 11:28:34 -06:00
|
|
|
|
|
|
|
NORTH_EAST = NORTH + EAST,
|
|
|
|
SOUTH_EAST = SOUTH + EAST,
|
|
|
|
SOUTH_WEST = SOUTH + WEST,
|
|
|
|
NORTH_WEST = NORTH + WEST
|
2011-02-23 13:27:22 -07:00
|
|
|
};
|
|
|
|
|
2016-10-20 22:48:07 -06:00
|
|
|
enum File : int {
|
2013-06-23 03:15:58 -06:00
|
|
|
FILE_A, FILE_B, FILE_C, FILE_D, FILE_E, FILE_F, FILE_G, FILE_H, FILE_NB
|
2011-02-23 13:27:22 -07:00
|
|
|
};
|
|
|
|
|
2016-10-20 22:48:07 -06:00
|
|
|
enum Rank : int {
|
2013-06-23 03:15:58 -06:00
|
|
|
RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8, RANK_NB
|
2011-02-23 13:27:22 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-01-18 00:00:50 -07:00
|
|
|
/// Score enum stores a middlegame and an endgame value in a single integer
|
|
|
|
/// (enum). The least significant 16 bits are used to store the endgame value
|
2016-10-20 22:48:07 -06:00
|
|
|
/// and the upper 16 bits are used to store the middlegame value. Take some
|
|
|
|
/// care to avoid left-shifting a signed int to avoid undefined behavior.
|
2015-01-18 00:00:50 -07:00
|
|
|
enum Score : int { SCORE_ZERO };
|
2011-06-29 10:40:33 -06:00
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Score make_score(int mg, int eg) {
|
2016-10-20 22:48:07 -06:00
|
|
|
return Score((int)((unsigned int)eg << 16) + mg);
|
2015-01-09 04:35:44 -07:00
|
|
|
}
|
2011-02-23 13:27:22 -07:00
|
|
|
|
2014-06-05 15:55:18 -06:00
|
|
|
/// 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.
|
2016-09-16 10:18:53 -06:00
|
|
|
inline Value eg_value(Score s) {
|
|
|
|
union { uint16_t u; int16_t s; } eg = { uint16_t(unsigned(s + 0x8000) >> 16) };
|
|
|
|
return Value(eg.s);
|
2014-05-01 15:08:07 -06:00
|
|
|
}
|
2011-02-23 13:27:22 -07:00
|
|
|
|
2016-09-16 10:18:53 -06:00
|
|
|
inline Value mg_value(Score s) {
|
|
|
|
union { uint16_t u; int16_t s; } mg = { uint16_t(unsigned(s)) };
|
|
|
|
return Value(mg.s);
|
2011-12-30 09:08:07 -07:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
#define ENABLE_BASE_OPERATORS_ON(T) \
|
|
|
|
constexpr T operator+(T d1, T d2) { return T(int(d1) + int(d2)); } \
|
|
|
|
constexpr T operator-(T d1, T d2) { return T(int(d1) - int(d2)); } \
|
|
|
|
constexpr T operator-(T d) { return T(-int(d)); } \
|
|
|
|
inline T& operator+=(T& d1, T d2) { return d1 = d1 + d2; } \
|
2017-12-04 09:52:31 -07:00
|
|
|
inline T& operator-=(T& d1, T d2) { return d1 = d1 - d2; }
|
|
|
|
|
|
|
|
#define ENABLE_INCR_OPERATORS_ON(T) \
|
|
|
|
inline T& operator++(T& d) { return d = T(int(d) + 1); } \
|
|
|
|
inline T& operator--(T& d) { return d = T(int(d) - 1); }
|
2017-11-25 20:33:34 -07:00
|
|
|
|
|
|
|
#define ENABLE_FULL_OPERATORS_ON(T) \
|
|
|
|
ENABLE_BASE_OPERATORS_ON(T) \
|
2017-12-04 09:52:31 -07:00
|
|
|
ENABLE_INCR_OPERATORS_ON(T) \
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr T operator*(int i, T d) { return T(i * int(d)); } \
|
|
|
|
constexpr T operator*(T d, int i) { return T(int(d) * i); } \
|
|
|
|
constexpr T operator/(T d, int i) { return T(int(d) / i); } \
|
|
|
|
constexpr int operator/(T d1, T d2) { return int(d1) / int(d2); } \
|
|
|
|
inline T& operator*=(T& d, int i) { return d = T(int(d) * i); } \
|
2013-09-15 01:02:09 -06:00
|
|
|
inline T& operator/=(T& d, int i) { return d = T(int(d) / i); }
|
2011-02-23 13:27:22 -07:00
|
|
|
|
2014-04-27 02:13:59 -06:00
|
|
|
ENABLE_FULL_OPERATORS_ON(Value)
|
|
|
|
ENABLE_FULL_OPERATORS_ON(Depth)
|
2017-12-04 09:52:31 -07:00
|
|
|
ENABLE_FULL_OPERATORS_ON(Direction)
|
|
|
|
|
|
|
|
ENABLE_INCR_OPERATORS_ON(PieceType)
|
|
|
|
ENABLE_INCR_OPERATORS_ON(Piece)
|
|
|
|
ENABLE_INCR_OPERATORS_ON(Color)
|
|
|
|
ENABLE_INCR_OPERATORS_ON(Square)
|
|
|
|
ENABLE_INCR_OPERATORS_ON(File)
|
|
|
|
ENABLE_INCR_OPERATORS_ON(Rank)
|
2014-04-27 02:13:59 -06:00
|
|
|
|
2015-01-09 04:35:44 -07:00
|
|
|
ENABLE_BASE_OPERATORS_ON(Score)
|
|
|
|
|
2014-04-27 02:13:59 -06:00
|
|
|
#undef ENABLE_FULL_OPERATORS_ON
|
2017-12-04 09:52:31 -07:00
|
|
|
#undef ENABLE_INCR_OPERATORS_ON
|
2014-04-27 02:13:59 -06:00
|
|
|
#undef ENABLE_BASE_OPERATORS_ON
|
2011-02-23 13:27:22 -07:00
|
|
|
|
2014-02-14 01:42:50 -07:00
|
|
|
/// Additional operators to add integers to a Value
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Value operator+(Value v, int i) { return Value(int(v) + i); }
|
|
|
|
constexpr Value operator-(Value v, int i) { return Value(int(v) - i); }
|
2014-04-27 02:13:59 -06:00
|
|
|
inline Value& operator+=(Value& v, int i) { return v = v + i; }
|
|
|
|
inline Value& operator-=(Value& v, int i) { return v = v - i; }
|
2011-02-23 13:27:22 -07:00
|
|
|
|
2017-12-04 09:52:31 -07:00
|
|
|
/// Additional operators to add a Direction to a Square
|
|
|
|
inline Square operator+(Square s, Direction d) { return Square(int(s) + int(d)); }
|
|
|
|
inline Square operator-(Square s, Direction d) { return Square(int(s) - int(d)); }
|
|
|
|
inline Square& operator+=(Square &s, Direction d) { return s = s + d; }
|
|
|
|
inline Square& operator-=(Square &s, Direction d) { return s = s - d; }
|
|
|
|
|
2011-12-30 09:08:07 -07:00
|
|
|
/// 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.
|
2017-12-04 09:01:17 -07:00
|
|
|
Score operator*(Score, Score) = delete;
|
2011-02-23 13:27:22 -07:00
|
|
|
|
2011-12-30 09:08:07 -07:00
|
|
|
/// 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);
|
|
|
|
}
|
|
|
|
|
2017-01-11 10:11:17 -07:00
|
|
|
/// Multiplication of a Score by an integer. We check for overflow in debug mode.
|
|
|
|
inline Score operator*(Score s, int i) {
|
2017-05-07 02:26:09 -06:00
|
|
|
|
2017-01-11 10:11:17 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Color operator~(Color c) {
|
2016-09-04 07:29:11 -06:00
|
|
|
return Color(c ^ BLACK); // Toggle color
|
2012-01-12 11:31:18 -07:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Square operator~(Square s) {
|
2013-10-13 03:20:35 -06:00
|
|
|
return Square(s ^ SQ_A8); // Vertical flip SQ_A1 -> SQ_A8
|
2012-01-12 11:31:18 -07:00
|
|
|
}
|
|
|
|
|
2017-12-04 09:52:31 -07:00
|
|
|
constexpr File operator~(File f) {
|
|
|
|
return File(f ^ FILE_H); // Horizontal flip FILE_A -> FILE_H
|
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Piece operator~(Piece pc) {
|
2016-09-04 07:29:11 -06:00
|
|
|
return Piece(pc ^ 8); // Swap color of piece B_KNIGHT -> W_KNIGHT
|
2016-09-03 10:14:01 -06:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr CastlingRight operator|(Color c, CastlingSide s) {
|
2014-03-08 07:08:55 -07:00
|
|
|
return CastlingRight(WHITE_OO << ((s == QUEEN_SIDE) + 2 * c));
|
2014-03-02 03:53:17 -07:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Value mate_in(int ply) {
|
2011-02-23 13:27:22 -07:00
|
|
|
return VALUE_MATE - ply;
|
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Value mated_in(int ply) {
|
2011-02-23 13:27:22 -07:00
|
|
|
return -VALUE_MATE + ply;
|
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Square make_square(File f, Rank r) {
|
2016-09-17 00:19:06 -06:00
|
|
|
return Square((r << 3) + f);
|
2014-03-22 16:35:30 -06:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Piece make_piece(Color c, PieceType pt) {
|
2016-09-03 10:14:01 -06:00
|
|
|
return Piece((c << 3) + pt);
|
2011-02-23 13:27:22 -07:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr PieceType type_of(Piece pc) {
|
2014-04-06 02:50:27 -06:00
|
|
|
return PieceType(pc & 7);
|
2011-02-23 13:27:22 -07:00
|
|
|
}
|
|
|
|
|
2014-04-06 02:50:27 -06:00
|
|
|
inline Color color_of(Piece pc) {
|
|
|
|
assert(pc != NO_PIECE);
|
|
|
|
return Color(pc >> 3);
|
2011-02-23 13:27:22 -07:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr bool is_ok(Square s) {
|
2011-06-11 08:50:14 -06:00
|
|
|
return s >= SQ_A1 && s <= SQ_H8;
|
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr File file_of(Square s) {
|
2011-05-22 01:52:39 -06:00
|
|
|
return File(s & 7);
|
2011-02-23 13:27:22 -07:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Rank rank_of(Square s) {
|
2011-05-22 01:52:39 -06:00
|
|
|
return Rank(s >> 3);
|
2011-02-23 13:27:22 -07:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Square relative_square(Color c, Square s) {
|
2011-05-22 01:52:39 -06:00
|
|
|
return Square(s ^ (c * 56));
|
2011-02-23 13:27:22 -07:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Rank relative_rank(Color c, Rank r) {
|
2011-05-22 01:52:39 -06:00
|
|
|
return Rank(r ^ (c * 7));
|
2011-02-23 13:27:22 -07:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Rank relative_rank(Color c, Square s) {
|
2011-10-02 01:33:40 -06:00
|
|
|
return relative_rank(c, rank_of(s));
|
2011-02-23 13:27:22 -07:00
|
|
|
}
|
|
|
|
|
2011-10-03 02:23:04 -06:00
|
|
|
inline bool opposite_colors(Square s1, Square s2) {
|
2012-06-02 01:51:58 -06:00
|
|
|
int s = int(s1) ^ int(s2);
|
2011-02-23 13:27:22 -07:00
|
|
|
return ((s >> 3) ^ s) & 1;
|
|
|
|
}
|
|
|
|
|
2017-12-04 09:52:31 -07:00
|
|
|
constexpr Direction pawn_push(Color c) {
|
2016-09-23 11:28:34 -06:00
|
|
|
return c == WHITE ? NORTH : SOUTH;
|
2011-04-09 12:50:56 -06:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Square from_sq(Move m) {
|
2011-12-04 02:53:40 -07:00
|
|
|
return Square((m >> 6) & 0x3F);
|
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Square to_sq(Move m) {
|
2011-12-04 02:53:40 -07:00
|
|
|
return Square(m & 0x3F);
|
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr int from_to(Move m) {
|
2017-05-26 00:42:50 -06:00
|
|
|
return m & 0xFFF;
|
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr MoveType type_of(Move m) {
|
2012-06-24 03:08:16 -06:00
|
|
|
return MoveType(m & (3 << 14));
|
2011-12-04 02:53:40 -07:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr PieceType promotion_type(Move m) {
|
2015-02-07 11:34:24 -07:00
|
|
|
return PieceType(((m >> 12) & 3) + KNIGHT);
|
2011-12-04 02:53:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
inline Move make_move(Square from, Square to) {
|
2016-09-17 00:19:06 -06:00
|
|
|
return Move((from << 6) + to);
|
2011-12-04 02:53:40 -07:00
|
|
|
}
|
|
|
|
|
2012-06-25 00:57:28 -06:00
|
|
|
template<MoveType T>
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr Move make(Square from, Square to, PieceType pt = KNIGHT) {
|
2016-09-17 00:19:06 -06:00
|
|
|
return Move(T + ((pt - KNIGHT) << 12) + (from << 6) + to);
|
2011-12-04 02:53:40 -07:00
|
|
|
}
|
|
|
|
|
2017-11-25 20:33:34 -07:00
|
|
|
constexpr bool is_ok(Move m) {
|
2015-01-09 04:35:44 -07:00
|
|
|
return from_sq(m) != to_sq(m); // Catch MOVE_NULL and MOVE_NONE
|
2011-12-04 02:53:40 -07:00
|
|
|
}
|
|
|
|
|
2013-07-23 07:31:57 -06:00
|
|
|
#endif // #ifndef TYPES_H_INCLUDED
|