Reputation: 744
To undo moves from my chess engine I heavily rely on a good caching system, which is updated everytime a move is done/undone. It is also used to "go back in time" and see earlier positions. The update code looks something like:
self.cache.append([copy.deepcopy(self.board), ..., copy.deepcopy(self.brokenCastles)])
with self.brokenCastles
being a set and self.board
a 2D list representing the board. There are some other lists and variables that get stored (like legal moves for each side) so they don't have to be calculated each time the same board is used. They haven't caused any problems so far (or I didn't notice them).
The big problem is with self.board
and self.brokenCastles
. If I just append them like all the other variables, massive problems appear (like kings getting taken and some weird stuff), which is fixed by making a deepcopy of the list/set respectively. Just using pythons built-in .copy()
or using a slice like [:]
didn't help.
I don't quite know why deepcopy is necessary and couldnt replicate the issue in a smaller environment. So my question is if deepcopy is even needed and if so, is there a way to make it faster, since it is the biggest bottleneck in my system right now.
The cache read function looks like this:
def undo_move(self):
self.board = self.cache[-1][0]
... # A lot more
self.brokenCastles = self.cache[-1][4]
self.cache.pop()
If there are any details missing, let me know. Thanks for any help.
Whole code (its a mess) is available at GitHub.
Upvotes: 0
Views: 738
Reputation: 744
I used an incredibly jank bypass solution for now:
Still quite slow, but a lot better than deepcopy.
EDIT: I made it a lot faster by using my own conversion to string and back:
def to_lst(my_string):
temp = my_string.split("|")
return [temp[i: i+8] for i in range(0, 64, 8)]
def to_str(my_list):
return "|".join([a for b in my_list for a in b])
Upvotes: 1