804 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			804 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Python
		
	
	
	
| from enum import Enum
 | |
| import re
 | |
| import copy
 | |
| from typing import List
 | |
| 
 | |
| from worlds.smz3.TotalSMZ3.Config import Config, SMLogic
 | |
| 
 | |
| class ItemType(Enum):
 | |
|     Nothing = 0
 | |
|     MapHC = 0x7F
 | |
|     MapEP = 0x7D
 | |
|     MapDP = 0x7C
 | |
|     MapTH = 0x75
 | |
|     MapPD = 0x79
 | |
|     MapSP = 0x7A
 | |
|     MapSW = 0x77
 | |
|     MapTT = 0x74
 | |
|     MapIP = 0x76
 | |
|     MapMM = 0x78
 | |
|     MapTR = 0x73
 | |
|     MapGT = 0x72
 | |
| 
 | |
|     CompassEP = 0x8D
 | |
|     CompassDP = 0x8C
 | |
|     CompassTH = 0x85
 | |
|     CompassPD = 0x89
 | |
|     CompassSP = 0x8A
 | |
|     CompassSW = 0x87
 | |
|     CompassTT = 0x84
 | |
|     CompassIP = 0x86
 | |
|     CompassMM = 0x88
 | |
|     CompassTR = 0x83
 | |
|     CompassGT = 0x82
 | |
| 
 | |
|     BigKeyEP = 0x9D
 | |
|     BigKeyDP = 0x9C
 | |
|     BigKeyTH = 0x95
 | |
|     BigKeyPD = 0x99
 | |
|     BigKeySP = 0x9A
 | |
|     BigKeySW = 0x97
 | |
|     BigKeyTT = 0x94
 | |
|     BigKeyIP = 0x96
 | |
|     BigKeyMM = 0x98
 | |
|     BigKeyTR = 0x93
 | |
|     BigKeyGT = 0x92       
 | |
|     
 | |
|     KeyHC = 0xA0
 | |
|     KeyCT = 0xA4
 | |
|     KeyDP = 0xA3
 | |
|     KeyTH = 0xAA
 | |
|     KeyPD = 0xA6
 | |
|     KeySP = 0xA5
 | |
|     KeySW = 0xA8
 | |
|     KeyTT = 0xAB
 | |
|     KeyIP = 0xA9
 | |
|     KeyMM = 0xA7
 | |
|     KeyTR = 0xAC
 | |
|     KeyGT = 0xAD
 | |
| 
 | |
|     Key = 0x24
 | |
|     Compass = 0x25
 | |
|     BigKey = 0x32
 | |
|     Map = 0x33
 | |
| 
 | |
|     Something = 0x6B
 | |
| 
 | |
|     ProgressiveTunic = 0x60
 | |
|     ProgressiveShield = 0x5F
 | |
|     ProgressiveSword = 0x5E
 | |
|     Bow = 0x0B
 | |
|     SilverArrows = 0x58
 | |
|     BlueBoomerang = 0x0C
 | |
|     RedBoomerang = 0x2A
 | |
|     Hookshot = 0x0A
 | |
|     Mushroom = 0x29
 | |
|     Powder = 0x0D
 | |
|     Firerod = 0x07
 | |
|     Icerod = 0x08
 | |
|     Bombos = 0x0f
 | |
|     Ether = 0x10
 | |
|     Quake = 0x11
 | |
|     Lamp = 0x12
 | |
|     Hammer = 0x09
 | |
|     Shovel = 0x13
 | |
|     Flute = 0x14
 | |
|     Bugnet = 0x21
 | |
|     Book = 0x1D
 | |
|     Bottle = 0x16
 | |
|     Somaria = 0x15
 | |
|     Byrna = 0x18
 | |
|     Cape = 0x19
 | |
|     Mirror = 0x1A
 | |
|     Boots = 0x4B
 | |
|     ProgressiveGlove = 0x61
 | |
|     Flippers = 0x1E
 | |
|     MoonPearl = 0x1F
 | |
|     HalfMagic = 0x4E
 | |
|     HeartPiece = 0x17
 | |
|     HeartContainer = 0x3E
 | |
|     HeartContainerRefill = 0x3F
 | |
|     ThreeBombs = 0x28
 | |
|     Arrow = 0x43
 | |
|     TenArrows = 0x44
 | |
|     OneRupee = 0x34
 | |
|     FiveRupees = 0x35
 | |
|     TwentyRupees = 0x36
 | |
|     TwentyRupees2 = 0x47
 | |
|     FiftyRupees = 0x41
 | |
|     OneHundredRupees = 0x40
 | |
|     ThreeHundredRupees = 0x46
 | |
|     BombUpgrade5 = 0x51
 | |
|     BombUpgrade10 = 0x52
 | |
|     ArrowUpgrade5 = 0x53
 | |
|     ArrowUpgrade10 = 0x54
 | |
