#include "movepick.h"
+int history_slot(Piece pc) {
+ return pc == NO_PIECE ? 0 : (type_of(pc) == KING ? PIECE_SLOTS - 1 : type_of(pc) % (PIECE_SLOTS - 1)) + color_of(pc) * PIECE_SLOTS;
+}
+
namespace {
enum Stages {
else if (Type == QUIETS)
m.value = (*mainHistory)[pos.side_to_move()][from_to(m)]
- + (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
- + (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)]
- + (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]
- + (*continuationHistory[5])[pos.moved_piece(m)][to_sq(m)] / 2;
+ + (*continuationHistory[0])[history_slot(pos.moved_piece(m))][to_sq(m)]
+ + (*continuationHistory[1])[history_slot(pos.moved_piece(m))][to_sq(m)]
+ + (*continuationHistory[3])[history_slot(pos.moved_piece(m))][to_sq(m)]
+ + (*continuationHistory[5])[history_slot(pos.moved_piece(m))][to_sq(m)] / 2;
else // Type == EVASIONS
{
- Value(type_of(pos.moved_piece(m)));
else
m.value = (*mainHistory)[pos.side_to_move()][from_to(m)]
- + (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
+ + (*continuationHistory[0])[history_slot(pos.moved_piece(m))][to_sq(m)]
- (1 << 28);
}
}
struct Stats<T, D, Size> : public std::array<StatsEntry<T, D>, Size> {};
/// In stats table, D=0 means that the template parameter is not used
-enum StatsParams { NOT_USED = 0 };
+enum StatsParams { NOT_USED = 0, PIECE_SLOTS = 8 };
/// ButterflyHistory records how often quiet moves have been successful or
/// ContinuationHistory is the combined history of a given pair of moves, usually
/// the current one given a previous one. The nested history table is based on
/// PieceToHistory instead of ButterflyBoards.
-typedef Stats<PieceToHistory, NOT_USED, PIECE_NB, SQUARE_NB> ContinuationHistory;
+typedef Stats<PieceToHistory, NOT_USED, 2 * PIECE_SLOTS, SQUARE_NB> ContinuationHistory;
+int history_slot(Piece pc);
/// MovePicker class is used to pick one pseudo legal move at a time from the
/// current position. The most important method is next_move(), which returns a
probCutCount++;
ss->currentMove = move;
- ss->continuationHistory = &thisThread->continuationHistory[pos.moved_piece(move)][to_sq(move)];
+ ss->continuationHistory = &thisThread->continuationHistory[history_slot(pos.moved_piece(move))][to_sq(move)];
assert(depth >= 5 * ONE_PLY);
// Countermoves based pruning (~20 Elo)
if ( lmrDepth < 3 + ((ss-1)->statScore > 0 || (ss-1)->moveCount == 1)
- && (*contHist[0])[movedPiece][to_sq(move)] < CounterMovePruneThreshold
- && (*contHist[1])[movedPiece][to_sq(move)] < CounterMovePruneThreshold)
+ && (*contHist[0])[history_slot(movedPiece)][to_sq(move)] < CounterMovePruneThreshold
+ && (*contHist[1])[history_slot(movedPiece)][to_sq(move)] < CounterMovePruneThreshold)
continue;
// Futility pruning: parent node (~2 Elo)
// Update the current move (this must be done after singular extension search)
ss->currentMove = move;
- ss->continuationHistory = &thisThread->continuationHistory[movedPiece][to_sq(move)];
+ ss->continuationHistory = &thisThread->continuationHistory[history_slot(movedPiece)][to_sq(move)];
// Step 15. Make the move
pos.do_move(move, st, givesCheck);
r -= 2 * ONE_PLY;
ss->statScore = thisThread->mainHistory[us][from_to(move)]
- + (*contHist[0])[movedPiece][to_sq(move)]
- + (*contHist[1])[movedPiece][to_sq(move)]
- + (*contHist[3])[movedPiece][to_sq(move)]
+ + (*contHist[0])[history_slot(movedPiece)][to_sq(move)]
+ + (*contHist[1])[history_slot(movedPiece)][to_sq(move)]
+ + (*contHist[3])[history_slot(movedPiece)][to_sq(move)]
- 4000;
// Decrease/increase reduction by comparing opponent's stat score (~10 Elo)
}
ss->currentMove = move;
- ss->continuationHistory = &thisThread->continuationHistory[pos.moved_piece(move)][to_sq(move)];
+ ss->continuationHistory = &thisThread->continuationHistory[history_slot(pos.moved_piece(move))][to_sq(move)];
// Make and search the move
pos.do_move(move, st, givesCheck);
for (int i : {1, 2, 4, 6})
if (is_ok((ss-i)->currentMove))
- (*(ss-i)->continuationHistory)[pc][to] << bonus;
+ (*(ss-i)->continuationHistory)[history_slot(pc)][to] << bonus;
}