本文整理汇总了C++中TTEntry::save方法的典型用法代码示例。如果您正苦于以下问题:C++ TTEntry::save方法的具体用法?C++ TTEntry::save怎么用?C++ TTEntry::save使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类TTEntry
的用法示例。
在下文中一共展示了TTEntry::save方法的5个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: insert_pv_in_tt
void RootMove::insert_pv_in_tt(Position& pos) {
StateInfo state[MAX_PLY], *st = state;
bool ttHit;
// 細かいことだがpvのtailから前方に向かって置換表に書き込んでいくほうが、
// pvの前のほうがエントリーの価値が高いので上書きされてしまう場合にわずかに得ではある。
// ただ、現実的にはほとんど起こりえないので気にしないことにする。
for (Move m : pv)
{
// 銀の不成の指し手をcounter moveとして登録して、この位置に角が来ると
// 角の不成の指し手を生成することになるからLEGALではなくLEGAL_ALLで判定しないといけない。
ASSERT_LV3(MoveList<LEGAL_ALL>(pos).contains(m));
TTEntry* tte = TT.probe(pos.state()->key(), ttHit);
// 正しいエントリーは書き換えない。
if (!ttHit || tte->move() != m)
tte->save(pos.state()->key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE,
m,
#ifndef NO_EVAL_IN_TT
VALUE_NONE,
#endif
TT.generation());
pos.do_move(m, *st++);
}
for (size_t i = pv.size(); i > 0; )
pos.undo_move(pv[--i]);
}
示例2: store
void TranspositionTable::store(const Key posKey, const Score score, const Bound bound, Depth depth,
Move move, const Score evalScore)
{
#ifdef OUTPUT_TRANSPOSITION_EXPIRATION_RATE
++numberOfSaves;
#endif
TTEntry* tte = firstEntry(posKey);
TTEntry* replace = tte;
const u32 posKeyHigh32 = posKey >> 32;
if (depth < Depth0) {
depth = Depth0;
}
for (int i = 0; i < ClusterSize; ++i, ++tte) {
// 置換表が空か、keyが同じな古い情報が入っているとき
if (!tte->key() || tte->key() == posKeyHigh32) {
// move が無いなら、とりあえず古い情報でも良いので、他の指し手を保存する。
if (move.isNone()) {
move = tte->move();
}
tte->save(depth, score, move, posKeyHigh32,
bound, this->generation(), evalScore);
return;
}
int c = (replace->generation() == this->generation() ? 2 : 0);
c += (tte->generation() == this->generation() || tte->type() == BoundExact ? -2 : 0);
c += (tte->depth() < replace->depth() ? 1 : 0);
if (0 < c) {
replace = tte;
}
}
#ifdef OUTPUT_TRANSPOSITION_EXPIRATION_RATE
if (replace->key() != 0 && replace->key() != posKeyHigh32) {
++numberOfCacheExpirations;
}
#endif
replace->save(depth, score, move, posKeyHigh32,
bound, this->generation(), evalScore);
}
示例3: think
// 基本思考ルーチン::depthMax手読み
int AI::think(LightField &self, LightField &enemy, int depth, int timeLimit)
{
if (calls_count++ > 1000)
{
checkTime();
calls_count = 0;
}
// rootからの手数
int ply = depth_max_ - depth;
#ifdef HASH
TTEntry *tte;
// 同一局面が発生するのは2手目以降しかありえない。
if (ply > 0)
{
bool tt_hit = TT.probe<true>(&self, nullptr, tte);
// 局面が登録されていた
if (tt_hit)
{
assert(tte->depth() >= 0);
// 局面表に登録されている局面が、現在の局面の残り深さ以上
if (tte->depth() >= depth)
{
best_[depth] = tte->move();
// 局面表のスコアは信用できるのでそのまま返す
return tte->score();
}
}
}
#endif
if (depth <= DEPTH_ZERO)
return evalate(self, enemy, depth, timeLimit);
else
{
int score;
int max = -SCORE_INFINITE - 1;
int movenum;
int con_prev[3];
self.saveConnect(con_prev);
Move move[22];// おける場所は最大で22種類なので
// 置く場所なし == 負け
if ((movenum = self.generateMoves(move)) == 0)
return -SCORE_INFINITE;
self.nextPlus();
#if defined(DEBUG)
LightField f = self;// debug
#endif
for (int i = 0; i < movenum; i++)
{
// generateMovesでもとめた場所においてみる
self.doMove<true>(move[i]);
assert(self.key() == self.keyInit());
// 設置にかかる時間を計算
// 落下にかかる時間は、13 - 設置位置のyの小さいほう ちぎりなら、余計に時間がかかる
int takeTime = (13 - std::min(toY(move[i].csq()), toY(move[i].psq()))) * FALLTIME + (move[i].isTigiri() ? TAKETIME_INCLUDETIGIRI : TAKETIME);
if (self.flag(VANISH))// 消えるなら
{
score = evalVanish(self, enemy, depth, timeLimit) - takeTime;
self.clearFlag(VANISH);
}
else// 消えないとき
{
if (timeLimit < takeTime)
{
// 致死量振るときに発火できなければ負け。
if (enemy.scoreMax() >= 30 * RATE || enemy.scoreMax() >= self.deadLine() * RATE)
score = -SCORE_INFINITE;
else
score = think(self, enemy, depth - ONE_PLY, timeLimit - takeTime) - takeTime;
}
else
score = think(self, enemy, depth - ONE_PLY, timeLimit - takeTime) - takeTime;
}
self.undoMove(move[i], con_prev);
if (stop)
return SCORE_ZERO;
if (max < score)
{
max = score;
best_[depth] = move[i];// もっとも評価の高い手を選ぶ
}
#if defined DEBUG
assert(self == f); // debug::きちんともとの局面に戻せているか
#endif
//.........这里部分代码省略.........
示例4: search
//.........这里部分代码省略.........
// (searchを再帰的に呼び出して、その先頭でチェックする呼び出しのオーバーヘッドが嫌なのでここで行なう)
bool fullDepthSearch = (PV && moveCount == 1);
if (!fullDepthSearch)
{
// nonPVならざっくり2手ぐらい深さを削っていいのでは..(本当はもっとちゃんとやるべき)
Depth R = ONE_PLY * 2;
value = depth - R < ONE_PLY ?
-qsearch<NonPV>(pos, -beta, -alpha, depth - R) :
-YaneuraOuNano::search<NonPV>(pos, -(alpha + 1), -alpha, depth - R);
// 上の探索によりalphaを更新しそうだが、いい加減な探索なので信頼できない。まともな探索で検証しなおす
fullDepthSearch = value > alpha;
}
if ( fullDepthSearch)
value = depth - ONE_PLY < ONE_PLY ?
-qsearch<PV>(pos, -beta, -alpha, depth - ONE_PLY) :
-YaneuraOuNano::search<PV>(pos, -beta, -alpha, depth - ONE_PLY);
// -----------------------
// 1手戻す
// -----------------------
pos.undo_move(move);
// 停止シグナルが来たら置換表を汚さずに終了。
if (Signals.stop)
return VALUE_ZERO;
// -----------------------
// root node用の特別な処理
// -----------------------
if (RootNode)
{
auto& rm = *std::find(thisThread->rootMoves.begin(), thisThread->rootMoves.end(), move);
if (moveCount == 1 || value > alpha)
{
// root nodeにおいてPVの指し手または、α値を更新した場合、スコアをセットしておく。
// (iterationの終わりでsortするのでそのときに指し手が入れ替わる。)
rm.score = value;
rm.pv.resize(1); // PVは変化するはずなのでいったんリセット
// ここにPVを代入するコードを書く。(か、置換表からPVをかき集めてくるか)
} else {
// root nodeにおいてα値を更新しなかったのであれば、この指し手のスコアを-VALUE_INFINITEにしておく。
// こうしておかなければ、stable_sort()しているにもかかわらず、前回の反復深化のときの値との
// 大小比較してしまい指し手の順番が入れ替わってしまうことによるオーダリング性能の低下がありうる。
rm.score = -VALUE_INFINITE;
}
}
// -----------------------
// alpha値の更新処理
// -----------------------
if (value > alpha)
{
alpha = value;
bestMove = move;
// αがβを上回ったらbeta cut
if (alpha >= beta)
break;
}
} // end of while
// -----------------------
// 生成された指し手がない?
// -----------------------
// 合法手がない == 詰まされている ので、rootの局面からの手数で詰まされたという評価値を返す。
if (moveCount == 0)
alpha = mated_in(ply_from_root);
// -----------------------
// 置換表に保存する
// -----------------------
tte->save(key, value_to_tt(alpha, ply_from_root),
alpha >= beta ? BOUND_LOWER :
PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER,
// betaを超えているということはbeta cutされるわけで残りの指し手を調べていないから真の値はまだ大きいと考えられる。
// すなわち、このとき値は下界と考えられるから、BOUND_LOWER。
// さもなくば、(PvNodeなら)枝刈りはしていないので、これが正確な値であるはずだから、BOUND_EXACTを返す。
// また、PvNodeでないなら、枝刈りをしているので、これは正確な値ではないから、BOUND_UPPERという扱いにする。
// ただし、指し手がない場合は、詰まされているスコアなので、これより短い/長い手順の詰みがあるかも知れないから、
// すなわち、スコアは変動するかも知れないので、BOUND_UPPERという扱いをする。
depth, bestMove, VALUE_NONE,TT.generation());
return alpha;
}
示例5: search
Score AI::search(Score alpha, Score beta, LightField& self, LightField& enemy, int depth, int my_remain_time)
{
if (calls_count++ > 100)
{
checkTime();
calls_count = 0;
}
node_searched++;
const bool rootnode = NT == ROOT;
assert(alpha >= -SCORE_INFINITE && alpha < beta && beta <= SCORE_INFINITE);
// ルートからの手数
int ply = depth_max_ - depth;
// 局面表を見る
Move tt_move, best_move;
Score tt_score;
TTEntry* tte;
const Key key = self.key() ^ enemy.key();
const bool tt_hit = TT.probe<false>(&self, &enemy, tte);
if (stop)
return SCORE_ZERO;
// 局面表の指し手
tt_move = tt_hit ? tte->move() :
rootnode ? root_moves[0].pv[0] : Move::moveNone();
// 置換表上のスコア
tt_score = tt_hit ? tte->score() : SCORE_NONE;
// 置換表のスコアが信用に足るならそのまま返す。
// 条件)
// root nodeではない
// 置換表にエントリーがあった
// 置換表のエントリーのdepthが今回の残り探索depth以上である
// 置換表のエントリーのスコアがSCORE_NONEではない。(置換表のアクセス競合のときにのみこの値になりうる)
// 置換表のスコアのboundがBOUND_EXACTなら信用に足るので置換表の指し手をそのまま返す
// non PV nodeであれば置換表の値がbetaを超えているならBOUND_LOWER(真の値はこれより上なのでこのときbeta cutできる)であるか、
// betaを超えていないのであれば、BOUND_UPPER(真の値はこれより下なのでこのときbeta cutが起きないことが確定)である。
if (!rootnode
&& tt_hit
&& tte->depth() >= depth
&& (depth == 0
|| (tte->bound() == BOUND_EXACT
|| (tte->bound() & BOUND_LOWER && tt_score >= beta))))
{
best_[depth] = tte->move();
assert(tte->move().isNone() || tte->move().isLegal(self));
// 局面表のスコアは信用できるのでそのまま返す
return tt_score;
}
// 最大探索深さまでいったら、その局面の点数を返す
if (depth <= DEPTH_ZERO)
{
Score s = evaluateEX(self, enemy, depth, my_remain_time);
// せっかく評価関数を呼び出したので局面表に登録しておく。
tte->save(key, 0, s, 0, BOUND_NONE, TT.generation(), self.player(), my_remain_time, self.ojama() - enemy.ojama());
return s;
}
Move move[23];
int move_max = 0;
Move *pmove = move;
if (!tt_move.isNone())
{
if (tt_move.isLegalAbout(self))
{
// 置換表にある手を手のバッファの先頭に入れる。
*pmove++ = tt_move;
move_max++;
}
}
if ((move_max += self.generateMoves(pmove)) == 0)
{
// 置く場所なし == 負け
return SCORE_MATED;
}
Score score, max = -SCORE_INFINITE;
// お邪魔ぷよが降る場合はenemyのojamaを減らしているので、
// このmoveを調べ終わった後元に戻さなければならない
int enemy_ojama_prev = enemy.ojama();
Flag enemy_flag = enemy.flag();
self.nextPlus();
// TODO:ムーブオーダリングしたい
// 手がある間、すべての手を試す
for (int i = 0; i < move_max; i++)
//.........这里部分代码省略.........