Castling moves showing properly. Become invalid if in check on square or square before castling square.

master
Tait Hoyem 5 years ago
parent 424a0fe7d0
commit ed39d8aefb

@ -6,7 +6,7 @@
const std::array<int, 4> ROOK_PIECE_OFFSETS = {-1, -10, 1, 10};
const std::array<int, 4> BISHOP_PIECE_OFFSETS = {-11, -9, 9, 11};
const std::array<int, 8> KNIGHT_PIECE_OFFSETS = {-12, -21, -19, -8, 8, 12, 19, 21};
const std::array<int, 8> KING_PIECE_OFFSETS = {-11, -10, -9, -1, 1, 9, 10, 11};
const std::array<int, 8> 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<int> *pns, std::array<Pi
}
}
}
// 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<int> *pns, std::array<PieceType, 120> *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<int> *pns, std::array<PieceType, 120> *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<int> *pns, std::array<PieceType,
}
void _get_all_moves_knight(int pos, std::vector<int> *pns, std::array<PieceType, 120>* 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<int> *pns, std::array<PieceType,
*/
}
void _get_all_moves_king(int pos, std::vector<int> *pns, std::array<PieceType, 120>* board, Color pc, Color rc){
void _get_all_moves_king(int pos, std::vector<int> *pns, std::array<PieceType, 120>* 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);

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

@ -11,6 +11,13 @@ enum Color {
BLACK
};
enum CastlePerms {
BQS=0b1,
BKS=0b10,
WQS=0b100,
WKS=0b1000
};
enum PieceType {
INV=-1,
NONE,

@ -40,7 +40,7 @@ Color get_color(PieceType pt){
return Color::NO_COLOR;
}
Color get_color(Position pn, std::array<PieceType, 120> const *board){
Color get_color(int pn, std::array<PieceType, 120> const *board){
return get_color((*board)[pn]);
}
@ -54,12 +54,6 @@ std::vector<int> get_possible_movers(Position pn, std::array<PieceType, 120> boa
return pns;
}
std::vector<int> get_possible_moves(Position pn, std::array<PieceType, 120> board){
std::vector<int> pns = {Position::A1};
get_all_moves(pn, &board, &pns);
return pns;
}
int get_pos_of(PieceType pt, std::array<PieceType, 120> 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<PieceType, 120>* board, std::vector<in
}
}
bool is_checked(int pos, std::array<PieceType, 120> 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<PieceType, 120> *board, std::vector<int> *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<PieceType, 120> moved_board = dumb_move(*p_pn, *board);
// Get all piecetypes of other team
std::array<PieceType, 6> 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<int> psns;
get_poss_of(other_p, &moved_board, &psns);
for (auto psn : psns){
std::vector<int> 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<PieceType, 120> 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<PieceType, 120>* board, std::vector<int>* moves, bool recursive, int en_passant){
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];
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<PieceType, 120>* board, std::vector<int>*
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<PieceType, 120>* board, std::vector<int>*
}
}
std::vector<int> get_all_moves(int pos, std::array<PieceType, 120> board, bool recursive, int en_passant){
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);
get_all_moves(pos, &board, &moves, recursive, en_passant, castle_perms);
return moves;
}
std::array<PieceType, 120> dumb_move(int move, std::array<PieceType, 120> board){
std::array<PieceType, 120> 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;
}

@ -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<PieceType, 120> const *board);
Color get_color(int pn, std::array<PieceType, 120> 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<PieceType, 120> *pt,std::vector<
void filter_checked_moves(int pos, std::array<PieceType, 120> *board, std::vector<int> *moves);
// 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);
std::vector<int> get_all_moves(int pos, std::array<PieceType, 120> board, bool recursive=true, int en_passant=Position::NA);
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);
// Decides if there this piece in position is in check
bool is_checked(int pos, std::array<PieceType, 120> board);

@ -110,8 +110,8 @@ const std::array<PieceType, 120> B_KING_BOARD = {
const std::vector<int> B_KING_ALL_MOVES = {
B5, C5, D5,
B4, D4,
B3, C3, D3
B3, C3, D3,
D4, B4
};
@ -170,8 +170,7 @@ const std::array<PieceType, 120> B_KING_SIDE1_BOARD = {
INV, INV, INV, INV, INV, INV, INV, INV, INV, INV
};
const std::vector<int> B_KING_SIDE1_ALL_MOVES = {
B8,
A7,B7
A7,B7,B8
};
const int B_PAWN_SIDE1_POS = A7;

@ -160,14 +160,14 @@ const std::array<PieceType, 120> W_KING_SIDE1_BOARD = {
};
const std::vector<int> W_KING_SIDE1_ALL_MOVES = {
B8,
A7,B7
A7,B7,
B8
};
const std::vector<int> W_KING_ALL_MOVES = {
B5, C5, D5,
B4, D4,
B3, C3, D3
B3, C3, D3,
D4, B4
};

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

@ -119,7 +119,7 @@ const std::array<PieceType, 120> 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<int> NO_EN_PASSANT_TEST_MOVES = {D6};
// Castling tests
const int CASTLING_POS = E1;
const int BCASTLING_POS = E8;
const std::array<PieceType, 120> 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<PieceType, 120> CASTLING_BOARD = {
INV, INV, INV, INV, INV, INV, INV, INV, INV, INV
};
// Should NOT inclde D7
const std::vector<int> CASTLING_MOVES = {
D1, D2, E2, F2, F1,
C1, G1
D2, E2, F2, F1,
D1, G1, C1
};
const std::vector<int> BCASTLING_MOVES = {
D7, E7, F7, F8, D8, G8, C8
};
const std::array<PieceType, 120> 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<PieceType, 120> 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<PieceType, 120> 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<int> 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<PieceType, 120> 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<int> KING_CHECK_TEST_MOVES = {
C7, E7,
D5,
E6, C6
};
const std::vector<int> KING_CHECK_ROOK_MOVES = {
C5, B5, A5,
D6, E5, F5,
D4, D3, D2, D1
};

Loading…
Cancel
Save