#include "bitboard.h"
#include "bitcount.h"
-#include "rkiss.h"
+#include "misc.h"
Bitboard RookMasks[SQUARE_NB];
Bitboard RookMagics[SQUARE_NB];
void init_magics(Bitboard table[], Bitboard* attacks[], Bitboard magics[],
Bitboard masks[], unsigned shifts[], Square deltas[], Fn index) {
- int MagicBoosters[][RANK_NB] = { { 969, 1976, 2850, 542, 2069, 2852, 1708, 164 },
- { 3101, 552, 3555, 926, 834, 26, 2131, 1117 } };
- RKISS rk;
+ int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 },
+ { 728, 10316, 55013, 32803, 12281, 15100, 16645, 255 } };
Bitboard occupancy[4096], reference[4096], edges, b;
- int i, size, booster;
+ int i, size;
// attacks[s] is a pointer to the beginning of the attacks table for square 's'
attacks[SQ_A1] = table;
if (HasPext)
continue;
- booster = MagicBoosters[Is64Bit][rank_of(s)];
+ PRNG rng(seeds[Is64Bit][rank_of(s)]);
// Find a magic for square 's' picking up an (almost) random number
// until we find the one that passes the verification test.
do {
do
- magics[s] = rk.magic_rand<Bitboard>(booster);
+ magics[s] = rng.sparse_rand<Bitboard>();
while (popcount<Max15>((magics[s] * masks[s]) >> 56) < 6);
std::memset(attacks[s], 0, size * sizeof(Bitboard));
#define sync_cout std::cout << IO_LOCK
#define sync_endl std::endl << IO_UNLOCK
+
+/// xorshift64star Pseudo-Random Number Generator
+/// This class is based on original code written and dedicated
+/// to the public domain by Sebastiano Vigna (2014).
+/// It has the following characteristics:
+/// - Outputs 64-bit numbers
+/// - Passes Dieharder and SmallCrush test batteries
+/// - Does not require warm-up, no zeroland to escape
+/// - Internal state is a single 64-bit integer
+/// - Period is 2^64 - 1
+/// - Speed: 1.60 ns/call (Core i7 @3.40GHz)
+/// For further analysis see
+/// <http://vigna.di.unimi.it/ftp/papers/xorshift.pdf>
+
+class PRNG {
+
+ uint64_t x;
+
+ uint64_t rand64() {
+ x^=x>>12; x^=x<<25; x^=x>>27;
+ return x * 2685821657736338717LL;
+ }
+
+public:
+ PRNG(uint64_t seed) : x(seed) { assert(seed); }
+
+ template<typename T> T rand() { return T(rand64()); }
+
+ /// Special generator used to fast init magic numbers.
+ /// Output values only have 1/8th of their bits set on average.
+ template<typename T> T sparse_rand() { return T(rand64() & rand64() & rand64()); }
+};
+
#endif // #ifndef MISC_H_INCLUDED
#include "movegen.h"
#include "position.h"
#include "psqtab.h"
-#include "rkiss.h"
+#include "misc.h"
#include "thread.h"
#include "tt.h"
#include "uci.h"
void Position::init() {
- RKISS rk;
+ PRNG rng(1070372);
for (Color c = WHITE; c <= BLACK; ++c)
for (PieceType pt = PAWN; pt <= KING; ++pt)
for (Square s = SQ_A1; s <= SQ_H8; ++s)
- Zobrist::psq[c][pt][s] = rk.rand<Key>();
+ Zobrist::psq[c][pt][s] = rng.rand<Key>();
for (File f = FILE_A; f <= FILE_H; ++f)
- Zobrist::enpassant[f] = rk.rand<Key>();
+ Zobrist::enpassant[f] = rng.rand<Key>();
for (int cr = NO_CASTLING; cr <= ANY_CASTLING; ++cr)
{
while (b)
{
Key k = Zobrist::castling[1ULL << pop_lsb(&b)];
- Zobrist::castling[cr] ^= k ? k : rk.rand<Key>();
+ Zobrist::castling[cr] ^= k ? k : rng.rand<Key>();
}
}
- Zobrist::side = rk.rand<Key>();
- Zobrist::exclusion = rk.rand<Key>();
+ Zobrist::side = rng.rand<Key>();
+ Zobrist::exclusion = rng.rand<Key>();
for (PieceType pt = PAWN; pt <= KING; ++pt)
{
+++ /dev/null
-/*
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
-
- Stockfish is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Stockfish is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- This file is based on original code by Heinz van Saanen and is
- available under the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-*/
-
-#ifndef RKISS_H_INCLUDED
-#define RKISS_H_INCLUDED
-
-#include "types.h"
-
-/// RKISS is our pseudo random number generator (PRNG) used to compute hash keys.
-/// George Marsaglia invented the RNG-Kiss-family in the early 90's. This is a
-/// specific version that Heinz van Saanen derived from some public domain code
-/// by Bob Jenkins. Following the feature list, as tested by Heinz.
-///
-/// - Quite platform independent
-/// - Passes ALL dieharder tests! Here *nix sys-rand() e.g. fails miserably:-)
-/// - ~12 times faster than my *nix sys-rand()
-/// - ~4 times faster than SSE2-version of Mersenne twister
-/// - Average cycle length: ~2^126
-/// - 64 bit seed
-/// - Return doubles with a full 53 bit mantissa
-/// - Thread safe
-
-class RKISS {
-
- uint64_t a, b, c, d;
-
- uint64_t rotate_L(uint64_t x, unsigned k) const {
- return (x << k) | (x >> (64 - k));
- }
-
- uint64_t rand64() {
-
- const uint64_t e = a - rotate_L(b, 7);
- a = b ^ rotate_L(c, 13);
- b = c + rotate_L(d, 37);
- c = d + e;
- return d = e + a;
- }
-
-public:
- RKISS(int seed = 73) {
-
- a = 0xF1EA5EED, b = c = d = 0xD4E12C77;
-
- for (int i = 0; i < seed; ++i) // Scramble a few rounds
- rand64();
- }
-
- template<typename T> T rand() { return T(rand64()); }
-
- /// Special generator used to fast init magic numbers. Here the
- /// trick is to rotate the randoms of a given quantity 's' known
- /// to be optimal to quickly find a good magic candidate.
- template<typename T> T magic_rand(int s) {
- return rotate_L(rotate_L(rand<T>(), (s >> 0) & 0x3F) & rand<T>()
- , (s >> 6) & 0x3F) & rand<T>();
- }
-};
-
-#endif // #ifndef RKISS_H_INCLUDED
#include "evaluate.h"
#include "movegen.h"
#include "movepick.h"
-#include "rkiss.h"
+#include "misc.h"
#include "search.h"
#include "timeman.h"
#include "thread.h"
Move Skill::pick_move() {
- static RKISS rk;
-
- // PRNG sequence should be not deterministic
- for (int i = Time::now() % 50; i > 0; --i)
- rk.rand<unsigned>();
+ // PRNG sequence should be non-deterministic, so we seed it with the time at init
+ static PRNG rng(Time::now());
// RootMoves are already sorted by score in descending order
int variance = std::min(RootMoves[0].score - RootMoves[candidates - 1].score, PawnValueMg);
// This is our magic formula
score += ( weakness * int(RootMoves[0].score - score)
- + variance * (rk.rand<unsigned>() % weakness)) / 128;
+ + variance * (rng.rand<unsigned>() % weakness)) / 128;
if (score > maxScore)
{