| 
 | |
|     CardCrateriaL1 = 0xD0
 | |
|     CardCrateriaL2 = 0xD1
 | |
|     CardCrateriaBoss = 0xD2
 | |
|     CardBrinstarL1 = 0xD3
 | |
|     CardBrinstarL2 = 0xD4
 | |
|     CardBrinstarBoss = 0xD5
 | |
|     CardNorfairL1 = 0xD6
 | |
|     CardNorfairL2 = 0xD7
 | |
|     CardNorfairBoss = 0xD8
 | |
|     CardMaridiaL1 = 0xD9
 | |
|     CardMaridiaL2 = 0xDA
 | |
|     CardMaridiaBoss = 0xDB
 | |
|     CardWreckedShipL1 = 0xDC
 | |
|     CardWreckedShipBoss = 0xDD
 | |
|     CardLowerNorfairL1 = 0xDE
 | |
|     CardLowerNorfairBoss = 0xDF
 | |
| 
 | |
|     SmMapBrinstar = 0xCA
 | |
|     SmMapWreckedShip = 0xCB
 | |
|     SmMapMaridia = 0xCC
 | |
|     SmMapLowerNorfair = 0xCD
 | |
| 
 | |
|     Missile = 0xC2
 | |
|     Super = 0xC3
 | |
|     PowerBomb = 0xC4
 | |
|     Grapple = 0xB0
 | |
|     XRay = 0xB1
 | |
|     ETank = 0xC0
 | |
|     ReserveTank = 0xC1
 | |
|     Charge = 0xBB
 | |
|     Ice = 0xBC
 | |
|     Wave = 0xBD
 | |
|     Spazer = 0xBE
 | |
|     Plasma = 0xBF
 | |
|     Varia = 0xB2
 | |
|     Gravity = 0xB6
 | |
|     Morph = 0xB4
 | |
|     Bombs = 0xB9
 | |
|     SpringBall = 0xB3
 | |
|     ScrewAttack = 0xB5
 | |
|     HiJump = 0xB7
 | |
|     SpaceJump = 0xB8
 | |
|     SpeedBooster = 0xBA
 | |
| 
 | |
|     BottleWithRedPotion = 0x2B
 | |
|     BottleWithGreenPotion = 0x2C
 | |
|     BottleWithBluePotion = 0x2D
 | |
|     BottleWithFairy = 0x3D
 | |
|     BottleWithBee = 0x3C
 | |
|     BottleWithGoldBee = 0x48
 | |
|     RedContent = 0x2E
 | |
|     GreenContent = 0x2F
 | |
|     BlueContent = 0x30
 | |
|     BeeContent = 0x0E
 | |
| 
 | |
| class Item:
 | |
|     Name: str
 | |
|     Type: ItemType
 | |
|     Progression: bool
 | |
| 
 | |
|     dungeon = re.compile("^(BigKey|Key|Map|Compass)")
 | |
|     bigKey = re.compile("^BigKey")
 | |
|     key = re.compile("^Key")
 | |
|     map = re.compile("^Map")
 | |
|     compass = re.compile("^Compass")
 | |
|     keycard = re.compile("^Card")
 | |
|     smMap = re.compile("^SmMap")
 | |
| 
 | |
|     def IsDungeonItem(self): return self.dungeon.match(self.Type.name)
 | |
|     def IsBigKey(self): return self.bigKey.match(self.Type.name)
 | |
|     def IsKey(self): return self.key.match(self.Type.name)
 | |
|     def IsMap(self): return self.map.match(self.Type.name)
 | |
|     def IsCompass(self): return self.compass.match(self.Type.name)
 | |
|     def IsKeycard(self): return self.keycard.match(self.Type.name)
 | |
|     def IsSmMap(self): return self.smMap.match(self.Type.name)
 | |
| 
 | |
|     def Is(self, type: ItemType, world):
 | |
|         return self.Type == type and self.World == world
 | |
| 
 | |
|     def IsNot(self, type: ItemType, world):
 | |
|         return not self.Is(type, world)
 | |
| 
 | |
|     def __init__(self, itemType: ItemType, world = None):
 | |
|         self.Type = itemType
 | |
|         self.World = world
 | |
|         self.Progression = False
 | |
|         #self.Name = itemType.GetDescription()
 | |
| 
 | |
|     @staticmethod
 | |
|     def Nothing(world):
 | |
|         return Item(ItemType.Nothing, world)
 | |
| 
 | |
|     @staticmethod
 | |
|     def AddRange(itemPool, count, item):
 | |
|         for i in range(count):
 | |
|             itemPool.append(copy.copy(item))
 | |
| 
 | |
|     @staticmethod
 | |
|     def CreateProgressionPool(world):
 | |
