mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 04:01:32 -06:00
SM: Speed up deepcopy in copy_mixin (#4228)
This commit is contained in:
@@ -66,6 +66,14 @@ class SMBool:
|
||||
def __copy__(self):
|
||||
return SMBool(self.bool, self.difficulty, self._knows, self._items)
|
||||
|
||||
def __deepcopy__(self, memodict):
|
||||
# `bool` and `difficulty` are a `bool` and `int`, so do not need to be copied.
|
||||
# The `_knows` list is never mutated, so does not need to be copied.
|
||||
# The `_items` list is a `list[str | list[str]]` (copied to a flat `list[str]` when accessed through the `items`
|
||||
# property) that is mutated by code in helpers.py, so needs to be copied. Because there could be lists within
|
||||
# the list, it is copied using the `flatten()` helper function.
|
||||
return SMBool(self.bool, self.difficulty, self._knows, flatten(self._items))
|
||||
|
||||
def json(self):
|
||||
# as we have slots instead of dict
|
||||
return {'bool': self.bool, 'difficulty': self.difficulty, 'knows': self.knows, 'items': self.items}
|
||||
|
@@ -8,6 +8,7 @@ from ..utils.doorsmanager import DoorsManager
|
||||
from ..utils.objectives import Objectives
|
||||
from ..utils.parameters import Knows, isKnows
|
||||
import logging
|
||||
from copy import deepcopy
|
||||
import sys
|
||||
|
||||
class SMBoolManager(object):
|
||||
@@ -34,6 +35,46 @@ class SMBoolManager(object):
|
||||
self.createFacadeFunctions()
|
||||
self.createKnowsFunctions(player)
|
||||
self.resetItems()
|
||||
self.itemsPositions = {}
|
||||
|
||||
def __deepcopy__(self, memodict):
|
||||
# Use __new__ to avoid calling __init__ like copy.deepcopy without __deepcopy__ implemented.
|
||||
new = object.__new__(type(self))
|
||||
|
||||
# Copy everything over in the same order as __init__, ensuring that mutable attributes are deeply copied.
|
||||
|
||||
# SMBool instances contain mutable lists, so must be deep-copied.
|
||||
new._items = {i: deepcopy(v, memodict) for i, v in self._items.items()}
|
||||
# `_counts` is a dict[str, int], so the dict can be copied because its keys and values are immutable.
|
||||
new._counts = self._counts.copy()
|
||||
# `player` is an int.
|
||||
new.player = self.player
|
||||
# `maxDiff` is an int.
|
||||
new.maxDiff = self.maxDiff
|
||||
# `onlyBossLeft` is a bool.
|
||||
new.onlyBossLeft = self.onlyBossLeft
|
||||
# The HelpersGraph keeps reference to the instance, so a new HelpersGraph is required.
|
||||
new.helpers = Logic.HelpersGraph(new)
|
||||
# DoorsManager is stateless, so the same instance can be used.
|
||||
new.doorsManager = self.doorsManager
|
||||
# Objectives are cached by self.player, so will be the same instance for the copy.
|
||||
new.objectives = self.objectives
|
||||
# Copy the facade functions from new.helpers into new.__dict__.
|
||||
new.createFacadeFunctions()
|
||||
# Copying the existing 'knows' functions from `self` to `new` is faster than re-creating all the lambdas with
|
||||
# `new.createKnowsFunctions(player)`.
|
||||
for key in Knows.__dict__.keys():
|
||||
if isKnows(key):
|
||||
attribute_name = "knows"+key
|
||||
knows_func = getattr(self, attribute_name)
|
||||
setattr(new, attribute_name, knows_func)
|
||||
# There is no need to call `new.resetItems()` because `_items` and `_counts` have been copied over.
|
||||
# new.resetItems()
|
||||
# itemsPositions is a `dict[str, tuple[int, int]]`, so the dict can be copied because the keys and values are
|
||||
# immutable.
|
||||
new.itemsPositions = self.itemsPositions.copy()
|
||||
|
||||
return new
|
||||
|
||||
def computeItemsPositions(self):
|
||||
# compute index in cache key for each items
|
||||
@@ -245,6 +286,9 @@ class SMBoolManagerPlando(SMBoolManager):
|
||||
def __init__(self):
|
||||
super(SMBoolManagerPlando, self).__init__()
|
||||
|
||||
def __deepcopy__(self, memodict):
|
||||
return super().__deepcopy__(memodict)
|
||||
|
||||
def addItem(self, item):
|
||||
# a new item is available
|
||||
already = self.haveItem(item)
|
||||
|
Reference in New Issue
Block a user