I try to make an undo function for an atomic chess game in c++. If it is a caputre this is how the function figures should move, so the squares around the capture square should be empty if it is not a pawn and the capture square is also empty after the capture.
if (is_capture) {
if (c.board[dest_row][dest_file]->representation() == 'k' ||
c.board[dest_row][dest_file]->representation() == 'K') {
c.board[dest_row][dest_file] = std::move(c.board[src_row][src_file]);
c.board[dest_row][dest_file] = nullptr;
won = 1;
} else {
c.board[dest_row][dest_file] = std::move(c.board[src_row][src_file]);
c.board[dest_row][dest_file] = nullptr;
}
if ((dest_row + 1) < 8) {
if (c.board[dest_row + 1][dest_file] != nullptr &&
(c.board[dest_row + 1][dest_file]->representation() != 'p' &&
c.board[dest_row + 1][dest_file]->representation() != 'P')) {
if (c.board[dest_row + 1][dest_file]->representation() == 'k' ||
c.board[dest_row + 1][dest_file]->representation() == 'K') {
won = 1;
}
c.board[dest_row + 1][dest_file] = nullptr;
}
} ....
Now the undo function works fine for normal moves and for captures if it is not a nullptr after the capture. I tried commenting out this line c.board[dest_row][dest_file] = nullptr; and then it was a normal capture that was possible to undo. I also tried setting it directly to a nullptr and got also a segmentation fault. So I think it is related to the nullptr, but I don't understand why I cannot put a new unique pointer on the nullptr. This is the undo function
void chess::undo(chess &c, vector<string> &move_history,
vector<piece> &last_captured) {
string undo_move;
if (!move_history.empty()) {
undo_move = move_history.back();
}
int dest_move_undo_file= undo_move[1] - 'a';
int dest_move_undo_row = undo_move[2] - '1';
int src_move_undo_file;
int src_move_undo_row;
if (undo_move[3] == 'x') {
src_move_undo_row = undo_move[5] - '1';
src_move_undo_file = undo_move[4] - 'a';
} else {
src_move_undo_row = undo_move[4] - '1';
src_move_undo_file = undo_move[3] - 'a';
}
if (undo_move[undo_move.length() - 2] == '=') {
c.board[dest_move_undo_row][dest_move_undo_file] = std::make_unique<piece>(
c.board[src_move_undo_row][src_move_undo_file]->p, shape::pawn);
} else {
c.board[dest_move_undo_row][dest_move_undo_file] = std::make_unique<piece>(
c.board[src_move_undo_row][src_move_undo_file]->p, c.board[src_move_undo_row][src_move_undo_file]->s);
}
c.board[src_move_undo_row][src_move_undo_file] = nullptr;
if (undo_move[3] == 'x') {
player captured_player = last_captured.back().p;
shape captured_shape = last_captured.back().s;
c.board[src_move_undo_row][src_move_undo_file] =
std::make_unique<piece>(captured_player, captured_shape);
last_captured.pop_back();}
move_history.pop_back();
c.next_to_move =
c.next_to_move == player::white ? player::black : player::white;
}
and before the move is done it is stored in these vectors to make the undo possible
move_history.push_back(move);
if (dest_square != nullptr) {
last_captured.push_back(*dest_square);
}
I wanted to try debugging with valgrind but I was not able to install it on macos and gdb seems also not to work on M1 chips, so I have no idea how to find the problem.