|         itemPool = [
 | |
|             Item(ItemType.ProgressiveShield),
 | |
|             Item(ItemType.ProgressiveShield),
 | |
|             Item(ItemType.ProgressiveShield),
 | |
|             Item(ItemType.ProgressiveSword),
 | |
|             Item(ItemType.ProgressiveSword),
 | |
|             Item(ItemType.Bow),
 | |
|             Item(ItemType.Hookshot),
 | |
|             Item(ItemType.Mushroom),
 | |
|             Item(ItemType.Powder),
 | |
|             Item(ItemType.Firerod),
 | |
|             Item(ItemType.Icerod),
 | |
|             Item(ItemType.Bombos),
 | |
|             Item(ItemType.Ether),
 | |
|             Item(ItemType.Quake),
 | |
|             Item(ItemType.Lamp),
 | |
|             Item(ItemType.Hammer),
 | |
|             Item(ItemType.Shovel),
 | |
|             Item(ItemType.Flute),
 | |
|             Item(ItemType.Bugnet),
 | |
|             Item(ItemType.Book),
 | |
|             Item(ItemType.Bottle),
 | |
|             Item(ItemType.Somaria),
 | |
|             Item(ItemType.Byrna),
 | |
|             Item(ItemType.Cape),
 | |
|             Item(ItemType.Mirror),
 | |
|             Item(ItemType.Boots),
 | |
|             Item(ItemType.ProgressiveGlove),
 | |
|             Item(ItemType.ProgressiveGlove),
 | |
|             Item(ItemType.Flippers),
 | |
|             Item(ItemType.MoonPearl),
 | |
|             Item(ItemType.HalfMagic),
 | |
| 
 | |
|             Item(ItemType.Grapple),
 | |
|             Item(ItemType.Charge),
 | |
|             Item(ItemType.Ice),
 | |
|             Item(ItemType.Wave),
 | |
|             Item(ItemType.Plasma),
 | |
|             Item(ItemType.Varia),
 | |
|             Item(ItemType.Gravity),
 | |
|             Item(ItemType.Morph),
 | |
|             Item(ItemType.Bombs),
 | |
|             Item(ItemType.SpringBall),
 | |
|             Item(ItemType.ScrewAttack),
 | |
|             Item(ItemType.HiJump),
 | |
|             Item(ItemType.SpaceJump),
 | |
|             Item(ItemType.SpeedBooster),
 | |
| 
 | |
|             Item(ItemType.Missile),
 | |
|             Item(ItemType.Super),
 | |
|             Item(ItemType.PowerBomb),
 | |
|             Item(ItemType.PowerBomb),
 | |
|             Item(ItemType.ETank),
 | |
|             Item(ItemType.ETank),
 | |
|             Item(ItemType.ETank),
 | |
|             Item(ItemType.ETank),
 | |
|             Item(ItemType.ETank),
 | |
| 
 | |
|             Item(ItemType.ReserveTank),
 | |
|             Item(ItemType.ReserveTank),
 | |
|             Item(ItemType.ReserveTank),
 | |
|             Item(ItemType.ReserveTank),
 | |
|         ]
 | |
| 
 | |
|         for item in itemPool:
 | |
|             item.Progression = True
 | |
|             item.World = world
 | |
|         return itemPool
 | |
| 
 | |
|     @staticmethod
 | |
|     def CreateNicePool(world):
 | |
|         itemPool = [
 | |
|             Item(ItemType.ProgressiveTunic),
 | |
|             Item(ItemType.ProgressiveTunic),
 | |
|             Item(ItemType.ProgressiveSword),
 | |
|             Item(ItemType.ProgressiveSword),
 | |
|             Item(ItemType.SilverArrows),
 | |
|             Item(ItemType.BlueBoomerang),
 | |
|             Item(ItemType.RedBoomerang),
 | |
|             Item(ItemType.Bottle),
 | |
|             Item(ItemType.Bottle),
 | |
|             Item(ItemType.Bottle),
 | |
|             Item(ItemType.HeartContainerRefill),
 | |
| 
 | |
|             Item(ItemType.Spazer),
 | |
|             Item(ItemType.XRay),
 | |
|         ]
 | |
| 
 | |
|         Item.AddRange(itemPool, 10, Item(ItemType.HeartContainer, world))
 | |
| 
 | |
|         for item in itemPool:
 | |
|             item.World = world
 | |
|         return itemPool
 | |
| 
 | |
|     @staticmethod
 | |
|     def CreateJunkPool(world):
 | |
|         itemPool = [
 | |
|             Item(ItemType.Arrow),
 | |
|             Item(ItemType.OneHundredRupees)
 | |
|         ]
 | |
| 
 | |
|         Item.AddRange(itemPool, 24, Item(ItemType.HeartPiece))
 | |
|         Item.AddRange(itemPool, 8, Item(ItemType.TenArrows))
 | |
|         Item.AddRange(itemPool, 13, Item(ItemType.ThreeBombs))
 | |
