diff --git a/DroidFish/build_copy_exe.xml b/DroidFish/build_copy_exe.xml
index 58788c0..5b180d6 100644
--- a/DroidFish/build_copy_exe.xml
+++ b/DroidFish/build_copy_exe.xml
@@ -6,8 +6,6 @@
-
-
diff --git a/DroidFish/jni/Application.mk b/DroidFish/jni/Application.mk
index 1d41207..2d75cf7 100644
--- a/DroidFish/jni/Application.mk
+++ b/DroidFish/jni/Application.mk
@@ -1,5 +1,5 @@
APP_PLATFORM := 11
-APP_ABI := all
+APP_ABI := arm64-v8a armeabi-v7a armeabi mips64 x86 x86_64
APP_STL := gnustl_static
APP_OPTIM := release
NDK_TOOLCHAIN_VERSION := 4.9
diff --git a/DroidFish/jni/stockfish/benchmark.cpp b/DroidFish/jni/stockfish/benchmark.cpp
index f2d1f06..75c7d1a 100644
--- a/DroidFish/jni/stockfish/benchmark.cpp
+++ b/DroidFish/jni/stockfish/benchmark.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,23 +23,20 @@
#include
#include
-#include "misc.h"
#include "position.h"
-#include "search.h"
-#include "thread.h"
-#include "uci.h"
using namespace std;
namespace {
const vector Defaults = {
+ "setoption name UCI_Chess960 value false",
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
"r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 10",
"8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 11",
"4rrk1/pp1n3p/3q2pQ/2p1pb2/2PP4/2P3N1/P2B2PP/4RRK1 b - - 7 19",
- "rq3rk1/ppp2ppp/1bnpb3/3N2B1/3NP3/7P/PPPQ1PP1/2KR3R w - - 7 14",
- "r1bq1r1k/1pp1n1pp/1p1p4/4p2Q/4Pp2/1BNP4/PPP2PPP/3R1RK1 w - - 2 14",
+ "rq3rk1/ppp2ppp/1bnpb3/3N2B1/3NP3/7P/PPPQ1PP1/2KR3R w - - 7 14 moves d4e6",
+ "r1bq1r1k/1pp1n1pp/1p1p4/4p2Q/4Pp2/1BNP4/PPP2PPP/3R1RK1 w - - 2 14 moves g2g4",
"r3r1k1/2p2ppp/p1p1bn2/8/1q2P3/2NPQN2/PPP3PP/R4RK1 b - - 2 15",
"r1bbk1nr/pp3p1p/2n5/1N4p1/2Np1B2/8/PPP2PPP/2KR1B1R w kq - 0 13",
"r1bq1rk1/ppp1nppp/4n3/3p3Q/3P4/1BP1B3/PP1N2PP/R4RK1 w - - 1 16",
@@ -52,7 +49,7 @@ const vector Defaults = {
"3q2k1/pb3p1p/4pbp1/2r5/PpN2N2/1P2P2P/5PP1/Q2R2K1 b - - 4 26",
"6k1/6p1/6Pp/ppp5/3pn2P/1P3K2/1PP2P2/3N4 b - - 0 1",
"3b4/5kp1/1p1p1p1p/pP1PpP1P/P1P1P3/3KN3/8/8 w - - 0 1",
- "2K5/p7/7P/5pR1/8/5k2/r7/8 w - - 0 1",
+ "2K5/p7/7P/5pR1/8/5k2/r7/8 w - - 0 1 moves g5g6 f3e3 g6g5 e3f3",
"8/6pk/1p6/8/PP3p1p/5P2/4KP1q/3Q4 w - - 0 1",
"7k/3p2pp/4q3/8/4Q3/5Kp1/P6b/8 w - - 0 1",
"8/2p5/8/2kPKp1p/2p4P/2P5/3P4/8 w - - 0 1",
@@ -79,28 +76,35 @@ const vector Defaults = {
"8/R7/2q5/8/6k1/8/1P5p/K6R w - - 0 124", // Draw
// Mate and stalemate positions
+ "6k1/3b3r/1p1p4/p1n2p2/1PPNpP1q/P3Q1p1/1R1RB1P1/5K2 b - - 0 1",
+ "r2r1n2/pp2bk2/2p1p2p/3q4/3PN1QP/2P3R1/P4PP1/5RK1 w - - 0 1",
"8/8/8/8/8/6k1/6p1/6K1 w - -",
- "5k2/5P2/5K2/8/8/8/8/8 b - -",
- "8/8/8/8/8/4k3/4p3/4K3 w - -",
- "8/8/8/8/8/5K2/8/3Q1k2 b - -",
- "7k/7P/6K1/8/3B4/8/8/8 b - -"
+ "7k/7P/6K1/8/3B4/8/8/8 b - -",
+
+ // Chess 960
+ "setoption name UCI_Chess960 value true",
+ "bbqnnrkr/pppppppp/8/8/8/8/PPPPPPPP/BBQNNRKR w KQkq - 0 1 moves g2g3 d7d5 d2d4 c8h3 c1g5 e8d6 g5e7 f7f6",
+ "setoption name UCI_Chess960 value false"
};
} // namespace
-/// benchmark() runs a simple benchmark by letting Stockfish analyze a set
-/// of positions for a given limit each. There are five parameters: the
-/// transposition table size, the number of search threads that should
-/// be used, the limit value spent for each position (optional, default is
-/// depth 13), an optional file name where to look for positions in FEN
-/// format (defaults are the positions defined above) and the type of the
-/// limit value: depth (default), time in millisecs or number of nodes.
+/// setup_bench() builds a list of UCI commands to be run by bench. There
+/// are five parameters: TT size in MB, number of search threads that
+/// should be used, the limit value spent for each position, a file name
+/// where to look for positions in FEN format and the type of the limit:
+/// depth, perft, nodes and movetime (in millisecs).
+///
+/// bench -> search default positions up to depth 13
+/// bench 64 1 15 -> search default positions up to depth 15 (TT = 64MB)
+/// bench 64 4 5000 current movetime -> search current position with 4 threads for 5 sec
+/// bench 64 1 100000 default nodes -> search default positions for 100K nodes each
+/// bench 16 1 5 default perft -> run a perft 5 on default positions
-void benchmark(const Position& current, istream& is) {
+vector setup_bench(const Position& current, istream& is) {
- string token;
- vector fens;
- Search::LimitsType limits;
+ vector fens, list;
+ string go, token;
// Assign default values to missing arguments
string ttSize = (is >> token) ? token : "16";
@@ -109,21 +113,7 @@ void benchmark(const Position& current, istream& is) {
string fenFile = (is >> token) ? token : "default";
string limitType = (is >> token) ? token : "depth";
- Options["Hash"] = ttSize;
- Options["Threads"] = threads;
- Search::clear();
-
- if (limitType == "time")
- limits.movetime = stoi(limit); // movetime is in millisecs
-
- else if (limitType == "nodes")
- limits.nodes = stoi(limit);
-
- else if (limitType == "mate")
- limits.mate = stoi(limit);
-
- else
- limits.depth = stoi(limit);
+ go = "go " + limitType + " " + limit;
if (fenFile == "default")
fens = Defaults;
@@ -139,7 +129,7 @@ void benchmark(const Position& current, istream& is) {
if (!file.is_open())
{
cerr << "Unable to open file " << fenFile << endl;
- return;
+ exit(EXIT_FAILURE);
}
while (getline(file, fen))
@@ -149,35 +139,18 @@ void benchmark(const Position& current, istream& is) {
file.close();
}
- uint64_t nodes = 0;
- TimePoint elapsed = now();
- Position pos;
-
- for (size_t i = 0; i < fens.size(); ++i)
- {
- StateListPtr states(new std::deque(1));
- pos.set(fens[i], Options["UCI_Chess960"], &states->back(), Threads.main());
-
- cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
-
- if (limitType == "perft")
- nodes += Search::perft(pos, limits.depth * ONE_PLY);
+ list.emplace_back("ucinewgame");
+ list.emplace_back("setoption name Threads value " + threads);
+ list.emplace_back("setoption name Hash value " + ttSize);
+ for (const string& fen : fens)
+ if (fen.find("setoption") != string::npos)
+ list.emplace_back(fen);
else
{
- limits.startTime = now();
- Threads.start_thinking(pos, states, limits);
- Threads.main()->wait_for_search_finished();
- nodes += Threads.nodes_searched();
+ list.emplace_back("position fen " + fen);
+ list.emplace_back(go);
}
- }
- elapsed = now() - elapsed + 1; // Ensure positivity to avoid a 'divide by zero'
-
- dbg_print(); // Just before exiting
-
- cerr << "\n==========================="
- << "\nTotal time (ms) : " << elapsed
- << "\nNodes searched : " << nodes
- << "\nNodes/second : " << 1000 * nodes / elapsed << endl;
+ return list;
}
diff --git a/DroidFish/jni/stockfish/bitbase.cpp b/DroidFish/jni/stockfish/bitbase.cpp
index 4170952..d206210 100644
--- a/DroidFish/jni/stockfish/bitbase.cpp
+++ b/DroidFish/jni/stockfish/bitbase.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -117,7 +117,7 @@ namespace {
if ( distance(ksq[WHITE], ksq[BLACK]) <= 1
|| ksq[WHITE] == psq
|| ksq[BLACK] == psq
- || (us == WHITE && (StepAttacksBB[PAWN][psq] & ksq[BLACK])))
+ || (us == WHITE && (PawnAttacks[WHITE][psq] & ksq[BLACK])))
result = INVALID;
// Immediate win if a pawn can be promoted without getting captured
@@ -125,13 +125,13 @@ namespace {
&& rank_of(psq) == RANK_7
&& ksq[us] != psq + NORTH
&& ( distance(ksq[~us], psq + NORTH) > 1
- || (StepAttacksBB[KING][ksq[us]] & (psq + NORTH))))
+ || (PseudoAttacks[KING][ksq[us]] & (psq + NORTH))))
result = WIN;
// Immediate draw if it is a stalemate or a king captures undefended pawn
else if ( us == BLACK
- && ( !(StepAttacksBB[KING][ksq[us]] & ~(StepAttacksBB[KING][ksq[~us]] | StepAttacksBB[PAWN][psq]))
- || (StepAttacksBB[KING][ksq[us]] & psq & ~StepAttacksBB[KING][ksq[~us]])))
+ && ( !(PseudoAttacks[KING][ksq[us]] & ~(PseudoAttacks[KING][ksq[~us]] | PawnAttacks[~us][psq]))
+ || (PseudoAttacks[KING][ksq[us]] & psq & ~PseudoAttacks[KING][ksq[~us]])))
result = DRAW;
// Position will be classified later
@@ -157,7 +157,7 @@ namespace {
const Result Bad = (Us == WHITE ? DRAW : WIN);
Result r = INVALID;
- Bitboard b = StepAttacksBB[KING][ksq[Us]];
+ Bitboard b = PseudoAttacks[KING][ksq[Us]];
while (b)
r |= Us == WHITE ? db[index(Them, ksq[Them] , pop_lsb(&b), psq)]
diff --git a/DroidFish/jni/stockfish/bitboard.cpp b/DroidFish/jni/stockfish/bitboard.cpp
index e329ab5..e3c9140 100644
--- a/DroidFish/jni/stockfish/bitboard.cpp
+++ b/DroidFish/jni/stockfish/bitboard.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,29 +26,22 @@
uint8_t PopCnt16[1 << 16];
int SquareDistance[SQUARE_NB][SQUARE_NB];
-Bitboard RookMasks [SQUARE_NB];
-Bitboard RookMagics [SQUARE_NB];
-Bitboard* RookAttacks[SQUARE_NB];
-unsigned RookShifts [SQUARE_NB];
-
-Bitboard BishopMasks [SQUARE_NB];
-Bitboard BishopMagics [SQUARE_NB];
-Bitboard* BishopAttacks[SQUARE_NB];
-unsigned BishopShifts [SQUARE_NB];
-
Bitboard SquareBB[SQUARE_NB];
Bitboard FileBB[FILE_NB];
Bitboard RankBB[RANK_NB];
Bitboard AdjacentFilesBB[FILE_NB];
-Bitboard InFrontBB[COLOR_NB][RANK_NB];
-Bitboard StepAttacksBB[PIECE_NB][SQUARE_NB];
+Bitboard ForwardRanksBB[COLOR_NB][RANK_NB];
Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
Bitboard LineBB[SQUARE_NB][SQUARE_NB];
Bitboard DistanceRingBB[SQUARE_NB][8];
-Bitboard ForwardBB[COLOR_NB][SQUARE_NB];
+Bitboard ForwardFileBB[COLOR_NB][SQUARE_NB];
Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
+Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
+
+Magic RookMagics[SQUARE_NB];
+Magic BishopMagics[SQUARE_NB];
namespace {
@@ -61,10 +54,7 @@ namespace {
Bitboard RookTable[0x19000]; // To store rook attacks
Bitboard BishopTable[0x1480]; // To store bishop attacks
- typedef unsigned (Fn)(Square, Bitboard);
-
- void init_magics(Bitboard table[], Bitboard* attacks[], Bitboard magics[],
- Bitboard masks[], unsigned shifts[], Square deltas[], Fn index);
+ void init_magics(Bitboard table[], Magic magics[], Square deltas[]);
// 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.
@@ -173,14 +163,14 @@ void Bitboards::init() {
AdjacentFilesBB[f] = (f > FILE_A ? FileBB[f - 1] : 0) | (f < FILE_H ? FileBB[f + 1] : 0);
for (Rank r = RANK_1; r < RANK_8; ++r)
- InFrontBB[WHITE][r] = ~(InFrontBB[BLACK][r + 1] = InFrontBB[BLACK][r] | RankBB[r]);
+ ForwardRanksBB[WHITE][r] = ~(ForwardRanksBB[BLACK][r + 1] = ForwardRanksBB[BLACK][r] | RankBB[r]);
for (Color c = WHITE; c <= BLACK; ++c)
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
- ForwardBB[c][s] = InFrontBB[c][rank_of(s)] & FileBB[file_of(s)];
- PawnAttackSpan[c][s] = InFrontBB[c][rank_of(s)] & AdjacentFilesBB[file_of(s)];
- PassedPawnMask[c][s] = ForwardBB[c][s] | PawnAttackSpan[c][s];
+ ForwardFileBB [c][s] = ForwardRanksBB[c][rank_of(s)] & FileBB[file_of(s)];
+ PawnAttackSpan[c][s] = ForwardRanksBB[c][rank_of(s)] & AdjacentFilesBB[file_of(s)];
+ PassedPawnMask[c][s] = ForwardFileBB [c][s] | PawnAttackSpan[c][s];
}
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
@@ -191,39 +181,43 @@ void Bitboards::init() {
DistanceRingBB[s1][SquareDistance[s1][s2] - 1] |= s2;
}
- int steps[][9] = { {}, { 7, 9 }, { 17, 15, 10, 6, -6, -10, -15, -17 },
- {}, {}, {}, { 9, 7, -7, -9, 8, 1, -1, -8 } };
+ int steps[][5] = { {}, { 7, 9 }, { 6, 10, 15, 17 }, {}, {}, {}, { 1, 7, 8, 9 } };
for (Color c = WHITE; c <= BLACK; ++c)
- for (PieceType pt = PAWN; pt <= KING; ++pt)
+ for (PieceType pt : { PAWN, KNIGHT, KING })
for (Square s = SQ_A1; s <= SQ_H8; ++s)
for (int i = 0; steps[pt][i]; ++i)
{
Square to = s + Square(c == WHITE ? steps[pt][i] : -steps[pt][i]);
if (is_ok(to) && distance(s, to) < 3)
- StepAttacksBB[make_piece(c, pt)][s] |= to;
+ {
+ if (pt == PAWN)
+ PawnAttacks[c][s] |= to;
+ else
+ PseudoAttacks[pt][s] |= to;
+ }
}
- Square RookDeltas[] = { NORTH, EAST, SOUTH, WEST };
+ Square RookDeltas[] = { NORTH, EAST, SOUTH, WEST };
Square BishopDeltas[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
- init_magics(RookTable, RookAttacks, RookMagics, RookMasks, RookShifts, RookDeltas, magic_index);
- init_magics(BishopTable, BishopAttacks, BishopMagics, BishopMasks, BishopShifts, BishopDeltas, magic_index);
+ init_magics(RookTable, RookMagics, RookDeltas);
+ init_magics(BishopTable, BishopMagics, BishopDeltas);
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
{
PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb(s1, 0);
PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(s1, 0);
- for (Piece pc = W_BISHOP; pc <= W_ROOK; ++pc)
+ for (PieceType pt : { BISHOP, ROOK })
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
{
- if (!(PseudoAttacks[pc][s1] & s2))
+ if (!(PseudoAttacks[pt][s1] & s2))
continue;
- LineBB[s1][s2] = (attacks_bb(pc, s1, 0) & attacks_bb(pc, s2, 0)) | s1 | s2;
- BetweenBB[s1][s2] = attacks_bb(pc, s1, SquareBB[s2]) & attacks_bb(pc, s2, SquareBB[s1]);
+ LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2;
+ BetweenBB[s1][s2] = attacks_bb(pt, s1, SquareBB[s2]) & attacks_bb(pt, s2, SquareBB[s1]);
}
}
}
@@ -255,17 +249,14 @@ namespace {
// chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we
// use the so called "fancy" approach.
- void init_magics(Bitboard table[], Bitboard* attacks[], Bitboard magics[],
- Bitboard masks[], unsigned shifts[], Square deltas[], Fn index) {
+ void init_magics(Bitboard table[], Magic magics[], Square deltas[]) {
+ // Optimal PRNG seeds to pick the correct magics in the shortest time
int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 },
{ 728, 10316, 55013, 32803, 12281, 15100, 16645, 255 } };
Bitboard occupancy[4096], reference[4096], edges, b;
- int age[4096] = {0}, current = 0, i, size;
-
- // attacks[s] is a pointer to the beginning of the attacks table for square 's'
- attacks[SQ_A1] = table;
+ int epoch[4096] = {}, cnt = 0, size = 0;
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
@@ -277,8 +268,13 @@ namespace {
// all the attacks for each possible subset of the mask and so is 2 power
// 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.
- masks[s] = sliding_attack(deltas, s, 0) & ~edges;
- shifts[s] = (Is64Bit ? 64 : 32) - popcount(masks[s]);
+ Magic& m = magics[s];
+ m.mask = sliding_attack(deltas, s, 0) & ~edges;
+ m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
+
+ // Set the offset for the attacks table of the square. We have individual
+ // table sizes for each square with "Fancy Magic Bitboards".
+ m.attacks = s == SQ_A1 ? table : magics[s - 1].attacks + size;
// Use Carry-Rippler trick to enumerate all subsets of masks[s] and
// store the corresponding sliding attack bitboard in reference[].
@@ -288,17 +284,12 @@ namespace {
reference[size] = sliding_attack(deltas, s, b);
if (HasPext)
- attacks[s][pext(b, masks[s])] = reference[size];
+ m.attacks[pext(b, m.mask)] = reference[size];
size++;
- b = (b - masks[s]) & masks[s];
+ b = (b - m.mask) & m.mask;
} while (b);
- // Set the offset for the table of the next square. We have individual
- // table sizes for each square with "Fancy Magic Bitboards".
- if (s < SQ_H8)
- attacks[s + 1] = attacks[s] + size;
-
if (HasPext)
continue;
@@ -306,28 +297,30 @@ namespace {
// Find a magic for square 's' picking up an (almost) random number
// until we find the one that passes the verification test.
- do {
- do
- magics[s] = rng.sparse_rand();
- while (popcount((magics[s] * masks[s]) >> 56) < 6);
+ for (int i = 0; i < size; )
+ {
+ for (m.magic = 0; popcount((m.magic * m.mask) >> 56) < 6; )
+ m.magic = rng.sparse_rand();
// A good magic must map every possible occupancy to an index that
// looks up the correct sliding attack in the attacks[s] database.
// Note that we build up the database for square 's' as a side
- // effect of verifying the magic.
- for (++current, i = 0; i < size; ++i)
+ // effect of verifying the magic. Keep track of the attempt count
+ // and save it in epoch[], little speed-up trick to avoid resetting
+ // m.attacks[] after every failed attempt.
+ for (++cnt, i = 0; i < size; ++i)
{
- unsigned idx = index(s, occupancy[i]);
+ unsigned idx = m.index(occupancy[i]);
- if (age[idx] < current)
+ if (epoch[idx] < cnt)
{
- age[idx] = current;
- attacks[s][idx] = reference[i];
+ epoch[idx] = cnt;
+ m.attacks[idx] = reference[i];
}
- else if (attacks[s][idx] != reference[i])
+ else if (m.attacks[idx] != reference[i])
break;
}
- } while (i < size);
+ }
}
}
}
diff --git a/DroidFish/jni/stockfish/bitboard.h b/DroidFish/jni/stockfish/bitboard.h
index 715f6c4..c9f199e 100644
--- a/DroidFish/jni/stockfish/bitboard.h
+++ b/DroidFish/jni/stockfish/bitboard.h
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -39,6 +39,7 @@ const std::string pretty(Bitboard b);
}
+const Bitboard AllSquares = ~Bitboard(0);
const Bitboard DarkSquares = 0xAA55AA55AA55AA55ULL;
const Bitboard FileABB = 0x0101010101010101ULL;
@@ -65,15 +66,41 @@ extern Bitboard SquareBB[SQUARE_NB];
extern Bitboard FileBB[FILE_NB];
extern Bitboard RankBB[RANK_NB];
extern Bitboard AdjacentFilesBB[FILE_NB];
-extern Bitboard InFrontBB[COLOR_NB][RANK_NB];
-extern Bitboard StepAttacksBB[PIECE_NB][SQUARE_NB];
+extern Bitboard ForwardRanksBB[COLOR_NB][RANK_NB];
extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
extern Bitboard DistanceRingBB[SQUARE_NB][8];
-extern Bitboard ForwardBB[COLOR_NB][SQUARE_NB];
+extern Bitboard ForwardFileBB[COLOR_NB][SQUARE_NB];
extern Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
extern Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
+extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
+
+
+/// Magic holds all magic bitboards relevant data for a single square
+struct Magic {
+ Bitboard mask;
+ Bitboard magic;
+ Bitboard* attacks;
+ unsigned shift;
+
+ // Compute the attack's index using the 'magic bitboards' approach
+ unsigned index(Bitboard occupied) const {
+
+ if (HasPext)
+ return unsigned(pext(occupied, mask));
+
+ if (Is64Bit)
+ return unsigned(((occupied & mask) * magic) >> shift);
+
+ unsigned lo = unsigned(occupied) & unsigned(mask);
+ unsigned hi = unsigned(occupied >> 32) & unsigned(mask >> 32);
+ return (lo * unsigned(magic) ^ hi * unsigned(magic >> 32)) >> shift;
+ }
+};
+
+extern Magic RookMagics[SQUARE_NB];
+extern Magic BishopMagics[SQUARE_NB];
/// Overloads of bitwise operators between a Bitboard and a Square for testing
@@ -153,28 +180,28 @@ inline Bitboard between_bb(Square s1, Square s2) {
}
-/// in_front_bb() returns a bitboard representing all the squares on all the ranks
+/// forward_ranks_bb() returns a bitboard representing all the squares on all the ranks
/// in front of the given one, from the point of view of the given color. For
-/// instance, in_front_bb(BLACK, RANK_3) will return the squares on ranks 1 and 2.
+/// instance, forward_ranks_bb(BLACK, SQ_D3) will return the 16 squares on ranks 1 and 2.
-inline Bitboard in_front_bb(Color c, Rank r) {
- return InFrontBB[c][r];
+inline Bitboard forward_ranks_bb(Color c, Square s) {
+ return ForwardRanksBB[c][rank_of(s)];
}
-/// forward_bb() returns a bitboard representing all the squares along the line
+/// forward_file_bb() returns a bitboard representing all the squares along the line
/// in front of the given one, from the point of view of the given color:
-/// ForwardBB[c][s] = in_front_bb(c, s) & file_bb(s)
+/// ForwardFileBB[c][s] = forward_ranks_bb(c, s) & file_bb(s)
-inline Bitboard forward_bb(Color c, Square s) {
- return ForwardBB[c][s];
+inline Bitboard forward_file_bb(Color c, Square s) {
+ return ForwardFileBB[c][s];
}
/// pawn_attack_span() returns a bitboard representing all the squares that can be
/// attacked by a pawn of the given color when it moves along its file, starting
/// from the given square:
-/// PawnAttackSpan[c][s] = in_front_bb(c, s) & adjacent_files_bb(s);
+/// PawnAttackSpan[c][s] = forward_ranks_bb(c, s) & adjacent_files_bb(file_of(s));
inline Bitboard pawn_attack_span(Color c, Square s) {
return PawnAttackSpan[c][s];
@@ -183,7 +210,7 @@ inline Bitboard pawn_attack_span(Color c, Square s) {
/// passed_pawn_mask() returns a bitboard mask which can be used to test if a
/// pawn of the given color and on the given square is a passed pawn:
-/// PassedPawnMask[c][s] = pawn_attack_span(c, s) | forward_bb(c, s)
+/// PassedPawnMask[c][s] = pawn_attack_span(c, s) | forward_file_bb(c, s)
inline Bitboard passed_pawn_mask(Color c, Square s) {
return PassedPawnMask[c][s];
@@ -210,50 +237,25 @@ template<> inline int distance(Square x, Square y) { return distance(rank_
/// attacks_bb() returns a bitboard representing all the squares attacked by a
-/// piece of type Pt (bishop or rook) placed on 's'. The helper magic_index()
-/// looks up the index using the 'magic bitboards' approach.
-template
-inline unsigned magic_index(Square s, Bitboard occupied) {
-
- extern Bitboard RookMasks[SQUARE_NB];
- extern Bitboard RookMagics[SQUARE_NB];
- extern unsigned RookShifts[SQUARE_NB];
- extern Bitboard BishopMasks[SQUARE_NB];
- extern Bitboard BishopMagics[SQUARE_NB];
- extern unsigned BishopShifts[SQUARE_NB];
-
- Bitboard* const Masks = Pt == ROOK ? RookMasks : BishopMasks;
- Bitboard* const Magics = Pt == ROOK ? RookMagics : BishopMagics;
- unsigned* const Shifts = Pt == ROOK ? RookShifts : BishopShifts;
-
- if (HasPext)
- return unsigned(pext(occupied, Masks[s]));
-
- if (Is64Bit)
- return unsigned(((occupied & Masks[s]) * Magics[s]) >> Shifts[s]);
-
- unsigned lo = unsigned(occupied) & unsigned(Masks[s]);
- unsigned hi = unsigned(occupied >> 32) & unsigned(Masks[s] >> 32);
- return (lo * unsigned(Magics[s]) ^ hi * unsigned(Magics[s] >> 32)) >> Shifts[s];
-}
+/// piece of type Pt (bishop or rook) placed on 's'.
template
inline Bitboard attacks_bb(Square s, Bitboard occupied) {
- extern Bitboard* RookAttacks[SQUARE_NB];
- extern Bitboard* BishopAttacks[SQUARE_NB];
-
- return (Pt == ROOK ? RookAttacks : BishopAttacks)[s][magic_index(s, occupied)];
+ const Magic& m = Pt == ROOK ? RookMagics[s] : BishopMagics[s];
+ return m.attacks[m.index(occupied)];
}
-inline Bitboard attacks_bb(Piece pc, Square s, Bitboard occupied) {
+inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) {
- switch (type_of(pc))
+ assert(pt != PAWN);
+
+ switch (pt)
{
case BISHOP: return attacks_bb(s, occupied);
- case ROOK : return attacks_bb(s, occupied);
+ case ROOK : return attacks_bb< ROOK>(s, occupied);
case QUEEN : return attacks_bb(s, occupied) | attacks_bb(s, occupied);
- default : return StepAttacksBB[pc][s];
+ default : return PseudoAttacks[pt][s];
}
}
@@ -291,7 +293,7 @@ inline Square lsb(Bitboard b) {
inline Square msb(Bitboard b) {
assert(b);
- return Square(63 - __builtin_clzll(b));
+ return Square(63 ^ __builtin_clzll(b));
}
#elif defined(_WIN64) && defined(_MSC_VER)
diff --git a/DroidFish/jni/stockfish/bitcount.h b/DroidFish/jni/stockfish/bitcount.h
deleted file mode 100644
index 7609da4..0000000
--- a/DroidFish/jni/stockfish/bitcount.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
-
- Stockfish is free software: you can redistribute it and/or modify
- 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 .
-*/
-
-#ifndef BITCOUNT_H_INCLUDED
-#define BITCOUNT_H_INCLUDED
-
-#include
-
-#include "types.h"
-
-enum BitCountType {
- CNT_64,
- CNT_64_MAX15,
- CNT_32,
- CNT_32_MAX15,
- CNT_HW_POPCNT
-};
-
-/// Determine at compile time the best popcount<> specialization according to
-/// whether the platform is 32 or 64 bit, the maximum number of non-zero
-/// bits to count and if the hardware popcnt instruction is available.
-const BitCountType Full = HasPopCnt ? CNT_HW_POPCNT : Is64Bit ? CNT_64 : CNT_32;
-const BitCountType Max15 = HasPopCnt ? CNT_HW_POPCNT : Is64Bit ? CNT_64_MAX15 : CNT_32_MAX15;
-
-
-/// popcount() counts the number of non-zero bits in a bitboard
-template inline int popcount(Bitboard);
-
-template<>
-inline int popcount(Bitboard b) {
- b -= (b >> 1) & 0x5555555555555555ULL;
- b = ((b >> 2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
- b = ((b >> 4) + b) & 0x0F0F0F0F0F0F0F0FULL;
- return (b * 0x0101010101010101ULL) >> 56;
-}
-
-template<>
-inline int popcount(Bitboard b) {
- b -= (b >> 1) & 0x5555555555555555ULL;
- b = ((b >> 2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
- return (b * 0x1111111111111111ULL) >> 60;
-}
-
-template<>
-inline int popcount(Bitboard b) {
- unsigned w = unsigned(b >> 32), v = unsigned(b);
- v -= (v >> 1) & 0x55555555; // 0-2 in 2 bits
- w -= (w >> 1) & 0x55555555;
- v = ((v >> 2) & 0x33333333) + (v & 0x33333333); // 0-4 in 4 bits
- w = ((w >> 2) & 0x33333333) + (w & 0x33333333);
- v = ((v >> 4) + v + (w >> 4) + w) & 0x0F0F0F0F;
- return (v * 0x01010101) >> 24;
-}
-
-template<>
-inline int popcount(Bitboard b) {
- unsigned w = unsigned(b >> 32), v = unsigned(b);
- v -= (v >> 1) & 0x55555555; // 0-2 in 2 bits
- w -= (w >> 1) & 0x55555555;
- v = ((v >> 2) & 0x33333333) + (v & 0x33333333); // 0-4 in 4 bits
- w = ((w >> 2) & 0x33333333) + (w & 0x33333333);
- return ((v + w) * 0x11111111) >> 28;
-}
-
-template<>
-inline int popcount(Bitboard b) {
-
-#ifndef USE_POPCNT
-
- assert(false);
- return b != 0; // Avoid 'b not used' warning
-
-#elif defined(_MSC_VER) && defined(__INTEL_COMPILER)
-
- return _mm_popcnt_u64(b);
-
-#elif defined(_MSC_VER)
-
- return (int)__popcnt64(b);
-
-#else // Assumed gcc or compatible compiler
-
- return __builtin_popcountll(b);
-
-#endif
-}
-
-#endif // #ifndef BITCOUNT_H_INCLUDED
diff --git a/DroidFish/jni/stockfish/endgame.cpp b/DroidFish/jni/stockfish/endgame.cpp
index cbca34b..ca17f6a 100644
--- a/DroidFish/jni/stockfish/endgame.cpp
+++ b/DroidFish/jni/stockfish/endgame.cpp
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -83,26 +83,6 @@ namespace {
return sq;
}
- // Get the material key of Position out of the given endgame key code
- // like "KBPKN". The trick here is to first forge an ad-hoc FEN string
- // and then let a Position object do the work for us.
- Key key(const string& code, Color c) {
-
- assert(code.length() > 0 && code.length() < 8);
- assert(code[0] == 'K');
-
- string sides[] = { code.substr(code.find('K', 1)), // Weak
- code.substr(0, code.find('K', 1)) }; // Strong
-
- std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower);
-
- string fen = sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/8/8/"
- + sides[1] + char(8 - sides[1].length() + '0') + " w - - 0 10";
-
- StateInfo st;
- return Position().set(fen, false, &st, nullptr).material_key();
- }
-
} // namespace
@@ -130,13 +110,6 @@ Endgames::Endgames() {
}
-template
-void Endgames::add(const string& code) {
- map()[key(code, WHITE)] = std::unique_ptr>(new Endgame(WHITE));
- map()[key(code, BLACK)] = std::unique_ptr>(new Endgame(BLACK));
-}
-
-
/// Mate with KX vs K. This function is used to evaluate positions with
/// king and plenty of material vs a lone king. It simply gives the
/// attacking side a bonus for driving the defending king towards the edge
@@ -162,8 +135,8 @@ Value Endgame::operator()(const Position& pos) const {
if ( pos.count(strongSide)
|| pos.count(strongSide)
||(pos.count(strongSide) && pos.count(strongSide))
- ||(pos.count(strongSide) > 1 && opposite_colors(pos.squares(strongSide)[0],
- pos.squares(strongSide)[1])))
+ || ( (pos.pieces(strongSide, BISHOP) & ~DarkSquares)
+ && (pos.pieces(strongSide, BISHOP) & DarkSquares)))
result = std::min(result + VALUE_KNOWN_WIN, VALUE_MATE_IN_MAX_PLY - 1);
return strongSide == pos.side_to_move() ? result : -result;
@@ -625,7 +598,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const {
// If all pawns are ahead of the king, on a single rook file and
// the king is within one file of the pawns, it's a draw.
- if ( !(pawns & ~in_front_bb(weakSide, rank_of(ksq)))
+ if ( !(pawns & ~forward_ranks_bb(weakSide, ksq))
&& !((pawns & ~FileABB) && (pawns & ~FileHBB))
&& distance(ksq, lsb(pawns)) <= 1)
return SCALE_FACTOR_DRAW;
@@ -671,17 +644,15 @@ ScaleFactor Endgame::operator()(const Position& pos) const {
if (relative_rank(strongSide, pawnSq) <= RANK_5)
return SCALE_FACTOR_DRAW;
- else
- {
- Bitboard path = forward_bb(strongSide, pawnSq);
- if (path & pos.pieces(weakSide, KING))
- return SCALE_FACTOR_DRAW;
+ Bitboard path = forward_file_bb(strongSide, pawnSq);
- if ( (pos.attacks_from(weakBishopSq) & path)
- && distance(weakBishopSq, pawnSq) >= 3)
- return SCALE_FACTOR_DRAW;
- }
+ if (path & pos.pieces(weakSide, KING))
+ return SCALE_FACTOR_DRAW;
+
+ if ( (pos.attacks_from(weakBishopSq) & path)
+ && distance(weakBishopSq, pawnSq) >= 3)
+ return SCALE_FACTOR_DRAW;
}
return SCALE_FACTOR_NONE;
}
@@ -809,7 +780,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const {
// King needs to get close to promoting pawn to prevent knight from blocking.
// Rules for this are very tricky, so just approximate.
- if (forward_bb(strongSide, pawnSq) & pos.attacks_from(bishopSq))
+ if (forward_file_bb(strongSide, pawnSq) & pos.attacks_from(bishopSq))
return ScaleFactor(distance(weakKingSq, pawnSq));
return SCALE_FACTOR_NONE;
diff --git a/DroidFish/jni/stockfish/endgame.h b/DroidFish/jni/stockfish/endgame.h
index 5f6b4bb..3d61207 100644
--- a/DroidFish/jni/stockfish/endgame.h
+++ b/DroidFish/jni/stockfish/endgame.h
@@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -31,12 +31,11 @@
#include "types.h"
-/// EndgameType lists all supported endgames
+/// EndgameCode lists all supported endgame functions by corresponding codes
-enum EndgameType {
-
- // Evaluation functions
+enum EndgameCode {
+ EVALUATION_FUNCTIONS,
KNNK, // KNN vs K
KXK, // Generic "mate lone king" eval
KBNK, // KBN vs K
@@ -47,10 +46,7 @@ enum EndgameType {
KQKP, // KQ vs KP
KQKR, // KQ vs KR
-
- // Scaling functions
SCALING_FUNCTIONS,
-
KBPsK, // KB and pawns vs K
KQKRPs, // KQ vs KR and pawns
KRPKR, // KRP vs KR
@@ -68,30 +64,28 @@ enum EndgameType {
/// Endgame functions can be of two types depending on whether they return a
/// Value or a ScaleFactor.
-template using
+template using
eg_type = typename std::conditional<(E < SCALING_FUNCTIONS), Value, ScaleFactor>::type;
-/// Base and derived templates for endgame evaluation and scaling functions
+/// Base and derived functors for endgame evaluation and scaling functions
template
struct EndgameBase {
+ explicit EndgameBase(Color c) : strongSide(c), weakSide(~c) {}
virtual ~EndgameBase() = default;
- virtual Color strong_side() const = 0;
virtual T operator()(const Position&) const = 0;
+
+ const Color strongSide, weakSide;
};
-template>
+template>
struct Endgame : public EndgameBase {
- explicit Endgame(Color c) : strongSide(c), weakSide(~c) {}
- Color strong_side() const { return strongSide; }
- T operator()(const Position&) const;
-
-private:
- Color strongSide, weakSide;
+ explicit Endgame(Color c) : EndgameBase(c) {}
+ T operator()(const Position&) const override;
};
@@ -101,16 +95,22 @@ private:
class Endgames {
- template using Map = std::map>>;
-
- template>
- void add(const std::string& code);
+ template using Ptr = std::unique_ptr>;
+ template using Map = std::map>;
template
Map& map() {
return std::get::value>(maps);
}
+ template, typename P = Ptr>
+ void add(const std::string& code) {
+
+ StateInfo st;
+ map()[Position().set(code, WHITE, &st).material_key()] = P(new Endgame(WHITE));
+ map()[Position().set(code, BLACK, &st).material_key()] = P(new Endgame(BLACK));
+ }
+
std::pair