Bitboard ForwardRanksBB[COLOR_NB][RANK_NB];
Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
Bitboard LineBB[SQUARE_NB][SQUARE_NB];
-Bitboard DistanceRingBB[SQUARE_NB][8];
+Bitboard DistanceRingBB[SQUARE_NB][FILE_NB];
Bitboard ForwardFileBB[COLOR_NB][SQUARE_NB];
Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
namespace {
+#ifdef LARGEBOARDS
+ Bitboard RookTable[0xA80000]; // To store rook attacks
+ Bitboard BishopTable[0x33C00]; // To store bishop attacks
+#else
Bitboard RookTable[0x19000]; // To store rook attacks
Bitboard BishopTable[0x1480]; // To store bishop attacks
+#endif
+
+#ifdef PRECOMPUTED_MAGICS
+#define B(a, b) (Bitboard(a) << 64) ^ Bitboard(b)
+ // Use precomputed magics if pext is not avaible,
+ // since the magics generation is very slow.
+ Bitboard RookMagicInit[SQUARE_NB] = {
+ B(0x4068000028000894, 0x20006051028),
+ B(0x2004000042000004, 0x2810000008004000),
+ B(0x1020000220004000, 0x8004290180020200),
+ B(0x4310000101000020, 0x8020100004002000),
+ B(0x38000080211108, 0x118000104000000),
+ B(0x4050000080400004, 0x2011040500118010),
+ B(0x4010000048100200, 0x100000840204000),
+ B(0x4020000820000100, 0x410106024000804),
+ B(0x910000008D00021, 0x800004400100010),
+ B(0x6830000821080004, 0x80C00010100000),
+ B(0x8040000040500008, 0x200031840804901),
+ B(0x4018000042201000, 0x8300002D80000841),
+ B(0x100008000044000, 0x1980020094A89400),
+ B(0x1000004000082000, 0x4408540710000181),
+ B(0x1206010001100802, 0x40004100048),
+ B(0x984010000410001, 0x208080028AE),
+ B(0x411210000261014, 0x8000414100011208),
+ B(0x8200100000B0002, 0x1082008404000008),
+ B(0x5004090000400096, 0x10004020001000E2),
+ B(0x8899220000020001, 0x8401004904082000),
+ B(0x801720000080040, 0x101000200082020),
+ B(0x800060000102411, 0xA8200008808400),
+ B(0x30C0000081004, 0x1004200082100418),
+ B(0x1018010000020102, 0x4100000040014082),
+ B(0x24000008000001, 0x4080041809020000),
+ B(0x3011200814000104, 0x2110004020000000),
+ B(0x1814410050000800, 0x4041010220000400),
+ B(0x20B002010000211, 0x100104188808),
+ B(0x821020000114, 0x22080A0200304020),
+ B(0xC0E0020000082, 0x1004108210042000),
+ B(0x9010010000084, 0x2000011014020406),
+ B(0x400208018000040, 0x20D000052800018),
+ B(0x108008000080, 0x240400000104),
+ B(0x8012001080004400, 0x102010420201000),
+ B(0x1000000C0001210, 0x821000080441200),
+ B(0x1C500000200004D0, 0x20042084400410),
+ B(0x4000284000108000, 0x1809420810080140),
+ B(0x40804004000, 0x2220005410000000),
+ B(0x4007080A1020000, 0x8004020D41200020),
+ B(0x1080000800008000, 0x4080210000002002),
+ B(0x400000400250000, 0x8000001100410000),
+ B(0xC8010090010001, 0x2004000068009022),
+ B(0x8300200008210000, 0x410804100111004),
+ B(0x42150008210000, 0x81100004A400200),
+ B(0x2C1410001810001, 0x8200800000411020),
+ B(0x28420004020000, 0x409002880830900),
+ B(0x200028000008000, 0x8100000040200004),
+ B(0x4001030120000, 0x41008A020140404),
+ B(0x288000004240804, 0x2410020000090),
+ B(0x104202000004004, 0x2008010000040),
+ B(0x800A020008022020, 0x4112108040400),
+ B(0x90044001082420, 0x239806020040A),
+ B(0x4018000414800030, 0x2001100010000),
+ B(0x102820010088120, 0x8002004090008),
+ B(0x280100200000410, 0x840441100000),
+ B(0x4A020000040020, 0x10820040C0881),
+ B(0x20000010020, 0x21000800402010),
+ B(0x161A0400212C80, 0x42000400203002),
+ B(0xAB00800181208440, 0x3120A01004040),
+ B(0x261100084025060, 0x81800A2100400),
+ B(0x1008000000A02000, 0x940000010040910),
+ B(0x1406400004A010, 0x100011080188C05),
+ B(0x400002000011000, 0x2080005008080002),
+ B(0x402C1004012, 0x600004200488003),
+ B(0x1800080802000409, 0x200012061200104),
+ B(0x843020018100800, 0xE2000040100E0A04),
+ B(0xA0010200005048, 0x80000851000012),
+ B(0x20000900041, 0x200006904002024),
+ B(0x20010000080002, 0x100000490211000),
+ B(0x1000018070C, 0x4100008200400010),
+ B(0x40000004101060, 0x40000109A800112),
+ B(0x44000908010404, 0x2200000420010409),
+ B(0x169D042288081204, 0x18000040A000),
+ B(0x1000041002000, 0x6040040001208000),
+ B(0x130040088200DA, 0x81600004010300),
+ B(0x3000062004000220, 0x8404200010200020),
+ B(0xC000102000020A, 0x108200004001000),
+ B(0x2000008606120000, 0xC010200008010821),
+ B(0x80040200000100, 0x80080000800440),
+ B(0x508028000040100, 0x4280000800124),
+ B(0x5AA422000B810100, 0xA802200002004404),
+ B(0x10000A0000012100, 0x8080200000400802),
+ B(0x240048004008102, 0x200400010800100),
+ B(0x4140030108004, 0x8C012000024909A0),
+ B(0x1400018A0A8000, 0x90841080008200),
+ B(0xA500120088001010, 0x4040020200008042),
+ B(0x5008024008888001, 0x1A0200A00005000),
+ B(0x4004D13000026, 0x800008008000A012),
+ B(0x201501022901000E, 0x8000024100001102),
+ B(0xE80010140000800C, 0x20004B1080000820),
+ B(0x8011010100046A00, 0x90010000C021),
+ B(0x1008020008401440, 0x80900020000E088),
+ B(0x100088000040000, 0x8124800080002200),
+ B(0x12C04120401200, 0x410500E80004040B),
+ B(0x9904A0100020008, 0x800108400020040),
+ B(0x4000842405D0004, 0x10220200000080),
+ B(0x4000001080802010, 0x4040880A00200001),
+ B(0x4000001080802010, 0x4040880A00200001),
+ B(0x800002021008000, 0xA04000420020000C),
+ B(0x12A6020000304, 0x8290144200000),
+ B(0x102803020008, 0x40824014A0200000),
+ B(0x1400020080210008, 0x8001004000500000),
+ B(0x120000148212, 0x801C001003A00000),
+ B(0x2020002908040, 0x2000804140200000),
+ B(0x820000010080, 0x10A2020420200000),
+ B(0x508200022440, 0xB004001108800040),
+ B(0x8202004084010C81, 0xC081A03000400008),
+ B(0xB04080040204050, 0x1810028080200000),
+ B(0xAA20014010120001, 0x80308004022200),
+ B(0xAA20014010120001, 0x80308004022200),
+ B(0x208018020814020, 0x2004020200410A00),
+ B(0x6000801000002800, 0xC80121082004080),
+ B(0x84002080140202, 0x8000004100090100),
+ B(0x3100114050000, 0x2000818014000100),
+ B(0x280805000008A400, 0x401042000000300),
+ B(0x245A20000040401, 0x1000850102080200),
+ B(0x4010430000D00240, 0xD0800001201100),
+ B(0x20000080040, 0x9053000880500600),
+ B(0x1840000610021088, 0x440801002428400),
+ B(0x448814040010, 0x8410085020500600)
+ };
+ Bitboard BishopMagicInit[SQUARE_NB] = {
+ B(0x2001040305000010, 0x830200040400082),
+ B(0x1042400080E01200, 0x2004904010811400),
+ B(0x400010120200, 0x880080D080018000),
+ B(0x240190C00100040, 0x100A020140044404),
+ B(0x1018010404010004, 0x1001010018081E0),
+ B(0x41200A804C0904, 0x40000322000008),
+ B(0x4001180A004, 0x8000001106000000),
+ B(0x6006020020030600, 0x1840002100004841),
+ B(0x4200200100, 0x4001041808002000),
+ B(0x4100020050124600, 0x1001802902400CA0),
+ B(0x448C0081440161, 0x200206010008000),
+ B(0x400008008008408, 0x1000080210100080),
+ B(0x200280C01008200, 0x210200813000080),
+ B(0x1A000204400, 0x222200401023000),
+ B(0x10081040640A00, 0x8410021881400000),
+ B(0x1840400318080008, 0x800800840080000),
+ B(0x4204050C040, 0x6500600200140000),
+ B(0x1012100040204, 0x402404444400000),
+ B(0x6000012680008240, 0x410140000004220),
+ B(0x1000020810040008, 0x2D0011000060000),
+ B(0x1020020400, 0x400108059001001),
+ B(0x400020001100808, 0x480204800200000B),
+ B(0x10000010030084, 0x2042000848900022),
+ B(0x10000010030084, 0x2042000848900022),
+ B(0x100D801402400, 0x1512404009000400),
+ B(0x8000208005112400, 0xA02040401000000),
+ B(0x1000420002800200, 0x4CA000183020000),
+ B(0x800811480020, 0x408801010224001),
+ B(0xC805200810900100, 0x9000084204004020),
+ B(0x8200160204100004, 0x8040004004002022),
+ B(0x104514013080080, 0x146410040001000),
+ B(0x140844000080002, 0x1008102020040001),
+ B(0x4040400041A2002, 0x8040000A8802510),
+ B(0x801014041008002, 0x80068008025200),
+ B(0xA00540A414040, 0x4101040010A0000),
+ B(0x6484008010810002, 0x1100506884024000),
+ B(0x2800401008006000, 0x1005420884029020),
+ B(0x6822091010004421, 0x2000458080480),
+ B(0x40101000200101, 0x10020100001C4E0),
+ B(0x100400008C42, 0x4000100009008000),
+ B(0x851220018800400, 0x1681800040080080),
+ B(0x64200002010, 0x900020200040002),
+ B(0x20800080000022, 0x80040810002010),
+ B(0xA88408000802080, 0x20808001000000),
+ B(0x200000400C005040, 0x100140020290108),
+ B(0x224100000800408, 0x4204802004400020),
+ B(0x80080620010210, 0x91080088804040),
+ B(0x4008002100010, 0x80AC201001000001),
+ B(0x10008200902C046, 0x8080D03004000010),
+ B(0x3002100081000180, 0x2210002121528408),
+ B(0x8C101800804420, 0x1019880200043008),
+ B(0x200022000920D0, 0x8000800081300020),
+ B(0x1D40800880000, 0x400040001400050),
+ B(0x2020004100040, 0x200008040008008),
+ B(0x4840800040100001, 0x100100040203040),
+ B(0x40084001105, 0x8800080088000089),
+ B(0x4000128008020008, 0x4004200200440020),
+ B(0x210040008520000, 0x820219001080022),
+ B(0x1494040018002116, 0x400101047020008),
+ B(0x510008001910C224, 0x80200148118000),
+ B(0xC0301002301000, 0x4211A08004801),
+ B(0x50008E0C01001080, 0x100C004102845100),
+ B(0x400600020060400, 0x88024100250050),
+ B(0x8202920002002040, 0x810012000003),
+ B(0x800004208800200, 0x18AA00201000048),
+ B(0x402100800100002, 0x411000081000400),
+ B(0x101000022004044, 0x9000100040000),
+ B(0x41068001001, 0xC00400010001),
+ B(0x310210001040, 0x1A1200020010000),
+ B(0xA082409200004048, 0x490040800124101),
+ B(0x18844820E0040212, 0x1000404420D10000),
+ B(0x802908A40003348, 0x20200040104140),
+ B(0x1800404028205003, 0xC020010401089020),
+ B(0x802100044D01000, 0x8C41888000800040),
+ B(0x1D0161011410081, 0x10008000100200),
+ B(0x401000480040100, 0x286800404002212),
+ B(0x821030000100009, 0x2000090200A00000),
+ B(0x200020800200800, 0x2000480900841012),
+ B(0x80A000048030080, 0x200000120200008),
+ B(0x40B1400008020020, 0x148000200008004),
+ B(0xA021700002002010, 0x3040E400040100),
+ B(0x400242C200200640, 0x20440210200281),
+ B(0x80AC140040206240, 0x120000102801401),
+ B(0x2020340040832040, 0x10402100A44000),
+ B(0x420100400040220, 0x80014C8004000106),
+ B(0x504300822421120, 0x8004004008400100),
+ B(0x2001100008040, 0x2020104302000000),
+ B(0xA500802000A, 0x2008008000114100),
+ B(0x8A0020000200, 0x9C00101001002408),
+ B(0x104000001001008, 0x9001000204040060),
+ B(0x1000820080108200, 0xA401000008100001),
+ B(0x2008600009000480, 0x9008020001400000),
+ B(0x4000800200040200, 0xA00030400308082),
+ B(0x4004300202004709, 0x1000100180010020),
+ B(0xC014800100440010, 0x402020280002C010),
+ B(0x220208010884680, 0x1040280000042110),
+ B(0x40B0018019202801, 0x1008408000100040),
+ B(0x8269010206080044, 0x8001810000000040),
+ B(0x4000020880081040, 0x208A44000028000),
+ B(0x4004004E9004220A, 0x2104004001400024),
+ B(0x8035006008C0904, 0x402002001080120),
+ B(0x1800884002, 0x404400820000000),
+ B(0x8088000004008910, 0x8024100401000000),
+ B(0x142200086000100, 0x28021040020002E),
+ B(0x1000409141004018, 0x100410820080040A),
+ B(0x1800801800140, 0x810801060C0801),
+ B(0x1000C00100402220, 0x808023420000000),
+ B(0x8A0A202414305008, 0x100040200000021),
+ B(0xC0208024050, 0x8003088008020401),
+ B(0x8044004201440101, 0x400820080C024022),
+ B(0x406018884120099, 0xB00088018002000),
+ B(0x2000800010403010, 0xC5A002002010010),
+ B(0x800020040840, 0x201800202800200),
+ B(0x201280120020008D, 0x258809001000040),
+ B(0x9100002020181, 0x80400082204000),
+ B(0x104010080201001, 0x40080080181080),
+ B(0x8440248092000430, 0xA200804900100000),
+ B(0x2031010C01000C20, 0x200310A560082008),
+ B(0x400202081811400, 0x40081802050000C),
+ B(0x1011002100821300, 0x2400825040804100)
+ };
+#undef B
+#endif
+#ifdef PRECOMPUTED_MAGICS
+ void init_magics(Bitboard table[], Magic magics[], Direction directions[], Bitboard magicsInit[]);
+#else
void init_magics(Bitboard table[], Magic magics[], Direction directions[]);
+#endif
// popcount16() counts the non-zero bits using SWAR-Popcount algorithm
return (u * 0x0101U) >> 8;
}
- Bitboard sliding_attack(Direction directions[], Square sq, Bitboard occupied, int maxDist = 7) {
+ Bitboard sliding_attack(Direction directions[], Square sq, Bitboard occupied, int maxDist = FILE_MAX, Color c = WHITE) {
Bitboard attack = 0;
for (int i = 0; directions[i]; ++i)
- for (Square s = sq + directions[i];
- is_ok(s) && distance(s, s - directions[i]) == 1 && distance(s, sq) <= maxDist;
- s += directions[i])
+ for (Square s = sq + (c == WHITE ? directions[i] : -directions[i]);
+ is_ok(s) && distance(s, s - (c == WHITE ? directions[i] : -directions[i])) == 1 && distance(s, sq) <= maxDist;
+ s += (c == WHITE ? directions[i] : -directions[i]))
{
attack |= s;
std::string s = "+---+---+---+---+---+---+---+---+\n";
- for (Rank r = RANK_8; r >= RANK_1; --r)
+ for (Rank r = RANK_MAX; r >= RANK_1; --r)
{
- for (File f = FILE_A; f <= FILE_H; ++f)
+ for (File f = FILE_A; f <= FILE_MAX; ++f)
s += b & make_square(f, r) ? "| X " : "| ";
s += "|\n+---+---+---+---+---+---+---+---+\n";
for (unsigned i = 0; i < (1 << 16); ++i)
PopCnt16[i] = (uint8_t) popcount16(i);
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
+ for (Square s = SQ_A1; s <= SQ_MAX; ++s)
SquareBB[s] = make_bitboard(s);
- for (File f = FILE_A; f <= FILE_H; ++f)
+ for (File f = FILE_A; f <= FILE_MAX; ++f)
FileBB[f] = f > FILE_A ? FileBB[f - 1] << 1 : FileABB;
- for (Rank r = RANK_1; r <= RANK_8; ++r)
- RankBB[r] = r > RANK_1 ? RankBB[r - 1] << 8 : Rank1BB;
+ for (Rank r = RANK_1; r <= RANK_MAX; ++r)
+ RankBB[r] = r > RANK_1 ? RankBB[r - 1] << FILE_NB : Rank1BB;
- for (File f = FILE_A; f <= FILE_H; ++f)
- AdjacentFilesBB[f] = (f > FILE_A ? FileBB[f - 1] : 0) | (f < FILE_H ? FileBB[f + 1] : 0);
+ for (File f = FILE_A; f <= FILE_MAX; ++f)
+ AdjacentFilesBB[f] = (f > FILE_A ? FileBB[f - 1] : 0) | (f < FILE_MAX ? FileBB[f + 1] : 0);
- for (Rank r = RANK_1; r < RANK_8; ++r)
+ for (Rank r = RANK_1; r < RANK_MAX; ++r)
ForwardRanksBB[WHITE][r] = ~(ForwardRanksBB[BLACK][r + 1] = ForwardRanksBB[BLACK][r] | RankBB[r]);
for (Color c = WHITE; c <= BLACK; ++c)
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
+ for (Square s = SQ_A1; s <= SQ_MAX; ++s)
{
ForwardFileBB [c][s] = ForwardRanksBB[c][rank_of(s)] & FileBB[file_of(s)];
PawnAttackSpan[c][s] = ForwardRanksBB[c][rank_of(s)] & AdjacentFilesBB[file_of(s)];
PassedPawnMask[c][s] = ForwardFileBB [c][s] | PawnAttackSpan[c][s];
}
- for (File f = FILE_A; f <= FILE_H; ++f)
- for (Rank r = RANK_1; r <= RANK_8; ++r)
+ for (File f = FILE_A; f <= FILE_MAX; ++f)
+ for (Rank r = RANK_1; r <= RANK_MAX; ++r)
BoardSizeBB[f][r] = ForwardFileBB[BLACK][make_square(f, r)] | SquareBB[make_square(f, r)] | (f > FILE_A ? BoardSizeBB[f - 1][r] : 0);
- for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
- for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
+ for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1)
+ for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2)
if (s1 != s2)
{
SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2));
Direction RookDirections[5] = { NORTH, EAST, SOUTH, WEST };
Direction BishopDirections[5] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
+#ifdef PRECOMPUTED_MAGICS
+ init_magics(RookTable, RookMagics, RookDirections, RookMagicInit);
+ init_magics(BishopTable, BishopMagics, BishopDirections, BishopMagicInit);
+#else
init_magics(RookTable, RookMagics, RookDirections);
init_magics(BishopTable, BishopMagics, BishopDirections);
+#endif
int stepsCapture[][13] = {
{}, // NO_PIECE_TYPE
- { 7, 9 }, // pawn
- { -17, -15, -10, -6, 6, 10, 15, 17 }, // knight
+ { NORTH_WEST, NORTH_EAST }, // pawn
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knight
{}, // bishop
{}, // rook
{}, // queen
- { -9, -7, 7, 9 }, // fers/met
- { -18, -14, 14, 18 }, // alfil
- { -9, -7, 7, 8, 9 }, // silver/khon
- { -17, -15, -10, -9, -7, -6, 6, 7, 9, 10, 15, 17 }, // aiwok
- { -9, -7, 7, 9 }, // bers/dragon
- { -17, -15, -10, -6, 6, 10, 15, 17 }, // chancellor
- { -17, -15, -10, -6, 6, 10, 15, 17 }, // amazon
+ { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // fers/met
+ { 2 * SOUTH_WEST, 2 * SOUTH_EAST, 2 * NORTH_WEST, 2 * NORTH_EAST }, // alfil
+ { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH, NORTH_EAST }, // silver/khon
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH_WEST, SOUTH_EAST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH_WEST, NORTH_EAST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // aiwok
+ { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // bers/dragon
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // chancellor
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // amazon
{}, // knibis
- { -17, -15, -10, -6, 6, 10, 15, 17 }, // biskni
- { 8 }, // shogi pawn
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // biskni
+ { NORTH }, // shogi pawn
{}, // lance
- { 15, 17 }, // shogi knight
- { -1, 1, 15, 17 }, // euroshogi knight
- { -8, -1, 1, 7, 8, 9 }, // gold
- { -8, -1, 1, 8 }, // horse
- { -8, -1, 1, 8 }, // clobber
- { 7, 9 }, // breakthrough
+ { 2 * NORTH + WEST, 2 * NORTH + EAST }, // shogi knight
+ { WEST, EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // euroshogi knight
+ { SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // gold
+ { SOUTH, WEST, EAST, NORTH }, // horse
+ { SOUTH, WEST, EAST, NORTH }, // clobber
+ { NORTH_WEST, NORTH_EAST }, // breakthrough
{}, // immobile
- { -9, -8, -7, -1, 1, 7, 8, 9 }, // commoner
- { -9, -8, -7, -1, 1, 7, 8, 9 } // king
+ { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // commoner
+ { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST } // king
};
int stepsQuiet[][13] = {
{}, // NO_PIECE_TYPE
- { 8 }, // pawn
- { -17, -15, -10, -6, 6, 10, 15, 17 }, // knight
+ { NORTH }, // pawn
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knight
{}, // bishop
{}, // rook
{}, // queen
- { -9, -7, 7, 9 }, // fers/met
- { -18, -14, 14, 18 }, // alfil
- { -9, -7, 7, 8, 9 }, // silver/khon
- { -17, -15, -10, -9, -7, -6, 6, 7, 9, 10, 15, 17 }, // aiwok
- { -9, -7, 7, 9 }, // bers/dragon
- { -17, -15, -10, -6, 6, 10, 15, 17 }, // chancellor
- { -17, -15, -10, -6, 6, 10, 15, 17 }, // amazon
- { -17, -15, -10, -6, 6, 10, 15, 17 }, // knibis
+ { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // fers/met
+ { 2 * SOUTH_WEST, 2 * SOUTH_EAST, 2 * NORTH_WEST, 2 * NORTH_EAST }, // alfil
+ { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH, NORTH_EAST }, // silver/khon
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH_WEST, SOUTH_EAST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH_WEST, NORTH_EAST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // aiwok
+ { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // bers/dragon
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // chancellor
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // amazon
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knibis
{}, // biskni
- { 8 }, // shogi pawn
+ { NORTH }, // shogi pawn
{}, // lance
- { 15, 17 }, // shogi knight
- { -1, 1, 15, 17 }, // euroshogi knight
- { -8, -1, 1, 7, 8, 9 }, // gold
- { -8, -1, 1, 8 }, // horse
+ { 2 * NORTH + WEST, 2 * NORTH + EAST }, // shogi knight
+ { WEST, EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // euroshogi knight
+ { SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // gold
+ { SOUTH, WEST, EAST, NORTH }, // horse
{}, // clobber
- { 7, 8, 9 }, // breakthrough
+ { NORTH_WEST, NORTH, NORTH_EAST }, // breakthrough
{}, // immobile
- { -9, -8, -7, -1, 1, 7, 8, 9 }, // commoner
- { -9, -8, -7, -1, 1, 7, 8, 9 } // king
+ { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // commoner
+ { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST } // king
};
Direction sliderCapture[][9] = {
{}, // NO_PIECE_TYPE
0, // NO_PIECE_TYPE
0, // pawn
0, // knight
- 7, // bishop
- 7, // rook
- 7, // queen
+ FILE_MAX, // bishop
+ FILE_MAX, // rook
+ FILE_MAX, // queen
0, // fers/met
0, // alfil
0, // silver/khon
- 7, // aiwok
- 7, // bers/dragon
- 7, // chancellor
- 7, // amazon
- 7, // knibis
+ FILE_MAX, // aiwok
+ FILE_MAX, // bers/dragon
+ FILE_MAX, // chancellor
+ FILE_MAX, // amazon
+ FILE_MAX, // knibis
0, // biskni
0, // shogi pawn
- 7, // lance
+ FILE_MAX, // lance
0, // shogi knight
0, // euroshogi knight
0, // gold
- 7, // horse
+ FILE_MAX, // horse
0, // clobber
0, // breakthrough
0, // immobile
0, // NO_PIECE_TYPE
0, // pawn
0, // knight
- 7, // bishop
- 7, // rook
- 7, // queen
+ FILE_MAX, // bishop
+ FILE_MAX, // rook
+ FILE_MAX, // queen
0, // fers/met
0, // alfil
0, // silver/khon
- 7, // aiwok
- 7, // bers/dragon
- 7, // chancellor
- 7, // amazon
+ FILE_MAX, // aiwok
+ FILE_MAX, // bers/dragon
+ FILE_MAX, // chancellor
+ FILE_MAX, // amazon
0, // knibis
- 7, // biskni
+ FILE_MAX, // biskni
0, // shogi pawn
- 7, // lance
+ FILE_MAX, // lance
0, // shogi knight
0, // euroshogi knight
0, // gold
- 7, // horse
+ FILE_MAX, // horse
0, // clobber
0, // breakthrough
0, // immobile
for (Color c = WHITE; c <= BLACK; ++c)
for (PieceType pt = PAWN; pt <= KING; ++pt)
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
+ for (Square s = SQ_A1; s <= SQ_MAX; ++s)
{
for (int i = 0; stepsCapture[pt][i]; ++i)
{
LeaperMoves[c][pt][s] |= to;
}
}
- PseudoAttacks[c][pt][s] |= sliding_attack(sliderCapture[pt], s, 0, sliderDistCapture[pt]);
- PseudoMoves[c][pt][s] |= sliding_attack(sliderQuiet[pt], s, 0, sliderDistQuiet[pt]);
+ PseudoAttacks[c][pt][s] |= sliding_attack(sliderCapture[pt], s, 0, sliderDistCapture[pt], c);
+ PseudoMoves[c][pt][s] |= sliding_attack(sliderQuiet[pt], s, 0, sliderDistQuiet[pt], c);
}
- for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
+ for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1)
{
for (PieceType pt : { BISHOP, ROOK })
- for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
+ for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2)
{
if (!(PseudoAttacks[WHITE][pt][s1] & s2))
continue;
// chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we
// use the so called "fancy" approach.
+#ifdef PRECOMPUTED_MAGICS
+ void init_magics(Bitboard table[], Magic magics[], Direction directions[], Bitboard magicsInit[]) {
+#else
void init_magics(Bitboard table[], Magic magics[], Direction directions[]) {
+#endif
// Optimal PRNG seeds to pick the correct magics in the shortest time
+#ifndef PRECOMPUTED_MAGICS
+#ifdef LARGEBOARDS
+ int seeds[][RANK_NB] = { {},
+ { 734, 10316, 55013, 32803, 12281, 15100, 16645, 255, 346, 89123} };
+#else
int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 },
{ 728, 10316, 55013, 32803, 12281, 15100, 16645, 255 } };
+#endif
+#endif
+
+ Bitboard* occupancy = new Bitboard[1 << (FILE_NB + RANK_NB - 4)];
+ Bitboard* reference = new Bitboard[1 << (FILE_NB + RANK_NB - 4)];
+ Bitboard edges, b;
+ int* epoch = new int[1 << (FILE_NB + RANK_NB - 4)]();
+ int cnt = 0, size = 0;
- Bitboard occupancy[4096], reference[4096], edges, b;
- int epoch[4096] = {}, cnt = 0, size = 0;
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
+ for (Square s = SQ_A1; s <= SQ_MAX; ++s)
{
// Board edges are not considered in the relevant occupancies
- edges = ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s));
+ edges = ((Rank1BB | rank_bb(RANK_MAX)) & ~rank_bb(s)) | ((FileABB | file_bb(FILE_MAX)) & ~file_bb(s));
// Given a square 's', the mask is the bitboard of sliding attacks from
// 's' computed on an empty board. The index must be big enough to contain
// apply to the 64 or 32 bits word to get the index.
Magic& m = magics[s];
m.mask = sliding_attack(directions, s, 0) & ~edges;
+#ifdef LARGEBOARDS
+ m.shift = 128 - popcount(m.mask);
+#else
m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
+#endif
// Set the offset for the attacks table of the square. We have individual
// table sizes for each square with "Fancy Magic Bitboards".
if (HasPext)
continue;
+#ifndef PRECOMPUTED_MAGICS
PRNG rng(seeds[Is64Bit][rank_of(s)]);
+#endif
// Find a magic for square 's' picking up an (almost) random number
// until we find the one that passes the verification test.
for (int i = 0; i < size; )
{
- for (m.magic = 0; popcount((m.magic * m.mask) >> 56) < 6; )
+ for (m.magic = 0; popcount(((m.magic * m.mask) & AllSquares) >> (SQUARE_NB - FILE_NB)) < FILE_NB - 2; )
+ {
+#ifdef LARGEBOARDS
+#ifdef PRECOMPUTED_MAGICS
+ m.magic = magicsInit[s];
+#else
+ m.magic = (rng.sparse_rand<Bitboard>() << 64) ^ rng.sparse_rand<Bitboard>();
+#endif
+#else
m.magic = rng.sparse_rand<Bitboard>();
+#endif
+ }
// A good magic must map every possible occupancy to an index that
// looks up the correct sliding attack in the attacks[s] database.
}
}
}
+
+ delete[] occupancy;
+ delete[] reference;
+ delete[] epoch;
}
}
#if defined(USE_PEXT)
# include <immintrin.h> // Header for _pext_u64() intrinsic
-# define pext(b, m) _pext_u64(b, m)
+# ifdef LARGEBOARDS
+# define pext(b, m) (_pext_u64(b, m) ^ (_pext_u64(b >> 64, m >> 64) << popcount((m << 64) >> 64)))
+# else
+# define pext(b, m) _pext_u64(b, m)
+# endif
#else
# define pext(b, m) 0
#endif
#endif
typedef uint64_t Key;
+#ifdef LARGEBOARDS
+typedef unsigned __int128 Bitboard;
+constexpr int SQUARE_BITS = 7;
+#else
typedef uint64_t Bitboard;
+constexpr int SQUARE_BITS = 6;
+#endif
constexpr int MAX_MOVES = 512;
constexpr int MAX_PLY = 128;
enum Move : int {
MOVE_NONE,
- MOVE_NULL = 65
+ MOVE_NULL = 1 + (1 << SQUARE_BITS)
};
-enum MoveType {
+enum MoveType : int {
NORMAL,
- ENPASSANT = 1 << 12,
- CASTLING = 2 << 12,
- PROMOTION = 3 << 12,
- DROP = 4 << 12,
- PIECE_PROMOTION = 5 << 12,
+ ENPASSANT = 1 << (2 * SQUARE_BITS),
+ CASTLING = 2 << (2 * SQUARE_BITS),
+ PROMOTION = 3 << (2 * SQUARE_BITS),
+ DROP = 4 << (2 * SQUARE_BITS),
+ PIECE_PROMOTION = 5 << (2 * SQUARE_BITS),
};
enum Color {
static_assert(!(ONE_PLY & (ONE_PLY - 1)), "ONE_PLY is not a power of 2");
enum Square : int {
+#ifdef LARGEBOARDS
+ SQ_A1, SQ_B1, SQ_C1, SQ_D1, SQ_E1, SQ_F1, SQ_G1, SQ_H1, SQ_I1, SQ_J1, SQ_K1, SQ_L1,
+ SQ_A2, SQ_B2, SQ_C2, SQ_D2, SQ_E2, SQ_F2, SQ_G2, SQ_H2, SQ_I2, SQ_J2, SQ_K2, SQ_L2,
+ SQ_A3, SQ_B3, SQ_C3, SQ_D3, SQ_E3, SQ_F3, SQ_G3, SQ_H3, SQ_I3, SQ_J3, SQ_K3, SQ_L3,
+ SQ_A4, SQ_B4, SQ_C4, SQ_D4, SQ_E4, SQ_F4, SQ_G4, SQ_H4, SQ_I4, SQ_J4, SQ_K4, SQ_L4,
+ SQ_A5, SQ_B5, SQ_C5, SQ_D5, SQ_E5, SQ_F5, SQ_G5, SQ_H5, SQ_I5, SQ_J5, SQ_K5, SQ_L5,
+ SQ_A6, SQ_B6, SQ_C6, SQ_D6, SQ_E6, SQ_F6, SQ_G6, SQ_H6, SQ_I6, SQ_J6, SQ_K6, SQ_L6,
+ SQ_A7, SQ_B7, SQ_C7, SQ_D7, SQ_E7, SQ_F7, SQ_G7, SQ_H7, SQ_I7, SQ_J7, SQ_K7, SQ_L7,
+ SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8, SQ_I8, SQ_J8, SQ_K8, SQ_L8,
+ SQ_A9, SQ_B9, SQ_C9, SQ_D9, SQ_E9, SQ_F9, SQ_G9, SQ_H9, SQ_I9, SQ_J9, SQ_K9, SQ_L9,
+ SQ_A10, SQ_B10, SQ_C10, SQ_D10, SQ_E10, SQ_F10, SQ_G10, SQ_H10, SQ_I10, SQ_J10, SQ_K10, SQ_L10,
+#else
SQ_A1, SQ_B1, SQ_C1, SQ_D1, SQ_E1, SQ_F1, SQ_G1, SQ_H1,
SQ_A2, SQ_B2, SQ_C2, SQ_D2, SQ_E2, SQ_F2, SQ_G2, SQ_H2,
SQ_A3, SQ_B3, SQ_C3, SQ_D3, SQ_E3, SQ_F3, SQ_G3, SQ_H3,
SQ_A6, SQ_B6, SQ_C6, SQ_D6, SQ_E6, SQ_F6, SQ_G6, SQ_H6,
SQ_A7, SQ_B7, SQ_C7, SQ_D7, SQ_E7, SQ_F7, SQ_G7, SQ_H7,
SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8,
+#endif
SQ_NONE,
- SQUARE_NB = 64
+#ifdef LARGEBOARDS
+ SQUARE_NB = 120,
+ SQUARE_BIT_MASK = 127,
+#else
+ SQUARE_NB = 64,
+ SQUARE_BIT_MASK = 63,
+#endif
+ SQ_MAX = SQUARE_NB - 1
};
enum Direction : int {
+#ifdef LARGEBOARDS
+ NORTH = 12,
+#else
NORTH = 8,
+#endif
EAST = 1,
SOUTH = -NORTH,
WEST = -EAST,
};
enum File : int {
- FILE_A, FILE_B, FILE_C, FILE_D, FILE_E, FILE_F, FILE_G, FILE_H, FILE_NB
+#ifdef LARGEBOARDS
+ FILE_A, FILE_B, FILE_C, FILE_D, FILE_E, FILE_F, FILE_G, FILE_H, FILE_I, FILE_J, FILE_K, FILE_L,
+#else
+ FILE_A, FILE_B, FILE_C, FILE_D, FILE_E, FILE_F, FILE_G, FILE_H,
+#endif
+ FILE_NB,
+ FILE_MAX = FILE_NB - 1
};
enum Rank : int {
- RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8, RANK_NB
+#ifdef LARGEBOARDS
+ RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8, RANK_9, RANK_10,
+#else
+ RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8,
+#endif
+ RANK_NB,
+ RANK_MAX = RANK_NB - 1
};
}
constexpr Square operator~(Square s) {
+#ifdef LARGEBOARDS
+ return Square(s - FILE_NB * (s / FILE_NB * 2 - RANK_MAX)); // Vertical flip SQ_A1 -> SQ_A10
+#else
return Square(s ^ SQ_A8); // Vertical flip SQ_A1 -> SQ_A8
+#endif
}
constexpr File operator~(File f) {
- return File(f ^ FILE_H); // Horizontal flip FILE_A -> FILE_H
+ return File(FILE_MAX - f); // Horizontal flip FILE_A -> FILE_H
}
constexpr Rank operator~(Rank r) {
- return Rank(r ^ RANK_8); // Vertical flip Rank_1 -> Rank_8
+ return Rank(RANK_MAX - r); // Vertical flip Rank_1 -> Rank_8
}
constexpr Piece operator~(Piece pc) {
}
constexpr Square make_square(File f, Rank r) {
- return Square((r << 3) + f);
+ return Square(r * FILE_NB + f);
}
constexpr Piece make_piece(Color c, PieceType pt) {
}
constexpr bool is_ok(Square s) {
- return s >= SQ_A1 && s <= SQ_H8;
+ return s >= SQ_A1 && s <= SQ_MAX;
}
constexpr File file_of(Square s) {
- return File(s & 7);
+ return File(s % FILE_NB);
}
constexpr Rank rank_of(Square s) {
- return Rank(s >> 3);
-}
-
-constexpr Square relative_square(Color c, Square s) {
- return Square(s ^ (c * 56));
+ return Rank(s / FILE_NB);
}
constexpr Rank relative_rank(Color c, Rank r, Rank maxRank = RANK_8) {
return relative_rank(c, rank_of(s), maxRank);
}
+constexpr Square relative_square(Color c, Square s) {
+#ifdef LARGEBOARDS
+ return make_square(file_of(s), relative_rank(c, s));
+#else
+ return Square(s ^ (c * 56));
+#endif
+}
+
inline bool opposite_colors(Square s1, Square s2) {
+#ifdef LARGEBOARDS
+ return int(s1 - (s1 % FILE_NB)) ^ int(s2 - (s2 % FILE_NB));
+#else
int s = int(s1) ^ int(s2);
return ((s >> 3) ^ s) & 1;
+#endif
}
constexpr Direction pawn_push(Color c) {
}
inline MoveType type_of(Move m) {
- return MoveType(m & (15 << 12));
+ return MoveType(m & (15 << (2 * SQUARE_BITS)));
}
constexpr Square to_sq(Move m) {
- return Square(m & 0x3F);
+ return Square(m & SQUARE_BIT_MASK);
}
inline Square from_sq(Move m) {
if (type_of(m) == DROP)
return SQ_NONE;
- return Square((m >> 6) & 0x3F);
+ return Square((m >> SQUARE_BITS) & SQUARE_BIT_MASK);
}
inline int from_to(Move m) {
- return to_sq(m) + (from_sq(m) << 6);
+ return to_sq(m) + (from_sq(m) << SQUARE_BITS);
}
inline PieceType promotion_type(Move m) {
- return type_of(m) == PROMOTION ? PieceType((m >> 16) & 63) : NO_PIECE_TYPE;
+ return type_of(m) == PROMOTION ? PieceType((m >> (2 * SQUARE_BITS + 4)) & (PIECE_TYPE_NB - 1)) : NO_PIECE_TYPE;
}
inline Move make_move(Square from, Square to) {
- return Move((from << 6) + to);
+ return Move((from << SQUARE_BITS) + to);
}
template<MoveType T>
inline Move make(Square from, Square to, PieceType pt = NO_PIECE_TYPE) {
- return Move((pt << 16) + T + (from << 6) + to);
+ return Move((pt << (2 * SQUARE_BITS + 4)) + T + (from << SQUARE_BITS) + to);
}
constexpr Move make_drop(Square to, PieceType pt) {
- return Move(DROP + (pt << 16) + to);
+ return Move((pt << (2 * SQUARE_BITS + 4)) + DROP + to);
}
constexpr PieceType dropped_piece_type(Move m) {
- return PieceType((m >> 16) & 63);
+ return PieceType((m >> (2 * SQUARE_BITS + 4)) & (PIECE_TYPE_NB - 1));
}
inline bool is_ok(Move m) {