|         Item.AddRange(itemPool, 4, Item(ItemType.ArrowUpgrade5))
 | |
|         Item.AddRange(itemPool, 4, Item(ItemType.BombUpgrade5))
 | |
|         Item.AddRange(itemPool, 2, Item(ItemType.OneRupee))
 | |
|         Item.AddRange(itemPool, 4, Item(ItemType.FiveRupees))
 | |
|         Item.AddRange(itemPool, 21 if world.Config.Keysanity else 28, Item(ItemType.TwentyRupees))
 | |
|         Item.AddRange(itemPool, 7, Item(ItemType.FiftyRupees))
 | |
|         Item.AddRange(itemPool, 5, Item(ItemType.ThreeHundredRupees))
 | |
| 
 | |
|         Item.AddRange(itemPool, 9, Item(ItemType.ETank))
 | |
|         Item.AddRange(itemPool, 39, Item(ItemType.Missile))
 | |
|         Item.AddRange(itemPool, 15, Item(ItemType.Super))
 | |
|         Item.AddRange(itemPool, 8, Item(ItemType.PowerBomb))
 | |
| 
 | |
|         for item in itemPool:
 | |
|             item.World = world
 | |
| 
 | |
|         return itemPool
 | |
| 
 | |
|     # The order of the dungeon pool is significant
 | |
|     @staticmethod
 | |
|     def CreateDungeonPool(world):
 | |
|         itemPool = [Item(ItemType.BigKeyGT)]
 | |
|         Item.AddRange(itemPool, 4, Item(ItemType.KeyGT))
 | |
|         if (not world.Config.Keysanity):
 | |
|             itemPool += [
 | |
|                 Item(ItemType.MapGT),
 | |
|                 Item(ItemType.CompassGT),
 | |
|                 ]
 | |
|         itemPool += [
 | |
|             Item(ItemType.BigKeyEP),
 | |
|             Item(ItemType.BigKeyDP),
 | |
|             Item(ItemType.BigKeyTH),
 | |
|             Item(ItemType.BigKeyPD),
 | |
|             Item(ItemType.BigKeySP),
 | |
|             Item(ItemType.BigKeySW),
 | |
|             Item(ItemType.BigKeyTT),
 | |
|             Item(ItemType.BigKeyIP),
 | |
|             Item(ItemType.BigKeyMM),
 | |
|             Item(ItemType.BigKeyTR),
 | |
|         ]
 | |
| 
 | |
|         Item.AddRange(itemPool, 1, Item(ItemType.KeyHC))
 | |
|         Item.AddRange(itemPool, 2, Item(ItemType.KeyCT))
 | |
|         Item.AddRange(itemPool, 1, Item(ItemType.KeyDP))
 | |
|         Item.AddRange(itemPool, 1, Item(ItemType.KeyTH))
 | |
|         Item.AddRange(itemPool, 6, Item(ItemType.KeyPD))
 | |
|         Item.AddRange(itemPool, 1, Item(ItemType.KeySP))
 | |
|         Item.AddRange(itemPool, 3, Item(ItemType.KeySW))
 | |
|         Item.AddRange(itemPool, 1, Item(ItemType.KeyTT))
 | |
|         Item.AddRange(itemPool, 2, Item(ItemType.KeyIP))
 | |
|         Item.AddRange(itemPool, 3, Item(ItemType.KeyMM))
 | |
|         Item.AddRange(itemPool, 4, Item(ItemType.KeyTR))
 | |
| 
 | |
|         itemPool += [
 | |
|             Item(ItemType.MapEP),
 | |
|             Item(ItemType.MapDP),
 | |
|             Item(ItemType.MapTH),
 | |
|             Item(ItemType.MapPD),
 | |
|             Item(ItemType.MapSP),
 | |
|             Item(ItemType.MapSW),
 | |
|             Item(ItemType.MapTT),
 | |
|             Item(ItemType.MapIP),
 | |
|             Item(ItemType.MapMM),
 | |
|             Item(ItemType.MapTR),
 | |
|         ]
 | |
|         if (not world.Config.Keysanity):
 | |
|             itemPool += [
 | |
|                 Item(ItemType.MapHC),
 | |
|                 Item(ItemType.CompassEP),
 | |
|                 Item(ItemType.CompassDP),
 | |
|                 Item(ItemType.CompassTH),
 | |
|                 Item(ItemType.CompassPD),
 | |
|                 Item(ItemType.CompassSP),
 | |
|                 Item(ItemType.CompassSW),
 | |
|                 Item(ItemType.CompassTT),
 | |
|                 Item(ItemType.CompassIP),
 | |
|                 Item(ItemType.CompassMM),
 | |
|                 Item(ItemType.CompassTR),
 | |
|             ]
 | |
| 
 | |
|         for item in itemPool:
 | |
|             item.World = world
 | |
| 
 | |
|         return itemPool
 | |
| 
 | |
|     @staticmethod
 | |
