-/// The Stats struct stores moves statistics. According to the template parameter
-/// the class can store History and Countermoves. History records how often
-/// different moves have been successful or unsuccessful during the current search
-/// and is used for reduction and move ordering decisions.
-/// Countermoves store the move that refute a previous one. Entries are stored
-/// using only the moving piece and destination square, hence two moves with
-/// different origin but same destination and piece will be considered identical.
-template<typename T, bool CM = false>
-struct Stats {
- const T* operator[](Piece pc) const { return table[pc]; }
- T* operator[](Piece pc) { return table[pc]; }
- void clear() { std::memset(table, 0, sizeof(table)); }
- void update(Piece pc, Square to, Move m) { table[pc][to] = m; }
- void update(Piece pc, Square to, Value v) {
-
- if (abs(int(v)) >= 324)
- return;
-
- table[pc][to] -= table[pc][to] * abs(int(v)) / (CM ? 936 : 324);
- table[pc][to] += int(v) * 32;
+ static const bool IsInt = std::is_integral<T>::value;
+ typedef typename std::conditional<IsInt, int, T>::type TT;
+
+ T entry;
+
+public:
+ T* get() { return &entry; }
+ void operator=(const T& v) { entry = v; }
+ operator TT() const { return entry; }
+
+ void operator<<(int bonus) {
+ assert(abs(bonus) <= D); // Ensure range is [-D, D]
+ static_assert(D <= std::numeric_limits<T>::max(), "D overflows T");
+
+ entry += bonus - entry * abs(bonus) / D;
+
+ assert(abs(entry) <= D);