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

commited on 20240509

parent e49b2623
No related merge requests found
...@@ -80,6 +80,12 @@ bool piece::get_color(){ ...@@ -80,6 +80,12 @@ bool piece::get_color(){
return white; return white;
} }
/// @brief retrieve if the piece has already moved during the game
/// @return the has_moved attribute
bool piece::get_has_moved(){
return has_moved;
}
/// @brief retrieve the piece's type /// @brief retrieve the piece's type
/// @return the type of the piece /// @return the type of the piece
piece_type piece::get_type(){ piece_type piece::get_type(){
......
...@@ -25,6 +25,7 @@ class piece{ ...@@ -25,6 +25,7 @@ class piece{
virtual void move(coordinates dest,bool debug_info); virtual void move(coordinates dest,bool debug_info);
coordinates get_coord(); coordinates get_coord();
bool get_color(); bool get_color();
bool get_has_moved();
piece_type get_type(); piece_type get_type();
}; };
......
No preview for this file type
...@@ -47,6 +47,75 @@ board::board(): ...@@ -47,6 +47,75 @@ board::board():
} }
} }
/// @brief the copy constructor, which also copy the pieces pointers
/// @param other
board::board(const board& other):
last_move(other.last_move), last_move_en_passant_eligible(other.last_move_en_passant_eligible)
{
white_pieces = {};
for(int i = 0; i < other.white_pieces.size(); i++){
switch (other.white_pieces[i]->get_type())
{
case pawn_type:
white_pieces.push_back(new pawn(other.white_pieces[i]->get_color(),other.white_pieces[i]->get_coord()));
break;
case bishop_type:
white_pieces.push_back(new bishop(other.white_pieces[i]->get_color(),other.white_pieces[i]->get_coord()));
break;
case knight_type:
white_pieces.push_back(new knight(other.white_pieces[i]->get_color(),other.white_pieces[i]->get_coord()));
break;
case rook_type:
white_pieces.push_back(new rook(other.white_pieces[i]->get_color(),other.white_pieces[i]->get_coord()));
break;
case queen_type:
white_pieces.push_back(new queen(other.white_pieces[i]->get_color(),other.white_pieces[i]->get_coord()));
break;
case king_type:
white_pieces.push_back(new king(other.white_pieces[i]->get_color(),other.white_pieces[i]->get_coord()));
break;
}
}
black_pieces = {};
for(int i = 0; i < other.black_pieces.size(); i++){
switch (other.black_pieces[i]->get_type())
{
case pawn_type:
black_pieces.push_back(new pawn(other.black_pieces[i]->get_color(),other.black_pieces[i]->get_coord()));
break;
case bishop_type:
black_pieces.push_back(new bishop(other.black_pieces[i]->get_color(),other.black_pieces[i]->get_coord()));
break;
case knight_type:
black_pieces.push_back(new knight(other.black_pieces[i]->get_color(),other.black_pieces[i]->get_coord()));
break;
case rook_type:
black_pieces.push_back(new rook(other.black_pieces[i]->get_color(),other.black_pieces[i]->get_coord()));
break;
case queen_type:
black_pieces.push_back(new queen(other.black_pieces[i]->get_color(),other.black_pieces[i]->get_coord()));
break;
case king_type:
black_pieces.push_back(new king(other.black_pieces[i]->get_color(),other.black_pieces[i]->get_coord()));
break;
}
}
// Initialize the board with empty pieces
for(int i = 0; i < 8; i++){
for(int j = 0; j < 8; j++){
board_data[i][j] = nullptr;
}
}
// Putting the pieces in place
for(int i = 0; i < white_pieces.size(); i++){
put(white_pieces[i]);
}
for(int i = 0; i < black_pieces.size(); i++){
put(black_pieces[i]);
}
}
/// @brief put a piece onto the board according to its coordinates /// @brief put a piece onto the board according to its coordinates
/// @param to_put /// @param to_put
void board::put(piece* to_put){ void board::put(piece* to_put){
...@@ -138,6 +207,16 @@ void board::print(){ ...@@ -138,6 +207,16 @@ void board::print(){
line_switcher = !line_switcher; line_switcher = !line_switcher;
} }
std::cout << " a b c d e f g h " << std::endl; std::cout << " a b c d e f g h " << std::endl;
// std::cout << "white:" << std::endl;
// for(int i = 0; i < white_pieces.size(); i ++){
// white_pieces[i]->canonical_print_piece();
// std::cout << " x=" << white_pieces[i]->get_coord().get_x() << " y=" << white_pieces[i]->get_coord().get_y() << std::endl;
// }
// std::cout << "black:" << std::endl;
// for(int i = 0; i < black_pieces.size(); i ++){
// black_pieces[i]->canonical_print_piece();
// std::cout << " x=" << black_pieces[i]->get_coord().get_x() << " y=" << black_pieces[i]->get_coord().get_y() << std::endl;
// }
} }
/// @brief print the board in canonical form /// @brief print the board in canonical form
...@@ -165,7 +244,6 @@ void board::erase_piece(coordinates coord){ ...@@ -165,7 +244,6 @@ void board::erase_piece(coordinates coord){
for(int i = 0; i < black_pieces.size() && !piece_found; i++){ for(int i = 0; i < black_pieces.size() && !piece_found; i++){
if(black_pieces[i]->get_coord().get_x() == coord.get_x() && black_pieces[i]->get_coord().get_y() == coord.get_y()){ if(black_pieces[i]->get_coord().get_x() == coord.get_x() && black_pieces[i]->get_coord().get_y() == coord.get_y()){
piece_found = true; piece_found = true;
std::cout << "piece erased" << std::endl;
black_pieces.erase(black_pieces.begin() + i); black_pieces.erase(black_pieces.begin() + i);
} }
} }
...@@ -213,7 +291,7 @@ bool board::is_en_passant_legal(coordinates move_from, coordinates move_to, bool ...@@ -213,7 +291,7 @@ bool board::is_en_passant_legal(coordinates move_from, coordinates move_to, bool
return true; return true;
} }
/// @brief Check if a move is legal /// @brief Check if a move is legal, without checking it in regards to king check state
/// @param move_from the initial position /// @param move_from the initial position
/// @param move_to the final position /// @param move_to the final position
/// @param white_move indicate if the current active player is White /// @param white_move indicate if the current active player is White
...@@ -309,6 +387,8 @@ bool board::is_check(bool white_king){ ...@@ -309,6 +387,8 @@ bool board::is_check(bool white_king){
bool result = false; bool result = false;
if(white_king){ if(white_king){
for(int i = 0; i < black_pieces.size(); i++){ for(int i = 0; i < black_pieces.size(); i++){
if(black_pieces[i]->get_type() == queen_type){
}
result = result || is_legal(black_pieces[i]->get_coord(),get_king_coord(white_king),!white_king); result = result || is_legal(black_pieces[i]->get_coord(),get_king_coord(white_king),!white_king);
} }
}else{ }else{
...@@ -317,4 +397,129 @@ bool board::is_check(bool white_king){ ...@@ -317,4 +397,129 @@ bool board::is_check(bool white_king){
} }
} }
return result; return result;
}
/// @brief check if the king-side castling move is legal, without checking it in regards to king check state
/// @param white_move if the current player is White
/// @return a boolean equals to true if the king-side castling move is legal
bool board::is_king_castling_legal(bool white_move){
int y;
if(white_move){
y = 0;
}else{
y = 7;
}
//We first check that the two pieces are in place
if(board_data[4][y] == nullptr || board_data[7][y] == nullptr){
return false;
}
//We then check that the two pieces didn't moved. Don't need to check the type since we check they didn't moved
if(board_data[4][y]->get_has_moved() || board_data[7][y]->get_has_moved()){
return false;
}
//We then check if there is space to perform the castling
return (board_data[5][y] == nullptr) && (board_data[6][y] == nullptr);
}
/// @brief check if the queen-side castling move is legal, without checking it in regards to king check state
/// @param white_move if the current player is White
/// @return a boolean equals to true if the queen-side castling move is legal
bool board::is_queen_castling_legal(bool white_move){
int y;
if(white_move){
y = 0;
}else{
y = 7;
}
//We first check that the two pieces are in place
if(board_data[4][y] == nullptr || board_data[0][y] == nullptr){
return false;
}
//We then check that the two pieces didn't moved
if(board_data[4][y]->get_has_moved() || board_data[0][y]->get_has_moved()){
return false;
}
//We then check if there is space to perform the castling
return (board_data[1][y] == nullptr) && (board_data[2][y] == nullptr) && (board_data[3][y] == nullptr);
}
/// @brief perform the king-side castling move
/// @param white_move true if the player is White
void board::king_castle(bool white_move){
int y;
if(white_move){
y = 0;
}else{
y = 7;
}
move(coordinates(4,y),coordinates(6,y));
move(coordinates(7,y),coordinates(5,y));
}
/// @brief perform the queen-side castling move
/// @param white_move true if the player is White
void board::queen_castle(bool white_move){
int y;
if(white_move){
y = 0;
}else{
y = 7;
}
move(coordinates(4,y),coordinates(2,y));
move(coordinates(0,y),coordinates(3,y));
}
/// @brief Perform a promotion on the specified coordinates. Don't check anything
/// @param to_promote the coordinates of the piece to promote
/// @param new_type the new type of the piece
void board::promote(coordinates to_promote, piece_type new_type){
bool color = board_data[to_promote.get_x()][to_promote.get_y()]->get_color();
erase_piece(to_promote);
if(color){
switch (new_type)
{
case rook_type:
white_pieces.push_back(new rook(color,to_promote));
break;
case bishop_type:
white_pieces.push_back(new bishop(color,to_promote));
break;
case knight_type:
white_pieces.push_back(new knight(color,to_promote));
break;
case queen_type:
white_pieces.push_back(new queen(color,to_promote));
break;
}
//Put the newly added piece on the board
put(white_pieces[white_pieces.size()]);
}else{
switch (new_type)
{
case rook_type:
black_pieces.push_back(new rook(color,to_promote));
break;
case bishop_type:
black_pieces.push_back(new bishop(color,to_promote));
break;
case knight_type:
black_pieces.push_back(new knight(color,to_promote));
break;
case queen_type:
black_pieces.push_back(new queen(color,to_promote));
break;
}
//Put the newly added piece on the board
put(black_pieces[black_pieces.size() - 1]);
}
}
/// @brief check if a promotion is needed
/// @param coord the coordinates to check
/// @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)));
} }
\ No newline at end of file
...@@ -28,6 +28,7 @@ class board{ ...@@ -28,6 +28,7 @@ class board{
bool last_move_en_passant_eligible; bool last_move_en_passant_eligible;
public: public:
board(); board();
board(const board& other);
void print(); void print();
void canonical_print(); void canonical_print();
void put(piece* to_put); void put(piece* to_put);
...@@ -37,6 +38,12 @@ class board{ ...@@ -37,6 +38,12 @@ class board{
coordinates get_king_coord(bool white_king); coordinates get_king_coord(bool white_king);
bool is_check(bool white_king); bool is_check(bool white_king);
bool is_en_passant_legal(coordinates move_from, coordinates move_to, bool white_move); bool is_en_passant_legal(coordinates move_from, coordinates move_to, bool white_move);
bool is_king_castling_legal(bool white_move);
bool is_queen_castling_legal(bool white_move);
void king_castle(bool white_move);
void queen_castle(bool white_move);
void promote(coordinates to_promote, piece_type new_type);
bool is_promotion_needed(coordinates coord);
}; };
void print_neutral_endl(); void print_neutral_endl();
......
...@@ -16,6 +16,7 @@ int main(){ ...@@ -16,6 +16,7 @@ int main(){
coordinates end(0,0); coordinates end(0,0);
bool white_move = true; bool white_move = true;
winner_type game_result; winner_type game_result;
board *chess_board_copy;
while(!game_end){ while(!game_end){
chess_board.print(); chess_board.print();
movement = ""; movement = "";
...@@ -63,25 +64,91 @@ int main(){ ...@@ -63,25 +64,91 @@ int main(){
}else{ }else{
if(correct_input(movement)){ if(correct_input(movement)){
//The movement input is correct //The movement input is correct
coordinates start = get_coord_from_string(movement.substr(0, 2)); if(standard_input(movement)){
coordinates end = get_coord_from_string(movement.substr(2, 2)); //Standard movement case
if(chess_board.is_legal(start,end,white_move)){ coordinates start = get_coord_from_string(movement.substr(0, 2));
//Apply the movement on a chess board copy and verify the check state of the current player's king coordinates end = get_coord_from_string(movement.substr(2, 2));
board chess_board_copy(chess_board); if(chess_board.is_legal(start,end,white_move)){
chess_board_copy.move(start,end); //Apply the movement on a chess board copy and verify the check state of the current player's king
if(chess_board_copy.is_check(white_move)){ chess_board_copy = new board(chess_board);
//The move is making the active player in check state, illegal chess_board_copy->move(start,end);
std::cout << "Illegal move. Your king will be checked" << std::endl; if(chess_board_copy->is_check(white_move)){
//The move is making the active player in check state, illegal
std::cout << "Illegal move. Your king will be checked" << std::endl;
}else{
chess_board.move(start,end);
correct_move = true;
if(chess_board.is_promotion_needed(end)){
// Promotion selection
std::cout << "Promotion. Choose a piece to substitue the pawn : B/N/R/Q" << std::endl;
std::string chose_promotion = "";
while((chose_promotion != "B") && (chose_promotion != "N")
&& (chose_promotion != "R") && (chose_promotion != "Q")){
std::cin >> chose_promotion;
if((chose_promotion != "B") && (chose_promotion != "N")
&& (chose_promotion != "R") && (chose_promotion != "Q")){
std::cout << "Wrong input format. Input to be among : B,N,R and Q" << std::endl;
}
}
// We promote to the right piece
if(chose_promotion == "B"){
chess_board.promote(end,bishop_type);
}
if(chose_promotion == "N"){
chess_board.promote(end,knight_type);
}
if(chose_promotion == "R"){
chess_board.promote(end,rook_type);
}
if(chose_promotion == "Q"){
chess_board.promote(end,queen_type);
}
}
}
delete chess_board_copy;
}else{ }else{
chess_board.move(start,end); std::cout << "Illegal move." << std::endl;
correct_move = true; }
}
if(king_castle_input(movement)){
//King-side castling move
if(chess_board.is_king_castling_legal(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->king_castle(white_move);
if(chess_board_copy->is_check(white_move)){
//The move is making the active player in check state, illegal
std::cout << "Illegal move. Your king will be checked" << std::endl;
}else{
chess_board.king_castle(white_move);
correct_move = true;
}
delete chess_board_copy;
}else{
std::cout << "Illegal move." << std::endl;
}
}
if(queen_castle_input(movement)){
//Queen-side castling move
if(chess_board.is_queen_castling_legal(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->queen_castle(white_move);
if(chess_board_copy->is_check(white_move)){
//The move is making the active player in check state, illegal
std::cout << "Illegal move. Your king will be checked" << std::endl;
}else{
chess_board.queen_castle(white_move);
correct_move = true;
}
delete chess_board_copy;
}else{
std::cout << "Illegal move." << std::endl;
} }
}else{
std::cout << "Illegal move." << std::endl;
} }
}else{ }else{
//The movement input is wrong //The movement input is wrong
std::cout << "Wrong input format. Format need to be in algrebic notation : b1c3 for example." << std::endl; std::cout << "Wrong input format. Format need to be in algrebic notation : b1c3 for example. 0-0-0 and 0-0 for the castlings" << std::endl;
} }
} }
} }
......
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