|     def CreateKeycards(world):
 | |
|         itemPool =  [
 | |
|             Item(ItemType.CardCrateriaL1, world),
 | |
|             Item(ItemType.CardCrateriaL2, world),
 | |
|             Item(ItemType.CardCrateriaBoss, world),
 | |
|             Item(ItemType.CardBrinstarL1, world),
 | |
|             Item(ItemType.CardBrinstarL2, world),
 | |
|             Item(ItemType.CardBrinstarBoss, world),
 | |
|             Item(ItemType.CardNorfairL1, world),
 | |
|             Item(ItemType.CardNorfairL2, world),
 | |
|             Item(ItemType.CardNorfairBoss, world),
 | |
|             Item(ItemType.CardMaridiaL1, world),
 | |
|             Item(ItemType.CardMaridiaL2, world),
 | |
|             Item(ItemType.CardMaridiaBoss, world),
 | |
|             Item(ItemType.CardWreckedShipL1, world),
 | |
|             Item(ItemType.CardWreckedShipBoss, world),
 | |
|             Item(ItemType.CardLowerNorfairL1, world),
 | |
|             Item(ItemType.CardLowerNorfairBoss, world),
 | |
|         ]
 | |
| 
 | |
|         for item in itemPool:
 | |
|             item.Progression = True
 | |
|             item.World = world
 | |
| 
 | |
|         return itemPool
 | |
| 
 | |
|     @staticmethod
 | |
|     def CreateSmMaps(world):
 | |
|         itemPool =  [
 | |
|             Item(ItemType.SmMapBrinstar, world),
 | |
|             Item(ItemType.SmMapWreckedShip, world),
 | |
|             Item(ItemType.SmMapMaridia, world),
 | |
|             Item(ItemType.SmMapLowerNorfair, world)
 | |
|         ]
 | |
| 
 | |
|         for item in itemPool:
 | |
|             item.Progression = True
 | |
|             item.World = world
 | |
| 
 | |
|         return itemPool
 | |
| 
 | |
|     @staticmethod
 | |
|     def Get(items, itemType:ItemType):
 | |
|         item = next((i for i in items if i.Type == itemType), None)
 | |
|         if (item == None):
 | |
|             raise Exception(f"Could not find an item of type {itemType}")
 | |
|         return item
 | |
| 
 | |
|     @staticmethod
 | |
|     def Get(items, itemType:ItemType, world):
 | |
|         item = next((i for i in items if i.Is(itemType, world)), None)
 | |
|         if (item == None):
 | |
|             raise Exception(f"Could not find an item of type {itemType} in world {world.Id}")
 | |
|         return item
 | |
| 
 | |
| class Progression:
 | |
|     BigKeyEP: bool
 | |
|     BigKeyDP: bool
 | |
|     BigKeyTH: bool
 | |
|     BigKeyPD: bool
 | |
|     BigKeySP: bool
 | |
|     BigKeySW: bool
 | |
|     BigKeyTT: bool
 | |
|     BigKeyIP: bool
 | |
|     BigKeyMM: bool
 | |
|     BigKeyTR: bool
 | |
|     BigKeyGT: bool
 | |
|     KeyHC: bool
 | |
|     KeyDP: bool
 | |
|     KeyTH: bool
 | |
|     KeySP: bool
 | |
|     KeyTT: bool
 | |
|     KeyCT: bool
 | |
|     KeyPD: bool
 | |
|     KeySW: bool
 | |
|     KeyIP: bool
 | |
|     KeyMM: bool
 | |
|     KeyTR: bool
 | |
|     KeyGT: bool
 | |
|     CardCrateriaL1: bool
 | |
|     CardCrateriaL2: bool
 | |
|     CardCrateriaBoss: bool
 | |
|     CardBrinstarL1: bool
 | |
|     CardBrinstarL2: bool
 | |
|     CardBrinstarBoss: bool
 | |
|     CardNorfairL1: bool
 | |
|     CardNorfairL2: bool
 | |
|     CardNorfairBoss: bool
 | |
|     CardMaridiaL1: bool
 | |
|     CardMaridiaL2: bool
 | |
|     CardMaridiaBoss: bool
 | |
|     CardWreckedShipL1: bool
 | |
|     CardWreckedShipBoss: bool
 | |
|     CardLowerNorfairL1: bool
 | |
|     CardLowerNorfairBoss: bool
 | |
|     def CanBlockLasers(self): return self.shield >= 3
 | |
|     Sword: bool
 | |
|     MasterSword: bool
 | |
|     Bow: bool
 | |
|     Hookshot: bool
 | |
|     Mushroom: bool
 | |
|     Powder: bool
 | |
|     Firerod: bool
 | |
|     Icerod: bool
 | |
|     Bombos: bool
 | |
|     Ether: bool
 | |
|     Quake: bool
 | |
|     Lamp: bool
 | |
