Implemented the logic to update Eval List and Dirty Pieces.

This commit is contained in:
Hisayori Noda
2019-06-16 10:33:53 +09:00
parent b330602cdc
commit 48bfe86d27
9 changed files with 313 additions and 30 deletions

View File

@@ -233,12 +233,14 @@ void prefetch_evalhash(const Key key) {
void load_eval() {
NNUE::Initialize();
#if defined(EVAL_LEARN)
if (!Options["SkipLoadingEval"])
#endif
{
const std::string dir_name = Options["EvalDir"];
const std::string file_name = Path::Combine(dir_name, NNUE::kFileName);
//{
// std::ofstream stream(file_name, std::ios::binary);
// NNUE::WriteParameters(stream);
//}
std::ifstream stream(file_name, std::ios::binary);
const bool result = NNUE::ReadParameters(stream);

View File

@@ -29,6 +29,7 @@
#include "material.h"
#include "pawns.h"
#include "thread.h"
#include "eval/nnue/evaluate_nnue.h"
namespace Trace {
@@ -864,7 +865,8 @@ namespace {
/// evaluation of the position from the point of view of the side to move.
Value Eval::evaluate(const Position& pos) {
return Evaluation<NO_TRACE>(pos).value();
//return Evaluation<NO_TRACE>(pos).value();
return Eval::NNUE::evaluate(pos);
}
@@ -907,3 +909,72 @@ std::string Eval::trace(const Position& pos) {
return ss.str();
}
namespace Eval {
ExtBonaPiece kpp_board_index[PIECE_NB] = {
{ BONA_PIECE_ZERO, BONA_PIECE_ZERO },
{ f_pawn, e_pawn },
{ f_knight, e_knight },
{ f_bishop, e_bishop },
{ f_rook, e_rook },
{ f_queen, e_queen },
{ f_king, e_king },
{ BONA_PIECE_ZERO, BONA_PIECE_ZERO },
// <20><><EFBFBD><EFBFBD><EFBFBD><E78CA9><EFBFBD><EFBFBD>Bf<42><66>e<EFBFBD><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ւ<EFBFBD><D682><EFBFBD><EFBFBD>B
{ BONA_PIECE_ZERO, BONA_PIECE_ZERO },
{ e_pawn, f_pawn },
{ e_knight, f_knight },
{ e_bishop, f_bishop },
{ e_rook, f_rook },
{ e_queen, f_queen },
{ e_king, f_king },
{ BONA_PIECE_ZERO, BONA_PIECE_ZERO }, // <20><><EFBFBD>̐<EFBFBD><CC90><EFBFBD><EFBFBD>͂Ȃ<CD82>
};
// <20><><EFBFBD><EFBFBD><EFBFBD>ŕێ<C595><DB8E><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD>pieceListFw[]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>BonaPiece<63>ł<EFBFBD><C582><EFBFBD><E982A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B
// <20><> : <20>f<EFBFBD>o<EFBFBD>b<EFBFBD>O<EFBFBD>p<EFBFBD>B<EFBFBD>x<EFBFBD><78><EFBFBD>B
bool EvalList::is_valid(const Position& pos)
{
for (int i = 0; i < length(); ++i)
{
BonaPiece fw = pieceListFw[i];
// <20><><EFBFBD><EFBFBD>fw<66><77><EFBFBD>{<7B><><EFBFBD>ɑ<EFBFBD><C991>݂<EFBFBD><DD82><EFBFBD><E982A9>Position<6F>N<EFBFBD><4E><EFBFBD>X<EFBFBD>̂ق<CC82><D982>ɒ<EFBFBD><C992>ׂɍs<C98D><73><EFBFBD>B
if (fw == Eval::BONA_PIECE_ZERO) {
continue;
}
// <20>͈͊O
if (!(0 <= fw && fw < fe_end))
return false;
// <20>Տ<EFBFBD><D58F>̋<EFBFBD><CC8B>Ȃ̂ł<CC82><C582>̋<CC8B>{<7B><><EFBFBD>ɑ<EFBFBD><C991>݂<EFBFBD><DD82><EFBFBD><E982A9><EFBFBD>ׂɂ<D782><C982><EFBFBD><EFBFBD>B
for (Piece pc = NO_PIECE; pc < PIECE_NB; ++pc)
{
auto pt = type_of(pc);
if (pt == NO_PIECE || pt == 7) // <20><><EFBFBD>݂<EFBFBD><DD82>Ȃ<EFBFBD><C882><EFBFBD>
continue;
// <20><>pc<70><63>BonaPiece<63>̊J<CC8A>n<EFBFBD>ԍ<EFBFBD>
auto s = BonaPiece(kpp_board_index[pc].fw);
if (s <= fw && fw < s + SQUARE_NB)
{
// <20><><EFBFBD>‚<EFBFBD><C282><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̂ł<CC82><C582>̋sq<73>̒n<CC92>_<EFBFBD>ɂ<EFBFBD><C982><EFBFBD>𒲂ׂ<F092B282><D782>B
Square sq = (Square)(fw - s);
Piece pc2 = pos.piece_on(sq);
if (pc2 != pc)
return false;
goto Found;
}
}
// <20><><EFBFBD>̂<EFBFBD><CC82><EFBFBD><EFBFBD>݂<EFBFBD><DD82>Ȃ<EFBFBD><C882><EFBFBD><EFBFBD>ł<EFBFBD><C582><EFBFBD><EFBFBD><EFBFBD>..
return false;
Found:;
}
return true;
}
}

View File

@@ -35,6 +35,15 @@ std::string trace(const Position& pos);
Value evaluate(const Position& pos);
// <20>]<5D><><EFBFBD>֐<EFBFBD><D690>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>ǂݍ<C782><DD8D>ށB
// <20><><EFBFBD><EFBFBD><EFBFBD>́A"is_ready"<22>R<EFBFBD>}<7D><><EFBFBD>h<EFBFBD>̉<EFBFBD><CC89><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD>x<EFBFBD><78><EFBFBD><EFBFBD><EFBFBD>Ăяo<D18F><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B2<42>x<EFBFBD>Ăяo<D18F><6F><EFBFBD><EFBFBD><EFBFBD>Ƃ͑z<CD91><EFBFBD>Ă<EFBFBD><C482>Ȃ<EFBFBD><C882>B
// (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>AEvalDir(<28>]<5D><><EFBFBD>֐<EFBFBD><D690>t<EFBFBD>H<EFBFBD><48><EFBFBD>_)<29><><EFBFBD>ύX<CF8D>ɂȂ<C982><C882><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƁAisready<64><79><EFBFBD>ēx<C493><78><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǂ݂Ȃ<DD82><C882><EFBFBD><EFBFBD>B)
void load_eval();
static uint64_t calc_check_sum() { return 0; }
static void print_softname(uint64_t check_sum) {}
// --- <20>]<5D><><EFBFBD>֐<EFBFBD><D690>Ŏg<C58E><67><EFBFBD>萔 KPP(<28>ʂƔC<C694><43>2<EFBFBD><32>)<29><>P<EFBFBD>ɑ<EFBFBD><C991><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>enum
// (<28>]<5D><><EFBFBD>֐<EFBFBD><D690>̎<EFBFBD><CC8E><EFBFBD><EFBFBD>̂Ƃ<CC82><C682>ɂ́ABonaPiece<63>͎<EFBFBD><CD8E>R<EFBFBD>ɒ<EFBFBD><C992>`<60><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̂ł<CC82><C582><EFBFBD><EFBFBD>ł͒<C582><CD92>`<60><><EFBFBD>Ȃ<EFBFBD><C882>B)
@@ -145,22 +154,10 @@ struct EvalList
v = PIECE_NUMBER_NB;
}
// list<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>•ς̂Ƃ<EFBFBD><EFBFBD>́Aadd()/remove()<29><><EFBFBD>T<EFBFBD>|<7C>[<5B>g<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B
// DirtyPiece<63>̂ق<CC82><D982><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ăяo<D18F><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B
// list<73><74>add()<29><><EFBFBD><EFBFBD><EFBFBD>B
void add(BonaPiece fb);
// list<73><74><EFBFBD><EFBFBD>remove<76><65><EFBFBD><EFBFBD><EFBFBD>B
void remove(BonaPiece fb);
// <20><><EFBFBD><EFBFBD><EFBFBD>ŕێ<C595><DB8E><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD>pieceListFb[]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>BonaPiece<63>ł<EFBFBD><C582><EFBFBD><E982A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŕێ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><EFBFBD><EFBFBD>pieceListFw[]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>BonaPiece<63>ł<EFBFBD><C582><EFBFBD><E982A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B
// <20><> : <20>f<EFBFBD>o<EFBFBD>b<EFBFBD>O<EFBFBD>p<EFBFBD>B<EFBFBD>x<EFBFBD><78><EFBFBD>B
bool is_valid(const Position& pos);
protected:
// <20>Տ<EFBFBD>sq<73>ɂ<EFBFBD><C982><EFBFBD>piece_no<6E>̋<EFBFBD><CC8B><EFBFBD>BonaPiece<63><65>fb,fw<66>ł<EFBFBD><C582><EFBFBD>Ƃ<EFBFBD><C682>ݒ肷<DD92><E882B7><EFBFBD>B
inline void set_piece_on_board(PieceNumber piece_no, BonaPiece fw, BonaPiece fb, Square sq)
{
@@ -173,7 +170,7 @@ protected:
// <20><EFBFBD>X<EFBFBD>g<EFBFBD>B<EFBFBD><42><EFBFBD>ԍ<EFBFBD>(PieceNumber)<29><><EFBFBD><EFBFBD><EFBFBD>‚̋<CC8B>ǂ<EFBFBD><C782>ɂ<EFBFBD><C982><EFBFBD><EFBFBD>̂<EFBFBD>(BonaPiece)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>BFV38<33>Ȃǂŗp<C597><70><EFBFBD><EFBFBD><EFBFBD>B
// <20><EFBFBD>X<EFBFBD>g<EFBFBD>̒<EFBFBD><CC92><EFBFBD>
// 38<33>Œ<EFBFBD>
// 38<33>Œ<EFBFBD>
public:
int length() const { return PIECE_NUMBER_KING; }
@@ -181,15 +178,15 @@ public:
// <20>܂<EFBFBD><DC82>AKPPT<50>^<5E>]<5D><><EFBFBD>֐<EFBFBD><D690>Ȃǂ́A39,40<34>Ԗڂ̗v<CC97>f<EFBFBD><66><EFBFBD>[<5B><><EFBFBD>ł<EFBFBD><C582><EFBFBD>Ƃ<EFBFBD><C682>O<EFBFBD><4F><EFBFBD>Ƃ<EFBFBD><C682><EFBFBD>
// <20>A<EFBFBD>N<EFBFBD>Z<EFBFBD>X<EFBFBD><58><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>ӏ<EFBFBD><D38F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̂Œ<CC82><C592>ӂ<EFBFBD><D382><EFBFBD>ƁB
static const int MAX_LENGTH = 40;
// <20>Տ<EFBFBD><D58F>̋<EFBFBD><CC8B>ɑ΂<C991><CE82>āA<C481><41><EFBFBD>̋<EFBFBD><CC8B>ԍ<EFBFBD>(PieceNumber)<29><><EFBFBD>ێ<EFBFBD><DB8E><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>z<EFBFBD><7A>
// <20>ʂ<EFBFBD>SQ_NB<4E>Ɉړ<C988><DA93><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>Ƃ<EFBFBD><C682>p<EFBFBD><70>+1<>܂ŕێ<C595><DB8E><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD><EFBFBD><EFBFBD>A
// SQ_NB<4E>̋ʂ<CC8B><CA82>ړ<EFBFBD><DA93><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882>̂ŁA<C581><41><EFBFBD>̒l<CC92><6C><EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD>Ƃ͂Ȃ<CD82><C882>͂<EFBFBD><CD82>B
PieceNumber piece_no_list_board[SQUARE_NB_PLUS1];
private:
BonaPiece pieceListFw[MAX_LENGTH];
BonaPiece pieceListFb[MAX_LENGTH];
// <20>Տ<EFBFBD><D58F>̋<EFBFBD><CC8B>ɑ΂<C991><CE82>āA<C481><41><EFBFBD>̋<EFBFBD><CC8B>ԍ<EFBFBD>(PieceNumber)<29><><EFBFBD>ێ<EFBFBD><DB8E><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>z<EFBFBD><7A>
// <20>ʂ<EFBFBD>SQ_NB<4E>Ɉړ<C988><DA93><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>Ƃ<EFBFBD><C682>p<EFBFBD><70>+1<>܂ŕێ<C595><DB8E><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD><EFBFBD><EFBFBD>A
// SQ_NB<4E>̋ʂ<CC8B><CA82>ړ<EFBFBD><DA93><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882>̂ŁA<C581><41><EFBFBD>̒l<CC92><6C><EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD>Ƃ͂Ȃ<CD82><C882>͂<EFBFBD><CD82>B
PieceNumber piece_no_list_board[SQUARE_NB_PLUS1];
};
// <20>]<5D><><EFBFBD>l<EFBFBD>̍<EFBFBD><CC8D><EFBFBD><EFBFBD>v<EFBFBD>Z<EFBFBD>̊Ǘ<CC8A><C797>p

View File

@@ -243,6 +243,20 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
std::fill_n(&pieceList[0][0], sizeof(pieceList) / sizeof(Square), SQ_NONE);
st = si;
// evalList<73><74>clear<61>B<EFBFBD><42><EFBFBD><EFBFBD>memset<65>Ń[<5B><><EFBFBD>N<EFBFBD><4E><EFBFBD>A<EFBFBD><41><EFBFBD><EFBFBD><EFBFBD>Ƃ<EFBFBD><C682>ɃN<C983><4E><EFBFBD>A<EFBFBD><41><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD>c<EFBFBD>B
evalList.clear();
// PieceList<73><74><EFBFBD>X<EFBFBD>V<EFBFBD><56><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŁA<C581>ǂ̋<CC8B>ǂ<EFBFBD><C782>ɂ<EFBFBD><C982><EFBFBD><E982A9><EFBFBD>ݒ肵<DD92>Ȃ<EFBFBD><C882><EFBFBD><EFBFBD>΂Ȃ<CE82><C882>Ȃ<EFBFBD><C882><EFBFBD><EFBFBD>A
// <20><><EFBFBD><EFBFBD><EA82BC><EFBFBD>̋<EFBFBD><CC8B><EFBFBD><EFBFBD>ǂ<EFBFBD><C782>܂Ŏg<C58E><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̃J<CC83>E<EFBFBD><45><EFBFBD>^<5E>[
PieceNumber piece_no_count[KING] = {
PIECE_NUMBER_ZERO,
PIECE_NUMBER_PAWN,
PIECE_NUMBER_KNIGHT,
PIECE_NUMBER_BISHOP,
PIECE_NUMBER_ROOK,
PIECE_NUMBER_QUEEN
};
ss >> std::noskipws;
// 1. Piece placement
@@ -256,7 +270,15 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
else if ((idx = PieceToChar.find(token)) != string::npos)
{
put_piece(Piece(idx), sq);
auto pc = Piece(idx);
put_piece(pc, sq);
PieceNumber piece_no =
(idx == W_KING) ? PIECE_NUMBER_WKING : // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
(idx == B_KING) ? PIECE_NUMBER_BKING : // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
piece_no_count[type_of(Piece(idx))]++; // <20><><EFBFBD><EFBFBD><EFBFBD>ȊO
evalList.put_piece(piece_no, sq, pc); // sq<73>̏<EFBFBD><CC8F><EFBFBD>pc<70>̋<EFBFBD><CC8B><EFBFBD><EFBFBD>z<EFBFBD>u<EFBFBD><75><EFBFBD><EFBFBD>
++sq;
}
}
@@ -319,6 +341,7 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
set_state(st);
assert(pos_is_ok());
assert(evalList.is_valid(*this));
return *this;
}
@@ -739,6 +762,9 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
++st->rule50;
++st->pliesFromNull;
st->accumulator.computed_accumulation = false;
st->accumulator.computed_score = false;
Color us = sideToMove;
Color them = ~us;
Square from = from_sq(m);
@@ -750,6 +776,9 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
assert(captured == NO_PIECE || color_of(captured) == (type_of(m) != CASTLING ? them : us));
assert(type_of(captured) != KING);
auto& dp = st->dirtyPiece;
dp.dirty_num = 1;
if (type_of(m) == CASTLING)
{
assert(pc == make_piece(us, KING));
@@ -766,6 +795,8 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
{
Square capsq = to;
PieceNumber piece_no1;
// If the captured piece is a pawn, update pawn hash key, otherwise
// update non-pawn material.
if (type_of(captured) == PAWN)
@@ -780,14 +811,22 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
assert(piece_on(to) == NO_PIECE);
assert(piece_on(capsq) == make_piece(them, PAWN));
piece_no1 = piece_no_of(capsq);
board[capsq] = NO_PIECE; // Not done by remove_piece()
}
else {
piece_no1 = piece_no_of(capsq);
}
st->pawnKey ^= Zobrist::psq[captured][capsq];
}
else
else {
st->nonPawnMaterial[them] -= PieceValue[MG][captured];
piece_no1 = piece_no_of(capsq);
}
// Update board and piece lists
remove_piece(captured, capsq);
@@ -798,6 +837,19 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
// Reset rule 50 counter
st->rule50 = 0;
dp.dirty_num = 2; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32>
dp.pieceNo[1] = piece_no1;
dp.changed_piece[1].old_piece = evalList.bona_piece(piece_no1);
// Do not use Eval::EvalList::put_piece() because the piece is removed
// from the game, and the corresponding elements of the piece lists
// needs to be Eval::BONA_PIECE_ZERO.
evalList.set_piece_on_board(piece_no1, Eval::BONA_PIECE_ZERO, Eval::BONA_PIECE_ZERO, capsq);
// Set PIECE_NUMBER_NB to piece_no_of_board[capsq] directly because it
// will not be overritten to pc if the move type is enpassant.
evalList.piece_no_list_board[capsq] = PIECE_NUMBER_NB;
dp.changed_piece[1].new_piece = evalList.bona_piece(piece_no1);
}
// Update hash key
@@ -819,8 +871,16 @@ 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)
move_piece(pc, from, to);
if (type_of(m) != CASTLING) {
PieceNumber piece_no0 = piece_no_of(from);
move_piece(pc, from, to);
dp.pieceNo[0] = piece_no0;
dp.changed_piece[0].old_piece = evalList.bona_piece(piece_no0);
evalList.put_piece(piece_no0, to, pc);
dp.changed_piece[0].new_piece = evalList.bona_piece(piece_no0);
}
// If the moving piece is a pawn do some special extra work
if (type_of(pc) == PAWN)
@@ -843,6 +903,12 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
remove_piece(pc, to);
put_piece(promotion, to);
PieceNumber piece_no0 = piece_no_of(to);
dp.pieceNo[0] = piece_no0;
dp.changed_piece[0].old_piece = evalList.bona_piece(piece_no0);
evalList.put_piece(piece_no0, to, promotion);
dp.changed_piece[0].new_piece = evalList.bona_piece(piece_no0);
// Update hash keys
k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
st->pawnKey ^= Zobrist::psq[pc][to];
@@ -894,6 +960,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
}
assert(pos_is_ok());
assert(evalList.is_valid(*this));
}
@@ -923,6 +990,9 @@ void Position::undo_move(Move m) {
remove_piece(pc, to);
pc = make_piece(us, PAWN);
put_piece(pc, to);
PieceNumber piece_no0 = st->dirtyPiece.pieceNo[0];
evalList.put_piece(piece_no0, to, pc);
}
if (type_of(m) == CASTLING)
@@ -932,8 +1002,12 @@ void Position::undo_move(Move m) {
}
else
{
move_piece(pc, to, from); // Put the piece back at the source square
PieceNumber piece_no0 = st->dirtyPiece.pieceNo[0];
evalList.put_piece(piece_no0, from, pc);
if (st->capturedPiece)
{
Square capsq = to;
@@ -950,6 +1024,11 @@ void Position::undo_move(Move m) {
}
put_piece(st->capturedPiece, capsq); // Restore the captured piece
PieceNumber piece_no1 = st->dirtyPiece.pieceNo[1];
assert(evalList.bona_piece(piece_no1).fw == Eval::BONA_PIECE_ZERO);
assert(evalList.bona_piece(piece_no1).fb == Eval::BONA_PIECE_ZERO);
evalList.put_piece(piece_no1, capsq, st->capturedPiece);
}
}
@@ -958,6 +1037,7 @@ void Position::undo_move(Move m) {
--gamePly;
assert(pos_is_ok());
assert(evalList.is_valid(*this));
}
@@ -965,18 +1045,50 @@ void Position::undo_move(Move m) {
/// is a bit tricky in Chess960 where from/to squares can overlap.
template<bool Do>
void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto) {
auto& dp = st->dirtyPiece;
// <20><><EFBFBD><EFBFBD><EFBFBD>v<EFBFBD>Z<EFBFBD>̂<EFBFBD><CC82>߂Ɉړ<C988><DA93><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>StateInfo<66>ɋL<C98B>^<5E><><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>B
dp.dirty_num = 2; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32>
PieceNumber piece_no0;
PieceNumber piece_no1;
if (Do) {
piece_no0 = piece_no_of(from);
piece_no1 = piece_no_of(to);
}
bool kingSide = to > from;
rfrom = to; // Castling is encoded as "king captures friendly rook"
rto = relative_square(us, kingSide ? SQ_F1 : SQ_D1);
to = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
if (!Do) {
piece_no0 = piece_no_of(to);
piece_no1 = piece_no_of(rto);
}
// Remove both pieces first since squares could overlap in Chess960
remove_piece(make_piece(us, KING), Do ? from : to);
remove_piece(make_piece(us, ROOK), Do ? rfrom : rto);
board[Do ? from : to] = board[Do ? rfrom : rto] = NO_PIECE; // Since remove_piece doesn't do it for us
put_piece(make_piece(us, KING), Do ? to : from);
put_piece(make_piece(us, ROOK), Do ? rto : rfrom);
if (Do) {
dp.pieceNo[0] = piece_no0;
dp.changed_piece[0].old_piece = evalList.bona_piece(piece_no0);
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.put_piece(piece_no1, rto, make_piece(us, ROOK));
dp.changed_piece[1].new_piece = evalList.bona_piece(piece_no1);
}
else {
evalList.put_piece(piece_no0, from, make_piece(us, KING));
evalList.put_piece(piece_no1, rfrom, make_piece(us, ROOK));
}
}
@@ -1313,3 +1425,14 @@ bool Position::pos_is_ok() const {
return true;
}
PieceNumber Position::piece_no_of(Square sq) const
{
if (piece_on(sq) == NO_PIECE) {
sync_cout << *this << sync_endl;
}
assert(piece_on(sq) != NO_PIECE);
PieceNumber n = evalList.piece_no_of_board(sq);
assert(is_ok(n));
return n;
}

