diff --git a/.gitignore b/.gitignore index a8ebd7c..fe99feb 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,9 @@ bld/ # Visual Studio 2017 auto generated files Generated\ Files/ +# vscode stuff +.vscode + # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* @@ -350,4 +353,4 @@ MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ -/movegen_compare +/movegen_compare diff --git a/Kindergarten.hpp b/Kindergarten.hpp index 3e527d3..c95ea3f 100644 --- a/Kindergarten.hpp +++ b/Kindergarten.hpp @@ -11,385 +11,83 @@ namespace Chess_Lookup::Kindergarten { - constexpr std::array ranks_64 = []() - { - uint64_t ranks[8] = {}; - for (uint64_t i = 0; i < 8; i++) - { - ranks[i] = (uint64_t)(0b11111111) << (i * 8); - } - std::array ranks_64_ret = {}; - for (uint64_t i = 0; i < 64; i++) - { - ranks_64_ret[i] = ranks[i / 8]; - } - return ranks_64_ret; - }(); - constexpr std::array files_64 = []() - { - uint64_t files[8] = {}; - for (uint64_t i = 0; i < 8; i++) - { - files[i] = (uint64_t)(0b0000000100000001000000010000000100000001000000010000000100000001) << i; - } - std::array files_64_ret = {}; - for (uint64_t i = 0; i < 64; i++) - { - files_64_ret[i] = files[i % 8]; - } - return files_64_ret; - }(); - constexpr uint64_t upper_left_side_zero = 0b1000000011000000111000001111000011111000111111001111111011111111; - constexpr uint64_t lower_right_side_zero = 0b1111111101111111001111110001111100001111000001110000001100000001; - constexpr uint64_t lower_left_side_zero = 0b1111111011111100111110001111000011100000110000001000000000000000; - constexpr uint64_t upper_right_side_zero = 0b0000000000000001000000110000011100001111000111110011111101111111; - constexpr uint64_t main_diagonal = 0b1000000001000000001000000001000000001000000001000000001000000001; //A1 to H8 - constexpr uint64_t anti_diagonal = 0b0000000100000010000001000000100000010000001000000100000010000000; //H1 to A8 - constexpr std::array diagonals_64 = []() + constexpr uint64_t main_diagonal = 0b1000000001000000001000000001000000001000000001000000001000000001; // A1 to H8 + constexpr uint64_t first_file = 0b0000000100000001000000010000000100000001000000010000000100000001; + + uint64_t occ_for_square(const uint8_t hash_key, const int square, const std::array dirs, std::function hash_key_fn) { - std::array diagonals_64_ret = {}; - for (uint64_t i = 0; i < 8; i++) + uint64_t result = 0; + for (const int dir : dirs) { - uint64_t current_diagonal = (main_diagonal << i) & upper_left_side_zero; - uint64_t tmp = current_diagonal; - while (tmp != 0) + int cur = square; + while (true) { - uint64_t index = std::countr_zero(tmp); - diagonals_64_ret[index] = current_diagonal; - tmp = tmp & (~(1ull << index)); - } - } - for (uint64_t i = 1; i < 8; i++) - { - uint64_t current_diagonal = (main_diagonal >> i) & lower_right_side_zero; - uint64_t tmp = current_diagonal; - while (tmp != 0) - { - uint64_t index = std::countr_zero(tmp); - diagonals_64_ret[index] = current_diagonal; - tmp = tmp & ~(1ull << index); + cur += dir; + if (cur >= 64 || cur < 0 || abs((cur % 8) - ((cur - dir) % 8)) >= 2) + { + break; + } + const uint64_t bit = 1ULL << cur; + result |= bit; + + if (hash_key_fn(square, bit) & hash_key) + { + break; + } } } - return diagonals_64_ret; - }(); - constexpr std::array anti_diagonals_64 = []() + return result; + } + + template + auto collect_64(F f) { - std::array anti_diagonals_64_ret = {}; - for (int i = 1; i < 8; i++) - { - uint64_t current_anti_diagonal = (anti_diagonal << i) & lower_left_side_zero; - uint64_t tmp = current_anti_diagonal; - while (tmp != 0) - { - uint64_t index = std::countr_zero(tmp); - anti_diagonals_64_ret[index] = current_anti_diagonal; - tmp = tmp & ~(1ull << index); - } - } + std::array result; + for (int i = 0; i < 64; i++) { - uint64_t current_anti_diagonal = anti_diagonal; - uint64_t tmp = current_anti_diagonal; - while (tmp != 0) - { - uint64_t index = std::countr_zero(tmp); - anti_diagonals_64_ret[index] = current_anti_diagonal; - tmp = tmp & ~(1ull << index); - } - } - for (int i = 1; i < 8; i++) - { - uint64_t current_anti_diagonal = (anti_diagonal >> i) & upper_right_side_zero; - uint64_t tmp = current_anti_diagonal; - while (tmp != 0) - { - uint64_t index = std::countr_zero(tmp); - anti_diagonals_64_ret[index] = current_anti_diagonal; - tmp = tmp & ~(1ull << index); - } + result[i] = f(i); } - return anti_diagonals_64_ret; - }(); + return result; + } + + const std::array diagonals_64 = collect_64([](int i){ + return occ_for_square(0, i, {9, -9}, [](auto s, auto occ){ return 0; }); + }); + + const std::array anti_diagonals_64 = collect_64([](int i){ + return occ_for_square(0, i, {7, -7}, [](auto s, auto occ){ return 0; }); + }); - constexpr inline uint8_t hashkeyRank(const int& square, const uint64_t& occupancy) + constexpr inline uint8_t hashkey_rank(const int square, const uint64_t occupancy) { return ((occupancy >> ((square / 8) * 8)) >> 1) & 0b111111U; } - constexpr inline uint8_t hashkeyFile(const int& square, const uint64_t& occupancy) + constexpr inline uint8_t hashkey_file(const int square, const uint64_t occupancy) { - return (((((occupancy >> (square % 8)) & files_64[0]) * main_diagonal) >> 56) >> 1) & 0b111111U; + return (((((occupancy >> (square % 8)) & first_file) * main_diagonal) >> 56) >> 1) & 0b111111U; } - constexpr inline uint8_t hashkeyDiagonal(const int& square, const uint64_t& occupancy) + constexpr inline uint8_t hashkey_diagonal(const int square, const uint64_t occupancy) { - return ((((occupancy & diagonals_64[square]) * files_64[0]) >> 56) >> 1) & 0b111111U; + return ((((occupancy & diagonals_64[square]) * first_file) >> 56) >> 1) & 0b111111U; } - constexpr inline uint8_t hashkeyAntiDiagonal(const int& square, const uint64_t& occupancy) + constexpr inline uint8_t hashkey_anti_diagonal(const int square, const uint64_t occupancy) { - return ((((occupancy & anti_diagonals_64[square]) * files_64[0]) >> 56) >> 1) & 0b111111U; + return ((((occupancy & anti_diagonals_64[square]) * first_file) >> 56) >> 1) & 0b111111U; } - constexpr uint64_t north = 8; - constexpr uint64_t south = -8; - constexpr uint64_t east = 1; - constexpr uint64_t west = -1; - constexpr uint64_t north_east = 9; - constexpr uint64_t north_west = 7; - constexpr uint64_t south_west = -9; - constexpr uint64_t south_east = -7; - constexpr std::array possible_ranks = []() - { - std::array possible_ranks_ret = {}; - for (uint64_t i = 0; i < 64; i++) - { - uint64_t tmp = (uint64_t)(0b10000001) | (((uint64_t)(i)) << 1); - for (int j = 0; j < 8; j++) - { - possible_ranks_ret[i] |= tmp << (j * 8); - } - } - return possible_ranks_ret; - }(); - constexpr std::array possible_files = []() + std::array, 64> attack_table(const std::array dirs, std::function hash_key_fn) { - std::array possible_files_ret = {}; - for (uint64_t i = 0; i < 64; i++) - { - auto rankToFile = [&](uint64_t rank) - { - return (((rank & 0b11111111U) * main_diagonal) & files_64[7]) >> 7; - }; - uint64_t tmp = rankToFile((uint64_t)(0b10000001) | (((uint64_t)(i)) << 1)); - for (int j = 0; j < 8; j++) - { - possible_files_ret[i] |= tmp << j; - } - } - return possible_files_ret; - }(); - constexpr std::array, 64> rank_attack_table = []() - { - std::array, 64> rank_attack_table_ret = {}; - for (int index = 0; index < 64; index++) - { - for (uint64_t possible_ranks_index = 0; possible_ranks_index < 64; possible_ranks_index++) - { - uint64_t tmp_attack_mask = 0; - uint64_t occupancy = possible_ranks[possible_ranks_index]; - uint64_t i = index; - while (true) - { - i += east; - if (i >= 64) - { - break; - } - if (index % 8 == 7) - { - break; - } - if ((occupancy & (1ull << i)) != 0) - { - tmp_attack_mask |= (1ull << i); - break; - } - else - { - tmp_attack_mask |= (1ull << i); - } - } - i = index; - while (true) - { - i += west; - if (i >= 64) //equals i < 0) - { - break; - } - if (index % 8 == 0) - { - break; - } - if ((occupancy & (1ull << i)) != 0) - { - tmp_attack_mask |= (1ull << i); - break; - } - else - { - tmp_attack_mask |= (1ull << i); - } - } - rank_attack_table_ret[index][hashkeyRank(index, occupancy)] = tmp_attack_mask; - } - } - return rank_attack_table_ret; - }(); - constexpr std::array, 64> file_attack_table = []() - { - std::array, 64> file_attack_table_ret = {}; - for (int index = 0; index < 64; index++) - { - for (uint64_t possible_files_index = 0; possible_files_index < 64; possible_files_index++) - { - uint64_t tmp_attack_mask = 0; - uint64_t occupancy = possible_files[possible_files_index]; - uint64_t i = index; - while (true) - { - i += north; - if (i >= 64) - { - break; - } - if ((occupancy & (1ull << i)) != 0) - { - tmp_attack_mask |= (1ull << i); - break; - } - else - { - tmp_attack_mask |= (1ull << i); - } - } - i = index; - while (true) - { - i += south; - if (i >= 64/*equals i < 0*/) - { - break; - } - if ((occupancy & (1ull << i)) != 0) - { - tmp_attack_mask |= (1ull << i); - break; - } - else - { - tmp_attack_mask |= (1ull << i); - } - } - file_attack_table_ret[index][hashkeyFile(index, occupancy)] = tmp_attack_mask; - } - } - return file_attack_table_ret; - }(); - constexpr std::array, 64> diagonal_attack_table = []() - { - std::array, 64> diagonal_attack_table_ret = {}; - for (int index = 0; index < 64; index++) - { - for (uint64_t possible_ranks_index = 0; possible_ranks_index < 64; possible_ranks_index++) - { - uint64_t tmp_attack_mask = 0; - uint64_t occupancy = possible_ranks[possible_ranks_index]; - uint64_t i = index; - while (true) - { - i += north_east; - if (i >= 64) - { - break; - } - if (index % 8 == 7) - { - break; - } - if ((occupancy & (1ull << i)) != 0) - { - tmp_attack_mask |= (1ull << i); - break; - } - else - { - tmp_attack_mask |= (1ull << i); - } - } - i = index; - while (true) - { - i += south_west; + return collect_64([&](int square){ + return collect_64([&](int hash_key){ + return occ_for_square(hash_key, square, dirs, hash_key_fn); + }); + }); + } - if (i >= 64/*equals i < 0*/) - { - break; - } - if (index % 8 == 0) - { - break; - } - if ((occupancy & (1ull << i)) != 0) - { - tmp_attack_mask |= (1ull << i); - break; - } - else - { - tmp_attack_mask |= (1ull << i); - } - } - diagonal_attack_table_ret[index][hashkeyDiagonal(index, occupancy)] = tmp_attack_mask; - } - } - return diagonal_attack_table_ret; - }(); - constexpr std::array, 64> anti_diagonal_attack_table = []() - { - std::array, 64> anti_diagonal_attack_table_ret = {}; - for (int index = 0; index < 64; index++) - { - for (uint64_t possible_ranks_index = 0; possible_ranks_index < 64; possible_ranks_index++) - { - uint64_t tmp_attack_mask = 0; - uint64_t occupancy = possible_ranks[possible_ranks_index]; - uint64_t i = index; - while (true) - { - i += north_west; - if (i >= 64) - { - break; - } - if (index % 8 == 0) - { - break; - } - if ((occupancy & (1ull << i)) != 0) - { - tmp_attack_mask |= (1ull << i); - break; - } - else - { - tmp_attack_mask |= (1ull << i); - } - } - i = index; - while (true) - { - i += south_east; - if (i >= 64/*equals i < 0*/) - { - break; - } - if (index % 8 == 7) - { - break; - } - if ((occupancy & (1ull << i)) != 0) - { - tmp_attack_mask |= (1ull << i); - break; - } - else - { - tmp_attack_mask |= (1ull << i); - } - } - anti_diagonal_attack_table_ret[index][hashkeyAntiDiagonal(index, occupancy)] = tmp_attack_mask; - } - } - return anti_diagonal_attack_table_ret; - }(); + const std::array, 64> rank_attack_table = attack_table({-1, 1}, hashkey_rank); + const std::array, 64> file_attack_table = attack_table({-8, 8}, hashkey_file); + const std::array, 64> diagonal_attack_table = attack_table({-9, 9}, hashkey_diagonal); + const std::array, 64> anti_diagonal_attack_table = attack_table({-7, 7}, hashkey_anti_diagonal); static constexpr auto Size = sizeof(anti_diagonal_attack_table) + @@ -397,28 +95,24 @@ namespace Chess_Lookup::Kindergarten sizeof(file_attack_table) + sizeof(rank_attack_table) + sizeof(anti_diagonals_64) + - sizeof(diagonals_64) + - sizeof(files_64) + - sizeof(ranks_64); + sizeof(diagonals_64); - //return the uint64 with the rook targets - static constexpr uint64_t Rook(int square, uint64_t occupation) + // return the uint64 with the rook targets + static uint64_t Rook(int square, uint64_t occupation) { - return rank_attack_table[square][hashkeyRank(square, occupation)] | - file_attack_table[square][hashkeyFile(square, occupation)]; + return rank_attack_table[square][hashkey_rank(square, occupation)] | + file_attack_table[square][hashkey_file(square, occupation)]; } - //return the uint64 with the bishops targets - static constexpr uint64_t Bishop(int square, uint64_t occupation) + // return the uint64 with the bishops targets + static uint64_t Bishop(int square, uint64_t occupation) { - return anti_diagonal_attack_table[square][hashkeyAntiDiagonal(square, occupation)] | - diagonal_attack_table[square][hashkeyDiagonal(square, occupation)]; + return anti_diagonal_attack_table[square][hashkey_anti_diagonal(square, occupation)] | + diagonal_attack_table[square][hashkey_diagonal(square, occupation)]; } - static uint64_t Queen(int square, uint64_t occupation) { - return anti_diagonal_attack_table[square][hashkeyAntiDiagonal(square, occupation)] | - diagonal_attack_table[square][hashkeyDiagonal(square, occupation)] | - rank_attack_table[square][hashkeyRank(square, occupation)] | - file_attack_table[square][hashkeyFile(square, occupation)]; + static uint64_t Queen(int square, uint64_t occupation) + { + return Rook(square, occupation) | Bishop(square, occupation); } } \ No newline at end of file diff --git a/Main.cpp b/Main.cpp index dc7d47b..9507135 100644 --- a/Main.cpp +++ b/Main.cpp @@ -77,6 +77,7 @@ static void PrintBrand() { #define Pext_ (1) #define SplitPext_ (1) #define Kindergarten_ (1) +#define PreSchool_ (1) #define PextEmu_ (1) #define Hyper_ (1) #define Explode_ (1) @@ -437,7 +438,7 @@ struct Bob_t { static uint64_t Size() { return Chess_Lookup::BobAdvanced::Size; } }; #else - Dummy(BobAdvanced_); + Dummy(BobAdvanced_t); #endif #if Leorik_ @@ -532,7 +533,7 @@ struct Hyper_t { struct PextEmu_t { static constexpr bool Supports_Template = false; static inline constexpr std::string_view name = "Pext Emulated"; - static inline constexpr std::string_view author = "Zach Wegner"; //Daniel Inführ + static inline constexpr std::string_view author = "Zach Wegner"; //Daniel Inführ static inline constexpr std::string_view reference = "https://randombit.net/bitbashing/posts/haswell_bit_permutations.html"; static inline constexpr std::string_view sp_op = "none"; @@ -645,7 +646,7 @@ Dummy(Fancy_t); struct Explode_t { static constexpr bool Supports_Template = false; static inline constexpr std::string_view name = "Exploding Bitboards"; - static inline constexpr std::string_view author = "Harald L\x81\xE1 \ben\t"; //Harald Lüßen + static inline constexpr std::string_view author = "Harald L\x81\xE1 \ben\t"; //Harald Lüßen static inline constexpr std::string_view reference = "http://www.open-aurec.com/wbforum/viewtopic.php?f=4&t=4523&start=80"; static inline constexpr std::string_view sp_op = "imul64"; @@ -812,6 +813,22 @@ struct Kindergarten_t { Dummy(Kindergarten_t); #endif +#if PreSchool_ +#include "PreSchool.hpp" +struct PreSchool_t { + static constexpr bool Supports_Template = false; + static inline constexpr std::string_view name = "PreSchool"; + static inline constexpr std::string_view author = "Jost Triller"; + static inline constexpr std::string_view reference = "nothing yet"; + static inline constexpr std::string_view sp_op = "imul64"; + + static uint64_t Queen(int sq, uint64_t occ) { return Chess_Lookup::PreSchool::Queen(sq, occ); } + static uint64_t Size() { return Chess_Lookup::PreSchool::Size; } +}; +#else +Dummy(PreSchool_t); +#endif + #if Obstrd_ #include "ObstructionDiff.hpp" @@ -967,6 +984,7 @@ X(GeneticObstructionDiffV2_t) \ X(Arithm_t); \ X(ArithmNT_t); \ X(Kindergarten_t) \ +X(PreSchool_t) \ X(Sissy_t); \ X(Kgssb_t); \ X(HVar_t); \ diff --git a/PreSchool.hpp b/PreSchool.hpp new file mode 100644 index 0000000..619c7f5 --- /dev/null +++ b/PreSchool.hpp @@ -0,0 +1,107 @@ +#pragma once +// Datum : 2023-10-24 +// Author : Tsoj +// Content: Pre-school bitboards, like kindergarten bitboards but unified rank+file and diag+anti-diag tables respectively. +#include +#include +#include +#include + +namespace Chess_Lookup::PreSchool +{ + constexpr uint64_t main_diagonal = 0b1000000001000000001000000001000000001000000001000000001000000001; // A1 to H8 + constexpr uint64_t first_file = 0b0000000100000001000000010000000100000001000000010000000100000001; + + template + uint64_t occ_for_square(const uint16_t hash_key, const int square, const std::array dirs, std::function hash_key_fn) + { + uint64_t result = 0; + for (const int dir : dirs) + { + int cur = square; + while (true) + { + cur += dir; + if (cur >= 64 || cur < 0 || abs((cur % 8) - ((cur - dir) % 8)) >= 2) + { + break; + } + const uint64_t bit = 1ULL << cur; + result |= bit; + + if (hash_key_fn(square, bit) & hash_key) + { + break; + } + } + } + return result; + } + + template + auto collect_n(auto f) + { + std::array result; + for (int i = 0; i < N; i++) + { + result[i] = f(i); + } + return result; + } + + const std::array diagonals_64 = collect_n<64>([](int i){ + return occ_for_square(0, i, std::array{9, -9}, [](auto s, auto occ){ return 0; }); + }); + + const std::array anti_diagonals_64 = collect_n<64>([](int i){ + return occ_for_square(0, i, std::array{7, -7}, [](auto s, auto occ){ return 0; }); + }); + + constexpr inline uint16_t hashkey_fr(const int square, const uint64_t occupancy) + { + return + ((((((occupancy >> (square % 8)) & first_file) * main_diagonal) >> 50) >> 1) & 0b111111000000U) | + (((occupancy >> ((square / 8) * 8)) >> 1) & 0b111111U); + } + constexpr inline uint16_t hashkey_d(const int square, const uint64_t occupancy) + { + return + (((((occupancy & anti_diagonals_64[square]) * first_file) >> 50) >> 1) & 0b111111000000U) | + (((((occupancy & diagonals_64[square]) * first_file) >> 56) >> 1) & 0b111111U); + } + + std::array, 64> attack_table(const std::array dirs, std::function hash_key_fn) + { + return collect_n<64>([&](int square){ + return collect_n<4096>([&](int hash_key){ + return occ_for_square(hash_key, square, dirs, hash_key_fn); + }); + }); + } + + const std::array, 64> fr_attack_table = attack_table({-1, 1, 8, -8}, hashkey_fr); + const std::array, 64> d_attack_table = attack_table({-7, 7, 9, -9}, hashkey_d); + + static constexpr auto Size = + sizeof(fr_attack_table) + + sizeof(d_attack_table) + + sizeof(anti_diagonals_64) + + sizeof(diagonals_64); + + // return the uint64 with the rook targets + static uint64_t Rook(int square, uint64_t occupation) + { + return fr_attack_table[square][hashkey_fr(square, occupation)]; + } + + // return the uint64 with the bishops targets + static uint64_t Bishop(int square, uint64_t occupation) + { + return d_attack_table[square][hashkey_d(square, occupation)]; + } + + static uint64_t Queen(int square, uint64_t occupation) + { + return Rook(square, occupation) | Bishop(square, occupation); + } +} \ No newline at end of file