From d76f2f13ef9278c141162ff07f6bf258d2c26cab Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 00:48:14 +0000 Subject: [PATCH 01/81] Remove unused variables, and justin's old bishop code --- src/functions.cpp | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index d3049d1..9c30cda 100755 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -46,8 +46,6 @@ std::vector get_all_moves(Position pn, std::array board 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: @@ -75,35 +73,7 @@ std::vector get_all_moves(Position pn, std::array board 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) && (jx) && (i<8)) && ((j>=0) && (j Date: Sun, 7 Apr 2019 21:25:45 -0600 Subject: [PATCH 02/81] broken knight --- src/functions.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/functions.cpp b/src/functions.cpp index 9c30cda..1cd049f 100755 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -77,6 +77,31 @@ std::vector get_all_moves(Position pn, std::array board } } break; + case PieceType::B_KNIGHT: + case PieceType::W_KNIGHT: + for (int j = 7; j >= 0; j--){ + for (int i = 0; i < 8; i++){ + if (pair_to_pos(std::make_pair(x-1,y+2)) == pair_to_pos(std::make_pair(i,j))) + pns.push_back(pair_to_pos(std::make_pair(i,j))); + if (pair_to_pos(std::make_pair(x+1,y+2)) == pair_to_pos(std::make_pair(i,j))) + pns.push_back(pair_to_pos(std::make_pair(i,j))); + if (pair_to_pos(std::make_pair(x-2,y+1)) == pair_to_pos(std::make_pair(i,j))) + pns.push_back(pair_to_pos(std::make_pair(i,j))); + if (pair_to_pos(std::make_pair(x+2,y+1)) == pair_to_pos(std::make_pair(i,j))) + pns.push_back(pair_to_pos(std::make_pair(i,j))); + if (pair_to_pos(std::make_pair(x,y)) == pair_to_pos(std::make_pair(i,j))) + pns.push_back(pair_to_pos(std::make_pair(i,j))); + if (pair_to_pos(std::make_pair(x-2,y-1)) == pair_to_pos(std::make_pair(i,j))) + pns.push_back(pair_to_pos(std::make_pair(i,j))); + if (pair_to_pos(std::make_pair(x+2,y-1)) == pair_to_pos(std::make_pair(i,j))) + pns.push_back(pair_to_pos(std::make_pair(i,j))); + if (pair_to_pos(std::make_pair(x-1,y-2)) == pair_to_pos(std::make_pair(i,j))) + pns.push_back(pair_to_pos(std::make_pair(i,j))); + if (pair_to_pos(std::make_pair(x+1,y-2)) == pair_to_pos(std::make_pair(i,j))) + pns.push_back(pair_to_pos(std::make_pair(i,j))); + } + } + break; default: break; } From 4f09433cb36d37bded396a5f5b813ae24c22215c Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 03:30:08 +0000 Subject: [PATCH 03/81] Fix curly brace --- src/functions.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/functions.cpp b/src/functions.cpp index 1cd049f..12f3d76 100755 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -75,7 +75,6 @@ std::vector get_all_moves(Position pn, std::array board } } } - } break; case PieceType::B_KNIGHT: case PieceType::W_KNIGHT: From 2f0be9c302be7bb7b64b83b691ae596230061ff4 Mon Sep 17 00:00:00 2001 From: Justin Pilon Date: Sun, 7 Apr 2019 21:58:06 -0600 Subject: [PATCH 04/81] fully implemented kinght and king for get all moves --- src/functions.cpp | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index 12f3d76..bffb255 100755 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -46,6 +46,10 @@ std::vector get_all_moves(Position pn, std::array board std::vector pns; int x = pos_to_pair(pn).first; int y = pos_to_pair(pn).second; + std::vector knt_dx = {-1,1,-2,2,0,-2,2,-1,1}; + std::vector knt_dy = {2,2,1,1,0,-1,-1,-2,-2}; + std::vector kg_dx = {-1,0,1,-1,0,1,-1,0,1}; + std::vector kg_dy = {1,1,1,0,0,0,-1,-1,-1}; switch(pt){ case PieceType::B_ROOK: case PieceType::W_ROOK: @@ -79,26 +83,23 @@ std::vector get_all_moves(Position pn, std::array board case PieceType::B_KNIGHT: case PieceType::W_KNIGHT: for (int j = 7; j >= 0; j--){ - for (int i = 0; i < 8; i++){ - if (pair_to_pos(std::make_pair(x-1,y+2)) == pair_to_pos(std::make_pair(i,j))) - pns.push_back(pair_to_pos(std::make_pair(i,j))); - if (pair_to_pos(std::make_pair(x+1,y+2)) == pair_to_pos(std::make_pair(i,j))) - pns.push_back(pair_to_pos(std::make_pair(i,j))); - if (pair_to_pos(std::make_pair(x-2,y+1)) == pair_to_pos(std::make_pair(i,j))) - pns.push_back(pair_to_pos(std::make_pair(i,j))); - if (pair_to_pos(std::make_pair(x+2,y+1)) == pair_to_pos(std::make_pair(i,j))) - pns.push_back(pair_to_pos(std::make_pair(i,j))); - if (pair_to_pos(std::make_pair(x,y)) == pair_to_pos(std::make_pair(i,j))) - pns.push_back(pair_to_pos(std::make_pair(i,j))); - if (pair_to_pos(std::make_pair(x-2,y-1)) == pair_to_pos(std::make_pair(i,j))) - pns.push_back(pair_to_pos(std::make_pair(i,j))); - if (pair_to_pos(std::make_pair(x+2,y-1)) == pair_to_pos(std::make_pair(i,j))) - pns.push_back(pair_to_pos(std::make_pair(i,j))); - if (pair_to_pos(std::make_pair(x-1,y-2)) == pair_to_pos(std::make_pair(i,j))) - pns.push_back(pair_to_pos(std::make_pair(i,j))); - if (pair_to_pos(std::make_pair(x+1,y-2)) == pair_to_pos(std::make_pair(i,j))) - pns.push_back(pair_to_pos(std::make_pair(i,j))); + for (int i = 0; i < 8; i++){ + for (int k = 0; k < 9; k++){ + if (pair_to_pos(std::make_pair(x+knt_dx[k],y+knt_dy[k])) == pair_to_pos(std::make_pair(i,j))) + pns.push_back(pair_to_pos(std::make_pair(i,j))); + } + } } + break; + case PieceType::B_KING: + case PieceType::W_KING: + for (int j = 7; j >= 0; j--){ + for (int i = 0; i < 8; i++){ + for (int k = 0; k < 9; k++){ + if (pair_to_pos(std::make_pair(x+kg_dx[k],y+kg_dy[k])) == pair_to_pos(std::make_pair(i,j))) + pns.push_back(pair_to_pos(std::make_pair(i,j))); + } + } } break; default: From 9b63cd6c5262ef13cd5ea31afed9721c2f42ede0 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 04:33:06 +0000 Subject: [PATCH 05/81] Fix king and knight checks by removing pair_to_pos in if statements --- src/functions.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index bffb255..77df767 100755 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -85,7 +85,7 @@ std::vector get_all_moves(Position pn, std::array board for (int j = 7; j >= 0; j--){ for (int i = 0; i < 8; i++){ for (int k = 0; k < 9; k++){ - if (pair_to_pos(std::make_pair(x+knt_dx[k],y+knt_dy[k])) == pair_to_pos(std::make_pair(i,j))) + if (std::make_pair(x+knt_dx[k],y+knt_dy[k]) == std::make_pair(i,j)) pns.push_back(pair_to_pos(std::make_pair(i,j))); } } @@ -96,7 +96,7 @@ std::vector get_all_moves(Position pn, std::array board for (int j = 7; j >= 0; j--){ for (int i = 0; i < 8; i++){ for (int k = 0; k < 9; k++){ - if (pair_to_pos(std::make_pair(x+kg_dx[k],y+kg_dy[k])) == pair_to_pos(std::make_pair(i,j))) + if (std::make_pair(x+kg_dx[k],y+kg_dy[k]) == std::make_pair(i,j)) pns.push_back(pair_to_pos(std::make_pair(i,j))); } } From 126a9b02e1979f646983c6528873adc53caae06c Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 04:33:24 +0000 Subject: [PATCH 06/81] Add some edge cases --- tests/B_test_boards.h | 49 ++++++++++++++++++++++++++++++++++++++++++ tests/W_test_boards.h | 50 +++++++++++++++++++++++++++++++++++++++++++ tests/tests_main.cpp | 12 +++++++++++ 3 files changed, 111 insertions(+) diff --git a/tests/B_test_boards.h b/tests/B_test_boards.h index 273ab76..da52c1a 100644 --- a/tests/B_test_boards.h +++ b/tests/B_test_boards.h @@ -121,3 +121,52 @@ const std::vector B_PAWN_ALL_MOVES = { E3, F3, G3, F2 }; +const Position B_KNIGHT_SIDE1_POS = B7; +const std::array B_KNIGHT_SIDE1_BOARD = { + 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, NONE, NONE, + NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, + NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE +}; +const std::vector B_KNIGHT_SIDE1_ALL_MOVES = { + D8, + B7, + D6, + A5, C5 +}; +const Position B_KING_SIDE1_POS = A8; +const std::array B_KING_SIDE1_BOARD = { + 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, 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 B_KING_SIDE1_ALL_MOVES = { + A8,B8, + A7,B7 +}; + +const Position B_PAWN_SIDE1_POS = A1; +const std::array B_PAWN_SIDE1_BOARD = { + 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, 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 B_PAWN_SIDE1_ALL_MOVES = { + A8, + A7, B7, + A6 +}; diff --git a/tests/W_test_boards.h b/tests/W_test_boards.h index b9ec152..4544b11 100644 --- a/tests/W_test_boards.h +++ b/tests/W_test_boards.h @@ -68,6 +68,24 @@ const std::array W_KNIGHT_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; +const Position W_KNIGHT_SIDE1_POS = B7; +const std::array W_KNIGHT_SIDE1_BOARD = { + 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, NONE, NONE, + NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, + NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE +}; +const std::vector W_KNIGHT_SIDE1_ALL_MOVES = { + D8, + B7, + D6, + A5, C5 +}; + const std::vector W_KNIGHT_ALL_MOVES = { C7, E7, B6, F6, @@ -107,6 +125,23 @@ const std::array W_KING_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; +const Position W_KING_SIDE1_POS = A8; +const std::array W_KING_SIDE1_BOARD = { + 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, 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_KING_SIDE1_ALL_MOVES = { + A8,B8, + A7,B7 +}; + const std::vector W_KING_ALL_MOVES = { B5, C5, D5, B4, C4, D4, @@ -131,3 +166,18 @@ const std::vector W_PAWN_ALL_MOVES = { E5, F5, G5, F4 }; + +const Position W_PAWN_SIDE1_POS = A1; +const std::array W_PAWN_SIDE1_BOARD = { + 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, 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_PAWN_SIDE1_ALL_MOVES = { + A8 +}; diff --git a/tests/tests_main.cpp b/tests/tests_main.cpp index 436c458..fc0cba9 100755 --- a/tests/tests_main.cpp +++ b/tests/tests_main.cpp @@ -148,3 +148,15 @@ TEST_CASE("Test all possible and impossible moves for whtie pieces", "[get_all_m CHECK(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_all_moves(W_KNIGHT_SIDE1_POS, W_KNIGHT_SIDE1_BOARD) == W_KNIGHT_SIDE1_ALL_MOVES); + CHECK(get_all_moves(W_KING_SIDE1_POS, W_KING_SIDE1_BOARD) == W_KING_SIDE1_ALL_MOVES); + CHECK(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_all_moves(B_KNIGHT_SIDE1_POS, B_KNIGHT_SIDE1_BOARD) == B_KNIGHT_SIDE1_ALL_MOVES); + CHECK(get_all_moves(B_KING_SIDE1_POS, B_KING_SIDE1_BOARD) == B_KING_SIDE1_ALL_MOVES); + CHECK(get_all_moves(B_PAWN_SIDE1_POS, B_PAWN_SIDE1_BOARD) == B_PAWN_SIDE1_ALL_MOVES); +} + + From 7804775b994734af4ac380440360104ab738cf65 Mon Sep 17 00:00:00 2001 From: Justin Pilon Date: Sun, 7 Apr 2019 22:55:19 -0600 Subject: [PATCH 07/81] broken pawns --- src/functions.cpp | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index 77df767..1ae1106 100755 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -48,8 +48,12 @@ std::vector get_all_moves(Position pn, std::array board int y = pos_to_pair(pn).second; std::vector knt_dx = {-1,1,-2,2,0,-2,2,-1,1}; std::vector knt_dy = {2,2,1,1,0,-1,-1,-2,-2}; - std::vector kg_dx = {-1,0,1,-1,0,1,-1,0,1}; - std::vector kg_dy = {1,1,1,0,0,0,-1,-1,-1}; + std::vector kg_dx = {-1,0,1,-1,0,1,-1,0,1}; + std::vector kg_dy = {1,1,1,0,0,0,-1,-1,-1}; + std::vector Bpa_dx = {0,-1,0,1,0,0}; + std::vector Bpa_dy = {-1,0,0,0,1,2}; + std::vector Wpa_dx = {0,0,-1,0,1,0}; + std::vector Wpa_dy = {2,1,0,0,0,-1}; switch(pt){ case PieceType::B_ROOK: case PieceType::W_ROOK: @@ -102,6 +106,26 @@ std::vector get_all_moves(Position pn, std::array board } } break; + case PieceType::B_PAWN: + for (int j = 7; j >= 0; j--){ + for (int i = 0; i < 8; i++){ + for (int k = 0; k < 6; k++){ + if (std::make_pair(x+Bpa_dx[k],y+Bpa_dy[k]) == std::make_pair(i,j)) + pns.push_back(pair_to_pos(std::make_pair(i,j))); + } + } + } + break; + case PieceType::W_PAWN: + for (int j = 7; j >= 0; j--){ + for (int i = 0; i < 8; i++){ + for (int k = 0; k < 6; k++){ + if (std::make_pair(x+Wpa_dx[k],y+Wpa_dy[k]) == std::make_pair(i,j)) + pns.push_back(pair_to_pos(std::make_pair(i,j))); + } + } + } + break; default: break; } From eb3a05ac615b21032e44649e610d194b0b860229 Mon Sep 17 00:00:00 2001 From: gitJustin86 Date: Mon, 8 Apr 2019 17:37:24 +0100 Subject: [PATCH 08/81] first polynomial attempt --- src/Makefile | 22 +++++++++++----------- src/chess.cpp | 4 ++++ src/functions.cpp | 13 +++++++++++++ src/functions.h | 7 +++++++ 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/Makefile b/src/Makefile index 90cd7b7..2e5e263 100755 --- a/src/Makefile +++ b/src/Makefile @@ -1,15 +1,15 @@ #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 -# -#main.o: main.cpp -# g++ -c -std=c++11 main.cpp -# -#SerialComm.o: SerialComm.cpp SerialComm.hpp -# g++ -c -std=c++11 SerialComm.cpp + +chess.out: functions.o + g++ chess.o functions.o -std=c++11 + +chess.o: chess.cpp + g++ -c -std=c++11 chess.cpp + +functions.o: functions.cpp functions.h + g++ -c -std=c++11 functions.cpp default: build -build: - g++ -o chess.out chess.cpp -std=c++11 +#build: +# g++ -o chess.out chess.cpp -std=c++11 diff --git a/src/chess.cpp b/src/chess.cpp index 963e626..0b8ad3b 100755 --- a/src/chess.cpp +++ b/src/chess.cpp @@ -2,6 +2,7 @@ #include #include #include "constants.h" +#include "functions.h" // See constants.h for CHESS_CHARS, and DEFAULT_BOARD @@ -15,4 +16,7 @@ int main(){ } cout << endl; } + + cout << "poly test" << endl; + cout << "(1," << poly_knight_offset_x(1) << ")" << endl; } diff --git a/src/functions.cpp b/src/functions.cpp index 1ae1106..7397e71 100755 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -4,6 +4,7 @@ #include #include #include +#include // TODO implement functions.h functions. // NOTE tests will NOT run unless you implement these functions. @@ -41,6 +42,18 @@ std::vector get_possible_moves(Position pn, std::array return pns; } +int poly_knight_offset_x(int x) { + return -2.1500176772557799*pow(10,2)*pow(x,0) + + +5.0175460279545990*pow(10,2)*pow(x,1) + + -4.3971301635198080*pow(10,2)*pow(x,2) + + +1.9251081929895420*pow(10,2)*pow(x,3) + + -4.6354931502296793*pow(10,1)*pow(x,4) + + +6.2293079395174518*pow(10,0)*pow(x,5) + + -4.3751543665888198*pow(10,1)*pow(x,6) + + +1.2500918807028260*pow(10,2)*pow(x,7) + + -2.2939912578846349*pow(10,8)*pow(x,8); +} + std::vector get_all_moves(Position pn, std::array board){ PieceType pt = board[pn]; std::vector pns; diff --git a/src/functions.h b/src/functions.h index ce5e347..7eed490 100755 --- a/src/functions.h +++ b/src/functions.h @@ -1,6 +1,13 @@ #include "constants.h" #include #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. From 735e14f3aa44a9fa091e9cd41c02394cc3ca23db Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 16:41:51 +0000 Subject: [PATCH 09/81] Let's keep the Makefile as simple as possible. --- src/Makefile | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Makefile b/src/Makefile index 2e5e263..f9d1d7f 100755 --- a/src/Makefile +++ b/src/Makefile @@ -1,15 +1,15 @@ #CC=g++-4.2 - -chess.out: functions.o - g++ chess.o functions.o -std=c++11 - -chess.o: chess.cpp - g++ -c -std=c++11 chess.cpp - -functions.o: functions.cpp functions.h - g++ -c -std=c++11 functions.cpp - +# +#chess.out: functions.o +# g++ chess.o functions.o -std=c++11 +# +#chess.o: chess.cpp +# g++ -c -std=c++11 chess.cpp +# +#functions.o: functions.cpp functions.h +# g++ -c -std=c++11 functions.cpp +# default: build -#build: -# g++ -o chess.out chess.cpp -std=c++11 +build: + g++ -o chess.out functions.cpp chess.cpp -std=c++11 From 7c45069bbb9a349f70588edaf0aeab7ee72dbd0e Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 18:14:12 +0000 Subject: [PATCH 10/81] Fix knight with fixed offset method --- src/functions.cpp | 37 ++++++++++++++++++++++++++++++------- src/functions.h | 7 +++++++ tests/tests_main.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index 7397e71..7318026 100755 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -32,6 +32,22 @@ Position pair_to_pos(std::pair pr){ throw std::invalid_argument(ss.str()); } } +Position pair_to_pos(int x, int y){ + return pair_to_pos(std::make_pair(x, y)); +} + +bool is_valid_position(int pos){ + return (pos >= 0 && pos < 64); +} +bool is_valid_position(std::pair pos){ + return (pos.first < 8 && pos.second < 8 && + pos.first >= 0 && pos.second >=0); +} +bool is_valid_position(int x, int y){ + return (x < 8 && x >= 0 && + y < 8 && y >= 0); +} + std::vector get_possible_movers(Position pn, std::array board){ std::vector pns = {Position::A1}; return pns; @@ -99,14 +115,21 @@ std::vector get_all_moves(Position pn, std::array board break; case PieceType::B_KNIGHT: case PieceType::W_KNIGHT: - for (int j = 7; j >= 0; j--){ - for (int i = 0; i < 8; i++){ - for (int k = 0; k < 9; k++){ - if (std::make_pair(x+knt_dx[k],y+knt_dy[k]) == std::make_pair(i,j)) - pns.push_back(pair_to_pos(std::make_pair(i,j))); - } + for (int xo=1;xo<=2;xo++){ + int yo=(xo==1)?2:1; + if (is_valid_position(x+xo, y+yo)){ + pns.push_back(pair_to_pos(std::make_pair(x+xo, y+yo))); + } + if (is_valid_position(x-xo, y-yo)){ + pns.push_back(pair_to_pos(std::make_pair(x-xo, y-yo))); + } + if (is_valid_position(x-xo, y+yo)){ + pns.push_back(pair_to_pos(std::make_pair(x-xo, y+yo))); + } + if (is_valid_position(x+xo, y-yo)){ + pns.push_back(pair_to_pos(std::make_pair(x+xo, y-yo))); + } } - } break; case PieceType::B_KING: case PieceType::W_KING: diff --git a/src/functions.h b/src/functions.h index 7eed490..2c6cb9e 100755 --- a/src/functions.h +++ b/src/functions.h @@ -12,10 +12,17 @@ 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); // 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); +bool is_valid_position(std::pair pos); +bool is_valid_position(int x, int y); + // 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. diff --git a/tests/tests_main.cpp b/tests/tests_main.cpp index fc0cba9..e72ed6c 100755 --- a/tests/tests_main.cpp +++ b/tests/tests_main.cpp @@ -109,6 +109,14 @@ TEST_CASE("Test convert method to go from X and Y to board position", "[pair_to_ 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))); + + CHECK(pair_to_pos(2, 3) == Position::C4); + CHECK(pair_to_pos(7, 0) == Position::H1); + CHECK(pair_to_pos(0, 0) == Position::A1); + CHECK(pair_to_pos(7, 7) == Position::H8); + CHECK_THROWS(pair_to_pos(8, 2)); + CHECK_THROWS(pair_to_pos(-1, 1)); + } TEST_CASE("Test convert method to go from a board position to an x and y", "[pos_to_pair]"){ @@ -118,6 +126,23 @@ TEST_CASE("Test convert method to go from a board position to an x and y", "[pos CHECK(pos_to_pair(Position::H8) == std::make_pair(7, 7)); } +TEST_CASE("Test that invalid position ints return false", "[is_valid_position]"){ + CHECK(is_valid_position(0)); // 0=A8 + CHECK(is_valid_position(63)); // 63=H1 + CHECK_FALSE(is_valid_position(-1)); // -1 is out of bounds + CHECK_FALSE(is_valid_position(64)); // 64 is out of bounds + + CHECK(is_valid_position(std::make_pair(0, 0))); // 0-7,0-7 should be valid + CHECK(is_valid_position(std::make_pair(7, 7))); + CHECK_FALSE(is_valid_position(std::make_pair(-1, 5))); // should fail + CHECK_FALSE(is_valid_position(std::make_pair(5, 8))); // should fail + + CHECK(is_valid_position(0, 0)); // 0-7,0-7 should be valid + CHECK(is_valid_position(7, 7)); + CHECK_FALSE(is_valid_position(-1, 5)); // should fail + CHECK_FALSE(is_valid_position(5, 8)); // should fail +} + 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); From 6b8f5ed7ad2f0e20669f50f134021b08ec5144f5 Mon Sep 17 00:00:00 2001 From: gitJustin86 Date: Mon, 8 Apr 2019 19:52:01 +0100 Subject: [PATCH 11/81] justins polynomial knight implementation please don't insult it, he loves math! --- src/chess.cpp | 21 ++++++++++++++++++++- src/functions.cpp | 37 +++++++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/chess.cpp b/src/chess.cpp index 0b8ad3b..58ad503 100755 --- a/src/chess.cpp +++ b/src/chess.cpp @@ -17,6 +17,25 @@ int main(){ cout << endl; } - cout << "poly test" << endl; + cout << "poly X" << endl; cout << "(1," << poly_knight_offset_x(1) << ")" << endl; + cout << "(2," << poly_knight_offset_x(2) << ")" << endl; + cout << "(3," << poly_knight_offset_x(3) << ")" << endl; + cout << "(4," << poly_knight_offset_x(4) << ")" << endl; + cout << "(5," << poly_knight_offset_x(5) << ")" << endl; + cout << "(6," << poly_knight_offset_x(6) << ")" << endl; + cout << "(7," << poly_knight_offset_x(7) << ")" << endl; + cout << "(8," << poly_knight_offset_x(8) << ")" << endl; + cout << "(9," << poly_knight_offset_x(9) << ")" << endl; + cout << "poly Y" << endl; + cout << "(1," << poly_knight_offset_y(1) << ")" << endl; + cout << "(2," << poly_knight_offset_y(2) << ")" << endl; + cout << "(3," << poly_knight_offset_y(3) << ")" << endl; + cout << "(4," << poly_knight_offset_y(4) << ")" << endl; + cout << "(5," << poly_knight_offset_y(5) << ")" << endl; + cout << "(6," << poly_knight_offset_y(6) << ")" << endl; + cout << "(7," << poly_knight_offset_y(7) << ")" << endl; + cout << "(8," << poly_knight_offset_y(8) << ")" << endl; + cout << "(9," << poly_knight_offset_y(9) << ")" << endl; + } diff --git a/src/functions.cpp b/src/functions.cpp index 7397e71..10e127f 100755 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -42,18 +42,31 @@ std::vector get_possible_moves(Position pn, std::array return pns; } -int poly_knight_offset_x(int x) { - return -2.1500176772557799*pow(10,2)*pow(x,0) + - +5.0175460279545990*pow(10,2)*pow(x,1) + - -4.3971301635198080*pow(10,2)*pow(x,2) + - +1.9251081929895420*pow(10,2)*pow(x,3) + - -4.6354931502296793*pow(10,1)*pow(x,4) + - +6.2293079395174518*pow(10,0)*pow(x,5) + - -4.3751543665888198*pow(10,1)*pow(x,6) + - +1.2500918807028260*pow(10,2)*pow(x,7) + - -2.2939912578846349*pow(10,8)*pow(x,8); +int poly_knight_offset_x(int x) { + return round(-214.986133*pow(10,0)*pow(x,0) + + +501.7139779*pow(10,0)*pow(x,1) + + -439.6717407*pow(10,0)*pow(x,2) + + +192.48892*pow(10,0)*pow(x,3) + + -46.34819552*pow(10,0)*pow(x,4) + + +6.228063921*pow(10,0)*pow(x,5) + + -4.373795219*pow(10,-1)*pow(x,6) + + +1.249282993*pow(10,-2)*pow(x,7) + + +1.789952521*pow(10,-7)*pow(x,8)); } +int poly_knight_offset_y(int x) { + return round(-31.99806307*pow(10,0)*pow(x,0) + + +79.90649854*pow(10,0)*pow(x,1) + + -70.06372154*pow(10,0)*pow(x,2) + + +30.59414865*pow(10,0)*pow(x,3) + + -7.360163258*pow(10,0)*pow(x,4) + + +9.887137664*pow(10,-1)*pow(x,5) + + -6.942530952*pow(10,-2)*pow(x,6) + + +1.98298821*pow(10,-3)*pow(x,7) + + +2.84277784*pow(10,-8)*pow(x,8)); +} + + std::vector get_all_moves(Position pn, std::array board){ PieceType pt = board[pn]; std::vector pns; @@ -101,8 +114,8 @@ std::vector get_all_moves(Position pn, std::array board case PieceType::W_KNIGHT: for (int j = 7; j >= 0; j--){ for (int i = 0; i < 8; i++){ - for (int k = 0; k < 9; k++){ - if (std::make_pair(x+knt_dx[k],y+knt_dy[k]) == std::make_pair(i,j)) + for (int k = 1; k < 10; k++){ + if (std::make_pair(x+poly_knight_offset_x(k),y+poly_knight_offset_y(k)) == std::make_pair(i,j)) pns.push_back(pair_to_pos(std::make_pair(i,j))); } } From f14ba6346a1f8e755dfe0e12b5278d35d513b55f Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 20:56:32 +0000 Subject: [PATCH 12/81] vector -> unordered_set --- src/chess.cpp | 22 ------ src/functions.cpp | 166 ++++++++++++++++++++++++++---------------- src/functions.h | 7 +- tests/B_test_boards.h | 31 ++++---- tests/W_test_boards.h | 35 ++++----- tests/tests_main.cpp | 12 +-- 6 files changed, 141 insertions(+), 132 deletions(-) diff --git a/src/chess.cpp b/src/chess.cpp index 58ad503..f9a5f94 100755 --- a/src/chess.cpp +++ b/src/chess.cpp @@ -16,26 +16,4 @@ int main(){ } cout << endl; } - - cout << "poly X" << endl; - cout << "(1," << poly_knight_offset_x(1) << ")" << endl; - cout << "(2," << poly_knight_offset_x(2) << ")" << endl; - cout << "(3," << poly_knight_offset_x(3) << ")" << endl; - cout << "(4," << poly_knight_offset_x(4) << ")" << endl; - cout << "(5," << poly_knight_offset_x(5) << ")" << endl; - cout << "(6," << poly_knight_offset_x(6) << ")" << endl; - cout << "(7," << poly_knight_offset_x(7) << ")" << endl; - cout << "(8," << poly_knight_offset_x(8) << ")" << endl; - cout << "(9," << poly_knight_offset_x(9) << ")" << endl; - cout << "poly Y" << endl; - cout << "(1," << poly_knight_offset_y(1) << ")" << endl; - cout << "(2," << poly_knight_offset_y(2) << ")" << endl; - cout << "(3," << poly_knight_offset_y(3) << ")" << endl; - cout << "(4," << poly_knight_offset_y(4) << ")" << endl; - cout << "(5," << poly_knight_offset_y(5) << ")" << endl; - cout << "(6," << poly_knight_offset_y(6) << ")" << endl; - cout << "(7," << poly_knight_offset_y(7) << ")" << endl; - cout << "(8," << poly_knight_offset_y(8) << ")" << endl; - cout << "(9," << poly_knight_offset_y(9) << ")" << endl; - } diff --git a/src/functions.cpp b/src/functions.cpp index 7d29995..0ac8536 100755 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -48,19 +48,83 @@ bool is_valid_position(int x, int y){ y < 8 && y >= 0); } -std::vector get_possible_movers(Position pn, std::array board){ - std::vector pns = {Position::A1}; +std::unordered_set get_possible_movers(Position pn, std::array board){ + std::unordered_set pns = {Position::A1}; return pns; } -std::vector get_possible_moves(Position pn, std::array board){ - std::vector pns = {Position::A1}; +std::unordered_set get_possible_moves(Position pn, std::array board){ + std::unordered_set pns = {Position::A1}; return pns; } -std::vector get_all_moves(Position pn, std::array board){ +void _push_if_valid_pos(int x, int y, std::unordered_set *pns){ + if (is_valid_position(x, y)){ + pns->insert(pair_to_pos(x, y)); + } +} +void _get_all_moves_rook(int x, int y, std::unordered_set *pns){ + for (int offset=1; offset<8; offset++){ + int xpoff = x+offset; + int ypoff = y+offset; + int xnoff = x-offset; + int ynoff = y-offset; + _push_if_valid_pos(xpoff, y, pns); + _push_if_valid_pos(x, ypoff, pns); + _push_if_valid_pos(xnoff, y, pns); + _push_if_valid_pos(x, ynoff, pns); + } +} +void _get_all_moves_bishop(int x, int y, std::unordered_set *pns){ + for (int offset=1; offset<8; offset++){ + int xpoff = x+offset; + int ypoff = y+offset; + int xnoff = x-offset; + int ynoff = y-offset; + _push_if_valid_pos(xpoff, ypoff, pns); + _push_if_valid_pos(xpoff, ynoff, pns); + _push_if_valid_pos(xnoff, ypoff, pns); + _push_if_valid_pos(xnoff, ynoff, pns); + } + +} +void _get_all_moves_knight(int x, int y, std::unordered_set *pns){ + for (int xo=1;xo<=2;xo++){ + int yo=(xo==1)?2:1; + _push_if_valid_pos(x+xo, y+yo, pns); + _push_if_valid_pos(x-xo, y+yo, pns); + _push_if_valid_pos(x+xo, y-yo, pns); + _push_if_valid_pos(x-xo, y-yo, pns); + } +} + +void _get_all_moves_king(int x, int y, std::unordered_set *pns){ + _push_if_valid_pos(x+1, y+1, pns); + _push_if_valid_pos(x+1, y-1, pns); + _push_if_valid_pos(x-1, y+1, pns); + _push_if_valid_pos(x-1, y-1, pns); + _push_if_valid_pos(x, y+1, pns); + _push_if_valid_pos(x, y-1, pns); + _push_if_valid_pos(x+1, y, pns); + _push_if_valid_pos(x-1, y, pns); +} +void _get_all_moves_w_pawn(int x, int y, std::unordered_set *pns){ + _push_if_valid_pos(x, y+1, pns); + _push_if_valid_pos(x, y+2, pns); + _push_if_valid_pos(x+1, y+1, pns); + _push_if_valid_pos(x-1, y+1, pns); +} +void _get_all_moves_b_pawn(int x, int y, std::unordered_set *pns){ + _push_if_valid_pos(x, y-1, pns); + _push_if_valid_pos(x, y-2, pns); + _push_if_valid_pos(x-1, y-1, pns); + _push_if_valid_pos(x+1, y-1, pns); +} + +std::unordered_set get_all_moves(Position pn, std::array board){ + PieceType pt = board[pn]; - std::vector pns; + std::unordered_set pns; int x = pos_to_pair(pn).first; int y = pos_to_pair(pn).second; std::vector kg_dx = {-1,0,1,-1,0,1,-1,0,1}; @@ -70,75 +134,49 @@ std::vector get_all_moves(Position pn, std::array board std::vector Wpa_dx = {0,0,-1,0,1,0}; std::vector Wpa_dy = {2,1,0,0,0,-1}; switch(pt){ + case PieceType::B_QUEEN: + case PieceType::W_QUEEN: + _get_all_moves_rook(x, y, &pns); + _get_all_moves_bishop(x, y, &pns); + break; 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))); - } - } - } - break; + _get_all_moves_rook(x, y, &pns); + 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; - } - } - } - } - break; + _get_all_moves_bishop(x, y, &pns); + break; case PieceType::B_KNIGHT: case PieceType::W_KNIGHT: - for (int xo=1;xo<=2;xo++){ - int yo=(xo==1)?2:1; - if (is_valid_position(x+xo, y+yo)){ - pns.push_back(pair_to_pos(std::make_pair(x+xo, y+yo))); - } - if (is_valid_position(x-xo, y-yo)){ - pns.push_back(pair_to_pos(std::make_pair(x-xo, y-yo))); - } - if (is_valid_position(x-xo, y+yo)){ - pns.push_back(pair_to_pos(std::make_pair(x-xo, y+yo))); - } - if (is_valid_position(x+xo, y-yo)){ - pns.push_back(pair_to_pos(std::make_pair(x+xo, y-yo))); - } - } - break; + _get_all_moves_knight(x, y, &pns); + break; case PieceType::B_KING: case PieceType::W_KING: - for (int j = 7; j >= 0; j--){ - for (int i = 0; i < 8; i++){ - for (int k = 0; k < 9; k++){ - if (std::make_pair(x+kg_dx[k],y+kg_dy[k]) == std::make_pair(i,j)) - pns.push_back(pair_to_pos(std::make_pair(i,j))); - } - } - } + _get_all_moves_king(x, y, &pns); +// for (int j = 7; j >= 0; j--){ +// for (int i = 0; i < 8; i++){ +// for (int k = 0; k < 9; k++){ +// if (std::make_pair(x+kg_dx[k],y+kg_dy[k]) == std::make_pair(i,j)) +// pns.push_back(pair_to_pos(std::make_pair(i,j))); +// } +// } +// } break; case PieceType::B_PAWN: - for (int j = 7; j >= 0; j--){ - for (int i = 0; i < 8; i++){ - for (int k = 0; k < 6; k++){ - if (std::make_pair(x+Bpa_dx[k],y+Bpa_dy[k]) == std::make_pair(i,j)) - pns.push_back(pair_to_pos(std::make_pair(i,j))); - } - } - } + _get_all_moves_b_pawn(x, y, &pns); +// for (int j = 7; j >= 0; j--){ +// for (int i = 0; i < 8; i++){ +// for (int k = 0; k < 6; k++){ +// if (std::make_pair(x+Bpa_dx[k],y+Bpa_dy[k]) == std::make_pair(i,j)) +// pns.push_back(pair_to_pos(std::make_pair(i,j))); +// } +// } +// } break; case PieceType::W_PAWN: + _get_all_moves_w_pawn(x, y, &pns); + /* for (int j = 7; j >= 0; j--){ for (int i = 0; i < 8; i++){ for (int k = 0; k < 6; k++){ @@ -146,7 +184,7 @@ std::vector get_all_moves(Position pn, std::array board pns.push_back(pair_to_pos(std::make_pair(i,j))); } } - } + }*/ break; default: break; diff --git a/src/functions.h b/src/functions.h index 2c6cb9e..8fc8758 100755 --- a/src/functions.h +++ b/src/functions.h @@ -1,4 +1,5 @@ #include "constants.h" +#include #include #include #include @@ -26,14 +27,14 @@ bool is_valid_position(int x, int y); // 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); +std::unordered_set get_possible_movers(Position pn, std::array pt); // 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); +std::unordered_set get_possible_moves(Position pn, std::array pt); // Get all moved for piece in Position pn. -std::vector get_all_moves(Position pn, std::array pt); +std::unordered_set 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 diff --git a/tests/B_test_boards.h b/tests/B_test_boards.h index da52c1a..9486097 100644 --- a/tests/B_test_boards.h +++ b/tests/B_test_boards.h @@ -1,3 +1,4 @@ +#include #include const Position B_QUEEN_POS = E4; @@ -12,12 +13,12 @@ const std::array B_QUEEN_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector B_QUEEN_ALL_MOVES = { +const std::unordered_set B_QUEEN_ALL_MOVES = { A8, E8, B7, E7, H7, C6, E6, G6, D5, E5, F5, - A4, B4, C4, D4, E4, F4, G4, H4, + A4, B4, C4, D4, F4, G4, H4, D3, E3, F3, C2, E2, G2, B1, E1, H1 @@ -35,12 +36,11 @@ const std::array B_BISHOP_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector B_BISHOP_ALL_MOVES = { +const std::unordered_set B_BISHOP_ALL_MOVES = { H8, A7, G7, B6, F6, C5, E5, - D4, C3, E3, B2, F2, A1, G1 @@ -58,10 +58,9 @@ const std::array B_KNIGHT_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector B_KNIGHT_ALL_MOVES = { +const std::unordered_set B_KNIGHT_ALL_MOVES = { C7, E7, B6, F6, - D5, B4, F4, C3, E3 }; @@ -78,9 +77,9 @@ const std::array B_ROOK_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector B_ROOK_ALL_MOVES = { +const std::unordered_set B_ROOK_ALL_MOVES = { E8, E7, E6, - A5, B5, C5, D5, E5, F5, G5, H5, + A5, B5, C5, D5, F5, G5, H5, E4, E3, E2, E1 }; @@ -97,9 +96,9 @@ const std::array B_KING_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector B_KING_ALL_MOVES = { +const std::unordered_set B_KING_ALL_MOVES = { B5, C5, D5, - B4, C4, D4, + B4, D4, B3, C3, D3 }; @@ -116,8 +115,7 @@ const std::array B_PAWN_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector B_PAWN_ALL_MOVES = { - F4, +const std::unordered_set B_PAWN_ALL_MOVES = { E3, F3, G3, F2 }; @@ -132,9 +130,8 @@ const std::array B_KNIGHT_SIDE1_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector B_KNIGHT_SIDE1_ALL_MOVES = { +const std::unordered_set B_KNIGHT_SIDE1_ALL_MOVES = { D8, - B7, D6, A5, C5 }; @@ -149,8 +146,8 @@ const std::array B_KING_SIDE1_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector B_KING_SIDE1_ALL_MOVES = { - A8,B8, +const std::unordered_set B_KING_SIDE1_ALL_MOVES = { + B8, A7,B7 }; @@ -165,7 +162,7 @@ const std::array B_PAWN_SIDE1_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector B_PAWN_SIDE1_ALL_MOVES = { +const std::unordered_set B_PAWN_SIDE1_ALL_MOVES = { A8, A7, B7, A6 diff --git a/tests/W_test_boards.h b/tests/W_test_boards.h index 4544b11..f8c3faa 100644 --- a/tests/W_test_boards.h +++ b/tests/W_test_boards.h @@ -1,3 +1,4 @@ +#include #include const Position W_QUEEN_POS = E4; @@ -22,12 +23,12 @@ const std::array W_QUEEN_BOARD_BLOCKED = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector W_QUEEN_ALL_MOVES = { +const std::unordered_set W_QUEEN_ALL_MOVES = { A8, E8, B7, E7, H7, C6, E6, G6, D5, E5, F5, - A4, B4, C4, D4, E4, F4, G4, H4, + A4, B4, C4, D4, F4, G4, H4, D3, E3, F3, C2, E2, G2, B1, E1, H1 @@ -45,12 +46,11 @@ const std::array W_BISHOP_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector W_BISHOP_ALL_MOVES = { +const std::unordered_set W_BISHOP_ALL_MOVES = { H8, A7, G7, B6, F6, C5, E5, - D4, C3, E3, B2, F2, A1, G1 @@ -79,17 +79,15 @@ const std::array W_KNIGHT_SIDE1_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector W_KNIGHT_SIDE1_ALL_MOVES = { +const std::unordered_set W_KNIGHT_SIDE1_ALL_MOVES = { D8, - B7, D6, A5, C5 }; -const std::vector W_KNIGHT_ALL_MOVES = { +const std::unordered_set W_KNIGHT_ALL_MOVES = { C7, E7, B6, F6, - D5, B4, F4, C3, E3 }; @@ -106,9 +104,9 @@ const std::array W_ROOK_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector W_ROOK_ALL_MOVES = { +const std::unordered_set W_ROOK_ALL_MOVES = { E8, E7, E6, - A5, B5, C5, D5, E5, F5, G5, H5, + A5, B5, C5, D5, F5, G5, H5, E4, E3, E2, E1 }; @@ -137,14 +135,14 @@ const std::array W_KING_SIDE1_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector W_KING_SIDE1_ALL_MOVES = { - A8,B8, +const std::unordered_set W_KING_SIDE1_ALL_MOVES = { + B8, A7,B7 }; -const std::vector W_KING_ALL_MOVES = { +const std::unordered_set W_KING_ALL_MOVES = { B5, C5, D5, - B4, C4, D4, + B4, D4, B3, C3, D3 }; @@ -161,10 +159,9 @@ const std::array W_PAWN_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector W_PAWN_ALL_MOVES = { +const std::unordered_set W_PAWN_ALL_MOVES = { F6, - E5, F5, G5, - F4 + E5, F5, G5 }; const Position W_PAWN_SIDE1_POS = A1; @@ -178,6 +175,4 @@ const std::array W_PAWN_SIDE1_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; -const std::vector W_PAWN_SIDE1_ALL_MOVES = { - A8 -}; +const std::unordered_set W_PAWN_SIDE1_ALL_MOVES; diff --git a/tests/tests_main.cpp b/tests/tests_main.cpp index e72ed6c..1c97bc4 100755 --- a/tests/tests_main.cpp +++ b/tests/tests_main.cpp @@ -43,8 +43,9 @@ namespace Catch { }; // 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){ + struct StringMaker> { + static std::string convert(std::unordered_set 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; @@ -144,13 +145,13 @@ TEST_CASE("Test that invalid position ints return false", "[is_valid_position]") } TEST_CASE("Test what pieces may move where functon", "[get_possible_movers]"){ - std::vector H1_possible_movers = {Position::H2, Position::G1}; + std::unordered_set 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}; + std::unordered_set white_right_knight_possible_moves = {Position::H3, Position::F3}; + std::unordered_set 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); } @@ -162,7 +163,6 @@ TEST_CASE("Test all possible and impossible moves for black pieces", "[get_all_m 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); From 4840be2ee4508083cfb819fba673afa17434798d Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 21:08:09 +0000 Subject: [PATCH 13/81] All [get_all_moves] tests working. --- src/functions.cpp | 38 +++----------------------------------- tests/B_test_boards.h | 5 ++--- tests/W_test_boards.h | 4 ++-- 3 files changed, 7 insertions(+), 40 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index 0ac8536..d247528 100755 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -122,17 +122,10 @@ void _get_all_moves_b_pawn(int x, int y, std::unordered_set *pns){ } std::unordered_set get_all_moves(Position pn, std::array board){ - PieceType pt = board[pn]; std::unordered_set pns; int x = pos_to_pair(pn).first; int y = pos_to_pair(pn).second; - std::vector kg_dx = {-1,0,1,-1,0,1,-1,0,1}; - std::vector kg_dy = {1,1,1,0,0,0,-1,-1,-1}; - std::vector Bpa_dx = {0,-1,0,1,0,0}; - std::vector Bpa_dy = {-1,0,0,0,1,2}; - std::vector Wpa_dx = {0,0,-1,0,1,0}; - std::vector Wpa_dy = {2,1,0,0,0,-1}; switch(pt){ case PieceType::B_QUEEN: case PieceType::W_QUEEN: @@ -154,38 +147,13 @@ std::unordered_set get_all_moves(Position pn, std::array= 0; j--){ -// for (int i = 0; i < 8; i++){ -// for (int k = 0; k < 9; k++){ -// if (std::make_pair(x+kg_dx[k],y+kg_dy[k]) == std::make_pair(i,j)) -// pns.push_back(pair_to_pos(std::make_pair(i,j))); -// } -// } -// } - break; + break; case PieceType::B_PAWN: _get_all_moves_b_pawn(x, y, &pns); -// for (int j = 7; j >= 0; j--){ -// for (int i = 0; i < 8; i++){ -// for (int k = 0; k < 6; k++){ -// if (std::make_pair(x+Bpa_dx[k],y+Bpa_dy[k]) == std::make_pair(i,j)) -// pns.push_back(pair_to_pos(std::make_pair(i,j))); -// } -// } -// } - break; + break; case PieceType::W_PAWN: _get_all_moves_w_pawn(x, y, &pns); - /* - for (int j = 7; j >= 0; j--){ - for (int i = 0; i < 8; i++){ - for (int k = 0; k < 6; k++){ - if (std::make_pair(x+Wpa_dx[k],y+Wpa_dy[k]) == std::make_pair(i,j)) - pns.push_back(pair_to_pos(std::make_pair(i,j))); - } - } - }*/ - break; + break; default: break; } diff --git a/tests/B_test_boards.h b/tests/B_test_boards.h index 9486097..0b1838e 100644 --- a/tests/B_test_boards.h +++ b/tests/B_test_boards.h @@ -109,7 +109,7 @@ 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, B_PAWN, 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 @@ -151,7 +151,7 @@ const std::unordered_set B_KING_SIDE1_ALL_MOVES = { A7,B7 }; -const Position B_PAWN_SIDE1_POS = A1; +const Position B_PAWN_SIDE1_POS = A8; const std::array B_PAWN_SIDE1_BOARD = { B_PAWN, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, @@ -163,7 +163,6 @@ const std::array B_PAWN_SIDE1_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; const std::unordered_set B_PAWN_SIDE1_ALL_MOVES = { - A8, A7, B7, A6 }; diff --git a/tests/W_test_boards.h b/tests/W_test_boards.h index f8c3faa..62b5453 100644 --- a/tests/W_test_boards.h +++ b/tests/W_test_boards.h @@ -153,7 +153,7 @@ 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, W_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, NONE, NONE, NONE, NONE @@ -164,7 +164,7 @@ const std::unordered_set W_PAWN_ALL_MOVES = { E5, F5, G5 }; -const Position W_PAWN_SIDE1_POS = A1; +const Position W_PAWN_SIDE1_POS = A8; const std::array W_PAWN_SIDE1_BOARD = { W_PAWN, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, From 5745f34b79db0d9229a4e50dc7b5166e198f35d5 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 21:15:26 +0000 Subject: [PATCH 14/81] Seperate all_moves sub functions into new file --- src/all_moves_functions.cpp | 67 +++++++++++++++++++++++++++++++++++++ src/functions.cpp | 64 +---------------------------------- 2 files changed, 68 insertions(+), 63 deletions(-) create mode 100644 src/all_moves_functions.cpp diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp new file mode 100644 index 0000000..aeff52e --- /dev/null +++ b/src/all_moves_functions.cpp @@ -0,0 +1,67 @@ + + + +/// TAKE +void _push_if_valid_pos(int x, int y, std::unordered_set *pns){ + if (is_valid_position(x, y)){ + pns->insert(pair_to_pos(x, y)); + } +} +void _get_all_moves_rook(int x, int y, std::unordered_set *pns){ + for (int offset=1; offset<8; offset++){ + int xpoff = x+offset; + int ypoff = y+offset; + int xnoff = x-offset; + int ynoff = y-offset; + _push_if_valid_pos(xpoff, y, pns); + _push_if_valid_pos(x, ypoff, pns); + _push_if_valid_pos(xnoff, y, pns); + _push_if_valid_pos(x, ynoff, pns); + } +} +void _get_all_moves_bishop(int x, int y, std::unordered_set *pns){ + for (int offset=1; offset<8; offset++){ + int xpoff = x+offset; + int ypoff = y+offset; + int xnoff = x-offset; + int ynoff = y-offset; + _push_if_valid_pos(xpoff, ypoff, pns); + _push_if_valid_pos(xpoff, ynoff, pns); + _push_if_valid_pos(xnoff, ypoff, pns); + _push_if_valid_pos(xnoff, ynoff, pns); + } + +} +void _get_all_moves_knight(int x, int y, std::unordered_set *pns){ + for (int xo=1;xo<=2;xo++){ + int yo=(xo==1)?2:1; + _push_if_valid_pos(x+xo, y+yo, pns); + _push_if_valid_pos(x-xo, y+yo, pns); + _push_if_valid_pos(x+xo, y-yo, pns); + _push_if_valid_pos(x-xo, y-yo, pns); + } +} + +void _get_all_moves_king(int x, int y, std::unordered_set *pns){ + _push_if_valid_pos(x+1, y+1, pns); + _push_if_valid_pos(x+1, y-1, pns); + _push_if_valid_pos(x-1, y+1, pns); + _push_if_valid_pos(x-1, y-1, pns); + _push_if_valid_pos(x, y+1, pns); + _push_if_valid_pos(x, y-1, pns); + _push_if_valid_pos(x+1, y, pns); + _push_if_valid_pos(x-1, y, pns); +} +void _get_all_moves_w_pawn(int x, int y, std::unordered_set *pns){ + _push_if_valid_pos(x, y+1, pns); + _push_if_valid_pos(x, y+2, pns); + _push_if_valid_pos(x+1, y+1, pns); + _push_if_valid_pos(x-1, y+1, pns); +} +void _get_all_moves_b_pawn(int x, int y, std::unordered_set *pns){ + _push_if_valid_pos(x, y-1, pns); + _push_if_valid_pos(x, y-2, pns); + _push_if_valid_pos(x-1, y-1, pns); + _push_if_valid_pos(x+1, y-1, pns); +} + diff --git a/src/functions.cpp b/src/functions.cpp index d247528..d775739 100755 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -1,4 +1,5 @@ #include "functions.h" +#include "all_moves_functions.cpp" #include #include #include @@ -58,69 +59,6 @@ std::unordered_set get_possible_moves(Position pn, std::array *pns){ - if (is_valid_position(x, y)){ - pns->insert(pair_to_pos(x, y)); - } -} -void _get_all_moves_rook(int x, int y, std::unordered_set *pns){ - for (int offset=1; offset<8; offset++){ - int xpoff = x+offset; - int ypoff = y+offset; - int xnoff = x-offset; - int ynoff = y-offset; - _push_if_valid_pos(xpoff, y, pns); - _push_if_valid_pos(x, ypoff, pns); - _push_if_valid_pos(xnoff, y, pns); - _push_if_valid_pos(x, ynoff, pns); - } -} -void _get_all_moves_bishop(int x, int y, std::unordered_set *pns){ - for (int offset=1; offset<8; offset++){ - int xpoff = x+offset; - int ypoff = y+offset; - int xnoff = x-offset; - int ynoff = y-offset; - _push_if_valid_pos(xpoff, ypoff, pns); - _push_if_valid_pos(xpoff, ynoff, pns); - _push_if_valid_pos(xnoff, ypoff, pns); - _push_if_valid_pos(xnoff, ynoff, pns); - } - -} -void _get_all_moves_knight(int x, int y, std::unordered_set *pns){ - for (int xo=1;xo<=2;xo++){ - int yo=(xo==1)?2:1; - _push_if_valid_pos(x+xo, y+yo, pns); - _push_if_valid_pos(x-xo, y+yo, pns); - _push_if_valid_pos(x+xo, y-yo, pns); - _push_if_valid_pos(x-xo, y-yo, pns); - } -} - -void _get_all_moves_king(int x, int y, std::unordered_set *pns){ - _push_if_valid_pos(x+1, y+1, pns); - _push_if_valid_pos(x+1, y-1, pns); - _push_if_valid_pos(x-1, y+1, pns); - _push_if_valid_pos(x-1, y-1, pns); - _push_if_valid_pos(x, y+1, pns); - _push_if_valid_pos(x, y-1, pns); - _push_if_valid_pos(x+1, y, pns); - _push_if_valid_pos(x-1, y, pns); -} -void _get_all_moves_w_pawn(int x, int y, std::unordered_set *pns){ - _push_if_valid_pos(x, y+1, pns); - _push_if_valid_pos(x, y+2, pns); - _push_if_valid_pos(x+1, y+1, pns); - _push_if_valid_pos(x-1, y+1, pns); -} -void _get_all_moves_b_pawn(int x, int y, std::unordered_set *pns){ - _push_if_valid_pos(x, y-1, pns); - _push_if_valid_pos(x, y-2, pns); - _push_if_valid_pos(x-1, y-1, pns); - _push_if_valid_pos(x+1, y-1, pns); -} - std::unordered_set get_all_moves(Position pn, std::array board){ PieceType pt = board[pn]; std::unordered_set pns; From 8347d833912253d76a80b7ba5aa69f385be9ce41 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 21:45:19 +0000 Subject: [PATCH 15/81] Cleanup --- src/all_moves_functions.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index aeff52e..947cecf 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -1,24 +1,21 @@ +#include "constants.h" +#include - - -/// TAKE void _push_if_valid_pos(int x, int y, std::unordered_set *pns){ if (is_valid_position(x, y)){ pns->insert(pair_to_pos(x, y)); } } + void _get_all_moves_rook(int x, int y, std::unordered_set *pns){ for (int offset=1; offset<8; offset++){ - int xpoff = x+offset; - int ypoff = y+offset; - int xnoff = x-offset; - int ynoff = y-offset; - _push_if_valid_pos(xpoff, y, pns); - _push_if_valid_pos(x, ypoff, pns); - _push_if_valid_pos(xnoff, y, pns); - _push_if_valid_pos(x, ynoff, pns); + _push_if_valid_pos(x+offset, y, pns); + _push_if_valid_pos(x, y+offset, pns); + _push_if_valid_pos(x-offset, y, pns); + _push_if_valid_pos(x, y-offset, pns); } } + void _get_all_moves_bishop(int x, int y, std::unordered_set *pns){ for (int offset=1; offset<8; offset++){ int xpoff = x+offset; From 3c45e0ad751a1bfd6e15445b791515f515bbda3f Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 22:08:24 +0000 Subject: [PATCH 16/81] Add some tests for checking only valid moves --- tests/tests_main.cpp | 4 ++++ tests/valid_moves.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 tests/valid_moves.h diff --git a/tests/tests_main.cpp b/tests/tests_main.cpp index 1c97bc4..d4af8dd 100755 --- a/tests/tests_main.cpp +++ b/tests/tests_main.cpp @@ -1,6 +1,7 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" #include "test_boards.h" +#include "valid_moves.h" #include #include @@ -146,6 +147,7 @@ TEST_CASE("Test that invalid position ints return false", "[is_valid_position]") TEST_CASE("Test what pieces may move where functon", "[get_possible_movers]"){ std::unordered_set H1_possible_movers = {Position::H2, Position::G1}; + CHECK(get_possible_movers(BISHOP_BLOCKED1_KING_POS, BISHOP_BLOCKED1_BOARD) == BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING); CHECK(get_possible_movers(Position::H3, DEFAULT_BOARD) == H1_possible_movers); } @@ -154,6 +156,8 @@ TEST_CASE("Test where this piece may move to", "[get_possible_moves]"){ std::unordered_set 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); + CHECK(get_possible_moves(KNIGHT_BLOCKED1_POS, KNIGHT_BLOCKED1_BOARD) == KNIGHT_BLOCKED1_MOVES); + CHECK(get_possible_moves(BISHOP_BLOCKED1_POS, BISHOP_BLOCKED1_BOARD) == BISHOP_BLOCKED1_MOVES); } TEST_CASE("Test all possible and impossible moves for black pieces", "[get_all_moves][black]"){ diff --git a/tests/valid_moves.h b/tests/valid_moves.h new file mode 100644 index 0000000..0ffff2f --- /dev/null +++ b/tests/valid_moves.h @@ -0,0 +1,43 @@ +#include +#include + +const Position KNIGHT_BLOCKED1_POS = B8; +const std::array KNIGHT_BLOCKED1_BOARD = { + NONE, B_KNIGHT, NONE, NONE, NONE, NONE, NONE, NONE, + NONE, NONE, NONE, B_PAWN, 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, NONE, + NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, + NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE +}; +// Should NOT inclde D7 +const std::unordered_set KNIGHT_BLOCKED1_MOVES = { + A6, C6 +}; + +const Position BISHOP_BLOCKED1_POS = D5; +const std::array BISHOP_BLOCKED1_BOARD = { + NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, + NONE, B_QUEEN, NONE , B_PAWN , NONE, W_KING, NONE, NONE, + NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE, + NONE, NONE , W_ROOK, W_BISHOP, 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 +}; +// Should NOT include A8, H8, G2, or H1 +const std::unordered_set BISHOP_BLOCKED1_MOVES = { + B7, + C6,E6, + C4,E4, + B3,F3, + A2 +}; +// Should NOT include B2 (black queen) as it is obstructed by the bishop on D5 +const std::unordered_set BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING = { + D5 +}; +const Position BISHOP_BLOCKED1_KING_POS = F3; From e8489425576d55cb02689da6b544929456526872 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 22:57:19 +0000 Subject: [PATCH 17/81] Split compiling of catch_main and tests. Hopefully better compile times. --- tests/Makefile | 7 +++++-- tests/catch_main.cpp | 2 ++ tests/tests_main.cpp | 1 - 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 tests/catch_main.cpp diff --git a/tests/Makefile b/tests/Makefile index 5463710..11c2ccd 100755 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,4 +1,7 @@ defualt: build -build: - g++ -std=c++11 -w -I../src/ -o tests.out ../src/functions.cpp tests_main.cpp +catch_main.o: + g++ -w -c -o catch_main.o catch_main.cpp + +build: catch_main.o + g++ -std=c++11 -w -I../src/ -o tests.out ../src/functions.cpp catch_main.o tests_main.cpp diff --git a/tests/catch_main.cpp b/tests/catch_main.cpp new file mode 100644 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/tests_main.cpp b/tests/tests_main.cpp index d4af8dd..f1cc74a 100755 --- a/tests/tests_main.cpp +++ b/tests/tests_main.cpp @@ -1,4 +1,3 @@ -#define CATCH_CONFIG_MAIN #include "catch.hpp" #include "test_boards.h" #include "valid_moves.h" From 00527816bf50dcb1071c5d1ff652a7907f3f6e97 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 22:58:08 +0000 Subject: [PATCH 18/81] Fix permissions. --- tests/catch.hpp | 0 tests/tests_main.cpp | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 tests/catch.hpp mode change 100755 => 100644 tests/tests_main.cpp diff --git a/tests/catch.hpp b/tests/catch.hpp old mode 100755 new mode 100644 diff --git a/tests/tests_main.cpp b/tests/tests_main.cpp old mode 100755 new mode 100644 From 91276cd24c16b71303b5f019e515657f866edf81 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 8 Apr 2019 23:01:31 +0000 Subject: [PATCH 19/81] Fix more permissions --- LICENSE | 0 README.md | 0 src/chess.cpp | 0 src/constants.h | 0 src/functions.cpp | 0 src/functions.h | 0 6 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 LICENSE mode change 100755 => 100644 README.md mode change 100755 => 100644 src/chess.cpp mode change 100755 => 100644 src/constants.h mode change 100755 => 100644 src/functions.cpp mode change 100755 => 100644 src/functions.h diff --git a/LICENSE b/LICENSE old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/src/chess.cpp b/src/chess.cpp old mode 100755 new mode 100644 diff --git a/src/constants.h b/src/constants.h old mode 100755 new mode 100644 diff --git a/src/functions.cpp b/src/functions.cpp old mode 100755 new mode 100644 diff --git a/src/functions.h b/src/functions.h old mode 100755 new mode 100644 From 832ca160130adaa4fbf11fa11f963f668d4ef9a2 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Tue, 9 Apr 2019 20:23:31 +0000 Subject: [PATCH 20/81] Add debugging symbols for gdb --- tests/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile b/tests/Makefile index 11c2ccd..e0dd132 100755 --- a/tests/Makefile +++ b/tests/Makefile @@ -4,4 +4,4 @@ catch_main.o: g++ -w -c -o catch_main.o catch_main.cpp build: catch_main.o - g++ -std=c++11 -w -I../src/ -o tests.out ../src/functions.cpp catch_main.o tests_main.cpp + g++ -std=c++11 -ggdb -w -I../src/ -o tests.out ../src/functions.cpp catch_main.o tests_main.cpp From 805360bb4ec07daee5d06fcbaa833577d74e37d1 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Tue, 9 Apr 2019 20:24:45 +0000 Subject: [PATCH 21/81] Return pseudo-valid moves. King check still WIP. --- src/all_moves_functions.cpp | 140 ++++++++++++++++++++++++++---------- src/constants.h | 9 +++ src/functions.cpp | 51 ++++++++++--- src/functions.h | 12 ++++ tests/B_test_boards.h | 10 ++- tests/W_test_boards.h | 3 +- tests/tests_main.cpp | 50 +++++++++++-- tests/valid_moves.h | 35 +++++++++ 8 files changed, 251 insertions(+), 59 deletions(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index 947cecf..421e484 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -1,64 +1,130 @@ #include "constants.h" #include +#include void _push_if_valid_pos(int x, int y, std::unordered_set *pns){ if (is_valid_position(x, y)){ pns->insert(pair_to_pos(x, y)); } } +// This function returns true if the color of the piece on tile (x,y) is the Color c +bool _xy_is_color(int x, int y, std::array board, Color c){ + return c==Color::WHITE ? is_white(board[pair_to_pos(x, y)]) : is_black(board[pair_to_pos(x, y)]); +} -void _get_all_moves_rook(int x, int y, std::unordered_set *pns){ - for (int offset=1; offset<8; offset++){ - _push_if_valid_pos(x+offset, y, pns); - _push_if_valid_pos(x, y+offset, pns); - _push_if_valid_pos(x-offset, y, pns); - _push_if_valid_pos(x, y-offset, pns); +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 x, int y, std::unordered_set *pns, std::array board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){ + if (*is_not_blocked && is_valid_position(x, y)){ + if (_xy_is_color(x, y, board, color_of_piece)){ + *is_not_blocked = false; + } else if (_xy_is_color(x, y, board, color_of_opposite)){ + pns->insert(pair_to_pos(x, y)); + *is_not_blocked = false; + } else { + pns->insert(pair_to_pos(x, y)); + } + } +} +// 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 x, int y, std::unordered_set *pns, std::array board, Color color_of_piece, Color color_of_opposite){ + if (is_valid_position(x, y)){ + if (_xy_is_color(x, y, board, color_of_piece)){ + return; + } else { + pns->insert(pair_to_pos(x, y)); + } } } -void _get_all_moves_bishop(int x, int y, std::unordered_set *pns){ +// 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 x, int y, std::unordered_set *pns, std::array board, Color color_of_piece, Color color_of_opposite){ + if (is_valid_position(x, y) && _xy_is_color(x, y, board, color_of_opposite)){ + pns->insert(pair_to_pos(x, y)); + } +} +// This is a specialized functions for the pawn's inability to take going forward. +// Notice the lack of insertion where there usually is when (x,y) is a different color. +void _pawn_add_if_not_blocked(int x, int y, std::unordered_set *pns, std::array board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){ + if (*is_not_blocked && is_valid_position(x, y)){ + if (_xy_is_color(x, y, board, color_of_piece)){ + *is_not_blocked = false; + } else if (_xy_is_color(x, y, board, color_of_opposite)){ + *is_not_blocked = false; + } else { + pns->insert(pair_to_pos(x, y)); + } + } +} + + +void _get_all_moves_rook(int x, int y, std::unordered_set *pns, std::array board, Color pc, Color rc){ + bool* not_blocked_addx = new bool(true); + bool* not_blocked_minx = new bool(true); + bool* not_blocked_addy = new bool(true); + bool* not_blocked_miny = new bool(true); + for (int offset=1; offset<8; offset++){ + _add_if_not_blocked(x+offset, y, pns, board, pc, rc, not_blocked_addx); + _add_if_not_blocked(x, y+offset, pns, board, pc, rc, not_blocked_addy); + _add_if_not_blocked(x-offset, y, pns, board, pc, rc, not_blocked_minx); + _add_if_not_blocked(x, y-offset, pns, board, pc, rc, not_blocked_miny); + } +} + +void _get_all_moves_bishop(int x, int y, std::unordered_set *pns, std::array board, Color pc, Color rc){ + bool* not_blocked_addx_addy = new bool(true); + bool* not_blocked_addx_miny = new bool(true); + bool* not_blocked_minx_addy = new bool(true); + bool* not_blocked_minx_miny = new bool(true); + for (int offset=1; offset<8; offset++){ int xpoff = x+offset; int ypoff = y+offset; int xnoff = x-offset; int ynoff = y-offset; - _push_if_valid_pos(xpoff, ypoff, pns); - _push_if_valid_pos(xpoff, ynoff, pns); - _push_if_valid_pos(xnoff, ypoff, pns); - _push_if_valid_pos(xnoff, ynoff, pns); + _add_if_not_blocked(xpoff, ypoff, pns, board, pc, rc, not_blocked_addx_addy); + _add_if_not_blocked(xpoff, ynoff, pns, board, pc, rc, not_blocked_addx_miny); + _add_if_not_blocked(xnoff, ypoff, pns, board, pc, rc, not_blocked_minx_addy); + _add_if_not_blocked(xnoff, ynoff, pns, board, pc, rc, not_blocked_minx_miny); } } -void _get_all_moves_knight(int x, int y, std::unordered_set *pns){ +void _get_all_moves_knight(int x, int y, std::unordered_set *pns, std::array board, Color pc, Color rc){ for (int xo=1;xo<=2;xo++){ int yo=(xo==1)?2:1; - _push_if_valid_pos(x+xo, y+yo, pns); - _push_if_valid_pos(x-xo, y+yo, pns); - _push_if_valid_pos(x+xo, y-yo, pns); - _push_if_valid_pos(x-xo, y-yo, pns); + _add_if_not_blocked(x+xo, y+yo, pns, board, pc, rc); + _add_if_not_blocked(x-xo, y+yo, pns, board, pc, rc); + _add_if_not_blocked(x+xo, y-yo, pns, board, pc, rc); + _add_if_not_blocked(x-xo, y-yo, pns, board, pc, rc); } } -void _get_all_moves_king(int x, int y, std::unordered_set *pns){ - _push_if_valid_pos(x+1, y+1, pns); - _push_if_valid_pos(x+1, y-1, pns); - _push_if_valid_pos(x-1, y+1, pns); - _push_if_valid_pos(x-1, y-1, pns); - _push_if_valid_pos(x, y+1, pns); - _push_if_valid_pos(x, y-1, pns); - _push_if_valid_pos(x+1, y, pns); - _push_if_valid_pos(x-1, y, pns); -} -void _get_all_moves_w_pawn(int x, int y, std::unordered_set *pns){ - _push_if_valid_pos(x, y+1, pns); - _push_if_valid_pos(x, y+2, pns); - _push_if_valid_pos(x+1, y+1, pns); - _push_if_valid_pos(x-1, y+1, pns); -} -void _get_all_moves_b_pawn(int x, int y, std::unordered_set *pns){ - _push_if_valid_pos(x, y-1, pns); - _push_if_valid_pos(x, y-2, pns); - _push_if_valid_pos(x-1, y-1, pns); - _push_if_valid_pos(x+1, y-1, pns); +void _get_all_moves_king(int x, int y, std::unordered_set *pns, std::array board, Color pc, Color rc){ + _add_if_not_blocked(x+1, y+1, pns, board, pc, rc); + _add_if_not_blocked(x+1, y-1, pns, board, pc, rc); + _add_if_not_blocked(x-1, y+1, pns, board, pc, rc); + _add_if_not_blocked(x-1, y-1, pns, board, pc, rc); + _add_if_not_blocked(x, y+1, pns, board, pc, rc); + _add_if_not_blocked(x, y-1, pns, board, pc, rc); + _add_if_not_blocked(x+1, y, pns, board, pc, rc); + _add_if_not_blocked(x-1, y, pns, board, pc, rc); } +void _get_all_moves_pawn(int x, int y, std::unordered_set *pns, std::array board, Color pc, Color rc){ + + // if it's white use different offsets, and pawn starting rank + int offset2 = pc==Color::WHITE?2:-2; + int offset1 = pc==Color::WHITE?1:-1; + int pawn_rank = pc==Color::WHITE?1:6; + bool *free_to_double_move = new bool(true); + _pawn_add_if_not_blocked(x, y+offset1, pns, board, pc, rc, free_to_double_move); + if (y == pawn_rank){ // If on second rank + _pawn_add_if_not_blocked(x, y+offset2, pns, board, pc, rc, free_to_double_move); + } + _pawn_diag_add_if_not_blocked(x+1, y+offset1, pns, board, pc, rc); + _pawn_diag_add_if_not_blocked(x-1, y+offset1, pns, board, pc, rc); +} diff --git a/src/constants.h b/src/constants.h index 273f3e5..1b029ac 100644 --- a/src/constants.h +++ b/src/constants.h @@ -22,6 +22,15 @@ enum PieceType { B_KING }; +namespace Pieces { + const std::array BLACK = {B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING}; + const std::array WHITE = {W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING}; +} + +enum Color { + NO_COLOR, BLACK, WHITE +}; + // Access with CHESS_CHARS[PieceType] to get the character for the piece. const std::array CHESS_CHARS = { ' ', diff --git a/src/functions.cpp b/src/functions.cpp index d775739..b645687 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -49,6 +49,36 @@ bool is_valid_position(int x, int y){ y < 8 && y >= 0); } +bool is_white(PieceType pt){ + for (auto pn : Pieces::WHITE){ + if (pn == pt) return true; + } + return false; +} +bool is_black(PieceType pt){ + for (auto pn : Pieces::BLACK){ + if (pn == pt) return true; + } + return false; +} + +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 x, int y, std::array board){ + return get_color(board[pair_to_pos(x, y)]); +} +Color get_color(Position pn, std::array board){ + return get_color(board[pn]); +} + +Color rev_color(Color c){ + if (c==Color::NO_COLOR) return Color::NO_COLOR; + return c==Color::WHITE?Color::BLACK:Color::WHITE; +} + std::unordered_set get_possible_movers(Position pn, std::array board){ std::unordered_set pns = {Position::A1}; return pns; @@ -56,7 +86,8 @@ std::unordered_set get_possible_movers(Position pn, std::array get_possible_moves(Position pn, std::array board){ std::unordered_set pns = {Position::A1}; - return pns; + + return get_all_moves(pn, board); } std::unordered_set get_all_moves(Position pn, std::array board){ @@ -64,33 +95,33 @@ std::unordered_set get_all_moves(Position pn, std::array pns; int x = pos_to_pair(pn).first; int y = pos_to_pair(pn).second; + 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_rook(x, y, &pns); - _get_all_moves_bishop(x, y, &pns); + _get_all_moves_rook(x, y, &pns, board, color_of_piece, color_of_opponent); + _get_all_moves_bishop(x, y, &pns, board, color_of_piece, color_of_opponent); break; case PieceType::B_ROOK: case PieceType::W_ROOK: - _get_all_moves_rook(x, y, &pns); + _get_all_moves_rook(x, y, &pns, board, color_of_piece, color_of_opponent); break; case PieceType::B_BISHOP: case PieceType::W_BISHOP: - _get_all_moves_bishop(x, y, &pns); + _get_all_moves_bishop(x, y, &pns, board, color_of_piece, color_of_opponent); break; case PieceType::B_KNIGHT: case PieceType::W_KNIGHT: - _get_all_moves_knight(x, y, &pns); + _get_all_moves_knight(x, y, &pns, board, color_of_piece, color_of_opponent); break; case PieceType::B_KING: case PieceType::W_KING: - _get_all_moves_king(x, y, &pns); + _get_all_moves_king(x, y, &pns, board, color_of_piece, color_of_opponent); break; case PieceType::B_PAWN: - _get_all_moves_b_pawn(x, y, &pns); - break; case PieceType::W_PAWN: - _get_all_moves_w_pawn(x, y, &pns); + _get_all_moves_pawn(x, y, &pns, board, color_of_piece, color_of_opponent); break; default: break; diff --git a/src/functions.h b/src/functions.h index 8fc8758..39e7fdb 100644 --- a/src/functions.h +++ b/src/functions.h @@ -24,6 +24,18 @@ bool is_valid_position(int pos); bool is_valid_position(std::pair pos); bool is_valid_position(int x, int y); +// Checks if given piece matches a certain color. +bool is_white(PieceType pt); +bool is_black(PieceType pt); + +Color get_color(int x, int y, std::array board); +Color get_color(Position pn, std::array board); +Color get_color(PieceType pt); +// NO_COLOR returns NO_COLOR +// WHITE returns BLACK +// BLACK returns WHITE +Color rev_color(Color c); + // 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. diff --git a/tests/B_test_boards.h b/tests/B_test_boards.h index 0b1838e..2b898e1 100644 --- a/tests/B_test_boards.h +++ b/tests/B_test_boards.h @@ -116,8 +116,7 @@ const std::array B_PAWN_BOARD = { }; const std::unordered_set B_PAWN_ALL_MOVES = { - E3, F3, G3, - F2 + F3 }; const Position B_KNIGHT_SIDE1_POS = B7; const std::array B_KNIGHT_SIDE1_BOARD = { @@ -151,10 +150,10 @@ const std::unordered_set B_KING_SIDE1_ALL_MOVES = { A7,B7 }; -const Position B_PAWN_SIDE1_POS = A8; +const Position B_PAWN_SIDE1_POS = A7; const std::array B_PAWN_SIDE1_BOARD = { - B_PAWN, 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, NONE, NONE, NONE, @@ -163,6 +162,5 @@ const std::array B_PAWN_SIDE1_BOARD = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE }; const std::unordered_set B_PAWN_SIDE1_ALL_MOVES = { - A7, B7, - A6 + A6, A5 }; diff --git a/tests/W_test_boards.h b/tests/W_test_boards.h index 62b5453..d077c16 100644 --- a/tests/W_test_boards.h +++ b/tests/W_test_boards.h @@ -160,8 +160,7 @@ const std::array W_PAWN_BOARD = { }; const std::unordered_set W_PAWN_ALL_MOVES = { - F6, - E5, F5, G5 + F5 }; const Position W_PAWN_SIDE1_POS = A8; diff --git a/tests/tests_main.cpp b/tests/tests_main.cpp index f1cc74a..ad218c2 100644 --- a/tests/tests_main.cpp +++ b/tests/tests_main.cpp @@ -24,6 +24,17 @@ namespace Catch { 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> { @@ -99,6 +110,37 @@ 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 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); + CHECK(get_color(2, 1, DUMB_MOVE_1) == Color::WHITE); + 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 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]"){ CHECK(dumb_move(Position::B2, Position::B5, DEFAULT_BOARD) == DUMB_MOVE_1); } @@ -151,12 +193,12 @@ TEST_CASE("Test what pieces may move where functon", "[get_possible_movers]"){ } TEST_CASE("Test where this piece may move to", "[get_possible_moves]"){ - std::unordered_set white_right_knight_possible_moves = {Position::H3, Position::F3}; - std::unordered_set 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); + CHECK(get_possible_moves(Position::G1, DEFAULT_BOARD) == DEFAULT_W_R_KNIGHT_POSSIBLE_MOVES); + CHECK(get_possible_moves(Position::A7, DEFAULT_BOARD) == DEFAULT_B_A_PAWN_POSSIBLE_MOVES); + CHECK(get_possible_moves(Position::A2, DEFAULT_BOARD) == DEFAULT_W_A_PAWN_POSSIBLE_MOVES); CHECK(get_possible_moves(KNIGHT_BLOCKED1_POS, KNIGHT_BLOCKED1_BOARD) == KNIGHT_BLOCKED1_MOVES); CHECK(get_possible_moves(BISHOP_BLOCKED1_POS, BISHOP_BLOCKED1_BOARD) == BISHOP_BLOCKED1_MOVES); + CHECK(get_possible_moves(ROOK_BLOCKED1_POS, ROOK_BLOCKED1_BOARD) == ROOK_BLOCKED1_MOVES); } TEST_CASE("Test all possible and impossible moves for black pieces", "[get_all_moves][black]"){ diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 0ffff2f..3479827 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -1,6 +1,21 @@ #include #include + +/// This is for possible moves on a default board +const std::unordered_set DEFAULT_B_A_PAWN_POSSIBLE_MOVES = { + A6, A5 +}; +const std::unordered_set DEFAULT_W_A_PAWN_POSSIBLE_MOVES = { + A3, A4 +}; +const std::unordered_set DEFAULT_W_R_KNIGHT_POSSIBLE_MOVES = { + H3, F3 +}; +// EMPTY +const std::unordered_set DEFAULT_W_R_ROOK_POSSIBLE_MOVES = {}; +// END of default selections + const Position KNIGHT_BLOCKED1_POS = B8; const std::array KNIGHT_BLOCKED1_BOARD = { NONE, B_KNIGHT, NONE, NONE, NONE, NONE, NONE, NONE, @@ -41,3 +56,23 @@ const std::unordered_set BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING = { D5 }; const Position BISHOP_BLOCKED1_KING_POS = F3; + + +const Position ROOK_BLOCKED1_POS = B7; +const std::array ROOK_BLOCKED1_BOARD = { + NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, + NONE, W_ROOK, NONE , B_PAWN , NONE, B_KING, 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, W_KING , NONE , NONE , NONE, NONE, NONE, NONE, + NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE, + NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE +}; +// Should NOT include E-H2 or B3-1 +const std::unordered_set ROOK_BLOCKED1_MOVES = { + B8, + A7, C7, D7, + B6,B5,B4 +}; + From fb8481bf6baa699729c359349328382ba0642abf Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Tue, 9 Apr 2019 23:49:09 +0000 Subject: [PATCH 22/81] Putting your own king in check now disqualifies a move. --- src/functions.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++- src/functions.h | 16 +++++------ tests/tests_main.cpp | 9 +++++++ tests/valid_moves.h | 48 +++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+), 9 deletions(-) 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}; From 792d0cc5ee5f3c4c66f061317ab4a91c3f5af2ec Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Wed, 10 Apr 2019 21:06:54 +0000 Subject: [PATCH 23/81] Add en passant as possible moves. Cannot move yet due to dumb_move being.. dumb. Seperate custom printing out of main test file. --- src/all_moves_functions.cpp | 16 ++++--- src/constants.h | 2 +- src/functions.cpp | 4 +- src/functions.h | 2 +- tests/Makefile | 7 ++- tests/custom_printing.cpp | 95 +++++++++++++++++++++++++++++++++++++ tests/tests_main.cpp | 94 ++---------------------------------- tests/valid_moves.h | 31 ++++++++++++ 8 files changed, 149 insertions(+), 102 deletions(-) create mode 100644 tests/custom_printing.cpp diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index 421e484..a797828 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -42,8 +42,9 @@ void _add_if_not_blocked(int x, int y, std::unordered_set *pns, std::a // 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 x, int y, std::unordered_set *pns, std::array board, Color color_of_piece, Color color_of_opposite){ - if (is_valid_position(x, y) && _xy_is_color(x, y, board, color_of_opposite)){ +void _pawn_diag_add_if_not_blocked(int x, int y, std::unordered_set *pns, std::array board, Color color_of_piece, Color color_of_opposite, Position en_passant){ + if (is_valid_position(x, y) && (_xy_is_color(x, y, board, color_of_opposite) || + pair_to_pos(x, y) == en_passant)){ pns->insert(pair_to_pos(x, y)); } } @@ -113,18 +114,19 @@ void _get_all_moves_king(int x, int y, std::unordered_set *pns, std::a _add_if_not_blocked(x+1, y, pns, board, pc, rc); _add_if_not_blocked(x-1, y, pns, board, pc, rc); } -void _get_all_moves_pawn(int x, int y, std::unordered_set *pns, std::array board, Color pc, Color rc){ + +void _get_all_moves_pawn(int x, int y, std::unordered_set *pns, std::array board, Color pc, Color rc, Position en_passant){ // if it's white use different offsets, and pawn starting rank int offset2 = pc==Color::WHITE?2:-2; int offset1 = pc==Color::WHITE?1:-1; - int pawn_rank = pc==Color::WHITE?1:6; + int default_pawn_rank = pc==Color::WHITE?1:6; bool *free_to_double_move = new bool(true); _pawn_add_if_not_blocked(x, y+offset1, pns, board, pc, rc, free_to_double_move); - if (y == pawn_rank){ // If on second rank + if (y == default_pawn_rank){ // If on second/seventh rank _pawn_add_if_not_blocked(x, y+offset2, pns, board, pc, rc, free_to_double_move); } - _pawn_diag_add_if_not_blocked(x+1, y+offset1, pns, board, pc, rc); - _pawn_diag_add_if_not_blocked(x-1, y+offset1, pns, board, pc, rc); + _pawn_diag_add_if_not_blocked(x+1, y+offset1, pns, board, pc, rc, en_passant); + _pawn_diag_add_if_not_blocked(x-1, y+offset1, pns, board, pc, rc, en_passant); } diff --git a/src/constants.h b/src/constants.h index 1b029ac..84ead3f 100644 --- a/src/constants.h +++ b/src/constants.h @@ -40,7 +40,7 @@ const std::array CHESS_CHARS = { // 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 + 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, NA }; // This allows the printing of Position enum variables in the tests. It matches the variables to strings. diff --git a/src/functions.cpp b/src/functions.cpp index 9d98b34..526eca0 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -101,7 +101,7 @@ std::unordered_set get_possible_moves(Position pn, std::array get_all_moves(Position pn, std::array board, bool recursive){ +std::unordered_set get_all_moves(Position pn, std::array board, bool recursive, Position en_passant){ PieceType pt = board[pn]; std::unordered_set pns; int x = pos_to_pair(pn).first; @@ -132,7 +132,7 @@ std::unordered_set get_all_moves(Position pn, std::array get_possible_movers(Position pn, std::array get_possible_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); +std::unordered_set get_all_moves(Position pn, std::array pt, bool recursive=true, Position en_pessant=Position::NA); // 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); diff --git a/tests/Makefile b/tests/Makefile index e0dd132..979c36e 100755 --- a/tests/Makefile +++ b/tests/Makefile @@ -3,5 +3,8 @@ defualt: build catch_main.o: g++ -w -c -o catch_main.o catch_main.cpp -build: catch_main.o - g++ -std=c++11 -ggdb -w -I../src/ -o tests.out ../src/functions.cpp catch_main.o tests_main.cpp +custom_printing.o: + g++ -w -I../src/ -c -o custom_printing.o custom_printing.cpp + +build: catch_main.o custom_printing.o + g++ -std=c++11 -ggdb -w -I../src/ -o tests.out ../src/functions.cpp catch_main.o custom_printing.o tests_main.cpp diff --git a/tests/custom_printing.cpp b/tests/custom_printing.cpp new file mode 100644 index 0000000..854a957 --- /dev/null +++ b/tests/custom_printing.cpp @@ -0,0 +1,95 @@ +#include "catch.hpp" +#include +#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 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 = 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::unordered_set 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 = 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(); + } + }; + +} + diff --git a/tests/tests_main.cpp b/tests/tests_main.cpp index fa5d4c1..278e570 100644 --- a/tests/tests_main.cpp +++ b/tests/tests_main.cpp @@ -1,98 +1,10 @@ #include "catch.hpp" #include "test_boards.h" #include "valid_moves.h" +#include "custom_printing.cpp" #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 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 = 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::unordered_set 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 = 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, @@ -237,5 +149,9 @@ TEST_CASE("Test that moves that put king in check are not returned", "[get_all_m 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); +} +TEST_CASE("Tests for en pessant squares.", "[get_all_moves]"){ + CHECK(get_all_moves(EN_PASSANT_TEST_POS, EN_PASSANT_TEST_BOARD, false, EN_PASSANT_SQUARE) == EN_PASSANT_TEST_MOVES); + CHECK(get_all_moves(NO_EN_PASSANT_TEST_POS, NO_EN_PASSANT_TEST_BOARD) == NO_EN_PASSANT_TEST_MOVES); } diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 47c6087..5df4808 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -124,3 +124,34 @@ const std::array PAWN_CHECK_TEST_BOARD = { 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}; + +// These boards tests for en pessent squares. + +const Position EN_PASSANT_SQUARE = E6; +const Position EN_PASSANT_TEST_POS = D5; +const std::array EN_PASSANT_TEST_BOARD = { + B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, + B_PAWN, B_PAWN, B_PAWN, NONE, B_PAWN, B_PAWN, B_PAWN, B_PAWN, + NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, + NONE, NONE, NONE, W_PAWN, B_PAWN, 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, NONE, W_PAWN, W_PAWN, W_PAWN, W_PAWN, + W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK +}; +const std::unordered_set EN_PASSANT_TEST_MOVES = { + E6, D6 +}; + +const Position NO_EN_PASSANT_TEST_POS = D5; +const std::array NO_EN_PASSANT_TEST_BOARD = { + B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, + B_PAWN, B_PAWN, B_PAWN, NONE, B_PAWN, B_PAWN, B_PAWN, B_PAWN, + NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, + NONE, NONE, NONE, W_PAWN, B_PAWN, 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, NONE, W_PAWN, W_PAWN, W_PAWN, W_PAWN, + W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK +}; +const std::unordered_set NO_EN_PASSANT_TEST_MOVES = {D6}; From 3a6c0a056258a4fbe95ba0dd2a26db3c539ee6c3 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Thu, 11 Apr 2019 21:57:47 +0000 Subject: [PATCH 24/81] Start adding bitwise opperators. Finish with Justin --- src/bitwise.h | 27 ++++++++++++++++++++++++++ tests/Makefile | 11 ++++++++--- tests/bitwise_tests.cpp | 42 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 src/bitwise.h create mode 100644 tests/bitwise_tests.cpp diff --git a/src/bitwise.h b/src/bitwise.h new file mode 100644 index 0000000..2fcb548 --- /dev/null +++ b/src/bitwise.h @@ -0,0 +1,27 @@ +#ifndef BITWISE_H +#define BITWISE_H + +// Using macros for ease of use, can also use inline functons, but I don't see the point. + +/* + * 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 + * + * 0000 0000 0000 0000 0011 1111 -> From square position (0x3F) + * 0000 0000 0000 1111 1100 0000 -> To square position (>> 6 0xFB) + * 0000 0000 1111 0000 0000 0000 -> captured piece, if any (>> 12 0xF) + * 0000 1111 0000 0000 0000 0000 -> if prmoted, what to? (>> 16 0xF) + * 0001 0000 0000 0000 0000 0000 -> en passant (0x100000) + * 0010 0000 0000 0000 0000 0000 -> pawn starting move (0x200000) + * 0100 0000 0000 0000 0000 0000 -> castle move (0x400000) + * */ + +#define FROMSQ(m) ((m) & 0x3f) +#define TOSQ(m) ((m>>6) & 0x3f) + +#endif diff --git a/tests/Makefile b/tests/Makefile index 979c36e..a038e1c 100755 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,4 +1,5 @@ -defualt: build +defualt: all.out +bitwise: bitwise.out catch_main.o: g++ -w -c -o catch_main.o catch_main.cpp @@ -6,5 +7,9 @@ catch_main.o: custom_printing.o: g++ -w -I../src/ -c -o custom_printing.o custom_printing.cpp -build: catch_main.o custom_printing.o - g++ -std=c++11 -ggdb -w -I../src/ -o tests.out ../src/functions.cpp catch_main.o custom_printing.o tests_main.cpp +bitwise.out: catch_main.o + g++ -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 -w -I../src/ -o all.out ../src/functions.cpp catch_main.o custom_printing.o tests_main.cpp diff --git a/tests/bitwise_tests.cpp b/tests/bitwise_tests.cpp new file mode 100644 index 0000000..71fb62a --- /dev/null +++ b/tests/bitwise_tests.cpp @@ -0,0 +1,42 @@ +#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 + * + * 0000 0000 0000 0000 0011 1111 -> From square position (0x3F) + * 0000 0000 0000 1111 1100 0000 -> To square position (>> 6 0xFB) + * 0000 0000 1111 0000 0000 0000 -> captured piece, if any (>> 12 0xF) + * 0000 1111 0000 0000 0000 0000 -> if prmoted, what to? (>> 16 0xF) + * 0001 0000 0000 0000 0000 0000 -> en passant (0x100000) + * 0010 0000 0000 0000 0000 0000 -> pawn starting move (0x200000) + * 0100 0000 0000 0000 0000 0000 -> castle move (0x400000) + * */ + +const unsigned int GET_FROM_PIECE_INT = 0x3f; +const unsigned int GET_FROM_PIECE_INT2 = 0x3e; +// Want: +// 1111 1111 1110 +// FFE +const unsigned int GET_TO_FROM_PIECE_INT = 0xffe; +// Want: +// 1111 1011 1111 +// FBF +const unsigned int GET_TO_FROM_PIECE_INT2 = 0xfbf; + +TEST_CASE("Test that bitwise operators return appropriate values. Move.from", "[bitwise_from_pos]"){ + CHECK(FROMSQ(GET_FROM_PIECE_INT) == Position::H1); + CHECK(FROMSQ(GET_FROM_PIECE_INT2) == Position::G1); + CHECK(TOSQ(GET_TO_FROM_PIECE_INT) == Position::H1); + CHECK(FROMSQ(GET_TO_FROM_PIECE_INT) == Position::G1); + + CHECK(TOSQ(GET_TO_FROM_PIECE_INT2) == Position::G1); + CHECK(FROMSQ(GET_TO_FROM_PIECE_INT2) == Position::H1); +} + From f811e44045386f228c31c1e7513d8a92cc5b7634 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Thu, 11 Apr 2019 22:15:09 +0000 Subject: [PATCH 25/81] Add more detailed comments --- tests/bitwise_tests.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/bitwise_tests.cpp b/tests/bitwise_tests.cpp index 71fb62a..507ab34 100644 --- a/tests/bitwise_tests.cpp +++ b/tests/bitwise_tests.cpp @@ -10,13 +10,14 @@ * pawn starting move flag: 1 bit * castle move flag: 1 bit * - * 0000 0000 0000 0000 0011 1111 -> From square position (0x3F) - * 0000 0000 0000 1111 1100 0000 -> To square position (>> 6 0xFB) - * 0000 0000 1111 0000 0000 0000 -> captured piece, if any (>> 12 0xF) - * 0000 1111 0000 0000 0000 0000 -> if prmoted, what to? (>> 16 0xF) - * 0001 0000 0000 0000 0000 0000 -> en passant (0x100000) - * 0010 0000 0000 0000 0000 0000 -> pawn starting move (0x200000) - * 0100 0000 0000 0000 0000 0000 -> castle move (0x400000) + * (32-bit int, room to exapnd if neccessary) + * 0000 0000 0000 0000 0000 0000 0011 1111 -> From square position (& 0x3F) + * 0000 0000 0000 0000 0000 1111 1100 0000 -> To square position (>> 6 & 0xFB) + * 0000 0000 0000 0000 1111 0000 0000 0000 -> captured piece, if any (>> 12 & 0xF) + * 0000 0000 0000 1111 0000 0000 0000 0000 -> if prmoted, what to? (>> 16 & 0xF) + * 0000 0000 0001 0000 0000 0000 0000 0000 -> en passant (& 0x100000) + * 0000 0000 0010 0000 0000 0000 0000 0000 -> pawn starting move (& 0x200000) + * 0000 0000 0100 0000 0000 0000 0000 0000 -> castle move (& 0x400000) * */ const unsigned int GET_FROM_PIECE_INT = 0x3f; From e1be66d8e9d224238ed095c1718f9edc9720b9c3 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Thu, 11 Apr 2019 22:36:55 +0000 Subject: [PATCH 26/81] Add into for complete move int --- tests/bitwise_tests.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/bitwise_tests.cpp b/tests/bitwise_tests.cpp index 507ab34..5242976 100644 --- a/tests/bitwise_tests.cpp +++ b/tests/bitwise_tests.cpp @@ -31,6 +31,18 @@ const unsigned int GET_TO_FROM_PIECE_INT = 0xffe; // FBF const unsigned int GET_TO_FROM_PIECE_INT2 = 0xfbf; +// Want: +// From: E3 (21) [0x15] [0x15] <0x15> +// To: D2 (12) [0xB] [0xB] <0x3DF> +// (these 2 combine together) (33) [0x20] [0x3DF] <> +// Captures: B_PAWM (7) [0x7] [0x7000] <0x73DF> +// Promoted: NONE (0) [0x0] [0x0] <> +// en passant: true (1) [0x1] [0x100000] <0x1003DF> +// pawn starting move: false (0) [0x0] [0x0] <> +// castle move: false (0) [0x0] [0x0] <> +// total value: (?) [?] [?} <0x1003DF> +const unsigned int GET_ALL_INT = 0x1003DF; + TEST_CASE("Test that bitwise operators return appropriate values. Move.from", "[bitwise_from_pos]"){ CHECK(FROMSQ(GET_FROM_PIECE_INT) == Position::H1); CHECK(FROMSQ(GET_FROM_PIECE_INT2) == Position::G1); From 50763bd2b5d04ff72abaead3ff88544d4c9dca1f Mon Sep 17 00:00:00 2001 From: Justin Pilon Date: Sat, 13 Apr 2019 21:53:52 -0600 Subject: [PATCH 27/81] implement bitwise operation for moves --- src/bitwise.h | 23 +++++++++++-------- tests/bitwise_tests.cpp | 51 ++++++++++++++++++++++++++++++++--------- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/bitwise.h b/src/bitwise.h index 2fcb548..fed74b4 100644 --- a/src/bitwise.h +++ b/src/bitwise.h @@ -12,16 +12,21 @@ * pawn starting move flag: 1 bit * castle move flag: 1 bit * - * 0000 0000 0000 0000 0011 1111 -> From square position (0x3F) - * 0000 0000 0000 1111 1100 0000 -> To square position (>> 6 0xFB) - * 0000 0000 1111 0000 0000 0000 -> captured piece, if any (>> 12 0xF) - * 0000 1111 0000 0000 0000 0000 -> if prmoted, what to? (>> 16 0xF) - * 0001 0000 0000 0000 0000 0000 -> en passant (0x100000) - * 0010 0000 0000 0000 0000 0000 -> pawn starting move (0x200000) - * 0100 0000 0000 0000 0000 0000 -> castle move (0x400000) + * 0000 0000 0000 0000 0011 1111 -> From square position (& 0x3F) + * 0000 0000 0000 1111 1100 0000 -> To square position (>> 6 & 0x3F) + * 0000 0000 1111 0000 0000 0000 -> captured piece, if any (>> 12 & 0xF) + * 0000 1111 0000 0000 0000 0000 -> if prmoted, what to? (>> 16 & 0xF) + * 0001 0000 0000 0000 0000 0000 -> en passant (& 0x100000) + * 0010 0000 0000 0000 0000 0000 -> pawn starting move (& 0x200000) + * 0100 0000 0000 0000 0000 0000 -> castle move (& 0x400000) * */ -#define FROMSQ(m) ((m) & 0x3f) -#define TOSQ(m) ((m>>6) & 0x3f) +#define FROMSQ(m) ((m) & 0x3f) +#define TOSQ(m) ((m>>6) & 0x3f) +#define CAPT(m) ((m>>12) & 0xf ) +#define PROM(m) ((m>>16) & 0xf ) +#define ENPASS(m) ((m>>20) & 0x1 ) +#define PAWNST(m) ((m>>21) & 0x1 ) +#define CAST(m) ((m>>22) & 0x1 ) #endif diff --git a/tests/bitwise_tests.cpp b/tests/bitwise_tests.cpp index 5242976..f26ed01 100644 --- a/tests/bitwise_tests.cpp +++ b/tests/bitwise_tests.cpp @@ -20,16 +20,38 @@ * 0000 0000 0100 0000 0000 0000 0000 0000 -> castle move (& 0x400000) * */ -const unsigned int GET_FROM_PIECE_INT = 0x3f; -const unsigned int GET_FROM_PIECE_INT2 = 0x3e; -// Want: +// This is testing position H1 +const unsigned int MOVE_G1 = 0x3f; + +// This is testing position G1 +const unsigned int MOVE_H1 = 0x3e; + +// This is testing a move with no flags from G1 to H1 +// // Want: // 1111 1111 1110 // FFE -const unsigned int GET_TO_FROM_PIECE_INT = 0xffe; +const unsigned int MOVE_G1_TO_H1 = 0xffe; + +// This is testing a move with no flags from H1 to G1 // Want: // 1111 1011 1111 // FBF -const unsigned int GET_TO_FROM_PIECE_INT2 = 0xfbf; +const unsigned int MOVE_H1_TO_G1 = 0b111110111111; + +// Move from H1 to G1 and capture +const unsigned int MOVE_H1_TO_G1_CAPTURE_B_KNIGHT = 0x8fbf; + +// Move from H1 to G1 and promote +const unsigned int MOVE_H1_TO_G1_PROMOTE_TO_QUEEN = 0xb0fbf; + +// Move from H1 to G1 and en passant +const unsigned int MOVE_H1_TO_G1_EN_PASSANT = 0x100fbf; + +// Move from H1 to G1 and its the starting move for a pawn +const unsigned int MOVE_H1_TO_G1_PAWN_START = 0x200fbf; + +// Move from H1 to G1 and castle +const unsigned int MOVE_H1_TO_G1_AND_CASTLE = 0x400fbf; // Want: // From: E3 (21) [0x15] [0x15] <0x15> @@ -44,12 +66,19 @@ const unsigned int GET_TO_FROM_PIECE_INT2 = 0xfbf; const unsigned int GET_ALL_INT = 0x1003DF; TEST_CASE("Test that bitwise operators return appropriate values. Move.from", "[bitwise_from_pos]"){ - CHECK(FROMSQ(GET_FROM_PIECE_INT) == Position::H1); - CHECK(FROMSQ(GET_FROM_PIECE_INT2) == Position::G1); - CHECK(TOSQ(GET_TO_FROM_PIECE_INT) == Position::H1); - CHECK(FROMSQ(GET_TO_FROM_PIECE_INT) == Position::G1); + CHECK(FROMSQ(MOVE_G1) == Position::H1); + CHECK(FROMSQ(MOVE_H1) == Position::G1); + CHECK(TOSQ(MOVE_G1_TO_H1) == Position::H1); + CHECK(FROMSQ(MOVE_G1_TO_H1) == Position::G1); - CHECK(TOSQ(GET_TO_FROM_PIECE_INT2) == Position::G1); - CHECK(FROMSQ(GET_TO_FROM_PIECE_INT2) == Position::H1); + CHECK(TOSQ(MOVE_H1_TO_G1) == Position::G1); + CHECK(FROMSQ(MOVE_H1_TO_G1) == Position::H1); + + CHECK(CAPT(MOVE_H1_TO_G1_CAPTURE_B_KNIGHT) == PieceType::B_KNIGHT); + CHECK(PROM(MOVE_H1_TO_G1_PROMOTE_TO_QUEEN) == PieceType::B_QUEEN); + + CHECK(ENPASS(MOVE_H1_TO_G1_EN_PASSANT) == 1); + CHECK(PAWNST(MOVE_H1_TO_G1_PAWN_START) == 1); + CHECK(CAST(MOVE_H1_TO_G1_AND_CASTLE) == 1); } From 9fcf3b8a98c66ec3b75759b44a0d5d4478dfc604 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Thu, 18 Apr 2019 01:20:13 +0000 Subject: [PATCH 28/81] Change macro to function for saftey, and style --- src/bitwise.cpp | 54 +++++++++++++++++++++++++++++++++++++++++ src/bitwise.h | 24 +++++++++++++++--- tests/Makefile | 2 +- tests/bitwise_tests.cpp | 29 +++++++++++----------- 4 files changed, 91 insertions(+), 18 deletions(-) create mode 100644 src/bitwise.cpp diff --git a/src/bitwise.cpp b/src/bitwise.cpp new file mode 100644 index 0000000..4fc311f --- /dev/null +++ b/src/bitwise.cpp @@ -0,0 +1,54 @@ +#include "bitwise.h" + +// Get first 6 bits of int +int get_from_sq(int mv){ + return (mv & 0x3f); +} + +// Get bits 7-12 of int +int get_to_sq(int mv){ + return ((mv >> 6) & 0x3f); +} + +// Get bits 13-16 of int +int get_captured_pc(int mv){ + return ((mv >> 12) & 0xf); +} + +// Get bits 17-20 of int +int get_promoted_to_pc(int mv){ + return ((mv >> 16) & 0xf); +} + +// Get 21st bit of int +int get_en_pass_flag(int mv){ + return ((mv >> 20) & 0x1); +} + +// Get 22nd bit of int +int get_pawn_st_flag(int mv){ + return ((mv >> 21) & 0x1); +} + +// Get 23rd bit of int +int get_castle_flag(int mv){ + return ((mv >> 22) & 0x1); +} + +// Get last 3 bits of number (the rank). +// Techincally this gets all bits 4-32/64 but I'm just assuming it won't be larger than 63 before the shift. +int get_rank(int position){ + return (position >> 3); +} + +// Get first 3 bits of number +int get_file(int position){ + return (position & 7); +} + +// if the position has a 7th bit we know it's off the board. +// it indicates that is it off the board. +// ASSUMING position <= 128 but if it was that big that'd be weird. +bool is_valid_position(int position){ + return (position & 0x40); +} diff --git a/src/bitwise.h b/src/bitwise.h index fed74b4..e5cd126 100644 --- a/src/bitwise.h +++ b/src/bitwise.h @@ -1,10 +1,12 @@ #ifndef BITWISE_H #define BITWISE_H -// Using macros for ease of use, can also use inline functons, but I don't see the point. +#include + +// Using macros for ease of use, can also use functons, but I don't see the point. /* - * From (Position): 6 bits (2^6 == 64) possibilities + * From (Position): 7 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 @@ -13,7 +15,7 @@ * castle move flag: 1 bit * * 0000 0000 0000 0000 0011 1111 -> From square position (& 0x3F) - * 0000 0000 0000 1111 1100 0000 -> To square position (>> 6 & 0x3F) + * 0000 0000 0000 0111 1100 0000 -> To square position (>> 6 & 0x3F) * 0000 0000 1111 0000 0000 0000 -> captured piece, if any (>> 12 & 0xF) * 0000 1111 0000 0000 0000 0000 -> if prmoted, what to? (>> 16 & 0xF) * 0001 0000 0000 0000 0000 0000 -> en passant (& 0x100000) @@ -21,6 +23,7 @@ * 0100 0000 0000 0000 0000 0000 -> castle move (& 0x400000) * */ +/* OLD, DO NOT USE #define FROMSQ(m) ((m) & 0x3f) #define TOSQ(m) ((m>>6) & 0x3f) #define CAPT(m) ((m>>12) & 0xf ) @@ -28,5 +31,20 @@ #define ENPASS(m) ((m>>20) & 0x1 ) #define PAWNST(m) ((m>>21) & 0x1 ) #define CAST(m) ((m>>22) & 0x1 ) +*/ + +// Redefine as functions for fun :shrug: +int get_from_sq(int mv); +int get_to_sq(int mv); +int get_captured_pc(int mv); +int get_promoted_to_pc(int mv); +int get_en_pass_flag(int mv); +int get_pawn_st_flag(int mv); +int get_castle_flag(int mv); + +int get_rank(int position); +int get_file(int position); + +bool is_valid_position(int position); #endif diff --git a/tests/Makefile b/tests/Makefile index a038e1c..648e44c 100755 --- a/tests/Makefile +++ b/tests/Makefile @@ -8,7 +8,7 @@ custom_printing.o: g++ -w -I../src/ -c -o custom_printing.o custom_printing.cpp bitwise.out: catch_main.o - g++ -I../src/ -o bitwise.out catch_main.o bitwise_tests.cpp + g++ -I../src/ -o bitwise.out ../src/bitwise.cpp catch_main.o bitwise_tests.cpp # TODO: Allw all.out to contain bitwise tests all.out: catch_main.o custom_printing.o diff --git a/tests/bitwise_tests.cpp b/tests/bitwise_tests.cpp index f26ed01..04647ff 100644 --- a/tests/bitwise_tests.cpp +++ b/tests/bitwise_tests.cpp @@ -1,6 +1,7 @@ #include #include #include "catch.hpp" + /* * From (Position): 6 bits (2^6 == 64) possibilities * To (Position): same as above @@ -39,10 +40,10 @@ const unsigned int MOVE_G1_TO_H1 = 0xffe; const unsigned int MOVE_H1_TO_G1 = 0b111110111111; // Move from H1 to G1 and capture -const unsigned int MOVE_H1_TO_G1_CAPTURE_B_KNIGHT = 0x8fbf; +const unsigned int MOVE_H1_TO_G1_get_captured_pcURE_B_KNIGHT = 0x8fbf; // Move from H1 to G1 and promote -const unsigned int MOVE_H1_TO_G1_PROMOTE_TO_QUEEN = 0xb0fbf; +const unsigned int MOVE_H1_TO_G1_get_promoted_to_pcOTE_TO_QUEEN = 0xb0fbf; // Move from H1 to G1 and en passant const unsigned int MOVE_H1_TO_G1_EN_PASSANT = 0x100fbf; @@ -51,7 +52,7 @@ const unsigned int MOVE_H1_TO_G1_EN_PASSANT = 0x100fbf; const unsigned int MOVE_H1_TO_G1_PAWN_START = 0x200fbf; // Move from H1 to G1 and castle -const unsigned int MOVE_H1_TO_G1_AND_CASTLE = 0x400fbf; +const unsigned int MOVE_H1_TO_G1_AND_get_castle_flagLE = 0x400fbf; // Want: // From: E3 (21) [0x15] [0x15] <0x15> @@ -66,19 +67,19 @@ const unsigned int MOVE_H1_TO_G1_AND_CASTLE = 0x400fbf; const unsigned int GET_ALL_INT = 0x1003DF; TEST_CASE("Test that bitwise operators return appropriate values. Move.from", "[bitwise_from_pos]"){ - CHECK(FROMSQ(MOVE_G1) == Position::H1); - CHECK(FROMSQ(MOVE_H1) == Position::G1); - CHECK(TOSQ(MOVE_G1_TO_H1) == Position::H1); - CHECK(FROMSQ(MOVE_G1_TO_H1) == Position::G1); + CHECK(get_from_sq(MOVE_G1) == Position::H1); + CHECK(get_from_sq(MOVE_H1) == Position::G1); + CHECK(get_to_sq(MOVE_G1_TO_H1) == Position::H1); + CHECK(get_from_sq(MOVE_G1_TO_H1) == Position::G1); - CHECK(TOSQ(MOVE_H1_TO_G1) == Position::G1); - CHECK(FROMSQ(MOVE_H1_TO_G1) == Position::H1); + CHECK(get_to_sq(MOVE_H1_TO_G1) == Position::G1); + CHECK(get_from_sq(MOVE_H1_TO_G1) == Position::H1); - CHECK(CAPT(MOVE_H1_TO_G1_CAPTURE_B_KNIGHT) == PieceType::B_KNIGHT); - CHECK(PROM(MOVE_H1_TO_G1_PROMOTE_TO_QUEEN) == PieceType::B_QUEEN); + CHECK(get_captured_pc(MOVE_H1_TO_G1_get_captured_pcURE_B_KNIGHT) == PieceType::B_KNIGHT); + CHECK(get_promoted_to_pc(MOVE_H1_TO_G1_get_promoted_to_pcOTE_TO_QUEEN) == PieceType::B_QUEEN); - CHECK(ENPASS(MOVE_H1_TO_G1_EN_PASSANT) == 1); - CHECK(PAWNST(MOVE_H1_TO_G1_PAWN_START) == 1); - CHECK(CAST(MOVE_H1_TO_G1_AND_CASTLE) == 1); + 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_get_castle_flagLE) == 1); } From f80d961deab026fe962b26305cb3ad27a8a17e01 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Thu, 18 Apr 2019 01:20:44 +0000 Subject: [PATCH 29/81] Minor refactoring in preperation for bitshift moves --- src/all_moves_functions.cpp | 22 ++++++--- src/functions.cpp | 99 ++++++++++++++++++++++--------------- 2 files changed, 72 insertions(+), 49 deletions(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index a797828..1bc1ff3 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -2,14 +2,20 @@ #include #include +inline Position _pair_to_pos_unsafe(int x, int y){ + return static_cast(std::abs(y-7)*8 + x); +} + void _push_if_valid_pos(int x, int y, std::unordered_set *pns){ if (is_valid_position(x, y)){ - pns->insert(pair_to_pos(x, y)); + pns->insert(_pair_to_pos_unsafe(x, y)); } } + + // This function returns true if the color of the piece on tile (x,y) is the Color c bool _xy_is_color(int x, int y, std::array board, Color c){ - return c==Color::WHITE ? is_white(board[pair_to_pos(x, y)]) : is_black(board[pair_to_pos(x, y)]); + return c==Color::WHITE ? is_white(board[_pair_to_pos_unsafe(x, y)]) : is_black(board[_pair_to_pos_unsafe(x, y)]); } Color _rev_color(Color c){ @@ -22,10 +28,10 @@ void _add_if_not_blocked(int x, int y, std::unordered_set *pns, std::a if (_xy_is_color(x, y, board, color_of_piece)){ *is_not_blocked = false; } else if (_xy_is_color(x, y, board, color_of_opposite)){ - pns->insert(pair_to_pos(x, y)); + pns->insert(_pair_to_pos_unsafe(x, y)); *is_not_blocked = false; } else { - pns->insert(pair_to_pos(x, y)); + pns->insert(_pair_to_pos_unsafe(x, y)); } } } @@ -35,7 +41,7 @@ void _add_if_not_blocked(int x, int y, std::unordered_set *pns, std::a if (_xy_is_color(x, y, board, color_of_piece)){ return; } else { - pns->insert(pair_to_pos(x, y)); + pns->insert(_pair_to_pos_unsafe(x, y)); } } } @@ -44,8 +50,8 @@ void _add_if_not_blocked(int x, int y, std::unordered_set *pns, std::a // It will only to pns if there is a piece of opposite color on it. void _pawn_diag_add_if_not_blocked(int x, int y, std::unordered_set *pns, std::array board, Color color_of_piece, Color color_of_opposite, Position en_passant){ if (is_valid_position(x, y) && (_xy_is_color(x, y, board, color_of_opposite) || - pair_to_pos(x, y) == en_passant)){ - pns->insert(pair_to_pos(x, y)); + _pair_to_pos_unsafe(x, y) == en_passant)){ + pns->insert(_pair_to_pos_unsafe(x, y)); } } // This is a specialized functions for the pawn's inability to take going forward. @@ -57,7 +63,7 @@ void _pawn_add_if_not_blocked(int x, int y, std::unordered_set *pns, s } else if (_xy_is_color(x, y, board, color_of_opposite)){ *is_not_blocked = false; } else { - pns->insert(pair_to_pos(x, y)); + pns->insert(_pair_to_pos_unsafe(x, y)); } } } diff --git a/src/functions.cpp b/src/functions.cpp index 526eca0..0b4aea9 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -78,6 +78,7 @@ Color get_color(PieceType pt){ if (is_black(pt)) return Color::BLACK; return Color::NO_COLOR; } + Color get_color(int x, int y, std::array board){ return get_color(board[pair_to_pos(x, y)]); } @@ -101,6 +102,62 @@ std::unordered_set get_possible_moves(Position pn, std::array get_all_moves_bitwise(Position pn, std::array board, bool recursive, Position en_passant){ + +} + +//TODO: Make faster by running from king squar eonly, instead of running on every piece of opposite team. +void filter_checked_moves(Position pn, PieceType pt, std::array board, std::unordered_set *pns){ + PieceType my_king = is_white(pt)?PieceType::W_KING:PieceType::B_KING; + std::vector king_poss = get_pos_of(my_king, board); + Position my_king_pos; + if (king_poss.empty()){ + return; + } else { + my_king_pos = king_poss[0]; + } + int attackers = 0; + for (auto p_pn= pns->begin(); p_pn!=pns->end();){ + // Make move + std::array moved_board = dumb_move(pn, *p_pn, board); + // Get all piecetypes of other team + std::array other_team = is_white(pt)?Pieces::BLACK:Pieces::WHITE; + bool checks_king = false; + // go through each piece of other team + for (PieceType other_p : other_team) { + checks_king = false; + // For every place the piecetype is + // NEW CODE +// for (Position psn : get_all_moves(my_king_pos, moved_board, false)){ +// +// } + // \NEW CODE + for (Position psn : get_pos_of(other_p, moved_board)){ + std::unordered_set other_moves = get_all_moves(psn, moved_board, false); + // for every position the piece can mvoe to + 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; + } + } +} + std::unordered_set get_all_moves(Position pn, std::array board, bool recursive, Position en_passant){ PieceType pt = board[pn]; std::unordered_set pns; @@ -137,48 +194,8 @@ 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; - } - } + filter_checked_moves(pn, pt, board, &pns); } return pns; } From 0422768eb0a2b12922eab5328019a0e99b37d69c Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Thu, 18 Apr 2019 01:27:38 +0000 Subject: [PATCH 30/81] Add tests for and fix is_valid_position --- src/bitwise.cpp | 2 +- tests/bitwise_tests.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/bitwise.cpp b/src/bitwise.cpp index 4fc311f..474a71e 100644 --- a/src/bitwise.cpp +++ b/src/bitwise.cpp @@ -50,5 +50,5 @@ int get_file(int position){ // it indicates that is it off the board. // ASSUMING position <= 128 but if it was that big that'd be weird. bool is_valid_position(int position){ - return (position & 0x40); + return !(position & 0x40); } diff --git a/tests/bitwise_tests.cpp b/tests/bitwise_tests.cpp index 04647ff..a6f9f3f 100644 --- a/tests/bitwise_tests.cpp +++ b/tests/bitwise_tests.cpp @@ -83,3 +83,9 @@ TEST_CASE("Test that bitwise operators return appropriate values. Move.from", "[ CHECK(get_castle_flag(MOVE_H1_TO_G1_AND_get_castle_flagLE) == 1); } +TEST_CASE("Test that is_valid_position works properly", "[is_valid_position]"){ + CHECK(is_valid_position(0)); + CHECK(is_valid_position(63)); + CHECK_FALSE(is_valid_position(-1)); + CHECK_FALSE(is_valid_position(64)); +} From 20c87a39882807658b780abf481c88c4b77f837b Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sat, 20 Apr 2019 04:26:00 +0000 Subject: [PATCH 31/81] Half-way done switching to bitwise moves. --- src/all_moves_bitwise_functions.cpp | 185 +++++++++++++++++++++++++ src/bitwise.cpp | 38 +---- src/bitwise.h | 44 ++++-- src/bitwise_constants.cpp | 16 +++ src/bitwise_constants.h | 76 ++++++++++ src/bitwise_functions.cpp | 207 ++++++++++++++++++++++++++++ src/bitwise_functions.h | 50 +++++++ tests/Makefile | 4 + tests/bitwise_main.cpp | 157 +++++++++++++++++++++ 9 files changed, 729 insertions(+), 48 deletions(-) create mode 100644 src/all_moves_bitwise_functions.cpp create mode 100644 src/bitwise_constants.cpp create mode 100644 src/bitwise_constants.h create mode 100644 src/bitwise_functions.cpp create mode 100644 src/bitwise_functions.h create mode 100644 tests/bitwise_main.cpp diff --git a/src/all_moves_bitwise_functions.cpp b/src/all_moves_bitwise_functions.cpp new file mode 100644 index 0000000..e39e395 --- /dev/null +++ b/src/all_moves_bitwise_functions.cpp @@ -0,0 +1,185 @@ +#include "bitwise_constants.h" +#include +#include +#include + +const std::array ROOK_PIECE_OFFSETS = {-1, -10, 1, 10}; +const std::array BISHOP_PIECE_OFFSETS = {-11, -9, 9, 11}; +const std::array KNIGHT_PIECE_OFFSETS = {-12, -21, -19, -8, 8, 12, 19, 21}; +const std::array KING_PIECE_OFFSETS = {-11, -10, -9, -1, 1, 9, 10, 11}; + + +inline Position _pair_to_pos_unsafe(int x, int y){ + return static_cast(std::abs(y-7)*8 + x); +} + +void _push_if_valid_pos(int pos, std::unordered_set *pns){ + if (is_valid_position(pos)){ + pns->insert(pos); + } +} + + +// This function returns true if the color of the piece on tile (x,y) is the Color c +bool _xy_is_color(int pos, 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, std::unordered_set *pns, 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->insert(pos); + *is_not_blocked = false; + } else { + pns->insert(pos); + } + } + } +} +// 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, std::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite){ + if (is_valid_position(pos)){ + if (_xy_is_color(pos, board, color_of_piece)){ + return; + } else { + pns->insert(pos); + } + } +} + +// 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, std::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite, int en_passant){ + if (is_valid_position(pos) && (_xy_is_color(pos, board, color_of_opposite) || + pos == en_passant)){ + pns->insert(pos); + } +} +// This is a specialized functions for the pawn's inability to take going forward. +// Notice the lack of insertion where there usually is when (x,y) is a different color. +void _pawn_add_if_not_blocked(int pos, std::unordered_set *pns, 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)){ + *is_not_blocked = false; + } else { + pns->insert(pos); + } + } + } +} + + +void _get_all_moves_rook(int pos, std::unordered_set *pns, std::array* board, Color pc, Color rc){ + for (int rk_off : ROOK_PIECE_OFFSETS){ + bool* not_blocked = new bool(true); + for (int offset=1; offset<8; offset++){ + _add_if_not_blocked(pos+(rk_off*offset), pns, board, pc, rc, not_blocked); + } + } + + /* + bool* not_blocked_addx = new bool(true); + bool* not_blocked_minx = new bool(true); + bool* not_blocked_addy = new bool(true); + bool* not_blocked_miny = new bool(true); + for (int offset=1; offset<8; offset++){ + _add_if_not_blocked(x+offset, y, pns, board, pc, rc, not_blocked_addx); + _add_if_not_blocked(x, y+offset, pns, board, pc, rc, not_blocked_addy); + _add_if_not_blocked(x-offset, y, pns, board, pc, rc, not_blocked_minx); + _add_if_not_blocked(x, y-offset, pns, board, pc, rc, not_blocked_miny); + } + */ +} + +void _get_all_moves_bishop(int pos, std::unordered_set *pns, std::array* board, Color pc, Color rc){ + for (int bs_off : BISHOP_PIECE_OFFSETS){ + bool* not_blocked = new bool(true); + for (int offset=1; offset<8; offset++){ + _add_if_not_blocked(pos+(bs_off*offset), pns, board, pc, rc, not_blocked); + } + } + /* + bool* not_blocked_addx_addy = new bool(true); + bool* not_blocked_addx_miny = new bool(true); + bool* not_blocked_minx_addy = new bool(true); + bool* not_blocked_minx_miny = new bool(true); + + for (int offset=1; offset<8; offset++){ + int xpoff = x+offset; + int ypoff = y+offset; + int xnoff = x-offset; + int ynoff = y-offset; + _add_if_not_blocked(xpoff, ypoff, pns, board, pc, rc, not_blocked_addx_addy); + _add_if_not_blocked(xpoff, ynoff, pns, board, pc, rc, not_blocked_addx_miny); + _add_if_not_blocked(xnoff, ypoff, pns, board, pc, rc, not_blocked_minx_addy); + _add_if_not_blocked(xnoff, ynoff, pns, board, pc, rc, not_blocked_minx_miny); + } + */ +} +void _get_all_moves_knight(int pos, std::unordered_set *pns, std::array* board, Color pc, Color rc){ + for (int kn_off : KNIGHT_PIECE_OFFSETS){ + bool* not_blocked = new bool(true); + _add_if_not_blocked(pos+kn_off, pns, board, pc, rc, not_blocked); + } + /* + for (int xo=1;xo<=2;xo++){ + int yo=(xo==1)?2:1; + _add_if_not_blocked(x+xo, y+yo, pns, board, pc, rc); + _add_if_not_blocked(x-xo, y+yo, pns, board, pc, rc); + _add_if_not_blocked(x+xo, y-yo, pns, board, pc, rc); + _add_if_not_blocked(x-xo, y-yo, pns, board, pc, rc); + } + */ +} + +void _get_all_moves_king(int pos, std::unordered_set *pns, std::array* board, Color pc, Color rc){ + for (int kn_off : KING_PIECE_OFFSETS){ + bool* not_blocked = new bool(true); + _add_if_not_blocked(pos+kn_off, pns, board, pc, rc, not_blocked); + } + + + /* + _add_if_not_blocked(x+1, y+1, pns, board, pc, rc); + _add_if_not_blocked(x+1, y-1, pns, board, pc, rc); + _add_if_not_blocked(x-1, y+1, pns, board, pc, rc); + _add_if_not_blocked(x-1, y-1, pns, board, pc, rc); + _add_if_not_blocked(x, y+1, pns, board, pc, rc); + _add_if_not_blocked(x, y-1, pns, board, pc, rc); + _add_if_not_blocked(x+1, y, pns, board, pc, rc); + _add_if_not_blocked(x-1, y, pns, board, pc, rc); + */ +} + +void _get_all_moves_pawn(int pos, std::unordered_set *pns, 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; + + bool *free_to_double_move = new bool(true); + _pawn_add_if_not_blocked(pos+offset1, pns, board, pc, rc, free_to_double_move); + if (get_rank(pos) == default_pawn_rank){ // If on second/seventh rank + _pawn_add_if_not_blocked(pos+offset2, pns, board, pc, rc, free_to_double_move); + } + // 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, pns, board, pc, rc, en_passant); + _pawn_diag_add_if_not_blocked(pos+offset1-1, pns, board, pc, rc, en_passant); +} diff --git a/src/bitwise.cpp b/src/bitwise.cpp index 474a71e..9063bf9 100644 --- a/src/bitwise.cpp +++ b/src/bitwise.cpp @@ -1,54 +1,18 @@ #include "bitwise.h" // Get first 6 bits of int -int get_from_sq(int mv){ - return (mv & 0x3f); -} - // Get bits 7-12 of int -int get_to_sq(int mv){ - return ((mv >> 6) & 0x3f); -} - // Get bits 13-16 of int -int get_captured_pc(int mv){ - return ((mv >> 12) & 0xf); -} - // Get bits 17-20 of int -int get_promoted_to_pc(int mv){ - return ((mv >> 16) & 0xf); -} - // Get 21st bit of int -int get_en_pass_flag(int mv){ - return ((mv >> 20) & 0x1); -} - // Get 22nd bit of int -int get_pawn_st_flag(int mv){ - return ((mv >> 21) & 0x1); -} - // Get 23rd bit of int -int get_castle_flag(int mv){ - return ((mv >> 22) & 0x1); -} // Get last 3 bits of number (the rank). // Techincally this gets all bits 4-32/64 but I'm just assuming it won't be larger than 63 before the shift. -int get_rank(int position){ - return (position >> 3); -} // Get first 3 bits of number -int get_file(int position){ - return (position & 7); -} - // if the position has a 7th bit we know it's off the board. + // it indicates that is it off the board. // ASSUMING position <= 128 but if it was that big that'd be weird. -bool is_valid_position(int position){ - return !(position & 0x40); -} diff --git a/src/bitwise.h b/src/bitwise.h index e5cd126..fd88d9c 100644 --- a/src/bitwise.h +++ b/src/bitwise.h @@ -34,17 +34,39 @@ */ // Redefine as functions for fun :shrug: -int get_from_sq(int mv); -int get_to_sq(int mv); -int get_captured_pc(int mv); -int get_promoted_to_pc(int mv); -int get_en_pass_flag(int mv); -int get_pawn_st_flag(int mv); -int get_castle_flag(int mv); +inline int get_from_sq(int mv){ + return (mv & 0x3f); +} +inline int get_to_sq(int mv){ + return ((mv >> 6) & 0x3f); +} +inline int get_captured_pc(int mv){ + return ((mv >> 12) & 0xf); +} +inline int get_promoted_to_pc(int mv){ + return ((mv >> 16) & 0xf); +} +inline int get_en_pass_flag(int mv){ + return ((mv >> 20) & 0x1); +} +inline int get_pawn_st_flag(int mv){ + return ((mv >> 21) & 0x1); +} +inline int get_castle_flag(int mv){ + return ((mv >> 22) & 0x1); +} -int get_rank(int position); -int get_file(int position); - -bool is_valid_position(int position); +inline int get_rank(int position){ + return (position >> 3); +} +inline int get_file(int position){ + return (position & 7); +} +inline bool is_valid_position(int position){ + return !(position & 0x40); +} +inline bool is_invalid_position(int position){ + return (position & 0x40); +} #endif diff --git a/src/bitwise_constants.cpp b/src/bitwise_constants.cpp new file mode 100644 index 0000000..0727647 --- /dev/null +++ b/src/bitwise_constants.cpp @@ -0,0 +1,16 @@ +#include "bitwise_constants.h" +#include +#include + +int main(){ + for (int y=0;y<12;y++){ + for (int x=0;x<10;x++){ + int cord = (y*10) + x; + int val = DEFAULT_BOARD[cord]; + val==-1?std::cout << '!':std::cout << CHESS_CHARS[val]; + std::cout << std::hex << y << "," << x << " "; + } + std::cout << std::endl; + } + return 0; +} diff --git a/src/bitwise_constants.h b/src/bitwise_constants.h new file mode 100644 index 0000000..8bb4b98 --- /dev/null +++ b/src/bitwise_constants.h @@ -0,0 +1,76 @@ +#ifndef BITWISE_CONSTANTS_H +#define BITWISE_CONSTANTS_H + +#include +#include + +enum Color { + NO_COLOR, + WHITE, + BLACK +}; + +enum PieceType { + NONE, + B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING, + W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING +}; +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}; +} +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 +}; + +enum Rank{ + RANK1, + RANK2, + RANK3, + RANK4, + RANK5, + RANK6, + RANK7, + RANK8 +}; + +enum File { + FILE1, + FILE2, + FILE3, + FILE4, + FILE5, + FILE6, + FILE7, + FILE8 +}; + +std::array DEFAULT_BOARD = { + NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, + NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, + NA, B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, NA, + NA, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, NA, + NA, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NA, + NA, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NA, + NA, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NA, + NA, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NA, + NA, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, NA, + NA, W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK, NA, + NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, + NA,NA,NA,NA,NA,NA,NA,NA,NA,NA +}; + +char CHESS_CHARS[13] = { + ' ', + 'P', 'N', 'B', 'R', 'Q', 'K', + 'p', 'n', 'b', 'r', 'q', 'k' +}; +#endif diff --git a/src/bitwise_functions.cpp b/src/bitwise_functions.cpp new file mode 100644 index 0000000..54796ab --- /dev/null +++ b/src/bitwise_functions.cpp @@ -0,0 +1,207 @@ +#include "bitwise.h" +#include "bitwise_functions.h" +#include "all_moves_bitwise_functions.cpp" +#include +#include +#include +#include +#include +#include +#include + +// TODO implement functions.h functions. +// NOTE tests will NOT run unless you implement these functions. + + +std::pair pos_to_pair(Position pn){ + int x,y = 0; + for (x = pn; x >= 8; x = x-8){ + ++y; + } + return std::make_pair(x, std::abs(y-7)); +} + +// 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."); + } + 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()); + } +} +Position pair_to_pos(int x, int y){ + return pair_to_pos(std::make_pair(x, y)); +} + +bool is_valid_position(std::pair pos){ + return (pos.first < 8 && pos.second < 8 && + pos.first >= 0 && pos.second >=0); +} +bool is_valid_position(int x, int y){ + return (x < 8 && x >= 0 && + y < 8 && y >= 0); +} + +bool is_white(PieceType pt){ + for (auto pn : Pieces::WHITE){ + if (pn == pt) return true; + } + return false; +} +bool is_black(PieceType pt){ + for (auto pn : Pieces::BLACK){ + if (pn == pt) return true; + } + return false; +} + +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 x, int y, std::array board){ + return get_color(board[pair_to_pos(x, y)]); +} +Color get_color(Position pn, std::array board){ + return get_color(board[pn]); +} + +Color rev_color(Color c){ + if (c==Color::NO_COLOR) return Color::NO_COLOR; + return c==Color::WHITE?Color::BLACK:Color::WHITE; +} + +std::unordered_set get_possible_movers(Position pn, std::array board){ + std::unordered_set pns = {Position::A1}; + return pns; +} + +std::unordered_set get_possible_moves(Position pn, std::array board){ + std::unordered_set pns = {Position::A1}; + get_all_moves(pn, &board, &pns); + return pns; +} + +int get_pos_of(PieceType pt, std::array *board){ + for (int pn = Position::A8; pn!=Position::H1; pn++){ + if ((*board)[pn] == pt){ + return pn; + } + } + return Position::NA; +} + +void get_poss_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)); + } + } +} + +//TODO: Make faster by running from king squar eonly, instead of running on every piece of opposite team. +void filter_checked_moves(Position pn, PieceType pt, std::array *board, std::unordered_set *pns){ + PieceType my_king = is_white(pt)?PieceType::W_KING:PieceType::B_KING; + int my_king_pos = get_pos_of(my_king, board); + int attackers = 0; + for (auto p_pn= pns->begin(); p_pn!=pns->end();){ + // Make move + int move_int = pn + (*p_pn >> 6); + std::array moved_board = dumb_move(move_int, board); + // Get all piecetypes of other team + std::array other_team = is_white(pt)?Pieces::BLACK:Pieces::WHITE; + bool checks_king = false; + // go through each piece of other team + for (PieceType other_p : other_team) { + checks_king = false; + // For every place the piecetype is + // NEW CODE +// for (Position psn : get_all_moves(my_king_pos, moved_board, false)){ +// +// } + // \NEW CODE + std::vector psns; + get_poss_of(other_p, &moved_board, &psns); + for (auto psn : psns){ + std::unordered_set other_moves; + get_all_moves(psn, &moved_board, &other_moves, false); + // for every position the piece can mvoe to + for (int cp : other_moves){ + if (get_to_sq(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; + } + } +} + +void get_all_moves(Position pn, std::array* board, std::unordered_set* moves, bool recursive, int en_passant){ + PieceType pt = (*board)[pn]; + int pos = pn; + int x = pos_to_pair(pn).first; + int y = pos_to_pair(pn).second; + 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_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_rook(pos, moves, board, color_of_piece, color_of_opponent); + break; + case PieceType::B_BISHOP: + case PieceType::W_BISHOP: + _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_knight(pos, moves, board, color_of_piece, color_of_opponent); + break; + case PieceType::B_KING: + case PieceType::W_KING: + _get_all_moves_king(pos, moves, board, color_of_piece, color_of_opponent); + 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; + } + if (recursive){ + filter_checked_moves(pn, 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; +} diff --git a/src/bitwise_functions.h b/src/bitwise_functions.h new file mode 100644 index 0000000..3854940 --- /dev/null +++ b/src/bitwise_functions.h @@ -0,0 +1,50 @@ +#include "bitwise_constants.h" +#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); +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); + +// Check if int is a valid position in enum of Position +// Allow ints, and pairs to be checked. +bool is_valid_position(int pos); +bool is_valid_position(std::pair pos); +bool is_valid_position(int x, int y); + +// Checks if given piece matches a certain color. +bool is_white(PieceType pt); +bool is_black(PieceType pt); + +Color get_color(int x, int y, std::array *board); +Color get_color(Position pn, std::array *board); +Color get_color(PieceType pt); +// NO_COLOR returns NO_COLOR +// WHITE returns BLACK +// BLACK returns WHITE +Color rev_color(Color c); + +// 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. +void get_possible_movers(Position pn, std::array *pt,std::unordered_set *moves); + +// Get all possible moved for piece in Position pn. +// This may require helper functions for each individual piece. +void get_possible_moves(Position pn, std::array *pt,std::unordered_set *moves); + +// Get all moves for piece in Position pn. +void get_all_moves(Position pn, std::array *pt,std::unordered_set *moves, bool recursive=true, int en_passant=Position::NA); + +// Dumb function to do board moves. +// Does not check if move is valid, just does it. +std::array dumb_move(int move, std::array *board); diff --git a/tests/Makefile b/tests/Makefile index 648e44c..d921376 100755 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,5 +1,6 @@ defualt: all.out bitwise: bitwise.out +bitwise_functions: bitwise_main.out catch_main.o: g++ -w -c -o catch_main.o catch_main.cpp @@ -10,6 +11,9 @@ custom_printing.o: bitwise.out: catch_main.o g++ -I../src/ -o bitwise.out ../src/bitwise.cpp catch_main.o bitwise_tests.cpp +bitwise_main.out: catch_main.o + g++ -I../src/ -o bitwise_functions.out ../src/bitwise.cpp catch_main.o ../src/bitwise_functions.cpp bitwise_main.cpp + # TODO: Allw all.out to contain bitwise tests all.out: catch_main.o custom_printing.o g++ -std=c++11 -ggdb -w -I../src/ -o all.out ../src/functions.cpp catch_main.o custom_printing.o tests_main.cpp diff --git a/tests/bitwise_main.cpp b/tests/bitwise_main.cpp new file mode 100644 index 0000000..d530a1c --- /dev/null +++ b/tests/bitwise_main.cpp @@ -0,0 +1,157 @@ +#include "catch.hpp" +#include "test_boards.h" +#include "valid_moves.h" +#include "custom_printing.cpp" +#include +#include + + +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 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); + CHECK(get_color(2, 1, DUMB_MOVE_1) == Color::WHITE); + 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 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]"){ + 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))); + + CHECK(pair_to_pos(2, 3) == Position::C4); + CHECK(pair_to_pos(7, 0) == Position::H1); + CHECK(pair_to_pos(0, 0) == Position::A1); + CHECK(pair_to_pos(7, 7) == Position::H8); + CHECK_THROWS(pair_to_pos(8, 2)); + CHECK_THROWS(pair_to_pos(-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 that invalid position ints return false", "[is_valid_position]"){ + CHECK(is_valid_position(0)); // 0=A8 + CHECK(is_valid_position(63)); // 63=H1 + CHECK_FALSE(is_valid_position(-1)); // -1 is out of bounds + CHECK_FALSE(is_valid_position(64)); // 64 is out of bounds + + CHECK(is_valid_position(std::make_pair(0, 0))); // 0-7,0-7 should be valid + CHECK(is_valid_position(std::make_pair(7, 7))); + CHECK_FALSE(is_valid_position(std::make_pair(-1, 5))); // should fail + CHECK_FALSE(is_valid_position(std::make_pair(5, 8))); // should fail + + CHECK(is_valid_position(0, 0)); // 0-7,0-7 should be valid + CHECK(is_valid_position(7, 7)); + CHECK_FALSE(is_valid_position(-1, 5)); // should fail + CHECK_FALSE(is_valid_position(5, 8)); // should fail +} + +TEST_CASE("Test what pieces may move where functon", "[get_possible_movers]"){ + std::unordered_set H1_possible_movers = {Position::H2, Position::G1}; + CHECK(get_possible_movers(BISHOP_BLOCKED1_KING_POS, BISHOP_BLOCKED1_BOARD) == BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING); + CHECK(get_possible_movers(Position::H3, DEFAULT_BOARD) == H1_possible_movers); +} + +TEST_CASE("Test where this piece may move to", "[get_possible_moves]"){ + CHECK(get_possible_moves(Position::G1, DEFAULT_BOARD) == DEFAULT_W_R_KNIGHT_POSSIBLE_MOVES); + CHECK(get_possible_moves(Position::A7, DEFAULT_BOARD) == DEFAULT_B_A_PAWN_POSSIBLE_MOVES); + CHECK(get_possible_moves(Position::A2, DEFAULT_BOARD) == DEFAULT_W_A_PAWN_POSSIBLE_MOVES); + CHECK(get_possible_moves(KNIGHT_BLOCKED1_POS, KNIGHT_BLOCKED1_BOARD) == KNIGHT_BLOCKED1_MOVES); + CHECK(get_possible_moves(BISHOP_BLOCKED1_POS, BISHOP_BLOCKED1_BOARD) == BISHOP_BLOCKED1_MOVES); + CHECK(get_possible_moves(ROOK_BLOCKED1_POS, ROOK_BLOCKED1_BOARD) == ROOK_BLOCKED1_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); +} + +TEST_CASE("Test all moves for white in edge cases.", "[get_all_moves][white]"){ + CHECK(get_all_moves(W_KNIGHT_SIDE1_POS, W_KNIGHT_SIDE1_BOARD) == W_KNIGHT_SIDE1_ALL_MOVES); + CHECK(get_all_moves(W_KING_SIDE1_POS, W_KING_SIDE1_BOARD) == W_KING_SIDE1_ALL_MOVES); + CHECK(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_all_moves(B_KNIGHT_SIDE1_POS, B_KNIGHT_SIDE1_BOARD) == B_KNIGHT_SIDE1_ALL_MOVES); + CHECK(get_all_moves(B_KING_SIDE1_POS, B_KING_SIDE1_BOARD) == B_KING_SIDE1_ALL_MOVES); + 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); +} + +TEST_CASE("Tests for en pessant squares.", "[get_all_moves]"){ + CHECK(get_all_moves(EN_PASSANT_TEST_POS, EN_PASSANT_TEST_BOARD, false, EN_PASSANT_SQUARE) == EN_PASSANT_TEST_MOVES); + CHECK(get_all_moves(NO_EN_PASSANT_TEST_POS, NO_EN_PASSANT_TEST_BOARD) == NO_EN_PASSANT_TEST_MOVES); +} From 580c43a8e82678bce9d161e2e693ca0b7fc482ad Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sat, 20 Apr 2019 21:56:42 +0000 Subject: [PATCH 32/81] Bitwise functions/tests now compile. --- src/all_moves_bitwise_functions.cpp | 14 +- src/bitwise.h | 50 ++--- src/bitwise_constants.h | 51 +++-- src/bitwise_functions.cpp | 57 ++++-- src/bitwise_functions.h | 21 ++- tests/B_test_boards.h | 242 ++++++++++++++---------- tests/Makefile | 7 +- tests/W_test_boards.h | 283 ++++++++++++++++------------ tests/bitwise_main.cpp | 107 +++++------ tests/bitwise_tests.cpp | 2 +- tests/custom_bitwise_printing.cpp | 95 ++++++++++ tests/valid_moves.h | 236 +++++++++++++---------- 12 files changed, 706 insertions(+), 459 deletions(-) create mode 100644 tests/custom_bitwise_printing.cpp diff --git a/src/all_moves_bitwise_functions.cpp b/src/all_moves_bitwise_functions.cpp index e39e395..cd6cd70 100644 --- a/src/all_moves_bitwise_functions.cpp +++ b/src/all_moves_bitwise_functions.cpp @@ -48,12 +48,10 @@ void _add_if_not_blocked(int pos, std::unordered_set *pns, std::array *pns, std::array *board, Color color_of_piece, Color color_of_opposite){ - if (is_valid_position(pos)){ - if (_xy_is_color(pos, board, color_of_piece)){ - return; - } else { - pns->insert(pos); - } + if (_xy_is_color(pos, board, color_of_piece)){ + return; + } else { + pns->insert(pos); } } @@ -134,7 +132,7 @@ void _get_all_moves_bishop(int pos, std::unordered_set *pns, std::array *pns, std::array* board, Color pc, Color rc){ for (int kn_off : KNIGHT_PIECE_OFFSETS){ bool* not_blocked = new bool(true); - _add_if_not_blocked(pos+kn_off, pns, board, pc, rc, not_blocked); + _add_if_not_blocked(pos+kn_off, pns, board, pc, rc); } /* for (int xo=1;xo<=2;xo++){ @@ -150,7 +148,7 @@ void _get_all_moves_knight(int pos, std::unordered_set *pns, std::array *pns, std::array* board, Color pc, Color rc){ for (int kn_off : KING_PIECE_OFFSETS){ bool* not_blocked = new bool(true); - _add_if_not_blocked(pos+kn_off, pns, board, pc, rc, not_blocked); + _add_if_not_blocked(pos+kn_off, pns, board, pc, rc); } diff --git a/src/bitwise.h b/src/bitwise.h index fd88d9c..611e7df 100644 --- a/src/bitwise.h +++ b/src/bitwise.h @@ -2,11 +2,12 @@ #define BITWISE_H #include +#include "bitwise_constants.h" // Using macros for ease of use, can also use functons, but I don't see the point. /* - * From (Position): 7 bits (2^6 == 64) possibilities + * 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 @@ -14,13 +15,13 @@ * pawn starting move flag: 1 bit * castle move flag: 1 bit * - * 0000 0000 0000 0000 0011 1111 -> From square position (& 0x3F) - * 0000 0000 0000 0111 1100 0000 -> To square position (>> 6 & 0x3F) - * 0000 0000 1111 0000 0000 0000 -> captured piece, if any (>> 12 & 0xF) - * 0000 1111 0000 0000 0000 0000 -> if prmoted, what to? (>> 16 & 0xF) - * 0001 0000 0000 0000 0000 0000 -> en passant (& 0x100000) - * 0010 0000 0000 0000 0000 0000 -> pawn starting move (& 0x200000) - * 0100 0000 0000 0000 0000 0000 -> castle move (& 0x400000) + * 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) * */ /* OLD, DO NOT USE @@ -35,38 +36,37 @@ // Redefine as functions for fun :shrug: inline int get_from_sq(int mv){ - return (mv & 0x3f); + return (mv & 0x7f); } inline int get_to_sq(int mv){ - return ((mv >> 6) & 0x3f); + return ((mv >> 7) & 0x7f); } inline int get_captured_pc(int mv){ - return ((mv >> 12) & 0xf); + return ((mv >> 14) & 0xf); } inline int get_promoted_to_pc(int mv){ - return ((mv >> 16) & 0xf); + return ((mv >> 18) & 0xf); } inline int get_en_pass_flag(int mv){ - return ((mv >> 20) & 0x1); + return ((mv >> 22) & 0x1); } inline int get_pawn_st_flag(int mv){ - return ((mv >> 21) & 0x1); + return ((mv >> 23) & 0x1); } inline int get_castle_flag(int mv){ - return ((mv >> 22) & 0x1); + return ((mv >> 24) & 0x1); } - -inline int get_rank(int position){ - return (position >> 3); -} -inline int get_file(int position){ - return (position & 7); +// Just trying to get working for now. +Rank get_rank(int pos){ + if (pos >30 && pos < 39){ + return Rank::RANK7; + } else if (pos > 80 && pos < 89){ + return Rank::RANK2; + } + return Rank::RANK1; } inline bool is_valid_position(int position){ - return !(position & 0x40); -} -inline bool is_invalid_position(int position){ - return (position & 0x40); + return DEFAULT_BOARD[position] == PieceType::INV; } #endif diff --git a/src/bitwise_constants.h b/src/bitwise_constants.h index 8bb4b98..c51be45 100644 --- a/src/bitwise_constants.h +++ b/src/bitwise_constants.h @@ -1,8 +1,9 @@ -#ifndef BITWISE_CONSTANTS_H -#define BITWISE_CONSTANTS_H +#ifndef BT_CONST_H +#define BT_CONST_H #include #include +#include enum Color { NO_COLOR, @@ -11,6 +12,7 @@ enum Color { }; enum PieceType { + INV=-1, NONE, B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING, W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING @@ -31,6 +33,22 @@ enum Position { A1=91, B1, C1, D1, E1, F1, G1, H1 }; +// Access with POSITION_STRING[Position] +const std::vector 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" +}; + enum Rank{ RANK1, RANK2, @@ -53,24 +71,25 @@ enum File { FILE8 }; -std::array DEFAULT_BOARD = { - NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, - NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, - NA, B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, NA, - NA, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, NA, - NA, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NA, - NA, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NA, - NA, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NA, - NA, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NA, - NA, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, NA, - NA, W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK, NA, - NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, - NA,NA,NA,NA,NA,NA,NA,NA,NA,NA +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 }; -char CHESS_CHARS[13] = { +const std::array CHESS_CHARS = { ' ', 'P', 'N', 'B', 'R', 'Q', 'K', 'p', 'n', 'b', 'r', 'q', 'k' }; #endif + diff --git a/src/bitwise_functions.cpp b/src/bitwise_functions.cpp index 54796ab..6efd637 100644 --- a/src/bitwise_functions.cpp +++ b/src/bitwise_functions.cpp @@ -68,11 +68,11 @@ Color get_color(PieceType pt){ return Color::NO_COLOR; } -Color get_color(int x, int y, std::array board){ - return get_color(board[pair_to_pos(x, y)]); +Color get_color(int x, int y, std::array const *board){ + return get_color((*board)[pair_to_pos(x, y)]); } -Color get_color(Position pn, std::array board){ - return get_color(board[pn]); +Color get_color(Position pn, std::array const *board){ + return get_color((*board)[pn]); } Color rev_color(Color c){ @@ -91,7 +91,7 @@ std::unordered_set get_possible_moves(Position pn, std::array *board){ +int get_pos_of(PieceType pt, std::array const *board){ for (int pn = Position::A8; pn!=Position::H1; pn++){ if ((*board)[pn] == pt){ return pn; @@ -100,6 +100,16 @@ int get_pos_of(PieceType pt, std::array *board){ return Position::NA; } +std::unordered_set get_poss_of(PieceType pt, std::array const *board){ + std::unordered_set results; + for (int pn = Position::A8; pn!=Position::H1; pn++){ + if ((*board)[pn] == pt){ + results.insert(pn); + } + } + return results; +} + void get_poss_of(PieceType pt, std::array* board, std::vector* pns){ for (int pn = Position::A8; pn!=Position::H1; pn++){ if ((*board)[pn] == pt){ @@ -109,14 +119,14 @@ void get_poss_of(PieceType pt, std::array* board, std::vector *board, std::unordered_set *pns){ +void filter_checked_moves(int pos, PieceType pt, std::array *board, std::unordered_set *pns){ PieceType my_king = is_white(pt)?PieceType::W_KING:PieceType::B_KING; int my_king_pos = get_pos_of(my_king, board); int attackers = 0; for (auto p_pn= pns->begin(); p_pn!=pns->end();){ // Make move - int move_int = pn + (*p_pn >> 6); - std::array moved_board = dumb_move(move_int, board); + int move_int = pos + (*p_pn >> 7); + std::array moved_board = dumb_move(move_int, *board); // Get all piecetypes of other team std::array other_team = is_white(pt)?Pieces::BLACK:Pieces::WHITE; bool checks_king = false; @@ -158,11 +168,8 @@ void filter_checked_moves(Position pn, PieceType pt, std::array } } -void get_all_moves(Position pn, std::array* board, std::unordered_set* moves, bool recursive, int en_passant){ - PieceType pt = (*board)[pn]; - int pos = pn; - int x = pos_to_pair(pn).first; - int y = pos_to_pair(pn).second; +void get_all_moves(int pos, std::array* board, std::unordered_set* moves, bool recursive, int en_passant){ + PieceType pt = (*board)[pos]; Color color_of_piece = get_color(pt); Color color_of_opponent = rev_color(color_of_piece); switch(pt){ @@ -195,13 +202,33 @@ void get_all_moves(Position pn, std::array* board, std::unordere break; } if (recursive){ - filter_checked_moves(pn, pt, board, moves); + filter_checked_moves(pos, pt, board, moves); } } -std::array dumb_move(Position from, Position to, std::array board){ +std::unordered_set get_all_moves(int pos, std::array board, bool recursive, int en_passant){ + std::unordered_set moves; + get_all_moves(pos, &board, &moves, recursive, en_passant); + return moves; +} + +std::array dumb_move(int move, std::array board){ + int from = get_from_sq(move); + int to = get_to_sq(move); PieceType piece = board[from]; board[to] = piece; board[from] = PieceType::NONE; return board; } + +std::unordered_set get_to_squares(std::unordered_set moves){ + std::unordered_set to_squares; + for (int move : moves){ + to_squares.insert(get_to_sq(move)); + } + return to_squares; +} +std::unordered_set get_from_squared(std::unordered_set moves){ + std::unordered_set from_squares; + return from_squares; +} diff --git a/src/bitwise_functions.h b/src/bitwise_functions.h index 3854940..1437f90 100644 --- a/src/bitwise_functions.h +++ b/src/bitwise_functions.h @@ -10,7 +10,8 @@ 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); +int get_pos_of(PieceType pt, std::array const *board); +std::unordered_set get_poss_of(PieceType pt, std::array const *board); // Convert a Position number into a pair of x y coordiinates std::pair pos_to_pair(Position pn); @@ -25,8 +26,8 @@ bool is_valid_position(int x, int y); bool is_white(PieceType pt); bool is_black(PieceType pt); -Color get_color(int x, int y, std::array *board); -Color get_color(Position pn, std::array *board); +Color get_color(int x, int y, std::array const *board); +Color get_color(Position pn, std::array const *board); Color get_color(PieceType pt); // NO_COLOR returns NO_COLOR // WHITE returns BLACK @@ -42,9 +43,19 @@ void get_possible_movers(Position pn, std::array *pt,std::unorde // This may require helper functions for each individual piece. void get_possible_moves(Position pn, std::array *pt,std::unordered_set *moves); +// This functions removes moves that put your own king in check. +void filter_checked_moves(int pos, std::array *board, std::unordered_set *moves); + // Get all moves for piece in Position pn. -void get_all_moves(Position pn, std::array *pt,std::unordered_set *moves, bool recursive=true, int en_passant=Position::NA); +void get_all_moves(int pos, std::array *pt,std::unordered_set *moves, bool recursive=true, int en_passant=Position::NA); +std::unordered_set get_all_moves(int pos, std::array board, bool recursive=true, int en_passant=Position::NA); // Dumb function to do board moves. // Does not check if move is valid, just does it. -std::array dumb_move(int move, std::array *board); +std::array dumb_move(int move, std::array board); + +// Allow the developer to get only certain pieces of the part of a move in a list. +// This will return a vector (or unordered_set) of elements with only a certain part of the move revealed bit bit-switching. +std::unordered_set get_from_squares(std::unordered_set moves); +std::unordered_set get_to_squares(std::unordered_set moves); + diff --git a/tests/B_test_boards.h b/tests/B_test_boards.h index 2b898e1..f413b9b 100644 --- a/tests/B_test_boards.h +++ b/tests/B_test_boards.h @@ -1,19 +1,23 @@ #include -#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::unordered_set B_QUEEN_ALL_MOVES = { +const std::unordered_set B_QUEEN_ALL_MOVES = { A8, E8, B7, E7, H7, C6, E6, G6, @@ -24,19 +28,23 @@ const std::unordered_set B_QUEEN_ALL_MOVES = { B1, E1, 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::unordered_set B_BISHOP_ALL_MOVES = { +const std::unordered_set B_BISHOP_ALL_MOVES = { H8, A7, G7, B6, F6, @@ -46,121 +54,149 @@ const std::unordered_set B_BISHOP_ALL_MOVES = { A1, 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::unordered_set B_KNIGHT_ALL_MOVES = { +const std::unordered_set B_KNIGHT_ALL_MOVES = { C7, E7, B6, 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::unordered_set B_ROOK_ALL_MOVES = { +const std::unordered_set B_ROOK_ALL_MOVES = { E8, E7, E6, A5, B5, C5, D5, 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::unordered_set B_KING_ALL_MOVES = { +const std::unordered_set B_KING_ALL_MOVES = { B5, C5, D5, B4, D4, B3, C3, D3 }; -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, 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 +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::unordered_set B_PAWN_ALL_MOVES = { +const std::unordered_set B_PAWN_ALL_MOVES = { F3 }; -const Position B_KNIGHT_SIDE1_POS = B7; -const std::array B_KNIGHT_SIDE1_BOARD = { - 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, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE -}; -const std::unordered_set B_KNIGHT_SIDE1_ALL_MOVES = { +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::unordered_set B_KNIGHT_SIDE1_ALL_MOVES = { D8, D6, A5, C5 }; -const Position B_KING_SIDE1_POS = A8; -const std::array B_KING_SIDE1_BOARD = { - 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, 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 B_KING_SIDE1_ALL_MOVES = { +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::unordered_set B_KING_SIDE1_ALL_MOVES = { B8, A7,B7 }; -const Position B_PAWN_SIDE1_POS = A7; -const std::array B_PAWN_SIDE1_BOARD = { - 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, 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 B_PAWN_SIDE1_ALL_MOVES = { +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::unordered_set B_PAWN_SIDE1_ALL_MOVES = { A6, A5 }; diff --git a/tests/Makefile b/tests/Makefile index d921376..6458377 100755 --- a/tests/Makefile +++ b/tests/Makefile @@ -8,11 +8,14 @@ catch_main.o: custom_printing.o: g++ -w -I../src/ -c -o custom_printing.o custom_printing.cpp +custom_bitwise_printing.o: + g++ -w -I../src/ -c -o custom_bitwise_printing.o custom_bitwise_printing.cpp + bitwise.out: catch_main.o g++ -I../src/ -o bitwise.out ../src/bitwise.cpp catch_main.o bitwise_tests.cpp -bitwise_main.out: catch_main.o - g++ -I../src/ -o bitwise_functions.out ../src/bitwise.cpp catch_main.o ../src/bitwise_functions.cpp bitwise_main.cpp +bitwise_main.out: catch_main.o custom_bitwise_printing.o + g++ -I../src/ -o bitwise_functions.out catch_main.o custom_bitwise_printing.o ../src/bitwise_functions.cpp bitwise_main.cpp # TODO: Allw all.out to contain bitwise tests all.out: catch_main.o custom_printing.o diff --git a/tests/W_test_boards.h b/tests/W_test_boards.h index d077c16..ae545c2 100644 --- a/tests/W_test_boards.h +++ b/tests/W_test_boards.h @@ -1,29 +1,38 @@ #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::unordered_set W_QUEEN_ALL_MOVES = { +#include + +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::unordered_set W_QUEEN_ALL_MOVES = { A8, E8, B7, E7, H7, C6, E6, G6, @@ -34,19 +43,23 @@ const std::unordered_set W_QUEEN_ALL_MOVES = { 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 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::unordered_set W_BISHOP_ALL_MOVES = { +const std::unordered_set W_BISHOP_ALL_MOVES = { H8, A7, G7, B6, F6, @@ -56,122 +69,150 @@ const std::unordered_set W_BISHOP_ALL_MOVES = { 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 Position W_KNIGHT_SIDE1_POS = B7; -const std::array W_KNIGHT_SIDE1_BOARD = { - 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, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE -}; -const std::unordered_set W_KNIGHT_SIDE1_ALL_MOVES = { +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::unordered_set W_KNIGHT_SIDE1_ALL_MOVES = { D8, D6, A5, C5 }; -const std::unordered_set W_KNIGHT_ALL_MOVES = { +const std::unordered_set W_KNIGHT_ALL_MOVES = { C7, E7, B6, F6, 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 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::unordered_set W_ROOK_ALL_MOVES = { +const std::unordered_set W_ROOK_ALL_MOVES = { E8, E7, E6, A5, B5, C5, D5, 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 Position W_KING_SIDE1_POS = A8; -const std::array W_KING_SIDE1_BOARD = { - 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, 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 W_KING_SIDE1_ALL_MOVES = { +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 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::unordered_set W_KING_SIDE1_ALL_MOVES = { B8, A7,B7 }; -const std::unordered_set W_KING_ALL_MOVES = { +const std::unordered_set W_KING_ALL_MOVES = { B5, C5, D5, B4, D4, B3, C3, D3 }; -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, 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 +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::unordered_set W_PAWN_ALL_MOVES = { +const std::unordered_set W_PAWN_ALL_MOVES = { F5 }; -const Position W_PAWN_SIDE1_POS = A8; -const std::array W_PAWN_SIDE1_BOARD = { - 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, 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::unordered_set W_PAWN_SIDE1_ALL_MOVES; +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::unordered_set W_PAWN_SIDE1_ALL_MOVES; diff --git a/tests/bitwise_main.cpp b/tests/bitwise_main.cpp index d530a1c..55e0261 100644 --- a/tests/bitwise_main.cpp +++ b/tests/bitwise_main.cpp @@ -1,38 +1,37 @@ #include "catch.hpp" #include "test_boards.h" #include "valid_moves.h" -#include "custom_printing.cpp" +#include "custom_bitwise_printing.cpp" #include #include -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 +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 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); + 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(2, 7, DUMB_MOVE_1) == Color::BLACK); - CHECK(get_color(3, 3, DUMB_MOVE_1) == Color::NO_COLOR); - CHECK(get_color(2, 1, DUMB_MOVE_1) == Color::WHITE); - 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); + CHECK(get_color(2, 7, &DUMB_MOVE_1) == Color::BLACK); + CHECK(get_color(3, 3, &DUMB_MOVE_1) == Color::NO_COLOR); + CHECK(get_color(2, 1, &DUMB_MOVE_1) == Color::WHITE); + 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); @@ -58,7 +57,8 @@ TEST_CASE("Test that is_black, and is_white are working", "[is_black][is_white]" } TEST_CASE("Test that dumb moves can be made.", "[dumb_move]"){ - CHECK(dumb_move(Position::B2, Position::B5, DEFAULT_BOARD) == DUMB_MOVE_1); + int move_int = Position::B2 + (Position::B5 << 7); + CHECK(dumb_move(move_int, DEFAULT_BOARD) == DUMB_MOVE_1); } TEST_CASE("Test convert method to go from X and Y to board position", "[pair_to_pos]"){ @@ -102,56 +102,41 @@ TEST_CASE("Test that invalid position ints return false", "[is_valid_position]") CHECK_FALSE(is_valid_position(5, 8)); // should fail } -TEST_CASE("Test what pieces may move where functon", "[get_possible_movers]"){ - std::unordered_set H1_possible_movers = {Position::H2, Position::G1}; - CHECK(get_possible_movers(BISHOP_BLOCKED1_KING_POS, BISHOP_BLOCKED1_BOARD) == BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING); - CHECK(get_possible_movers(Position::H3, DEFAULT_BOARD) == H1_possible_movers); -} - -TEST_CASE("Test where this piece may move to", "[get_possible_moves]"){ - CHECK(get_possible_moves(Position::G1, DEFAULT_BOARD) == DEFAULT_W_R_KNIGHT_POSSIBLE_MOVES); - CHECK(get_possible_moves(Position::A7, DEFAULT_BOARD) == DEFAULT_B_A_PAWN_POSSIBLE_MOVES); - CHECK(get_possible_moves(Position::A2, DEFAULT_BOARD) == DEFAULT_W_A_PAWN_POSSIBLE_MOVES); - CHECK(get_possible_moves(KNIGHT_BLOCKED1_POS, KNIGHT_BLOCKED1_BOARD) == KNIGHT_BLOCKED1_MOVES); - CHECK(get_possible_moves(BISHOP_BLOCKED1_POS, BISHOP_BLOCKED1_BOARD) == BISHOP_BLOCKED1_MOVES); - CHECK(get_possible_moves(ROOK_BLOCKED1_POS, ROOK_BLOCKED1_BOARD) == ROOK_BLOCKED1_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); + CHECK(get_to_squares(get_all_moves(B_KING_POS, B_KING_BOARD)) == get_to_squares(B_KING_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(B_QUEEN_POS, B_QUEEN_BOARD)) == get_to_squares(B_QUEEN_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(B_ROOK_POS, B_ROOK_BOARD)) == get_to_squares(B_ROOK_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(B_BISHOP_POS, B_BISHOP_BOARD)) == get_to_squares(B_BISHOP_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(B_KNIGHT_POS, B_KNIGHT_BOARD)) == get_to_squares(B_KNIGHT_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(B_PAWN_POS, B_PAWN_BOARD)) == get_to_squares(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); + CHECK(get_to_squares(get_all_moves(W_KING_POS, W_KING_BOARD)) == get_to_squares(W_KING_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(W_QUEEN_POS, W_QUEEN_BOARD)) == get_to_squares(W_QUEEN_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(W_ROOK_POS, W_ROOK_BOARD)) == get_to_squares(W_ROOK_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(W_BISHOP_POS, W_BISHOP_BOARD)) == get_to_squares(W_BISHOP_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(W_KNIGHT_POS, W_KNIGHT_BOARD)) == get_to_squares(W_KNIGHT_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(W_PAWN_POS, W_PAWN_BOARD)) == get_to_squares(W_PAWN_ALL_MOVES)); } TEST_CASE("Test all moves for white in edge cases.", "[get_all_moves][white]"){ - CHECK(get_all_moves(W_KNIGHT_SIDE1_POS, W_KNIGHT_SIDE1_BOARD) == W_KNIGHT_SIDE1_ALL_MOVES); - CHECK(get_all_moves(W_KING_SIDE1_POS, W_KING_SIDE1_BOARD) == W_KING_SIDE1_ALL_MOVES); - CHECK(get_all_moves(W_PAWN_SIDE1_POS, W_PAWN_SIDE1_BOARD) == W_PAWN_SIDE1_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(W_KNIGHT_SIDE1_POS, W_KNIGHT_SIDE1_BOARD)) == get_to_squares(W_KNIGHT_SIDE1_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(W_KING_SIDE1_POS, W_KING_SIDE1_BOARD)) == get_to_squares(W_KING_SIDE1_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(W_PAWN_SIDE1_POS, W_PAWN_SIDE1_BOARD)) == get_to_squares(W_PAWN_SIDE1_ALL_MOVES)); } TEST_CASE("Test all moves for black in edge cases.", "[get_all_moves][black]"){ - CHECK(get_all_moves(B_KNIGHT_SIDE1_POS, B_KNIGHT_SIDE1_BOARD) == B_KNIGHT_SIDE1_ALL_MOVES); - CHECK(get_all_moves(B_KING_SIDE1_POS, B_KING_SIDE1_BOARD) == B_KING_SIDE1_ALL_MOVES); - CHECK(get_all_moves(B_PAWN_SIDE1_POS, B_PAWN_SIDE1_BOARD) == B_PAWN_SIDE1_ALL_MOVES); + CHECK(get_to_squares(get_all_moves(B_KNIGHT_SIDE1_POS, B_KNIGHT_SIDE1_BOARD)) == get_to_squares(B_KNIGHT_SIDE1_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(B_KING_SIDE1_POS, B_KING_SIDE1_BOARD)) == get_to_squares(B_KING_SIDE1_ALL_MOVES)); + CHECK(get_to_squares(get_all_moves(B_PAWN_SIDE1_POS, B_PAWN_SIDE1_BOARD)) == get_to_squares(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); + CHECK(get_to_squares(get_all_moves(ROOK_CHECK_TEST_POS, ROOK_CHECK_TEST_BOARD)) == get_to_squares(ROOK_CHECK_TEST_MOVES)); + CHECK(get_to_squares(get_all_moves(PAWN_CHECK_TEST_POS, PAWN_CHECK_TEST_BOARD)) == get_to_squares(PAWN_CHECK_TEST_MOVES)); + CHECK(get_to_squares(get_all_moves(PAWN_DIAG_TEST1_POS, PAWN_DIAG_TEST1_BOARD)) == get_to_squares(PAWN_DIAG_TEST1_MOVES)); } TEST_CASE("Tests for en pessant squares.", "[get_all_moves]"){ - CHECK(get_all_moves(EN_PASSANT_TEST_POS, EN_PASSANT_TEST_BOARD, false, EN_PASSANT_SQUARE) == EN_PASSANT_TEST_MOVES); - CHECK(get_all_moves(NO_EN_PASSANT_TEST_POS, NO_EN_PASSANT_TEST_BOARD) == NO_EN_PASSANT_TEST_MOVES); + CHECK(get_to_squares(get_all_moves(EN_PASSANT_TEST_POS, EN_PASSANT_TEST_BOARD, false, EN_PASSANT_SQUARE)) == get_to_squares(EN_PASSANT_TEST_MOVES)); + CHECK(get_to_squares(get_all_moves(NO_EN_PASSANT_TEST_POS, NO_EN_PASSANT_TEST_BOARD)) == get_to_squares(NO_EN_PASSANT_TEST_MOVES)); } diff --git a/tests/bitwise_tests.cpp b/tests/bitwise_tests.cpp index a6f9f3f..030dca4 100644 --- a/tests/bitwise_tests.cpp +++ b/tests/bitwise_tests.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include "catch.hpp" diff --git a/tests/custom_bitwise_printing.cpp b/tests/custom_bitwise_printing.cpp new file mode 100644 index 0000000..60831d4 --- /dev/null +++ b/tests/custom_bitwise_printing.cpp @@ -0,0 +1,95 @@ +#include "catch.hpp" +#include +#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 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::unordered_set 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 = 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(); + } + }; + +} + diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 5df4808..c35fac4 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -1,55 +1,63 @@ #include -#include +#include /// This is for possible moves on a default board -const std::unordered_set DEFAULT_B_A_PAWN_POSSIBLE_MOVES = { +const std::unordered_set DEFAULT_B_A_PAWN_POSSIBLE_MOVES = { A6, A5 }; -const std::unordered_set DEFAULT_W_A_PAWN_POSSIBLE_MOVES = { +const std::unordered_set DEFAULT_W_A_PAWN_POSSIBLE_MOVES = { A3, A4 }; -const std::unordered_set DEFAULT_W_R_KNIGHT_POSSIBLE_MOVES = { +const std::unordered_set DEFAULT_W_R_KNIGHT_POSSIBLE_MOVES = { H3, F3 }; // EMPTY -const std::unordered_set DEFAULT_W_R_ROOK_POSSIBLE_MOVES = {}; +const std::unordered_set DEFAULT_W_R_ROOK_POSSIBLE_MOVES = {}; -const std::vector B_PAWNS_SQUARES = { +const std::unordered_set B_PAWNS_SQUARES = { A7, B7, C7, D7, E7, F7, G7, H7 }; // END of default selections -const Position KNIGHT_BLOCKED1_POS = B8; -const std::array KNIGHT_BLOCKED1_BOARD = { - NONE, B_KNIGHT, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, B_PAWN, 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, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE +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::unordered_set KNIGHT_BLOCKED1_MOVES = { +const std::unordered_set KNIGHT_BLOCKED1_MOVES = { A6, C6 }; -const Position BISHOP_BLOCKED1_POS = D5; -const std::array BISHOP_BLOCKED1_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, B_QUEEN, NONE , B_PAWN , NONE, W_KING, NONE, NONE, - NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE, - NONE, NONE , W_ROOK, W_BISHOP, 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 +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::unordered_set BISHOP_BLOCKED1_MOVES = { +const std::unordered_set BISHOP_BLOCKED1_MOVES = { B7, C6,E6, C4,E4, @@ -57,101 +65,125 @@ const std::unordered_set BISHOP_BLOCKED1_MOVES = { A2 }; // Should NOT include B2 (black queen) as it is obstructed by the bishop on D5 -const std::unordered_set BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING = { +const std::unordered_set BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING = { D5 }; -const Position BISHOP_BLOCKED1_KING_POS = F3; +const int BISHOP_BLOCKED1_KING_POS = F3; -const Position ROOK_BLOCKED1_POS = B7; -const std::array ROOK_BLOCKED1_BOARD = { - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, W_ROOK, NONE , B_PAWN , NONE, B_KING, 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, W_KING , NONE , NONE , NONE, NONE, NONE, NONE, - NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE, - NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE +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::unordered_set ROOK_BLOCKED1_MOVES = { +const std::unordered_set ROOK_BLOCKED1_MOVES = { B8, A7, C7, D7, 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 = { +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::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 = { +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, NONE, 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::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}; +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::unordered_set PAWN_CHECK_TEST_MOVES = {E6, E5}; // These boards tests for en pessent squares. -const Position EN_PASSANT_SQUARE = E6; -const Position EN_PASSANT_TEST_POS = D5; -const std::array EN_PASSANT_TEST_BOARD = { - B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, - B_PAWN, B_PAWN, B_PAWN, NONE, B_PAWN, B_PAWN, B_PAWN, B_PAWN, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, W_PAWN, B_PAWN, 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, NONE, W_PAWN, W_PAWN, W_PAWN, W_PAWN, - W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK -}; -const std::unordered_set EN_PASSANT_TEST_MOVES = { +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::unordered_set EN_PASSANT_TEST_MOVES = { E6, D6 }; -const Position NO_EN_PASSANT_TEST_POS = D5; -const std::array NO_EN_PASSANT_TEST_BOARD = { - B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, - B_PAWN, B_PAWN, B_PAWN, NONE, B_PAWN, B_PAWN, B_PAWN, B_PAWN, - NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, - NONE, NONE, NONE, W_PAWN, B_PAWN, 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, NONE, W_PAWN, W_PAWN, W_PAWN, W_PAWN, - W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK -}; -const std::unordered_set NO_EN_PASSANT_TEST_MOVES = {D6}; +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::unordered_set NO_EN_PASSANT_TEST_MOVES = {D6}; From f18240cf5aa9a328bd1466a6d30ea1a0c7a33259 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sat, 20 Apr 2019 22:06:11 +0000 Subject: [PATCH 33/81] Fix names, remove bitwise_ prefix --- src/all_moves_bitwise_functions.cpp | 183 --------------------- src/all_moves_functions.cpp | 133 ++++++++++----- src/bitwise.cpp | 18 --- src/bitwise.h | 2 +- src/bitwise_constants.h | 95 ----------- src/bitwise_functions.cpp | 234 --------------------------- src/bitwise_functions.h | 61 ------- src/constants.h | 145 +++++++++-------- src/functions.cpp | 132 ++++++++------- src/functions.h | 32 ++-- tests/B_test_boards.h | 2 +- tests/Makefile | 13 +- tests/W_test_boards.h | 2 +- tests/custom_bitwise_printing.cpp | 95 ----------- tests/custom_printing.cpp | 10 +- tests/{bitwise_main.cpp => main.cpp} | 3 +- tests/tests_main.cpp | 157 ------------------ tests/valid_moves.h | 2 +- 18 files changed, 271 insertions(+), 1048 deletions(-) delete mode 100644 src/all_moves_bitwise_functions.cpp delete mode 100644 src/bitwise.cpp delete mode 100644 src/bitwise_constants.h delete mode 100644 src/bitwise_functions.cpp delete mode 100644 src/bitwise_functions.h delete mode 100644 tests/custom_bitwise_printing.cpp rename tests/{bitwise_main.cpp => main.cpp} (99%) delete mode 100644 tests/tests_main.cpp diff --git a/src/all_moves_bitwise_functions.cpp b/src/all_moves_bitwise_functions.cpp deleted file mode 100644 index cd6cd70..0000000 --- a/src/all_moves_bitwise_functions.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include "bitwise_constants.h" -#include -#include -#include - -const std::array ROOK_PIECE_OFFSETS = {-1, -10, 1, 10}; -const std::array BISHOP_PIECE_OFFSETS = {-11, -9, 9, 11}; -const std::array KNIGHT_PIECE_OFFSETS = {-12, -21, -19, -8, 8, 12, 19, 21}; -const std::array KING_PIECE_OFFSETS = {-11, -10, -9, -1, 1, 9, 10, 11}; - - -inline Position _pair_to_pos_unsafe(int x, int y){ - return static_cast(std::abs(y-7)*8 + x); -} - -void _push_if_valid_pos(int pos, std::unordered_set *pns){ - if (is_valid_position(pos)){ - pns->insert(pos); - } -} - - -// This function returns true if the color of the piece on tile (x,y) is the Color c -bool _xy_is_color(int pos, 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, std::unordered_set *pns, 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->insert(pos); - *is_not_blocked = false; - } else { - pns->insert(pos); - } - } - } -} -// 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, std::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite){ - if (_xy_is_color(pos, board, color_of_piece)){ - return; - } else { - pns->insert(pos); - } -} - -// 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, std::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite, int en_passant){ - if (is_valid_position(pos) && (_xy_is_color(pos, board, color_of_opposite) || - pos == en_passant)){ - pns->insert(pos); - } -} -// This is a specialized functions for the pawn's inability to take going forward. -// Notice the lack of insertion where there usually is when (x,y) is a different color. -void _pawn_add_if_not_blocked(int pos, std::unordered_set *pns, 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)){ - *is_not_blocked = false; - } else { - pns->insert(pos); - } - } - } -} - - -void _get_all_moves_rook(int pos, std::unordered_set *pns, std::array* board, Color pc, Color rc){ - for (int rk_off : ROOK_PIECE_OFFSETS){ - bool* not_blocked = new bool(true); - for (int offset=1; offset<8; offset++){ - _add_if_not_blocked(pos+(rk_off*offset), pns, board, pc, rc, not_blocked); - } - } - - /* - bool* not_blocked_addx = new bool(true); - bool* not_blocked_minx = new bool(true); - bool* not_blocked_addy = new bool(true); - bool* not_blocked_miny = new bool(true); - for (int offset=1; offset<8; offset++){ - _add_if_not_blocked(x+offset, y, pns, board, pc, rc, not_blocked_addx); - _add_if_not_blocked(x, y+offset, pns, board, pc, rc, not_blocked_addy); - _add_if_not_blocked(x-offset, y, pns, board, pc, rc, not_blocked_minx); - _add_if_not_blocked(x, y-offset, pns, board, pc, rc, not_blocked_miny); - } - */ -} - -void _get_all_moves_bishop(int pos, std::unordered_set *pns, std::array* board, Color pc, Color rc){ - for (int bs_off : BISHOP_PIECE_OFFSETS){ - bool* not_blocked = new bool(true); - for (int offset=1; offset<8; offset++){ - _add_if_not_blocked(pos+(bs_off*offset), pns, board, pc, rc, not_blocked); - } - } - /* - bool* not_blocked_addx_addy = new bool(true); - bool* not_blocked_addx_miny = new bool(true); - bool* not_blocked_minx_addy = new bool(true); - bool* not_blocked_minx_miny = new bool(true); - - for (int offset=1; offset<8; offset++){ - int xpoff = x+offset; - int ypoff = y+offset; - int xnoff = x-offset; - int ynoff = y-offset; - _add_if_not_blocked(xpoff, ypoff, pns, board, pc, rc, not_blocked_addx_addy); - _add_if_not_blocked(xpoff, ynoff, pns, board, pc, rc, not_blocked_addx_miny); - _add_if_not_blocked(xnoff, ypoff, pns, board, pc, rc, not_blocked_minx_addy); - _add_if_not_blocked(xnoff, ynoff, pns, board, pc, rc, not_blocked_minx_miny); - } - */ -} -void _get_all_moves_knight(int pos, std::unordered_set *pns, std::array* board, Color pc, Color rc){ - for (int kn_off : KNIGHT_PIECE_OFFSETS){ - bool* not_blocked = new bool(true); - _add_if_not_blocked(pos+kn_off, pns, board, pc, rc); - } - /* - for (int xo=1;xo<=2;xo++){ - int yo=(xo==1)?2:1; - _add_if_not_blocked(x+xo, y+yo, pns, board, pc, rc); - _add_if_not_blocked(x-xo, y+yo, pns, board, pc, rc); - _add_if_not_blocked(x+xo, y-yo, pns, board, pc, rc); - _add_if_not_blocked(x-xo, y-yo, pns, board, pc, rc); - } - */ -} - -void _get_all_moves_king(int pos, std::unordered_set *pns, std::array* board, Color pc, Color rc){ - for (int kn_off : KING_PIECE_OFFSETS){ - bool* not_blocked = new bool(true); - _add_if_not_blocked(pos+kn_off, pns, board, pc, rc); - } - - - /* - _add_if_not_blocked(x+1, y+1, pns, board, pc, rc); - _add_if_not_blocked(x+1, y-1, pns, board, pc, rc); - _add_if_not_blocked(x-1, y+1, pns, board, pc, rc); - _add_if_not_blocked(x-1, y-1, pns, board, pc, rc); - _add_if_not_blocked(x, y+1, pns, board, pc, rc); - _add_if_not_blocked(x, y-1, pns, board, pc, rc); - _add_if_not_blocked(x+1, y, pns, board, pc, rc); - _add_if_not_blocked(x-1, y, pns, board, pc, rc); - */ -} - -void _get_all_moves_pawn(int pos, std::unordered_set *pns, 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; - - bool *free_to_double_move = new bool(true); - _pawn_add_if_not_blocked(pos+offset1, pns, board, pc, rc, free_to_double_move); - if (get_rank(pos) == default_pawn_rank){ // If on second/seventh rank - _pawn_add_if_not_blocked(pos+offset2, pns, board, pc, rc, free_to_double_move); - } - // 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, pns, board, pc, rc, en_passant); - _pawn_diag_add_if_not_blocked(pos+offset1-1, pns, board, pc, rc, en_passant); -} diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index 1bc1ff3..c0ff52a 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -1,21 +1,28 @@ #include "constants.h" #include +#include #include +const std::array ROOK_PIECE_OFFSETS = {-1, -10, 1, 10}; +const std::array BISHOP_PIECE_OFFSETS = {-11, -9, 9, 11}; +const std::array KNIGHT_PIECE_OFFSETS = {-12, -21, -19, -8, 8, 12, 19, 21}; +const std::array KING_PIECE_OFFSETS = {-11, -10, -9, -1, 1, 9, 10, 11}; + + inline Position _pair_to_pos_unsafe(int x, int y){ return static_cast(std::abs(y-7)*8 + x); } -void _push_if_valid_pos(int x, int y, std::unordered_set *pns){ - if (is_valid_position(x, y)){ - pns->insert(_pair_to_pos_unsafe(x, y)); +void _push_if_valid_pos(int pos, std::unordered_set *pns){ + if (is_valid_position(pos)){ + pns->insert(pos); } } // This function returns true if the color of the piece on tile (x,y) is the Color c -bool _xy_is_color(int x, int y, std::array board, Color c){ - return c==Color::WHITE ? is_white(board[_pair_to_pos_unsafe(x, y)]) : is_black(board[_pair_to_pos_unsafe(x, y)]); +bool _xy_is_color(int pos, std::array* board, Color c){ + return c==Color::WHITE ? is_white((*board)[pos]) : is_black((*board)[pos]); } Color _rev_color(Color c){ @@ -23,53 +30,67 @@ Color _rev_color(Color c){ } // 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 x, int y, std::unordered_set *pns, std::array board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){ - if (*is_not_blocked && is_valid_position(x, y)){ - if (_xy_is_color(x, y, board, color_of_piece)){ - *is_not_blocked = false; - } else if (_xy_is_color(x, y, board, color_of_opposite)){ - pns->insert(_pair_to_pos_unsafe(x, y)); +void _add_if_not_blocked(int pos, std::unordered_set *pns, 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 { - pns->insert(_pair_to_pos_unsafe(x, y)); + if (_xy_is_color(pos, board, color_of_piece)){ + *is_not_blocked = false; + } else if (_xy_is_color(pos, board, color_of_opposite)){ + pns->insert(pos); + *is_not_blocked = false; + } else { + pns->insert(pos); + } } } } // 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 x, int y, std::unordered_set *pns, std::array board, Color color_of_piece, Color color_of_opposite){ - if (is_valid_position(x, y)){ - if (_xy_is_color(x, y, board, color_of_piece)){ - return; - } else { - pns->insert(_pair_to_pos_unsafe(x, y)); - } - } +void _add_if_not_blocked(int pos, std::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite){ + if (_xy_is_color(pos, board, color_of_piece)){ + return; + } else { + pns->insert(pos); + } } // 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 x, int y, std::unordered_set *pns, std::array board, Color color_of_piece, Color color_of_opposite, Position en_passant){ - if (is_valid_position(x, y) && (_xy_is_color(x, y, board, color_of_opposite) || - _pair_to_pos_unsafe(x, y) == en_passant)){ - pns->insert(_pair_to_pos_unsafe(x, y)); +void _pawn_diag_add_if_not_blocked(int pos, std::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite, int en_passant){ + if (is_valid_position(pos) && (_xy_is_color(pos, board, color_of_opposite) || + pos == en_passant)){ + pns->insert(pos); } } // This is a specialized functions for the pawn's inability to take going forward. // Notice the lack of insertion where there usually is when (x,y) is a different color. -void _pawn_add_if_not_blocked(int x, int y, std::unordered_set *pns, std::array board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){ - if (*is_not_blocked && is_valid_position(x, y)){ - if (_xy_is_color(x, y, board, color_of_piece)){ - *is_not_blocked = false; - } else if (_xy_is_color(x, y, board, color_of_opposite)){ +void _pawn_add_if_not_blocked(int pos, std::unordered_set *pns, 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 { - pns->insert(_pair_to_pos_unsafe(x, y)); + if (_xy_is_color(pos, board, color_of_piece)){ + *is_not_blocked = false; + } else if (_xy_is_color(pos, board, color_of_opposite)){ + *is_not_blocked = false; + } else { + pns->insert(pos); + } } } } -void _get_all_moves_rook(int x, int y, std::unordered_set *pns, std::array board, Color pc, Color rc){ +void _get_all_moves_rook(int pos, std::unordered_set *pns, std::array* board, Color pc, Color rc){ + for (int rk_off : ROOK_PIECE_OFFSETS){ + bool* not_blocked = new bool(true); + for (int offset=1; offset<8; offset++){ + _add_if_not_blocked(pos+(rk_off*offset), pns, board, pc, rc, not_blocked); + } + } + + /* bool* not_blocked_addx = new bool(true); bool* not_blocked_minx = new bool(true); bool* not_blocked_addy = new bool(true); @@ -80,9 +101,17 @@ void _get_all_moves_rook(int x, int y, std::unordered_set *pns, std::a _add_if_not_blocked(x-offset, y, pns, board, pc, rc, not_blocked_minx); _add_if_not_blocked(x, y-offset, pns, board, pc, rc, not_blocked_miny); } + */ } -void _get_all_moves_bishop(int x, int y, std::unordered_set *pns, std::array board, Color pc, Color rc){ +void _get_all_moves_bishop(int pos, std::unordered_set *pns, std::array* board, Color pc, Color rc){ + for (int bs_off : BISHOP_PIECE_OFFSETS){ + bool* not_blocked = new bool(true); + for (int offset=1; offset<8; offset++){ + _add_if_not_blocked(pos+(bs_off*offset), pns, board, pc, rc, not_blocked); + } + } + /* bool* not_blocked_addx_addy = new bool(true); bool* not_blocked_addx_miny = new bool(true); bool* not_blocked_minx_addy = new bool(true); @@ -98,9 +127,14 @@ void _get_all_moves_bishop(int x, int y, std::unordered_set *pns, std: _add_if_not_blocked(xnoff, ypoff, pns, board, pc, rc, not_blocked_minx_addy); _add_if_not_blocked(xnoff, ynoff, pns, board, pc, rc, not_blocked_minx_miny); } - + */ } -void _get_all_moves_knight(int x, int y, std::unordered_set *pns, std::array board, Color pc, Color rc){ +void _get_all_moves_knight(int pos, std::unordered_set *pns, std::array* board, Color pc, Color rc){ + for (int kn_off : KNIGHT_PIECE_OFFSETS){ + bool* not_blocked = new bool(true); + _add_if_not_blocked(pos+kn_off, pns, board, pc, rc); + } + /* for (int xo=1;xo<=2;xo++){ int yo=(xo==1)?2:1; _add_if_not_blocked(x+xo, y+yo, pns, board, pc, rc); @@ -108,9 +142,17 @@ void _get_all_moves_knight(int x, int y, std::unordered_set *pns, std: _add_if_not_blocked(x+xo, y-yo, pns, board, pc, rc); _add_if_not_blocked(x-xo, y-yo, pns, board, pc, rc); } + */ } -void _get_all_moves_king(int x, int y, std::unordered_set *pns, std::array board, Color pc, Color rc){ +void _get_all_moves_king(int pos, std::unordered_set *pns, std::array* board, Color pc, Color rc){ + for (int kn_off : KING_PIECE_OFFSETS){ + bool* not_blocked = new bool(true); + _add_if_not_blocked(pos+kn_off, pns, board, pc, rc); + } + + + /* _add_if_not_blocked(x+1, y+1, pns, board, pc, rc); _add_if_not_blocked(x+1, y-1, pns, board, pc, rc); _add_if_not_blocked(x-1, y+1, pns, board, pc, rc); @@ -119,20 +161,23 @@ void _get_all_moves_king(int x, int y, std::unordered_set *pns, std::a _add_if_not_blocked(x, y-1, pns, board, pc, rc); _add_if_not_blocked(x+1, y, pns, board, pc, rc); _add_if_not_blocked(x-1, y, pns, board, pc, rc); + */ } -void _get_all_moves_pawn(int x, int y, std::unordered_set *pns, std::array board, Color pc, Color rc, Position en_passant){ +void _get_all_moves_pawn(int pos, std::unordered_set *pns, 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?2:-2; - int offset1 = pc==Color::WHITE?1:-1; - int default_pawn_rank = pc==Color::WHITE?1:6; + 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; bool *free_to_double_move = new bool(true); - _pawn_add_if_not_blocked(x, y+offset1, pns, board, pc, rc, free_to_double_move); - if (y == default_pawn_rank){ // If on second/seventh rank - _pawn_add_if_not_blocked(x, y+offset2, pns, board, pc, rc, free_to_double_move); + _pawn_add_if_not_blocked(pos+offset1, pns, board, pc, rc, free_to_double_move); + if (get_rank(pos) == default_pawn_rank){ // If on second/seventh rank + _pawn_add_if_not_blocked(pos+offset2, pns, board, pc, rc, free_to_double_move); } - _pawn_diag_add_if_not_blocked(x+1, y+offset1, pns, board, pc, rc, en_passant); - _pawn_diag_add_if_not_blocked(x-1, y+offset1, pns, board, pc, rc, en_passant); + // 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, pns, board, pc, rc, en_passant); + _pawn_diag_add_if_not_blocked(pos+offset1-1, pns, board, pc, rc, en_passant); } diff --git a/src/bitwise.cpp b/src/bitwise.cpp deleted file mode 100644 index 9063bf9..0000000 --- a/src/bitwise.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "bitwise.h" - -// Get first 6 bits of int -// Get bits 7-12 of int -// Get bits 13-16 of int -// Get bits 17-20 of int -// Get 21st bit of int -// Get 22nd bit of int -// Get 23rd bit of int - -// Get last 3 bits of number (the rank). -// Techincally this gets all bits 4-32/64 but I'm just assuming it won't be larger than 63 before the shift. - -// Get first 3 bits of number -// if the position has a 7th bit we know it's off the board. - -// it indicates that is it off the board. -// ASSUMING position <= 128 but if it was that big that'd be weird. diff --git a/src/bitwise.h b/src/bitwise.h index 611e7df..358bae8 100644 --- a/src/bitwise.h +++ b/src/bitwise.h @@ -2,7 +2,7 @@ #define BITWISE_H #include -#include "bitwise_constants.h" +#include "constants.h" // Using macros for ease of use, can also use functons, but I don't see the point. diff --git a/src/bitwise_constants.h b/src/bitwise_constants.h deleted file mode 100644 index c51be45..0000000 --- a/src/bitwise_constants.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef BT_CONST_H -#define BT_CONST_H - -#include -#include -#include - -enum Color { - NO_COLOR, - WHITE, - BLACK -}; - -enum PieceType { - INV=-1, - NONE, - B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING, - W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING -}; -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}; -} -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 -}; - -// Access with POSITION_STRING[Position] -const std::vector 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" -}; - -enum Rank{ - RANK1, - RANK2, - RANK3, - RANK4, - RANK5, - RANK6, - RANK7, - RANK8 -}; - -enum File { - FILE1, - FILE2, - FILE3, - FILE4, - FILE5, - FILE6, - FILE7, - FILE8 -}; - -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 CHESS_CHARS = { - ' ', - 'P', 'N', 'B', 'R', 'Q', 'K', - 'p', 'n', 'b', 'r', 'q', 'k' -}; -#endif - diff --git a/src/bitwise_functions.cpp b/src/bitwise_functions.cpp deleted file mode 100644 index 6efd637..0000000 --- a/src/bitwise_functions.cpp +++ /dev/null @@ -1,234 +0,0 @@ -#include "bitwise.h" -#include "bitwise_functions.h" -#include "all_moves_bitwise_functions.cpp" -#include -#include -#include -#include -#include -#include -#include - -// TODO implement functions.h functions. -// NOTE tests will NOT run unless you implement these functions. - - -std::pair pos_to_pair(Position pn){ - int x,y = 0; - for (x = pn; x >= 8; x = x-8){ - ++y; - } - return std::make_pair(x, std::abs(y-7)); -} - -// 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."); - } - 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()); - } -} -Position pair_to_pos(int x, int y){ - return pair_to_pos(std::make_pair(x, y)); -} - -bool is_valid_position(std::pair pos){ - return (pos.first < 8 && pos.second < 8 && - pos.first >= 0 && pos.second >=0); -} -bool is_valid_position(int x, int y){ - return (x < 8 && x >= 0 && - y < 8 && y >= 0); -} - -bool is_white(PieceType pt){ - for (auto pn : Pieces::WHITE){ - if (pn == pt) return true; - } - return false; -} -bool is_black(PieceType pt){ - for (auto pn : Pieces::BLACK){ - if (pn == pt) return true; - } - return false; -} - -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 x, int y, std::array const *board){ - return get_color((*board)[pair_to_pos(x, y)]); -} -Color get_color(Position pn, std::array const *board){ - return get_color((*board)[pn]); -} - -Color rev_color(Color c){ - if (c==Color::NO_COLOR) return Color::NO_COLOR; - return c==Color::WHITE?Color::BLACK:Color::WHITE; -} - -std::unordered_set get_possible_movers(Position pn, std::array board){ - std::unordered_set pns = {Position::A1}; - return pns; -} - -std::unordered_set get_possible_moves(Position pn, std::array board){ - std::unordered_set pns = {Position::A1}; - get_all_moves(pn, &board, &pns); - return pns; -} - -int get_pos_of(PieceType pt, std::array const *board){ - for (int pn = Position::A8; pn!=Position::H1; pn++){ - if ((*board)[pn] == pt){ - return pn; - } - } - return Position::NA; -} - -std::unordered_set get_poss_of(PieceType pt, std::array const *board){ - std::unordered_set results; - for (int pn = Position::A8; pn!=Position::H1; pn++){ - if ((*board)[pn] == pt){ - results.insert(pn); - } - } - return results; -} - -void get_poss_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)); - } - } -} - -//TODO: Make faster by running from king squar eonly, instead of running on every piece of opposite team. -void filter_checked_moves(int pos, PieceType pt, std::array *board, std::unordered_set *pns){ - PieceType my_king = is_white(pt)?PieceType::W_KING:PieceType::B_KING; - int my_king_pos = get_pos_of(my_king, board); - int attackers = 0; - for (auto p_pn= pns->begin(); p_pn!=pns->end();){ - // Make move - int move_int = pos + (*p_pn >> 7); - std::array moved_board = dumb_move(move_int, *board); - // Get all piecetypes of other team - std::array other_team = is_white(pt)?Pieces::BLACK:Pieces::WHITE; - bool checks_king = false; - // go through each piece of other team - for (PieceType other_p : other_team) { - checks_king = false; - // For every place the piecetype is - // NEW CODE -// for (Position psn : get_all_moves(my_king_pos, moved_board, false)){ -// -// } - // \NEW CODE - std::vector psns; - get_poss_of(other_p, &moved_board, &psns); - for (auto psn : psns){ - std::unordered_set other_moves; - get_all_moves(psn, &moved_board, &other_moves, false); - // for every position the piece can mvoe to - for (int cp : other_moves){ - if (get_to_sq(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; - } - } -} - -void get_all_moves(int pos, std::array* board, std::unordered_set* moves, bool recursive, int en_passant){ - PieceType pt = (*board)[pos]; - 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_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_rook(pos, moves, board, color_of_piece, color_of_opponent); - break; - case PieceType::B_BISHOP: - case PieceType::W_BISHOP: - _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_knight(pos, moves, board, color_of_piece, color_of_opponent); - break; - case PieceType::B_KING: - case PieceType::W_KING: - _get_all_moves_king(pos, moves, board, color_of_piece, color_of_opponent); - 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; - } - if (recursive){ - filter_checked_moves(pos, pt, board, moves); - } -} - -std::unordered_set get_all_moves(int pos, std::array board, bool recursive, int en_passant){ - std::unordered_set moves; - get_all_moves(pos, &board, &moves, recursive, en_passant); - return moves; -} - -std::array dumb_move(int move, std::array board){ - int from = get_from_sq(move); - int to = get_to_sq(move); - PieceType piece = board[from]; - board[to] = piece; - board[from] = PieceType::NONE; - return board; -} - -std::unordered_set get_to_squares(std::unordered_set moves){ - std::unordered_set to_squares; - for (int move : moves){ - to_squares.insert(get_to_sq(move)); - } - return to_squares; -} -std::unordered_set get_from_squared(std::unordered_set moves){ - std::unordered_set from_squares; - return from_squares; -} diff --git a/src/bitwise_functions.h b/src/bitwise_functions.h deleted file mode 100644 index 1437f90..0000000 --- a/src/bitwise_functions.h +++ /dev/null @@ -1,61 +0,0 @@ -#include "bitwise_constants.h" -#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); -Position pair_to_pos(int x, int y); - -// Returns a list of positions with PieceType pt -int get_pos_of(PieceType pt, std::array const *board); -std::unordered_set get_poss_of(PieceType pt, std::array const *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); -bool is_valid_position(std::pair pos); -bool is_valid_position(int x, int y); - -// Checks if given piece matches a certain color. -bool is_white(PieceType pt); -bool is_black(PieceType pt); - -Color get_color(int x, int y, std::array const *board); -Color get_color(Position pn, std::array const *board); -Color get_color(PieceType pt); -// NO_COLOR returns NO_COLOR -// WHITE returns BLACK -// BLACK returns WHITE -Color rev_color(Color c); - -// 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. -void get_possible_movers(Position pn, std::array *pt,std::unordered_set *moves); - -// Get all possible moved for piece in Position pn. -// This may require helper functions for each individual piece. -void get_possible_moves(Position pn, std::array *pt,std::unordered_set *moves); - -// This functions removes moves that put your own king in check. -void filter_checked_moves(int pos, std::array *board, std::unordered_set *moves); - -// Get all moves for piece in Position pn. -void get_all_moves(int pos, std::array *pt,std::unordered_set *moves, bool recursive=true, int en_passant=Position::NA); -std::unordered_set get_all_moves(int pos, std::array board, bool recursive=true, int en_passant=Position::NA); - -// Dumb function to do board moves. -// Does not check if move is valid, just does it. -std::array dumb_move(int move, std::array board); - -// Allow the developer to get only certain pieces of the part of a move in a list. -// This will return a vector (or unordered_set) of elements with only a certain part of the move revealed bit bit-switching. -std::unordered_set get_from_squares(std::unordered_set moves); -std::unordered_set get_to_squares(std::unordered_set moves); - diff --git a/src/constants.h b/src/constants.h index 84ead3f..c51be45 100644 --- a/src/constants.h +++ b/src/constants.h @@ -1,88 +1,95 @@ -#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, + WHITE, + BLACK +}; -// 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 }; - -namespace Pieces { - const std::array BLACK = {B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING}; +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}; } - -enum Color { - NO_COLOR, BLACK, WHITE -}; - -// 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' -}; - -// 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, NA +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" + "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{ + RANK1, + RANK2, + RANK3, + RANK4, + RANK5, + RANK6, + RANK7, + RANK8 }; +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 +}; -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' +}; #endif + diff --git a/src/functions.cpp b/src/functions.cpp index 0b4aea9..11266c5 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -1,3 +1,4 @@ +#include "bitwise.h" #include "functions.h" #include "all_moves_functions.cpp" #include @@ -11,15 +12,6 @@ // 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; @@ -48,9 +40,6 @@ Position pair_to_pos(int x, int y){ return pair_to_pos(std::make_pair(x, y)); } -bool is_valid_position(int pos){ - return (pos >= 0 && pos < 64); -} bool is_valid_position(std::pair pos){ return (pos.first < 8 && pos.second < 8 && pos.first >= 0 && pos.second >=0); @@ -79,11 +68,11 @@ Color get_color(PieceType pt){ return Color::NO_COLOR; } -Color get_color(int x, int y, std::array board){ - return get_color(board[pair_to_pos(x, y)]); +Color get_color(int x, int y, std::array const *board){ + return get_color((*board)[pair_to_pos(x, y)]); } -Color get_color(Position pn, std::array board){ - return get_color(board[pn]); +Color get_color(Position pn, std::array const *board){ + return get_color((*board)[pn]); } Color rev_color(Color c){ @@ -91,35 +80,53 @@ Color rev_color(Color c){ return c==Color::WHITE?Color::BLACK:Color::WHITE; } -std::unordered_set get_possible_movers(Position pn, std::array board){ - std::unordered_set pns = {Position::A1}; +std::unordered_set get_possible_movers(Position pn, std::array board){ + std::unordered_set pns = {Position::A1}; return pns; } -std::unordered_set get_possible_moves(Position pn, std::array board){ - std::unordered_set pns = {Position::A1}; +std::unordered_set get_possible_moves(Position pn, std::array board){ + std::unordered_set pns = {Position::A1}; + get_all_moves(pn, &board, &pns); + return pns; +} - return get_all_moves(pn, board); +int get_pos_of(PieceType pt, std::array const *board){ + for (int pn = Position::A8; pn!=Position::H1; pn++){ + if ((*board)[pn] == pt){ + return pn; + } + } + return Position::NA; } -std::unordered_set get_all_moves_bitwise(Position pn, std::array board, bool recursive, Position en_passant){ - +std::unordered_set get_poss_of(PieceType pt, std::array const *board){ + std::unordered_set results; + for (int pn = Position::A8; pn!=Position::H1; pn++){ + if ((*board)[pn] == pt){ + results.insert(pn); + } + } + return results; +} + +void get_poss_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)); + } + } } //TODO: Make faster by running from king squar eonly, instead of running on every piece of opposite team. -void filter_checked_moves(Position pn, PieceType pt, std::array board, std::unordered_set *pns){ +void filter_checked_moves(int pos, PieceType pt, std::array *board, std::unordered_set *pns){ PieceType my_king = is_white(pt)?PieceType::W_KING:PieceType::B_KING; - std::vector king_poss = get_pos_of(my_king, board); - Position my_king_pos; - if (king_poss.empty()){ - return; - } else { - my_king_pos = king_poss[0]; - } + int my_king_pos = get_pos_of(my_king, board); int attackers = 0; for (auto p_pn= pns->begin(); p_pn!=pns->end();){ // Make move - std::array moved_board = dumb_move(pn, *p_pn, board); + int move_int = pos + (*p_pn >> 7); + std::array moved_board = dumb_move(move_int, *board); // Get all piecetypes of other team std::array other_team = is_white(pt)?Pieces::BLACK:Pieces::WHITE; bool checks_king = false; @@ -132,11 +139,14 @@ void filter_checked_moves(Position pn, PieceType pt, std::array b // // } // \NEW CODE - for (Position psn : get_pos_of(other_p, moved_board)){ - std::unordered_set other_moves = get_all_moves(psn, moved_board, false); + std::vector psns; + get_poss_of(other_p, &moved_board, &psns); + for (auto psn : psns){ + std::unordered_set other_moves; + get_all_moves(psn, &moved_board, &other_moves, false); // for every position the piece can mvoe to - for (Position cp : other_moves){ - if (cp == my_king_pos){ + for (int cp : other_moves){ + if (get_to_sq(cp) == my_king_pos){ checks_king = true; attackers++; break; @@ -158,59 +168,67 @@ void filter_checked_moves(Position pn, PieceType pt, std::array b } } -std::unordered_set get_all_moves(Position pn, std::array board, bool recursive, Position en_passant){ - PieceType pt = board[pn]; - std::unordered_set pns; - int x = pos_to_pair(pn).first; - int y = pos_to_pair(pn).second; +void get_all_moves(int pos, std::array* board, std::unordered_set* moves, bool recursive, int en_passant){ + PieceType pt = (*board)[pos]; 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_rook(x, y, &pns, board, color_of_piece, color_of_opponent); - _get_all_moves_bishop(x, y, &pns, 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_rook(x, y, &pns, 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_bishop(x, y, &pns, 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_knight(x, y, &pns, 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_king(x, y, &pns, board, color_of_piece, color_of_opponent); + _get_all_moves_king(pos, moves, board, color_of_piece, color_of_opponent); break; case PieceType::B_PAWN: case PieceType::W_PAWN: - _get_all_moves_pawn(x, y, &pns, board, color_of_piece, color_of_opponent, en_passant); + _get_all_moves_pawn(pos, moves, board, color_of_piece, color_of_opponent, en_passant); break; default: break; } if (recursive){ - filter_checked_moves(pn, pt, board, &pns); + filter_checked_moves(pos, pt, board, moves); } - 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::unordered_set get_all_moves(int pos, std::array board, bool recursive, int en_passant){ + std::unordered_set moves; + get_all_moves(pos, &board, &moves, recursive, en_passant); + return moves; } -std::array dumb_move(Position from, Position to, std::array board){ +std::array dumb_move(int move, std::array board){ + int from = get_from_sq(move); + int to = get_to_sq(move); PieceType piece = board[from]; board[to] = piece; board[from] = PieceType::NONE; return board; } + +std::unordered_set get_to_squares(std::unordered_set moves){ + std::unordered_set to_squares; + for (int move : moves){ + to_squares.insert(get_to_sq(move)); + } + return to_squares; +} +std::unordered_set get_from_squared(std::unordered_set moves){ + std::unordered_set from_squares; + return from_squares; +} diff --git a/src/functions.h b/src/functions.h index 77bb956..6557a89 100644 --- a/src/functions.h +++ b/src/functions.h @@ -10,7 +10,8 @@ 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); +int get_pos_of(PieceType pt, std::array const *board); +std::unordered_set get_poss_of(PieceType pt, std::array const *board); // Convert a Position number into a pair of x y coordiinates std::pair pos_to_pair(Position pn); @@ -25,8 +26,8 @@ bool is_valid_position(int x, int y); bool is_white(PieceType pt); bool is_black(PieceType pt); -Color get_color(int x, int y, std::array board); -Color get_color(Position pn, std::array board); +Color get_color(int x, int y, std::array const *board); +Color get_color(Position pn, std::array const *board); Color get_color(PieceType pt); // NO_COLOR returns NO_COLOR // WHITE returns BLACK @@ -36,18 +37,25 @@ Color rev_color(Color c); // 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::unordered_set get_possible_movers(Position pn, std::array pt); +void get_possible_movers(Position pn, std::array *pt,std::unordered_set *moves); // Get all possible moved for piece in Position pn. // This may require helper functions for each individual piece. -std::unordered_set get_possible_moves(Position pn, std::array pt); +void get_possible_moves(Position pn, std::array *pt,std::unordered_set *moves); -// Get all moves for piece in Position pn. -std::unordered_set get_all_moves(Position pn, std::array pt, bool recursive=true, Position en_pessant=Position::NA); -// 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); +// This functions removes moves that put your own king in check. +void filter_checked_moves(int pos, std::array *board, std::unordered_set *moves); + +// Get all moves for piece in Position pn. +void get_all_moves(int pos, std::array *pt,std::unordered_set *moves, bool recursive=true, int en_passant=Position::NA); +std::unordered_set get_all_moves(int pos, std::array board, bool recursive=true, int en_passant=Position::NA); // 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. +std::array dumb_move(int move, std::array board); + +// Allow the developer to get only certain pieces of the part of a move in a list. +// This will return a vector (or unordered_set) of elements with only a certain part of the move revealed bit bit-switching. +std::unordered_set get_from_squares(std::unordered_set moves); +std::unordered_set get_to_squares(std::unordered_set moves); + diff --git a/tests/B_test_boards.h b/tests/B_test_boards.h index f413b9b..d8eafb1 100644 --- a/tests/B_test_boards.h +++ b/tests/B_test_boards.h @@ -1,5 +1,5 @@ #include -#include +#include const int B_QUEEN_POS = E4; const std::array B_QUEEN_BOARD = { diff --git a/tests/Makefile b/tests/Makefile index 6458377..c67d884 100755 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,6 +1,4 @@ defualt: all.out -bitwise: bitwise.out -bitwise_functions: bitwise_main.out catch_main.o: g++ -w -c -o catch_main.o catch_main.cpp @@ -8,15 +6,6 @@ catch_main.o: custom_printing.o: g++ -w -I../src/ -c -o custom_printing.o custom_printing.cpp -custom_bitwise_printing.o: - g++ -w -I../src/ -c -o custom_bitwise_printing.o custom_bitwise_printing.cpp - -bitwise.out: catch_main.o - g++ -I../src/ -o bitwise.out ../src/bitwise.cpp catch_main.o bitwise_tests.cpp - -bitwise_main.out: catch_main.o custom_bitwise_printing.o - g++ -I../src/ -o bitwise_functions.out catch_main.o custom_bitwise_printing.o ../src/bitwise_functions.cpp bitwise_main.cpp - # TODO: Allw all.out to contain bitwise tests all.out: catch_main.o custom_printing.o - g++ -std=c++11 -ggdb -w -I../src/ -o all.out ../src/functions.cpp catch_main.o custom_printing.o tests_main.cpp + g++ -std=c++11 -ggdb -w -I../src/ -o all.out ../src/functions.cpp catch_main.o custom_printing.o main.cpp diff --git a/tests/W_test_boards.h b/tests/W_test_boards.h index ae545c2..21eb95e 100644 --- a/tests/W_test_boards.h +++ b/tests/W_test_boards.h @@ -1,5 +1,5 @@ #include -#include +#include const int W_QUEEN_POS = E4; const std::array W_QUEEN_BOARD = { diff --git a/tests/custom_bitwise_printing.cpp b/tests/custom_bitwise_printing.cpp deleted file mode 100644 index 60831d4..0000000 --- a/tests/custom_bitwise_printing.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include "catch.hpp" -#include -#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 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::unordered_set 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 = 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(); - } - }; - -} - diff --git a/tests/custom_printing.cpp b/tests/custom_printing.cpp index 854a957..e89962c 100644 --- a/tests/custom_printing.cpp +++ b/tests/custom_printing.cpp @@ -36,13 +36,13 @@ namespace Catch { }; // 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){ + 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; + 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; diff --git a/tests/bitwise_main.cpp b/tests/main.cpp similarity index 99% rename from tests/bitwise_main.cpp rename to tests/main.cpp index 55e0261..44d648b 100644 --- a/tests/bitwise_main.cpp +++ b/tests/main.cpp @@ -1,9 +1,8 @@ #include "catch.hpp" #include "test_boards.h" #include "valid_moves.h" -#include "custom_bitwise_printing.cpp" #include -#include +#include const std::array DUMB_MOVE_1 = { diff --git a/tests/tests_main.cpp b/tests/tests_main.cpp deleted file mode 100644 index 278e570..0000000 --- a/tests/tests_main.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include "catch.hpp" -#include "test_boards.h" -#include "valid_moves.h" -#include "custom_printing.cpp" -#include -#include - - -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 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); - CHECK(get_color(2, 1, DUMB_MOVE_1) == Color::WHITE); - 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 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]"){ - 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))); - - CHECK(pair_to_pos(2, 3) == Position::C4); - CHECK(pair_to_pos(7, 0) == Position::H1); - CHECK(pair_to_pos(0, 0) == Position::A1); - CHECK(pair_to_pos(7, 7) == Position::H8); - CHECK_THROWS(pair_to_pos(8, 2)); - CHECK_THROWS(pair_to_pos(-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 that invalid position ints return false", "[is_valid_position]"){ - CHECK(is_valid_position(0)); // 0=A8 - CHECK(is_valid_position(63)); // 63=H1 - CHECK_FALSE(is_valid_position(-1)); // -1 is out of bounds - CHECK_FALSE(is_valid_position(64)); // 64 is out of bounds - - CHECK(is_valid_position(std::make_pair(0, 0))); // 0-7,0-7 should be valid - CHECK(is_valid_position(std::make_pair(7, 7))); - CHECK_FALSE(is_valid_position(std::make_pair(-1, 5))); // should fail - CHECK_FALSE(is_valid_position(std::make_pair(5, 8))); // should fail - - CHECK(is_valid_position(0, 0)); // 0-7,0-7 should be valid - CHECK(is_valid_position(7, 7)); - CHECK_FALSE(is_valid_position(-1, 5)); // should fail - CHECK_FALSE(is_valid_position(5, 8)); // should fail -} - -TEST_CASE("Test what pieces may move where functon", "[get_possible_movers]"){ - std::unordered_set H1_possible_movers = {Position::H2, Position::G1}; - CHECK(get_possible_movers(BISHOP_BLOCKED1_KING_POS, BISHOP_BLOCKED1_BOARD) == BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING); - CHECK(get_possible_movers(Position::H3, DEFAULT_BOARD) == H1_possible_movers); -} - -TEST_CASE("Test where this piece may move to", "[get_possible_moves]"){ - CHECK(get_possible_moves(Position::G1, DEFAULT_BOARD) == DEFAULT_W_R_KNIGHT_POSSIBLE_MOVES); - CHECK(get_possible_moves(Position::A7, DEFAULT_BOARD) == DEFAULT_B_A_PAWN_POSSIBLE_MOVES); - CHECK(get_possible_moves(Position::A2, DEFAULT_BOARD) == DEFAULT_W_A_PAWN_POSSIBLE_MOVES); - CHECK(get_possible_moves(KNIGHT_BLOCKED1_POS, KNIGHT_BLOCKED1_BOARD) == KNIGHT_BLOCKED1_MOVES); - CHECK(get_possible_moves(BISHOP_BLOCKED1_POS, BISHOP_BLOCKED1_BOARD) == BISHOP_BLOCKED1_MOVES); - CHECK(get_possible_moves(ROOK_BLOCKED1_POS, ROOK_BLOCKED1_BOARD) == ROOK_BLOCKED1_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); -} - -TEST_CASE("Test all moves for white in edge cases.", "[get_all_moves][white]"){ - CHECK(get_all_moves(W_KNIGHT_SIDE1_POS, W_KNIGHT_SIDE1_BOARD) == W_KNIGHT_SIDE1_ALL_MOVES); - CHECK(get_all_moves(W_KING_SIDE1_POS, W_KING_SIDE1_BOARD) == W_KING_SIDE1_ALL_MOVES); - CHECK(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_all_moves(B_KNIGHT_SIDE1_POS, B_KNIGHT_SIDE1_BOARD) == B_KNIGHT_SIDE1_ALL_MOVES); - CHECK(get_all_moves(B_KING_SIDE1_POS, B_KING_SIDE1_BOARD) == B_KING_SIDE1_ALL_MOVES); - 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); -} - -TEST_CASE("Tests for en pessant squares.", "[get_all_moves]"){ - CHECK(get_all_moves(EN_PASSANT_TEST_POS, EN_PASSANT_TEST_BOARD, false, EN_PASSANT_SQUARE) == EN_PASSANT_TEST_MOVES); - CHECK(get_all_moves(NO_EN_PASSANT_TEST_POS, NO_EN_PASSANT_TEST_BOARD) == NO_EN_PASSANT_TEST_MOVES); -} diff --git a/tests/valid_moves.h b/tests/valid_moves.h index c35fac4..ca759ae 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -1,5 +1,5 @@ #include -#include +#include /// This is for possible moves on a default board From 6caf487f94a9b82aab8390c2cf3189831722e7fd Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sat, 20 Apr 2019 22:22:29 +0000 Subject: [PATCH 34/81] Add custom printing back --- tests/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/main.cpp b/tests/main.cpp index 44d648b..85a6bac 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -1,10 +1,10 @@ #include "catch.hpp" #include "test_boards.h" #include "valid_moves.h" +#include "custom_printing.cpp" #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, From b9487242bc8f5c2fe5f85c120d5675975953506e Mon Sep 17 00:00:00 2001 From: Justin Pilon Date: Sun, 21 Apr 2019 16:19:07 -0600 Subject: [PATCH 35/81] Remove get_to_squares from right hand side of tests --- tests/main.cpp | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/tests/main.cpp b/tests/main.cpp index 85a6bac..d759546 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -102,40 +102,40 @@ TEST_CASE("Test that invalid position ints return false", "[is_valid_position]") } 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)) == get_to_squares(B_KING_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(B_QUEEN_POS, B_QUEEN_BOARD)) == get_to_squares(B_QUEEN_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(B_ROOK_POS, B_ROOK_BOARD)) == get_to_squares(B_ROOK_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(B_BISHOP_POS, B_BISHOP_BOARD)) == get_to_squares(B_BISHOP_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(B_KNIGHT_POS, B_KNIGHT_BOARD)) == get_to_squares(B_KNIGHT_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(B_PAWN_POS, B_PAWN_BOARD)) == get_to_squares(B_PAWN_ALL_MOVES)); + 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)) == get_to_squares(W_KING_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(W_QUEEN_POS, W_QUEEN_BOARD)) == get_to_squares(W_QUEEN_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(W_ROOK_POS, W_ROOK_BOARD)) == get_to_squares(W_ROOK_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(W_BISHOP_POS, W_BISHOP_BOARD)) == get_to_squares(W_BISHOP_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(W_KNIGHT_POS, W_KNIGHT_BOARD)) == get_to_squares(W_KNIGHT_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(W_PAWN_POS, W_PAWN_BOARD)) == get_to_squares(W_PAWN_ALL_MOVES)); + 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)) == get_to_squares(W_KNIGHT_SIDE1_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(W_KING_SIDE1_POS, W_KING_SIDE1_BOARD)) == get_to_squares(W_KING_SIDE1_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(W_PAWN_SIDE1_POS, W_PAWN_SIDE1_BOARD)) == get_to_squares(W_PAWN_SIDE1_ALL_MOVES)); + 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)) == get_to_squares(B_KNIGHT_SIDE1_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(B_KING_SIDE1_POS, B_KING_SIDE1_BOARD)) == get_to_squares(B_KING_SIDE1_ALL_MOVES)); - CHECK(get_to_squares(get_all_moves(B_PAWN_SIDE1_POS, B_PAWN_SIDE1_BOARD)) == get_to_squares(B_PAWN_SIDE1_ALL_MOVES)); + 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("Test that moves that put king in check are not returned", "[get_all_moves]"){ - CHECK(get_to_squares(get_all_moves(ROOK_CHECK_TEST_POS, ROOK_CHECK_TEST_BOARD)) == get_to_squares(ROOK_CHECK_TEST_MOVES)); - CHECK(get_to_squares(get_all_moves(PAWN_CHECK_TEST_POS, PAWN_CHECK_TEST_BOARD)) == get_to_squares(PAWN_CHECK_TEST_MOVES)); - CHECK(get_to_squares(get_all_moves(PAWN_DIAG_TEST1_POS, PAWN_DIAG_TEST1_BOARD)) == get_to_squares(PAWN_DIAG_TEST1_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); + CHECK(get_to_squares(get_all_moves(PAWN_DIAG_TEST1_POS, PAWN_DIAG_TEST1_BOARD)) == PAWN_DIAG_TEST1_MOVES); } TEST_CASE("Tests for en pessant squares.", "[get_all_moves]"){ - CHECK(get_to_squares(get_all_moves(EN_PASSANT_TEST_POS, EN_PASSANT_TEST_BOARD, false, EN_PASSANT_SQUARE)) == get_to_squares(EN_PASSANT_TEST_MOVES)); - CHECK(get_to_squares(get_all_moves(NO_EN_PASSANT_TEST_POS, NO_EN_PASSANT_TEST_BOARD)) == get_to_squares(NO_EN_PASSANT_TEST_MOVES)); + CHECK(get_to_squares(get_all_moves(EN_PASSANT_TEST_POS, EN_PASSANT_TEST_BOARD, false, EN_PASSANT_SQUARE)) == EN_PASSANT_TEST_MOVES); + CHECK(get_to_squares(get_all_moves(NO_EN_PASSANT_TEST_POS, NO_EN_PASSANT_TEST_BOARD)) == NO_EN_PASSANT_TEST_MOVES); } From 62a0b4ce6a3ded9bd31db8800c339256768d8e61 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Tue, 23 Apr 2019 17:12:12 +0000 Subject: [PATCH 36/81] Fix some bugs, make bitwise tests pass. --- src/bitwise.h | 4 +- src/constants.h | 4 +- tests/Makefile | 4 ++ tests/bitwise_tests.cpp | 89 +++++++++++++++++++++-------------------- 4 files changed, 54 insertions(+), 47 deletions(-) diff --git a/src/bitwise.h b/src/bitwise.h index 358bae8..9a7a274 100644 --- a/src/bitwise.h +++ b/src/bitwise.h @@ -1,8 +1,8 @@ #ifndef BITWISE_H #define BITWISE_H -#include #include "constants.h" +#include // Using macros for ease of use, can also use functons, but I don't see the point. @@ -67,6 +67,6 @@ Rank get_rank(int pos){ } inline bool is_valid_position(int position){ - return DEFAULT_BOARD[position] == PieceType::INV; + return DEFAULT_BOARD[position] != PieceType::INV; } #endif diff --git a/src/constants.h b/src/constants.h index c51be45..c2a23b0 100644 --- a/src/constants.h +++ b/src/constants.h @@ -17,10 +17,12 @@ enum PieceType { B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING, W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING }; + 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}; } + enum Position { NA=-1, A8=21, B8, C8, D8, E8, F8, G8, H8, @@ -34,7 +36,7 @@ enum Position { }; // Access with POSITION_STRING[Position] -const std::vector POSITION_STRING = { +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", diff --git a/tests/Makefile b/tests/Makefile index c67d884..b8438ad 100755 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,4 +1,5 @@ defualt: all.out +bitwise: bitwise.out catch_main.o: g++ -w -c -o catch_main.o catch_main.cpp @@ -6,6 +7,9 @@ catch_main.o: custom_printing.o: g++ -w -I../src/ -c -o custom_printing.o custom_printing.cpp +bitwise.out: catch_main.o + g++ -w -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 -w -I../src/ -o all.out ../src/functions.cpp catch_main.o custom_printing.o main.cpp diff --git a/tests/bitwise_tests.cpp b/tests/bitwise_tests.cpp index 030dca4..596b0bc 100644 --- a/tests/bitwise_tests.cpp +++ b/tests/bitwise_tests.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include "catch.hpp" /* @@ -12,80 +12,81 @@ * castle move flag: 1 bit * * (32-bit int, room to exapnd if neccessary) - * 0000 0000 0000 0000 0000 0000 0011 1111 -> From square position (& 0x3F) - * 0000 0000 0000 0000 0000 1111 1100 0000 -> To square position (>> 6 & 0xFB) - * 0000 0000 0000 0000 1111 0000 0000 0000 -> captured piece, if any (>> 12 & 0xF) - * 0000 0000 0000 1111 0000 0000 0000 0000 -> if prmoted, what to? (>> 16 & 0xF) - * 0000 0000 0001 0000 0000 0000 0000 0000 -> en passant (& 0x100000) - * 0000 0000 0010 0000 0000 0000 0000 0000 -> pawn starting move (& 0x200000) - * 0000 0000 0100 0000 0000 0000 0000 0000 -> castle move (& 0x400000) + * 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 H1 -const unsigned int MOVE_G1 = 0x3f; - // This is testing position G1 -const unsigned int MOVE_H1 = 0x3e; +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 -// // Want: -// 1111 1111 1110 -// FFE -const unsigned int MOVE_G1_TO_H1 = 0xffe; +const unsigned int MOVE_G1_TO_H1 = 0b1100010'1100001; // This is testing a move with no flags from H1 to G1 -// Want: -// 1111 1011 1111 -// FBF -const unsigned int MOVE_H1_TO_G1 = 0b111110111111; +const unsigned int MOVE_H1_TO_G1 = 0b1100001'1100010; // Move from H1 to G1 and capture -const unsigned int MOVE_H1_TO_G1_get_captured_pcURE_B_KNIGHT = 0x8fbf; +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_get_promoted_to_pcOTE_TO_QUEEN = 0xb0fbf; +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 = 0x100fbf; +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 = 0x200fbf; +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_get_castle_flagLE = 0x400fbf; +const unsigned int MOVE_H1_TO_G1_AND_CASTLE = 0b1'0'0'0000'0000'1100001'1100010; // Want: -// From: E3 (21) [0x15] [0x15] <0x15> -// To: D2 (12) [0xB] [0xB] <0x3DF> -// (these 2 combine together) (33) [0x20] [0x3DF] <> -// Captures: B_PAWM (7) [0x7] [0x7000] <0x73DF> -// Promoted: NONE (0) [0x0] [0x0] <> -// en passant: true (1) [0x1] [0x100000] <0x1003DF> -// pawn starting move: false (0) [0x0] [0x0] <> -// castle move: false (0) [0x0] [0x0] <> -// total value: (?) [?] [?} <0x1003DF> -const unsigned int GET_ALL_INT = 0x1003DF; +// 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::H1); - CHECK(get_from_sq(MOVE_H1) == Position::G1); + 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_get_captured_pcURE_B_KNIGHT) == PieceType::B_KNIGHT); - CHECK(get_promoted_to_pc(MOVE_H1_TO_G1_get_promoted_to_pcOTE_TO_QUEEN) == PieceType::B_QUEEN); + 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_get_castle_flagLE) == 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(is_valid_position(0)); - CHECK(is_valid_position(63)); - CHECK_FALSE(is_valid_position(-1)); - CHECK_FALSE(is_valid_position(64)); + CHECK_FALSE(is_valid_position(0)); + CHECK(is_valid_position(Position::A8)); + CHECK(is_valid_position(Position::H1)); } From c585c1543e33730d0b22eecff795cb920c5f524e Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Tue, 23 Apr 2019 17:24:21 +0000 Subject: [PATCH 37/81] Check get_to_squares works properly --- src/functions.cpp | 1 + tests/main.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/functions.cpp b/src/functions.cpp index 11266c5..b059e94 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -224,6 +224,7 @@ std::array dumb_move(int move, std::array board) std::unordered_set get_to_squares(std::unordered_set moves){ std::unordered_set to_squares; for (int move : moves){ + std::cout << "SQ: " << get_to_sq(move) << "\n"; to_squares.insert(get_to_sq(move)); } return to_squares; diff --git a/tests/main.cpp b/tests/main.cpp index d759546..f43946b 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -20,6 +20,12 @@ const std::array DUMB_MOVE_1 = { 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::unordered_set to_squares = {Position::H1}; + std::unordered_set moves = {0b11000100000000}; + REQUIRE(get_to_squares(moves) == to_squares); +} + 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); } From 0b84fcf8e0f8e1475a79d5376df8b416786d1d25 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Tue, 23 Apr 2019 20:48:52 +0000 Subject: [PATCH 38/81] All tests running on 10x12 board, and bitwise moves. --- src/all_moves_functions.cpp | 57 +++++++++++++++---------------------- src/bitwise.h | 40 ++++++++++++++++++++------ src/constants.h | 14 ++++----- src/functions.cpp | 57 ++++++++----------------------------- src/functions.h | 11 ++----- tests/custom_printing.cpp | 29 +++++++------------ tests/main.cpp | 49 ++++++------------------------- 7 files changed, 94 insertions(+), 163 deletions(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index c0ff52a..3e79d77 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -13,13 +13,6 @@ inline Position _pair_to_pos_unsafe(int x, int y){ return static_cast(std::abs(y-7)*8 + x); } -void _push_if_valid_pos(int pos, std::unordered_set *pns){ - if (is_valid_position(pos)){ - pns->insert(pos); - } -} - - // This function returns true if the color of the piece on tile (x,y) is the Color c bool _xy_is_color(int pos, std::array* board, Color c){ return c==Color::WHITE ? is_white((*board)[pos]) : is_black((*board)[pos]); @@ -30,7 +23,7 @@ Color _rev_color(Color c){ } // 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, std::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){ +void _add_if_not_blocked(int pos, int from, std::unordered_set *pns, 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; @@ -38,45 +31,41 @@ void _add_if_not_blocked(int pos, std::unordered_set *pns, std::arrayinsert(pos); + pns->insert(make_move(from, pos)); *is_not_blocked = false; } else { - pns->insert(pos); + pns->insert(make_move(from, pos)); } } } } // 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, std::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite){ - if (_xy_is_color(pos, board, color_of_piece)){ +void _add_if_not_blocked(int pos, int from, std::unordered_set *pns, 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->insert(pos); + pns->insert(make_move(from, pos)); } } // 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, std::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite, int en_passant){ +void _pawn_diag_add_if_not_blocked(int pos, int from, std::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite, int en_passant){ if (is_valid_position(pos) && (_xy_is_color(pos, board, color_of_opposite) || pos == en_passant)){ - pns->insert(pos); + pns->insert(make_move(from, pos)); } } // This is a specialized functions for the pawn's inability to take going forward. // Notice the lack of insertion where there usually is when (x,y) is a different color. -void _pawn_add_if_not_blocked(int pos, std::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){ +void _pawn_add_if_not_blocked(int pos, int from, std::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){ if (*is_not_blocked){ - if (is_valid_position(pos)){ + if ((*board)[pos] != PieceType::NONE || + (*board)[pos] == PieceType::INV){ *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)){ - *is_not_blocked = false; - } else { - pns->insert(pos); - } + pns->insert(make_move(from, pos)); } } } @@ -86,7 +75,7 @@ void _get_all_moves_rook(int pos, std::unordered_set *pns, std::array *pns, std::array *pns, std::array *pns, std::array* board, Color pc, Color rc){ for (int kn_off : KNIGHT_PIECE_OFFSETS){ bool* not_blocked = new bool(true); - _add_if_not_blocked(pos+kn_off, pns, board, pc, rc); + _add_if_not_blocked(pos+kn_off, pos, pns, board, pc, rc); } /* for (int xo=1;xo<=2;xo++){ @@ -148,7 +137,7 @@ void _get_all_moves_knight(int pos, std::unordered_set *pns, std::array *pns, std::array* board, Color pc, Color rc){ for (int kn_off : KING_PIECE_OFFSETS){ bool* not_blocked = new bool(true); - _add_if_not_blocked(pos+kn_off, pns, board, pc, rc); + _add_if_not_blocked(pos+kn_off, pos, pns, board, pc, rc); } @@ -167,17 +156,17 @@ void _get_all_moves_king(int pos, std::unordered_set *pns, std::array *pns, 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 offset2 = pc==Color::WHITE?-20:20; + int offset1 = pc==Color::WHITE?-10:10; int default_pawn_rank = pc==Color::WHITE?Rank::RANK2:Rank::RANK7; bool *free_to_double_move = new bool(true); - _pawn_add_if_not_blocked(pos+offset1, pns, board, pc, rc, free_to_double_move); + _pawn_add_if_not_blocked(pos+offset1, pos, pns, board, pc, rc, free_to_double_move); if (get_rank(pos) == default_pawn_rank){ // If on second/seventh rank - _pawn_add_if_not_blocked(pos+offset2, pns, board, pc, rc, free_to_double_move); + _pawn_add_if_not_blocked(pos+offset2, pos, pns, board, pc, rc, free_to_double_move); } // 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, pns, board, pc, rc, en_passant); - _pawn_diag_add_if_not_blocked(pos+offset1-1, pns, board, pc, rc, en_passant); + _pawn_diag_add_if_not_blocked(pos+offset1+1, pos, pns, board, pc, rc, en_passant); + _pawn_diag_add_if_not_blocked(pos+offset1-1, pos, pns, board, pc, rc, en_passant); } diff --git a/src/bitwise.h b/src/bitwise.h index 9a7a274..48618a8 100644 --- a/src/bitwise.h +++ b/src/bitwise.h @@ -56,17 +56,39 @@ inline int get_pawn_st_flag(int mv){ inline int get_castle_flag(int mv){ return ((mv >> 24) & 0x1); } -// Just trying to get working for now. -Rank get_rank(int pos){ - if (pos >30 && pos < 39){ - return Rank::RANK7; - } else if (pos > 80 && pos < 89){ - return Rank::RANK2; - } - return Rank::RANK1; -} inline bool is_valid_position(int position){ return DEFAULT_BOARD[position] != PieceType::INV; } + +inline int set_to_sq(int sq, int base){ + return base + (sq << 7); +} +inline int set_to_sq(int sq){ + return (sq << 7); +} + +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); +} + + #endif diff --git a/src/constants.h b/src/constants.h index c2a23b0..a35fcc2 100644 --- a/src/constants.h +++ b/src/constants.h @@ -52,14 +52,14 @@ const std::array POSITION_STRING = { }; enum Rank{ - RANK1, - RANK2, - RANK3, - RANK4, - RANK5, - RANK6, + RANK8, RANK7, - RANK8 + RANK6, + RANK5, + RANK4, + RANK3, + RANK2, + RANK1 }; enum File { diff --git a/src/functions.cpp b/src/functions.cpp index b059e94..ff2965c 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -12,41 +12,13 @@ // TODO implement functions.h functions. // NOTE tests will NOT run unless you implement these functions. - -std::pair pos_to_pair(Position pn){ - int x,y = 0; - for (x = pn; x >= 8; x = x-8){ - ++y; - } - return std::make_pair(x, std::abs(y-7)); -} - -// 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."); - } - 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()); +Rank get_rank(int pos){ + int rank = 0; + while (pos >= 0){ + pos -= 10; + rank++; } -} -Position pair_to_pos(int x, int y){ - return pair_to_pos(std::make_pair(x, y)); -} - -bool is_valid_position(std::pair pos){ - return (pos.first < 8 && pos.second < 8 && - pos.first >= 0 && pos.second >=0); -} -bool is_valid_position(int x, int y){ - return (x < 8 && x >= 0 && - y < 8 && y >= 0); + return static_cast(rank - 3); } bool is_white(PieceType pt){ @@ -68,9 +40,6 @@ Color get_color(PieceType pt){ return Color::NO_COLOR; } -Color get_color(int x, int y, std::array const *board){ - return get_color((*board)[pair_to_pos(x, y)]); -} Color get_color(Position pn, std::array const *board){ return get_color((*board)[pn]); } @@ -110,23 +79,22 @@ std::unordered_set get_poss_of(PieceType pt, std::array con return results; } -void get_poss_of(PieceType pt, std::array* board, std::vector* pns){ +void get_poss_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)); + pns->push_back(pn); } } } //TODO: Make faster by running from king squar eonly, instead of running on every piece of opposite team. -void filter_checked_moves(int pos, PieceType pt, std::array *board, std::unordered_set *pns){ +void filter_checked_moves(PieceType pt, std::array *board, std::unordered_set *pns){ PieceType my_king = is_white(pt)?PieceType::W_KING:PieceType::B_KING; int my_king_pos = get_pos_of(my_king, board); int attackers = 0; for (auto p_pn= pns->begin(); p_pn!=pns->end();){ // Make move - int move_int = pos + (*p_pn >> 7); - std::array moved_board = dumb_move(move_int, *board); + std::array moved_board = dumb_move(*p_pn, *board); // Get all piecetypes of other team std::array other_team = is_white(pt)?Pieces::BLACK:Pieces::WHITE; bool checks_king = false; @@ -139,7 +107,7 @@ void filter_checked_moves(int pos, PieceType pt, std::array *boa // // } // \NEW CODE - std::vector psns; + std::vector psns; get_poss_of(other_p, &moved_board, &psns); for (auto psn : psns){ std::unordered_set other_moves; @@ -202,7 +170,7 @@ void get_all_moves(int pos, std::array* board, std::unordered_se break; } if (recursive){ - filter_checked_moves(pos, pt, board, moves); + filter_checked_moves(pt, board, moves); } } @@ -224,7 +192,6 @@ std::array dumb_move(int move, std::array board) std::unordered_set get_to_squares(std::unordered_set moves){ std::unordered_set to_squares; for (int move : moves){ - std::cout << "SQ: " << get_to_sq(move) << "\n"; to_squares.insert(get_to_sq(move)); } return to_squares; diff --git a/src/functions.h b/src/functions.h index 6557a89..abe80d5 100644 --- a/src/functions.h +++ b/src/functions.h @@ -4,11 +4,6 @@ #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); -Position pair_to_pos(int x, int y); - // Returns a list of positions with PieceType pt int get_pos_of(PieceType pt, std::array const *board); std::unordered_set get_poss_of(PieceType pt, std::array const *board); @@ -19,14 +14,14 @@ 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); -bool is_valid_position(std::pair pos); -bool is_valid_position(int x, int y); + +// Returns rank enum value for given pos +Rank get_rank(int pos); // Checks if given piece matches a certain color. bool is_white(PieceType pt); bool is_black(PieceType pt); -Color get_color(int x, int y, std::array const *board); Color get_color(Position pn, std::array const *board); Color get_color(PieceType pt); // NO_COLOR returns NO_COLOR diff --git a/tests/custom_printing.cpp b/tests/custom_printing.cpp index e89962c..fa9fd33 100644 --- a/tests/custom_printing.cpp +++ b/tests/custom_printing.cpp @@ -3,18 +3,9 @@ #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). +// 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){ @@ -53,20 +44,20 @@ namespace Catch { }; // 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::unordered_set const& uo_poss){ - std::vector poss(uo_poss.begin(), uo_poss.end()); + struct StringMaker> { + static std::string convert(std::unordered_set 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 = 0; i < 8; ++i){ - ss << 8-i << "|"; - for (int j = 0; j < 8; ++j){ - int index = (i*8)+j; + for (int i = 2; i < 10; ++i){ + ss << i-1 << "|"; + 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 (Position p : poss){ + for (int p : poss){ if (index == p) { part_of_poss = true; break; @@ -76,7 +67,7 @@ namespace Catch { // (if) part_of_poss ?(then) do this :(else) do that. part_of_poss ? ss << "* " : ss << " "; } - ss << "|" << 8-i; + ss << "|" << i-1; ss << std::endl; } ss << files << std::endl; diff --git a/tests/main.cpp b/tests/main.cpp index f43946b..ec8cee2 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -26,14 +26,16 @@ TEST_CASE("Test that the get_to_squares works, this is required!", "[get_to_squa 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(2, 7, &DUMB_MOVE_1) == Color::BLACK); - CHECK(get_color(3, 3, &DUMB_MOVE_1) == Color::NO_COLOR); - CHECK(get_color(2, 1, &DUMB_MOVE_1) == Color::WHITE); 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); @@ -66,45 +68,10 @@ TEST_CASE("Test that dumb moves can be made.", "[dumb_move]"){ CHECK(dumb_move(move_int, 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))); - - CHECK(pair_to_pos(2, 3) == Position::C4); - CHECK(pair_to_pos(7, 0) == Position::H1); - CHECK(pair_to_pos(0, 0) == Position::A1); - CHECK(pair_to_pos(7, 7) == Position::H8); - CHECK_THROWS(pair_to_pos(8, 2)); - CHECK_THROWS(pair_to_pos(-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 that invalid position ints return false", "[is_valid_position]"){ - CHECK(is_valid_position(0)); // 0=A8 - CHECK(is_valid_position(63)); // 63=H1 - CHECK_FALSE(is_valid_position(-1)); // -1 is out of bounds - CHECK_FALSE(is_valid_position(64)); // 64 is out of bounds - - CHECK(is_valid_position(std::make_pair(0, 0))); // 0-7,0-7 should be valid - CHECK(is_valid_position(std::make_pair(7, 7))); - CHECK_FALSE(is_valid_position(std::make_pair(-1, 5))); // should fail - CHECK_FALSE(is_valid_position(std::make_pair(5, 8))); // should fail - - CHECK(is_valid_position(0, 0)); // 0-7,0-7 should be valid - CHECK(is_valid_position(7, 7)); - CHECK_FALSE(is_valid_position(-1, 5)); // should fail - CHECK_FALSE(is_valid_position(5, 8)); // should fail + 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]"){ From 52ec82f7df8614dfa180af0b50cf892950295379 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Tue, 23 Apr 2019 22:00:43 +0000 Subject: [PATCH 39/81] Half-done fixing the conversion of moves to bit-shifted variants --- src/functions.cpp | 12 --------- src/functions.h | 5 ---- tests/Makefile | 2 +- tests/main.cpp | 6 ++++- tests/test_functions.cpp | 56 ++++++++++++++++++++++++++++++++++++++++ tests/test_functions.h | 12 +++++++++ 6 files changed, 74 insertions(+), 19 deletions(-) create mode 100644 tests/test_functions.cpp create mode 100644 tests/test_functions.h diff --git a/src/functions.cpp b/src/functions.cpp index ff2965c..3a99961 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -188,15 +188,3 @@ std::array dumb_move(int move, std::array board) board[from] = PieceType::NONE; return board; } - -std::unordered_set get_to_squares(std::unordered_set moves){ - std::unordered_set to_squares; - for (int move : moves){ - to_squares.insert(get_to_sq(move)); - } - return to_squares; -} -std::unordered_set get_from_squared(std::unordered_set moves){ - std::unordered_set from_squares; - return from_squares; -} diff --git a/src/functions.h b/src/functions.h index abe80d5..0c15038 100644 --- a/src/functions.h +++ b/src/functions.h @@ -49,8 +49,3 @@ std::unordered_set get_all_moves(int pos, std::array board, // Does not check if move is valid, just does it. std::array dumb_move(int move, std::array board); -// Allow the developer to get only certain pieces of the part of a move in a list. -// This will return a vector (or unordered_set) of elements with only a certain part of the move revealed bit bit-switching. -std::unordered_set get_from_squares(std::unordered_set moves); -std::unordered_set get_to_squares(std::unordered_set moves); - diff --git a/tests/Makefile b/tests/Makefile index b8438ad..4e4370d 100755 --- a/tests/Makefile +++ b/tests/Makefile @@ -12,4 +12,4 @@ bitwise.out: catch_main.o # TODO: Allw all.out to contain bitwise tests all.out: catch_main.o custom_printing.o - g++ -std=c++11 -ggdb -w -I../src/ -o all.out ../src/functions.cpp catch_main.o custom_printing.o main.cpp + g++ -std=c++11 -ggdb -w -I../src/ -o all.out ../src/functions.cpp catch_main.o custom_printing.o test_functions.cpp main.cpp diff --git a/tests/main.cpp b/tests/main.cpp index ec8cee2..e0d4aa0 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -2,6 +2,7 @@ #include "test_boards.h" #include "valid_moves.h" #include "custom_printing.cpp" +#include "test_functions.h" #include #include @@ -105,7 +106,10 @@ TEST_CASE("Test all moves for black in edge cases.", "[get_all_moves][black]"){ TEST_CASE("Test that moves that put 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); - CHECK(get_to_squares(get_all_moves(PAWN_DIAG_TEST1_POS, PAWN_DIAG_TEST1_BOARD)) == PAWN_DIAG_TEST1_MOVES); + auto pawn_diag_moves = get_all_moves(PAWN_DIAG_TEST1_POS, PAWN_DIAG_TEST1_BOARD); + std::unordered_set 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]"){ diff --git a/tests/test_functions.cpp b/tests/test_functions.cpp new file mode 100644 index 0000000..0ebeeaa --- /dev/null +++ b/tests/test_functions.cpp @@ -0,0 +1,56 @@ +#include "test_functions.h" +#include +#include +#include + +std::unordered_set get_to_squares(std::unordered_set moves){ + std::unordered_set transformed; + for (int mv : moves){ + transformed.insert(get_to_sq(mv)); + } + return transformed; +} +std::unordered_set get_from_squared(std::unordered_set moves){ + std::unordered_set transformed; + for (int mv : moves){ + transformed.insert(get_from_sq(mv)); + } + return transformed; +} +std::unordered_set get_captured_pieces(std::unordered_set moves){ + std::unordered_set transformed; + for (int mv : moves){ + transformed.insert(get_captured_pc(mv)); + } + return transformed; +} +std::unordered_set get_promoted_pieces(std::unordered_set moves){ + std::unordered_set transformed; + for (int mv : moves){ + transformed.insert(get_promoted_to_pc(mv)); + } + return transformed; +} +std::unordered_set get_en_passant_flags(std::unordered_set moves){ + std::unordered_set transformed; + for (int mv : moves){ + transformed.insert(get_en_pass_flag(mv)); + } + return transformed; +} +std::unordered_set get_pawn_start_flags(std::unordered_set moves){ + std::unordered_set transformed; + for (int mv : moves){ + std::cout << "MOVE: \n"; + transformed.insert(get_pawn_st_flag(mv)); + } + return transformed; +} +std::unordered_set get_castle_flags(std::unordered_set moves){ + std::unordered_set transformed; + for (int mv : moves){ + transformed.insert(get_castle_flag(mv)); + } + return transformed; +} + diff --git a/tests/test_functions.h b/tests/test_functions.h new file mode 100644 index 0000000..d427f0e --- /dev/null +++ b/tests/test_functions.h @@ -0,0 +1,12 @@ +#ifndef TEST_FUNCTIONS_H +#define TEST_FUNCTOPMS_H +#include + +std::unordered_set get_from_squares(std::unordered_set moves); +std::unordered_set get_to_squares(std::unordered_set moves); +std::unordered_set get_captured_pieces(std::unordered_set moves); +std::unordered_set get_promoted_pieces(std::unordered_set moves); +std::unordered_set get_en_passant_flags(std::unordered_set moves); +std::unordered_set get_pawn_start_flags(std::unordered_set moves); +std::unordered_set get_castle_flags(std::unordered_set moves); +#endif From 16add284ef012f914d0d3442ee67ec2149a30db7 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Tue, 23 Apr 2019 22:36:16 +0000 Subject: [PATCH 40/81] Make unordered_sets unto vectors --- src/all_moves_functions.cpp | 32 +++++++++++++-------------- src/bitwise.h | 2 +- src/functions.cpp | 24 ++++++++++---------- src/functions.h | 14 ++++++------ tests/B_test_boards.h | 20 ++++++++--------- tests/W_test_boards.h | 20 ++++++++--------- tests/custom_printing.cpp | 6 ++--- tests/main.cpp | 6 ++--- tests/test_functions.cpp | 44 ++++++++++++++++++------------------- tests/test_functions.h | 16 +++++++------- tests/valid_moves.h | 30 ++++++++++++------------- 11 files changed, 107 insertions(+), 107 deletions(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index 3e79d77..b918e79 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -1,5 +1,5 @@ #include "constants.h" -#include +#include #include #include @@ -23,7 +23,7 @@ Color _rev_color(Color c){ } // 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::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){ +void _add_if_not_blocked(int pos, int from, std::vector *pns, 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; @@ -31,47 +31,47 @@ void _add_if_not_blocked(int pos, int from, std::unordered_set *pns, std::a if (_xy_is_color(pos, board, color_of_piece)){ *is_not_blocked = false; } else if (_xy_is_color(pos, board, color_of_opposite)){ - pns->insert(make_move(from, pos)); + pns->push_back(make_move(from, pos)); *is_not_blocked = false; } else { - pns->insert(make_move(from, pos)); + pns->push_back(make_move(from, pos)); } } } } // 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::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite){ +void _add_if_not_blocked(int pos, int from, std::vector *pns, 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->insert(make_move(from, pos)); + pns->push_back(make_move(from, pos)); } } // 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::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite, int en_passant){ +void _pawn_diag_add_if_not_blocked(int pos, int from, std::vector *pns, std::array *board, Color color_of_piece, Color color_of_opposite, int en_passant){ if (is_valid_position(pos) && (_xy_is_color(pos, board, color_of_opposite) || pos == en_passant)){ - pns->insert(make_move(from, pos)); + pns->push_back(make_move(from, pos)); } } // This is a specialized functions for the pawn's inability to take going forward. -// Notice the lack of insertion where there usually is when (x,y) is a different color. -void _pawn_add_if_not_blocked(int pos, int from, std::unordered_set *pns, std::array *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){ +// 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, std::array *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){ if (*is_not_blocked){ if ((*board)[pos] != PieceType::NONE || (*board)[pos] == PieceType::INV){ *is_not_blocked = false; } else { - pns->insert(make_move(from, pos)); + pns->push_back(make_move(from, pos)); } } } -void _get_all_moves_rook(int pos, std::unordered_set *pns, std::array* board, Color pc, Color rc){ +void _get_all_moves_rook(int pos, std::vector *pns, std::array* board, Color pc, Color rc){ for (int rk_off : ROOK_PIECE_OFFSETS){ bool* not_blocked = new bool(true); for (int offset=1; offset<8; offset++){ @@ -93,7 +93,7 @@ void _get_all_moves_rook(int pos, std::unordered_set *pns, std::array *pns, std::array* board, Color pc, Color rc){ +void _get_all_moves_bishop(int pos, std::vector *pns, std::array* board, Color pc, Color rc){ for (int bs_off : BISHOP_PIECE_OFFSETS){ bool* not_blocked = new bool(true); for (int offset=1; offset<8; offset++){ @@ -118,7 +118,7 @@ void _get_all_moves_bishop(int pos, std::unordered_set *pns, std::array *pns, std::array* board, Color pc, Color rc){ +void _get_all_moves_knight(int pos, std::vector *pns, std::array* board, Color pc, Color rc){ for (int kn_off : KNIGHT_PIECE_OFFSETS){ bool* not_blocked = new bool(true); _add_if_not_blocked(pos+kn_off, pos, pns, board, pc, rc); @@ -134,7 +134,7 @@ void _get_all_moves_knight(int pos, std::unordered_set *pns, std::array *pns, std::array* board, Color pc, Color rc){ +void _get_all_moves_king(int pos, std::vector *pns, std::array* board, Color pc, Color rc){ for (int kn_off : KING_PIECE_OFFSETS){ bool* not_blocked = new bool(true); _add_if_not_blocked(pos+kn_off, pos, pns, board, pc, rc); @@ -153,7 +153,7 @@ void _get_all_moves_king(int pos, std::unordered_set *pns, std::array *pns, std::array* board, Color pc, Color rc, int en_passant){ +void _get_all_moves_pawn(int pos, std::vector *pns, 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; diff --git a/src/bitwise.h b/src/bitwise.h index 48618a8..7ae0d1e 100644 --- a/src/bitwise.h +++ b/src/bitwise.h @@ -2,7 +2,7 @@ #define BITWISE_H #include "constants.h" -#include +#include // Using macros for ease of use, can also use functons, but I don't see the point. diff --git a/src/functions.cpp b/src/functions.cpp index 3a99961..a405c68 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -49,13 +49,13 @@ Color rev_color(Color c){ return c==Color::WHITE?Color::BLACK:Color::WHITE; } -std::unordered_set get_possible_movers(Position pn, std::array board){ - std::unordered_set pns = {Position::A1}; +std::vector get_possible_movers(Position pn, std::array board){ + std::vector pns = {Position::A1}; return pns; } -std::unordered_set get_possible_moves(Position pn, std::array board){ - std::unordered_set pns = {Position::A1}; +std::vector get_possible_moves(Position pn, std::array board){ + std::vector pns = {Position::A1}; get_all_moves(pn, &board, &pns); return pns; } @@ -69,11 +69,11 @@ int get_pos_of(PieceType pt, std::array const *board){ return Position::NA; } -std::unordered_set get_poss_of(PieceType pt, std::array const *board){ - std::unordered_set results; +std::vector get_poss_of(PieceType pt, std::array const *board){ + std::vector results; for (int pn = Position::A8; pn!=Position::H1; pn++){ if ((*board)[pn] == pt){ - results.insert(pn); + results.push_back(pn); } } return results; @@ -88,7 +88,7 @@ void get_poss_of(PieceType pt, std::array* board, std::vector *board, std::unordered_set *pns){ +void filter_checked_moves(PieceType pt, 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); int attackers = 0; @@ -110,7 +110,7 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: std::vector psns; get_poss_of(other_p, &moved_board, &psns); for (auto psn : psns){ - std::unordered_set other_moves; + std::vector other_moves; get_all_moves(psn, &moved_board, &other_moves, false); // for every position the piece can mvoe to for (int cp : other_moves){ @@ -136,7 +136,7 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: } } -void get_all_moves(int pos, std::array* board, std::unordered_set* moves, bool recursive, int en_passant){ +void get_all_moves(int pos, std::array* board, std::vector* moves, bool recursive, int en_passant){ PieceType pt = (*board)[pos]; Color color_of_piece = get_color(pt); Color color_of_opponent = rev_color(color_of_piece); @@ -174,8 +174,8 @@ void get_all_moves(int pos, std::array* board, std::unordered_se } } -std::unordered_set get_all_moves(int pos, std::array board, bool recursive, int en_passant){ - std::unordered_set moves; +std::vector get_all_moves(int pos, std::array board, bool recursive, int en_passant){ + std::vector moves; get_all_moves(pos, &board, &moves, recursive, en_passant); return moves; } diff --git a/src/functions.h b/src/functions.h index 0c15038..f5ac4cd 100644 --- a/src/functions.h +++ b/src/functions.h @@ -1,12 +1,12 @@ #include "constants.h" -#include +#include #include #include #include // Returns a list of positions with PieceType pt int get_pos_of(PieceType pt, std::array const *board); -std::unordered_set get_poss_of(PieceType pt, std::array const *board); +std::vector get_poss_of(PieceType pt, std::array const *board); // Convert a Position number into a pair of x y coordiinates std::pair pos_to_pair(Position pn); @@ -32,18 +32,18 @@ Color rev_color(Color c); // 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. -void get_possible_movers(Position pn, std::array *pt,std::unordered_set *moves); +void get_possible_movers(Position pn, std::array *pt,std::vector *moves); // Get all possible moved for piece in Position pn. // This may require helper functions for each individual piece. -void get_possible_moves(Position pn, std::array *pt,std::unordered_set *moves); +void get_possible_moves(Position pn, std::array *pt,std::vector *moves); // This functions removes moves that put your own king in check. -void filter_checked_moves(int pos, std::array *board, std::unordered_set *moves); +void filter_checked_moves(int pos, std::array *board, std::vector *moves); // Get all moves for piece in Position pn. -void get_all_moves(int pos, std::array *pt,std::unordered_set *moves, bool recursive=true, int en_passant=Position::NA); -std::unordered_set get_all_moves(int pos, std::array board, bool recursive=true, int en_passant=Position::NA); +void get_all_moves(int pos, std::array *pt,std::vector *moves, bool recursive=true, int en_passant=Position::NA); +std::vector get_all_moves(int pos, std::array board, bool recursive=true, int en_passant=Position::NA); // Dumb function to do board moves. // Does not check if move is valid, just does it. diff --git a/tests/B_test_boards.h b/tests/B_test_boards.h index d8eafb1..5cff8c2 100644 --- a/tests/B_test_boards.h +++ b/tests/B_test_boards.h @@ -1,4 +1,4 @@ -#include +#include #include const int B_QUEEN_POS = E4; @@ -17,7 +17,7 @@ const std::array B_QUEEN_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::unordered_set B_QUEEN_ALL_MOVES = { +const std::vector B_QUEEN_ALL_MOVES = { A8, E8, B7, E7, H7, C6, E6, G6, @@ -44,7 +44,7 @@ const std::array B_BISHOP_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::unordered_set B_BISHOP_ALL_MOVES = { +const std::vector B_BISHOP_ALL_MOVES = { H8, A7, G7, B6, F6, @@ -70,7 +70,7 @@ const std::array B_KNIGHT_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::unordered_set B_KNIGHT_ALL_MOVES = { +const std::vector B_KNIGHT_ALL_MOVES = { C7, E7, B6, F6, B4, F4, @@ -93,7 +93,7 @@ const std::array B_ROOK_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::unordered_set B_ROOK_ALL_MOVES = { +const std::vector B_ROOK_ALL_MOVES = { E8, E7, E6, A5, B5, C5, D5, F5, G5, H5, E4, E3, E2, E1 @@ -116,7 +116,7 @@ const std::array B_KING_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::unordered_set B_KING_ALL_MOVES = { +const std::vector B_KING_ALL_MOVES = { B5, C5, D5, B4, D4, B3, C3, D3 @@ -139,7 +139,7 @@ const std::array B_PAWN_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::unordered_set B_PAWN_ALL_MOVES = { +const std::vector B_PAWN_ALL_MOVES = { F3 }; const int B_KNIGHT_SIDE1_POS = B7; @@ -157,7 +157,7 @@ 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 }; -const std::unordered_set B_KNIGHT_SIDE1_ALL_MOVES = { +const std::vector B_KNIGHT_SIDE1_ALL_MOVES = { D8, D6, A5, C5 @@ -177,7 +177,7 @@ 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 }; -const std::unordered_set B_KING_SIDE1_ALL_MOVES = { +const std::vector B_KING_SIDE1_ALL_MOVES = { B8, A7,B7 }; @@ -197,6 +197,6 @@ 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 }; -const std::unordered_set B_PAWN_SIDE1_ALL_MOVES = { +const std::vector B_PAWN_SIDE1_ALL_MOVES = { A6, A5 }; diff --git a/tests/W_test_boards.h b/tests/W_test_boards.h index 21eb95e..6372426 100644 --- a/tests/W_test_boards.h +++ b/tests/W_test_boards.h @@ -1,4 +1,4 @@ -#include +#include #include const int W_QUEEN_POS = E4; @@ -32,7 +32,7 @@ const std::array W_QUEEN_BOARD_BLOCKED = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::unordered_set W_QUEEN_ALL_MOVES = { +const std::vector W_QUEEN_ALL_MOVES = { A8, E8, B7, E7, H7, C6, E6, G6, @@ -59,7 +59,7 @@ const std::array W_BISHOP_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::unordered_set W_BISHOP_ALL_MOVES = { +const std::vector W_BISHOP_ALL_MOVES = { H8, A7, G7, B6, F6, @@ -100,13 +100,13 @@ 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 }; -const std::unordered_set W_KNIGHT_SIDE1_ALL_MOVES = { +const std::vector W_KNIGHT_SIDE1_ALL_MOVES = { D8, D6, A5, C5 }; -const std::unordered_set W_KNIGHT_ALL_MOVES = { +const std::vector W_KNIGHT_ALL_MOVES = { C7, E7, B6, F6, B4, F4, @@ -129,7 +129,7 @@ const std::array W_ROOK_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::unordered_set W_ROOK_ALL_MOVES = { +const std::vector W_ROOK_ALL_MOVES = { E8, E7, E6, A5, B5, C5, D5, F5, G5, H5, E4, E3, E2, E1 @@ -168,12 +168,12 @@ const std::array W_KING_SIDE1_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::unordered_set W_KING_SIDE1_ALL_MOVES = { +const std::vector W_KING_SIDE1_ALL_MOVES = { B8, A7,B7 }; -const std::unordered_set W_KING_ALL_MOVES = { +const std::vector W_KING_ALL_MOVES = { B5, C5, D5, B4, D4, B3, C3, D3 @@ -196,7 +196,7 @@ const std::array W_PAWN_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::unordered_set W_PAWN_ALL_MOVES = { +const std::vector W_PAWN_ALL_MOVES = { F5 }; @@ -215,4 +215,4 @@ 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 }; -const std::unordered_set W_PAWN_SIDE1_ALL_MOVES; +const std::vector W_PAWN_SIDE1_ALL_MOVES; diff --git a/tests/custom_printing.cpp b/tests/custom_printing.cpp index fa9fd33..5d3dd89 100644 --- a/tests/custom_printing.cpp +++ b/tests/custom_printing.cpp @@ -1,7 +1,7 @@ #include "catch.hpp" #include #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) @@ -44,8 +44,8 @@ namespace Catch { }; // 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::unordered_set const& uo_poss){ + 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"; diff --git a/tests/main.cpp b/tests/main.cpp index e0d4aa0..f1adcc9 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -22,8 +22,8 @@ const std::array DUMB_MOVE_1 = { }; TEST_CASE("Test that the get_to_squares works, this is required!", "[get_to_squares]"){ - std::unordered_set to_squares = {Position::H1}; - std::unordered_set moves = {0b11000100000000}; + std::vector to_squares = {Position::H1}; + std::vector moves = {0b11000100000000}; REQUIRE(get_to_squares(moves) == to_squares); } @@ -107,7 +107,7 @@ TEST_CASE("Test that moves that put king in check are not returned", "[get_all_m 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::unordered_set pawn_start_flags = {0, 1, 0}; + 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); } diff --git a/tests/test_functions.cpp b/tests/test_functions.cpp index 0ebeeaa..4b2c538 100644 --- a/tests/test_functions.cpp +++ b/tests/test_functions.cpp @@ -1,55 +1,55 @@ #include "test_functions.h" #include -#include +#include #include -std::unordered_set get_to_squares(std::unordered_set moves){ - std::unordered_set transformed; +std::vector get_to_squares(std::vector moves){ + std::vector transformed; for (int mv : moves){ - transformed.insert(get_to_sq(mv)); + transformed.push_back(get_to_sq(mv)); } return transformed; } -std::unordered_set get_from_squared(std::unordered_set moves){ - std::unordered_set transformed; +std::vector get_from_squared(std::vector moves){ + std::vector transformed; for (int mv : moves){ - transformed.insert(get_from_sq(mv)); + transformed.push_back(get_from_sq(mv)); } return transformed; } -std::unordered_set get_captured_pieces(std::unordered_set moves){ - std::unordered_set transformed; +std::vector get_captured_pieces(std::vector moves){ + std::vector transformed; for (int mv : moves){ - transformed.insert(get_captured_pc(mv)); + transformed.push_back(get_captured_pc(mv)); } return transformed; } -std::unordered_set get_promoted_pieces(std::unordered_set moves){ - std::unordered_set transformed; +std::vector get_promoted_pieces(std::vector moves){ + std::vector transformed; for (int mv : moves){ - transformed.insert(get_promoted_to_pc(mv)); + transformed.push_back(get_promoted_to_pc(mv)); } return transformed; } -std::unordered_set get_en_passant_flags(std::unordered_set moves){ - std::unordered_set transformed; +std::vector get_en_passant_flags(std::vector moves){ + std::vector transformed; for (int mv : moves){ - transformed.insert(get_en_pass_flag(mv)); + transformed.push_back(get_en_pass_flag(mv)); } return transformed; } -std::unordered_set get_pawn_start_flags(std::unordered_set moves){ - std::unordered_set transformed; +std::vector get_pawn_start_flags(std::vector moves){ + std::vector transformed; for (int mv : moves){ std::cout << "MOVE: \n"; - transformed.insert(get_pawn_st_flag(mv)); + transformed.push_back(get_pawn_st_flag(mv)); } return transformed; } -std::unordered_set get_castle_flags(std::unordered_set moves){ - std::unordered_set transformed; +std::vector get_castle_flags(std::vector moves){ + std::vector transformed; for (int mv : moves){ - transformed.insert(get_castle_flag(mv)); + transformed.push_back(get_castle_flag(mv)); } return transformed; } diff --git a/tests/test_functions.h b/tests/test_functions.h index d427f0e..3bb71ea 100644 --- a/tests/test_functions.h +++ b/tests/test_functions.h @@ -1,12 +1,12 @@ #ifndef TEST_FUNCTIONS_H #define TEST_FUNCTOPMS_H -#include +#include -std::unordered_set get_from_squares(std::unordered_set moves); -std::unordered_set get_to_squares(std::unordered_set moves); -std::unordered_set get_captured_pieces(std::unordered_set moves); -std::unordered_set get_promoted_pieces(std::unordered_set moves); -std::unordered_set get_en_passant_flags(std::unordered_set moves); -std::unordered_set get_pawn_start_flags(std::unordered_set moves); -std::unordered_set get_castle_flags(std::unordered_set moves); +std::vector get_from_squares(std::vector moves); +std::vector get_to_squares(std::vector moves); +std::vector get_captured_pieces(std::vector moves); +std::vector get_promoted_pieces(std::vector moves); +std::vector get_en_passant_flags(std::vector moves); +std::vector get_pawn_start_flags(std::vector moves); +std::vector get_castle_flags(std::vector moves); #endif diff --git a/tests/valid_moves.h b/tests/valid_moves.h index ca759ae..a519e07 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -1,21 +1,21 @@ -#include +#include #include /// This is for possible moves on a default board -const std::unordered_set DEFAULT_B_A_PAWN_POSSIBLE_MOVES = { +const std::vector DEFAULT_B_A_PAWN_POSSIBLE_MOVES = { A6, A5 }; -const std::unordered_set DEFAULT_W_A_PAWN_POSSIBLE_MOVES = { +const std::vector DEFAULT_W_A_PAWN_POSSIBLE_MOVES = { A3, A4 }; -const std::unordered_set DEFAULT_W_R_KNIGHT_POSSIBLE_MOVES = { +const std::vector DEFAULT_W_R_KNIGHT_POSSIBLE_MOVES = { H3, F3 }; // EMPTY -const std::unordered_set DEFAULT_W_R_ROOK_POSSIBLE_MOVES = {}; +const std::vector DEFAULT_W_R_ROOK_POSSIBLE_MOVES = {}; -const std::unordered_set B_PAWNS_SQUARES = { +const std::vector B_PAWNS_SQUARES = { A7, B7, C7, D7, E7, F7, G7, H7 }; @@ -37,7 +37,7 @@ const std::array KNIGHT_BLOCKED1_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; // Should NOT inclde D7 -const std::unordered_set KNIGHT_BLOCKED1_MOVES = { +const std::vector KNIGHT_BLOCKED1_MOVES = { A6, C6 }; @@ -57,7 +57,7 @@ const std::array BISHOP_BLOCKED1_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; // Should NOT include A8, H8, G2, or H1 -const std::unordered_set BISHOP_BLOCKED1_MOVES = { +const std::vector BISHOP_BLOCKED1_MOVES = { B7, C6,E6, C4,E4, @@ -65,7 +65,7 @@ const std::unordered_set BISHOP_BLOCKED1_MOVES = { A2 }; // Should NOT include B2 (black queen) as it is obstructed by the bishop on D5 -const std::unordered_set BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING = { +const std::vector BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING = { D5 }; const int BISHOP_BLOCKED1_KING_POS = F3; @@ -87,7 +87,7 @@ const std::array ROOK_BLOCKED1_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; // Should NOT include E-H2 or B3-1 -const std::unordered_set ROOK_BLOCKED1_MOVES = { +const std::vector ROOK_BLOCKED1_MOVES = { B8, A7, C7, D7, B6,B5,B4 @@ -108,7 +108,7 @@ 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 }; -const std::unordered_set PAWN_DIAG_TEST1_MOVES = { +const std::vector PAWN_DIAG_TEST1_MOVES = { D6, E6, E5 }; @@ -128,7 +128,7 @@ 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 }; -const std::unordered_set ROOK_CHECK_TEST_MOVES = { +const std::vector ROOK_CHECK_TEST_MOVES = { C5, E5 }; @@ -147,7 +147,7 @@ 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 }; -const std::unordered_set PAWN_CHECK_TEST_MOVES = {E6, E5}; +const std::vector PAWN_CHECK_TEST_MOVES = {E6, E5}; // These boards tests for en pessent squares. @@ -167,7 +167,7 @@ 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 }; -const std::unordered_set EN_PASSANT_TEST_MOVES = { +const std::vector EN_PASSANT_TEST_MOVES = { E6, D6 }; @@ -186,4 +186,4 @@ 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 }; -const std::unordered_set NO_EN_PASSANT_TEST_MOVES = {D6}; +const std::vector NO_EN_PASSANT_TEST_MOVES = {D6}; From e06887fe8fb85a53da286d02bfd5a3f51231f257 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Wed, 24 Apr 2019 01:08:18 +0000 Subject: [PATCH 41/81] Fix order of possible moves --- tests/B_test_boards.h | 34 +++++++++++++--------------------- tests/W_test_boards.h | 33 ++++++++++++--------------------- tests/valid_moves.h | 4 ++-- 3 files changed, 27 insertions(+), 44 deletions(-) diff --git a/tests/B_test_boards.h b/tests/B_test_boards.h index 5cff8c2..7606959 100644 --- a/tests/B_test_boards.h +++ b/tests/B_test_boards.h @@ -18,14 +18,14 @@ const std::array B_QUEEN_BOARD = { }; const std::vector B_QUEEN_ALL_MOVES = { - A8, E8, - B7, E7, H7, - C6, E6, G6, - D5, E5, F5, - A4, B4, C4, D4, F4, G4, H4, - D3, E3, F3, - C2, E2, G2, - B1, E1, H1 + 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 B_BISHOP_POS = D4; @@ -45,13 +45,7 @@ const std::array B_BISHOP_BOARD = { }; const std::vector B_BISHOP_ALL_MOVES = { - H8, - A7, G7, - B6, F6, - C5, E5, - C3, E3, - B2, F2, - A1, G1 + C5, B6, A7, E5, F6, G7, H8, C3, B2, A1, E3, F2, G1 }; const int B_KNIGHT_POS = D5; @@ -71,10 +65,7 @@ const std::array B_KNIGHT_BOARD = { }; const std::vector B_KNIGHT_ALL_MOVES = { - C7, E7, - B6, F6, - B4, F4, - C3, E3 + B6, C7, E7, F6, B4, F4, C3, E3 }; const int B_ROOK_POS = E5; @@ -94,8 +85,9 @@ const std::array B_ROOK_BOARD = { }; const std::vector B_ROOK_ALL_MOVES = { - E8, E7, E6, - A5, B5, C5, D5, F5, G5, H5, + D5, C5, B5, A5, + E6, E7, E8, + F5, G5, H5, E4, E3, E2, E1 }; diff --git a/tests/W_test_boards.h b/tests/W_test_boards.h index 6372426..485a2b4 100644 --- a/tests/W_test_boards.h +++ b/tests/W_test_boards.h @@ -33,14 +33,13 @@ const std::array W_QUEEN_BOARD_BLOCKED = { }; const std::vector W_QUEEN_ALL_MOVES = { - A8, E8, - B7, E7, H7, - C6, E6, G6, - D5, E5, F5, - A4, B4, C4, D4, F4, G4, H4, - D3, E3, F3, - C2, E2, G2, - B1, E1, H1 + 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; @@ -60,13 +59,7 @@ const std::array W_BISHOP_BOARD = { }; const std::vector W_BISHOP_ALL_MOVES = { - H8, - A7, G7, - B6, F6, - C5, E5, - C3, E3, - B2, F2, - A1, G1 + C5, B6, A7, E5, F6, G7, H8, C3, B2, A1, E3, F2, G1 }; const int W_KNIGHT_POS = D5; @@ -107,10 +100,7 @@ const std::vector W_KNIGHT_SIDE1_ALL_MOVES = { }; const std::vector W_KNIGHT_ALL_MOVES = { - C7, E7, - B6, F6, - B4, F4, - C3, E3 + B6, C7, E7, F6, B4, F4, C3, E3 }; const int W_ROOK_POS = E5; @@ -130,8 +120,9 @@ const std::array W_ROOK_BOARD = { }; const std::vector W_ROOK_ALL_MOVES = { - E8, E7, E6, - A5, B5, C5, D5, F5, G5, H5, + D5, C5, B5, A5, + E6, E7, E8, + F5, G5, H5, E4, E3, E2, E1 }; diff --git a/tests/valid_moves.h b/tests/valid_moves.h index a519e07..703fa17 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -109,7 +109,7 @@ const std::array PAWN_DIAG_TEST1_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; const std::vector PAWN_DIAG_TEST1_MOVES = { - D6, E6, E5 + E6, E5, D6 }; // For testing the invalidating of moves because of putting own king in check @@ -168,7 +168,7 @@ const std::array EN_PASSANT_TEST_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; const std::vector EN_PASSANT_TEST_MOVES = { - E6, D6 + D6, E6 }; const int NO_EN_PASSANT_TEST_POS = D5; From 14b15087d2afdd5917d78a655cc89242e0f41085 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Wed, 24 Apr 2019 04:38:22 +0000 Subject: [PATCH 42/81] Remove cout --- tests/test_functions.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_functions.cpp b/tests/test_functions.cpp index 4b2c538..fdef10f 100644 --- a/tests/test_functions.cpp +++ b/tests/test_functions.cpp @@ -41,7 +41,6 @@ std::vector get_en_passant_flags(std::vector moves){ std::vector get_pawn_start_flags(std::vector moves){ std::vector transformed; for (int mv : moves){ - std::cout << "MOVE: \n"; transformed.push_back(get_pawn_st_flag(mv)); } return transformed; From 5b7e16c081688dec69f3d3f9d1dc942cf1661ff5 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Wed, 24 Apr 2019 16:25:50 +0000 Subject: [PATCH 43/81] Pawn promotions addad. --- src/all_moves_functions.cpp | 40 +++++++++++++++----- src/bitwise.h | 12 +++--- tests/Makefile | 6 +++ tests/custom_printing.cpp | 4 +- tests/main.cpp | 14 ++++++- tests/valid_moves.h | 74 +++++++++++++++++++++++++++++++++++++ 6 files changed, 131 insertions(+), 19 deletions(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index b918e79..72e1d89 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -51,21 +51,39 @@ void _add_if_not_blocked(int pos, int from, std::vector *pns, std::array *pns, std::array *board, Color color_of_piece, Color color_of_opposite, int en_passant){ - if (is_valid_position(pos) && (_xy_is_color(pos, board, color_of_opposite) || - pos == en_passant)){ - pns->push_back(make_move(from, pos)); +void _pawn_diag_add_if_not_blocked(int pos, int from, std::vector *pns, std::array *board, Color color_of_piece, Color color_of_opposite, int en_passant, int promoting){ + if (is_valid_position(pos)){ + if (_xy_is_color(pos, board, color_of_opposite)){ + if (promoting){ + if (color_of_piece == Color::WHITE){ + pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::W_KNIGHT)); + pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::W_BISHOP)); + pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::W_ROOK)); + pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::W_QUEEN)); + } else { + pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::B_KNIGHT)); + pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::B_BISHOP)); + pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::B_ROOK)); + pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::B_QUEEN)); + } + } else { + pns->push_back(make_move(from, pos)); + } + } else if (pos == en_passant){ + pns->push_back(make_move(from, pos, PieceType::NONE, 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, std::array *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){ +void _pawn_add_if_not_blocked(int pos, int from, std::vector *pns, std::array *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked, bool double_move){ if (*is_not_blocked){ if ((*board)[pos] != PieceType::NONE || (*board)[pos] == PieceType::INV){ *is_not_blocked = false; } else { - pns->push_back(make_move(from, pos)); + double_move?pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::NONE, PieceType::NONE, 1)):pns->push_back(make_move(from, pos)); } } } @@ -159,14 +177,16 @@ void _get_all_moves_pawn(int pos, std::vector *pns, std::array 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); +} diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 703fa17..73f12b2 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -170,6 +170,56 @@ const std::array EN_PASSANT_TEST_BOARD = { const std::vector EN_PASSANT_TEST_MOVES = { D6, E6 }; +// 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 +}; + +// 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 int NO_EN_PASSANT_TEST_POS = D5; const std::array NO_EN_PASSANT_TEST_BOARD = { @@ -187,3 +237,27 @@ const std::array NO_EN_PASSANT_TEST_BOARD = { 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 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 +}; + +// Should NOT inclde D7 +const std::vector CASTLING_MOVES = { + D1, D2, E2, F2, F1, + C1, G1 +}; + From 424a0fe7d00b675d84cfb4f4d814805d50ba00a3 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Wed, 24 Apr 2019 16:49:22 +0000 Subject: [PATCH 44/81] Fix left side of board showing 9-2, instead of 8-1 --- tests/custom_printing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/custom_printing.cpp b/tests/custom_printing.cpp index 58971e2..3866eee 100644 --- a/tests/custom_printing.cpp +++ b/tests/custom_printing.cpp @@ -52,7 +52,7 @@ namespace Catch { ss << "{ {" << std::endl; ss << files << std::endl; for (int i = 2; i < 10; ++i){ - ss << 9-(i-2) << "|"; + 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. From ed39d8aefb365b403a0fd6aa0d008d17e09e674d Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Thu, 25 Apr 2019 03:20:47 +0000 Subject: [PATCH 45/81] Castling moves showing properly. Become invalid if in check on square or square before castling square. --- src/all_moves_functions.cpp | 50 ++++++++++++++-- src/bitwise.h | 20 ++++++- src/constants.h | 7 +++ src/functions.cpp | 110 ++++++++++++++++++++---------------- src/functions.h | 8 ++- tests/B_test_boards.h | 7 +-- tests/W_test_boards.h | 8 +-- tests/main.cpp | 25 ++++++++ tests/valid_moves.h | 87 ++++++++++++++++++++++++++-- 9 files changed, 249 insertions(+), 73 deletions(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index 72e1d89..000927f 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -6,7 +6,7 @@ const std::array ROOK_PIECE_OFFSETS = {-1, -10, 1, 10}; const std::array BISHOP_PIECE_OFFSETS = {-11, -9, 9, 11}; const std::array KNIGHT_PIECE_OFFSETS = {-12, -21, -19, -8, 8, 12, 19, 21}; -const std::array KING_PIECE_OFFSETS = {-11, -10, -9, -1, 1, 9, 10, 11}; +const std::array KING_PIECE_OFFSETS = {-11, -10, -9, 9, 10, 11}; inline Position _pair_to_pos_unsafe(int x, int y){ @@ -39,6 +39,26 @@ void _add_if_not_blocked(int pos, int from, std::vector *pns, std::array *pns, 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, PieceType::NONE, PieceType::NONE, 0, 0, castle_flag)); + *is_not_blocked = false; + } else { + pns->push_back(make_move(from, pos, PieceType::NONE, 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, std::array *board, Color color_of_piece, Color color_of_opposite){ if (!is_valid_position(pos) || @@ -138,7 +158,6 @@ void _get_all_moves_bishop(int pos, std::vector *pns, std::array *pns, std::array* board, Color pc, Color rc){ for (int kn_off : KNIGHT_PIECE_OFFSETS){ - bool* not_blocked = new bool(true); _add_if_not_blocked(pos+kn_off, pos, pns, board, pc, rc); } /* @@ -152,13 +171,32 @@ void _get_all_moves_knight(int pos, std::vector *pns, std::array *pns, std::array* board, Color pc, Color rc){ +void _get_all_moves_king(int pos, std::vector *pns, std::array* board, Color pc, Color rc, int castle_perms){ for (int kn_off : KING_PIECE_OFFSETS){ - bool* not_blocked = new bool(true); _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); + 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){ + _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){ + _king_add_if_not_blocked(pos-2, pos, pns, board, pc, rc, left_castle, 1); + } + } /* _add_if_not_blocked(x+1, y+1, pns, board, pc, rc); _add_if_not_blocked(x+1, y-1, pns, board, pc, rc); diff --git a/src/bitwise.h b/src/bitwise.h index 7e0d109..ad9d4ef 100644 --- a/src/bitwise.h +++ b/src/bitwise.h @@ -61,12 +61,28 @@ inline bool is_valid_position(int position){ return DEFAULT_BOARD[position] != PieceType::INV; } -inline int set_to_sq(int sq, int base){ - return base + (sq << 7); +// 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; diff --git a/src/constants.h b/src/constants.h index a35fcc2..25361a9 100644 --- a/src/constants.h +++ b/src/constants.h @@ -11,6 +11,13 @@ enum Color { BLACK }; +enum CastlePerms { + BQS=0b1, + BKS=0b10, + WQS=0b100, + WKS=0b1000 +}; + enum PieceType { INV=-1, NONE, diff --git a/src/functions.cpp b/src/functions.cpp index a405c68..d5292b5 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -40,7 +40,7 @@ Color get_color(PieceType pt){ return Color::NO_COLOR; } -Color get_color(Position pn, std::array const *board){ +Color get_color(int pn, std::array const *board){ return get_color((*board)[pn]); } @@ -54,12 +54,6 @@ std::vector get_possible_movers(Position pn, std::array boa return pns; } -std::vector get_possible_moves(Position pn, std::array board){ - std::vector pns = {Position::A1}; - get_all_moves(pn, &board, &pns); - return pns; -} - int get_pos_of(PieceType pt, std::array const *board){ for (int pn = Position::A8; pn!=Position::H1; pn++){ if ((*board)[pn] == pt){ @@ -87,56 +81,70 @@ void get_poss_of(PieceType pt, std::array* board, std::vector board){ + PieceType ptt = board[pos]; + Color pc = get_color(ptt); + auto other_pieces = pc==Color::WHITE?Pieces::BLACK:Pieces::WHITE; + for (PieceType pt : other_pieces){ + for (int pos_of_other : get_poss_of(pt, &board)) { + for (int possible_takes : get_all_moves(pos_of_other, board, false)){ + if (get_to_sq(possible_takes) == pos) { + return true; + } + } + } + } + return false; +} + //TODO: Make faster by running from king squar eonly, instead of running on every piece of opposite team. void filter_checked_moves(PieceType pt, 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); int attackers = 0; for (auto p_pn= pns->begin(); p_pn!=pns->end();){ - // Make move - std::array moved_board = dumb_move(*p_pn, *board); - // Get all piecetypes of other team - std::array other_team = is_white(pt)?Pieces::BLACK:Pieces::WHITE; - bool checks_king = false; - // go through each piece of other team - for (PieceType other_p : other_team) { - checks_king = false; - // For every place the piecetype is - // NEW CODE -// for (Position psn : get_all_moves(my_king_pos, moved_board, false)){ -// -// } - // \NEW CODE - std::vector psns; - get_poss_of(other_p, &moved_board, &psns); - for (auto psn : psns){ - std::vector other_moves; - get_all_moves(psn, &moved_board, &other_moves, false); - // for every position the piece can mvoe to - for (int cp : other_moves){ - if (get_to_sq(cp) == my_king_pos){ - checks_king = true; - attackers++; - break; - } - } - if (checks_king){ + if (get_castle_flag(*p_pn)){ + // If moved left + // B1 - A1 = -1 + // A1 - B1 = +1 + if ((get_from_sq(*p_pn) - get_to_sq(*p_pn)) > 0){ + int right_move = make_move(get_from_sq(*p_pn), get_to_sq(*p_pn)+1); + auto right_board = dumb_move(right_move, *board); + if (is_checked(get_to_sq(*p_pn)+1, right_board)){ + p_pn = pns->erase(p_pn); + } else { + ++p_pn; break; } + } else { + int left_move = make_move(get_from_sq(*p_pn), get_to_sq(*p_pn)-1); + auto left_board = dumb_move(left_move, *board); + if (is_checked(get_to_sq(*p_pn)-1, left_board)){ + p_pn = pns->erase(p_pn); + } else { + ++p_pn; + continue; + } } - if (checks_king){ - break; - } - } - if (checks_king){ - p_pn = pns->erase(p_pn); } else { - ++p_pn; + // Make move + std::array moved_board = dumb_move(*p_pn, *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_checked(my_king_pos, moved_board)){ + p_pn = pns->erase(p_pn); + } else { + ++p_pn; + } } } } -void get_all_moves(int pos, std::array* board, std::vector* moves, bool recursive, int en_passant){ +void get_all_moves(int pos, std::array* board, std::vector* moves, bool recursive, int en_passant, int castle_perms){ PieceType pt = (*board)[pos]; Color color_of_piece = get_color(pt); Color color_of_opponent = rev_color(color_of_piece); @@ -160,7 +168,7 @@ void get_all_moves(int pos, std::array* board, std::vector* break; case PieceType::B_KING: case PieceType::W_KING: - _get_all_moves_king(pos, moves, board, color_of_piece, color_of_opponent); + _get_all_moves_king(pos, moves, board, color_of_piece, color_of_opponent, castle_perms); break; case PieceType::B_PAWN: case PieceType::W_PAWN: @@ -174,17 +182,19 @@ void get_all_moves(int pos, std::array* board, std::vector* } } -std::vector get_all_moves(int pos, std::array board, bool recursive, int en_passant){ +std::vector get_all_moves(int pos, std::array board, bool recursive, int en_passant, int castle_perms){ std::vector moves; - get_all_moves(pos, &board, &moves, recursive, en_passant); + get_all_moves(pos, &board, &moves, recursive, en_passant, castle_perms); return moves; } std::array dumb_move(int move, std::array board){ + std::array new_board; + std::copy(std::begin(board), std::end(board), std::begin(new_board)); int from = get_from_sq(move); int to = get_to_sq(move); - PieceType piece = board[from]; - board[to] = piece; - board[from] = PieceType::NONE; - return board; + PieceType piece = new_board[from]; + new_board[to] = piece; + new_board[from] = PieceType::NONE; + return new_board; } diff --git a/src/functions.h b/src/functions.h index f5ac4cd..cb4fbb4 100644 --- a/src/functions.h +++ b/src/functions.h @@ -22,7 +22,7 @@ Rank get_rank(int pos); bool is_white(PieceType pt); bool is_black(PieceType pt); -Color get_color(Position pn, std::array const *board); +Color get_color(int pn, std::array const *board); Color get_color(PieceType pt); // NO_COLOR returns NO_COLOR // WHITE returns BLACK @@ -42,10 +42,12 @@ void get_possible_moves(Position pn, std::array *pt,std::vector< void filter_checked_moves(int pos, std::array *board, std::vector *moves); // Get all moves for piece in Position pn. -void get_all_moves(int pos, std::array *pt,std::vector *moves, bool recursive=true, int en_passant=Position::NA); -std::vector get_all_moves(int pos, std::array board, bool recursive=true, int en_passant=Position::NA); +void get_all_moves(int pos, 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, std::array board, bool recursive=true, int en_passant=Position::NA, int castle_perms=0); // Dumb function to do board moves. // Does not check if move is valid, just does it. std::array dumb_move(int move, std::array board); +// Decides if there this piece in position is in check +bool is_checked(int pos, std::array board); diff --git a/tests/B_test_boards.h b/tests/B_test_boards.h index 7606959..b218031 100644 --- a/tests/B_test_boards.h +++ b/tests/B_test_boards.h @@ -110,8 +110,8 @@ const std::array B_KING_BOARD = { const std::vector B_KING_ALL_MOVES = { B5, C5, D5, - B4, D4, - B3, C3, D3 + B3, C3, D3, + D4, B4 }; @@ -170,8 +170,7 @@ const std::array B_KING_SIDE1_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; const std::vector B_KING_SIDE1_ALL_MOVES = { - B8, - A7,B7 + A7,B7,B8 }; const int B_PAWN_SIDE1_POS = A7; diff --git a/tests/W_test_boards.h b/tests/W_test_boards.h index 485a2b4..4b53c26 100644 --- a/tests/W_test_boards.h +++ b/tests/W_test_boards.h @@ -160,14 +160,14 @@ const std::array W_KING_SIDE1_BOARD = { }; const std::vector W_KING_SIDE1_ALL_MOVES = { - B8, - A7,B7 + A7,B7, + B8 }; const std::vector W_KING_ALL_MOVES = { B5, C5, D5, - B4, D4, - B3, C3, D3 + B3, C3, D3, + D4, B4 }; diff --git a/tests/main.cpp b/tests/main.cpp index 0860776..0152245 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -103,6 +103,16 @@ TEST_CASE("Test all moves for black in edge cases.", "[get_all_moves][black]"){ 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_checked]"){ + 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_checked(KING_CHECK_TEST_POS, KING_CHECK_TEST_BOARD)); + CHECK(is_checked(BLACK_CHECK_POS1, BLACK_CHECK_BOARD1)); + CHECK(is_checked(BLACK_CHECK_POS2, BLACK_CHECK_BOARD2)); +} + TEST_CASE("Test that moves that put 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); @@ -128,3 +138,18 @@ TEST_CASE("Test for pawn promotions.", "[get_all_moves]"){ CHECK(get_to_squares(bprom_moves) == PROM_BPAWN_MOVES); CHECK(get_promoted_pieces(bprom_moves) == PROM_BPAWN_PROMS); } + +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); +} diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 73f12b2..4e6f284 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -119,7 +119,7 @@ const std::array ROOK_CHECK_TEST_BOARD = { 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, 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, @@ -240,6 +240,7 @@ 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, @@ -255,9 +256,87 @@ const std::array CASTLING_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -// Should NOT inclde D7 const std::vector CASTLING_MOVES = { - D1, D2, E2, F2, F1, - C1, G1 + D2, E2, F2, F1, + D1, G1, C1 +}; +const std::vector BCASTLING_MOVES = { + D7, E7, F7, F8, D8, G8, C8 }; +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 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, 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 KING_CHECK_TEST_MOVES = { + C7, E7, + D5, + E6, C6 +}; +const std::vector KING_CHECK_ROOK_MOVES = { + C5, B5, A5, + D6, E5, F5, + D4, D3, D2, D1 +}; From c0a05a17bd0dfae42ee0d230deb1024a743a2220 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Thu, 25 Apr 2019 16:34:27 +0000 Subject: [PATCH 46/81] Make en passant moves work properly in the dumb_move function --- src/functions.cpp | 22 +++++++- tests/main.cpp | 8 +++ tests/valid_moves.h | 132 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 2 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index d5292b5..8837f4c 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -191,10 +191,28 @@ std::vector get_all_moves(int pos, std::array board, bool r std::array dumb_move(int move, 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 from = get_from_sq(move); int to = get_to_sq(move); PieceType piece = new_board[from]; - new_board[to] = piece; - new_board[from] = PieceType::NONE; + 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 { + new_board[to] = piece; + new_board[from] = PieceType::NONE; + } return new_board; } diff --git a/tests/main.cpp b/tests/main.cpp index 0152245..70ea985 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -3,6 +3,7 @@ #include "valid_moves.h" #include "custom_printing.cpp" #include "test_functions.h" +#include #include #include @@ -153,3 +154,10 @@ TEST_CASE("Test for castling moves.", "[get_all_moves]"){ CHECK(get_to_squares(bcast_checked_moves) == BCASTLING_CHECK_MOVES); CHECK(get_castle_flags(bcast_checked_moves) == checked_cast_flags); } + +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); +} diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 4e6f284..0fe497c 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -340,3 +340,135 @@ const std::vector KING_CHECK_ROOK_MOVES = { 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, 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_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, 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 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, 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 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, 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 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, 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, 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, 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, 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, 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, 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, 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, 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 +}; + + + From b53c46cb63b382baa24e4591887a4746e0504998 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Thu, 25 Apr 2019 17:25:52 +0000 Subject: [PATCH 47/81] Disallow queenside casle when the rook is blocked --- src/all_moves_functions.cpp | 4 +- src/functions.cpp | 21 ++++++- tests/main.cpp | 12 ++++ tests/valid_moves.h | 122 ++++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 3 deletions(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index 000927f..34e0a2f 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -184,7 +184,7 @@ void _get_all_moves_king(int pos, std::vector *pns, std::array *pns, std::array dumb_move(int move, 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]; @@ -210,7 +211,25 @@ std::array dumb_move(int move, std::array board) new_board[other_pawn_pos] = PieceType::NONE; new_board[to] = piece; new_board[from] = PieceType::NONE; - } else { + } 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; } diff --git a/tests/main.cpp b/tests/main.cpp index 70ea985..a358a75 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -153,6 +153,11 @@ TEST_CASE("Test for castling moves.", "[get_all_moves]"){ 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"){ @@ -161,3 +166,10 @@ TEST_CASE("Test that en passant moves are properly handled by dumb_move", "dumb_ 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); +} diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 0fe497c..32c970c 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -311,6 +311,128 @@ 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 From 1920250a25e6272b9e4515f853de03ffbe07e891 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Thu, 25 Apr 2019 18:16:18 +0000 Subject: [PATCH 48/81] Put captured piece in move int --- src/all_moves_functions.cpp | 32 +++++++++++++++---------------- tests/main.cpp | 22 +++++++++++++++++++++ tests/valid_moves.h | 38 +++++++++++++++++++++++++++++-------- 3 files changed, 68 insertions(+), 24 deletions(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index 34e0a2f..1c33ede 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -31,10 +31,10 @@ void _add_if_not_blocked(int pos, int from, std::vector *pns, std::arraypush_back(make_move(from, pos)); + pns->push_back(make_move(from, pos, (*board)[pos])); *is_not_blocked = false; } else { - pns->push_back(make_move(from, pos)); + pns->push_back(make_move(from, pos, (*board)[pos])); } } } @@ -49,10 +49,10 @@ void _king_add_if_not_blocked(int pos, int from, std::vector *pns, std::arr 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, PieceType::NONE, PieceType::NONE, 0, 0, castle_flag)); + pns->push_back(make_move(from, pos, (*board)[pos], PieceType::NONE, 0, 0, castle_flag)); *is_not_blocked = false; } else { - pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::NONE, 0, 0, castle_flag)); + pns->push_back(make_move(from, pos, (*board)[pos], PieceType::NONE, 0, 0, castle_flag)); } } } @@ -65,7 +65,7 @@ void _add_if_not_blocked(int pos, int from, std::vector *pns, std::arraypush_back(make_move(from, pos)); + pns->push_back(make_move(from, pos, (*board)[pos])); } } @@ -76,21 +76,21 @@ void _pawn_diag_add_if_not_blocked(int pos, int from, std::vector *pns, std if (_xy_is_color(pos, board, color_of_opposite)){ if (promoting){ if (color_of_piece == Color::WHITE){ - pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::W_KNIGHT)); - pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::W_BISHOP)); - pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::W_ROOK)); - pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::W_QUEEN)); + pns->push_back(make_move(from, pos, (*board)[pos], PieceType::W_KNIGHT)); + pns->push_back(make_move(from, pos, (*board)[pos], PieceType::W_BISHOP)); + pns->push_back(make_move(from, pos, (*board)[pos], PieceType::W_ROOK)); + pns->push_back(make_move(from, pos, (*board)[pos], PieceType::W_QUEEN)); } else { - pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::B_KNIGHT)); - pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::B_BISHOP)); - pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::B_ROOK)); - pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::B_QUEEN)); + pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_KNIGHT)); + pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_BISHOP)); + pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_ROOK)); + pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_QUEEN)); } } else { - pns->push_back(make_move(from, pos)); + pns->push_back(make_move(from, pos, (*board)[pos])); } } else if (pos == en_passant){ - pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::NONE, 1)); + pns->push_back(make_move(from, pos, (*board)[en_passant], PieceType::NONE, 1)); } } } @@ -103,7 +103,7 @@ void _pawn_add_if_not_blocked(int pos, int from, std::vector *pns, std::arr (*board)[pos] == PieceType::INV){ *is_not_blocked = false; } else { - double_move?pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::NONE, PieceType::NONE, 1)):pns->push_back(make_move(from, pos)); + double_move?pns->push_back(make_move(from, pos, (*board)[pos], PieceType::NONE, 0, 1)):pns->push_back(make_move(from, pos, (*board)[pos])); } } } diff --git a/tests/main.cpp b/tests/main.cpp index a358a75..9a8e297 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -140,6 +140,28 @@ TEST_CASE("Test for pawn promotions.", "[get_all_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); + 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); +} + +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); diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 32c970c..421e162 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -40,6 +40,9 @@ const std::array KNIGHT_BLOCKED1_BOARD = { const std::vector KNIGHT_BLOCKED1_MOVES = { A6, C6 }; +const std::vector KNIGHT_BLOCKED1_CAPTS = { + NONE, W_PAWN +}; const int BISHOP_BLOCKED1_POS = D5; const std::array BISHOP_BLOCKED1_BOARD = { @@ -58,11 +61,16 @@ const std::array BISHOP_BLOCKED1_BOARD = { }; // Should NOT include A8, H8, G2, or H1 const std::vector BISHOP_BLOCKED1_MOVES = { - B7, - C6,E6, - C4,E4, - B3,F3, - A2 + C6, B7, + E6, + C4, B3, A2, + E4, F3 +}; +const std::vector BISHOP_BLOCKED1_CAPTS = { + NONE, B_QUEEN, + NONE, + NONE, NONE, NONE, + NONE, B_KING, }; // 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 = { @@ -70,7 +78,6 @@ const std::vector BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING = { }; 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, @@ -88,9 +95,16 @@ const std::array ROOK_BLOCKED1_BOARD = { }; // Should NOT include E-H2 or B3-1 const std::vector ROOK_BLOCKED1_MOVES = { + A7, B8, - A7, C7, D7, - B6,B5,B4 + C7, D7, + B6, B5, B4 +}; +const std::vector ROOK_BLOCKED1_CAPTS = { + NONE, + NONE, + NONE, B_PAWN, + NONE, NONE, NONE }; const int PAWN_DIAG_TEST1_POS = E7; @@ -111,6 +125,9 @@ const std::array PAWN_DIAG_TEST1_BOARD = { const std::vector PAWN_DIAG_TEST1_MOVES = { E6, E5, D6 }; +const std::vector PAWN_DIAG_TEST1_CAPTS = { + NONE, NONE, W_QUEEN +}; // For testing the invalidating of moves because of putting own king in check const int ROOK_CHECK_TEST_POS = D5; @@ -457,6 +474,11 @@ const std::vector KING_CHECK_TEST_MOVES = { D5, E6, C6 }; +const std::vector KING_CHECK_TEST_CAPTS = { + NONE, NONE, + B_ROOK, + NONE, NONE +}; const std::vector KING_CHECK_ROOK_MOVES = { C5, B5, A5, D6, E5, F5, From ffa404f0cb91a8bfb723cfb6dcf3e4a975a5f691 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Thu, 25 Apr 2019 22:03:00 +0000 Subject: [PATCH 49/81] Partial implementation of agebraic notation. --- src/all_moves_functions.cpp | 7 ++++-- src/constants.h | 16 ++++++------ src/functions.cpp | 50 +++++++++++++++++++++++++++++++++++++ src/functions.h | 5 ++++ tests/main.cpp | 20 +++++++++++++++ tests/test_functions.cpp | 11 +++++++- tests/test_functions.h | 4 +++ tests/valid_moves.h | 39 ++++++++++++++++++++++++++--- 8 files changed, 138 insertions(+), 14 deletions(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index 1c33ede..5d7bd28 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -84,13 +84,16 @@ void _pawn_diag_add_if_not_blocked(int pos, int from, std::vector *pns, std pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_KNIGHT)); pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_BISHOP)); pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_ROOK)); - pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_QUEEN)); + pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_QUEEN)); } } else { pns->push_back(make_move(from, pos, (*board)[pos])); } } else if (pos == en_passant){ - pns->push_back(make_move(from, pos, (*board)[en_passant], PieceType::NONE, 1)); + // 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)); } } } diff --git a/src/constants.h b/src/constants.h index 25361a9..034d51d 100644 --- a/src/constants.h +++ b/src/constants.h @@ -46,14 +46,14 @@ enum Position { 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", "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" }; diff --git a/src/functions.cpp b/src/functions.cpp index 79158e2..51da313 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -1,6 +1,7 @@ #include "bitwise.h" #include "functions.h" #include "all_moves_functions.cpp" +#include #include #include #include @@ -235,3 +236,52 @@ std::array dumb_move(int move, std::array board) } return new_board; } + +std::string to_notation(int move, std::array *board){ + std::stringstream ss; + + int from = get_from_sq(move); + std::string from_string = POSITION_STRING[from]; + int to = get_to_sq(move); + int captured_piece = get_captured_pc(move); + std::string piece_character = ""; + std::string capture_character = ""; + int piecetype = (*board)[from]; + switch(piecetype){ + case PieceType::W_KNIGHT: + case PieceType::B_KNIGHT: + piece_character = "N"; + break; + case PieceType::W_BISHOP: + case PieceType::B_BISHOP: + piece_character = "B"; + break; + case PieceType::W_ROOK: + case PieceType::B_ROOK: + piece_character = "R"; + break; + case PieceType::W_QUEEN: + case PieceType::B_QUEEN: + piece_character = "Q"; + break; + case PieceType::W_KING: + case PieceType::B_KING: + piece_character = "K"; + break; + } + if (captured_piece > 0){ + capture_character = "x"; + // If is a pawn + } + if (get_en_pass_flag(move) == 1){ + if (piece_character == ""){ + ss << from_string[0]; + } + } + if (get_castle_flag(move) == 1){ + return to-from<0 ? "O-O-O" : "O-O"; + } else { + ss << piece_character << capture_character << POSITION_STRING[to]; + } + return ss.str(); +} diff --git a/src/functions.h b/src/functions.h index cb4fbb4..67bb18e 100644 --- a/src/functions.h +++ b/src/functions.h @@ -1,4 +1,5 @@ #include "constants.h" +#include #include #include #include @@ -51,3 +52,7 @@ std::array dumb_move(int move, std::array board) // Decides if there this piece in position is in check bool is_checked(int pos, std::array board); + +// Convert move (and board becuase notation needs more info than the move itself) +// ...into algbraic notation. +std::string to_notation(int move, std::array *board); diff --git a/tests/main.cpp b/tests/main.cpp index 9a8e297..b7cd1ba 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -195,3 +195,23 @@ TEST_CASE("Test that castle moves are poperly handled by dumb_mobe", "[dumb_move 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); + + 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); +} diff --git a/tests/test_functions.cpp b/tests/test_functions.cpp index fdef10f..e36f434 100644 --- a/tests/test_functions.cpp +++ b/tests/test_functions.cpp @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include std::vector get_to_squares(std::vector moves){ std::vector transformed; @@ -52,4 +55,10 @@ std::vector get_castle_flags(std::vector moves){ } return transformed; } - +std::vector get_notations(std::vector moves, 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 index 3bb71ea..50311a9 100644 --- a/tests/test_functions.h +++ b/tests/test_functions.h @@ -1,6 +1,9 @@ #ifndef TEST_FUNCTIONS_H #define TEST_FUNCTOPMS_H +#include #include +#include +#include std::vector get_from_squares(std::vector moves); std::vector get_to_squares(std::vector moves); @@ -9,4 +12,5 @@ std::vector get_promoted_pieces(std::vector moves); std::vector get_en_passant_flags(std::vector moves); std::vector get_pawn_start_flags(std::vector moves); std::vector get_castle_flags(std::vector moves); +std::vector get_notations(std::vector moves, std::array board); #endif diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 421e162..acdca78 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -1,4 +1,5 @@ #include +#include #include @@ -43,6 +44,9 @@ const std::vector KNIGHT_BLOCKED1_MOVES = { 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 = { @@ -72,6 +76,13 @@ const std::vector BISHOP_BLOCKED1_CAPTS = { 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 @@ -106,6 +117,12 @@ const std::vector ROOK_BLOCKED1_CAPTS = { 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 = { @@ -128,6 +145,9 @@ const std::vector PAWN_DIAG_TEST1_MOVES = { const std::vector PAWN_DIAG_TEST1_CAPTS = { NONE, NONE, W_QUEEN }; +const std::vector PAWN_DIAG_TEST1_NOTATION = { + "e6", "e5", "xd6" +}; // For testing the invalidating of moves because of putting own king in check const int ROOK_CHECK_TEST_POS = D5; @@ -187,6 +207,9 @@ const std::array EN_PASSANT_TEST_BOARD = { const std::vector EN_PASSANT_TEST_MOVES = { D6, E6 }; +const std::vector EN_PASSANT_TEST_NOTATION = { + "d6", "dxe6" +}; // Test pawn promotion const int PROM_PAWN_POS = G7; const std::array PROM_PAWN_BOARD = { @@ -280,6 +303,14 @@ const std::vector CASTLING_MOVES = { 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, @@ -479,6 +510,11 @@ const std::vector KING_CHECK_TEST_CAPTS = { 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, @@ -613,6 +649,3 @@ 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 }; - - - From 036d41e5890acc1f9babf7698000908a81e28091 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Fri, 26 Apr 2019 19:35:15 +0000 Subject: [PATCH 50/81] Checkmate marks (#) now work. --- src/bitwise.h | 7 +++++ src/functions.cpp | 64 +++++++++++++++++++++++++++++++++++----- src/functions.h | 10 +++++-- tests/main.cpp | 43 +++++++++++++++++++++++++++ tests/valid_moves.h | 71 +++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 180 insertions(+), 15 deletions(-) diff --git a/src/bitwise.h b/src/bitwise.h index ad9d4ef..19d9da2 100644 --- a/src/bitwise.h +++ b/src/bitwise.h @@ -22,6 +22,7 @@ * 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) * */ /* OLD, DO NOT USE @@ -56,6 +57,9 @@ inline int get_pawn_st_flag(int mv){ inline int get_castle_flag(int mv){ return ((mv >> 24) & 0x1); } +inline int get_check_flag(int mv){ + return ((mv >> 25) & 0x1); +} inline bool is_valid_position(int position){ return DEFAULT_BOARD[position] != PieceType::INV; @@ -105,6 +109,9 @@ inline int make_move(int from, int to, PieceType captured, PieceType promotion, 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/functions.cpp b/src/functions.cpp index 51da313..225b578 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -22,13 +22,13 @@ Rank get_rank(int pos){ return static_cast(rank - 3); } -bool is_white(PieceType pt){ +bool is_white(int pt){ for (auto pn : Pieces::WHITE){ if (pn == pt) return true; } return false; } -bool is_black(PieceType pt){ +bool is_black(int pt){ for (auto pn : Pieces::BLACK){ if (pn == pt) return true; } @@ -49,6 +49,19 @@ 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){ + 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, std::array board){ std::vector pns = {Position::A1}; @@ -98,6 +111,18 @@ bool is_checked(int pos, std::array board){ return false; } +void add_checked_flags(PieceType pt, 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); + for (auto move_pn=pns->begin(); move_pn!=pns->end();){ + auto moved_board = dumb_move(*move_pn, *board); + if (is_checked(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, std::array *board, std::vector *pns){ PieceType my_king = is_white(pt)?PieceType::W_KING:PieceType::B_KING; @@ -145,8 +170,7 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: } } -void get_all_moves(int pos, std::array* board, std::vector* moves, bool recursive, int en_passant, int castle_perms){ - PieceType pt = (*board)[pos]; +void get_all_moves_as_if(int pos, PieceType pt, std::array* board, std::vector* moves, bool recursive, int en_passant, int castle_perms){ Color color_of_piece = get_color(pt); Color color_of_opponent = rev_color(color_of_piece); switch(pt){ @@ -180,9 +204,14 @@ void get_all_moves(int pos, std::array* board, std::vector* } if (recursive){ filter_checked_moves(pt, board, moves); + add_checked_flags(pt, board, moves); } } +void get_all_moves(int pos, 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, std::array board, bool recursive, int en_passant, int castle_perms){ std::vector moves; get_all_moves(pos, &board, &moves, recursive, en_passant, castle_perms); @@ -246,7 +275,10 @@ std::string to_notation(int move, std::array *board){ int captured_piece = get_captured_pc(move); std::string piece_character = ""; std::string capture_character = ""; - int piecetype = (*board)[from]; + std::string en_passant = ""; + std::string check = ""; + int piecetype = (*board)[from]; + auto other_pieces = is_white(piecetype)?Pieces::BLACK:Pieces::WHITE; switch(piecetype){ case PieceType::W_KNIGHT: case PieceType::B_KNIGHT: @@ -272,16 +304,32 @@ std::string to_notation(int move, std::array *board){ if (captured_piece > 0){ capture_character = "x"; // If is a pawn - } - if (get_en_pass_flag(move) == 1){ if (piece_character == ""){ ss << from_string[0]; } } + if (get_en_pass_flag(move) == 1){ + en_passant = "e.p."; + } + if (get_check_flag(move) == 1){ + check = "+"; + auto moved_board = dumb_move(move, *board); + // This checks if the other team has any valid moves. + // If not, the check sign changes to a hashtag (#). + std::vector other_moves = {}; + for (PieceType opt : other_pieces){ + for (int pos_of_opt : get_poss_of(opt, board)){ + get_all_moves(pos_of_opt, &moved_board, &other_moves); + } + } + if (other_moves.empty()){ + check = "#"; + } + } if (get_castle_flag(move) == 1){ return to-from<0 ? "O-O-O" : "O-O"; } else { - ss << piece_character << capture_character << POSITION_STRING[to]; + ss << piece_character << capture_character << POSITION_STRING[to] << en_passant << check; } return ss.str(); } diff --git a/src/functions.h b/src/functions.h index 67bb18e..ba970f1 100644 --- a/src/functions.h +++ b/src/functions.h @@ -20,8 +20,8 @@ bool is_valid_position(int pos); Rank get_rank(int pos); // Checks if given piece matches a certain color. -bool is_white(PieceType pt); -bool is_black(PieceType pt); +bool is_white(int pt); +bool is_black(int pt); Color get_color(int pn, std::array const *board); Color get_color(PieceType pt); @@ -29,6 +29,7 @@ Color get_color(PieceType pt); // 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. @@ -42,10 +43,15 @@ void get_possible_moves(Position pn, std::array *pt,std::vector< // This functions removes moves that put your own king in check. void filter_checked_moves(int pos, 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, 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, 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, std::array board, bool recursive=true, int en_passant=Position::NA, int castle_perms=0); + // Dumb function to do board moves. // Does not check if move is valid, just does it. std::array dumb_move(int move, std::array board); diff --git a/tests/main.cpp b/tests/main.cpp index b7cd1ba..38ea7c3 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -54,6 +54,21 @@ TEST_CASE("Test reversing color", "[rev_color]"){ 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])); @@ -215,3 +230,31 @@ TEST_CASE("Test that algebraic notation conversion is working.", "[to_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); } + +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_BISHOP1_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); +} diff --git a/tests/valid_moves.h b/tests/valid_moves.h index acdca78..a3e725c 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -77,10 +77,10 @@ const std::vector BISHOP_BLOCKED1_CAPTS = { NONE, B_KING, }; const std::vector BISHOP_BLOCKED1_NOTATION = { - "Bc6", "Bxb7", + "Bc6+", "Bxb7+", "Be6", "Bc4", "Bb3", "Ba2", - "Be4", "Bxf3" + "Be4+", "Bxf3+" }; // Should NOT include B2 (black queen) as it is obstructed by the bishop on D5 @@ -120,7 +120,7 @@ const std::vector ROOK_BLOCKED1_CAPTS = { const std::vector ROOK_BLOCKED1_NOTATION = { "Ra7", "Rb8", - "Rc7", "Rxd7", + "Rc7", "Rxd7+", "Rb6", "Rb5", "Rb4" }; @@ -146,7 +146,7 @@ const std::vector PAWN_DIAG_TEST1_CAPTS = { NONE, NONE, W_QUEEN }; const std::vector PAWN_DIAG_TEST1_NOTATION = { - "e6", "e5", "xd6" + "e6", "e5", "exd6" }; // For testing the invalidating of moves because of putting own king in check @@ -208,7 +208,7 @@ const std::vector EN_PASSANT_TEST_MOVES = { D6, E6 }; const std::vector EN_PASSANT_TEST_NOTATION = { - "d6", "dxe6" + "d6", "dxe6e.p." }; // Test pawn promotion const int PROM_PAWN_POS = G7; @@ -649,3 +649,64 @@ 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 }; + +// 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 = H8; + +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_BISHOP1_NOTATION = {}; +const std::vector DISAMB_BISHOP2_NOTATION = {}; +const std::vector DISAMB_BROOK1_NOTATION = {}; +const std::vector DISAMB_BROOK2_NOTATION = {}; +const std::vector DISAMB_WROOK1_NOTATION = {}; +const std::vector DISAMB_WROOK2_NOTATION = {}; +const std::vector DISAMB_QUEEN1_NOTATION = {}; +const std::vector DISAMB_QUEEN2_NOTATION = {}; +const std::vector DISAMB_QUEEN3_NOTATION = {}; + + +// 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#" +}; + From d69be941e43c0c71e7fb509326261d9ed9c27e43 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sat, 27 Apr 2019 03:02:26 +0000 Subject: [PATCH 51/81] to_notation working --- src/functions.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++--- tests/main.cpp | 2 +- tests/valid_moves.h | 20 ++++++++--------- 3 files changed, 63 insertions(+), 14 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index 225b578..afe745a 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -269,16 +269,33 @@ std::array dumb_move(int move, std::array board) std::string to_notation(int move, std::array *board){ std::stringstream ss; + auto moved_board = dumb_move(move, *board); int from = get_from_sq(move); std::string from_string = POSITION_STRING[from]; int to = get_to_sq(move); int captured_piece = get_captured_pc(move); + // Blank if pawn + // otherwise N/B/R/Q/K corresponding to each piece + // same 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 = ""; - int piecetype = (*board)[from]; + // 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 = ""; + PieceType piecetype = (*board)[from]; auto other_pieces = is_white(piecetype)?Pieces::BLACK:Pieces::WHITE; + switch(piecetype){ case PieceType::W_KNIGHT: case PieceType::B_KNIGHT: @@ -313,7 +330,6 @@ std::string to_notation(int move, std::array *board){ } if (get_check_flag(move) == 1){ check = "+"; - auto moved_board = dumb_move(move, *board); // This checks if the other team has any valid moves. // If not, the check sign changes to a hashtag (#). std::vector other_moves = {}; @@ -326,10 +342,43 @@ std::string to_notation(int move, std::array *board){ check = "#"; } } + // Simulated a piece of the same type, and opposite coor moving from the to square + // to check if any other pieces can also move here. + PieceType opposite_piece = rev_color(piecetype); + std::vector moves = {}; + get_all_moves_as_if(to, opposite_piece, board, &moves, false); + // Pawns do not require this, as their file is ALWAYS enough to identify them, + // and the file is always speicified on a pawn capture. + if (piecetype != PieceType::W_PAWN && + piecetype != PieceType::B_PAWN){ + for (auto move_pn=moves.begin(); move_pn!=moves.end();){ + if (get_captured_pc(*move_pn) == piecetype && + get_to_sq(*move_pn) != from){ + ++move_pn; + } else { + move_pn = moves.erase(move_pn); + } + } + 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]; + } + } + // end of checking for multiple pieces if (get_castle_flag(move) == 1){ return to-from<0 ? "O-O-O" : "O-O"; } else { - ss << piece_character << capture_character << POSITION_STRING[to] << en_passant << check; + ss << piece_character << disambig << capture_character << POSITION_STRING[to] << en_passant << check; } return ss.str(); } diff --git a/tests/main.cpp b/tests/main.cpp index 38ea7c3..66c377a 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -247,7 +247,7 @@ TEST_CASE("Test for disambiguating moves in algebraic notation", "[to_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_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); diff --git a/tests/valid_moves.h b/tests/valid_moves.h index a3e725c..f1ad8c7 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -660,7 +660,7 @@ 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 = H8; +const int DISAMB_QUEEN3_POS = H1; const std::array DISAMB_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, @@ -677,15 +677,15 @@ const std::array DISAMB_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; -const std::vector DISAMB_BISHOP1_NOTATION = {}; -const std::vector DISAMB_BISHOP2_NOTATION = {}; -const std::vector DISAMB_BROOK1_NOTATION = {}; -const std::vector DISAMB_BROOK2_NOTATION = {}; -const std::vector DISAMB_WROOK1_NOTATION = {}; -const std::vector DISAMB_WROOK2_NOTATION = {}; -const std::vector DISAMB_QUEEN1_NOTATION = {}; -const std::vector DISAMB_QUEEN2_NOTATION = {}; -const std::vector DISAMB_QUEEN3_NOTATION = {}; +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 (#) From 601b4d1439507ddc404012fba8b488b07f794b9d Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sat, 27 Apr 2019 04:24:10 +0000 Subject: [PATCH 52/81] Add pawn promotion notation --- src/constants.h | 6 ++++++ src/functions.cpp | 51 +++++++++++++++++++-------------------------- tests/main.cpp | 4 ++++ tests/valid_moves.h | 8 +++++++ 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/constants.h b/src/constants.h index 034d51d..cd52254 100644 --- a/src/constants.h +++ b/src/constants.h @@ -100,5 +100,11 @@ 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" +}; #endif diff --git a/src/functions.cpp b/src/functions.cpp index afe745a..a3aee78 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -271,12 +271,17 @@ std::string to_notation(int move, std::array *board){ auto moved_board = dumb_move(move, *board); int from = get_from_sq(move); + PieceType piecetype = (*board)[from]; std::string from_string = POSITION_STRING[from]; int to = get_to_sq(move); 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 black and white + // same for black and white std::string piece_character = ""; // Blank if not a capture // x if a capture move @@ -293,38 +298,22 @@ std::string to_notation(int move, std::array *board){ // 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 = ""; - PieceType piecetype = (*board)[from]; + // Blank if not a pawn promotion move. + // Otherwise is equal to "=P/N/B/R/Q". + std::stringstream promotion; auto other_pieces = is_white(piecetype)?Pieces::BLACK:Pieces::WHITE; - switch(piecetype){ - case PieceType::W_KNIGHT: - case PieceType::B_KNIGHT: - piece_character = "N"; - break; - case PieceType::W_BISHOP: - case PieceType::B_BISHOP: - piece_character = "B"; - break; - case PieceType::W_ROOK: - case PieceType::B_ROOK: - piece_character = "R"; - break; - case PieceType::W_QUEEN: - case PieceType::B_QUEEN: - piece_character = "Q"; - break; - case PieceType::W_KING: - case PieceType::B_KING: - piece_character = "K"; - break; - } - if (captured_piece > 0){ + if (captured_piece != 0){ capture_character = "x"; - // If is a pawn - if (piece_character == ""){ - ss << from_string[0]; + if (piecetype == PieceType::W_PAWN || + piecetype == PieceType::B_PAWN){ + pawn_file = POSITION_STRING[from][0]; } } + if (piecetype != PieceType::W_PAWN && + piecetype != PieceType::B_PAWN){ + piece_character = CHESS_CHARS_INSENSITIVE[piecetype]; + } if (get_en_pass_flag(move) == 1){ en_passant = "e.p."; } @@ -374,11 +363,15 @@ std::string to_notation(int move, std::array *board){ disambig = POSITION_STRING[from]; } } + + if (promoting_to != PieceType::NONE){ + promotion << "=" << CHESS_CHARS_INSENSITIVE[promoting_to]; + } // end of checking for multiple pieces if (get_castle_flag(move) == 1){ return to-from<0 ? "O-O-O" : "O-O"; } else { - ss << piece_character << disambig << capture_character << POSITION_STRING[to] << en_passant << check; + ss << pawn_file << piece_character << disambig << capture_character << POSITION_STRING[to] << en_passant << promotion.str() << check; } return ss.str(); } diff --git a/tests/main.cpp b/tests/main.cpp index 66c377a..9d76e6b 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -220,6 +220,8 @@ TEST_CASE("Test that algebraic notation conversion is working.", "[to_notation]" 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); @@ -229,6 +231,8 @@ TEST_CASE("Test that algebraic notation conversion is working.", "[to_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]"){ diff --git a/tests/valid_moves.h b/tests/valid_moves.h index f1ad8c7..ff35dd6 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -234,6 +234,10 @@ 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; @@ -260,6 +264,10 @@ 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 = { From f2cff7440be7ac2e49b25734a4e725e2ccc4ba37 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sat, 27 Apr 2019 15:01:45 +0000 Subject: [PATCH 53/81] Make terminal output look nice --- src/chess.cpp | 27 +++++++-- src/color.hpp | 146 ++++++++++++++++++++++++++++++++++++++++++++++++ src/constants.h | 5 ++ 3 files changed, 173 insertions(+), 5 deletions(-) create mode 100644 src/color.hpp diff --git a/src/chess.cpp b/src/chess.cpp index f9a5f94..e7a4b43 100644 --- a/src/chess.cpp +++ b/src/chess.cpp @@ -3,17 +3,34 @@ #include #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(array const& board){ + 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]; + if (is_white(piece)){ + cout << color::rize(piece_string, "White", "Default"); + } else { + cout << color::rize(piece_string, "Black", "Default"); + } + cout << " "; } cout << endl; } + cout << "-------------------" << endl; + cout << " A B C D E F G H" << endl; +} + + +int main(){ + print_board(DEFAULT_BOARD); + return 0; } diff --git a/src/color.hpp b/src/color.hpp new file mode 100644 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 cd52254..bb1f8f8 100644 --- a/src/constants.h +++ b/src/constants.h @@ -106,5 +106,10 @@ 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 From 70129a32196981875a94dee3a8062a323166fb7f Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sat, 27 Apr 2019 16:15:43 +0000 Subject: [PATCH 54/81] Working on bug...TBC --- src/chess.cpp | 63 ++++++++++++++++++++++++++++++++++++++++----- src/functions.cpp | 15 +++++++++++ src/functions.h | 4 +++ tests/main.cpp | 9 +++++++ tests/valid_moves.h | 57 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 142 insertions(+), 6 deletions(-) diff --git a/src/chess.cpp b/src/chess.cpp index e7a4b43..319ad24 100644 --- a/src/chess.cpp +++ b/src/chess.cpp @@ -16,11 +16,8 @@ void print_board(array const& board){ int ix = (i*10) + j; int piece = board[ix]; string piece_string = FANCY_CHESS_CHARS[piece]; - if (is_white(piece)){ - cout << color::rize(piece_string, "White", "Default"); - } else { - cout << color::rize(piece_string, "Black", "Default"); - } + string color = is_white(piece)?"White":"Black"; + cout << color::rize(piece_string, color, "Default"); cout << " "; } cout << endl; @@ -30,7 +27,61 @@ void print_board(array const& board){ } +// TODO: allow algebraic notation. int main(){ - print_board(DEFAULT_BOARD); + 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 = {}; + + while (true){ + all_moves = {}; + all_moves_notation = {}; + + // Gets all moves for color who's turn it is. + if (whos_turn == Color::WHITE){ + get_all_white_moves(&my_board, &all_moves); + } else { + get_all_black_moves(&my_board, &all_moves); + } + + print_board(my_board); + // Gets a string from cin called input + string input; + getline(cin, input); + // Quits + if (input == "q"){ + break; + } + + // 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; + } + } + // If the input did not match any legal move. + if (!move_exec){ + cout << "These are the only valid moves: "; + for (string notation : all_moves_notation){ + cout << notation << " "; + } + cout << endl; + // If the input did match a legal move. + } else { + my_board = dumb_move(move_to_exec, my_board); + whos_turn = rev_color(whos_turn); + } + } return 0; } diff --git a/src/functions.cpp b/src/functions.cpp index a3aee78..2534926 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -375,3 +375,18 @@ std::string to_notation(int move, std::array *board){ } return ss.str(); } + +void get_all_white_moves(std::array *board, std::vector *moves){ + for (PieceType pt : Pieces::WHITE){ + for (int pos_of : get_poss_of(pt, board)){ + get_all_moves_as_if(pos_of, pt, board, moves); + } + } +} +void get_all_black_moves(std::array *board, std::vector *moves){ + for (PieceType pt : Pieces::BLACK){ + for (int pos_of : get_poss_of(pt, board)){ + get_all_moves_as_if(pos_of, pt, board, moves); + } + } +} diff --git a/src/functions.h b/src/functions.h index ba970f1..cde7a69 100644 --- a/src/functions.h +++ b/src/functions.h @@ -62,3 +62,7 @@ bool is_checked(int pos, std::array board); // Convert move (and board becuase notation needs more info than the move itself) // ...into algbraic notation. std::string to_notation(int move, std::array *board); + +// These functions are just for printing (for now) so they are not included in the tests. +void get_all_white_moves(std::array *board, std::vector *moves); +void get_all_black_moves(std::array *board, std::vector *moves); diff --git a/tests/main.cpp b/tests/main.cpp index 9d76e6b..ac6312f 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -262,3 +262,12 @@ TEST_CASE("Test for disambiguating moves, and checkmate mark (#)", "[to_notation 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); + +} diff --git a/tests/valid_moves.h b/tests/valid_moves.h index ff35dd6..c46544c 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -718,3 +718,60 @@ const std::vector CHECKMATE_ROOK_NOTATION = { "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 = { + "Nh3", "Nf3", "Ne4", "Ne6", "Nf7", "Nxh7" +}; + +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 = { + B3, F3, F5, E6, C6, B5 +}; +const std::vector KNIGHT_EXTRA2_NOTATION = { + +}; + +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 +}; + From 979d12553f40f209e3fbe32ed16fd248a73afb06 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sat, 27 Apr 2019 23:39:42 +0000 Subject: [PATCH 55/81] Fix bug where moves would accumulate in get_all__moves. --- src/functions.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index 2534926..776b3f2 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -128,8 +128,9 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: PieceType my_king = is_white(pt)?PieceType::W_KING:PieceType::B_KING; int my_king_pos = get_pos_of(my_king, board); int attackers = 0; + std::cout << "PC: " << FANCY_CHESS_CHARS[pt] << "\nPos: " << my_king_pos << std::endl; for (auto p_pn= pns->begin(); p_pn!=pns->end();){ - if (get_castle_flag(*p_pn)){ + if (get_castle_flag(*p_pn) == 1){ // If moved left // B1 - A1 = -1 // A1 - B1 = +1 @@ -158,10 +159,13 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: // 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){ + std::cout << "King move!" << std::endl; my_king_pos = get_to_sq(*p_pn); } + std::cout << "Is " << POSITION_STRING[my_king_pos] << " in check?" <erase(p_pn); } else { ++p_pn; @@ -379,14 +383,18 @@ std::string to_notation(int move, std::array *board){ void get_all_white_moves(std::array *board, std::vector *moves){ for (PieceType pt : Pieces::WHITE){ for (int pos_of : get_poss_of(pt, board)){ - get_all_moves_as_if(pos_of, pt, board, moves); + std::vector local_moves = {}; + get_all_moves_as_if(pos_of, pt, board, &local_moves); + moves->insert(moves->end(), local_moves.begin(), local_moves.end()); } } } void get_all_black_moves(std::array *board, std::vector *moves){ for (PieceType pt : Pieces::BLACK){ for (int pos_of : get_poss_of(pt, board)){ - get_all_moves_as_if(pos_of, pt, board, moves); + std::vector local_moves = {}; + get_all_moves_as_if(pos_of, pt, board, &local_moves); + moves->insert(moves->end(), local_moves.begin(), local_moves.end()); } } } From 0dbeb14c04c6be23d83d76e49942c5e32b5e0862 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sat, 27 Apr 2019 23:40:42 +0000 Subject: [PATCH 56/81] Add optimization argument to compiler --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index f9d1d7f..77310f4 100755 --- a/src/Makefile +++ b/src/Makefile @@ -12,4 +12,4 @@ default: build build: - g++ -o chess.out functions.cpp chess.cpp -std=c++11 + g++ -O2 -o chess.out functions.cpp chess.cpp -std=c++11 From 0270636ee24d65372a52948aa4b933f61caf883d Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sat, 27 Apr 2019 23:41:28 +0000 Subject: [PATCH 57/81] Remove cout statments --- src/functions.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index 776b3f2..e9b7a24 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -128,7 +128,6 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: PieceType my_king = is_white(pt)?PieceType::W_KING:PieceType::B_KING; int my_king_pos = get_pos_of(my_king, board); int attackers = 0; - std::cout << "PC: " << FANCY_CHESS_CHARS[pt] << "\nPos: " << my_king_pos << std::endl; for (auto p_pn= pns->begin(); p_pn!=pns->end();){ if (get_castle_flag(*p_pn) == 1){ // If moved left @@ -159,13 +158,10 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: // 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){ - std::cout << "King move!" << std::endl; my_king_pos = get_to_sq(*p_pn); } - std::cout << "Is " << POSITION_STRING[my_king_pos] << " in check?" <erase(p_pn); } else { ++p_pn; From e8c884f5a826a77d8a1080710e9c74ae3f616ad8 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sun, 28 Apr 2019 01:47:33 +0000 Subject: [PATCH 58/81] Almost done. Check checks not working properly. --- src/all_moves_functions.cpp | 42 ++++++++++++++--------- src/chess.cpp | 68 +++++++++++++++++++++++++++++++------ src/functions.cpp | 21 ++++++------ src/functions.h | 4 +-- tests/main.cpp | 9 +++++ tests/valid_moves.h | 50 +++++++++++++++++++++++++-- 6 files changed, 151 insertions(+), 43 deletions(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index 5d7bd28..1f35616 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -69,23 +69,29 @@ void _add_if_not_blocked(int pos, int from, std::vector *pns, std::array *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, 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){ - if (color_of_piece == Color::WHITE){ - pns->push_back(make_move(from, pos, (*board)[pos], PieceType::W_KNIGHT)); - pns->push_back(make_move(from, pos, (*board)[pos], PieceType::W_BISHOP)); - pns->push_back(make_move(from, pos, (*board)[pos], PieceType::W_ROOK)); - pns->push_back(make_move(from, pos, (*board)[pos], PieceType::W_QUEEN)); - } else { - pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_KNIGHT)); - pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_BISHOP)); - pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_ROOK)); - pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_QUEEN)); - } + _add_pawn_promotions(from, pos, (*board)[pos], color_of_piece, pns); } else { pns->push_back(make_move(from, pos, (*board)[pos])); } @@ -94,19 +100,23 @@ void _pawn_diag_add_if_not_blocked(int pos, int from, std::vector *pns, std // ...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, std::array *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked, bool double_move){ +void _pawn_add_if_not_blocked(int pos, int from, std::vector *pns, 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 { - double_move?pns->push_back(make_move(from, pos, (*board)[pos], PieceType::NONE, 0, 1)):pns->push_back(make_move(from, pos, (*board)[pos])); + pns->push_back(make_move(from, pos, (*board)[pos])); } } } @@ -222,9 +232,9 @@ void _get_all_moves_pawn(int pos, std::vector *pns, std::array #include #include +#include "bitwise.h" #include "constants.h" #include "functions.h" #include "color.hpp" @@ -37,26 +38,21 @@ int main(){ vector all_moves = {}; vector all_moves_notation = {}; + int en_passant_square = 0; + int castle_perms = 0xF; + bool reset_en_passant = false; 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. - if (whos_turn == Color::WHITE){ - get_all_white_moves(&my_board, &all_moves); - } else { - get_all_black_moves(&my_board, &all_moves); - } + get_all_moves_for_pieces(my_pieces, &my_board, &all_moves, en_passant_square, castle_perms); print_board(my_board); // Gets a string from cin called input string input; getline(cin, input); - // Quits - if (input == "q"){ - break; - } - // Gets all moves and stores them in a notation list // TODO make into own function bool move_exec = false; @@ -70,15 +66,65 @@ int main(){ break; } } + // Quits + if (input == "q"){ + break; + } else if (input == "l"){ + cout << "Listing moves: \n"; + for (string notation : all_moves_notation){ + cout << notation << " "; + } + cout << endl; + continue; + } // If the input did not match any legal move. if (!move_exec){ + 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 == 1)){ + castle_perms - CastlePerms::WQS; + } else if (moving_from_pos == Position::H1 && + (castle_perms & CastlePerms::WKS == 1)){ + castle_perms - CastlePerms::WKS; + } + } else if (moving_piece == B_ROOK){ + if (moving_from_pos == Position::H8 && + (castle_perms & CastlePerms::BKS == 1)){ + castle_perms - CastlePerms::BKS; + } else if (moving_from_pos == Position::A8 && + (castle_perms & CastlePerms::BQS == 1)){ + castle_perms - CastlePerms::BQS; + } + + } + // 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){ + cout << "En passant move at: " << POSITION_STRING[en_passant_square] << endl; + 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); } diff --git a/src/functions.cpp b/src/functions.cpp index e9b7a24..ee1fdc1 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -1,6 +1,8 @@ #include "bitwise.h" #include "functions.h" #include "all_moves_functions.cpp" +#include +#include #include #include #include @@ -376,21 +378,18 @@ std::string to_notation(int move, std::array *board){ return ss.str(); } -void get_all_white_moves(std::array *board, std::vector *moves){ - for (PieceType pt : Pieces::WHITE){ +void get_all_moves_for_pieces(std::array pieces, 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); + 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()); } } } -void get_all_black_moves(std::array *board, std::vector *moves){ - for (PieceType pt : Pieces::BLACK){ - for (int pos_of : get_poss_of(pt, board)){ - std::vector local_moves = {}; - get_all_moves_as_if(pos_of, pt, board, &local_moves); - 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 cde7a69..c94dced 100644 --- a/src/functions.h +++ b/src/functions.h @@ -64,5 +64,5 @@ bool is_checked(int pos, std::array board); std::string to_notation(int move, std::array *board); // These functions are just for printing (for now) so they are not included in the tests. -void get_all_white_moves(std::array *board, std::vector *moves); -void get_all_black_moves(std::array *board, std::vector *moves); +void get_all_moves_for_pieces(std::array pieces, std::array *board, std::vector *moves, int en_passant, int castle_perms); +void remove_chars_from_string(std::string &std, std::string to_remove); diff --git a/tests/main.cpp b/tests/main.cpp index ac6312f..dc68434 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -269,5 +269,14 @@ TEST_CASE("Do extra (random board tests) on notation and move generation", "[to_ 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); + CHECK(get_notations(cannot_queenside, CASTLE_CHECK1_BOARD) == CASTLE_CHECK1_NOTATION); } diff --git a/tests/valid_moves.h b/tests/valid_moves.h index c46544c..f4c5db5 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -735,7 +735,7 @@ const std::array EXTRA1_BOARD = { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }; const std::vector KNIGHT_EXTRA1_NOTATION = { - "Nh3", "Nf3", "Ne4", "Ne6", "Nf7", "Nxh7" + "Ne6", "Nf7", "Nxh7", "Ne4", "Nf3", "Nh3" }; const int KNIGHT_EXTRA2_POS = D4; @@ -754,10 +754,10 @@ const std::array EXTRA2_BOARD = { INV,INV,INV,INV,INV,INV,INV,INV,INV,INV }; const std::vector KNIGHT_EXTRA2_MOVES = { - B3, F3, F5, E6, C6, B5 + B5, C6, E6, F5, B3, F3 }; const std::vector KNIGHT_EXTRA2_NOTATION = { - + "Nb5", "Nc6", "Nxe6", "Nf5", "Nb3", "Ndf3" }; const std::array EXTRA3_BOARD = { @@ -775,3 +775,47 @@ const std::array EXTRA3_BOARD = { 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, 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 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" +}; + + From 7f489bbc33a3facf9a728d896e9932de590a5c14 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sun, 28 Apr 2019 02:07:15 +0000 Subject: [PATCH 59/81] Remove unecessary options --- src/all_moves_functions.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index 1f35616..7ede64e 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -49,7 +49,7 @@ void _king_add_if_not_blocked(int pos, int from, std::vector *pns, std::arr 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, 0, 0, castle_flag)); + 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)); @@ -194,6 +194,8 @@ void _get_all_moves_king(int pos, std::vector *pns, std::array Date: Sun, 28 Apr 2019 02:10:36 +0000 Subject: [PATCH 60/81] More tests --- tests/main.cpp | 3 +++ tests/valid_moves.h | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/tests/main.cpp b/tests/main.cpp index dc68434..08f9b82 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -278,5 +278,8 @@ TEST_CASE("Test for promotions on empty squares", "[get_all_moves]"){ 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); + auto cannot_queenside2 = get_all_moves(CASTLE_CHECK2_POS, CASTLE_CHECK2_BOARD); + CHECK(get_notations(cannot_queenside, CASTLE_CHECK1_BOARD) == CASTLE_CHECK1_NOTATION); + CHECK(get_notations(cannot_queenside2, CASTLE_CHECK2_BOARD) == CASTLE_CHECK2_NOTATION); } diff --git a/tests/valid_moves.h b/tests/valid_moves.h index f4c5db5..f515433 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -817,5 +817,23 @@ const std::array CASTLE_CHECK1_BOARD = { 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" +}; From 96848371d64d6562e900e272862b7adf60311423 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sun, 28 Apr 2019 03:02:19 +0000 Subject: [PATCH 61/81] Fix an error where castling is allowed even when it a) puts the king in check or b) puts the king in check on one of the squares on the way to the final position --- src/all_moves_functions.cpp | 50 +------------------------------------ src/functions.cpp | 18 ++++++++----- tests/main.cpp | 6 +++-- tests/valid_moves.h | 18 +++++++++++++ 4 files changed, 35 insertions(+), 57 deletions(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index 7ede64e..200e8ff 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -129,19 +129,6 @@ void _get_all_moves_rook(int pos, std::vector *pns, std::array *pns, std::array* board, Color pc, Color rc){ @@ -151,37 +138,12 @@ void _get_all_moves_bishop(int pos, std::vector *pns, std::array *pns, std::array* board, Color pc, Color rc){ for (int kn_off : KNIGHT_PIECE_OFFSETS){ _add_if_not_blocked(pos+kn_off, pos, pns, board, pc, rc); } - /* - for (int xo=1;xo<=2;xo++){ - int yo=(xo==1)?2:1; - _add_if_not_blocked(x+xo, y+yo, pns, board, pc, rc); - _add_if_not_blocked(x-xo, y+yo, pns, board, pc, rc); - _add_if_not_blocked(x+xo, y-yo, pns, board, pc, rc); - _add_if_not_blocked(x-xo, y-yo, pns, board, pc, rc); - } - */ } void _get_all_moves_king(int pos, std::vector *pns, std::array* board, Color pc, Color rc, int castle_perms){ @@ -212,16 +174,6 @@ void _get_all_moves_king(int pos, std::vector *pns, std::array *pns, std::array* board, Color pc, Color rc, int en_passant){ diff --git a/src/functions.cpp b/src/functions.cpp index ee1fdc1..c275e44 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -133,25 +133,31 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: for (auto p_pn= pns->begin(); p_pn!=pns->end();){ if (get_castle_flag(*p_pn) == 1){ // If moved left - // B1 - A1 = -1 - // A1 - B1 = +1 + // Queenside if ((get_from_sq(*p_pn) - get_to_sq(*p_pn)) > 0){ int right_move = make_move(get_from_sq(*p_pn), get_to_sq(*p_pn)+1); + int full_move = make_move(get_from_sq(*p_pn), get_to_sq(*p_pn)); auto right_board = dumb_move(right_move, *board); - if (is_checked(get_to_sq(*p_pn)+1, right_board)){ - p_pn = pns->erase(p_pn); + auto full_board = dumb_move(full_move, *board); + if (is_checked(get_to_sq(*p_pn)+1, right_board) || + is_checked(get_to_sq(*p_pn), full_board)){ + p_pn = pns->erase(p_pn); } else { ++p_pn; break; } + // Kingside } else { int left_move = make_move(get_from_sq(*p_pn), get_to_sq(*p_pn)-1); + int full_move = make_move(get_from_sq(*p_pn), get_to_sq(*p_pn)); auto left_board = dumb_move(left_move, *board); - if (is_checked(get_to_sq(*p_pn)-1, left_board)){ + auto full_board = dumb_move(full_move, *board); + if (is_checked(get_to_sq(*p_pn)-1, left_board) || + is_checked(get_to_sq(*p_pn), full_board)){ p_pn = pns->erase(p_pn); } else { ++p_pn; - continue; + break; } } } else { diff --git a/tests/main.cpp b/tests/main.cpp index 08f9b82..7c28a2f 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -277,9 +277,11 @@ TEST_CASE("Test for promotions on empty squares", "[get_all_moves]"){ } 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); - auto cannot_queenside2 = get_all_moves(CASTLE_CHECK2_POS, CASTLE_CHECK2_BOARD); + 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); 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); } diff --git a/tests/valid_moves.h b/tests/valid_moves.h index f515433..0b8fdfd 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -835,5 +835,23 @@ const std::array CASTLE_CHECK2_BOARD = { 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" +}; From abccfc903005a44f94d86e33f3159a9896f4c77f Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sun, 28 Apr 2019 03:10:05 +0000 Subject: [PATCH 62/81] Fix tests --- tests/main.cpp | 2 ++ tests/valid_moves.h | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/main.cpp b/tests/main.cpp index 7c28a2f..1a2660a 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -280,8 +280,10 @@ 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); } diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 0b8fdfd..3997f06 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -853,5 +853,19 @@ const std::array CASTLE_CHECK3_BOARD = { 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, W_BISHOP, 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 = {}; From 8ed2904517f2500936dfb75c7004b8dd9dd4fe53 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sun, 28 Apr 2019 03:10:51 +0000 Subject: [PATCH 63/81] Actually fix tests --- tests/valid_moves.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 3997f06..71ab29e 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -858,7 +858,7 @@ 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, W_BISHOP, B_PAWN, NONE, NONE, 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, From 6cad4ca225127ad01ce24d19f5e6ec902d5ff5d1 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sun, 28 Apr 2019 03:19:30 +0000 Subject: [PATCH 64/81] Fix error where castle moves are allowed even when in check --- src/functions.cpp | 16 ++++++++++++++++ tests/valid_moves.h | 4 +++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/functions.cpp b/src/functions.cpp index c275e44..e22de7d 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -130,8 +130,17 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: PieceType my_king = is_white(pt)?PieceType::W_KING:PieceType::B_KING; int my_king_pos = get_pos_of(my_king, board); int attackers = 0; + bool remove_all_castles = false; 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; + } // If moved left // Queenside if ((get_from_sq(*p_pn) - get_to_sq(*p_pn)) > 0){ @@ -161,6 +170,13 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: } } } else { + // if it is a king, that is in check + // remove all castle moves + if ((pt == PieceType::W_KING || + pt == PieceType::B_KING) && + is_checked(get_from_sq(*p_pn), *board)){ + remove_all_castles = true; + } // Make move std::array moved_board = dumb_move(*p_pn, *board); // This is for when the king is the same piece that is moving. diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 71ab29e..7180729 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -868,4 +868,6 @@ 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 }; -const std::vector CASTLE_CHECK4_NOTATION = {}; +const std::vector CASTLE_CHECK4_NOTATION = { + "Kf8" +}; From 447e4a0f0d4e5f12a81920ae899fd9100cb3cb17 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sun, 28 Apr 2019 04:42:05 +0000 Subject: [PATCH 65/81] Cleanup code a bit --- src/functions.cpp | 86 ++++++++++++++++++++++++++--------------------- src/functions.h | 2 +- 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index e22de7d..95cf9aa 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -290,6 +290,35 @@ std::array dumb_move(int move, std::array 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, 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, std::array *board){ std::stringstream ss; @@ -329,14 +358,31 @@ std::string to_notation(int move, std::array *board){ if (captured_piece != 0){ 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."; @@ -346,48 +392,12 @@ std::string to_notation(int move, std::array *board){ // This checks if the other team has any valid moves. // If not, the check sign changes to a hashtag (#). std::vector other_moves = {}; - for (PieceType opt : other_pieces){ - for (int pos_of_opt : get_poss_of(opt, board)){ - get_all_moves(pos_of_opt, &moved_board, &other_moves); - } - } + get_all_moves_for_pieces(other_pieces, &moved_board, &other_moves); if (other_moves.empty()){ check = "#"; } } - // Simulated a piece of the same type, and opposite coor moving from the to square - // to check if any other pieces can also move here. - PieceType opposite_piece = rev_color(piecetype); - std::vector moves = {}; - get_all_moves_as_if(to, opposite_piece, board, &moves, false); - // Pawns do not require this, as their file is ALWAYS enough to identify them, - // and the file is always speicified on a pawn capture. - if (piecetype != PieceType::W_PAWN && - piecetype != PieceType::B_PAWN){ - for (auto move_pn=moves.begin(); move_pn!=moves.end();){ - if (get_captured_pc(*move_pn) == piecetype && - get_to_sq(*move_pn) != from){ - ++move_pn; - } else { - move_pn = moves.erase(move_pn); - } - } - 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]; - } - } - + // If promoting, add an equals sign and the piece promoting to. if (promoting_to != PieceType::NONE){ promotion << "=" << CHESS_CHARS_INSENSITIVE[promoting_to]; } diff --git a/src/functions.h b/src/functions.h index c94dced..92e6836 100644 --- a/src/functions.h +++ b/src/functions.h @@ -64,5 +64,5 @@ bool is_checked(int pos, std::array board); std::string to_notation(int move, 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, std::array *board, std::vector *moves, int en_passant, int castle_perms); +void get_all_moves_for_pieces(std::array pieces, 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); From da57a72a2e791e767e798516ea619b05561d18ad Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sun, 28 Apr 2019 15:20:11 +0000 Subject: [PATCH 66/81] Try to track down a bug with checking kings. Add tests. --- src/chess.cpp | 22 ++++++++++++++++------ tests/main.cpp | 14 +++++++++++++- tests/test_functions.cpp | 7 +++++++ tests/test_functions.h | 1 + tests/valid_moves.h | 39 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 76 insertions(+), 7 deletions(-) diff --git a/src/chess.cpp b/src/chess.cpp index 552dd07..bec4398 100644 --- a/src/chess.cpp +++ b/src/chess.cpp @@ -49,6 +49,7 @@ int main(){ // 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); + cout << "Castle perms: " << castle_perms << endl; print_board(my_board); // Gets a string from cin called input string input; @@ -99,20 +100,29 @@ int main(){ if (moving_piece == W_ROOK){ if (moving_from_pos == Position::A1 && (castle_perms & CastlePerms::WQS == 1)){ - castle_perms - CastlePerms::WQS; + castle_perms -= CastlePerms::WQS; } else if (moving_from_pos == Position::H1 && (castle_perms & CastlePerms::WKS == 1)){ - castle_perms - CastlePerms::WKS; + castle_perms -= CastlePerms::WKS; } } else if (moving_piece == B_ROOK){ if (moving_from_pos == Position::H8 && (castle_perms & CastlePerms::BKS == 1)){ - castle_perms - CastlePerms::BKS; + castle_perms -= CastlePerms::BKS; } else if (moving_from_pos == Position::A8 && (castle_perms & CastlePerms::BQS == 1)){ - castle_perms - 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){ diff --git a/tests/main.cpp b/tests/main.cpp index 1a2660a..69d1e76 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -129,7 +129,7 @@ TEST_CASE("Tests is_king_checked works", "[is_checked]"){ CHECK(is_checked(BLACK_CHECK_POS2, BLACK_CHECK_BOARD2)); } -TEST_CASE("Test that moves that put king in check are not returned", "[get_all_moves]"){ +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); @@ -287,3 +287,15 @@ TEST_CASE("Tests for check on square of queenside capture", "[get_all_moves]"){ 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.", "[is_checked]"){ + CHECK(is_checked(ROOK_CHECK_KING_POS, ROOK_CHECK_MOVED_BOARD)); +} + +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); +} + diff --git a/tests/test_functions.cpp b/tests/test_functions.cpp index e36f434..125882a 100644 --- a/tests/test_functions.cpp +++ b/tests/test_functions.cpp @@ -55,6 +55,13 @@ std::vector get_castle_flags(std::vector moves){ } return transformed; } +std::vector get_checked_flags(std::vector moves){ + std::vector transformed; + for (int mv : moves){ + transformed.push_back(get_check_flag(mv)); + } + return transformed; +} std::vector get_notations(std::vector moves, std::array board){ std::vector notations; for (int move : moves){ diff --git a/tests/test_functions.h b/tests/test_functions.h index 50311a9..0c217c0 100644 --- a/tests/test_functions.h +++ b/tests/test_functions.h @@ -12,5 +12,6 @@ std::vector get_promoted_pieces(std::vector moves); std::vector get_en_passant_flags(std::vector moves); std::vector get_pawn_start_flags(std::vector moves); std::vector get_castle_flags(std::vector moves); +std::vector get_checked_flags(std::vector moves); std::vector get_notations(std::vector moves, std::array board); #endif diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 7180729..7f6acec 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -871,3 +871,42 @@ const std::array CASTLE_CHECK4_BOARD = { 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_KING_POS = H3; +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_FLAGS = { + 0, 1 +}; + From 25ddada7447f61f967f32d1cb0e72297838e9e89 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sun, 28 Apr 2019 16:41:36 +0000 Subject: [PATCH 67/81] is_checked() -> is_attacked(). Fix checking bug/refactored is_attacked. --- src/functions.cpp | 29 +++++++++++++++-------------- src/functions.h | 2 +- tests/main.cpp | 15 +++++++++------ tests/valid_moves.h | 9 ++++++++- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index 95cf9aa..def07ac 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -97,16 +97,17 @@ void get_poss_of(PieceType pt, std::array* board, std::vector board){ +bool is_attacked(int pos, std::array board){ PieceType ptt = board[pos]; Color pc = get_color(ptt); auto other_pieces = pc==Color::WHITE?Pieces::BLACK:Pieces::WHITE; - for (PieceType pt : other_pieces){ - for (int pos_of_other : get_poss_of(pt, &board)) { - for (int possible_takes : get_all_moves(pos_of_other, board, false)){ - if (get_to_sq(possible_takes) == pos) { - return true; - } + 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; } } } @@ -118,7 +119,7 @@ void add_checked_flags(PieceType pt, std::array *board, std::vec int other_king_pos = get_pos_of(other_king, board); for (auto move_pn=pns->begin(); move_pn!=pns->end();){ auto moved_board = dumb_move(*move_pn, *board); - if (is_checked(other_king_pos, moved_board)){ + if (is_attacked(other_king_pos, moved_board)){ *move_pn |= (1 << 25); } ++move_pn; @@ -148,8 +149,8 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: int full_move = make_move(get_from_sq(*p_pn), get_to_sq(*p_pn)); auto right_board = dumb_move(right_move, *board); auto full_board = dumb_move(full_move, *board); - if (is_checked(get_to_sq(*p_pn)+1, right_board) || - is_checked(get_to_sq(*p_pn), full_board)){ + if (is_attacked(get_to_sq(*p_pn)+1, right_board) || + is_attacked(get_to_sq(*p_pn), full_board)){ p_pn = pns->erase(p_pn); } else { ++p_pn; @@ -161,8 +162,8 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: int full_move = make_move(get_from_sq(*p_pn), get_to_sq(*p_pn)); auto left_board = dumb_move(left_move, *board); auto full_board = dumb_move(full_move, *board); - if (is_checked(get_to_sq(*p_pn)-1, left_board) || - is_checked(get_to_sq(*p_pn), full_board)){ + if (is_attacked(get_to_sq(*p_pn)-1, left_board) || + is_attacked(get_to_sq(*p_pn), full_board)){ p_pn = pns->erase(p_pn); } else { ++p_pn; @@ -174,7 +175,7 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: // remove all castle moves if ((pt == PieceType::W_KING || pt == PieceType::B_KING) && - is_checked(get_from_sq(*p_pn), *board)){ + is_attacked(get_from_sq(*p_pn), *board)){ remove_all_castles = true; } // Make move @@ -185,7 +186,7 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: my_king_pos = get_to_sq(*p_pn); } - if (is_checked(my_king_pos, moved_board)){ + if (is_attacked(my_king_pos, moved_board)){ p_pn = pns->erase(p_pn); } else { ++p_pn; diff --git a/src/functions.h b/src/functions.h index 92e6836..e0b385c 100644 --- a/src/functions.h +++ b/src/functions.h @@ -57,7 +57,7 @@ std::vector get_all_moves(int pos, std::array board, bool r std::array dumb_move(int move, std::array board); // Decides if there this piece in position is in check -bool is_checked(int pos, std::array board); +bool is_attacked(int pos, std::array board); // Convert move (and board becuase notation needs more info than the move itself) // ...into algbraic notation. diff --git a/tests/main.cpp b/tests/main.cpp index 69d1e76..e828eb2 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -119,14 +119,14 @@ TEST_CASE("Test all moves for black in edge cases.", "[get_all_moves][black]"){ 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_checked]"){ +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_checked(KING_CHECK_TEST_POS, KING_CHECK_TEST_BOARD)); - CHECK(is_checked(BLACK_CHECK_POS1, BLACK_CHECK_BOARD1)); - CHECK(is_checked(BLACK_CHECK_POS2, BLACK_CHECK_BOARD2)); + 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 that moves that put own king in check are not returned", "[get_all_moves]"){ @@ -161,11 +161,14 @@ TEST_CASE("Test that the captures moves are returned", "[get_all_moves]"){ 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]"){ @@ -288,8 +291,8 @@ TEST_CASE("Tests for check on square of queenside capture", "[get_all_moves]"){ CHECK(get_notations(cannot_queenside4, CASTLE_CHECK4_BOARD) == CASTLE_CHECK4_NOTATION); } -TEST_CASE("Test that king check detection is working correctly.", "[is_checked]"){ - CHECK(is_checked(ROOK_CHECK_KING_POS, ROOK_CHECK_MOVED_BOARD)); +TEST_CASE("Test that king check detection is working correctly.", "[is_attacked]"){ + CHECK(is_attacked(ROOK_CHECK_KING_POS, ROOK_CHECK_MOVED_BOARD)); } TEST_CASE("Test for add_checked_flags is working correctly.", "[get_all_moves][add_checked_flags]"){ diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 7f6acec..339d98b 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -874,7 +874,8 @@ const std::vector CASTLE_CHECK4_NOTATION = { // This is a check that moves are being marked as "check moves" poperly const int ROOK_CHECK_POS = H3; -const int ROOK_CHECK_KING_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, @@ -906,6 +907,12 @@ const std::array ROOK_CHECK_MOVED_BOARD = { 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 }; From c563e611c1b64e02b18bdd0d5b2cfaa98e8ab07f Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sun, 28 Apr 2019 18:22:53 +0000 Subject: [PATCH 68/81] Add king_checked, fancify chess board. --- src/chess.cpp | 110 +++++++++++++++++++++++++++++++++++++++------- src/constants.h | 14 ++++++ src/functions.cpp | 6 +++ src/functions.h | 1 + tests/main.cpp | 5 ++- 5 files changed, 117 insertions(+), 19 deletions(-) diff --git a/src/chess.cpp b/src/chess.cpp index bec4398..3fe13d8 100644 --- a/src/chess.cpp +++ b/src/chess.cpp @@ -10,26 +10,50 @@ using namespace std; -void print_board(array const& board){ +void print_board(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]; + int piece = (*board)[ix]; string piece_string = FANCY_CHESS_CHARS[piece]; - string color = is_white(piece)?"White":"Black"; - cout << color::rize(piece_string, color, "Default"); - cout << " "; + 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; + 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(), @@ -41,6 +65,9 @@ int main(){ int en_passant_square = 0; int castle_perms = 0xF; bool reset_en_passant = false; + + vector highlighted_moves = {}; + while (true){ all_moves = {}; @@ -49,8 +76,21 @@ int main(){ // 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); - cout << "Castle perms: " << castle_perms << endl; - print_board(my_board); + 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); @@ -71,22 +111,58 @@ int main(){ if (input == "q"){ break; } else if (input == "l"){ - cout << "Listing moves: \n"; 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){ - cout << "Invalid move!" << std::endl; - cout << "These are the only valid moves: "; - for (string notation : all_moves_notation){ - cout << notation << " "; + 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; + } } - cout << endl; - continue; // If the input did match a legal move. } else { int moving_from_pos = get_from_sq(move_to_exec); @@ -130,13 +206,13 @@ int main(){ reset_en_passant = false; } if (en_passant_square != 0){ - cout << "En passant move at: " << POSITION_STRING[en_passant_square] << endl; 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/constants.h b/src/constants.h index bb1f8f8..4a4f37b 100644 --- a/src/constants.h +++ b/src/constants.h @@ -94,6 +94,20 @@ 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 }; +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 +}; const std::array CHESS_CHARS = { ' ', diff --git a/src/functions.cpp b/src/functions.cpp index def07ac..fd438aa 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -114,6 +114,12 @@ bool is_attacked(int pos, std::array board){ return false; } +bool king_checked(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, 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); diff --git a/src/functions.h b/src/functions.h index e0b385c..7803622 100644 --- a/src/functions.h +++ b/src/functions.h @@ -58,6 +58,7 @@ std::array dumb_move(int move, std::array board) // Decides if there this piece in position is in check bool is_attacked(int pos, std::array board); +bool king_checked(std::array *board, Color king_color); // Convert move (and board becuase notation needs more info than the move itself) // ...into algbraic notation. diff --git a/tests/main.cpp b/tests/main.cpp index e828eb2..9eaa7ce 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -291,8 +291,9 @@ TEST_CASE("Tests for check on square of queenside capture", "[get_all_moves]"){ CHECK(get_notations(cannot_queenside4, CASTLE_CHECK4_BOARD) == CASTLE_CHECK4_NOTATION); } -TEST_CASE("Test that king check detection is working correctly.", "[is_attacked]"){ - CHECK(is_attacked(ROOK_CHECK_KING_POS, ROOK_CHECK_MOVED_BOARD)); +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]"){ From 472ff827a8a8cfbe93e579df1e122f9e6741a5ab Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sun, 28 Apr 2019 20:02:18 +0000 Subject: [PATCH 69/81] Turn on warnings --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 77310f4..a12a2ac 100755 --- a/src/Makefile +++ b/src/Makefile @@ -12,4 +12,4 @@ default: build build: - g++ -O2 -o chess.out functions.cpp chess.cpp -std=c++11 + g++ -O2 -Wall -o chess.out functions.cpp chess.cpp -std=c++11 From 096676fc364314d0f58c30ca7cba771ff3581ab1 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Sun, 28 Apr 2019 20:11:05 +0000 Subject: [PATCH 70/81] Fix warnings --- src/chess.cpp | 8 ++++---- src/functions.cpp | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/chess.cpp b/src/chess.cpp index 3fe13d8..f0166e5 100644 --- a/src/chess.cpp +++ b/src/chess.cpp @@ -175,18 +175,18 @@ int main(){ } if (moving_piece == W_ROOK){ if (moving_from_pos == Position::A1 && - (castle_perms & CastlePerms::WQS == 1)){ + ((castle_perms & CastlePerms::WQS) == CastlePerms::WQS)){ castle_perms -= CastlePerms::WQS; } else if (moving_from_pos == Position::H1 && - (castle_perms & CastlePerms::WKS == 1)){ + ((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 == 1)){ + ((castle_perms & CastlePerms::BKS) == CastlePerms::BKS)){ castle_perms -= CastlePerms::BKS; } else if (moving_from_pos == Position::A8 && - (castle_perms & CastlePerms::BQS == 1)){ + ((castle_perms & CastlePerms::BQS) == CastlePerms::BQS)){ castle_perms -= CastlePerms::BQS; } } diff --git a/src/functions.cpp b/src/functions.cpp index fd438aa..0b193d3 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -136,7 +136,6 @@ void add_checked_flags(PieceType pt, std::array *board, std::vec void filter_checked_moves(PieceType pt, 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); - int attackers = 0; bool remove_all_castles = false; for (auto p_pn= pns->begin(); p_pn!=pns->end();){ if (get_castle_flag(*p_pn) == 1){ @@ -148,6 +147,8 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: ++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){ From 6269bc0311c9ffaa2cd2bc36ef941c42c1d1d81c Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 29 Apr 2019 17:20:08 +0000 Subject: [PATCH 71/81] * -> & (use references instead of pointers) --- src/all_moves_functions.cpp | 70 +++++++++--------- src/functions.cpp | 140 ++++++++++++++++++------------------ src/functions.h | 35 +++++---- tests/main.cpp | 15 ++-- tests/test_functions.cpp | 20 +++--- tests/test_functions.h | 18 ++--- 6 files changed, 153 insertions(+), 145 deletions(-) diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index 200e8ff..bec21a7 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -14,8 +14,8 @@ inline Position _pair_to_pos_unsafe(int x, int y){ } // This function returns true if the color of the piece on tile (x,y) is the Color c -bool _xy_is_color(int pos, std::array* board, Color c){ - return c==Color::WHITE ? is_white((*board)[pos]) : is_black((*board)[pos]); +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){ @@ -23,7 +23,7 @@ Color _rev_color(Color c){ } // 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, std::array *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){ +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; @@ -31,17 +31,17 @@ void _add_if_not_blocked(int pos, int from, std::vector *pns, std::arraypush_back(make_move(from, pos, (*board)[pos])); + pns.push_back(make_move(from, pos, board[pos])); *is_not_blocked = false; } else { - pns->push_back(make_move(from, pos, (*board)[pos])); + 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, std::array *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked, int castle_flag){ +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; @@ -49,10 +49,10 @@ void _king_add_if_not_blocked(int pos, int from, std::vector *pns, std::arr 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)); + 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)); + pns.push_back(make_move(from, pos, board[pos], PieceType::NONE, 0, 0, castle_flag)); } } } @@ -60,69 +60,69 @@ void _king_add_if_not_blocked(int pos, int from, std::vector *pns, std::arr // 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, std::array *board, Color color_of_piece, Color color_of_opposite){ +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])); + 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){ +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)); + 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)); + 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, std::array *board, Color color_of_piece, Color color_of_opposite, int en_passant, int promoting){ +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); + _add_pawn_promotions(from, pos, board[pos], color_of_piece, pns); } else { - pns->push_back(make_move(from, pos, (*board)[pos])); + 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)); + 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, std::array *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked, bool double_move, bool promoted){ +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){ + 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)); + 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])); + pns.push_back(make_move(from, pos, board[pos])); } } } -void _get_all_moves_rook(int pos, std::vector *pns, std::array* board, Color pc, Color rc){ +void _get_all_moves_rook(int pos, std::vector& pns, const std::array& board, Color pc, Color rc){ for (int rk_off : ROOK_PIECE_OFFSETS){ bool* not_blocked = new bool(true); for (int offset=1; offset<8; offset++){ @@ -131,7 +131,7 @@ void _get_all_moves_rook(int pos, std::vector *pns, std::array *pns, std::array* board, Color pc, Color rc){ +void _get_all_moves_bishop(int pos, std::vector& pns, const std::array& board, Color pc, Color rc){ for (int bs_off : BISHOP_PIECE_OFFSETS){ bool* not_blocked = new bool(true); for (int offset=1; offset<8; offset++){ @@ -140,13 +140,13 @@ void _get_all_moves_bishop(int pos, std::vector *pns, std::array *pns, std::array* board, Color pc, Color rc){ +void _get_all_moves_knight(int pos, std::vector& pns, const std::array& board, Color pc, Color rc){ for (int kn_off : KNIGHT_PIECE_OFFSETS){ _add_if_not_blocked(pos+kn_off, pos, pns, board, pc, rc); } } -void _get_all_moves_king(int pos, std::vector *pns, std::array* board, Color pc, Color rc, int castle_perms){ +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); } @@ -161,7 +161,7 @@ void _get_all_moves_king(int pos, std::vector *pns, std::array *pns, std::array *pns, std::array* board, Color pc, Color rc, int en_passant){ +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; diff --git a/src/functions.cpp b/src/functions.cpp index 0b193d3..d5a44a7 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -12,9 +12,6 @@ #include #include -// TODO implement functions.h functions. -// NOTE tests will NOT run unless you implement these functions. - Rank get_rank(int pos){ int rank = 0; while (pos >= 0){ @@ -43,8 +40,8 @@ Color get_color(PieceType pt){ return Color::NO_COLOR; } -Color get_color(int pn, std::array const *board){ - return get_color((*board)[pn]); +Color get_color(int pn, const std::array& board){ + return get_color(board[pn]); } Color rev_color(Color c){ @@ -65,46 +62,45 @@ PieceType rev_color(PieceType pt){ return PieceType::NONE; } -std::vector get_possible_movers(Position pn, std::array board){ +std::vector get_possible_movers(Position pn, const std::array& board){ std::vector pns = {Position::A1}; return pns; } -int get_pos_of(PieceType pt, std::array const *board){ +int get_pos_of(PieceType pt, const std::array& board){ for (int pn = Position::A8; pn!=Position::H1; pn++){ - if ((*board)[pn] == pt){ + if (board[pn] == pt){ return pn; } } return Position::NA; } -std::vector get_poss_of(PieceType pt, std::array const *board){ +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){ + if (board[pn] == pt){ results.push_back(pn); } } return results; } -void get_poss_of(PieceType pt, std::array* board, std::vector* pns){ +void get_poss_of(PieceType pt, const std::array& board, std::vector& pns){ for (int pn = Position::A8; pn!=Position::H1; pn++){ - if ((*board)[pn] == pt){ - pns->push_back(pn); + if (board[pn] == pt){ + pns.push_back(pn); } } } -bool is_attacked(int pos, std::array board){ - PieceType ptt = board[pos]; - Color pc = get_color(ptt); +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); + 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; @@ -112,19 +108,25 @@ bool is_attacked(int pos, std::array board){ } } return false; + +} + +bool is_attacked(int pos, const std::array& board){ + return would_be_attacked(pos, board[pos], board); } -bool king_checked(std::array *board, Color color_of_king){ +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); + return is_attacked(king_pos, board); } -void add_checked_flags(PieceType pt, std::array *board, std::vector *pns){ +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); - for (auto move_pn=pns->begin(); move_pn!=pns->end();){ - auto moved_board = dumb_move(*move_pn, *board); + 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); } @@ -133,17 +135,17 @@ void add_checked_flags(PieceType pt, std::array *board, std::vec } //TODO: Make faster by running from king squar eonly, instead of running on every piece of opposite team. -void filter_checked_moves(PieceType pt, std::array *board, std::vector *pns){ +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; - for (auto p_pn= pns->begin(); p_pn!=pns->end();){ + 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 = pns.erase(p_pn); ++p_pn; break; } @@ -152,26 +154,18 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: // If moved left // Queenside if ((get_from_sq(*p_pn) - get_to_sq(*p_pn)) > 0){ - int right_move = make_move(get_from_sq(*p_pn), get_to_sq(*p_pn)+1); - int full_move = make_move(get_from_sq(*p_pn), get_to_sq(*p_pn)); - auto right_board = dumb_move(right_move, *board); - auto full_board = dumb_move(full_move, *board); - if (is_attacked(get_to_sq(*p_pn)+1, right_board) || - is_attacked(get_to_sq(*p_pn), full_board)){ - p_pn = pns->erase(p_pn); + 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; } // Kingside } else { - int left_move = make_move(get_from_sq(*p_pn), get_to_sq(*p_pn)-1); - int full_move = make_move(get_from_sq(*p_pn), get_to_sq(*p_pn)); - auto left_board = dumb_move(left_move, *board); - auto full_board = dumb_move(full_move, *board); - if (is_attacked(get_to_sq(*p_pn)-1, left_board) || - is_attacked(get_to_sq(*p_pn), full_board)){ - p_pn = pns->erase(p_pn); + 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; @@ -182,11 +176,12 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: // remove all castle moves if ((pt == PieceType::W_KING || pt == PieceType::B_KING) && - is_attacked(get_from_sq(*p_pn), *board)){ + is_attacked(get_from_sq(*p_pn), board)){ remove_all_castles = true; } // Make move - std::array moved_board = dumb_move(*p_pn, *board); + std::array 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){ @@ -194,7 +189,7 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: } if (is_attacked(my_king_pos, moved_board)){ - p_pn = pns->erase(p_pn); + p_pn = pns.erase(p_pn); } else { ++p_pn; } @@ -202,7 +197,7 @@ void filter_checked_moves(PieceType pt, std::array *board, std:: } } -void get_all_moves_as_if(int pos, PieceType pt, std::array* board, std::vector* moves, bool recursive, int en_passant, int castle_perms){ +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){ Color color_of_piece = get_color(pt); Color color_of_opponent = rev_color(color_of_piece); switch(pt){ @@ -240,18 +235,16 @@ void get_all_moves_as_if(int pos, PieceType pt, std::array* boar } } -void get_all_moves(int pos, 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); +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, std::array board, bool recursive, int en_passant, int castle_perms){ - std::vector moves; - get_all_moves(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; } -std::array dumb_move(int move, std::array board){ - std::array new_board; +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); @@ -295,44 +288,49 @@ std::array dumb_move(int move, std::array board) 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();){ +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); + move_pn = moves.erase(move_pn); } } }; -void _non_pawn_disambiguate(int from, int to, int piecetype, std::vector *moves, std::string *disambig){ - if (moves->size() == 1){ - *disambig = POSITION_STRING[from][0]; - int other_from = get_to_sq(moves->at(0)); +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]; + disambig = POSITION_STRING[from][1]; } - } else if (moves->size() > 1){ - *disambig = POSITION_STRING[from]; + } else if (moves.size() > 1){ + disambig = POSITION_STRING[from]; } } -std::string to_notation(int move, std::array *board){ +std::string to_notation(int move, const std::array& board){ std::stringstream ss; - auto moved_board = dumb_move(move, *board); + std::array moved_board; + dumb_move(move, board, moved_board); int from = get_from_sq(move); - PieceType piecetype = (*board)[from]; + PieceType piecetype = board[from]; std::string from_string = POSITION_STRING[from]; int to = get_to_sq(move); int captured_piece = get_captured_pc(move); @@ -386,11 +384,11 @@ std::string to_notation(int move, std::array *board){ // 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); + 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); + _filter_unneeded_squares(other_moves, piecetype, from); piece_character = CHESS_CHARS_INSENSITIVE[piecetype]; - _non_pawn_disambiguate(from, to, piecetype, &other_moves, &disambig); + _non_pawn_disambiguate(from, to, piecetype, other_moves, disambig); } if (get_en_pass_flag(move) == 1){ en_passant = "e.p."; @@ -400,7 +398,7 @@ std::string to_notation(int move, std::array *board){ // This checks if the other team has any valid moves. // If not, the check sign changes to a hashtag (#). std::vector other_moves = {}; - get_all_moves_for_pieces(other_pieces, &moved_board, &other_moves); + get_all_moves_for_pieces(other_pieces, moved_board, other_moves); if (other_moves.empty()){ check = "#"; } @@ -418,12 +416,12 @@ std::string to_notation(int move, std::array *board){ return ss.str(); } -void get_all_moves_for_pieces(std::array pieces, std::array *board, std::vector *moves, int en_passant, int castle_perms){ +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()); + 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()); } } } diff --git a/src/functions.h b/src/functions.h index 7803622..8d1d473 100644 --- a/src/functions.h +++ b/src/functions.h @@ -6,8 +6,8 @@ #include // Returns a list of positions with PieceType pt -int get_pos_of(PieceType pt, std::array const *board); -std::vector get_poss_of(PieceType pt, std::array const *board); +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); @@ -23,7 +23,7 @@ Rank get_rank(int pos); bool is_white(int pt); bool is_black(int pt); -Color get_color(int pn, std::array const *board); +Color get_color(int pn, const std::array& board); Color get_color(PieceType pt); // NO_COLOR returns NO_COLOR // WHITE returns BLACK @@ -34,36 +34,41 @@ 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. -void get_possible_movers(Position pn, std::array *pt,std::vector *moves); +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. -void get_possible_moves(Position pn, std::array *pt,std::vector *moves); +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, std::array *board, std::vector *moves); +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, std::array *board, std::vector *moves, bool recursvie=true, int en_passant=Position::NA, int castle_perms=0); +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, 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, std::array board, bool recursive=true, int en_passant=Position::NA, int castle_perms=0); +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); // Dumb function to do board moves. // Does not check if move is valid, just does it. -std::array dumb_move(int move, std::array board); +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 there this piece in position is in check -bool is_attacked(int pos, std::array board); -bool king_checked(std::array *board, Color king_color); +// 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, std::array *board); +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, std::array *board, std::vector *moves, int en_passant=0, int castle_perms=0); +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/main.cpp b/tests/main.cpp index 9eaa7ce..d457402 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -34,13 +34,13 @@ TEST_CASE("Test that get_rank() works)", "[get_rank]"){ } 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); + 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); + 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); @@ -129,6 +129,11 @@ TEST_CASE("Tests is_king_checked works", "[is_attacked]"){ 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); @@ -293,7 +298,7 @@ TEST_CASE("Tests for check on square of queenside capture", "[get_all_moves]"){ 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)); + 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]"){ diff --git a/tests/test_functions.cpp b/tests/test_functions.cpp index 125882a..fe351f8 100644 --- a/tests/test_functions.cpp +++ b/tests/test_functions.cpp @@ -6,66 +6,66 @@ #include #include -std::vector get_to_squares(std::vector moves){ +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(std::vector moves){ +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(std::vector moves){ +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(std::vector moves){ +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(std::vector moves){ +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(std::vector moves){ +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(std::vector moves){ +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(std::vector moves){ +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(std::vector moves, std::array board){ +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)); + notations.push_back(to_notation(move, board)); } return notations; } diff --git a/tests/test_functions.h b/tests/test_functions.h index 0c217c0..38cb3e5 100644 --- a/tests/test_functions.h +++ b/tests/test_functions.h @@ -5,13 +5,13 @@ #include #include -std::vector get_from_squares(std::vector moves); -std::vector get_to_squares(std::vector moves); -std::vector get_captured_pieces(std::vector moves); -std::vector get_promoted_pieces(std::vector moves); -std::vector get_en_passant_flags(std::vector moves); -std::vector get_pawn_start_flags(std::vector moves); -std::vector get_castle_flags(std::vector moves); -std::vector get_checked_flags(std::vector moves); -std::vector get_notations(std::vector moves, std::array board); +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 From 695c8f5b8e9140d5e96f308f14eaede8ffb4dc34 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 29 Apr 2019 17:45:23 +0000 Subject: [PATCH 72/81] Improve preformace. Add tests. --- src/functions.cpp | 2 +- tests/main.cpp | 5 +++++ tests/valid_moves.h | 21 +++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/functions.cpp b/src/functions.cpp index d5a44a7..8d7b5cc 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -181,7 +181,7 @@ void filter_checked_moves(PieceType pt, const std::array& board, } // Make move std::array moved_board; - dumb_move(*p_pn, board, 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){ diff --git a/tests/main.cpp b/tests/main.cpp index d457402..95d0a8c 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -308,3 +308,8 @@ TEST_CASE("Test for add_checked_flags is working correctly.", "[get_all_moves][a 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/valid_moves.h b/tests/valid_moves.h index 339d98b..a15a4b3 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -917,3 +917,24 @@ 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 +}; From 1954ef3dc291857323a164b78ccd0f3f97601a3d Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 29 Apr 2019 18:08:14 +0000 Subject: [PATCH 73/81] Fix chess.cpp to comply with new internals --- src/chess.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/chess.cpp b/src/chess.cpp index f0166e5..57fdffc 100644 --- a/src/chess.cpp +++ b/src/chess.cpp @@ -10,12 +10,12 @@ using namespace std; -void print_board(array *board, vector &highlighted_moves){ +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]; + int piece = board[ix]; string piece_string = FANCY_CHESS_CHARS[piece]; string foreground_color = is_white(piece)?"White":"Black"; string background_color = ""; @@ -74,14 +74,14 @@ int main(){ 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); + get_all_moves_for_pieces(my_pieces, my_board, all_moves, en_passant_square, castle_perms); - print_board(&my_board, highlighted_moves); + 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)){ + 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; @@ -99,7 +99,7 @@ int main(){ bool move_exec = false; int move_to_exec = 0; for (int move : all_moves){ - string move_notation = to_notation(move, &my_board); + string move_notation = to_notation(move, my_board); all_moves_notation.push_back(move_notation); if (move_notation == input){ move_exec = true; @@ -149,7 +149,7 @@ int main(){ 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 << to_notation(move, my_board) << " "; } } cout << endl; From 5d679607213e960fb190c3c2a02adb77a4350ff5 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 29 Apr 2019 18:08:37 +0000 Subject: [PATCH 74/81] Add optomization options by using 'make release' --- src/Makefile | 6 +++++- tests/Makefile | 19 ++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index a12a2ac..f0edd4b 100755 --- a/src/Makefile +++ b/src/Makefile @@ -10,6 +10,10 @@ # g++ -c -std=c++11 functions.cpp # default: build +release: optimized + +optimized: + g++ -std=c++11 -O2 -Wall -o chess.out functions.cpp chess.cpp build: - g++ -O2 -Wall -o chess.out functions.cpp chess.cpp -std=c++11 + g++ -Wall -o chess_unoptimized.out functions.cpp chess.cpp -std=c++11 diff --git a/tests/Makefile b/tests/Makefile index 402f303..2a8f2f5 100755 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,5 +1,6 @@ defualt: all.out bitwise: bitwise.out +release: all_optimized.out clean: rm all.out @@ -11,11 +12,23 @@ catch_main.o: g++ -w -c -o catch_main.o catch_main.cpp custom_printing.o: - g++ -w -I../src/ -c -o custom_printing.o custom_printing.cpp + g++ -Wall -I../src/ -c -o custom_printing.o custom_printing.cpp bitwise.out: catch_main.o - g++ -w -I../src -o bitwise.out catch_main.o bitwise_tests.cpp + 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 -w -I../src/ -o all.out ../src/functions.cpp catch_main.o custom_printing.o test_functions.cpp main.cpp + 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 From 3c8577fb42955672825a8c4d9faeafc3f4c71ece Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 29 Apr 2019 21:01:31 +0000 Subject: [PATCH 75/81] Start tracking speed of various functions. Uncomplete --- tests/speed.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/speed.cpp diff --git a/tests/speed.cpp b/tests/speed.cpp new file mode 100644 index 0000000..704f175 --- /dev/null +++ b/tests/speed.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace std::chrono; + +// TODO make complete, add complex scenarios. +// Test every function on their edge cases. +int main(){ + 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; +} From 0c202900fa37114ab75db1c839aede73b29233c6 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Mon, 29 Apr 2019 22:22:20 +0000 Subject: [PATCH 76/81] Add various compile options, and remove some whitespace --- tests/Makefile | 4 ++++ tests/speed.cpp | 28 +++++++++++++++++++++++++++- tests/valid_moves.h | 1 - 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 2a8f2f5..6b5afa3 100755 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,6 +1,7 @@ defualt: all.out bitwise: bitwise.out release: all_optimized.out +speed_tests: speed_tests.out clean: rm all.out @@ -32,3 +33,6 @@ bitwise_optimized.out: catch_main_optimized.o 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/speed.cpp b/tests/speed.cpp index 704f175..e2692c4 100644 --- a/tests/speed.cpp +++ b/tests/speed.cpp @@ -1,3 +1,4 @@ +#include "valid_moves.h" #include #include #include @@ -9,9 +10,21 @@ 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 = {}; @@ -19,6 +32,19 @@ int main(){ } 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/valid_moves.h b/tests/valid_moves.h index a15a4b3..38f2d57 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -2,7 +2,6 @@ #include #include - /// This is for possible moves on a default board const std::vector DEFAULT_B_A_PAWN_POSSIBLE_MOVES = { A6, A5 From 7b6db255cca5833e57a5ae77791daf49cff2de89 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Thu, 2 May 2019 19:33:57 +0000 Subject: [PATCH 77/81] Start refactor of get_all_moves_as_if. Goal: remove all_moves_functions.cpp --- src/all_moves_functions.cpp | 33 ++-------- src/bitwise.h | 46 ++++++++------ src/bitwise_constants.cpp | 16 ----- src/constants.h | 18 +++--- src/functions.cpp | 122 ++++++++++++++++++++++++++++++++++-- tests/valid_moves.h | 24 +++---- 6 files changed, 169 insertions(+), 90 deletions(-) delete mode 100644 src/bitwise_constants.cpp diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp index bec21a7..b219897 100644 --- a/src/all_moves_functions.cpp +++ b/src/all_moves_functions.cpp @@ -3,10 +3,10 @@ #include #include -const std::array ROOK_PIECE_OFFSETS = {-1, -10, 1, 10}; -const std::array BISHOP_PIECE_OFFSETS = {-11, -9, 9, 11}; -const std::array KNIGHT_PIECE_OFFSETS = {-12, -21, -19, -8, 8, 12, 19, 21}; -const std::array KING_PIECE_OFFSETS = {-11, -10, -9, 9, 10, 11}; +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){ @@ -121,31 +121,6 @@ void _pawn_add_if_not_blocked(int pos, int from, std::vector& pns, const st } } - -void _get_all_moves_rook(int pos, std::vector& pns, const std::array& board, Color pc, Color rc){ - for (int rk_off : ROOK_PIECE_OFFSETS){ - bool* not_blocked = new bool(true); - for (int offset=1; offset<8; offset++){ - _add_if_not_blocked(pos+(rk_off*offset), pos, pns, board, pc, rc, not_blocked); - } - } -} - -void _get_all_moves_bishop(int pos, std::vector& pns, const std::array& board, Color pc, Color rc){ - for (int bs_off : BISHOP_PIECE_OFFSETS){ - bool* not_blocked = new bool(true); - for (int offset=1; offset<8; offset++){ - _add_if_not_blocked(pos+(bs_off*offset), pos, pns, board, pc, rc, not_blocked); - } - } -} - -void _get_all_moves_knight(int pos, std::vector& pns, const std::array& board, Color pc, Color rc){ - for (int kn_off : KNIGHT_PIECE_OFFSETS){ - _add_if_not_blocked(pos+kn_off, pos, pns, board, pc, rc); - } -} - 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); diff --git a/src/bitwise.h b/src/bitwise.h index 19d9da2..ebcff61 100644 --- a/src/bitwise.h +++ b/src/bitwise.h @@ -25,37 +25,47 @@ * 0010 0000 0000 0000 0000 0000 0000 -> check flag (& 0x2000000) * */ -/* OLD, DO NOT USE -#define FROMSQ(m) ((m) & 0x3f) -#define TOSQ(m) ((m>>6) & 0x3f) -#define CAPT(m) ((m>>12) & 0xf ) -#define PROM(m) ((m>>16) & 0xf ) -#define ENPASS(m) ((m>>20) & 0x1 ) -#define PAWNST(m) ((m>>21) & 0x1 ) -#define CAST(m) ((m>>22) & 0x1 ) -*/ - -// Redefine as functions for fun :shrug: +// 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 & 0x7f); + return (mv & FROM_MASK); } inline int get_to_sq(int mv){ - return ((mv >> 7) & 0x7f); + return ((mv >> TO_SHIFT) & TO_MASK); } inline int get_captured_pc(int mv){ - return ((mv >> 14) & 0xf); + return ((mv >> CAPTURED_SHIFT) & CAPTURED_MASK); } inline int get_promoted_to_pc(int mv){ - return ((mv >> 18) & 0xf); + return ((mv >> PROMOTED_SHIFT) & PROMOTED_MASK); } inline int get_en_pass_flag(int mv){ - return ((mv >> 22) & 0x1); + return ((mv >> EN_PASS_SHIFT) & EN_PASS_MASK); } inline int get_pawn_st_flag(int mv){ - return ((mv >> 23) & 0x1); + return ((mv >> PAWN_ST_SHIFT) & PAWN_ST_MASK); } inline int get_castle_flag(int mv){ - return ((mv >> 24) & 0x1); + return ((mv >> CASTLE_SHIFT) & CASTLE_MASK); } inline int get_check_flag(int mv){ return ((mv >> 25) & 0x1); diff --git a/src/bitwise_constants.cpp b/src/bitwise_constants.cpp deleted file mode 100644 index 0727647..0000000 --- a/src/bitwise_constants.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "bitwise_constants.h" -#include -#include - -int main(){ - for (int y=0;y<12;y++){ - for (int x=0;x<10;x++){ - int cord = (y*10) + x; - int val = DEFAULT_BOARD[cord]; - val==-1?std::cout << '!':std::cout << CHESS_CHARS[val]; - std::cout << std::hex << y << "," << x << " "; - } - std::cout << std::endl; - } - return 0; -} diff --git a/src/constants.h b/src/constants.h index 4a4f37b..62c5e43 100644 --- a/src/constants.h +++ b/src/constants.h @@ -7,8 +7,8 @@ enum Color { NO_COLOR, - WHITE, - BLACK + BLACK, + WHITE }; enum CastlePerms { @@ -22,7 +22,7 @@ enum PieceType { INV=-1, NONE, B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING, - W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING + W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING, }; namespace Pieces{ @@ -109,21 +109,21 @@ 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 }; -const std::array CHESS_CHARS = { +const std::array CHESS_CHARS = { ' ', 'P', 'N', 'B', 'R', 'Q', 'K', - '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 = { +const std::array CHESS_CHARS_INSENSITIVE = { " ", "P", "N", "B", "R", "Q", "K", - "P", "N", "B", "R", "Q", "K" + "P", "N", "B", "R", "Q", "K", }; -const std::array FANCY_CHESS_CHARS = { +const std::array FANCY_CHESS_CHARS = { " ", "♟", "♞", "♝", "♜", "♛", "♚", - "♙", "♘", "♗", "♖", "♕", "♔" + "♙", "♘", "♗", "♖", "♕", "♔", }; #endif diff --git a/src/functions.cpp b/src/functions.cpp index 8d7b5cc..e93f3fe 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -12,6 +12,74 @@ #include #include +/* + * + * 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) + * +**/ + +/* + * 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){ @@ -49,6 +117,7 @@ Color rev_color(Color c){ 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]; @@ -124,6 +193,10 @@ bool king_checked(const std::array& board, Color color_of_king){ 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); @@ -139,6 +212,10 @@ void filter_checked_moves(PieceType pt, const std::array& board, 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 @@ -197,26 +274,58 @@ void filter_checked_moves(PieceType pt, const std::array& board, } } +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])); + } + } +} + 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_rook(pos, moves, board, color_of_piece, color_of_opponent); - _get_all_moves_bishop(pos, moves, board, color_of_piece, color_of_opponent); + _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_rook(pos, moves, board, color_of_piece, color_of_opponent); + _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_bishop(pos, moves, board, color_of_piece, color_of_opponent); + _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_knight(pos, moves, board, color_of_piece, color_of_opponent); + _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: @@ -362,7 +471,7 @@ std::string to_notation(int move, const std::array& board){ std::stringstream promotion; auto other_pieces = is_white(piecetype)?Pieces::BLACK:Pieces::WHITE; - if (captured_piece != 0){ + if (captured_piece != PieceType::NONE){ capture_character = "x"; // Comment #6 // if a pawn is capturing, have the disambiguation be the pawn's file @@ -431,3 +540,4 @@ void remove_chars_from_string(std::string &str, std::string charsToRemove ) { str.erase( remove(str.begin(), str.end(), charsToRemove.at(i)), str.end() ); } } + diff --git a/tests/valid_moves.h b/tests/valid_moves.h index 38f2d57..71ea472 100644 --- a/tests/valid_moves.h +++ b/tests/valid_moves.h @@ -501,7 +501,7 @@ const std::array KING_CHECK_TEST_BOARD = { 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, 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, @@ -542,7 +542,7 @@ const std::array EN_PASSANT_CHECK_BOARD = { 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 }; @@ -556,7 +556,7 @@ const std::array EN_PASSANT_CHECK_MOVED_BOARD = { 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 }; @@ -574,9 +574,9 @@ const std::array EN_PASSANT_CHECK_BOARD1 = { 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, NONE, NONE, NONE, 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 }; @@ -588,9 +588,9 @@ const std::array EN_PASSANT_CHECK_MOVED_BOARD1 = { 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, 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 }; @@ -600,7 +600,7 @@ 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, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, 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, @@ -614,7 +614,7 @@ const std::array EN_PASSANT_CHECK_BOARD2 = { 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, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, 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, @@ -631,7 +631,7 @@ 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, NONE, NONE, NONE, NONE, NONE, NONE, 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, @@ -645,7 +645,7 @@ const std::array EN_PASSANT_CHECK_BOARD3 = { 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, NONE, NONE, NONE, NONE, NONE, NONE, 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, @@ -787,7 +787,7 @@ const std::array PAWN_PROM_BLANK_BOARD = { 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, 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 }; From 3885264dd48a7bf1b6868f013d312974bf94d471 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Fri, 3 May 2019 00:16:50 +0000 Subject: [PATCH 78/81] Move moved_board to local scope --- src/functions.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index e93f3fe..46f6ae6 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -301,6 +301,18 @@ void _get_all_moves_as_if_not_ray(int pos, std::vector offsets, std::vector } } + +// 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); @@ -329,6 +341,10 @@ void get_all_moves_as_if(int pos, PieceType pt, const std::array 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: @@ -436,8 +452,6 @@ void _non_pawn_disambiguate(int from, int to, int piecetype, const std::vector& board){ std::stringstream ss; - std::array moved_board; - dumb_move(move, board, moved_board); int from = get_from_sq(move); PieceType piecetype = board[from]; std::string from_string = POSITION_STRING[from]; @@ -506,6 +520,9 @@ std::string to_notation(int move, const std::array& board){ 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()){ From e40865a7ba91a48104e310173beea64be5c0baab Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Fri, 3 May 2019 00:42:44 +0000 Subject: [PATCH 79/81] Move castleing case to start of to_notation --- src/functions.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index 46f6ae6..13269cd 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -452,10 +452,16 @@ void _non_pawn_disambiguate(int from, int to, int piecetype, const std::vector& board){ std::stringstream ss; + 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 to = get_to_sq(move); int captured_piece = get_captured_pc(move); int promoting_to = get_promoted_to_pc(move); // Blank if not pawn @@ -534,11 +540,7 @@ std::string to_notation(int move, const std::array& board){ promotion << "=" << CHESS_CHARS_INSENSITIVE[promoting_to]; } // end of checking for multiple pieces - if (get_castle_flag(move) == 1){ - return to-from<0 ? "O-O-O" : "O-O"; - } else { - ss << pawn_file << piece_character << disambig << capture_character << POSITION_STRING[to] << en_passant << promotion.str() << check; - } + ss << pawn_file << piece_character << disambig << capture_character << POSITION_STRING[to] << en_passant << promotion.str() << check; return ss.str(); } From f92cf22fb047865675f764ca4615312ae1f73935 Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Fri, 3 May 2019 00:51:57 +0000 Subject: [PATCH 80/81] Switch to using string, instead of stringstream in to_notation --- src/functions.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/functions.cpp b/src/functions.cpp index 13269cd..4049d8c 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -450,8 +450,6 @@ void _non_pawn_disambiguate(int from, int to, int piecetype, const std::vector& board){ - std::stringstream ss; - int to = get_to_sq(move); int from = get_from_sq(move); @@ -488,7 +486,7 @@ std::string to_notation(int move, const std::array& board){ std::string disambig = ""; // Blank if not a pawn promotion move. // Otherwise is equal to "=P/N/B/R/Q". - std::stringstream promotion; + std::string promotion; auto other_pieces = is_white(piecetype)?Pieces::BLACK:Pieces::WHITE; if (captured_piece != PieceType::NONE){ @@ -537,11 +535,13 @@ std::string to_notation(int move, const std::array& board){ } // If promoting, add an equals sign and the piece promoting to. if (promoting_to != PieceType::NONE){ - promotion << "=" << CHESS_CHARS_INSENSITIVE[promoting_to]; + promotion += "="; + promotion += CHESS_CHARS_INSENSITIVE[promoting_to]; } // end of checking for multiple pieces - ss << pawn_file << piece_character << disambig << capture_character << POSITION_STRING[to] << en_passant << promotion.str() << check; - return ss.str(); + 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){ From b47a447e547c12fed235917219882111996062ac Mon Sep 17 00:00:00 2001 From: Tait Hoyem <44244401+TTWNO@users.noreply.github.com> Date: Tue, 17 Mar 2020 18:03:17 +0000 Subject: [PATCH 81/81] Add all other functionality. I forgot to commit for some months --- LICENSE | 0 README.md | 0 src/all_moves_functions.cpp | 0 src/bitwise.h | 0 src/chess.cpp | 0 src/color.hpp | 0 src/constants.h | 0 src/functions.cpp | 0 src/functions.h | 0 tests/B_test_boards.h | 0 tests/W_test_boards.h | 0 tests/bitwise_tests.cpp | 0 tests/catch.hpp | 0 tests/catch_main.cpp | 0 tests/custom_printing.cpp | 0 tests/main.cpp | 0 tests/speed.cpp | 0 tests/test_boards.h | 0 tests/test_functions.cpp | 0 tests/test_functions.h | 0 tests/valid_moves.h | 0 21 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 src/all_moves_functions.cpp mode change 100644 => 100755 src/bitwise.h mode change 100644 => 100755 src/chess.cpp mode change 100644 => 100755 src/color.hpp mode change 100644 => 100755 src/constants.h mode change 100644 => 100755 src/functions.cpp mode change 100644 => 100755 src/functions.h mode change 100644 => 100755 tests/B_test_boards.h mode change 100644 => 100755 tests/W_test_boards.h mode change 100644 => 100755 tests/bitwise_tests.cpp mode change 100644 => 100755 tests/catch.hpp mode change 100644 => 100755 tests/catch_main.cpp mode change 100644 => 100755 tests/custom_printing.cpp mode change 100644 => 100755 tests/main.cpp mode change 100644 => 100755 tests/speed.cpp mode change 100644 => 100755 tests/test_boards.h mode change 100644 => 100755 tests/test_functions.cpp mode change 100644 => 100755 tests/test_functions.h mode change 100644 => 100755 tests/valid_moves.h diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/src/all_moves_functions.cpp b/src/all_moves_functions.cpp old mode 100644 new mode 100755 diff --git a/src/bitwise.h b/src/bitwise.h old mode 100644 new mode 100755 diff --git a/src/chess.cpp b/src/chess.cpp old mode 100644 new mode 100755 diff --git a/src/color.hpp b/src/color.hpp old mode 100644 new mode 100755 diff --git a/src/constants.h b/src/constants.h old mode 100644 new mode 100755 diff --git a/src/functions.cpp b/src/functions.cpp old mode 100644 new mode 100755 diff --git a/src/functions.h b/src/functions.h old mode 100644 new mode 100755 diff --git a/tests/B_test_boards.h b/tests/B_test_boards.h old mode 100644 new mode 100755 diff --git a/tests/W_test_boards.h b/tests/W_test_boards.h old mode 100644 new mode 100755 diff --git a/tests/bitwise_tests.cpp b/tests/bitwise_tests.cpp old mode 100644 new mode 100755 diff --git a/tests/catch.hpp b/tests/catch.hpp old mode 100644 new mode 100755 diff --git a/tests/catch_main.cpp b/tests/catch_main.cpp old mode 100644 new mode 100755 diff --git a/tests/custom_printing.cpp b/tests/custom_printing.cpp old mode 100644 new mode 100755 diff --git a/tests/main.cpp b/tests/main.cpp old mode 100644 new mode 100755 diff --git a/tests/speed.cpp b/tests/speed.cpp old mode 100644 new mode 100755 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 old mode 100644 new mode 100755 diff --git a/tests/test_functions.h b/tests/test_functions.h old mode 100644 new mode 100755 diff --git a/tests/valid_moves.h b/tests/valid_moves.h old mode 100644 new mode 100755