Skip to content
Snippets Groups Projects
Commit 893ead75 authored by Clément Desberg's avatar Clément Desberg
Browse files

commited on 20240510

parent ae35c97c
Branches
No related merge requests found
......@@ -74,4 +74,10 @@ bool pawn::is_possible_attack(coordinates dest){
return is_corresponding(coord,dest,coordinates(1,-1)) || is_corresponding(coord,dest,coordinates(-1,-1));
}
}
/// @brief retrieve the piece's legal moves
/// @return the legal moves vector
std::vector<coordinates> pawn::get_legals(){
return possible_legals;
}
\ No newline at end of file
......@@ -7,6 +7,9 @@
/// @brief the pawn piece class.
class pawn : public piece{
private:
// The standard moves and the attack moves all at once
std::vector<coordinates> possible_legals;
public:
pawn(bool _white, coordinates _coord):
piece(_white,_coord)
......@@ -20,13 +23,20 @@ class pawn : public piece{
}
// The attack moves list is managed in the overrided is_possible_attack function.
legals.push_back(coordinates(0,2*direction));
possible_legals.push_back(coordinates(0,2*direction));
legals.push_back(coordinates(0,direction));
possible_legals.push_back(coordinates(0,direction));
// Attack moves in possible_legals
possible_legals.push_back(coordinates(1,direction));
possible_legals.push_back(coordinates(-1,direction));
}
void needed_space(coordinates dest, std::vector<coordinates> *to_calculate) override;
void print_piece() override;
void canonical_print_piece() override;
void move(coordinates dest, bool debug_info) override;
bool is_possible_attack(coordinates dest) override;
// We need to override because the pawn has attack moves that differs from legals (standard) move
std::vector<coordinates> get_legals() override;
};
#endif
\ No newline at end of file
......@@ -93,7 +93,7 @@ piece_type piece::get_type(){
}
/// @brief retrieve the piece's legal moves
/// @return the legal moves vectro
/// @return the legal moves vector
std::vector<coordinates> piece::get_legals(){
return legals;
}
\ No newline at end of file
......@@ -27,7 +27,7 @@ class piece{
bool get_color();
bool get_has_moved();
piece_type get_type();
std::vector<coordinates> get_legals();
virtual std::vector<coordinates> get_legals();
};
#endif
\ No newline at end of file
No preview for this file type
......@@ -4,6 +4,7 @@
board::board():
last_move(0,0)
{
without_attack_or_pawn_counter = 0;
last_move_en_passant_eligible = false;
white_pieces = {};
for(int i = 0; i < 8; i++){
......@@ -52,6 +53,7 @@ board::board():
board::board(const board& other):
last_move(other.last_move), last_move_en_passant_eligible(other.last_move_en_passant_eligible)
{
without_attack_or_pawn_counter = 0;
white_pieces = {};
for(int i = 0; i < other.white_pieces.size(); i++){
switch (other.white_pieces[i]->get_type())
......@@ -234,6 +236,8 @@ void board::canonical_print(){
/// @brief Erase a piece from its corresponding vector according to its coordinates
/// @param coord the coordinates of the piece to erase
void board::erase_piece(coordinates coord){
// Reset the counter
without_attack_or_pawn_counter = 0;
bool piece_found = false;
for(int i = 0; i < white_pieces.size() && !piece_found; i++){
if(white_pieces[i]->get_coord().get_x() == coord.get_x() && white_pieces[i]->get_coord().get_y() == coord.get_y()){
......@@ -253,6 +257,12 @@ void board::erase_piece(coordinates coord){
/// @param move_from the initial coordinates of the piece
/// @param move_to the final coordinates of the piece
void board::move(coordinates move_from, coordinates move_to){
// Increment the counter if not a pawn, else reset it
if(board_data[move_from.get_x()][move_from.get_y()]->get_type() == pawn_type){
without_attack_or_pawn_counter = 0;
}else{
without_attack_or_pawn_counter++;
}
if(board_data[move_to.get_x()][move_to.get_y()] != nullptr){
//Attack case : remove the other piece
erase_piece(move_to);
......@@ -297,6 +307,12 @@ bool board::is_en_passant_legal(coordinates move_from, coordinates move_to, bool
/// @param white_move indicate if the current active player is White
/// @return a boolean indicating if the move is legal
bool board::is_legal(coordinates move_from, coordinates move_to, bool white_move){
//Check the move isn't off the board
if(move_from.get_x() < 0 || move_from.get_x() > 7 || move_from.get_y() < 0 || move_from.get_y() > 7 ||
move_to.get_x() < 0 || move_to.get_x() > 7 || move_to.get_y() < 0 || move_to.get_y() > 7){
return false;
}
if(board_data[move_from.get_x()][move_from.get_y()] == nullptr){
//Moving from an empty space, wrong move
return false;
......@@ -522,4 +538,75 @@ void board::promote(coordinates to_promote, piece_type new_type){
/// @return if a promotion is needed at the selected coordinates
bool board::is_promotion_needed(coordinates coord){
return((board_data[coord.get_x()][coord.get_y()]->get_type() == pawn_type) && ((coord.get_y() == 0)||(coord.get_y() == 7)));
}
/// @brief check if the other player can move without being in a check state
/// @param white_move true if the player that just played is White
/// @return true if the opposite player can't move without being in check state
bool board::is_checkmate_or_pat(bool white_move){
// 50 moves rule
if(without_attack_or_pawn_counter >= 50){
return true;
}
bool result = true;
// The copy of the copy
board *chess_board_copy;
// A check board copy
board *chess_board;
coordinates start(0,0);
coordinates end(0,0);
if(white_move){
for(int i = 0; i < black_pieces.size(); i++){
// For each piece, we test all moves
// We don't have to check the castling moves because they're unauthorized when in a check state
for(int j = 0; j < black_pieces[i]->get_legals().size(); j++){
// For a move, we check if it's still in check
chess_board = new board(*this);
start.move(black_pieces[i]->get_coord());
// Simulate a movement
end.move(coordinates(black_pieces[i]->get_coord().get_x() + black_pieces[i]->get_legals()[j].get_x(),
black_pieces[i]->get_coord().get_y() + black_pieces[i]->get_legals()[j].get_y()));
if(chess_board->is_legal(start,end,!white_move)){
//Apply the movement on a chess board copy and verify the check state of the current player's king
chess_board_copy = new board(*chess_board);
chess_board_copy->move(start,end);
if(chess_board_copy->is_check(!white_move)){
//The move is making the active player in check state, illegal
}else{
//The move is legal and the player isn't in check, therefore it isn't a checkmate.
result = false;
}
delete chess_board_copy;
}
delete chess_board;
}
}
}else{
for(int i = 0; i < white_pieces.size(); i++){
// For each piece, we test all moves
// We don't have to check the castling moves because they're unauthorized when in a check state
for(int j = 0; j < white_pieces[i]->get_legals().size(); j++){
// For a move, we check if it's still in check
chess_board = new board(*this);
start.move(white_pieces[i]->get_coord());
// Simulate a movement
end.move(coordinates(white_pieces[i]->get_coord().get_x() + white_pieces[i]->get_legals()[j].get_x(),
white_pieces[i]->get_coord().get_y() + white_pieces[i]->get_legals()[j].get_y()));
if(chess_board->is_legal(start,end,!white_move)){
//Apply the movement on a chess board copy and verify the check state of the current player's king
chess_board_copy = new board(*chess_board);
chess_board_copy->move(start,end);
if(chess_board_copy->is_check(!white_move)){
//The move is making the active player in check state, illegal
}else{
//The move is legal and the player isn't in check, therefore it isn't a checkmate.
result = false;
}
delete chess_board_copy;
}
delete chess_board;
}
}
}
return result;
}
\ No newline at end of file
......@@ -26,6 +26,7 @@ class board{
std::vector<piece*> black_pieces;
coordinates last_move;
bool last_move_en_passant_eligible;
int without_attack_or_pawn_counter;
public:
board();
board(const board& other);
......@@ -44,6 +45,7 @@ class board{
void queen_castle(bool white_move);
void promote(coordinates to_promote, piece_type new_type);
bool is_promotion_needed(coordinates coord);
bool is_checkmate_or_pat(bool white_move);
};
void print_neutral_endl();
......
......@@ -153,6 +153,36 @@ int main(){
}
}
}
//Checkmate and pat detection
if(chess_board.is_checkmate_or_pat(white_move)){
game_end = true;
chess_board.print();
if(white_move){
if(chess_board.is_check(!white_move)){
game_result = win_white;
terminal_set_background_color(BACKGROUND_COLOR1);
terminal_set_text_color(PIECES_COLOR);
std::cout << "White win.";
print_neutral_endl();
}else{
game_result = draw;
std::cout << "Draw.";
print_neutral_endl();
}
}else{
if(chess_board.is_check(!white_move)){
game_result = win_black;
terminal_set_background_color(PIECES_COLOR);
terminal_set_text_color(BACKGROUND_COLOR1);
std::cout << "Black win.";
print_neutral_endl();
}else{
game_result = draw;
std::cout << "Draw.";
print_neutral_endl();
}
}
}
white_move = !white_move;
}
chess_board.canonical_print();
......
......@@ -112,4 +112,10 @@ bool king_castle_input(std::string const & cmd){
bool queen_castle_input(std::string const & cmd){
std::regex queencastlemouvmtpattern("(O|o|0)-(O|o|0)-(O|o|0)");
return regex_match(cmd,queencastlemouvmtpattern);
}
/// @brief Print a message to the standard output : "test i". Used for debug purposes
/// @param i the number that appear on the debug message
void print_debug(int i){
std::cout << "test" << i << std::endl;
}
\ No newline at end of file
......@@ -14,5 +14,6 @@ bool correct_input(std::string const & cmd);
bool standard_input(std::string const & cmd);
bool king_castle_input(std::string const & cmd);
bool queen_castle_input(std::string const & cmd);
void print_debug(int i);
#endif
\ No newline at end of file
This diff is collapsed.
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment