this code to other chess engines.
*/
+#define NOMINMAX
+
+#include <algorithm>
+
#include "../position.h"
#include "../movegen.h"
#include "../bitboard.h"
#include "../search.h"
-#include "../bitcount.h"
#include "tbprobe.h"
#include "tbcore.h"
#include "tbcore.cpp"
namespace Zobrist {
- extern Key psq[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
+ extern Key psq[PIECE_NB][SQUARE_NB];
}
-int Tablebases::TBLargest = 0;
+int Tablebases::MaxCardinality = 0;
// Given a position with 6 or fewer pieces, produce a text string
// of the form KQPvKRP, where "KQP" represents the white pieces if
Color color;
PieceType pt;
int i;
-
+
color = !mirror ? WHITE : BLACK;
for (pt = KING; pt >= PAWN; --pt)
- for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
+ for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
*str++ = pchr[6 - pt];
*str++ = 'v';
color = ~color;
for (pt = KING; pt >= PAWN; --pt)
- for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
+ for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
*str++ = pchr[6 - pt];
*str++ = 0;
}
color = !mirror ? WHITE : BLACK;
for (pt = PAWN; pt <= KING; ++pt)
- for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
- key ^= Zobrist::psq[WHITE][pt][i - 1];
+ for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
+ key ^= Zobrist::psq[make_piece(WHITE, pt)][i - 1];
color = ~color;
for (pt = PAWN; pt <= KING; ++pt)
- for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
- key ^= Zobrist::psq[BLACK][pt][i - 1];
+ for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
+ key ^= Zobrist::psq[make_piece(BLACK, pt)][i - 1];
return key;
}
color = !mirror ? 0 : 8;
for (pt = PAWN; pt <= KING; ++pt)
for (i = 0; i < pcs[color + pt]; i++)
- key ^= Zobrist::psq[WHITE][pt][i];
+ key ^= Zobrist::psq[make_piece(WHITE, pt)][i];
color ^= 8;
for (pt = PAWN; pt <= KING; ++pt)
for (i = 0; i < pcs[color + pt]; i++)
- key ^= Zobrist::psq[BLACK][pt][i];
+ key ^= Zobrist::psq[make_piece(BLACK, pt)][i];
return key;
}
key = pos.material_key();
// Test for KvK.
- if (key == (Zobrist::psq[WHITE][KING][0] ^ Zobrist::psq[BLACK][KING][0]))
+ if (key == (Zobrist::psq[W_KING][0] ^ Zobrist::psq[B_KING][0]))
return 0;
ptr2 = TB_hash[key >> (64 - TBHASHBITS)];
return 0;
}
// Memory barrier to ensure ptr->ready = 1 is not reordered.
+#ifdef _MSC_VER
+ _ReadWriteBarrier();
+#else
__asm__ __volatile__ ("" ::: "memory");
+#endif
ptr->ready = 1;
}
UNLOCK(TB_mutex);
} else
end = generate<EVASIONS>(pos, stack);
- CheckInfo ci(pos);
-
for (moves = stack; moves < end; moves++) {
Move capture = moves->move;
if (!pos.capture(capture) || type_of(capture) == ENPASSANT
- || !pos.legal(capture, ci.pinned))
+ || !pos.legal(capture))
continue;
- pos.do_move(capture, st, ci, pos.gives_check(capture, ci));
+ pos.do_move(capture, st, pos.gives_check(capture));
v = -probe_ab(pos, -beta, -alpha, success);
pos.undo_move(capture);
if (*success == 0) return 0;
else
end = generate<EVASIONS>(pos, stack);
- CheckInfo ci(pos);
-
for (moves = stack; moves < end; moves++) {
Move capture = moves->move;
if (type_of(capture) != ENPASSANT
- || !pos.legal(capture, ci.pinned))
+ || !pos.legal(capture))
continue;
- pos.do_move(capture, st, ci, pos.gives_check(capture, ci));
+ pos.do_move(capture, st, pos.gives_check(capture));
int v0 = -probe_ab(pos, -2, 2, success);
pos.undo_move(capture);
if (*success == 0) return 0;
for (moves = stack; moves < end; moves++) {
Move capture = moves->move;
if (type_of(capture) == ENPASSANT) continue;
- if (pos.legal(capture, ci.pinned)) break;
+ if (pos.legal(capture)) break;
}
if (moves == end && !pos.checkers()) {
end = generate<QUIETS>(pos, end);
for (; moves < end; moves++) {
Move move = moves->move;
- if (pos.legal(move, ci.pinned))
+ if (pos.legal(move))
break;
}
}
ExtMove stack[192];
ExtMove *moves, *end = NULL;
StateInfo st;
- CheckInfo ci(pos);
if (wdl > 0) {
// Generate at least all legal non-capturing pawn moves
for (moves = stack; moves < end; moves++) {
Move move = moves->move;
if (type_of(pos.moved_piece(move)) != PAWN || pos.capture(move)
- || !pos.legal(move, ci.pinned))
+ || !pos.legal(move))
continue;
- pos.do_move(move, st, ci, pos.gives_check(move, ci));
- int v = -probe_ab(pos, -2, -wdl + 1, success);
+ pos.do_move(move, st, pos.gives_check(move));
+ int v = -Tablebases::probe_wdl(pos, success);
pos.undo_move(move);
if (*success == 0) return 0;
if (v == wdl)
for (moves = stack; moves < end; moves++) {
Move move = moves->move;
if (pos.capture(move) || type_of(pos.moved_piece(move)) == PAWN
- || !pos.legal(move, ci.pinned))
+ || !pos.legal(move))
continue;
- pos.do_move(move, st, ci, pos.gives_check(move, ci));
+ pos.do_move(move, st, pos.gives_check(move));
int v = -Tablebases::probe_dtz(pos, success);
pos.undo_move(move);
if (*success == 0) return 0;
for (moves = stack; moves < end; moves++) {
int v;
Move move = moves->move;
- if (!pos.legal(move, ci.pinned))
+ if (!pos.legal(move))
continue;
- pos.do_move(move, st, ci, pos.gives_check(move, ci));
+ pos.do_move(move, st, pos.gives_check(move));
if (st.rule50 == 0) {
if (wdl == -2) v = -1;
else {
end = generate<CAPTURES>(pos, stack);
else
end = generate<EVASIONS>(pos, stack);
- CheckInfo ci(pos);
for (moves = stack; moves < end; moves++) {
Move capture = moves->move;
if (type_of(capture) != ENPASSANT
- || !pos.legal(capture, ci.pinned))
+ || !pos.legal(capture))
continue;
- pos.do_move(capture, st, ci, pos.gives_check(capture, ci));
+ pos.do_move(capture, st, pos.gives_check(capture));
int v0 = -probe_ab(pos, -2, 2, success);
pos.undo_move(capture);
if (*success == 0) return 0;
if (v1 >= 0)
v = v1;
} else if (v < 0) {
- if (v1 >= 0 || v1 < 100)
+ if (v1 >= 0 || v1 < -100)
v = v1;
} else if (v > 100) {
if (v1 > 0)
for (moves = stack; moves < end; moves++) {
Move move = moves->move;
if (type_of(move) == ENPASSANT) continue;
- if (pos.legal(move, ci.pinned)) break;
+ if (pos.legal(move)) break;
}
if (moves == end && !pos.checkers()) {
end = generate<QUIETS>(pos, end);
for (; moves < end; moves++) {
Move move = moves->move;
- if (pos.legal(move, ci.pinned))
+ if (pos.legal(move))
break;
}
}
//
// A return value false indicates that not all probes were successful and that
// no moves were filtered out.
-bool Tablebases::root_probe(Position& pos, Value& TBScore)
+bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, Value& score)
{
int success;
if (!success) return false;
StateInfo st;
- CheckInfo ci(pos);
// Probe each move.
- for (size_t i = 0; i < Search::RootMoves.size(); i++) {
- Move move = Search::RootMoves[i].pv[0];
- pos.do_move(move, st, ci, pos.gives_check(move, ci));
+ for (size_t i = 0; i < rootMoves.size(); i++) {
+ Move move = rootMoves[i].pv[0];
+ pos.do_move(move, st, pos.gives_check(move));
int v = 0;
if (pos.checkers() && dtz > 0) {
ExtMove s[192];
}
pos.undo_move(move);
if (!success) return false;
- Search::RootMoves[i].score = (Value)v;
+ rootMoves[i].score = (Value)v;
}
// Obtain 50-move counter for the root position.
wdl = (-dtz + cnt50 <= 100) ? -2 : -1;
// Determine the score to report to the user.
- TBScore = wdl_to_Value[wdl + 2];
+ score = wdl_to_Value[wdl + 2];
// If the position is winning or losing, but too few moves left, adjust the
// score to show how close it is to winning or losing.
// NOTE: int(PawnValueEg) is used as scaling factor in score_to_uci().
if (wdl == 1 && dtz <= 100)
- TBScore = (Value)(((200 - dtz - cnt50) * int(PawnValueEg)) / 200);
+ score = (Value)(((200 - dtz - cnt50) * int(PawnValueEg)) / 200);
else if (wdl == -1 && dtz >= -100)
- TBScore = -(Value)(((200 + dtz - cnt50) * int(PawnValueEg)) / 200);
+ score = -(Value)(((200 + dtz - cnt50) * int(PawnValueEg)) / 200);
// Now be a bit smart about filtering out moves.
size_t j = 0;
if (dtz > 0) { // winning (or 50-move rule draw)
int best = 0xffff;
- for (size_t i = 0; i < Search::RootMoves.size(); i++) {
- int v = Search::RootMoves[i].score;
+ for (size_t i = 0; i < rootMoves.size(); i++) {
+ int v = rootMoves[i].score;
if (v > 0 && v < best)
best = v;
}
// that stay safely within the 50-move budget, if there are any.
if (!has_repeated(st.previous) && best + cnt50 <= 99)
max = 99 - cnt50;
- for (size_t i = 0; i < Search::RootMoves.size(); i++) {
- int v = Search::RootMoves[i].score;
+ for (size_t i = 0; i < rootMoves.size(); i++) {
+ int v = rootMoves[i].score;
if (v > 0 && v <= max)
- Search::RootMoves[j++] = Search::RootMoves[i];
+ rootMoves[j++] = rootMoves[i];
}
} else if (dtz < 0) { // losing (or 50-move rule draw)
int best = 0;
- for (size_t i = 0; i < Search::RootMoves.size(); i++) {
- int v = Search::RootMoves[i].score;
+ for (size_t i = 0; i < rootMoves.size(); i++) {
+ int v = rootMoves[i].score;
if (v < best)
best = v;
}
// Try all moves, unless we approach or have a 50-move rule draw.
if (-best * 2 + cnt50 < 100)
return true;
- for (size_t i = 0; i < Search::RootMoves.size(); i++) {
- if (Search::RootMoves[i].score == best)
- Search::RootMoves[j++] = Search::RootMoves[i];
+ for (size_t i = 0; i < rootMoves.size(); i++) {
+ if (rootMoves[i].score == best)
+ rootMoves[j++] = rootMoves[i];
}
} else { // drawing
// Try all moves that preserve the draw.
- for (size_t i = 0; i < Search::RootMoves.size(); i++) {
- if (Search::RootMoves[i].score == 0)
- Search::RootMoves[j++] = Search::RootMoves[i];
+ for (size_t i = 0; i < rootMoves.size(); i++) {
+ if (rootMoves[i].score == 0)
+ rootMoves[j++] = rootMoves[i];
}
}
- Search::RootMoves.resize(j, Search::RootMove(MOVE_NONE));
+ rootMoves.resize(j, Search::RootMove(MOVE_NONE));
return true;
}
//
// A return value false indicates that not all probes were successful and that
// no moves were filtered out.
-bool Tablebases::root_probe_wdl(Position& pos, Value& TBScore)
+bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Value& score)
{
int success;
int wdl = Tablebases::probe_wdl(pos, &success);
if (!success) return false;
- TBScore = wdl_to_Value[wdl + 2];
+ score = wdl_to_Value[wdl + 2];
StateInfo st;
- CheckInfo ci(pos);
int best = -2;
// Probe each move.
- for (size_t i = 0; i < Search::RootMoves.size(); i++) {
- Move move = Search::RootMoves[i].pv[0];
- pos.do_move(move, st, ci, pos.gives_check(move, ci));
+ for (size_t i = 0; i < rootMoves.size(); i++) {
+ Move move = rootMoves[i].pv[0];
+ pos.do_move(move, st, pos.gives_check(move));
int v = -Tablebases::probe_wdl(pos, &success);
pos.undo_move(move);
if (!success) return false;
- Search::RootMoves[i].score = (Value)v;
+ rootMoves[i].score = (Value)v;
if (v > best)
best = v;
}
size_t j = 0;
- for (size_t i = 0; i < Search::RootMoves.size(); i++) {
- if (Search::RootMoves[i].score == best)
- Search::RootMoves[j++] = Search::RootMoves[i];
+ for (size_t i = 0; i < rootMoves.size(); i++) {
+ if (rootMoves[i].score == best)
+ rootMoves[j++] = rootMoves[i];
}
- Search::RootMoves.resize(j, Search::RootMove(MOVE_NONE));
+ rootMoves.resize(j, Search::RootMove(MOVE_NONE));
return true;
}