diff --git a/src/Makefile b/src/Makefile index 90cd7b7..f0edd4b 100755 --- a/src/Makefile +++ b/src/Makefile @@ -1,15 +1,19 @@ #CC=g++-4.2 # -#a.out: main.o SerialComm.o -# g++ main.o SerialComm.o -lboost_system -lboost_filesystem -lboost_serialization -lpthread -std=c++11 +#chess.out: functions.o +# g++ chess.o functions.o -std=c++11 # -#main.o: main.cpp -# g++ -c -std=c++11 main.cpp +#chess.o: chess.cpp +# g++ -c -std=c++11 chess.cpp +# +#functions.o: functions.cpp functions.h +# g++ -c -std=c++11 functions.cpp # -#SerialComm.o: SerialComm.cpp SerialComm.hpp -# g++ -c -std=c++11 SerialComm.cpp - default: build +release: optimized + +optimized: + g++ -std=c++11 -O2 -Wall -o chess.out functions.cpp chess.cpp build: - g++ -o chess.out chess.cpp -std=c++11 + g++ -Wall -o chess_unoptimized.out functions.cpp chess.cpp -std=c++11 diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp new file mode 100755 index 0000000..b219897 --- /dev/null +++ b/src/all_moves_functions.cpp @@ -0,0 +1,172 @@ +#include "constants.h" +#include +#include +#include + +const std::vector ROOK_PIECE_OFFSETS = {-1, -10, 1, 10}; +const std::vector BISHOP_PIECE_OFFSETS = {-11, -9, 9, 11}; +const std::vector KNIGHT_PIECE_OFFSETS = {-12, -21, -19, -8, 8, 12, 19, 21}; +const std::vector KING_PIECE_OFFSETS = {-11, -10, -9, 9, 10, 11}; + + +inline Position _pair_to_pos_unsafe(int x, int y){ + return static_cast(std::abs(y-7)*8 + x); +} + +// This function returns true if the color of the piece on tile (x,y) is the Color c +bool _xy_is_color(int pos, const std::array& board, Color c){ + return c==Color::WHITE ? is_white(board[pos]) : is_black(board[pos]); +} + +Color _rev_color(Color c){ + return c==Color::WHITE ? Color::BLACK : Color::WHITE; +} + +// This function will set the boolean guarding it to false if it is blocked, thus stopping it from running. +void _add_if_not_blocked(int pos, int from, std::vector& pns, const std::array& board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){ + if (*is_not_blocked){ + if (!is_valid_position(pos)){ + *is_not_blocked = false; + } else { + if (_xy_is_color(pos, board, color_of_piece)){ + *is_not_blocked = false; + } else if (_xy_is_color(pos, board, color_of_opposite)){ + pns.push_back(make_move(from, pos, board[pos])); + *is_not_blocked = false; + } else { + pns.push_back(make_move(from, pos, board[pos])); + } + } + } +} + +// Only for the king, using rays for left and right, and adding the castle flag if needed. +void _king_add_if_not_blocked(int pos, int from, std::vector& pns, const std::array& board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked, int castle_flag){ + if (*is_not_blocked){ + if (!is_valid_position(pos)){ + *is_not_blocked = false; + } else { + if (_xy_is_color(pos, board, color_of_piece)){ + *is_not_blocked = false; + } else if (_xy_is_color(pos, board, color_of_opposite)){ + pns.push_back(make_move(from, pos, board[pos], PieceType::NONE)); + *is_not_blocked = false; + } else { + pns.push_back(make_move(from, pos, board[pos], PieceType::NONE, 0, 0, castle_flag)); + } + } + } +} + + +// This function is for non-ray types only, as it ignores the 'ray rules', and just jumps over stuff (e.g. knight), or only moves one space generally (e.g. king) +void _add_if_not_blocked(int pos, int from, std::vector& pns, const std::array& board, Color color_of_piece, Color color_of_opposite){ + if (!is_valid_position(pos) || + _xy_is_color(pos, board, color_of_piece)){ + return; + } else { + pns.push_back(make_move(from, pos, board[pos])); + } +} + +void _add_pawn_promotions(int from, int to, PieceType capture, Color color_of_piece, std::vector& pns){ + if (color_of_piece == Color::WHITE){ + pns.push_back(make_move(from, to, capture, PieceType::W_KNIGHT)); + pns.push_back(make_move(from, to, capture, PieceType::W_BISHOP)); + pns.push_back(make_move(from, to, capture, PieceType::W_ROOK)); + pns.push_back(make_move(from, to, capture, PieceType::W_QUEEN)); + } else { + pns.push_back(make_move(from, to, capture, PieceType::B_KNIGHT)); + pns.push_back(make_move(from, to, capture, PieceType::B_BISHOP)); + pns.push_back(make_move(from, to, capture, PieceType::B_ROOK)); + pns.push_back(make_move(from, to, capture, PieceType::B_QUEEN)); + } + +} + +// This is a specialized function for the pawn's diagonal takes. +// It will only to pns if there is a piece of opposite color on it. +void _pawn_diag_add_if_not_blocked(int pos, int from, std::vector& pns, const std::array& board, Color color_of_piece, Color color_of_opposite, int en_passant, int promoting){ + if (is_valid_position(pos)){ + // Theoretically this is not run with en_passant because those flags should NEVER overlap, but if it does, my tests will alert me. + if (_xy_is_color(pos, board, color_of_opposite)){ + if (promoting){ + _add_pawn_promotions(from, pos, board[pos], color_of_piece, pns); + } else { + pns.push_back(make_move(from, pos, board[pos])); + } + } else if (pos == en_passant){ + // If capturing from the left to the right, set the captured piece to directly right of current from pos (+1) + // ...otherwise get to the right (-1) + int captured_pos = from-pos>0?from+1:from-1; + pns.push_back(make_move(from, pos, board[captured_pos], PieceType::NONE, 1)); + } + } +} + +// This is a specialized functions for the pawn's inability to take going forward. +// Notice the lack of push_backion where there usually is when (x,y) is a different color. +void _pawn_add_if_not_blocked(int pos, int from, std::vector& pns, const std::array& board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked, bool double_move, bool promoted){ + if (*is_not_blocked){ + if (board[pos] != PieceType::NONE || + board[pos] == PieceType::INV){ + *is_not_blocked = false; + } else if (double_move){ + pns.push_back(make_move(from, pos, PieceType::NONE, PieceType::NONE, 0, 1)); + } else if (promoted){ + _add_pawn_promotions(from, pos, PieceType::NONE, color_of_piece, pns); + } else { + pns.push_back(make_move(from, pos, board[pos])); + } + } +} + +void _get_all_moves_king(int pos, std::vector& pns, const std::array& board, Color pc, Color rc, int castle_perms){ + for (int kn_off : KING_PIECE_OFFSETS){ + _add_if_not_blocked(pos+kn_off, pos, pns, board, pc, rc); + } + bool* left_castle = new bool(true); + bool* right_castle = new bool(true); + + if (pc == Color::WHITE){ + _king_add_if_not_blocked(pos+1, pos, pns, board, pc, rc, right_castle, 0); + _king_add_if_not_blocked(pos-1, pos, pns, board, pc, rc, left_castle, 0); + // THe right castle doesn't need to know if pos-/+ something is blank, because there is only + // ... 2 blank squares between the king and the rook. + if (castle_perms & CastlePerms::WKS){ + _king_add_if_not_blocked(pos+2, pos, pns, board, pc, rc, right_castle, 1); + } + if (castle_perms & CastlePerms::WQS && board[pos-3] == PieceType::NONE){ + _king_add_if_not_blocked(pos-2, pos, pns, board, pc, rc, left_castle, 1); + } + } else { + _king_add_if_not_blocked(pos+1, pos, pns, board, pc, rc, right_castle, 0); + _king_add_if_not_blocked(pos-1, pos, pns, board, pc, rc, left_castle, 0); + if (castle_perms & CastlePerms::BKS){ + _king_add_if_not_blocked(pos+2, pos, pns, board, pc, rc, right_castle, 1); + } + if (castle_perms & CastlePerms::BQS && board[pos-3] == PieceType::NONE){ + _king_add_if_not_blocked(pos-2, pos, pns, board, pc, rc, left_castle, 1); + } + } +} + +void _get_all_moves_pawn(int pos, std::vector& pns, const std::array& board, Color pc, Color rc, int en_passant){ + + // if it's white use different offsets, and pawn starting rank + int offset2 = pc==Color::WHITE?-20:20; + int offset1 = pc==Color::WHITE?-10:10; + int default_pawn_rank = pc==Color::WHITE?Rank::RANK2:Rank::RANK7; + int promotion_rank = pc==Color::WHITE?Rank::RANK7:Rank::RANK2; + int is_promoting_if_forward = get_rank(pos) == promotion_rank?1:0; + + bool *free_to_double_move = new bool(true); + _pawn_add_if_not_blocked(pos+offset1, pos, pns, board, pc, rc, free_to_double_move, false, is_promoting_if_forward); + if (get_rank(pos) == default_pawn_rank){ // If on second/seventh rank + _pawn_add_if_not_blocked(pos+offset2, pos, pns, board, pc, rc, free_to_double_move, true, is_promoting_if_forward); + } + // pos+offset1 is 1 rank up (or down) depending on color. + // Adding, or removing one will shift it over by one square, hence diagnoals. + _pawn_diag_add_if_not_blocked(pos+offset1+1, pos, pns, board, pc, rc, en_passant, is_promoting_if_forward); + _pawn_diag_add_if_not_blocked(pos+offset1-1, pos, pns, board, pc, rc, en_passant, is_promoting_if_forward); +} diff --git a/src/bitwise.h b/src/bitwise.h new file mode 100755 index 0000000..ebcff61 --- /dev/null +++ b/src/bitwise.h @@ -0,0 +1,127 @@ +#ifndef BITWISE_H +#define BITWISE_H + +#include "constants.h" +#include + +// Using macros for ease of use, can also use functons, but I don't see the point. + +/* + * From (Position): 7 bits (2^7 == 128) possibilities + * To (Position): same as above + * Captured piece, if any: 4 bits (16) possibilities + * Promoted to, if any: 4 bits (16) possibilities + * en passant flag: 1 bit + * pawn starting move flag: 1 bit + * castle move flag: 1 bit + * + * 0000 0000 0000 0000 0000 0111 1111 -> From square position (& 0x7F) + * 0000 0000 0000 0011 1111 1000 0000 -> To square position (>> 7 & 0x7F) + * 0000 0000 0011 1100 0000 0000 0000 -> captured piece, if any (>> 14 & 0xF) + * 0000 0011 1100 0000 0000 0000 0000 -> if prmoted, what to? (>> 18 & 0xF) + * 0000 0100 0000 0000 0000 0000 0000 -> en passant (& 0x400000) + * 0000 1000 0000 0000 0000 0000 0000 -> pawn starting move (& 0x800000) + * 0001 0000 0000 0000 0000 0000 0000 -> castle move (& 0x1000000) + * 0010 0000 0000 0000 0000 0000 0000 -> check flag (& 0x2000000) + * */ + +// No offset becuase at beginning of int +#define FROM_MASK 0x7F + +#define TO_MASK 0x7F +#define TO_SHIFT 7 + +#define CAPTURED_MASK 0xF +#define CAPTURED_SHIFT 14 + +#define PROMOTED_MASK 0xF +#define PROMOTED_SHIFT 18 + +#define EN_PASS_MASK 0x1 +#define EN_PASS_SHIFT 22 + +#define PAWN_ST_MASK 0x1 +#define PAWN_ST_SHIFT 23 + +#define CASTLE_MASK 0x1 +#define CASTLE_SHIFT 24 + +inline int get_from_sq(int mv){ + return (mv & FROM_MASK); +} +inline int get_to_sq(int mv){ + return ((mv >> TO_SHIFT) & TO_MASK); +} +inline int get_captured_pc(int mv){ + return ((mv >> CAPTURED_SHIFT) & CAPTURED_MASK); +} +inline int get_promoted_to_pc(int mv){ + return ((mv >> PROMOTED_SHIFT) & PROMOTED_MASK); +} +inline int get_en_pass_flag(int mv){ + return ((mv >> EN_PASS_SHIFT) & EN_PASS_MASK); +} +inline int get_pawn_st_flag(int mv){ + return ((mv >> PAWN_ST_SHIFT) & PAWN_ST_MASK); +} +inline int get_castle_flag(int mv){ + return ((mv >> CASTLE_SHIFT) & CASTLE_MASK); +} +inline int get_check_flag(int mv){ + return ((mv >> 25) & 0x1); +} + +inline bool is_valid_position(int position){ + return DEFAULT_BOARD[position] != PieceType::INV; +} + +// bitwise OR (|) with any int to "add" them together +inline int set_from_sq(int sq){ + return sq; +} +inline int set_to_sq(int sq){ + return (sq << 7); +} +inline int set_captured_pc(int pc){ + return (pc << 14); +} +inline int set_promoted_pc(int pc){ + return (pc << 16); +} +inline int set_en_passant_flag(){ + return (1 << 20); +} +inline int set_pawn_start_flag(){ + return (1 << 21); +} +inline int set_castle_flag(){ + return (1 << 22); +} + +inline int make_move(int from){ + return from; +} +inline int make_move(int from, int to){ + return from | (to << 7); +} +inline int make_move(int from, int to, PieceType captured){ + return from | (to << 7) | ((int) captured << 14); +} +inline int make_move(int from, int to, PieceType captured, PieceType promotion){ + return from | (to << 7) | ((int) captured << 14) | ((int) promotion << 18); +} +inline int make_move(int from, int to, PieceType captured, PieceType promotion, int en_passant){ + return from | (to << 7) | ((int) captured << 14) | ((int) promotion << 18) | (en_passant << 22); +} +inline int make_move(int from, int to, PieceType captured, PieceType promotion, int en_passant, int pawn_start){ + return from | (to << 7) | ((int) captured << 14) | ((int) promotion << 18) | (en_passant << 22) | (pawn_start << 23); +} +inline int make_move(int from, int to, PieceType captured, PieceType promotion, int en_passant, int pawn_start, int castle_move){ + return from | (to << 7) | ((int) captured << 14) | ((int) promotion << 18) | (en_passant << 22) | (pawn_start << 23) | (castle_move << 24); +} +inline int make_move(int from, int to, PieceType captured, PieceType promotion, int en_passant, int pawn_start, int castle_move, int check_flag){ + return from | (to << 7) | ((int) captured << 14) | ((int) promotion << 18) | (en_passant << 22) | (pawn_start << 23) | (castle_move << 24) | (check_flag << 25); +} + + +#endif diff --git a/src/chess.cpp b/src/chess.cpp index 963e626..57fdffc 100755 --- a/src/chess.cpp +++ b/src/chess.cpp @@ -1,18 +1,219 @@ #include #include #include +#include "bitwise.h" #include "constants.h" +#include "functions.h" +#include "color.hpp" // See constants.h for CHESS_CHARS, and DEFAULT_BOARD using namespace std; -int main(){ - for (int i = 0; i < 8; ++i){ - for (int j = 0; j < 8; ++j){ - int ix = (i*8) + j; - cout << CHESS_CHARS[DEFAULT_BOARD[ix]]; +void print_board(const array& board, vector &highlighted_moves){ + for (int i = 2; i < 10; ++i){ + cout << 10-i << " |"; + for (int j = 1; j < 9; ++j){ + int ix = (i*10) + j; + int piece = board[ix]; + string piece_string = FANCY_CHESS_CHARS[piece]; + string foreground_color = is_white(piece)?"White":"Black"; + string background_color = ""; + string modifier = ""; + + for (int move : highlighted_moves){ + if (get_to_sq(move) == ix){ + if (get_check_flag(move) == 1){ + background_color = "Light Red"; + } else if (get_captured_pc(move) != 0){ + background_color = "Green"; + // If a checkmate occors on this move + // Doesn't appear to work in practoce. + } else if (to_notation(move, board).find("#") != string::npos){ + background_color = "White"; + modifier = "Blink"; + } else { + background_color = "Yellow"; + } + } + } + + cout << color::rize(" ", foreground_color, background_color, modifier); + cout << color::rize(piece_string, foreground_color, background_color, modifier); + cout << color::rize(" ", foreground_color, background_color, modifier); } cout << endl; } + cout << "--------------------------" << endl; + cout << " A B C D E F G H" << endl; +} + + +// TODO: allow algebraic notation. +int main(){ + + cout << "Hit h for help!" << endl; + + Color whos_turn = Color::WHITE; + array my_board; + copy(DEFAULT_BOARD.begin(), DEFAULT_BOARD.end(), + my_board.begin()); + + vector all_moves = {}; + vector all_moves_notation = {}; + + int en_passant_square = 0; + int castle_perms = 0xF; + bool reset_en_passant = false; + + vector highlighted_moves = {}; + + while (true){ + + all_moves = {}; + all_moves_notation = {}; + array my_pieces = whos_turn==Color::WHITE?Pieces::WHITE:Pieces::BLACK; + // Gets all moves for color who's turn it is. + get_all_moves_for_pieces(my_pieces, my_board, all_moves, en_passant_square, castle_perms); + + print_board(my_board, highlighted_moves); + + // If there are no moves. The game is over. + // If the king is ALSO in check, then the other team won! + if (all_moves.empty()){ + if (king_checked(my_board, whos_turn)){ + string winning_team = rev_color(whos_turn)==Color::WHITE?"White":"Black"; + cout << "GG! " << winning_team << " won!" << endl; + break; + } else { + cout << "Stalemate, too bad!" << endl; + break; + } + } + + // Gets a string from cin called input + string input; + getline(cin, input); + // Gets all moves and stores them in a notation list + // TODO make into own function + bool move_exec = false; + int move_to_exec = 0; + for (int move : all_moves){ + string move_notation = to_notation(move, my_board); + all_moves_notation.push_back(move_notation); + if (move_notation == input){ + move_exec = true; + move_to_exec = move; + break; + } + } + // Quits + if (input == "q"){ + break; + } else if (input == "l"){ + for (string notation : all_moves_notation){ + cout << notation << " "; + } + cout << endl; + continue; + } else if (input == "c"){ + highlighted_moves = {}; + } else if (input == "h"){ + cout << "Commands:" < to list all moves for a specific position." << endl; + cout << " these will be highlighted on the board with various colors" << endl; + cout << " Red: Checking move"<< endl; + cout << " Blue: capturing move" << endl; + cout << " Yellow: all other moves" << endl; + cout << " c to clear the highlights" << endl; + } + // If the input did not match any legal move. + if (!move_exec){ + int l_pos = input.find("l"); + // If input starts with "l". + // It cannot equal only l because that case is taken care of above. + // And it continues to the next loop. + if (l_pos == 0){ + string possible_position = input.substr(2, 2); + bool asking_for_specific_moves = false; + for (string pos : POSITION_STRING){ + if(pos == possible_position){ + asking_for_specific_moves = true; + } + } + // If input matches a position. + if (asking_for_specific_moves){ + highlighted_moves = {}; + for (int move : all_moves){ + if (POSITION_STRING[get_from_sq(move)] == possible_position){ + highlighted_moves.push_back(move); + cout << to_notation(move, my_board) << " "; + } + } + cout << endl; + } else { + cout << "Invalid move!" << std::endl; + cout << "These are the only valid moves: "; + for (string notation : all_moves_notation){ + cout << notation << " "; + } + cout << endl; + continue; + } + } + // If the input did match a legal move. + } else { + int moving_from_pos = get_from_sq(move_to_exec); + int moving_piece = my_board[moving_from_pos]; + // Depending on move, change castle perms, or en_passant square + if (get_pawn_st_flag(move_to_exec) == 1){ + int en_pass_offset = whos_turn==Color::WHITE?10:-10; + en_passant_square = get_to_sq(move_to_exec)+en_pass_offset; + reset_en_passant = false; + } + if (moving_piece == W_ROOK){ + if (moving_from_pos == Position::A1 && + ((castle_perms & CastlePerms::WQS) == CastlePerms::WQS)){ + castle_perms -= CastlePerms::WQS; + } else if (moving_from_pos == Position::H1 && + ((castle_perms & CastlePerms::WKS) == CastlePerms::WKS)){ + castle_perms -= CastlePerms::WKS; + } + } else if (moving_piece == B_ROOK){ + if (moving_from_pos == Position::H8 && + ((castle_perms & CastlePerms::BKS) == CastlePerms::BKS)){ + castle_perms -= CastlePerms::BKS; + } else if (moving_from_pos == Position::A8 && + ((castle_perms & CastlePerms::BQS) == CastlePerms::BQS)){ + castle_perms -= CastlePerms::BQS; + } + } + // Removes castle perms after castling + if (is_white(moving_piece) && + get_castle_flag(move_to_exec)){ + castle_perms -= CastlePerms::WQS; + castle_perms -= CastlePerms::WKS; + } else if (is_black(moving_piece) && + get_castle_flag(move_to_exec)) { + castle_perms -= CastlePerms::BQS; + castle_perms -= CastlePerms::BKS; + } + // This will keep the en passant sqaure for one whole turn. + if (reset_en_passant){ + en_passant_square = 0; + reset_en_passant = false; + } + if (en_passant_square != 0){ + reset_en_passant = true; + } + // This reverses the whos_turn variable. + // and runs the move on the my_board variable. + my_board = dumb_move(move_to_exec, my_board); + whos_turn = rev_color(whos_turn); + highlighted_moves = {}; + } + } + return 0; } diff --git a/src/color.hpp b/src/color.hpp new file mode 100755 index 0000000..5e1570e --- /dev/null +++ b/src/color.hpp @@ -0,0 +1,146 @@ +#if 0 +Copyright <2018> + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endif +#ifndef BKSDMLDVRLVOKOCTERXUEIKDNCRAQXFWSMBUNVVYFAPNJYHYEBBVBMCDQGBQWGARFUYWEDMFN +#define BKSDMLDVRLVOKOCTERXUEIKDNCRAQXFWSMBUNVVYFAPNJYHYEBBVBMCDQGBQWGARFUYWEDMFN + +#ifdef __clang__ +#define SUPPRESS_WARNINGS \ +_Pragma("clang diagnostic push ") \ +_Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \ +_Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ +_Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \ +_Pragma("clang diagnostic ignored \"-Wc++98-c++11-c++14-compat\"") \ +_Pragma("clang diagnostic ignored \"-Wmissing-variable-declarations\"" ) +#define RESTORE_WARNINGS \ +_Pragma( "clang diagnostic pop" ) +#else +#define SUPPRESS_WARNINGS +#define RESTORE_WARNINGS +#endif + +#include +#include + +SUPPRESS_WARNINGS + +namespace color +{ + + const static std::map color_foreground = + { + { "Default", "39" }, + { "Black", "30" }, + { "Red", "31" }, + { "Green", "32" }, + { "Yellow", "33" }, + { "Blue", "34" }, + { "Magenta", "35" }, + { "Cyan", "36" }, + { "Light Gray", "37" }, + { "Dark Gray", "90" }, + { "Light Red", "91" }, + { "Light Green", "92" }, + { "Light Yellow", "93" }, + { "Light Blue", "94" }, + { "Light Magenta", "95" }, + { "Light Cyan", "96" }, + { "White", "97" } + }; + + const static std::map color_background = + { + { "Default", "49" }, + { "Black", "40" }, + { "Red", "41" }, + { "Green", "42" }, + { "Yellow", "43" }, + { "Blue", "44" }, + { "Megenta", "45" }, + { "Cyan", "46" }, + { "Light Gray", "47" }, + { "Dark Gray", "100" }, + { "Light Red", "101" }, + { "Light Green", "102" }, + { "Light Yellow", "103" }, + { "Light Blue", "104" }, + { "Light Magenta", "105" }, + { "Light Cyan", "106" }, + { "White", "107" } + }; + + + const static std::map formatting_set = + { + { "Default", "0" }, + { "Bold", "1" }, + { "Dim", "2" }, + { "Underlined", "4" }, + { "Blink", "5" }, + { "Reverse", "7" }, + { "Hidden", "8" } + }; + + const static std::map formatting_reset = + { + { "All", "0" }, + { "Bold", "21" }, + { "Dim", "22" }, + { "Underlined", "24" }, + { "Blink", "25" }, + { "Reverse", "27" }, + { "Hidden", "28" } + }; + + // Usage: + // + // auto new_message = color::rize( "I am a banana!", "Yellow", "Green" ); + // std::cout << new_message << std::endl; + // + inline std::string rize( std::string const& source, + std::string foreground_color = "Default", + std::string background_color = "Default", + std::string set_formatting = "Default", + std::string reset_formatting = "All" + ) + { + std::string const control = "\033"; + + if ( color_foreground.find( foreground_color ) == color_foreground.end() ) + foreground_color = "Default"; + + if ( color_background.find( background_color ) == color_background.end() ) + background_color = "Default"; + + if ( formatting_set.find( set_formatting ) == formatting_set.end() ) + set_formatting = "Default"; + + if ( formatting_reset.find( reset_formatting ) == formatting_reset.end() ) + reset_formatting = "All"; + + std::string ans = control + std::string{"["} + + formatting_set.at( set_formatting ) + std::string{";"} + + color_background.at( background_color ) + std::string{";"} + + color_foreground.at( foreground_color ) + std::string{"m"} + + source + + control + std::string{"["} + + formatting_reset.at( reset_formatting ) + std::string{"m"}; + return ans; + } + +}//namespace color + +RESTORE_WARNINGS + +#endif//BKSDMLDVRLVOKOCTERXUEIKDNCRAQXFWSMBUNVVYFAPNJYHYEBBVBMCDQGBQWGARFUYWEDMFN + diff --git a/src/constants.h b/src/constants.h index 273f3e5..62c5e43 100755 --- a/src/constants.h +++ b/src/constants.h @@ -1,79 +1,129 @@ -#ifndef CHESS_CONSTANTS_H -#define CHESS_CONSTANTS_H +#ifndef BT_CONST_H +#define BT_CONST_H -#include #include -#include +#include +#include + +enum Color { + NO_COLOR, + BLACK, + WHITE +}; + +enum CastlePerms { + BQS=0b1, + BKS=0b10, + WQS=0b100, + WKS=0b1000 +}; -// Access with PieceType::ANY_FOLLOWING_OPTION enum PieceType { + INV=-1, NONE, - W_PAWN, - W_KNIGHT, - W_BISHOP, - W_ROOK, - W_QUEEN, - W_KING, - B_PAWN, - B_KNIGHT, - B_BISHOP, - B_ROOK, - B_QUEEN, - B_KING + B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING, + W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING, }; -// Access with CHESS_CHARS[PieceType] to get the character for the piece. -const std::array CHESS_CHARS = { - ' ', - 'p', 'n', 'b', 'r', 'q', 'k', - 'P', 'N', 'B', 'R', 'Q', 'K' -}; +namespace Pieces{ + const std::array WHITE = {W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING}; + const std::array BLACK = {B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING}; +} -// This allows reference to DEFAULT_BOARD (or more likely, a copy of it. -enum Position{ - A8, B8, C8, D8, E8, F8, G8, H8, A7, B7, C7, D7, E7, F7, G7, H7, A6, B6, C6, D6, E6, F6, G6, H6, A5, B5, C5, D5, E5, F5, G5, H5, A4, B4, C4, D4, E4, F4, G4, H4, A3, B3, C3, D3, E3, F3, G3, H3, A2, B2, C2, D2, E2, F2, G2, H2, A1, B1, C1, D1, E1, F1, G1, H1 +enum Position { + NA=-1, + A8=21, B8, C8, D8, E8, F8, G8, H8, + A7=31, B7, C7, D7, E7, F7, G7, H7, + A6=41, B6, C6, D6, E6, F6, G6, H6, + A5=51, B5, C5, D5, E5, F5, G5, H5, + A4=61, B4, C4, D4, E4, F4, G4, H4, + A3=71, B3, C3, D3, E3, F3, G3, H3, + A2=81, B2, C2, D2, E2, F2, G2, H2, + A1=91, B1, C1, D1, E1, F1, G1, H1 }; -// This allows the printing of Position enum variables in the tests. It matches the variables to strings. -// Variable names are discarded at compile time to optimize. // Access with POSITION_STRING[Position] -const std::vector POSITION_STRING = { - "A8", "B8", "C8", "D8", "E8", "F8", "G8", "H8", "A7", "B7", "C7", "D7", "E7", "F7", "G7", "H7", "A6", "B6", "C6", "D6", "E6", "F6", "G6", "H6", "A5", "B5", "C5", "D5", "E5", "F5", "G5", "H5", "A4", "B4", "C4", "D4", "E4", "F4", "G4", "H4", "A3", "B3", "C3", "D3", "E3", "F3", "G3", "H3", "A2", "B2", "C2", "D2", "E2", "F2", "G2", "H2", "A1", "B1", "C1", "D1", "E1", "F1", "G1", "H1" +const std::array POSITION_STRING = { + "INV", "INV", "INV", "INV", "INV", "INV", "INV", "INV", "INV", "INV", + "INV", "INV", "INV", "INV", "INV", "INV", "INV", "INV", "INV", "INV", + "INV", "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8", "INV", + "INV", "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7", "INV", + "INV", "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6", "INV", + "INV", "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5", "INV", + "INV", "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4", "INV", + "INV", "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3", "INV", + "INV", "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2", "INV", + "INV", "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", "INV", + "INV", "INV", "INV", "INV", "INV", "INV", "INV", "INV", "INV", "INV", + "INV", "INV", "INV", "INV", "INV", "INV", "INV", "INV", "INV", "INV" }; -// Access with normal ways of accessing an array. -// OR like so DEFAULT_BOARD[Position::G1] would equal PieceType::W_KNIGHT -const std::array DEFAULT_BOARD = { - B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, - B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, - W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK +enum Rank{ + RANK8, + RANK7, + RANK6, + RANK5, + RANK4, + RANK3, + RANK2, + RANK1 }; +enum File { + FILE1, + FILE2, + FILE3, + FILE4, + FILE5, + FILE6, + FILE7, + FILE8 +}; -namespace Rank{ - const int A[8] = {A1, A2, A3, A4, A5, A6, A7, A8}; - const int B[8] = {B1, B2, B3, B4, B5, B6, B7, B8}; - const int C[8] = {C1, C2, C3, C4, C5, C6, C7, C8}; - const int D[8] = {D1, D2, D3, D4, D5, D6, D7, D8}; - const int E[8] = {E1, E2, E3, E4, E5, E6, E7, E8}; - const int F[8] = {F1, F2, F3, F4, F5, F6, F7, F8}; - const int G[8] = {G1, G2, G3, G4, G5, G6, G7, G8}; - const int H[8] = {H1, H2, H3, H4, H5, H6, H7, H8}; -} +const std::array DEFAULT_BOARD = { + INV,INV,INV,INV,INV,INV,INV,INV,INV,INV, + INV,INV,INV,INV,INV,INV,INV,INV,INV,INV, + INV, B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, INV, + INV, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, INV, + INV, W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK, INV, + INV,INV,INV,INV,INV,INV,INV,INV,INV,INV, + INV,INV,INV,INV,INV,INV,INV,INV,INV,INV +}; +const std::array BOARD_COLORS = { + NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR, + NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR, + NO_COLOR, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, NO_COLOR, + NO_COLOR, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, NO_COLOR, + NO_COLOR, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, NO_COLOR, + NO_COLOR, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, NO_COLOR, + NO_COLOR, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, NO_COLOR, + NO_COLOR, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, NO_COLOR, + NO_COLOR, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, NO_COLOR, + NO_COLOR, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, NO_COLOR, + NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR, + NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR,NO_COLOR +}; -namespace File{ - const int ONE[8] = {A1, B1, C1, D1, E1, F1, G1, H1}; - const int TWO[8] = {A2, B2, C2, D2, E2, F2, G2, H2}; - const int THREE[8] = {A3, B3, C3, D3, E3, F3, G3, H3}; - const int FOUR[8] = {A4, B4, C4, D4, E4, F4, G4, H4}; - const int FIVE[8] = {A5, B5, C5, D5, E5, F5, G5, H5}; - const int SIX[8] = {A6, B6, C6, D6, E6, F6, G6, H6}; - const int SEVEN[8] = {A7, B7, C7, D7, E7, F7, G7, H7}; - const int EIGHT[8] = {A8, B8, C8, D8, E8, F8, G8, H8}; -} +const std::array CHESS_CHARS = { + ' ', + 'P', 'N', 'B', 'R', 'Q', 'K', + 'p', 'n', 'b', 'r', 'q', 'k', +}; +// This returns the same letter weather the team is black or white +const std::array CHESS_CHARS_INSENSITIVE = { + " ", + "P", "N", "B", "R", "Q", "K", + "P", "N", "B", "R", "Q", "K", +}; +const std::array FANCY_CHESS_CHARS = { + " ", + "♟", "♞", "♝", "♜", "♛", "♚", + "♙", "♘", "♗", "♖", "♕", "♔", +}; #endif + diff --git a/src/functions.cpp b/src/functions.cpp index d3049d1..4049d8c 100755 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -1,121 +1,562 @@ +#include "bitwise.h" #include "functions.h" +#include "all_moves_functions.cpp" +#include +#include +#include #include #include #include #include +#include #include +#include -// TODO implement functions.h functions. -// NOTE tests will NOT run unless you implement these functions. +/* + * + * These functions use an int to pass a lot of information. + * The notation is like this: + * 0000 0000 0000 0000 0111 1111 -> position of piece + * 0000 0000 0000 0111 1000 0000 -> piece type + * 0000 0000 0111 1000 0000 0000 -> piece of opposite type (eg. opposite of W_KING, is B_KING; B_ROOK, W_ROOK etc...) + * 0000 0000 1000 0000 0000 0000 -> team of the piece (1=white, 0=black) + * 0111 1111 0000 0000 0000 0000 -> new position (if applicable) + * +**/ -std::pair pos_to_pair(Position pn){ - int x,y = 0; - for (x = pn; x >= 8; x = x-8){ - ++y; +/* + * These functions also use an int for king info. This is so: + * a) I don't have to recompute the info each time I nedd it in a functoin. + * b) So that I don't have the overhead of a struct. (I know, "micro optimizations are the root of all evil", I can't help myself) + * The notation is as follows: + * 0000 0000 0000 0000 0111 1111 -> position of piece + * 0000 0000 0000 0111 1000 0000 -> piece type + * 0000 0011 1111 1000 0000 0000 -> opposite piece position + * 0011 1100 0000 0000 0000 0000 -> piece of opposite type + * 0100 0000 0000 0000 0000 0000 -> team of the piece (1=white, 0=black) + */ + +inline int get_piece_pos(int pieceinfo){ + return (pieceinfo & 0x7f); +} +inline int get_piece_type(int pieceinfo){ + return ((pieceinfo << 7) & 0xf); +} +inline int get_opposite_piece_type(int pieceinfo){ + return ((pieceinfo << 11) & 0xf); +} +// TO find out if white/black use: +// get_team_of_piece_type == Color::WHITE/BLACK +inline int get_team_of_piece_type(int pieceinfo){ + return ((pieceinfo << 15) & 0x1); +} +inline int get_new_position_of_piece(int pieceinfo){ + return ((pieceinfo << 16) & 0xf); +} + + +/* Move ints contain a lot of information as well. However, these are DIFFERENt from the other dense ints. Moves are universalyl passed by reference (&) to a vector of ints, whereas the above is passed only is 1 int by itself. + * Here is the notation for moves (although it is obscured by the make_move(), get_to/from_sq(), get_captured_pc() etc... functions. + * + * From (Position): 7 bits (2^7 == 128) possibilities + * To (Position): same as above + * Captured piece, if any: 4 bits (16) possibilities + * Promoted to, if any: 4 bits (16) possibilities + * en passant flag: 1 bit + * pawn starting move flag: 1 bit + * castle move flag: 1 bit + * + * 0000 0000 0000 0000 0000 0111 1111 -> From square position (& 0x7F) + * 0000 0000 0000 0011 1111 1000 0000 -> To square position (>> 7 & 0x7F) + * 0000 0000 0011 1100 0000 0000 0000 -> captured piece, if any (>> 14 & 0xF) + * 0000 0011 1100 0000 0000 0000 0000 -> if prmoted, what to? (>> 18 & 0xF) + * 0000 0100 0000 0000 0000 0000 0000 -> en passant (>> 22 &0x1) + * 0000 1000 0000 0000 0000 0000 0000 -> pawn starting move (>> 23 &0x1) + * 0001 0000 0000 0000 0000 0000 0000 -> castle move (>> 24 0x1) + * 0010 0000 0000 0000 0000 0000 0000 -> check flag (>> 25 &0x1) + * */ + +//const std::array ROOK_PIECE_OFFSETS = {-1, -10, 1, 10}; +//const std::array BISHOP_PIECE_OFFSETS = {-11, -9, 9, 11}; +const std::vector QUEEN_PIECE_OFFSETS = {-1, -10, 1, 10, -11, -9, 9, 11}; + +Rank get_rank(int pos){ + int rank = 0; + while (pos >= 0){ + pos -= 10; + rank++; } - return std::make_pair(x, std::abs(y-7)); + return static_cast(rank - 3); } -// TODO find way to make function arbitary to board size as to allow wide game chess variants. Do much later. Not important now. -Position pair_to_pos(std::pair pr){ - if (pr.first > 7 || pr.first < 0 - || pr.second > 7 || pr.second < 0) { - throw std::invalid_argument("Cannot use any pairs with values > 7 or < 0."); +bool is_white(int pt){ + for (auto pn : Pieces::WHITE){ + if (pn == pt) return true; } - int int_val = std::abs(pr.second - 7)*8 + pr.first; - if (int_val >= 0 && int_val < 64) { - return static_cast(int_val); - } else { - std::stringstream ss; - ss << "Something went terribly wrong. x and y < 8 && x and y >= 0 but abs(y-7)*8 + x < 0 or >= 64. It equalled: " << int_val; - throw std::invalid_argument(ss.str()); + return false; +} +bool is_black(int pt){ + for (auto pn : Pieces::BLACK){ + if (pn == pt) return true; } + return false; } -std::vector get_possible_movers(Position pn, std::array board){ - std::vector pns = {Position::A1}; - return pns; + +Color get_color(PieceType pt){ + if (is_white(pt)) return Color::WHITE; + if (is_black(pt)) return Color::BLACK; + return Color::NO_COLOR; +} + +Color get_color(int pn, const std::array& board){ + return get_color(board[pn]); } -std::vector get_possible_moves(Position pn, std::array board){ - std::vector pns = {Position::A1}; +Color rev_color(Color c){ + if (c==Color::NO_COLOR) return Color::NO_COLOR; + return c==Color::WHITE?Color::BLACK:Color::WHITE; +} +PieceType rev_color(PieceType pt){ + //return static_cast((~pt) & 0xf); + for (int i=0; i!=Pieces::WHITE.size(); i++){ + if (pt == Pieces::WHITE[i]){ + return Pieces::BLACK[i]; + } + } + for (int i=0; i!=Pieces::BLACK.size(); i++){ + if (pt == Pieces::BLACK[i]){ + return Pieces::WHITE[i]; + } + } + return PieceType::NONE; +} + +std::vector get_possible_movers(Position pn, const std::array& board){ + std::vector pns = {Position::A1}; return pns; } -std::vector get_all_moves(Position pn, std::array board){ - PieceType pt = board[pn]; - std::vector pns; - int x = pos_to_pair(pn).first; - int y = pos_to_pair(pn).second; - int dx; - int dy; - switch(pt){ - case PieceType::B_ROOK: - case PieceType::W_ROOK: - for (int j = 7; j >= 0; j--){ - if (j != y){ - pns.push_back(pair_to_pos(std::make_pair(x,j))); - } - for (int i = 0; i < 8; i++){ - if (j == y){ - pns.push_back(pair_to_pos(std::make_pair(i,y))); - } +int get_pos_of(PieceType pt, const std::array& board){ + for (int pn = Position::A8; pn!=Position::H1; pn++){ + if (board[pn] == pt){ + return pn; } + } + return Position::NA; +} + +std::vector get_poss_of(PieceType pt, const std::array& board){ + std::vector results; + for (int pn = Position::A8; pn!=Position::H1; pn++){ + if (board[pn] == pt){ + results.push_back(pn); } - break; - case PieceType::B_BISHOP: - case PieceType::W_BISHOP: - for (int r = 7; r >= 0; r--){ - for (int f = 0; f < 8; f++){ - for (int i=0; i<8; i++){ - if ((f-i == x && r-i == y) || - (f+i == x && r+i == y) || - (f-i == x && r+i == y) || - (f+i == x && r-i == y)){ - pns.push_back(pair_to_pos(std::make_pair(f, r))); - break; - } - } - /* - if (((i>x) && (i<8)) && ((j>y) && (j<8))) - { - dx = i-x; - dy = j-y; - if (dx == dy){pns.push_back(pair_to_pos(std::make_pair(x+dx,y+dy)));} - } - if (((i>=0) && (iy) && (j<8))) - { - dx = i+1; - dy = j-y; - if (dx == dy){pns.push_back(pair_to_pos(std::make_pair(x-dx,y+dy)));} - } - if (((i>=0) && (i=0) && (j& board, std::vector& pns){ + for (int pn = Position::A8; pn!=Position::H1; pn++){ + if (board[pn] == pt){ + pns.push_back(pn); + } + } +} + +bool would_be_attacked(int pos, PieceType piece, const std::array& board){ + Color pc = get_color(piece); + auto other_pieces = pc==Color::WHITE?Pieces::BLACK:Pieces::WHITE; + for (PieceType opposite_color_piece : other_pieces){ + PieceType same_color_piece = rev_color(opposite_color_piece); + std::vector moves; + get_all_moves_as_if(pos, same_color_piece, board, moves, false); + for (int reverse_move : moves){ + if (get_captured_pc(reverse_move) == opposite_color_piece){ + return true; + } + } + } + return false; + +} + +bool is_attacked(int pos, const std::array& board){ + return would_be_attacked(pos, board[pos], board); +} + +bool king_checked(const std::array& board, Color color_of_king){ + PieceType king = color_of_king==WHITE?W_KING:B_KING; + int king_pos = get_pos_of(king, board); + return is_attacked(king_pos, board); +} + +void add_checked_flags(PieceType pt, const std::array& board, std::vector& pns){ + PieceType other_king = is_white(pt)?PieceType::B_KING:PieceType::W_KING; + int other_king_pos = get_pos_of(other_king, board); + // If the other team doesn't have a king, don't add any checked flags + if (other_king_pos == Position::NA){ + return; + } + for (auto move_pn=pns.begin(); move_pn!=pns.end();){ + std::array moved_board; + dumb_move(*move_pn, board, moved_board); + if (is_attacked(other_king_pos, moved_board)){ + *move_pn |= (1 << 25); + } + ++move_pn; + } +} + +//TODO: Make faster by running from king squar eonly, instead of running on every piece of opposite team. +void filter_checked_moves(PieceType pt, const std::array& board, std::vector& pns){ + PieceType my_king = is_white(pt)?PieceType::W_KING:PieceType::B_KING; + int my_king_pos = get_pos_of(my_king, board); + bool remove_all_castles = false; + // If this team doesn't have a king, don't do anything, jsut return. + if (my_king_pos == Position::NA){ + return; + } + for (auto p_pn= pns.begin(); p_pn!=pns.end();){ + if (get_castle_flag(*p_pn) == 1){ + // If removing all castle flags is triggered + // (by being in check) + // remove all of them. + if (remove_all_castles){ + p_pn = pns.erase(p_pn); + ++p_pn; + break; + } + // TODO: Make this more effecient. + // There is no way in hell, this is as complicated as it seems. + // If moved left + // Queenside + if ((get_from_sq(*p_pn) - get_to_sq(*p_pn)) > 0){ + if(would_be_attacked(get_to_sq(*p_pn), my_king, board) || + would_be_attacked(get_to_sq(*p_pn)+1, my_king, board)){ + p_pn = pns.erase(p_pn); + } else { + ++p_pn; + break; } - if (((i>x) && (i<8)) && ((j>=0) && (j moved_board; + dumb_move(*p_pn, board, moved_board); + // This is for when the king is the same piece that is moving. + // If this is the case, reset to king position to the new position given by the get_to_sq() of the move. + if (pt == my_king){ + my_king_pos = get_to_sq(*p_pn); + } + + if (is_attacked(my_king_pos, moved_board)){ + p_pn = pns.erase(p_pn); + } else { + ++p_pn; } } - break; + } +} + +void _get_all_moves_as_if_ray_type(int pos, std::vector offsets, std::vector& moves, const std::array& board, Color color_of_piece, Color color_of_opponent){ + for (int offset : offsets){ + for (int times = 1; times < 8; ++times){ + int true_offset = pos+(offset*times); + if (get_color(board[true_offset]) == color_of_opponent){ + moves.push_back(make_move(pos, true_offset, board[true_offset])); + break; + } else if (get_color(board[true_offset]) == color_of_piece || + board[true_offset] == PieceType::INV){ + break; + } else { + moves.push_back(make_move(pos, true_offset, board[true_offset])); + } + } + } +} + +void _get_all_moves_as_if_not_ray(int pos, std::vector offsets, std::vector& moves, const std::array& board, Color color_of_piece, Color color_of_opponent){ + for (int offset : offsets){ + int true_offset = pos+offset; + if (board[true_offset] == PieceType::NONE || + get_color(board[true_offset]) == color_of_opponent){ + moves.push_back(make_move(pos, true_offset, board[true_offset])); + } + } +} + + +// WARNING: This function depends on the order of the moves being correct. +// The last two king moves MUST be for the king's position +1, and -1 respectively. +// TODO finish function +void _get_all_castle_moves(int pos, int castle_perms, std::vector& moves, const std::array& board, Color color_of_piece, Color color_of_opponent){ + if (color_of_piece == Color::WHITE){ + + } else { + + } +} + +void get_all_moves_as_if(int pos, PieceType pt, const std::array& board, std::vector& moves, bool recursive, int en_passant, int castle_perms){ + int piece_info = 0; + Color color_of_piece = get_color(pt); + Color color_of_opponent = rev_color(color_of_piece); + switch(pt){ + case PieceType::B_QUEEN: + case PieceType::W_QUEEN: + _get_all_moves_as_if_ray_type(pos, QUEEN_PIECE_OFFSETS, moves, board, color_of_piece, color_of_opponent); + //_get_all_moves_rook(pos, moves, board, color_of_piece, color_of_opponent); + //_get_all_moves_bishop(pos, moves, board, color_of_piece, color_of_opponent); + break; + case PieceType::B_ROOK: + case PieceType::W_ROOK: + _get_all_moves_as_if_ray_type(pos, ROOK_PIECE_OFFSETS, moves, board, color_of_piece, color_of_opponent); + //_get_all_moves_rook(pos, moves, board, color_of_piece, color_of_opponent); + break; + case PieceType::B_BISHOP: + case PieceType::W_BISHOP: + _get_all_moves_as_if_ray_type(pos, BISHOP_PIECE_OFFSETS, moves, board, color_of_piece, color_of_opponent); + //_get_all_moves_bishop(pos, moves, board, color_of_piece, color_of_opponent); + break; + case PieceType::B_KNIGHT: + case PieceType::W_KNIGHT: + _get_all_moves_as_if_not_ray(pos, KNIGHT_PIECE_OFFSETS, moves, board, color_of_piece, color_of_opponent); + //_get_all_moves_knight(pos, moves, board, color_of_piece, color_of_opponent); + break; + case PieceType::B_KING: + case PieceType::W_KING: +// _get_all_moves_as_if_not_ray(pos, KING_PIECE_OFFSETS, moves, board, color_of_piece, color_of_opponent); +// if (castle_perms != 0){ +// _get_all_castle_moves(); +// } + _get_all_moves_king(pos, moves, board, color_of_piece, color_of_opponent, castle_perms); + break; + case PieceType::B_PAWN: + case PieceType::W_PAWN: + _get_all_moves_pawn(pos, moves, board, color_of_piece, color_of_opponent, en_passant); + break; default: break; } - return pns; + if (recursive){ + filter_checked_moves(pt, board, moves); + add_checked_flags(pt, board, moves); + } } -std::array dumb_move(Position from, Position to, std::array board){ - PieceType piece = board[from]; - board[to] = piece; - board[from] = PieceType::NONE; - return board; +void get_all_moves(int pos, const std::array& board, std::vector& moves, bool recursive, int en_passant, int castle_perms){ + get_all_moves_as_if(pos, board[pos], board, moves, recursive, en_passant, castle_perms); +} +std::vector get_all_moves(int pos, const std::array& board, bool recursive, int en_passant, int castle_perms){ + std::vector moves = {}; + get_all_moves_as_if(pos, board[pos], board, moves, recursive, en_passant, castle_perms); + return moves; } + +void dumb_move(int move, const std::array& board, std::array& new_board){ + std::copy(std::begin(board), std::end(board), std::begin(new_board)); + int en_passant_flag = get_en_pass_flag(move); + int castle_flag = get_castle_flag(move); + int from = get_from_sq(move); + int to = get_to_sq(move); + PieceType piece = new_board[from]; + if (en_passant_flag == 1) { + int diff = to-from; + int other_pawn_pos = 0; + if (diff == -11){ + other_pawn_pos = from-1; + } else if (diff == -9){ + other_pawn_pos = from+1; + } else if (diff == 11){ + other_pawn_pos = from+1; + } else if (diff == 9){ + other_pawn_pos = from-1; + } + new_board[other_pawn_pos] = PieceType::NONE; + new_board[to] = piece; + new_board[from] = PieceType::NONE; + } else if(castle_flag == 1){ + int diff = to-from; + int rook_from_pos = 0; + int rook_to_pos = 0; + // If castling queenside + if (diff == -2){ + rook_from_pos = to-2; + rook_to_pos = from-1; + // If caslting kingside + } else if (diff == 2){ + rook_from_pos = to+1; + rook_to_pos = from+1; + } + PieceType rook_pt = new_board[rook_from_pos]; + new_board[rook_from_pos] = PieceType::NONE; + new_board[rook_to_pos] = rook_pt; + new_board[from] = PieceType::NONE; + new_board[to] = piece; + } else { + new_board[to] = piece; + new_board[from] = PieceType::NONE; + } +} +std::array dumb_move(int pos, const std::array& board){ + std::array new_board = {}; + dumb_move(pos, board, new_board); + return new_board; +} + +void _filter_unneeded_squares(std::vector& moves, int piecetype, int origin){ + for (auto move_pn=moves.begin(); move_pn!=moves.end();){ + if (get_captured_pc(*move_pn) == piecetype && + get_to_sq(*move_pn) != origin){ + ++move_pn; + } else { + move_pn = moves.erase(move_pn); + } + } + +}; + +void _non_pawn_disambiguate(int from, int to, int piecetype, const std::vector& moves, std::string& disambig){ + if (moves.size() == 1){ + disambig = POSITION_STRING[from][0]; + int other_from = get_to_sq(moves.at(0)); + int min_from = other_fromfrom?other_from:from; + // If the remainder of the difference divided by 10 is 0 + // they are on the same file. + // Use rank to disambiguate + if ((max_from-min_from) % 10 == 0){ + disambig = POSITION_STRING[from][1]; + } + } else if (moves.size() > 1){ + disambig = POSITION_STRING[from]; + } +} + +std::string to_notation(int move, const std::array& board){ + int to = get_to_sq(move); + int from = get_from_sq(move); + + // This can be ran right away due to the simplicity of the notation. + if (get_castle_flag(move) == 1){ + return to-from<0 ? "O-O-O" : "O-O"; + } + + PieceType piecetype = board[from]; + std::string from_string = POSITION_STRING[from]; + int captured_piece = get_captured_pc(move); + int promoting_to = get_promoted_to_pc(move); + // Blank if not pawn + // file if pawn and capture move + std::string pawn_file = ""; + // Blank if pawn + // otherwise N/B/R/Q/K corresponding to each piece + // same for black and white + std::string piece_character = ""; + // Blank if not a capture + // x if a capture move + std::string capture_character = ""; + // Blank if not en passant move + // otherwise e.p. + std::string en_passant = ""; + // Black if no check, + // + if check + // # if checkmate + std::string check = ""; + // Blank if only this piece can move to the to square + // include file (a-h) if another piece can move to the to square + // includes rank (1-8) if pieces have same file + // includes both (f)(r) if 2+ identical piece can move to the to square + std::string disambig = ""; + // Blank if not a pawn promotion move. + // Otherwise is equal to "=P/N/B/R/Q". + std::string promotion; + auto other_pieces = is_white(piecetype)?Pieces::BLACK:Pieces::WHITE; + + if (captured_piece != PieceType::NONE){ + capture_character = "x"; + // Comment #6 + // if a pawn is capturing, have the disambiguation be the pawn's file + // stored in a seperate variable because pawn disabiguation by file happens at the start of a notation. For example: + // exf4 as opposed to Qh1xf4 + if (piecetype == PieceType::W_PAWN || + piecetype == PieceType::B_PAWN){ + pawn_file = POSITION_STRING[from][0]; + } + } + // Pawns do not require this, as their file is ALWAYS enough to identify them, + // and the file is always speicified on a pawn capture. + // (See comment #6) + if (piecetype != PieceType::W_PAWN && + piecetype != PieceType::B_PAWN){ + // Simulated a piece of the same type, and opposite color moving from the to square + // to check if any other pieces can also move here. + // Basically it searches to see if there are duplicate pieces which can move to the same spot. + // and stores any duplicates in the other_moves variable. + PieceType opposite_piece = rev_color(piecetype); + std::vector other_moves = {}; + get_all_moves_as_if(to, opposite_piece, board, other_moves, false); + // This takes out any mention of other squares involing blank pieces, or any peices that do not invole the current one. + _filter_unneeded_squares(other_moves, piecetype, from); + piece_character = CHESS_CHARS_INSENSITIVE[piecetype]; + _non_pawn_disambiguate(from, to, piecetype, other_moves, disambig); + } + if (get_en_pass_flag(move) == 1){ + en_passant = "e.p."; + } + if (get_check_flag(move) == 1){ + check = "+"; + // This checks if the other team has any valid moves. + // If not, the check sign changes to a hashtag (#). + std::array moved_board; + dumb_move(move, board, moved_board); + + std::vector other_moves = {}; + get_all_moves_for_pieces(other_pieces, moved_board, other_moves); + if (other_moves.empty()){ + check = "#"; + } + } + // If promoting, add an equals sign and the piece promoting to. + if (promoting_to != PieceType::NONE){ + promotion += "="; + promotion += CHESS_CHARS_INSENSITIVE[promoting_to]; + } + // end of checking for multiple pieces + std::string result = ""; + result += pawn_file + piece_character + disambig + capture_character + POSITION_STRING[to] + en_passant + promotion + check; + return result; +} + +void get_all_moves_for_pieces(std::array pieces, const std::array& board, std::vector& moves, int en_passant, int castle_perms){ + for (PieceType pt : pieces){ + for (int pos_of : get_poss_of(pt, board)){ + std::vector local_moves = {}; + get_all_moves_as_if(pos_of, pt, board, local_moves, true, en_passant, castle_perms); + moves.insert(moves.end(), local_moves.begin(), local_moves.end()); + } + } +} +// From StackOverflow (https://stackoverflow.com/questions/5891610/how-to-remove-certain-characters-from-a-string-in-c#5891643) +void remove_chars_from_string(std::string &str, std::string charsToRemove ) { + for ( unsigned int i = 0; i < charsToRemove.length(); ++i ) { + str.erase( remove(str.begin(), str.end(), charsToRemove.at(i)), str.end() ); + } +} + diff --git a/src/functions.h b/src/functions.h index ce5e347..8d1d473 100755 --- a/src/functions.h +++ b/src/functions.h @@ -1,26 +1,74 @@ #include "constants.h" +#include +#include #include #include +#include -// Convert pair of x y coordinates to Position enum member. -// If pr contains values above 7, or below 0 it will fail with an InvalidArgument exception. -Position pair_to_pos(std::pair pr); +// Returns a list of positions with PieceType pt +int get_pos_of(PieceType pt, const std::array& board); +std::vector get_poss_of(PieceType pt, const std::array& board); // Convert a Position number into a pair of x y coordiinates std::pair pos_to_pair(Position pn); +// Check if int is a valid position in enum of Position +// Allow ints, and pairs to be checked. +bool is_valid_position(int pos); + +// Returns rank enum value for given pos +Rank get_rank(int pos); + +// Checks if given piece matches a certain color. +bool is_white(int pt); +bool is_black(int pt); + +Color get_color(int pn, const std::array& board); +Color get_color(PieceType pt); +// NO_COLOR returns NO_COLOR +// WHITE returns BLACK +// BLACK returns WHITE +Color rev_color(Color c); +PieceType rev_color(PieceType pt); + // Get all positions of pieces which can move to this square // This may require helper functions for each individual peice. // TODO rename to something less stupid. -std::vector get_possible_movers(Position pn, std::array pt); +void get_possible_movers(Position pn, const std::array& pt ,std::vector& moves); // Get all possible moved for piece in Position pn. // This may require helper functions for each individual piece. -std::vector get_possible_moves(Position pn, std::array pt); +void get_possible_moves(Position pn, const std::array& pt, std::vector& moves); + +// This functions removes moves that put your own king in check. +void filter_checked_moves(int pos, const std::array& board, std::vector& moves); + +// This function is like get_all_moves, except it doesn't check pos and base the piecetype on that, +// ... but instead acts as if the PieceType pt is on pos, and returns possible move sbased on that. +void get_all_moves_as_if(int pos, PieceType pt, const std::array& board, std::vector& moves, bool recursvie=true, int en_passant=Position::NA, int castle_perms=0); + +// Get all moves for piece in Position pn. +void get_all_moves(int pos, const std::array& pt, std::vector& moves, bool recursive=true, int en_passant=Position::NA, int castle_perms=0); +std::vector get_all_moves(int pos, const std::array& board, bool recursive=true, int en_passant=Position::NA, int castle_perms=0); -// Get all moved for piece in Position pn. -std::vector get_all_moves(Position pn, std::array pt); // Dumb function to do board moves. -// Does NOT check for valid moves. Only moves PieceType of Pos1 to Pos2, then replaces Pos1 with Piecetype::NONE -std::array dumb_move(Position from, Position to, std::array board); +// Does not check if move is valid, just does it. +void dumb_move(int move, const std::array& board, std::array& new_board); +std::array dumb_move(int move, const std::array& board); + +// Decides if piece pt in position pos is/would be (theoretichally) in check +bool would_be_attacked(int pos, PieceType pt, const std::array& board); + +bool is_attacked(int pos, const std::array& board); + + +bool king_checked(const std::array& board, Color king_color); + +// Convert move (and board becuase notation needs more info than the move itself) +// ...into algbraic notation. +std::string to_notation(int move, const std::array& board); + +// These functions are just for printing (for now) so they are not included in the tests. +void get_all_moves_for_pieces(std::array pieces, const std::array& board, std::vector& moves, int en_passant=0, int castle_perms=0); +void remove_chars_from_string(std::string &std, std::string to_remove); diff --git a/tests/B_test_boards.h b/tests/B_test_boards.h old mode 100644 new mode 100755 index 273ab76..b218031 --- a/tests/B_test_boards.h +++ b/tests/B_test_boards.h @@ -1,123 +1,193 @@ +#include #include -const Position B_QUEEN_POS = E4; -const std::array B_QUEEN_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, B_QUEEN, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE +const int B_QUEEN_POS = E4; +const std::array B_QUEEN_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, B_QUEEN, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::vector B_QUEEN_ALL_MOVES = { - A8, E8, - B7, E7, H7, - C6, E6, G6, - D5, E5, F5, - A4, B4, C4, D4, E4, F4, G4, H4, - D3, E3, F3, - C2, E2, G2, - B1, E1, H1 +const std::vector B_QUEEN_ALL_MOVES = { + D4, C4, B4, A4, + E5, E6, E7, E8, + F4, G4, H4, + E3, E2, E1, + D5, C6, B7, A8, + F5, G6, H7, + D3, C2, B1, + F3, G2, H1 }; -const Position B_BISHOP_POS = D4; -const std::array B_BISHOP_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, B_BISHOP, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE +const int B_BISHOP_POS = D4; +const std::array B_BISHOP_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, B_BISHOP, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::vector B_BISHOP_ALL_MOVES = { - H8, - A7, G7, - B6, F6, - C5, E5, - D4, - C3, E3, - B2, F2, - A1, G1 +const std::vector B_BISHOP_ALL_MOVES = { + C5, B6, A7, E5, F6, G7, H8, C3, B2, A1, E3, F2, G1 }; -const Position B_KNIGHT_POS = D5; -const std::array B_KNIGHT_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, B_KNIGHT, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE +const int B_KNIGHT_POS = D5; +const std::array B_KNIGHT_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, B_KNIGHT, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::vector B_KNIGHT_ALL_MOVES = { - C7, E7, - B6, F6, - D5, - B4, F4, - C3, E3 +const std::vector B_KNIGHT_ALL_MOVES = { + B6, C7, E7, F6, B4, F4, C3, E3 }; -const Position B_ROOK_POS = E5; -const std::array B_ROOK_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, B_ROOK, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE +const int B_ROOK_POS = E5; +const std::array B_ROOK_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, B_ROOK, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::vector B_ROOK_ALL_MOVES = { - E8, E7, E6, - A5, B5, C5, D5, E5, F5, G5, H5, +const std::vector B_ROOK_ALL_MOVES = { + D5, C5, B5, A5, + E6, E7, E8, + F5, G5, H5, E4, E3, E2, E1 }; -const Position B_KING_POS = C4; -const std::array B_KING_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, B_KING, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE +const int B_KING_POS = C4; +const std::array B_KING_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, B_KING, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::vector B_KING_ALL_MOVES = { +const std::vector B_KING_ALL_MOVES = { B5, C5, D5, - B4, C4, D4, - B3, C3, D3 + B3, C3, D3, + D4, B4 }; -const Position B_PAWN_POS = F4; -const std::array B_PAWN_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, B_PAWN, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE +const int B_PAWN_POS = F4; +const std::array B_PAWN_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, B_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::vector B_PAWN_ALL_MOVES = { - F4, - E3, F3, G3, - F2 +const std::vector B_PAWN_ALL_MOVES = { + F3 +}; +const int B_KNIGHT_SIDE1_POS = B7; +const std::array B_KNIGHT_SIDE1_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, B_KNIGHT, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector B_KNIGHT_SIDE1_ALL_MOVES = { + D8, + D6, + A5, C5 +}; +const int B_KING_SIDE1_POS = A8; +const std::array B_KING_SIDE1_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_KING, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector B_KING_SIDE1_ALL_MOVES = { + A7,B7,B8 +}; + +const int B_PAWN_SIDE1_POS = A7; +const std::array B_PAWN_SIDE1_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, B_PAWN, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector B_PAWN_SIDE1_ALL_MOVES = { + A6, A5 }; diff --git a/tests/Makefile b/tests/Makefile index 5463710..6b5afa3 100755 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,4 +1,38 @@ -defualt: build +defualt: all.out +bitwise: bitwise.out +release: all_optimized.out +speed_tests: speed_tests.out -build: - g++ -std=c++11 -w -I../src/ -o tests.out ../src/functions.cpp tests_main.cpp +clean: + rm all.out +distclean: + rm *.o + rm *.out + +catch_main.o: + g++ -w -c -o catch_main.o catch_main.cpp + +custom_printing.o: + g++ -Wall -I../src/ -c -o custom_printing.o custom_printing.cpp + +bitwise.out: catch_main.o + g++ -Wall -I../src -o bitwise.out catch_main.o bitwise_tests.cpp + +# TODO: Allw all.out to contain bitwise tests +all.out: catch_main.o custom_printing.o + g++ -std=c++11 -ggdb -Wall -I../src/ -o all.out ../src/functions.cpp catch_main.o custom_printing.o test_functions.cpp main.cpp + +catch_main_optimized.o: + g++ -w -O2 -c -o catch_main_optimized.o catch_main.cpp + +custom_printing_optimized.o: + g++ -Wall -O2 -I../src/ -c -o custom_printing_optimized.o custom_printing.cpp + +bitwise_optimized.out: catch_main_optimized.o + g++ -Wall -O2 -I../src -o bitwise_optimized.out catch_main_optimized.o bitwise_tests.cpp + +all_optimized.out: catch_main_optimized.o custom_printing_optimized.o + g++ -std=c++11 -O2 -Wall -I../src/ -o all_optimized.out ../src/functions.cpp catch_main_optimized.o custom_printing_optimized.o test_functions.cpp main.cpp + +speed_tests.out: + g++ -O2 -Wall -I../src/ -o speed_tests.out ../src/functions.cpp speed.cpp diff --git a/tests/W_test_boards.h b/tests/W_test_boards.h old mode 100644 new mode 100755 index b9ec152..4b53c26 --- a/tests/W_test_boards.h +++ b/tests/W_test_boards.h @@ -1,133 +1,209 @@ +#include #include -const Position W_QUEEN_POS = E4; -const std::array W_QUEEN_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, W_QUEEN, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE -}; -const std::array W_QUEEN_BOARD_BLOCKED = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, B_PAWN, W_PAWN, B_PAWN, NONE, NONE, - NONE, NONE, NONE, W_KNIGHT, W_QUEEN, B_PAWN, NONE, NONE, - NONE, NONE, NONE, B_QUEEN, B_KNIGHT, W_PAWN, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE -}; - -const std::vector W_QUEEN_ALL_MOVES = { - A8, E8, - B7, E7, H7, - C6, E6, G6, - D5, E5, F5, - A4, B4, C4, D4, E4, F4, G4, H4, - D3, E3, F3, - C2, E2, G2, - B1, E1, H1 -}; - -const Position W_BISHOP_POS = D4; -const std::array W_BISHOP_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, W_BISHOP, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE -}; - -const std::vector W_BISHOP_ALL_MOVES = { - H8, - A7, G7, - B6, F6, - C5, E5, - D4, - C3, E3, - B2, F2, - A1, G1 -}; - -const Position W_KNIGHT_POS = D5; -const std::array W_KNIGHT_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, W_KNIGHT, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE -}; - -const std::vector W_KNIGHT_ALL_MOVES = { - C7, E7, - B6, F6, - D5, - B4, F4, - C3, E3 -}; - -const Position W_ROOK_POS = E5; -const std::array W_ROOK_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, W_ROOK, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE -}; - -const std::vector W_ROOK_ALL_MOVES = { - E8, E7, E6, - A5, B5, C5, D5, E5, F5, G5, H5, +const int W_QUEEN_POS = E4; +const std::array W_QUEEN_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, W_QUEEN, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +const std::array W_QUEEN_BOARD_BLOCKED = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, B_PAWN, W_PAWN, B_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, W_KNIGHT, W_QUEEN, B_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, B_QUEEN, B_KNIGHT, W_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +const std::vector W_QUEEN_ALL_MOVES = { + D4, C4, B4, A4, + E5, E6, E7, E8, + F4, G4, H4, + E3, E2, E1, + D5, C6, B7, A8, + F5, + G6, H7, D3, C2, B1, F3, G2, H1 +}; + +const int W_BISHOP_POS = D4; +const std::array W_BISHOP_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, W_BISHOP, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +const std::vector W_BISHOP_ALL_MOVES = { + C5, B6, A7, E5, F6, G7, H8, C3, B2, A1, E3, F2, G1 +}; + +const int W_KNIGHT_POS = D5; +const std::array W_KNIGHT_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, W_KNIGHT, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +const int W_KNIGHT_SIDE1_POS = B7; +const std::array W_KNIGHT_SIDE1_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, W_KNIGHT, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector W_KNIGHT_SIDE1_ALL_MOVES = { + D8, + D6, + A5, C5 +}; + +const std::vector W_KNIGHT_ALL_MOVES = { + B6, C7, E7, F6, B4, F4, C3, E3 +}; + +const int W_ROOK_POS = E5; +const std::array W_ROOK_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, W_ROOK, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +const std::vector W_ROOK_ALL_MOVES = { + D5, C5, B5, A5, + E6, E7, E8, + F5, G5, H5, E4, E3, E2, E1 }; -const Position W_KING_POS = C4; -const std::array W_KING_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, W_KING, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE +const int W_KING_POS = C4; +const std::array W_KING_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, W_KING, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::vector W_KING_ALL_MOVES = { +const int W_KING_SIDE1_POS = A8; +const std::array W_KING_SIDE1_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, W_KING, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +const std::vector W_KING_SIDE1_ALL_MOVES = { + A7,B7, + B8 +}; + +const std::vector W_KING_ALL_MOVES = { B5, C5, D5, - B4, C4, D4, - B3, C3, D3 + B3, C3, D3, + D4, B4 }; -const Position W_PAWN_POS = F4; -const std::array W_PAWN_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, W_PAWN, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE +const int W_PAWN_POS = F4; +const std::array W_PAWN_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, W_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +const std::vector W_PAWN_ALL_MOVES = { + F5 }; -const std::vector W_PAWN_ALL_MOVES = { - F6, - E5, F5, G5, - F4 +const int W_PAWN_SIDE1_POS = A8; +const std::array W_PAWN_SIDE1_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, W_PAWN, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; +const std::vector W_PAWN_SIDE1_ALL_MOVES; diff --git a/tests/bitwise_tests.cpp b/tests/bitwise_tests.cpp new file mode 100755 index 0000000..596b0bc --- /dev/null +++ b/tests/bitwise_tests.cpp @@ -0,0 +1,92 @@ +#include +#include +#include "catch.hpp" + +/* + * From (Position): 6 bits (2^6 == 64) possibilities + * To (Position): same as above + * Captured piece, if any: 4 bits (16) possibilities + * Promoted to, if any: 4 bits (16) possibilities + * en passant flag: 1 bit + * pawn starting move flag: 1 bit + * castle move flag: 1 bit + * + * (32-bit int, room to exapnd if neccessary) + * 0000 0000 0000 0000 0000 0000 0111 1111 -> From square position (& 0x7F) + * 0000 0000 0000 0000 0011 1111 1000 0000 -> To square position (>> 7 & 0x3F8) + * 0000 0000 0000 0011 1100 0000 0000 0000 -> captured piece, if any (>> 14 & 0xF) + * 0000 0000 0011 1100 0000 0000 0000 0000 -> if prmoted, what to? (>> 18 & 0xF) + * 0000 0000 0100 0000 0000 0000 0000 0000 -> en passant (& 0x400000) + * 0000 0000 1000 0000 0000 0000 0000 0000 -> pawn starting move (& 0x800000) + * 0000 0001 0000 0000 0000 0000 0000 0000 -> castle move (& 0x1000000) + * */ + +// This is testing position G1 +const unsigned int MOVE_G1 = Position::G1; + +// This is testing position H1 +const unsigned int MOVE_H1 = Position::H1; + +// This is testing a move with no flags from G1 to H1 +const unsigned int MOVE_G1_TO_H1 = 0b1100010'1100001; + +// This is testing a move with no flags from H1 to G1 +const unsigned int MOVE_H1_TO_G1 = 0b1100001'1100010; + +// Move from H1 to G1 and capture +const unsigned int MOVE_H1_TO_G1_CAPTURE_B_KNIGHT = 0b0010'1100001'1100010; + +// Move from H1 to G1 and promote +const unsigned int MOVE_H1_TO_G1_PROMOTE_TO_QUEEN = 0b0101'0000'1100001'1100010; + +// Move from H1 to G1 and en passant +const unsigned int MOVE_H1_TO_G1_EN_PASSANT = 0b1'0000'0000'1100001'1100010; + +// Move from H1 to G1 and its the starting move for a pawn +const unsigned int MOVE_H1_TO_G1_PAWN_START = 0b1'0'0000'0000'1100001'1100010; + +// Move from H1 to G1 and castle +const unsigned int MOVE_H1_TO_G1_AND_CASTLE = 0b1'0'0'0000'0000'1100001'1100010; + +// Want: +// From: E4 (65) +// To: D3 (74) +// (these 2 combine together) (33) +// Captures: B_PAWM (7) +// Promoted: NONE (0) +// en passant: true (1) +// pawn starting move: false (0) +// castle move: false (0) +// total value: (?) +const unsigned int GET_ALL_INT = 0b0'0'1'0000'0001'1001010'1000001; + +TEST_CASE("Test that bitwise operators return appropriate values. Move.from", "[bitwise_from_pos]"){ + CHECK(get_from_sq(MOVE_G1) == Position::G1); + CHECK(get_from_sq(MOVE_H1) == Position::H1); + CHECK(get_to_sq(MOVE_G1_TO_H1) == Position::H1); + CHECK(get_from_sq(MOVE_G1_TO_H1) == Position::G1); + + CHECK(get_to_sq(MOVE_H1_TO_G1) == Position::G1); + CHECK(get_from_sq(MOVE_H1_TO_G1) == Position::H1); + + CHECK(get_captured_pc(MOVE_H1_TO_G1_CAPTURE_B_KNIGHT) == PieceType::B_KNIGHT); + CHECK(get_promoted_to_pc(MOVE_H1_TO_G1_PROMOTE_TO_QUEEN) == PieceType::B_QUEEN); + + CHECK(get_en_pass_flag(MOVE_H1_TO_G1_EN_PASSANT) == 1); + CHECK(get_pawn_st_flag(MOVE_H1_TO_G1_PAWN_START) == 1); + CHECK(get_castle_flag(MOVE_H1_TO_G1_AND_CASTLE) == 1); + + CHECK(get_from_sq(GET_ALL_INT) == Position::E4); + CHECK(get_to_sq(GET_ALL_INT) == Position::D3); + CHECK(get_captured_pc(GET_ALL_INT) == PieceType::B_PAWN); + CHECK(get_promoted_to_pc(GET_ALL_INT) == PieceType::NONE); + CHECK(get_en_pass_flag(GET_ALL_INT) == 1); + CHECK(get_pawn_st_flag(GET_ALL_INT) == 0); + CHECK(get_castle_flag(GET_ALL_INT) == 0); +} + +TEST_CASE("Test that is_valid_position works properly", "[is_valid_position]"){ + CHECK_FALSE(is_valid_position(0)); + CHECK(is_valid_position(Position::A8)); + CHECK(is_valid_position(Position::H1)); +} diff --git a/tests/catch_main.cpp b/tests/catch_main.cpp new file mode 100755 index 0000000..0c7c351 --- /dev/null +++ b/tests/catch_main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" diff --git a/tests/custom_printing.cpp b/tests/custom_printing.cpp new file mode 100755 index 0000000..3866eee --- /dev/null +++ b/tests/custom_printing.cpp @@ -0,0 +1,86 @@ +#include "catch.hpp" +#include +#include +#include + +// override default printing for Positions so it prints the value (e.g. 32), then, in parenthasies, the location (e.g. A4). +// Example: A4(32) +namespace Catch { + template<> + struct StringMaker { + static std::string convert(Position const& p){ + std::stringstream ss; + ss << (int) p << "(" << POSITION_STRING[p] << ")"; + return ss.str(); + } + }; + // This override makes sure that Color enum variables are printed properly + template<> + struct StringMaker { + static std::string convert(Color const& c){ + std::stringstream ss; + if (c==Color::WHITE) ss << "white"; + if (c==Color::BLACK) ss << "black"; + if (c==Color::NO_COLOR) ss << "N/A"; + return ss.str(); + } + }; + // This prints all board comparisons in a readable fashion. Using the string name of the pieces, and newlines to seperate them. + template<> + struct StringMaker> { + static std::string convert(std::array const& board){ + std::stringstream ss; + ss << "{" << std::endl; + for (int i = 2; i < 10; ++i){ + for (int j = 1; j < 9; ++j){ + int index = (i*10)+j; + ss << CHESS_CHARS[board[index]] << ", "; + } + ss << std::endl; + } + ss << "}" << std::endl; + return ss.str(); + } + }; + // This overrides vectors of positions. I want it to print a board with the positions that are selected so we can see a representation of what positions are selected. + template<> + struct StringMaker> { + static std::string convert(std::vector const& uo_poss){ + std::vector poss(uo_poss.begin(), uo_poss.end()); + std::stringstream ss; + std::string files = " A B C D E F G H"; + ss << "{ {" << std::endl; + ss << files << std::endl; + for (int i = 2; i < 10; ++i){ + ss << 8-(i-2) << "|"; + for (int j = 1; j < 9; ++j){ + int index = (i*10)+j; + // This part loops through all positions in the list and checks if it contains the current index. + bool part_of_poss = false; + for (int p : poss){ + if (index == p) { + part_of_poss = true; + break; + } + } + // Justin, this is how this oporator works. + // (if) part_of_poss ?(then) do this :(else) do that. + part_of_poss ? ss << "* " : ss << " "; + } + ss << "|" << 8-(i-2); + ss << std::endl; + } + ss << files << std::endl; + ss << "}" << std::endl; + ss << "," << std::endl; + ss << "{ "; + for (int pi = 0; pi < poss.size(); ++pi){ + pi == poss.size()-1 ? ss << poss[pi] << "(" << POSITION_STRING[poss[pi]] << ")" : ss << poss[pi] << "(" << POSITION_STRING[poss[pi]] << "), "; + } + ss << " } }" << std::endl; + return ss.str(); + } + }; + +} + diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100755 index 0000000..95d0a8c --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,315 @@ +#include "catch.hpp" +#include "test_boards.h" +#include "valid_moves.h" +#include "custom_printing.cpp" +#include "test_functions.h" +#include +#include +#include + +const std::array DUMB_MOVE_1 = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK,INV, + INV, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, W_PAWN, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, W_PAWN, NONE, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN,INV, + INV, W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +TEST_CASE("Test that the get_to_squares works, this is required!", "[get_to_squares]"){ + std::vector to_squares = {Position::H1}; + std::vector moves = {0b11000100000000}; + REQUIRE(get_to_squares(moves) == to_squares); +} + +TEST_CASE("Test that get_rank() works)", "[get_rank]"){ + CHECK(get_rank(Position::F3) == Rank::RANK3); + CHECK(get_rank(Position::G1) == Rank::RANK1); +} + +TEST_CASE("Test that an unordered set of positions are returned when looking for a piece type through a board", "[get_pos_of]"){ + CHECK(get_poss_of(PieceType::B_PAWN, DEFAULT_BOARD) == B_PAWNS_SQUARES); +} + +TEST_CASE("Test that a color can be gotten from a given square on the board", "[get_color]"){ + CHECK(get_color(Position::C8, DUMB_MOVE_1) == Color::BLACK); + CHECK(get_color(Position::F4, DUMB_MOVE_1) == Color::NO_COLOR); + CHECK(get_color(Position::C2, DUMB_MOVE_1) == Color::WHITE); +} +TEST_CASE("Test that a color can be gotten from a PieceType", "[get_color]"){ + CHECK(get_color(PieceType::NONE) == Color::NO_COLOR); + CHECK(get_color(PieceType::W_KING) == Color::WHITE); + CHECK(get_color(PieceType::B_KING) == Color::BLACK); +} + +TEST_CASE("Test reversing color", "[rev_color]"){ + CHECK(rev_color(Color::NO_COLOR) == Color::NO_COLOR); + CHECK(rev_color(Color::WHITE) == Color::BLACK); + CHECK(rev_color(Color::BLACK) == Color::WHITE); +} + +TEST_CASE("Test reversing color on pieve", "[rev_color]"){ + CHECK(rev_color(PieceType::B_KING) == W_KING); + CHECK(rev_color(PieceType::B_QUEEN) == W_QUEEN); + CHECK(rev_color(PieceType::B_ROOK) == W_ROOK); + CHECK(rev_color(PieceType::B_BISHOP) == W_BISHOP); + CHECK(rev_color(PieceType::B_KNIGHT) == W_KNIGHT); + CHECK(rev_color(PieceType::B_PAWN) == W_PAWN); + CHECK(rev_color(PieceType::W_KING) == B_KING); + CHECK(rev_color(PieceType::W_QUEEN) == B_QUEEN); + CHECK(rev_color(PieceType::W_ROOK) == B_ROOK); + CHECK(rev_color(PieceType::W_BISHOP) == B_BISHOP); + CHECK(rev_color(PieceType::W_KNIGHT) == B_KNIGHT); + CHECK(rev_color(PieceType::W_PAWN) == B_PAWN); +} + +TEST_CASE("Test that is_black, and is_white are working", "[is_black][is_white]"){ + CHECK(is_white(DUMB_MOVE_1[Position::A2])); + CHECK(is_black(DUMB_MOVE_1[Position::F7])); + CHECK_FALSE(is_white(DUMB_MOVE_1[Position::B2])); + CHECK_FALSE(is_black(DUMB_MOVE_1[Position::B5])); + + // Test that NONE squares return false + CHECK_FALSE(is_white(DUMB_MOVE_1[Position::F4])); + CHECK_FALSE(is_black(DUMB_MOVE_1[Position::F4])); +} + +TEST_CASE("Test that dumb moves can be made.", "[dumb_move]"){ + int move_int = Position::B2 + (Position::B5 << 7); + CHECK(dumb_move(move_int, DEFAULT_BOARD) == DUMB_MOVE_1); +} + +TEST_CASE("Test that invalid position ints return false", "[is_valid_position]"){ + CHECK(is_valid_position(Position::A8)); + CHECK(is_valid_position(Position::H1)); + CHECK_FALSE(is_valid_position(((int) Position::H1) + 1)); +} + +TEST_CASE("Test all possible and impossible moves for black pieces", "[get_all_moves][black]"){ + CHECK(get_to_squares(get_all_moves(B_KING_POS, B_KING_BOARD)) == B_KING_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(B_QUEEN_POS, B_QUEEN_BOARD)) == B_QUEEN_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(B_ROOK_POS, B_ROOK_BOARD)) == B_ROOK_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(B_BISHOP_POS, B_BISHOP_BOARD)) == B_BISHOP_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(B_KNIGHT_POS, B_KNIGHT_BOARD)) == B_KNIGHT_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(B_PAWN_POS, B_PAWN_BOARD)) == B_PAWN_ALL_MOVES); +} +TEST_CASE("Test all possible and impossible moves for whtie pieces", "[get_all_moves][white]"){ + CHECK(get_to_squares(get_all_moves(W_KING_POS, W_KING_BOARD)) == W_KING_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(W_QUEEN_POS, W_QUEEN_BOARD)) == W_QUEEN_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(W_ROOK_POS, W_ROOK_BOARD)) == W_ROOK_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(W_BISHOP_POS, W_BISHOP_BOARD)) == W_BISHOP_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(W_KNIGHT_POS, W_KNIGHT_BOARD)) == W_KNIGHT_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(W_PAWN_POS, W_PAWN_BOARD)) == W_PAWN_ALL_MOVES); +} + +TEST_CASE("Test all moves for white in edge cases.", "[get_all_moves][white]"){ + CHECK(get_to_squares(get_all_moves(W_KNIGHT_SIDE1_POS, W_KNIGHT_SIDE1_BOARD)) == W_KNIGHT_SIDE1_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(W_KING_SIDE1_POS, W_KING_SIDE1_BOARD)) == W_KING_SIDE1_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(W_PAWN_SIDE1_POS, W_PAWN_SIDE1_BOARD)) == W_PAWN_SIDE1_ALL_MOVES); +} +TEST_CASE("Test all moves for black in edge cases.", "[get_all_moves][black]"){ + CHECK(get_to_squares(get_all_moves(B_KNIGHT_SIDE1_POS, B_KNIGHT_SIDE1_BOARD)) == B_KNIGHT_SIDE1_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(B_KING_SIDE1_POS, B_KING_SIDE1_BOARD)) == B_KING_SIDE1_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(B_PAWN_SIDE1_POS, B_PAWN_SIDE1_BOARD)) == B_PAWN_SIDE1_ALL_MOVES); +} + +TEST_CASE("Tests is_king_checked works", "[is_attacked]"){ + auto king_checked_moves = get_all_moves(KING_CHECK_TEST_POS, KING_CHECK_TEST_BOARD); + auto rook_checked_moves = get_all_moves(ROOK_CHECK_TEST_POS, KING_CHECK_TEST_BOARD); + CHECK(get_to_squares(king_checked_moves) == KING_CHECK_TEST_MOVES); + CHECK(get_to_squares(rook_checked_moves) == KING_CHECK_ROOK_MOVES); + CHECK(is_attacked(KING_CHECK_TEST_POS, KING_CHECK_TEST_BOARD)); + CHECK(is_attacked(BLACK_CHECK_POS1, BLACK_CHECK_BOARD1)); + CHECK(is_attacked(BLACK_CHECK_POS2, BLACK_CHECK_BOARD2)); +} + +TEST_CASE("Test the hypothetical positions can be tests for attacking", "[would_be_checked]"){ + CHECK_FALSE(would_be_attacked(BCASTLE_FROM_POS+1, PieceType::B_KING, CASTLE_BOARD)); + CHECK_FALSE(would_be_attacked(BCASTLE_FROM_POS+2, PieceType::B_KING, CASTLE_BOARD)); +} + +TEST_CASE("Test that moves that put own king in check are not returned", "[get_all_moves]"){ + CHECK(get_to_squares(get_all_moves(ROOK_CHECK_TEST_POS, ROOK_CHECK_TEST_BOARD)) == ROOK_CHECK_TEST_MOVES); + CHECK(get_to_squares(get_all_moves(PAWN_CHECK_TEST_POS, PAWN_CHECK_TEST_BOARD)) == PAWN_CHECK_TEST_MOVES); + auto pawn_diag_moves = get_all_moves(PAWN_DIAG_TEST1_POS, PAWN_DIAG_TEST1_BOARD); + std::vector pawn_start_flags = {0, 1, 0}; + CHECK(get_to_squares(pawn_diag_moves) == PAWN_DIAG_TEST1_MOVES); + CHECK(get_pawn_start_flags(pawn_diag_moves) == pawn_start_flags); +} + +TEST_CASE("Tests for en pessant squares.", "[get_all_moves]"){ + auto en_pass_moves = get_all_moves(EN_PASSANT_TEST_POS, EN_PASSANT_TEST_BOARD, true, EN_PASSANT_SQUARE); + std::vector en_passant_flags = {0, 1}; + CHECK(get_to_squares(en_pass_moves) == EN_PASSANT_TEST_MOVES); + CHECK(get_en_passant_flags(en_pass_moves) == en_passant_flags); + CHECK(get_to_squares(get_all_moves(NO_EN_PASSANT_TEST_POS, NO_EN_PASSANT_TEST_BOARD)) == NO_EN_PASSANT_TEST_MOVES); +} + +TEST_CASE("Test for pawn promotions.", "[get_all_moves]"){ + auto prom_moves = get_all_moves(PROM_PAWN_POS, PROM_PAWN_BOARD); + CHECK(get_to_squares(prom_moves) == PROM_PAWN_MOVES); + CHECK(get_promoted_pieces(prom_moves) == PROM_PAWN_PROMS); + auto bprom_moves = get_all_moves(PROM_BPAWN_POS, PROM_BPAWN_BOARD); + CHECK(get_to_squares(bprom_moves) == PROM_BPAWN_MOVES); + CHECK(get_promoted_pieces(bprom_moves) == PROM_BPAWN_PROMS); +} + +TEST_CASE("Test that the captures moves are returned", "[get_all_moves]"){ + auto knight_moves = get_all_moves(KNIGHT_BLOCKED1_POS, KNIGHT_BLOCKED1_BOARD); + auto bishop_moves = get_all_moves(BISHOP_BLOCKED1_POS, BISHOP_BLOCKED1_BOARD); + auto rook_moves = get_all_moves(ROOK_BLOCKED1_POS, ROOK_BLOCKED1_BOARD); + auto pawn_moves = get_all_moves(PAWN_DIAG_TEST1_POS, PAWN_DIAG_TEST1_BOARD); + auto king_moves = get_all_moves(KING_CHECK_TEST_POS, KING_CHECK_TEST_BOARD); + auto rook_check_moves = get_all_moves(ROOK_CHECK_MOVED_POS, ROOK_CHECK_MOVED_BOARD); + + CHECK(get_captured_pieces(knight_moves) == KNIGHT_BLOCKED1_CAPTS); + CHECK(get_captured_pieces(bishop_moves) == BISHOP_BLOCKED1_CAPTS); + CHECK(get_captured_pieces(rook_moves) == ROOK_BLOCKED1_CAPTS); + CHECK(get_captured_pieces(pawn_moves) == PAWN_DIAG_TEST1_CAPTS); + CHECK(get_captured_pieces(king_moves) == KING_CHECK_TEST_CAPTS); + CHECK(get_captured_pieces(rook_check_moves) == ROOK_CHECK_MOVED_CAPTURES); +} + +TEST_CASE("Test that being blocked, stops moves from generating", "[get_all_moves]"){ + auto knight_moves = get_all_moves(KNIGHT_BLOCKED1_POS, KNIGHT_BLOCKED1_BOARD); + auto bishop_moves = get_all_moves(BISHOP_BLOCKED1_POS, BISHOP_BLOCKED1_BOARD); + auto rook_moves = get_all_moves(ROOK_BLOCKED1_POS, ROOK_BLOCKED1_BOARD); + CHECK(get_to_squares(knight_moves) == KNIGHT_BLOCKED1_MOVES); + CHECK(get_to_squares(bishop_moves) == BISHOP_BLOCKED1_MOVES); + CHECK(get_to_squares(rook_moves) == ROOK_BLOCKED1_MOVES); +} + +TEST_CASE("Test for castling moves.", "[get_all_moves]"){ + std::vector cast_flags = {0, 0, 0, 0, 0, 1, 1}; + auto cast_moves = get_all_moves(CASTLING_POS, CASTLING_BOARD, true, 0, 0xF); + CHECK(get_to_squares(cast_moves) == CASTLING_MOVES); + CHECK(get_castle_flags(cast_moves) == cast_flags); + auto bcast_moves = get_all_moves(BCASTLING_POS, CASTLING_BOARD, true, 0, 0xF); + CHECK(get_to_squares(bcast_moves) == BCASTLING_MOVES); + CHECK(get_castle_flags(bcast_moves) == cast_flags); + // Check refuses castle + std::vector checked_cast_flags = {0, 0, 0}; + auto bcast_checked_moves = get_all_moves(BCASTLING_POS, CASTLING_CHECK_BOARD, true, 0, 0xF); + CHECK(get_to_squares(bcast_checked_moves) == BCASTLING_CHECK_MOVES); + CHECK(get_castle_flags(bcast_checked_moves) == checked_cast_flags); + // Check that castling moves are not allowed when the rook is blocked. + auto blocked_castling_moves = get_all_moves(CASTLE_BLOCKED_POS, CASTLE_BLOCKED_BOARD, true, 0, 0xF); + CHECK(get_to_squares(blocked_castling_moves) == CASTLE_BLOCKED_MOVES); + auto blocked_castling_qmoves = get_all_moves(CASTLE_BLOCKED_QPOS, CASTLE_BLOCKED_QBOARD, true, 0, 0xF); + CHECK(get_to_squares(blocked_castling_qmoves) == CASTLE_BLOCKED_QMOVES); +} + +TEST_CASE("Test that en passant moves are properly handled by dumb_move", "dumb_move"){ + CHECK(dumb_move(make_move(EN_PASSANT_CHECK_POS, EN_PASSANT_EN_PASSANT_SQUARE, PieceType::B_PAWN, PieceType::NONE, 1), EN_PASSANT_CHECK_BOARD) == EN_PASSANT_CHECK_MOVED_BOARD); + CHECK(dumb_move(make_move(EN_PASSANT_CHECK_POS1, EN_PASSANT_EN_PASSANT_SQUARE1, PieceType::B_PAWN, PieceType::NONE, 1), EN_PASSANT_CHECK_BOARD1) == EN_PASSANT_CHECK_MOVED_BOARD1); + CHECK(dumb_move(make_move(EN_PASSANT_CHECK_POS2, EN_PASSANT_EN_PASSANT_SQUARE2, PieceType::B_PAWN, PieceType::NONE, 1), EN_PASSANT_CHECK_BOARD2) == EN_PASSANT_CHECK_MOVED_BOARD2); + CHECK(dumb_move(make_move(EN_PASSANT_CHECK_POS3, EN_PASSANT_EN_PASSANT_SQUARE3, PieceType::B_PAWN, PieceType::NONE, 1), EN_PASSANT_CHECK_BOARD3) == EN_PASSANT_CHECK_MOVED_BOARD3); +} + +TEST_CASE("Test that castle moves are poperly handled by dumb_mobe", "[dumb_move]"){ + CHECK(dumb_move(make_move(CASTLE_FROM_POS, CASTLE_TO_POS, PieceType::NONE, PieceType::NONE, 0, 0, 1), CASTLE_BOARD) == CASTLE_BOARD_WK); + CHECK(dumb_move(make_move(CASTLE_FROM_QPOS, CASTLE_TO_QPOS, PieceType::NONE, PieceType::NONE, 0, 0, 1), CASTLE_BOARD) == CASTLE_BOARD_WQ); + CHECK(dumb_move(make_move(BCASTLE_FROM_POS, BCASTLE_TO_POS, PieceType::NONE, PieceType::NONE, 0, 0, 1), CASTLE_BOARD) == CASTLE_BOARD_BK); + CHECK(dumb_move(make_move(BCASTLE_FROM_QPOS, BCASTLE_TO_QPOS, PieceType::NONE, PieceType::NONE, 0, 0, 1), CASTLE_BOARD) == CASTLE_BOARD_BQ); +} + +TEST_CASE("Test that algebraic notation conversion is working.", "[to_notation]"){ + auto knight_moves = get_all_moves(KNIGHT_BLOCKED1_POS, KNIGHT_BLOCKED1_BOARD); + auto bishop_moves = get_all_moves(BISHOP_BLOCKED1_POS, BISHOP_BLOCKED1_BOARD); + auto rook_moves = get_all_moves(ROOK_BLOCKED1_POS, ROOK_BLOCKED1_BOARD); + auto pawn_moves = get_all_moves(PAWN_DIAG_TEST1_POS, PAWN_DIAG_TEST1_BOARD); + auto king_moves = get_all_moves(KING_CHECK_TEST_POS, KING_CHECK_TEST_BOARD); + auto king_castle_moves = get_all_moves(CASTLING_POS, CASTLE_BOARD, true, 0, 0xF); + auto king_bcastle_moves = get_all_moves(BCASTLING_POS, CASTLE_BOARD, true, 0, 0xF); + auto en_passant_moves = get_all_moves(EN_PASSANT_TEST_POS, EN_PASSANT_TEST_BOARD, true, EN_PASSANT_SQUARE, 0); + auto pawn_prom_moves = get_all_moves(PROM_PAWN_POS, PROM_PAWN_BOARD); + auto bpawn_prom_moves = get_all_moves(PROM_BPAWN_POS, PROM_BPAWN_BOARD); + + CHECK(get_notations(knight_moves, KNIGHT_BLOCKED1_BOARD) == KNIGHT_BLOCKED1_NOTATION); + CHECK(get_notations(bishop_moves, BISHOP_BLOCKED1_BOARD) == BISHOP_BLOCKED1_NOTATION); + CHECK(get_notations(rook_moves, ROOK_BLOCKED1_BOARD) == ROOK_BLOCKED1_NOTATION); + CHECK(get_notations(pawn_moves, PAWN_DIAG_TEST1_BOARD) == PAWN_DIAG_TEST1_NOTATION); + CHECK(get_notations(king_moves, KING_CHECK_TEST_BOARD) == KING_CHECK_TEST_NOTATION); + CHECK(get_notations(king_castle_moves, CASTLE_BOARD) == CASTLING_MOVES_NOTATION); + CHECK(get_notations(king_bcastle_moves, CASTLE_BOARD) == BCASTLING_MOVES_NOTATION); + CHECK(get_notations(en_passant_moves, EN_PASSANT_TEST_BOARD) == EN_PASSANT_TEST_NOTATION); + CHECK(get_notations(pawn_prom_moves, PROM_PAWN_BOARD) == PROM_PAWN_NOTATION); + CHECK(get_notations(bpawn_prom_moves, PROM_BPAWN_BOARD) == PROM_BPAWN_NOTATION); +} + +TEST_CASE("Test for disambiguating moves in algebraic notation", "[to_notation]"){ + auto brook1_moves = get_all_moves(DISAMB_BROOK1_POS, DISAMB_BOARD); + auto brook2_moves = get_all_moves(DISAMB_BROOK2_POS, DISAMB_BOARD); + auto wrook1_moves = get_all_moves(DISAMB_WROOK1_POS, DISAMB_BOARD); + auto wrook2_moves = get_all_moves(DISAMB_WROOK2_POS, DISAMB_BOARD); + auto bishop1_moves = get_all_moves(DISAMB_BISHOP1_POS, DISAMB_BOARD); + auto bishop2_moves = get_all_moves(DISAMB_BISHOP2_POS, DISAMB_BOARD); + auto queen1_moves = get_all_moves(DISAMB_QUEEN1_POS, DISAMB_BOARD); + auto queen2_moves = get_all_moves(DISAMB_QUEEN2_POS, DISAMB_BOARD); + auto queen3_moves = get_all_moves(DISAMB_QUEEN3_POS, DISAMB_BOARD); + + CHECK(get_notations(brook1_moves, DISAMB_BOARD) == DISAMB_BROOK1_NOTATION); + CHECK(get_notations(brook2_moves, DISAMB_BOARD) == DISAMB_BROOK2_NOTATION); + CHECK(get_notations(wrook1_moves, DISAMB_BOARD) == DISAMB_WROOK1_NOTATION); + CHECK(get_notations(wrook2_moves, DISAMB_BOARD) == DISAMB_WROOK2_NOTATION); + CHECK(get_notations(bishop1_moves, DISAMB_BOARD) == DISAMB_BISHOP1_NOTATION); + CHECK(get_notations(bishop2_moves, DISAMB_BOARD) == DISAMB_BISHOP2_NOTATION); + CHECK(get_notations(queen1_moves, DISAMB_BOARD) == DISAMB_QUEEN1_NOTATION); + CHECK(get_notations(queen2_moves, DISAMB_BOARD) == DISAMB_QUEEN2_NOTATION); + CHECK(get_notations(queen3_moves, DISAMB_BOARD) == DISAMB_QUEEN3_NOTATION); +} + +TEST_CASE("Test for disambiguating moves, and checkmate mark (#)", "[to_notation]"){ + auto check_rook_moves = get_all_moves(CHECKMATE_ROOK_POS, CHECKMATE_ROOK_BOARD); + + CHECK(get_notations(check_rook_moves, CHECKMATE_ROOK_BOARD) == CHECKMATE_ROOK_NOTATION); +} + +TEST_CASE("Do extra (random board tests) on notation and move generation", "[to_notation][get_all_moves]"){ + auto knight_moves = get_all_moves(KNIGHT_EXTRA1_POS, EXTRA1_BOARD); + auto knight_moves2 = get_all_moves(KNIGHT_EXTRA2_POS, EXTRA2_BOARD); + CHECK(get_notations(knight_moves, EXTRA1_BOARD) == KNIGHT_EXTRA1_NOTATION); + CHECK(get_notations(knight_moves2, EXTRA2_BOARD) == KNIGHT_EXTRA2_NOTATION); + CHECK(get_to_squares(knight_moves2) == KNIGHT_EXTRA2_MOVES); +} + +TEST_CASE("Test for promotions on empty squares", "[get_all_moves]"){ + auto pawn_prom = get_all_moves(PAWN_PROM_BLANK_POS, PAWN_PROM_BLANK_BOARD); + CHECK(get_notations(pawn_prom, PAWN_PROM_BLANK_BOARD) == PAWN_PROM_BLANK_NOTATION); +} + +TEST_CASE("Tests for check on square of queenside capture", "[get_all_moves]"){ + auto cannot_queenside = get_all_moves(CASTLE_CHECK1_POS, CASTLE_CHECK1_BOARD, true, 0, 0xF); + auto cannot_queenside2 = get_all_moves(CASTLE_CHECK2_POS, CASTLE_CHECK2_BOARD, true, 0, 0xF); + auto cannot_queenside3 = get_all_moves(CASTLE_CHECK3_POS, CASTLE_CHECK3_BOARD, true, 0, 0xF); + auto cannot_queenside4 = get_all_moves(CASTLE_CHECK4_POS, CASTLE_CHECK4_BOARD, true, 0, 0xF); + + CHECK(get_notations(cannot_queenside, CASTLE_CHECK1_BOARD) == CASTLE_CHECK1_NOTATION); + CHECK(get_notations(cannot_queenside2, CASTLE_CHECK2_BOARD) == CASTLE_CHECK2_NOTATION); + CHECK(get_notations(cannot_queenside3, CASTLE_CHECK3_BOARD) == CASTLE_CHECK3_NOTATION); + CHECK(get_notations(cannot_queenside4, CASTLE_CHECK4_BOARD) == CASTLE_CHECK4_NOTATION); +} + +TEST_CASE("Test that king check detection is working correctly.", "[king_checked]"){ + auto rook_check_moved_board = ROOK_CHECK_MOVED_BOARD; + CHECK(king_checked(rook_check_moved_board, Color::WHITE)); +} + +TEST_CASE("Test for add_checked_flags is working correctly.", "[get_all_moves][add_checked_flags]"){ + auto rook_checked_flags = get_all_moves(ROOK_CHECK_POS, ROOK_CHECK_BOARD); + + CHECK(get_notations(rook_checked_flags, ROOK_CHECK_BOARD) == ROOK_CHECK_NOTATION); + CHECK(get_checked_flags(rook_checked_flags) == ROOK_CHECK_FLAGS); +} + +TEST_CASE("Test that kings cannot move backwards into check", "[get_all_moves]"){ + auto king_back_checked = get_all_moves(BACK_CHECK_POS, BACK_CHECK_BOARD); + + CHECK(get_to_squares(king_back_checked) == BACK_CHECK_KING_MOVES); +} diff --git a/tests/speed.cpp b/tests/speed.cpp new file mode 100755 index 0000000..e2692c4 --- /dev/null +++ b/tests/speed.cpp @@ -0,0 +1,50 @@ +#include "valid_moves.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace std::chrono; + +#define TEST_FUNCTION(pre_func, function_with_params, number_of_times_to_run, test_number){\ + high_resolution_clock::time_point ts_(test_number) = high_resolution_clock::now();\ + for (int i = 0; i < (number_of_times_to_run); ++i){\ + (pre_func);\ + (functions_with_params);\ + }\ + high_resolution_clock::time_print te_(test_number) = high_resolution_clock::now();\ + auto duration = duration_cast(te_(test_number) - ts_(test_number)).count();\ + cout << "Function (functions_with_params) ran (number_of_times_to_run) times in " << duration_(test_number) << " micro seconds" << endl; + + +// TODO make complete, add complex scenarios. +// Test every function on their edge cases. +int main(){ + // Get all moves + high_resolution_clock::time_point t1 = high_resolution_clock::now(); + for (int i = 0; i < 10000000; i++){ + vector moves = {}; + get_all_moves(Position::E8, DEFAULT_BOARD, moves); + } + high_resolution_clock::time_point t2 = high_resolution_clock::now(); + auto duration = duration_cast( t2 - t1 ).count(); + cout << "10,000,000 iterations of get_all_moves took " << duration << " micro seconds" << endl; + + // to_notation (Rook) + high_resolution_clock::time_point t3 = high_resolution_clock::now(); + std::vector checkmate_rook_moves; + get_all_moves(CHECKMATE_ROOK_POS, CHECKMATE_ROOK_BOARD, checkmate_rook_moves); + for (int i = 0; i < 1000000; i++){ + for (int mv : checkmate_rook_moves){ + string notation = to_notation(mv, CHECKMATE_ROOK_BOARD); + } + } + high_resolution_clock::time_point t4 = high_resolution_clock::now(); + auto duration2 = duration_cast( t4 - t3 ).count(); + + cout << "~15,000,000 iterations of to_notation took " << duration2 << " micro seconds" << endl; +} diff --git a/tests/test_boards.h b/tests/test_boards.h old mode 100644 new mode 100755 diff --git a/tests/test_functions.cpp b/tests/test_functions.cpp new file mode 100755 index 0000000..fe351f8 --- /dev/null +++ b/tests/test_functions.cpp @@ -0,0 +1,71 @@ +#include "test_functions.h" +#include +#include +#include +#include +#include +#include + +std::vector get_to_squares(const std::vector& moves){ + std::vector transformed; + for (int mv : moves){ + transformed.push_back(get_to_sq(mv)); + } + return transformed; +} +std::vector get_from_squared(const std::vector& moves){ + std::vector transformed; + for (int mv : moves){ + transformed.push_back(get_from_sq(mv)); + } + return transformed; +} +std::vector get_captured_pieces(const std::vector& moves){ + std::vector transformed; + for (int mv : moves){ + transformed.push_back(get_captured_pc(mv)); + } + return transformed; +} +std::vector get_promoted_pieces(const std::vector& moves){ + std::vector transformed; + for (int mv : moves){ + transformed.push_back(get_promoted_to_pc(mv)); + } + return transformed; +} +std::vector get_en_passant_flags(const std::vector& moves){ + std::vector transformed; + for (int mv : moves){ + transformed.push_back(get_en_pass_flag(mv)); + } + return transformed; +} +std::vector get_pawn_start_flags(const std::vector& moves){ + std::vector transformed; + for (int mv : moves){ + transformed.push_back(get_pawn_st_flag(mv)); + } + return transformed; +} +std::vector get_castle_flags(const std::vector& moves){ + std::vector transformed; + for (int mv : moves){ + transformed.push_back(get_castle_flag(mv)); + } + return transformed; +} +std::vector get_checked_flags(const std::vector& moves){ + std::vector transformed; + for (int mv : moves){ + transformed.push_back(get_check_flag(mv)); + } + return transformed; +} +std::vector get_notations(const std::vector& moves, const std::array& board){ + std::vector notations; + for (int move : moves){ + notations.push_back(to_notation(move, board)); + } + return notations; +} diff --git a/tests/test_functions.h b/tests/test_functions.h new file mode 100755 index 0000000..38cb3e5 --- /dev/null +++ b/tests/test_functions.h @@ -0,0 +1,17 @@ +#ifndef TEST_FUNCTIONS_H +#define TEST_FUNCTOPMS_H +#include +#include +#include +#include + +std::vector get_from_squares(const std::vector& moves); +std::vector get_to_squares(const std::vector& moves); +std::vector get_captured_pieces(const std::vector& moves); +std::vector get_promoted_pieces(const std::vector& moves); +std::vector get_en_passant_flags(const std::vector& moves); +std::vector get_pawn_start_flags(const std::vector& moves); +std::vector get_castle_flags(const std::vector& moves); +std::vector get_checked_flags(const std::vector& moves); +std::vector get_notations(const std::vector& moves, const std::array& board); +#endif diff --git a/tests/tests_main.cpp b/tests/tests_main.cpp deleted file mode 100755 index 436c458..0000000 --- a/tests/tests_main.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#define CATCH_CONFIG_MAIN -#include "catch.hpp" -#include "test_boards.h" -#include -#include - -// For some retarted reason, I need to implement the printing of pairs, otherwise in the test outputs they show up as {?} -// Also override default printing for Positions so it prints the value (e.g. 32), then, in parenthasies, the location (e.g. A4). -// Example: A4(32) -namespace Catch { - template<> - struct StringMaker> { - static std::string convert(std::pair const& p){ - std::stringstream ss; - ss << "{ " << p.first << ", " << p.second << " }"; - return ss.str(); - } - }; - template<> - struct StringMaker { - static std::string convert(Position const& p){ - std::stringstream ss; - ss << (int) p << "(" << POSITION_STRING[p] << ")"; - return ss.str(); - } - }; - // This prints all board comparisons in a readable fashion. Using the string name of the pieces, and newlines to seperate them. - template<> - struct StringMaker> { - static std::string convert(std::array const& board){ - std::stringstream ss; - ss << "{" << std::endl; - for (int i = 0; i < 8; ++i){ - for (int j = 0; j < 8; ++j){ - int index = (i*8)+j; - ss << CHESS_CHARS[board[index]] << ", "; - } - ss << std::endl; - } - ss << "}" << std::endl; - return ss.str(); - } - }; - // This overrides vectors of positions. I want it to print a board with the positions that are selected so we can see a representation of what positions are selected. - template<> - struct StringMaker> { - static std::string convert(std::vector const& poss){ - std::stringstream ss; - std::string files = " A B C D E F G H"; - ss << "{ {" << std::endl; - ss << files << std::endl; - for (int i = 0; i < 8; ++i){ - ss << 8-i << "|"; - for (int j = 0; j < 8; ++j){ - int index = (i*8)+j; - // This part loops through all positions in the list and checks if it contains the current index. - bool part_of_poss = false; - for (Position p : poss){ - if (index == p) { - part_of_poss = true; - break; - } - } - // Justin, this is how this oporator works. - // (if) part_of_poss ?(then) do this :(else) do that. - part_of_poss ? ss << "* " : ss << " "; - } - ss << "|" << 8-i; - ss << std::endl; - } - ss << files << std::endl; - ss << "}" << std::endl; - ss << "," << std::endl; - ss << "{ "; - for (int pi = 0; pi < poss.size(); ++pi){ - pi == poss.size()-1 ? ss << poss[pi] << "(" << POSITION_STRING[poss[pi]] << ")" : ss << poss[pi] << "(" << POSITION_STRING[poss[pi]] << "), "; - } - ss << " } }" << std::endl; - return ss.str(); - } - }; - -} - -const std::array TEST_MOVES = { - W_QUEEN, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, B_KNIGHT -}; - -const std::array DUMB_MOVE_1 = { - B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, - B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, W_PAWN, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - W_PAWN, NONE, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, - W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK -}; - -TEST_CASE("Test that dumb moves can be made.", "[dumb_move]"){ - CHECK(dumb_move(Position::B2, Position::B5, DEFAULT_BOARD) == DUMB_MOVE_1); -} - -TEST_CASE("Test convert method to go from X and Y to board position", "[pair_to_pos]"){ - CHECK(pair_to_pos(std::make_pair(2, 3)) == Position::C4); - CHECK(pair_to_pos(std::make_pair(7, 0)) == Position::H1); - CHECK(pair_to_pos(std::make_pair(0, 0)) == Position::A1); - CHECK(pair_to_pos(std::make_pair(7, 7)) == Position::H8); - CHECK_THROWS(pair_to_pos(std::make_pair(8, 2))); - CHECK_THROWS(pair_to_pos(std::make_pair(-1, 1))); -} - -TEST_CASE("Test convert method to go from a board position to an x and y", "[pos_to_pair]"){ - CHECK(pos_to_pair(Position::A3) == std::make_pair(0, 2)); - CHECK(pos_to_pair(Position::A4) == std::make_pair(0, 3)); - CHECK(pos_to_pair(Position::B2) == std::make_pair(1, 1)); - CHECK(pos_to_pair(Position::H8) == std::make_pair(7, 7)); -} - -TEST_CASE("Test what pieces may move where functon", "[get_possible_movers]"){ - std::vector H1_possible_movers = {Position::H2, Position::G1}; - CHECK(get_possible_movers(Position::H3, DEFAULT_BOARD) == H1_possible_movers); -} - -TEST_CASE("Test where this piece may move to", "[get_possible_moves]"){ - std::vector white_right_knight_possible_moves = {Position::H3, Position::F3}; - std::vector black_A_pawn_possible_moves = {Position::A6,Position::A5}; - CHECK(get_possible_moves(Position::G1, DEFAULT_BOARD) == white_right_knight_possible_moves); - CHECK(get_possible_moves(Position::A7, DEFAULT_BOARD) == black_A_pawn_possible_moves); -} - -TEST_CASE("Test all possible and impossible moves for black pieces", "[get_all_moves][black]"){ - CHECK(get_all_moves(B_KING_POS, B_KING_BOARD) == B_KING_ALL_MOVES); - CHECK(get_all_moves(B_QUEEN_POS, B_QUEEN_BOARD) == B_QUEEN_ALL_MOVES); - CHECK(get_all_moves(B_ROOK_POS, B_ROOK_BOARD) == B_ROOK_ALL_MOVES); - CHECK(get_all_moves(B_BISHOP_POS, B_BISHOP_BOARD) == B_BISHOP_ALL_MOVES); - CHECK(get_all_moves(B_KNIGHT_POS, B_KNIGHT_BOARD) == B_KNIGHT_ALL_MOVES); - CHECK(get_all_moves(B_PAWN_POS, B_PAWN_BOARD) == B_PAWN_ALL_MOVES); - -} -TEST_CASE("Test all possible and impossible moves for whtie pieces", "[get_all_moves][white]"){ - CHECK(get_all_moves(W_KING_POS, W_KING_BOARD) == W_KING_ALL_MOVES); - CHECK(get_all_moves(W_QUEEN_POS, W_QUEEN_BOARD) == W_QUEEN_ALL_MOVES); - CHECK(get_all_moves(W_ROOK_POS, W_ROOK_BOARD) == W_ROOK_ALL_MOVES); - CHECK(get_all_moves(W_BISHOP_POS, W_BISHOP_BOARD) == W_BISHOP_ALL_MOVES); - CHECK(get_all_moves(W_KNIGHT_POS, W_KNIGHT_BOARD) == W_KNIGHT_ALL_MOVES); - CHECK(get_all_moves(W_PAWN_POS, W_PAWN_BOARD) == W_PAWN_ALL_MOVES); -} - diff --git a/tests/valid_moves.h b/tests/valid_moves.h new file mode 100755 index 0000000..71ea472 --- /dev/null +++ b/tests/valid_moves.h @@ -0,0 +1,939 @@ +#include +#include +#include + +/// This is for possible moves on a default board +const std::vector DEFAULT_B_A_PAWN_POSSIBLE_MOVES = { + A6, A5 +}; +const std::vector DEFAULT_W_A_PAWN_POSSIBLE_MOVES = { + A3, A4 +}; +const std::vector DEFAULT_W_R_KNIGHT_POSSIBLE_MOVES = { + H3, F3 +}; +// EMPTY +const std::vector DEFAULT_W_R_ROOK_POSSIBLE_MOVES = {}; + +const std::vector B_PAWNS_SQUARES = { + A7, B7, C7, D7, E7, F7, G7, H7 +}; + +// END of default selections + +const int KNIGHT_BLOCKED1_POS = B8; +const std::array KNIGHT_BLOCKED1_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, B_KNIGHT, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, B_PAWN, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, W_PAWN, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +// Should NOT inclde D7 +const std::vector KNIGHT_BLOCKED1_MOVES = { + A6, C6 +}; +const std::vector KNIGHT_BLOCKED1_CAPTS = { + NONE, W_PAWN +}; +const std::vector KNIGHT_BLOCKED1_NOTATION = { + "Na6", "Nxc6" +}; + +const int BISHOP_BLOCKED1_POS = D5; +const std::array BISHOP_BLOCKED1_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, B_QUEEN, NONE , B_PAWN , NONE, W_KING, NONE, NONE, INV, + INV, NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE , W_ROOK, W_BISHOP, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE , NONE , NONE , NONE, B_KING, NONE, NONE, INV, + INV, NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +// Should NOT include A8, H8, G2, or H1 +const std::vector BISHOP_BLOCKED1_MOVES = { + C6, B7, + E6, + C4, B3, A2, + E4, F3 +}; +const std::vector BISHOP_BLOCKED1_CAPTS = { + NONE, B_QUEEN, + NONE, + NONE, NONE, NONE, + NONE, B_KING, +}; +const std::vector BISHOP_BLOCKED1_NOTATION = { + "Bc6+", "Bxb7+", + "Be6", + "Bc4", "Bb3", "Ba2", + "Be4+", "Bxf3+" +}; + +// Should NOT include B2 (black queen) as it is obstructed by the bishop on D5 +const std::vector BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING = { + D5 +}; +const int BISHOP_BLOCKED1_KING_POS = F3; + +const int ROOK_BLOCKED1_POS = B7; +const std::array ROOK_BLOCKED1_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, W_ROOK, NONE , B_PAWN , NONE, B_KING, NONE, NONE, INV, + INV, NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE , B_BISHOP, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE, INV, + INV, NONE, W_KING , NONE , NONE , NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +// Should NOT include E-H2 or B3-1 +const std::vector ROOK_BLOCKED1_MOVES = { + A7, + B8, + C7, D7, + B6, B5, B4 +}; +const std::vector ROOK_BLOCKED1_CAPTS = { + NONE, + NONE, + NONE, B_PAWN, + NONE, NONE, NONE +}; +const std::vector ROOK_BLOCKED1_NOTATION = { + "Ra7", + "Rb8", + "Rc7", "Rxd7+", + "Rb6", "Rb5", "Rb4" +}; + +const int PAWN_DIAG_TEST1_POS = E7; +const std::array PAWN_DIAG_TEST1_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK,INV, + INV, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN,INV, + INV, NONE, NONE, NONE, W_QUEEN, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN,INV, + INV, W_ROOK, W_KNIGHT, W_BISHOP, NONE, W_KING, W_BISHOP, W_KNIGHT, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector PAWN_DIAG_TEST1_MOVES = { + E6, E5, D6 +}; +const std::vector PAWN_DIAG_TEST1_CAPTS = { + NONE, NONE, W_QUEEN +}; +const std::vector PAWN_DIAG_TEST1_NOTATION = { + "e6", "e5", "exd6" +}; + +// For testing the invalidating of moves because of putting own king in check +const int ROOK_CHECK_TEST_POS = D5; +const std::array ROOK_CHECK_TEST_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, W_KING, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, W_QUEEN, B_ROOK, NONE, B_KING, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector ROOK_CHECK_TEST_MOVES = { + C5, E5 +}; + +const int PAWN_CHECK_TEST_POS = E7; +const std::array PAWN_CHECK_TEST_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK,INV, + INV, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN,INV, + INV, NONE, NONE, NONE, W_PAWN, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, W_QUEEN, NONE, NONE, NONE,INV, + INV, W_PAWN, W_PAWN, W_PAWN, NONE, W_PAWN, W_PAWN, W_PAWN, W_PAWN,INV, + INV, W_ROOK, W_KNIGHT, W_BISHOP, NONE, W_KING, W_BISHOP, W_KNIGHT, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector PAWN_CHECK_TEST_MOVES = {E6, E5}; + +// These boards tests for en pessent squares. + +const int EN_PASSANT_SQUARE = E6; +const int EN_PASSANT_TEST_POS = D5; +const std::array EN_PASSANT_TEST_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK,INV, + INV, B_PAWN, B_PAWN, B_PAWN, NONE, B_PAWN, B_PAWN, B_PAWN, B_PAWN,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, W_PAWN, B_PAWN, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, W_PAWN, W_PAWN, W_PAWN, NONE, W_PAWN, W_PAWN, W_PAWN, W_PAWN,INV, + INV, W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector EN_PASSANT_TEST_MOVES = { + D6, E6 +}; +const std::vector EN_PASSANT_TEST_NOTATION = { + "d6", "dxe6e.p." +}; +// Test pawn promotion +const int PROM_PAWN_POS = G7; +const std::array PROM_PAWN_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK,INV, + INV, B_PAWN, B_PAWN, B_PAWN, NONE, B_PAWN, B_PAWN, W_PAWN, B_PAWN,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, W_PAWN, W_PAWN, W_PAWN, NONE, W_PAWN, W_PAWN, W_PAWN, W_PAWN,INV, + INV, W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector PROM_PAWN_MOVES = { + H8, H8, H8, H8, + F8, F8, F8, F8 +}; +const std::vector PROM_PAWN_PROMS = { + W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, + W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN +}; +const std::vector PROM_PAWN_NOTATION = { + "gxh8=N","gxh8=B","gxh8=R","gxh8=Q", + "gxf8=N","gxf8=B","gxf8=R","gxf8=Q" +}; + +// Black pawn promotion +const int PROM_BPAWN_POS = B2; +const std::array PROM_BPAWN_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK,INV, + INV, B_PAWN, B_PAWN, B_PAWN, NONE, B_PAWN, B_PAWN, B_PAWN, B_PAWN,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,INV, + INV, W_PAWN, B_PAWN, W_PAWN, NONE, W_PAWN, W_PAWN, W_PAWN, W_PAWN,INV, + INV, W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector PROM_BPAWN_MOVES = { + C1, C1, C1, C1, + A1, A1, A1, A1 +}; + +const std::vector PROM_BPAWN_PROMS = { + B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, + B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN +}; +const std::vector PROM_BPAWN_NOTATION = { + "bxc1=N","bxc1=B","bxc1=R","bxc1=Q", + "bxa1=N","bxa1=B","bxa1=R","bxa1=Q" +}; + +const int NO_EN_PASSANT_TEST_POS = D5; +const std::array NO_EN_PASSANT_TEST_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, INV, + INV, B_PAWN, B_PAWN, B_PAWN, NONE, B_PAWN, B_PAWN, B_PAWN, B_PAWN, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, W_PAWN, B_PAWN, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_PAWN, W_PAWN, W_PAWN, NONE, W_PAWN, W_PAWN, W_PAWN, W_PAWN, INV, + INV, W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector NO_EN_PASSANT_TEST_MOVES = {D6}; + +// Castling tests +const int CASTLING_POS = E1; +const int BCASTLING_POS = E8; +const std::array CASTLING_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, NONE, NONE, B_KING, NONE, NONE, B_ROOK, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_ROOK, NONE, NONE, NONE, W_KING, NONE, NONE, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +const std::vector CASTLING_MOVES = { + D2, E2, F2, F1, + D1, G1, C1 +}; +const std::vector BCASTLING_MOVES = { + D7, E7, F7, F8, D8, G8, C8 +}; +const std::vector CASTLING_MOVES_NOTATION = { + "Kd2", "Ke2", "Kf2", "Kf1", + "Kd1", "O-O", "O-O-O" +}; +const std::vector BCASTLING_MOVES_NOTATION = { + "Kd7", "Ke7", "Kf7", + "Kf8", "Kd8", "O-O", "O-O-O" +}; + +const std::array CASTLING_CHECK_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, NONE, NONE, B_KING, NONE, NONE, B_ROOK, INV, + INV, NONE, NONE, NONE, NONE, W_BISHOP, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_ROOK, NONE, NONE, NONE, W_KING, NONE, NONE, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::array BLACK_CHECK_BOARD1 = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, NONE, NONE, NONE, B_KING, NONE, B_ROOK, INV, + INV, NONE, NONE, NONE, NONE, W_BISHOP, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_ROOK, NONE, NONE, NONE, W_KING, NONE, NONE, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::array BLACK_CHECK_BOARD2 = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, NONE, B_KING, NONE, NONE, NONE, B_ROOK, INV, + INV, NONE, NONE, NONE, NONE, W_BISHOP, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_ROOK, NONE, NONE, NONE, W_KING, NONE, NONE, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const int BLACK_CHECK_POS1 = D8; +const int BLACK_CHECK_POS2 = F8; +const std::vector BCASTLING_CHECK_MOVES = { + D7, E7, F7 +}; +// Check that the dumb_move function actually moves the rook and the king to the right squares. +const int CASTLE_FROM_POS = E1; +const int CASTLE_TO_POS = G1; +const int BCASTLE_FROM_POS = E8; +const int BCASTLE_TO_POS = G8; + +const int CASTLE_FROM_QPOS = E1; +const int CASTLE_TO_QPOS = C1; +const int BCASTLE_FROM_QPOS = E8; +const int BCASTLE_TO_QPOS = C8; + +const std::array CASTLE_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, NONE, NONE, B_KING, NONE, NONE, B_ROOK, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_ROOK, NONE, NONE, NONE, W_KING, NONE, NONE, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::array CASTLE_BOARD_WK = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, NONE, NONE, B_KING, NONE, NONE, B_ROOK, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_ROOK, NONE, NONE, NONE, NONE, W_ROOK, W_KING, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::array CASTLE_BOARD_BK = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, NONE, NONE, NONE, B_ROOK, B_KING, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_ROOK, NONE, NONE, NONE, W_KING, NONE, NONE, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::array CASTLE_BOARD_WQ = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, NONE, NONE, B_KING, NONE, NONE, B_ROOK, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, W_KING, W_ROOK, NONE, NONE, NONE, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::array CASTLE_BOARD_BQ = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, B_KING, B_ROOK, NONE, NONE, NONE, B_ROOK, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_ROOK, NONE, NONE, NONE, W_KING, NONE, NONE, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +// Check that castling is disallowed when there is a piece blocking the rook queenside. +const int CASTLE_BLOCKED_POS = E1; +const std::array CASTLE_BLOCKED_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, NONE, NONE, B_KING, NONE, NONE, B_ROOK, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_ROOK, W_KNIGHT, NONE, NONE, W_KING, NONE, NONE, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector CASTLE_BLOCKED_MOVES = { + D2, E2, F2, + F1, D1, G1 +}; + +const int CASTLE_BLOCKED_QPOS = E8; +const std::array CASTLE_BLOCKED_QBOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, B_KNIGHT, NONE, NONE, B_KING, NONE, NONE, B_ROOK, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_ROOK, W_KNIGHT, NONE, NONE, W_KING, NONE, NONE, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector CASTLE_BLOCKED_QMOVES = { + D7, E7, F7, + F8, D8, G8 +}; + +// Check tests for king + +const int KING_CHECK_TEST_POS = D6; +const int KING_CHECK_ROOK_POS = D5; +const std::array KING_CHECK_TEST_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, W_KING, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, B_ROOK, NONE, NONE, B_KING, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, W_KING, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector KING_CHECK_TEST_MOVES = { + C7, E7, + D5, + E6, C6 +}; +const std::vector KING_CHECK_TEST_CAPTS = { + NONE, NONE, + B_ROOK, + NONE, NONE +}; +const std::vector KING_CHECK_TEST_NOTATION = { + "Kc7", "Ke7", + "Kxd5", + "Ke6", "Kc6" +}; +const std::vector KING_CHECK_ROOK_MOVES = { + C5, B5, A5, + D6, E5, F5, + D4, D3, D2, D1 +}; + +// This checks that en passant moves are handled correctly +// by the dumb_move method. +const int EN_PASSANT_EN_PASSANT_SQUARE = D7; +const int EN_PASSANT_CHECK_POS = E6; +const std::array EN_PASSANT_CHECK_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, B_QUEEN, NONE, NONE, B_PAWN, W_PAWN, NONE, NONE, W_KING, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, B_KING, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::array EN_PASSANT_CHECK_MOVED_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, W_PAWN, NONE, NONE, NONE, NONE, INV, + INV, B_QUEEN, NONE, NONE, NONE, NONE, NONE, NONE, W_KING, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, B_KING, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector EN_PASSANT_CHECKED_MOVES = { + E7 +}; + +const int EN_PASSANT_EN_PASSANT_SQUARE1 = F7; +const int EN_PASSANT_CHECK_POS1 = E6; +const std::array EN_PASSANT_CHECK_BOARD1 = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, W_PAWN, B_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, W_KING, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, B_KING, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::array EN_PASSANT_CHECK_MOVED_BOARD1 = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, W_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, W_KING, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, B_KING, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +const int EN_PASSANT_EN_PASSANT_SQUARE2 = D2; +const int EN_PASSANT_CHECK_POS2 = C3; +const std::array EN_PASSANT_CHECK_BOARD2 = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, W_KING, NONE, NONE, NONE, NONE, NONE, B_KING, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, B_PAWN, W_PAWN, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::array EN_PASSANT_CHECK_MOVED_BOARD2 = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, W_KING, NONE, NONE, NONE, NONE, NONE, B_KING, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, B_PAWN, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +const int EN_PASSANT_EN_PASSANT_SQUARE3 = D2; +const int EN_PASSANT_CHECK_POS3 = E3; +const std::array EN_PASSANT_CHECK_BOARD3 = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, B_KING, NONE, W_KING, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, W_PAWN, B_PAWN, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::array EN_PASSANT_CHECK_MOVED_BOARD3 = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, B_KING, NONE, W_KING, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, B_PAWN, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +// This tests for disambiguating moves with algebraic notation + +const int DISAMB_BISHOP1_POS = D6; +const int DISAMB_BISHOP2_POS = A7; +const int DISAMB_BROOK1_POS = D8; +const int DISAMB_BROOK2_POS = H8; +const int DISAMB_WROOK1_POS = A5; +const int DISAMB_WROOK2_POS = A1; +const int DISAMB_QUEEN1_POS = E4; +const int DISAMB_QUEEN2_POS = H4; +const int DISAMB_QUEEN3_POS = H1; + +const std::array DISAMB_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, B_ROOK, NONE, NONE, NONE, B_ROOK, INV, + INV, B_BISHOP, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, B_BISHOP, NONE, NONE, NONE, NONE, INV, + INV, W_ROOK, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, W_QUEEN, NONE, NONE, W_QUEEN, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_ROOK, NONE, NONE, NONE, NONE, NONE, NONE, W_QUEEN, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; + +const std::vector DISAMB_BROOK1_NOTATION = {"Rc8", "Rb8", "Ra8", "Rde8", "Rdf8", "Rdg8", "Rd7"}; +const std::vector DISAMB_BROOK2_NOTATION = {"Rhg8", "Rhf8", "Rhe8", "Rh7", "Rh6", "Rh5", "Rxh4"}; +const std::vector DISAMB_WROOK1_NOTATION = {"Ra6", "Rxa7", "Rb5", "Rc5", "Rd5", "Re5", "Rf5", "Rg5", "Rh5", "R5a4", "R5a3", "R5a2"}; +const std::vector DISAMB_WROOK2_NOTATION = {"R1a2", "R1a3", "R1a4", "Rb1", "Rc1", "Rd1", "Re1", "Rf1", "Rg1"}; +const std::vector DISAMB_BISHOP1_NOTATION = {"Bc7", "Bdb8", "Be7", "Bf8", "Bdc5", "Bb4", "Ba3", "Be5", "Bf4", "Bg3", "Bh2"}; +const std::vector DISAMB_BISHOP2_NOTATION = {"Bab8", "Bb6", "Bac5", "Bd4", "Be3", "Bf2", "Bg1"}; +const std::vector DISAMB_QUEEN1_NOTATION = {"Qd4", "Qc4", "Qb4", "Qa4", "Qe5", "Qe6", "Qee7", "Qe8", "Qef4", "Qeg4", "Qe3", "Qe2", "Qe4e1", "Qd5", "Qc6", "Qb7", "Qa8", "Qf5", "Qg6", "Qeh7", "Qd3", "Qc2", "Qeb1", "Qef3", "Qeg2"}; +const std::vector DISAMB_QUEEN2_NOTATION = {"Qhg4", "Qhf4", "Qh5", "Qh6", "Qhh7", "Qxh8", "Q4h3", "Q4h2", "Qg5", "Qf6", "Qhe7", "Qxd8", "Qg3", "Qf2", "Qh4e1"}; +const std::vector DISAMB_QUEEN3_NOTATION = {"Qg1", "Qf1", "Qh1e1", "Qd1", "Qc1", "Qhb1", "Q1h2", "Q1h3", "Qhg2", "Qhf3"}; + + +// CHeck that converting moves to algebraic notation have checkmate marks (#) +const int CHECKMATE_ROOK_POS = D8; +const std::array CHECKMATE_ROOK_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, B_ROOK, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, B_ROOK, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, W_KING, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector CHECKMATE_ROOK_NOTATION = { + "Rc8", "Rdb8", "Ra8", + "Re8", "Rf8", "Rg8+", "Rh8", + "Rd7", "Rd6", "Rd5", "Rd4", "Rd3", "Rdd2", "Rd1#" +}; + +// Extra checks on valid moves +const int KNIGHT_EXTRA1_POS = G5; +const std::array EXTRA1_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, INV, + INV, NONE, B_PAWN, B_PAWN, B_PAWN, NONE, NONE, B_PAWN, B_PAWN, INV, + INV, NONE, NONE, W_KNIGHT, NONE, NONE, B_PAWN, NONE, NONE, INV, + INV, B_PAWN, NONE, NONE, NONE, B_PAWN, W_PAWN, W_KNIGHT, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, NONE, W_PAWN, W_PAWN, INV, + INV, W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, NONE, W_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector KNIGHT_EXTRA1_NOTATION = { + "Ne6", "Nf7", "Nxh7", "Ne4", "Nf3", "Nh3" +}; + +const int KNIGHT_EXTRA2_POS = D4; +const std::array EXTRA2_BOARD = { + INV,INV,INV,INV,INV,INV,INV,INV,INV,INV, + INV,INV,INV,INV,INV,INV,INV,INV,INV,INV, + INV, B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, INV, + INV, B_PAWN, B_PAWN, B_PAWN, B_PAWN, NONE, B_PAWN, B_PAWN, B_PAWN, INV, + INV, NONE, NONE, NONE, NONE, B_PAWN, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, W_KNIGHT, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, INV, + INV, W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK, INV, + INV,INV,INV,INV,INV,INV,INV,INV,INV,INV, + INV,INV,INV,INV,INV,INV,INV,INV,INV,INV +}; +const std::vector KNIGHT_EXTRA2_MOVES = { + B5, C6, E6, F5, B3, F3 +}; +const std::vector KNIGHT_EXTRA2_NOTATION = { + "Nb5", "Nc6", "Nxe6", "Nf5", "Nb3", "Ndf3" +}; + +const std::array EXTRA3_BOARD = { + INV,INV,INV,INV,INV,INV,INV,INV,INV,INV, + INV,INV,INV,INV,INV,INV,INV,INV,INV,INV, + INV, B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, INV, + INV, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, W_KNIGHT, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, INV, + INV, W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK, INV, + INV,INV,INV,INV,INV,INV,INV,INV,INV,INV, + INV,INV,INV,INV,INV,INV,INV,INV,INV,INV +}; + + +// Tests that a pawn has promotion moves, even if there are only blank sqaures to move to. +const int PAWN_PROM_BLANK_POS = D7; +const std::array PAWN_PROM_BLANK_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, W_PAWN, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, B_ROOK, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, B_KING, NONE, W_KING, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector PAWN_PROM_BLANK_NOTATION = { + "d8=N", "d8=B", "d8=R", "d8=Q" +}; + +// This is another test for castling. +// As of the writing of this, the castling works even if the king is in check +// in the square it moves to... WTF? +const int CASTLE_CHECK1_POS = E8; +const std::array CASTLE_CHECK1_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, NONE, NONE, B_KING, B_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, B_PAWN, B_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, W_BISHOP, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, W_KING, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector CASTLE_CHECK1_NOTATION = { + "Kd8" +}; +const int CASTLE_CHECK2_POS = E8; +const std::array CASTLE_CHECK2_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, NONE, NONE, B_KING, B_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, B_QUEEN, B_PAWN, B_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, W_KNIGHT, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, W_KING, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector CASTLE_CHECK2_NOTATION = { + "Kd8" +}; +const int CASTLE_CHECK3_POS = E8; +const std::array CASTLE_CHECK3_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, NONE, B_PAWN, B_KING, NONE, NONE, B_ROOK, INV, + INV, NONE, NONE, NONE, B_QUEEN, B_PAWN, B_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, W_ROOK, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, W_KING, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector CASTLE_CHECK3_NOTATION = { + "Kf8" +}; +const int CASTLE_CHECK4_POS = E8; +const std::array CASTLE_CHECK4_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, B_ROOK, NONE, NONE, B_PAWN, B_KING, NONE, NONE, B_ROOK, INV, + INV, NONE, NONE, NONE, B_QUEEN, B_PAWN, B_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, W_KNIGHT, W_ROOK, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, W_KING, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector CASTLE_CHECK4_NOTATION = { + "Kf8" +}; + +// This is a check that moves are being marked as "check moves" poperly +const int ROOK_CHECK_POS = H3; +const int ROOK_CHECK_MOVED_POS = H1; +const int ROOK_CHECK_KING_POS = G1; +const std::array ROOK_CHECK_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, B_PAWN, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, B_PAWN, B_ROOK, INV, + INV, NONE, NONE, NONE, NONE, NONE, W_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, W_ROOK, W_KING, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::array ROOK_CHECK_MOVED_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, B_PAWN, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, B_PAWN, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, W_PAWN, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, W_ROOK, W_KING, B_ROOK, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector ROOK_CHECK_NOTATION = { + "Rh2", "Rh1+" +}; +const std::vector ROOK_CHECK_MOVED_MOVES = { + H3, H2, G1 +}; +const std::vector ROOK_CHECK_MOVED_CAPTURES = { + W_KING, NONE, NONE +}; +const std::vector ROOK_CHECK_FLAGS = { + 0, 1 +}; + +// This tests that kings cannot move backward into check from check +const int BACK_CHECK_POS = E6; +const std::array BACK_CHECK_BOARD = { + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, B_KING, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, W_ROOK, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, + INV, INV, INV, INV, INV, INV, INV, INV, INV, INV +}; +const std::vector BACK_CHECK_KING_MOVES = { + D7, F7, + D5, F5, + F6, D6 +};