123 lines
3.4 KiB
Python
123 lines
3.4 KiB
Python
def flatten(l):
|
|
if type(l) is list:
|
|
return [ y for x in l for y in flatten(x) ]
|
|
else:
|
|
return [ l ]
|
|
|
|
# super metroid boolean
|
|
class SMBool:
|
|
__slots__ = ('bool', 'difficulty', '_knows', '_items')
|
|
def __init__(self, boolean, difficulty=0, knows=[], items=[]):
|
|
self.bool = boolean
|
|
self.difficulty = difficulty
|
|
self._knows = knows
|
|
self._items = items
|
|
|
|
@property
|
|
def knows(self):
|
|
self._knows = list(set(flatten(self._knows)))
|
|
return self._knows
|
|
|
|
@knows.setter
|
|
def knows(self, knows):
|
|
self._knows = knows
|
|
|
|
@property
|
|
def items(self):
|
|
self._items = list(set(flatten(self._items)))
|
|
return self._items
|
|
|
|
@items.setter
|
|
def items(self, items):
|
|
self._items = items
|
|
|
|
def __repr__(self):
|
|
# to display the smbool as a string
|
|
return 'SMBool({}, {}, {}, {})'.format(self.bool, self.difficulty, sorted(self.knows), sorted(self.items))
|
|
|
|
def __getitem__(self, index):
|
|
# to acces the smbool as [0] for the bool and [1] for the difficulty.
|
|
# required when we load a json preset where the smbool is stored as a list,
|
|
# and we add missing smbools to it, so we have a mix of lists and smbools.
|
|
if index == 0:
|
|
return self.bool
|
|
elif index == 1:
|
|
return self.difficulty
|
|
|
|
def __bool__(self):
|
|
# when used in boolean expressions (with and/or/not) (python3)
|
|
return self.bool
|
|
|
|
def __eq__(self, other):
|
|
# for ==
|
|
return self.bool == other
|
|
|
|
def __ne__(self, other):
|
|
# for !=
|
|
return self.bool != other
|
|
|
|
def __lt__(self, other):
|
|
# for <
|
|
if self.bool and other.bool:
|
|
return self.difficulty < other.difficulty
|
|
else:
|
|
return self.bool
|
|
|
|
def __copy__(self):
|
|
return SMBool(self.bool, self.difficulty, self._knows, 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}
|
|
|
|
def wand(*args):
|
|
# looping here is faster than using "if ... in" construct
|
|
for smb in args:
|
|
if not smb.bool:
|
|
return smboolFalse
|
|
|
|
difficulty = 0
|
|
|
|
for smb in args:
|
|
difficulty += smb.difficulty
|
|
|
|
return SMBool(True,
|
|
difficulty,
|
|
[ smb._knows for smb in args ],
|
|
[ smb._items for smb in args ])
|
|
|
|
def wandmax(*args):
|
|
# looping here is faster than using "if ... in" construct
|
|
for smb in args:
|
|
if not smb.bool:
|
|
return smboolFalse
|
|
|
|
difficulty = 0
|
|
|
|
for smb in args:
|
|
if smb.difficulty > difficulty:
|
|
difficulty = smb.difficulty
|
|
|
|
return SMBool(True,
|
|
difficulty,
|
|
[ smb._knows for smb in args ],
|
|
[ smb._items for smb in args ])
|
|
|
|
def wor(*args):
|
|
# looping here is faster than using "if ... in" construct
|
|
for smb in args:
|
|
if smb.bool:
|
|
return min(args)
|
|
|
|
return smboolFalse
|
|
|
|
# negates boolean part of the SMBool
|
|
def wnot(a):
|
|
return smboolFalse if a.bool else SMBool(True, a.difficulty)
|
|
|
|
__and__ = wand
|
|
__or__ = wor
|
|
__not__ = wnot
|
|
|
|
smboolFalse = SMBool(False)
|