diff --git a/BaseClasses.py b/BaseClasses.py index 2e57d831..66631f27 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -336,6 +336,9 @@ class CollectionState(object): def can_lift_rocks(self): return self.has('Power Glove') or self.has('Titans Mitts') + def has_bottle(self): + return self.has('Bottle') or self.has('BottleRedPotion') or self.has('BottleGreenPotion') or self.has('BottleBluePotion') or self.has('BottleFairy') or self.has('BottleBee') or self.has('BottleGoodBee') + def can_lift_heavy_rocks(self): return self.has('Titans Mitts') diff --git a/ItemList.py b/ItemList.py index 79d51717..679a67f3 100644 --- a/ItemList.py +++ b/ItemList.py @@ -10,7 +10,10 @@ alwaysitems = ['Bombos', 'Book of Mudora', 'Bow', 'Cane of Somaria', 'Ether', 'F progressivegloves = ['Progressive Glove'] * 2 basicgloves = ['Power Glove', 'Titans Mitts'] -normalbaseitems = (['Blue Boomerang', 'Red Boomerang', 'Silver Arrows', 'Magic Upgrade (1/2)'] + ['Bottle'] * 4 + ['Rupees (300)'] * 4 + +normalbottles = ['Bottle', 'BottleRedPotion', 'BottleGreenPotion', 'BottleBluePotion', 'BottleFairy', 'BottleBee', 'BottleGoodBee'] +hardbottles = ['Bottle', 'BottleRedPotion', 'BottleGreenPotion', 'BottleBluePotion', 'BottleBee', 'BottleGoodBee'] + +normalbaseitems = (['Blue Boomerang', 'Red Boomerang', 'Silver Arrows', 'Magic Upgrade (1/2)'] + ['Rupees (300)'] * 4 + ['Single Arrow', 'Sanctuary Heart Container', 'Arrow Upgrade (+10)', 'Bomb Upgrade (+10)'] + ['Boss Heart Container'] * 10 + ['Piece of Heart'] * 24) normalfirst15extra = ['Rupees (100)', 'Rupees (300)', 'Rupees (50)'] + ['Arrow Upgrade (+5)'] * 6 + ['Bomb Upgrade (+5)'] * 6 normalsecond15extra = ['Bombs (3)'] * 10 + ['Rupees (50)'] * 2 + ['Arrows (10)'] * 2 + ['Rupee (1)'] @@ -28,7 +31,7 @@ normalbasicshield = ['Blue Shield', 'Red Shield', 'Mirror Shield'] normalprogressivearmor = ['Progressive Armor'] * 2 normalbasicarmor = ['Blue Mail', 'Red Mail'] -easybaseitems = (['Blue Boomerang', 'Red Boomerang', 'Silver Arrows'] + ['Bottle'] * 8 + ['Rupees (300)'] * 4 + ['Magic Upgrade (1/2)'] * 2 + +easybaseitems = (['Blue Boomerang', 'Red Boomerang', 'Silver Arrows'] + ['Rupees (300)'] * 4 + ['Magic Upgrade (1/2)'] * 2 + ['Single Arrow', 'Sanctuary Heart Container', 'Arrow Upgrade (+10)', 'Bomb Upgrade (+10)'] + ['Boss Heart Container'] * 10 + ['Piece of Heart'] * 12) easyextra = ['Piece of Heart'] * 12 + ['Rupees (300)'] easylimitedextra = ['Boss Heart Container'] * 3 @@ -48,7 +51,7 @@ easybasicshield = ['Blue Shield', 'Blue Shield', 'Red Shield', 'Red Shield', 'Mi easyprogressivearmor = ['Progressive Armor'] * 4 easybasicarmor = ['Blue Mail', 'Blue Mail', 'Red Mail', 'Red Mail'] -hardbaseitems = (['Silver Arrows', 'Single Arrow'] + ['Bottle'] * 4 + ['Rupees (300)'] + ['Rupees (100)'] * 2 + ['Rupees (50)'] + ['Bombs (3)'] + +hardbaseitems = (['Silver Arrows', 'Single Arrow'] + ['Rupees (300)'] + ['Rupees (100)'] * 2 + ['Rupees (50)'] + ['Bombs (3)'] + ['Boss Heart Container'] * 5 + ['Piece of Heart'] * 24) hardfirst20extra = ['Bombs (3)'] * 4 + ['Single Bomb'] * 4 + ['Rupees (5)'] * 5 + ['Rupee (1)'] * 2 + ['Rupees (100)'] + ['Rupees (50)'] * 4 hardsecond20extra = ['Single Bomb'] * 4 + ['Rupees (5)'] * 10 + ['Rupees (20)'] * 2 + ['Rupee (1)'] * 3 + ['Arrows (10)'] @@ -65,7 +68,7 @@ hardbasicshield = ['Blue Shield', 'Red Shield', 'Red Shield'] hardarmor = ['Progressive Armor', 'Progressive Armor'] expertbaseitems = (['Single Arrow', 'Rupees (300)', 'Rupees (100)', 'Bombs (3)', 'Arrows (10)'] + ['Rupees (50)'] * 4 + ['Rupees (5)'] * 5 + - ['Bottle'] * 4 + ['Rupees (20)'] + ['Single Bomb'] * 2 + ['Piece of Heart'] * 24) + ['Rupees (20)'] + ['Single Bomb'] * 2 + ['Piece of Heart'] * 24) expertfirst15extra = ['Single Bomb'] * 13 + ['Rupees (20)'] * 2 expertsecond25extra = ['Single Bomb'] * 8 + ['Single Arrow'] * 9 + ['Rupees (20)'] * 3 + ['Rupee (1)'] * 5 expertthird15extra = ['Rupees (5)'] * 5 + ['Single Bomb'] * 3 + ['Rupees (20)'] * 2 + ['Single Arrow'] * 5 @@ -78,7 +81,7 @@ expertbasicsword = ['Fighter Sword', 'Master Sword', 'Master Sword'] expertswordless = ['Rupees (20)'] * 3 + ['Silver Arrows'] insanebaseitems = (['Single Arrow', 'Bombs (3)', 'Arrows (10)'] + ['Rupees (50)'] * 3 + ['Rupees (5)'] * 10 + ['Rupees (300)'] * 4 + ['Rupees (100)'] * 3 + - ['Bottle'] * 4 + ['Rupee (1)'] * 4 + ['Single Bomb'] * 4) + ['Rupee (1)'] * 4 + ['Single Bomb'] * 4) insanefirst15extra = ['Single Bomb'] * 4 + ['Single Arrow'] * 4 + ['Rupee (1)'] * 4 + ['Rupees (300)'] + ['Rupees (100)'] + ['Rupees (50)'] insanesecond25extra = ['Single Bomb'] * 7 + ['Single Arrow'] * 7 + ['Rupee (1)'] * 7 + ['Rupees (20)'] * 4 insanethird10extra = ['Single Bomb'] * 3 + ['Single Arrow'] * 3 + ['Rupee (1)'] * 3 + ['Rupees (20)'] @@ -130,6 +133,9 @@ def generate_itempool(world): if world.difficulty == 'normal': world.itempool.extend(ItemFactory(normalbaseitems)) + for i in range (0, 4): + thisbottle = normalbottles[random.randint(0, 6)] + world.itempool.append(ItemFactory(thisbottle)) extraitems = 70 if world.timer in ['timed', 'timed-countdown']: world.itempool.extend(ItemFactory(normaltimedother)) @@ -214,6 +220,9 @@ def generate_itempool(world): world.itempool.extend(ItemFactory(['Fighter Sword'])) elif world.difficulty == 'easy': world.itempool.extend(ItemFactory(easybaseitems)) + for i in range (0, 8): + thisbottle = normalbottles[random.randint(0, 6)] + world.itempool.append(ItemFactory(thisbottle)) extraitems = 70 if world.timer in ['timed', 'timed-countdown']: world.itempool.extend(ItemFactory(easytimedother)) @@ -303,6 +312,9 @@ def generate_itempool(world): elif world.difficulty == 'hard': world.itempool.extend(ItemFactory(hardbaseitems)) + for i in range (0, 4): + thisbottle = hardbottles[random.randint(0, 5)] + world.itempool.append(ItemFactory(thisbottle)) extraitems = 80 if world.timer in ['timed', 'timed-countdown']: world.itempool.extend(ItemFactory(hardtimedother)) @@ -379,6 +391,9 @@ def generate_itempool(world): elif world.difficulty == 'expert': world.itempool.extend(ItemFactory(expertbaseitems)) + thisbottle = hardbottles[random.randint(0, 5)] + for i in range (0, 4): + world.itempool.append(ItemFactory(thisbottle)) extraitems = 80 if world.timer in ['timed', 'timed-countdown']: world.itempool.extend(ItemFactory(experttimedother)) @@ -444,6 +459,9 @@ def generate_itempool(world): elif world.difficulty == 'insane': world.itempool.extend(ItemFactory(insanebaseitems)) + thisbottle = hardbottles[random.randint(0, 5)] + for i in range (0, 4): + world.itempool.append(ItemFactory(thisbottle)) extraitems = 90 if world.timer in ['timed', 'timed-countdown']: world.itempool.extend(ItemFactory(insanetimedother)) diff --git a/Items.py b/Items.py index 9b2442c7..b93d778f 100644 --- a/Items.py +++ b/Items.py @@ -1,4 +1,4 @@ -from BaseClasses import Item +from BaseClasses import World, Item import random import logging @@ -12,12 +12,6 @@ def ItemFactory(items): for item in items: if item in item_table: advancement, priority, type, code, pedestal_hint, pedestal_credit, sickkid_credit, zora_credit, witch_credit, fluteboy_credit = item_table[item] - if item == 'Bottle': - # randomly fill bottle - if world.difficulty in ['hard', 'expert', insane']: - code = [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x48][random.randint(0, 5)] - else: - code = [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x3D, 0x48][random.randint(0, 6)] ret.append(Item(item, advancement, priority, type, code, pedestal_hint, pedestal_credit, sickkid_credit, zora_credit, witch_credit, fluteboy_credit)) else: logging.getLogger('').warning('Unknown Item: %s' % item) @@ -52,7 +46,13 @@ item_table = {'Bow': (True, False, None, 0x0B, 'You have\nchosen the\narcher cla 'Ether': (True, False, None, 0x10, 'This magic\ncoin freezes\neverything!', 'and the bolt coin', 'coin-collecting kid', 'bolt coin for sale', 'shrooms for bolt-coin', 'boy hides coin again'), 'Bombos': (True, False, None, 0x0F, 'Burn, baby,\nburn! Fear my\nring of fire!', 'and the swirly coin', 'coin-collecting kid', 'swirly coin for sale', 'shrooms for swirly-coin', 'boy hides coin again'), 'Quake': (True, False, None, 0x11, 'Maxing out the\nRichter scale\nis what I do!', 'and the wavy coin', 'coin-collecting kid', 'wavy coin for sale', 'shrooms for wavy-coin', 'boy hides coin again'), - 'Bottle': (True, False, None, 0xFF, 'Now you can\nstore potions\nand stuff!', 'and the terrarium', 'the terrarium kid', 'terrarium for sale', 'special promotion', 'boy stores things again'), # specific content written on creation + 'Bottle': (True, False, None, 0x16, 'Now you can\nstore potions\nand stuff!', 'and the terrarium', 'the terrarium kid', 'terrarium for sale', 'special promotion', 'boy stores things again'), + 'BottleRedPotion': (True, False, None, 0x2B, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'boy drinks again'), + 'BottleGreenPotion': (True, False, None, 0x2C, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'boy drinks again'), + 'BottleBluePotion': (True, False, None, 0x2D, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'boy stores drinks again'), + 'BottleFairy': (True, False, None, 0x3D, 'Save me and I will revive you', 'and the captive', 'the tingle kid', 'hostage for sale', 'fairy dust and shrooms', 'boy revives again'), + 'BottleBee': (True, False, None, 0x3C, 'I will sting your foes a few times', 'and the sting buddy', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'boy is stung again'), + 'BottleGoodBee': (True, False, None, 0x48, 'I will sting your foes a whole lot!', 'and the sparkle sting', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'boy is stung again'), 'Master Sword': (True, False, None, 0x50, 'I beat barries and pigs alike', 'and the master sword', 'sword-wielding kid', 'glow sword for sale', 'fungus for blue slasher', 'boy fights again'), 'Tempered Sword': (True, False, None, 0x02, 'I stole the\nblacksmith\'s\njob!', 'the tempered sword', 'sword-wielding kid', 'flame sword for sale', 'fungus for red slasher', 'boy fights again'), 'Fighter Sword': (True, False, None, 0x49, 'A pathetic\nsword rests\nhere!', 'the tiny sword', 'sword-wielding kid', 'tiny sword for sale', 'fungus for tiny slasher', 'boy fights again'), diff --git a/Rules.py b/Rules.py index cff73537..d7fe41c8 100644 --- a/Rules.py +++ b/Rules.py @@ -100,7 +100,7 @@ def global_rules(world): set_rule(world.get_entrance('Waterfall of Wishing'), lambda state: state.has('Flippers')) # can be fake flippered into, but is in weird state inside that might prevent you from doing things. Can be improved in future Todo set_rule(world.get_location('Blacksmith'), lambda state: state.can_lift_heavy_rocks() and state.can_reach('West Dark World')) # Can S&Q with smith set_rule(world.get_location('Magic Bat'), lambda state: state.has('Magic Powder')) - set_rule(world.get_location('Sick Kid'), lambda state: state.has('Bottle')) + set_rule(world.get_location('Sick Kid'), lambda state: state.has_bottle()) set_rule(world.get_location('Library'), lambda state: state.has_Boots()) set_rule(world.get_location('Potion Shop'), lambda state: state.has('Mushroom')) set_rule(world.get_entrance('Desert Palace Entrance (North) Rocks'), lambda state: state.can_lift_rocks()) @@ -177,7 +177,7 @@ def global_rules(world): set_rule(world.get_entrance('Superbunny Cave (Bottom)'), lambda state: state.has_Pearl()) set_rule(world.get_entrance('Cave Shop (Dark Death Mountain)'), lambda state: state.has_Pearl()) # just for save bunny algo for now set_rule(world.get_entrance('Superbunny Cave Exit (Bottom)'), lambda state: False) # Cannot get to bottom exit from top. Just exists for shuffling - set_rule(world.get_location('Spike Cave'), lambda state: state.has('Hammer') and state.can_lift_rocks() and (state.has('Cane of Byrna') or state.has('Cape')) and (state.has('Bottle') or state.has('Half Magic') or state.has('Quarter Magic'))) + set_rule(world.get_location('Spike Cave'), lambda state: state.has('Hammer') and state.can_lift_rocks() and (state.has('Cane of Byrna') or state.has('Cape')) and (state.has_bottle() or state.has('Half Magic') or state.has('Quarter Magic'))) set_rule(world.get_location('Hookshot Cave - Top Right'), lambda state: state.has('Hookshot')) set_rule(world.get_location('Hookshot Cave - Top Left'), lambda state: state.has('Hookshot')) set_rule(world.get_location('Hookshot Cave - Bottom Right'), lambda state: state.has('Hookshot') or state.has('Pegasus Boots')) @@ -291,7 +291,7 @@ def global_rules(world): set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Left'), lambda state: state.has('Cane of Byrna') or state.has('Cape') or state.has('Mirror Shield')) set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Right'), lambda state: state.has('Cane of Byrna') or state.has('Cape') or state.has('Mirror Shield')) set_rule(world.get_entrance('Turtle Rock (Trinexx)'), lambda state: state.has('Small Key (Turtle Rock)', 4) and state.has('Big Key (Turtle Rock)') and state.has('Cane of Somaria') and state.has('Fire Rod') and state.has('Ice Rod') and - (state.has('Hammer') or state.has_beam_sword() or state.has('Bottle') or state.has('Half Magic') or state.has('Quarter Magic'))) + (state.has('Hammer') or state.has_beam_sword() or state.has_bottle() or state.has('Half Magic') or state.has('Quarter Magic'))) set_trock_key_rules(world) set_rule(world.get_entrance('Palace of Darkness Bonk Wall'), lambda state: state.has('Bow')) @@ -364,7 +364,7 @@ def global_rules(world): set_rule(world.get_location('Ganon'), lambda state: state.has_beam_sword() and state.has_fire_source() and state.has('Crystal 1') and state.has('Crystal 2') and state.has('Crystal 3') and state.has('Crystal 4') and state.has('Crystal 5') and state.has('Crystal 6') and state.has('Crystal 7') - and (state.has('Tempered Sword') or state.has('Golden Sword') or (state.has('Silver Arrows') and state.has('Bow')) or state.has('Lamp') or state.has('Bottle') or state.has('Half Magic') or state.has('Quarter Magic'))) # need to light torch a sufficient amount of times + and (state.has('Tempered Sword') or state.has('Golden Sword') or (state.has('Silver Arrows') and state.has('Bow')) or state.has('Lamp') or state.has_bottle() or state.has('Half Magic') or state.has('Quarter Magic'))) # need to light torch a sufficient amount of times set_rule(world.get_entrance('Ganon Drop'), lambda state: state.has_beam_sword()) # need to damage ganon to get tiles to drop