#include #include #include #include #include #include #include #include const std::set> correct_pieces = { std::make_pair('R', 2), std::make_pair('N', 2), std::make_pair('B', 2), std::make_pair('Q', 1), std::make_pair('K', 1) }; std::map, int32_t> knights_table = { { std::vector{ 0, 1 }, 0 }, { std::vector{ 0, 2 }, 1 }, { std::vector{ 0, 3 }, 2 }, { std::vector{ 0, 4 }, 3 }, { std::vector{ 1, 2 }, 4 }, { std::vector{ 1, 3 }, 5 }, { std::vector{ 1, 4 }, 6 }, { std::vector{ 2, 3 }, 7 }, { std::vector{ 2, 4 }, 8 }, { std::vector{ 3, 4 }, 9 } }; void validate(const std::string& position) { if ( position.length() != 8 ) { throw std::invalid_argument("Chess position has invalid length" + std::to_string(position.length())); } std::map position_map; for ( const char& ch : position ) { if ( position_map.find(ch) == position_map.end() ) { position_map.emplace(ch, 1); } else { position_map[ch]++; } } std::set> pieces; std::transform(position_map.begin(), position_map.end(), std::inserter(pieces, pieces.begin()), [](const std::pair& entry) { return entry; }); if ( pieces != correct_pieces ) { throw std::invalid_argument("Chess position contains incorrect pieces."); } const std::vector bishops = { position.find_first_of('B'), position.find_last_of('B') }; if ( ( bishops[1] - bishops[0] ) % 2 == 0 ) { throw std::invalid_argument("Bishops must be on different coloured squares."); } std::vector rook_king = { position.find_first_of('R'), position.find_first_of('K'), position.find_last_of('R') }; if ( ! ( rook_king[0] < rook_king[1] && rook_king[1] < rook_king[2] ) ) { throw std::invalid_argument("The king must be between the two rooks."); } } int32_t calculate_SPID(std::string& position) { const int32_t index_one = position.find_first_of('B'); const int32_t index_two = position.find_last_of('B'); const int32_t D = ( index_one % 2 == 0 ) ? index_one / 2 : index_two / 2; const int32_t L = ( index_one % 2 == 0 ) ? index_two / 2 : index_one / 2; position.erase(remove_if(position.begin(), position.end(), [](const char& ch){ return ch == 'B'; }), position.end()); const uint64_t Q = position.find_first_of('Q'); position.erase(remove_if(position.begin(), position.end(), [](const char& ch){ return ch == 'Q'; }), position.end()); const int32_t N = knights_table[ { (int32_t) position.find_first_of('N'), (int32_t) position.find_last_of('N') } ]; return 96 * N + 16 * Q + 4 * D + L; } int main() { std::vector positions = { "QNRBBNKR", "RNBQKBNR", "RQNBBKRN", "RNQBBKRN" }; for ( std::string& position : positions ) { validate(position); std::cout << "Position " << position << " has Chess960 SP-ID = " << calculate_SPID(position) << std::endl; } }