|     Hammer: bool
 | |
|     Shovel: bool
 | |
|     Flute: bool
 | |
|     Book: bool
 | |
|     Bottle: bool
 | |
|     Somaria: bool
 | |
|     Byrna: bool
 | |
|     Cape: bool
 | |
|     Mirror: bool
 | |
|     Boots: bool
 | |
|     Glove: bool
 | |
|     Mitt: bool
 | |
|     Flippers: bool
 | |
|     MoonPearl: bool
 | |
|     HalfMagic: bool
 | |
|     Grapple: bool
 | |
|     Charge: bool
 | |
|     Ice: bool
 | |
|     Wave: bool
 | |
|     Plasma: bool
 | |
|     Varia: bool
 | |
|     Gravity: bool
 | |
|     Morph: bool
 | |
|     Bombs: bool
 | |
|     SpringBall: bool
 | |
|     ScrewAttack: bool
 | |
|     HiJump: bool
 | |
|     SpaceJump: bool
 | |
|     SpeedBooster: bool
 | |
|     Missile: bool
 | |
|     Super: bool
 | |
|     PowerBomb: bool
 | |
|     TwoPowerBombs: bool
 | |
|     ETank: int
 | |
|     ReserveTank: int
 | |
| 
 | |
|     shield: int
 | |
| 
 | |
|     itemMapping = [
 | |
|         ItemType.BigKeyEP,
 | |
|         ItemType.BigKeyDP,
 | |
|         ItemType.BigKeyTH,
 | |
|         ItemType.BigKeyPD,
 | |
|         ItemType.BigKeySP,
 | |
|         ItemType.BigKeySW,
 | |
|         ItemType.BigKeyTT,
 | |
|         ItemType.BigKeyIP,
 | |
|         ItemType.BigKeyMM,
 | |
|         ItemType.BigKeyTR,
 | |
|         ItemType.BigKeyGT,
 | |
|         ItemType.KeyHC,
 | |
|         ItemType.KeyDP,
 | |
|         ItemType.KeyTH,
 | |
|         ItemType.KeySP,
 | |
|         ItemType.KeyTT,
 | |
|         ItemType.CardCrateriaL1,
 | |
|         ItemType.CardCrateriaL2,
 | |
|         ItemType.CardCrateriaBoss,
 | |
|         ItemType.CardBrinstarL1,
 | |
|         ItemType.CardBrinstarL2,
 | |
|         ItemType.CardBrinstarBoss,
 | |
|         ItemType.CardNorfairL1,
 | |
|         ItemType.CardNorfairL2,
 | |
|         ItemType.CardNorfairBoss,
 | |
|         ItemType.CardMaridiaL1,
 | |
|         ItemType.CardMaridiaL2,
 | |
|         ItemType.CardMaridiaBoss,
 | |
|         ItemType.CardWreckedShipL1,
 | |
|         ItemType.CardWreckedShipBoss,
 | |
|         ItemType.CardLowerNorfairL1,
 | |
|         ItemType.CardLowerNorfairBoss,
 | |
|         ItemType.Bow,
 | |
|         ItemType.Hookshot,
 | |
|         ItemType.Mushroom,
 | |
|         ItemType.Powder,
 | |
|         ItemType.Firerod,
 | |
|         ItemType.Icerod,
 | |
|         ItemType.Bombos,
 | |
|         ItemType.Ether,
 | |
|         ItemType.Quake,
 | |
|         ItemType.Lamp,
 | |
|         ItemType.Hammer,
 | |
|         ItemType.Shovel,
 | |
|         ItemType.Flute,
 | |
|         ItemType.Book,
 | |
|         ItemType.Bottle,
 | |
|         ItemType.Somaria,
 | |
|         ItemType.Byrna,
 | |
|         ItemType.Cape,
 | |
|         ItemType.Mirror,
 | |
|         ItemType.Boots,
 | |
|         ItemType.Flippers,
 | |
|         ItemType.MoonPearl,
 | |
|         ItemType.HalfMagic,
 | |
|         ItemType.Grapple,
 | |
|         ItemType.Charge,
 | |
|         ItemType.Ice,
 | |
|         ItemType.Wave,
 | |
|         ItemType.Plasma,
 | |
|         ItemType.Varia,
 | |
|         ItemType.Gravity,
 | |
|         ItemType.Morph,
 | |
|         ItemType.Bombs,
 | |
|         ItemType.SpringBall,
 | |
|         ItemType.ScrewAttack,
 | |
|         ItemType.HiJump,
 | |
|         ItemType.SpaceJump,
 | |
|         ItemType.SpeedBooster,
 | |
|         ItemType.Missile,
 | |
|         ItemType.Super,
 | |
|     ]
 | |
| 
 | |
|     def __init__(self, items):
 | |
|         for item in Progression.itemMapping:
 | |
|             setattr(self, item.name, False)
 | |
