2

I am writing a chess program and I have an abstract class named Pieces. I use this abstract class in my main class by using a pointer, like such: Pieces * newset = currentboard[][];

If I make moves on this board the moves are actually made. I want to analyse the board's current state, hence create a copy of the board. How do I do that?

A sample of my Piece class and what I am doing is given below.

class Piece
{
  public:
    Piece(char cColor) : mcColor(cColor) {}
    ~Piece() {}
    virtual char GetPiece() = 0;
    virtual int GetValue() = 0;
    virtual int GetPieceActionValue() = 0;
    char GetColor() {
        return mcColor;
    }
    bool IsLegalMove(int CurrentRow, int CurrentCol, int DestRow, int DestCol, Piece* NewBoard[8][8]) {
        Piece* qpDest = NewBoard[DestRow][DestCol];
        if ((qpDest == 0) || (mcColor != qpDest->GetColor())) {
            return LegalSquares(CurrentRow, CurrentCol, DestRow, DestCol, NewBoard);
        }
        return false;
    }

  private:
    virtual bool LegalSquares(int CurrentRow, int CurrentCol, int DestRow, int DestCol, Piece* NewBoard[8][8]) = 0;
    char mcColor;
};

Here is a sample of a derived Class :

class Bishop
{
  public:
    Bishop(char cColor) : Piece(cColor) {}
    ~Bishop() {}

  private:
    virtual char GetPiece() {
        return 'B';
    }
    virtual int GetValue() {
        return 325;
    }
    virtual int GetPieceActionValue() {
        return 3;
    }
    bool LegalSquares(int CurrentRow, int CurrentCol, int DestRow, int DestCol, Piece* NewBoard[8][8]) {
        if ((DestCol - CurrentCol == DestRow - CurrentRow) || (DestCol - CurrentCol == CurrentRow - DestRow)) {
            // Make sure that all invervening squares are empty
            int iRowOffset = (DestRow - CurrentRow > 0) ? 1 : -1;
            int iColOffset = (DestCol - CurrentCol > 0) ? 1 : -1;
            int iCheckRow;
            int iCheckCol;
            for (iCheckRow = CurrentRow + iRowOffset, iCheckCol = CurrentCol + iColOffset;
                iCheckRow !=  DestRow;
                iCheckRow = iCheckRow + iRowOffset, iCheckCol = iCheckCol + iColOffset)
            {
                if (NewBoard[iCheckRow][iCheckCol] != 0) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
};

Using the class to make moves:

if (qpCurrPiece->IsLegalMove(StartRow, StartCol, EndRow, EndCol, NewBoard)) {

  // Make the move
  Piece* qpTemp = NewBoard[EndRow][EndCol];
  NewBoard[EndRow][EndCol] = NewBoard[StartRow][StartCol];
  NewBoard[StartRow][StartCol] = 0;

  // Make sure that the current player is not in check
  if (!GameBoard.IsInCheck(mcPlayerTurn)) {
    delete qpTemp;
    bValidMove = true;
  } else { 

    // Undo the last move
    NewBoard[StartRow][StartCol] = NewBoard[EndRow][EndCol];
    NewBoard[EndRow][EndCol] = qpTemp;
  }
}

I want to be able to reference this class without using a pointer so that permanent changes are not made to the board.

JoshDM
  • 4,939
  • 7
  • 43
  • 72
GeeKaush
  • 33
  • 1
  • 6

3 Answers3

4

You need to provide each class with a virtual Clone() function, which for Bishop would look like:

Piece * Bishop :: Clone() {
     return new Bishop( * this );
}

Now to clone the board from OldBoard something like:

Board newboard;   // assume board is 8x8 matrix of Piece *

for ( int i = 0; i < 8; i++ ) {
    for ( int j = 0; j < 8; j++ ) {
       newboard[i][j] = OldBoard[i][j]->Clone();
    }
}
  • +1 from me. One thing worth mentioning would be that it could be useful to use covariant return types on the Clone method i.e. in Bishop the function could return Bishop* (i.e. one does not have to cast when one has a Bishop instance). Also the copy constructor and assignment operator should be probably protected – ds27680 May 04 '11 at 10:47
  • 1
    I'm sorry to be a spoilsport, but to play real computer chess you will have to do this a couple of million times per second. Cloning pieces in dynamic memory is not practical, except as an exercise. Perhaps you should take a look here [chessprogramming.wikispaces.com](http://chessprogramming.wikispaces.com/)? – Bo Persson May 04 '11 at 15:33
2

You need to have an abstract method

 Piece *Piece::Duplicate()

and then implement it in the subclasses, i.e.

 class Bishop {
   Bishop(const Bishop &b) { ... } // copy constructor
   Piece *Duplicate() { Bishop *n = new Bishop(*this); // calls copy constructor
     return n; }
 }
Antti Huima
  • 25,136
  • 3
  • 52
  • 71
1

Or you could write a copy constructor to Bishop class which in turn implements a deep copy assuming your currentBoard is an instance of Bishop class.

Ramya Maithreyi
  • 507
  • 3
  • 12