diff --git a/src/functions.cpp b/src/functions.cpp index b645687..9d98b34 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -4,12 +4,23 @@ #include #include #include +#include #include #include // TODO implement functions.h functions. // NOTE tests will NOT run unless you implement these functions. +std::vector get_pos_of(PieceType pt, std::array board){ + std::vector pns; + for (int pn = Position::A8; pn!=Position::H1; pn++){ + if (board[pn] == pt){ + pns.push_back(static_cast(pn)); + } + } + return pns; +} + std::pair pos_to_pair(Position pn){ int x,y = 0; for (x = pn; x >= 8; x = x-8){ @@ -90,7 +101,7 @@ std::unordered_set get_possible_moves(Position pn, std::array get_all_moves(Position pn, std::array board){ +std::unordered_set get_all_moves(Position pn, std::array board, bool recursive){ PieceType pt = board[pn]; std::unordered_set pns; int x = pos_to_pair(pn).first; @@ -126,9 +137,60 @@ std::unordered_set get_all_moves(Position pn, std::array king_poss = get_pos_of(my_king, board); + Position my_king_pos; + if (king_poss.empty()){ + return pns; + } else { + my_king_pos = king_poss[0]; + } + int attackers = 0; + for (auto p_pn= pns.begin(); p_pn!=pns.end();){ + std::array moved_board = dumb_move(pn, *p_pn, board); + std::array other_team = is_white(pt)?Pieces::BLACK:Pieces::WHITE; + bool checks_king = false; + for (PieceType other_p : other_team) { + checks_king = false; + for (Position psn : get_pos_of(other_p, moved_board)){ + std::unordered_set other_moves = get_all_moves(psn, moved_board, false); + for (Position cp : other_moves){ + if (cp == my_king_pos){ + checks_king = true; + attackers++; + break; + } + } + if (checks_king){ + break; + } + } + if (checks_king){ + break; + } + } + if (checks_king){ + p_pn = pns.erase(p_pn); + } else { + ++p_pn; + } + } + } return pns; } +std::vector> get_all_moves_vec(std::vector v_pns, std::array board){ + std::vector> list_of_positions_for_pieces; + for (Position pn : v_pns){ + list_of_positions_for_pieces.push_back(get_all_moves(pn, board)); + } + return list_of_positions_for_pieces; +} + std::array dumb_move(Position from, Position to, std::array board){ PieceType piece = board[from]; board[to] = piece; diff --git a/src/functions.h b/src/functions.h index 39e7fdb..6856f30 100644 --- a/src/functions.h +++ b/src/functions.h @@ -4,17 +4,14 @@ #include #include -// x offset for knight -int poly_knight_offset_x(int x); - -// y offset for knight -int poly_knight_offset_y(int y); - // 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); Position pair_to_pos(int x, int y); +// Returns a list of positions with PieceType pt +std::vector get_pos_of(PieceType pt, std::array); + // Convert a Position number into a pair of x y coordiinates std::pair pos_to_pair(Position pn); @@ -45,8 +42,11 @@ std::unordered_set get_possible_movers(Position pn, std::array get_possible_moves(Position pn, std::array pt); -// Get all moved for piece in Position pn. -std::unordered_set get_all_moves(Position pn, std::array pt); +// Get all moves for piece in Position pn. +std::unordered_set get_all_moves(Position pn, std::array pt, bool recursive=true); +// Get all moves for a list of Pieces given as std::vector +// I'm not testing this because it's literally just a for loop and the above function. +std::vector> get_all_moves_vec(std::vector v_pns, std::array board); // 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 diff --git a/tests/tests_main.cpp b/tests/tests_main.cpp index ad218c2..fa5d4c1 100644 --- a/tests/tests_main.cpp +++ b/tests/tests_main.cpp @@ -110,6 +110,10 @@ const std::array DUMB_MOVE_1 = { W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK }; +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_pos_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(2, 7, DUMB_MOVE_1) == Color::BLACK); CHECK(get_color(3, 3, DUMB_MOVE_1) == Color::NO_COLOR); @@ -229,4 +233,9 @@ TEST_CASE("Test all moves for black in edge cases.", "[get_all_moves][black]"){ CHECK(get_all_moves(B_PAWN_SIDE1_POS, B_PAWN_SIDE1_BOARD) == B_PAWN_SIDE1_ALL_MOVES); } +TEST_CASE("Test that moves that put king in check are not returned", "[get_all_moves]"){ + CHECK(get_all_moves(ROOK_CHECK_TEST_POS, ROOK_CHECK_TEST_BOARD) == ROOK_CHECK_TEST_MOVES); + CHECK(get_all_moves(PAWN_CHECK_TEST_POS, PAWN_CHECK_TEST_BOARD) == PAWN_CHECK_TEST_MOVES); + CHECK(get_all_moves(PAWN_DIAG_TEST1_POS, PAWN_DIAG_TEST1_BOARD) == PAWN_DIAG_TEST1_MOVES); +} diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 3479827..47c6087 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -14,6 +14,11 @@ const std::unordered_set DEFAULT_W_R_KNIGHT_POSSIBLE_MOVES = { }; // EMPTY const std::unordered_set 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 Position KNIGHT_BLOCKED1_POS = B8; @@ -76,3 +81,46 @@ const std::unordered_set ROOK_BLOCKED1_MOVES = { B6,B5,B4 }; +const Position PAWN_DIAG_TEST1_POS = E7; +const std::array PAWN_DIAG_TEST1_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, 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, NONE, + W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, + W_ROOK, W_KNIGHT, W_BISHOP, NONE, W_KING, W_BISHOP, W_KNIGHT, W_ROOK +}; +const std::unordered_set PAWN_DIAG_TEST1_MOVES = { + D6, E6, E5 +}; + +// For testing the invalidating of moves because of putting own king in check +const Position ROOK_CHECK_TEST_POS = D5; +const std::array ROOK_CHECK_TEST_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, W_QUEEN, B_ROOK, 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, NONE, NONE, NONE, NONE, NONE +}; +const std::unordered_set ROOK_CHECK_TEST_MOVES = { + C5, E5 +}; + +const Position PAWN_CHECK_TEST_POS = E7; +const std::array PAWN_CHECK_TEST_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, 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, W_QUEEN, NONE, NONE, NONE, + W_PAWN, W_PAWN, W_PAWN, NONE, W_PAWN, W_PAWN, W_PAWN, W_PAWN, + W_ROOK, W_KNIGHT, W_BISHOP, NONE, W_KING, W_BISHOP, W_KNIGHT, W_ROOK +}; +const std::unordered_set PAWN_CHECK_TEST_MOVES = {E6, E5};