Honn
Honn

Reputation: 744

Alternatives to copy.deepcopy; Or is it even necessary?

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

Answers (1)

Honn
Honn

Reputation: 744

I used an incredibly jank bypass solution for now:

  1. Convert the list to a string
  2. Use the built-in eval function to retrieve it's information

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

Related Questions