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] 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 }; - - -