Home > OS >  How to make a deep copy of an array of pointers
How to make a deep copy of an array of pointers

Time:01-27

I am in the process of creating a chess engine and I am using a chess engine that can be found here for it's ChessBoard and Piece classes. as part of the engine I have to make a deep copy of an instance of the ChessBoard class and and I am having a great deal of difficulty doing this. I have tried editing the copy constructor in the class in multiple ways and changing the my own code but to no avail.

Here is the problematic part of my code:

move_list = j->data().board->getPossibleMoves(board->flip(colour));
for (auto k : move_list) {
    print_board(j->data().board);
    current_node.board = j->data().board;
    current_node.board->moveTo(std::tuple<char, char>(std::get<0>(k), std::get<1>(k)), std::tuple<char, char>(std::get<2>(k), std::get<3>(k)));
    std::cout << "After :" << std::endl;
    print_board(j->data().board);
    j->insert(current_node);

//"j" is a node in a tree class
//"k" is structured like this: std::vector<std::tuple<char, char, char, char>>
//"MoveTo" moves a chess piece to a location on the chess board

This yields an output like this:

Before :
 R  N  B  Q  K  B  N  R
 P  P  P  P  P  P  P  P
                        



 p  p  p  p  p  p  p  p
 R  N  B  Q  K  B  N  R
After :
 R  N  B  Q  K  B  N  R
 P  P  P  P  P  P  P  P
                        


 p
    p  p  p  p  p  p  p
 R  N  B  Q  K  B  N  R

As you can see, the value of "j->data()" changes even though I change the new "ChessBoard" therefore "j->data()" and the new board are pointing to the same location in memory.

Here are the copy constructors of ChessBoard and Piece:

//board.h
ChessBoard(const ChessBoard& rhs) { //Copy constructor
        //This is the section that I'm concerned about ↓ (Until the other comment)
        for (int x = 0; x < 8; x  ) {
            for (int y = 0; y < 8; y  ) {
                Piece* piece = new Piece(rhs.squares[x][y]->colour);
                piece->value = rhs.squares[x][y]->value;
                piece->symbol = rhs.squares[x][y]->symbol;
                piece->pieceType = rhs.squares[x][y]->pieceType;
                piece->moveCount = rhs.squares[x][y]->moveCount;
                ChessBoard::squares[x][y] = piece;
            }
        }
        //This is the section that I'm concerned about ↑ (Until the other comment)
        for (auto itr = rhs.promotedQueens.begin(); itr != promotedQueens.end();   itr) {
            Piece piece = **(itr);
            promotedQueens.push_back(&piece);
        }
        whiteCastled = rhs.whiteCastled;
        blackCastled = rhs.blackCastled;
        plyCount = rhs.plyCount;
        allowIllegalMoves = rhs.allowIllegalMoves;
        improvedDrawDetection = rhs.improvedDrawDetection;
        ChessBoard::transpos_table.initializeHash(this, Colour::White);
        initializeOriginalSquares();
    }

//Pieces.h
Piece(const Piece& rhs) { //Copy constructor
        value = rhs.value;
        symbol = rhs.symbol;
        pieceType = rhs.pieceType;
        moveCount = rhs.moveCount;
        colour = rhs.colour;
    };

To summarize, how could I make a copy constructor that makes a deep copy of the ChessBoard class or create a deep copy of it in some other way?

CodePudding user response:

You are using runtime polymorphism for your pieces. I.e. you have a chess board of pointers to Piece, which can be of different types (Horse, Bishop and so on). And your problem is that, when you copy construct your chess board, you need to copy construct each piece, but you only hold a Piece* to a polymorphic object. You need a virtual copy constructor. As suggested in the link, you can:

  • add a pure virtual clone method to your Piece base class.
  • override that method for each of your final classes, doing the copy construction there.

The code below uses smart pointers instead of raw pointers.

[Demo]

class Piece {
public:
    virtual std::unique_ptr<Piece> clone() = 0;
};

class Horse : public Piece {
public:
    virtual std::unique_ptr<Piece> clone() override {
        return std::make_unique<Horse>(*this);
    };
};

ChessBoard(const ChessBoard& cb) {
    for (size_t x{0}; x < board_size;   x) {
        for (size_t y{0}; y < board_size;   y) {
            squares[x][y] = cb.squares[x][y]->clone();
        }
    }
}

Some other related links: another question asking about virtual copy constructors. And two useful answers to that question, 1, and 2.

  •  Tags:  
  • Related