|         self.KeyCT = 0
 | |
|         self.KeyPD = 0
 | |
|         self.KeySW = 0
 | |
|         self.KeyIP = 0
 | |
|         self.KeyMM = 0
 | |
|         self.KeyTR = 0
 | |
|         self.KeyGT = 0
 | |
|         self.ETank = 0
 | |
|         self.ReserveTank = 0
 | |
|         self.shield = 0
 | |
|         self.MasterSword = False
 | |
|         self.Sword = False
 | |
|         self.Mitt = False
 | |
|         self.Glove = False
 | |
|         self.TwoPowerBombs = False
 | |
|         self.PowerBomb = False
 | |
|         self.Add(items)
 | |
| 
 | |
|     def Add(self, items:List[Item]):
 | |
|         for item in items:
 | |
|             found = item.Type in Progression.itemMapping
 | |
|             if found:
 | |
|                 setattr(self, item.Type.name, True)
 | |
|                 continue
 | |
| 
 | |
|             if (item.Type == ItemType.KeyCT):
 | |
|                 self.KeyCT += 1
 | |
|             elif (item.Type == ItemType.KeyPD):
 | |
|                 self.KeyPD += 1
 | |
|             elif (item.Type == ItemType.KeySW):
 | |
|                 self.KeySW += 1
 | |
|             elif (item.Type == ItemType.KeyIP):
 | |
|                 self.KeyIP += 1
 | |
|             elif (item.Type == ItemType.KeyMM):
 | |
|                 self.KeyMM += 1
 | |
|             elif (item.Type == ItemType.KeyTR):
 | |
|                 self.KeyTR += 1
 | |
|             elif (item.Type == ItemType.KeyGT):
 | |
|                 self.KeyGT += 1
 | |
|             elif (item.Type == ItemType.ETank):
 | |
|                 self.ETank += 1
 | |
|             elif (item.Type == ItemType.ReserveTank):
 | |
|                 self.ReserveTank += 1
 | |
|             elif (item.Type == ItemType.KeyPD):
 | |
|                 self.shield += 1
 | |
|             elif (item.Type == ItemType.ProgressiveSword):
 | |
|                 self.MasterSword = self.Sword
 | |
|                 self.Sword = True
 | |
|             elif (item.Type == ItemType.ProgressiveGlove):
 | |
|                 self.Mitt = self.Glove
 | |
|                 self.Glove = True
 | |
|             elif (item.Type == ItemType.PowerBomb):
 | |
|                 self.TwoPowerBombs = self.PowerBomb
 | |
|                 self.PowerBomb = True     
 | |
| 
 | |
|     def Remove(self, items:List[Item]):
 | |
|         for item in items:
 | |
|             found = item.Type in Progression.itemMapping
 | |
|             if found:
 | |
|                 setattr(self, item.Type.name, False)
 | |
|                 continue
 | |
| 
 | |
|             if (item.Type == ItemType.KeyCT):
 | |
|                 self.KeyCT -= 1
 | |
|             elif (item.Type == ItemType.KeyPD):
 | |
|                 self.KeyPD -= 1
 | |
|             elif (item.Type == ItemType.KeySW):
 | |
|                 self.KeySW -= 1
 | |
|             elif (item.Type == ItemType.KeyIP):
 | |
|                 self.KeyIP -= 1
 | |
|             elif (item.Type == ItemType.KeyMM):
 | |
|                 self.KeyMM -= 1
 | |
|             elif (item.Type == ItemType.KeyTR):
 | |
|                 self.KeyTR -= 1
 | |
|             elif (item.Type == ItemType.KeyGT):
 | |
|                 self.KeyGT -= 1
 | |
|             elif (item.Type == ItemType.ETank):
 | |
|                 self.ETank -= 1
 | |
|             elif (item.Type == ItemType.ReserveTank):
 | |
|                 self.ReserveTank -= 1
 | |
|             elif (item.Type == ItemType.KeyPD):
 | |
|                 self.shield -= 1
 | |
|             elif (item.Type == ItemType.ProgressiveSword):
 | |
|                 self.Sword = self.MasterSword
 | |
|                 self.MasterSword = False
 | |
|             elif (item.Type == ItemType.ProgressiveGlove):
 | |
|                 self.Glove = self.Mitt
 | |
|                 self.Mitt = False
 | |
|             elif (item.Type == ItemType.PowerBomb):
 | |
|                 self.PowerBomb = self.TwoPowerBombs
 | |
|                 self.TwoPowerBombs = False           
 | |
| 
 | |
|     def CanLiftLight(self): return self.Glove
 | |
| 
 | |
|     def CanLiftHeavy(self): return self.Mitt
 | |
| 
 | |
|     def CanLightTorches(self): return self.Firerod or self.Lamp
 | |
| 
 | |
|     def CanMeltFreezors(self): return self.Firerod or self.Bombos and self.Sword
 | |
