DroidFish: Updated stockfish engine to version 2.2.1.

This commit is contained in:
Peter Osterlund 2012-01-07 02:07:28 +00:00
parent bd14dedd1d
commit 6c85f9e0c1
18 changed files with 244 additions and 290 deletions

View File

@ -17,13 +17,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
The code in this file is based on the opening book code in PolyGlot
by Fabien Letouzey. PolyGlot is available under the GNU General
Public License, and can be downloaded from http://wbec-ridderkerk.nl
*/
#include <algorithm>
#include <cassert>
#include <iostream>
@ -306,225 +306,182 @@ namespace {
const Key* ZobEnPassant = PolyGlotRandoms + 772;
const Key* ZobTurn = PolyGlotRandoms + 780;
// Piece offset is calculated as 64 * (PolyPiece ^ 1) where
// PolyPiece is: BP = 0, WP = 1, BN = 2, WN = 3 ... BK = 10, WK = 11
const int PieceOfs[] = { 0, 64, 192, 320, 448, 576, 704, 0,
0, 0, 128, 256, 384, 512, 640 };
// PieceOffset is calculated as 64 * (PolyPiece ^ 1) where PolyPiece
// is: BP = 0, WP = 1, BN = 2, WN = 3 ... BK = 10, WK = 11
const int PieceOffset[] = { 0, 64, 192, 320, 448, 576, 704, 0,
0, 0, 128, 256, 384, 512, 640 };
// book_key() builds up a PolyGlot hash key out of a position
// book_key() returns the PolyGlot hash key of the given position
uint64_t book_key(const Position& pos) {
uint64_t result = 0;
uint64_t key = 0;
Bitboard b = pos.occupied_squares();
while (b)
{
Square s = pop_1st_bit(&b);
result ^= ZobPiece[PieceOfs[pos.piece_on(s)] + s];
key ^= ZobPiece[PieceOffset[pos.piece_on(s)] + s];
}
if (pos.can_castle(WHITE_OO))
result ^= ZobCastle[0];
b = (pos.can_castle(WHITE_OO) << 0) | (pos.can_castle(WHITE_OOO) << 1)
| (pos.can_castle(BLACK_OO) << 2) | (pos.can_castle(BLACK_OOO) << 3);
if (pos.can_castle(WHITE_OOO))
result ^= ZobCastle[1];
if (pos.can_castle(BLACK_OO))
result ^= ZobCastle[2];
if (pos.can_castle(BLACK_OOO))
result ^= ZobCastle[3];
while (b)
key ^= ZobCastle[pop_1st_bit(&b)];
if (pos.ep_square() != SQ_NONE)
result ^= ZobEnPassant[file_of(pos.ep_square())];
key ^= ZobEnPassant[file_of(pos.ep_square())];
if (pos.side_to_move() == WHITE)
result ^= ZobTurn[0];
key ^= ZobTurn[0];
return result;
return key;
}
}
} // namespace
/// Book c'tor. Make random number generation less deterministic, for book moves
Book::Book() : bookSize(0) {
Book::Book() : size(0) {
for (int i = abs(system_time() % 10000); i > 0; i--)
RKiss.rand<unsigned>();
RKiss.rand<unsigned>(); // Make random number generation less deterministic
}
Book::~Book() { if (is_open()) close(); }
/// Book::operator>>() reads sizeof(T) chars from the file's binary byte stream
/// and converts them in a number of type T. A Polyglot book stores numbers in
/// big-endian format.
template<typename T> Book& Book::operator>>(T& n) {
n = 0;
for (size_t i = 0; i < sizeof(T); i++)
n = T((n << 8) + ifstream::get());
return *this;
}
template<> Book& Book::operator>>(BookEntry& e) {
return *this >> e.key >> e.move >> e.count >> e.learn;
}
/// Book destructor. Be sure file is closed before we leave.
/// Book::open() tries to open a book file with the given name after closing
/// any exsisting one.
Book::~Book() {
bool Book::open(const char* fName) {
close();
}
fileName = "";
if (is_open()) // Cannot close an already closed file
close();
/// Book::close() closes the file only if it is open, otherwise the call fails
/// and the failbit internal state flag is set.
ifstream::open(fName, ifstream::in | ifstream::binary | ios::ate);
void Book::close() {
if (!is_open())
return false; // Silently fail if the file is not found
if (bookFile.is_open())
bookFile.close();
// Get the book size in number of entries, we are already at the end of file
size = tellg() / sizeof(BookEntry);
bookName = "";
bookSize = 0;
}
/// Book::open() opens a book file with a given name
void Book::open(const string& fileName) {
// Close old file before opening the new
close();
bookFile.open(fileName.c_str(), ifstream::in | ifstream::binary |ios::ate);
// Silently return when asked to open a non-exsistent file
if (!bookFile.is_open())
return;
// Get the book size in number of entries, we are already at the file end
bookSize = long(bookFile.tellg()) / sizeof(BookEntry);
if (!bookFile.good())
if (!good())
{
cerr << "Failed to open book file " << fileName << endl;
cerr << "Failed to open book file " << fName << endl;
exit(EXIT_FAILURE);
}
// Set only if successful
bookName = fileName;
fileName = fName; // Set only if successful
return true;
}
/// Book::probe() gets a book move for a given position. Returns MOVE_NONE
/// if no book move is found. If findBest is true then returns always the
/// highest rated move otherwise chooses randomly based on the move score.
/// Book::probe() tries to find a book move for the given position. If no move
/// is found returns MOVE_NONE. If pickBest is true returns always the highest
/// rated move, otherwise randomly chooses one, based on the move score.
Move Book::probe(const Position& pos, bool findBest) {
Move Book::probe(const Position& pos, const string& fName, bool pickBest) {
if (!bookSize || !bookFile.is_open())
BookEntry e;
uint16_t best = 0;
unsigned sum = 0;
Move move = MOVE_NONE;
uint64_t key = book_key(pos);
if (fileName != fName && !open(fName.c_str()))
return MOVE_NONE;
BookEntry entry;
unsigned scoresSum = 0, bestScore = 0, bookMove = 0;
uint64_t key = book_key(pos);
int idx = first_entry(key) - 1;
binary_search(key);
// Choose a book move among the possible moves for the given position
while (++idx < bookSize && (entry = read_entry(idx), entry.key == key))
while (*this >> e, e.key == key && good())
{
scoresSum += entry.count;
best = max(best, e.count);
sum += e.count;
// Choose book move according to its score. If a move has a very
// high score it has higher probability to be choosen than a move
// with lower score. Note that first entry is always chosen.
if ( RKiss.rand<unsigned>() % scoresSum < entry.count
|| (findBest && entry.count > bestScore))
bookMove = entry.move;
if (entry.count > bestScore)
bestScore = entry.count;
if ( (RKiss.rand<unsigned>() % sum < e.count)
|| (pickBest && e.count == best))
move = Move(e.move);
}
if (!bookMove)
if (!move)
return MOVE_NONE;
// A PolyGlot book move is encoded as follows:
//
// bit 0- 5: destination square (from 0 to 63)
// bit 6-11: origin square (from 0 to 63)
// bit 12-13-14: promotion piece (from KNIGHT == 1 to QUEEN == 4)
// bit 12-14: promotion piece (from KNIGHT == 1 to QUEEN == 4)
//
// Castling moves follow "king captures rook" representation. So in case
// book move is a promotion we have to convert to our representation, in
// all other cases we can directly compare with a Move after having
// masked out special Move's flags that are not supported by PolyGlot.
int promotion = (bookMove >> 12) & 7;
// Castling moves follow "king captures rook" representation. So in case book
// move is a promotion we have to convert to our representation, in all the
// other cases we can directly compare with a Move after having masked out
// the special Move's flags (bit 14-15) that are not supported by PolyGlot.
int pt = (move >> 12) & 7;
if (pt)
move = make_promotion(from_sq(move), to_sq(move), PieceType(pt + 1));
if (promotion)
bookMove = make_promotion_move(move_from(Move(bookMove)),
move_to(Move(bookMove)),
PieceType(promotion + 1));
// Verify the book move is legal
// Add 'special move' flags and verify it is legal
for (MoveList<MV_LEGAL> ml(pos); !ml.end(); ++ml)
if (unsigned(ml.move() & ~(3 << 14)) == bookMove) // Mask out special flags
if (move == (ml.move() & 0x3FFF))
return ml.move();
return MOVE_NONE;
}
/// Book::first_entry() takes a book key as input, and does a binary search
/// through the book file for the given key. The index to the first (leftmost)
/// book entry with the same key as the input is returned. When the key is not
/// found in the book file, bookSize is returned.
/// Book::binary_search() takes a book key as input, and does a binary search
/// through the book file for the given key. File stream current position is set
/// to the leftmost book entry with the same key as the input.
int Book::first_entry(uint64_t key) {
int left, right, mid;
// Binary search (finds the leftmost entry with given key)
left = 0;
right = bookSize - 1;
assert(left <= right);
while (left < right)
{
mid = (left + right) / 2;
assert(mid >= left && mid < right);
if (key <= read_entry(mid).key)
right = mid;
else
left = mid + 1;
}
assert(left == right);
return read_entry(left).key == key ? left : bookSize;
}
/// Book::operator>>() reads sizeof(T) chars from the file's binary byte
/// stream and converts them in a number of type T.
template<typename T>
Book& Book::operator>>(T& n) {
n = 0;
for (size_t i = 0; i < sizeof(T); i++)
n = T((n << 8) + bookFile.get());
return *this;
}
/// Book::read_entry() takes an integer index, and returns the BookEntry
/// at the given index in the book file.
BookEntry Book::read_entry(int idx) {
assert(idx >= 0 && idx < bookSize);
assert(bookFile.is_open());
void Book::binary_search(uint64_t key) {
size_t low, high, mid;
BookEntry e;
bookFile.seekg(idx * sizeof(BookEntry), ios_base::beg);
low = 0;
high = size - 1;
*this >> e.key >> e.move >> e.count >> e.learn;
assert(low <= high);
if (!bookFile.good())
while (low < high && good())
{
cerr << "Failed to read book entry at index " << idx << endl;
exit(EXIT_FAILURE);
mid = (low + high) / 2;
assert(mid >= low && mid < high);
seekg(mid * sizeof(BookEntry), ios_base::beg);
*this >> e;
if (key <= e.key)
high = mid;
else
low = mid + 1;
}
return e;
assert(low == high);
seekg(low * sizeof(BookEntry), ios_base::beg);
}

View File

@ -37,25 +37,22 @@ struct BookEntry {
uint32_t learn;
};
class Book {
class Book : private std::ifstream {
public:
Book();
~Book();
void open(const std::string& fileName);
void close();
Move probe(const Position& pos, bool findBestMove);
const std::string name() const { return bookName; }
Move probe(const Position& pos, const std::string& fName, bool pickBest);
private:
template<typename T> Book& operator>>(T& n);
BookEntry read_entry(int idx);
int first_entry(uint64_t key);
bool open(const char* fName);
void binary_search(uint64_t key);
RKISS RKiss;
std::ifstream bookFile;
std::string bookName;
int bookSize;
std::string fileName;
size_t size;
};
#endif // !defined(BOOK_H_INCLUDED)

View File

@ -19,12 +19,14 @@
#include <algorithm>
#include <cassert>
#include <ctype.h>
#include "bitcount.h"
#include "endgame.h"
#include "pawns.h"
using std::string;
using std::transform;
extern uint32_t probe_kpk_bitbase(Square wksq, Square wpsq, Square bksq, Color stm);
@ -72,7 +74,7 @@ namespace {
string sides[] = { code.substr(code.find('K', 1)), // Weaker
code.substr(0, code.find('K', 1)) }; // Stronger
std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower);
transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower);
string fen = sides[0] + char('0' + int(8 - code.length()))
+ sides[1] + "/8/8/8/8/8/8/8 w - - 0 10";

View File

@ -75,8 +75,8 @@ typedef HANDLE WaitCondition;
# define cond_init(x) { *x = CreateEvent(0, FALSE, FALSE, 0); }
# define cond_destroy(x) CloseHandle(*x)
# define cond_signal(x) SetEvent(*x)
# define cond_wait(x,y) { ResetEvent(*x); lock_release(y); WaitForSingleObject(*x, INFINITE); lock_grab(y); }
# define cond_timedwait(x,y,z) { ResetEvent(*x); lock_release(y); WaitForSingleObject(*x,z); lock_grab(y); }
# define cond_wait(x,y) { lock_release(y); WaitForSingleObject(*x, INFINITE); lock_grab(y); }
# define cond_timedwait(x,y,z) { lock_release(y); WaitForSingleObject(*x,z); lock_grab(y); }
#endif

View File

@ -55,8 +55,8 @@ using namespace std;
/// Version number. If Version is left empty, then Tag plus current
/// date (in the format YYMMDD) is used as a version number.
static const string Version = "2.2";
static const string Tag = "";
static const string Version = "2.2.1";
static const string Tag = "";
/// engine_info() returns the full name of the current Stockfish version.

View File

@ -20,6 +20,7 @@
#include <cassert>
#include <cstring>
#include <string>
#include <ctype.h>
#include "movegen.h"
#include "position.h"
@ -33,8 +34,8 @@ using std::string;
const string move_to_uci(Move m, bool chess960) {
Square from = move_from(m);
Square to = move_to(m);
Square from = from_sq(m);
Square to = to_sq(m);
string promotion;
if (m == MOVE_NONE)
@ -83,13 +84,13 @@ const string move_to_san(Position& pos, Move m) {
Bitboard attackers;
bool ambiguousMove, ambiguousFile, ambiguousRank;
Square sq, from = move_from(m);
Square to = move_to(m);
Square sq, from = from_sq(m);
Square to = to_sq(m);
PieceType pt = type_of(pos.piece_on(from));
string san;
if (is_castle(m))
san = (move_to(m) < move_from(m) ? "O-O-O" : "O-O");
san = (to_sq(m) < from_sq(m) ? "O-O-O" : "O-O");
else
{
if (pt != PAWN)

View File

@ -101,8 +101,6 @@ namespace {
FORCE_INLINE MoveStack* generate_piece_moves(const Position& p, MoveStack* m, Color us, Bitboard t) {
assert(Pt == PAWN);
assert(Type == MV_CAPTURE || Type == MV_NON_CAPTURE || Type == MV_EVASION);
return (us == WHITE ? generate_pawn_moves<WHITE, Type>(p, m, t, SQ_NONE)
: generate_pawn_moves<BLACK, Type>(p, m, t, SQ_NONE));
}
@ -151,27 +149,22 @@ namespace {
template<MoveType Type>
MoveStack* generate(const Position& pos, MoveStack* mlist) {
assert(Type == MV_CAPTURE || Type == MV_NON_CAPTURE || Type == MV_NON_EVASION);
assert(!pos.in_check());
Color us = pos.side_to_move();
Bitboard target;
if (Type == MV_CAPTURE || Type == MV_NON_EVASION)
if (Type == MV_CAPTURE)
target = pos.pieces(flip(us));
else if (Type == MV_NON_CAPTURE)
target = pos.empty_squares();
else
assert(false);
if (Type == MV_NON_EVASION)
{
mlist = generate_piece_moves<PAWN, MV_CAPTURE>(pos, mlist, us, target);
mlist = generate_piece_moves<PAWN, MV_NON_CAPTURE>(pos, mlist, us, pos.empty_squares());
target |= pos.empty_squares();
}
else
mlist = generate_piece_moves<PAWN, Type>(pos, mlist, us, target);
else if (Type == MV_NON_EVASION)
target = pos.pieces(flip(us)) | pos.empty_squares();
mlist = generate_piece_moves<PAWN, Type>(pos, mlist, us, target);
mlist = generate_piece_moves<KNIGHT>(pos, mlist, us, target);
mlist = generate_piece_moves<BISHOP>(pos, mlist, us, target);
mlist = generate_piece_moves<ROOK>(pos, mlist, us, target);
@ -339,7 +332,7 @@ namespace {
Delta == DELTA_NW ? p << 7 : Delta == DELTA_SW ? p >> 9 : p;
}
template<MoveType Type, Square Delta>
template<Square Delta>
inline MoveStack* generate_pawn_captures(MoveStack* mlist, Bitboard pawns, Bitboard target) {
const Bitboard TFileABB = (Delta == DELTA_NE || Delta == DELTA_SE ? FileABB : FileHBB);
@ -371,21 +364,21 @@ namespace {
{
to = pop_1st_bit(&b);
if (Type == MV_CAPTURE || Type == MV_EVASION)
(*mlist++).move = make_promotion_move(to - Delta, to, QUEEN);
if (Type == MV_CAPTURE || Type == MV_EVASION || Type == MV_NON_EVASION)
(*mlist++).move = make_promotion(to - Delta, to, QUEEN);
if (Type == MV_NON_CAPTURE || Type == MV_EVASION)
if (Type == MV_NON_CAPTURE || Type == MV_EVASION || Type == MV_NON_EVASION)
{
(*mlist++).move = make_promotion_move(to - Delta, to, ROOK);
(*mlist++).move = make_promotion_move(to - Delta, to, BISHOP);
(*mlist++).move = make_promotion_move(to - Delta, to, KNIGHT);
(*mlist++).move = make_promotion(to - Delta, to, ROOK);
(*mlist++).move = make_promotion(to - Delta, to, BISHOP);
(*mlist++).move = make_promotion(to - Delta, to, KNIGHT);
}
// This is the only possible under promotion that can give a check
// not already included in the queen-promotion.
if ( Type == MV_CHECK
&& bit_is_set(pos.attacks_from<KNIGHT>(to), pos.king_square(Delta > 0 ? BLACK : WHITE)))
(*mlist++).move = make_promotion_move(to - Delta, to, KNIGHT);
(*mlist++).move = make_promotion(to - Delta, to, KNIGHT);
else (void)pos; // Silence a warning under MSVC
}
return mlist;
@ -435,10 +428,10 @@ namespace {
}
// Standard captures
if (Type == MV_CAPTURE || Type == MV_EVASION)
if (Type == MV_CAPTURE || Type == MV_EVASION || Type == MV_NON_EVASION)
{
mlist = generate_pawn_captures<Type, RIGHT_UP>(mlist, pawns, enemyPieces);
mlist = generate_pawn_captures<Type, LEFT_UP>(mlist, pawns, enemyPieces);
mlist = generate_pawn_captures<RIGHT_UP>(mlist, pawns, enemyPieces);
mlist = generate_pawn_captures<LEFT_UP>(mlist, pawns, enemyPieces);
}
// Single and double pawn pushes
@ -470,7 +463,8 @@ namespace {
}
// En passant captures
if ((Type == MV_CAPTURE || Type == MV_EVASION) && pos.ep_square() != SQ_NONE)
if ( (Type == MV_CAPTURE || Type == MV_EVASION || Type == MV_NON_EVASION)
&& pos.ep_square() != SQ_NONE)
{
assert(Us != WHITE || rank_of(pos.ep_square()) == RANK_6);
assert(Us != BLACK || rank_of(pos.ep_square()) == RANK_3);
@ -488,7 +482,7 @@ namespace {
while (b1)
{
to = pop_1st_bit(&b1);
(*mlist++).move = make_enpassant_move(to, pos.ep_square());
(*mlist++).move = make_enpassant(to, pos.ep_square());
}
}
return mlist;
@ -535,7 +529,7 @@ namespace {
return mlist;
}
(*mlist++).move = make_castle_move(kfrom, rfrom);
(*mlist++).move = make_castle(kfrom, rfrom);
return mlist;
}

View File

@ -254,8 +254,8 @@ void MovePicker::score_captures() {
for (MoveStack* cur = moves; cur != lastMove; cur++)
{
m = cur->move;
cur->score = PieceValueMidgame[pos.piece_on(move_to(m))]
- type_of(pos.piece_on(move_from(m)));
cur->score = PieceValueMidgame[pos.piece_on(to_sq(m))]
- type_of(pos.piece_on(from_sq(m)));
if (is_promotion(m))
cur->score += PieceValueMidgame[Piece(promotion_piece_type(m))];
@ -270,8 +270,8 @@ void MovePicker::score_noncaptures() {
for (MoveStack* cur = moves; cur != lastMove; cur++)
{
m = cur->move;
from = move_from(m);
cur->score = H.value(pos.piece_on(from), move_to(m));
from = from_sq(m);
cur->score = H.value(pos.piece_on(from), to_sq(m));
}
}
@ -293,10 +293,10 @@ void MovePicker::score_evasions() {
if ((seeScore = pos.see_sign(m)) < 0)
cur->score = seeScore - History::MaxValue; // Be sure we are at the bottom
else if (pos.is_capture(m))
cur->score = PieceValueMidgame[pos.piece_on(move_to(m))]
- type_of(pos.piece_on(move_from(m))) + History::MaxValue;
cur->score = PieceValueMidgame[pos.piece_on(to_sq(m))]
- type_of(pos.piece_on(from_sq(m))) + History::MaxValue;
else
cur->score = H.value(pos.piece_on(move_from(m)), move_to(m));
cur->score = H.value(pos.piece_on(from_sq(m)), to_sq(m));
}
}
@ -378,7 +378,7 @@ Move MovePicker::next_move() {
case PH_QRECAPTURES:
move = (curMove++)->move;
if (move_to(move) == recaptureSquare)
if (to_sq(move) == recaptureSquare)
return move;
break;

View File

@ -23,6 +23,7 @@
#include <iostream>
#include <sstream>
#include <algorithm>
#include <ctype.h>
#include "bitcount.h"
#include "movegen.h"
@ -420,8 +421,8 @@ bool Position::move_attacks_square(Move m, Square s) const {
assert(square_is_ok(s));
Bitboard occ, xray;
Square from = move_from(m);
Square to = move_to(m);
Square from = from_sq(m);
Square to = to_sq(m);
Piece piece = piece_on(from);
assert(!square_is_empty(from));
@ -451,7 +452,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
assert(pinned == pinned_pieces());
Color us = side_to_move();
Square from = move_from(m);
Square from = from_sq(m);
assert(color_of(piece_on(from)) == us);
assert(piece_on(king_square(us)) == make_piece(us, KING));
@ -462,7 +463,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
if (is_enpassant(m))
{
Color them = flip(us);
Square to = move_to(m);
Square to = to_sq(m);
Square capsq = to + pawn_push(them);
Square ksq = king_square(us);
Bitboard b = occupied_squares();
@ -484,13 +485,13 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
// square is attacked by the opponent. Castling moves are checked
// for legality during move generation.
if (type_of(piece_on(from)) == KING)
return is_castle(m) || !(attackers_to(move_to(m)) & pieces(flip(us)));
return is_castle(m) || !(attackers_to(to_sq(m)) & pieces(flip(us)));
// A non-king move is legal if and only if it is not pinned or it
// is moving along the ray towards or away from the king.
return !pinned
|| !bit_is_set(pinned, from)
|| squares_aligned(from, move_to(m), king_square(us));
|| squares_aligned(from, to_sq(m), king_square(us));
}
@ -516,8 +517,8 @@ bool Position::is_pseudo_legal(const Move m) const {
Color us = sideToMove;
Color them = flip(sideToMove);
Square from = move_from(m);
Square to = move_to(m);
Square from = from_sq(m);
Square to = to_sq(m);
Piece pc = piece_on(from);
// Use a slower but simpler function for uncommon cases
@ -613,7 +614,7 @@ bool Position::is_pseudo_legal(const Move m) const {
{
Bitboard b = occupied_squares();
clear_bit(&b, from);
if (attackers_to(move_to(m), b) & pieces(flip(us)))
if (attackers_to(to_sq(m), b) & pieces(flip(us)))
return false;
}
else
@ -626,7 +627,7 @@ bool Position::is_pseudo_legal(const Move m) const {
// Our move must be a blocking evasion or a capture of the checking piece
target = squares_between(checksq, king_square(us)) | checkers();
if (!bit_is_set(target, move_to(m)))
if (!bit_is_set(target, to_sq(m)))
return false;
}
}
@ -641,10 +642,10 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const {
assert(is_ok(m));
assert(ci.dcCandidates == discovered_check_candidates());
assert(color_of(piece_on(move_from(m))) == side_to_move());
assert(color_of(piece_on(from_sq(m))) == side_to_move());
Square from = move_from(m);
Square to = move_to(m);
Square from = from_sq(m);
Square to = to_sq(m);
PieceType pt = type_of(piece_on(from));
// Direct check ?
@ -766,8 +767,8 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
Color us = side_to_move();
Color them = flip(us);
Square from = move_from(m);
Square to = move_to(m);
Square from = from_sq(m);
Square to = to_sq(m);
Piece piece = piece_on(from);
PieceType pt = type_of(piece);
PieceType capture = is_enpassant(m) ? PAWN : type_of(piece_on(to));
@ -982,8 +983,8 @@ void Position::undo_move(Move m) {
Color us = side_to_move();
Color them = flip(us);
Square from = move_from(m);
Square to = move_to(m);
Square from = from_sq(m);
Square to = to_sq(m);
Piece piece = piece_on(to);
PieceType pt = type_of(piece);
PieceType capture = st->capturedType;
@ -1077,8 +1078,8 @@ void Position::do_castle_move(Move m) {
Square kto, kfrom, rfrom, rto, kAfter, rAfter;
Color us = side_to_move();
Square kBefore = move_from(m);
Square rBefore = move_to(m);
Square kBefore = from_sq(m);
Square rBefore = to_sq(m);
// Find after-castle squares for king and rook
if (rBefore > kBefore) // O-O
@ -1228,8 +1229,8 @@ int Position::see_sign(Move m) const {
assert(is_ok(m));
Square from = move_from(m);
Square to = move_to(m);
Square from = from_sq(m);
Square to = to_sq(m);
// Early return if SEE cannot be negative because captured piece value
// is not less then capturing one. Note that king moves always return
@ -1256,8 +1257,8 @@ int Position::see(Move m) const {
if (is_castle(m))
return 0;
from = move_from(m);
to = move_to(m);
from = from_sq(m);
to = to_sq(m);
capturedType = type_of(piece_on(to));
occ = occupied_squares();

View File

@ -428,8 +428,8 @@ inline Value Position::non_pawn_material(Color c) const {
inline bool Position::is_passed_pawn_push(Move m) const {
return board[move_from(m)] == make_piece(sideToMove, PAWN)
&& pawn_is_passed(sideToMove, move_to(m));
return board[from_sq(m)] == make_piece(sideToMove, PAWN)
&& pawn_is_passed(sideToMove, to_sq(m));
}
inline int Position::startpos_ply_counter() const {
@ -454,14 +454,14 @@ inline bool Position::is_chess960() const {
inline bool Position::is_capture_or_promotion(Move m) const {
assert(is_ok(m));
return is_special(m) ? !is_castle(m) : !square_is_empty(move_to(m));
return is_special(m) ? !is_castle(m) : !square_is_empty(to_sq(m));
}
inline bool Position::is_capture(Move m) const {
// Note that castle is coded as "king captures the rook"
assert(is_ok(m));
return (!square_is_empty(move_to(m)) && !is_castle(m)) || is_enpassant(m);
return (!square_is_empty(to_sq(m)) && !is_castle(m)) || is_enpassant(m);
}
inline PieceType Position::captured_piece_type() const {

View File

@ -49,8 +49,9 @@ namespace Search {
using std::string;
using std::cout;
using std::endl;
using std::count;
using std::find;
using namespace Search;
using namespace std;
namespace {
@ -140,6 +141,9 @@ namespace {
// better than the second best move.
const Value EasyMoveMargin = Value(0x150);
// This is the minimum interval in msec between two check_time() calls
const int TimerResolution = 5;
/// Namespace variables
@ -198,19 +202,19 @@ namespace {
FORCE_INLINE bool is_dangerous(const Position& pos, Move m, bool captureOrPromotion) {
// Test for a pawn pushed to 7th or a passed pawn move
if (type_of(pos.piece_on(move_from(m))) == PAWN)
if (type_of(pos.piece_on(from_sq(m))) == PAWN)
{
Color c = pos.side_to_move();
if ( relative_rank(c, move_to(m)) == RANK_7
|| pos.pawn_is_passed(c, move_to(m)))
if ( relative_rank(c, to_sq(m)) == RANK_7
|| pos.pawn_is_passed(c, to_sq(m)))
return true;
}
// Test for a capture that triggers a pawn endgame
if ( captureOrPromotion
&& type_of(pos.piece_on(move_to(m))) != PAWN
&& type_of(pos.piece_on(to_sq(m))) != PAWN
&& ( pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK)
- PieceValueMidgame[pos.piece_on(move_to(m))] == VALUE_ZERO)
- PieceValueMidgame[pos.piece_on(to_sq(m))] == VALUE_ZERO)
&& !is_special(m))
return true;
@ -291,22 +295,17 @@ void Search::think() {
// Populate RootMoves with all the legal moves (default) or, if a SearchMoves
// is given, with the subset of legal moves to search.
for (MoveList<MV_LEGAL> ml(pos); !ml.end(); ++ml)
if ( SearchMoves.empty()
|| count(SearchMoves.begin(), SearchMoves.end(), ml.move()))
if (SearchMoves.empty() || count(SearchMoves.begin(), SearchMoves.end(), ml.move()))
RootMoves.push_back(RootMove(ml.move()));
if (Options["OwnBook"])
{
if (book.name() != (string)Options["Book File"])
book.open(Options["Book File"]);
Move bookMove = book.probe(pos, Options["Book File"], Options["Best Book Move"]);
Move bookMove = book.probe(pos, Options["Best Book Move"]);
if ( bookMove != MOVE_NONE
&& count(RootMoves.begin(), RootMoves.end(), bookMove))
if (bookMove && count(RootMoves.begin(), RootMoves.end(), bookMove))
{
std::swap(RootMoves[0], *find(RootMoves.begin(), RootMoves.end(), bookMove));
goto finish;
goto finalize;
}
}
@ -349,8 +348,8 @@ void Search::think() {
// Set best timer interval to avoid lagging under time pressure. Timer is
// used to check for remaining available thinking time.
if (TimeMgr.available_time())
Threads.set_timer(std::min(100, std::max(TimeMgr.available_time() / 8, 20)));
if (Limits.use_time_management())
Threads.set_timer(std::min(100, std::max(TimeMgr.available_time() / 16, TimerResolution)));
else
Threads.set_timer(100);
@ -376,7 +375,7 @@ void Search::think() {
pos.undo_move(RootMoves[0].pv[0]);
}
finish:
finalize:
// When we reach max depth we arrive here even without a StopRequest, but if
// we are pondering or in infinite search, we shouldn't print the best move
@ -519,7 +518,7 @@ namespace {
bestMoveNeverChanged = false;
// Do we have time for the next iteration? Can we stop searching now?
if (!Signals.stop && !Signals.stopOnPonderhit && Limits.useTimeManagement())
if (!Signals.stop && !Signals.stopOnPonderhit && Limits.use_time_management())
{
bool stop = false; // Local variable, not the volatile Signals.stop
@ -707,7 +706,7 @@ namespace {
&& pos.captured_piece_type() == NO_PIECE_TYPE
&& !is_special(move))
{
Square to = move_to(move);
Square to = to_sq(move);
H.update_gain(pos.piece_on(to), to, -(ss-1)->eval - ss->eval);
}
@ -871,7 +870,8 @@ split_point_start: // At split points actual search starts from here
// Loop through all pseudo-legal moves until no moves remain or a beta cutoff occurs
while ( bestValue < beta
&& (move = mp.next_move()) != MOVE_NONE
&& !thread.cutoff_occurred())
&& !thread.cutoff_occurred()
&& !Signals.stop)
{
assert(is_ok(move));
@ -972,7 +972,7 @@ split_point_start: // At split points actual search starts from here
// but fixing this made program slightly weaker.
Depth predictedDepth = newDepth - reduction<PvNode>(depth, moveCount);
futilityValue = futilityBase + futility_margin(predictedDepth, moveCount)
+ H.gain(pos.piece_on(move_from(move)), move_to(move));
+ H.gain(pos.piece_on(from_sq(move)), to_sq(move));
if (futilityValue < beta)
{
@ -1156,13 +1156,13 @@ split_point_start: // At split points actual search starts from here
// Increase history value of the cut-off move
Value bonus = Value(int(depth) * int(depth));
H.add(pos.piece_on(move_from(move)), move_to(move), bonus);
H.add(pos.piece_on(from_sq(move)), to_sq(move), bonus);
// Decrease history of all the other played non-capture moves
for (int i = 0; i < playedMoveCount - 1; i++)
{
Move m = movesSearched[i];
H.add(pos.piece_on(move_from(m)), move_to(m), -bonus);
H.add(pos.piece_on(from_sq(m)), to_sq(m), -bonus);
}
}
}
@ -1268,7 +1268,7 @@ split_point_start: // At split points actual search starts from here
// to search the moves. Because the depth is <= 0 here, only captures,
// queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will
// be generated.
MovePicker mp(pos, ttMove, depth, H, move_to((ss-1)->currentMove));
MovePicker mp(pos, ttMove, depth, H, to_sq((ss-1)->currentMove));
CheckInfo ci(pos);
// Loop through the moves until no moves remain or a beta cutoff occurs
@ -1289,7 +1289,7 @@ split_point_start: // At split points actual search starts from here
&& !pos.is_passed_pawn_push(move))
{
futilityValue = futilityBase
+ PieceValueEndgame[pos.piece_on(move_to(move))]
+ PieceValueEndgame[pos.piece_on(to_sq(move))]
+ (is_enpassant(move) ? PawnValueEndgame : VALUE_ZERO);
if (futilityValue < beta)
@ -1393,8 +1393,8 @@ split_point_start: // At split points actual search starts from here
Color them;
Value futilityValue, bv = *bestValue;
from = move_from(move);
to = move_to(move);
from = from_sq(move);
to = to_sq(move);
them = flip(pos.side_to_move());
ksq = pos.king_square(them);
kingAtt = pos.attacks_from<KING>(ksq);
@ -1454,14 +1454,14 @@ split_point_start: // At split points actual search starts from here
assert(is_ok(m2));
// Case 1: The moving piece is the same in both moves
f2 = move_from(m2);
t1 = move_to(m1);
f2 = from_sq(m2);
t1 = to_sq(m1);
if (f2 == t1)
return true;
// Case 2: The destination square for m2 was vacated by m1
t2 = move_to(m2);
f1 = move_from(m1);
t2 = to_sq(m2);
f1 = from_sq(m1);
if (t2 == f1)
return true;
@ -1534,10 +1534,10 @@ split_point_start: // At split points actual search starts from here
Square mfrom, mto, tfrom, tto;
mfrom = move_from(m);
mto = move_to(m);
tfrom = move_from(threat);
tto = move_to(threat);
mfrom = from_sq(m);
mto = to_sq(m);
tfrom = from_sq(threat);
tto = to_sq(threat);
// Case 1: Don't prune moves which move the threatened piece
if (mfrom == tto)
@ -1963,11 +1963,11 @@ void Thread::idle_loop(SplitPoint* sp) {
}
/// do_timer_event() is called by the timer thread when the timer triggers. It
/// is used to print debug info and, more important, to detect when we are out of
/// check_time() is called by the timer thread when the timer triggers. It is
/// used to print debug info and, more important, to detect when we are out of
/// available time and so stop the search.
void do_timer_event() {
void check_time() {
static int lastInfoTime;
int e = elapsed_time();
@ -1985,10 +1985,10 @@ void do_timer_event() {
&& !Signals.failedLowAtRoot
&& e > TimeMgr.available_time();
bool noMoreTime = e > TimeMgr.maximum_time()
bool noMoreTime = e > TimeMgr.maximum_time() - 2 * TimerResolution
|| stillAtFirstMove;
if ( (Limits.useTimeManagement() && noMoreTime)
if ( (Limits.use_time_management() && noMoreTime)
|| (Limits.maxTime && e >= Limits.maxTime)
/* missing nodes limit */ ) // FIXME
Signals.stop = true;

View File

@ -55,7 +55,7 @@ struct Stack {
struct LimitsType {
LimitsType() { memset(this, 0, sizeof(LimitsType)); }
bool useTimeManagement() const { return !(maxTime | maxDepth | maxNodes | infinite); }
bool use_time_management() const { return !(maxTime | maxDepth | maxNodes | infinite); }
int time, increment, movesToGo, maxTime, maxDepth, maxNodes, infinite, ponder;
};

View File

@ -172,7 +172,7 @@ void ThreadsManager::init() {
for (int i = 0; i <= MAX_THREADS; i++)
{
threads[i].is_searching = false;
threads[i].do_sleep = true;
threads[i].do_sleep = (i != 0); // Avoid a race with start_thinking()
threads[i].threadID = i;
#if defined(_MSC_VER)
@ -202,7 +202,7 @@ void ThreadsManager::exit() {
// Wait for thread termination
#if defined(_MSC_VER)
WaitForSingleObject(threads[i].handle, 0);
WaitForSingleObject(threads[i].handle, INFINITE);
CloseHandle(threads[i].handle);
#else
pthread_join(threads[i].handle, NULL);
@ -367,7 +367,7 @@ template Value ThreadsManager::split<true>(Position&, Stack*, Value, Value, Valu
// Thread::timer_loop() is where the timer thread waits maxPly milliseconds and
// then calls do_timer_event(). If maxPly is 0 thread sleeps until is woken up.
extern void do_timer_event();
extern void check_time();
void Thread::timer_loop() {
@ -376,7 +376,7 @@ void Thread::timer_loop() {
lock_grab(&sleepLock);
timed_wait(&sleepCond, &sleepLock, maxPly ? maxPly : INT_MAX);
lock_release(&sleepLock);
do_timer_event();
check_time();
}
}
@ -452,7 +452,8 @@ void ThreadsManager::start_thinking(const Position& pos, const LimitsType& limit
cond_signal(&main.sleepCond); // Wake up main thread and start searching
if (!asyncMode)
cond_wait(&sleepCond, &main.sleepLock);
while (!main.do_sleep)
cond_wait(&sleepCond, &main.sleepLock);
lock_release(&main.sleepLock);
}

View File

@ -42,7 +42,6 @@
#include <climits>
#include <cstdlib>
#include <ctype.h>
#if defined(_MSC_VER)
@ -433,11 +432,11 @@ inline Square pawn_push(Color c) {
return c == WHITE ? DELTA_N : DELTA_S;
}
inline Square move_from(Move m) {
inline Square from_sq(Move m) {
return Square((m >> 6) & 0x3F);
}
inline Square move_to(Move m) {
inline Square to_sq(Move m) {
return Square(m & 0x3F);
}
@ -465,20 +464,20 @@ inline Move make_move(Square from, Square to) {
return Move(to | (from << 6));
}
inline Move make_promotion_move(Square from, Square to, PieceType promotion) {
return Move(to | (from << 6) | (1 << 14) | ((promotion - 2) << 12)) ;
inline Move make_promotion(Square from, Square to, PieceType pt) {
return Move(to | (from << 6) | (1 << 14) | ((pt - 2) << 12)) ;
}
inline Move make_enpassant_move(Square from, Square to) {
inline Move make_enpassant(Square from, Square to) {
return Move(to | (from << 6) | (2 << 14));
}
inline Move make_castle_move(Square from, Square to) {
inline Move make_castle(Square from, Square to) {
return Move(to | (from << 6) | (3 << 14));
}
inline bool is_ok(Move m) {
return move_from(m) != move_to(m); // Catches also MOVE_NULL and MOVE_NONE
return from_sq(m) != to_sq(m); // Catches also MOVE_NULL and MOVE_NONE
}
#include <string>

View File

@ -19,12 +19,14 @@
#include <algorithm>
#include <sstream>
#include <ctype.h>
#include "misc.h"
#include "thread.h"
#include "ucioption.h"
using std::string;
using std::lexicographical_compare;
OptionsMap Options; // Global object
@ -33,7 +35,7 @@ OptionsMap Options; // Global object
static bool ci_less(char c1, char c2) { return tolower(c1) < tolower(c2); }
bool CaseInsensitiveLess::operator() (const string& s1, const string& s2) const {
return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), ci_less);
return lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), ci_less);
}

View File

@ -174,7 +174,7 @@
<string name="about_info">\
<b>Information</b>\n\
<i>DroidFish</i> ist eine Android-Version von <i>Stockfish 2.2</i>, \
<i>DroidFish</i> ist eine Android-Version von <i>Stockfish 2.2.1</i>, \
das zu den spielstärksten Schachprogrammen der Welt zählt. \
Die Android-Version erreicht auf einem 1GHz-Snapdragon-Prozessor oft eine Rechentiefe von 15 oder mehr Halbzügen.\n\
\n\

View File

@ -174,7 +174,7 @@
<string name="about_info">\
<b>About</b>\n\
<i>DroidFish</i> es un derivado Android del famoso motor de ajedrez <i>stockfish 2.2</i> . \
<i>DroidFish</i> es un derivado Android del famoso motor de ajedrez <i>stockfish 2.2.1</i> . \
<i>Stockfish</i> es uno de los motores de ajedrez más fuertes del mundo. \
En su versión Android, a menudo profundiza 15 ply e incluso más, con un procesador Snapdragon a 1GHz.\n\
\n\

View File

@ -174,7 +174,7 @@
<string name="about_info">\
<b>About</b>\n\
<i>DroidFish</i> is an Android port of the famous <i>stockfish 2.2</i> chess engine. \
<i>DroidFish</i> is an Android port of the famous <i>stockfish 2.2.1</i> chess engine. \
<i>Stockfish</i> is one of the strongest chess engines in the world. \
The Android version can often search 15 ply or deeper on a 1GHz Snapdragon CPU.\n\
\n\