mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 00:33:09 +00:00
Use a Direction enum for Square deltas
Currently the NORTH/WEST/SOUTH/EAST values are of type Square, but conceptually they are not squares but directions. This patch separates these values into a Direction enum and overloads addition and subtraction to allow adding a Square to a Direction (to get a new Square). I have also slightly trimmed the possible overloadings to improve type safety. For example, it would normally not make sense to add a Color to a Color or a Piece to a Piece, or to multiply or divide them by an integer. It would also normally not make sense to add a Square to a Square. This is a non-functional change.
This commit is contained in:
parent
2acda1fde3
commit
822695d4d3
10 changed files with 81 additions and 63 deletions
|
@ -111,7 +111,7 @@ namespace {
|
||||||
ksq[WHITE] = Square((idx >> 0) & 0x3F);
|
ksq[WHITE] = Square((idx >> 0) & 0x3F);
|
||||||
ksq[BLACK] = Square((idx >> 6) & 0x3F);
|
ksq[BLACK] = Square((idx >> 6) & 0x3F);
|
||||||
us = Color ((idx >> 12) & 0x01);
|
us = Color ((idx >> 12) & 0x01);
|
||||||
psq = make_square(File((idx >> 13) & 0x3), RANK_7 - Rank((idx >> 15) & 0x7));
|
psq = make_square(File((idx >> 13) & 0x3), Rank(RANK_7 - ((idx >> 15) & 0x7)));
|
||||||
|
|
||||||
// Check if two pieces are on the same square or if a king can be captured
|
// Check if two pieces are on the same square or if a king can be captured
|
||||||
if ( distance(ksq[WHITE], ksq[BLACK]) <= 1
|
if ( distance(ksq[WHITE], ksq[BLACK]) <= 1
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace {
|
||||||
Bitboard RookTable[0x19000]; // To store rook attacks
|
Bitboard RookTable[0x19000]; // To store rook attacks
|
||||||
Bitboard BishopTable[0x1480]; // To store bishop attacks
|
Bitboard BishopTable[0x1480]; // To store bishop attacks
|
||||||
|
|
||||||
void init_magics(Bitboard table[], Magic magics[], Square deltas[]);
|
void init_magics(Bitboard table[], Magic magics[], Direction directions[]);
|
||||||
|
|
||||||
// bsf_index() returns the index into BSFTable[] to look up the bitscan. Uses
|
// bsf_index() returns the index into BSFTable[] to look up the bitscan. Uses
|
||||||
// Matt Taylor's folding for 32 bit case, extended to 64 bit by Kim Walisch.
|
// Matt Taylor's folding for 32 bit case, extended to 64 bit by Kim Walisch.
|
||||||
|
@ -188,7 +188,7 @@ void Bitboards::init() {
|
||||||
for (Square s = SQ_A1; s <= SQ_H8; ++s)
|
for (Square s = SQ_A1; s <= SQ_H8; ++s)
|
||||||
for (int i = 0; steps[pt][i]; ++i)
|
for (int i = 0; steps[pt][i]; ++i)
|
||||||
{
|
{
|
||||||
Square to = s + Square(c == WHITE ? steps[pt][i] : -steps[pt][i]);
|
Square to = s + Direction(c == WHITE ? steps[pt][i] : -steps[pt][i]);
|
||||||
|
|
||||||
if (is_ok(to) && distance(s, to) < 3)
|
if (is_ok(to) && distance(s, to) < 3)
|
||||||
{
|
{
|
||||||
|
@ -199,11 +199,11 @@ void Bitboards::init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Square RookDeltas[] = { NORTH, EAST, SOUTH, WEST };
|
Direction RookDirections[] = { NORTH, EAST, SOUTH, WEST };
|
||||||
Square BishopDeltas[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
|
Direction BishopDirections[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
|
||||||
|
|
||||||
init_magics(RookTable, RookMagics, RookDeltas);
|
init_magics(RookTable, RookMagics, RookDirections);
|
||||||
init_magics(BishopTable, BishopMagics, BishopDeltas);
|
init_magics(BishopTable, BishopMagics, BishopDirections);
|
||||||
|
|
||||||
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
|
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
|
||||||
{
|
{
|
||||||
|
@ -225,14 +225,14 @@ void Bitboards::init() {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
Bitboard sliding_attack(Square deltas[], Square sq, Bitboard occupied) {
|
Bitboard sliding_attack(Direction directions[], Square sq, Bitboard occupied) {
|
||||||
|
|
||||||
Bitboard attack = 0;
|
Bitboard attack = 0;
|
||||||
|
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
for (Square s = sq + deltas[i];
|
for (Square s = sq + directions[i];
|
||||||
is_ok(s) && distance(s, s - deltas[i]) == 1;
|
is_ok(s) && distance(s, s - directions[i]) == 1;
|
||||||
s += deltas[i])
|
s += directions[i])
|
||||||
{
|
{
|
||||||
attack |= s;
|
attack |= s;
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ namespace {
|
||||||
// chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we
|
// chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we
|
||||||
// use the so called "fancy" approach.
|
// use the so called "fancy" approach.
|
||||||
|
|
||||||
void init_magics(Bitboard table[], Magic magics[], Square deltas[]) {
|
void init_magics(Bitboard table[], Magic magics[], Direction directions[]) {
|
||||||
|
|
||||||
// Optimal PRNG seeds to pick the correct magics in the shortest time
|
// Optimal PRNG seeds to pick the correct magics in the shortest time
|
||||||
int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 },
|
int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 },
|
||||||
|
@ -269,7 +269,7 @@ namespace {
|
||||||
// the number of 1s of the mask. Hence we deduce the size of the shift to
|
// the number of 1s of the mask. Hence we deduce the size of the shift to
|
||||||
// apply to the 64 or 32 bits word to get the index.
|
// apply to the 64 or 32 bits word to get the index.
|
||||||
Magic& m = magics[s];
|
Magic& m = magics[s];
|
||||||
m.mask = sliding_attack(deltas, s, 0) & ~edges;
|
m.mask = sliding_attack(directions, s, 0) & ~edges;
|
||||||
m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
|
m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
|
||||||
|
|
||||||
// Set the offset for the attacks table of the square. We have individual
|
// Set the offset for the attacks table of the square. We have individual
|
||||||
|
@ -281,7 +281,7 @@ namespace {
|
||||||
b = size = 0;
|
b = size = 0;
|
||||||
do {
|
do {
|
||||||
occupancy[size] = b;
|
occupancy[size] = b;
|
||||||
reference[size] = sliding_attack(deltas, s, b);
|
reference[size] = sliding_attack(directions, s, b);
|
||||||
|
|
||||||
if (HasPext)
|
if (HasPext)
|
||||||
m.attacks[pext(b, m.mask)] = reference[size];
|
m.attacks[pext(b, m.mask)] = reference[size];
|
||||||
|
|
|
@ -152,7 +152,7 @@ inline Bitboard file_bb(Square s) {
|
||||||
|
|
||||||
/// shift() moves a bitboard one step along direction D. Mainly for pawns
|
/// shift() moves a bitboard one step along direction D. Mainly for pawns
|
||||||
|
|
||||||
template<Square D>
|
template<Direction D>
|
||||||
constexpr Bitboard shift(Bitboard b) {
|
constexpr Bitboard shift(Bitboard b) {
|
||||||
return D == NORTH ? b << 8 : D == SOUTH ? b >> 8
|
return D == NORTH ? b << 8 : D == SOUTH ? b >> 8
|
||||||
: D == NORTH_EAST ? (b & ~FileHBB) << 9 : D == SOUTH_EAST ? (b & ~FileHBB) >> 7
|
: D == NORTH_EAST ? (b & ~FileHBB) << 9 : D == SOUTH_EAST ? (b & ~FileHBB) >> 7
|
||||||
|
|
|
@ -524,7 +524,7 @@ ScaleFactor Endgame<KRPKB>::operator()(const Position& pos) const {
|
||||||
Square bsq = pos.square<BISHOP>(weakSide);
|
Square bsq = pos.square<BISHOP>(weakSide);
|
||||||
Square psq = pos.square<PAWN>(strongSide);
|
Square psq = pos.square<PAWN>(strongSide);
|
||||||
Rank rk = relative_rank(strongSide, psq);
|
Rank rk = relative_rank(strongSide, psq);
|
||||||
Square push = pawn_push(strongSide);
|
Direction push = pawn_push(strongSide);
|
||||||
|
|
||||||
// If the pawn is on the 5th rank and the pawn (currently) is on
|
// If the pawn is on the 5th rank and the pawn (currently) is on
|
||||||
// the same color square as the bishop then there is a chance of
|
// the same color square as the bishop then there is a chance of
|
||||||
|
|
|
@ -254,8 +254,8 @@ namespace {
|
||||||
void Evaluation<T>::initialize() {
|
void Evaluation<T>::initialize() {
|
||||||
|
|
||||||
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
||||||
const Square Up = (Us == WHITE ? NORTH : SOUTH);
|
const Direction Up = (Us == WHITE ? NORTH : SOUTH);
|
||||||
const Square Down = (Us == WHITE ? SOUTH : NORTH);
|
const Direction Down = (Us == WHITE ? SOUTH : NORTH);
|
||||||
const Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB: Rank7BB | Rank6BB);
|
const Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB: Rank7BB | Rank6BB);
|
||||||
|
|
||||||
// Find our pawns on the first two ranks, and those which are blocked
|
// Find our pawns on the first two ranks, and those which are blocked
|
||||||
|
@ -372,7 +372,7 @@ namespace {
|
||||||
&& pos.is_chess960()
|
&& pos.is_chess960()
|
||||||
&& (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1)))
|
&& (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1)))
|
||||||
{
|
{
|
||||||
Square d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST);
|
Direction d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST);
|
||||||
if (pos.piece_on(s + d) == make_piece(Us, PAWN))
|
if (pos.piece_on(s + d) == make_piece(Us, PAWN))
|
||||||
score -= !pos.empty(s + d + pawn_push(Us)) ? TrappedBishopA1H1 * 4
|
score -= !pos.empty(s + d + pawn_push(Us)) ? TrappedBishopA1H1 * 4
|
||||||
: pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? TrappedBishopA1H1 * 2
|
: pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? TrappedBishopA1H1 * 2
|
||||||
|
@ -423,7 +423,7 @@ namespace {
|
||||||
Score Evaluation<T>::evaluate_king() {
|
Score Evaluation<T>::evaluate_king() {
|
||||||
|
|
||||||
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
||||||
const Square Up = (Us == WHITE ? NORTH : SOUTH);
|
const Direction Up = (Us == WHITE ? NORTH : SOUTH);
|
||||||
const Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB
|
const Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB
|
||||||
: AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
|
: AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
|
||||||
|
|
||||||
|
@ -531,9 +531,9 @@ namespace {
|
||||||
Score Evaluation<T>::evaluate_threats() {
|
Score Evaluation<T>::evaluate_threats() {
|
||||||
|
|
||||||
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
||||||
const Square Up = (Us == WHITE ? NORTH : SOUTH);
|
const Direction Up = (Us == WHITE ? NORTH : SOUTH);
|
||||||
const Square Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
|
const Direction Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
|
||||||
const Square Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
|
const Direction Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
|
||||||
const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
|
const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
|
||||||
|
|
||||||
Bitboard b, weak, defended, stronglyProtected, safeThreats;
|
Bitboard b, weak, defended, stronglyProtected, safeThreats;
|
||||||
|
@ -637,7 +637,7 @@ namespace {
|
||||||
Score Evaluation<T>::evaluate_passed_pawns() {
|
Score Evaluation<T>::evaluate_passed_pawns() {
|
||||||
|
|
||||||
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
||||||
const Square Up = (Us == WHITE ? NORTH : SOUTH);
|
const Direction Up = (Us == WHITE ? NORTH : SOUTH);
|
||||||
|
|
||||||
Bitboard b, bb, squaresToQueen, defendedSquares, unsafeSquares;
|
Bitboard b, bb, squaresToQueen, defendedSquares, unsafeSquares;
|
||||||
Score score = SCORE_ZERO;
|
Score score = SCORE_ZERO;
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace {
|
||||||
|
|
||||||
assert(!pos.checkers());
|
assert(!pos.checkers());
|
||||||
|
|
||||||
const Square K = Chess960 ? kto > kfrom ? WEST : EAST
|
const Direction K = Chess960 ? kto > kfrom ? WEST : EAST
|
||||||
: KingSide ? WEST : EAST;
|
: KingSide ? WEST : EAST;
|
||||||
|
|
||||||
for (Square s = kto; s != kfrom; s += K)
|
for (Square s = kto; s != kfrom; s += K)
|
||||||
|
@ -65,7 +65,7 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<GenType Type, Square D>
|
template<GenType Type, Direction D>
|
||||||
ExtMove* make_promotions(ExtMove* moveList, Square to, Square ksq) {
|
ExtMove* make_promotions(ExtMove* moveList, Square to, Square ksq) {
|
||||||
|
|
||||||
if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
|
if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
|
||||||
|
@ -98,9 +98,9 @@ namespace {
|
||||||
const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
|
const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
|
||||||
const Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
|
const Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
|
||||||
const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
|
const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
|
||||||
const Square Up = (Us == WHITE ? NORTH : SOUTH);
|
const Direction Up = (Us == WHITE ? NORTH : SOUTH);
|
||||||
const Square Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
|
const Direction Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
|
||||||
const Square Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
|
const Direction Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
|
||||||
|
|
||||||
Bitboard emptySquares;
|
Bitboard emptySquares;
|
||||||
|
|
||||||
|
|
|
@ -95,9 +95,9 @@ namespace {
|
||||||
Score evaluate(const Position& pos, Pawns::Entry* e) {
|
Score evaluate(const Position& pos, Pawns::Entry* e) {
|
||||||
|
|
||||||
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
||||||
const Square Up = (Us == WHITE ? NORTH : SOUTH);
|
const Direction Up = (Us == WHITE ? NORTH : SOUTH);
|
||||||
const Square Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
|
const Direction Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
|
||||||
const Square Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
|
const Direction Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
|
||||||
|
|
||||||
Bitboard b, neighbours, stoppers, doubled, supported, phalanx;
|
Bitboard b, neighbours, stoppers, doubled, supported, phalanx;
|
||||||
Bitboard lever, leverPush;
|
Bitboard lever, leverPush;
|
||||||
|
@ -254,7 +254,7 @@ Value Entry::shelter_storm(const Position& pos, Square ksq) {
|
||||||
Value safety = MaxSafetyBonus;
|
Value safety = MaxSafetyBonus;
|
||||||
File center = std::max(FILE_B, std::min(FILE_G, file_of(ksq)));
|
File center = std::max(FILE_B, std::min(FILE_G, file_of(ksq)));
|
||||||
|
|
||||||
for (File f = center - File(1); f <= center + File(1); ++f)
|
for (File f = File(center - 1); f <= File(center + 1); ++f)
|
||||||
{
|
{
|
||||||
b = ourPawns & file_bb(f);
|
b = ourPawns & file_bb(f);
|
||||||
Rank rkUs = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1;
|
Rank rkUs = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1;
|
||||||
|
@ -262,7 +262,7 @@ Value Entry::shelter_storm(const Position& pos, Square ksq) {
|
||||||
b = theirPawns & file_bb(f);
|
b = theirPawns & file_bb(f);
|
||||||
Rank rkThem = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1;
|
Rank rkThem = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1;
|
||||||
|
|
||||||
int d = std::min(f, FILE_H - f);
|
int d = std::min(f, ~f);
|
||||||
safety -= ShelterWeakness[f == file_of(ksq)][d][rkUs]
|
safety -= ShelterWeakness[f == file_of(ksq)][d][rkUs]
|
||||||
+ StormDanger
|
+ StormDanger
|
||||||
[f == file_of(ksq) && rkThem == relative_rank(Us, ksq) + 1 ? BlockedByKing :
|
[f == file_of(ksq) && rkThem == relative_rank(Us, ksq) + 1 ? BlockedByKing :
|
||||||
|
|
|
@ -211,10 +211,10 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
|
||||||
while ((ss >> token) && !isspace(token))
|
while ((ss >> token) && !isspace(token))
|
||||||
{
|
{
|
||||||
if (isdigit(token))
|
if (isdigit(token))
|
||||||
sq += Square(token - '0'); // Advance the given number of files
|
sq += (token - '0') * EAST; // Advance the given number of files
|
||||||
|
|
||||||
else if (token == '/')
|
else if (token == '/')
|
||||||
sq -= Square(16);
|
sq += 2 * SOUTH;
|
||||||
|
|
||||||
else if ((idx = PieceToChar.find(token)) != string::npos)
|
else if ((idx = PieceToChar.find(token)) != string::npos)
|
||||||
{
|
{
|
||||||
|
@ -787,7 +787,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
|
||||||
if ( (int(to) ^ int(from)) == 16
|
if ( (int(to) ^ int(from)) == 16
|
||||||
&& (attacks_from<PAWN>(to - pawn_push(us), us) & pieces(them, PAWN)))
|
&& (attacks_from<PAWN>(to - pawn_push(us), us) & pieces(them, PAWN)))
|
||||||
{
|
{
|
||||||
st->epSquare = (from + to) / 2;
|
st->epSquare = to - pawn_push(us);
|
||||||
k ^= Zobrist::enpassant[file_of(st->epSquare)];
|
k ^= Zobrist::enpassant[file_of(st->epSquare)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ void init() {
|
||||||
|
|
||||||
for (Square s = SQ_A1; s <= SQ_H8; ++s)
|
for (Square s = SQ_A1; s <= SQ_H8; ++s)
|
||||||
{
|
{
|
||||||
File f = std::min(file_of(s), FILE_H - file_of(s));
|
File f = std::min(file_of(s), ~file_of(s));
|
||||||
psq[ pc][ s] = v + Bonus[pc][rank_of(s)][f];
|
psq[ pc][ s] = v + Bonus[pc][rank_of(s)][f];
|
||||||
psq[~pc][~s] = -psq[pc][s];
|
psq[~pc][~s] = -psq[pc][s];
|
||||||
}
|
}
|
||||||
|
|
42
src/types.h
42
src/types.h
|
@ -223,7 +223,7 @@ enum Depth : int {
|
||||||
|
|
||||||
static_assert(!(ONE_PLY & (ONE_PLY - 1)), "ONE_PLY is not a power of 2");
|
static_assert(!(ONE_PLY & (ONE_PLY - 1)), "ONE_PLY is not a power of 2");
|
||||||
|
|
||||||
enum Square {
|
enum Square : int {
|
||||||
SQ_A1, SQ_B1, SQ_C1, SQ_D1, SQ_E1, SQ_F1, SQ_G1, SQ_H1,
|
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_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_A3, SQ_B3, SQ_C3, SQ_D3, SQ_E3, SQ_F3, SQ_G3, SQ_H3,
|
||||||
|
@ -234,8 +234,10 @@ enum Square {
|
||||||
SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8,
|
SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8,
|
||||||
SQ_NONE,
|
SQ_NONE,
|
||||||
|
|
||||||
SQUARE_NB = 64,
|
SQUARE_NB = 64
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Direction : int {
|
||||||
NORTH = 8,
|
NORTH = 8,
|
||||||
EAST = 1,
|
EAST = 1,
|
||||||
SOUTH = -NORTH,
|
SOUTH = -NORTH,
|
||||||
|
@ -284,31 +286,37 @@ 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 d1, T d2) { return T(int(d1) - int(d2)); } \
|
||||||
constexpr T operator-(T d) { return T(-int(d)); } \
|
constexpr T operator-(T d) { return T(-int(d)); } \
|
||||||
inline T& operator+=(T& d1, T d2) { return d1 = d1 + d2; } \
|
inline T& operator+=(T& d1, T d2) { return d1 = d1 + d2; } \
|
||||||
inline T& operator-=(T& d1, T d2) { return d1 = d1 - d2; } \
|
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); }
|
||||||
|
|
||||||
#define ENABLE_FULL_OPERATORS_ON(T) \
|
#define ENABLE_FULL_OPERATORS_ON(T) \
|
||||||
ENABLE_BASE_OPERATORS_ON(T) \
|
ENABLE_BASE_OPERATORS_ON(T) \
|
||||||
|
ENABLE_INCR_OPERATORS_ON(T) \
|
||||||
constexpr T operator*(int i, T d) { return T(i * int(d)); } \
|
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); } \
|
||||||
inline T& operator++(T& d) { return d = T(int(d) + 1); } \
|
|
||||||
inline T& operator--(T& d) { return d = T(int(d) - 1); } \
|
|
||||||
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); } \
|
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); } \
|
inline T& operator*=(T& d, int i) { return d = T(int(d) * i); } \
|
||||||
inline T& operator/=(T& d, int i) { return d = T(int(d) / i); }
|
inline T& operator/=(T& d, int i) { return d = T(int(d) / i); }
|
||||||
|
|
||||||
ENABLE_FULL_OPERATORS_ON(Value)
|
ENABLE_FULL_OPERATORS_ON(Value)
|
||||||
ENABLE_FULL_OPERATORS_ON(PieceType)
|
|
||||||
ENABLE_FULL_OPERATORS_ON(Piece)
|
|
||||||
ENABLE_FULL_OPERATORS_ON(Color)
|
|
||||||
ENABLE_FULL_OPERATORS_ON(Depth)
|
ENABLE_FULL_OPERATORS_ON(Depth)
|
||||||
ENABLE_FULL_OPERATORS_ON(Square)
|
ENABLE_FULL_OPERATORS_ON(Direction)
|
||||||
ENABLE_FULL_OPERATORS_ON(File)
|
|
||||||
ENABLE_FULL_OPERATORS_ON(Rank)
|
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)
|
||||||
|
|
||||||
ENABLE_BASE_OPERATORS_ON(Score)
|
ENABLE_BASE_OPERATORS_ON(Score)
|
||||||
|
|
||||||
#undef ENABLE_FULL_OPERATORS_ON
|
#undef ENABLE_FULL_OPERATORS_ON
|
||||||
|
#undef ENABLE_INCR_OPERATORS_ON
|
||||||
#undef ENABLE_BASE_OPERATORS_ON
|
#undef ENABLE_BASE_OPERATORS_ON
|
||||||
|
|
||||||
/// Additional operators to add integers to a Value
|
/// Additional operators to add integers to a Value
|
||||||
|
@ -317,6 +325,12 @@ constexpr Value operator-(Value v, int i) { return Value(int(v) - i); }
|
||||||
inline Value& operator+=(Value& v, int i) { return v = v + i; }
|
inline Value& operator+=(Value& v, int i) { return v = v + i; }
|
||||||
inline Value& operator-=(Value& v, int i) { return v = v - i; }
|
inline Value& operator-=(Value& v, int i) { return v = v - i; }
|
||||||
|
|
||||||
|
/// 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; }
|
||||||
|
|
||||||
/// Only declared but not defined. We don't want to multiply two scores due to
|
/// 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.
|
/// a very high risk of overflow. So user should explicitly convert to integer.
|
||||||
Score operator*(Score s1, Score s2) = delete;
|
Score operator*(Score s1, Score s2) = delete;
|
||||||
|
@ -346,6 +360,10 @@ constexpr Square operator~(Square s) {
|
||||||
return Square(s ^ SQ_A8); // Vertical flip SQ_A1 -> SQ_A8
|
return Square(s ^ SQ_A8); // Vertical flip SQ_A1 -> SQ_A8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr File operator~(File f) {
|
||||||
|
return File(f ^ FILE_H); // Horizontal flip FILE_A -> FILE_H
|
||||||
|
}
|
||||||
|
|
||||||
constexpr Piece operator~(Piece pc) {
|
constexpr Piece operator~(Piece pc) {
|
||||||
return Piece(pc ^ 8); // Swap color of piece B_KNIGHT -> W_KNIGHT
|
return Piece(pc ^ 8); // Swap color of piece B_KNIGHT -> W_KNIGHT
|
||||||
}
|
}
|
||||||
|
@ -408,7 +426,7 @@ inline bool opposite_colors(Square s1, Square s2) {
|
||||||
return ((s >> 3) ^ s) & 1;
|
return ((s >> 3) ^ s) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Square pawn_push(Color c) {
|
constexpr Direction pawn_push(Color c) {
|
||||||
return c == WHITE ? NORTH : SOUTH;
|
return c == WHITE ? NORTH : SOUTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue