319 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			319 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								from typing import Optional
							 | 
						||
| 
								 | 
							
								from ..locations.items import *
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class OR:
							 | 
						||
| 
								 | 
							
								    __slots__ = ('__items', '__children')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __new__(cls, *args):
							 | 
						||
| 
								 | 
							
								        if True in args:
							 | 
						||
| 
								 | 
							
								            return True
							 | 
						||
| 
								 | 
							
								        return super().__new__(cls)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self, *args):
							 | 
						||
| 
								 | 
							
								        self.__items = [item for item in args if isinstance(item, str)]
							 | 
						||
| 
								 | 
							
								        self.__children = [item for item in args if type(item) not in (bool, str) and item is not None]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        assert self.__items or self.__children, args
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __repr__(self) -> str:
							 | 
						||
| 
								 | 
							
								        return "or%s" % (self.__items+self.__children)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def remove(self, item) -> None:
							 | 
						||
| 
								 | 
							
								        if item in self.__items:
							 | 
						||
| 
								 | 
							
								            self.__items.remove(item)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def hasConsumableRequirement(self) -> bool:
							 | 
						||
| 
								 | 
							
								        for item in self.__items:
							 | 
						||
| 
								 | 
							
								            if isConsumable(item):
							 | 
						||
| 
								 | 
							
								                print("Consumable OR requirement? %r" % self)
							 | 
						||
| 
								 | 
							
								                return True
							 | 
						||
| 
								 | 
							
								        for child in self.__children:
							 | 
						||
| 
								 | 
							
								            if child.hasConsumableRequirement():
							 | 
						||
| 
								 | 
							
								                print("Consumable OR requirement? %r" % self)
							 | 
						||
| 
								 | 
							
								                return True
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test(self, inventory) -> bool:
							 | 
						||
| 
								 | 
							
								        for item in self.__items:
							 | 
						||
| 
								 | 
							
								            if item in inventory:
							 | 
						||
| 
								 | 
							
								                return True
							 | 
						||
| 
								 | 
							
								        for child in self.__children:
							 | 
						||
| 
								 | 
							
								            if child.test(inventory):
							 | 
						||
| 
								 | 
							
								                return True
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def consume(self, inventory) -> bool:
							 | 
						||
| 
								 | 
							
								        for item in self.__items:
							 | 
						||
| 
								 | 
							
								            if item in inventory:
							 | 
						||
| 
								 | 
							
								                if isConsumable(item):
							 | 
						||
| 
								 | 
							
								                    inventory[item] -= 1
							 | 
						||
| 
								 | 
							
								                    if inventory[item] == 0:
							 | 
						||
| 
								 | 
							
								                        del inventory[item]
							 | 
						||
| 
								 | 
							
								                    inventory["%s_USED" % item] = inventory.get("%s_USED" % item, 0) + 1
							 | 
						||
| 
								 | 
							
								                return True
							 | 
						||
| 
								 | 
							
								        for child in self.__children:
							 | 
						||
| 
								 | 
							
								            if child.consume(inventory):
							 | 
						||
| 
								 | 
							
								                return True
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def getItems(self, inventory, target_set) -> None:
							 | 
						||
| 
								 | 
							
								        if self.test(inventory):
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        for item in self.__items:
							 | 
						||
| 
								 | 
							
								            target_set.add(item)
							 | 
						||
| 
								 | 
							
								        for child in self.__children:
							 | 
						||
| 
								 | 
							
								            child.getItems(inventory, target_set)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def copyWithModifiedItemNames(self, f) -> "OR":
							 | 
						||
| 
								 | 
							
								        return OR(*(f(item) for item in self.__items), *(child.copyWithModifiedItemNames(f) for child in self.__children))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class AND:
							 | 
						||
| 
								 | 
							
								    __slots__ = ('__items', '__children')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __new__(cls, *args):
							 | 
						||
| 
								 | 
							
								        if False in args:
							 | 
						||
| 
								 | 
							
								            return False
							 | 
						||
| 
								 | 
							
								        return super().__new__(cls)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self, *args):
							 | 
						||
| 
								 | 
							
								        self.__items = [item for item in args if isinstance(item, str)]
							 | 
						||
| 
								 | 
							
								        self.__children = [item for item in args if type(item) not in (bool, str) and item is not None]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __repr__(self) -> str:
							 | 
						||
| 
								 | 
							
								        return "and%s" % (self.__items+self.__children)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def remove(self, item) -> None:
							 | 
						||
| 
								 | 
							
								        if item in self.__items:
							 | 
						||
| 
								 | 
							
								            self.__items.remove(item)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def hasConsumableRequirement(self) -> bool:
							 | 
						||
| 
								 | 
							
								        for item in self.__items:
							 | 
						||
| 
								 | 
							
								            if isConsumable(item):
							 | 
						||
| 
								 | 
							
								                return True
							 | 
						||
| 
								 | 
							
								        for child in self.__children:
							 | 
						||
| 
								 | 
							
								            if child.hasConsumableRequirement():
							 | 
						||
| 
								 | 
							
								                return True
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test(self, inventory) -> bool:
							 | 
						||
| 
								 | 
							
								        for item in self.__items:
							 | 
						||
| 
								 | 
							
								            if item not in inventory:
							 | 
						||
| 
								 | 
							
								                return False
							 | 
						||
| 
								 | 
							
								        for child in self.__children:
							 | 
						||
| 
								 | 
							
								            if not child.test(inventory):
							 | 
						||
| 
								 | 
							
								                return False
							 | 
						||
| 
								 | 
							
								        return True
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def consume(self, inventory) -> bool:
							 | 
						||
| 
								 | 
							
								        for item in self.__items:
							 | 
						||
| 
								 | 
							
								            if isConsumable(item):
							 | 
						||
| 
								 | 
							
								                inventory[item] -= 1
							 | 
						||
| 
								 | 
							
								                if inventory[item] == 0:
							 | 
						||
| 
								 | 
							
								                    del inventory[item]
							 | 
						||
| 
								 | 
							
								                inventory["%s_USED" % item] = inventory.get("%s_USED" % item, 0) + 1
							 | 
						||
| 
								 | 
							
								        for child in self.__children:
							 | 
						||
| 
								 | 
							
								            if not child.consume(inventory):
							 | 
						||
| 
								 | 
							
								                return False
							 | 
						||
| 
								 | 
							
								        return True
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def getItems(self, inventory, target_set) -> None:
							 | 
						||
| 
								 | 
							
								        if self.test(inventory):
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        for item in self.__items:
							 | 
						||
| 
								 | 
							
								            target_set.add(item)
							 | 
						||
| 
								 | 
							
								        for child in self.__children:
							 | 
						||
| 
								 | 
							
								            child.getItems(inventory, target_set)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def copyWithModifiedItemNames(self, f) -> "AND":
							 | 
						||
| 
								 | 
							
								        return AND(*(f(item) for item in self.__items), *(child.copyWithModifiedItemNames(f) for child in self.__children))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class COUNT:
							 | 
						||
| 
								 | 
							
								    __slots__ = ('__item', '__amount')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self, item: str, amount: int) -> None:
							 | 
						||
| 
								 | 
							
								        self.__item = item
							 | 
						||
| 
								 | 
							
								        self.__amount = amount
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __repr__(self) -> str:
							 | 
						||
| 
								 | 
							
								        return "<%dx%s>" % (self.__amount, self.__item)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def hasConsumableRequirement(self) -> bool:
							 | 
						||
| 
								 | 
							
								        if isConsumable(self.__item):
							 | 
						||
| 
								 | 
							
								            return True
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test(self, inventory) -> bool:
							 | 
						||
| 
								 | 
							
								        return inventory.get(self.__item, 0) >= self.__amount
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def consume(self, inventory) -> None:
							 | 
						||
| 
								 | 
							
								        if isConsumable(self.__item):
							 | 
						||
| 
								 | 
							
								            inventory[self.__item] -= self.__amount
							 | 
						||
| 
								 | 
							
								            if inventory[self.__item] == 0:
							 | 
						||
| 
								 | 
							
								                del inventory[self.__item]
							 | 
						||
| 
								 | 
							
								            inventory["%s_USED" % self.__item] = inventory.get("%s_USED" % self.__item, 0) + self.__amount
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def getItems(self, inventory, target_set) -> None:
							 | 
						||
| 
								 | 
							
								        if self.test(inventory):
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        target_set.add(self.__item)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def copyWithModifiedItemNames(self, f) -> "COUNT":
							 | 
						||
| 
								 | 
							
								        return COUNT(f(self.__item), self.__amount)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class COUNTS:
							 | 
						||
| 
								 | 
							
								    __slots__ = ('__items', '__amount')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self, items, amount):
							 | 
						||
| 
								 | 
							
								        self.__items = items
							 | 
						||
| 
								 | 
							
								        self.__amount = amount
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __repr__(self) -> str:
							 | 
						||
| 
								 | 
							
								        return "<%dx%s>" % (self.__amount, self.__items)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def hasConsumableRequirement(self) -> bool:
							 | 
						||
| 
								 | 
							
								        for item in self.__items:
							 | 
						||
| 
								 | 
							
								            if isConsumable(item):
							 | 
						||
| 
								 | 
							
								                print("Consumable COUNTS requirement? %r" % (self))
							 | 
						||
| 
								 | 
							
								                return True
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test(self, inventory) -> bool:
							 | 
						||
| 
								 | 
							
								        count = 0
							 | 
						||
| 
								 | 
							
								        for item in self.__items:
							 | 
						||
| 
								 | 
							
								            count += inventory.get(item, 0)
							 | 
						||
| 
								 | 
							
								        return count >= self.__amount
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def consume(self, inventory) -> None:
							 | 
						||
| 
								 | 
							
								        for item in self.__items:
							 | 
						||
| 
								 | 
							
								            if isConsumable(item):
							 | 
						||
| 
								 | 
							
								                inventory[item] -= self.__amount
							 | 
						||
| 
								 | 
							
								                if inventory[item] == 0:
							 | 
						||
| 
								 | 
							
								                    del inventory[item]
							 | 
						||
| 
								 | 
							
								                inventory["%s_USED" % item] = inventory.get("%s_USED" % item, 0) + self.__amount
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def getItems(self, inventory, target_set) -> None:
							 | 
						||
| 
								 | 
							
								        if self.test(inventory):
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        for item in self.__items:
							 | 
						||
| 
								 | 
							
								            target_set.add(item)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def copyWithModifiedItemNames(self, f) -> "COUNTS":
							 | 
						||
| 
								 | 
							
								        return COUNTS([f(item) for item in self.__items], self.__amount)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class FOUND:
							 | 
						||
| 
								 | 
							
								    __slots__ = ('__item', '__amount')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self, item: str, amount: int) -> None:
							 | 
						||
| 
								 | 
							
								        self.__item = item
							 | 
						||
| 
								 | 
							
								        self.__amount = amount
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __repr__(self) -> str:
							 | 
						||
| 
								 | 
							
								        return "{%dx%s}" % (self.__amount, self.__item)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def hasConsumableRequirement(self) -> bool:
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test(self, inventory) -> bool:
							 | 
						||
| 
								 | 
							
								        return inventory.get(self.__item, 0) + inventory.get("%s_USED" % self.__item, 0) >= self.__amount
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def consume(self, inventory) -> None:
							 | 
						||
| 
								 | 
							
								        pass
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def getItems(self, inventory, target_set) -> None:
							 | 
						||
| 
								 | 
							
								        if self.test(inventory):
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        target_set.add(self.__item)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def copyWithModifiedItemNames(self, f) -> "FOUND":
							 | 
						||
| 
								 | 
							
								        return FOUND(f(self.__item), self.__amount)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def hasConsumableRequirement(requirements) -> bool:
							 | 
						||
| 
								 | 
							
								    if isinstance(requirements, str):
							 | 
						||
| 
								 | 
							
								        return isConsumable(requirements)
							 | 
						||
| 
								 | 
							
								    if requirements is None:
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								    return requirements.hasConsumableRequirement()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def isConsumable(item) -> bool:
							 | 
						||
| 
								 | 
							
								    if item is None:
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								    #if item.startswith("RUPEES_") or item == "RUPEES":
							 | 
						||
| 
								 | 
							
								    #    return True
							 | 
						||
| 
								 | 
							
								    if item.startswith("KEY"):
							 | 
						||
| 
								 | 
							
								        return True
							 | 
						||
| 
								 | 
							
								    return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class RequirementsSettings:
							 | 
						||
| 
								 | 
							
								    def __init__(self, options):
							 | 
						||
| 
								 | 
							
								        self.bush = OR(SWORD, MAGIC_POWDER, MAGIC_ROD, POWER_BRACELET, BOOMERANG)
							 | 
						||
| 
								 | 
							
								        self.attack = OR(SWORD, BOMB, BOW, MAGIC_ROD, BOOMERANG)
							 | 
						||
| 
								 | 
							
								        self.attack_hookshot = OR(SWORD, BOMB, BOW, MAGIC_ROD, BOOMERANG, HOOKSHOT) # switches, hinox, shrouded stalfos
							 | 
						||
| 
								 | 
							
								        self.attack_hookshot_powder = OR(SWORD, BOMB, BOW, MAGIC_ROD, BOOMERANG, HOOKSHOT, MAGIC_POWDER) # zols, keese, moldorm
							 | 
						||
| 
								 | 
							
								        self.attack_no_bomb = OR(SWORD, BOW, MAGIC_ROD, BOOMERANG, HOOKSHOT) # ?
							 | 
						||
| 
								 | 
							
								        self.attack_hookshot_no_bomb = OR(SWORD, BOW, MAGIC_ROD, BOOMERANG, HOOKSHOT) # vire
							 | 
						||
| 
								 | 
							
								        self.attack_no_boomerang = OR(SWORD, BOMB, BOW, MAGIC_ROD, HOOKSHOT) # teleporting owls
							 | 
						||
| 
								 | 
							
								        self.attack_skeleton = OR(SWORD, BOMB, BOW, BOOMERANG, HOOKSHOT)  # cannot kill skeletons with the fire rod
							 | 
						||
| 
								 | 
							
								        self.rear_attack = OR(SWORD, BOMB) # mimic
							 | 
						||
| 
								 | 
							
								        self.rear_attack_range = OR(MAGIC_ROD, BOW) # mimic
							 | 
						||
| 
								 | 
							
								        self.fire = OR(MAGIC_POWDER, MAGIC_ROD) # torches
							 | 
						||
| 
								 | 
							
								        self.push_hardhat = OR(SHIELD, SWORD, HOOKSHOT, BOOMERANG)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.boss_requirements = [
							 | 
						||
| 
								 | 
							
								            SWORD,  # D1 boss
							 | 
						||
| 
								 | 
							
								            AND(OR(SWORD, MAGIC_ROD), POWER_BRACELET),  # D2 boss
							 | 
						||
| 
								 | 
							
								            AND(PEGASUS_BOOTS, SWORD),  # D3 boss
							 | 
						||
| 
								 | 
							
								            AND(FLIPPERS, OR(SWORD, MAGIC_ROD, BOW)),  # D4 boss
							 | 
						||
| 
								 | 
							
								            AND(HOOKSHOT, SWORD),  # D5 boss
							 | 
						||
| 
								 | 
							
								            BOMB,  # D6 boss
							 | 
						||
| 
								 | 
							
								            AND(OR(MAGIC_ROD, SWORD, HOOKSHOT), COUNT(SHIELD, 2)),  # D7 boss
							 | 
						||
| 
								 | 
							
								            MAGIC_ROD,  # D8 boss
							 | 
						||
| 
								 | 
							
								            self.attack_hookshot_no_bomb,  # D9 boss
							 | 
						||
| 
								 | 
							
								        ]
							 | 
						||
| 
								 | 
							
								        self.miniboss_requirements = {
							 | 
						||
| 
								 | 
							
								            "ROLLING_BONES":    self.attack_hookshot,
							 | 
						||
| 
								 | 
							
								            "HINOX":            self.attack_hookshot,
							 | 
						||
| 
								 | 
							
								            "DODONGO":          BOMB,
							 | 
						||
| 
								 | 
							
								            "CUE_BALL":         SWORD,
							 | 
						||
| 
								 | 
							
								            "GHOMA":            OR(BOW, HOOKSHOT),
							 | 
						||
| 
								 | 
							
								            "SMASHER":          POWER_BRACELET,
							 | 
						||
| 
								 | 
							
								            "GRIM_CREEPER":     self.attack_hookshot_no_bomb,
							 | 
						||
| 
								 | 
							
								            "BLAINO":           SWORD,
							 | 
						||
| 
								 | 
							
								            "AVALAUNCH":        self.attack_hookshot,
							 | 
						||
| 
								 | 
							
								            "GIANT_BUZZ_BLOB":  MAGIC_POWDER,
							 | 
						||
| 
								 | 
							
								            "MOBLIN_KING":      SWORD,
							 | 
						||
| 
								 | 
							
								            "ARMOS_KNIGHT":     OR(BOW, MAGIC_ROD, SWORD),
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Adjust for options
							 | 
						||
| 
								 | 
							
								        if options.bowwow != 'normal':
							 | 
						||
| 
								 | 
							
								            # We cheat in bowwow mode, we pretend we have the sword, as bowwow can pretty much do all what the sword ca$            # Except for taking out bushes (and crystal pillars are removed)
							 | 
						||
| 
								 | 
							
								            self.bush.remove(SWORD)
							 | 
						||
| 
								 | 
							
								        if options.logic == "casual":
							 | 
						||
| 
								 | 
							
								            # In casual mode, remove the more complex kill methods
							 | 
						||
| 
								 | 
							
								            self.bush.remove(MAGIC_POWDER)
							 | 
						||
| 
								 | 
							
								            self.attack_hookshot_powder.remove(MAGIC_POWDER)
							 | 
						||
| 
								 | 
							
								            self.attack.remove(BOMB)
							 | 
						||
| 
								 | 
							
								            self.attack_hookshot.remove(BOMB)
							 | 
						||
| 
								 | 
							
								            self.attack_hookshot_powder.remove(BOMB)
							 | 
						||
| 
								 | 
							
								            self.attack_no_boomerang.remove(BOMB)
							 | 
						||
| 
								 | 
							
								            self.attack_skeleton.remove(BOMB)
							 | 
						||
| 
								 | 
							
								        if options.logic == "hard":
							 | 
						||
| 
								 | 
							
								            self.boss_requirements[3] = AND(FLIPPERS, OR(SWORD, MAGIC_ROD, BOW, BOMB))  # bomb angler fish
							 | 
						||
| 
								 | 
							
								            self.boss_requirements[6] = OR(MAGIC_ROD, AND(BOMB, BOW), COUNT(SWORD, 2), AND(OR(SWORD, HOOKSHOT, BOW), SHIELD))  # evil eagle 3 cycle magic rod / bomb arrows / l2 sword, and bow kill
							 | 
						||
| 
								 | 
							
								        if options.logic == "glitched":
							 | 
						||
| 
								 | 
							
								            self.boss_requirements[3] = AND(FLIPPERS, OR(SWORD, MAGIC_ROD, BOW, BOMB))  # bomb angler fish
							 | 
						||
| 
								 | 
							
								            self.boss_requirements[6] = OR(MAGIC_ROD, BOMB, BOW, HOOKSHOT, COUNT(SWORD, 2), AND(SWORD, SHIELD))  # evil eagle off screen kill or 3 cycle with bombs
							 | 
						||
| 
								 | 
							
								        if options.logic == "hell":
							 | 
						||
| 
								 | 
							
								            self.boss_requirements[3] = AND(FLIPPERS, OR(SWORD, MAGIC_ROD, BOW, BOMB))  # bomb angler fish
							 | 
						||
| 
								 | 
							
								            self.boss_requirements[6] = OR(MAGIC_ROD, BOMB, BOW, HOOKSHOT, COUNT(SWORD, 2), AND(SWORD, SHIELD))  # evil eagle off screen kill or 3 cycle with bombs
							 | 
						||
| 
								 | 
							
								            self.boss_requirements[7] = OR(MAGIC_ROD, COUNT(SWORD, 2)) # hot head sword beams
							 | 
						||
| 
								 | 
							
								            self.miniboss_requirements["GIANT_BUZZ_BLOB"] = OR(MAGIC_POWDER, COUNT(SWORD,2)) # use sword beams to damage buzz blob
							 |