mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 12:11:33 -06:00
SM: Speed up deepcopy in copy_mixin (#4228)
This commit is contained in:
@@ -66,6 +66,14 @@ class SMBool:
|
|||||||
def __copy__(self):
|
def __copy__(self):
|
||||||
return SMBool(self.bool, self.difficulty, self._knows, self._items)
|
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):
|
def json(self):
|
||||||
# as we have slots instead of dict
|
# as we have slots instead of dict
|
||||||
return {'bool': self.bool, 'difficulty': self.difficulty, 'knows': self.knows, 'items': self.items}
|
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.objectives import Objectives
|
||||||
from ..utils.parameters import Knows, isKnows
|
from ..utils.parameters import Knows, isKnows
|
||||||
import logging
|
import logging
|
||||||
|
from copy import deepcopy
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
class SMBoolManager(object):
|
class SMBoolManager(object):
|
||||||
@@ -34,6 +35,46 @@ class SMBoolManager(object):
|
|||||||
self.createFacadeFunctions()
|
self.createFacadeFunctions()
|
||||||
self.createKnowsFunctions(player)
|
self.createKnowsFunctions(player)
|
||||||
self.resetItems()
|
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):
|
def computeItemsPositions(self):
|
||||||
# compute index in cache key for each items
|
# compute index in cache key for each items
|
||||||
@@ -245,6 +286,9 @@ class SMBoolManagerPlando(SMBoolManager):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(SMBoolManagerPlando, self).__init__()
|
super(SMBoolManagerPlando, self).__init__()
|
||||||
|
|
||||||
|
def __deepcopy__(self, memodict):
|
||||||
|
return super().__deepcopy__(memodict)
|
||||||
|
|
||||||
def addItem(self, item):
|
def addItem(self, item):
|
||||||
# a new item is available
|
# a new item is available
|
||||||
already = self.haveItem(item)
|
already = self.haveItem(item)
|
||||||
|
Reference in New Issue
Block a user