mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 09:13:08 +00:00
More comment translation
including 11 files in /src
This commit is contained in:
parent
f5cc77bc7c
commit
8f31d74cf6
11 changed files with 293 additions and 293 deletions
|
@ -945,7 +945,7 @@ ExtBonaPiece kpp_board_index[PIECE_NB] = {
|
||||||
{ f_king, e_king },
|
{ f_king, e_king },
|
||||||
{ BONA_PIECE_ZERO, BONA_PIECE_ZERO },
|
{ BONA_PIECE_ZERO, BONA_PIECE_ZERO },
|
||||||
|
|
||||||
// 後手から見た場合。fとeが入れ替わる。
|
// When viewed from behind. f and e are exchanged.
|
||||||
{ BONA_PIECE_ZERO, BONA_PIECE_ZERO },
|
{ BONA_PIECE_ZERO, BONA_PIECE_ZERO },
|
||||||
{ e_pawn, f_pawn },
|
{ e_pawn, f_pawn },
|
||||||
{ e_knight, f_knight },
|
{ e_knight, f_knight },
|
||||||
|
@ -953,11 +953,11 @@ ExtBonaPiece kpp_board_index[PIECE_NB] = {
|
||||||
{ e_rook, f_rook },
|
{ e_rook, f_rook },
|
||||||
{ e_queen, f_queen },
|
{ e_queen, f_queen },
|
||||||
{ e_king, f_king },
|
{ e_king, f_king },
|
||||||
{ BONA_PIECE_ZERO, BONA_PIECE_ZERO }, // 金の成りはない
|
{ BONA_PIECE_ZERO, BONA_PIECE_ZERO }, // no money
|
||||||
};
|
};
|
||||||
|
|
||||||
// 内部で保持しているpieceListFw[]が正しいBonaPieceであるかを検査する。
|
// Check whether the pieceListFw[] held internally is a correct BonaPiece.
|
||||||
// 注 : デバッグ用。遅い。
|
// Note: For debugging. slow.
|
||||||
bool EvalList::is_valid(const Position& pos)
|
bool EvalList::is_valid(const Position& pos)
|
||||||
{
|
{
|
||||||
std::set<PieceNumber> piece_numbers;
|
std::set<PieceNumber> piece_numbers;
|
||||||
|
@ -973,28 +973,28 @@ bool EvalList::is_valid(const Position& pos)
|
||||||
for (int i = 0; i < length(); ++i)
|
for (int i = 0; i < length(); ++i)
|
||||||
{
|
{
|
||||||
BonaPiece fw = pieceListFw[i];
|
BonaPiece fw = pieceListFw[i];
|
||||||
// このfwが本当に存在するかをPositionクラスのほうに調べに行く。
|
// Go to the Position class to see if this fw really exists.
|
||||||
|
|
||||||
if (fw == Eval::BONA_PIECE_ZERO) {
|
if (fw == Eval::BONA_PIECE_ZERO) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 範囲外
|
// Out of range
|
||||||
if (!(0 <= fw && fw < fe_end))
|
if (!(0 <= fw && fw < fe_end))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// 盤上の駒なのでこの駒が本当に存在するか調べにいく。
|
// Since it is a piece on the board, I will check if this piece really exists.
|
||||||
for (Piece pc = NO_PIECE; pc < PIECE_NB; ++pc)
|
for (Piece pc = NO_PIECE; pc < PIECE_NB; ++pc)
|
||||||
{
|
{
|
||||||
auto pt = type_of(pc);
|
auto pt = type_of(pc);
|
||||||
if (pt == NO_PIECE_TYPE || pt == 7) // 存在しない駒
|
if (pt == NO_PIECE_TYPE || pt == 7) // non-existing piece
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// 駒pcのBonaPieceの開始番号
|
// BonaPiece start number of piece pc
|
||||||
auto s = BonaPiece(kpp_board_index[pc].fw);
|
auto s = BonaPiece(kpp_board_index[pc].fw);
|
||||||
if (s <= fw && fw < s + SQUARE_NB)
|
if (s <= fw && fw < s + SQUARE_NB)
|
||||||
{
|
{
|
||||||
// 見つかったのでこの駒がsqの地点にあるかを調べる。
|
// Since it was found, check if this piece is at sq.
|
||||||
Square sq = (Square)(fw - s);
|
Square sq = (Square)(fw - s);
|
||||||
Piece pc2 = pos.piece_on(sq);
|
Piece pc2 = pos.piece_on(sq);
|
||||||
|
|
||||||
|
@ -1004,7 +1004,7 @@ bool EvalList::is_valid(const Position& pos)
|
||||||
goto Found;
|
goto Found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 何故か存在しない駒であった..
|
// It was a piece that did not exist for some reason..
|
||||||
return false;
|
return false;
|
||||||
Found:;
|
Found:;
|
||||||
}
|
}
|
||||||
|
|
104
src/evaluate.h
104
src/evaluate.h
|
@ -38,39 +38,39 @@ void evaluate_with_no_return(const Position& pos);
|
||||||
Value compute_eval(const Position& pos);
|
Value compute_eval(const Position& pos);
|
||||||
|
|
||||||
#if defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
#if defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
||||||
// 評価関数ファイルを読み込む。
|
// Read the evaluation function file.
|
||||||
// これは、"is_ready"コマンドの応答時に1度だけ呼び出される。2度呼び出すことは想定していない。
|
// This is only called once in response to the "is_ready" command. It is not supposed to be called twice.
|
||||||
// (ただし、EvalDir(評価関数フォルダ)が変更になったあと、isreadyが再度送られてきたら読みなおす。)
|
// (However, if isready is sent again after EvalDir (evaluation function folder) has been changed, read it again.)
|
||||||
void load_eval();
|
void load_eval();
|
||||||
|
|
||||||
static uint64_t calc_check_sum() {return 0;}
|
static uint64_t calc_check_sum() {return 0;}
|
||||||
|
|
||||||
static void print_softname(uint64_t check_sum) {}
|
static void print_softname(uint64_t check_sum) {}
|
||||||
|
|
||||||
// --- 評価関数で使う定数 KPP(玉と任意2駒)のPに相当するenum
|
// --- enum corresponding to P of constant KPP (ball and arbitrary 2 pieces) used in evaluation function
|
||||||
|
|
||||||
// (評価関数の実験のときには、BonaPieceは自由に定義したいのでここでは定義しない。)
|
// (BonaPiece wants to define freely in experiment of evaluation function, so I don't define it here.)
|
||||||
|
|
||||||
|
|
||||||
// BonanzaでKKP/KPPと言うときのP(Piece)を表現する型。
|
// A type that represents P(Piece) when calling KKP/KPP in Bonanza.
|
||||||
// Σ KPPを求めるときに、39の地点の歩のように、升×駒種に対して一意な番号が必要となる。
|
// When you ask for ƒ° KPP, you need a unique number for each box <20>~ piece type, like the step at 39 points.
|
||||||
enum BonaPiece : int32_t
|
enum BonaPiece : int32_t
|
||||||
{
|
{
|
||||||
// f = friend(≒先手)の意味。e = enemy(≒後手)の意味
|
// Meaning of f = friend (<28>àfirst move). Meaning of e = enemy (<28>àrear)
|
||||||
|
|
||||||
// 未初期化の時の値
|
// Value when uninitialized
|
||||||
BONA_PIECE_NOT_INIT = -1,
|
BONA_PIECE_NOT_INIT = -1,
|
||||||
|
|
||||||
// 無効な駒。駒落ちのときなどは、不要な駒をここに移動させる。
|
// Invalid piece. When you drop a piece, move unnecessary pieces here.
|
||||||
BONA_PIECE_ZERO = 0,
|
BONA_PIECE_ZERO = 0,
|
||||||
|
|
||||||
fe_hand_end = BONA_PIECE_ZERO + 1,
|
fe_hand_end = BONA_PIECE_ZERO + 1,
|
||||||
|
|
||||||
// Bonanzaのように盤上のありえない升の歩や香の番号を詰めない。
|
// Don't pack the numbers of unrealistic walks and incense on the board like Bonanza.
|
||||||
// 理由1) 学習のときに相対PPで1段目に香がいるときがあって、それを逆変換において正しく表示するのが難しい。
|
// Reason 1) When learning, there are times when the incense is on the first stage in relative PP, and it is difficult to display it correctly in the inverse transformation.
|
||||||
// 理由2) 縦型BitboardだとSquareからの変換に困る。
|
// Reason 2) It is difficult to convert from Square with vertical Bitboard.
|
||||||
|
|
||||||
// --- 盤上の駒
|
// --- Pieces on the board
|
||||||
f_pawn = fe_hand_end,
|
f_pawn = fe_hand_end,
|
||||||
e_pawn = f_pawn + SQUARE_NB,
|
e_pawn = f_pawn + SQUARE_NB,
|
||||||
f_knight = e_pawn + SQUARE_NB,
|
f_knight = e_pawn + SQUARE_NB,
|
||||||
|
@ -84,7 +84,7 @@ enum BonaPiece : int32_t
|
||||||
fe_end = e_queen + SQUARE_NB,
|
fe_end = e_queen + SQUARE_NB,
|
||||||
f_king = fe_end,
|
f_king = fe_end,
|
||||||
e_king = f_king + SQUARE_NB,
|
e_king = f_king + SQUARE_NB,
|
||||||
fe_end2 = e_king + SQUARE_NB, // 玉も含めた末尾の番号。
|
fe_end2 = e_king + SQUARE_NB, // Last number including balls.
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ENABLE_INCR_OPERATORS_ON(T) \
|
#define ENABLE_INCR_OPERATORS_ON(T) \
|
||||||
|
@ -95,8 +95,8 @@ ENABLE_INCR_OPERATORS_ON(BonaPiece)
|
||||||
|
|
||||||
#undef ENABLE_INCR_OPERATORS_ON
|
#undef ENABLE_INCR_OPERATORS_ON
|
||||||
|
|
||||||
// BonaPieceを後手から見たとき(先手の39の歩を後手から見ると後手の71の歩)の番号とを
|
// The number when you look at BonaPiece from the back (the number of steps from the previous 39 to the number 71 from the back)
|
||||||
// ペアにしたものをExtBonaPiece型と呼ぶことにする。
|
// Let's call the paired one the ExtBonaPiece type.
|
||||||
union ExtBonaPiece
|
union ExtBonaPiece
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
|
@ -109,28 +109,28 @@ union ExtBonaPiece
|
||||||
ExtBonaPiece(BonaPiece fw_, BonaPiece fb_) : fw(fw_), fb(fb_) {}
|
ExtBonaPiece(BonaPiece fw_, BonaPiece fb_) : fw(fw_), fb(fb_) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 駒が今回の指し手によってどこからどこに移動したのかの情報。
|
// Information about where the piece has moved from where to by this move.
|
||||||
// 駒はExtBonaPiece表現であるとする。
|
// Assume the piece is an ExtBonaPiece expression.
|
||||||
struct ChangedBonaPiece
|
struct ChangedBonaPiece
|
||||||
{
|
{
|
||||||
ExtBonaPiece old_piece;
|
ExtBonaPiece old_piece;
|
||||||
ExtBonaPiece new_piece;
|
ExtBonaPiece new_piece;
|
||||||
};
|
};
|
||||||
|
|
||||||
// KPPテーブルの盤上の駒pcに対応するBonaPieceを求めるための配列。
|
// An array for finding the BonaPiece corresponding to the piece pc on the board of the KPP table.
|
||||||
// 例)
|
// example)
|
||||||
// BonaPiece fb = kpp_board_index[pc].fb + sq; // 先手から見たsqにあるpcに対応するBonaPiece
|
// BonaPiece fb = kpp_board_index[pc].fb + sq; // BonaPiece corresponding to pc in sq seen from the front
|
||||||
// BonaPiece fw = kpp_board_index[pc].fw + sq; // 後手から見たsqにあるpcに対応するBonaPiece
|
// BonaPiece fw = kpp_board_index[pc].fw + sq; // BonaPiece corresponding to pc in sq seen from behind
|
||||||
extern ExtBonaPiece kpp_board_index[PIECE_NB];
|
extern ExtBonaPiece kpp_board_index[PIECE_NB];
|
||||||
|
|
||||||
// 評価関数で用いる駒リスト。どの駒(PieceNumber)がどこにあるのか(BonaPiece)を保持している構造体
|
// List of pieces used in the evaluation function. A structure holding which piece (PieceNumber) is where (BonaPiece)
|
||||||
struct EvalList
|
struct EvalList
|
||||||
{
|
{
|
||||||
// 評価関数(FV38型)で用いる駒番号のリスト
|
// List of frame numbers used in evaluation function (FV38 type)
|
||||||
BonaPiece* piece_list_fw() const { return const_cast<BonaPiece*>(pieceListFw); }
|
BonaPiece* piece_list_fw() const { return const_cast<BonaPiece*>(pieceListFw); }
|
||||||
BonaPiece* piece_list_fb() const { return const_cast<BonaPiece*>(pieceListFb); }
|
BonaPiece* piece_list_fb() const { return const_cast<BonaPiece*>(pieceListFb); }
|
||||||
|
|
||||||
// 指定されたpiece_noの駒をExtBonaPiece型に変換して返す。
|
// Convert the specified piece_no piece to ExtBonaPiece type and return it.
|
||||||
ExtBonaPiece bona_piece(PieceNumber piece_no) const
|
ExtBonaPiece bona_piece(PieceNumber piece_no) const
|
||||||
{
|
{
|
||||||
ExtBonaPiece bp;
|
ExtBonaPiece bp;
|
||||||
|
@ -139,18 +139,18 @@ struct EvalList
|
||||||
return bp;
|
return bp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 盤上のsqの升にpiece_noのpcの駒を配置する
|
// Place the piece_no pc piece in the sq box on the board
|
||||||
void put_piece(PieceNumber piece_no, Square sq, Piece pc) {
|
void put_piece(PieceNumber piece_no, Square sq, Piece pc) {
|
||||||
set_piece_on_board(piece_no, BonaPiece(kpp_board_index[pc].fw + sq), BonaPiece(kpp_board_index[pc].fb + Inv(sq)), sq);
|
set_piece_on_board(piece_no, BonaPiece(kpp_board_index[pc].fw + sq), BonaPiece(kpp_board_index[pc].fb + Inv(sq)), sq);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 盤上のある升sqに対応するPieceNumberを返す。
|
// Returns the PieceNumber corresponding to a box on the board.
|
||||||
PieceNumber piece_no_of_board(Square sq) const { return piece_no_list_board[sq]; }
|
PieceNumber piece_no_of_board(Square sq) const { return piece_no_list_board[sq]; }
|
||||||
|
|
||||||
// pieceListを初期化する。
|
// Initialize the pieceList.
|
||||||
// 駒落ちに対応させる時のために、未使用の駒の値はBONA_PIECE_ZEROにしておく。
|
// Set the value of unused pieces to BONA_PIECE_ZERO in case you want to deal with dropped pieces.
|
||||||
// 通常の評価関数を駒落ちの評価関数として流用できる。
|
// A normal evaluation function can be used as an evaluation function for missing frames.
|
||||||
// piece_no_listのほうはデバッグが捗るようにPIECE_NUMBER_NBで初期化。
|
// piece_no_list is initialized with PIECE_NUMBER_NB to facilitate debugging.
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -164,11 +164,11 @@ struct EvalList
|
||||||
v = PIECE_NUMBER_NB;
|
v = PIECE_NUMBER_NB;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 内部で保持しているpieceListFw[]が正しいBonaPieceであるかを検査する。
|
// Check whether the pieceListFw[] held internally is a correct BonaPiece.
|
||||||
// 注 : デバッグ用。遅い。
|
// Note: For debugging. slow.
|
||||||
bool is_valid(const Position& pos);
|
bool is_valid(const Position& pos);
|
||||||
|
|
||||||
// 盤上sqにあるpiece_noの駒のBonaPieceがfb,fwであることを設定する。
|
// Set that the BonaPiece of the piece_no piece on the board sq is fb,fw.
|
||||||
inline void set_piece_on_board(PieceNumber piece_no, BonaPiece fw, BonaPiece fb, Square sq)
|
inline void set_piece_on_board(PieceNumber piece_no, BonaPiece fw, BonaPiece fb, Square sq)
|
||||||
{
|
{
|
||||||
assert(is_ok(piece_no));
|
assert(is_ok(piece_no));
|
||||||
|
@ -177,21 +177,21 @@ struct EvalList
|
||||||
piece_no_list_board[sq] = piece_no;
|
piece_no_list_board[sq] = piece_no;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 駒リスト。駒番号(PieceNumber)いくつの駒がどこにあるのか(BonaPiece)を示す。FV38などで用いる。
|
// Piece list. Piece Number Shows how many pieces are in place (Bona Piece). Used in FV38 etc.
|
||||||
|
|
||||||
// 駒リストの長さ
|
// Length of piece list
|
||||||
// 38固定
|
// 38 fixed
|
||||||
public:
|
public:
|
||||||
int length() const { return PIECE_NUMBER_KING; }
|
int length() const { return PIECE_NUMBER_KING; }
|
||||||
|
|
||||||
// VPGATHERDDを使う都合、4の倍数でなければならない。
|
// Must be a multiple of 4 to use VPGATHERDD.
|
||||||
// また、KPPT型評価関数などは、39,40番目の要素がゼロであることを前提とした
|
// In addition, the KPPT type evaluation function, etc. is based on the assumption that the 39th and 40th elements are zero.
|
||||||
// アクセスをしている箇所があるので注意すること。
|
// Please note that there is a part that is accessed.
|
||||||
static const int MAX_LENGTH = 32;
|
static const int MAX_LENGTH = 32;
|
||||||
|
|
||||||
// 盤上の駒に対して、その駒番号(PieceNumber)を保持している配列
|
// An array that holds the piece number (PieceNumber) for the pieces on the board
|
||||||
// 玉がSQUARE_NBに移動しているとき用に+1まで保持しておくが、
|
// Hold up to +1 for when the ball is moving to SQUARE_NB,
|
||||||
// SQUARE_NBの玉を移動させないので、この値を使うことはないはず。
|
// SQUARE_NB balls are not moved, so this value should never be used.
|
||||||
PieceNumber piece_no_list_board[SQUARE_NB_PLUS1];
|
PieceNumber piece_no_list_board[SQUARE_NB_PLUS1];
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -199,20 +199,20 @@ private:
|
||||||
BonaPiece pieceListFb[MAX_LENGTH];
|
BonaPiece pieceListFb[MAX_LENGTH];
|
||||||
};
|
};
|
||||||
|
|
||||||
// 評価値の差分計算の管理用
|
// For management of evaluation value difference calculation
|
||||||
// 前の局面から移動した駒番号を管理するための構造体
|
// A structure for managing the number of pieces that have moved from the previous stage
|
||||||
// 動く駒は、最大で2個。
|
// Up to 2 moving pieces.
|
||||||
struct DirtyPiece
|
struct DirtyPiece
|
||||||
{
|
{
|
||||||
// その駒番号の駒が何から何に変わったのか
|
// What changed from the piece with that piece number
|
||||||
Eval::ChangedBonaPiece changed_piece[2];
|
Eval::ChangedBonaPiece changed_piece[2];
|
||||||
|
|
||||||
// dirtyになった駒番号
|
// The number of dirty pieces
|
||||||
PieceNumber pieceNo[2];
|
PieceNumber pieceNo[2];
|
||||||
|
|
||||||
// dirtyになった個数。
|
// The number of dirty files.
|
||||||
// null moveだと0ということもありうる。
|
// It can be 0 for null move.
|
||||||
// 動く駒と取られる駒とで最大で2つ。
|
// Up to 2 moving pieces and taken pieces.
|
||||||
int dirty_num;
|
int dirty_num;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
52
src/misc.cpp
52
src/misc.cpp
|
@ -527,11 +527,11 @@ void bindThisThread(size_t idx) {
|
||||||
|
|
||||||
} // namespace WinProcGroup
|
} // namespace WinProcGroup
|
||||||
|
|
||||||
// 現在時刻を文字列化したもを返す。(評価関数の学習時などに用いる)
|
// Returns a string that represents the current time. (Used when learning evaluation functions)
|
||||||
std::string now_string()
|
std::string now_string()
|
||||||
{
|
{
|
||||||
// std::ctime(), localtime()を使うと、MSVCでセキュアでないという警告が出る。
|
// Using std::ctime(), localtime() gives a warning that MSVC is not secure.
|
||||||
// C++標準的にはそんなことないはずなのだが…。
|
// This shouldn't happen in the C++ standard, but...
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
// C4996 : 'ctime' : This function or variable may be unsafe.Consider using ctime_s instead.
|
// C4996 : 'ctime' : This function or variable may be unsafe.Consider using ctime_s instead.
|
||||||
|
@ -542,7 +542,7 @@ std::string now_string()
|
||||||
auto tp = std::chrono::system_clock::to_time_t(now);
|
auto tp = std::chrono::system_clock::to_time_t(now);
|
||||||
auto result = string(std::ctime(&tp));
|
auto result = string(std::ctime(&tp));
|
||||||
|
|
||||||
// 末尾に改行コードが含まれているならこれを除去する
|
// remove line endings if they are included at the end
|
||||||
while (*result.rbegin() == '\n' || (*result.rbegin() == '\r'))
|
while (*result.rbegin() == '\n' || (*result.rbegin() == '\r'))
|
||||||
result.pop_back();
|
result.pop_back();
|
||||||
return result;
|
return result;
|
||||||
|
@ -572,31 +572,31 @@ int read_file_to_memory(std::string filename, std::function<void* (uint64_t)> ca
|
||||||
|
|
||||||
fs.seekg(0, fstream::end);
|
fs.seekg(0, fstream::end);
|
||||||
uint64_t eofPos = (uint64_t)fs.tellg();
|
uint64_t eofPos = (uint64_t)fs.tellg();
|
||||||
fs.clear(); // これをしないと次のseekに失敗することがある。
|
fs.clear(); // Otherwise the next seek may fail.
|
||||||
fs.seekg(0, fstream::beg);
|
fs.seekg(0, fstream::beg);
|
||||||
uint64_t begPos = (uint64_t)fs.tellg();
|
uint64_t begPos = (uint64_t)fs.tellg();
|
||||||
uint64_t file_size = eofPos - begPos;
|
uint64_t file_size = eofPos - begPos;
|
||||||
//std::cout << "filename = " << filename << " , file_size = " << file_size << endl;
|
//std::cout << "filename = " << filename << " , file_size = " << file_size << endl;
|
||||||
|
|
||||||
// ファイルサイズがわかったのでcallback_funcを呼び出してこの分のバッファを確保してもらい、
|
// I know the file size, so call callback_func to get a buffer for this,
|
||||||
// そのポインターをもらう。
|
// Get the pointer.
|
||||||
void* ptr = callback_func(file_size);
|
void* ptr = callback_func(file_size);
|
||||||
|
|
||||||
// バッファが確保できなかった場合や、想定していたファイルサイズと異なった場合は、
|
// If the buffer could not be secured, or if the file size is different from the expected file size,
|
||||||
// nullptrを返すことになっている。このとき、読み込みを中断し、エラーリターンする。
|
// It is supposed to return nullptr. At this time, reading is interrupted and an error is returned.
|
||||||
if (ptr == nullptr)
|
if (ptr == nullptr)
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
// 細切れに読み込む
|
// read in pieces
|
||||||
|
|
||||||
const uint64_t block_size = 1024 * 1024 * 1024; // 1回のreadで読み込む要素の数(1GB)
|
const uint64_t block_size = 1024 * 1024 * 1024; // number of elements to read in one read (1GB)
|
||||||
for (uint64_t pos = 0; pos < file_size; pos += block_size)
|
for (uint64_t pos = 0; pos < file_size; pos += block_size)
|
||||||
{
|
{
|
||||||
// 今回読み込むサイズ
|
// size to read this time
|
||||||
uint64_t read_size = (pos + block_size < file_size) ? block_size : (file_size - pos);
|
uint64_t read_size = (pos + block_size < file_size) ? block_size : (file_size - pos);
|
||||||
fs.read((char*)ptr + pos, read_size);
|
fs.read((char*)ptr + pos, read_size);
|
||||||
|
|
||||||
// ファイルの途中で読み込みエラーに至った。
|
// Read error occurred in the middle of the file.
|
||||||
if (fs.fail())
|
if (fs.fail())
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
|
@ -613,10 +613,10 @@ int write_memory_to_file(std::string filename, void* ptr, uint64_t size)
|
||||||
if (fs.fail())
|
if (fs.fail())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
const uint64_t block_size = 1024 * 1024 * 1024; // 1回のwriteで書き出す要素の数(1GB)
|
const uint64_t block_size = 1024 * 1024 * 1024; // number of elements to write in one write (1GB)
|
||||||
for (uint64_t pos = 0; pos < size; pos += block_size)
|
for (uint64_t pos = 0; pos < size; pos += block_size)
|
||||||
{
|
{
|
||||||
// 今回書き出すメモリサイズ
|
// Memory size to write this time
|
||||||
uint64_t write_size = (pos + block_size < size) ? block_size : (size - pos);
|
uint64_t write_size = (pos + block_size < size) ? block_size : (size - pos);
|
||||||
fs.write((char*)ptr + pos, write_size);
|
fs.write((char*)ptr + pos, write_size);
|
||||||
//cout << ".";
|
//cout << ".";
|
||||||
|
@ -629,17 +629,17 @@ int write_memory_to_file(std::string filename, void* ptr, uint64_t size)
|
||||||
// mkdir wrapper
|
// mkdir wrapper
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
|
|
||||||
// カレントフォルダ相対で指定する。成功すれば0、失敗すれば非0が返る。
|
// Specify relative to the current folder. Returns 0 on success, non-zero on failure.
|
||||||
// フォルダを作成する。日本語は使っていないものとする。
|
// Create a folder. Japanese is not used.
|
||||||
// どうもmsys2環境下のgccだと_wmkdir()だとフォルダの作成に失敗する。原因不明。
|
// In case of gcc under msys2 environment, folder creation fails with _wmkdir(). Cause unknown.
|
||||||
// 仕方ないので_mkdir()を用いる。
|
// Use _mkdir() because there is no help for it.
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// Windows用
|
// for Windows
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#include <codecvt> // mkdirするのにwstringが欲しいのでこれが必要
|
#include <codecvt> // I need this because I want wstring to mkdir
|
||||||
#include <locale> // wstring_convertにこれが必要。
|
#include <locale> // This is required for wstring_convert.
|
||||||
|
|
||||||
namespace Dependency {
|
namespace Dependency {
|
||||||
int mkdir(std::string dir_name)
|
int mkdir(std::string dir_name)
|
||||||
|
@ -663,9 +663,9 @@ namespace Dependency {
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
|
|
||||||
// linux環境において、この_LINUXというシンボルはmakefileにて定義されるものとする。
|
// In the linux environment, this symbol _LINUX is defined in the makefile.
|
||||||
|
|
||||||
// Linux用のmkdir実装。
|
// mkdir implementation for Linux.
|
||||||
#include "sys/stat.h"
|
#include "sys/stat.h"
|
||||||
|
|
||||||
namespace Dependency {
|
namespace Dependency {
|
||||||
|
@ -676,8 +676,8 @@ namespace Dependency {
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Linux環境かどうかを判定するためにはmakefileを分けないといけなくなってくるな..
|
// In order to judge whether it is a Linux environment, we have to divide the makefile..
|
||||||
// linuxでフォルダ掘る機能は、とりあえずナシでいいや..。評価関数ファイルの保存にしか使ってないし…。
|
// The function to dig a folder on linux is good for the time being... Only used to save the evaluation function file...
|
||||||
|
|
||||||
namespace Dependency {
|
namespace Dependency {
|
||||||
int mkdir(std::string dir_name)
|
int mkdir(std::string dir_name)
|
||||||
|
|
82
src/misc.h
82
src/misc.h
|
@ -115,15 +115,14 @@ public:
|
||||||
/// Output values only have 1/8th of their bits set on average.
|
/// Output values only have 1/8th of their bits set on average.
|
||||||
template<typename T> T sparse_rand()
|
template<typename T> T sparse_rand()
|
||||||
{ return T(rand64() & rand64() & rand64()); }
|
{ return T(rand64() & rand64() & rand64()); }
|
||||||
|
// Returns a random number from 0 to n-1. (Not uniform distribution, but this is enough in reality)
|
||||||
// 0からn-1までの乱数を返す。(一様分布ではないが現実的にはこれで十分)
|
|
||||||
uint64_t rand(uint64_t n) { return rand<uint64_t>() % n; }
|
uint64_t rand(uint64_t n) { return rand<uint64_t>() % n; }
|
||||||
|
|
||||||
// 内部で使用している乱数seedを返す。
|
// Return the random seed used internally.
|
||||||
uint64_t get_seed() const { return s; }
|
uint64_t get_seed() const { return s; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// 乱数のseedを表示する。(デバッグ用)
|
// Display a random seed. (For debugging)
|
||||||
inline std::ostream& operator<<(std::ostream& os, PRNG& prng)
|
inline std::ostream& operator<<(std::ostream& os, PRNG& prng)
|
||||||
{
|
{
|
||||||
os << "PRNG::seed = " << std::hex << prng.get_seed() << std::dec;
|
os << "PRNG::seed = " << std::hex << prng.get_seed() << std::dec;
|
||||||
|
@ -153,54 +152,53 @@ inline uint64_t mul_hi64(uint64_t a, uint64_t b) {
|
||||||
namespace WinProcGroup {
|
namespace WinProcGroup {
|
||||||
void bindThisThread(size_t idx);
|
void bindThisThread(size_t idx);
|
||||||
}
|
}
|
||||||
|
// sleep for the specified number of milliseconds.
|
||||||
// 指定されたミリ秒だけsleepする。
|
|
||||||
extern void sleep(int ms);
|
extern void sleep(int ms);
|
||||||
|
|
||||||
// 現在時刻を文字列化したもを返す。(評価関数の学習時などにログ出力のために用いる)
|
// Returns a string that represents the current time. (Used for log output when learning evaluation function)
|
||||||
std::string now_string();
|
std::string now_string();
|
||||||
|
|
||||||
// 途中での終了処理のためのwrapper
|
// wrapper for end processing on the way
|
||||||
static void my_exit()
|
static void my_exit()
|
||||||
{
|
{
|
||||||
sleep(3000); // エラーメッセージが出力される前に終了するのはまずいのでwaitを入れておく。
|
sleep(3000); // It is bad to finish before the error message is output, so put wait.
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// msys2、Windows Subsystem for Linuxなどのgcc/clangでコンパイルした場合、
|
// When compiled with gcc/clang such as msys2, Windows Subsystem for Linux,
|
||||||
// C++のstd::ifstreamで::read()は、一発で2GB以上のファイルの読み書きが出来ないのでそのためのwrapperである。
|
// In C++ std::ifstream, ::read() is a wrapper for that because it is not possible to read and write files larger than 2GB in one shot.
|
||||||
//
|
//
|
||||||
// read_file_to_memory()の引数のcallback_funcは、ファイルがオープン出来た時点でそのファイルサイズを引数として
|
// callback_func of the argument of read_file_to_memory() uses the file size as an argument when the file can be opened
|
||||||
// callbackされるので、バッファを確保して、その先頭ポインタを返す関数を渡すと、そこに読み込んでくれる。
|
// It will be called back, so if you allocate a buffer and pass a function that returns the first pointer, it will be read there.
|
||||||
// これらの関数は、ファイルが見つからないときなどエラーの際には非0を返す。
|
// These functions return non-zero on error, such as when the file cannot be found.
|
||||||
//
|
//
|
||||||
// また、callbackされた関数のなかでバッファが確保できなかった場合や、想定していたファイルサイズと異なった場合は、
|
// Also, if the buffer cannot be allocated in the callback function or if the file size is different from the expected file size,
|
||||||
// nullptrを返せば良い。このとき、read_file_to_memory()は、読み込みを中断し、エラーリターンする。
|
// Return nullptr. At this time, read_file_to_memory() interrupts reading and returns with an error.
|
||||||
|
|
||||||
int read_file_to_memory(std::string filename, std::function<void* (uint64_t)> callback_func);
|
int read_file_to_memory(std::string filename, std::function<void* (uint64_t)> callback_func);
|
||||||
int write_memory_to_file(std::string filename, void* ptr, uint64_t size);
|
int write_memory_to_file(std::string filename, void* ptr, uint64_t size);
|
||||||
|
|
||||||
// --------------------
|
// --------------------
|
||||||
// PRNGのasync版
|
// async version of PRNG
|
||||||
// --------------------
|
// --------------------
|
||||||
|
|
||||||
// PRNGのasync版
|
// async version of PRNG
|
||||||
struct AsyncPRNG
|
struct AsyncPRNG
|
||||||
{
|
{
|
||||||
AsyncPRNG(uint64_t seed) : prng(seed) { assert(seed); }
|
AsyncPRNG(uint64_t seed) : prng(seed) { assert(seed); }
|
||||||
// [ASYNC] 乱数を一つ取り出す。
|
// [ASYNC] Extract one random number.
|
||||||
template<typename T> T rand() {
|
template<typename T> T rand() {
|
||||||
std::unique_lock<std::mutex> lk(mutex);
|
std::unique_lock<std::mutex> lk(mutex);
|
||||||
return prng.rand<T>();
|
return prng.rand<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// [ASYNC] 0からn-1までの乱数を返す。(一様分布ではないが現実的にはこれで十分)
|
// [ASYNC] Returns a random number from 0 to n-1. (Not uniform distribution, but this is enough in reality)
|
||||||
uint64_t rand(uint64_t n) {
|
uint64_t rand(uint64_t n) {
|
||||||
std::unique_lock<std::mutex> lk(mutex);
|
std::unique_lock<std::mutex> lk(mutex);
|
||||||
return prng.rand(n);
|
return prng.rand(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 内部で使用している乱数seedを返す。
|
// Return the random seed used internally.
|
||||||
uint64_t get_seed() const { return prng.get_seed(); }
|
uint64_t get_seed() const { return prng.get_seed(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -208,7 +206,7 @@ protected:
|
||||||
PRNG prng;
|
PRNG prng;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 乱数のseedを表示する。(デバッグ用)
|
// Display a random seed. (For debugging)
|
||||||
inline std::ostream& operator<<(std::ostream& os, AsyncPRNG& prng)
|
inline std::ostream& operator<<(std::ostream& os, AsyncPRNG& prng)
|
||||||
{
|
{
|
||||||
os << "AsyncPRNG::seed = " << std::hex << prng.get_seed() << std::dec;
|
os << "AsyncPRNG::seed = " << std::hex << prng.get_seed() << std::dec;
|
||||||
|
@ -219,18 +217,18 @@ inline std::ostream& operator<<(std::ostream& os, AsyncPRNG& prng)
|
||||||
// Math
|
// Math
|
||||||
// --------------------
|
// --------------------
|
||||||
|
|
||||||
// 進行度の計算や学習で用いる数学的な関数
|
// Mathematical function used for progress calculation and learning
|
||||||
namespace Math {
|
namespace Math {
|
||||||
// シグモイド関数
|
// Sigmoid function
|
||||||
// = 1.0 / (1.0 + std::exp(-x))
|
// = 1.0 / (1.0 + std::exp(-x))
|
||||||
double sigmoid(double x);
|
double sigmoid(double x);
|
||||||
|
|
||||||
// シグモイド関数の微分
|
// Differentiation of sigmoid function
|
||||||
// = sigmoid(x) * (1.0-sigmoid(x))
|
// = sigmoid(x) * (1.0-sigmoid(x))
|
||||||
double dsigmoid(double x);
|
double dsigmoid(double x);
|
||||||
|
|
||||||
// vを[lo,hi]の間に収まるようにクリップする。
|
// Clip v so that it fits between [lo,hi].
|
||||||
// ※ Stockfishではこの関数、bitboard.hに書いてある。
|
// * In Stockfish, this function is written in bitboard.h.
|
||||||
template<class T> constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
|
template<class T> constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
|
||||||
return v < lo ? lo : v > hi ? hi : v;
|
return v < lo ? lo : v > hi ? hi : v;
|
||||||
}
|
}
|
||||||
|
@ -241,12 +239,12 @@ namespace Math {
|
||||||
// Path
|
// Path
|
||||||
// --------------------
|
// --------------------
|
||||||
|
|
||||||
// C#にあるPathクラス的なもの。ファイル名の操作。
|
// Something like Path class in C#. File name manipulation.
|
||||||
// C#のメソッド名に合わせておく。
|
// Match with the C# method name.
|
||||||
struct Path
|
struct Path
|
||||||
{
|
{
|
||||||
// path名とファイル名を結合して、それを返す。
|
// Combine the path name and file name and return it.
|
||||||
// folder名のほうは空文字列でないときに、末尾に'/'か'\\'がなければそれを付与する。
|
// If the folder name is not an empty string, append it if there is no'/' or'\\' at the end.
|
||||||
static std::string Combine(const std::string& folder, const std::string& filename)
|
static std::string Combine(const std::string& folder, const std::string& filename)
|
||||||
{
|
{
|
||||||
if (folder.length() >= 1 && *folder.rbegin() != '/' && *folder.rbegin() != '\\')
|
if (folder.length() >= 1 && *folder.rbegin() != '/' && *folder.rbegin() != '\\')
|
||||||
|
@ -255,10 +253,10 @@ struct Path
|
||||||
return folder + filename;
|
return folder + filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
// full path表現から、(フォルダ名を除いた)ファイル名の部分を取得する。
|
// Get the file name part (excluding the folder name) from the full path expression.
|
||||||
static std::string GetFileName(const std::string& path)
|
static std::string GetFileName(const std::string& path)
|
||||||
{
|
{
|
||||||
// "\"か"/"か、どちらを使ってあるかはわからない。
|
// I don't know which "\" or "/" is used.
|
||||||
auto path_index1 = path.find_last_of("\\") + 1;
|
auto path_index1 = path.find_last_of("\\") + 1;
|
||||||
auto path_index2 = path.find_last_of("/") + 1;
|
auto path_index2 = path.find_last_of("/") + 1;
|
||||||
auto path_index = std::max(path_index1, path_index2);
|
auto path_index = std::max(path_index1, path_index2);
|
||||||
|
@ -270,8 +268,8 @@ struct Path
|
||||||
extern void* aligned_malloc(size_t size, size_t align);
|
extern void* aligned_malloc(size_t size, size_t align);
|
||||||
static void aligned_free(void* ptr) { _mm_free(ptr); }
|
static void aligned_free(void* ptr) { _mm_free(ptr); }
|
||||||
|
|
||||||
// alignasを指定しているのにnewのときに無視される&STLのコンテナがメモリ確保するときに無視するので、
|
// It is ignored when new even though alignas is specified & because it is ignored when the STL container allocates memory,
|
||||||
// そのために用いるカスタムアロケーター。
|
// A custom allocator used for that.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class AlignedAllocator {
|
class AlignedAllocator {
|
||||||
public:
|
public:
|
||||||
|
@ -293,15 +291,15 @@ public:
|
||||||
|
|
||||||
namespace Dependency
|
namespace Dependency
|
||||||
{
|
{
|
||||||
// Linux環境ではgetline()したときにテキストファイルが'\r\n'だと
|
// In the Linux environment, if you getline() the text file is'\r\n'
|
||||||
// '\r'が末尾に残るのでこの'\r'を除去するためにwrapperを書く。
|
// Since'\r' remains at the end, write a wrapper to remove this'\r'.
|
||||||
// そのため、fstreamに対してgetline()を呼び出すときは、
|
// So when calling getline() on fstream,
|
||||||
// std::getline()ではなく単にgetline()と書いて、この関数を使うべき。
|
// just write getline() instead of std::getline() and use this function.
|
||||||
extern bool getline(std::ifstream& fs, std::string& s);
|
extern bool getline(std::ifstream& fs, std::string& s);
|
||||||
|
|
||||||
// フォルダを作成する。
|
// Create a folder.
|
||||||
// カレントフォルダ相対で指定する。dir_nameに日本語は使っていないものとする。
|
// Specify relative to the current folder. Japanese is not used for dir_name.
|
||||||
// 成功すれば0、失敗すれば非0が返る。
|
// Returns 0 on success, non-zero on failure.
|
||||||
extern int mkdir(std::string dir_name);
|
extern int mkdir(std::string dir_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -209,11 +209,11 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
|
||||||
st = si;
|
st = si;
|
||||||
|
|
||||||
#if defined(EVAL_NNUE)
|
#if defined(EVAL_NNUE)
|
||||||
// evalListのclear。上でmemsetでゼロクリアしたときにクリアされているが…。
|
// clear evalList. It is cleared when memset is cleared to zero above...
|
||||||
evalList.clear();
|
evalList.clear();
|
||||||
|
|
||||||
// PieceListを更新する上で、どの駒がどこにあるかを設定しなければならないが、
|
// In updating the PieceList, we have to set which piece is where,
|
||||||
// それぞれの駒をどこまで使ったかのカウンター
|
// A counter of how much each piece has been used
|
||||||
PieceNumber next_piece_number = PIECE_NUMBER_ZERO;
|
PieceNumber next_piece_number = PIECE_NUMBER_ZERO;
|
||||||
#endif // defined(EVAL_NNUE)
|
#endif // defined(EVAL_NNUE)
|
||||||
|
|
||||||
|
@ -235,10 +235,10 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
|
||||||
|
|
||||||
#if defined(EVAL_NNUE)
|
#if defined(EVAL_NNUE)
|
||||||
PieceNumber piece_no =
|
PieceNumber piece_no =
|
||||||
(idx == W_KING) ? PIECE_NUMBER_WKING : // 先手玉
|
(idx == W_KING) ?PIECE_NUMBER_WKING : //
|
||||||
(idx == B_KING) ? PIECE_NUMBER_BKING : // 後手玉
|
(idx == B_KING) ?PIECE_NUMBER_BKING : // back ball
|
||||||
next_piece_number++; // それ以外
|
next_piece_number++; // otherwise
|
||||||
evalList.put_piece(piece_no, sq, pc); // sqの升にpcの駒を配置する
|
evalList.put_piece(piece_no, sq, pc); // Place the pc piece in the sq box
|
||||||
#endif // defined(EVAL_NNUE)
|
#endif // defined(EVAL_NNUE)
|
||||||
|
|
||||||
++sq;
|
++sq;
|
||||||
|
@ -823,7 +823,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
|
||||||
st->rule50 = 0;
|
st->rule50 = 0;
|
||||||
|
|
||||||
#if defined(EVAL_NNUE)
|
#if defined(EVAL_NNUE)
|
||||||
dp.dirty_num = 2; // 動いた駒は2個
|
dp.dirty_num = 2; // 2 pieces moved
|
||||||
|
|
||||||
dp.pieceNo[1] = piece_no1;
|
dp.pieceNo[1] = piece_no1;
|
||||||
dp.changed_piece[1].old_piece = evalList.bona_piece(piece_no1);
|
dp.changed_piece[1].old_piece = evalList.bona_piece(piece_no1);
|
||||||
|
@ -1054,8 +1054,8 @@ template<bool Do>
|
||||||
void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto) {
|
void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto) {
|
||||||
#if defined(EVAL_NNUE)
|
#if defined(EVAL_NNUE)
|
||||||
auto& dp = st->dirtyPiece;
|
auto& dp = st->dirtyPiece;
|
||||||
// 差分計算のために移動した駒をStateInfoに記録しておく。
|
// Record the moved pieces in StateInfo for difference calculation.
|
||||||
dp.dirty_num = 2; // 動いた駒は2個
|
dp.dirty_num = 2; // 2 pieces moved
|
||||||
|
|
||||||
PieceNumber piece_no0;
|
PieceNumber piece_no0;
|
||||||
PieceNumber piece_no1;
|
PieceNumber piece_no1;
|
||||||
|
|
|
@ -63,7 +63,7 @@ struct StateInfo {
|
||||||
#if defined(EVAL_NNUE)
|
#if defined(EVAL_NNUE)
|
||||||
Eval::NNUE::Accumulator accumulator;
|
Eval::NNUE::Accumulator accumulator;
|
||||||
|
|
||||||
// 評価値の差分計算の管理用
|
// For management of evaluation value difference calculation
|
||||||
Eval::DirtyPiece dirtyPiece;
|
Eval::DirtyPiece dirtyPiece;
|
||||||
#endif // defined(EVAL_NNUE)
|
#endif // defined(EVAL_NNUE)
|
||||||
};
|
};
|
||||||
|
@ -82,7 +82,7 @@ typedef std::unique_ptr<std::deque<StateInfo>> StateListPtr;
|
||||||
/// traversing the search tree.
|
/// traversing the search tree.
|
||||||
class Thread;
|
class Thread;
|
||||||
|
|
||||||
// packされたsfen
|
// packed sfen
|
||||||
struct PackedSfen { uint8_t data[32]; };
|
struct PackedSfen { uint8_t data[32]; };
|
||||||
|
|
||||||
class Position {
|
class Position {
|
||||||
|
@ -181,31 +181,31 @@ public:
|
||||||
#if defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
#if defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
||||||
// --- StateInfo
|
// --- StateInfo
|
||||||
|
|
||||||
// 現在の局面に対応するStateInfoを返す。
|
// Returns the StateInfo corresponding to the current situation.
|
||||||
// たとえば、state()->capturedPieceであれば、前局面で捕獲された駒が格納されている。
|
// For example, if state()->capturedPiece, the pieces captured in the previous phase are stored.
|
||||||
StateInfo* state() const { return st; }
|
StateInfo* state() const { return st; }
|
||||||
|
|
||||||
// 評価関数で使うための、どの駒番号の駒がどこにあるかなどの情報。
|
// Information such as where and which piece number is used for the evaluation function.
|
||||||
const Eval::EvalList* eval_list() const { return &evalList; }
|
const Eval::EvalList* eval_list() const { return &evalList; }
|
||||||
#endif // defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
#endif // defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
||||||
|
|
||||||
#if defined(EVAL_LEARN)
|
#if defined(EVAL_LEARN)
|
||||||
// -- sfen化ヘルパ
|
// --sfenization helper
|
||||||
|
|
||||||
// packされたsfenを得る。引数に指定したバッファに返す。
|
// Get the packed sfen. Returns to the buffer specified in the argument.
|
||||||
// gamePlyはpackに含めない。
|
// Do not include gamePly in pack.
|
||||||
void sfen_pack(PackedSfen& sfen);
|
void sfen_pack(PackedSfen& sfen);
|
||||||
|
|
||||||
// ↑sfenを経由すると遅いので直接packされたsfenをセットする関数を作った。
|
// <EFBFBD>ª It is slow to go through sfen, so I made a function to set packed sfen directly.
|
||||||
// pos.set(sfen_unpack(data),si,th); と等価。
|
// Equivalent to pos.set(sfen_unpack(data),si,th);.
|
||||||
// 渡された局面に問題があって、エラーのときは非0を返す。
|
// If there is a problem with the passed phase and there is an error, non-zero is returned.
|
||||||
// PackedSfenにgamePlyは含まないので復元できない。そこを設定したいのであれば引数で指定すること。
|
// PackedSfen does not include gamePly so it cannot be restored. If you want to set it, specify it with an argument.
|
||||||
int set_from_packed_sfen(const PackedSfen& sfen, StateInfo* si, Thread* th, bool mirror = false);
|
int set_from_packed_sfen(const PackedSfen& sfen, StateInfo* si, Thread* th, bool mirror = false);
|
||||||
|
|
||||||
// 盤面と手駒、手番を与えて、そのsfenを返す。
|
// Give the board, hand piece, and turn, and return the sfen.
|
||||||
//static std::string sfen_from_rawdata(Piece board[81], Hand hands[2], Color turn, int gamePly);
|
//static std::string sfen_from_rawdata(Piece board[81], Hand hands[2], Color turn, int gamePly);
|
||||||
|
|
||||||
// c側の玉の位置を返す。
|
// Returns the position of the ball on the c side.
|
||||||
Square king_square(Color c) const { return pieceList[make_piece(c, KING)][0]; }
|
Square king_square(Color c) const { return pieceList[make_piece(c, KING)][0]; }
|
||||||
#endif // EVAL_LEARN
|
#endif // EVAL_LEARN
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ private:
|
||||||
void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto);
|
void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto);
|
||||||
|
|
||||||
#if defined(EVAL_NNUE)
|
#if defined(EVAL_NNUE)
|
||||||
// 盤上のsqの升にある駒のPieceNumberを返す。
|
// Returns the PieceNumber of the piece in the sq box on the board.
|
||||||
PieceNumber piece_no_of(Square sq) const;
|
PieceNumber piece_no_of(Square sq) const;
|
||||||
#endif // defined(EVAL_NNUE)
|
#endif // defined(EVAL_NNUE)
|
||||||
|
|
||||||
|
@ -245,7 +245,7 @@ private:
|
||||||
bool chess960;
|
bool chess960;
|
||||||
|
|
||||||
#if defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
#if defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
||||||
// 評価関数で用いる駒のリスト
|
// List of pieces used in the evaluation function
|
||||||
Eval::EvalList evalList;
|
Eval::EvalList evalList;
|
||||||
#endif // defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
#endif // defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
||||||
};
|
};
|
||||||
|
|
143
src/search.cpp
143
src/search.cpp
|
@ -1938,60 +1938,61 @@ void Tablebases::rank_root_moves(Position& pos, Search::RootMoves& rootMoves) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- 学習時に用いる、depth固定探索などの関数を外部に対して公開
|
// --- expose the functions such as fixed depth search used for learning to the outside
|
||||||
|
|
||||||
#if defined (EVAL_LEARN)
|
#if defined (EVAL_LEARN)
|
||||||
|
|
||||||
namespace Learner
|
namespace Learner
|
||||||
{
|
{
|
||||||
// 学習用に、1つのスレッドからsearch,qsearch()を呼び出せるようなスタブを用意する。
|
// For learning, prepare a stub that can call search,qsearch() from one thread.
|
||||||
// いまにして思えば、AperyのようにSearcherを持ってスレッドごとに置換表などを用意するほうが
|
// From now on, it is better to have a Searcher and prepare a substitution table for each thread like Apery.
|
||||||
// 良かったかも知れない。
|
// It might have been good.
|
||||||
|
|
||||||
// 学習のための初期化。
|
// Initialization for learning.
|
||||||
// Learner::search(),Learner::qsearch()から呼び出される。
|
// Called from Learner::search(),Learner::qsearch().
|
||||||
void init_for_search(Position& pos, Stack* ss)
|
void init_for_search(Position& pos, Stack* ss)
|
||||||
{
|
{
|
||||||
|
|
||||||
// RootNodeはss->ply == 0がその条件。
|
// RootNode requires ss->ply == 0.
|
||||||
// ゼロクリアするので、ss->ply == 0となるので大丈夫…。
|
// Because it clears to zero, ss->ply == 0, so it's okay...
|
||||||
|
|
||||||
std::memset(ss - 7, 0, 10 * sizeof(Stack));
|
std::memset(ss - 7, 0, 10 * sizeof(Stack));
|
||||||
|
|
||||||
// Search::Limitsに関して
|
// About Search::Limits
|
||||||
// このメンバー変数はglobalなので他のスレッドに影響を及ぼすので気をつけること。
|
// Be careful because this member variable is global and affects other threads.
|
||||||
{
|
{
|
||||||
auto& limits = Search::Limits;
|
auto& limits = Search::Limits;
|
||||||
|
|
||||||
// 探索を"go infinite"コマンド相当にする。(time managementされると困るため)
|
// Make the search equivalent to the "go infinite" command. (Because it is troublesome if time management is done)
|
||||||
limits.infinite = true;
|
limits.infinite = true;
|
||||||
|
|
||||||
// PVを表示されると邪魔なので消しておく。
|
// Since PV is an obstacle when displayed, erase it.
|
||||||
limits.silent = true;
|
limits.silent = true;
|
||||||
|
|
||||||
// これを用いると各スレッドのnodesを積算したものと比較されてしまう。ゆえに使用しない。
|
// If you use this, it will be compared with the accumulated nodes of each thread. Therefore, do not use it.
|
||||||
limits.nodes = 0;
|
limits.nodes = 0;
|
||||||
|
|
||||||
// depthも、Learner::search()の引数として渡されたもので処理する。
|
// depth is also processed by the one passed as an argument of Learner::search().
|
||||||
limits.depth = 0;
|
limits.depth = 0;
|
||||||
|
|
||||||
// 引き分け付近の手数で引き分けの値が返るのを防ぐために大きな値にしておく。
|
// Set a large value to prevent the draw value from being returned due to the number of moves near the draw.
|
||||||
//limits.max_game_ply = 1 << 16;
|
//limits.max_game_ply = 1 << 16;
|
||||||
|
|
||||||
// 入玉ルールも入れておかないと引き分けになって決着つきにくい。
|
// If you do not include the ball entry rule, it will be a draw and it will be difficult to settle.
|
||||||
//limits.enteringKingRule = EnteringKingRule::EKR_27_POINT;
|
//limits.enteringKingRule = EnteringKingRule::EKR_27_POINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawValueの設定
|
// Set DrawValue
|
||||||
{
|
{
|
||||||
// スレッドごとに用意してないので
|
// Because it is not prepared for each thread
|
||||||
// 他のスレッドで上書きされかねない。仕方がないが。
|
// May be overwritten by another thread. There is no help for it.
|
||||||
// どうせそうなるなら、0にすべきだと思う。
|
// If that happens, I think it should be 0.
|
||||||
//drawValueTable[REPETITION_DRAW][BLACK] = VALUE_ZERO;
|
//drawValueTable[REPETITION_DRAW][BLACK] = VALUE_ZERO;
|
||||||
//drawValueTable[REPETITION_DRAW][WHITE] = VALUE_ZERO;
|
//drawValueTable[REPETITION_DRAW][WHITE] = VALUE_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this_threadに関して。
|
// Regarding this_thread.
|
||||||
|
|
||||||
{
|
{
|
||||||
auto th = pos.this_thread();
|
auto th = pos.this_thread();
|
||||||
|
|
||||||
|
@ -1999,10 +2000,10 @@ namespace Learner
|
||||||
th->selDepth = 0;
|
th->selDepth = 0;
|
||||||
th->rootDepth = 0;
|
th->rootDepth = 0;
|
||||||
|
|
||||||
// 探索ノード数のゼロ初期化
|
// Zero initialization of the number of search nodes
|
||||||
th->nodes = 0;
|
th->nodes = 0;
|
||||||
|
|
||||||
// history類を全部クリアする。この初期化は少し時間がかかるし、探索の精度はむしろ下がるので善悪はよくわからない。
|
// Clear all history types. This initialization takes a little time, and the accuracy of the search is rather low, so the good and bad are not well understood.
|
||||||
// th->clear();
|
// th->clear();
|
||||||
|
|
||||||
int ct = int(Options["Contempt"]) * PawnValueEg / 100; // From centipawns
|
int ct = int(Options["Contempt"]) * PawnValueEg / 100; // From centipawns
|
||||||
|
@ -2023,7 +2024,7 @@ namespace Learner
|
||||||
for (int i = 7; i > 0; i--)
|
for (int i = 7; i > 0; i--)
|
||||||
(ss - i)->continuationHistory = &th->continuationHistory[0][0][NO_PIECE][0]; // Use as a sentinel
|
(ss - i)->continuationHistory = &th->continuationHistory[0][0][NO_PIECE][0]; // Use as a sentinel
|
||||||
|
|
||||||
// rootMovesの設定
|
// set rootMoves
|
||||||
auto& rootMoves = th->rootMoves;
|
auto& rootMoves = th->rootMoves;
|
||||||
|
|
||||||
rootMoves.clear();
|
rootMoves.clear();
|
||||||
|
@ -2033,47 +2034,47 @@ namespace Learner
|
||||||
assert(!rootMoves.empty());
|
assert(!rootMoves.empty());
|
||||||
|
|
||||||
//#if defined(USE_GLOBAL_OPTIONS)
|
//#if defined(USE_GLOBAL_OPTIONS)
|
||||||
// 探索スレッドごとの置換表の世代を管理しているはずなので、
|
// Since the generation of the substitution table for each search thread should be managed,
|
||||||
// 新規の探索であるから、このスレッドに対する置換表の世代を増やす。
|
// Increase the generation of the substitution table for this thread because it is a new search.
|
||||||
//TT.new_search(th->thread_id());
|
//TT.new_search(th->thread_id());
|
||||||
|
|
||||||
// ↑ここでnew_searchを呼び出すと1手前の探索結果が使えなくて損ということはあるのでは…。
|
// ↑ If you call new_search here, it may be a loss because you can't use the previous search result.
|
||||||
// ここでこれはやらずに、呼び出し側で1局ごとにTT.new_search(th->thread_id())をやるべきでは…。
|
// Do not do this here, but caller should do TT.new_search(th->thread_id()) for each station ...
|
||||||
|
|
||||||
// → 同一の終局図に至るのを回避したいので、教師生成時には置換表は全スレ共通で使うようにする。
|
// →Because we want to avoid reaching the same final diagram, use the substitution table commonly for all threads when generating teachers.
|
||||||
//#endif
|
//#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 読み筋と評価値のペア。Learner::search(),Learner::qsearch()が返す。
|
// A pair of reader and evaluation value. Returned by Learner::search(),Learner::qsearch().
|
||||||
typedef std::pair<Value, std::vector<Move> > ValueAndPV;
|
typedef std::pair<Value, std::vector<Move> > ValueAndPV;
|
||||||
|
|
||||||
// 静止探索。
|
// Stationary search.
|
||||||
//
|
//
|
||||||
// 前提条件) pos.set_this_thread(Threads[thread_id])で探索スレッドが設定されていること。
|
// Precondition) Search thread is set by pos.set_this_thread(Threads[thread_id]).
|
||||||
// また、Threads.stopが来ると探索を中断してしまうので、そのときのPVは正しくない。
|
// Also, when Threads.stop arrives, the search is interrupted, so the PV at that time is not correct.
|
||||||
// search()から戻ったあと、Threads.stop == trueなら、その探索結果を用いてはならない。
|
// After returning from search(), if Threads.stop == true, do not use the search result.
|
||||||
// あと、呼び出し前は、Threads.stop == falseの状態で呼び出さないと、探索を中断して返ってしまうので注意。
|
// Also, note that before calling, if you do not call it with Threads.stop == false, the search will be interrupted and it will return.
|
||||||
//
|
//
|
||||||
// 詰まされている場合は、PV配列にMOVE_RESIGNが返る。
|
// If it is clogged, MOVE_RESIGN is returned in the PV array.
|
||||||
//
|
//
|
||||||
// 引数でalpha,betaを指定できるようにしていたが、これがその窓で探索したときの結果を
|
//Although it was possible to specify alpha and beta with arguments, this will show the result when searching in that window
|
||||||
// 置換表に書き込むので、その窓に対して枝刈りが出来るような値が書き込まれて学習のときに
|
// Because it writes to the substitution table, the value that can be pruned is written to that window when learning
|
||||||
// 悪い影響があるので、窓の範囲を指定できるようにするのをやめることにした。
|
// As it has a bad effect, I decided to stop allowing the window range to be specified.
|
||||||
ValueAndPV qsearch(Position& pos)
|
ValueAndPV qsearch(Position& pos)
|
||||||
{
|
{
|
||||||
Stack stack[MAX_PLY + 10], * ss = stack + 7;
|
Stack stack[MAX_PLY + 10], * ss = stack + 7;
|
||||||
Move pv[MAX_PLY + 1];
|
Move pv[MAX_PLY + 1];
|
||||||
|
|
||||||
init_for_search(pos, ss);
|
init_for_search(pos, ss);
|
||||||
ss->pv = pv; // とりあえずダミーでどこかバッファがないといけない。
|
ss->pv = pv; // For the time being, it must be a dummy and somewhere with a buffer.
|
||||||
|
|
||||||
if (pos.is_draw(0)) {
|
if (pos.is_draw(0)) {
|
||||||
// Return draw value if draw.
|
// Return draw value if draw.
|
||||||
return { VALUE_DRAW, {} };
|
return { VALUE_DRAW, {} };
|
||||||
}
|
}
|
||||||
|
|
||||||
// 詰まされているのか
|
// Is it stuck?
|
||||||
if (MoveList<LEGAL>(pos).size() == 0)
|
if (MoveList<LEGAL>(pos).size() == 0)
|
||||||
{
|
{
|
||||||
// Return the mated value if checkmated.
|
// Return the mated value if checkmated.
|
||||||
|
@ -2082,7 +2083,7 @@ namespace Learner
|
||||||
|
|
||||||
auto bestValue = ::qsearch<PV>(pos, ss, -VALUE_INFINITE, VALUE_INFINITE, 0);
|
auto bestValue = ::qsearch<PV>(pos, ss, -VALUE_INFINITE, VALUE_INFINITE, 0);
|
||||||
|
|
||||||
// 得られたPVを返す。
|
// Returns the PV obtained.
|
||||||
std::vector<Move> pvs;
|
std::vector<Move> pvs;
|
||||||
for (Move* p = &ss->pv[0]; is_ok(*p); ++p)
|
for (Move* p = &ss->pv[0]; is_ok(*p); ++p)
|
||||||
pvs.push_back(*p);
|
pvs.push_back(*p);
|
||||||
|
@ -2090,21 +2091,21 @@ namespace Learner
|
||||||
return ValueAndPV(bestValue, pvs);
|
return ValueAndPV(bestValue, pvs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通常探索。深さdepth(整数で指定)。
|
// Normal search. Depth depth (specified as an integer).
|
||||||
// 3手読み時のスコアが欲しいなら、
|
// 3 If you want a score for hand reading,
|
||||||
// auto v = search(pos,3);
|
// auto v = search(pos,3);
|
||||||
// のようにすべし。
|
// Do something like
|
||||||
// v.firstに評価値、v.secondにPVが得られる。
|
// Evaluation value is obtained in v.first and PV is obtained in v.second.
|
||||||
// multi pvが有効のときは、pos.this_thread()->rootMoves[N].pvにそのPV(読み筋)の配列が得られる。
|
// When multi pv is enabled, you can get the PV (reading line) array in pos.this_thread()->rootMoves[N].pv.
|
||||||
// multi pvの指定はこの関数の引数multiPVで行なう。(Options["MultiPV"]の値は無視される)
|
// Specify multi pv with the argument multiPV of this function. (The value of Options["MultiPV"] is ignored)
|
||||||
//
|
//
|
||||||
// rootでの宣言勝ち判定はしないので(扱いが面倒なので)、ここでは行わない。
|
// Declaration win judgment is not done as root (because it is troublesome to handle), so it is not done here.
|
||||||
// 呼び出し側で処理すること。
|
// Handle it by the caller.
|
||||||
//
|
//
|
||||||
// 前提条件) pos.set_this_thread(Threads[thread_id])で探索スレッドが設定されていること。
|
// Precondition) Search thread is set by pos.set_this_thread(Threads[thread_id]).
|
||||||
// また、Threads.stopが来ると探索を中断してしまうので、そのときのPVは正しくない。
|
// Also, when Threads.stop arrives, the search is interrupted, so the PV at that time is not correct.
|
||||||
// search()から戻ったあと、Threads.stop == trueなら、その探索結果を用いてはならない。
|
// After returning from search(), if Threads.stop == true, do not use the search result.
|
||||||
// あと、呼び出し前は、Threads.stop == falseの状態で呼び出さないと、探索を中断して返ってしまうので注意。
|
// Also, note that before calling, if you do not call it with Threads.stop == false, the search will be interrupted and it will return.
|
||||||
|
|
||||||
ValueAndPV search(Position& pos, int depth_, size_t multiPV /* = 1 */, uint64_t nodesLimit /* = 0 */)
|
ValueAndPV search(Position& pos, int depth_, size_t multiPV /* = 1 */, uint64_t nodesLimit /* = 0 */)
|
||||||
{
|
{
|
||||||
|
@ -2122,9 +2123,9 @@ namespace Learner
|
||||||
|
|
||||||
init_for_search(pos, ss);
|
init_for_search(pos, ss);
|
||||||
|
|
||||||
ss->pv = pv; // とりあえずダミーでどこかバッファがないといけない。
|
ss->pv = pv; // For the time being, it must be a dummy and somewhere with a buffer.
|
||||||
|
|
||||||
// this_threadに関連する変数の初期化
|
// Initialize the variables related to this_thread
|
||||||
auto th = pos.this_thread();
|
auto th = pos.this_thread();
|
||||||
auto& rootDepth = th->rootDepth;
|
auto& rootDepth = th->rootDepth;
|
||||||
auto& pvIdx = th->pvIdx;
|
auto& pvIdx = th->pvIdx;
|
||||||
|
@ -2133,13 +2134,13 @@ namespace Learner
|
||||||
auto& completedDepth = th->completedDepth;
|
auto& completedDepth = th->completedDepth;
|
||||||
auto& selDepth = th->selDepth;
|
auto& selDepth = th->selDepth;
|
||||||
|
|
||||||
// bestmoveとしてしこの局面の上位N個を探索する機能
|
// A function to search the top N of this stage as best move
|
||||||
//size_t multiPV = Options["MultiPV"];
|
//size_t multiPV = Options["MultiPV"];
|
||||||
|
|
||||||
// この局面での指し手の数を上回ってはいけない
|
// Do not exceed the number of moves in this situation
|
||||||
multiPV = std::min(multiPV, rootMoves.size());
|
multiPV = std::min(multiPV, rootMoves.size());
|
||||||
|
|
||||||
// ノード制限にMultiPVの値を掛けておかないと、depth固定、MultiPVありにしたときに1つの候補手に同じnodeだけ思考したことにならない。
|
// If you do not multiply the node limit by the value of MultiPV, you will not be thinking about the same node for one candidate hand when you fix the depth and have MultiPV.
|
||||||
nodesLimit *= multiPV;
|
nodesLimit *= multiPV;
|
||||||
|
|
||||||
Value alpha = -VALUE_INFINITE;
|
Value alpha = -VALUE_INFINITE;
|
||||||
|
@ -2148,9 +2149,9 @@ namespace Learner
|
||||||
Value bestValue = -VALUE_INFINITE;
|
Value bestValue = -VALUE_INFINITE;
|
||||||
|
|
||||||
while ((rootDepth += 1) <= depth
|
while ((rootDepth += 1) <= depth
|
||||||
// node制限を超えた場合もこのループを抜ける
|
// exit this loop even if the node limit is exceeded
|
||||||
// 探索ノード数は、この関数の引数で渡されている。
|
// The number of search nodes is passed in the argument of this function.
|
||||||
&& !(nodesLimit /*node制限あり*/ && th->nodes.load(std::memory_order_relaxed) >= nodesLimit)
|
&& !(nodesLimit /* limited nodes */ && th->nodes.load(std::memory_order_relaxed) >= nodesLimit)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
for (RootMove& rm : rootMoves)
|
for (RootMove& rm : rootMoves)
|
||||||
|
@ -2170,10 +2171,10 @@ namespace Learner
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// それぞれのdepthとPV lineに対するUSI infoで出力するselDepth
|
// selDepth output with USI info for each depth and PV line
|
||||||
selDepth = 0;
|
selDepth = 0;
|
||||||
|
|
||||||
// depth 5以上においてはaspiration searchに切り替える。
|
// Switch to aspiration search for depth 5 and above.
|
||||||
if (rootDepth >= 5 * 1)
|
if (rootDepth >= 5 * 1)
|
||||||
{
|
{
|
||||||
delta = Value(20);
|
delta = Value(20);
|
||||||
|
@ -2194,8 +2195,8 @@ namespace Learner
|
||||||
stable_sort(rootMoves.begin() + pvIdx, rootMoves.end());
|
stable_sort(rootMoves.begin() + pvIdx, rootMoves.end());
|
||||||
//my_stable_sort(pos.this_thread()->thread_id(),&rootMoves[0] + pvIdx, rootMoves.size() - pvIdx);
|
//my_stable_sort(pos.this_thread()->thread_id(),&rootMoves[0] + pvIdx, rootMoves.size() - pvIdx);
|
||||||
|
|
||||||
// fail low/highに対してaspiration windowを広げる。
|
// Expand aspiration window for fail low/high.
|
||||||
// ただし、引数で指定されていた値になっていたら、もうfail low/high扱いとしてbreakする。
|
// However, if it is the value specified by the argument, it will be treated as fail low/high and break.
|
||||||
if (bestValue <= alpha)
|
if (bestValue <= alpha)
|
||||||
{
|
{
|
||||||
beta = (alpha + beta) / 2;
|
beta = (alpha + beta) / 2;
|
||||||
|
@ -2217,7 +2218,7 @@ namespace Learner
|
||||||
delta += delta / 4 + 5;
|
delta += delta / 4 + 5;
|
||||||
assert(-VALUE_INFINITE <= alpha && beta <= VALUE_INFINITE);
|
assert(-VALUE_INFINITE <= alpha && beta <= VALUE_INFINITE);
|
||||||
|
|
||||||
// 暴走チェック
|
// runaway check
|
||||||
//assert(th->nodes.load(std::memory_order_relaxed) <= 1000000 );
|
//assert(th->nodes.load(std::memory_order_relaxed) <= 1000000 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2229,9 +2230,9 @@ namespace Learner
|
||||||
completedDepth = rootDepth;
|
completedDepth = rootDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
// このPV、途中でNULL_MOVEの可能性があるかも知れないので排除するためにis_ok()を通す。
|
// Pass PV_is(ok) to eliminate this PV, there may be NULL_MOVE in the middle.
|
||||||
// → PVなのでNULL_MOVEはしないことになっているはずだし、
|
// → PV should not be NULL_MOVE because it is PV
|
||||||
// MOVE_WINも突っ込まれていることはない。(いまのところ)
|
// MOVE_WIN has never been thrust. (For now)
|
||||||
for (Move move : rootMoves[0].pv)
|
for (Move move : rootMoves[0].pv)
|
||||||
{
|
{
|
||||||
if (!is_ok(move))
|
if (!is_ok(move))
|
||||||
|
@ -2241,7 +2242,7 @@ namespace Learner
|
||||||
|
|
||||||
//sync_cout << rootDepth << sync_endl;
|
//sync_cout << rootDepth << sync_endl;
|
||||||
|
|
||||||
// multiPV時を考慮して、rootMoves[0]のscoreをbestValueとして返す。
|
// Considering multiPV, the score of rootMoves[0] is returned as bestValue.
|
||||||
bestValue = rootMoves[0].score;
|
bestValue = rootMoves[0].score;
|
||||||
|
|
||||||
return ValueAndPV(bestValue, pvs);
|
return ValueAndPV(bestValue, pvs);
|
||||||
|
|
16
src/types.h
16
src/types.h
|
@ -192,7 +192,7 @@ enum Value : int {
|
||||||
|
|
||||||
MidgameLimit = 15258, EndgameLimit = 3915,
|
MidgameLimit = 15258, EndgameLimit = 3915,
|
||||||
|
|
||||||
// 評価関数の返す値の最大値(2**14ぐらいに収まっていて欲しいところだが..)
|
// Maximum value returned by the evaluation function (I want it to be around 2**14..)
|
||||||
VALUE_MAX_EVAL = 27000,
|
VALUE_MAX_EVAL = 27000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -239,7 +239,7 @@ enum Square : int {
|
||||||
SQ_NONE,
|
SQ_NONE,
|
||||||
|
|
||||||
SQUARE_ZERO = 0, SQUARE_NB = 64,
|
SQUARE_ZERO = 0, SQUARE_NB = 64,
|
||||||
SQUARE_NB_PLUS1 = SQUARE_NB + 1, // 玉がいない場合、SQUARE_NBに移動したものとして扱うため、配列をSQUARE_NB+1で確保しないといけないときがあるのでこの定数を用いる。
|
SQUARE_NB_PLUS1 = SQUARE_NB + 1, // If there are no balls, it is treated as having moved to SQUARE_NB, so it may be necessary to secure the array with SQUARE_NB+1, so this constant is used.
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Direction : int {
|
enum Direction : int {
|
||||||
|
@ -463,18 +463,18 @@ constexpr bool is_ok(Move m) {
|
||||||
return from_sq(m) != to_sq(m); // Catch MOVE_NULL and MOVE_NONE
|
return from_sq(m) != to_sq(m); // Catch MOVE_NULL and MOVE_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
// 盤面を180°回したときの升目を返す
|
// Return squares when turning the board 180<38>‹
|
||||||
constexpr Square Inv(Square sq) { return (Square)((SQUARE_NB - 1) - sq); }
|
constexpr Square Inv(Square sq) { return (Square)((SQUARE_NB - 1) - sq); }
|
||||||
|
|
||||||
// 盤面をミラーしたときの升目を返す
|
// Return squares when mirroring the board
|
||||||
constexpr Square Mir(Square sq) { return make_square(File(7 - (int)file_of(sq)), rank_of(sq)); }
|
constexpr Square Mir(Square sq) { return make_square(File(7 - (int)file_of(sq)), rank_of(sq)); }
|
||||||
|
|
||||||
#if defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
#if defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
||||||
// --------------------
|
// --------------------
|
||||||
// 駒箱
|
// piece box
|
||||||
// --------------------
|
// --------------------
|
||||||
|
|
||||||
// Positionクラスで用いる、駒リスト(どの駒がどこにあるのか)を管理するときの番号。
|
// A number used to manage the piece list (which piece is where) used in the Position class.
|
||||||
enum PieceNumber : uint8_t
|
enum PieceNumber : uint8_t
|
||||||
{
|
{
|
||||||
PIECE_NUMBER_PAWN = 0,
|
PIECE_NUMBER_PAWN = 0,
|
||||||
|
@ -484,7 +484,7 @@ enum PieceNumber : uint8_t
|
||||||
PIECE_NUMBER_QUEEN = 28,
|
PIECE_NUMBER_QUEEN = 28,
|
||||||
PIECE_NUMBER_KING = 30,
|
PIECE_NUMBER_KING = 30,
|
||||||
PIECE_NUMBER_WKING = 30,
|
PIECE_NUMBER_WKING = 30,
|
||||||
PIECE_NUMBER_BKING = 31, // 先手、後手の玉の番号が必要な場合はこっちを用いる
|
PIECE_NUMBER_BKING = 31, // Use this if you need the numbers of the first and second balls
|
||||||
PIECE_NUMBER_ZERO = 0,
|
PIECE_NUMBER_ZERO = 0,
|
||||||
PIECE_NUMBER_NB = 32,
|
PIECE_NUMBER_NB = 32,
|
||||||
};
|
};
|
||||||
|
@ -497,7 +497,7 @@ inline PieceNumber operator++(PieceNumber& d, int) {
|
||||||
}
|
}
|
||||||
inline PieceNumber& operator--(PieceNumber& d) { return d = PieceNumber(int8_t(d) - 1); }
|
inline PieceNumber& operator--(PieceNumber& d) { return d = PieceNumber(int8_t(d) - 1); }
|
||||||
|
|
||||||
// PieceNumberの整合性の検査。assert用。
|
// Piece Number integrity check. for assert.
|
||||||
constexpr bool is_ok(PieceNumber pn) { return pn < PIECE_NUMBER_NB; }
|
constexpr bool is_ok(PieceNumber pn) { return pn < PIECE_NUMBER_NB; }
|
||||||
#endif // defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
#endif // defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
||||||
|
|
||||||
|
|
62
src/uci.cpp
62
src/uci.cpp
|
@ -44,22 +44,22 @@ extern vector<string> setup_bench(const Position&, istream&);
|
||||||
// FEN string of the initial position, normal chess
|
// FEN string of the initial position, normal chess
|
||||||
const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
||||||
|
|
||||||
// 棋譜を自動生成するコマンド
|
// Command to automatically generate a game record
|
||||||
#if defined (EVAL_LEARN)
|
#if defined (EVAL_LEARN)
|
||||||
namespace Learner
|
namespace Learner
|
||||||
{
|
{
|
||||||
// 教師局面の自動生成
|
// Automatic generation of teacher position
|
||||||
void gen_sfen(Position& pos, istringstream& is);
|
void gen_sfen(Position& pos, istringstream& is);
|
||||||
|
|
||||||
// 生成した棋譜からの学習
|
// Learning from the generated game record
|
||||||
void learn(Position& pos, istringstream& is);
|
void learn(Position& pos, istringstream& is);
|
||||||
|
|
||||||
#if defined(GENSFEN2019)
|
#if defined(GENSFEN2019)
|
||||||
// 開発中の教師局面の自動生成コマンド
|
// Automatic generation command of teacher phase under development
|
||||||
void gen_sfen2019(Position& pos, istringstream& is);
|
void gen_sfen2019(Position& pos, istringstream& is);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 読み筋と評価値のペア。Learner::search(),Learner::qsearch()が返す。
|
// A pair of reader and evaluation value. Returned by Learner::search(),Learner::qsearch().
|
||||||
typedef std::pair<Value, std::vector<Move> > ValueAndPV;
|
typedef std::pair<Value, std::vector<Move> > ValueAndPV;
|
||||||
|
|
||||||
ValueAndPV qsearch(Position& pos);
|
ValueAndPV qsearch(Position& pos);
|
||||||
|
@ -71,7 +71,7 @@ namespace Learner
|
||||||
#if defined(EVAL_NNUE) && defined(ENABLE_TEST_CMD)
|
#if defined(EVAL_NNUE) && defined(ENABLE_TEST_CMD)
|
||||||
void test_cmd(Position& pos, istringstream& is)
|
void test_cmd(Position& pos, istringstream& is)
|
||||||
{
|
{
|
||||||
// 探索をするかも知れないので初期化しておく。
|
// Initialize as it may be searched.
|
||||||
is_ready();
|
is_ready();
|
||||||
|
|
||||||
std::string param;
|
std::string param;
|
||||||
|
@ -221,21 +221,21 @@ namespace {
|
||||||
<< "\nNodes/second : " << 1000 * nodes / elapsed << endl;
|
<< "\nNodes/second : " << 1000 * nodes / elapsed << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check sumを計算したとき、それを保存しておいてあとで次回以降、整合性のチェックを行なう。
|
// When you calculate check sum, save it and check the consistency later.
|
||||||
uint64_t eval_sum;
|
uint64_t eval_sum;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// is_ready_cmd()を外部から呼び出せるようにしておく。(benchコマンドなどから呼び出したいため)
|
// Make is_ready_cmd() callable from outside. (Because I want to call it from the bench command etc.)
|
||||||
// 局面は初期化されないので注意。
|
// Note that the phase is not initialized.
|
||||||
void is_ready(bool skipCorruptCheck)
|
void is_ready(bool skipCorruptCheck)
|
||||||
{
|
{
|
||||||
#if defined(EVAL_NNUE)
|
#if defined(EVAL_NNUE)
|
||||||
// "isready"を受け取ったあと、"readyok"を返すまで5秒ごとに改行を送るように修正する。(keep alive的な処理)
|
// After receiving "isready", modify so that a line feed is sent every 5 seconds until "readyok" is returned. (keep alive processing)
|
||||||
// USI2.0の仕様より。
|
// From USI 2.0 specifications.
|
||||||
// -"isready"のあとのtime out時間は、30秒程度とする。これを超えて、評価関数の初期化、hashテーブルの確保をしたい場合、
|
// -The time out time after "is ready" is about 30 seconds. Beyond this, if you want to initialize the evaluation function and secure the hash table,
|
||||||
// 思考エンジン側から定期的に何らかのメッセージ(改行可)を送るべきである。
|
// You should send some kind of message (breakable) from the thinking engine side.
|
||||||
// -ShogiGUIではすでにそうなっているので、MyShogiもそれに追随する。
|
// -Shogi GUI already does so, so MyShogi will follow along.
|
||||||
// -また、やねうら王のエンジン側は、"isready"を受け取ったあと、"readyok"を返すまで5秒ごとに改行を送るように修正する。
|
//-Also, the engine side of Yaneura King modifies it so that after "isready" is received, a line feed is sent every 5 seconds until "readyok" is returned.
|
||||||
|
|
||||||
auto ended = false;
|
auto ended = false;
|
||||||
auto th = std::thread([&ended] {
|
auto th = std::thread([&ended] {
|
||||||
|
@ -243,25 +243,25 @@ void is_ready(bool skipCorruptCheck)
|
||||||
while (!ended)
|
while (!ended)
|
||||||
{
|
{
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
if (++count >= 50 /* 5秒 */)
|
if (++count >= 50 /* 5 seconds */)
|
||||||
{
|
{
|
||||||
count = 0;
|
count = 0;
|
||||||
sync_cout << sync_endl; // 改行を送信する。
|
sync_cout << sync_endl; // Send a line break.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 評価関数の読み込みなど時間のかかるであろう処理はこのタイミングで行なう。
|
// Perform processing that may take time, such as reading the evaluation function, at this timing.
|
||||||
// 起動時に時間のかかる処理をしてしまうと将棋所がタイムアウト判定をして、思考エンジンとしての認識をリタイアしてしまう。
|
// If you do a time-consuming process at startup, Shogi place will make a timeout judgment and retire the recognition as a thinking engine.
|
||||||
if (!UCI::load_eval_finished)
|
if (!UCI::load_eval_finished)
|
||||||
{
|
{
|
||||||
// 評価関数の読み込み
|
// Read evaluation function
|
||||||
Eval::load_eval();
|
Eval::load_eval();
|
||||||
|
|
||||||
// チェックサムの計算と保存(その後のメモリ破損のチェックのため)
|
// Calculate and save checksum (to check for subsequent memory corruption)
|
||||||
eval_sum = Eval::calc_check_sum();
|
eval_sum = Eval::calc_check_sum();
|
||||||
|
|
||||||
// ソフト名の表示
|
// display soft name
|
||||||
Eval::print_softname(eval_sum);
|
Eval::print_softname(eval_sum);
|
||||||
|
|
||||||
UCI::load_eval_finished = true;
|
UCI::load_eval_finished = true;
|
||||||
|
@ -269,14 +269,14 @@ void is_ready(bool skipCorruptCheck)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// メモリが破壊されていないかを調べるためにチェックサムを毎回調べる。
|
// Check the checksum every time to see if the memory has been corrupted.
|
||||||
// 時間が少しもったいない気もするが.. 0.1秒ぐらいのことなので良しとする。
|
// It seems that the time is a little wasteful, but it is good because it is about 0.1 seconds.
|
||||||
if (!skipCorruptCheck && eval_sum != Eval::calc_check_sum())
|
if (!skipCorruptCheck && eval_sum != Eval::calc_check_sum())
|
||||||
sync_cout << "Error! : EVAL memory is corrupted" << sync_endl;
|
sync_cout << "Error! : EVAL memory is corrupted" << sync_endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// isreadyに対してはreadyokを返すまで次のコマンドが来ないことは約束されているので
|
// For isready, it is promised that the next command will not come until it returns readyok.
|
||||||
// このタイミングで各種変数の初期化もしておく。
|
// Initialize various variables at this timing.
|
||||||
|
|
||||||
TT.resize(Options["Hash"]);
|
TT.resize(Options["Hash"]);
|
||||||
Search::clear();
|
Search::clear();
|
||||||
|
@ -284,7 +284,7 @@ void is_ready(bool skipCorruptCheck)
|
||||||
|
|
||||||
Threads.stop = false;
|
Threads.stop = false;
|
||||||
|
|
||||||
// keep aliveを送信するために生成したスレッドを終了させ、待機する。
|
// Terminate the thread created to send keep alive and wait.
|
||||||
ended = true;
|
ended = true;
|
||||||
th.join();
|
th.join();
|
||||||
#endif // defined(EVAL_NNUE)
|
#endif // defined(EVAL_NNUE)
|
||||||
|
@ -294,7 +294,7 @@ void is_ready(bool skipCorruptCheck)
|
||||||
|
|
||||||
|
|
||||||
// --------------------
|
// --------------------
|
||||||
// テスト用にqsearch(),search()を直接呼ぶ
|
// Call qsearch(),search() directly for testing
|
||||||
// --------------------
|
// --------------------
|
||||||
|
|
||||||
#if defined(EVAL_LEARN)
|
#if defined(EVAL_LEARN)
|
||||||
|
@ -391,10 +391,10 @@ void UCI::loop(int argc, char* argv[]) {
|
||||||
else if (token == "learn") Learner::learn(pos, is);
|
else if (token == "learn") Learner::learn(pos, is);
|
||||||
|
|
||||||
#if defined (GENSFEN2019)
|
#if defined (GENSFEN2019)
|
||||||
// 開発中の教師局面生成コマンド
|
// Command to generate teacher phase under development
|
||||||
else if (token == "gensfen2019") Learner::gen_sfen2019(pos, is);
|
else if (token == "gensfen2019") Learner::gen_sfen2019(pos, is);
|
||||||
#endif
|
#endif
|
||||||
// テスト用にqsearch(),search()を直接呼ぶコマンド
|
// Command to call qsearch(),search() directly for testing
|
||||||
else if (token == "qsearch") qsearch_cmd(pos);
|
else if (token == "qsearch") qsearch_cmd(pos);
|
||||||
else if (token == "search") search_cmd(pos, is);
|
else if (token == "search") search_cmd(pos, is);
|
||||||
|
|
||||||
|
@ -405,7 +405,7 @@ void UCI::loop(int argc, char* argv[]) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(EVAL_NNUE) && defined(ENABLE_TEST_CMD)
|
#if defined(EVAL_NNUE) && defined(ENABLE_TEST_CMD)
|
||||||
// テストコマンド
|
// test command
|
||||||
else if (token == "test") test_cmd(pos, is);
|
else if (token == "test") test_cmd(pos, is);
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
|
|
11
src/uci.h
11
src/uci.h
|
@ -75,16 +75,17 @@ std::string move(Move m, bool chess960);
|
||||||
std::string pv(const Position& pos, Depth depth, Value alpha, Value beta);
|
std::string pv(const Position& pos, Depth depth, Value alpha, Value beta);
|
||||||
Move to_move(const Position& pos, std::string& str);
|
Move to_move(const Position& pos, std::string& str);
|
||||||
|
|
||||||
// 評価関数を読み込んだかのフラグ。これはevaldirの変更にともなってfalseにする。
|
// Flag that read the evaluation function. This is set to false when evaldir is changed.
|
||||||
extern bool load_eval_finished; // = false;
|
extern bool load_eval_finished; // = false;
|
||||||
} // namespace UCI
|
} // namespace UCI
|
||||||
|
|
||||||
extern UCI::OptionsMap Options;
|
extern UCI::OptionsMap Options;
|
||||||
|
|
||||||
// USIの"isready"コマンドが呼び出されたときの処理。このときに評価関数の読み込みなどを行なう。
|
// Processing when USI "isready" command is called. At this time, the evaluation function is read.
|
||||||
// benchmarkコマンドのハンドラなどで"isready"が来ていないときに評価関数を読み込ませたいときに用いる。
|
// Used when you want to load the evaluation function when "isready" does not come in handler of benchmark command etc.
|
||||||
// skipCorruptCheck == trueのときは評価関数の2度目の読み込みのときのcheck sumによるメモリ破損チェックを省略する。
|
// If skipCorruptCheck == true, skip memory corruption check by check sum when reading the evaluation function a second time.
|
||||||
// ※ この関数は、Stockfishにはないがないと不便なので追加しておく。
|
// * This function is inconvenient if it is not available in Stockfish, so add it.
|
||||||
|
|
||||||
void is_ready(bool skipCorruptCheck = false);
|
void is_ready(bool skipCorruptCheck = false);
|
||||||
|
|
||||||
extern const char* StartFEN;
|
extern const char* StartFEN;
|
||||||
|
|
|
@ -79,21 +79,21 @@ void init(OptionsMap& o) {
|
||||||
o["SyzygyProbeDepth"] << Option(1, 1, 100);
|
o["SyzygyProbeDepth"] << Option(1, 1, 100);
|
||||||
o["Syzygy50MoveRule"] << Option(true);
|
o["Syzygy50MoveRule"] << Option(true);
|
||||||
o["SyzygyProbeLimit"] << Option(7, 0, 7);
|
o["SyzygyProbeLimit"] << Option(7, 0, 7);
|
||||||
// 評価関数フォルダ。これを変更したとき、評価関数を次のisreadyタイミングで読み直す必要がある。
|
// Evaluation function folder. When this is changed, it is necessary to reread the evaluation function at the next isready timing.
|
||||||
o["EvalDir"] << Option("eval", on_eval_dir);
|
o["EvalDir"] << Option("eval", on_eval_dir);
|
||||||
// isreadyタイミングで評価関数を読み込まれると、新しい評価関数の変換のために
|
// When the evaluation function is loaded at the isready timing, it is necessary to convert the new evaluation function.
|
||||||
// test evalconvertコマンドを叩きたいのに、その新しい評価関数がないがために
|
// I want to hit the test eval convert command, but there is no new evaluation function
|
||||||
// このコマンドの実行前に異常終了してしまう。
|
// It ends abnormally before executing this command.
|
||||||
// そこでこの隠しオプションでisready時の評価関数の読み込みを抑制して、
|
// Therefore, with this hidden option, you can suppress the loading of the evaluation function when isready,
|
||||||
// test evalconvertコマンドを叩く。
|
// Hit the test eval convert command.
|
||||||
o["SkipLoadingEval"] << Option(false);
|
o["SkipLoadingEval"] << Option(false);
|
||||||
// 定跡の指し手を何手目まで用いるか
|
// how many moves to use a fixed move
|
||||||
o["BookMoves"] << Option(16, 0, 10000);
|
o["BookMoves"] << Option(16, 0, 10000);
|
||||||
|
|
||||||
#if defined(EVAL_LEARN)
|
#if defined(EVAL_LEARN)
|
||||||
// 評価関数の学習を行なうときは、評価関数の保存先のフォルダを変更できる。
|
// When learning the evaluation function, you can change the folder to save the evaluation function.
|
||||||
// デフォルトではevalsave。このフォルダは事前に用意されているものとする。
|
// Evalsave by default. This folder shall be prepared in advance.
|
||||||
// このフォルダ配下にフォルダを"0/","1/",…のように自動的に掘り、そこに評価関数ファイルを保存する。
|
// Automatically dig a folder under this folder like "0/", "1/", ... and save the evaluation function file there.
|
||||||
o["EvalSaveDir"] << Option("evalsave");
|
o["EvalSaveDir"] << Option("evalsave");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -204,6 +204,6 @@ Option& Option::operator=(const string& v) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 評価関数を読み込んだかのフラグ。これはevaldirの変更にともなってfalseにする。
|
// Flag that read the evaluation function. This is set to false when evaldir is changed.
|
||||||
bool load_eval_finished = false;
|
bool load_eval_finished = false;
|
||||||
} // namespace UCI
|
} // namespace UCI
|
||||||
|
|
Loading…
Add table
Reference in a new issue