Finished version, might have memory leaks

This commit is contained in:
2022-04-15 23:13:15 -04:00
parent e6e567e734
commit cbdf377c86
9 changed files with 703 additions and 41 deletions
+291 -29
View File
@@ -9,6 +9,7 @@
Board::Board()
{
load_FEN(std::string("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"));
//load_FEN(std::string("socqkcos/pppppppp/8/8/8/8/PPPPPPPP/SOCQKCOS w KQkq - 0 1"));
}
Board::Board(std::string board_fen)
@@ -31,7 +32,7 @@ void Board::load_FEN(std::string board_fen)
int x=0,y=0;
std::string black_team("kqbnrpcos");
std::string white_team("KQBNRPCOS");
for(int i = 0; i < board_fen.size() && !(x==BOARD_SIZE-1 && y==BOARD_SIZE); i++)
for(unsigned int i = 0; i < board_fen.size() && board_fen[i] != ' '; i++)
{
if (board_fen[i] == '/')
{
@@ -135,11 +136,125 @@ void Board::load_FEN(std::string board_fen)
full_turn_count = strtol(full_turn_count_loc, nullptr, 10);
}
std::string Board::make_FEN()
{
std::string str_out = "";
std::string black_team("kqbnrpcos");
std::string white_team("KQBNRPCOS");
for (int y = 0; y < BOARD_SIZE; y++)
{
int skipped_count = 0;
for (int x = 0; x < BOARD_SIZE; x++)
{
Piece cur_piece = game_board[x][y];
if (cur_piece.get_type() != NO_TYPE)
{
if (skipped_count != 0)
{
str_out += skipped_count+'0';
}
if (cur_piece.get_vis() == HIDDEN)
{
cur_piece = Piece((Type)(cur_piece.get_type()+UNKNOWN-BISHOP), cur_piece.get_team(), SHOWN);
}
if (cur_piece.get_team() == WHITE)
{
str_out+=white_team[cur_piece.get_type()];
}
else if (cur_piece.get_team() == BLACK)
{
str_out+=black_team[cur_piece.get_type()];
}
skipped_count = 0;
}
else
{
skipped_count++;
}
}
if (skipped_count != 0)
{
str_out += skipped_count+'0';
}
str_out += "/";
}
str_out += " ";
if (active_color == WHITE)
{
str_out += "w ";
}
else
{
str_out += "b ";
}
if (able_to_castle[0][0] || able_to_castle[0][1] || able_to_castle[1][0] || able_to_castle[1][1])
{
if (able_to_castle[WHITE][KING])
{
str_out += "K";
}
if (able_to_castle[WHITE][QUEEN])
{
str_out += "Q";
}
if (able_to_castle[BLACK][KING])
{
str_out += "k";
}
if (able_to_castle[BLACK][QUEEN])
{
str_out += "q";
}
}
else
{
str_out += "-";
}
str_out += " ";
if (en_passant == -1)
{
str_out += "- ";
}
else
{
int ep_x = en_passant%BOARD_SIZE;
int ep_y = en_passant/BOARD_SIZE;
str_out += ep_x+'a';
str_out += ep_y+'0';
str_out += " ";
}
str_out += std::to_string(half_turn_count);
str_out += " ";
str_out += std::to_string(full_turn_count);
return str_out;
}
void Board::draw_board(SDL_Surface* dest_surface)
{
bool light_tile = true;
std::vector<int> target_spaces = get_moves_for_space(selected_space);
std::vector<int> target_spaces = get_moves_for_space(selected_space, true);
for (int x = 0; x < BOARD_SIZE; x++)
{
@@ -205,7 +320,13 @@ void Board::draw_board(SDL_Surface* dest_surface)
SDL_FillRect(piece_surface, nullptr, SDL_MapRGB(piece_surface->format, 0xFF, 0x00, 0xFF));
SDL_SetColorKey(piece_surface, SDL_TRUE, SDL_MapRGB(piece_surface->format, 0xFF, 0x00, 0xFF));
if (0 == Sprite::get(game_board[x][y], piece_surface))
Piece cur_piece = game_board[x][y];
if (cur_piece.get_vis() == HIDDEN && cur_piece.get_team() == BLACK)
{
cur_piece = Piece(UNKNOWN, BLACK, SHOWN);
}
if (0 == Sprite::get(cur_piece, piece_surface))
{
SDL_BlitSurface(piece_surface, nullptr, dest_surface, &dest_rect);
}
@@ -262,14 +383,20 @@ int Board::get_full_turn_count()
void Board::set_selected_space(int x, int y)
{
if (game_board[x][y].get_team() != WHITE)
{
selected_space = -1;
return;
}
selected_space = x+y*BOARD_SIZE;
}
void Board::set_selected_space(int space)
{
if (game_board[space%BOARD_SIZE][space/BOARD_SIZE].get_team() != WHITE)
{
selected_space = -1;
return;
}
selected_space = space;
}
@@ -286,16 +413,18 @@ int Board::get_selected_space()
return selected_space;
}
std::vector<int> Board::get_moves_for_space(int x, int y)
std::vector<int> Board::get_moves_for_space(int x, int y, bool check_for_check)
{
if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE || game_board[x][y].get_type() == NO_TYPE)
return std::vector<int>();
int forward_direction = (game_board[x][y].get_team() == WHITE)?-1:1;
bool is_team_in_check = (check_for_check && is_check(game_board[x][y].get_team()));
std::vector<int> out_spaces;
Type piece_type = (game_board[x][y].get_vis() == VIS_NONE)?UNKNOWN:game_board[x][y].get_type();
Type piece_type = (game_board[x][y].get_vis() == HIDDEN)?UNKNOWN:game_board[x][y].get_type();
if (PAWN == piece_type)
{
@@ -327,7 +456,7 @@ std::vector<int> Board::get_moves_for_space(int x, int y)
if (QUEEN == piece_type || ROOK == piece_type)
{
for (int x1 = x-1; x1 > 0; x1--)
for (int x1 = x-1; x1 >= 0; x1--)
{
MoveType result = can_move(x+y*BOARD_SIZE, x1+y*BOARD_SIZE);
if (BLOCKED == result)
@@ -347,7 +476,7 @@ std::vector<int> Board::get_moves_for_space(int x, int y)
break;
}
for (int y1 = y-1; y1 > 0; y1--)
for (int y1 = y-1; y1 >= 0; y1--)
{
MoveType result = can_move(x+y*BOARD_SIZE, x+y1*BOARD_SIZE);
if (BLOCKED == result)
@@ -357,7 +486,7 @@ std::vector<int> Board::get_moves_for_space(int x, int y)
break;
}
for (int y1 = y+1; y1 > 0; y1++)
for (int y1 = y+1; y1 < BOARD_SIZE; y1++)
{
MoveType result = can_move(x+y*BOARD_SIZE, x+y1*BOARD_SIZE);
if (BLOCKED == result)
@@ -441,19 +570,7 @@ std::vector<int> Board::get_moves_for_space(int x, int y)
continue;
}
Piece old_piece = game_board[x1][y1];
game_board[x1][y1] = game_board[x][y];
game_board[x][y] = Piece();
bool was_check = is_check(game_board[x1][y1].get_team());
game_board[x][y] = game_board[x1][y1];
game_board[x1][y1] = old_piece;
if (!was_check)
{
out_spaces.push_back(x1+y1*BOARD_SIZE);
}
out_spaces.push_back(x1+y1*BOARD_SIZE);
}
if (able_to_castle[game_board[x][y].get_team()][KING] &&
@@ -511,10 +628,10 @@ std::vector<int> Board::get_moves_for_space(int x, int y)
if (CAPTURE != result)
{
int x1 = x+2*unknown_offsets[i][0];
int y1 = y+2*unknown_offsets[i][1];
x1 = x+2*unknown_offsets[i][0];
y1 = y+2*unknown_offsets[i][1];
if (x1 >= 0 && x1 < BOARD_SIZE && y1 >= 0 && y1 < BOARD_SIZE || BLOCKED == can_move(x+y*BOARD_SIZE, x1+y1*BOARD_SIZE))
if (x1 >= 0 && x1 < BOARD_SIZE && y1 >= 0 && y1 < BOARD_SIZE && BLOCKED != can_move(x+y*BOARD_SIZE, x1+y1*BOARD_SIZE))
{
out_spaces.push_back(x1+y1*BOARD_SIZE);
}
@@ -525,14 +642,20 @@ std::vector<int> Board::get_moves_for_space(int x, int y)
out_spaces.push_back(x+y*BOARD_SIZE);
}
if (is_team_in_check)
{
std::vector<int>::iterator new_end = std::remove_if(out_spaces.begin(), out_spaces.end(), [this, x, y](const int& target_space){ return !this->does_move_solve_check(x+y*BOARD_SIZE, target_space); });
out_spaces.erase(new_end, out_spaces.end());
}
return out_spaces;
}
std::vector<int> Board::get_moves_for_space(int space)
std::vector<int> Board::get_moves_for_space(int space, bool check_for_check)
{
if (space < 0 || space >= BOARD_SIZE*BOARD_SIZE)
return std::vector<int>();
return get_moves_for_space(space%BOARD_SIZE, space/BOARD_SIZE);
return get_moves_for_space(space%BOARD_SIZE, space/BOARD_SIZE, check_for_check);
}
bool Board::is_check(Team team)
@@ -557,13 +680,13 @@ bool Board::is_check(Team team)
return false;
}
for(int x = 0; x < BOARD_SIZE && king_space == -1; x++)
for(int x = 0; x < BOARD_SIZE; x++)
{
for(int y = 0; y < BOARD_SIZE && king_space == -1; y++)
for(int y = 0; y < BOARD_SIZE; y++)
{
if (game_board[x][y].get_team() == enemy_team)
{
std::vector<int> possible_moves = get_moves_for_space(x,y);
std::vector<int> possible_moves = get_moves_for_space(x,y, false);
if (possible_moves.end() != std::find(possible_moves.begin(), possible_moves.end(), king_space))
{
return true;
@@ -575,6 +698,121 @@ bool Board::is_check(Team team)
return false;
}
bool Board::is_mate(Team team)
{
if (!is_check(team))
{
return false;
}
for(int x = 0; x < BOARD_SIZE; x++)
{
for(int y = 0; y < BOARD_SIZE; y++)
{
if (game_board[x][y].get_team() == team)
{
std::vector<int> possible_moves = get_moves_for_space(x,y,false);
if (possible_moves.end() != std::find_if(possible_moves.begin(), possible_moves.end(), [this, x, y](const int& target_space){ return this->does_move_solve_check(x+y*BOARD_SIZE, target_space); }))
{
return false;
}
}
}
}
return true;
}
void Board::do_move(int space_from, int space_to, bool holding_k)
{
if (space_from < 0 || space_to < 0 || space_from >= BOARD_SIZE*BOARD_SIZE || space_to >= BOARD_SIZE*BOARD_SIZE)
{
return;
}
int xf=space_from%BOARD_SIZE,yf=space_from/BOARD_SIZE,xt=space_to%BOARD_SIZE,yt=space_to/BOARD_SIZE;
Piece cur_piece = game_board[xf][yf];
Piece target_piece = game_board[xt][yt];
Team enemy_team = (cur_piece.get_team() == WHITE)?BLACK:WHITE;
en_passant = -1;
if (cur_piece.get_team() == BLACK)
{
full_turn_count++;
}
if (cur_piece.get_type() == PAWN)
{
half_turn_count = 0;
if (yf-yt == 2 || yt-yf == 2)
{
int ep_y = (yt+yf)/2;
en_passant = xf+ep_y*BOARD_SIZE;
}
if (yt == 7 && cur_piece.get_team() == BLACK)
{
cur_piece = Piece((holding_k)?KNIGHT:QUEEN, BLACK, SHOWN);
}
if (yt == 0 && cur_piece.get_team() == WHITE)
{
cur_piece = Piece((holding_k)?KNIGHT:QUEEN, WHITE, SHOWN);
}
}
if (cur_piece.get_type() == ROOK && cur_piece.get_vis() == SHOWN)
{
if (xf == 7)
{
able_to_castle[cur_piece.get_team()][KING] = false;
}
if (xf == 0)
{
able_to_castle[cur_piece.get_team()][QUEEN] = false;
}
}
bool castling = false;
if (cur_piece.get_type() == KING)
{
if (target_piece.get_type() == ROOK && target_piece.get_team() == cur_piece.get_team() && target_piece.get_vis() == SHOWN)
{
castling = true;
}
able_to_castle[cur_piece.get_team()][KING] = false;
able_to_castle[cur_piece.get_team()][QUEEN] = false;
}
if (xf == xt && yf == yt && cur_piece.get_vis() == HIDDEN)
{
cur_piece = Piece(cur_piece.get_type(), cur_piece.get_team(), SHOWN);
}
if (castling)
{
game_board[xf][yf] = target_piece;
}
else
{
game_board[xf][yf] = Piece();
}
game_board[xt][yt] = cur_piece;
if(is_check(enemy_team))
{
able_to_castle[enemy_team][KING] = false;
able_to_castle[enemy_team][QUEEN] = false;
}
active_color = (active_color == WHITE)?BLACK:WHITE;
selected_space = -1;
}
MoveType Board::can_move(int space_from, int space_to)
{
if (space_from < 0 || space_to < 0 || space_from >= BOARD_SIZE*BOARD_SIZE || space_to >= BOARD_SIZE*BOARD_SIZE)
@@ -602,5 +840,29 @@ MoveType Board::can_move(int space_from, int space_to)
return CAPTURE;
}
if (game_board[xf][yf].get_type() == KING)
{
if (able_to_castle[game_board[xf][yf].get_team()][KING] &&
game_board[7][yf].get_team() == game_board[xf][yf].get_team() && game_board[7][yf].get_type() == ROOK && game_board[7][yf].get_vis() == SHOWN &&
game_board[6][yf].get_type() == NO_TYPE && game_board[5][yf].get_type() == NO_TYPE)
{
return FREE;
}
if (able_to_castle[game_board[xf][yf].get_team()][QUEEN] &&
game_board[0][yf].get_team() == game_board[xf][yf].get_team() && game_board[0][yf].get_type() == ROOK && game_board[0][yf].get_vis() == SHOWN &&
game_board[1][yf].get_type() == NO_TYPE && game_board[2][yf].get_type() == NO_TYPE && game_board[3][yf].get_type() == NO_TYPE)
{
return FREE;
}
}
return BLOCKED;
}
bool Board::does_move_solve_check(int space_from, int space_to)
{
Board test_board(make_FEN());
test_board.do_move(space_from, space_to, false);
return !test_board.is_check(game_board[space_from%BOARD_SIZE][space_from/BOARD_SIZE].get_team());
}