| 
 | |
|     def CanExtendMagic(self, bars:int = 2): return (2 if self.HalfMagic else 1) * (2 if self.Bottle else 1) >= bars
 | |
| 
 | |
|     def CanKillManyEnemies(self):
 | |
|         return self.Sword or self.Hammer or self.Bow or self.Firerod or \
 | |
|                 self.Somaria or self.Byrna and self.CanExtendMagic()
 | |
| 
 | |
|     def CanAccessDeathMountainPortal(self):
 | |
|         return (self.CanDestroyBombWalls() or self.SpeedBooster) and self.Super and self.Morph
 | |
|         
 | |
| 
 | |
|     def CanAccessDarkWorldPortal(self, config: Config):
 | |
|         if (config.SMLogic == SMLogic.Normal):
 | |
|             return self.CardMaridiaL1 and self.CardMaridiaL2 and self.CanUsePowerBombs() and self.Super and self.Gravity and self.SpeedBooster
 | |
|         else:
 | |
|             return self.CardMaridiaL1 and self.CardMaridiaL2 and self.CanUsePowerBombs() and self.Super and \
 | |
|                 (self.Charge or self.Super and self.Missile) and \
 | |
|                 (self.Gravity or self.HiJump and self.Ice and self.Grapple) and \
 | |
|                 (self.Ice or self.Gravity and self.SpeedBooster)
 | |
| 
 | |
| 
 | |
|     def CanAccessMiseryMirePortal(self, config: Config):
 | |
|         if (config.SMLogic == SMLogic.Normal):
 | |
|             return (self.CardNorfairL2 or (self.SpeedBooster and self.Wave)) and self.Varia and self.Super and self.Gravity and self.SpaceJump and self.CanUsePowerBombs()
 | |
|         else:
 | |
|             return (self.CardNorfairL2 or self.SpeedBooster) and self.Varia and self.Super and \
 | |
|                     (self.CanFly() or self.HiJump or self.SpeedBooster or self.CanSpringBallJump() or self.Ice) \
 | |
|                     and (self.Gravity or self.HiJump) and self.CanUsePowerBombs() 
 | |
| 
 | |
|     def CanIbj(self):
 | |
|             return self.Morph and self.Bombs
 | |
| 
 | |
|     def CanFly(self):
 | |
|             return self.SpaceJump or self.CanIbj()
 | |
| 
 | |
|     def CanUsePowerBombs(self):
 | |
|             return self.Morph and self.PowerBomb
 | |
| 
 | |
|     def CanPassBombPassages(self):
 | |
|             return self.Morph and (self.Bombs or self.PowerBomb)
 | |
| 
 | |
|     def CanDestroyBombWalls(self):
 | |
|             return self.CanPassBombPassages() or self.ScrewAttack
 | |
| 
 | |
|     def CanSpringBallJump(self):
 | |
|             return self.Morph and self.SpringBall
 | |
| 
 | |
|     def CanHellRun(self):
 | |
|             return self.Varia or self.HasEnergyReserves(5)
 | |
| 
 | |
|     def HasEnergyReserves(self, amount: int):
 | |
|             return (self.ETank + self.ReserveTank) >= amount
 | |
| 
 | |
|     def CanOpenRedDoors(self):
 | |
|             return self.Missile or self.Super
 | |
| 
 | |
|     def CanAccessNorfairUpperPortal(self):
 | |
|             return self.Flute or self.CanLiftLight() and self.Lamp
 | |
| 
 | |
|     def CanAccessNorfairLowerPortal(self):
 | |
|             return self.Flute and self.CanLiftHeavy()
 | |
| 
 | |
|     def CanAccessMaridiaPortal(self, world):
 | |
|         import worlds.smz3.TotalSMZ3.Region
 | |
|         if (world.Config.SMLogic == SMLogic.Normal):
 | |
|             return self.MoonPearl and self.Flippers and \
 | |
|                     self.Gravity and self.Morph and \
 | |
|                     (world.CanAcquire(self, worlds.smz3.TotalSMZ3.Region.RewardType.Agahnim) or self.Hammer and self.CanLiftLight() or self.CanLiftHeavy())
 | |
|         else:
 | |
|             return self.MoonPearl and self.Flippers and \
 | |
|                     (self.CanSpringBallJump() or self.HiJump or self.Gravity) and self.Morph and \
 | |
|                     (world.CanAcquire(self, worlds.smz3.TotalSMZ3.Region.RewardType.Agahnim) or self.Hammer and self.CanLiftLight() or self.CanLiftHeavy())
 | |
| 
 | |
| # Start of AP integration
 | |
| items_start_id = 84000
 | |
| 
 | |
| lookup_id_to_name = { items_start_id + enum.value : enum.name for enum in ItemType }
 | |
| lookup_name_to_id = { item_name : item_id for item_id, item_name in lookup_id_to_name.items() } |