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