Reputation: 14895
Hi! I'm making a chess engine and I have some problems with the make/ unmake methods.
I have a Piece class that holds the type (pawn, queen, etc..) and position of the piece and a Move class that holds the target square, the moved piece and captured piece.
The problem is that, when I call the makeMove method, it changes the piece's position to target square inside the Piece object. But now, I can't call the unmakeMove with the Move object, because now i have no information about where the move came from, as I have just changed the piece's position. How would you tackle this problem?
Thank you very much!
class Board:
# Previous methods omitted.
def makeMove(self, move, player):
""" Makes a move on the board and changes Piece object. Returns None. """
self.moved_piece = move.getPiece()
self.captured_piece = move.getCapturedPiece(self)
if self.captured_piece: # Remove captured piece from player's piece dict.
player.removePiece(self.captured_piece)
self.setPiece(move.getTargetSquare(), self.moved_piece) # Set moved piece on target square.
self.setPiece(self.moved_piece.getPosition(), EMPTY) # Make the origin square empty.
self.moved_piece.changePosition(move.getTargetSquare()) # Change piece object's position.
def unmakeMove(self, move, player):
""" Unmakes a move. Returns None. """
self.moved_piece = move.getPiece()
self.captured_piece = move.getCapturedPiece(self)
self.setPiece(self.moved_piece.getPosition(), captured_piece) # Set captured piece or empty square to target square.
# Set piece to original square. HOW !?
Upvotes: 1
Views: 3180
Reputation: 24788
Based on my comment and the link on the Memento pattern that Fred Larson posted, here is an example implementation of what you might want to do:
class Engine(object):
def __init__(self):
self.board = Board()
self.move_list = []
def make_move(self, from, to):
#board.makeMove returns a "memento object".
self.move_list.append(board.makeMove(from, to))
...
def undo_move(self):
board.undo(self.move_list.pop())
...
...
And let's say you have a move object of this structure:
class Move(object):
def __init__(self, from_coords, to_coords, capture=None):
self.from = from_coords
self.to = to_coords
self.capture = capture
You're Board
object would implement the following methods:
class Board(object):
...
def make_move(self, from_coords, to_coords):
#move logic here
return Move(from_coords, to_coords, capturedPiece)
def undo_move(self, move_object):
self.make_move(move_object.to_coords, move_object.from_coords)
self.uncapture(move_object.capture, move_object.to_coords)
Obviously, the code above is just conceptual. The actual implementation would depend on how the rest of your code is structured.
Note: I used a class for the Move
object because attribute access is explicit and easy to follow. In reality, a object as basic as this could simply be a tuple of the form (from, to, capturedpiece)
.
Upvotes: 2