mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 09:13:08 +00:00
Fixed crash bugs.
This commit is contained in:
parent
24576d77ab
commit
90ef97dcbd
8 changed files with 108 additions and 42 deletions
|
@ -22,6 +22,7 @@
|
|||
#include <cassert>
|
||||
#include <cstring> // For std::memset
|
||||
#include <iomanip>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
#include "bitboard.h"
|
||||
|
@ -938,6 +939,16 @@ ExtBonaPiece kpp_board_index[PIECE_NB] = {
|
|||
// 注 : デバッグ用。遅い。
|
||||
bool EvalList::is_valid(const Position& pos)
|
||||
{
|
||||
std::set<PieceNumber> piece_numbers;
|
||||
for (Square sq = SQ_A1; sq != SQUARE_NB; ++sq) {
|
||||
auto piece_number = piece_no_of_board(sq);
|
||||
if (piece_number == PIECE_NUMBER_NB) {
|
||||
continue;
|
||||
}
|
||||
assert(!piece_numbers.count(piece_number));
|
||||
piece_numbers.insert(piece_number);
|
||||
}
|
||||
|
||||
for (int i = 0; i < length(); ++i)
|
||||
{
|
||||
BonaPiece fw = pieceListFw[i];
|
||||
|
|
|
@ -187,7 +187,7 @@ public:
|
|||
// VPGATHERDDを使う都合、4の倍数でなければならない。
|
||||
// また、KPPT型評価関数などは、39,40番目の要素がゼロであることを前提とした
|
||||
// アクセスをしている箇所があるので注意すること。
|
||||
static const int MAX_LENGTH = 40;
|
||||
static const int MAX_LENGTH = 32;
|
||||
|
||||
// 盤上の駒に対して、その駒番号(PieceNumber)を保持している配列
|
||||
// 玉がSQUARE_NBに移動しているとき用に+1まで保持しておくが、
|
||||
|
|
|
@ -126,11 +126,12 @@ struct HuffmanedPiece
|
|||
|
||||
HuffmanedPiece huffman_table[] =
|
||||
{
|
||||
{0b000,1}, // NO_PIECE
|
||||
{0b001,3}, // PAWN
|
||||
{0b011,3}, // KNIGHT
|
||||
{0b101,3}, // BISHOP
|
||||
{0b111,3}, // ROOK
|
||||
{0b0000,1}, // NO_PIECE
|
||||
{0b0001,4}, // PAWN
|
||||
{0b0011,4}, // KNIGHT
|
||||
{0b0101,4}, // BISHOP
|
||||
{0b0111,4}, // ROOK
|
||||
{0b1001,4}, // QUEEN
|
||||
};
|
||||
|
||||
// sfenを圧縮/解凍するためのクラス
|
||||
|
@ -269,6 +270,7 @@ int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thre
|
|||
|
||||
std::memset(this, 0, sizeof(Position));
|
||||
std::memset(si, 0, sizeof(StateInfo));
|
||||
std::fill_n(&pieceList[0][0], sizeof(pieceList) / sizeof(Square), SQ_NONE);
|
||||
st = si;
|
||||
|
||||
// Active color
|
||||
|
@ -279,13 +281,7 @@ int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thre
|
|||
|
||||
// PieceListを更新する上で、どの駒がどこにあるかを設定しなければならないが、
|
||||
// それぞれの駒をどこまで使ったかのカウンター
|
||||
PieceNumber piece_no_count[KING] = {
|
||||
PIECE_NUMBER_ZERO,
|
||||
PIECE_NUMBER_PAWN,
|
||||
PIECE_NUMBER_KNIGHT,
|
||||
PIECE_NUMBER_BISHOP,
|
||||
PIECE_NUMBER_ROOK,
|
||||
};
|
||||
PieceNumber next_piece_number = PIECE_NUMBER_ZERO;
|
||||
|
||||
pieceList[W_KING][0] = SQUARE_NB;
|
||||
pieceList[B_KING][0] = SQUARE_NB;
|
||||
|
@ -294,12 +290,12 @@ int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thre
|
|||
if (mirror)
|
||||
{
|
||||
for (auto c : Colors)
|
||||
board[Mir((Square)stream.read_n_bit(7))] = make_piece(c, KING);
|
||||
board[Mir((Square)stream.read_n_bit(6))] = make_piece(c, KING);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto c : Colors)
|
||||
board[stream.read_n_bit(7)] = make_piece(c, KING);
|
||||
board[stream.read_n_bit(6)] = make_piece(c, KING);
|
||||
}
|
||||
|
||||
// Piece placement
|
||||
|
@ -335,7 +331,7 @@ int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thre
|
|||
PieceNumber piece_no =
|
||||
(pc == B_KING) ? PIECE_NUMBER_BKING : // 先手玉
|
||||
(pc == W_KING) ? PIECE_NUMBER_WKING : // 後手玉
|
||||
piece_no_count[type_of(pc)]++; // それ以外
|
||||
next_piece_number++; // それ以外
|
||||
|
||||
evalList.put_piece(piece_no, sq, pc); // sqの升にpcの駒を配置する
|
||||
|
||||
|
@ -363,12 +359,12 @@ int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thre
|
|||
}
|
||||
if (stream.read_one_bit()) {
|
||||
Square rsq;
|
||||
for (rsq = relative_square(BLACK, SQ_H1); piece_on(rsq) != W_ROOK; --rsq) {}
|
||||
for (rsq = relative_square(BLACK, SQ_H1); piece_on(rsq) != B_ROOK; --rsq) {}
|
||||
set_castling_right(BLACK, rsq);
|
||||
}
|
||||
if (stream.read_one_bit()) {
|
||||
Square rsq;
|
||||
for (rsq = relative_square(BLACK, SQ_A1); piece_on(rsq) != W_ROOK; ++rsq) {}
|
||||
for (rsq = relative_square(BLACK, SQ_A1); piece_on(rsq) != B_ROOK; ++rsq) {}
|
||||
set_castling_right(BLACK, rsq);
|
||||
}
|
||||
|
||||
|
@ -381,6 +377,9 @@ int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thre
|
|||
|| !(pieces(~sideToMove, PAWN) & (st->epSquare + pawn_push(~sideToMove))))
|
||||
st->epSquare = SQ_NONE;
|
||||
}
|
||||
else {
|
||||
st->epSquare = SQ_NONE;
|
||||
}
|
||||
|
||||
// Halfmove clock
|
||||
st->rule50 = static_cast<Square>(stream.read_n_bit(6));
|
||||
|
@ -397,6 +396,8 @@ int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thre
|
|||
thisThread = th;
|
||||
set_state(st);
|
||||
|
||||
//std::cout << *this << std::endl;
|
||||
|
||||
assert(pos_is_ok());
|
||||
#if defined(EVAL_NNUE)
|
||||
assert(evalList.is_valid(*this));
|
||||
|
|
|
@ -392,6 +392,16 @@ void MultiThinkGenSfen::thread_worker(size_t thread_id)
|
|||
auto& pos = th->rootPos;
|
||||
pos.set(StartFEN, false, &si, th);
|
||||
|
||||
// Test cod for Packed SFEN.
|
||||
//{
|
||||
// PackedSfen packed_sfen;
|
||||
// pos.sfen_pack(packed_sfen);
|
||||
// std::cout << pos << std::endl;
|
||||
// pos.set_from_packed_sfen(packed_sfen, &si, th);
|
||||
// std::string actual = pos.fen();
|
||||
// assert(actual == StartFEN);
|
||||
//}
|
||||
|
||||
// 探索部で定義されているBookMoveSelectorのメンバを参照する。
|
||||
//auto& book = ::book;
|
||||
|
||||
|
|
|
@ -249,14 +249,7 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
|
|||
|
||||
// PieceListを更新する上で、どの駒がどこにあるかを設定しなければならないが、
|
||||
// それぞれの駒をどこまで使ったかのカウンター
|
||||
PieceNumber piece_no_count[KING] = {
|
||||
PIECE_NUMBER_ZERO,
|
||||
PIECE_NUMBER_PAWN,
|
||||
PIECE_NUMBER_KNIGHT,
|
||||
PIECE_NUMBER_BISHOP,
|
||||
PIECE_NUMBER_ROOK,
|
||||
PIECE_NUMBER_QUEEN
|
||||
};
|
||||
PieceNumber next_piece_number = PIECE_NUMBER_ZERO;
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
ss >> std::noskipws;
|
||||
|
@ -279,7 +272,7 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
|
|||
PieceNumber piece_no =
|
||||
(idx == W_KING) ? PIECE_NUMBER_WKING : // 先手玉
|
||||
(idx == B_KING) ? PIECE_NUMBER_BKING : // 後手玉
|
||||
piece_no_count[type_of(Piece(idx))]++; // ‚»‚êˆÈŠO
|
||||
next_piece_number++; // ‚»‚ę<E2809A>ČŠO
|
||||
evalList.put_piece(piece_no, sq, pc); // sqの升にpcの駒を配置する
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
|
@ -780,6 +773,9 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
|
|||
Piece pc = piece_on(from);
|
||||
Piece captured = type_of(m) == ENPASSANT ? make_piece(them, PAWN) : piece_on(to);
|
||||
|
||||
PieceNumber piece_no0 = PIECE_NUMBER_NB;
|
||||
PieceNumber piece_no1 = PIECE_NUMBER_NB;
|
||||
|
||||
assert(color_of(pc) == us);
|
||||
assert(captured == NO_PIECE || color_of(captured) == (type_of(m) != CASTLING ? them : us));
|
||||
assert(type_of(captured) != KING);
|
||||
|
@ -805,10 +801,6 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
|
|||
{
|
||||
Square capsq = to;
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
PieceNumber piece_no1;
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
// If the captured piece is a pawn, update pawn hash key, otherwise
|
||||
// update non-pawn material.
|
||||
if (type_of(captured) == PAWN)
|
||||
|
@ -828,6 +820,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
|
|||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
board[capsq] = NO_PIECE; // Not done by remove_piece()
|
||||
evalList.piece_no_list_board[capsq] = PIECE_NUMBER_NB;
|
||||
}
|
||||
else {
|
||||
#if defined(EVAL_NNUE)
|
||||
|
@ -893,7 +886,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
|
|||
// Move the piece. The tricky Chess960 castling is handled earlier
|
||||
if (type_of(m) != CASTLING) {
|
||||
#if defined(EVAL_NNUE)
|
||||
PieceNumber piece_no0 = piece_no_of(from);
|
||||
piece_no0 = piece_no_of(from);
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
move_piece(pc, from, to);
|
||||
|
@ -901,6 +894,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
|
|||
#if defined(EVAL_NNUE)
|
||||
dp.pieceNo[0] = piece_no0;
|
||||
dp.changed_piece[0].old_piece = evalList.bona_piece(piece_no0);
|
||||
evalList.piece_no_list_board[from] = PIECE_NUMBER_NB;
|
||||
evalList.put_piece(piece_no0, to, pc);
|
||||
dp.changed_piece[0].new_piece = evalList.bona_piece(piece_no0);
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
@ -928,9 +922,10 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
|
|||
put_piece(promotion, to);
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
PieceNumber piece_no0 = piece_no_of(to);
|
||||
piece_no0 = piece_no_of(to);
|
||||
dp.pieceNo[0] = piece_no0;
|
||||
dp.changed_piece[0].old_piece = evalList.bona_piece(piece_no0);
|
||||
assert(evalList.piece_no_list_board[from] == PIECE_NUMBER_NB);
|
||||
evalList.put_piece(piece_no0, to, promotion);
|
||||
dp.changed_piece[0].new_piece = evalList.bona_piece(piece_no0);
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
@ -985,6 +980,8 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
|
|||
}
|
||||
}
|
||||
|
||||
//std::cout << *this << std::endl;
|
||||
|
||||
assert(pos_is_ok());
|
||||
#if defined(EVAL_NNUE)
|
||||
assert(evalList.is_valid(*this));
|
||||
|
@ -1038,6 +1035,7 @@ void Position::undo_move(Move m) {
|
|||
#if defined(EVAL_NNUE)
|
||||
PieceNumber piece_no0 = st->dirtyPiece.pieceNo[0];
|
||||
evalList.put_piece(piece_no0, from, pc);
|
||||
evalList.piece_no_list_board[to] = PIECE_NUMBER_NB;
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
if (st->capturedPiece)
|
||||
|
@ -1118,16 +1116,20 @@ void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Squ
|
|||
if (Do) {
|
||||
dp.pieceNo[0] = piece_no0;
|
||||
dp.changed_piece[0].old_piece = evalList.bona_piece(piece_no0);
|
||||
evalList.piece_no_list_board[from] = PIECE_NUMBER_NB;
|
||||
evalList.put_piece(piece_no0, to, make_piece(us, KING));
|
||||
dp.changed_piece[0].new_piece = evalList.bona_piece(piece_no0);
|
||||
|
||||
dp.pieceNo[1] = piece_no1;
|
||||
dp.changed_piece[1].old_piece = evalList.bona_piece(piece_no1);
|
||||
evalList.piece_no_list_board[rfrom] = PIECE_NUMBER_NB;
|
||||
evalList.put_piece(piece_no1, rto, make_piece(us, ROOK));
|
||||
dp.changed_piece[1].new_piece = evalList.bona_piece(piece_no1);
|
||||
}
|
||||
else {
|
||||
evalList.piece_no_list_board[to] = PIECE_NUMBER_NB;
|
||||
evalList.put_piece(piece_no0, from, make_piece(us, KING));
|
||||
evalList.piece_no_list_board[rto] = PIECE_NUMBER_NB;
|
||||
evalList.put_piece(piece_no1, rfrom, make_piece(us, ROOK));
|
||||
}
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
|
|
@ -871,7 +871,7 @@ moves_loop: // When in check, search starts from here
|
|||
|
||||
ss->moveCount = ++moveCount;
|
||||
|
||||
if (rootNode && thisThread == Threads.main() && Time.elapsed() > 3000)
|
||||
if (rootNode && thisThread == Threads.main() && Time.elapsed() > 3000 && !Limits.silent)
|
||||
sync_cout << "info depth " << depth / ONE_PLY
|
||||
<< " currmove " << UCI::move(move, pos.is_chess960())
|
||||
<< " currmovenumber " << moveCount + thisThread->pvIdx << sync_endl;
|
||||
|
@ -1382,7 +1382,9 @@ moves_loop: // When in check, search starts from here
|
|||
ss->continuationHistory = &thisThread->continuationHistory[pos.moved_piece(move)][to_sq(move)];
|
||||
|
||||
// Make and search the move
|
||||
//std::cout << pos << std::endl;
|
||||
pos.do_move(move, st, givesCheck);
|
||||
//std::cout << pos << std::endl;
|
||||
value = -qsearch<NT>(pos, ss+1, -beta, -alpha, depth - ONE_PLY);
|
||||
pos.undo_move(move);
|
||||
|
||||
|
@ -1740,7 +1742,7 @@ namespace Learner
|
|||
// RootNodeはss->ply == 0がその条件。
|
||||
// ゼロクリアするので、ss->ply == 0となるので大丈夫…。
|
||||
|
||||
memset(ss - 4, 0, 7 * sizeof(Stack));
|
||||
std::memset(ss - 7, 0, 10 * sizeof(Stack));
|
||||
|
||||
// Search::Limitsに関して
|
||||
// このメンバー変数はglobalなので他のスレッドに影響を及ぼすので気をつけること。
|
||||
|
@ -1751,7 +1753,7 @@ namespace Learner
|
|||
limits.infinite = true;
|
||||
|
||||
// PVを表示されると邪魔なので消しておく。
|
||||
//limits.silent = true;
|
||||
limits.silent = true;
|
||||
|
||||
// これを用いると各スレッドのnodesを積算したものと比較されてしまう。ゆえに使用しない。
|
||||
limits.nodes = 0;
|
||||
|
@ -1789,8 +1791,23 @@ namespace Learner
|
|||
// history類を全部クリアする。この初期化は少し時間がかかるし、探索の精度はむしろ下がるので善悪はよくわからない。
|
||||
// th->clear();
|
||||
|
||||
for (int i = 4; i > 0; i--)
|
||||
(ss - i)->continuationHistory = &th->continuationHistory[SQUARE_ZERO][NO_PIECE];
|
||||
int ct = int(Options["Contempt"]) * PawnValueEg / 100; // From centipawns
|
||||
Color us = pos.side_to_move();
|
||||
|
||||
// In analysis mode, adjust contempt in accordance with user preference
|
||||
if (Limits.infinite || Options["UCI_AnalyseMode"])
|
||||
ct = Options["Analysis Contempt"] == "Off" ? 0
|
||||
: Options["Analysis Contempt"] == "Both" ? ct
|
||||
: Options["Analysis Contempt"] == "White" && us == BLACK ? -ct
|
||||
: Options["Analysis Contempt"] == "Black" && us == WHITE ? -ct
|
||||
: ct;
|
||||
|
||||
// Evaluation score is from the white point of view
|
||||
th->contempt = (us == WHITE ? make_score(ct, ct / 2)
|
||||
: -make_score(ct, ct / 2));
|
||||
|
||||
for (int i = 7; i > 0; i--)
|
||||
(ss - i)->continuationHistory = &th->continuationHistory[NO_PIECE][0]; // Use as sentinel
|
||||
|
||||
// rootMovesの設定
|
||||
auto& rootMoves = th->rootMoves;
|
||||
|
@ -1831,7 +1848,7 @@ namespace Learner
|
|||
// 悪い影響があるので、窓の範囲を指定できるようにするのをやめることにした。
|
||||
ValueAndPV qsearch(Position& pos)
|
||||
{
|
||||
Stack stack[MAX_PLY + 7], * ss = stack + 4;
|
||||
Stack stack[MAX_PLY + 10], * ss = stack + 7;
|
||||
Move pv[MAX_PLY + 1];
|
||||
std::vector<Move> pvs;
|
||||
|
||||
|
@ -1881,7 +1898,7 @@ namespace Learner
|
|||
if (depth == DEPTH_ZERO)
|
||||
return qsearch(pos);
|
||||
|
||||
Stack stack[MAX_PLY + 7], * ss = stack + 4;
|
||||
Stack stack[MAX_PLY + 10], * ss = stack + 7;
|
||||
Move pv[MAX_PLY + 1];
|
||||
|
||||
init_for_search(pos, ss);
|
||||
|
@ -1892,6 +1909,7 @@ namespace Learner
|
|||
auto th = pos.this_thread();
|
||||
auto& rootDepth = th->rootDepth;
|
||||
auto& pvIdx = th->pvIdx;
|
||||
auto& pvLast = th->pvLast;
|
||||
auto& rootMoves = th->rootMoves;
|
||||
auto& completedDepth = th->completedDepth;
|
||||
auto& selDepth = th->selDepth;
|
||||
|
@ -1919,9 +1937,20 @@ namespace Learner
|
|||
for (RootMove& rm : rootMoves)
|
||||
rm.previousScore = rm.score;
|
||||
|
||||
// MultiPV
|
||||
size_t pvFirst = 0;
|
||||
pvLast = 0;
|
||||
|
||||
// MultiPV loop. We perform a full root search for each PV line
|
||||
for (pvIdx = 0; pvIdx < multiPV && !Threads.stop; ++pvIdx)
|
||||
{
|
||||
if (pvIdx == pvLast)
|
||||
{
|
||||
pvFirst = pvLast;
|
||||
for (pvLast++; pvLast < rootMoves.size(); pvLast++)
|
||||
if (rootMoves[pvLast].tbRank != rootMoves[pvFirst].tbRank)
|
||||
break;
|
||||
}
|
||||
|
||||
// それぞれのdepthとPV lineに対するUSI infoで出力するselDepth
|
||||
selDepth = 0;
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ struct LimitsType {
|
|||
time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = npmsec = movetime = TimePoint(0);
|
||||
movestogo = depth = mate = perft = infinite = 0;
|
||||
nodes = 0;
|
||||
silent = false;
|
||||
}
|
||||
|
||||
bool use_time_management() const {
|
||||
|
@ -96,6 +97,9 @@ struct LimitsType {
|
|||
TimePoint time[COLOR_NB], inc[COLOR_NB], npmsec, movetime, startTime;
|
||||
int movestogo, depth, mate, perft, infinite;
|
||||
int64_t nodes;
|
||||
// 画面に出力しないサイレントモード(プロセス内での連続自己対戦のとき用)
|
||||
// このときPVを出力しない。
|
||||
bool silent;
|
||||
};
|
||||
|
||||
extern LimitsType Limits;
|
||||
|
|
|
@ -87,6 +87,15 @@ void init(OptionsMap& o) {
|
|||
// そこでこの隠しオプションでisready時の評価関数の読み込みを抑制して、
|
||||
// test evalconvertコマンドを叩く。
|
||||
o["SkipLoadingEval"] << Option(false);
|
||||
// 定跡の指し手を何手目まで用いるか
|
||||
o["BookMoves"] << Option(16, 0, 10000);
|
||||
|
||||
#if defined(EVAL_LEARN)
|
||||
// 評価関数の学習を行なうときは、評価関数の保存先のフォルダを変更できる。
|
||||
// デフォルトではevalsave。このフォルダは事前に用意されているものとする。
|
||||
// このフォルダ配下にフォルダを"0/","1/",…のように自動的に掘り、そこに評価関数ファイルを保存する。
|
||||
o["EvalSaveDir"] << Option("evalsave");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue