Checkmate marks (#) now work.

master
Tait Hoyem 5 years ago
parent ffa404f0cb
commit 036d41e589

@ -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

@ -22,13 +22,13 @@ Rank get_rank(int pos){
return static_cast<Rank>(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<int> get_possible_movers(Position pn, std::array<PieceType, 120> board){
std::vector<int> pns = {Position::A1};
@ -98,6 +111,18 @@ bool is_checked(int pos, std::array<PieceType, 120> board){
return false;
}
void add_checked_flags(PieceType pt, std::array<PieceType, 120> *board, std::vector<int> *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<PieceType, 120> *board, std::vector<int> *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<PieceType, 120> *board, std::
}
}
void get_all_moves(int pos, std::array<PieceType, 120>* board, std::vector<int>* 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<PieceType, 120>* board, std::vector<int>* 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<PieceType, 120>* board, std::vector<int>*
}
if (recursive){
filter_checked_moves(pt, board, moves);
add_checked_flags(pt, board, moves);
}
}
void get_all_moves(int pos, std::array<PieceType, 120> *board, std::vector<int> *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<int> get_all_moves(int pos, std::array<PieceType, 120> board, bool recursive, int en_passant, int castle_perms){
std::vector<int> moves;
get_all_moves(pos, &board, &moves, recursive, en_passant, castle_perms);
@ -246,7 +275,10 @@ std::string to_notation(int move, std::array<PieceType, 120> *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<PieceType, 120> *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<int> 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();
}

@ -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<PieceType, 120> 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<PieceType, 120> *pt,std::vector<
// This functions removes moves that put your own king in check.
void filter_checked_moves(int pos, std::array<PieceType, 120> *board, std::vector<int> *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<PieceType, 120> *board, std::vector<int> *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<PieceType, 120> *pt, std::vector<int> *moves, bool recursive=true, int en_passant=Position::NA, int castle_perms=0);
std::vector<int> get_all_moves(int pos, std::array<PieceType, 120> 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<PieceType, 120> dumb_move(int move, std::array<PieceType, 120> board);

@ -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);
}

@ -77,10 +77,10 @@ const std::vector<int> BISHOP_BLOCKED1_CAPTS = {
NONE, B_KING,
};
const std::vector<std::string> 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<int> ROOK_BLOCKED1_CAPTS = {
const std::vector<std::string> ROOK_BLOCKED1_NOTATION = {
"Ra7",
"Rb8",
"Rc7", "Rxd7",
"Rc7", "Rxd7+",
"Rb6", "Rb5", "Rb4"
};
@ -146,7 +146,7 @@ const std::vector<int> PAWN_DIAG_TEST1_CAPTS = {
NONE, NONE, W_QUEEN
};
const std::vector<std::string> 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<int> EN_PASSANT_TEST_MOVES = {
D6, E6
};
const std::vector<std::string> 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<PieceType, 120> 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<PieceType, 120> 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<std::string> DISAMB_BISHOP1_NOTATION = {};
const std::vector<std::string> DISAMB_BISHOP2_NOTATION = {};
const std::vector<std::string> DISAMB_BROOK1_NOTATION = {};
const std::vector<std::string> DISAMB_BROOK2_NOTATION = {};
const std::vector<std::string> DISAMB_WROOK1_NOTATION = {};
const std::vector<std::string> DISAMB_WROOK2_NOTATION = {};
const std::vector<std::string> DISAMB_QUEEN1_NOTATION = {};
const std::vector<std::string> DISAMB_QUEEN2_NOTATION = {};
const std::vector<std::string> DISAMB_QUEEN3_NOTATION = {};
// CHeck that converting moves to algebraic notation have checkmate marks (#)
const int CHECKMATE_ROOK_POS = D8;
const std::array<PieceType, 120> 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<std::string> CHECKMATE_ROOK_NOTATION = {
"Rc8", "Rdb8", "Ra8",
"Re8", "Rf8", "Rg8+", "Rh8",
"Rd7", "Rd6", "Rd5", "Rd4", "Rd3", "Rdd2", "Rd1#"
};

Loading…
Cancel
Save