mirror of
https://github.com/HChaZZY/Stockfish.git
synced 2025-12-15 22:56:25 +08:00
Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67ac358ef2 | ||
|
|
341f42be8c | ||
|
|
72ab2cd3e9 | ||
|
|
92b625d04f | ||
|
|
2b32571de8 | ||
|
|
36437f14e8 | ||
|
|
08f3aac97c | ||
|
|
48b0d41220 | ||
|
|
5d79af9e0d | ||
|
|
a87ea9846d | ||
|
|
063e2441b1 | ||
|
|
b45936a8c7 | ||
|
|
d39ddb9077 | ||
|
|
bbb2462576 | ||
|
|
d9e3be4790 | ||
|
|
36c0ab3a50 | ||
|
|
ad4eac376f | ||
|
|
657286b0e5 | ||
|
|
3a4d6e2034 | ||
|
|
b1e79fed99 | ||
|
|
190f88e532 | ||
|
|
8acb1d7e4d | ||
|
|
46c0bdb74f | ||
|
|
8225fdd5bb | ||
|
|
e3c02d231a | ||
|
|
9847adf19f | ||
|
|
630fda2e2c | ||
|
|
8bec65029d | ||
|
|
b5685fc564 | ||
|
|
d2c2af9e1c | ||
|
|
3e0753bef3 | ||
|
|
c7843f2f79 | ||
|
|
9005ea6339 | ||
|
|
6d117e4a23 | ||
|
|
b8ab5d533b | ||
|
|
bbd3e30b4e | ||
|
|
e41602b721 | ||
|
|
48c95706c8 | ||
|
|
2f760cdf8d | ||
|
|
b58ecb85c7 | ||
|
|
b4a04d8038 | ||
|
|
c1b60269a2 | ||
|
|
e1ed67aacb | ||
|
|
5b1316f7bb | ||
|
|
bafb9f1a25 | ||
|
|
738bf66a2d | ||
|
|
3d0b60b065 | ||
|
|
bdb1bfecfb | ||
|
|
f1591447cf | ||
|
|
d63ff85a43 | ||
|
|
76024ac40e | ||
|
|
6c9a64124a | ||
|
|
f90f810ac4 | ||
|
|
ce5d9eb19d | ||
|
|
628f844c11 | ||
|
|
c729e4e1ab | ||
|
|
0228ff9ca0 | ||
|
|
e7d3a006cd | ||
|
|
3376c68f4b | ||
|
|
1b0888708d | ||
|
|
229274546f | ||
|
|
3e40bd0648 | ||
|
|
595c7d75a2 | ||
|
|
5603e25a7f | ||
|
|
20c2a31464 | ||
|
|
d3c4618b3a | ||
|
|
b98bcf858b | ||
|
|
3b1e64ab72 | ||
|
|
72ecd9e20d | ||
|
|
25286e9932 | ||
|
|
4f7ec4128f | ||
|
|
1e4472b651 | ||
|
|
da579e46b7 | ||
|
|
f83b899f39 | ||
|
|
a75aa6035b | ||
|
|
436fa5c8fa | ||
|
|
8df816f869 | ||
|
|
9c428afb6d | ||
|
|
27619830d4 | ||
|
|
78eecbf6d7 | ||
|
|
980124c609 | ||
|
|
5f7d37273c | ||
|
|
be4ee0729d | ||
|
|
9fbe9af0a0 | ||
|
|
1d15b38cd8 | ||
|
|
5c81602d14 | ||
|
|
a88e762b4e | ||
|
|
2155fb7825 | ||
|
|
a03b8074c8 | ||
|
|
afadc33fb4 | ||
|
|
92ca97d121 | ||
|
|
da91fab8cb | ||
|
|
6176357ac1 | ||
|
|
46bb6c6dc3 | ||
|
|
5c703b7526 | ||
|
|
412d68fe4f | ||
|
|
9144e48eb6 | ||
|
|
aabd526f7c | ||
|
|
fdb2242d34 | ||
|
|
991ab2bea8 |
28
Readme.txt
28
Readme.txt
@@ -45,7 +45,6 @@ PolyGlot documentation. The book file can be selected by setting the
|
||||
UCI parameter "Book File".
|
||||
|
||||
|
||||
|
||||
4. Compiling it yourself
|
||||
------------------------
|
||||
|
||||
@@ -54,27 +53,18 @@ Stockfish directly from the source code with the included Makefile.
|
||||
The exception is computer with big-endian CPUs, like PowerPC
|
||||
Macintoshes. Some of the bitboard routines in the current version of
|
||||
Stockfish are endianness-sensitive, and won't work on a big-endian CPU.
|
||||
Ensuring that the line with #define USE_32BIT_ATTACKS" near the top
|
||||
of bitboard.h is commented out should solve this problem.
|
||||
Commenting out the line with "#define USE_32BIT_ATTACKS" near the
|
||||
|
||||
There is also a problem with compiling Stockfish on certain 64-bit
|
||||
systems, regardless of the endianness. If Stockfish segfaults
|
||||
immediately after startup, try to comment out the line with
|
||||
"#define USE_FOLDED_BITSCAN" near the beginning of bitboard.h and
|
||||
recompile.
|
||||
Stockfish has POPCNT instruction runtime detection and support. This can
|
||||
give an extra speed on Core i7 or similar systems. To enable this feature
|
||||
(disabled by default) simply uncomment #define USE_POPCNT in bitcount.h
|
||||
before to compile.
|
||||
|
||||
Finally, even if Stockfish does work without any changes on your
|
||||
computer, it might be possible to improve the performance by changing
|
||||
some of the #define directives in bitboard.h. The default settings
|
||||
are optimized for 64-bit CPUs. On 32-bit CPUs, it is probably better
|
||||
to switch on USE_32BIT_ATTACKS, and to use BITCOUNT_SWAR_32 instead of
|
||||
BITCOUNT_SWAR_64. For computers with very little memory (like
|
||||
handheld devices), it is possible to conserve memory by defining
|
||||
USE_COMPACT_ROOK_ATTACKS.
|
||||
On 64 bit Unix-like systems the 'bsfq' assembly instruction will be used
|
||||
for bit counting. Detection is automatic at compile time, but in case you
|
||||
experience compile problems you can comment out #define USE_BSFQ line in types.h
|
||||
|
||||
|
||||
6. Terms of use
|
||||
5. Terms of use
|
||||
---------------
|
||||
|
||||
Stockfish is free, and distributed under the GNU General Public License
|
||||
@@ -93,7 +83,7 @@ For full details, read the copy of the GPL found in the file named
|
||||
Copying.txt.
|
||||
|
||||
|
||||
7. Feedback
|
||||
6. Feedback
|
||||
-----------
|
||||
|
||||
The author's e-mail address is mcostalba@gmail.com
|
||||
|
||||
26
src/Makefile
26
src/Makefile
@@ -24,7 +24,7 @@
|
||||
|
||||
EXE = stockfish
|
||||
|
||||
OBJS = bitboard.o pawns.o material.o endgame.o evaluate.o main.o \
|
||||
OBJS = application.o bitboard.o pawns.o material.o endgame.o evaluate.o main.o \
|
||||
misc.o move.o movegen.o history.o movepick.o search.o piece.o \
|
||||
position.o direction.o tt.o value.o uci.o ucioption.o \
|
||||
mersenne.o book.o bitbase.o san.o benchmark.o
|
||||
@@ -44,9 +44,8 @@ clean:
|
||||
### Compiler:
|
||||
###
|
||||
|
||||
# CXX = g++
|
||||
# CXX = g++-4.2
|
||||
CXX = icpc
|
||||
CXX = g++
|
||||
# CXX = icpc
|
||||
|
||||
|
||||
###
|
||||
@@ -66,24 +65,25 @@ include .depend
|
||||
### Compiler and linker switches
|
||||
###
|
||||
|
||||
# Enable/disable debugging:
|
||||
# Enable/disable debugging, disabled by default
|
||||
|
||||
CXXFLAGS += -DNDEBUG
|
||||
|
||||
|
||||
# Compile with full warnings, and symbol names
|
||||
# Compile with full warnings, and symbol names stripped, you can use
|
||||
# -g instead of -s to compile symbol's table in, useful for debugging.
|
||||
|
||||
CXXFLAGS += -Wall -g
|
||||
CXXFLAGS += -Wall -s
|
||||
|
||||
|
||||
# General optimization flags. Note that -O2 might be faster than -O3 on some
|
||||
# General optimization flags. Note that -O2 might be faster than -O3 on some
|
||||
# systems; this requires testing.
|
||||
|
||||
CXXFLAGS += -O3 -fno-exceptions -fomit-frame-pointer -fno-rtti -fno-strict-aliasing
|
||||
CXXFLAGS += -O3 -fno-exceptions -fno-rtti -fno-strict-aliasing
|
||||
|
||||
# Disable most annoying warnings for the Intel C++ compiler
|
||||
|
||||
CXXFLAGS += -wd383,869,981
|
||||
# CXXFLAGS += -wd383,869,981
|
||||
|
||||
|
||||
# Compiler optimization flags for the Intel C++ compiler in Mac OS X:
|
||||
@@ -91,15 +91,15 @@ CXXFLAGS += -wd383,869,981
|
||||
# CXXFLAGS += -mdynamic-no-pic -no-prec-div -ipo -static -xP
|
||||
|
||||
|
||||
# Profiler guided optimization with the Intel C++ compiler. To use it, first
|
||||
# Profiler guided optimization with the Intel C++ compiler v11. To use it, first
|
||||
# create the directory ./profdata if it does not already exist, and delete its
|
||||
# contents if it does exist. Then compile with -prof_gen, and run the
|
||||
# resulting binary for a while (for instance, do ./stockfish bench 128 1, and
|
||||
# wait 15 minutes for the benchmark to complete). Then do a 'make clean', and
|
||||
# recompile with -prof_use.
|
||||
|
||||
# CXXFLAGS += -prof_gen -prof_dir profdata
|
||||
# CXXFLAGS += -prof_use -prof_dir ./profdata
|
||||
# CXXFLAGS += -prof-gen -prof-dir./profdata
|
||||
# CXXFLAGS += -prof-use -ipo -prof_dir./profdata
|
||||
|
||||
|
||||
# Profiler guided optimization with GCC. I've never been able to make this
|
||||
|
||||
80
src/application.cpp
Normal file
80
src/application.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
////
|
||||
//// Includes
|
||||
////
|
||||
|
||||
#include "bitboard.h"
|
||||
#include "direction.h"
|
||||
#include "endgame.h"
|
||||
#include "evaluate.h"
|
||||
#include "material.h"
|
||||
#include "mersenne.h"
|
||||
#include "misc.h"
|
||||
#include "movepick.h"
|
||||
#include "position.h"
|
||||
#include "search.h"
|
||||
#include "thread.h"
|
||||
#include "ucioption.h"
|
||||
|
||||
|
||||
/// Application class is in charge of initializing global resources
|
||||
/// at startup and cleanly releases them when program terminates.
|
||||
|
||||
Application::Application() {
|
||||
|
||||
init_mersenne();
|
||||
init_direction_table();
|
||||
init_bitboards();
|
||||
init_uci_options();
|
||||
Position::init_zobrist();
|
||||
Position::init_piece_square_tables();
|
||||
MovePicker::init_phase_table();
|
||||
init_eval(1);
|
||||
init_bitbases();
|
||||
init_threads();
|
||||
|
||||
// Make random number generation less deterministic, for book moves
|
||||
for (int i = abs(get_system_time() % 10000); i > 0; i--)
|
||||
genrand_int32();
|
||||
}
|
||||
|
||||
Application::~Application() {
|
||||
|
||||
stop_threads();
|
||||
quit_eval();
|
||||
}
|
||||
|
||||
void Application::initialize() {
|
||||
|
||||
instance();
|
||||
}
|
||||
|
||||
Application& Application::instance() {
|
||||
|
||||
static Application singleton;
|
||||
return singleton;
|
||||
}
|
||||
|
||||
void Application::exit_with_failure() {
|
||||
|
||||
exit(EXIT_FAILURE); // d'tor will be called automatically
|
||||
}
|
||||
46
src/application.h
Normal file
46
src/application.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(APPLICATION_H_INCLUDED)
|
||||
#define APPLICATION_H_INCLUDED
|
||||
|
||||
|
||||
/// Singleton class used to housekeep memory and global resources
|
||||
/// so to be sure we always leave in a clean state.
|
||||
|
||||
class Application {
|
||||
|
||||
Application();
|
||||
Application(const Application&);
|
||||
|
||||
public:
|
||||
static void initialize();
|
||||
static void exit_with_failure();
|
||||
|
||||
~Application();
|
||||
|
||||
private:
|
||||
static Application& instance();
|
||||
|
||||
void init();
|
||||
void deallocateAll();
|
||||
};
|
||||
|
||||
#endif // !defined(APPLICATION_H_INCLUDED)
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -30,12 +30,13 @@
|
||||
#include "thread.h"
|
||||
#include "ucioption.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
////
|
||||
//// Variables
|
||||
////
|
||||
|
||||
const std::string BenchmarkPositions[] = {
|
||||
const string BenchmarkPositions[] = {
|
||||
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
|
||||
"r4rk1/1b2qppp/p1n1p3/1p6/1b1PN3/3BRN2/PP3PPP/R2Q2K1 b - - 7 16",
|
||||
"4r1k1/ppq3pp/3b4/2pP4/2Q1p3/4B1P1/PP5P/R5K1 b - - 0 20",
|
||||
@@ -67,27 +68,26 @@ const std::string BenchmarkPositions[] = {
|
||||
/// format (default are the BenchmarkPositions defined above).
|
||||
/// The analysis is written to a file named bench.txt.
|
||||
|
||||
void benchmark(const std::string& commandLine) {
|
||||
void benchmark(const string& commandLine) {
|
||||
|
||||
std::istringstream csVal(commandLine);
|
||||
std::istringstream csStr(commandLine);
|
||||
std::string ttSize, threads, fileName, limitType;
|
||||
istringstream csVal(commandLine);
|
||||
istringstream csStr(commandLine);
|
||||
string ttSize, threads, fileName, limitType, timFile;
|
||||
int val, secsPerPos, maxDepth, maxNodes;
|
||||
|
||||
csStr >> ttSize;
|
||||
csVal >> val;
|
||||
if (val < 4 || val > 1024)
|
||||
{
|
||||
std::cerr << "The hash table size must be between 4 and 1024" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
cerr << "The hash table size must be between 4 and 1024" << endl;
|
||||
Application::exit_with_failure();
|
||||
}
|
||||
csStr >> threads;
|
||||
csVal >> val;
|
||||
if (val < 1 || val > THREAD_MAX)
|
||||
{
|
||||
std::cerr << "The number of threads must be between 1 and " << THREAD_MAX
|
||||
<< std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
cerr << "The number of threads must be between 1 and " << THREAD_MAX << endl;
|
||||
Application::exit_with_failure();
|
||||
}
|
||||
set_option_value("Hash", ttSize);
|
||||
set_option_value("Threads", threads);
|
||||
@@ -98,6 +98,7 @@ void benchmark(const std::string& commandLine) {
|
||||
csVal >> val;
|
||||
csVal >> fileName;
|
||||
csVal >> limitType;
|
||||
csVal >> timFile;
|
||||
|
||||
secsPerPos = maxDepth = maxNodes = 0;
|
||||
|
||||
@@ -108,44 +109,71 @@ void benchmark(const std::string& commandLine) {
|
||||
else
|
||||
maxNodes = val;
|
||||
|
||||
std::vector<std::string> positions;
|
||||
vector<string> positions;
|
||||
|
||||
if (fileName != "default")
|
||||
{
|
||||
std::ifstream fenFile(fileName.c_str());
|
||||
ifstream fenFile(fileName.c_str());
|
||||
if (!fenFile.is_open())
|
||||
{
|
||||
std::cerr << "Unable to open positions file " << fileName
|
||||
<< std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
cerr << "Unable to open positions file " << fileName << endl;
|
||||
Application::exit_with_failure();
|
||||
}
|
||||
std::string pos;
|
||||
string pos;
|
||||
while (fenFile.good())
|
||||
{
|
||||
std::getline(fenFile, pos);
|
||||
getline(fenFile, pos);
|
||||
if (!pos.empty())
|
||||
positions.push_back(pos);
|
||||
}
|
||||
fenFile.close();
|
||||
} else
|
||||
for (int i = 0; i < 16; i++)
|
||||
positions.push_back(std::string(BenchmarkPositions[i]));
|
||||
positions.push_back(string(BenchmarkPositions[i]));
|
||||
|
||||
int startTime = get_system_time();
|
||||
std::vector<std::string>::iterator it;
|
||||
ofstream timingFile;
|
||||
if (!timFile.empty())
|
||||
{
|
||||
timingFile.open(timFile.c_str(), ios::out | ios::app);
|
||||
if (!timingFile.is_open())
|
||||
{
|
||||
cerr << "Unable to open timing file " << timFile << endl;
|
||||
Application::exit_with_failure();
|
||||
}
|
||||
}
|
||||
|
||||
vector<string>::iterator it;
|
||||
int cnt = 1;
|
||||
int64_t totalNodes = 0;
|
||||
int startTime = get_system_time();
|
||||
|
||||
for (it = positions.begin(); it != positions.end(); ++it, ++cnt)
|
||||
{
|
||||
Move moves[1] = {MOVE_NONE};
|
||||
int dummy[2] = {0, 0};
|
||||
Position pos(*it);
|
||||
std::cout << "\nProcessing position " << cnt << '/' << positions.size() << std::endl << std::endl;
|
||||
think(pos, true, false, 0, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves);
|
||||
cerr << "\nBench position: " << cnt << '/' << positions.size() << endl << endl;
|
||||
if (!think(pos, true, false, 0, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves))
|
||||
break;
|
||||
totalNodes += nodes_searched();
|
||||
}
|
||||
std::cout << "\nProcessing time (ms) " << get_system_time() - startTime << std::endl
|
||||
<< "Nodes searched " << totalNodes << std::endl
|
||||
<< "Press any key to exit" << std::endl;
|
||||
std::cin >> fileName;
|
||||
|
||||
cnt = get_system_time() - startTime;
|
||||
cerr << "==============================="
|
||||
<< "\nTotal time (ms) : " << cnt
|
||||
<< "\nNodes searched : " << totalNodes
|
||||
<< "\nNodes/second : " << (int)(totalNodes/(cnt/1000.0)) << endl << endl;
|
||||
|
||||
if (!timFile.empty())
|
||||
{
|
||||
timingFile << cnt << endl << endl;
|
||||
timingFile.close();
|
||||
}
|
||||
|
||||
// Under MS Visual C++ debug window always unconditionally closes
|
||||
// when program exits, this is bad because we want to read results before.
|
||||
#if (defined(WINDOWS) || defined(WIN32) || defined(WIN64))
|
||||
cerr << "Press any key to exit" << endl;
|
||||
cin >> fileName;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
412
src/bitboard.cpp
412
src/bitboard.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -22,137 +22,14 @@
|
||||
//// Includes
|
||||
////
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#ifdef _WIN64
|
||||
#pragma intrinsic(_BitScanForward64)
|
||||
#else
|
||||
#pragma intrinsic(_BitScanForward)
|
||||
#endif
|
||||
#define USING_INTRINSICS
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "bitboard.h"
|
||||
#include "bitcount.h"
|
||||
#include "direction.h"
|
||||
|
||||
|
||||
#if defined(USE_COMPACT_ROOK_ATTACKS)
|
||||
|
||||
Bitboard RankAttacks[8][64], FileAttacks[8][64];
|
||||
|
||||
#elif defined(USE_32BIT_ATTACKS)
|
||||
|
||||
const uint64_t RMult[64] = {
|
||||
0xd7445cdec88002c0ULL, 0xd0a505c1f2001722ULL, 0xe065d1c896002182ULL,
|
||||
0x9a8c41e75a000892ULL, 0x8900b10c89002aa8ULL, 0x9b28d1c1d60005a2ULL,
|
||||
0x15d6c88de002d9aULL, 0xb1dbfc802e8016a9ULL, 0x149a1042d9d60029ULL,
|
||||
0xb9c08050599e002fULL, 0x132208c3af300403ULL, 0xc1000ce2e9c50070ULL,
|
||||
0x9d9aa13c99020012ULL, 0xb6b078daf71e0046ULL, 0x9d880182fb6e002eULL,
|
||||
0x52889f467e850037ULL, 0xda6dc008d19a8480ULL, 0x468286034f902420ULL,
|
||||
0x7140ac09dc54c020ULL, 0xd76ffffa39548808ULL, 0xea901c4141500808ULL,
|
||||
0xc91004093f953a02ULL, 0x2882afa8f6bb402ULL, 0xaebe335692442c01ULL,
|
||||
0xe904a22079fb91eULL, 0x13a514851055f606ULL, 0x76c782018c8fe632ULL,
|
||||
0x1dc012a9d116da06ULL, 0x3c9e0037264fffa6ULL, 0x2036002853c6e4a2ULL,
|
||||
0xe3fe08500afb47d4ULL, 0xf38af25c86b025c2ULL, 0xc0800e2182cf9a40ULL,
|
||||
0x72002480d1f60673ULL, 0x2500200bae6e9b53ULL, 0xc60018c1eefca252ULL,
|
||||
0x600590473e3608aULL, 0x46002c4ab3fe51b2ULL, 0xa200011486bcc8d2ULL,
|
||||
0xb680078095784c63ULL, 0x2742002639bf11aeULL, 0xc7d60021a5bdb142ULL,
|
||||
0xc8c04016bb83d820ULL, 0xbd520028123b4842ULL, 0x9d1600344ac2a832ULL,
|
||||
0x6a808005631c8a05ULL, 0x604600a148d5389aULL, 0xe2e40103d40dea65ULL,
|
||||
0x945b5a0087c62a81ULL, 0x12dc200cd82d28eULL, 0x2431c600b5f9ef76ULL,
|
||||
0xfb142a006a9b314aULL, 0x6870e00a1c97d62ULL, 0x2a9db2004a2689a2ULL,
|
||||
0xd3594600caf5d1a2ULL, 0xee0e4900439344a7ULL, 0x89c4d266ca25007aULL,
|
||||
0x3e0013a2743f97e3ULL, 0x180e31a0431378aULL, 0x3a9e465a4d42a512ULL,
|
||||
0x98d0a11a0c0d9cc2ULL, 0x8e711c1aba19b01eULL, 0x8dcdc836dd201142ULL,
|
||||
0x5ac08a4735370479ULL,
|
||||
};
|
||||
|
||||
const int RShift[64] = {
|
||||
20, 21, 21, 21, 21, 21, 21, 20, 21, 22, 22, 22, 22, 22, 22, 21,
|
||||
21, 22, 22, 22, 22, 22, 22, 21, 21, 22, 22, 22, 22, 22, 22, 21,
|
||||
21, 22, 22, 22, 22, 22, 22, 21, 21, 22, 22, 22, 22, 22, 22, 21,
|
||||
21, 22, 22, 22, 22, 22, 22, 21, 20, 21, 21, 21, 21, 21, 21, 20
|
||||
};
|
||||
|
||||
#else // if defined(USE_32BIT_ATTACKS)
|
||||
|
||||
const uint64_t RMult[64] = {
|
||||
0xa8002c000108020ULL, 0x4440200140003000ULL, 0x8080200010011880ULL,
|
||||
0x380180080141000ULL, 0x1a00060008211044ULL, 0x410001000a0c0008ULL,
|
||||
0x9500060004008100ULL, 0x100024284a20700ULL, 0x802140008000ULL,
|
||||
0x80c01002a00840ULL, 0x402004282011020ULL, 0x9862000820420050ULL,
|
||||
0x1001448011100ULL, 0x6432800200800400ULL, 0x40100010002000cULL,
|
||||
0x2800d0010c080ULL, 0x90c0008000803042ULL, 0x4010004000200041ULL,
|
||||
0x3010010200040ULL, 0xa40828028001000ULL, 0x123010008000430ULL,
|
||||
0x24008004020080ULL, 0x60040001104802ULL, 0x582200028400d1ULL,
|
||||
0x4000802080044000ULL, 0x408208200420308ULL, 0x610038080102000ULL,
|
||||
0x3601000900100020ULL, 0x80080040180ULL, 0xc2020080040080ULL,
|
||||
0x80084400100102ULL, 0x4022408200014401ULL, 0x40052040800082ULL,
|
||||
0xb08200280804000ULL, 0x8a80a008801000ULL, 0x4000480080801000ULL,
|
||||
0x911808800801401ULL, 0x822a003002001894ULL, 0x401068091400108aULL,
|
||||
0x4a10a00004cULL, 0x2000800640008024ULL, 0x1486408102020020ULL,
|
||||
0x100a000d50041ULL, 0x810050020b0020ULL, 0x204000800808004ULL,
|
||||
0x20048100a000cULL, 0x112000831020004ULL, 0x9000040810002ULL,
|
||||
0x440490200208200ULL, 0x8910401000200040ULL, 0x6404200050008480ULL,
|
||||
0x4b824a2010010100ULL, 0x4080801810c0080ULL, 0x400802a0080ULL,
|
||||
0x8224080110026400ULL, 0x40002c4104088200ULL, 0x1002100104a0282ULL,
|
||||
0x1208400811048021ULL, 0x3201014a40d02001ULL, 0x5100019200501ULL,
|
||||
0x101000208001005ULL, 0x2008450080702ULL, 0x1002080301d00cULL,
|
||||
0x410201ce5c030092ULL
|
||||
};
|
||||
|
||||
const int RShift[64] = {
|
||||
52, 53, 53, 53, 53, 53, 53, 52, 53, 54, 54, 54, 54, 54, 54, 53,
|
||||
53, 54, 54, 54, 54, 54, 54, 53, 53, 54, 54, 54, 54, 54, 54, 53,
|
||||
53, 54, 54, 54, 54, 54, 54, 53, 53, 54, 54, 54, 54, 54, 54, 53,
|
||||
53, 54, 54, 54, 54, 54, 54, 53, 52, 53, 53, 53, 53, 53, 53, 52
|
||||
};
|
||||
|
||||
#endif // defined(USE_32BIT_ATTACKS)
|
||||
|
||||
#if !defined(USE_COMPACT_ROOK_ATTACKS)
|
||||
Bitboard RMask[64];
|
||||
int RAttackIndex[64];
|
||||
Bitboard RAttacks[0x19000];
|
||||
#endif
|
||||
|
||||
#if defined(USE_32BIT_ATTACKS)
|
||||
|
||||
const uint64_t BMult[64] = {
|
||||
0x54142844c6a22981ULL, 0x710358a6ea25c19eULL, 0x704f746d63a4a8dcULL,
|
||||
0xbfed1a0b80f838c5ULL, 0x90561d5631e62110ULL, 0x2804260376e60944ULL,
|
||||
0x84a656409aa76871ULL, 0xf0267f64c28b6197ULL, 0x70764ebb762f0585ULL,
|
||||
0x92aa09e0cfe161deULL, 0x41ee1f6bb266f60eULL, 0xddcbf04f6039c444ULL,
|
||||
0x5a3fab7bac0d988aULL, 0xd3727877fa4eaa03ULL, 0xd988402d868ddaaeULL,
|
||||
0x812b291afa075c7cULL, 0x94faf987b685a932ULL, 0x3ed867d8470d08dbULL,
|
||||
0x92517660b8901de8ULL, 0x2d97e43e058814b4ULL, 0x880a10c220b25582ULL,
|
||||
0xc7c6520d1f1a0477ULL, 0xdbfc7fbcd7656aa6ULL, 0x78b1b9bfb1a2b84fULL,
|
||||
0x2f20037f112a0bc1ULL, 0x657171ea2269a916ULL, 0xc08302b07142210eULL,
|
||||
0x880a4403064080bULL, 0x3602420842208c00ULL, 0x852800dc7e0b6602ULL,
|
||||
0x595a3fbbaa0f03b2ULL, 0x9f01411558159d5eULL, 0x2b4a4a5f88b394f2ULL,
|
||||
0x4afcbffc292dd03aULL, 0x4a4094a3b3f10522ULL, 0xb06f00b491f30048ULL,
|
||||
0xd5b3820280d77004ULL, 0x8b2e01e7c8e57a75ULL, 0x2d342794e886c2e6ULL,
|
||||
0xc302c410cde21461ULL, 0x111f426f1379c274ULL, 0xe0569220abb31588ULL,
|
||||
0x5026d3064d453324ULL, 0xe2076040c343cd8aULL, 0x93efd1e1738021eeULL,
|
||||
0xb680804bed143132ULL, 0x44e361b21986944cULL, 0x44c60170ef5c598cULL,
|
||||
0xf4da475c195c9c94ULL, 0xa3afbb5f72060b1dULL, 0xbc75f410e41c4ffcULL,
|
||||
0xb51c099390520922ULL, 0x902c011f8f8ec368ULL, 0x950b56b3d6f5490aULL,
|
||||
0x3909e0635bf202d0ULL, 0x5744f90206ec10ccULL, 0xdc59fd76317abbc1ULL,
|
||||
0x881c7c67fcbfc4f6ULL, 0x47ca41e7e440d423ULL, 0xeb0c88112048d004ULL,
|
||||
0x51c60e04359aef1aULL, 0x1aa1fe0e957a5554ULL, 0xdd9448db4f5e3104ULL,
|
||||
0xdc01f6dca4bebbdcULL,
|
||||
};
|
||||
|
||||
const int BShift[64] = {
|
||||
26, 27, 27, 27, 27, 27, 27, 26, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 25, 25, 25, 25, 27, 27, 27, 27, 25, 23, 23, 25, 27, 27,
|
||||
27, 27, 25, 23, 23, 25, 27, 27, 27, 27, 25, 25, 25, 25, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 26, 27, 27, 27, 27, 27, 27, 26
|
||||
};
|
||||
|
||||
#else // if defined(USE_32BIT_ATTACKS)
|
||||
#if defined(IS_64BIT)
|
||||
|
||||
const uint64_t BMult[64] = {
|
||||
0x440049104032280ULL, 0x1021023c82008040ULL, 0x404040082000048ULL,
|
||||
@@ -179,6 +56,31 @@ const uint64_t BMult[64] = {
|
||||
0xa08520292120600ULL
|
||||
};
|
||||
|
||||
const uint64_t RMult[64] = {
|
||||
0xa8002c000108020ULL, 0x4440200140003000ULL, 0x8080200010011880ULL,
|
||||
0x380180080141000ULL, 0x1a00060008211044ULL, 0x410001000a0c0008ULL,
|
||||
0x9500060004008100ULL, 0x100024284a20700ULL, 0x802140008000ULL,
|
||||
0x80c01002a00840ULL, 0x402004282011020ULL, 0x9862000820420050ULL,
|
||||
0x1001448011100ULL, 0x6432800200800400ULL, 0x40100010002000cULL,
|
||||
0x2800d0010c080ULL, 0x90c0008000803042ULL, 0x4010004000200041ULL,
|
||||
0x3010010200040ULL, 0xa40828028001000ULL, 0x123010008000430ULL,
|
||||
0x24008004020080ULL, 0x60040001104802ULL, 0x582200028400d1ULL,
|
||||
0x4000802080044000ULL, 0x408208200420308ULL, 0x610038080102000ULL,
|
||||
0x3601000900100020ULL, 0x80080040180ULL, 0xc2020080040080ULL,
|
||||
0x80084400100102ULL, 0x4022408200014401ULL, 0x40052040800082ULL,
|
||||
0xb08200280804000ULL, 0x8a80a008801000ULL, 0x4000480080801000ULL,
|
||||
0x911808800801401ULL, 0x822a003002001894ULL, 0x401068091400108aULL,
|
||||
0x4a10a00004cULL, 0x2000800640008024ULL, 0x1486408102020020ULL,
|
||||
0x100a000d50041ULL, 0x810050020b0020ULL, 0x204000800808004ULL,
|
||||
0x20048100a000cULL, 0x112000831020004ULL, 0x9000040810002ULL,
|
||||
0x440490200208200ULL, 0x8910401000200040ULL, 0x6404200050008480ULL,
|
||||
0x4b824a2010010100ULL, 0x4080801810c0080ULL, 0x400802a0080ULL,
|
||||
0x8224080110026400ULL, 0x40002c4104088200ULL, 0x1002100104a0282ULL,
|
||||
0x1208400811048021ULL, 0x3201014a40d02001ULL, 0x5100019200501ULL,
|
||||
0x101000208001005ULL, 0x2008450080702ULL, 0x1002080301d00cULL,
|
||||
0x410201ce5c030092ULL
|
||||
};
|
||||
|
||||
const int BShift[64] = {
|
||||
58, 59, 59, 59, 59, 59, 59, 58, 59, 59, 59, 59, 59, 59, 59, 59,
|
||||
59, 59, 57, 57, 57, 57, 59, 59, 59, 59, 57, 55, 55, 57, 59, 59,
|
||||
@@ -186,7 +88,85 @@ const int BShift[64] = {
|
||||
59, 59, 59, 59, 59, 59, 59, 59, 58, 59, 59, 59, 59, 59, 59, 58
|
||||
};
|
||||
|
||||
#endif // defined(USE_32BIT_ATTACKS)
|
||||
const int RShift[64] = {
|
||||
52, 53, 53, 53, 53, 53, 53, 52, 53, 54, 54, 54, 54, 54, 54, 53,
|
||||
53, 54, 54, 54, 54, 54, 54, 53, 53, 54, 54, 54, 54, 54, 54, 53,
|
||||
53, 54, 54, 54, 54, 54, 54, 53, 53, 54, 54, 54, 54, 54, 54, 53,
|
||||
53, 54, 54, 54, 54, 54, 54, 53, 52, 53, 53, 53, 53, 53, 53, 52
|
||||
};
|
||||
|
||||
#else // if !defined(IS_64BIT)
|
||||
|
||||
const uint64_t BMult[64] = {
|
||||
0x54142844c6a22981ULL, 0x710358a6ea25c19eULL, 0x704f746d63a4a8dcULL,
|
||||
0xbfed1a0b80f838c5ULL, 0x90561d5631e62110ULL, 0x2804260376e60944ULL,
|
||||
0x84a656409aa76871ULL, 0xf0267f64c28b6197ULL, 0x70764ebb762f0585ULL,
|
||||
0x92aa09e0cfe161deULL, 0x41ee1f6bb266f60eULL, 0xddcbf04f6039c444ULL,
|
||||
0x5a3fab7bac0d988aULL, 0xd3727877fa4eaa03ULL, 0xd988402d868ddaaeULL,
|
||||
0x812b291afa075c7cULL, 0x94faf987b685a932ULL, 0x3ed867d8470d08dbULL,
|
||||
0x92517660b8901de8ULL, 0x2d97e43e058814b4ULL, 0x880a10c220b25582ULL,
|
||||
0xc7c6520d1f1a0477ULL, 0xdbfc7fbcd7656aa6ULL, 0x78b1b9bfb1a2b84fULL,
|
||||
0x2f20037f112a0bc1ULL, 0x657171ea2269a916ULL, 0xc08302b07142210eULL,
|
||||
0x880a4403064080bULL, 0x3602420842208c00ULL, 0x852800dc7e0b6602ULL,
|
||||
0x595a3fbbaa0f03b2ULL, 0x9f01411558159d5eULL, 0x2b4a4a5f88b394f2ULL,
|
||||
0x4afcbffc292dd03aULL, 0x4a4094a3b3f10522ULL, 0xb06f00b491f30048ULL,
|
||||
0xd5b3820280d77004ULL, 0x8b2e01e7c8e57a75ULL, 0x2d342794e886c2e6ULL,
|
||||
0xc302c410cde21461ULL, 0x111f426f1379c274ULL, 0xe0569220abb31588ULL,
|
||||
0x5026d3064d453324ULL, 0xe2076040c343cd8aULL, 0x93efd1e1738021eeULL,
|
||||
0xb680804bed143132ULL, 0x44e361b21986944cULL, 0x44c60170ef5c598cULL,
|
||||
0xf4da475c195c9c94ULL, 0xa3afbb5f72060b1dULL, 0xbc75f410e41c4ffcULL,
|
||||
0xb51c099390520922ULL, 0x902c011f8f8ec368ULL, 0x950b56b3d6f5490aULL,
|
||||
0x3909e0635bf202d0ULL, 0x5744f90206ec10ccULL, 0xdc59fd76317abbc1ULL,
|
||||
0x881c7c67fcbfc4f6ULL, 0x47ca41e7e440d423ULL, 0xeb0c88112048d004ULL,
|
||||
0x51c60e04359aef1aULL, 0x1aa1fe0e957a5554ULL, 0xdd9448db4f5e3104ULL,
|
||||
0xdc01f6dca4bebbdcULL,
|
||||
};
|
||||
|
||||
const uint64_t RMult[64] = {
|
||||
0xd7445cdec88002c0ULL, 0xd0a505c1f2001722ULL, 0xe065d1c896002182ULL,
|
||||
0x9a8c41e75a000892ULL, 0x8900b10c89002aa8ULL, 0x9b28d1c1d60005a2ULL,
|
||||
0x15d6c88de002d9aULL, 0xb1dbfc802e8016a9ULL, 0x149a1042d9d60029ULL,
|
||||
0xb9c08050599e002fULL, 0x132208c3af300403ULL, 0xc1000ce2e9c50070ULL,
|
||||
0x9d9aa13c99020012ULL, 0xb6b078daf71e0046ULL, 0x9d880182fb6e002eULL,
|
||||
0x52889f467e850037ULL, 0xda6dc008d19a8480ULL, 0x468286034f902420ULL,
|
||||
0x7140ac09dc54c020ULL, 0xd76ffffa39548808ULL, 0xea901c4141500808ULL,
|
||||
0xc91004093f953a02ULL, 0x2882afa8f6bb402ULL, 0xaebe335692442c01ULL,
|
||||
0xe904a22079fb91eULL, 0x13a514851055f606ULL, 0x76c782018c8fe632ULL,
|
||||
0x1dc012a9d116da06ULL, 0x3c9e0037264fffa6ULL, 0x2036002853c6e4a2ULL,
|
||||
0xe3fe08500afb47d4ULL, 0xf38af25c86b025c2ULL, 0xc0800e2182cf9a40ULL,
|
||||
0x72002480d1f60673ULL, 0x2500200bae6e9b53ULL, 0xc60018c1eefca252ULL,
|
||||
0x600590473e3608aULL, 0x46002c4ab3fe51b2ULL, 0xa200011486bcc8d2ULL,
|
||||
0xb680078095784c63ULL, 0x2742002639bf11aeULL, 0xc7d60021a5bdb142ULL,
|
||||
0xc8c04016bb83d820ULL, 0xbd520028123b4842ULL, 0x9d1600344ac2a832ULL,
|
||||
0x6a808005631c8a05ULL, 0x604600a148d5389aULL, 0xe2e40103d40dea65ULL,
|
||||
0x945b5a0087c62a81ULL, 0x12dc200cd82d28eULL, 0x2431c600b5f9ef76ULL,
|
||||
0xfb142a006a9b314aULL, 0x6870e00a1c97d62ULL, 0x2a9db2004a2689a2ULL,
|
||||
0xd3594600caf5d1a2ULL, 0xee0e4900439344a7ULL, 0x89c4d266ca25007aULL,
|
||||
0x3e0013a2743f97e3ULL, 0x180e31a0431378aULL, 0x3a9e465a4d42a512ULL,
|
||||
0x98d0a11a0c0d9cc2ULL, 0x8e711c1aba19b01eULL, 0x8dcdc836dd201142ULL,
|
||||
0x5ac08a4735370479ULL,
|
||||
};
|
||||
|
||||
const int BShift[64] = {
|
||||
26, 27, 27, 27, 27, 27, 27, 26, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 25, 25, 25, 25, 27, 27, 27, 27, 25, 23, 23, 25, 27, 27,
|
||||
27, 27, 25, 23, 23, 25, 27, 27, 27, 27, 25, 25, 25, 25, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 26, 27, 27, 27, 27, 27, 27, 26
|
||||
};
|
||||
|
||||
const int RShift[64] = {
|
||||
20, 21, 21, 21, 21, 21, 21, 20, 21, 22, 22, 22, 22, 22, 22, 21,
|
||||
21, 22, 22, 22, 22, 22, 22, 21, 21, 22, 22, 22, 22, 22, 22, 21,
|
||||
21, 22, 22, 22, 22, 22, 22, 21, 21, 22, 22, 22, 22, 22, 22, 21,
|
||||
21, 22, 22, 22, 22, 22, 22, 21, 20, 21, 21, 21, 21, 21, 21, 20
|
||||
};
|
||||
|
||||
#endif // defined(IS_64BIT)
|
||||
|
||||
|
||||
Bitboard RMask[64];
|
||||
int RAttackIndex[64];
|
||||
Bitboard RAttacks[0x19000];
|
||||
|
||||
Bitboard BMask[64];
|
||||
int BAttackIndex[64];
|
||||
@@ -225,9 +205,6 @@ namespace {
|
||||
const int shift[2], const Bitboard mult[],
|
||||
int deltas[][2]);
|
||||
void init_pseudo_attacks();
|
||||
#if defined(USE_COMPACT_ROOK_ATTACKS)
|
||||
void init_file_and_rank_attacks();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -259,87 +236,17 @@ void init_bitboards() {
|
||||
init_ray_bitboards();
|
||||
init_attacks();
|
||||
init_between_bitboards();
|
||||
#if defined(USE_COMPACT_ROOK_ATTACKS)
|
||||
init_file_and_rank_attacks();
|
||||
#else
|
||||
init_sliding_attacks(RAttacks, RAttackIndex, RMask, RShift,
|
||||
RMult, rookDeltas);
|
||||
#endif
|
||||
init_sliding_attacks(BAttacks, BAttackIndex, BMask, BShift,
|
||||
BMult, bishopDeltas);
|
||||
init_sliding_attacks(RAttacks, RAttackIndex, RMask, RShift, RMult, rookDeltas);
|
||||
init_sliding_attacks(BAttacks, BAttackIndex, BMask, BShift, BMult, bishopDeltas);
|
||||
init_pseudo_attacks();
|
||||
}
|
||||
|
||||
|
||||
#if defined(USE_FOLDED_BITSCAN)
|
||||
|
||||
static const int BitTable[64] = {
|
||||
63, 30, 3, 32, 25, 41, 22, 33, 15, 50, 42, 13, 11, 53, 19, 34, 61, 29, 2,
|
||||
51, 21, 43, 45, 10, 18, 47, 1, 54, 9, 57, 0, 35, 62, 31, 40, 4, 49, 5, 52,
|
||||
26, 60, 6, 23, 44, 46, 27, 56, 16, 7, 39, 48, 24, 59, 14, 12, 55, 38, 28,
|
||||
58, 20, 37, 17, 36, 8
|
||||
};
|
||||
|
||||
|
||||
/// first_1() finds the least significant nonzero bit in a nonzero bitboard.
|
||||
|
||||
Square first_1(Bitboard b) {
|
||||
b ^= (b - 1);
|
||||
uint32_t fold = int(b) ^ int(b >> 32);
|
||||
return Square(BitTable[(fold * 0x783a9b23) >> 26]);
|
||||
}
|
||||
|
||||
|
||||
/// pop_1st_bit() finds and clears the least significant nonzero bit in a
|
||||
/// nonzero bitboard.
|
||||
|
||||
#if defined(USE_32BIT_ATTACKS)
|
||||
|
||||
// Use type-punning
|
||||
union b_union {
|
||||
|
||||
Bitboard b;
|
||||
struct {
|
||||
uint32_t l;
|
||||
uint32_t h;
|
||||
};
|
||||
};
|
||||
|
||||
// WARNING: Needs -fno-strict-aliasing compiler option
|
||||
Square pop_1st_bit(Bitboard *bb) {
|
||||
|
||||
b_union u;
|
||||
uint32_t b;
|
||||
|
||||
u.b = *bb;
|
||||
|
||||
if (u.l)
|
||||
{
|
||||
b = u.l;
|
||||
*((uint32_t*)bb) = b & (b - 1);
|
||||
b ^= (b - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
b = u.h;
|
||||
*((uint32_t*)bb+1) = b & (b - 1); // Little endian only?
|
||||
b = ~(b ^ (b - 1));
|
||||
}
|
||||
return Square(BitTable[(b * 0x783a9b23) >> 26]);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
Square pop_1st_bit(Bitboard *b) {
|
||||
Bitboard bb = *b ^ (*b - 1);
|
||||
uint32_t fold = int(bb) ^ int(bb >> 32);
|
||||
*b &= (*b - 1);
|
||||
return Square(BitTable[(fold * 0x783a9b23) >> 26]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
#if defined(IS_64BIT) && !defined(USE_BSFQ)
|
||||
|
||||
static const int BitTable[64] = {
|
||||
0, 1, 2, 7, 3, 13, 8, 19, 4, 25, 14, 28, 9, 34, 20, 40, 5, 17, 26, 38, 15,
|
||||
@@ -348,25 +255,65 @@ static const int BitTable[64] = {
|
||||
51, 60, 42, 59, 58
|
||||
};
|
||||
|
||||
|
||||
/// first_1() finds the least significant nonzero bit in a nonzero bitboard.
|
||||
|
||||
Square first_1(Bitboard b) {
|
||||
return Square(BitTable[((b & -b) * 0x218a392cd3d5dbfULL) >> 58]);
|
||||
}
|
||||
|
||||
|
||||
/// pop_1st_bit() finds and clears the least significant nonzero bit in a
|
||||
/// nonzero bitboard.
|
||||
|
||||
Square pop_1st_bit(Bitboard *b) {
|
||||
Square pop_1st_bit(Bitboard* b) {
|
||||
Bitboard bb = *b;
|
||||
*b &= (*b - 1);
|
||||
return Square(BitTable[((bb & -bb) * 0x218a392cd3d5dbfULL) >> 58]);
|
||||
}
|
||||
|
||||
#endif // defined(USE_FOLDED_BITSCAN)
|
||||
#elif !defined(USE_BSFQ)
|
||||
|
||||
static const int BitTable[64] = {
|
||||
63, 30, 3, 32, 25, 41, 22, 33, 15, 50, 42, 13, 11, 53, 19, 34, 61, 29, 2,
|
||||
51, 21, 43, 45, 10, 18, 47, 1, 54, 9, 57, 0, 35, 62, 31, 40, 4, 49, 5, 52,
|
||||
26, 60, 6, 23, 44, 46, 27, 56, 16, 7, 39, 48, 24, 59, 14, 12, 55, 38, 28,
|
||||
58, 20, 37, 17, 36, 8
|
||||
};
|
||||
|
||||
Square first_1(Bitboard b) {
|
||||
b ^= (b - 1);
|
||||
uint32_t fold = int(b) ^ int(b >> 32);
|
||||
return Square(BitTable[(fold * 0x783a9b23) >> 26]);
|
||||
}
|
||||
|
||||
// Use type-punning
|
||||
union b_union {
|
||||
|
||||
Bitboard b;
|
||||
struct {
|
||||
uint32_t l;
|
||||
uint32_t h;
|
||||
} dw;
|
||||
};
|
||||
|
||||
// WARNING: Needs -fno-strict-aliasing compiler option
|
||||
Square pop_1st_bit(Bitboard* bb) {
|
||||
|
||||
b_union u;
|
||||
uint32_t b;
|
||||
|
||||
u.b = *bb;
|
||||
|
||||
if (u.dw.l)
|
||||
{
|
||||
b = u.dw.l;
|
||||
*((uint32_t*)bb) = b & (b - 1);
|
||||
b ^= (b - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
b = u.dw.h;
|
||||
*((uint32_t*)bb+1) = b & (b - 1); // Little endian only?
|
||||
b = ~(b ^ (b - 1));
|
||||
}
|
||||
return Square(BitTable[(b * 0x783a9b23) >> 26]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -480,25 +427,25 @@ namespace {
|
||||
attackIndex[i] = index;
|
||||
mask[i] = sliding_attacks(i, 0ULL, 4, deltas, 1, 6, 1, 6);
|
||||
|
||||
#if defined(USE_32BIT_ATTACKS)
|
||||
j = (1 << (32 - shift[i]));
|
||||
#else
|
||||
#if defined(IS_64BIT)
|
||||
j = (1 << (64 - shift[i]));
|
||||
#else
|
||||
j = (1 << (32 - shift[i]));
|
||||
#endif
|
||||
|
||||
for(k = 0; k < j; k++) {
|
||||
|
||||
#if defined(USE_32BIT_ATTACKS)
|
||||
#if defined(IS_64BIT)
|
||||
b = index_to_bitboard(k, mask[i]);
|
||||
attacks[index + ((b * mult[i]) >> shift[i])] =
|
||||
sliding_attacks(i, b, 4, deltas);
|
||||
#else
|
||||
b = index_to_bitboard(k, mask[i]);
|
||||
attacks[index +
|
||||
(unsigned(int(b) * int(mult[i]) ^
|
||||
int(b >> 32) * int(mult[i] >> 32))
|
||||
>> shift[i])] =
|
||||
sliding_attacks(i, b, 4, deltas);
|
||||
#else
|
||||
b = index_to_bitboard(k, mask[i]);
|
||||
attacks[index + ((b * mult[i]) >> shift[i])] =
|
||||
sliding_attacks(i, b, 4, deltas);
|
||||
#endif
|
||||
}
|
||||
index += j;
|
||||
@@ -515,29 +462,4 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_COMPACT_ROOK_ATTACKS)
|
||||
void init_file_and_rank_attacks() {
|
||||
int i, j, k, l, m, s;
|
||||
Bitboard b1, b2;
|
||||
for(i = 0; i < 64; i++) {
|
||||
|
||||
for(m = 0; m <= 1; m++) {
|
||||
b1 = 0ULL;
|
||||
for(j = 0; j < 6; j++) if(i & (1<<j)) b1 |= (1ULL << ((j+1)*(1+m*7)));
|
||||
for(j = 0; j < 8; j++) {
|
||||
b2 = 0ULL;
|
||||
for(k = 0, s = 1; k < 2; k++, s *= -1) {
|
||||
for(l = j+s; l >= 0 && l <= 7; l += s) {
|
||||
b2 |= (m? RankBB[l] : FileBB[l]);
|
||||
if(b1 & (1ULL << (l*(1+m*7)))) break;
|
||||
}
|
||||
}
|
||||
if(m) FileAttacks[j][(b1*0xd6e8802041d0c441ULL) >> 58] = b2;
|
||||
else RankAttacks[j][i] = b2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // defined(USE_COMPACT_ROOK_ATTACKS)
|
||||
|
||||
}
|
||||
|
||||
177
src/bitboard.h
177
src/bitboard.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -22,43 +22,6 @@
|
||||
#if !defined(BITBOARD_H_INCLUDED)
|
||||
#define BITBOARD_H_INCLUDED
|
||||
|
||||
|
||||
////
|
||||
//// Defines
|
||||
////
|
||||
|
||||
// Comment following define if you prefer manually adjust
|
||||
// platform macros defined below
|
||||
#define AUTO_CONFIGURATION
|
||||
|
||||
// Quiet a warning on Intel compiler
|
||||
#if !defined(__SIZEOF_INT__ )
|
||||
#define __SIZEOF_INT__ 0
|
||||
#endif
|
||||
|
||||
// Check for 64 bits for different compilers: Intel, MSVC and gcc
|
||||
#if defined(__x86_64) || defined(_WIN64) || (__SIZEOF_INT__ > 4)
|
||||
#define IS_64BIT
|
||||
#endif
|
||||
|
||||
#if !defined(AUTO_CONFIGURATION) || defined(IS_64BIT)
|
||||
|
||||
//#define USE_COMPACT_ROOK_ATTACKS
|
||||
//#define USE_32BIT_ATTACKS
|
||||
#define USE_FOLDED_BITSCAN
|
||||
|
||||
#define BITCOUNT_SWAR_64
|
||||
//#define BITCOUNT_SWAR_32
|
||||
//#define BITCOUNT_LOOP
|
||||
|
||||
#else
|
||||
|
||||
#define USE_32BIT_ATTACKS
|
||||
#define USE_FOLDED_BITSCAN
|
||||
#define BITCOUNT_SWAR_32
|
||||
|
||||
#endif
|
||||
|
||||
////
|
||||
//// Includes
|
||||
////
|
||||
@@ -69,13 +32,6 @@
|
||||
#include "types.h"
|
||||
|
||||
|
||||
////
|
||||
//// Types
|
||||
////
|
||||
|
||||
typedef uint64_t Bitboard;
|
||||
|
||||
|
||||
////
|
||||
//// Constants and variables
|
||||
////
|
||||
@@ -160,20 +116,12 @@ extern Bitboard BetweenBB[64][64];
|
||||
extern Bitboard PassedPawnMask[2][64];
|
||||
extern Bitboard OutpostMask[2][64];
|
||||
|
||||
#if defined(USE_COMPACT_ROOK_ATTACKS)
|
||||
|
||||
extern Bitboard RankAttacks[8][64], FileAttacks[8][64];
|
||||
|
||||
#else
|
||||
|
||||
extern const uint64_t RMult[64];
|
||||
extern const int RShift[64];
|
||||
extern Bitboard RMask[64];
|
||||
extern int RAttackIndex[64];
|
||||
extern Bitboard RAttacks[0x19000];
|
||||
|
||||
#endif // defined(USE_COMPACT_ROOK_ATTACKS)
|
||||
|
||||
extern const uint64_t BMult[64];
|
||||
extern const int BShift[64];
|
||||
extern Bitboard BMask[64];
|
||||
@@ -205,6 +153,17 @@ inline void clear_bit(Bitboard *b, Square s) {
|
||||
}
|
||||
|
||||
|
||||
/// Functions used to update a bitboard after a move. This is faster
|
||||
/// then calling a sequence of clear_bit() + set_bit()
|
||||
|
||||
inline Bitboard make_move_bb(Square from, Square to) {
|
||||
return SetMaskBB[from] | SetMaskBB[to];
|
||||
}
|
||||
|
||||
inline void do_move_bb(Bitboard *b, Bitboard move_bb) {
|
||||
*b ^= move_bb;
|
||||
}
|
||||
|
||||
/// rank_bb() and file_bb() gives a bitboard containing all squares on a given
|
||||
/// file or rank. It is also possible to pass a square as input to these
|
||||
/// functions.
|
||||
@@ -298,29 +257,24 @@ inline Bitboard ray_bb(Square s, SignedDirection d) {
|
||||
}
|
||||
|
||||
|
||||
/// Functions for computing sliding attack bitboards. rook_attacks_bb(),
|
||||
/// Functions for computing sliding attack bitboards. rook_attacks_bb(),
|
||||
/// bishop_attacks_bb() and queen_attacks_bb() all take a square and a
|
||||
/// bitboard of occupied squares as input, and return a bitboard representing
|
||||
/// all squares attacked by a rook, bishop or queen on the given square.
|
||||
|
||||
#if defined(USE_COMPACT_ROOK_ATTACKS)
|
||||
|
||||
inline Bitboard file_attacks_bb(Square s, Bitboard blockers) {
|
||||
Bitboard b = (blockers >> square_file(s)) & 0x01010101010100ULL;
|
||||
return
|
||||
FileAttacks[square_rank(s)][(b*0xd6e8802041d0c441ULL)>>58] & file_bb(s);
|
||||
}
|
||||
|
||||
inline Bitboard rank_attacks_bb(Square s, Bitboard blockers) {
|
||||
Bitboard b = (blockers >> ((s & 56) + 1)) & 63;
|
||||
return RankAttacks[square_file(s)][b] & rank_bb(s);
|
||||
}
|
||||
#if defined(IS_64BIT)
|
||||
|
||||
inline Bitboard rook_attacks_bb(Square s, Bitboard blockers) {
|
||||
return file_attacks_bb(s, blockers) | rank_attacks_bb(s, blockers);
|
||||
Bitboard b = blockers & RMask[s];
|
||||
return RAttacks[RAttackIndex[s] + ((b * RMult[s]) >> RShift[s])];
|
||||
}
|
||||
|
||||
#elif defined(USE_32BIT_ATTACKS)
|
||||
inline Bitboard bishop_attacks_bb(Square s, Bitboard blockers) {
|
||||
Bitboard b = blockers & BMask[s];
|
||||
return BAttacks[BAttackIndex[s] + ((b * BMult[s]) >> BShift[s])];
|
||||
}
|
||||
|
||||
#else // if !defined(IS_64BIT)
|
||||
|
||||
inline Bitboard rook_attacks_bb(Square s, Bitboard blockers) {
|
||||
Bitboard b = blockers & RMask[s];
|
||||
@@ -330,17 +284,6 @@ inline Bitboard rook_attacks_bb(Square s, Bitboard blockers) {
|
||||
>> RShift[s])];
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline Bitboard rook_attacks_bb(Square s, Bitboard blockers) {
|
||||
Bitboard b = blockers & RMask[s];
|
||||
return RAttacks[RAttackIndex[s] + ((b * RMult[s]) >> RShift[s])];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(USE_32BIT_ATTACKS)
|
||||
|
||||
inline Bitboard bishop_attacks_bb(Square s, Bitboard blockers) {
|
||||
Bitboard b = blockers & BMask[s];
|
||||
return BAttacks[BAttackIndex[s] +
|
||||
@@ -349,14 +292,7 @@ inline Bitboard bishop_attacks_bb(Square s, Bitboard blockers) {
|
||||
>> BShift[s])];
|
||||
}
|
||||
|
||||
#else // defined(USE_32BIT_ATTACKS)
|
||||
|
||||
inline Bitboard bishop_attacks_bb(Square s, Bitboard blockers) {
|
||||
Bitboard b = blockers & BMask[s];
|
||||
return BAttacks[BAttackIndex[s] + ((b * BMult[s]) >> BShift[s])];
|
||||
}
|
||||
|
||||
#endif // defined(USE_32BIT_ATTACKS)
|
||||
#endif
|
||||
|
||||
inline Bitboard queen_attacks_bb(Square s, Bitboard blockers) {
|
||||
return rook_attacks_bb(s, blockers) | bishop_attacks_bb(s, blockers);
|
||||
@@ -418,63 +354,30 @@ inline Bitboard isolated_pawn_mask(Square s) {
|
||||
}
|
||||
|
||||
|
||||
/// count_1s() counts the number of nonzero bits in a bitboard.
|
||||
/// first_1() finds the least significant nonzero bit in a nonzero bitboard.
|
||||
/// pop_1st_bit() finds and clears the least significant nonzero bit in a
|
||||
/// nonzero bitboard.
|
||||
|
||||
#if defined(BITCOUNT_LOOP)
|
||||
#if defined(USE_BSFQ) // Assembly code by Heinz van Saanen
|
||||
|
||||
inline int count_1s(Bitboard b) {
|
||||
int r;
|
||||
for(r = 0; b; r++, b &= b - 1);
|
||||
return r;
|
||||
inline Square __attribute__((always_inline)) first_1(Bitboard b) {
|
||||
Bitboard dummy;
|
||||
__asm__("bsfq %1, %0": "=r"(dummy): "rm"(b) );
|
||||
return (Square)(dummy);
|
||||
}
|
||||
|
||||
inline int count_1s_max_15(Bitboard b) {
|
||||
return count_1s(b);
|
||||
inline Square __attribute__((always_inline)) pop_1st_bit(Bitboard* b) {
|
||||
const Square s = first_1(*b);
|
||||
*b &= ~(1ULL<<s);
|
||||
return s;
|
||||
}
|
||||
|
||||
#elif defined(BITCOUNT_SWAR_32)
|
||||
#else // if !defined(USE_BSFQ)
|
||||
|
||||
inline int count_1s(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) & 0x0F0F0F0F; // 0-8 in 8 bits
|
||||
v += (((w >> 4) + w) & 0x0F0F0F0F); // 0-16 in 8 bits
|
||||
v *= 0x01010101; // mul is fast on amd procs
|
||||
return int(v >> 24);
|
||||
}
|
||||
extern Square first_1(Bitboard b);
|
||||
extern Square pop_1st_bit(Bitboard* b);
|
||||
|
||||
inline int count_1s_max_15(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 += w; // 0-8 in 4 bits
|
||||
v *= 0x11111111;
|
||||
return int(v >> 28);
|
||||
}
|
||||
|
||||
#elif defined(BITCOUNT_SWAR_64)
|
||||
|
||||
inline int count_1s(Bitboard b) {
|
||||
b -= ((b>>1) & 0x5555555555555555ULL);
|
||||
b = ((b>>2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
|
||||
b = ((b>>4) + b) & 0x0F0F0F0F0F0F0F0FULL;
|
||||
b *= 0x0101010101010101ULL;
|
||||
return int(b >> 56);
|
||||
}
|
||||
|
||||
inline int count_1s_max_15(Bitboard b) {
|
||||
b -= (b>>1) & 0x5555555555555555ULL;
|
||||
b = ((b>>2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
|
||||
b *= 0x1111111111111111ULL;
|
||||
return int(b >> 60);
|
||||
}
|
||||
|
||||
#endif // BITCOUNT
|
||||
#endif
|
||||
|
||||
|
||||
////
|
||||
@@ -483,8 +386,6 @@ inline int count_1s_max_15(Bitboard b) {
|
||||
|
||||
extern void print_bitboard(Bitboard b);
|
||||
extern void init_bitboards();
|
||||
extern Square first_1(Bitboard b);
|
||||
extern Square pop_1st_bit(Bitboard *b);
|
||||
|
||||
|
||||
#endif // !defined(BITBOARD_H_INCLUDED)
|
||||
|
||||
161
src/bitcount.h
Normal file
161
src/bitcount.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(BITCOUNT_H_INCLUDED)
|
||||
#define BITCOUNT_H_INCLUDED
|
||||
|
||||
// To enable POPCNT support uncomment USE_POPCNT define. For PGO compile on a Core i7
|
||||
// you may want to collect profile data first with USE_POPCNT disabled and then, in a
|
||||
// second profiling session, with USE_POPCNT enabled so to exercise both paths. Don't
|
||||
// forget to leave USE_POPCNT enabled for the final optimized compile though ;-)
|
||||
|
||||
//#define USE_POPCNT
|
||||
|
||||
|
||||
#include "types.h"
|
||||
|
||||
// Select type of intrinsic bit count instruction to use
|
||||
|
||||
#if defined(__INTEL_COMPILER) && defined(IS_64BIT) && defined(USE_POPCNT) // Intel compiler
|
||||
|
||||
#include <nmmintrin.h>
|
||||
|
||||
inline bool cpu_has_popcnt() {
|
||||
|
||||
int CPUInfo[4] = {-1};
|
||||
__cpuid(CPUInfo, 0x00000001);
|
||||
return (CPUInfo[2] >> 23) & 1;
|
||||
}
|
||||
|
||||
// Define a dummy template to workaround a compile error if _mm_popcnt_u64() is not defined.
|
||||
//
|
||||
// If _mm_popcnt_u64() is defined in <nmmintrin.h> it will be choosen first due to
|
||||
// C++ overload rules that always prefer a function to a template with the same name.
|
||||
// If not, we avoid a compile error and because cpu_has_popcnt() should return false,
|
||||
// our templetized _mm_popcnt_u64() is never called anyway.
|
||||
template<typename T> inline unsigned _mm_popcnt_u64(T) { return 0; } // Is never called
|
||||
|
||||
#define POPCNT_INTRINSIC(x) _mm_popcnt_u64(x)
|
||||
|
||||
#elif defined(_MSC_VER) && defined(IS_64BIT) && defined(USE_POPCNT) // Microsoft compiler
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
inline bool cpu_has_popcnt() {
|
||||
|
||||
int CPUInfo[4] = {-1};
|
||||
__cpuid(CPUInfo, 0x00000001);
|
||||
return (CPUInfo[2] >> 23) & 1;
|
||||
}
|
||||
|
||||
// See comment of _mm_popcnt_u64<>() few lines above for an explanation.
|
||||
template<typename T> inline unsigned __popcnt64(T) { return 0; } // Is never called
|
||||
|
||||
#define POPCNT_INTRINSIC(x) __popcnt64(x)
|
||||
|
||||
#else // Safe fallback for unsupported compilers or when USE_POPCNT is disabled
|
||||
|
||||
inline bool cpu_has_popcnt() { return false; }
|
||||
|
||||
#define POPCNT_INTRINSIC(x) 0
|
||||
|
||||
#endif // cpu_has_popcnt() and POPCNT_INTRINSIC() definitions
|
||||
|
||||
|
||||
/// Software implementation of bit count functions
|
||||
|
||||
#if defined(IS_64BIT)
|
||||
|
||||
inline int count_1s(Bitboard b) {
|
||||
b -= ((b>>1) & 0x5555555555555555ULL);
|
||||
b = ((b>>2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
|
||||
b = ((b>>4) + b) & 0x0F0F0F0F0F0F0F0FULL;
|
||||
b *= 0x0101010101010101ULL;
|
||||
return int(b >> 56);
|
||||
}
|
||||
|
||||
inline int count_1s_max_15(Bitboard b) {
|
||||
b -= (b>>1) & 0x5555555555555555ULL;
|
||||
b = ((b>>2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
|
||||
b *= 0x1111111111111111ULL;
|
||||
return int(b >> 60);
|
||||
}
|
||||
|
||||
#else // if !defined(IS_64BIT)
|
||||
|
||||
inline int count_1s(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) & 0x0F0F0F0F; // 0-8 in 8 bits
|
||||
v += (((w >> 4) + w) & 0x0F0F0F0F); // 0-16 in 8 bits
|
||||
v *= 0x01010101; // mul is fast on amd procs
|
||||
return int(v >> 24);
|
||||
}
|
||||
|
||||
inline int count_1s_max_15(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 += w; // 0-8 in 4 bits
|
||||
v *= 0x11111111;
|
||||
return int(v >> 28);
|
||||
}
|
||||
|
||||
#endif // BITCOUNT
|
||||
|
||||
|
||||
/// count_1s() counts the number of nonzero bits in a bitboard.
|
||||
/// If template parameter is true an intrinsic is called, otherwise
|
||||
/// we fallback on a software implementation.
|
||||
|
||||
template<bool UseIntrinsic>
|
||||
inline int count_1s(Bitboard b) {
|
||||
|
||||
return UseIntrinsic ? POPCNT_INTRINSIC(b) : count_1s(b);
|
||||
}
|
||||
|
||||
template<bool UseIntrinsic>
|
||||
inline int count_1s_max_15(Bitboard b) {
|
||||
|
||||
return UseIntrinsic ? POPCNT_INTRINSIC(b) : count_1s_max_15(b);
|
||||
}
|
||||
|
||||
|
||||
// Global constant initialized at startup that is set to true if
|
||||
// CPU on which application runs supports POPCNT intrinsic. Unless
|
||||
// USE_POPCNT is not defined.
|
||||
const bool CpuHasPOPCNT = cpu_has_popcnt();
|
||||
|
||||
|
||||
// Global constant used to print info about the use of 64 optimized
|
||||
// functions to verify that a 64 bit compile has been correctly built.
|
||||
#if defined(IS_64BIT)
|
||||
const bool CpuHas64BitPath = true;
|
||||
#else
|
||||
const bool CpuHas64BitPath = false;
|
||||
#endif
|
||||
|
||||
#endif // !defined(BITCOUNT_H_INCLUDED)
|
||||
309
src/book.cpp
309
src/book.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "mersenne.h"
|
||||
#include "movegen.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
////
|
||||
//// Global variables
|
||||
@@ -49,7 +50,11 @@ Book OpeningBook;
|
||||
|
||||
namespace {
|
||||
|
||||
/// Random numbers from PolyGlot, used to compute book hash keys.
|
||||
/// Book entry size in bytes
|
||||
const int EntrySize = 16;
|
||||
|
||||
|
||||
/// Random numbers from PolyGlot, used to compute book hash keys
|
||||
|
||||
const uint64_t Random64[781] = {
|
||||
0x9D39247E33776D41ULL, 0x2AF7398005AAA5C7ULL, 0x44DB015024623547ULL,
|
||||
@@ -318,30 +323,19 @@ namespace {
|
||||
|
||||
/// Indices to the Random64[] array
|
||||
|
||||
const int RandomPiece = 0;
|
||||
const int RandomCastle = 768;
|
||||
const int RandomPiece = 0;
|
||||
const int RandomCastle = 768;
|
||||
const int RandomEnPassant = 772;
|
||||
const int RandomTurn = 780;
|
||||
|
||||
|
||||
/// Convert pieces to the range 0..1
|
||||
|
||||
const int PieceTo12[] = {
|
||||
0, 0, 2, 4, 6, 8, 10, 0, 0, 1, 3, 5, 7, 9, 11
|
||||
};
|
||||
const int RandomTurn = 780;
|
||||
|
||||
|
||||
/// Prototypes
|
||||
|
||||
uint64_t book_key(const Position &pos);
|
||||
uint64_t book_key(const Position& pos);
|
||||
uint64_t book_piece_key(Piece p, Square s);
|
||||
uint64_t book_castle_key(const Position &pos);
|
||||
uint64_t book_ep_key(const Position &pos);
|
||||
uint64_t book_color_key(const Position &pos);
|
||||
|
||||
uint16_t read_integer16(std::ifstream& file);
|
||||
uint64_t read_integer64(std::ifstream& file);
|
||||
uint64_t read_integer(std::ifstream& file, int size);
|
||||
uint64_t book_castle_key(const Position& pos);
|
||||
uint64_t book_ep_key(const Position& pos);
|
||||
uint64_t book_color_key(const Position& pos);
|
||||
}
|
||||
|
||||
|
||||
@@ -350,99 +344,108 @@ namespace {
|
||||
////
|
||||
|
||||
|
||||
/// Constructor
|
||||
/// Destructor. Be sure file is closed before we leave.
|
||||
|
||||
Book::Book() : bookSize(0) {}
|
||||
Book::~Book() {
|
||||
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
/// Book::open() opens a book file with a given file name.
|
||||
/// Book::open() opens a book file with a given file name
|
||||
|
||||
void Book::open(const std::string &fName) {
|
||||
void Book::open(const string& fName) {
|
||||
|
||||
// Close old file before opening the new
|
||||
close();
|
||||
|
||||
fileName = fName;
|
||||
bookFile.open(fileName.c_str(), std::ifstream::in | std::ifstream::binary);
|
||||
if (!bookFile.is_open())
|
||||
ifstream::open(fileName.c_str(), ifstream::in | ifstream::binary);
|
||||
if (!is_open())
|
||||
return;
|
||||
|
||||
bookFile.seekg(0, std::ios::end);
|
||||
bookSize = bookFile.tellg() / 16;
|
||||
bookFile.seekg(0, std::ios::beg);
|
||||
// Get the book size in number of entries
|
||||
seekg(0, ios::end);
|
||||
bookSize = tellg() / EntrySize;
|
||||
seekg(0, ios::beg);
|
||||
|
||||
if (!bookFile.good())
|
||||
if (!good())
|
||||
{
|
||||
std::cerr << "Failed to open book file " << fileName << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
cerr << "Failed to open book file " << fileName << endl;
|
||||
Application::exit_with_failure();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Book::close() closes the currently open book file.
|
||||
/// Book::close() closes the file only if it is open, otherwise
|
||||
/// we can end up in a little mess due to how std::ifstream works.
|
||||
|
||||
void Book::close() {
|
||||
|
||||
if (bookFile.is_open())
|
||||
bookFile.close();
|
||||
}
|
||||
|
||||
|
||||
/// Book::is_open() tests whether a book file has been opened.
|
||||
|
||||
bool Book::is_open() const {
|
||||
|
||||
return bookFile.is_open() && bookSize != 0;
|
||||
if (is_open())
|
||||
ifstream::close();
|
||||
}
|
||||
|
||||
|
||||
/// Book::file_name() returns the file name of the currently active book,
|
||||
/// or the empty string if no book is open.
|
||||
|
||||
const std::string Book::file_name() const {
|
||||
const string Book::file_name() const {
|
||||
|
||||
return bookFile.is_open() ? fileName : "";
|
||||
return is_open() ? fileName : "";
|
||||
}
|
||||
|
||||
|
||||
/// Book::get_move() gets a book move for a given position. Returns
|
||||
/// Book::get_move() gets a book move for a given position. Returns
|
||||
/// MOVE_NONE if no book move is found.
|
||||
|
||||
Move Book::get_move(const Position &pos) const {
|
||||
if(this->is_open()) {
|
||||
int bestMove = 0, bestScore = 0, move, score;
|
||||
uint64_t key = book_key(pos);
|
||||
BookEntry entry;
|
||||
Move Book::get_move(const Position& pos) {
|
||||
|
||||
if (!is_open() || bookSize == 0)
|
||||
return MOVE_NONE;
|
||||
|
||||
int bookMove = 0, scoresSum = 0;
|
||||
uint64_t key = book_key(pos);
|
||||
BookEntry entry;
|
||||
|
||||
// Choose a book move among the possible moves for the given position
|
||||
for (int idx = find_key(key); idx < bookSize; idx++)
|
||||
{
|
||||
read_entry(entry, idx);
|
||||
if (entry.key != key)
|
||||
break;
|
||||
|
||||
int score = entry.count;
|
||||
|
||||
for(int i = this->find_key(key); i < bookSize; i++) {
|
||||
this->read_entry(entry, i);
|
||||
if(entry.key != key)
|
||||
break;
|
||||
move = entry.move;
|
||||
score = entry.count;
|
||||
assert(score > 0);
|
||||
|
||||
bestScore += score;
|
||||
if(int(genrand_int32() % bestScore) < score)
|
||||
bestMove = move;
|
||||
}
|
||||
|
||||
if(bestMove != 0) {
|
||||
MoveStack moves[256];
|
||||
int n, j;
|
||||
n = generate_legal_moves(pos, moves);
|
||||
for(j = 0; j < n; j++)
|
||||
if((int(moves[j].move) & 07777) == bestMove)
|
||||
return moves[j].move;
|
||||
}
|
||||
// Choose book move according to its score. If a move has a very
|
||||
// high score it has more probability to be choosen then a one with
|
||||
// lower score. Note that first entry is always chosen.
|
||||
scoresSum += score;
|
||||
if (int(genrand_int32() % scoresSum) < score)
|
||||
bookMove = entry.move;
|
||||
}
|
||||
if (!bookMove)
|
||||
return MOVE_NONE;
|
||||
|
||||
MoveStack moves[256];
|
||||
int n = generate_legal_moves(pos, moves);
|
||||
for (int j = 0; j < n; j++)
|
||||
if ((int(moves[j].move) & 07777) == bookMove)
|
||||
return moves[j].move;
|
||||
|
||||
return MOVE_NONE;
|
||||
}
|
||||
|
||||
|
||||
/// Book::find_key() takes a book key as input, and does a binary search
|
||||
/// through the book file for the given key. The index to the first book
|
||||
/// entry with the same key as the input is returned. When the key is not
|
||||
/// through the book file for the given key. The index to the first book
|
||||
/// entry with the same key as the input is returned. When the key is not
|
||||
/// found in the book file, bookSize is returned.
|
||||
|
||||
int Book::find_key(uint64_t key) const {
|
||||
int Book::find_key(uint64_t key) {
|
||||
|
||||
int left, right, mid;
|
||||
BookEntry entry;
|
||||
|
||||
@@ -452,46 +455,59 @@ int Book::find_key(uint64_t key) const {
|
||||
|
||||
assert(left <= right);
|
||||
|
||||
while(left < right) {
|
||||
mid = (left + right) / 2;
|
||||
assert(mid >= left && mid < right);
|
||||
while (left < right)
|
||||
{
|
||||
mid = (left + right) / 2;
|
||||
|
||||
this->read_entry(entry, mid);
|
||||
assert(mid >= left && mid < right);
|
||||
|
||||
if(key <= entry.key)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
read_entry(entry, mid);
|
||||
if (key <= entry.key)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
|
||||
assert(left == right);
|
||||
|
||||
this->read_entry(entry, left);
|
||||
|
||||
read_entry(entry, left);
|
||||
return (entry.key == key)? left : bookSize;
|
||||
}
|
||||
|
||||
|
||||
/// Book::read_entry() takes a BookEntry reference and an integer index as
|
||||
/// input, and looks up the opening book entry at the given index in the book
|
||||
/// file. The book entry is copied to the first input parameter.
|
||||
/// file. The book entry is copied to the first input parameter.
|
||||
|
||||
void Book::read_entry(BookEntry& entry, int n) const {
|
||||
void Book::read_entry(BookEntry& entry, int idx) {
|
||||
|
||||
assert(n >= 0 && n < bookSize);
|
||||
assert(bookFile.is_open());
|
||||
assert(idx >= 0 && idx < bookSize);
|
||||
assert(is_open());
|
||||
|
||||
bookFile.seekg(n*16, std::ios_base::beg);
|
||||
if (!bookFile.good())
|
||||
seekg(idx * EntrySize, ios_base::beg);
|
||||
*this >> entry;
|
||||
if (!good())
|
||||
{
|
||||
std::cerr << "Failed to read book entry at index " << n << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
cerr << "Failed to read book entry at index " << idx << endl;
|
||||
Application::exit_with_failure();
|
||||
}
|
||||
entry.key = read_integer64(bookFile);
|
||||
entry.move = read_integer16(bookFile);
|
||||
entry.count = read_integer16(bookFile);
|
||||
entry.n = read_integer16(bookFile);
|
||||
entry.sum = read_integer16(bookFile);
|
||||
}
|
||||
|
||||
|
||||
/// Book::read_integer() reads size chars from the file stream
|
||||
/// and converts them in an integer number.
|
||||
|
||||
uint64_t Book::read_integer(int size) {
|
||||
|
||||
char buf[8];
|
||||
read(buf, size);
|
||||
|
||||
// Numbers are stored on disk as a binary byte stream
|
||||
uint64_t n = 0ULL;
|
||||
for (int i = 0; i < size; i++)
|
||||
n = (n << 8) + (unsigned char)buf[i];
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
@@ -501,92 +517,67 @@ void Book::read_entry(BookEntry& entry, int n) const {
|
||||
|
||||
namespace {
|
||||
|
||||
uint64_t book_key(const Position &pos) {
|
||||
uint64_t book_key(const Position& pos) {
|
||||
|
||||
uint64_t result = 0ULL;
|
||||
|
||||
for(Color c = WHITE; c <= BLACK; c++) {
|
||||
Bitboard b = pos.pieces_of_color(c);
|
||||
Square s;
|
||||
Piece p;
|
||||
while(b != EmptyBoardBB) {
|
||||
s = pop_1st_bit(&b);
|
||||
p = pos.piece_on(s);
|
||||
assert(piece_is_ok(p));
|
||||
assert(color_of_piece(p) == c);
|
||||
for (Color c = WHITE; c <= BLACK; c++)
|
||||
{
|
||||
Bitboard b = pos.pieces_of_color(c);
|
||||
|
||||
result ^= book_piece_key(p, s);
|
||||
}
|
||||
while (b)
|
||||
{
|
||||
Square s = pop_1st_bit(&b);
|
||||
Piece p = pos.piece_on(s);
|
||||
|
||||
assert(piece_is_ok(p));
|
||||
assert(color_of_piece(p) == c);
|
||||
|
||||
result ^= book_piece_key(p, s);
|
||||
}
|
||||
}
|
||||
|
||||
result ^= book_castle_key(pos);
|
||||
result ^= book_ep_key(pos);
|
||||
result ^= book_color_key(pos);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
uint64_t book_piece_key(Piece p, Square s) {
|
||||
return Random64[RandomPiece + (PieceTo12[int(p)]^1)*64 + int(s)];
|
||||
|
||||
/// Convert pieces to the range 0..11
|
||||
static const int PieceTo12[] = { 0, 0, 2, 4, 6, 8, 10, 0, 0, 1, 3, 5, 7, 9, 11 };
|
||||
|
||||
return Random64[RandomPiece + (PieceTo12[int(p)]^1) * 64 + int(s)];
|
||||
}
|
||||
|
||||
|
||||
uint64_t book_castle_key(const Position &pos) {
|
||||
uint64_t book_castle_key(const Position& pos) {
|
||||
|
||||
uint64_t result = 0ULL;
|
||||
|
||||
if(pos.can_castle_kingside(WHITE))
|
||||
result ^= Random64[RandomCastle+0];
|
||||
if(pos.can_castle_queenside(WHITE))
|
||||
result ^= Random64[RandomCastle+1];
|
||||
if(pos.can_castle_kingside(BLACK))
|
||||
result ^= Random64[RandomCastle+2];
|
||||
if(pos.can_castle_queenside(BLACK))
|
||||
result ^= Random64[RandomCastle+3];
|
||||
if (pos.can_castle_kingside(WHITE))
|
||||
result ^= Random64[RandomCastle+0];
|
||||
|
||||
if (pos.can_castle_queenside(WHITE))
|
||||
result ^= Random64[RandomCastle+1];
|
||||
|
||||
if (pos.can_castle_kingside(BLACK))
|
||||
result ^= Random64[RandomCastle+2];
|
||||
|
||||
if (pos.can_castle_queenside(BLACK))
|
||||
result ^= Random64[RandomCastle+3];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
uint64_t book_ep_key(const Position &pos) {
|
||||
return (pos.ep_square() == SQ_NONE)?
|
||||
0ULL : Random64[RandomEnPassant + square_file(pos.ep_square())];
|
||||
uint64_t book_ep_key(const Position& pos) {
|
||||
return (pos.ep_square() == SQ_NONE ? 0ULL : Random64[RandomEnPassant + square_file(pos.ep_square())]);
|
||||
}
|
||||
|
||||
|
||||
uint64_t book_color_key(const Position &pos) {
|
||||
return (pos.side_to_move() == WHITE)? Random64[RandomTurn] : 0ULL;
|
||||
}
|
||||
|
||||
|
||||
uint16_t read_integer16(std::ifstream& file) {
|
||||
|
||||
uint64_t n = read_integer(file, 2);
|
||||
assert(n == (uint16_t)n);
|
||||
return (uint16_t)n;
|
||||
}
|
||||
|
||||
|
||||
uint64_t read_integer64(std::ifstream& file) {
|
||||
|
||||
return read_integer(file, 8);
|
||||
}
|
||||
|
||||
|
||||
uint64_t read_integer(std::ifstream& file, int size) {
|
||||
|
||||
char buf[8];
|
||||
file.read(buf, size);
|
||||
|
||||
if (!file.good())
|
||||
{
|
||||
std::cerr << "Failed to read " << size << " bytes from book file"
|
||||
<< std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// Numbers are stored in little endian format
|
||||
uint64_t n = 0ULL;
|
||||
for (int i = 0; i < size; i++)
|
||||
n = (n << 8) + (unsigned char)buf[i];
|
||||
|
||||
return n;
|
||||
uint64_t book_color_key(const Position& pos) {
|
||||
return (pos.side_to_move() == WHITE ? Random64[RandomTurn] : 0ULL);
|
||||
}
|
||||
}
|
||||
|
||||
31
src/book.h
31
src/book.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -52,31 +52,24 @@ struct BookEntry {
|
||||
uint16_t sum;
|
||||
};
|
||||
|
||||
class Book {
|
||||
|
||||
class Book : private std::ifstream {
|
||||
public:
|
||||
// Constructors
|
||||
Book();
|
||||
|
||||
// Open and close book files
|
||||
void open(const std::string &fName);
|
||||
~Book();
|
||||
void open(const std::string& fName);
|
||||
void close();
|
||||
|
||||
// Testing if a book is opened
|
||||
bool is_open() const;
|
||||
|
||||
// The file name of the currently active book
|
||||
const std::string file_name() const;
|
||||
|
||||
// Get a book move for a given position
|
||||
Move get_move(const Position &pos) const;
|
||||
Move get_move(const Position& pos);
|
||||
|
||||
private:
|
||||
int find_key(uint64_t key) const;
|
||||
void read_entry(BookEntry &entry, int n) const;
|
||||
Book& operator>>(uint64_t& n) { n = read_integer(8); return *this; }
|
||||
Book& operator>>(uint16_t& n) { n = (uint16_t)read_integer(2); return *this; }
|
||||
void operator>>(BookEntry& e) { *this >> e.key >> e.move >> e.count >> e.n >> e.sum; }
|
||||
|
||||
uint64_t read_integer(int size);
|
||||
void read_entry(BookEntry& e, int n);
|
||||
int find_key(uint64_t key);
|
||||
|
||||
std::string fileName;
|
||||
mutable std::ifstream bookFile;
|
||||
int bookSize;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -37,7 +37,6 @@ enum Color {
|
||||
//// Inline functions
|
||||
////
|
||||
|
||||
inline Color operator+ (Color c, int i) { return Color(int(c) + i); }
|
||||
inline void operator++ (Color &c, int) { c = Color(int(c) + 1); }
|
||||
|
||||
inline Color opposite_color(Color c) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -35,9 +35,6 @@ enum Depth {
|
||||
//// Constants
|
||||
////
|
||||
|
||||
/// Note: If OnePly is changed, the constant HistoryMax in history.h should
|
||||
/// probably also be changed.
|
||||
|
||||
const Depth OnePly = Depth(2);
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
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,6 +26,32 @@
|
||||
#include "square.h"
|
||||
|
||||
|
||||
////
|
||||
//// Local definitions
|
||||
////
|
||||
|
||||
namespace {
|
||||
|
||||
const SquareDelta directionToDelta[] = {
|
||||
DELTA_E, DELTA_W, DELTA_N, DELTA_S, DELTA_NE, DELTA_SW, DELTA_NW, DELTA_SE
|
||||
};
|
||||
|
||||
bool reachable(Square orig, Square dest, SignedDirection dir) {
|
||||
|
||||
SquareDelta delta = directionToDelta[dir];
|
||||
Square from = orig;
|
||||
Square to = from + delta;
|
||||
while (to != dest && square_distance(to, from) == 1 && square_is_ok(to))
|
||||
{
|
||||
from = to;
|
||||
to += delta;
|
||||
}
|
||||
return (to == dest && square_distance(from, to) == 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
////
|
||||
//// Variables
|
||||
////
|
||||
@@ -39,25 +65,23 @@ uint8_t SignedDirectionTable[64][64];
|
||||
////
|
||||
|
||||
void init_direction_table() {
|
||||
SquareDelta deltas[8] = {
|
||||
DELTA_E, DELTA_W, DELTA_N, DELTA_S, DELTA_NE, DELTA_SW, DELTA_NW, DELTA_SE
|
||||
};
|
||||
for(Square s1 = SQ_A1; s1 <= SQ_H8; s1++)
|
||||
for(Square s2 = SQ_A1; s2 <= SQ_H8; s2++) {
|
||||
DirectionTable[s1][s2] = uint8_t(DIR_NONE);
|
||||
SignedDirectionTable[s1][s2] = uint8_t(SIGNED_DIR_NONE);
|
||||
if(s1 == s2) continue;
|
||||
for(SignedDirection d = SIGNED_DIR_E; d <= SIGNED_DIR_SE; d++) {
|
||||
SquareDelta delta = deltas[d];
|
||||
Square s3, s4;
|
||||
for(s4 = s1 + delta, s3 = s1;
|
||||
square_distance(s4, s3) == 1 && s4 != s2 && square_is_ok(s4);
|
||||
s3 = s4, s4 += delta);
|
||||
if(s4 == s2 && square_distance(s4, s3) == 1) {
|
||||
SignedDirectionTable[s1][s2] = uint8_t(d);
|
||||
DirectionTable[s1][s2] = uint8_t(d/2);
|
||||
break;
|
||||
}
|
||||
|
||||
for (Square s1 = SQ_A1; s1 <= SQ_H8; s1++)
|
||||
for (Square s2 = SQ_A1; s2 <= SQ_H8; s2++)
|
||||
{
|
||||
DirectionTable[s1][s2] = uint8_t(DIR_NONE);
|
||||
SignedDirectionTable[s1][s2] = uint8_t(SIGNED_DIR_NONE);
|
||||
if (s1 == s2)
|
||||
continue;
|
||||
|
||||
for (SignedDirection d = SIGNED_DIR_E; d != SIGNED_DIR_NONE; d++)
|
||||
{
|
||||
if (reachable(s1, s2, d))
|
||||
{
|
||||
SignedDirectionTable[s1][s2] = uint8_t(d);
|
||||
DirectionTable[s1][s2] = uint8_t(d / 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <cassert>
|
||||
|
||||
#include "bitbase.h"
|
||||
#include "bitcount.h"
|
||||
#include "endgame.h"
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -65,7 +65,7 @@ enum EndgameType {
|
||||
template<typename T>
|
||||
class EndgameFunctionBase {
|
||||
public:
|
||||
EndgameFunctionBase(Color c) : strongerSide(c) { weakerSide = opposite_color(strongerSide); }
|
||||
EndgameFunctionBase(Color c) : strongerSide(c), weakerSide(opposite_color(c)) {}
|
||||
virtual ~EndgameFunctionBase() {}
|
||||
virtual T apply(const Position&) = 0;
|
||||
|
||||
|
||||
333
src/evaluate.cpp
333
src/evaluate.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include "bitcount.h"
|
||||
#include "evaluate.h"
|
||||
#include "material.h"
|
||||
#include "pawns.h"
|
||||
@@ -39,23 +40,20 @@
|
||||
|
||||
namespace {
|
||||
|
||||
const int Sign[2] = {1, -1};
|
||||
const int Sign[2] = { 1, -1 };
|
||||
|
||||
// Evaluation grain size, must be a power of 2.
|
||||
// Evaluation grain size, must be a power of 2
|
||||
const int GrainSize = 4;
|
||||
|
||||
// Evaluation weights
|
||||
int WeightMobilityMidgame = 0x100;
|
||||
int WeightMobilityEndgame = 0x100;
|
||||
int WeightPawnStructureMidgame = 0x100;
|
||||
int WeightPawnStructureEndgame = 0x100;
|
||||
int WeightPassedPawnsMidgame = 0x100;
|
||||
int WeightPassedPawnsEndgame = 0x100;
|
||||
int WeightKingSafety[2] = { 0x100, 0x100 };
|
||||
// Evaluation weights, initialized from UCI options
|
||||
int WeightMobilityMidgame, WeightMobilityEndgame;
|
||||
int WeightPawnStructureMidgame, WeightPawnStructureEndgame;
|
||||
int WeightPassedPawnsMidgame, WeightPassedPawnsEndgame;
|
||||
int WeightKingSafety[2];
|
||||
int WeightSpace;
|
||||
|
||||
// Internal evaluation weights. These are applied on top of the evaluation
|
||||
// weights read from UCI parameters. The purpose is to be able to change
|
||||
// Internal evaluation weights. These are applied on top of the evaluation
|
||||
// weights read from UCI parameters. The purpose is to be able to change
|
||||
// the evaluation weights while keeping the default values of the UCI
|
||||
// parameters at 100, which looks prettier.
|
||||
//
|
||||
@@ -70,6 +68,8 @@ namespace {
|
||||
const int WeightKingOppSafetyInternal = 0x101;
|
||||
const int WeightSpaceInternal = 0x02F;
|
||||
|
||||
// Mobility and outposts bonus modified by Joona Kiiski
|
||||
//
|
||||
// Visually better to define tables constants
|
||||
typedef Value V;
|
||||
|
||||
@@ -77,70 +77,70 @@ namespace {
|
||||
// of attacked squares not occupied by friendly piecess.
|
||||
const Value MidgameKnightMobilityBonus[] = {
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
V(-30), V(-20),V(-10), V(0), V(10), V(20), V(25), V(30), V(30)
|
||||
V(-38), V(-25),V(-12), V(0), V(12), V(25), V(31), V(38), V(38)
|
||||
};
|
||||
|
||||
const Value EndgameKnightMobilityBonus[] = {
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
V(-30), V(-20),V(-10), V(0), V(10), V(20), V(25), V(30), V(30)
|
||||
V(-33), V(-23),V(-13), V(-3), V(7), V(17), V(22), V(27), V(27)
|
||||
};
|
||||
|
||||
// Bishop mobility bonus in middle game and endgame, indexed by the number
|
||||
// of attacked squares not occupied by friendly pieces. X-ray attacks through
|
||||
// of attacked squares not occupied by friendly pieces. X-ray attacks through
|
||||
// queens are also included.
|
||||
const Value MidgameBishopMobilityBonus[] = {
|
||||
// 0 1 2 3 4 5 6 7
|
||||
V(-30), V(-15), V(0), V(15), V(30), V(45), V(58), V(66),
|
||||
V(-25), V(-11), V(3), V(17), V(31), V(45), V(57), V(65),
|
||||
// 8 9 10 11 12 13 14 15
|
||||
V( 72), V( 76), V(78), V(80), V(81), V(82), V(83), V(83)
|
||||
V( 71), V( 74), V(76), V(78), V(79), V(80), V(81), V(81)
|
||||
};
|
||||
|
||||
const Value EndgameBishopMobilityBonus[] = {
|
||||
// 0 1 2 3 4 5 6 7
|
||||
V(-30), V(-15), V(0), V(15), V(30), V(45), V(58), V(66),
|
||||
V(-30), V(-16), V(-2), V(12), V(26), V(40), V(52), V(60),
|
||||
// 8 9 10 11 12 13 14 15
|
||||
V( 72), V( 76), V(78), V(80), V(81), V(82), V(83), V(83)
|
||||
V( 65), V( 69), V(71), V(73), V(74), V(75), V(76), V(76)
|
||||
};
|
||||
|
||||
// Rook mobility bonus in middle game and endgame, indexed by the number
|
||||
// of attacked squares not occupied by friendly pieces. X-ray attacks through
|
||||
// of attacked squares not occupied by friendly pieces. X-ray attacks through
|
||||
// queens and rooks are also included.
|
||||
const Value MidgameRookMobilityBonus[] = {
|
||||
// 0 1 2 3 4 5 6 7
|
||||
V(-18), V(-12), V(-6), V(0), V(6), V(12), V(16), V(21),
|
||||
V(-20), V(-14), V(-8), V(-2), V(4), V(10), V(14), V(19),
|
||||
// 8 9 10 11 12 13 14 15
|
||||
V( 24), V( 27), V(28), V(29), V(30), V(31), V(32), V(33)
|
||||
V( 23), V( 26), V(27), V(28), V(29), V(30), V(31), V(32)
|
||||
};
|
||||
|
||||
const Value EndgameRookMobilityBonus[] = {
|
||||
// 0 1 2 3 4 5 6 7
|
||||
V(-30), V(-18), V(-6), V(6), V(18), V(30), V(42), V(54),
|
||||
V(-36), V(-19), V(-3), V(13), V(29), V(46), V(62), V(79),
|
||||
// 8 9 10 11 12 13 14 15
|
||||
V( 66), V( 74), V(78), V(80), V(81), V(82), V(83), V(83)
|
||||
V( 95), V(106),V(111),V(114),V(116),V(117),V(118),V(118)
|
||||
};
|
||||
|
||||
// Queen mobility bonus in middle game and endgame, indexed by the number
|
||||
// of attacked squares not occupied by friendly pieces.
|
||||
const Value MidgameQueenMobilityBonus[] = {
|
||||
// 0 1 2 3 4 5 6 7
|
||||
V(-10), V(-8), V(-6), V(-4), V(-2), V( 0), V( 2), V( 4),
|
||||
V(-10), V(-8), V(-6), V(-3), V(-1), V( 1), V( 3), V( 5),
|
||||
// 8 9 10 11 12 13 14 15
|
||||
V( 6), V( 8), V(10), V(12), V(13), V(14), V(15), V(16),
|
||||
V( 8), V(10), V(12), V(15), V(16), V(17), V(18), V(20),
|
||||
// 16 17 18 19 20 21 22 23
|
||||
V( 16), V(16), V(16), V(16), V(16), V(16), V(16), V(16),
|
||||
V( 20), V(20), V(20), V(20), V(20), V(20), V(20), V(20),
|
||||
// 24 25 26 27 28 29 30 31
|
||||
V( 16), V(16), V(16), V(16), V(16), V(16), V(16), V(16)
|
||||
V( 20), V(20), V(20), V(20), V(20), V(20), V(20), V(20)
|
||||
};
|
||||
|
||||
const Value EndgameQueenMobilityBonus[] = {
|
||||
// 0 1 2 3 4 5 6 7
|
||||
V(-20),V(-15),V(-10), V(-5), V( 0), V( 5), V(10), V(15),
|
||||
V(-18),V(-13), V(-7), V(-2), V( 3), V (8), V(13), V(19),
|
||||
// 8 9 10 11 12 13 14 15
|
||||
V( 19), V(23), V(27), V(29), V(30), V(30), V(30), V(30),
|
||||
V( 23), V(27), V(32), V(34), V(35), V(35), V(35), V(35),
|
||||
// 16 17 18 19 20 21 22 23
|
||||
V( 30), V(30), V(30), V(30), V(30), V(30), V(30), V(30),
|
||||
V( 35), V(35), V(35), V(35), V(35), V(35), V(35), V(35),
|
||||
// 24 25 26 27 28 29 30 31
|
||||
V( 30), V(30), V(30), V(30), V(30), V(30), V(30), V(30)
|
||||
V( 35), V(35), V(35), V(35), V(35), V(35), V(35), V(35)
|
||||
};
|
||||
|
||||
// Outpost bonuses for knights and bishops, indexed by square (from white's
|
||||
@@ -149,10 +149,10 @@ namespace {
|
||||
// A B C D E F G H
|
||||
V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 1
|
||||
V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 2
|
||||
V(0), V(0), V(5),V(10),V(10), V(5), V(0), V(0), // 3
|
||||
V(0), V(5),V(20),V(30),V(30),V(20), V(5), V(0), // 4
|
||||
V(0),V(10),V(30),V(40),V(40),V(30),V(10), V(0), // 5
|
||||
V(0), V(5),V(20),V(20),V(20),V(20), V(5), V(0), // 6
|
||||
V(0), V(0), V(4), V(8), V(8), V(4), V(0), V(0), // 3
|
||||
V(0), V(4),V(17),V(26),V(26),V(17), V(4), V(0), // 4
|
||||
V(0), V(8),V(26),V(35),V(35),V(26), V(8), V(0), // 5
|
||||
V(0), V(4),V(17),V(17),V(17),V(17), V(4), V(0), // 6
|
||||
V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 7
|
||||
V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0) // 8
|
||||
};
|
||||
@@ -163,7 +163,7 @@ namespace {
|
||||
V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 2
|
||||
V(0), V(0), V(5), V(5), V(5), V(5), V(0), V(0), // 3
|
||||
V(0), V(5),V(10),V(10),V(10),V(10), V(5), V(0), // 4
|
||||
V(0),V(10),V(20),V(20),V(20),V(20),V(10), V(0), // 5
|
||||
V(0),V(10),V(21),V(21),V(21),V(21),V(10), V(0), // 5
|
||||
V(0), V(5), V(8), V(8), V(8), V(8), V(5), V(0), // 6
|
||||
V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 7
|
||||
V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0) // 8
|
||||
@@ -172,44 +172,43 @@ namespace {
|
||||
// Bonus for unstoppable passed pawns
|
||||
const Value UnstoppablePawnValue = Value(0x500);
|
||||
|
||||
// Rooks and queens on the 7th rank
|
||||
// Rooks and queens on the 7th rank (modified by Joona Kiiski)
|
||||
const Value MidgameRookOn7thBonus = Value(47);
|
||||
const Value EndgameRookOn7thBonus = Value(98);
|
||||
const Value MidgameQueenOn7thBonus = Value(27);
|
||||
const Value EndgameQueenOn7thBonus = Value(54);
|
||||
|
||||
|
||||
// Rooks on open files
|
||||
// Rooks on open files (modified by Joona Kiiski)
|
||||
const Value RookOpenFileBonus = Value(43);
|
||||
const Value RookHalfOpenFileBonus = Value(19);
|
||||
|
||||
// Penalty for rooks trapped inside a friendly king which has lost the
|
||||
// right to castle:
|
||||
// right to castle.
|
||||
const Value TrappedRookPenalty = Value(180);
|
||||
|
||||
// Penalty for a bishop on a7/h7 (a2/h2 for black) which is trapped by
|
||||
// enemy pawns:
|
||||
// enemy pawns.
|
||||
const Value TrappedBishopA7H7Penalty = Value(300);
|
||||
|
||||
// Bitboard masks for detecting trapped bishops on a7/h7 (a2/h2 for black):
|
||||
// Bitboard masks for detecting trapped bishops on a7/h7 (a2/h2 for black)
|
||||
const Bitboard MaskA7H7[2] = {
|
||||
((1ULL << SQ_A7) | (1ULL << SQ_H7)),
|
||||
((1ULL << SQ_A2) | (1ULL << SQ_H2))
|
||||
};
|
||||
|
||||
// Penalty for a bishop on a1/h1 (a8/h8 for black) which is trapped by
|
||||
// a friendly pawn on b2/g2 (b7/g7 for black). This can obviously only
|
||||
// a friendly pawn on b2/g2 (b7/g7 for black). This can obviously only
|
||||
// happen in Chess960 games.
|
||||
const Value TrappedBishopA1H1Penalty = Value(100);
|
||||
|
||||
// Bitboard masks for detecting trapped bishops on a1/h1 (a8/h8 for black):
|
||||
// Bitboard masks for detecting trapped bishops on a1/h1 (a8/h8 for black)
|
||||
const Bitboard MaskA1H1[2] = {
|
||||
((1ULL << SQ_A1) | (1ULL << SQ_H1)),
|
||||
((1ULL << SQ_A8) | (1ULL << SQ_H8))
|
||||
};
|
||||
|
||||
// The SpaceMask[color] contains area of the board which is consdered by
|
||||
// the space evaluation. In the middle game, each side is given a bonus
|
||||
// the space evaluation. In the middle game, each side is given a bonus
|
||||
// based on how many squares inside this area are safe and available for
|
||||
// friendly minor pieces.
|
||||
const Bitboard SpaceMask[2] = {
|
||||
@@ -221,30 +220,26 @@ namespace {
|
||||
(1ULL<<SQ_C5) | (1ULL<<SQ_D5) | (1ULL<<SQ_E5) | (1ULL<<SQ_F5)
|
||||
};
|
||||
|
||||
/// King safety constants and variables. The king safety scores are taken
|
||||
/// from the array SafetyTable[]. Various little "meta-bonuses" measuring
|
||||
/// King safety constants and variables. The king safety scores are taken
|
||||
/// from the array SafetyTable[]. Various little "meta-bonuses" measuring
|
||||
/// the strength of the attack are added up into an integer, which is used
|
||||
/// as an index to SafetyTable[].
|
||||
|
||||
// Attack weights for each piece type.
|
||||
// Attack weights for each piece type
|
||||
const int QueenAttackWeight = 5;
|
||||
const int RookAttackWeight = 3;
|
||||
const int BishopAttackWeight = 2;
|
||||
const int KnightAttackWeight = 2;
|
||||
|
||||
// Bonuses for safe checks for each piece type.
|
||||
int QueenContactCheckBonus = 3;
|
||||
int QueenCheckBonus = 2;
|
||||
int RookCheckBonus = 1;
|
||||
int BishopCheckBonus = 1;
|
||||
int KnightCheckBonus = 1;
|
||||
int DiscoveredCheckBonus = 3;
|
||||
// Bonuses for safe checks, initialized from UCI options
|
||||
int QueenContactCheckBonus, DiscoveredCheckBonus;
|
||||
int QueenCheckBonus, RookCheckBonus, BishopCheckBonus, KnightCheckBonus;
|
||||
|
||||
// Scan for queen contact mates?
|
||||
const bool QueenContactMates = true;
|
||||
|
||||
// Bonus for having a mate threat.
|
||||
int MateThreatBonus = 3;
|
||||
// Bonus for having a mate threat, initialized from UCI options
|
||||
int MateThreatBonus;
|
||||
|
||||
// InitKingDanger[] contains bonuses based on the position of the defending
|
||||
// king.
|
||||
@@ -259,40 +254,41 @@ namespace {
|
||||
15, 15, 15, 15, 15, 15, 15, 15
|
||||
};
|
||||
|
||||
// SafetyTable[] contains the actual king safety scores. It is initialized
|
||||
// SafetyTable[] contains the actual king safety scores. It is initialized
|
||||
// in init_safety().
|
||||
Value SafetyTable[100];
|
||||
|
||||
// Pawn and material hash tables, indexed by the current thread id
|
||||
PawnInfoTable *PawnTable[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
MaterialInfoTable *MaterialTable[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
PawnInfoTable* PawnTable[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
MaterialInfoTable* MaterialTable[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
// Sizes of pawn and material hash tables
|
||||
const int PawnTableSize = 16384;
|
||||
const int MaterialTableSize = 1024;
|
||||
|
||||
// Array which gives the number of nonzero bits in an 8-bit integer:
|
||||
// Array which gives the number of nonzero bits in an 8-bit integer
|
||||
uint8_t BitCount8Bit[256];
|
||||
|
||||
// Function prototypes
|
||||
template<PieceType Piece>
|
||||
template<bool HasPopCnt>
|
||||
Value do_evaluate(const Position& pos, EvalInfo& ei, int threadID);
|
||||
|
||||
template<PieceType Piece, bool HasPopCnt>
|
||||
void evaluate_pieces(const Position& p, Color us, EvalInfo& ei);
|
||||
|
||||
template<>
|
||||
void evaluate_pieces<KING>(const Position& p, Color us, EvalInfo &ei);
|
||||
template<bool HasPopCnt>
|
||||
void evaluate_king(const Position& p, Color us, EvalInfo &ei);
|
||||
|
||||
void evaluate_passed_pawns(const Position &pos, EvalInfo &ei);
|
||||
void evaluate_trapped_bishop_a7h7(const Position &pos, Square s, Color us,
|
||||
EvalInfo &ei);
|
||||
void evaluate_trapped_bishop_a1h1(const Position &pos, Square s, Color us,
|
||||
EvalInfo &ei);
|
||||
|
||||
template<bool HasPopCnt>
|
||||
void evaluate_space(const Position &p, Color us, EvalInfo &ei);
|
||||
inline Value apply_weight(Value v, int w);
|
||||
Value scale_by_game_phase(Value mv, Value ev, Phase ph, const ScaleFactor sf[]);
|
||||
|
||||
int count_1s_8bit(Bitboard b);
|
||||
|
||||
int compute_weight(int uciWeight, int internalWeight);
|
||||
int weight_option(const std::string& opt, int weight);
|
||||
void init_safety();
|
||||
@@ -304,11 +300,19 @@ namespace {
|
||||
//// Functions
|
||||
////
|
||||
|
||||
/// evaluate() is the main evaluation function. It always computes two
|
||||
/// evaluate() is the main evaluation function. It always computes two
|
||||
/// values, an endgame score and a middle game score, and interpolates
|
||||
/// between them based on the remaining material.
|
||||
Value evaluate(const Position& pos, EvalInfo& ei, int threadID) {
|
||||
|
||||
Value evaluate(const Position &pos, EvalInfo &ei, int threadID) {
|
||||
return CpuHasPOPCNT ? do_evaluate<true>(pos, ei, threadID)
|
||||
: do_evaluate<false>(pos, ei, threadID);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template<bool HasPopCnt>
|
||||
Value do_evaluate(const Position& pos, EvalInfo& ei, int threadID) {
|
||||
|
||||
assert(pos.is_ok());
|
||||
assert(threadID >= 0 && threadID < THREAD_MAX);
|
||||
@@ -349,16 +353,16 @@ Value evaluate(const Position &pos, EvalInfo &ei, int threadID) {
|
||||
// Initialize pawn attack bitboards for both sides
|
||||
ei.attackedBy[WHITE][PAWN] = ((pos.pawns(WHITE) << 9) & ~FileABB) | ((pos.pawns(WHITE) << 7) & ~FileHBB);
|
||||
ei.attackedBy[BLACK][PAWN] = ((pos.pawns(BLACK) >> 7) & ~FileABB) | ((pos.pawns(BLACK) >> 9) & ~FileHBB);
|
||||
ei.kingAttackersCount[WHITE] = count_1s_max_15(ei.attackedBy[WHITE][PAWN] & ei.attackedBy[BLACK][KING])/2;
|
||||
ei.kingAttackersCount[BLACK] = count_1s_max_15(ei.attackedBy[BLACK][PAWN] & ei.attackedBy[WHITE][KING])/2;
|
||||
ei.kingAttackersCount[WHITE] = count_1s_max_15<HasPopCnt>(ei.attackedBy[WHITE][PAWN] & ei.attackedBy[BLACK][KING])/2;
|
||||
ei.kingAttackersCount[BLACK] = count_1s_max_15<HasPopCnt>(ei.attackedBy[BLACK][PAWN] & ei.attackedBy[WHITE][KING])/2;
|
||||
|
||||
// Evaluate pieces
|
||||
for (Color c = WHITE; c <= BLACK; c++)
|
||||
{
|
||||
evaluate_pieces<KNIGHT>(pos, c, ei);
|
||||
evaluate_pieces<BISHOP>(pos, c, ei);
|
||||
evaluate_pieces<ROOK>(pos, c, ei);
|
||||
evaluate_pieces<QUEEN>(pos, c, ei);
|
||||
evaluate_pieces<KNIGHT, HasPopCnt>(pos, c, ei);
|
||||
evaluate_pieces<BISHOP, HasPopCnt>(pos, c, ei);
|
||||
evaluate_pieces<ROOK, HasPopCnt>(pos, c, ei);
|
||||
evaluate_pieces<QUEEN, HasPopCnt>(pos, c, ei);
|
||||
|
||||
// Sum up all attacked squares
|
||||
ei.attackedBy[c][0] = ei.attackedBy[c][PAWN] | ei.attackedBy[c][KNIGHT]
|
||||
@@ -366,11 +370,11 @@ Value evaluate(const Position &pos, EvalInfo &ei, int threadID) {
|
||||
| ei.attackedBy[c][QUEEN] | ei.attackedBy[c][KING];
|
||||
}
|
||||
|
||||
// Kings. Kings are evaluated after all other pieces for both sides,
|
||||
// Kings. Kings are evaluated after all other pieces for both sides,
|
||||
// because we need complete attack information for all pieces when computing
|
||||
// the king safety evaluation.
|
||||
for (Color c = WHITE; c <= BLACK; c++)
|
||||
evaluate_pieces<KING>(pos, c, ei);
|
||||
evaluate_king<HasPopCnt>(pos, c, ei);
|
||||
|
||||
// Evaluate passed pawns. We evaluate passed pawns for both sides at once,
|
||||
// because we need to know which side promotes first in positions where
|
||||
@@ -399,8 +403,8 @@ Value evaluate(const Position &pos, EvalInfo &ei, int threadID) {
|
||||
// Evaluate space for both sides
|
||||
if (ei.mi->space_weight() > 0)
|
||||
{
|
||||
evaluate_space(pos, WHITE, ei);
|
||||
evaluate_space(pos, BLACK, ei);
|
||||
evaluate_space<HasPopCnt>(pos, WHITE, ei);
|
||||
evaluate_space<HasPopCnt>(pos, BLACK, ei);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,6 +450,7 @@ Value evaluate(const Position &pos, EvalInfo &ei, int threadID) {
|
||||
return (ei.mateThreat[stm] == MOVE_NONE ? v : 8 * QueenValueMidgame - v);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/// quick_evaluate() does a very approximate evaluation of the current position.
|
||||
/// It currently considers only material and piece square table scores. Perhaps
|
||||
@@ -505,6 +510,8 @@ void quit_eval() {
|
||||
{
|
||||
delete PawnTable[i];
|
||||
delete MaterialTable[i];
|
||||
PawnTable[i] = NULL;
|
||||
MaterialTable[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,76 +540,76 @@ void read_weights(Color us) {
|
||||
|
||||
namespace {
|
||||
|
||||
// evaluate_common() computes terms common to all pieces attack
|
||||
// evaluate_mobility() computes mobility and attacks for every piece
|
||||
|
||||
template<PieceType Piece>
|
||||
int evaluate_common(const Position& p, const Bitboard& b, Color us, EvalInfo& ei, Square s = SQ_NONE) {
|
||||
template<PieceType Piece, bool HasPopCnt>
|
||||
int evaluate_mobility(const Position& p, const Bitboard& b, Color us, Color them, EvalInfo& ei) {
|
||||
|
||||
static const int AttackWeight[] = { 0, 0, KnightAttackWeight, BishopAttackWeight, RookAttackWeight, QueenAttackWeight };
|
||||
static const Value* MgBonus[] = { 0, 0, MidgameKnightMobilityBonus, MidgameBishopMobilityBonus, MidgameRookMobilityBonus, MidgameQueenMobilityBonus };
|
||||
static const Value* EgBonus[] = { 0, 0, EndgameKnightMobilityBonus, EndgameBishopMobilityBonus, EndgameRookMobilityBonus, EndgameQueenMobilityBonus };
|
||||
static const Value* OutpostBonus[] = { 0, 0, KnightOutpostBonus, BishopOutpostBonus, 0, 0 };
|
||||
|
||||
Color them = opposite_color(us);
|
||||
|
||||
// Update attack info
|
||||
ei.attackedBy[us][Piece] |= b;
|
||||
|
||||
// King attack
|
||||
// King attacks
|
||||
if (b & ei.kingZone[us])
|
||||
{
|
||||
ei.kingAttackersCount[us]++;
|
||||
ei.kingAttackersWeight[us] += AttackWeight[Piece];
|
||||
Bitboard bb = (b & ei.attackedBy[them][KING]);
|
||||
if (bb)
|
||||
ei.kingAdjacentZoneAttacksCount[us] += count_1s_max_15(bb);
|
||||
ei.kingAdjacentZoneAttacksCount[us] += count_1s_max_15<HasPopCnt>(bb);
|
||||
}
|
||||
|
||||
// Remove squares protected by enemy pawns
|
||||
Bitboard bb = (b & ~ei.attackedBy[them][PAWN]);
|
||||
|
||||
// Mobility
|
||||
int mob = (Piece != QUEEN ? count_1s_max_15(bb & ~p.pieces_of_color(us))
|
||||
: count_1s(bb & ~p.pieces_of_color(us)));
|
||||
int mob = (Piece != QUEEN ? count_1s_max_15<HasPopCnt>(bb & ~p.pieces_of_color(us))
|
||||
: count_1s<HasPopCnt>(bb & ~p.pieces_of_color(us)));
|
||||
|
||||
ei.mgMobility += Sign[us] * MgBonus[Piece][mob];
|
||||
ei.egMobility += Sign[us] * EgBonus[Piece][mob];
|
||||
return mob;
|
||||
}
|
||||
|
||||
// Bishop and Knight outposts
|
||||
if ( (Piece != BISHOP && Piece != KNIGHT) // compile time condition
|
||||
|| !p.square_is_weak(s, them))
|
||||
return mob;
|
||||
|
||||
// evaluate_outposts() evaluates bishop and knight outposts squares
|
||||
|
||||
template<PieceType Piece>
|
||||
void evaluate_outposts(const Position& p, Color us, Color them, EvalInfo& ei, Square s) {
|
||||
|
||||
// Initial bonus based on square
|
||||
Value v, bonus;
|
||||
v = bonus = OutpostBonus[Piece][relative_square(us, s)];
|
||||
Value bonus = (Piece == BISHOP ? BishopOutpostBonus[relative_square(us, s)]
|
||||
: KnightOutpostBonus[relative_square(us, s)]);
|
||||
|
||||
// Increase bonus if supported by pawn, especially if the opponent has
|
||||
// no minor piece which can exchange the outpost piece
|
||||
if (v && (p.pawn_attacks(them, s) & p.pawns(us)))
|
||||
if (bonus && (p.pawn_attacks(them, s) & p.pawns(us)))
|
||||
{
|
||||
bonus += v / 2;
|
||||
if ( p.piece_count(them, KNIGHT) == 0
|
||||
if ( p.knights(them) == EmptyBoardBB
|
||||
&& (SquaresByColorBB[square_color(s)] & p.bishops(them)) == EmptyBoardBB)
|
||||
bonus += v;
|
||||
bonus += bonus + bonus / 2;
|
||||
else
|
||||
bonus += bonus / 2;
|
||||
}
|
||||
ei.mgValue += Sign[us] * bonus;
|
||||
ei.egValue += Sign[us] * bonus;
|
||||
return mob;
|
||||
}
|
||||
|
||||
|
||||
// evaluate_pieces<>() assigns bonuses and penalties to the pieces of a given
|
||||
// color.
|
||||
|
||||
template<PieceType Piece>
|
||||
template<PieceType Piece, bool HasPopCnt>
|
||||
void evaluate_pieces(const Position& pos, Color us, EvalInfo& ei) {
|
||||
|
||||
Bitboard b;
|
||||
Square s, ksq;
|
||||
Color them;
|
||||
int mob;
|
||||
File f;
|
||||
Color them = opposite_color(us);
|
||||
|
||||
for (int i = 0, e = pos.piece_count(us, Piece); i < e; i++)
|
||||
{
|
||||
@@ -614,9 +621,15 @@ namespace {
|
||||
b = bishop_attacks_bb(s, pos.occupied_squares() & ~pos.queens(us));
|
||||
else if (Piece == ROOK)
|
||||
b = rook_attacks_bb(s, pos.occupied_squares() & ~pos.rooks_and_queens(us));
|
||||
else
|
||||
assert(false);
|
||||
|
||||
// Attacks, mobility and outposts
|
||||
mob = evaluate_common<Piece>(pos, b, us, ei, s);
|
||||
// Attacks and mobility
|
||||
mob = evaluate_mobility<Piece, HasPopCnt>(pos, b, us, them, ei);
|
||||
|
||||
// Bishop and knight outposts squares
|
||||
if ((Piece == BISHOP || Piece == KNIGHT) && pos.square_is_weak(s, them))
|
||||
evaluate_outposts<Piece>(pos, us, them, ei, s);
|
||||
|
||||
// Special patterns: trapped bishops on a7/h7/a2/h2
|
||||
// and trapped bishops on a1/h1/a8/h8 in Chess960.
|
||||
@@ -632,8 +645,6 @@ namespace {
|
||||
if (Piece == ROOK || Piece == QUEEN)
|
||||
{
|
||||
// Queen or rook on 7th rank
|
||||
them = opposite_color(us);
|
||||
|
||||
if ( relative_rank(us, s) == RANK_7
|
||||
&& relative_rank(us, pos.king_square(them)) == RANK_8)
|
||||
{
|
||||
@@ -695,11 +706,10 @@ namespace {
|
||||
return b >> (num << 3);
|
||||
}
|
||||
|
||||
// evaluate_pieces<KING>() assigns bonuses and penalties to a king of a given
|
||||
// color.
|
||||
// evaluate_king<>() assigns bonuses and penalties to a king of a given color.
|
||||
|
||||
template<>
|
||||
void evaluate_pieces<KING>(const Position& p, Color us, EvalInfo& ei) {
|
||||
template<bool HasPopCnt>
|
||||
void evaluate_king(const Position& p, Color us, EvalInfo& ei) {
|
||||
|
||||
int shelter = 0, sign = Sign[us];
|
||||
Square s = p.king_square(us);
|
||||
@@ -707,15 +717,23 @@ namespace {
|
||||
// King shelter
|
||||
if (relative_rank(us, s) <= RANK_4)
|
||||
{
|
||||
Bitboard pawns = p.pawns(us) & this_and_neighboring_files_bb(s);
|
||||
Rank r = square_rank(s);
|
||||
for (int i = 1; i < 4; i++)
|
||||
shelter += count_1s_8bit(shiftRowsDown(pawns, r+i*sign)) * (128>>i);
|
||||
// Shelter cache lookup
|
||||
shelter = ei.pi->kingShelter(us, s);
|
||||
if (shelter == -1)
|
||||
{
|
||||
shelter = 0;
|
||||
Bitboard pawns = p.pawns(us) & this_and_neighboring_files_bb(s);
|
||||
Rank r = square_rank(s);
|
||||
for (int i = 1; i < 4; i++)
|
||||
shelter += BitCount8Bit[shiftRowsDown(pawns, r+i*sign) & 0xFF] * (128 >> i);
|
||||
|
||||
// Cache shelter value in pawn info
|
||||
ei.pi->setKingShelter(us, s, shelter);
|
||||
}
|
||||
ei.mgValue += sign * Value(shelter);
|
||||
}
|
||||
|
||||
// King safety. This is quite complicated, and is almost certainly far
|
||||
// King safety. This is quite complicated, and is almost certainly far
|
||||
// from optimally tuned.
|
||||
Color them = opposite_color(us);
|
||||
|
||||
@@ -744,7 +762,7 @@ namespace {
|
||||
// quality of the pawn shelter.
|
||||
int attackUnits =
|
||||
Min((ei.kingAttackersCount[them] * ei.kingAttackersWeight[them]) / 2, 25)
|
||||
+ (ei.kingAdjacentZoneAttacksCount[them] + count_1s_max_15(undefended)) * 3
|
||||
+ (ei.kingAdjacentZoneAttacksCount[them] + count_1s_max_15<HasPopCnt>(undefended)) * 3
|
||||
+ InitKingDanger[relative_square(us, s)] - (shelter >> 5);
|
||||
|
||||
// Analyse safe queen contact checks
|
||||
@@ -760,7 +778,7 @@ namespace {
|
||||
{
|
||||
// The bitboard b now contains the squares available for safe queen
|
||||
// contact checks.
|
||||
int count = count_1s_max_15(b);
|
||||
int count = count_1s_max_15<HasPopCnt>(b);
|
||||
attackUnits += QueenContactCheckBonus * count * (sente ? 2 : 1);
|
||||
|
||||
// Is there a mate threat?
|
||||
@@ -800,12 +818,12 @@ namespace {
|
||||
// Queen checks
|
||||
b2 = b & ei.attacked_by(them, QUEEN);
|
||||
if( b2)
|
||||
attackUnits += QueenCheckBonus * count_1s_max_15(b2);
|
||||
attackUnits += QueenCheckBonus * count_1s_max_15<HasPopCnt>(b2);
|
||||
|
||||
// Rook checks
|
||||
b2 = b & ei.attacked_by(them, ROOK);
|
||||
if (b2)
|
||||
attackUnits += RookCheckBonus * count_1s_max_15(b2);
|
||||
attackUnits += RookCheckBonus * count_1s_max_15<HasPopCnt>(b2);
|
||||
}
|
||||
if (QueenCheckBonus > 0 || BishopCheckBonus > 0)
|
||||
{
|
||||
@@ -814,12 +832,12 @@ namespace {
|
||||
// Queen checks
|
||||
b2 = b & ei.attacked_by(them, QUEEN);
|
||||
if (b2)
|
||||
attackUnits += QueenCheckBonus * count_1s_max_15(b2);
|
||||
attackUnits += QueenCheckBonus * count_1s_max_15<HasPopCnt>(b2);
|
||||
|
||||
// Bishop checks
|
||||
b2 = b & ei.attacked_by(them, BISHOP);
|
||||
if (b2)
|
||||
attackUnits += BishopCheckBonus * count_1s_max_15(b2);
|
||||
attackUnits += BishopCheckBonus * count_1s_max_15<HasPopCnt>(b2);
|
||||
}
|
||||
if (KnightCheckBonus > 0)
|
||||
{
|
||||
@@ -828,7 +846,7 @@ namespace {
|
||||
// Knight checks
|
||||
b2 = b & ei.attacked_by(them, KNIGHT);
|
||||
if (b2)
|
||||
attackUnits += KnightCheckBonus * count_1s_max_15(b2);
|
||||
attackUnits += KnightCheckBonus * count_1s_max_15<HasPopCnt>(b2);
|
||||
}
|
||||
|
||||
// Analyse discovered checks (only for non-pawns right now, consider
|
||||
@@ -837,7 +855,7 @@ namespace {
|
||||
{
|
||||
b = p.discovered_check_candidates(them) & ~p.pawns();
|
||||
if (b)
|
||||
attackUnits += DiscoveredCheckBonus * count_1s_max_15(b) * (sente? 2 : 1);
|
||||
attackUnits += DiscoveredCheckBonus * count_1s_max_15<HasPopCnt>(b) * (sente? 2 : 1);
|
||||
}
|
||||
|
||||
// Has a mate threat been found? We don't do anything here if the
|
||||
@@ -920,29 +938,23 @@ namespace {
|
||||
&& (squares_behind(us, s) & pos.rooks_and_queens(them)))
|
||||
b3 = b2;
|
||||
|
||||
if ((b2 & pos.pieces_of_color(them)) == EmptyBoardBB)
|
||||
{
|
||||
// There are no enemy pieces in the pawn's path! Are any of the
|
||||
// squares in the pawn's path attacked by the enemy?
|
||||
if (b3 == EmptyBoardBB)
|
||||
// No enemy attacks, huge bonus!
|
||||
ebonus += Value(tr * (b2 == b4 ? 17 : 15));
|
||||
else
|
||||
// OK, there are enemy attacks. Are those squares which are
|
||||
// attacked by the enemy also attacked by us? If yes, big bonus
|
||||
// (but smaller than when there are no enemy attacks), if no,
|
||||
// somewhat smaller bonus.
|
||||
ebonus += Value(tr * ((b3 & b4) == b3 ? 13 : 8));
|
||||
}
|
||||
// Squares attacked or occupied by enemy pieces
|
||||
b3 |= (b2 & pos.pieces_of_color(them));
|
||||
|
||||
// There are no enemy pawns in the pawn's path
|
||||
assert((b2 & pos.pieces_of_color_and_type(them, PAWN)) == EmptyBoardBB);
|
||||
|
||||
// Are any of the squares in the pawn's path attacked or occupied by the enemy?
|
||||
if (b3 == EmptyBoardBB)
|
||||
// No enemy attacks or pieces, huge bonus!
|
||||
ebonus += Value(tr * (b2 == b4 ? 17 : 15));
|
||||
else
|
||||
{
|
||||
// There are some enemy pieces in the pawn's path. While this is
|
||||
// sad, we still assign a moderate bonus if all squares in the path
|
||||
// which are either occupied by or attacked by enemy pieces are
|
||||
// also attacked by us.
|
||||
if (((b3 | (b2 & pos.pieces_of_color(them))) & ~b4) == EmptyBoardBB)
|
||||
ebonus += Value(tr * 6);
|
||||
}
|
||||
// OK, there are enemy attacks or pieces (but not pawns). Are those
|
||||
// squares which are attacked by the enemy also attacked by us?
|
||||
// If yes, big bonus (but smaller than when there are no enemy attacks),
|
||||
// if no, somewhat smaller bonus.
|
||||
ebonus += Value(tr * ((b3 & b4) == b3 ? 13 : 8));
|
||||
|
||||
// At last, add a small bonus when there are no *friendly* pieces
|
||||
// in the pawn's path.
|
||||
if ((b2 & pos.pieces_of_color(us)) == EmptyBoardBB)
|
||||
@@ -982,7 +994,7 @@ namespace {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Rook pawns are a special case: They are sometimes worse, and
|
||||
// Rook pawns are a special case: They are sometimes worse, and
|
||||
// sometimes better than other passed pawns. It is difficult to find
|
||||
// good rules for determining whether they are good or bad. For now,
|
||||
// we try the following: Increase the value for rook pawns if the
|
||||
@@ -990,10 +1002,10 @@ namespace {
|
||||
// value if the other side has a rook or queen.
|
||||
if (square_file(s) == FILE_A || square_file(s) == FILE_H)
|
||||
{
|
||||
if( pos.non_pawn_material(them) <= KnightValueMidgame
|
||||
&& pos.piece_count(them, KNIGHT) <= 1)
|
||||
if ( pos.non_pawn_material(them) <= KnightValueMidgame
|
||||
&& pos.piece_count(them, KNIGHT) <= 1)
|
||||
ebonus += ebonus / 4;
|
||||
else if(pos.rooks_and_queens(them))
|
||||
else if (pos.rooks_and_queens(them))
|
||||
ebonus -= ebonus / 4;
|
||||
}
|
||||
|
||||
@@ -1005,9 +1017,9 @@ namespace {
|
||||
|
||||
// Does either side have an unstoppable passed pawn?
|
||||
if (hasUnstoppable[WHITE] && !hasUnstoppable[BLACK])
|
||||
ei.egValue += UnstoppablePawnValue - Value(0x40 * movesToGo[WHITE]);
|
||||
ei.egValue += UnstoppablePawnValue - Value(0x40 * movesToGo[WHITE]);
|
||||
else if (hasUnstoppable[BLACK] && !hasUnstoppable[WHITE])
|
||||
ei.egValue -= UnstoppablePawnValue - Value(0x40 * movesToGo[BLACK]);
|
||||
ei.egValue -= UnstoppablePawnValue - Value(0x40 * movesToGo[BLACK]);
|
||||
else if (hasUnstoppable[BLACK] && hasUnstoppable[WHITE])
|
||||
{
|
||||
// Both sides have unstoppable pawns! Try to find out who queens
|
||||
@@ -1105,7 +1117,7 @@ namespace {
|
||||
// squares one, two or three squares behind a friendly pawn are counted
|
||||
// twice. Finally, the space bonus is scaled by a weight taken from the
|
||||
// material hash table.
|
||||
|
||||
template<bool HasPopCnt>
|
||||
void evaluate_space(const Position &pos, Color us, EvalInfo &ei) {
|
||||
|
||||
Color them = opposite_color(us);
|
||||
@@ -1133,8 +1145,8 @@ namespace {
|
||||
behindFriendlyPawns |= (behindFriendlyPawns << 16);
|
||||
}
|
||||
|
||||
int space = count_1s_max_15(safeSquares)
|
||||
+ count_1s_max_15(behindFriendlyPawns & safeSquares);
|
||||
int space = count_1s_max_15<HasPopCnt>(safeSquares)
|
||||
+ count_1s_max_15<HasPopCnt>(behindFriendlyPawns & safeSquares);
|
||||
|
||||
ei.mgValue += Sign[us] * apply_weight(Value(space * ei.mi->space_weight()), WeightSpace);
|
||||
}
|
||||
@@ -1164,15 +1176,6 @@ namespace {
|
||||
}
|
||||
|
||||
|
||||
// count_1s_8bit() counts the number of nonzero bits in the 8 least
|
||||
// significant bits of a Bitboard. This function is used by the king
|
||||
// shield evaluation.
|
||||
|
||||
int count_1s_8bit(Bitboard b) {
|
||||
return int(BitCount8Bit[b & 0xFF]);
|
||||
}
|
||||
|
||||
|
||||
// compute_weight() computes the value of an evaluation weight, by combining
|
||||
// an UCI-configurable weight with an internal weight.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
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,7 +39,7 @@
|
||||
/// arguments to the evaluation function, and the search can make use of its
|
||||
/// contents to make intelligent search decisions.
|
||||
///
|
||||
/// At the moment, this is not utilized very much: The only part of the
|
||||
/// At the moment, this is not utilized very much: The only part of the
|
||||
/// EvalInfo object which is used by the search is futilityMargin.
|
||||
class Position;
|
||||
|
||||
@@ -53,16 +53,16 @@ struct EvalInfo {
|
||||
PawnInfo* pi;
|
||||
|
||||
// attackedBy[color][piece type] is a bitboard representing all squares
|
||||
// attacked by a given color and piece type. attackedBy[color][0] contains
|
||||
// attacked by a given color and piece type, attackedBy[color][0] contains
|
||||
// all squares attacked by the given color.
|
||||
Bitboard attackedBy[2][8];
|
||||
Bitboard attacked_by(Color c) const { return attackedBy[c][0]; }
|
||||
Bitboard attacked_by(Color c, PieceType pt) const { return attackedBy[c][pt]; }
|
||||
|
||||
// kingZone[color] is the zone around the enemy king which is considered
|
||||
// by the king safety evaluation. This consists of the squares directly
|
||||
// by the king safety evaluation. This consists of the squares directly
|
||||
// adjacent to the king, and the three (or two, for a king on an edge file)
|
||||
// squares two ranks in front of the king. For instance, if black's king
|
||||
// squares two ranks in front of the king. For instance, if black's king
|
||||
// is on g8, kingZone[WHITE] is a bitboard containing the squares f8, h8,
|
||||
// f7, g7, h7, f6, g6 and h6.
|
||||
Bitboard kingZone[2];
|
||||
@@ -91,7 +91,7 @@ struct EvalInfo {
|
||||
// Middle game and endgame mobility scores.
|
||||
Value mgMobility, egMobility;
|
||||
|
||||
// Extra futility margin. This is added to the standard futility margin
|
||||
// Extra futility margin. This is added to the standard futility margin
|
||||
// in the quiescence search.
|
||||
Value futilityMargin;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -32,14 +32,13 @@
|
||||
//// Functions
|
||||
////
|
||||
|
||||
|
||||
/// Constructor
|
||||
|
||||
History::History() {
|
||||
this->clear();
|
||||
}
|
||||
History::History() { clear(); }
|
||||
|
||||
|
||||
/// History::clear() clears the history tables.
|
||||
/// History::clear() clears the history tables
|
||||
|
||||
void History::clear() {
|
||||
memset(history, 0, 2 * 8 * 64 * sizeof(int));
|
||||
@@ -48,55 +47,59 @@ void History::clear() {
|
||||
}
|
||||
|
||||
|
||||
/// History::success() registers a move as being successful. This is done
|
||||
/// History::success() registers a move as being successful. This is done
|
||||
/// whenever a non-capturing move causes a beta cutoff in the main search.
|
||||
/// The three parameters are the moving piece, the move itself, and the
|
||||
/// search depth.
|
||||
/// The three parameters are the moving piece, the destination square, and
|
||||
/// the search depth.
|
||||
|
||||
void History::success(Piece p, Square to, Depth d) {
|
||||
|
||||
void History::success(Piece p, Move m, Depth d) {
|
||||
assert(piece_is_ok(p));
|
||||
assert(move_is_ok(m));
|
||||
assert(square_is_ok(to));
|
||||
|
||||
history[p][move_to(m)] += int(d) * int(d);
|
||||
successCount[p][move_to(m)]++;
|
||||
history[p][to] += int(d) * int(d);
|
||||
successCount[p][to]++;
|
||||
|
||||
// Prevent history overflow:
|
||||
if(history[p][move_to(m)] >= HistoryMax)
|
||||
for(int i = 0; i < 16; i++)
|
||||
for(int j = 0; j < 64; j++)
|
||||
history[i][j] /= 2;
|
||||
// Prevent history overflow
|
||||
if (history[p][to] >= HistoryMax)
|
||||
for (int i = 0; i < 16; i++)
|
||||
for (int j = 0; j < 64; j++)
|
||||
history[i][j] /= 4;
|
||||
}
|
||||
|
||||
|
||||
/// History::failure() registers a move as being unsuccessful. The function is
|
||||
/// History::failure() registers a move as being unsuccessful. The function is
|
||||
/// called for each non-capturing move which failed to produce a beta cutoff
|
||||
/// at a node where a beta cutoff was finally found.
|
||||
|
||||
void History::failure(Piece p, Move m) {
|
||||
assert(piece_is_ok(p));
|
||||
assert(move_is_ok(m));
|
||||
void History::failure(Piece p, Square to) {
|
||||
|
||||
failureCount[p][move_to(m)]++;
|
||||
assert(piece_is_ok(p));
|
||||
assert(square_is_ok(to));
|
||||
|
||||
failureCount[p][to]++;
|
||||
}
|
||||
|
||||
|
||||
/// History::move_ordering_score() returns an integer value used to order the
|
||||
/// non-capturing moves in the MovePicker class.
|
||||
|
||||
int History::move_ordering_score(Piece p, Move m) const {
|
||||
assert(piece_is_ok(p));
|
||||
assert(move_is_ok(m));
|
||||
int History::move_ordering_score(Piece p, Square to) const {
|
||||
|
||||
return history[p][move_to(m)];
|
||||
assert(piece_is_ok(p));
|
||||
assert(square_is_ok(to));
|
||||
|
||||
return history[p][to];
|
||||
}
|
||||
|
||||
|
||||
/// History::ok_to_prune() decides whether a move has been sufficiently
|
||||
/// unsuccessful that it makes sense to prune it entirely.
|
||||
|
||||
bool History::ok_to_prune(Piece p, Move m, Depth d) const {
|
||||
assert(piece_is_ok(p));
|
||||
assert(move_is_ok(m));
|
||||
bool History::ok_to_prune(Piece p, Square to, Depth d) const {
|
||||
|
||||
return (int(d) * successCount[p][move_to(m)] < failureCount[p][move_to(m)]);
|
||||
assert(piece_is_ok(p));
|
||||
assert(square_is_ok(to));
|
||||
|
||||
return (int(d) * successCount[p][to] < failureCount[p][to]);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -34,19 +34,22 @@
|
||||
//// Types
|
||||
////
|
||||
|
||||
/// The History class stores statistics about how often different moves have
|
||||
/// been successful or unsuccessful during the current search. These
|
||||
/// statistics are used for reduction and move ordering decisions.
|
||||
/// The History class stores statistics about how often different moves
|
||||
/// have been successful or unsuccessful during the current search. These
|
||||
/// statistics are used for reduction and move ordering decisions. History
|
||||
/// entries are stored according only to moving piece and destination square,
|
||||
/// in particular two moves with different origin but same destination and
|
||||
/// same piece will be considered identical.
|
||||
|
||||
class History {
|
||||
|
||||
public:
|
||||
History();
|
||||
void clear();
|
||||
void success(Piece p, Move m, Depth d);
|
||||
void failure(Piece p, Move m);
|
||||
int move_ordering_score(Piece p, Move m) const;
|
||||
bool ok_to_prune(Piece p, Move m, Depth d) const;
|
||||
void success(Piece p, Square to, Depth d);
|
||||
void failure(Piece p, Square to);
|
||||
int move_ordering_score(Piece p, Square to) const;
|
||||
bool ok_to_prune(Piece p, Square to, Depth d) const;
|
||||
|
||||
private:
|
||||
int history[16][64]; // [piece][square]
|
||||
@@ -61,17 +64,13 @@ private:
|
||||
|
||||
/// HistoryMax controls how often the history counters will be scaled down:
|
||||
/// When the history score for a move gets bigger than HistoryMax, all
|
||||
/// entries in the table are divided by 2. It is difficult to guess what
|
||||
/// the ideal value of this constant is. Scaling down the scores often has
|
||||
/// entries in the table are divided by 2. It is difficult to guess what
|
||||
/// the ideal value of this constant is. Scaling down the scores often has
|
||||
/// the effect that parts of the search tree which have been searched
|
||||
/// recently have a bigger importance for move ordering than the moves which
|
||||
/// have been searched a long time ago.
|
||||
///
|
||||
/// Note that HistoryMax should probably be changed whenever the constant
|
||||
/// OnePly in depth.h is changed. This is somewhat annoying. Perhaps it
|
||||
/// would be better to scale down the history table at regular intervals?
|
||||
|
||||
const int HistoryMax = 50000;
|
||||
const int HistoryMax = 25000 * OnePly;
|
||||
|
||||
|
||||
#endif // !defined(HISTORY_H_INCLUDED)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
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,7 +23,7 @@
|
||||
|
||||
|
||||
// x86 assembly language locks or OS spin locks may perform faster than
|
||||
// mutex locks on some platforms. On my machine, mutexes seem to be the
|
||||
// mutex locks on some platforms. On my machine, mutexes seem to be the
|
||||
// best.
|
||||
|
||||
//#define ASM_LOCK
|
||||
|
||||
82
src/main.cpp
82
src/main.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -17,29 +17,28 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// To profile with callgrind uncomment following line
|
||||
//#define USE_CALLGRIND
|
||||
|
||||
|
||||
////
|
||||
//// Includes
|
||||
////
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "benchmark.h"
|
||||
#include "bitboard.h"
|
||||
#include "direction.h"
|
||||
#include "endgame.h"
|
||||
#include "evaluate.h"
|
||||
#include "material.h"
|
||||
#include "mersenne.h"
|
||||
#include "bitcount.h"
|
||||
#include "misc.h"
|
||||
#include "movepick.h"
|
||||
#include "position.h"
|
||||
#include "search.h"
|
||||
#include "thread.h"
|
||||
#include "uci.h"
|
||||
#include "ucioption.h"
|
||||
|
||||
using std::string;
|
||||
#ifdef USE_CALLGRIND
|
||||
#include <valgrind/callgrind.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
////
|
||||
//// Functions
|
||||
@@ -48,50 +47,43 @@ using std::string;
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
// Disable IO buffering
|
||||
std::cout.rdbuf()->pubsetbuf(NULL, 0);
|
||||
std::cin.rdbuf()->pubsetbuf(NULL, 0);
|
||||
cout.rdbuf()->pubsetbuf(NULL, 0);
|
||||
cin.rdbuf()->pubsetbuf(NULL, 0);
|
||||
|
||||
// Initialization
|
||||
init_mersenne();
|
||||
init_direction_table();
|
||||
init_bitboards();
|
||||
init_uci_options();
|
||||
Position::init_zobrist();
|
||||
Position::init_piece_square_tables();
|
||||
MovePicker::init_phase_table();
|
||||
init_eval(1);
|
||||
init_bitbases();
|
||||
init_threads();
|
||||
// Initialization through global resources manager
|
||||
Application::initialize();
|
||||
|
||||
// Make random number generation less deterministic, for book moves
|
||||
for (int i = abs(get_system_time() % 10000); i > 0; i--)
|
||||
genrand_int32();
|
||||
#ifdef USE_CALLGRIND
|
||||
CALLGRIND_START_INSTRUMENTATION;
|
||||
#endif
|
||||
|
||||
// Process command line arguments
|
||||
if (argc >= 2 && string(argv[1]) == "bench")
|
||||
// Process command line arguments if any
|
||||
if (argc > 1)
|
||||
{
|
||||
if (argc < 4 || argc > 7)
|
||||
if (string(argv[1]) != "bench" || argc < 4 || argc > 8)
|
||||
cout << "Usage: stockfish bench <hash size> <threads> "
|
||||
<< "[time = 60s] [fen positions file = default] "
|
||||
<< "[time, depth or node limited = time] "
|
||||
<< "[timing file name = none]" << endl;
|
||||
else
|
||||
{
|
||||
std::cout << "Usage: stockfish bench <hash size> <threads> "
|
||||
<< "[time = 60s] [fen positions file = default] "
|
||||
<< "[time, depth or node limited = time]"
|
||||
<< std::endl;
|
||||
exit(0);
|
||||
string time = argc > 4 ? argv[4] : "60";
|
||||
string fen = argc > 5 ? argv[5] : "default";
|
||||
string lim = argc > 6 ? argv[6] : "time";
|
||||
string tim = argc > 7 ? argv[7] : "";
|
||||
benchmark(string(argv[2]) + " " + string(argv[3]) + " " + time + " " + fen + " " + lim + " " + tim);
|
||||
}
|
||||
string time = argc > 4 ? argv[4] : "60";
|
||||
string fen = argc > 5 ? argv[5] : "default";
|
||||
string lim = argc > 6 ? argv[6] : "time";
|
||||
benchmark(string(argv[2]) + " " + string(argv[3]) + " " + time + " " + fen + " " + lim);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Print copyright notice
|
||||
std::cout << engine_name() << ". Copyright (C) "
|
||||
<< "2004-2008 Tord Romstad, Marco Costalba. "
|
||||
<< std::endl;
|
||||
cout << engine_name()
|
||||
<< ". By Tord Romstad, Marco Costalba, Joona Kiiski." << endl;
|
||||
|
||||
if (CpuHasPOPCNT)
|
||||
cout << "Good! CPU has hardware POPCNT. We will use it." << endl;
|
||||
|
||||
// Enter UCI mode
|
||||
uci_main_loop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
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,12 +23,12 @@
|
||||
////
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
#include "material.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
////
|
||||
//// Local definitions
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
namespace {
|
||||
|
||||
// Values modified by Joona Kiiski
|
||||
const Value BishopPairMidgameBonus = Value(109);
|
||||
const Value BishopPairEndgameBonus = Value(97);
|
||||
|
||||
@@ -59,9 +60,9 @@ public:
|
||||
EndgameScalingFunctionBase* getESF(Key key, Color* c) const;
|
||||
|
||||
private:
|
||||
void add(const std::string& keyCode, EndgameEvaluationFunctionBase* f);
|
||||
void add(const std::string& keyCode, Color c, EndgameScalingFunctionBase* f);
|
||||
Key buildKey(const std::string& keyCode);
|
||||
void add(const string& keyCode, EndgameEvaluationFunctionBase* f);
|
||||
void add(const string& keyCode, Color c, EndgameScalingFunctionBase* f);
|
||||
Key buildKey(const string& keyCode);
|
||||
|
||||
struct ScalingInfo
|
||||
{
|
||||
@@ -90,9 +91,8 @@ MaterialInfoTable::MaterialInfoTable(unsigned int numOfEntries) {
|
||||
{
|
||||
std::cerr << "Failed to allocate " << (numOfEntries * sizeof(MaterialInfo))
|
||||
<< " bytes for material hash table." << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
Application::exit_with_failure();
|
||||
}
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -100,17 +100,8 @@ MaterialInfoTable::MaterialInfoTable(unsigned int numOfEntries) {
|
||||
|
||||
MaterialInfoTable::~MaterialInfoTable() {
|
||||
|
||||
delete [] entries;
|
||||
delete funcs;
|
||||
}
|
||||
|
||||
|
||||
/// MaterialInfoTable::clear() clears a material hash table by setting
|
||||
/// all entries to 0.
|
||||
|
||||
void MaterialInfoTable::clear() {
|
||||
|
||||
memset(entries, 0, size * sizeof(MaterialInfo));
|
||||
delete [] entries;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,14 +143,14 @@ MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) {
|
||||
|
||||
else if ( pos.non_pawn_material(BLACK) == Value(0)
|
||||
&& pos.piece_count(BLACK, PAWN) == 0
|
||||
&& pos.non_pawn_material(WHITE) >= RookValueEndgame)
|
||||
&& pos.non_pawn_material(WHITE) >= RookValueMidgame)
|
||||
{
|
||||
mi->evaluationFunction = &EvaluateKXK;
|
||||
return mi;
|
||||
}
|
||||
else if ( pos.non_pawn_material(WHITE) == Value(0)
|
||||
&& pos.piece_count(WHITE, PAWN) == 0
|
||||
&& pos.non_pawn_material(BLACK) >= RookValueEndgame)
|
||||
&& pos.non_pawn_material(BLACK) >= RookValueMidgame)
|
||||
{
|
||||
mi->evaluationFunction = &EvaluateKKX;
|
||||
return mi;
|
||||
@@ -352,7 +343,7 @@ EndgameFunctions::EndgameFunctions() {
|
||||
add("KRPKRPP", BLACK, &ScaleKRPKRPP);
|
||||
}
|
||||
|
||||
Key EndgameFunctions::buildKey(const std::string& keyCode) {
|
||||
Key EndgameFunctions::buildKey(const string& keyCode) {
|
||||
|
||||
assert(keyCode.length() > 0 && keyCode[0] == 'K');
|
||||
assert(keyCode.length() < 8);
|
||||
@@ -373,12 +364,12 @@ Key EndgameFunctions::buildKey(const std::string& keyCode) {
|
||||
return Position(s.str()).get_material_key();
|
||||
}
|
||||
|
||||
void EndgameFunctions::add(const std::string& keyCode, EndgameEvaluationFunctionBase* f) {
|
||||
void EndgameFunctions::add(const string& keyCode, EndgameEvaluationFunctionBase* f) {
|
||||
|
||||
EEFmap.insert(std::pair<Key, EndgameEvaluationFunctionBase*>(buildKey(keyCode), f));
|
||||
}
|
||||
|
||||
void EndgameFunctions::add(const std::string& keyCode, Color c, EndgameScalingFunctionBase* f) {
|
||||
void EndgameFunctions::add(const string& keyCode, Color c, EndgameScalingFunctionBase* f) {
|
||||
|
||||
ScalingInfo s = {c, f};
|
||||
ESFmap.insert(std::pair<Key, ScalingInfo>(buildKey(keyCode), s));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -49,6 +49,8 @@ class MaterialInfo {
|
||||
friend class MaterialInfoTable;
|
||||
|
||||
public:
|
||||
MaterialInfo() : key(0) { clear(); }
|
||||
|
||||
Value mg_value() const;
|
||||
Value eg_value() const;
|
||||
ScaleFactor scale_factor(const Position& pos, Color c) const;
|
||||
@@ -57,7 +59,7 @@ public:
|
||||
Value evaluate(const Position& pos) const;
|
||||
|
||||
private:
|
||||
void clear();
|
||||
inline void clear();
|
||||
|
||||
Key key;
|
||||
int16_t mgValue;
|
||||
@@ -87,7 +89,6 @@ class MaterialInfoTable {
|
||||
public:
|
||||
MaterialInfoTable(unsigned numOfEntries);
|
||||
~MaterialInfoTable();
|
||||
void clear();
|
||||
MaterialInfo* get_material_info(const Position& pos);
|
||||
|
||||
private:
|
||||
@@ -116,20 +117,20 @@ inline Value MaterialInfo::eg_value() const {
|
||||
|
||||
|
||||
/// MaterialInfo::clear() resets a MaterialInfo object to an empty state,
|
||||
/// with all slots at their default values.
|
||||
/// with all slots at their default values but the key.
|
||||
|
||||
inline void MaterialInfo::clear() {
|
||||
|
||||
mgValue = egValue = 0;
|
||||
factor[WHITE] = factor[BLACK] = uint8_t(SCALE_FACTOR_NORMAL);
|
||||
spaceWeight = 0;
|
||||
evaluationFunction = NULL;
|
||||
scalingFunction[WHITE] = scalingFunction[BLACK] = NULL;
|
||||
spaceWeight = 0;
|
||||
}
|
||||
|
||||
|
||||
/// MaterialInfo::scale_factor takes a position and a color as input, and
|
||||
/// returns a scale factor for the given color. We have to provide the
|
||||
/// returns a scale factor for the given color. We have to provide the
|
||||
/// position in addition to the color, because the scale factor need not
|
||||
/// to be a constant: It can also be a function which should be applied to
|
||||
/// the position. For instance, in KBP vs K endgames, a scaling function
|
||||
@@ -167,7 +168,7 @@ inline bool MaterialInfo::specialized_eval_exists() const {
|
||||
|
||||
|
||||
/// MaterialInfo::evaluate applies a specialized evaluation function
|
||||
/// to a given position object. It should only be called when
|
||||
/// to a given position object. It should only be called when
|
||||
/// specialized_eval_exists() returns 'true'.
|
||||
|
||||
inline Value MaterialInfo::evaluate(const Position& pos) const {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
18
src/misc.cpp
18
src/misc.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -38,6 +38,7 @@
|
||||
# include <windows.h>
|
||||
# include <time.h>
|
||||
# include "dos.h"
|
||||
|
||||
static int gettimeofday(struct timeval* tp, struct timezone*)
|
||||
{
|
||||
SYSTEMTIME systime;
|
||||
@@ -64,6 +65,7 @@ static int gettimeofday(struct timeval* tp, struct timezone*)
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "bitcount.h"
|
||||
#include "misc.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -71,7 +73,7 @@ using namespace std;
|
||||
/// Version number. If this is left empty, the current date (in the format
|
||||
/// YYMMDD) is used as a version number.
|
||||
|
||||
static const string EngineVersion = "1.3.1";
|
||||
static const string EngineVersion = "1.4";
|
||||
static const string AppName = "Stockfish";
|
||||
static const string AppTag = "";
|
||||
|
||||
@@ -80,8 +82,10 @@ static const string AppTag = "";
|
||||
//// Variables
|
||||
////
|
||||
|
||||
long dbg_cnt0 = 0;
|
||||
long dbg_cnt1 = 0;
|
||||
bool Chess960;
|
||||
|
||||
uint64_t dbg_cnt0 = 0;
|
||||
uint64_t dbg_cnt1 = 0;
|
||||
|
||||
bool dbg_show_mean = false;
|
||||
bool dbg_show_hit_rate = false;
|
||||
@@ -159,8 +163,10 @@ void dbg_print_mean(ofstream& logFile) {
|
||||
|
||||
const string engine_name() {
|
||||
|
||||
const string cpu64(CpuHas64BitPath ? " 64bit" : "");
|
||||
|
||||
if (!EngineVersion.empty())
|
||||
return "Stockfish " + EngineVersion;
|
||||
return AppName+ " " + EngineVersion + cpu64;
|
||||
|
||||
string date(__DATE__); // From compiler, format is "Sep 21 2008"
|
||||
string months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec");
|
||||
@@ -173,7 +179,7 @@ const string engine_name() {
|
||||
string name = AppName + " " + AppTag + " ";
|
||||
|
||||
s << name << date.substr(date.length() - 2) << setfill('0')
|
||||
<< setw(2) << mon << setw(2) << day;
|
||||
<< setw(2) << mon << setw(2) << day << cpu64;
|
||||
|
||||
return s.str();
|
||||
}
|
||||
|
||||
16
src/misc.h
16
src/misc.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -29,6 +29,8 @@
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "application.h"
|
||||
#include "types.h"
|
||||
|
||||
////
|
||||
//// Macros
|
||||
@@ -38,6 +40,13 @@
|
||||
#define Max(x, y) (((x) < (y))? (y) : (x))
|
||||
|
||||
|
||||
////
|
||||
//// Variables
|
||||
////
|
||||
|
||||
extern bool Chess960;
|
||||
|
||||
|
||||
////
|
||||
//// Prototypes
|
||||
////
|
||||
@@ -47,6 +56,7 @@ extern int get_system_time();
|
||||
extern int cpu_count();
|
||||
extern int Bioskey();
|
||||
|
||||
|
||||
////
|
||||
//// Debug
|
||||
////
|
||||
@@ -54,8 +64,8 @@ extern int Bioskey();
|
||||
extern bool dbg_show_mean;
|
||||
extern bool dbg_show_hit_rate;
|
||||
|
||||
extern long dbg_cnt0;
|
||||
extern long dbg_cnt1;
|
||||
extern uint64_t dbg_cnt0;
|
||||
extern uint64_t dbg_cnt1;
|
||||
|
||||
extern void dbg_hit_on(bool b);
|
||||
extern void dbg_hit_on_c(bool c, bool b);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "move.h"
|
||||
#include "piece.h"
|
||||
#include "position.h"
|
||||
#include "ucioption.h"
|
||||
|
||||
|
||||
////
|
||||
@@ -130,8 +129,8 @@ const std::string move_to_string(Move move) {
|
||||
return (from == SQ_E1 ? "e1c1" : "e8c8");
|
||||
}
|
||||
str = square_to_string(from) + square_to_string(to);
|
||||
if (move_promotion(move))
|
||||
str += piece_type_to_char(move_promotion(move), false);
|
||||
if (move_is_promotion(move))
|
||||
str += piece_type_to_char(move_promotion_piece(move), false);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
18
src/move.h
18
src/move.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -78,16 +78,20 @@ inline Square move_to(Move m) {
|
||||
return Square(m & 0x3F);
|
||||
}
|
||||
|
||||
inline PieceType move_promotion(Move m) {
|
||||
inline PieceType move_promotion_piece(Move m) {
|
||||
return PieceType((int(m) >> 12) & 7);
|
||||
}
|
||||
|
||||
inline bool move_is_ep(Move m) {
|
||||
return bool((int(m) >> 15) & 1);
|
||||
inline int move_is_promotion(Move m) {
|
||||
return m & (7 << 12);
|
||||
}
|
||||
|
||||
inline bool move_is_castle(Move m) {
|
||||
return bool((int(m) >> 16) & 1);
|
||||
inline int move_is_ep(Move m) {
|
||||
return m & (1 << 15);
|
||||
}
|
||||
|
||||
inline int move_is_castle(Move m) {
|
||||
return m & (1 << 16);
|
||||
}
|
||||
|
||||
inline bool move_is_short_castle(Move m) {
|
||||
@@ -119,7 +123,7 @@ inline Move make_ep_move(Square from, Square to) {
|
||||
//// Prototypes
|
||||
////
|
||||
|
||||
extern std::ostream &operator << (std::ostream &os, Move m);
|
||||
extern std::ostream& operator<<(std::ostream &os, Move m);
|
||||
extern Move move_from_string(const Position &pos, const std::string &str);
|
||||
extern const std::string move_to_string(Move m);
|
||||
extern bool move_is_ok(Move m);
|
||||
|
||||
196
src/movegen.cpp
196
src/movegen.cpp
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
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,6 +24,7 @@
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "bitcount.h"
|
||||
#include "movegen.h"
|
||||
|
||||
// Simple macro to wrap a very common while loop, no facny, no flexibility,
|
||||
@@ -52,16 +54,19 @@ namespace {
|
||||
template<CastlingSide Side>
|
||||
MoveStack* generate_castle_moves(const Position& pos, MoveStack* mlist);
|
||||
|
||||
template<Color Us, Rank, Bitboard, SquareDelta>
|
||||
template<Color Us>
|
||||
MoveStack* generate_pawn_blocking_evasions(const Position&, Bitboard, Bitboard, MoveStack*);
|
||||
|
||||
template<Color, Color, Bitboard, SquareDelta, SquareDelta, SquareDelta>
|
||||
template<Color Us>
|
||||
MoveStack* generate_pawn_captures(const Position& pos, MoveStack* mlist);
|
||||
|
||||
template<Color, Color, Bitboard, Bitboard, SquareDelta, SquareDelta, SquareDelta>
|
||||
template<Color Us, SquareDelta Diagonal>
|
||||
MoveStack* generate_pawn_captures_diagonal(MoveStack* mlist, Bitboard pawns, Bitboard enemyPieces);
|
||||
|
||||
template<Color Us>
|
||||
MoveStack* generate_pawn_noncaptures(const Position& pos, MoveStack* mlist);
|
||||
|
||||
template<Color, Color, Bitboard, Bitboard, SquareDelta>
|
||||
template<Color Us>
|
||||
MoveStack* generate_pawn_checks(const Position&, Bitboard, Square, MoveStack*);
|
||||
|
||||
template<Color Us, SquareDelta Direction>
|
||||
@@ -84,11 +89,8 @@ namespace {
|
||||
template<>
|
||||
inline MoveStack* generate_piece_checks<PAWN>(const Position& p, MoveStack* m, Color us, Bitboard dc, Square ksq) {
|
||||
|
||||
if (us == WHITE)
|
||||
return generate_pawn_checks<WHITE, BLACK, Rank8BB, Rank3BB, DELTA_N>(p, dc, ksq, m);
|
||||
else
|
||||
return generate_pawn_checks<BLACK, WHITE, Rank1BB, Rank6BB, DELTA_S>(p, dc, ksq, m);
|
||||
|
||||
return (us == WHITE ? generate_pawn_checks<WHITE>(p, dc, ksq, m)
|
||||
: generate_pawn_checks<BLACK>(p, dc, ksq, m));
|
||||
}
|
||||
|
||||
// Template generate_piece_moves() with specializations and overloads
|
||||
@@ -104,11 +106,11 @@ namespace {
|
||||
assert(Piece == PAWN);
|
||||
|
||||
if (Type == CAPTURE)
|
||||
return (us == WHITE ? generate_pawn_captures<WHITE, BLACK, Rank8BB, DELTA_NE, DELTA_NW, DELTA_N>(p, m)
|
||||
: generate_pawn_captures<BLACK, WHITE, Rank1BB, DELTA_SE, DELTA_SW, DELTA_S>(p, m));
|
||||
return (us == WHITE ? generate_pawn_captures<WHITE>(p, m)
|
||||
: generate_pawn_captures<BLACK>(p, m));
|
||||
else
|
||||
return (us == WHITE ? generate_pawn_noncaptures<WHITE, BLACK, Rank8BB, Rank3BB, DELTA_NE, DELTA_NW, DELTA_N>(p, m)
|
||||
: generate_pawn_noncaptures<BLACK, WHITE, Rank1BB, Rank6BB, DELTA_SE, DELTA_SW, DELTA_S>(p, m));
|
||||
return (us == WHITE ? generate_pawn_noncaptures<WHITE>(p, m)
|
||||
: generate_pawn_noncaptures<BLACK>(p, m));
|
||||
}
|
||||
|
||||
template<PieceType>
|
||||
@@ -117,10 +119,9 @@ namespace {
|
||||
template<>
|
||||
inline MoveStack* generate_piece_moves<PAWN>(const Position& p, MoveStack* m,
|
||||
Color us, Bitboard t, Bitboard pnd) {
|
||||
if (us == WHITE)
|
||||
return generate_pawn_blocking_evasions<WHITE, RANK_8, Rank3BB, DELTA_N>(p, pnd, t, m);
|
||||
else
|
||||
return generate_pawn_blocking_evasions<BLACK, RANK_1, Rank6BB, DELTA_S>(p, pnd, t, m);
|
||||
|
||||
return (us == WHITE ? generate_pawn_blocking_evasions<WHITE>(p, pnd, t, m)
|
||||
: generate_pawn_blocking_evasions<BLACK>(p, pnd, t, m));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +132,7 @@ namespace {
|
||||
|
||||
|
||||
/// generate_captures generates() all pseudo-legal captures and queen
|
||||
/// promotions. The return value is the number of moves generated.
|
||||
/// promotions. The return value is the number of moves generated.
|
||||
|
||||
int generate_captures(const Position& pos, MoveStack* mlist) {
|
||||
|
||||
@@ -392,7 +393,6 @@ bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) {
|
||||
assert(pinned == pos.pinned_pieces(pos.side_to_move()));
|
||||
|
||||
Color us = pos.side_to_move();
|
||||
Color them = opposite_color(us);
|
||||
Square from = move_from(m);
|
||||
Piece pc = pos.piece_on(from);
|
||||
|
||||
@@ -401,6 +401,7 @@ bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) {
|
||||
if (color_of_piece(pc) != us)
|
||||
return false;
|
||||
|
||||
Color them = opposite_color(us);
|
||||
Square to = move_to(m);
|
||||
|
||||
// En passant moves
|
||||
@@ -496,16 +497,21 @@ bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) {
|
||||
// Proceed according to the type of the moving piece.
|
||||
if (type_of_piece(pc) == PAWN)
|
||||
{
|
||||
// Move direction must be compatible with pawn color
|
||||
int direction = to - from;
|
||||
if ((us == WHITE) != (direction > 0))
|
||||
return false;
|
||||
|
||||
// If the destination square is on the 8/1th rank, the move must
|
||||
// be a promotion.
|
||||
if ( ( (square_rank(to) == RANK_8 && us == WHITE)
|
||||
||(square_rank(to) == RANK_1 && us != WHITE))
|
||||
&& !move_promotion(m))
|
||||
&& !move_is_promotion(m))
|
||||
return false;
|
||||
|
||||
// Proceed according to the square delta between the source and
|
||||
// destionation squares.
|
||||
switch (to - from)
|
||||
switch (direction)
|
||||
{
|
||||
case DELTA_NW:
|
||||
case DELTA_NE:
|
||||
@@ -554,7 +560,7 @@ bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) {
|
||||
// Luckly we can handle all the other pieces in one go
|
||||
return ( pos.piece_attacks_square(pos.piece_on(from), from, to)
|
||||
&& pos.pl_move_is_legal(m, pinned)
|
||||
&& !move_promotion(m));
|
||||
&& !move_is_promotion(m));
|
||||
}
|
||||
|
||||
|
||||
@@ -604,24 +610,27 @@ namespace {
|
||||
return mlist;
|
||||
}
|
||||
|
||||
template<Color Us, Color Them, Bitboard TRank8BB, SquareDelta TDELTA_NE,
|
||||
SquareDelta TDELTA_NW, SquareDelta TDELTA_N
|
||||
>
|
||||
MoveStack* generate_pawn_captures(const Position& pos, MoveStack* mlist) {
|
||||
template<Color Us, SquareDelta Diagonal>
|
||||
MoveStack* generate_pawn_captures_diagonal(MoveStack* mlist, Bitboard pawns, Bitboard enemyPieces) {
|
||||
|
||||
// Calculate our parametrized parameters at compile time
|
||||
const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
|
||||
const Bitboard TFileABB = (Diagonal == DELTA_NE ? FileABB : FileHBB);
|
||||
const SquareDelta TDELTA_NE = (Us == WHITE ? DELTA_NE : DELTA_SE);
|
||||
const SquareDelta TDELTA_NW = (Us == WHITE ? DELTA_NW : DELTA_SW);
|
||||
const SquareDelta TTDELTA_NE = (Diagonal == DELTA_NE ? TDELTA_NE : TDELTA_NW);
|
||||
|
||||
Square to;
|
||||
Bitboard pawns = pos.pawns(Us);
|
||||
Bitboard enemyPieces = pos.pieces_of_color(Them);
|
||||
|
||||
// Captures in the a1-h8 (a8-h1 for black) direction
|
||||
Bitboard b1 = move_pawns<Us, DELTA_NE>(pawns) & ~FileABB & enemyPieces;
|
||||
// Captures in the a1-h8 (a8-h1 for black) diagonal or in the h1-a8 (h8-a1 for black)
|
||||
Bitboard b1 = move_pawns<Us, Diagonal>(pawns) & ~TFileABB & enemyPieces;
|
||||
|
||||
// Capturing promotions
|
||||
Bitboard b2 = b1 & TRank8BB;
|
||||
while (b2)
|
||||
{
|
||||
to = pop_1st_bit(&b2);
|
||||
(*mlist++).move = make_promotion_move(to - TDELTA_NE, to, QUEEN);
|
||||
(*mlist++).move = make_promotion_move(to - TTDELTA_NE, to, QUEEN);
|
||||
}
|
||||
|
||||
// Capturing non-promotions
|
||||
@@ -629,30 +638,29 @@ namespace {
|
||||
while (b2)
|
||||
{
|
||||
to = pop_1st_bit(&b2);
|
||||
(*mlist++).move = make_move(to - TDELTA_NE, to);
|
||||
(*mlist++).move = make_move(to - TTDELTA_NE, to);
|
||||
}
|
||||
return mlist;
|
||||
}
|
||||
|
||||
// Captures in the h1-a8 (h8-a1 for black) direction
|
||||
b1 = move_pawns<Us, DELTA_NW>(pawns) & ~FileHBB & enemyPieces;
|
||||
template<Color Us>
|
||||
MoveStack* generate_pawn_captures(const Position& pos, MoveStack* mlist) {
|
||||
|
||||
// Capturing promotions
|
||||
b2 = b1 & TRank8BB;
|
||||
while (b2)
|
||||
{
|
||||
to = pop_1st_bit(&b2);
|
||||
(*mlist++).move = make_promotion_move(to - TDELTA_NW, to, QUEEN);
|
||||
}
|
||||
// Calculate our parametrized parameters at compile time
|
||||
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
||||
const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
|
||||
const SquareDelta TDELTA_N = (Us == WHITE ? DELTA_N : DELTA_S);
|
||||
|
||||
// Capturing non-promotions
|
||||
b2 = b1 & ~TRank8BB;
|
||||
while (b2)
|
||||
{
|
||||
to = pop_1st_bit(&b2);
|
||||
(*mlist++).move = make_move(to - TDELTA_NW, to);
|
||||
}
|
||||
Square to;
|
||||
Bitboard pawns = pos.pawns(Us);
|
||||
Bitboard enemyPieces = pos.pieces_of_color(opposite_color(Us));
|
||||
|
||||
// Standard captures and capturing promotions in both directions
|
||||
mlist = generate_pawn_captures_diagonal<Us, DELTA_NE>(mlist, pawns, enemyPieces);
|
||||
mlist = generate_pawn_captures_diagonal<Us, DELTA_NW>(mlist, pawns, enemyPieces);
|
||||
|
||||
// Non-capturing promotions
|
||||
b1 = move_pawns<Us, DELTA_N>(pawns) & pos.empty_squares() & TRank8BB;
|
||||
Bitboard b1 = move_pawns<Us, DELTA_N>(pawns) & pos.empty_squares() & TRank8BB;
|
||||
while (b1)
|
||||
{
|
||||
to = pop_1st_bit(&b1);
|
||||
@@ -677,16 +685,21 @@ namespace {
|
||||
return mlist;
|
||||
}
|
||||
|
||||
template<Color Us, Color Them, Bitboard TRank8BB, Bitboard TRank3BB,
|
||||
SquareDelta TDELTA_NE, SquareDelta TDELTA_NW, SquareDelta TDELTA_N
|
||||
>
|
||||
template<Color Us>
|
||||
MoveStack* generate_pawn_noncaptures(const Position& pos, MoveStack* mlist) {
|
||||
|
||||
Bitboard pawns = pos.pawns(Us);
|
||||
Bitboard enemyPieces = pos.pieces_of_color(Them);
|
||||
Bitboard emptySquares = pos.empty_squares();
|
||||
// Calculate our parametrized parameters at compile time
|
||||
const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
|
||||
const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
|
||||
const SquareDelta TDELTA_NE = (Us == WHITE ? DELTA_NE : DELTA_SE);
|
||||
const SquareDelta TDELTA_NW = (Us == WHITE ? DELTA_NW : DELTA_SW);
|
||||
const SquareDelta TDELTA_N = (Us == WHITE ? DELTA_N : DELTA_S);
|
||||
|
||||
Bitboard b1, b2;
|
||||
Square to;
|
||||
Bitboard pawns = pos.pawns(Us);
|
||||
Bitboard enemyPieces = pos.pieces_of_color(opposite_color(Us));
|
||||
Bitboard emptySquares = pos.empty_squares();
|
||||
|
||||
// Underpromotion captures in the a1-h8 (a8-h1 for black) direction
|
||||
b1 = move_pawns<Us, DELTA_NE>(pawns) & ~FileABB & enemyPieces & TRank8BB;
|
||||
@@ -736,19 +749,27 @@ namespace {
|
||||
}
|
||||
|
||||
|
||||
template<Color Us, Color Them, Bitboard TRank8BB, Bitboard TRank3BB, SquareDelta TDELTA_N>
|
||||
template<Color Us>
|
||||
MoveStack* generate_pawn_checks(const Position& pos, Bitboard dc, Square ksq, MoveStack* mlist)
|
||||
{
|
||||
// Find all friendly pawns not on the enemy king's file
|
||||
Bitboard b1, b2, b3;
|
||||
Bitboard empty = pos.empty_squares();
|
||||
// Calculate our parametrized parameters at compile time
|
||||
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
||||
const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
|
||||
const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
|
||||
const SquareDelta TDELTA_N = (Us == WHITE ? DELTA_N : DELTA_S);
|
||||
const SquareDelta TDELTA_S = (Us == WHITE ? DELTA_S : DELTA_N);
|
||||
|
||||
if (dc != EmptyBoardBB)
|
||||
Bitboard b1, b2, b3;
|
||||
Bitboard pawns = pos.pawns(Us);
|
||||
|
||||
if (dc & pawns)
|
||||
{
|
||||
Bitboard empty = pos.empty_squares();
|
||||
|
||||
// Pawn moves which gives discovered check. This is possible only if the
|
||||
// pawn is not on the same file as the enemy king, because we don't
|
||||
// generate captures.
|
||||
b1 = pos.pawns(Us) & ~file_bb(ksq);
|
||||
b1 = pawns & ~file_bb(ksq);
|
||||
|
||||
// Discovered checks, single pawn pushes, no promotions
|
||||
b2 = b3 = move_pawns<Us, DELTA_N>(b1 & dc) & empty & ~TRank8BB;
|
||||
@@ -768,10 +789,17 @@ namespace {
|
||||
}
|
||||
|
||||
// Direct checks. These are possible only for pawns on neighboring files
|
||||
// of the enemy king.
|
||||
b1 = pos.pawns(Us) & neighboring_files_bb(ksq) & ~dc;
|
||||
// and in the two ranks that, after the push, are in front of the enemy king.
|
||||
b1 = pawns & neighboring_files_bb(ksq) & ~dc;
|
||||
|
||||
// We can get false positives if (ksq + x) is not in [0,63] range but
|
||||
// is not a problem, they will be filtered out later.
|
||||
b2 = b1 & (rank_bb(ksq + 2 * TDELTA_S) | rank_bb(ksq + 3 * TDELTA_S));
|
||||
if (!b2)
|
||||
return mlist;
|
||||
|
||||
// Direct checks, single pawn pushes
|
||||
Bitboard empty = pos.empty_squares();
|
||||
b2 = move_pawns<Us, DELTA_N>(b1) & empty;
|
||||
b3 = b2 & pos.pawn_attacks(Them, ksq);
|
||||
while (b3)
|
||||
@@ -810,30 +838,36 @@ namespace {
|
||||
|
||||
// Direct checks
|
||||
b = target & ~dc;
|
||||
if (Piece == KING || !b)
|
||||
return mlist;
|
||||
|
||||
Bitboard checkSqs = pos.piece_attacks<Piece>(ksq) & pos.empty_squares();
|
||||
if (!checkSqs)
|
||||
return mlist;
|
||||
|
||||
while (b)
|
||||
if (Piece != KING || b)
|
||||
{
|
||||
Square from = pop_1st_bit(&b);
|
||||
if ( (Piece == QUEEN && !(QueenPseudoAttacks[from] & checkSqs))
|
||||
|| (Piece == ROOK && !(RookPseudoAttacks[from] & checkSqs))
|
||||
|| (Piece == BISHOP && !(BishopPseudoAttacks[from] & checkSqs)))
|
||||
continue;
|
||||
Bitboard checkSqs = pos.piece_attacks<Piece>(ksq) & pos.empty_squares();
|
||||
if (!checkSqs)
|
||||
return mlist;
|
||||
|
||||
Bitboard bb = pos.piece_attacks<Piece>(from) & checkSqs;
|
||||
SERIALIZE_MOVES(bb);
|
||||
while (b)
|
||||
{
|
||||
Square from = pop_1st_bit(&b);
|
||||
if ( (Piece == QUEEN && !(QueenPseudoAttacks[from] & checkSqs))
|
||||
|| (Piece == ROOK && !(RookPseudoAttacks[from] & checkSqs))
|
||||
|| (Piece == BISHOP && !(BishopPseudoAttacks[from] & checkSqs)))
|
||||
continue;
|
||||
|
||||
Bitboard bb = pos.piece_attacks<Piece>(from) & checkSqs;
|
||||
SERIALIZE_MOVES(bb);
|
||||
}
|
||||
}
|
||||
return mlist;
|
||||
}
|
||||
|
||||
template<Color Us, Rank TRANK_8, Bitboard TRank3BB, SquareDelta TDELTA_N>
|
||||
template<Color Us>
|
||||
MoveStack* generate_pawn_blocking_evasions(const Position& pos, Bitboard pinned,
|
||||
Bitboard blockSquares, MoveStack* mlist) {
|
||||
|
||||
// Calculate our parametrized parameters at compile time
|
||||
const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
|
||||
const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
|
||||
const SquareDelta TDELTA_N = (Us == WHITE ? DELTA_N : DELTA_S);
|
||||
|
||||
Square to;
|
||||
|
||||
// Find non-pinned pawns and push them one square
|
||||
@@ -848,7 +882,7 @@ namespace {
|
||||
|
||||
assert(pos.piece_on(to) == EMPTY);
|
||||
|
||||
if (square_rank(to) == TRANK_8)
|
||||
if (square_rank(to) == TRank8BB)
|
||||
{
|
||||
(*mlist++).move = make_promotion_move(to - TDELTA_N, to, QUEEN);
|
||||
(*mlist++).move = make_promotion_move(to - TDELTA_N, to, ROOK);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -63,23 +63,25 @@ namespace {
|
||||
/// search captures, promotions and some checks) and about how important good
|
||||
/// move ordering is at the current node.
|
||||
|
||||
MovePicker::MovePicker(const Position& p, bool pv, Move ttm,
|
||||
const SearchStack& ss, Depth d) : pos(p) {
|
||||
pvNode = pv;
|
||||
MovePicker::MovePicker(const Position& p, Move ttm, Depth d,
|
||||
const History& h, SearchStack* ss) : pos(p), H(h) {
|
||||
ttMove = ttm;
|
||||
mateKiller = (ss.mateKiller == ttm)? MOVE_NONE : ss.mateKiller;
|
||||
killer1 = ss.killers[0];
|
||||
killer2 = ss.killers[1];
|
||||
depth = d;
|
||||
movesPicked = 0;
|
||||
numOfMoves = 0;
|
||||
numOfBadCaptures = 0;
|
||||
if (ss)
|
||||
{
|
||||
mateKiller = (ss->mateKiller == ttm)? MOVE_NONE : ss->mateKiller;
|
||||
killer1 = ss->killers[0];
|
||||
killer2 = ss->killers[1];
|
||||
} else
|
||||
mateKiller = killer1 = killer2 = MOVE_NONE;
|
||||
|
||||
movesPicked = numOfMoves = numOfBadCaptures = 0;
|
||||
checkKillers = checkLegal = finished = false;
|
||||
|
||||
if (p.is_check())
|
||||
phaseIndex = EvasionsPhaseIndex;
|
||||
else if (depth > Depth(0))
|
||||
else if (d > Depth(0))
|
||||
phaseIndex = MainSearchPhaseIndex;
|
||||
else if (depth == Depth(0))
|
||||
else if (d == Depth(0))
|
||||
phaseIndex = QsearchWithChecksPhaseIndex;
|
||||
else
|
||||
phaseIndex = QsearchWithoutChecksPhaseIndex;
|
||||
@@ -139,18 +141,32 @@ Move MovePicker::get_next_move() {
|
||||
score_captures();
|
||||
std::sort(moves, moves + numOfMoves);
|
||||
movesPicked = 0;
|
||||
checkLegal = true;
|
||||
break;
|
||||
|
||||
case PH_BAD_CAPTURES:
|
||||
// It's probably a good idea to use SEE move ordering here. FIXME
|
||||
movesPicked = 0;
|
||||
case PH_KILLERS:
|
||||
movesPicked = numOfMoves = 0;
|
||||
checkLegal = false;
|
||||
if (killer1 != MOVE_NONE && move_is_legal(pos, killer1, pinned) && !pos.move_is_capture(killer1))
|
||||
moves[numOfMoves++].move = killer1;
|
||||
if (killer2 != MOVE_NONE && move_is_legal(pos, killer2, pinned) && !pos.move_is_capture(killer2) )
|
||||
moves[numOfMoves++].move = killer2;
|
||||
break;
|
||||
|
||||
case PH_NONCAPTURES:
|
||||
checkKillers = (numOfMoves != 0); // previous phase is PH_KILLERS
|
||||
numOfMoves = generate_noncaptures(pos, moves);
|
||||
score_noncaptures();
|
||||
std::sort(moves, moves + numOfMoves);
|
||||
movesPicked = 0;
|
||||
checkLegal = true;
|
||||
break;
|
||||
|
||||
case PH_BAD_CAPTURES:
|
||||
// Bad captures SEE value is already calculated by score_captures()
|
||||
// so just sort them to get SEE move ordering.
|
||||
std::sort(badCaptures, badCaptures + numOfBadCaptures);
|
||||
movesPicked = 0;
|
||||
break;
|
||||
|
||||
case PH_EVASIONS:
|
||||
@@ -231,7 +247,7 @@ void MovePicker::score_captures() {
|
||||
seeValue = pos.see(m);
|
||||
if (seeValue >= 0)
|
||||
{
|
||||
if (move_promotion(m))
|
||||
if (move_is_promotion(m))
|
||||
moves[i].score = QueenValueMidgame;
|
||||
else
|
||||
moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
|
||||
@@ -252,26 +268,23 @@ void MovePicker::score_noncaptures() {
|
||||
// First score by history, when no history is available then use
|
||||
// piece/square tables values. This seems to be better then a
|
||||
// random choice when we don't have an history for any move.
|
||||
Move m;
|
||||
Piece piece;
|
||||
Square from, to;
|
||||
int hs;
|
||||
|
||||
for (int i = 0; i < numOfMoves; i++)
|
||||
{
|
||||
m = moves[i].move;
|
||||
|
||||
if (m == killer1)
|
||||
hs = HistoryMax + 2;
|
||||
else if (m == killer2)
|
||||
hs = HistoryMax + 1;
|
||||
else
|
||||
hs = H.move_ordering_score(pos.piece_on(move_from(m)), m);
|
||||
from = move_from(moves[i].move);
|
||||
to = move_to(moves[i].move);
|
||||
piece = pos.piece_on(from);
|
||||
hs = H.move_ordering_score(piece, to);
|
||||
|
||||
// Ensure history is always preferred to pst
|
||||
if (hs > 0)
|
||||
hs += 1000;
|
||||
|
||||
// pst based scoring
|
||||
moves[i].score = hs + pos.mg_pst_delta(m);
|
||||
moves[i].score = hs + pos.pst_delta<Position::MidGame>(piece, from, to);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +300,7 @@ void MovePicker::score_evasions() {
|
||||
int seeScore = pos.see(m);
|
||||
moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore;
|
||||
} else
|
||||
moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
|
||||
moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), move_to(m));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,7 +310,7 @@ void MovePicker::score_qcaptures() {
|
||||
for (int i = 0; i < numOfMoves; i++)
|
||||
{
|
||||
Move m = moves[i].move;
|
||||
if (move_promotion(m))
|
||||
if (move_is_promotion(m))
|
||||
moves[i].score = QueenValueMidgame;
|
||||
else
|
||||
moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
|
||||
@@ -320,13 +333,15 @@ Move MovePicker::pick_move_from_list() {
|
||||
switch (PhaseTable[phaseIndex]) {
|
||||
|
||||
case PH_GOOD_CAPTURES:
|
||||
case PH_KILLERS:
|
||||
case PH_NONCAPTURES:
|
||||
while (movesPicked < numOfMoves)
|
||||
{
|
||||
Move move = moves[movesPicked++].move;
|
||||
if ( move != ttMove
|
||||
&& move != mateKiller
|
||||
&& pos.pl_move_is_legal(move, pinned))
|
||||
&& (!checkKillers || (move != killer1 && move != killer2))
|
||||
&& (!checkLegal || pos.pl_move_is_legal(move, pinned)))
|
||||
return move;
|
||||
}
|
||||
break;
|
||||
@@ -381,9 +396,7 @@ void MovePicker::init_phase_table() {
|
||||
PhaseTable[i++] = PH_TT_MOVE;
|
||||
PhaseTable[i++] = PH_MATE_KILLER;
|
||||
PhaseTable[i++] = PH_GOOD_CAPTURES;
|
||||
// PH_KILLER_1 and PH_KILLER_2 are not yet used.
|
||||
// PhaseTable[i++] = PH_KILLER_1;
|
||||
// PhaseTable[i++] = PH_KILLER_2;
|
||||
PhaseTable[i++] = PH_KILLERS;
|
||||
PhaseTable[i++] = PH_NONCAPTURES;
|
||||
PhaseTable[i++] = PH_BAD_CAPTURES;
|
||||
PhaseTable[i++] = PH_STOP;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
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,6 +26,7 @@
|
||||
////
|
||||
|
||||
#include "depth.h"
|
||||
#include "history.h"
|
||||
#include "lock.h"
|
||||
#include "position.h"
|
||||
|
||||
@@ -38,8 +39,8 @@ struct EvalInfo;
|
||||
struct SearchStack;
|
||||
|
||||
/// MovePicker is a class which is used to pick one legal move at a time from
|
||||
/// the current position. It is initialized with a Position object and a few
|
||||
/// moves we have reason to believe are good. The most important method is
|
||||
/// the current position. It is initialized with a Position object and a few
|
||||
/// moves we have reason to believe are good. The most important method is
|
||||
/// MovePicker::pick_next_move(), which returns a new legal move each time it
|
||||
/// is called, until there are no legal moves left, when MOVE_NONE is returned.
|
||||
/// In order to improve the efficiency of the alpha beta algorithm, MovePicker
|
||||
@@ -47,7 +48,7 @@ struct SearchStack;
|
||||
|
||||
class MovePicker {
|
||||
|
||||
MovePicker& operator=(const MovePicker&); // Silence a warning under MSVC
|
||||
MovePicker& operator=(const MovePicker&); // silence a warning under MSVC
|
||||
|
||||
public:
|
||||
|
||||
@@ -55,21 +56,19 @@ public:
|
||||
PH_TT_MOVE, // Transposition table move
|
||||
PH_MATE_KILLER, // Mate killer from the current ply
|
||||
PH_GOOD_CAPTURES, // Queen promotions and captures with SEE values >= 0
|
||||
PH_BAD_CAPTURES, // Queen promotions and captures with SEE values < 0
|
||||
PH_KILLER_1, // Killer move 1 from the current ply (not used yet).
|
||||
PH_KILLER_2, // Killer move 2 from the current ply (not used yet).
|
||||
PH_KILLERS, // Killer moves from the current ply
|
||||
PH_NONCAPTURES, // Non-captures and underpromotions
|
||||
PH_BAD_CAPTURES, // Queen promotions and captures with SEE values < 0
|
||||
PH_EVASIONS, // Check evasions
|
||||
PH_QCAPTURES, // Captures in quiescence search
|
||||
PH_QCHECKS, // Checks in quiescence search
|
||||
PH_QCHECKS, // Non-capture checks in quiescence search
|
||||
PH_STOP
|
||||
};
|
||||
|
||||
MovePicker(const Position& p, bool pvnode, Move ttm, const SearchStack& ss, Depth d);
|
||||
MovePicker(const Position& p, Move ttm, Depth d, const History& h, SearchStack* ss = NULL);
|
||||
Move get_next_move();
|
||||
Move get_next_move(Lock &lock);
|
||||
Move get_next_move(Lock& lock);
|
||||
int number_of_moves() const;
|
||||
int current_move_score() const;
|
||||
Bitboard discovered_check_candidates() const;
|
||||
|
||||
static void init_phase_table();
|
||||
@@ -82,14 +81,14 @@ private:
|
||||
Move pick_move_from_list();
|
||||
|
||||
const Position& pos;
|
||||
const History& H;
|
||||
Move ttMove, mateKiller, killer1, killer2;
|
||||
Bitboard pinned, dc;
|
||||
MoveStack moves[256], badCaptures[64];
|
||||
bool pvNode;
|
||||
Depth depth;
|
||||
int phaseIndex;
|
||||
int numOfMoves, numOfBadCaptures;
|
||||
int movesPicked;
|
||||
bool checkKillers, checkLegal;
|
||||
bool finished;
|
||||
};
|
||||
|
||||
@@ -108,7 +107,7 @@ inline int MovePicker::number_of_moves() const {
|
||||
}
|
||||
|
||||
/// MovePicker::discovered_check_candidates() returns a bitboard containing
|
||||
/// all pieces which can possibly give discovered check. This bitboard is
|
||||
/// all pieces which can possibly give discovered check. This bitboard is
|
||||
/// computed by the constructor function.
|
||||
|
||||
inline Bitboard MovePicker::discovered_check_candidates() const {
|
||||
|
||||
103
src/pawns.cpp
103
src/pawns.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
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,8 +23,8 @@
|
||||
////
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include "bitcount.h"
|
||||
#include "pawns.h"
|
||||
#include "position.h"
|
||||
|
||||
@@ -39,93 +39,93 @@ namespace {
|
||||
|
||||
// Doubled pawn penalty by file, middle game.
|
||||
const Value DoubledPawnMidgamePenalty[8] = {
|
||||
Value(20), Value(30), Value(34), Value(34),
|
||||
Value(34), Value(34), Value(30), Value(20)
|
||||
Value(13), Value(20), Value(23), Value(23),
|
||||
Value(23), Value(23), Value(20), Value(13)
|
||||
};
|
||||
|
||||
// Doubled pawn penalty by file, endgame.
|
||||
const Value DoubledPawnEndgamePenalty[8] = {
|
||||
Value(35), Value(40), Value(40), Value(40),
|
||||
Value(40), Value(40), Value(40), Value(35)
|
||||
Value(43), Value(48), Value(48), Value(48),
|
||||
Value(48), Value(48), Value(48), Value(43)
|
||||
};
|
||||
|
||||
// Isolated pawn penalty by file, middle game.
|
||||
const Value IsolatedPawnMidgamePenalty[8] = {
|
||||
Value(20), Value(30), Value(34), Value(34),
|
||||
Value(34), Value(34), Value(30), Value(20)
|
||||
Value(25), Value(36), Value(40), Value(40),
|
||||
Value(40), Value(40), Value(36), Value(25)
|
||||
};
|
||||
|
||||
// Isolated pawn penalty by file, endgame.
|
||||
const Value IsolatedPawnEndgamePenalty[8] = {
|
||||
Value(35), Value(40), Value(40), Value(40),
|
||||
Value(40), Value(40), Value(40), Value(35)
|
||||
Value(30), Value(35), Value(35), Value(35),
|
||||
Value(35), Value(35), Value(35), Value(30)
|
||||
};
|
||||
|
||||
// Backward pawn penalty by file, middle game.
|
||||
const Value BackwardPawnMidgamePenalty[8] = {
|
||||
Value(16), Value(24), Value(27), Value(27),
|
||||
Value(27), Value(27), Value(24), Value(16)
|
||||
Value(20), Value(29), Value(33), Value(33),
|
||||
Value(33), Value(33), Value(29), Value(20)
|
||||
};
|
||||
|
||||
// Backward pawn penalty by file, endgame.
|
||||
const Value BackwardPawnEndgamePenalty[8] = {
|
||||
Value(28), Value(32), Value(32), Value(32),
|
||||
Value(32), Value(32), Value(32), Value(28)
|
||||
Value(28), Value(31), Value(31), Value(31),
|
||||
Value(31), Value(31), Value(31), Value(28)
|
||||
};
|
||||
|
||||
// Pawn chain membership bonus by file, middle game.
|
||||
const Value ChainMidgameBonus[8] = {
|
||||
Value(14), Value(16), Value(17), Value(18),
|
||||
Value(18), Value(17), Value(16), Value(14)
|
||||
Value(11), Value(13), Value(13), Value(14),
|
||||
Value(14), Value(13), Value(13), Value(11)
|
||||
};
|
||||
|
||||
// Pawn chain membership bonus by file, endgame.
|
||||
const Value ChainEndgameBonus[8] = {
|
||||
Value(16), Value(16), Value(16), Value(16),
|
||||
Value(16), Value(16), Value(16), Value(16)
|
||||
Value(-1), Value(-1), Value(-1), Value(-1),
|
||||
Value(-1), Value(-1), Value(-1), Value(-1)
|
||||
};
|
||||
|
||||
// Candidate passed pawn bonus by rank, middle game.
|
||||
const Value CandidateMidgameBonus[8] = {
|
||||
Value( 0), Value(12), Value(12), Value(20),
|
||||
Value(40), Value(90), Value( 0), Value( 0)
|
||||
Value( 0), Value( 6), Value(6), Value(14),
|
||||
Value(34), Value(83), Value(0), Value( 0)
|
||||
};
|
||||
|
||||
// Candidate passed pawn bonus by rank, endgame.
|
||||
const Value CandidateEndgameBonus[8] = {
|
||||
Value( 0), Value(24), Value(24), Value(40),
|
||||
Value(80), Value(180), Value(0), Value( 0)
|
||||
Value( 0), Value( 13), Value(13), Value(29),
|
||||
Value(68), Value(166), Value( 0), Value( 0)
|
||||
};
|
||||
|
||||
// Pawn storm tables for positions with opposite castling:
|
||||
const int QStormTable[64] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
-22,-22,-22,-13,-4, 0, 0, 0,
|
||||
-4, -9, -9, -9,-4, 0, 0, 0,
|
||||
9, 18, 22, 18, 9, 0, 0, 0,
|
||||
22, 31, 31, 22, 0, 0, 0, 0,
|
||||
31, 40, 40, 31, 0, 0, 0, 0,
|
||||
31, 40, 40, 31, 0, 0, 0, 0,
|
||||
-22,-22,-22,-14,-6, 0, 0, 0,
|
||||
-6,-10,-10,-10,-6, 0, 0, 0,
|
||||
4, 12, 16, 12, 4, 0, 0, 0,
|
||||
16, 23, 23, 16, 0, 0, 0, 0,
|
||||
23, 31, 31, 23, 0, 0, 0, 0,
|
||||
23, 31, 31, 23, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
const int KStormTable[64] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,-4,-13,-22,-27,-27,
|
||||
0, 0, 0,-4, -9,-13,-18,-18,
|
||||
0, 0, 0, 0, 9, 9, 9, 9,
|
||||
0, 0, 0, 0, 9, 18, 27, 27,
|
||||
0, 0, 0, 0, 9, 27, 40, 36,
|
||||
0, 0, 0, 0, 0, 31, 40, 31,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,-10,-19,-28,-33,-33,
|
||||
0, 0, 0,-10,-15,-19,-24,-24,
|
||||
0, 0, 0, 0, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 1, 10, 19, 19,
|
||||
0, 0, 0, 0, 1, 19, 31, 27,
|
||||
0, 0, 0, 0, 0, 22, 31, 22,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
// Pawn storm open file bonuses by file
|
||||
const int16_t KStormOpenFileBonus[8] = { 45, 45, 30, 0, 0, 0, 0, 0 };
|
||||
const int16_t QStormOpenFileBonus[8] = { 0, 0, 0, 0, 0, 30, 45, 30 };
|
||||
const int16_t KStormOpenFileBonus[8] = { 31, 31, 18, 0, 0, 0, 0, 0 };
|
||||
const int16_t QStormOpenFileBonus[8] = { 0, 0, 0, 0, 0, 26, 42, 26 };
|
||||
|
||||
// Pawn storm lever bonuses by file
|
||||
const int StormLeverBonus[8] = { 20, 20, 10, 0, 0, 10, 20, 20 };
|
||||
const int StormLeverBonus[8] = { -8, -8, -13, 0, 0, -13, -8, -8 };
|
||||
|
||||
}
|
||||
|
||||
@@ -144,9 +144,8 @@ PawnInfoTable::PawnInfoTable(unsigned numOfEntries) {
|
||||
{
|
||||
std::cerr << "Failed to allocate " << (numOfEntries * sizeof(PawnInfo))
|
||||
<< " bytes for pawn hash table." << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
Application::exit_with_failure();
|
||||
}
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -157,14 +156,6 @@ PawnInfoTable::~PawnInfoTable() {
|
||||
}
|
||||
|
||||
|
||||
/// PawnInfoTable::clear() clears the pawn hash table by setting all
|
||||
/// entries to 0.
|
||||
|
||||
void PawnInfoTable::clear() {
|
||||
memset(entries, 0, size * sizeof(PawnInfo));
|
||||
}
|
||||
|
||||
|
||||
/// PawnInfoTable::get_pawn_info() takes a position object as input, computes
|
||||
/// a PawnInfo object, and returns a pointer to it. The result is also
|
||||
/// stored in a hash table, so we don't have to recompute everything when
|
||||
@@ -202,7 +193,7 @@ PawnInfo *PawnInfoTable::get_pawn_info(const Position &pos) {
|
||||
|
||||
// Initialize pawn storm scores by giving bonuses for open files
|
||||
for (File f = FILE_A; f <= FILE_H; f++)
|
||||
if (pos.file_is_half_open(us, f))
|
||||
if (Position::file_is_half_open(ourPawns, f))
|
||||
{
|
||||
pi->ksStormValue[us] += KStormOpenFileBonus[f];
|
||||
pi->qsStormValue[us] += QStormOpenFileBonus[f];
|
||||
@@ -222,9 +213,9 @@ PawnInfo *PawnInfoTable::get_pawn_info(const Position &pos) {
|
||||
pi->halfOpenFiles[us] &= ~(1 << f);
|
||||
|
||||
// Passed, isolated or doubled pawn?
|
||||
passed = pos.pawn_is_passed(us, s);
|
||||
isolated = pos.pawn_is_isolated(us, s);
|
||||
doubled = pos.pawn_is_doubled(us, s);
|
||||
passed = Position::pawn_is_passed(theirPawns, us, s);
|
||||
isolated = Position::pawn_is_isolated(ourPawns, s);
|
||||
doubled = Position::pawn_is_doubled(ourPawns, us, s);
|
||||
|
||||
// We calculate kingside and queenside pawn storm
|
||||
// scores for both colors. These are used when evaluating
|
||||
@@ -328,7 +319,7 @@ PawnInfo *PawnInfoTable::get_pawn_info(const Position &pos) {
|
||||
|
||||
// Test for candidate passed pawn
|
||||
candidate = !passed
|
||||
&& pos.file_is_half_open(them, f)
|
||||
&& Position::file_is_half_open(theirPawns, f)
|
||||
&& ( count_1s_max_15(neighboring_files_bb(f) & (behind_bb(us, r) | rank_bb(r)) & ourPawns)
|
||||
- count_1s_max_15(neighboring_files_bb(f) & in_front_bb(us, r) & theirPawns)
|
||||
>= 0);
|
||||
@@ -348,7 +339,7 @@ PawnInfo *PawnInfoTable::get_pawn_info(const Position &pos) {
|
||||
{
|
||||
mv -= IsolatedPawnMidgamePenalty[f];
|
||||
ev -= IsolatedPawnEndgamePenalty[f];
|
||||
if (pos.file_is_half_open(them, f))
|
||||
if (Position::file_is_half_open(theirPawns, f))
|
||||
{
|
||||
mv -= IsolatedPawnMidgamePenalty[f] / 2;
|
||||
ev -= IsolatedPawnEndgamePenalty[f] / 2;
|
||||
@@ -363,7 +354,7 @@ PawnInfo *PawnInfoTable::get_pawn_info(const Position &pos) {
|
||||
{
|
||||
mv -= BackwardPawnMidgamePenalty[f];
|
||||
ev -= BackwardPawnEndgamePenalty[f];
|
||||
if (pos.file_is_half_open(them, f))
|
||||
if (Position::file_is_half_open(theirPawns, f))
|
||||
{
|
||||
mv -= BackwardPawnMidgamePenalty[f] / 2;
|
||||
ev -= BackwardPawnEndgamePenalty[f] / 2;
|
||||
|
||||
28
src/pawns.h
28
src/pawns.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -33,9 +33,9 @@
|
||||
////
|
||||
|
||||
/// PawnInfo is a class which contains various information about a pawn
|
||||
/// structure. Currently, it only includes a middle game and an end game
|
||||
/// pawn structure evaluation, and a bitboard of passed pawns. We may want
|
||||
/// to add further information in the future. A lookup to the pawn hash table
|
||||
/// structure. Currently, it only includes a middle game and an end game
|
||||
/// pawn structure evaluation, and a bitboard of passed pawns. We may want
|
||||
/// to add further information in the future. A lookup to the pawn hash table
|
||||
/// (performed by calling the get_pawn_info method in a PawnInfoTable object)
|
||||
/// returns a pointer to a PawnInfo object.
|
||||
class Position;
|
||||
@@ -45,6 +45,8 @@ class PawnInfo {
|
||||
friend class PawnInfoTable;
|
||||
|
||||
public:
|
||||
PawnInfo() : key(0) { clear(); }
|
||||
|
||||
Value mg_value() const;
|
||||
Value eg_value() const;
|
||||
Value kingside_storm_value(Color c) const;
|
||||
@@ -53,18 +55,21 @@ public:
|
||||
int file_is_half_open(Color c, File f) const;
|
||||
int has_open_file_to_left(Color c, File f) const;
|
||||
int has_open_file_to_right(Color c, File f) const;
|
||||
int kingShelter(Color c, Square ksq) const;
|
||||
void setKingShelter(Color c, Square ksq, int value);
|
||||
|
||||
private:
|
||||
void clear();
|
||||
inline void clear();
|
||||
|
||||
Key key;
|
||||
Bitboard passedPawns;
|
||||
int16_t mgValue, egValue;
|
||||
int16_t ksStormValue[2], qsStormValue[2];
|
||||
uint8_t halfOpenFiles[2];
|
||||
Square kingSquares[2];
|
||||
int16_t kingShelters[2];
|
||||
};
|
||||
|
||||
|
||||
/// The PawnInfoTable class represents a pawn hash table. It is basically
|
||||
/// just an array of PawnInfo objects and a few methods for accessing these
|
||||
/// objects. The most important method is get_pawn_info, which looks up a
|
||||
@@ -75,7 +80,6 @@ class PawnInfoTable {
|
||||
public:
|
||||
PawnInfoTable(unsigned numOfEntries);
|
||||
~PawnInfoTable();
|
||||
void clear();
|
||||
PawnInfo* get_pawn_info(const Position& pos);
|
||||
|
||||
private:
|
||||
@@ -120,6 +124,15 @@ inline int PawnInfo::has_open_file_to_right(Color c, File f) const {
|
||||
return halfOpenFiles[c] & ~((1 << int(f+1)) - 1);
|
||||
}
|
||||
|
||||
inline int PawnInfo::kingShelter(Color c, Square ksq) const {
|
||||
return (kingSquares[c] == ksq ? kingShelters[c] : -1);
|
||||
}
|
||||
|
||||
inline void PawnInfo::setKingShelter(Color c, Square ksq, int value) {
|
||||
kingSquares[c] = ksq;
|
||||
kingShelters[c] = (int16_t)value;
|
||||
}
|
||||
|
||||
inline void PawnInfo::clear() {
|
||||
|
||||
passedPawns = EmptyBoardBB;
|
||||
@@ -127,6 +140,7 @@ inline void PawnInfo::clear() {
|
||||
ksStormValue[WHITE] = ksStormValue[BLACK] = 0;
|
||||
qsStormValue[WHITE] = qsStormValue[BLACK] = 0;
|
||||
halfOpenFiles[WHITE] = halfOpenFiles[BLACK] = 0xFF;
|
||||
kingSquares[WHITE] = kingSquares[BLACK] = SQ_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
254
src/position.cpp
254
src/position.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "bitcount.h"
|
||||
#include "mersenne.h"
|
||||
#include "movegen.h"
|
||||
#include "movepick.h"
|
||||
@@ -35,13 +36,13 @@
|
||||
#include "san.h"
|
||||
#include "ucioption.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
|
||||
////
|
||||
//// Variables
|
||||
////
|
||||
|
||||
extern SearchStack EmptySearchStack;
|
||||
|
||||
int Position::castleRightsMask[64];
|
||||
|
||||
Key Position::zobrist[2][8][64];
|
||||
@@ -65,7 +66,7 @@ Position::Position(const Position& pos) {
|
||||
copy(pos);
|
||||
}
|
||||
|
||||
Position::Position(const std::string& fen) {
|
||||
Position::Position(const string& fen) {
|
||||
from_fen(fen);
|
||||
}
|
||||
|
||||
@@ -74,9 +75,9 @@ Position::Position(const std::string& fen) {
|
||||
/// string. This function is not very robust - make sure that input FENs are
|
||||
/// correct (this is assumed to be the responsibility of the GUI).
|
||||
|
||||
void Position::from_fen(const std::string& fen) {
|
||||
void Position::from_fen(const string& fen) {
|
||||
|
||||
static const std::string pieceLetters = "KQRBNPkqrbnp";
|
||||
static const string pieceLetters = "KQRBNPkqrbnp";
|
||||
static const Piece pieces[] = { WK, WQ, WR, WB, WN, WP, BK, BQ, BR, BB, BN, BP };
|
||||
|
||||
clear();
|
||||
@@ -100,7 +101,7 @@ void Position::from_fen(const std::string& fen) {
|
||||
continue;
|
||||
}
|
||||
size_t idx = pieceLetters.find(fen[i]);
|
||||
if (idx == std::string::npos)
|
||||
if (idx == string::npos)
|
||||
{
|
||||
std::cout << "Error in FEN at character " << i << std::endl;
|
||||
return;
|
||||
@@ -213,18 +214,18 @@ void Position::from_fen(const std::string& fen) {
|
||||
st->materialKey = compute_material_key();
|
||||
st->mgValue = compute_value<MidGame>();
|
||||
st->egValue = compute_value<EndGame>();
|
||||
npMaterial[WHITE] = compute_non_pawn_material(WHITE);
|
||||
npMaterial[BLACK] = compute_non_pawn_material(BLACK);
|
||||
st->npMaterial[WHITE] = compute_non_pawn_material(WHITE);
|
||||
st->npMaterial[BLACK] = compute_non_pawn_material(BLACK);
|
||||
}
|
||||
|
||||
|
||||
/// Position::to_fen() converts the position object to a FEN string. This is
|
||||
/// probably only useful for debugging.
|
||||
|
||||
const std::string Position::to_fen() const {
|
||||
const string Position::to_fen() const {
|
||||
|
||||
static const std::string pieceLetters = " PNBRQK pnbrqk";
|
||||
std::string fen;
|
||||
static const string pieceLetters = " PNBRQK pnbrqk";
|
||||
string fen;
|
||||
int skip;
|
||||
|
||||
for (Rank rank = RANK_8; rank >= RANK_1; rank--)
|
||||
@@ -274,7 +275,7 @@ const std::string Position::to_fen() const {
|
||||
|
||||
void Position::print(Move m) const {
|
||||
|
||||
static const std::string pieceLetters = " PNBRQK PNBRQK .";
|
||||
static const string pieceLetters = " PNBRQK PNBRQK .";
|
||||
|
||||
// Check for reentrancy, as example when called from inside
|
||||
// MovePicker that is used also here in move_to_san()
|
||||
@@ -286,7 +287,7 @@ void Position::print(Move m) const {
|
||||
std::cout << std::endl;
|
||||
if (m != MOVE_NONE)
|
||||
{
|
||||
std::string col = (color_of_piece_on(move_from(m)) == BLACK ? ".." : "");
|
||||
string col = (color_of_piece_on(move_from(m)) == BLACK ? ".." : "");
|
||||
std::cout << "Move is: " << col << move_to_san(*this, m) << std::endl;
|
||||
}
|
||||
for (Rank rank = RANK_8; rank >= RANK_1; rank--)
|
||||
@@ -314,9 +315,10 @@ void Position::print(Move m) const {
|
||||
|
||||
/// Position::copy() creates a copy of the input position.
|
||||
|
||||
void Position::copy(const Position &pos) {
|
||||
void Position::copy(const Position& pos) {
|
||||
|
||||
memcpy(this, &pos, sizeof(Position));
|
||||
saveState(); // detach and copy state info
|
||||
}
|
||||
|
||||
|
||||
@@ -377,9 +379,7 @@ Bitboard Position::discovered_check_candidates(Color c) const {
|
||||
}
|
||||
|
||||
/// Position::attacks_to() computes a bitboard containing all pieces which
|
||||
/// attacks a given square. There are two versions of this function: One
|
||||
/// which finds attackers of both colors, and one which only finds the
|
||||
/// attackers for one side.
|
||||
/// attacks a given square.
|
||||
|
||||
Bitboard Position::attacks_to(Square s) const {
|
||||
|
||||
@@ -460,7 +460,9 @@ void Position::find_checkers() {
|
||||
|
||||
bool Position::pl_move_is_legal(Move m) const {
|
||||
|
||||
return pl_move_is_legal(m, pinned_pieces(side_to_move()));
|
||||
// If we're in check, all pseudo-legal moves are legal, because our
|
||||
// check evasion generator only generates true legal moves.
|
||||
return is_check() || pl_move_is_legal(m, pinned_pieces(side_to_move()));
|
||||
}
|
||||
|
||||
bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
|
||||
@@ -468,11 +470,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
|
||||
assert(is_ok());
|
||||
assert(move_is_ok(m));
|
||||
assert(pinned == pinned_pieces(side_to_move()));
|
||||
|
||||
// If we're in check, all pseudo-legal moves are legal, because our
|
||||
// check evasion generator only generates true legal moves.
|
||||
if (is_check())
|
||||
return true;
|
||||
assert(!is_check());
|
||||
|
||||
// Castling moves are checked for legality during move generation.
|
||||
if (move_is_castle(m))
|
||||
@@ -557,12 +555,12 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const {
|
||||
&& (direction_between_squares(from, ksq) != direction_between_squares(to, ksq)))
|
||||
return true;
|
||||
|
||||
if (move_promotion(m)) // Promotion with check?
|
||||
if (move_is_promotion(m)) // Promotion with check?
|
||||
{
|
||||
Bitboard b = occupied_squares();
|
||||
clear_bit(&b, from);
|
||||
|
||||
switch (move_promotion(m))
|
||||
switch (move_promotion_piece(m))
|
||||
{
|
||||
case KNIGHT:
|
||||
return bit_is_set(piece_attacks<KNIGHT>(to), ksq);
|
||||
@@ -660,6 +658,7 @@ inline void Position::update_checkers(Bitboard* pCheckersBB, Square ksq, Square
|
||||
const bool Rook = (Piece == QUEEN || Piece == ROOK);
|
||||
const bool Slider = Bishop || Rook;
|
||||
|
||||
// Direct checks
|
||||
if ( ( (Bishop && bit_is_set(BishopPseudoAttacks[ksq], to))
|
||||
|| (Rook && bit_is_set(RookPseudoAttacks[ksq], to)))
|
||||
&& bit_is_set(piece_attacks<Piece>(ksq), to)) // slow, try to early skip
|
||||
@@ -670,6 +669,7 @@ inline void Position::update_checkers(Bitboard* pCheckersBB, Square ksq, Square
|
||||
&& bit_is_set(piece_attacks<Piece>(ksq), to))
|
||||
set_bit(pCheckersBB, to);
|
||||
|
||||
// Discovery checks
|
||||
if (Piece != QUEEN && bit_is_set(dcCandidates, from))
|
||||
{
|
||||
if (Piece != ROOK)
|
||||
@@ -703,6 +703,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
|
||||
int castleRights, rule50;
|
||||
Square epSquare;
|
||||
Value mgValue, egValue;
|
||||
Value npMaterial[2];
|
||||
};
|
||||
|
||||
memcpy(&newSt, st, sizeof(ReducedStateInfo));
|
||||
@@ -720,7 +721,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
|
||||
|
||||
if (move_is_castle(m))
|
||||
do_castle_move(m);
|
||||
else if (move_promotion(m))
|
||||
else if (move_is_promotion(m))
|
||||
do_promotion_move(m);
|
||||
else if (move_is_ep(m))
|
||||
do_ep_move(m);
|
||||
@@ -734,7 +735,8 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
|
||||
assert(color_of_piece_on(from) == us);
|
||||
assert(color_of_piece_on(to) == them || piece_on(to) == EMPTY);
|
||||
|
||||
PieceType piece = type_of_piece_on(from);
|
||||
Piece piece = piece_on(from);
|
||||
PieceType pt = type_of_piece(piece);
|
||||
|
||||
st->capture = type_of_piece_on(to);
|
||||
|
||||
@@ -742,26 +744,23 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
|
||||
do_capture_move(st->capture, them, to);
|
||||
|
||||
// Move the piece
|
||||
clear_bit(&(byColorBB[us]), from);
|
||||
clear_bit(&(byTypeBB[piece]), from);
|
||||
clear_bit(&(byTypeBB[0]), from); // HACK: byTypeBB[0] == occupied squares
|
||||
set_bit(&(byColorBB[us]), to);
|
||||
set_bit(&(byTypeBB[piece]), to);
|
||||
set_bit(&(byTypeBB[0]), to); // HACK: byTypeBB[0] == occupied squares
|
||||
Bitboard move_bb = make_move_bb(from, to);
|
||||
do_move_bb(&(byColorBB[us]), move_bb);
|
||||
do_move_bb(&(byTypeBB[pt]), move_bb);
|
||||
do_move_bb(&(byTypeBB[0]), move_bb); // HACK: byTypeBB[0] == occupied squares
|
||||
|
||||
board[to] = board[from];
|
||||
board[from] = EMPTY;
|
||||
|
||||
// Update hash key
|
||||
st->key ^= zobrist[us][piece][from] ^ zobrist[us][piece][to];
|
||||
st->key ^= zobrist[us][pt][from] ^ zobrist[us][pt][to];
|
||||
|
||||
// Update incremental scores
|
||||
st->mgValue -= pst<MidGame>(us, piece, from);
|
||||
st->mgValue += pst<MidGame>(us, piece, to);
|
||||
st->egValue -= pst<EndGame>(us, piece, from);
|
||||
st->egValue += pst<EndGame>(us, piece, to);
|
||||
st->mgValue += pst_delta<MidGame>(piece, from, to);
|
||||
st->egValue += pst_delta<EndGame>(piece, from, to);
|
||||
|
||||
// If the moving piece was a king, update the king square
|
||||
if (piece == KING)
|
||||
if (pt == KING)
|
||||
kingSquare[us] = to;
|
||||
|
||||
// Reset en passant square
|
||||
@@ -772,7 +771,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
|
||||
}
|
||||
|
||||
// If the moving piece was a pawn do some special extra work
|
||||
if (piece == PAWN)
|
||||
if (pt == PAWN)
|
||||
{
|
||||
// Reset rule 50 draw counter
|
||||
st->rule50 = 0;
|
||||
@@ -793,19 +792,22 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
|
||||
}
|
||||
|
||||
// Update piece lists
|
||||
pieceList[us][piece][index[from]] = to;
|
||||
pieceList[us][pt][index[from]] = to;
|
||||
index[to] = index[from];
|
||||
|
||||
// Update castle rights
|
||||
st->key ^= zobCastle[st->castleRights];
|
||||
st->castleRights &= castleRightsMask[from];
|
||||
st->castleRights &= castleRightsMask[to];
|
||||
st->key ^= zobCastle[st->castleRights];
|
||||
// Update castle rights, try to shortcut a common case
|
||||
if ((castleRightsMask[from] & castleRightsMask[to]) != ALL_CASTLES)
|
||||
{
|
||||
st->key ^= zobCastle[st->castleRights];
|
||||
st->castleRights &= castleRightsMask[from];
|
||||
st->castleRights &= castleRightsMask[to];
|
||||
st->key ^= zobCastle[st->castleRights];
|
||||
}
|
||||
|
||||
// Update checkers bitboard, piece must be already moved
|
||||
st->checkersBB = EmptyBoardBB;
|
||||
Square ksq = king_square(them);
|
||||
switch (piece)
|
||||
switch (pt)
|
||||
{
|
||||
case PAWN: update_checkers<PAWN>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
|
||||
case KNIGHT: update_checkers<KNIGHT>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
|
||||
@@ -839,6 +841,7 @@ void Position::do_capture_move(PieceType capture, Color them, Square to) {
|
||||
// Remove captured piece
|
||||
clear_bit(&(byColorBB[them]), to);
|
||||
clear_bit(&(byTypeBB[capture]), to);
|
||||
clear_bit(&(byTypeBB[0]), to);
|
||||
|
||||
// Update hash key
|
||||
st->key ^= zobrist[them][capture][to];
|
||||
@@ -853,7 +856,7 @@ void Position::do_capture_move(PieceType capture, Color them, Square to) {
|
||||
|
||||
// Update material
|
||||
if (capture != PAWN)
|
||||
npMaterial[them] -= piece_value_midgame(capture);
|
||||
st->npMaterial[them] -= piece_value_midgame(capture);
|
||||
|
||||
// Update material hash key
|
||||
st->materialKey ^= zobMaterial[them][capture][pieceCount[them][capture]];
|
||||
@@ -919,9 +922,11 @@ void Position::do_castle_move(Move m) {
|
||||
set_bit(&(byTypeBB[0]), rto); // HACK: byTypeBB[0] == occupied squares
|
||||
|
||||
// Update board array
|
||||
Piece king = piece_of_color_and_type(us, KING);
|
||||
Piece rook = piece_of_color_and_type(us, ROOK);
|
||||
board[kfrom] = board[rfrom] = EMPTY;
|
||||
board[kto] = piece_of_color_and_type(us, KING);
|
||||
board[rto] = piece_of_color_and_type(us, ROOK);
|
||||
board[kto] = king;
|
||||
board[rto] = rook;
|
||||
|
||||
// Update king square
|
||||
kingSquare[us] = kto;
|
||||
@@ -934,14 +939,10 @@ void Position::do_castle_move(Move m) {
|
||||
index[rto] = tmp;
|
||||
|
||||
// Update incremental scores
|
||||
st->mgValue -= pst<MidGame>(us, KING, kfrom);
|
||||
st->mgValue += pst<MidGame>(us, KING, kto);
|
||||
st->egValue -= pst<EndGame>(us, KING, kfrom);
|
||||
st->egValue += pst<EndGame>(us, KING, kto);
|
||||
st->mgValue -= pst<MidGame>(us, ROOK, rfrom);
|
||||
st->mgValue += pst<MidGame>(us, ROOK, rto);
|
||||
st->egValue -= pst<EndGame>(us, ROOK, rfrom);
|
||||
st->egValue += pst<EndGame>(us, ROOK, rto);
|
||||
st->mgValue += pst_delta<MidGame>(king, kfrom, kto);
|
||||
st->egValue += pst_delta<EndGame>(king, kfrom, kto);
|
||||
st->mgValue += pst_delta<MidGame>(rook, rfrom, rto);
|
||||
st->egValue += pst_delta<EndGame>(rook, rfrom, rto);
|
||||
|
||||
// Update hash key
|
||||
st->key ^= zobrist[us][KING][kfrom] ^ zobrist[us][KING][kto];
|
||||
@@ -978,7 +979,7 @@ void Position::do_promotion_move(Move m) {
|
||||
|
||||
assert(is_ok());
|
||||
assert(move_is_ok(m));
|
||||
assert(move_promotion(m));
|
||||
assert(move_is_promotion(m));
|
||||
|
||||
us = side_to_move();
|
||||
them = opposite_color(us);
|
||||
@@ -992,7 +993,7 @@ void Position::do_promotion_move(Move m) {
|
||||
st->capture = type_of_piece_on(to);
|
||||
|
||||
if (st->capture)
|
||||
do_capture_move(st->capture, them, to);
|
||||
do_capture_move(st->capture, them, to);
|
||||
|
||||
// Remove pawn
|
||||
clear_bit(&(byColorBB[us]), from);
|
||||
@@ -1001,7 +1002,7 @@ void Position::do_promotion_move(Move m) {
|
||||
board[from] = EMPTY;
|
||||
|
||||
// Insert promoted piece
|
||||
promotion = move_promotion(m);
|
||||
promotion = move_promotion_piece(m);
|
||||
assert(promotion >= KNIGHT && promotion <= QUEEN);
|
||||
set_bit(&(byColorBB[us]), to);
|
||||
set_bit(&(byTypeBB[promotion]), to);
|
||||
@@ -1035,7 +1036,7 @@ void Position::do_promotion_move(Move m) {
|
||||
st->egValue += pst<EndGame>(us, promotion, to);
|
||||
|
||||
// Update material
|
||||
npMaterial[us] += piece_value_midgame(promotion);
|
||||
st->npMaterial[us] += piece_value_midgame(promotion);
|
||||
|
||||
// Clear the en passant square
|
||||
if (st->epSquare != SQ_NONE)
|
||||
@@ -1081,21 +1082,17 @@ void Position::do_ep_move(Move m) {
|
||||
assert(piece_on(from) == piece_of_color_and_type(us, PAWN));
|
||||
assert(piece_on(capsq) == piece_of_color_and_type(them, PAWN));
|
||||
|
||||
// Remove captured piece
|
||||
// Remove captured pawn
|
||||
clear_bit(&(byColorBB[them]), capsq);
|
||||
clear_bit(&(byTypeBB[PAWN]), capsq);
|
||||
clear_bit(&(byTypeBB[0]), capsq); // HACK: byTypeBB[0] == occupied squares
|
||||
board[capsq] = EMPTY;
|
||||
|
||||
// Remove moving piece from source square
|
||||
clear_bit(&(byColorBB[us]), from);
|
||||
clear_bit(&(byTypeBB[PAWN]), from);
|
||||
clear_bit(&(byTypeBB[0]), from); // HACK: byTypeBB[0] == occupied squares
|
||||
|
||||
// Put moving piece on destination square
|
||||
set_bit(&(byColorBB[us]), to);
|
||||
set_bit(&(byTypeBB[PAWN]), to);
|
||||
set_bit(&(byTypeBB[0]), to); // HACK: byTypeBB[0] == occupied squares
|
||||
// Move capturing pawn
|
||||
Bitboard move_bb = make_move_bb(from, to);
|
||||
do_move_bb(&(byColorBB[us]), move_bb);
|
||||
do_move_bb(&(byTypeBB[PAWN]), move_bb);
|
||||
do_move_bb(&(byTypeBB[0]), move_bb); // HACK: byTypeBB[0] == occupied squares
|
||||
board[to] = board[from];
|
||||
board[from] = EMPTY;
|
||||
|
||||
@@ -1121,12 +1118,11 @@ void Position::do_ep_move(Move m) {
|
||||
st->pawnKey ^= zobrist[them][PAWN][capsq];
|
||||
|
||||
// Update incremental scores
|
||||
Piece pawn = piece_of_color_and_type(us, PAWN);
|
||||
st->mgValue += pst_delta<MidGame>(pawn, from, to);
|
||||
st->egValue += pst_delta<EndGame>(pawn, from, to);
|
||||
st->mgValue -= pst<MidGame>(them, PAWN, capsq);
|
||||
st->mgValue -= pst<MidGame>(us, PAWN, from);
|
||||
st->mgValue += pst<MidGame>(us, PAWN, to);
|
||||
st->egValue -= pst<EndGame>(them, PAWN, capsq);
|
||||
st->egValue -= pst<EndGame>(us, PAWN, from);
|
||||
st->egValue += pst<EndGame>(us, PAWN, to);
|
||||
|
||||
// Reset en passant square
|
||||
st->epSquare = SQ_NONE;
|
||||
@@ -1152,7 +1148,7 @@ void Position::undo_move(Move m) {
|
||||
|
||||
if (move_is_castle(m))
|
||||
undo_castle_move(m);
|
||||
else if (move_promotion(m))
|
||||
else if (move_is_promotion(m))
|
||||
undo_promotion_move(m);
|
||||
else if (move_is_ep(m))
|
||||
undo_ep_move(m);
|
||||
@@ -1171,17 +1167,13 @@ void Position::undo_move(Move m) {
|
||||
assert(color_of_piece_on(to) == us);
|
||||
|
||||
// Put the piece back at the source square
|
||||
Bitboard move_bb = make_move_bb(to, from);
|
||||
piece = type_of_piece_on(to);
|
||||
set_bit(&(byColorBB[us]), from);
|
||||
set_bit(&(byTypeBB[piece]), from);
|
||||
set_bit(&(byTypeBB[0]), from); // HACK: byTypeBB[0] == occupied squares
|
||||
do_move_bb(&(byColorBB[us]), move_bb);
|
||||
do_move_bb(&(byTypeBB[piece]), move_bb);
|
||||
do_move_bb(&(byTypeBB[0]), move_bb); // HACK: byTypeBB[0] == occupied squares
|
||||
board[from] = piece_of_color_and_type(us, piece);
|
||||
|
||||
// Clear the destination square
|
||||
clear_bit(&(byColorBB[us]), to);
|
||||
clear_bit(&(byTypeBB[piece]), to);
|
||||
clear_bit(&(byTypeBB[0]), to); // HACK: byTypeBB[0] == occupied squares
|
||||
|
||||
// If the moving piece was a king, update the king square
|
||||
if (piece == KING)
|
||||
kingSquare[us] = from;
|
||||
@@ -1194,16 +1186,12 @@ void Position::undo_move(Move m) {
|
||||
{
|
||||
assert(st->capture != KING);
|
||||
|
||||
// Replace the captured piece
|
||||
// Restore the captured piece
|
||||
set_bit(&(byColorBB[them]), to);
|
||||
set_bit(&(byTypeBB[st->capture]), to);
|
||||
set_bit(&(byTypeBB[0]), to);
|
||||
board[to] = piece_of_color_and_type(them, st->capture);
|
||||
|
||||
// Update material
|
||||
if (st->capture != PAWN)
|
||||
npMaterial[them] += piece_value_midgame(st->capture);
|
||||
|
||||
// Update piece list
|
||||
pieceList[them][st->capture][pieceCount[them][st->capture]] = to;
|
||||
index[to] = pieceCount[them][st->capture];
|
||||
@@ -1298,7 +1286,7 @@ void Position::undo_promotion_move(Move m) {
|
||||
PieceType promotion;
|
||||
|
||||
assert(move_is_ok(m));
|
||||
assert(move_promotion(m));
|
||||
assert(move_is_promotion(m));
|
||||
|
||||
// When we have arrived here, some work has already been done by
|
||||
// Position::undo_move. In particular, the side to move has been switched,
|
||||
@@ -1312,7 +1300,7 @@ void Position::undo_promotion_move(Move m) {
|
||||
assert(piece_on(from) == EMPTY);
|
||||
|
||||
// Remove promoted piece
|
||||
promotion = move_promotion(m);
|
||||
promotion = move_promotion_piece(m);
|
||||
assert(piece_on(to)==piece_of_color_and_type(us, promotion));
|
||||
assert(promotion >= KNIGHT && promotion <= QUEEN);
|
||||
clear_bit(&(byColorBB[us]), to);
|
||||
@@ -1325,9 +1313,6 @@ void Position::undo_promotion_move(Move m) {
|
||||
set_bit(&(byTypeBB[0]), from); // HACK: byTypeBB[0] == occupied squares
|
||||
board[from] = piece_of_color_and_type(us, PAWN);
|
||||
|
||||
// Update material
|
||||
npMaterial[us] -= piece_value_midgame(promotion);
|
||||
|
||||
// Update piece list
|
||||
pieceList[us][PAWN][pieceCount[us][PAWN]] = from;
|
||||
index[from] = pieceCount[us][PAWN];
|
||||
@@ -1349,11 +1334,6 @@ void Position::undo_promotion_move(Move m) {
|
||||
set_bit(&(byTypeBB[0]), to); // HACK: byTypeBB[0] == occupied squares
|
||||
board[to] = piece_of_color_and_type(them, st->capture);
|
||||
|
||||
// Update material. Because the move is a promotion move, we know
|
||||
// that the captured piece cannot be a pawn.
|
||||
assert(st->capture != PAWN);
|
||||
npMaterial[them] += piece_value_midgame(st->capture);
|
||||
|
||||
// Update piece list
|
||||
pieceList[them][st->capture][pieceCount[them][st->capture]] = to;
|
||||
index[to] = pieceCount[them][st->capture];
|
||||
@@ -1388,31 +1368,27 @@ void Position::undo_ep_move(Move m) {
|
||||
assert(piece_on(from) == EMPTY);
|
||||
assert(piece_on(capsq) == EMPTY);
|
||||
|
||||
// Replace captured piece
|
||||
// Restore captured pawn
|
||||
set_bit(&(byColorBB[them]), capsq);
|
||||
set_bit(&(byTypeBB[PAWN]), capsq);
|
||||
set_bit(&(byTypeBB[0]), capsq);
|
||||
board[capsq] = piece_of_color_and_type(them, PAWN);
|
||||
|
||||
// Remove moving piece from destination square
|
||||
clear_bit(&(byColorBB[us]), to);
|
||||
clear_bit(&(byTypeBB[PAWN]), to);
|
||||
clear_bit(&(byTypeBB[0]), to);
|
||||
// Move capturing pawn back to source square
|
||||
Bitboard move_bb = make_move_bb(to, from);
|
||||
do_move_bb(&(byColorBB[us]), move_bb);
|
||||
do_move_bb(&(byTypeBB[PAWN]), move_bb);
|
||||
do_move_bb(&(byTypeBB[0]), move_bb);
|
||||
board[to] = EMPTY;
|
||||
|
||||
// Replace moving piece at source square
|
||||
set_bit(&(byColorBB[us]), from);
|
||||
set_bit(&(byTypeBB[PAWN]), from);
|
||||
set_bit(&(byTypeBB[0]), from);
|
||||
board[from] = piece_of_color_and_type(us, PAWN);
|
||||
|
||||
// Update piece list:
|
||||
// Update piece list
|
||||
pieceList[us][PAWN][index[to]] = from;
|
||||
index[from] = index[to];
|
||||
pieceList[them][PAWN][pieceCount[them][PAWN]] = capsq;
|
||||
index[capsq] = pieceCount[them][PAWN];
|
||||
|
||||
// Update piece count:
|
||||
// Update piece count
|
||||
pieceCount[them][PAWN]++;
|
||||
}
|
||||
|
||||
@@ -1426,12 +1402,13 @@ void Position::do_null_move(StateInfo& backupSt) {
|
||||
assert(!is_check());
|
||||
|
||||
// Back up the information necessary to undo the null move to the supplied
|
||||
// StateInfo object. In the case of a null move, the only thing we need to
|
||||
// remember is the last move made and the en passant square.
|
||||
// StateInfo object.
|
||||
// Note that differently from normal case here backupSt is actually used as
|
||||
// a backup storage not as a new state to be used.
|
||||
backupSt.lastMove = st->lastMove;
|
||||
backupSt.epSquare = st->epSquare;
|
||||
backupSt.key = st->key;
|
||||
backupSt.mgValue = st->mgValue;
|
||||
backupSt.egValue = st->egValue;
|
||||
backupSt.previous = st->previous;
|
||||
st->previous = &backupSt;
|
||||
|
||||
@@ -1464,21 +1441,16 @@ void Position::undo_null_move() {
|
||||
assert(!is_check());
|
||||
|
||||
// Restore information from the our backup StateInfo object
|
||||
st->lastMove = st->previous->lastMove;
|
||||
st->epSquare = st->previous->epSquare;
|
||||
st->key = st->previous->key;
|
||||
st->mgValue = st->previous->mgValue;
|
||||
st->egValue = st->previous->egValue;
|
||||
st->previous = st->previous->previous;
|
||||
|
||||
if (st->epSquare != SQ_NONE)
|
||||
st->key ^= zobEp[st->epSquare];
|
||||
|
||||
// Update the necessary information
|
||||
sideToMove = opposite_color(sideToMove);
|
||||
st->rule50--;
|
||||
gamePly--;
|
||||
st->key ^= zobSideToMove;
|
||||
|
||||
st->mgValue += (sideToMove == WHITE)? TempoValueMidgame : -TempoValueMidgame;
|
||||
st->egValue += (sideToMove == WHITE)? TempoValueEndgame : -TempoValueEndgame;
|
||||
|
||||
assert(is_ok());
|
||||
}
|
||||
@@ -1513,7 +1485,7 @@ int Position::see(Square from, Square to) const {
|
||||
0, 0
|
||||
};
|
||||
|
||||
Bitboard attackers, occ, b;
|
||||
Bitboard attackers, stmAttackers, occ, b;
|
||||
|
||||
assert(square_is_ok(from) || from == SQ_NONE);
|
||||
assert(square_is_ok(to));
|
||||
@@ -1537,7 +1509,6 @@ int Position::see(Square from, Square to) const {
|
||||
|
||||
Square capQq = (side_to_move() == WHITE)? (to - DELTA_N) : (to - DELTA_S);
|
||||
capture = piece_on(capQq);
|
||||
|
||||
assert(type_of_piece_on(capQq) == PAWN);
|
||||
|
||||
// Remove the captured pawn
|
||||
@@ -1572,7 +1543,8 @@ int Position::see(Square from, Square to) const {
|
||||
}
|
||||
|
||||
// If the opponent has no attackers we are finished
|
||||
if ((attackers & pieces_of_color(them)) == EmptyBoardBB)
|
||||
stmAttackers = attackers & pieces_of_color(them);
|
||||
if (!stmAttackers)
|
||||
return seeValues[capture];
|
||||
|
||||
attackers &= occ; // Remove the moving piece
|
||||
@@ -1594,12 +1566,12 @@ int Position::see(Square from, Square to) const {
|
||||
// Locate the least valuable attacker for the side to move. The loop
|
||||
// below looks like it is potentially infinite, but it isn't. We know
|
||||
// that the side to move still has at least one attacker left.
|
||||
for (pt = PAWN; !(attackers & pieces_of_color_and_type(c, pt)); pt++)
|
||||
for (pt = PAWN; !(stmAttackers & pieces_of_type(pt)); pt++)
|
||||
assert(pt < KING);
|
||||
|
||||
// Remove the attacker we just found from the 'attackers' bitboard,
|
||||
// and scan for new X-ray attacks behind the attacker.
|
||||
b = attackers & pieces_of_color_and_type(c, pt);
|
||||
b = stmAttackers & pieces_of_type(pt);
|
||||
occ ^= (b & (~b + 1));
|
||||
attackers |= (rook_attacks_bb(to, occ) & rooks_and_queens())
|
||||
| (bishop_attacks_bb(to, occ) & bishops_and_queens());
|
||||
@@ -1615,15 +1587,16 @@ int Position::see(Square from, Square to) const {
|
||||
// before beginning the next iteration
|
||||
lastCapturingPieceValue = seeValues[pt];
|
||||
c = opposite_color(c);
|
||||
stmAttackers = attackers & pieces_of_color(c);
|
||||
|
||||
// Stop after a king capture
|
||||
if (pt == KING && (attackers & pieces_of_color(c)))
|
||||
if (pt == KING && stmAttackers)
|
||||
{
|
||||
assert(n < 32);
|
||||
swapList[n++] = 100;
|
||||
swapList[n++] = QueenValueMidgame*10;
|
||||
break;
|
||||
}
|
||||
} while (attackers & pieces_of_color(c));
|
||||
} while (stmAttackers);
|
||||
|
||||
// Having built the swap list, we negamax through it to find the best
|
||||
// achievable score from the point of view of the side to move
|
||||
@@ -1634,15 +1607,16 @@ int Position::see(Square from, Square to) const {
|
||||
}
|
||||
|
||||
|
||||
/// Position::setStartState() copies the content of the argument
|
||||
/// Position::saveState() copies the content of the current state
|
||||
/// inside startState and makes st point to it. This is needed
|
||||
/// when the st pointee could become stale, as example because
|
||||
/// the caller is about to going out of scope.
|
||||
|
||||
void Position::setStartState(const StateInfo& s) {
|
||||
void Position::saveState() {
|
||||
|
||||
startState = s;
|
||||
startState = *st;
|
||||
st = &startState;
|
||||
st->previous = NULL; // as a safe guard
|
||||
}
|
||||
|
||||
|
||||
@@ -1993,7 +1967,7 @@ void Position::init_piece_square_tables() {
|
||||
/// the white and black sides reversed. This is only useful for debugging,
|
||||
/// especially for finding evaluation symmetry bugs.
|
||||
|
||||
void Position::flipped_copy(const Position &pos) {
|
||||
void Position::flipped_copy(const Position& pos) {
|
||||
|
||||
assert(pos.is_ok());
|
||||
|
||||
@@ -2044,8 +2018,8 @@ void Position::flipped_copy(const Position &pos) {
|
||||
st->egValue = compute_value<EndGame>();
|
||||
|
||||
// Material
|
||||
npMaterial[WHITE] = compute_non_pawn_material(WHITE);
|
||||
npMaterial[BLACK] = compute_non_pawn_material(BLACK);
|
||||
st->npMaterial[WHITE] = compute_non_pawn_material(WHITE);
|
||||
st->npMaterial[BLACK] = compute_non_pawn_material(BLACK);
|
||||
|
||||
assert(is_ok());
|
||||
}
|
||||
@@ -2181,10 +2155,10 @@ bool Position::is_ok(int* failedStep) const {
|
||||
if (failedStep) (*failedStep)++;
|
||||
if (debugNonPawnMaterial)
|
||||
{
|
||||
if (npMaterial[WHITE] != compute_non_pawn_material(WHITE))
|
||||
if (st->npMaterial[WHITE] != compute_non_pawn_material(WHITE))
|
||||
return false;
|
||||
|
||||
if (npMaterial[BLACK] != compute_non_pawn_material(BLACK))
|
||||
if (st->npMaterial[BLACK] != compute_non_pawn_material(BLACK))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
118
src/position.h
118
src/position.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -21,7 +21,7 @@
|
||||
#if !defined(POSITION_H_INCLUDED)
|
||||
#define POSITION_H_INCLUDED
|
||||
|
||||
// Disable a silly and noisy warning from MSVC compiler
|
||||
// Disable some silly and noisy warning from MSVC compiler
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
// Forcing value to bool 'true' or 'false' (performance warning)
|
||||
@@ -50,13 +50,12 @@
|
||||
//// Constants
|
||||
////
|
||||
|
||||
/// FEN string for the initial position:
|
||||
const std::string StartPosition =
|
||||
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
||||
/// FEN string for the initial position
|
||||
const std::string StartPosition = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
||||
|
||||
/// Maximum number of plies per game (220 should be enough, because the
|
||||
/// maximum search depth is 100, and during position setup we reset the
|
||||
/// move counter for every non-reversible move):
|
||||
/// move counter for every non-reversible move).
|
||||
const int MaxGameLength = 220;
|
||||
|
||||
|
||||
@@ -67,11 +66,11 @@ const int MaxGameLength = 220;
|
||||
/// Castle rights, encoded as bit fields
|
||||
|
||||
enum CastleRights {
|
||||
NO_CASTLES = 0,
|
||||
WHITE_OO = 1,
|
||||
BLACK_OO = 2,
|
||||
WHITE_OOO = 4,
|
||||
BLACK_OOO = 8,
|
||||
NO_CASTLES = 0,
|
||||
WHITE_OO = 1,
|
||||
BLACK_OO = 2,
|
||||
WHITE_OOO = 4,
|
||||
BLACK_OOO = 8,
|
||||
ALL_CASTLES = 15
|
||||
};
|
||||
|
||||
@@ -92,34 +91,33 @@ struct StateInfo {
|
||||
int castleRights, rule50;
|
||||
Square epSquare;
|
||||
Value mgValue, egValue;
|
||||
Value npMaterial[2];
|
||||
|
||||
PieceType capture;
|
||||
Bitboard checkersBB;
|
||||
Move lastMove;
|
||||
StateInfo* previous;
|
||||
};
|
||||
|
||||
|
||||
/// The position data structure. A position consists of the following data:
|
||||
/// The position data structure. A position consists of the following data:
|
||||
///
|
||||
/// * For each piece type, a bitboard representing the squares occupied
|
||||
/// by pieces of that type.
|
||||
/// * For each color, a bitboard representing the squares occupiecd by
|
||||
/// * For each color, a bitboard representing the squares occupied by
|
||||
/// pieces of that color.
|
||||
/// * A bitboard of all occupied squares.
|
||||
/// * A bitboard of all checking pieces.
|
||||
/// * A 64-entry array of pieces, indexed by the squares of the board.
|
||||
/// * The current side to move.
|
||||
/// * Information about the castling rights for both sides.
|
||||
/// * The initial files of the kings and both pairs of rooks. This is
|
||||
/// * The initial files of the kings and both pairs of rooks. This is
|
||||
/// used to implement the Chess960 castling rules.
|
||||
/// * The en passant square (which is SQ_NONE if no en passant capture is
|
||||
/// possible).
|
||||
/// * The squares of the kings for both sides.
|
||||
/// * The last move played.
|
||||
/// * Hash keys for the position itself, the current pawn structure, and
|
||||
/// the current material situation.
|
||||
/// * Hash keys for all previous positions in the game (for detecting
|
||||
/// * Hash keys for all previous positions in the game for detecting
|
||||
/// repetition draws.
|
||||
/// * A counter for detecting 50 move rule draws.
|
||||
|
||||
@@ -129,6 +127,11 @@ class Position {
|
||||
friend class EndgameFunctions;
|
||||
|
||||
public:
|
||||
enum GamePhase {
|
||||
MidGame,
|
||||
EndGame
|
||||
};
|
||||
|
||||
// Constructors
|
||||
Position() {};
|
||||
Position(const Position& pos);
|
||||
@@ -140,8 +143,8 @@ public:
|
||||
void print(Move m = MOVE_NONE) const;
|
||||
|
||||
// Copying
|
||||
void copy(const Position &pos);
|
||||
void flipped_copy(const Position &pos);
|
||||
void copy(const Position& pos);
|
||||
void flipped_copy(const Position& pos);
|
||||
|
||||
// The piece on a given square
|
||||
Piece piece_on(Square s) const;
|
||||
@@ -241,18 +244,19 @@ public:
|
||||
|
||||
// Information about pawns
|
||||
bool pawn_is_passed(Color c, Square s) const;
|
||||
bool pawn_is_isolated(Color c, Square s) const;
|
||||
bool pawn_is_doubled(Color c, Square s) const;
|
||||
static bool pawn_is_passed(Bitboard theirPawns, Color c, Square s);
|
||||
static bool pawn_is_isolated(Bitboard ourPawns, Square s);
|
||||
static bool pawn_is_doubled(Bitboard ourPawns, Color c, Square s);
|
||||
|
||||
// Open and half-open files
|
||||
bool file_is_open(File f) const;
|
||||
bool file_is_half_open(Color c, File f) const;
|
||||
static bool file_is_open(Bitboard pawns, File f);
|
||||
static bool file_is_half_open(Bitboard pawns, File f);
|
||||
|
||||
// Weak squares
|
||||
bool square_is_weak(Square s, Color c) const;
|
||||
|
||||
// Doing and undoing moves
|
||||
void setStartState(const StateInfo& st);
|
||||
void saveState();
|
||||
void do_move(Move m, StateInfo& st);
|
||||
void do_move(Move m, StateInfo& st, Bitboard dcCandidates);
|
||||
void undo_move(Move m);
|
||||
@@ -274,7 +278,7 @@ public:
|
||||
Value eg_value() const;
|
||||
Value non_pawn_material(Color c) const;
|
||||
Phase game_phase() const;
|
||||
Value mg_pst_delta(Move m) const;
|
||||
template<GamePhase> Value pst_delta(Piece piece, Square from, Square to) const;
|
||||
|
||||
// Game termination checks
|
||||
bool is_mate() const;
|
||||
@@ -330,10 +334,6 @@ private:
|
||||
Key compute_material_key() const;
|
||||
|
||||
// Computing incremental evaluation scores and material counts
|
||||
enum GamePhase {
|
||||
MidGame,
|
||||
EndGame
|
||||
};
|
||||
template<GamePhase> Value pst(Color c, PieceType pt, Square s) const;
|
||||
template<GamePhase> Value compute_value() const;
|
||||
Value compute_non_pawn_material(Color c) const;
|
||||
@@ -356,7 +356,6 @@ private:
|
||||
Color sideToMove;
|
||||
int gamePly;
|
||||
Key history[MaxGameLength];
|
||||
Value npMaterial[2];
|
||||
File initialKFile, initialKRFile, initialQRFile;
|
||||
StateInfo startState;
|
||||
StateInfo* st;
|
||||
@@ -497,10 +496,6 @@ inline Bitboard Position::bishops_and_queens(Color c) const {
|
||||
return bishops_and_queens() & pieces_of_color(c);
|
||||
}
|
||||
|
||||
inline Bitboard Position::sliders_of_color(Color c) const {
|
||||
return sliders() & pieces_of_color(c);
|
||||
}
|
||||
|
||||
inline int Position::piece_count(Color c, PieceType pt) const {
|
||||
return pieceCount[c][pt];
|
||||
}
|
||||
@@ -541,14 +536,14 @@ inline Bitboard Position::pawn_attacks(Color c, Square s) const {
|
||||
return StepAttackBB[piece_of_color_and_type(c, PAWN)][s];
|
||||
}
|
||||
|
||||
template<>
|
||||
inline Bitboard Position::piece_attacks<PAWN>(Square s) const {
|
||||
return StepAttackBB[piece_of_color_and_type(opposite_color(sideToMove), PAWN)][s];
|
||||
template<PieceType Piece> // Knight and King
|
||||
inline Bitboard Position::piece_attacks(Square s) const {
|
||||
return StepAttackBB[Piece][s];
|
||||
}
|
||||
|
||||
template<>
|
||||
inline Bitboard Position::piece_attacks<KNIGHT>(Square s) const {
|
||||
return StepAttackBB[KNIGHT][s];
|
||||
inline Bitboard Position::piece_attacks<PAWN>(Square s) const {
|
||||
return StepAttackBB[piece_of_color_and_type(opposite_color(sideToMove), PAWN)][s];
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -566,11 +561,6 @@ inline Bitboard Position::piece_attacks<QUEEN>(Square s) const {
|
||||
return piece_attacks<ROOK>(s) | piece_attacks<BISHOP>(s);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline Bitboard Position::piece_attacks<KING>(Square s) const {
|
||||
return StepAttackBB[KING][s];
|
||||
}
|
||||
|
||||
inline Bitboard Position::checkers() const {
|
||||
return st->checkersBB;
|
||||
}
|
||||
@@ -602,20 +592,24 @@ inline bool Position::pawn_is_passed(Color c, Square s) const {
|
||||
return !(pawns(opposite_color(c)) & passed_pawn_mask(c, s));
|
||||
}
|
||||
|
||||
inline bool Position::pawn_is_isolated(Color c, Square s) const {
|
||||
return !(pawns(c) & neighboring_files_bb(s));
|
||||
inline bool Position::pawn_is_passed(Bitboard theirPawns, Color c, Square s) {
|
||||
return !(theirPawns & passed_pawn_mask(c, s));
|
||||
}
|
||||
|
||||
inline bool Position::pawn_is_doubled(Color c, Square s) const {
|
||||
return pawns(c) & squares_behind(c, s);
|
||||
inline bool Position::pawn_is_isolated(Bitboard ourPawns, Square s) {
|
||||
return !(ourPawns & neighboring_files_bb(s));
|
||||
}
|
||||
|
||||
inline bool Position::file_is_open(File f) const {
|
||||
return !(pawns() & file_bb(f));
|
||||
inline bool Position::pawn_is_doubled(Bitboard ourPawns, Color c, Square s) {
|
||||
return ourPawns & squares_behind(c, s);
|
||||
}
|
||||
|
||||
inline bool Position::file_is_half_open(Color c, File f) const {
|
||||
return !(pawns(c) & file_bb(f));
|
||||
inline bool Position::file_is_open(Bitboard pawns, File f) {
|
||||
return !(pawns & file_bb(f));
|
||||
}
|
||||
|
||||
inline bool Position::file_is_half_open(Bitboard pawns, File f) {
|
||||
return !(pawns & file_bb(f));
|
||||
}
|
||||
|
||||
inline bool Position::square_is_weak(Square s, Color c) const {
|
||||
@@ -634,15 +628,16 @@ inline Key Position::get_material_key() const {
|
||||
return st->materialKey;
|
||||
}
|
||||
|
||||
template<Position::GamePhase Phase>
|
||||
template<Position::GamePhase Ph>
|
||||
inline Value Position::pst(Color c, PieceType pt, Square s) const {
|
||||
return (Phase == MidGame ? MgPieceSquareTable[piece_of_color_and_type(c, pt)][s]
|
||||
: EgPieceSquareTable[piece_of_color_and_type(c, pt)][s]);
|
||||
return (Ph == MidGame ? MgPieceSquareTable[piece_of_color_and_type(c, pt)][s]
|
||||
: EgPieceSquareTable[piece_of_color_and_type(c, pt)][s]);
|
||||
}
|
||||
|
||||
inline Value Position::mg_pst_delta(Move m) const {
|
||||
return MgPieceSquareTable[piece_on(move_from(m))][move_to(m)]
|
||||
-MgPieceSquareTable[piece_on(move_from(m))][move_from(m)];
|
||||
template<Position::GamePhase Ph>
|
||||
inline Value Position::pst_delta(Piece piece, Square from, Square to) const {
|
||||
return (Ph == MidGame ? MgPieceSquareTable[piece][to] - MgPieceSquareTable[piece][from]
|
||||
: EgPieceSquareTable[piece][to] - EgPieceSquareTable[piece][from]);
|
||||
}
|
||||
|
||||
inline Value Position::mg_value() const {
|
||||
@@ -654,7 +649,7 @@ inline Value Position::eg_value() const {
|
||||
}
|
||||
|
||||
inline Value Position::non_pawn_material(Color c) const {
|
||||
return npMaterial[c];
|
||||
return st->npMaterial[c];
|
||||
}
|
||||
|
||||
inline Phase Position::game_phase() const {
|
||||
@@ -722,10 +717,7 @@ inline bool Position::move_is_capture(Move m) const {
|
||||
|
||||
// Move must not be MOVE_NONE !
|
||||
|
||||
return ( !square_is_empty(move_to(m))
|
||||
&& (color_of_piece_on(move_to(m)) != color_of_piece_on(move_from(m)))
|
||||
)
|
||||
|| move_is_ep(m);
|
||||
return (!square_is_empty(move_to(m)) && !move_is_castle(m)) || move_is_ep(m);
|
||||
}
|
||||
|
||||
#endif // !defined(POSITION_H_INCLUDED)
|
||||
|
||||
204
src/psqtab.h
204
src/psqtab.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
|
||||
////
|
||||
//// Variables
|
||||
//// Constants modified by Joona Kiiski
|
||||
////
|
||||
|
||||
static const Value MP = PawnValueMidgame;
|
||||
@@ -41,70 +41,70 @@ static const Value MQ = QueenValueMidgame;
|
||||
static const int MgPST[][64] = {
|
||||
{ },
|
||||
{// Pawn
|
||||
// A B C D E F G H
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
MP-38, MP-12, MP- 0, MP+12, MP+12, MP- 0, MP-12, MP-38,
|
||||
MP-38, MP-12, MP+ 6, MP+38, MP+38, MP+ 6, MP-12, MP-38,
|
||||
MP-38, MP-12, MP+16, MP+64, MP+64, MP+16, MP-12, MP-38,
|
||||
MP-38, MP-12, MP+16, MP+38, MP+38, MP+16, MP-12, MP-38,
|
||||
MP-38, MP-12, MP+ 6, MP+12, MP+12, MP+ 6, MP-12, MP-38,
|
||||
MP-38, MP-12, MP- 0, MP+12, MP+12, MP- 0, MP-12, MP-38,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
// A B C D E F G H
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
MP-28, MP-6, MP+ 4, MP+14, MP+14, MP+ 4, MP-6, MP-28,
|
||||
MP-28, MP-6, MP+ 9, MP+36, MP+36, MP+ 9, MP-6, MP-28,
|
||||
MP-28, MP-6, MP+17, MP+58, MP+58, MP+17, MP-6, MP-28,
|
||||
MP-28, MP-6, MP+17, MP+36, MP+36, MP+17, MP-6, MP-28,
|
||||
MP-28, MP-6, MP+ 9, MP+14, MP+14, MP+ 9, MP-6, MP-28,
|
||||
MP-28, MP-6, MP+ 4, MP+14, MP+14, MP+ 4, MP-6, MP-28,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
},
|
||||
{// Knight
|
||||
// A B C D E F G H
|
||||
MK-128, MK-102, MK-76, MK-64, MK-64, MK-76, MK-102, MK-128,
|
||||
MK- 89, MK- 64, MK-38, MK-25, MK-25, MK-38, MK- 64, MK- 89,
|
||||
MK- 51, MK- 25, MK- 0, MK+12, MK+12, MK- 0, MK- 25, MK- 51,
|
||||
MK- 25, MK- 0, MK+25, MK+38, MK+38, MK+25, MK- 0, MK- 25,
|
||||
MK- 12, MK+ 12, MK+38, MK+51, MK+51, MK+38, MK+ 12, MK- 12,
|
||||
MK- 12, MK+ 12, MK+38, MK+51, MK+51, MK+38, MK+ 12, MK- 12,
|
||||
MK- 51, MK- 25, MK- 0, MK+12, MK+12, MK- 0, MK- 25, MK- 51,
|
||||
MK-182, MK- 64, MK-38, MK-25, MK-25, MK-38, MK- 64, MK-182
|
||||
MK-135, MK-107, MK-80, MK-67, MK-67, MK-80, MK-107, MK-135,
|
||||
MK- 93, MK- 67, MK-39, MK-25, MK-25, MK-39, MK- 67, MK- 93,
|
||||
MK- 53, MK- 25, MK+ 1, MK+13, MK+13, MK+ 1, MK- 25, MK- 53,
|
||||
MK- 25, MK+ 1, MK+27, MK+41, MK+41, MK+27, MK+ 1, MK- 25,
|
||||
MK- 11, MK+ 13, MK+41, MK+55, MK+55, MK+41, MK+ 13, MK- 11,
|
||||
MK- 11, MK+ 13, MK+41, MK+55, MK+55, MK+41, MK+ 13, MK- 11,
|
||||
MK- 53, MK- 25, MK+ 1, MK+13, MK+13, MK+ 1, MK- 25, MK- 53,
|
||||
MK-193, MK- 67, MK-39, MK-25, MK-25, MK-39, MK- 67, MK-193
|
||||
},
|
||||
{// Bishop
|
||||
// A B C D E F G H
|
||||
MB-46, MB-46, MB-40, MB-35, MB-35, MB-40, MB-46, MB-46,
|
||||
MB-20, MB- 0, MB- 5, MB- 0, MB- 0, MB- 5, MB- 0, MB-20,
|
||||
MB-15, MB- 5, MB+10, MB+ 5, MB+ 5, MB+10, MB- 5, MB-15,
|
||||
MB-10, MB- 0, MB+ 5, MB+20, MB+20, MB+ 5, MB- 0, MB-10,
|
||||
MB-10, MB- 0, MB+ 5, MB+20, MB+20, MB+ 5, MB- 0, MB-10,
|
||||
MB-15, MB- 5, MB+10, MB+ 5, MB+ 5, MB+10, MB- 5, MB-15,
|
||||
MB-20, MB- 0, MB- 5, MB- 0, MB- 0, MB- 5, MB- 0, MB-20,
|
||||
MB-20, MB-20, MB-15, MB-10, MB-10, MB-15, MB-20, MB-20
|
||||
MB-40, MB-40, MB-35, MB-30, MB-30, MB-35, MB-40, MB-40,
|
||||
MB-17, MB+ 0, MB- 4, MB+ 0, MB+ 0, MB- 4, MB+ 0, MB-17,
|
||||
MB-13, MB- 4, MB+ 8, MB+ 4, MB+ 4, MB+ 8, MB- 4, MB-13,
|
||||
MB- 8, MB+ 0, MB+ 4, MB+17, MB+17, MB+ 4, MB+ 0, MB- 8,
|
||||
MB- 8, MB+ 0, MB+ 4, MB+17, MB+17, MB+ 4, MB+ 0, MB- 8,
|
||||
MB-13, MB- 4, MB+ 8, MB+ 4, MB+ 4, MB+ 8, MB- 4, MB-13,
|
||||
MB-17, MB+ 0, MB- 4, MB+ 0, MB+ 0, MB- 4, MB+ 0, MB-17,
|
||||
MB-17, MB-17, MB-13, MB- 8, MB- 8, MB-13, MB-17, MB-17
|
||||
},
|
||||
{// Rook
|
||||
// A B C D E F G H
|
||||
MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
|
||||
MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
|
||||
MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
|
||||
MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
|
||||
MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
|
||||
MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
|
||||
MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
|
||||
MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18
|
||||
// A B C D E F G H
|
||||
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
|
||||
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
|
||||
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
|
||||
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
|
||||
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
|
||||
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
|
||||
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
|
||||
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12
|
||||
},
|
||||
{// Queen
|
||||
//A B C D E F G H
|
||||
MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
|
||||
MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
|
||||
MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
|
||||
MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
|
||||
MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
|
||||
MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
|
||||
MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
|
||||
MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ
|
||||
// A B C D E F G H
|
||||
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
|
||||
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
|
||||
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
|
||||
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
|
||||
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
|
||||
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
|
||||
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
|
||||
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8
|
||||
},
|
||||
{// King
|
||||
//A B C D E F G H
|
||||
302, 328, 276, 225, 225, 276, 328, 302,
|
||||
276, 302, 251, 200, 200, 251, 302, 276,
|
||||
225, 251, 200, 149, 149, 200, 251, 225,
|
||||
200, 225, 175, 124, 124, 175, 225, 200,
|
||||
175, 200, 149, 98, 98, 149, 200, 175,
|
||||
149, 175, 124, 72, 72, 124, 175, 149,
|
||||
124, 149, 98, 47, 47, 98, 149, 124,
|
||||
98, 124, 72, 21, 21, 72, 124, 98
|
||||
287, 311, 262, 214, 214, 262, 311, 287,
|
||||
262, 287, 238, 190, 190, 238, 287, 262,
|
||||
214, 238, 190, 142, 142, 190, 238, 214,
|
||||
190, 214, 167, 119, 119, 167, 214, 190,
|
||||
167, 190, 142, 94, 94, 142, 190, 167,
|
||||
142, 167, 119, 69, 69, 119, 167, 142,
|
||||
119, 142, 94, 46, 46, 94, 142, 119,
|
||||
94, 119, 69, 21, 21, 69, 119, 94
|
||||
}
|
||||
};
|
||||
|
||||
@@ -117,70 +117,70 @@ static const Value EQ = QueenValueEndgame;
|
||||
static const int EgPST[][64] = {
|
||||
{ },
|
||||
{// Pawn
|
||||
//A B C D E F G H
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
EP, EP, EP, EP, EP, EP, EP, EP,
|
||||
EP, EP, EP, EP, EP, EP, EP, EP,
|
||||
EP, EP, EP, EP, EP, EP, EP, EP,
|
||||
EP, EP, EP, EP, EP, EP, EP, EP,
|
||||
EP, EP, EP, EP, EP, EP, EP, EP,
|
||||
EP, EP, EP, EP, EP, EP, EP, EP,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
// A B C D E F G H
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8,
|
||||
EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8,
|
||||
EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8,
|
||||
EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8,
|
||||
EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8,
|
||||
EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
},
|
||||
{// Knight
|
||||
// A B C D E F G H
|
||||
EK-102, EK-76, EK-51, EK-38, EK-38, EK-51, EK-76, EK-102,
|
||||
EK- 76, EK-51, EK-25, EK-12, EK-12, EK-25, EK-51, EK-76,
|
||||
EK- 51, EK-25, EK- 0, EK+12, EK+12, EK- 0, EK-25, EK-51,
|
||||
EK- 38, EK-12, EK+12, EK+25, EK+25, EK+12, EK-12, EK-38,
|
||||
EK- 38, EK-12, EK+12, EK+25, EK+25, EK+12, EK-12, EK-38,
|
||||
EK- 51, EK-25, EK- 0, EK+12, EK+12, EK- 0, EK-25, EK-51,
|
||||
EK- 76, EK-51, EK-25, EK-12, EK-12, EK-25, EK-51, EK-76,
|
||||
EK-102, EK-76, EK-51, EK-38, EK-38, EK-51, EK-76, EK-102
|
||||
EK-104, EK-79, EK-55, EK-42, EK-42, EK-55, EK-79, EK-104,
|
||||
EK- 79, EK-55, EK-30, EK-17, EK-17, EK-30, EK-55, EK- 79,
|
||||
EK- 55, EK-30, EK- 6, EK+ 5, EK+ 5, EK- 6, EK-30, EK- 55,
|
||||
EK- 42, EK-17, EK+ 5, EK+18, EK+18, EK+ 5, EK-17, EK- 42,
|
||||
EK- 42, EK-17, EK+ 5, EK+18, EK+18, EK+ 5, EK-17, EK- 42,
|
||||
EK- 55, EK-30, EK- 6, EK+ 5, EK+ 5, EK- 6, EK-30, EK- 55,
|
||||
EK- 79, EK-55, EK-30, EK-17, EK-17, EK-30, EK-55, EK- 79,
|
||||
EK-104, EK-79, EK-55, EK-42, EK-42, EK-55, EK-79, EK-104
|
||||
},
|
||||
{// Bishop
|
||||
// A B C D E F G H
|
||||
EB-46, EB-30, EB-23, EB-15, EB-15, EB-23, EB-30, EB-46,
|
||||
EB-30, EB-15, EB- 7, EB- 0, EB- 0, EB- 7, EB-15, EB-30,
|
||||
EB-23, EB- 7, EB- 0, EB+ 7, EB+ 7, EB- 0, EB- 7, EB-23,
|
||||
EB-15, EB- 0, EB+ 7, EB+15, EB+15, EB+ 7, EB- 0, EB-15,
|
||||
EB-15, EB- 0, EB+ 7, EB+15, EB+15, EB+ 7, EB- 0, EB-15,
|
||||
EB-23, EB- 7, EB- 0, EB+ 7, EB+ 7, EB- 0, EB- 7, EB-23,
|
||||
EB-30, EB-15, EB- 7, EB- 0, EB- 0, EB- 7, EB-15, EB-30,
|
||||
EB-46, EB-30, EB-23, EB-15, EB-15, EB-23, EB-30, EB-46
|
||||
EB-59, EB-42, EB-35, EB-26, EB-26, EB-35, EB-42, EB-59,
|
||||
EB-42, EB-26, EB-18, EB-11, EB-11, EB-18, EB-26, EB-42,
|
||||
EB-35, EB-18, EB-11, EB- 4, EB- 4, EB-11, EB-18, EB-35,
|
||||
EB-26, EB-11, EB- 4, EB+ 4, EB+ 4, EB- 4, EB-11, EB-26,
|
||||
EB-26, EB-11, EB- 4, EB+ 4, EB+ 4, EB- 4, EB-11, EB-26,
|
||||
EB-35, EB-18, EB-11, EB- 4, EB- 4, EB-11, EB-18, EB-35,
|
||||
EB-42, EB-26, EB-18, EB-11, EB-11, EB-18, EB-26, EB-42,
|
||||
EB-59, EB-42, EB-35, EB-26, EB-26, EB-35, EB-42, EB-59
|
||||
},
|
||||
{// Rook
|
||||
// A B C D E F G H
|
||||
ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3,
|
||||
ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3,
|
||||
ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3,
|
||||
ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3,
|
||||
ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3,
|
||||
ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3,
|
||||
ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3,
|
||||
ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3
|
||||
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
|
||||
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
|
||||
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
|
||||
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
|
||||
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
|
||||
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
|
||||
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
|
||||
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3
|
||||
},
|
||||
{// Queen
|
||||
// A B C D E F G H
|
||||
EQ-61, EQ-40, EQ-30, EQ-20, EQ-20, EQ-30, EQ-40, EQ-61,
|
||||
EQ-40, EQ-20, EQ-10, EQ- 0, EQ- 0, EQ-10, EQ-20, EQ-40,
|
||||
EQ-30, EQ-10, EQ- 0, EQ+10, EQ+10, EQ- 0, EQ-10, EQ-30,
|
||||
EQ-20, EQ- 0, EQ+10, EQ+20, EQ+20, EQ+10, EQ- 0, EQ-20,
|
||||
EQ-20, EQ- 0, EQ+10, EQ+20, EQ+20, EQ+10, EQ- 0, EQ-20,
|
||||
EQ-30, EQ-10, EQ- 0, EQ+10, EQ+10, EQ- 0, EQ-10, EQ-30,
|
||||
EQ-40, EQ-20, EQ-10, EQ- 0, EQ- 0, EQ-10, EQ-20, EQ-40,
|
||||
EQ-61, EQ-40, EQ-30, EQ-20, EQ-20, EQ-30, EQ-40, EQ-61
|
||||
EQ-80, EQ-54, EQ-42, EQ-30, EQ-30, EQ-42, EQ-54, EQ-80,
|
||||
EQ-54, EQ-30, EQ-18, EQ- 6, EQ- 6, EQ-18, EQ-30, EQ-54,
|
||||
EQ-42, EQ-18, EQ- 6, EQ+ 6, EQ+ 6, EQ- 6, EQ-18, EQ-42,
|
||||
EQ-30, EQ- 6, EQ+ 6, EQ+18, EQ+18, EQ+ 6, EQ- 6, EQ-30,
|
||||
EQ-30, EQ- 6, EQ+ 6, EQ+18, EQ+18, EQ+ 6, EQ- 6, EQ-30,
|
||||
EQ-42, EQ-18, EQ- 6, EQ+ 6, EQ+ 6, EQ- 6, EQ-18, EQ-42,
|
||||
EQ-54, EQ-30, EQ-18, EQ- 6, EQ- 6, EQ-18, EQ-30, EQ-54,
|
||||
EQ-80, EQ-54, EQ-42, EQ-30, EQ-30, EQ-42, EQ-54, EQ-80
|
||||
},
|
||||
{// King
|
||||
//A B C D E F G H
|
||||
16, 78, 108, 139, 139, 108, 78, 16,
|
||||
78, 139, 170, 200, 200, 170, 139, 78,
|
||||
108, 170, 200, 230, 230, 200, 170, 108,
|
||||
139, 200, 230, 261, 261, 230, 200, 139,
|
||||
139, 200, 230, 261, 261, 230, 200, 139,
|
||||
108, 170, 200, 230, 230, 200, 170, 108,
|
||||
78, 139, 170, 200, 200, 170, 139, 78,
|
||||
16, 78, 108, 139, 139, 108, 78, 16
|
||||
18, 77, 105, 135, 135, 105, 77, 18,
|
||||
77, 135, 165, 193, 193, 165, 135, 77,
|
||||
105, 165, 193, 222, 222, 193, 165, 105,
|
||||
135, 193, 222, 251, 251, 222, 193, 135,
|
||||
135, 193, 222, 251, 251, 222, 193, 135,
|
||||
105, 165, 193, 222, 222, 193, 165, 105,
|
||||
77, 135, 165, 193, 193, 165, 135, 77,
|
||||
18, 77, 105, 135, 135, 105, 77, 18
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
46
src/san.cpp
46
src/san.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -28,10 +28,11 @@
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "history.h"
|
||||
#include "movepick.h"
|
||||
#include "san.h"
|
||||
|
||||
extern SearchStack EmptySearchStack;
|
||||
using std::string;
|
||||
|
||||
////
|
||||
//// Local definitions
|
||||
@@ -39,8 +40,6 @@ extern SearchStack EmptySearchStack;
|
||||
|
||||
namespace {
|
||||
|
||||
/// Types
|
||||
|
||||
enum Ambiguity {
|
||||
AMBIGUITY_NONE,
|
||||
AMBIGUITY_FILE,
|
||||
@@ -48,12 +47,11 @@ namespace {
|
||||
AMBIGUITY_BOTH
|
||||
};
|
||||
|
||||
|
||||
/// Functions
|
||||
const History H; // used as dummy argument for MovePicker c'tor
|
||||
|
||||
Ambiguity move_ambiguity(const Position& pos, Move m);
|
||||
const std::string time_string(int milliseconds);
|
||||
const std::string score_string(Value v);
|
||||
const string time_string(int milliseconds);
|
||||
const string score_string(Value v);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +63,7 @@ namespace {
|
||||
/// that the move is a legal move from the position. The return value is
|
||||
/// a string containing the move in short algebraic notation.
|
||||
|
||||
const std::string move_to_san(const Position& pos, Move m) {
|
||||
const string move_to_san(const Position& pos, Move m) {
|
||||
|
||||
assert(pos.is_ok());
|
||||
assert(move_is_ok(m));
|
||||
@@ -77,7 +75,7 @@ const std::string move_to_san(const Position& pos, Move m) {
|
||||
to = move_to(m);
|
||||
pt = type_of_piece(pos.piece_on(move_from(m)));
|
||||
|
||||
std::string san = "";
|
||||
string san = "";
|
||||
|
||||
if (m == MOVE_NONE)
|
||||
return "(none)";
|
||||
@@ -115,10 +113,10 @@ const std::string move_to_san(const Position& pos, Move m) {
|
||||
san += "x";
|
||||
}
|
||||
san += square_to_string(move_to(m));
|
||||
if (move_promotion(m))
|
||||
if (move_is_promotion(m))
|
||||
{
|
||||
san += '=';
|
||||
san += piece_type_to_char(move_promotion(m), true);
|
||||
san += piece_type_to_char(move_promotion_piece(m), true);
|
||||
}
|
||||
}
|
||||
// Is the move check? We don't use pos.move_is_check(m) here, because
|
||||
@@ -139,11 +137,11 @@ const std::string move_to_san(const Position& pos, Move m) {
|
||||
/// the move is returned. On failure (i.e. if the string is unparsable, or
|
||||
/// if the move is illegal or ambiguous), MOVE_NONE is returned.
|
||||
|
||||
Move move_from_san(const Position& pos, const std::string& movestr) {
|
||||
Move move_from_san(const Position& pos, const string& movestr) {
|
||||
|
||||
assert(pos.is_ok());
|
||||
|
||||
MovePicker mp = MovePicker(pos, false, MOVE_NONE, EmptySearchStack, OnePly);
|
||||
MovePicker mp = MovePicker(pos, MOVE_NONE, OnePly, H);
|
||||
|
||||
// Castling moves
|
||||
if (movestr == "O-O-O" || movestr == "O-O-O+")
|
||||
@@ -167,7 +165,7 @@ Move move_from_san(const Position& pos, const std::string& movestr) {
|
||||
|
||||
// Normal moves. We use a simple FSM to parse the san string.
|
||||
enum { START, TO_FILE, TO_RANK, PROMOTION_OR_CHECK, PROMOTION, CHECK, END };
|
||||
static const std::string pieceLetters = "KQRBN";
|
||||
static const string pieceLetters = "KQRBN";
|
||||
PieceType pt = NO_PIECE_TYPE, promotion = NO_PIECE_TYPE;
|
||||
File fromFile = FILE_NONE, toFile = FILE_NONE;
|
||||
Rank fromRank = RANK_NONE, toRank = RANK_NONE;
|
||||
@@ -177,7 +175,7 @@ Move move_from_san(const Position& pos, const std::string& movestr) {
|
||||
for (size_t i = 0; i < movestr.length(); i++)
|
||||
{
|
||||
char type, c = movestr[i];
|
||||
if (pieceLetters.find(c) != std::string::npos)
|
||||
if (pieceLetters.find(c) != string::npos)
|
||||
type = 'P';
|
||||
else if (c >= 'a' && c <= 'h')
|
||||
type = 'F';
|
||||
@@ -275,7 +273,7 @@ Move move_from_san(const Position& pos, const std::string& movestr) {
|
||||
while ((m = mp.get_next_move()) != MOVE_NONE)
|
||||
if ( pos.type_of_piece_on(move_from(m)) == pt
|
||||
&& move_to(m) == to
|
||||
&& move_promotion(m) == promotion
|
||||
&& move_promotion_piece(m) == promotion
|
||||
&& (fromFile == FILE_NONE || fromFile == square_file(move_from(m)))
|
||||
&& (fromRank == RANK_NONE || fromRank == square_rank(move_from(m))))
|
||||
{
|
||||
@@ -293,11 +291,11 @@ Move move_from_san(const Position& pos, const std::string& movestr) {
|
||||
/// length of 80 characters. After a line break, 'startColumn' spaces are
|
||||
/// inserted at the beginning of the new line.
|
||||
|
||||
const std::string line_to_san(const Position& pos, Move line[], int startColumn, bool breakLines) {
|
||||
const string line_to_san(const Position& pos, Move line[], int startColumn, bool breakLines) {
|
||||
|
||||
StateInfo st;
|
||||
std::stringstream s;
|
||||
std::string moveStr;
|
||||
string moveStr;
|
||||
size_t length = 0;
|
||||
size_t maxLength = 80 - startColumn;
|
||||
Position p(pos);
|
||||
@@ -326,8 +324,8 @@ const std::string line_to_san(const Position& pos, Move line[], int startColumn,
|
||||
/// It is used to write search information to the log file (which is created
|
||||
/// when the UCI parameter "Use Search Log" is "true").
|
||||
|
||||
const std::string pretty_pv(const Position& pos, int time, int depth,
|
||||
uint64_t nodes, Value score, Move pv[]) {
|
||||
const string pretty_pv(const Position& pos, int time, int depth,
|
||||
uint64_t nodes, Value score, Move pv[]) {
|
||||
std::stringstream s;
|
||||
|
||||
// Depth
|
||||
@@ -367,7 +365,7 @@ namespace {
|
||||
if (type_of_piece(pc) == KING)
|
||||
return AMBIGUITY_NONE;
|
||||
|
||||
MovePicker mp = MovePicker(pos, false, MOVE_NONE, EmptySearchStack, OnePly);
|
||||
MovePicker mp = MovePicker(pos, MOVE_NONE, OnePly, H);
|
||||
Move mv, moveList[8];
|
||||
|
||||
int n = 0;
|
||||
@@ -397,7 +395,7 @@ namespace {
|
||||
}
|
||||
|
||||
|
||||
const std::string time_string(int milliseconds) {
|
||||
const string time_string(int milliseconds) {
|
||||
|
||||
std::stringstream s;
|
||||
s << std::setfill('0');
|
||||
@@ -414,7 +412,7 @@ namespace {
|
||||
}
|
||||
|
||||
|
||||
const std::string score_string(Value v) {
|
||||
const string score_string(Value v) {
|
||||
|
||||
std::stringstream s;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
562
src/search.cpp
562
src/search.cpp
File diff suppressed because it is too large
Load Diff
24
src/search.h
24
src/search.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
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,12 +26,7 @@
|
||||
////
|
||||
|
||||
#include "depth.h"
|
||||
#include "history.h"
|
||||
#include "lock.h"
|
||||
#include "movegen.h"
|
||||
#include "position.h"
|
||||
#include "tt.h"
|
||||
#include "value.h"
|
||||
#include "move.h"
|
||||
|
||||
|
||||
////
|
||||
@@ -65,26 +60,13 @@ struct SearchStack {
|
||||
};
|
||||
|
||||
|
||||
////
|
||||
//// Global variables
|
||||
////
|
||||
|
||||
extern SearchStack EmptySearchStack;
|
||||
extern TranspositionTable TT;
|
||||
extern int ActiveThreads;
|
||||
extern Lock SMPLock;
|
||||
|
||||
// Perhaps better to make H local, and pass as parameter to MovePicker?
|
||||
extern History H;
|
||||
|
||||
|
||||
////
|
||||
//// Prototypes
|
||||
////
|
||||
|
||||
extern void init_threads();
|
||||
extern void stop_threads();
|
||||
extern void think(const Position &pos, bool infinite, bool ponder, int side_to_move,
|
||||
extern bool think(const Position &pos, bool infinite, bool ponder, int side_to_move,
|
||||
int time[], int increment[], int movesToGo, int maxDepth,
|
||||
int maxNodes, int maxTime, Move searchMoves[]);
|
||||
extern int64_t nodes_searched();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -66,13 +66,14 @@ struct Thread {
|
||||
SplitPoint *splitPoint;
|
||||
int activeSplitPoints;
|
||||
uint64_t nodes;
|
||||
uint64_t betaCutOffs[2];
|
||||
bool failHighPly1;
|
||||
volatile bool stop;
|
||||
volatile bool running;
|
||||
volatile bool idle;
|
||||
volatile bool workIsWaiting;
|
||||
volatile bool printCurrentLine;
|
||||
unsigned char pad[64];
|
||||
unsigned char pad[64]; // set some distance among local data for each thread
|
||||
};
|
||||
|
||||
|
||||
|
||||
26
src/tt.cpp
26
src/tt.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -69,7 +69,7 @@ void TranspositionTable::set_size(unsigned mbSize) {
|
||||
{
|
||||
std::cerr << "Failed to allocate " << mbSize
|
||||
<< " MB for transposition table." << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
Application::exit_with_failure();
|
||||
}
|
||||
clear();
|
||||
}
|
||||
@@ -97,14 +97,14 @@ void TranspositionTable::clear() {
|
||||
/// is bigger than the depth of t2. A TTEntry of type VALUE_TYPE_EVAL
|
||||
/// never replaces another entry for the same position.
|
||||
|
||||
void TranspositionTable::store(const Position& p, Value v, ValueType t, Depth d, Move m) {
|
||||
void TranspositionTable::store(const Key posKey, Value v, ValueType t, Depth d, Move m) {
|
||||
|
||||
TTEntry *tte, *replace;
|
||||
|
||||
tte = replace = first_entry(p);
|
||||
tte = replace = first_entry(posKey);
|
||||
for (int i = 0; i < 4; i++, tte++)
|
||||
{
|
||||
if (!tte->key() || tte->key() == p.get_key()) // empty or overwrite old
|
||||
if (!tte->key() || tte->key() == posKey) // empty or overwrite old
|
||||
{
|
||||
// Do not overwrite when new type is VALUE_TYPE_EVAL
|
||||
if (tte->key() && t == VALUE_TYPE_EVAL)
|
||||
@@ -113,7 +113,7 @@ void TranspositionTable::store(const Position& p, Value v, ValueType t, Depth d,
|
||||
if (m == MOVE_NONE)
|
||||
m = tte->move();
|
||||
|
||||
*tte = TTEntry(p.get_key(), v, t, d, m, generation);
|
||||
*tte = TTEntry(posKey, v, t, d, m, generation);
|
||||
return;
|
||||
}
|
||||
else if (i == 0) // replace would be a no-op in this common case
|
||||
@@ -126,7 +126,7 @@ void TranspositionTable::store(const Position& p, Value v, ValueType t, Depth d,
|
||||
if (c1 + c2 + c3 > 0)
|
||||
replace = tte;
|
||||
}
|
||||
*replace = TTEntry(p.get_key(), v, t, d, m, generation);
|
||||
*replace = TTEntry(posKey, v, t, d, m, generation);
|
||||
writes++;
|
||||
}
|
||||
|
||||
@@ -135,12 +135,12 @@ void TranspositionTable::store(const Position& p, Value v, ValueType t, Depth d,
|
||||
/// transposition table. Returns a pointer to the TTEntry or NULL
|
||||
/// if position is not found.
|
||||
|
||||
TTEntry* TranspositionTable::retrieve(const Position& pos) const {
|
||||
TTEntry* TranspositionTable::retrieve(const Key posKey) const {
|
||||
|
||||
TTEntry *tte = first_entry(pos);
|
||||
TTEntry *tte = first_entry(posKey);
|
||||
|
||||
for (int i = 0; i < 4; i++, tte++)
|
||||
if (tte->key() == pos.get_key())
|
||||
if (tte->key() == posKey)
|
||||
return tte;
|
||||
|
||||
return NULL;
|
||||
@@ -150,9 +150,9 @@ TTEntry* TranspositionTable::retrieve(const Position& pos) const {
|
||||
/// TranspositionTable::first_entry returns a pointer to the first
|
||||
/// entry of a cluster given a position.
|
||||
|
||||
inline TTEntry* TranspositionTable::first_entry(const Position& pos) const {
|
||||
inline TTEntry* TranspositionTable::first_entry(const Key posKey) const {
|
||||
|
||||
return entries + (int(pos.get_key() & (size - 1)) << 2);
|
||||
return entries + (int(posKey & (size - 1)) << 2);
|
||||
}
|
||||
|
||||
/// TranspositionTable::new_search() is called at the beginning of every new
|
||||
@@ -179,7 +179,7 @@ void TranspositionTable::insert_pv(const Position& pos, Move pv[]) {
|
||||
|
||||
for (int i = 0; pv[i] != MOVE_NONE; i++)
|
||||
{
|
||||
store(p, VALUE_NONE, VALUE_TYPE_NONE, Depth(-127*OnePly), pv[i]);
|
||||
store(p.get_key(), VALUE_NONE, VALUE_TYPE_NONE, Depth(-127*OnePly), pv[i]);
|
||||
p.do_move(pv[i], st);
|
||||
}
|
||||
}
|
||||
|
||||
16
src/tt.h
16
src/tt.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
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,16 +83,22 @@ public:
|
||||
~TranspositionTable();
|
||||
void set_size(unsigned mbSize);
|
||||
void clear();
|
||||
void store(const Position& pos, Value v, ValueType type, Depth d, Move m);
|
||||
TTEntry* retrieve(const Position& pos) const;
|
||||
void store(const Key posKey, Value v, ValueType type, Depth d, Move m);
|
||||
TTEntry* retrieve(const Key posKey) const;
|
||||
void new_search();
|
||||
void insert_pv(const Position& pos, Move pv[]);
|
||||
int full() const;
|
||||
|
||||
private:
|
||||
inline TTEntry* first_entry(const Position& pos) const;
|
||||
inline TTEntry* first_entry(const Key posKey) const;
|
||||
|
||||
unsigned size, writes;
|
||||
// Be sure 'writes' is at least one cacheline away
|
||||
// from read only variables.
|
||||
unsigned char pad_before[64 - sizeof(unsigned)];
|
||||
unsigned writes; // heavy SMP read/write access here
|
||||
unsigned char pad_after[64];
|
||||
|
||||
unsigned size;
|
||||
TTEntry* entries;
|
||||
uint8_t generation;
|
||||
};
|
||||
|
||||
26
src/types.h
26
src/types.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -41,7 +41,29 @@ typedef __int64 int64_t;
|
||||
|
||||
#endif // !defined(_MSC_VER)
|
||||
|
||||
// Hash keys:
|
||||
// Hash keys
|
||||
typedef uint64_t Key;
|
||||
|
||||
// Bitboard type
|
||||
typedef uint64_t Bitboard;
|
||||
|
||||
|
||||
////
|
||||
//// Compiler specific defines
|
||||
////
|
||||
|
||||
// Quiet a warning on Intel compiler
|
||||
#if !defined(__SIZEOF_INT__ )
|
||||
#define __SIZEOF_INT__ 0
|
||||
#endif
|
||||
|
||||
// Check for 64 bits for different compilers: Intel, MSVC and gcc
|
||||
#if defined(__x86_64) || defined(_M_X64) || defined(_WIN64) || (__SIZEOF_INT__ > 4)
|
||||
#define IS_64BIT
|
||||
#endif
|
||||
|
||||
#if defined(IS_64BIT) && !defined(_WIN64) && (defined(__GNUC__) || defined(__INTEL_COMPILER))
|
||||
#define USE_BSFQ
|
||||
#endif
|
||||
|
||||
#endif // !defined(TYPES_H_INCLUDED)
|
||||
|
||||
159
src/uci.cpp
159
src/uci.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "uci.h"
|
||||
#include "ucioption.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
////
|
||||
//// Local definitions:
|
||||
@@ -45,22 +46,21 @@
|
||||
|
||||
namespace {
|
||||
|
||||
// UCIInputParser is a class for parsing UCI input. The class
|
||||
// UCIInputParser is a class for parsing UCI input. The class
|
||||
// is actually a string stream built on a given input string.
|
||||
|
||||
typedef std::istringstream UCIInputParser;
|
||||
typedef istringstream UCIInputParser;
|
||||
|
||||
// The root position. This is set up when the user (or in practice, the GUI)
|
||||
// sends the "position" UCI command. The root position is sent to the think()
|
||||
// The root position. This is set up when the user (or in practice, the GUI)
|
||||
// sends the "position" UCI command. The root position is sent to the think()
|
||||
// function when the program receives the "go" command.
|
||||
Position RootPosition;
|
||||
|
||||
// Local functions
|
||||
void get_command();
|
||||
void handle_command(const std::string &command);
|
||||
void set_option(UCIInputParser &uip);
|
||||
void set_position(UCIInputParser &uip);
|
||||
void go(UCIInputParser &uip);
|
||||
bool handle_command(const string& command);
|
||||
void set_option(UCIInputParser& uip);
|
||||
void set_position(UCIInputParser& uip);
|
||||
bool go(UCIInputParser& uip);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,17 +68,25 @@ namespace {
|
||||
//// Functions
|
||||
////
|
||||
|
||||
/// uci_main_loop() is the only global function in this file. It is
|
||||
/// uci_main_loop() is the only global function in this file. It is
|
||||
/// called immediately after the program has finished initializing.
|
||||
/// The program remains in this loop until it receives the "quit" UCI
|
||||
/// command.
|
||||
/// command. It waits for a command from the user, and passes this
|
||||
/// command to handle_command and also intercepts EOF from stdin,
|
||||
/// by translating EOF to the "quit" command. This ensures that Stockfish
|
||||
/// exits gracefully if the GUI dies unexpectedly.
|
||||
|
||||
void uci_main_loop() {
|
||||
|
||||
RootPosition.from_fen(StartPosition);
|
||||
string command;
|
||||
|
||||
while (1)
|
||||
get_command();
|
||||
do {
|
||||
// Wait for a command from stdin
|
||||
if (!getline(cin, command))
|
||||
command = "quit";
|
||||
|
||||
} while (handle_command(command));
|
||||
}
|
||||
|
||||
|
||||
@@ -88,64 +96,43 @@ void uci_main_loop() {
|
||||
|
||||
namespace {
|
||||
|
||||
// get_command() waits for a command from the user, and passes
|
||||
// this command to handle_command. get_command also intercepts
|
||||
// EOF from stdin, by translating EOF to the "quit" command. This
|
||||
// ensures that Stockfish exits gracefully if the GUI dies
|
||||
// unexpectedly.
|
||||
|
||||
void get_command() {
|
||||
|
||||
std::string command;
|
||||
|
||||
if (!std::getline(std::cin, command))
|
||||
command = "quit";
|
||||
|
||||
handle_command(command);
|
||||
}
|
||||
|
||||
|
||||
// handle_command() takes a text string as input, uses a
|
||||
// UCIInputParser object to parse this text string as a UCI command,
|
||||
// and calls the appropriate functions. In addition to the UCI
|
||||
// and calls the appropriate functions. In addition to the UCI
|
||||
// commands, the function also supports a few debug commands.
|
||||
|
||||
void handle_command(const std::string &command) {
|
||||
bool handle_command(const string& command) {
|
||||
|
||||
UCIInputParser uip(command);
|
||||
std::string token;
|
||||
string token;
|
||||
|
||||
uip >> token; // operator >> skips any whitespace
|
||||
uip >> token; // operator>>() skips any whitespace
|
||||
|
||||
if (token == "quit")
|
||||
return false;
|
||||
|
||||
if (token == "go")
|
||||
return go(uip);
|
||||
|
||||
if (token == "uci")
|
||||
{
|
||||
OpeningBook.close();
|
||||
stop_threads();
|
||||
quit_eval();
|
||||
exit(0);
|
||||
}
|
||||
else if (token == "uci")
|
||||
{
|
||||
std::cout << "id name " << engine_name() << std::endl
|
||||
<< "id author Tord Romstad, Marco Costalba"
|
||||
<< std::endl;
|
||||
cout << "id name " << engine_name()
|
||||
<< "\nid author Tord Romstad, Marco Costalba, Joona Kiiski\n";
|
||||
print_uci_options();
|
||||
std::cout << "uciok" << std::endl;
|
||||
cout << "uciok" << endl;
|
||||
}
|
||||
else if (token == "ucinewgame")
|
||||
{
|
||||
TT.clear();
|
||||
push_button("Clear Hash");
|
||||
Position::init_piece_square_tables();
|
||||
RootPosition.from_fen(StartPosition);
|
||||
}
|
||||
else if (token == "isready")
|
||||
std::cout << "readyok" << std::endl;
|
||||
cout << "readyok" << endl;
|
||||
else if (token == "position")
|
||||
set_position(uip);
|
||||
else if (token == "setoption")
|
||||
set_option(uip);
|
||||
else if (token == "go")
|
||||
go(uip);
|
||||
|
||||
// The remaining commands are for debugging purposes only.
|
||||
// Perhaps they should be removed later in order to reduce the
|
||||
@@ -160,55 +147,49 @@ namespace {
|
||||
else if (token == "eval")
|
||||
{
|
||||
EvalInfo ei;
|
||||
std::cout << "Incremental mg: " << RootPosition.mg_value()
|
||||
<< std::endl;
|
||||
std::cout << "Incremental eg: " << RootPosition.eg_value()
|
||||
<< std::endl;
|
||||
std::cout << "Full eval: "
|
||||
<< evaluate(RootPosition, ei, 0)
|
||||
<< std::endl;
|
||||
cout << "Incremental mg: " << RootPosition.mg_value()
|
||||
<< "\nIncremental eg: " << RootPosition.eg_value()
|
||||
<< "\nFull eval: " << evaluate(RootPosition, ei, 0) << endl;
|
||||
}
|
||||
else if (token == "key")
|
||||
{
|
||||
std::cout << "key: " << std::hex << RootPosition.get_key()
|
||||
<< " material key: " << RootPosition.get_material_key()
|
||||
<< " pawn key: " << RootPosition.get_pawn_key()
|
||||
<< std::endl;
|
||||
}
|
||||
cout << "key: " << hex << RootPosition.get_key()
|
||||
<< "\nmaterial key: " << RootPosition.get_material_key()
|
||||
<< "\npawn key: " << RootPosition.get_pawn_key() << endl;
|
||||
else
|
||||
{
|
||||
std::cout << "Unknown command: " << command << std::endl;
|
||||
cout << "Unknown command: " << command << endl;
|
||||
while (!uip.eof())
|
||||
{
|
||||
uip >> token;
|
||||
std::cout << token << std::endl;
|
||||
cout << token << endl;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// set_position() is called when Stockfish receives the "position" UCI
|
||||
// command. The input parameter is a UCIInputParser. It is assumed
|
||||
// command. The input parameter is a UCIInputParser. It is assumed
|
||||
// that this parser has consumed the first token of the UCI command
|
||||
// ("position"), and is ready to read the second token ("startpos"
|
||||
// or "fen", if the input is well-formed).
|
||||
|
||||
void set_position(UCIInputParser &uip) {
|
||||
void set_position(UCIInputParser& uip) {
|
||||
|
||||
std::string token;
|
||||
string token;
|
||||
|
||||
uip >> token; // operator >> skips any whitespace
|
||||
uip >> token; // operator>>() skips any whitespace
|
||||
|
||||
if (token == "startpos")
|
||||
RootPosition.from_fen(StartPosition);
|
||||
else if (token == "fen")
|
||||
{
|
||||
std::string fen;
|
||||
string fen;
|
||||
while (token != "moves" && !uip.eof())
|
||||
{
|
||||
uip >> token;
|
||||
fen += token;
|
||||
fen += ' ';
|
||||
uip >> token;
|
||||
fen += token;
|
||||
fen += ' ';
|
||||
}
|
||||
RootPosition.from_fen(fen);
|
||||
}
|
||||
@@ -229,23 +210,23 @@ namespace {
|
||||
if (RootPosition.rule_50_counter() == 0)
|
||||
RootPosition.reset_game_ply();
|
||||
}
|
||||
// Our StateInfo st is about going out of scope,
|
||||
// so save its content before they disappear.
|
||||
RootPosition.setStartState(st);
|
||||
// Our StateInfo st is about going out of scope so copy
|
||||
// its content inside RootPosition before they disappear.
|
||||
RootPosition.saveState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// set_option() is called when Stockfish receives the "setoption" UCI
|
||||
// command. The input parameter is a UCIInputParser. It is assumed
|
||||
// command. The input parameter is a UCIInputParser. It is assumed
|
||||
// that this parser has consumed the first token of the UCI command
|
||||
// ("setoption"), and is ready to read the second token ("name", if
|
||||
// the input is well-formed).
|
||||
|
||||
void set_option(UCIInputParser &uip) {
|
||||
void set_option(UCIInputParser& uip) {
|
||||
|
||||
std::string token, name;
|
||||
string token, name;
|
||||
|
||||
uip >> token;
|
||||
if (token == "name")
|
||||
@@ -261,7 +242,7 @@ namespace {
|
||||
}
|
||||
if (token == "value")
|
||||
{
|
||||
std::getline(uip, token); // reads until end of line
|
||||
getline(uip, token); // reads until end of line
|
||||
set_option_value(name, token);
|
||||
} else
|
||||
push_button(name);
|
||||
@@ -269,17 +250,18 @@ namespace {
|
||||
}
|
||||
|
||||
|
||||
// go() is called when Stockfish receives the "go" UCI command. The
|
||||
// input parameter is a UCIInputParser. It is assumed that this
|
||||
// go() is called when Stockfish receives the "go" UCI command. The
|
||||
// input parameter is a UCIInputParser. It is assumed that this
|
||||
// parser has consumed the first token of the UCI command ("go"),
|
||||
// and is ready to read the second token. The function sets the
|
||||
// and is ready to read the second token. The function sets the
|
||||
// thinking time and other parameters from the input string, and
|
||||
// calls think() (defined in search.cpp) with the appropriate
|
||||
// parameters.
|
||||
// parameters. Returns false if a quit command is received while
|
||||
// thinking, returns true otherwise.
|
||||
|
||||
void go(UCIInputParser &uip) {
|
||||
bool go(UCIInputParser& uip) {
|
||||
|
||||
std::string token;
|
||||
string token;
|
||||
|
||||
int time[2] = {0, 0}, inc[2] = {0, 0};
|
||||
int movesToGo = 0, depth = 0, nodes = 0, moveTime = 0;
|
||||
@@ -329,7 +311,8 @@ namespace {
|
||||
|
||||
assert(RootPosition.is_ok());
|
||||
|
||||
think(RootPosition, infinite, ponder, RootPosition.side_to_move(), time,
|
||||
inc, movesToGo, depth, nodes, moveTime, searchMoves);
|
||||
return think(RootPosition, infinite, ponder, RootPosition.side_to_move(),
|
||||
time, inc, movesToGo, depth, nodes, moveTime, searchMoves);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -33,13 +33,7 @@
|
||||
#include "thread.h"
|
||||
#include "ucioption.h"
|
||||
|
||||
|
||||
////
|
||||
//// Variables
|
||||
////
|
||||
|
||||
bool Chess960;
|
||||
|
||||
using std::string;
|
||||
|
||||
////
|
||||
//// Local definitions
|
||||
@@ -53,11 +47,11 @@ namespace {
|
||||
|
||||
enum OptionType { SPIN, COMBO, CHECK, STRING, BUTTON };
|
||||
|
||||
typedef std::vector<std::string> ComboValues;
|
||||
typedef std::vector<string> ComboValues;
|
||||
|
||||
struct Option {
|
||||
|
||||
std::string name, defaultValue, currentValue;
|
||||
string name, defaultValue, currentValue;
|
||||
OptionType type;
|
||||
size_t idx;
|
||||
int minValue, maxValue;
|
||||
@@ -71,7 +65,7 @@ namespace {
|
||||
bool operator<(const Option& o) const { return this->idx < o.idx; }
|
||||
};
|
||||
|
||||
typedef std::map<std::string, Option> Options;
|
||||
typedef std::map<string, Option> Options;
|
||||
|
||||
///
|
||||
/// Constants
|
||||
@@ -125,8 +119,6 @@ namespace {
|
||||
o["Full Depth Moves (PV nodes)"] = Option(14, 1, 100);
|
||||
o["Full Depth Moves (non-PV nodes)"] = Option(3, 1, 100);
|
||||
o["Threat Depth"] = Option(5, 0, 100);
|
||||
o["Futility Pruning (Main Search)"] = Option(true);
|
||||
o["Futility Pruning (Quiescence Search)"] = Option(true);
|
||||
o["LSN filtering"] = Option(false);
|
||||
o["LSN Time Margin (sec)"] = Option(4, 1, 10);
|
||||
o["LSN Value Margin"] = Option(200, 100, 600);
|
||||
@@ -155,7 +147,7 @@ namespace {
|
||||
|
||||
// stringify converts a value of type T to a std::string
|
||||
template<typename T>
|
||||
std::string stringify(const T& v) {
|
||||
string stringify(const T& v) {
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << v;
|
||||
@@ -168,7 +160,7 @@ namespace {
|
||||
// type changes a template seems a proper solution.
|
||||
|
||||
template<typename T>
|
||||
T get_option_value(const std::string& optionName) {
|
||||
T get_option_value(const string& optionName) {
|
||||
|
||||
T ret = T();
|
||||
if (options.find(optionName) == options.end())
|
||||
@@ -245,9 +237,7 @@ void print_uci_options() {
|
||||
std::cout << " default " << it->defaultValue;
|
||||
|
||||
if (it->type == SPIN)
|
||||
std::cout << " min " << it->minValue
|
||||
<< " max " << it->maxValue;
|
||||
|
||||
std::cout << " min " << it->minValue << " max " << it->maxValue;
|
||||
else if (it->type == COMBO)
|
||||
for (ComboValues::const_iterator itc = it->comboValues.begin();
|
||||
itc != it->comboValues.end(); ++itc)
|
||||
@@ -260,7 +250,7 @@ void print_uci_options() {
|
||||
/// get_option_value_bool() returns the current value of a UCI parameter of
|
||||
/// type "check".
|
||||
|
||||
bool get_option_value_bool(const std::string& optionName) {
|
||||
bool get_option_value_bool(const string& optionName) {
|
||||
|
||||
return get_option_value<bool>(optionName);
|
||||
}
|
||||
@@ -271,7 +261,7 @@ bool get_option_value_bool(const std::string& optionName) {
|
||||
/// it could also be used with a "combo" parameter, where all the available
|
||||
/// values are integers.
|
||||
|
||||
int get_option_value_int(const std::string& optionName) {
|
||||
int get_option_value_int(const string& optionName) {
|
||||
|
||||
return get_option_value<int>(optionName);
|
||||
}
|
||||
@@ -280,9 +270,9 @@ int get_option_value_int(const std::string& optionName) {
|
||||
/// get_option_value_string() returns the current value of a UCI parameter as
|
||||
/// a string. It is used with parameters of type "combo" and "string".
|
||||
|
||||
const std::string get_option_value_string(const std::string& optionName) {
|
||||
string get_option_value_string(const string& optionName) {
|
||||
|
||||
return get_option_value<std::string>(optionName);
|
||||
return get_option_value<string>(optionName);
|
||||
}
|
||||
|
||||
|
||||
@@ -290,28 +280,27 @@ const std::string get_option_value_string(const std::string& optionName) {
|
||||
/// the function does not check that the new value is legal for the given
|
||||
/// parameter: This is assumed to be the responsibility of the GUI.
|
||||
|
||||
void set_option_value(const std::string& optionName,
|
||||
const std::string& newValue) {
|
||||
void set_option_value(const string& name, const string& value) {
|
||||
|
||||
// UCI protocol uses "true" and "false" instead of "1" and "0", so convert
|
||||
// newValue according to standard C++ convention before to store it.
|
||||
std::string v(newValue);
|
||||
// value according to standard C++ convention before to store it.
|
||||
string v(value);
|
||||
if (v == "true")
|
||||
v = "1";
|
||||
else if (v == "false")
|
||||
v = "0";
|
||||
|
||||
if (options.find(optionName) != options.end())
|
||||
options[optionName].currentValue = v;
|
||||
if (options.find(name) != options.end())
|
||||
options[name].currentValue = v;
|
||||
else
|
||||
std::cout << "No such option: " << optionName << std::endl;
|
||||
std::cout << "No such option: " << name << std::endl;
|
||||
}
|
||||
|
||||
|
||||
/// push_button() is used to tell the engine that a UCI parameter of type
|
||||
/// "button" has been selected:
|
||||
|
||||
void push_button(const std::string& buttonName) {
|
||||
void push_button(const string& buttonName) {
|
||||
|
||||
set_option_value(buttonName, "true");
|
||||
}
|
||||
@@ -321,7 +310,7 @@ void push_button(const std::string& buttonName) {
|
||||
/// been selected since the last time the function was called, in this case
|
||||
/// it also resets the button.
|
||||
|
||||
bool button_was_pressed(const std::string& buttonName) {
|
||||
bool button_was_pressed(const string& buttonName) {
|
||||
|
||||
if (!get_option_value<bool>(buttonName))
|
||||
return false;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -27,27 +27,18 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
////
|
||||
//// Variables
|
||||
////
|
||||
|
||||
extern bool Chess960;
|
||||
|
||||
|
||||
////
|
||||
//// Prototypes
|
||||
////
|
||||
|
||||
extern void init_uci_options();
|
||||
extern void print_uci_options();
|
||||
extern bool get_option_value_bool(const std::string &optionName);
|
||||
extern int get_option_value_int(const std::string &optionName);
|
||||
extern const std::string get_option_value_string(const std::string &optionName);
|
||||
extern bool button_was_pressed(const std::string &buttonName);
|
||||
extern void set_option_value(const std::string &optionName,
|
||||
const std::string &newValue);
|
||||
extern void push_button(const std::string &buttonName);
|
||||
extern bool get_option_value_bool(const std::string& optionName);
|
||||
extern int get_option_value_int(const std::string& optionName);
|
||||
extern std::string get_option_value_string(const std::string& optionName);
|
||||
extern bool button_was_pressed(const std::string& buttonName);
|
||||
extern void set_option_value(const std::string& optionName,const std::string& newValue);
|
||||
extern void push_button(const std::string& buttonName);
|
||||
|
||||
|
||||
#endif // !defined(UCIOPTION_H_INCLUDED)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
22
src/value.h
22
src/value.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
|
||||
Copyright (C) 2008 Marco Costalba
|
||||
Copyright (C) 2008-2009 Marco Costalba
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -62,16 +62,16 @@ enum Value {
|
||||
///
|
||||
/// Values modified by Joona Kiiski
|
||||
|
||||
const Value PawnValueMidgame = Value(0x0CC);
|
||||
const Value PawnValueEndgame = Value(0x101);
|
||||
const Value KnightValueMidgame = Value(0x332);
|
||||
const Value PawnValueMidgame = Value(0x0C6);
|
||||
const Value PawnValueEndgame = Value(0x102);
|
||||
const Value KnightValueMidgame = Value(0x331);
|
||||
const Value KnightValueEndgame = Value(0x34E);
|
||||
const Value BishopValueMidgame = Value(0x345);
|
||||
const Value BishopValueEndgame = Value(0x356);
|
||||
const Value RookValueMidgame = Value(0x4F8);
|
||||
const Value RookValueEndgame = Value(0x500);
|
||||
const Value QueenValueMidgame = Value(0x9D5);
|
||||
const Value QueenValueEndgame = Value(0x9FB);
|
||||
const Value BishopValueMidgame = Value(0x344);
|
||||
const Value BishopValueEndgame = Value(0x359);
|
||||
const Value RookValueMidgame = Value(0x4F6);
|
||||
const Value RookValueEndgame = Value(0x4FE);
|
||||
const Value QueenValueMidgame = Value(0x9D9);
|
||||
const Value QueenValueEndgame = Value(0x9FE);
|
||||
|
||||
const Value PieceValueMidgame[17] = {
|
||||
Value(0),
|
||||
@@ -93,7 +93,7 @@ const Value PieceValueEndgame[17] = {
|
||||
Value(0), Value(0), Value(0)
|
||||
};
|
||||
|
||||
/// Bonus for having the side to move
|
||||
/// Bonus for having the side to move (modified by Joona Kiiski)
|
||||
|
||||
const Value TempoValueMidgame = Value(48);
|
||||
const Value TempoValueEndgame = Value(21);
|
||||
|
||||
Reference in New Issue
Block a user