View File

@@ -23,10 +23,12 @@
#include <cassert>
#include <deque>
#include <iostream>
#include <memory> // For std::unique_ptr
#include <string>
#include "bitboard.h"
#include "misc.h"
#include "types.h"
#include "eval/nnue/nnue_accumulator.h"
@@ -194,6 +196,9 @@ private:
template<bool Do>
void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto);
// <20>Տ<EFBFBD><D58F><EFBFBD>sq<73>̏<EFBFBD><CC8F>ɂ<EFBFBD><C982><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PieceNumber<65><72><EFBFBD>Ԃ<EFBFBD><D482>B
PieceNumber piece_no_of(Square sq) const;
// Data members
Piece board[SQUARE_NB];
Bitboard byTypeBB[PIECE_TYPE_NB];

View File

@@ -469,7 +469,7 @@ constexpr bool is_ok(Move m) {
// --------------------
// Position<6F>N<EFBFBD><4E><EFBFBD>X<EFBFBD>ŗp<C597><70><EFBFBD><EFBFBD><EFBFBD>A<EFBFBD><EFBFBD>X<EFBFBD>g(<28>ǂ̋<CC8B>ǂ<EFBFBD><C782>ɂ<EFBFBD><C982><EFBFBD><EFBFBD>̂<EFBFBD>)<29><><EFBFBD>Ǘ<EFBFBD><C797><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƃ<EFBFBD><C682>̔ԍ<CC94><D48D>B
enum PieceNumber : int8_t
enum PieceNumber : uint8_t
{
PIECE_NUMBER_PAWN = 0,
PIECE_NUMBER_KNIGHT = 16,
@@ -483,8 +483,13 @@ enum PieceNumber : int8_t
PIECE_NUMBER_NB = 32,
};
inline PieceNumber& operator++(PieceNumber& d) { return d = PieceNumber(int(d) + 1); } \
inline PieceNumber& operator--(PieceNumber& d) { return d = PieceNumber(int(d) - 1); }
inline PieceNumber& operator++(PieceNumber& d) { return d = PieceNumber(int8_t(d) + 1); }
inline PieceNumber operator++(PieceNumber& d, int) {
PieceNumber x = d;
d = PieceNumber(int8_t(d) + 1);
return x;
}
inline PieceNumber& operator--(PieceNumber& d) { return d = PieceNumber(int8_t(d) - 1); }
// PieceNumber<65>̐<EFBFBD><CC90><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̌<EFBFBD><CC8C><EFBFBD><EFBFBD>Bassert<72>p<EFBFBD>B
constexpr bool is_ok(PieceNumber pn) { return pn < PIECE_NUMBER_NB; }

View File

@@ -177,6 +177,73 @@ namespace {
<< "\nNodes/second : " << 1000 * nodes / elapsed << endl;
}
// check sum<75><6D><EFBFBD>v<EFBFBD>Z<EFBFBD><5A><EFBFBD><EFBFBD><EFBFBD>Ƃ<EFBFBD><C682>A<EFBFBD><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۑ<EFBFBD><DB91><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>Ă<EFBFBD><C482>ƂŎ<C682><C58E><EFBFBD><EFBFBD>ȍ~<7E>A<EFBFBD><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̃`<60>F<EFBFBD>b<EFBFBD>N<EFBFBD><4E><EFBFBD>s<EFBFBD>Ȃ<EFBFBD><C882>B
uint64_t eval_sum;
// is_ready_cmd()<29><><EFBFBD>O<EFBFBD><4F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ăяo<D18F><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɂ<EFBFBD><C982>Ă<EFBFBD><C482><EFBFBD><EFBFBD>B(bench<63>R<EFBFBD>}<7D><><EFBFBD>h<EFBFBD>Ȃǂ<C882><C782><EFBFBD><EFBFBD>Ăяo<D18F><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
// <20>ǖʂ͏<CA82><CD8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882>̂Œ<CC82><C592>ӁB
void is_ready(Position& pos, istringstream& is, StateListPtr& states)
{
// "isready"<22><><EFBFBD>󂯎<EFBFBD><F382AF8E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƁA"readyok"<22><><EFBFBD>Ԃ<EFBFBD><D482>܂<EFBFBD>5<EFBFBD>b<EFBFBD><62><EFBFBD>Ƃɉ<C682><C989>s<EFBFBD>𑗂<EFBFBD><F0919782><EFBFBD>ɏC<C98F><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B(keep alive<76>I<EFBFBD>ȏ<EFBFBD><C88F><EFBFBD>)
// USI2.0<EFBFBD>̎d<EFBFBD>l<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B
// -"isready"<22>̂<EFBFBD><CC82>Ƃ<EFBFBD>time out<75><74><EFBFBD>Ԃ́A30<33>b<EFBFBD><62><EFBFBD>x<EFBFBD>Ƃ<EFBFBD><C682><EFBFBD><EFBFBD>B<EFBFBD><42><EFBFBD><EFBFBD><EFBFBD>𒴂<EFBFBD><F092B482>āA<C481>]<5D><><EFBFBD>֐<EFBFBD><D690>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ahash<73>e<EFBFBD>[<5B>u<EFBFBD><75><EFBFBD>̊m<CC8A>ۂ<EFBFBD><DB82><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>A
// <20>v<EFBFBD>l<EFBFBD>G<EFBFBD><47><EFBFBD>W<EFBFBD><57><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>I<EFBFBD>ɉ<EFBFBD><C989><EFBFBD>̃<EFBFBD><CC83>b<EFBFBD>Z<EFBFBD>[<5B>W(<28><><EFBFBD>s<EFBFBD><73>)<29>𑗂<EFBFBD><F0919782>ׂ<EFBFBD><D782>ł<EFBFBD><C582><EFBFBD><EFBFBD>B
// -ShogiGUI<55>ł͂<C582><CD82>łɂ<C582><C982><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882>Ă<EFBFBD><C482><EFBFBD><EFBFBD>̂ŁAMyShogi<67><69><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɒǐ<C992><C790><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B
// -<2D>܂<EFBFBD><DC82>A<EFBFBD><41><EFBFBD>˂<EFBFBD><CB82><EFBFBD>̃G<CC83><47><EFBFBD>W<EFBFBD><57><EFBFBD><EFBFBD><EFBFBD>́A"isready"<22><><EFBFBD>󂯎<EFBFBD><F382AF8E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƁA"readyok"<22><><EFBFBD>Ԃ<EFBFBD><D482>܂<EFBFBD>5<EFBFBD>b<EFBFBD><62><EFBFBD>Ƃɉ<C682><C989>s<EFBFBD>𑗂<EFBFBD><F0919782><EFBFBD>ɏC<C98F><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B
auto ended = false;
auto th = std::thread([&ended] {
int count = 0;
while (!ended)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (++count >= 50 /* 5<>b */)
{
count = 0;
sync_cout << sync_endl; // <20><><EFBFBD>s<EFBFBD>𑗐M<F0919790><4D><EFBFBD><EFBFBD><EFBFBD>B
}
}
});
// <20>]<5D><><EFBFBD>֐<EFBFBD><D690>̓ǂݍ<C782><DD8D>݂Ȃǎ<C882><C78E>Ԃ̂<D482><CC82><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ł<EFBFBD><C582><EFBFBD><EB82A4><EFBFBD><EFBFBD><EFBFBD>͂<EFBFBD><CD82>̃^<5E>C<EFBFBD>~<7E><><EFBFBD>O<EFBFBD>ōs<C58D>Ȃ<EFBFBD><C882>B
// <20>N<EFBFBD><4E><EFBFBD><EFBFBD><EFBFBD>Ɏ<EFBFBD><C98E>Ԃ̂<D482><CC82><EFBFBD><EFBFBD><EFBFBD><E98F88><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>܂<EFBFBD><DC82>Ə<EFBFBD><C68F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>^<5E>C<EFBFBD><43><EFBFBD>A<EFBFBD>E<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>āA<C481>v<EFBFBD>l<EFBFBD>G<EFBFBD><47><EFBFBD>W<EFBFBD><57><EFBFBD>Ƃ<EFBFBD><C682>Ă̔F<CC94><46><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>^<5E>C<EFBFBD>A<EFBFBD><41><EFBFBD>Ă<EFBFBD><C482>܂<EFBFBD><DC82>B
if (!UCI::load_eval_finished)
{
// <20>]<5D><><EFBFBD>֐<EFBFBD><D690>̓ǂݍ<C782><DD8D><EFBFBD>
Eval::load_eval();
// <20>`<60>F<EFBFBD>b<EFBFBD>N<EFBFBD>T<EFBFBD><54><EFBFBD>̌v<CC8C>Z<EFBFBD>ƕۑ<C695>(<28><><EFBFBD>̌<EFBFBD><CC8C>̃<EFBFBD><CC83><EFBFBD><EFBFBD><EFBFBD><EFBFBD>j<EFBFBD><6A><EFBFBD>̃`<60>F<EFBFBD>b<EFBFBD>N<EFBFBD>̂<EFBFBD><CC82><EFBFBD>)
eval_sum = Eval::calc_check_sum();
// <20>\<5C>t<EFBFBD>g<EFBFBD><67><EFBFBD>̕\<5C><>
Eval::print_softname(eval_sum);
UCI::load_eval_finished = true;
}
else
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>j<EFBFBD>󂳂<EFBFBD><F382B382>Ă<EFBFBD><C482>Ȃ<EFBFBD><C882><EFBFBD><EFBFBD>𒲂ׂ邽<D782>߂Ƀ`<60>F<EFBFBD>b<EFBFBD>N<EFBFBD>T<EFBFBD><54><EFBFBD>𖈉񒲂ׂ<F192B282><D782>B
// <20><><EFBFBD>Ԃ<EFBFBD><D482><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>邪.. 0.1<EFBFBD>b<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̂<EFBFBD><EFBFBD>ƂȂ̂ŗǂ<EFBFBD><EFBFBD>Ƃ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>B
if (eval_sum != Eval::calc_check_sum())
sync_cout << "Error! : EVAL memory is corrupted" << sync_endl;
}
// isready<64>ɑ΂<C991><CE82>Ă<EFBFBD>readyok<6F><6B><EFBFBD>Ԃ<EFBFBD><D482>܂Ŏ<DC82><C58E>̃R<CC83>}<7D><><EFBFBD>h<EFBFBD><68><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882><EFBFBD><EFBFBD>Ƃ͖񑩂<CD96><F191A982><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>̂<EFBFBD>
// <20><><EFBFBD>̃^<5E>C<EFBFBD>~<7E><><EFBFBD>O<EFBFBD>Ŋe<C58A><65><EFBFBD>ϐ<EFBFBD><CF90>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>B
TT.resize(Options["Hash"]);
Search::clear();
Time.availableNodes = 0;
Threads.stop = false;
// keep alive<76>𑗐M<F0919790><4D><EFBFBD><EFBFBD>߂ɐ<DF82><C990><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>X<EFBFBD><58><EFBFBD>b<EFBFBD>h<EFBFBD><68><EFBFBD>I<EFBFBD><49><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>A<EFBFBD>ҋ@<40><><EFBFBD><EFBFBD><EFBFBD>B
ended = true;
th.join();
sync_cout << "readyok" << sync_endl;
}
} // namespace
@@ -227,7 +294,7 @@ void UCI::loop(int argc, char* argv[]) {
else if (token == "go") go(pos, is, states);
else if (token == "position") position(pos, is, states);
else if (token == "ucinewgame") Search::clear();
else if (token == "isready") sync_cout << "readyok" << sync_endl;
else if (token == "isready") is_ready(pos, is, states);
// Additional custom non-UCI commands, mainly for debugging
else if (token == "flip") pos.flip();

View File

@@ -75,6 +75,8 @@ std::string move(Move m, bool chess960);
std::string pv(const Position& pos, Depth depth, Value alpha, Value beta);
Move to_move(const Position& pos, std::string& str);
// <20>]<5D><><EFBFBD>֐<EFBFBD><D690><EFBFBD><EFBFBD>ǂݍ<C782><DD8D>񂾂<EFBFBD><F182BE82>̃t<CC83><74><EFBFBD>O<EFBFBD>B<EFBFBD><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD>evaldir<69>̕ύX<CF8D>ɂƂ<C982><C682>Ȃ<EFBFBD><C882><EFBFBD>false<73>ɂ<EFBFBD><C982><EFBFBD><EFBFBD>B
extern bool load_eval_finished; // = false;
} // namespace UCI
extern UCI::OptionsMap Options;

View File

@@ -42,6 +42,7 @@ void on_hash_size(const Option& o) { TT.resize(o); }
void on_logger(const Option& o) { start_logger(o); }
void on_threads(const Option& o) { Threads.set(o); }
void on_tb_path(const Option& o) { Tablebases::init(o); }
void on_eval_dir(const Option& o) { load_eval_finished = false; }
/// Our case insensitive less() function as required by UCI protocol
@@ -78,6 +79,14 @@ void init(OptionsMap& o) {
o["SyzygyProbeDepth"] << Option(1, 1, 100);
o["Syzygy50MoveRule"] << Option(true);
o["SyzygyProbeLimit"] << Option(7, 0, 7);
// <20>]<5D><><EFBFBD>֐<EFBFBD><D690>t<EFBFBD>H<EFBFBD><48><EFBFBD>_<EFBFBD>B<EFBFBD><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ύX<CF8D><58><EFBFBD><EFBFBD><EFBFBD>Ƃ<EFBFBD><C682>A<EFBFBD>]<5D><><EFBFBD>֐<EFBFBD><D690><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>isready<64>^<5E>C<EFBFBD>~<7E><><EFBFBD>O<EFBFBD>œǂݒ<C782><DD92><EFBFBD><EFBFBD>K<EFBFBD>v<EFBFBD><76><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B
o["EvalDir"] << Option("eval", on_eval_dir);
// isready<64>^<5E>C<EFBFBD>~<7E><><EFBFBD>O<EFBFBD>ŕ]<5D><><EFBFBD>֐<EFBFBD><D690><EFBFBD><EFBFBD>ǂݍ<C782><DD8D>܂<EFBFBD><DC82><EFBFBD><EFBFBD>ƁA<C681>V<EFBFBD><56><EFBFBD><EFBFBD><EFBFBD>]<5D><><EFBFBD>֐<EFBFBD><D690>̕ϊ<CC95><CF8A>̂<EFBFBD><CC82>߂<EFBFBD>
// test evalconvert<72>R<EFBFBD>}<7D><><EFBFBD>h<EFBFBD><68><EFBFBD>@<40><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̂ɁA<C981><41><EFBFBD>̐V<CC90><56><EFBFBD><EFBFBD><EFBFBD>]<5D><><EFBFBD>֐<EFBFBD><D690><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߂<EFBFBD>
// <20><><EFBFBD>̃R<CC83>}<7D><><EFBFBD>h<EFBFBD>̎<EFBFBD><CC8E>s<EFBFBD>O<EFBFBD>Ɉُ<C988><D98F>I<EFBFBD><49><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>܂<EFBFBD><DC82>B
// <20><><EFBFBD><EFBFBD><EFBFBD>ł<EFBFBD><C582>̉B<CC89><42><EFBFBD>I<EFBFBD>v<EFBFBD>V<EFBFBD><56><EFBFBD><EFBFBD><EFBFBD><EFBFBD>isready<64><79><EFBFBD>̕]<5D><><EFBFBD>֐<EFBFBD><D690>̓ǂݍ<C782><DD8D>݂<EFBFBD><DD82>}<7D><><EFBFBD><EFBFBD><EFBFBD>āA
// test evalconvert<72>R<EFBFBD>}<7D><><EFBFBD>h<EFBFBD><68><EFBFBD>@<40><><EFBFBD>B
o["SkipLoadingEval"] << Option(false);
}
@@ -186,4 +195,6 @@ Option& Option::operator=(const string& v) {
return *this;
}
// <20>]<5D><><EFBFBD>֐<EFBFBD><D690><EFBFBD><EFBFBD>ǂݍ<C782><DD8D>񂾂<EFBFBD><F182BE82>̃t<CC83><74><EFBFBD>O<EFBFBD>B<EFBFBD><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD>evaldir<69>̕ύX<CF8D>ɂƂ<C982><C682>Ȃ<EFBFBD><C882><EFBFBD>false<73>ɂ<EFBFBD><C982><EFBFBD><EFBFBD>B
bool load_eval_finished = false;
} // namespace UCI