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)
							 |