diff --git a/BaseClasses.py b/BaseClasses.py index 648af224..d931309f 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -169,6 +169,11 @@ class MultiWorld(): def factorio_player_ids(self): yield from (player for player in range(1, self.players + 1) if self.game[player] == "Factorio") + @property + def minecraft_player_ids(self): + yield from (player for player in range(1, self.players + 1) if self.game[player] == "Minecraft") + + def get_name_string_for_object(self, obj) -> str: return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})' @@ -234,6 +239,7 @@ class MultiWorld(): def soft_collect(item): if item.game == "A Link to the Past" and item.name.startswith('Progressive '): + # ALttP items if 'Sword' in item.name: if ret.has('Golden Sword', item.player): pass @@ -806,6 +812,91 @@ class CollectionState(object): rules.append(self.has('Moon Pearl', player)) return all(rules) + # Minecraft logic functions + def has_iron_ingots(self, player: int): + return self.has('Progressive Tools', player) and self.has('Ingot Crafting', player) + + def has_gold_ingots(self, player: int): + return self.has('Ingot Crafting', player) and (self.has('Progressive Tools', player, 2) or self.can_reach('The Nether', 'Region', player)) + + def has_diamond_pickaxe(self, player: int): + return self.has('Progressive Tools', player, 3) and self.has_iron_ingots(player) + + def craft_crossbow(self, player: int): + return self.has('Archery', player) and self.has_iron_ingots(player) + + def has_bottle_mc(self, player: int): + return self.has('Bottles', player) and self.has('Ingot Crafting', player) + + def can_enchant(self, player: int): + return self.has('Enchanting', player) and self.has_diamond_pickaxe(player) # mine obsidian and lapis + + def can_use_anvil(self, player: int): + return self.has('Enchanting', player) and self.has('Resource Blocks', player) and self.has_iron_ingots(player) + + def fortress_loot(self, player: int): # saddles, blaze rods, wither skulls + return self.can_reach('Nether Fortress', 'Region', player) and self.basic_combat(player) + + def can_brew_potions(self, player: int): + return self.fortress_loot(player) and self.has('Brewing', player) and self.has_bottle_mc(player) + + def can_piglin_trade(self, player: int): + return self.has_gold_ingots(player) and (self.can_reach('The Nether', 'Region', player) or self.can_reach('Bastion Remnant', 'Region', player)) + + def enter_stronghold(self, player: int): + return self.fortress_loot(player) and self.has('Brewing', player) and self.has('3 Ender Pearls', player) + + # Difficulty-dependent functions + def combat_difficulty(self, player: int): + return self.world.combat_difficulty[player].get_option_name() + + def can_adventure(self, player: int): + if self.combat_difficulty(player) == 'easy': + return self.has('Progressive Weapons', player, 2) and self.has_iron_ingots(player) + elif self.combat_difficulty(player) == 'hard': + return True + return self.has('Progressive Weapons', player) and (self.has('Ingot Crafting', player) or self.has('Campfire', player)) + + def basic_combat(self, player: int): + if self.combat_difficulty(player) == 'easy': + return self.has('Progressive Weapons', player, 2) and self.has('Progressive Armor', player) and \ + self.has('Shield', player) and self.has_iron_ingots(player) + elif self.combat_difficulty(player) == 'hard': + return True + return self.has('Progressive Weapons', player) and (self.has('Progressive Armor', player) or self.has('Shield', player)) and self.has_iron_ingots(player) + + def complete_raid(self, player: int): + reach_regions = self.can_reach('Village', 'Region', player) and self.can_reach('Pillager Outpost', 'Region', player) + if self.combat_difficulty(player) == 'easy': + return reach_regions and \ + self.has('Progressive Weapons', player, 3) and self.has('Progressive Armor', player, 2) and \ + self.has('Shield', player) and self.has('Archery', player) and \ + self.has('Progressive Tools', player, 2) and self.has_iron_ingots(player) + elif self.combat_difficulty(player) == 'hard': # might be too hard? + return reach_regions and self.has('Progressive Weapons', player, 2) and self.has_iron_ingots(player) and \ + (self.has('Progressive Armor', player) or self.has('Shield', player)) + return reach_regions and self.has('Progressive Weapons', player, 2) and self.has_iron_ingots(player) and \ + self.has('Progressive Armor', player) and self.has('Shield', player) + + def can_kill_wither(self, player: int): + build_wither = self.fortress_loot(player) and (self.can_reach('The Nether', 'Region', player) or self.can_piglin_trade(player)) + normal_kill = self.has("Progressive Weapons", player, 3) and self.has("Progressive Armor", player, 2) and self.can_brew_potions(player) and self.can_enchant(player) + if self.combat_difficulty(player) == 'easy': + return build_wither and normal_kill and self.has('Archery', player) + elif self.combat_difficulty(player) == 'hard': # cheese kill using bedrock ceilings + return build_wither and (normal_kill or self.can_reach('The Nether', 'Region', player) or self.can_reach('The End', 'Region', player)) + return build_wither and normal_kill + + def can_kill_ender_dragon(self, player: int): + if self.combat_difficulty(player) == 'easy': + return self.has("Progressive Weapons", player, 3) and self.has("Progressive Armor", player, 2) and self.has('Archery', player) and \ + self.can_brew_potions(player) and self.can_enchant(player) + if self.combat_difficulty(player) == 'hard': + return (self.has('Progressive Weapons', player, 2) and self.has('Progressive Armor', player)) or \ + (self.has('Progressive Weapons', player, 1) and self.has('Bed', player)) + return self.has('Progressive Weapons', player, 2) and self.has('Progressive Armor', player) and self.has('Archery', player) + + def collect(self, item: Item, event: bool = False, location: Location = None) -> bool: if location: self.locations_checked.add(location) @@ -1403,6 +1494,11 @@ class Spoiler(object): for hk_option in Options.hollow_knight_options: res = getattr(self.world, hk_option)[player] outfile.write(f'{hk_option+":":33}{res}\n') + if player in self.world.minecraft_player_ids: + import Options + for mc_option in Options.minecraft_options: + res = getattr(self.world, mc_option)[player] + outfile.write(f'{mc_option+":":33}{bool_to_text(res) if type(res) == Options.Toggle else res.get_option_name()}\n') if player in self.world.alttp_player_ids: for team in range(self.world.teams): outfile.write('%s%s\n' % ( @@ -1418,7 +1514,7 @@ class Spoiler(object): outfile.write('Mode: %s\n' % self.metadata['mode'][player]) outfile.write('Retro: %s\n' % ('Yes' if self.metadata['retro'][player] else 'No')) - outfile.write('Swordless: %s\n' % ('Yes' if self.metadata['swordless'][player] else 'No')) + outfile.write('Swordless: %s\n' % ('Yes' if self.metadata['swordless'][player] else 'No')) outfile.write('Goal: %s\n' % self.metadata['goal'][player]) if "triforce" in self.metadata["goal"][player]: # triforce hunt outfile.write("Pieces available for Triforce: %s\n" % diff --git a/Main.py b/Main.py index 0993777f..289869dc 100644 --- a/Main.py +++ b/Main.py @@ -26,6 +26,8 @@ from worlds.hk import gen_hollow from worlds.hk import create_regions as hk_create_regions from worlds.factorio import gen_factorio, factorio_create_regions from worlds.factorio.Mod import generate_mod +from worlds.minecraft import gen_minecraft, fill_minecraft_slot_data, generate_mc_data +from worlds.minecraft.Regions import minecraft_create_regions from worlds.generic.Rules import locality_rules from worlds import Games import Patch @@ -136,6 +138,8 @@ def main(args, seed=None): setattr(world, hk_option, getattr(args, hk_option, {})) for factorio_option in Options.factorio_options: setattr(world, factorio_option, getattr(args, factorio_option, {})) + for minecraft_option in Options.minecraft_options: + setattr(world, minecraft_option, getattr(args, minecraft_option, {})) world.glitch_triforce = args.glitch_triforce # This is enabled/disabled globally, no per player option. world.rom_seeds = {player: random.Random(world.random.randint(0, 999999999)) for player in range(1, world.players + 1)} @@ -207,6 +211,9 @@ def main(args, seed=None): for player in world.factorio_player_ids: factorio_create_regions(world, player) + for player in world.minecraft_player_ids: + minecraft_create_regions(world, player) + for player in world.alttp_player_ids: if world.open_pyramid[player] == 'goal': world.open_pyramid[player] = world.goal[player] in {'crystals', 'ganontriforcehunt', 'localganontriforcehunt', 'ganonpedestal'} @@ -266,6 +273,9 @@ def main(args, seed=None): for player in world.factorio_player_ids: gen_factorio(world, player) + for player in world.minecraft_player_ids: + gen_minecraft(world, player) + logger.info("Running Item Plando") for item in world.itempool: @@ -305,9 +315,7 @@ def main(args, seed=None): balance_multiworld_progression(world) logger.info('Generating output files.') - outfilebase = 'AP_%s' % (args.outputname if args.outputname else world.seed) - rom_names = [] def _gen_rom(team: int, player: int): @@ -511,6 +519,8 @@ def main(args, seed=None): for option_name in Options.hollow_knight_options: option = getattr(world, option_name)[slot] slots_data[option_name] = int(option.value) + for slot in world.minecraft_player_ids: + slot_data[slot] = fill_minecraft_slot_data(world, slot) multidata = zlib.compress(pickle.dumps({ "slot_data" : slot_data, "games": games, @@ -549,9 +559,11 @@ def main(args, seed=None): if multidata_task: multidata_task.result() # retrieve exception if one exists pool.shutdown() # wait for all queued tasks to complete + for player in world.minecraft_player_ids: # Doing this after shutdown prevents the .apmc from being generated if there's an error + generate_mc_data(world, player, str(args.outputname if args.outputname else world.seed)) if not args.skip_playthrough: logger.info('Calculating playthrough.') - create_playthrough(world) + create_playthrough(world) if args.create_spoiler: # needs spoiler.hashes to be filled, that depend on rom_futures being done world.spoiler.to_file(output_path('%s_Spoiler.txt' % outfilebase)) diff --git a/Options.py b/Options.py index 7958fea3..e9c2e80e 100644 --- a/Options.py +++ b/Options.py @@ -296,7 +296,26 @@ factorio_options: typing.Dict[str, type(Option)] = {"max_science_pack": MaxScien "visibility": Visibility, "random_tech_ingredients": Toggle} -minecraft_options: typing.Dict[str, type(Option)] = {} +class AdvancementGoal(Choice): + option_few = 0 + option_normal = 1 + option_many = 2 + default = 1 + +class CombatDifficulty(Choice): + option_easy = 0 + option_normal = 1 + option_hard = 2 + default = 1 + +minecraft_options: typing.Dict[str, type(Option)] = { + "advancement_goal": AdvancementGoal, + "combat_difficulty": CombatDifficulty, + "include_hard_advancements": Toggle, + "include_insane_advancements": Toggle, + "include_postgame_advancements": Toggle, + "shuffle_structures": Toggle +} if __name__ == "__main__": import argparse diff --git a/playerSettings.yaml b/playerSettings.yaml index fc4abbdb..0efc65e2 100644 --- a/playerSettings.yaml +++ b/playerSettings.yaml @@ -70,6 +70,27 @@ visibility: random_tech_ingredients: on: 1 off: 0 +# Minecraft options: +advancement_goal: # Number of advancements required (out of 92 total) to spawn the Ender Dragon and complete the game. + few: 0 # 30 advancements + normal: 1 # 50 + many: 0 # 70 +combat_difficulty: # Modifies the level of items logically required for exploring dangerous areas and fighting bosses. + easy: 0 + normal: 1 + hard: 0 +include_hard_advancements: # Junk-fills certain RNG-reliant or tedious advancements with XP rewards. + on: 0 + off: 1 +include_insane_advancements: # Junk-fills extremely difficult advancements; this is only How Did We Get Here? and Adventuring Time. + on: 0 + off: 1 +include_postgame_advancements: # Some advancements require defeating the Ender Dragon; this will junk-fill them so you won't have to finish to send some items. + on: 0 + off: 1 +shuffle_structures: # CURRENTLY DISABLED; enables shuffling of villages, outposts, fortresses, bastions, and end cities. + on: 0 + off: 1 # A Link to the Past options: ### Logic Section ### # Warning: overworld_glitches is not available and minor_glitches is only partially implemented on the door-rando version diff --git a/test/minecraft/TestAdvancements.py b/test/minecraft/TestAdvancements.py new file mode 100644 index 00000000..2306f9e9 --- /dev/null +++ b/test/minecraft/TestAdvancements.py @@ -0,0 +1,1145 @@ +from test.minecraft.TestMinecraft import TestMinecraft + +# Format: +# [location, expected_result, given_items, [excluded_items]] +# Every advancement has its own test, named by its internal ID number. +class TestAdvancements(TestMinecraft): + + def test_42000(self): + self.run_location_tests([ + ["Who is Cutting Onions?", False, []], + ["Who is Cutting Onions?", False, [], ['Ingot Crafting']], + ["Who is Cutting Onions?", False, [], ['Flint and Steel']], + ["Who is Cutting Onions?", False, [], ['Progressive Tools']], + ["Who is Cutting Onions?", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Who is Cutting Onions?", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket']], + ["Who is Cutting Onions?", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools']], + ]) + + def test_42001(self): + self.run_location_tests([ + ["Oh Shiny", False, []], + ["Oh Shiny", False, [], ['Ingot Crafting']], + ["Oh Shiny", False, [], ['Flint and Steel']], + ["Oh Shiny", False, [], ['Progressive Tools']], + ["Oh Shiny", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Oh Shiny", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket']], + ["Oh Shiny", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools']], + ]) + + def test_42002(self): + self.run_location_tests([ + ["Suit Up", False, []], + ["Suit Up", False, [], ["Progressive Armor"]], + ["Suit Up", False, [], ["Ingot Crafting"]], + ["Suit Up", False, [], ["Progressive Tools"]], + ["Suit Up", True, ["Progressive Armor", "Ingot Crafting", "Progressive Tools"]], + ]) + + def test_42003(self): + self.run_location_tests([ + ["Very Very Frightening", False, []], + ["Very Very Frightening", False, [], ['Channeling Book']], + ["Very Very Frightening", False, [], ['Resource Blocks']], + ["Very Very Frightening", False, [], ['Ingot Crafting']], + ["Very Very Frightening", False, [], ['Enchanting']], + ["Very Very Frightening", False, [], ['Progressive Tools']], + ["Very Very Frightening", False, [], ['Progressive Weapons']], + ["Very Very Frightening", True, ['Progressive Weapons', 'Progressive Tools', 'Progressive Tools', 'Progressive Tools', + 'Enchanting', 'Ingot Crafting', 'Resource Blocks', 'Channeling Book']], + ]) + + def test_42004(self): + self.run_location_tests([ + ["Hot Stuff", False, []], + ["Hot Stuff", False, [], ["Bucket"]], + ["Hot Stuff", False, [], ["Ingot Crafting"]], + ["Hot Stuff", False, [], ["Progressive Tools"]], + ["Hot Stuff", True, ["Bucket", "Ingot Crafting", "Progressive Tools"]], + ]) + + def test_42005(self): + self.run_location_tests([ + ["Free the End", False, []], + ["Free the End", False, [], ['Ingot Crafting']], + ["Free the End", False, [], ['Flint and Steel']], + ["Free the End", False, [], ['Progressive Tools']], + ["Free the End", False, ['Progressive Weapons'], ['Progressive Weapons', 'Progressive Weapons']], + ["Free the End", False, [], ['Progressive Armor']], + ["Free the End", False, [], ['Brewing']], + ["Free the End", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Free the End", False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ["Free the End", False, [], ['Archery']], + ["Free the End", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Weapons', 'Archery', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["Free the End", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Weapons', 'Archery', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ]) + + def test_42006(self): + self.run_location_tests([ + ["A Furious Cocktail", False, []], + ["A Furious Cocktail", False, [], ['Ingot Crafting']], + ["A Furious Cocktail", False, [], ['Flint and Steel']], + ["A Furious Cocktail", False, [], ['Progressive Tools']], + ["A Furious Cocktail", False, [], ['Progressive Weapons']], + ["A Furious Cocktail", False, [], ['Progressive Armor', 'Shield']], + ["A Furious Cocktail", False, [], ['Brewing']], + ["A Furious Cocktail", False, [], ['Bottles']], + ["A Furious Cocktail", False, [], ['Fishing Rod']], + ["A Furious Cocktail", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["A Furious Cocktail", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', 'Brewing', 'Bottles', 'Fishing Rod']], + ["A Furious Cocktail", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', 'Brewing', 'Bottles', 'Fishing Rod']], + ["A Furious Cocktail", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Shield', 'Brewing', 'Bottles', 'Fishing Rod']], + ["A Furious Cocktail", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', 'Brewing', 'Bottles', 'Fishing Rod']], + ]) + + def test_42007(self): + self.run_location_tests([ + ["Best Friends Forever", True, []], + ]) + + def test_42008(self): + self.run_location_tests([ + ["Bring Home the Beacon", False, []], + ["Bring Home the Beacon", False, [], ['Ingot Crafting']], + ["Bring Home the Beacon", False, [], ['Flint and Steel']], + ["Bring Home the Beacon", False, ['Progressive Tools', 'Progressive Tools'], ['Progressive Tools']], + ["Bring Home the Beacon", False, ['Progressive Weapons'], ['Progressive Weapons', 'Progressive Weapons']], + ["Bring Home the Beacon", False, ['Progressive Armor'], ['Progressive Armor']], + ["Bring Home the Beacon", False, [], ['Enchanting']], + ["Bring Home the Beacon", False, [], ['Brewing']], + ["Bring Home the Beacon", False, [], ['Bottles']], + ["Bring Home the Beacon", False, [], ['Resource Blocks']], + ["Bring Home the Beacon", True, [], ['Bucket']], + ["Bring Home the Beacon", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Weapons', 'Progressive Weapons', + 'Progressive Armor', 'Progressive Armor', + 'Enchanting', 'Brewing', 'Bottles', 'Resource Blocks']], + ]) + + def test_42009(self): + self.run_location_tests([ + ["Not Today, Thank You", False, []], + ["Not Today, Thank You", False, [], ["Shield"]], + ["Not Today, Thank You", False, [], ["Ingot Crafting"]], + ["Not Today, Thank You", False, [], ["Progressive Tools"]], + ["Not Today, Thank You", True, ["Shield", "Ingot Crafting", "Progressive Tools"]], + ]) + + def test_42010(self): + self.run_location_tests([ + ["Isn't It Iron Pick", False, []], + ["Isn't It Iron Pick", True, ["Progressive Tools", "Progressive Tools"], ["Progressive Tools"]], + ["Isn't It Iron Pick", False, [], ["Progressive Tools", "Progressive Tools"]], + ["Isn't It Iron Pick", False, [], ["Ingot Crafting"]], + ["Isn't It Iron Pick", False, ["Progressive Tools", "Ingot Crafting"]], + ["Isn't It Iron Pick", True, ["Progressive Tools", "Progressive Tools", "Ingot Crafting"]], + ]) + + def test_42011(self): + self.run_location_tests([ + ["Local Brewery", False, []], + ["Local Brewery", False, [], ['Ingot Crafting']], + ["Local Brewery", False, [], ['Flint and Steel']], + ["Local Brewery", False, [], ['Progressive Tools']], + ["Local Brewery", False, [], ['Progressive Weapons']], + ["Local Brewery", False, [], ['Progressive Armor', 'Shield']], + ["Local Brewery", False, [], ['Brewing']], + ["Local Brewery", False, [], ['Bottles']], + ["Local Brewery", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Local Brewery", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', 'Brewing', 'Bottles']], + ["Local Brewery", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', 'Brewing', 'Bottles']], + ["Local Brewery", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Shield', 'Brewing', 'Bottles']], + ["Local Brewery", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', 'Brewing', 'Bottles']], + ]) + + def test_42012(self): + self.run_location_tests([ + ["The Next Generation", False, []], + ["The Next Generation", False, [], ['Ingot Crafting']], + ["The Next Generation", False, [], ['Flint and Steel']], + ["The Next Generation", False, [], ['Progressive Tools']], + ["The Next Generation", False, ['Progressive Weapons'], ['Progressive Weapons', 'Progressive Weapons']], + ["The Next Generation", False, [], ['Progressive Armor']], + ["The Next Generation", False, [], ['Brewing']], + ["The Next Generation", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["The Next Generation", False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ["The Next Generation", False, [], ['Archery']], + ["The Next Generation", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Weapons', 'Archery', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["The Next Generation", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Weapons', 'Archery', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ]) + + def test_42013(self): + self.run_location_tests([ + ["Fishy Business", False, []], + ["Fishy Business", False, [], ['Fishing Rod']], + ["Fishy Business", True, ['Fishing Rod']], + ]) + + def test_42014(self): + self.run_location_tests([ + ["Hot Tourist Destinations", False, []], + ["Hot Tourist Destinations", False, [], ['Ingot Crafting']], + ["Hot Tourist Destinations", False, [], ['Flint and Steel']], + ["Hot Tourist Destinations", False, [], ['Progressive Tools']], + ["Hot Tourist Destinations", False, [], ['Progressive Weapons']], + ["Hot Tourist Destinations", False, [], ['Progressive Armor', 'Shield']], + ["Hot Tourist Destinations", False, [], ['Fishing Rod']], + ["Hot Tourist Destinations", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Hot Tourist Destinations", True, ['Ingot Crafting', 'Progressive Tools', 'Progressive Weapons', 'Progressive Armor', 'Flint and Steel', 'Bucket', 'Fishing Rod']], + ["Hot Tourist Destinations", True, ['Ingot Crafting', 'Progressive Tools', 'Progressive Weapons', 'Progressive Armor', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Fishing Rod']], + ["Hot Tourist Destinations", True, ['Ingot Crafting', 'Progressive Tools', 'Progressive Weapons', 'Shield', 'Flint and Steel', 'Bucket', 'Fishing Rod']], + ["Hot Tourist Destinations", True, ['Ingot Crafting', 'Progressive Tools', 'Progressive Weapons', 'Shield', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Fishing Rod']], + ]) + + def test_42015(self): + self.run_location_tests([ + ["This Boat Has Legs", False, []], + ["This Boat Has Legs", False, [], ['Ingot Crafting']], + ["This Boat Has Legs", False, [], ['Flint and Steel']], + ["This Boat Has Legs", False, [], ['Progressive Tools']], + ["This Boat Has Legs", False, [], ['Progressive Weapons']], + ["This Boat Has Legs", False, [], ['Progressive Armor', 'Shield']], + ["This Boat Has Legs", False, [], ['Fishing Rod']], + ["This Boat Has Legs", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["This Boat Has Legs", True, ['Ingot Crafting', 'Progressive Tools', 'Progressive Weapons', 'Progressive Armor', 'Flint and Steel', 'Bucket', 'Fishing Rod']], + ["This Boat Has Legs", True, ['Ingot Crafting', 'Progressive Tools', 'Progressive Weapons', 'Progressive Armor', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Fishing Rod']], + ["This Boat Has Legs", True, ['Ingot Crafting', 'Progressive Tools', 'Progressive Weapons', 'Shield', 'Flint and Steel', 'Bucket', 'Fishing Rod']], + ["This Boat Has Legs", True, ['Ingot Crafting', 'Progressive Tools', 'Progressive Weapons', 'Shield', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Fishing Rod']], + ]) + + def test_42016(self): + self.run_location_tests([ + ["Sniper Duel", False, []], + ["Sniper Duel", False, [], ['Archery']], + ["Sniper Duel", True, ['Archery']], + ]) + + def test_42017(self): + self.run_location_tests([ + ["Nether", False, []], + ["Nether", False, [], ['Ingot Crafting']], + ["Nether", False, [], ['Flint and Steel']], + ["Nether", False, [], ['Progressive Tools']], + ["Nether", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Nether", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket']], + ["Nether", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools']], + ]) + + def test_42018(self): + self.run_location_tests([ + ["Great View From Up Here", False, []], + ["Great View From Up Here", False, [], ['Ingot Crafting']], + ["Great View From Up Here", False, [], ['Flint and Steel']], + ["Great View From Up Here", False, [], ['Progressive Tools']], + ["Great View From Up Here", False, [], ['Progressive Weapons']], + ["Great View From Up Here", False, [], ['Progressive Armor', 'Shield']], + ["Great View From Up Here", False, [], ['Brewing']], + ["Great View From Up Here", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Great View From Up Here", False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ["Great View From Up Here", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["Great View From Up Here", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["Great View From Up Here", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["Great View From Up Here", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ]) + + def test_42019(self): + self.run_location_tests([ + ["How Did We Get Here?", False, []], + ["How Did We Get Here?", False, [], ['Ingot Crafting']], + ["How Did We Get Here?", False, [], ['Flint and Steel']], + ["How Did We Get Here?", False, ['Progressive Tools', 'Progressive Tools'], ['Progressive Tools']], + ["How Did We Get Here?", False, ['Progressive Weapons', 'Progressive Weapons'], ['Progressive Weapons']], + ["How Did We Get Here?", False, ['Progressive Armor'], ['Progressive Armor']], + ["How Did We Get Here?", False, [], ['Shield']], + ["How Did We Get Here?", False, [], ['Enchanting']], + ["How Did We Get Here?", False, [], ['Brewing']], + ["How Did We Get Here?", False, [], ['Bottles']], + ["How Did We Get Here?", False, [], ['Archery']], + ["How Did We Get Here?", False, [], ['Resource Blocks']], + ["How Did We Get Here?", False, [], ['Fishing Rod']], + ["How Did We Get Here?", False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ["How Did We Get Here?", True, ['Ingot Crafting', 'Flint and Steel', + 'Progressive Tools', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Weapons', 'Progressive Weapons', + 'Progressive Armor', 'Progressive Armor', 'Shield', + 'Enchanting', 'Brewing', 'Archery', 'Bottles', 'Resource Blocks', 'Fishing Rod', + '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ]) + + def test_42020(self): + self.run_location_tests([ + ["Bullseye", False, []], + ["Bullseye", False, [], ['Archery']], + ["Bullseye", False, [], ['Ingot Crafting']], + ["Bullseye", False, [], ['Progressive Tools']], + ["Bullseye", True, ['Progressive Tools', 'Progressive Tools', 'Ingot Crafting', 'Archery']], + ]) + + def test_42021(self): + self.run_location_tests([ + ["Spooky Scary Skeleton", False, []], + ["Spooky Scary Skeleton", False, [], ['Ingot Crafting']], + ["Spooky Scary Skeleton", False, [], ['Flint and Steel']], + ["Spooky Scary Skeleton", False, [], ['Progressive Tools']], + ["Spooky Scary Skeleton", False, [], ['Progressive Weapons']], + ["Spooky Scary Skeleton", False, [], ['Progressive Armor', 'Shield']], + ["Spooky Scary Skeleton", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Spooky Scary Skeleton", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', 'Progressive Weapons', 'Progressive Armor']], + ["Spooky Scary Skeleton", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Progressive Weapons', 'Progressive Armor']], + ["Spooky Scary Skeleton", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', 'Progressive Weapons', 'Shield']], + ["Spooky Scary Skeleton", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Progressive Weapons', 'Shield']], + ]) + + def test_42022(self): + self.run_location_tests([ + ["Two by Two", False, []], + ["Two by Two", False, [], ['Ingot Crafting']], + ["Two by Two", False, [], ['Flint and Steel']], + ["Two by Two", False, [], ['Progressive Tools']], + ["Two by Two", False, [], ['Progressive Weapons']], + ["Two by Two", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Two by Two", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', 'Progressive Weapons']], + ["Two by Two", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Progressive Weapons']], + ]) + + def test_42023(self): + self.run_location_tests([ + ["Stone Age", True, []], + ]) + + def test_42024(self): + self.run_location_tests([ + ["Two Birds, One Arrow", False, []], + ["Two Birds, One Arrow", False, [], ['Archery']], + ["Two Birds, One Arrow", False, [], ['Ingot Crafting']], + ["Two Birds, One Arrow", False, ['Progressive Tools'], ['Progressive Tools', 'Progressive Tools']], + ["Two Birds, One Arrow", False, [], ['Enchanting']], + ["Two Birds, One Arrow", True, ['Archery', 'Ingot Crafting', 'Progressive Tools', 'Progressive Tools', 'Progressive Tools', 'Enchanting']], + ]) + + def test_42025(self): + self.run_location_tests([ + ["We Need to Go Deeper", False, []], + ["We Need to Go Deeper", False, [], ['Ingot Crafting']], + ["We Need to Go Deeper", False, [], ['Flint and Steel']], + ["We Need to Go Deeper", False, [], ['Progressive Tools']], + ["We Need to Go Deeper", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["We Need to Go Deeper", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket']], + ["We Need to Go Deeper", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools']], + ]) + + def test_42026(self): + self.run_location_tests([ + ["Who's the Pillager Now?", False, []], + ["Who's the Pillager Now?", False, [], ['Archery']], + ["Who's the Pillager Now?", False, [], ['Ingot Crafting']], + ["Who's the Pillager Now?", False, [], ['Progressive Tools']], + ["Who's the Pillager Now?", False, [], ['Progressive Weapons']], + ["Who's the Pillager Now?", True, ['Archery', 'Progressive Tools', 'Progressive Weapons', 'Ingot Crafting']], + ]) + + def test_42027(self): + self.run_location_tests([ + ["Getting an Upgrade", False, []], + ["Getting an Upgrade", True, ["Progressive Tools"]], + ]) + + def test_42028(self): + self.run_location_tests([ + ["Tactical Fishing", False, []], + ["Tactical Fishing", False, [], ['Ingot Crafting']], + ["Tactical Fishing", False, [], ['Progressive Tools']], + ["Tactical Fishing", False, [], ['Bucket']], + ["Tactical Fishing", True, ['Ingot Crafting', 'Progressive Tools', 'Bucket']], + ]) + + def test_42029(self): + self.run_location_tests([ + ["Zombie Doctor", False, []], + ["Zombie Doctor", False, [], ['Ingot Crafting']], + ["Zombie Doctor", False, [], ['Flint and Steel']], + ["Zombie Doctor", False, [], ['Progressive Tools']], + ["Zombie Doctor", False, [], ['Progressive Weapons']], + ["Zombie Doctor", False, [], ['Progressive Armor', 'Shield']], + ["Zombie Doctor", False, [], ['Brewing']], + ["Zombie Doctor", False, [], ['Bottles']], + ["Zombie Doctor", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Zombie Doctor", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', 'Brewing', 'Bottles']], + ["Zombie Doctor", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', 'Brewing', 'Bottles']], + ["Zombie Doctor", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Shield', 'Brewing', 'Bottles']], + ["Zombie Doctor", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', 'Brewing', 'Bottles']], + ]) + + def test_42030(self): + self.run_location_tests([ + ["The City at the End of the Game", False, []], + ["The City at the End of the Game", False, [], ['Ingot Crafting']], + ["The City at the End of the Game", False, [], ['Flint and Steel']], + ["The City at the End of the Game", False, [], ['Progressive Tools']], + ["The City at the End of the Game", False, [], ['Progressive Weapons']], + ["The City at the End of the Game", False, [], ['Progressive Armor', 'Shield']], + ["The City at the End of the Game", False, [], ['Brewing']], + ["The City at the End of the Game", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["The City at the End of the Game", False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ["The City at the End of the Game", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["The City at the End of the Game", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["The City at the End of the Game", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["The City at the End of the Game", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ]) + + def test_42031(self): + self.run_location_tests([ + ["Ice Bucket Challenge", False, []], + ["Ice Bucket Challenge", False, ["Progressive Tools", "Progressive Tools"], ["Progressive Tools"]], + ["Ice Bucket Challenge", False, [], ["Ingot Crafting"]], + ["Ice Bucket Challenge", True, ["Progressive Tools", "Progressive Tools", "Progressive Tools", "Ingot Crafting"]], + ]) + + def test_42032(self): + self.run_location_tests([ + ["Remote Getaway", False, []], + ["Remote Getaway", False, [], ['Ingot Crafting']], + ["Remote Getaway", False, [], ['Flint and Steel']], + ["Remote Getaway", False, [], ['Progressive Tools']], + ["Remote Getaway", False, [], ['Progressive Weapons']], + ["Remote Getaway", False, [], ['Progressive Armor', 'Shield']], + ["Remote Getaway", False, [], ['Brewing']], + ["Remote Getaway", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Remote Getaway", False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ["Remote Getaway", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["Remote Getaway", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["Remote Getaway", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["Remote Getaway", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ]) + + def test_42033(self): + self.run_location_tests([ + ["Into Fire", False, []], + ["Into Fire", False, [], ['Ingot Crafting']], + ["Into Fire", False, [], ['Flint and Steel']], + ["Into Fire", False, [], ['Progressive Tools']], + ["Into Fire", False, [], ['Progressive Weapons']], + ["Into Fire", False, [], ['Progressive Armor', 'Shield']], + ["Into Fire", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Into Fire", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', 'Progressive Weapons', 'Progressive Armor']], + ["Into Fire", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Progressive Weapons', 'Progressive Armor']], + ["Into Fire", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', 'Progressive Weapons', 'Shield']], + ["Into Fire", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Progressive Weapons', 'Shield']], + ]) + + def test_42034(self): + self.run_location_tests([ + ["War Pigs", False, []], + ["War Pigs", False, [], ['Ingot Crafting']], + ["War Pigs", False, [], ['Flint and Steel']], + ["War Pigs", False, [], ['Progressive Tools']], + ["War Pigs", False, [], ['Progressive Weapons']], + ["War Pigs", False, [], ['Progressive Armor', 'Shield']], + ["War Pigs", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["War Pigs", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', 'Progressive Weapons', 'Shield']], + ["War Pigs", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Progressive Weapons', 'Shield']], + ]) + + def test_42035(self): + self.run_location_tests([ + ["Take Aim", False, []], + ["Take Aim", False, [], ['Archery']], + ["Take Aim", True, ['Archery']], + ]) + + def test_42036(self): + self.run_location_tests([ + ["Total Beelocation", False, []], + ["Total Beelocation", False, [], ['Enchanting']], + ["Total Beelocation", False, [], ['Silk Touch Book']], + ["Total Beelocation", False, [], ['Resource Blocks']], + ["Total Beelocation", False, [], ['Ingot Crafting']], + ["Total Beelocation", False, ['Progressive Tools', 'Progressive Tools'], ['Progressive Tools']], + ["Total Beelocation", True, ['Enchanting', 'Silk Touch Book', 'Resource Blocks', 'Ingot Crafting', 'Progressive Tools', 'Progressive Tools', 'Progressive Tools']], + ]) + + def test_42037(self): + self.run_location_tests([ + ["Arbalistic", False, []], + ["Arbalistic", False, [], ['Enchanting']], + ["Arbalistic", False, [], ['Piercing IV Book']], + ["Arbalistic", False, [], ['Resource Blocks']], + ["Arbalistic", False, [], ['Ingot Crafting']], + ["Arbalistic", False, ['Progressive Tools', 'Progressive Tools'], ['Progressive Tools']], + ["Arbalistic", False, [], ['Archery']], + ["Arbalistic", True, ['Enchanting', 'Piercing IV Book', 'Resource Blocks', 'Ingot Crafting', 'Progressive Tools', 'Progressive Tools', 'Progressive Tools', 'Archery']], + ]) + + def test_42038(self): + self.run_location_tests([ + ["The End... Again...", False, []], + ["The End... Again...", False, [], ['Ingot Crafting']], + ["The End... Again...", False, [], ['Flint and Steel']], + ["The End... Again...", False, [], ['Progressive Tools']], + ["The End... Again...", False, ['Progressive Weapons'], ['Progressive Weapons', 'Progressive Weapons']], + ["The End... Again...", False, [], ['Progressive Armor']], + ["The End... Again...", False, [], ['Brewing']], + ["The End... Again...", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["The End... Again...", False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ["The End... Again...", False, [], ['Archery']], + ["The End... Again...", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Weapons', 'Archery', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["The End... Again...", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Weapons', 'Archery', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ]) + + def test_42039(self): + self.run_location_tests([ + ["Acquire Hardware", False, []], + ["Acquire Hardware", False, [], ["Progressive Tools"]], + ["Acquire Hardware", False, [], ["Ingot Crafting"]], + ["Acquire Hardware", True, ["Progressive Tools", "Ingot Crafting"]], + ]) + + def test_42040(self): + self.run_location_tests([ + ["Not Quite \"Nine\" Lives", False, []], + ["Not Quite \"Nine\" Lives", False, [], ['Ingot Crafting']], + ["Not Quite \"Nine\" Lives", False, [], ['Flint and Steel']], + ["Not Quite \"Nine\" Lives", False, [], ['Progressive Tools']], + ["Not Quite \"Nine\" Lives", False, [], ['Resource Blocks']], + ["Not Quite \"Nine\" Lives", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Not Quite \"Nine\" Lives", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', 'Resource Blocks']], + ["Not Quite \"Nine\" Lives", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Resource Blocks']], + ]) + + def test_42041(self): + self.run_location_tests([ + ["Cover Me With Diamonds", False, []], + ["Cover Me With Diamonds", False, ['Progressive Armor'], ['Progressive Armor']], + ["Cover Me With Diamonds", False, ['Progressive Tools'], ['Progressive Tools', 'Progressive Tools']], + ["Cover Me With Diamonds", False, [], ['Ingot Crafting']], + ["Cover Me With Diamonds", True, ['Ingot Crafting', 'Progressive Tools', 'Progressive Tools', 'Progressive Armor', 'Progressive Armor']], + ]) + + def test_42042(self): + self.run_location_tests([ + ["Sky's the Limit", False, []], + ["Sky's the Limit", False, [], ['Ingot Crafting']], + ["Sky's the Limit", False, [], ['Flint and Steel']], + ["Sky's the Limit", False, [], ['Progressive Tools']], + ["Sky's the Limit", False, [], ['Progressive Weapons']], + ["Sky's the Limit", False, [], ['Progressive Armor', 'Shield']], + ["Sky's the Limit", False, [], ['Brewing']], + ["Sky's the Limit", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Sky's the Limit", False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ["Sky's the Limit", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["Sky's the Limit", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["Sky's the Limit", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["Sky's the Limit", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ]) + + def test_42043(self): + self.run_location_tests([ + ["Hired Help", False, []], + ["Hired Help", False, [], ['Resource Blocks']], + ["Hired Help", False, [], ['Ingot Crafting']], + ["Hired Help", False, [], ['Progressive Tools']], + ["Hired Help", True, ['Progressive Tools', 'Ingot Crafting', 'Resource Blocks']], + ]) + + def test_42044(self): + self.run_location_tests([ + ["Return to Sender", False, []], + ["Return to Sender", False, [], ['Ingot Crafting']], + ["Return to Sender", False, [], ['Flint and Steel']], + ["Return to Sender", False, [], ['Progressive Tools']], + ["Return to Sender", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Return to Sender", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket']], + ["Return to Sender", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools']], + ]) + + def test_42045(self): + self.run_location_tests([ + ["Sweet Dreams", False, []], + ["Sweet Dreams", True, ['Bed']], + ["Sweet Dreams", False, [], ['Bed', 'Progressive Weapons']], + ["Sweet Dreams", False, [], ['Bed', 'Ingot Crafting', 'Campfire']], + ["Sweet Dreams", True, ['Progressive Weapons', 'Ingot Crafting'], ['Bed', 'Campfire']], + ["Sweet Dreams", True, ['Progressive Weapons', 'Campfire'], ['Bed', 'Ingot Crafting']], + ]) + + def test_42046(self): + self.run_location_tests([ + ["You Need a Mint", False, []], + ["You Need a Mint", False, [], ['Ingot Crafting']], + ["You Need a Mint", False, [], ['Flint and Steel']], + ["You Need a Mint", False, [], ['Progressive Tools']], + ["You Need a Mint", False, ['Progressive Weapons'], ['Progressive Weapons', 'Progressive Weapons']], + ["You Need a Mint", False, [], ['Progressive Armor']], + ["You Need a Mint", False, [], ['Brewing']], + ["You Need a Mint", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["You Need a Mint", False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ["You Need a Mint", False, [], ['Archery']], + ["You Need a Mint", False, [], ['Bottles']], + ["You Need a Mint", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Weapons', 'Archery', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', 'Bottles']], + ["You Need a Mint", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Weapons', 'Archery', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', 'Bottles']], + ]) + + def test_42047(self): + self.run_location_tests([ + ["Adventure", True, []], + ]) + + def test_42048(self): + self.run_location_tests([ + ["Monsters Hunted", False, []], + ["Monsters Hunted", False, [], ['Ingot Crafting']], + ["Monsters Hunted", False, [], ['Flint and Steel']], + ["Monsters Hunted", False, [], ['Progressive Tools']], + ["Monsters Hunted", False, ['Progressive Weapons'], ['Progressive Weapons', 'Progressive Weapons']], + ["Monsters Hunted", False, [], ['Progressive Armor']], + ["Monsters Hunted", False, [], ['Brewing']], + ["Monsters Hunted", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Monsters Hunted", False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ["Monsters Hunted", False, [], ['Archery']], + ["Monsters Hunted", False, [], ['Enchanting']], + ["Monsters Hunted", False, [], ['Fishing Rod']], + ["Monsters Hunted", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Weapons', 'Progressive Weapons', 'Archery', + 'Progressive Armor', 'Progressive Armor', 'Enchanting', + 'Fishing Rod', 'Brewing', 'Bottles', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ]) + + def test_42049(self): + self.run_location_tests([ + ["Enchanter", False, []], + ["Enchanter", False, [], ['Enchanting']], + ["Enchanter", False, ['Progressive Tools', 'Progressive Tools'], ['Progressive Tools']], + ["Enchanter", False, [], ['Ingot Crafting']], + ["Enchanter", True, ['Progressive Tools', 'Progressive Tools', 'Progressive Tools', 'Enchanting', 'Ingot Crafting']], + ]) + + def test_42050(self): + self.run_location_tests([ + ["Voluntary Exile", False, []], + ["Voluntary Exile", False, [], ['Progressive Weapons']], + ["Voluntary Exile", False, [], ['Progressive Armor', 'Shield']], + ["Voluntary Exile", False, [], ['Progressive Tools']], + ["Voluntary Exile", False, [], ['Ingot Crafting']], + ["Voluntary Exile", True, ['Progressive Tools', 'Progressive Armor', 'Progressive Weapons', 'Ingot Crafting']], + ["Voluntary Exile", True, ['Progressive Tools', 'Shield', 'Progressive Weapons', 'Ingot Crafting']], + ]) + + def test_42051(self): + self.run_location_tests([ + ["Eye Spy", False, []], + ["Eye Spy", False, [], ['Ingot Crafting']], + ["Eye Spy", False, [], ['Flint and Steel']], + ["Eye Spy", False, [], ['Progressive Tools']], + ["Eye Spy", False, [], ['Progressive Weapons']], + ["Eye Spy", False, [], ['Progressive Armor', 'Shield']], + ["Eye Spy", False, [], ['Brewing']], + ["Eye Spy", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Eye Spy", False, [], ['3 Ender Pearls']], + ["Eye Spy", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', 'Brewing', '3 Ender Pearls']], + ["Eye Spy", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', 'Brewing', '3 Ender Pearls']], + ["Eye Spy", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Shield', 'Brewing', '3 Ender Pearls']], + ["Eye Spy", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', 'Brewing', '3 Ender Pearls']], + ]) + + def test_42052(self): + self.run_location_tests([ + ["The End", False, []], + ["The End", False, [], ['Ingot Crafting']], + ["The End", False, [], ['Flint and Steel']], + ["The End", False, [], ['Progressive Tools']], + ["The End", False, [], ['Progressive Weapons']], + ["The End", False, [], ['Progressive Armor', 'Shield']], + ["The End", False, [], ['Brewing']], + ["The End", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["The End", False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ["The End", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["The End", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["The End", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["The End", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ]) + + def test_42053(self): + self.run_location_tests([ + ["Serious Dedication", False, []], + ["Serious Dedication", False, [], ['Ingot Crafting']], + ["Serious Dedication", False, [], ['Flint and Steel']], + ["Serious Dedication", False, ['Progressive Tools', 'Progressive Tools'], ['Progressive Tools']], + ["Serious Dedication", False, [], ['Progressive Weapons']], + ["Serious Dedication", False, [], ['Progressive Armor', 'Shield']], + ["Serious Dedication", False, [], ['Brewing']], + ["Serious Dedication", False, [], ['Bottles']], + ["Serious Dedication", False, [], ['Bed']], + ["Serious Dedication", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', 'Brewing', 'Bottles', 'Bed']], + ["Serious Dedication", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', 'Brewing', 'Bottles', 'Bed']], + ]) + + def test_42054(self): + self.run_location_tests([ + ["Postmortal", False, []], + ["Postmortal", False, ['Progressive Weapons'], ['Progressive Weapons', 'Progressive Weapons']], + ["Postmortal", False, [], ['Progressive Armor']], + ["Postmortal", False, [], ['Shield']], + ["Postmortal", False, [], ['Ingot Crafting']], + ["Postmortal", False, [], ['Progressive Tools']], + ["Postmortal", True, ['Progressive Weapons', 'Progressive Weapons', 'Progressive Armor', 'Shield', 'Ingot Crafting', 'Progressive Tools']], + ]) + + def test_42055(self): + self.run_location_tests([ + ["Monster Hunter", True, []], + ]) + + def test_42056(self): + self.run_location_tests([ + ["Adventuring Time", False, []], + ["Adventuring Time", False, [], ['Progressive Weapons']], + ["Adventuring Time", False, [], ['Campfire', 'Ingot Crafting']], + ["Adventuring Time", True, ['Progressive Weapons', 'Campfire']], + ["Adventuring Time", True, ['Progressive Weapons', 'Ingot Crafting']], + ]) + + def test_42057(self): + self.run_location_tests([ + ["A Seedy Place", True, []], + ]) + + def test_42058(self): + self.run_location_tests([ + ["Those Were the Days", False, []], + ["Those Were the Days", False, [], ['Ingot Crafting']], + ["Those Were the Days", False, [], ['Flint and Steel']], + ["Those Were the Days", False, [], ['Progressive Tools']], + ["Those Were the Days", False, [], ['Progressive Weapons']], + ["Those Were the Days", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Those Were the Days", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', 'Progressive Weapons']], + ["Those Were the Days", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Progressive Weapons']], + ]) + + def test_42059(self): + self.run_location_tests([ + ["Hero of the Village", False, []], + ["Hero of the Village", False, ['Progressive Weapons'], ['Progressive Weapons', 'Progressive Weapons']], + ["Hero of the Village", False, [], ['Progressive Armor']], + ["Hero of the Village", False, [], ['Shield']], + ["Hero of the Village", False, [], ['Ingot Crafting']], + ["Hero of the Village", False, [], ['Progressive Tools']], + ["Hero of the Village", True, ['Progressive Weapons', 'Progressive Weapons', 'Progressive Armor', 'Shield', 'Ingot Crafting', 'Progressive Tools']], + ]) + + def test_42060(self): + self.run_location_tests([ + ["Hidden in the Depths", False, []], + ["Hidden in the Depths", False, [], ['Ingot Crafting']], + ["Hidden in the Depths", False, [], ['Flint and Steel']], + ["Hidden in the Depths", False, ['Progressive Tools', 'Progressive Tools'], ['Progressive Tools']], + ["Hidden in the Depths", False, [], ['Progressive Weapons']], + ["Hidden in the Depths", False, [], ['Progressive Armor', 'Shield']], + ["Hidden in the Depths", False, [], ['Brewing']], + ["Hidden in the Depths", False, [], ['Bottles']], + ["Hidden in the Depths", False, [], ['Bed']], + ["Hidden in the Depths", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', 'Brewing', 'Bottles', 'Bed']], + ["Hidden in the Depths", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', 'Brewing', 'Bottles', 'Bed']], + ]) + + def test_42061(self): + self.run_location_tests([ + ["Beaconator", False, []], + ["Beaconator", False, [], ['Ingot Crafting']], + ["Beaconator", False, [], ['Flint and Steel']], + ["Beaconator", False, ['Progressive Tools', 'Progressive Tools'], ['Progressive Tools']], + ["Beaconator", False, ['Progressive Weapons'], ['Progressive Weapons', 'Progressive Weapons']], + ["Beaconator", False, ['Progressive Armor'], ['Progressive Armor']], + ["Beaconator", False, [], ['Brewing']], + ["Beaconator", False, [], ['Bottles']], + ["Beaconator", False, [], ['Resource Blocks']], + ["Beaconator", False, [], ['Enchanting']], + ["Beaconator", True, [], ['Bucket']], + ["Beaconator", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Weapons', 'Progressive Weapons', 'Progressive Armor', 'Progressive Armor', + 'Brewing', 'Bottles', 'Resource Blocks', 'Enchanting']], + ]) + + def test_42062(self): + self.run_location_tests([ + ["Withering Heights", False, []], + ["Withering Heights", False, [], ['Ingot Crafting']], + ["Withering Heights", False, [], ['Flint and Steel']], + ["Withering Heights", False, [], ['Progressive Tools']], + ["Withering Heights", False, ['Progressive Weapons'], ['Progressive Weapons', 'Progressive Weapons']], + ["Withering Heights", False, ['Progressive Armor'], ['Progressive Armor']], + ["Withering Heights", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Withering Heights", False, [], ['Brewing']], + ["Withering Heights", False, [], ['Bottles']], + ["Withering Heights", False, [], ['Enchanting']], + ["Withering Heights", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Weapons', 'Progressive Weapons', 'Progressive Armor', 'Progressive Armor', + 'Brewing', 'Bottles', 'Enchanting']], + ]) + + def test_42063(self): + self.run_location_tests([ + ["A Balanced Diet", False, []], + ["A Balanced Diet", False, [], ['Bottles']], + ["A Balanced Diet", False, [], ['Ingot Crafting']], + ["A Balanced Diet", False, [], ['Resource Blocks']], + ["A Balanced Diet", False, [], ['Flint and Steel']], + ["A Balanced Diet", False, [], ['Progressive Tools']], + ["A Balanced Diet", False, [], ['Progressive Weapons']], + ["A Balanced Diet", False, [], ['Progressive Armor', 'Shield']], + ["A Balanced Diet", False, [], ['Brewing']], + ["A Balanced Diet", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["A Balanced Diet", False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ["A Balanced Diet", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', 'Bottles', 'Resource Blocks', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["A Balanced Diet", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', 'Bottles', 'Resource Blocks', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["A Balanced Diet", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Shield', 'Bottles', 'Resource Blocks', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["A Balanced Diet", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', 'Bottles', 'Resource Blocks', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ]) + + def test_42064(self): + self.run_location_tests([ + ["Subspace Bubble", False, []], + ["Subspace Bubble", False, [], ['Ingot Crafting']], + ["Subspace Bubble", False, [], ['Flint and Steel']], + ["Subspace Bubble", False, [], ['Progressive Tools', 'Progressive Tools'], ['Progressive Tools']], + ["Subspace Bubble", True, ['Progressive Tools', 'Progressive Tools', 'Progressive Tools', 'Flint and Steel', 'Ingot Crafting']], + ]) + + def test_42065(self): + self.run_location_tests([ + ["Husbandry", True, []], + ]) + + def test_42066(self): + self.run_location_tests([ + ["Country Lode, Take Me Home", False, []], + ["Country Lode, Take Me Home", False, [], ['Ingot Crafting']], + ["Country Lode, Take Me Home", False, [], ['Flint and Steel']], + ["Country Lode, Take Me Home", False, ['Progressive Tools', 'Progressive Tools'], ['Progressive Tools']], + ["Country Lode, Take Me Home", False, [], ['Progressive Weapons']], + ["Country Lode, Take Me Home", False, [], ['Progressive Armor', 'Shield']], + ["Country Lode, Take Me Home", False, [], ['Brewing']], + ["Country Lode, Take Me Home", False, [], ['Bottles']], + ["Country Lode, Take Me Home", False, [], ['Bed']], + ["Country Lode, Take Me Home", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', 'Brewing', 'Bottles', 'Bed']], + ["Country Lode, Take Me Home", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', 'Brewing', 'Bottles', 'Bed']], + ]) + + def test_42067(self): + self.run_location_tests([ + ["Bee Our Guest", False, []], + ["Bee Our Guest", False, [], ['Campfire']], + ["Bee Our Guest", False, [], ['Bottles']], + ["Bee Our Guest", False, [], ['Ingot Crafting']], + ["Bee Our Guest", True, ['Campfire', 'Bottles', 'Ingot Crafting']], + ]) + + def test_42068(self): + self.run_location_tests([ + ["What a Deal!", False, []], + ["What a Deal!", False, [], ['Progressive Weapons']], + ["What a Deal!", False, [], ['Campfire', 'Ingot Crafting']], + ["What a Deal!", True, ['Progressive Weapons', 'Campfire']], + ["What a Deal!", True, ['Progressive Weapons', 'Ingot Crafting']], + ]) + + def test_42069(self): + self.run_location_tests([ + ["Uneasy Alliance", False, []], + ["Uneasy Alliance", False, [], ['Ingot Crafting']], + ["Uneasy Alliance", False, [], ['Flint and Steel']], + ["Uneasy Alliance", False, [], ['Progressive Tools', 'Progressive Tools'], ['Progressive Tools']], + ["Uneasy Alliance", True, ['Progressive Tools', 'Progressive Tools', 'Progressive Tools', 'Flint and Steel', 'Ingot Crafting']], + ]) + + def test_42070(self): + self.run_location_tests([ + ["Diamonds!", False, []], + ["Diamonds!", True, ["Progressive Tools", "Progressive Tools"], ["Progressive Tools"]], + ["Diamonds!", False, [], ["Progressive Tools", "Progressive Tools"]], + ["Diamonds!", False, [], ["Ingot Crafting"]], + ["Diamonds!", False, ["Progressive Tools", "Ingot Crafting"]], + ["Diamonds!", True, ["Progressive Tools", "Progressive Tools", "Ingot Crafting"]], + ]) + + def test_42071(self): + self.run_location_tests([ + ["A Terrible Fortress", False, []], + ["A Terrible Fortress", False, [], ['Ingot Crafting']], + ["A Terrible Fortress", False, [], ['Flint and Steel']], + ["A Terrible Fortress", False, [], ['Progressive Tools']], + ["A Terrible Fortress", False, [], ['Progressive Weapons']], + ["A Terrible Fortress", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["A Terrible Fortress", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', 'Progressive Weapons']], + ["A Terrible Fortress", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Progressive Weapons']], + ]) + + def test_42072(self): + self.run_location_tests([ + ["A Throwaway Joke", True, []], + ]) + + def test_42073(self): + self.run_location_tests([ + ["Minecraft", True, []], + ]) + + def test_42074(self): + self.run_location_tests([ + ["Sticky Situation", False, []], + ["Sticky Situation", False, [], ['Bottles']], + ["Sticky Situation", False, [], ['Ingot Crafting']], + ["Sticky Situation", True, ['Bottles', 'Ingot Crafting']], + ]) + + def test_42075(self): + self.run_location_tests([ + ["Ol' Betsy", False, []], + ["Ol' Betsy", False, [], ['Archery']], + ["Ol' Betsy", False, [], ['Ingot Crafting']], + ["Ol' Betsy", False, [], ['Progressive Tools']], + ["Ol' Betsy", True, ['Archery', 'Ingot Crafting', 'Progressive Tools']], + ]) + + def test_42076(self): + self.run_location_tests([ + ["Cover Me in Debris", False, []], + ["Cover Me in Debris", False, [], ['Ingot Crafting']], + ["Cover Me in Debris", False, [], ['Flint and Steel']], + ["Cover Me in Debris", False, ['Progressive Tools', 'Progressive Tools'], ['Progressive Tools']], + ["Cover Me in Debris", False, [], ['Progressive Weapons']], + ["Cover Me in Debris", False, ['Progressive Armor'], ['Progressive Armor']], + ["Cover Me in Debris", False, [], ['Brewing']], + ["Cover Me in Debris", False, [], ['Bottles']], + ["Cover Me in Debris", False, [], ['Bed']], + ["Cover Me in Debris", False, ['8 Netherite Scrap'], ['8 Netherite Scrap']], + ["Cover Me in Debris", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', 'Progressive Armor', + 'Brewing', 'Bottles', 'Bed', '8 Netherite Scrap', '8 Netherite Scrap']], + ]) + + def test_42077(self): + self.run_location_tests([ + ["The End?", False, []], + ["The End?", False, [], ['Ingot Crafting']], + ["The End?", False, [], ['Flint and Steel']], + ["The End?", False, [], ['Progressive Tools']], + ["The End?", False, [], ['Progressive Weapons']], + ["The End?", False, [], ['Progressive Armor', 'Shield']], + ["The End?", False, [], ['Brewing']], + ["The End?", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["The End?", False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ["The End?", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["The End?", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["The End?", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ["The End?", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ]) + + def test_42078(self): + self.run_location_tests([ + ["The Parrots and the Bats", True, []], + ]) + + def test_42079(self): + self.run_location_tests([ + ["A Complete Catalogue", False, []], + ["A Complete Catalogue", False, [], ['Progressive Weapons']], + ["A Complete Catalogue", False, [], ['Campfire', 'Ingot Crafting']], + ["A Complete Catalogue", True, ['Progressive Weapons', 'Campfire']], + ["A Complete Catalogue", True, ['Progressive Weapons', 'Ingot Crafting']], + ]) + + def test_42080(self): + self.run_location_tests([ + ["Getting Wood", True, []], + ]) + + def test_42081(self): + self.run_location_tests([ + ["Time to Mine!", True, []], + ]) + + def test_42082(self): + self.run_location_tests([ + ["Hot Topic", False, []], + ["Hot Topic", True, ['Ingot Crafting']], + ]) + + def test_42083(self): + self.run_location_tests([ + ["Bake Bread", True, []], + ]) + + def test_42084(self): + self.run_location_tests([ + ["The Lie", False, []], + ["The Lie", False, [], ['Ingot Crafting']], + ["The Lie", False, [], ['Bucket']], + ["The Lie", False, [], ['Progressive Tools']], + ["The Lie", True, ['Bucket', 'Ingot Crafting', 'Progressive Tools']], + ]) + + def test_42085(self): + self.run_location_tests([ + ["On a Rail", False, []], + ["On a Rail", False, [], ['Ingot Crafting']], + ["On a Rail", False, [], ['Progressive Tools']], + ["On a Rail", True, ['Ingot Crafting', 'Progressive Tools']], + ]) + + def test_42086(self): + self.run_location_tests([ + ["Time to Strike!", True, []], + ]) + + def test_42087(self): + self.run_location_tests([ + ["Cow Tipper", True, []], + ]) + + def test_42088(self): + self.run_location_tests([ + ["When Pigs Fly", False, []], + ["When Pigs Fly", False, [], ['Ingot Crafting']], + ["When Pigs Fly", False, [], ['Flint and Steel']], + ["When Pigs Fly", False, [], ['Progressive Tools']], + ["When Pigs Fly", False, [], ['Progressive Weapons']], + ["When Pigs Fly", False, [], ['Progressive Armor', 'Shield']], + ["When Pigs Fly", False, [], ['Fishing Rod']], + ["When Pigs Fly", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["When Pigs Fly", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', 'Progressive Weapons', 'Progressive Armor', 'Fishing Rod']], + ["When Pigs Fly", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Progressive Weapons', 'Progressive Armor', 'Fishing Rod']], + ["When Pigs Fly", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', 'Progressive Weapons', 'Shield', 'Fishing Rod']], + ["When Pigs Fly", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', 'Progressive Weapons', 'Shield', 'Fishing Rod']], + ]) + + def test_42089(self): + self.run_location_tests([ + ["Overkill", False, []], + ["Overkill", False, [], ['Ingot Crafting']], + ["Overkill", False, [], ['Flint and Steel']], + ["Overkill", False, [], ['Progressive Tools']], + ["Overkill", False, [], ['Progressive Weapons']], + ["Overkill", False, [], ['Progressive Armor', 'Shield']], + ["Overkill", False, [], ['Brewing']], + ["Overkill", False, [], ['Bottles']], + ["Overkill", False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ["Overkill", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', 'Brewing', 'Bottles']], + ["Overkill", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', 'Brewing', 'Bottles']], + ["Overkill", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Bucket', + 'Progressive Weapons', 'Shield', 'Brewing', 'Bottles']], + ["Overkill", True, ['Ingot Crafting', 'Progressive Tools', 'Flint and Steel', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', 'Brewing', 'Bottles']], + ]) + + def test_42090(self): + self.run_location_tests([ + ["Librarian", False, []], + ["Librarian", True, ['Enchanting']], + ]) + + def test_42091(self): + self.run_location_tests([ + ["Overpowered", False, []], + ["Overpowered", False, [], ['Ingot Crafting']], + ["Overpowered", False, [], ['Resource Blocks']], + ["Overpowered", False, ['Progressive Tools'], ['Flint and Steel', 'Progressive Tools', 'Progressive Tools']], + ["Overpowered", True, ['Resource Blocks', 'Ingot Crafting', 'Progressive Tools', 'Progressive Tools']], + ["Overpowered", True, ['Resource Blocks', 'Ingot Crafting', 'Progressive Tools', 'Bucket', 'Flint and Steel']], + ]) + diff --git a/test/minecraft/TestEntrances.py b/test/minecraft/TestEntrances.py new file mode 100644 index 00000000..65c5f49d --- /dev/null +++ b/test/minecraft/TestEntrances.py @@ -0,0 +1,92 @@ +from test.minecraft.TestMinecraft import TestMinecraft + +class TestEntrances(TestMinecraft): + + def testPortals(self): + self.run_entrance_tests([ + ['Nether Portal', False, []], + ['Nether Portal', False, [], ['Flint and Steel']], + ['Nether Portal', False, [], ['Ingot Crafting']], + ['Nether Portal', False, [], ['Progressive Tools']], + ['Nether Portal', False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ['Nether Portal', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Bucket']], + ['Nether Portal', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Progressive Tools', 'Progressive Tools']], + + ['End Portal', False, []], + ['End Portal', False, [], ['Brewing']], + ['End Portal', False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ['End Portal', False, [], ['Flint and Steel']], + ['End Portal', False, [], ['Ingot Crafting']], + ['End Portal', False, [], ['Progressive Tools']], + ['End Portal', False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ['End Portal', False, [], ['Progressive Weapons']], + ['End Portal', False, [], ['Progressive Armor', 'Shield']], + ['End Portal', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ['End Portal', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Bucket', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ['End Portal', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ['End Portal', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ]) + + def testStructures(self): + self.run_entrance_tests([ # Structures 1 and 2 should be logically equivalent + ['Overworld Structure 1', False, []], + ['Overworld Structure 1', False, [], ['Progressive Weapons']], + ['Overworld Structure 1', False, [], ['Ingot Crafting', 'Campfire']], + ['Overworld Structure 1', True, ['Progressive Weapons', 'Ingot Crafting']], + ['Overworld Structure 1', True, ['Progressive Weapons', 'Campfire']], + + ['Overworld Structure 2', False, []], + ['Overworld Structure 2', False, [], ['Progressive Weapons']], + ['Overworld Structure 2', False, [], ['Ingot Crafting', 'Campfire']], + ['Overworld Structure 2', True, ['Progressive Weapons', 'Ingot Crafting']], + ['Overworld Structure 2', True, ['Progressive Weapons', 'Campfire']], + + ['Nether Structure 1', False, []], + ['Nether Structure 1', False, [], ['Flint and Steel']], + ['Nether Structure 1', False, [], ['Ingot Crafting']], + ['Nether Structure 1', False, [], ['Progressive Tools']], + ['Nether Structure 1', False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ['Nether Structure 1', False, [], ['Progressive Weapons']], + ['Nether Structure 1', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Bucket', 'Progressive Weapons']], + ['Nether Structure 1', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Progressive Tools', 'Progressive Tools', 'Progressive Weapons']], + + ['Nether Structure 2', False, []], + ['Nether Structure 2', False, [], ['Flint and Steel']], + ['Nether Structure 2', False, [], ['Ingot Crafting']], + ['Nether Structure 2', False, [], ['Progressive Tools']], + ['Nether Structure 2', False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ['Nether Structure 2', False, [], ['Progressive Weapons']], + ['Nether Structure 2', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Bucket', 'Progressive Weapons']], + ['Nether Structure 2', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Progressive Tools', 'Progressive Tools', 'Progressive Weapons']], + + ['The End Structure', False, []], + ['The End Structure', False, [], ['Brewing']], + ['The End Structure', False, ['3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls'], ['3 Ender Pearls']], + ['The End Structure', False, [], ['Flint and Steel']], + ['The End Structure', False, [], ['Ingot Crafting']], + ['The End Structure', False, [], ['Progressive Tools']], + ['The End Structure', False, ['Progressive Tools', 'Progressive Tools'], ['Bucket', 'Progressive Tools']], + ['The End Structure', False, [], ['Progressive Weapons']], + ['The End Structure', False, [], ['Progressive Armor', 'Shield']], + ['The End Structure', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Bucket', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ['The End Structure', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Bucket', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ['The End Structure', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Progressive Armor', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + ['The End Structure', True, ['Flint and Steel', 'Ingot Crafting', 'Progressive Tools', 'Progressive Tools', 'Progressive Tools', + 'Progressive Weapons', 'Shield', + 'Brewing', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls', '3 Ender Pearls']], + + ]) \ No newline at end of file diff --git a/test/minecraft/TestMinecraft.py b/test/minecraft/TestMinecraft.py new file mode 100644 index 00000000..375de5f5 --- /dev/null +++ b/test/minecraft/TestMinecraft.py @@ -0,0 +1,57 @@ +from test.TestBase import TestBase +from BaseClasses import MultiWorld +from worlds.minecraft import minecraft_gen_item_pool +from worlds.minecraft.Regions import minecraft_create_regions, link_minecraft_structures +from worlds.minecraft.Rules import set_rules +from worlds.minecraft.Items import MinecraftItem, item_table +import Options + +# Converts the name of an item into an item object +def MCItemFactory(items, player: int): + ret = [] + singleton = False + if isinstance(items, str): + items = [items] + singleton = True + for item in items: + if item in item_table: + ret.append(MinecraftItem(item, item_table[item].progression, item_table[item].code, player)) + else: + raise Exception(f"Unknown item {item}") + + if singleton: + return ret[0] + return ret + +class TestMinecraft(TestBase): + + def setUp(self): + self.world = MultiWorld(1) + self.world.game[1] = "Minecraft" + exclusion_pools = ['hard', 'insane', 'postgame'] + for pool in exclusion_pools: + setattr(self.world, f"include_{pool}_advancements", [False, False]) + setattr(self.world, "advancement_goal", [0, Options.AdvancementGoal(value=0)]) + setattr(self.world, "shuffle_structures", [False, False]) + setattr(self.world, "combat_difficulty", [0, Options.CombatDifficulty(value=1)]) + minecraft_create_regions(self.world, 1) + link_minecraft_structures(self.world, 1) + minecraft_gen_item_pool(self.world, 1) + set_rules(self.world, 1) + + def _get_items(self, item_pool, all_except): + if all_except and len(all_except) > 0: + items = self.world.itempool[:] + items = [item for item in items if + item.name not in all_except and not ("Bottle" in item.name and "AnyBottle" in all_except)] + items.extend(MCItemFactory(item_pool[0], 1)) + else: + items = MCItemFactory(item_pool[0], 1) + return self.get_state(items) + + def _get_items_partial(self, item_pool, missing_item): + new_items = item_pool[0].copy() + new_items.remove(missing_item) + items = MCItemFactory(new_items, 1) + return self.get_state(items) + diff --git a/test/minecraft/__init__.py b/test/minecraft/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/worlds/__init__.py b/worlds/__init__.py index 38fcf0c9..67608fe4 100644 --- a/worlds/__init__.py +++ b/worlds/__init__.py @@ -8,23 +8,26 @@ __all__ = {"lookup_any_item_id_to_name", from .alttp.Items import lookup_id_to_name as alttp from .hk.Items import lookup_id_to_name as hk from .factorio import Technologies +from .minecraft.Items import lookup_id_to_name as mc -lookup_any_item_id_to_name = {**alttp, **hk, **Technologies.lookup_id_to_name} -assert len(alttp) + len(hk) + len(Technologies.lookup_id_to_name) == len(lookup_any_item_id_to_name) +lookup_any_item_id_to_name = {**alttp, **hk, **Technologies.lookup_id_to_name, **mc} +assert len(alttp) + len(hk) + len(Technologies.lookup_id_to_name) + len(mc) == len(lookup_any_item_id_to_name) lookup_any_item_name_to_id = {name: id for id, name in lookup_any_item_id_to_name.items()} from .alttp import Regions from .hk import Locations +from .minecraft import Locations as Advancements lookup_any_location_id_to_name = {**Regions.lookup_id_to_name, **Locations.lookup_id_to_name, - **Technologies.lookup_id_to_name} -assert len(Regions.lookup_id_to_name) + len(Locations.lookup_id_to_name) + len(Technologies.lookup_id_to_name) == \ + **Technologies.lookup_id_to_name, **Advancements.lookup_id_to_name} +assert len(Regions.lookup_id_to_name) + len(Locations.lookup_id_to_name) + \ + len(Technologies.lookup_id_to_name) + len(Advancements.lookup_id_to_name) == \ len(lookup_any_location_id_to_name) lookup_any_location_name_to_id = {name: id for id, name in lookup_any_location_id_to_name.items()} network_data_package = {"lookup_any_location_id_to_name": lookup_any_location_id_to_name, "lookup_any_item_id_to_name": lookup_any_item_id_to_name, - "version": 4} + "version": 5} @enum.unique diff --git a/worlds/alttp/Rom.py b/worlds/alttp/Rom.py index 85676555..5a426d6d 100644 --- a/worlds/alttp/Rom.py +++ b/worlds/alttp/Rom.py @@ -751,6 +751,13 @@ bonk_addresses = [0x4CF6C, 0x4CFBA, 0x4CFE0, 0x4CFFB, 0x4D018, 0x4D01B, 0x4D028, 0x4D3F8, 0x4D416, 0x4D420, 0x4D423, 0x4D42D, 0x4D449, 0x4D48C, 0x4D4D9, 0x4D4DC, 0x4D4E3, 0x4D504, 0x4D507, 0x4D55E, 0x4D56A] +def get_nonnative_item_sprite(game): + game_to_id = { + "Factorio": 0x09, # Hammer + "Hollow Knight": 0x21, # Bug Catching Net + "Minecraft": 0x13, # Shovel + } + return game_to_id.get(game, 0x6B) # default to Power Star def patch_rom(world, rom, player, team, enemized): local_random = world.rom_seeds[player] @@ -774,10 +781,7 @@ def patch_rom(world, rom, player, team, enemized): if location.item is not None: if location.item.game != "A Link to the Past": - if location.item.game == "Factorio": - itemid = 0x09 # Hammer Sprite - else: - itemid = 0x21 # Bug Catching Net + itemid = get_nonnative_item_sprite(location.item.game) # Keys in their native dungeon should use the orignal item code for keys elif location.parent_region.dungeon: if location.parent_region.dungeon.is_dungeon_item(location.item): @@ -1715,7 +1719,20 @@ def write_custom_shops(rom, world, player): if item is None: break if not item['item'] in item_table: # item not native to ALTTP - item_code = 0x09 # Hammer + # This is a terrible way to do this, please fix later + from worlds.hk.Items import lookup_id_to_name as hk_lookup + from worlds.factorio.Technologies import lookup_id_to_name as factorio_lookup + from worlds.minecraft.Items import lookup_id_to_name as mc_lookup + item_name = item['item'] + if item_name in hk_lookup.values(): + item_game = 'Hollow Knight' + elif item_name in factorio_lookup.values(): + item_game = 'Factorio' + elif item_name in mc_lookup.values(): + item_game = 'Minecraft' + else: + item_game = 'Generic' + item_code = get_nonnative_item_sprite(item_game) else: item_code = ItemFactory(item['item'], player).code if item['item'] == 'Single Arrow' and item['player'] == 0 and world.retro[player]: diff --git a/worlds/minecraft/Items.py b/worlds/minecraft/Items.py new file mode 100644 index 00000000..89de300e --- /dev/null +++ b/worlds/minecraft/Items.py @@ -0,0 +1,74 @@ +from BaseClasses import Region, Entrance, Location, MultiWorld, Item +import typing + +class ItemData(typing.NamedTuple): + code: int + progression: bool + +class MinecraftItem(Item): + game: str = "Minecraft" + def __init__(self, name: str, progression: bool, code: int, player: int): + super().__init__(name, progression, code if code else None, player) + +item_table = { + "Archery": ItemData(45000, True), + "Ingot Crafting": ItemData(45001, True), + "Resource Blocks": ItemData(45002, True), + "Brewing": ItemData(45003, True), + "Enchanting": ItemData(45004, True), + "Bucket": ItemData(45005, True), + "Flint and Steel": ItemData(45006, True), + "Bed": ItemData(45007, True), + "Bottles": ItemData(45008, True), + "Shield": ItemData(45009, True), + "Fishing Rod": ItemData(45010, True), + "Campfire": ItemData(45011, True), + "Progressive Weapons": ItemData(45012, True), + "Progressive Tools": ItemData(45013, True), + "Progressive Armor": ItemData(45014, True), + "8 Netherite Scrap": ItemData(45015, True), + "8 Emeralds": ItemData(45016, False), + "4 Emeralds": ItemData(45017, False), + "Channeling Book": ItemData(45018, True), + "Silk Touch Book": ItemData(45019, True), + "Sharpness III Book": ItemData(45020, False), + "Piercing IV Book": ItemData(45021, True), + "Looting III Book": ItemData(45022, False), + "Infinity Book": ItemData(45023, False), + "4 Diamond Ore": ItemData(45024, False), + "16 Iron Ore": ItemData(45025, False), + "500 XP": ItemData(45026, False), + "100 XP": ItemData(45027, False), + "50 XP": ItemData(45028, False), + "3 Ender Pearls": ItemData(45029, True), + "4 Lapis Lazuli": ItemData(45030, False), + "16 Porkchops": ItemData(45031, False), + "8 Gold Ore": ItemData(45032, False), + "Rotten Flesh": ItemData(45033, False), + "Single Arrow": ItemData(45034, False), + + "Victory": ItemData(0, True) +} + +# If not listed here then has frequency 1 +item_frequencies = { + "Progressive Weapons": 3, + "Progressive Tools": 3, + "Progressive Armor": 2, + "8 Netherite Scrap": 2, + "8 Emeralds": 0, + "4 Emeralds": 8, + "4 Diamond Ore": 4, + "16 Iron Ore": 4, + "500 XP": 4, # 2 after exclusions + "100 XP": 10, # 4 after exclusions + "50 XP": 12, # 4 after exclusions + "3 Ender Pearls": 4, + "4 Lapis Lazuli": 2, + "16 Porkchops": 8, + "8 Gold Ore": 4, + "Rotten Flesh": 4, + "Single Arrow": 0 +} + +lookup_id_to_name: typing.Dict[int, str] = {data.code: item_name for item_name, data in item_table.items() if data.code} diff --git a/worlds/minecraft/Locations.py b/worlds/minecraft/Locations.py new file mode 100644 index 00000000..8d24338d --- /dev/null +++ b/worlds/minecraft/Locations.py @@ -0,0 +1,142 @@ +from BaseClasses import Region, Entrance, Location, MultiWorld, Item +import typing + +class AdvData(typing.NamedTuple): + id: int + region: str + +class MinecraftAdvancement(Location): + game: str = "Minecraft" + def __init__(self, player: int, name: str, address: int, parent): + super().__init__(player, name, address if address else None, parent) + self.event = True if address == 0 else False + +advancement_table = { + "Who is Cutting Onions?": AdvData(42000, 'Overworld'), + "Oh Shiny": AdvData(42001, 'Overworld'), + "Suit Up": AdvData(42002, 'Overworld'), + "Very Very Frightening": AdvData(42003, 'Village'), + "Hot Stuff": AdvData(42004, 'Overworld'), + "Free the End": AdvData(42005, 'The End'), + "A Furious Cocktail": AdvData(42006, 'Nether Fortress'), + "Best Friends Forever": AdvData(42007, 'Overworld'), + "Bring Home the Beacon": AdvData(42008, 'Nether Fortress'), + "Not Today, Thank You": AdvData(42009, 'Overworld'), + "Isn't It Iron Pick": AdvData(42010, 'Overworld'), + "Local Brewery": AdvData(42011, 'Nether Fortress'), + "The Next Generation": AdvData(42012, 'The End'), + "Fishy Business": AdvData(42013, 'Overworld'), + "Hot Tourist Destinations": AdvData(42014, 'The Nether'), + "This Boat Has Legs": AdvData(42015, 'The Nether'), + "Sniper Duel": AdvData(42016, 'Overworld'), + "Nether": AdvData(42017, 'The Nether'), + "Great View From Up Here": AdvData(42018, 'End City'), + "How Did We Get Here?": AdvData(42019, 'Nether Fortress'), + "Bullseye": AdvData(42020, 'Overworld'), + "Spooky Scary Skeleton": AdvData(42021, 'Nether Fortress'), + "Two by Two": AdvData(42022, 'The Nether'), + "Stone Age": AdvData(42023, 'Overworld'), + "Two Birds, One Arrow": AdvData(42024, 'Overworld'), + "We Need to Go Deeper": AdvData(42025, 'The Nether'), + "Who's the Pillager Now?": AdvData(42026, 'Pillager Outpost'), + "Getting an Upgrade": AdvData(42027, 'Overworld'), + "Tactical Fishing": AdvData(42028, 'Overworld'), + "Zombie Doctor": AdvData(42029, 'Overworld'), + "The City at the End of the Game": AdvData(42030, 'End City'), + "Ice Bucket Challenge": AdvData(42031, 'Overworld'), + "Remote Getaway": AdvData(42032, 'The End'), + "Into Fire": AdvData(42033, 'Nether Fortress'), + "War Pigs": AdvData(42034, 'Bastion Remnant'), + "Take Aim": AdvData(42035, 'Overworld'), + "Total Beelocation": AdvData(42036, 'Overworld'), + "Arbalistic": AdvData(42037, 'Overworld'), + "The End... Again...": AdvData(42038, 'The End'), + "Acquire Hardware": AdvData(42039, 'Overworld'), + "Not Quite \"Nine\" Lives": AdvData(42040, 'The Nether'), + "Cover Me With Diamonds": AdvData(42041, 'Overworld'), + "Sky's the Limit": AdvData(42042, 'End City'), + "Hired Help": AdvData(42043, 'Overworld'), + "Return to Sender": AdvData(42044, 'The Nether'), + "Sweet Dreams": AdvData(42045, 'Overworld'), + "You Need a Mint": AdvData(42046, 'The End'), + "Adventure": AdvData(42047, 'Overworld'), + "Monsters Hunted": AdvData(42048, 'Overworld'), + "Enchanter": AdvData(42049, 'Overworld'), + "Voluntary Exile": AdvData(42050, 'Pillager Outpost'), + "Eye Spy": AdvData(42051, 'Overworld'), + "The End": AdvData(42052, 'The End'), + "Serious Dedication": AdvData(42053, 'The Nether'), + "Postmortal": AdvData(42054, 'Village'), + "Monster Hunter": AdvData(42055, 'Overworld'), + "Adventuring Time": AdvData(42056, 'Overworld'), + "A Seedy Place": AdvData(42057, 'Overworld'), + "Those Were the Days": AdvData(42058, 'Bastion Remnant'), + "Hero of the Village": AdvData(42059, 'Village'), + "Hidden in the Depths": AdvData(42060, 'The Nether'), + "Beaconator": AdvData(42061, 'Nether Fortress'), + "Withering Heights": AdvData(42062, 'Nether Fortress'), + "A Balanced Diet": AdvData(42063, 'Village'), + "Subspace Bubble": AdvData(42064, 'The Nether'), + "Husbandry": AdvData(42065, 'Overworld'), + "Country Lode, Take Me Home": AdvData(42066, 'The Nether'), + "Bee Our Guest": AdvData(42067, 'Overworld'), + "What a Deal!": AdvData(42068, 'Village'), + "Uneasy Alliance": AdvData(42069, 'The Nether'), + "Diamonds!": AdvData(42070, 'Overworld'), + "A Terrible Fortress": AdvData(42071, 'Nether Fortress'), + "A Throwaway Joke": AdvData(42072, 'Overworld'), + "Minecraft": AdvData(42073, 'Overworld'), + "Sticky Situation": AdvData(42074, 'Overworld'), + "Ol' Betsy": AdvData(42075, 'Overworld'), + "Cover Me in Debris": AdvData(42076, 'The Nether'), + "The End?": AdvData(42077, 'The End'), + "The Parrots and the Bats": AdvData(42078, 'Overworld'), + "A Complete Catalogue": AdvData(42079, 'Village'), + "Getting Wood": AdvData(42080, 'Overworld'), + "Time to Mine!": AdvData(42081, 'Overworld'), + "Hot Topic": AdvData(42082, 'Overworld'), + "Bake Bread": AdvData(42083, 'Overworld'), + "The Lie": AdvData(42084, 'Overworld'), + "On a Rail": AdvData(42085, 'Overworld'), + "Time to Strike!": AdvData(42086, 'Overworld'), + "Cow Tipper": AdvData(42087, 'Overworld'), + "When Pigs Fly": AdvData(42088, 'Overworld'), + "Overkill": AdvData(42089, 'Nether Fortress'), + "Librarian": AdvData(42090, 'Overworld'), + "Overpowered": AdvData(42091, 'Overworld'), + + "Ender Dragon": AdvData(0, 'The End') +} + +exclusion_table = { + "hard": { + "Very Very Frightening": "50 XP", + "Two by Two": "100 XP", + "Two Birds, One Arrow": "50 XP", + "Arbalistic": "100 XP", + "Beaconator": "50 XP", + "A Balanced Diet": "100 XP", + "Uneasy Alliance": "100 XP", + "Cover Me in Debris": "100 XP", + "A Complete Catalogue": "50 XP", + "Overpowered": "50 XP" + }, + "insane": { + "How Did We Get Here?": "500 XP", + "Adventuring Time": "500 XP" + }, + "postgame": { + "The Next Generation": "50 XP", + "The End... Again...": "50 XP", + "You Need a Mint": "50 XP", + "Monsters Hunted": "100 XP" + } +} + + +events_table = { + "Ender Dragon": "Victory" +} + + +lookup_id_to_name: typing.Dict[int, str] = {loc_data.id: loc_name for loc_name, loc_data in advancement_table.items() if loc_data.id} diff --git a/worlds/minecraft/Regions.py b/worlds/minecraft/Regions.py new file mode 100644 index 00000000..e3cc53b0 --- /dev/null +++ b/worlds/minecraft/Regions.py @@ -0,0 +1,101 @@ +from .Locations import MinecraftAdvancement, advancement_table + +from BaseClasses import Region, Entrance, Location, MultiWorld, Item + +def minecraft_create_regions(world: MultiWorld, player: int): + + def MCRegion(region_name: str, exits=[]): + ret = Region(region_name, None, region_name, player) + ret.world = world + ret.locations = [ MinecraftAdvancement(player, loc_name, loc_data.id, ret) + for loc_name, loc_data in advancement_table.items() + if loc_data.region == region_name ] + for exit in exits: + ret.exits.append(Entrance(player, exit, ret)) + return ret + + world.regions += [MCRegion(*r) for r in mc_regions] + + for (exit, region) in mandatory_connections: + world.get_entrance(exit, player).connect(world.get_region(region, player)) + +def link_minecraft_structures(world: MultiWorld, player: int): + + # Get all unpaired exits and all regions without entrances (except the Menu) + # This function is destructive on these lists. + exits = [exit.name for r in world.regions if r.player == player for exit in r.exits if exit.connected_region == None] + structs = [r.name for r in world.regions if r.player == player and r.entrances == [] and r.name != 'Menu'] + try: + assert len(exits) == len(structs) + except AssertionError as e: # this should never happen + raise Exception(f"Could not obtain equal numbers of Minecraft exits and structures for player {player}") from e + num_regions = len(exits) + pairs = {} + + def check_valid_connection(exit, struct): + if (exit in exits) and (struct in structs) and (exit not in pairs): + return True + return False + + def set_pair(exit, struct): + pairs[exit] = struct + exits.remove(exit) + structs.remove(struct) + + # Plando stuff. Remove any utilized exits/structs from the lists. + # Raise error if trying to put Nether Fortress in the End. + + if world.shuffle_structures[player]: + # Can't put Nether Fortress in the End + if 'The End Structure' in exits and 'Nether Fortress' in structs: + try: + end_struct = world.random.choice([s for s in structs if s != 'Nether Fortress']) + set_pair('The End Structure', end_struct) + except IndexError as e: + raise Exception(f"Plando forced Nether Fortress in the End for player {player}") from e + world.random.shuffle(structs) + for exit, struct in zip(exits[:], structs[:]): + set_pair(exit, struct) + else: # write remaining default connections + for (exit, struct) in default_connections: + if exit in exits: + set_pair(exit, struct) + + # Make sure we actually paired everything; might fail if plando + try: + assert len(exits) == len(structs) == 0 + except AssertionError as e: + raise Exception(f"Failed to connect all Minecraft structures for player {player}; check plando settings in yaml") from e + + for exit, struct in pairs.items(): + world.get_entrance(exit, player).connect(world.get_region(struct, player)) + if world.shuffle_structures[player]: + world.spoiler.set_entrance(exit, struct, 'entrance', player) + +# (Region name, list of exits) +mc_regions = [ + ('Menu', ['New World']), + ('Overworld', ['Nether Portal', 'End Portal', 'Overworld Structure 1', 'Overworld Structure 2']), + ('The Nether', ['Nether Structure 1', 'Nether Structure 2']), + ('The End', ['The End Structure']), + ('Village', []), + ('Pillager Outpost', []), + ('Nether Fortress', []), + ('Bastion Remnant', []), + ('End City', []) +] + +# (Entrance, region pointed to) +mandatory_connections = [ + ('New World', 'Overworld'), + ('Nether Portal', 'The Nether'), + ('End Portal', 'The End') +] + +default_connections = { + ('Overworld Structure 1', 'Village'), + ('Overworld Structure 2', 'Pillager Outpost'), + ('Nether Structure 1', 'Nether Fortress'), + ('Nether Structure 2', 'Bastion Remnant'), + ('The End Structure', 'End City') +} diff --git a/worlds/minecraft/Rules.py b/worlds/minecraft/Rules.py new file mode 100644 index 00000000..ba9bbc04 --- /dev/null +++ b/worlds/minecraft/Rules.py @@ -0,0 +1,143 @@ +from ..generic.Rules import set_rule +from .Locations import exclusion_table, events_table +from BaseClasses import Region, Entrance, Location, MultiWorld, Item +from Options import AdvancementGoal + +def set_rules(world: MultiWorld, player: int): + + def reachable_locations(state): + postgame_advancements = set(exclusion_table['postgame'].keys()) + postgame_advancements.add('Free the End') + for event in events_table.keys(): + postgame_advancements.add(event) + return [location for location in world.get_locations() if + (player is None or location.player == player) and + (location.name not in postgame_advancements) and + location.can_reach(state)] + + # 92 total advancements, 16 are typically excluded, 1 is Free the End. Goal is to complete X advancements and then Free the End. + goal_map = { + 'few': 30, + 'normal': 50, + 'many': 70 + } + goal = goal_map[getattr(world, 'advancement_goal')[player].get_option_name()] + can_complete = lambda state: len(reachable_locations(state)) >= goal and state.can_reach('The End', 'Region', player) and state.can_kill_ender_dragon(player) + + if world.logic[player] != 'nologic': + world.completion_condition[player] = lambda state: state.has('Victory', player) + + set_rule(world.get_entrance("Nether Portal", player), lambda state: state.has('Flint and Steel', player) and + (state.has('Bucket', player) or state.has('Progressive Tools', player, 3)) and + state.has_iron_ingots(player)) + set_rule(world.get_entrance("End Portal", player), lambda state: state.enter_stronghold(player) and state.has('3 Ender Pearls', player, 4)) + set_rule(world.get_entrance("Overworld Structure 1", player), lambda state: state.can_adventure(player)) + set_rule(world.get_entrance("Overworld Structure 2", player), lambda state: state.can_adventure(player)) + set_rule(world.get_entrance("Nether Structure 1", player), lambda state: state.can_adventure(player)) + set_rule(world.get_entrance("Nether Structure 2", player), lambda state: state.can_adventure(player)) + set_rule(world.get_entrance("The End Structure", player), lambda state: state.can_adventure(player)) + + set_rule(world.get_location("Ender Dragon", player), lambda state: can_complete(state)) + + set_rule(world.get_location("Who is Cutting Onions?", player), lambda state: state.can_piglin_trade(player)) + set_rule(world.get_location("Oh Shiny", player), lambda state: state.can_piglin_trade(player)) + set_rule(world.get_location("Suit Up", player), lambda state: state.has("Progressive Armor", player) and state.has_iron_ingots(player)) + set_rule(world.get_location("Very Very Frightening", player), lambda state: state.has("Channeling Book", player) and state.can_use_anvil(player) and state.can_enchant(player)) + set_rule(world.get_location("Hot Stuff", player), lambda state: state.has("Bucket", player) and state.has_iron_ingots(player)) + set_rule(world.get_location("Free the End", player), lambda state: can_complete(state)) + set_rule(world.get_location("A Furious Cocktail", player), lambda state: state.can_brew_potions(player) and state.has("Fishing Rod", player) and state.can_reach('The Nether', 'Region', player)) + set_rule(world.get_location("Best Friends Forever", player), lambda state: True) + set_rule(world.get_location("Bring Home the Beacon", player), lambda state: state.can_kill_wither(player) and state.has_diamond_pickaxe(player) and + state.has("Ingot Crafting", player) and state.has("Resource Blocks", player)) + set_rule(world.get_location("Not Today, Thank You", player), lambda state: state.has("Shield", player) and state.has_iron_ingots(player)) + set_rule(world.get_location("Isn't It Iron Pick", player), lambda state: state.has("Progressive Tools", player, 2) and state.has_iron_ingots(player)) + set_rule(world.get_location("Local Brewery", player), lambda state: state.can_brew_potions(player)) + set_rule(world.get_location("The Next Generation", player), lambda state: can_complete(state)) + set_rule(world.get_location("Fishy Business", player), lambda state: state.has("Fishing Rod", player)) + set_rule(world.get_location("Hot Tourist Destinations", player), lambda state: state.fortress_loot(player) and state.has("Fishing Rod", player)) + set_rule(world.get_location("This Boat Has Legs", player), lambda state: state.fortress_loot(player) and state.has("Fishing Rod", player)) + set_rule(world.get_location("Sniper Duel", player), lambda state: state.has("Archery", player)) + set_rule(world.get_location("Nether", player), lambda state: True) + set_rule(world.get_location("Great View From Up Here", player), lambda state: state.basic_combat(player)) + set_rule(world.get_location("How Did We Get Here?", player), lambda state: state.can_brew_potions(player) and state.has_gold_ingots(player) and # most effects; Absorption + state.can_reach('End City', 'Region', player) and state.can_reach('The Nether', 'Region', player) and # Levitation; potion ingredients + state.has("Fishing Rod", player) and state.has("Archery", player) and # Pufferfish, Nautilus Shells; spectral arrows + state.can_reach("Bring Home the Beacon", "Location", player) and # Haste + state.can_reach("Hero of the Village", "Location", player)) # Bad Omen, Hero of the Village + set_rule(world.get_location("Bullseye", player), lambda state: state.has("Archery", player) and state.has("Progressive Tools", player, 2) and state.has_iron_ingots(player)) + set_rule(world.get_location("Spooky Scary Skeleton", player), lambda state: state.basic_combat(player)) + set_rule(world.get_location("Two by Two", player), lambda state: state.has_iron_ingots(player) and state.can_adventure(player)) # shears > seagrass > turtles; nether > striders; gold carrots > horses skips ingots + set_rule(world.get_location("Stone Age", player), lambda state: True) + set_rule(world.get_location("Two Birds, One Arrow", player), lambda state: state.craft_crossbow(player) and state.can_enchant(player)) + set_rule(world.get_location("We Need to Go Deeper", player), lambda state: True) + set_rule(world.get_location("Who's the Pillager Now?", player), lambda state: state.craft_crossbow(player)) + set_rule(world.get_location("Getting an Upgrade", player), lambda state: state.has("Progressive Tools", player)) + set_rule(world.get_location("Tactical Fishing", player), lambda state: state.has("Bucket", player) and state.has_iron_ingots(player)) + set_rule(world.get_location("Zombie Doctor", player), lambda state: state.can_brew_potions(player) and state.has_gold_ingots(player)) + set_rule(world.get_location("The City at the End of the Game", player), lambda state: True) + set_rule(world.get_location("Ice Bucket Challenge", player), lambda state: state.has_diamond_pickaxe(player)) + set_rule(world.get_location("Remote Getaway", player), lambda state: True) + set_rule(world.get_location("Into Fire", player), lambda state: state.basic_combat(player)) + set_rule(world.get_location("War Pigs", player), lambda state: state.basic_combat(player)) + set_rule(world.get_location("Take Aim", player), lambda state: state.has("Archery", player)) + set_rule(world.get_location("Total Beelocation", player), lambda state: state.has("Silk Touch Book", player) and state.can_use_anvil(player) and state.can_enchant(player)) + set_rule(world.get_location("Arbalistic", player), lambda state: state.craft_crossbow(player) and state.has("Piercing IV Book", player) and + state.can_use_anvil(player) and state.can_enchant(player)) + set_rule(world.get_location("The End... Again...", player), lambda state: can_complete(state) and state.has("Ingot Crafting", player) and state.can_reach('The Nether', 'Region', player)) # furnace for glass, nether for ghast tears + set_rule(world.get_location("Acquire Hardware", player), lambda state: state.has_iron_ingots(player)) + set_rule(world.get_location("Not Quite \"Nine\" Lives", player), lambda state: state.can_piglin_trade(player) and state.has("Resource Blocks", player)) + set_rule(world.get_location("Cover Me With Diamonds", player), lambda state: state.has("Progressive Armor", player, 2) and state.can_reach("Diamonds!", "Location", player)) + set_rule(world.get_location("Sky's the Limit", player), lambda state: state.basic_combat(player)) + set_rule(world.get_location("Hired Help", player), lambda state: state.has("Resource Blocks", player) and state.has_iron_ingots(player)) + set_rule(world.get_location("Return to Sender", player), lambda state: True) + set_rule(world.get_location("Sweet Dreams", player), lambda state: state.has("Bed", player) or state.can_reach('Village', 'Region', player)) + set_rule(world.get_location("You Need a Mint", player), lambda state: can_complete(state) and state.has_bottle_mc(player)) + set_rule(world.get_location("Adventure", player), lambda state: True) + set_rule(world.get_location("Monsters Hunted", player), lambda state: can_complete(state) and state.can_kill_wither(player) and state.has("Fishing Rod", player)) # pufferfish for Water Breathing + set_rule(world.get_location("Enchanter", player), lambda state: state.can_enchant(player)) + set_rule(world.get_location("Voluntary Exile", player), lambda state: state.basic_combat(player)) + set_rule(world.get_location("Eye Spy", player), lambda state: state.enter_stronghold(player)) + set_rule(world.get_location("The End", player), lambda state: True) + set_rule(world.get_location("Serious Dedication", player), lambda state: state.can_reach("Hidden in the Depths", "Location", player) and state.has_gold_ingots(player)) + set_rule(world.get_location("Postmortal", player), lambda state: state.complete_raid(player)) + set_rule(world.get_location("Monster Hunter", player), lambda state: True) + set_rule(world.get_location("Adventuring Time", player), lambda state: state.can_adventure(player)) + set_rule(world.get_location("A Seedy Place", player), lambda state: True) + set_rule(world.get_location("Those Were the Days", player), lambda state: True) + set_rule(world.get_location("Hero of the Village", player), lambda state: state.complete_raid(player)) + set_rule(world.get_location("Hidden in the Depths", player), lambda state: state.can_brew_potions(player) and state.has("Bed", player) and state.has_diamond_pickaxe(player)) # bed mining :) + set_rule(world.get_location("Beaconator", player), lambda state: state.can_kill_wither(player) and state.has_diamond_pickaxe(player) and + state.has("Ingot Crafting", player) and state.has("Resource Blocks", player)) + set_rule(world.get_location("Withering Heights", player), lambda state: state.can_kill_wither(player)) + set_rule(world.get_location("A Balanced Diet", player), lambda state: state.has_bottle_mc(player) and state.has_gold_ingots(player) and # honey bottle; gapple + state.has("Resource Blocks", player) and state.can_reach('The End', 'Region', player)) # notch apple, chorus fruit + set_rule(world.get_location("Subspace Bubble", player), lambda state: state.has_diamond_pickaxe(player)) + set_rule(world.get_location("Husbandry", player), lambda state: True) + set_rule(world.get_location("Country Lode, Take Me Home", player), lambda state: state.can_reach("Hidden in the Depths", "Location", player) and state.has_gold_ingots(player)) + set_rule(world.get_location("Bee Our Guest", player), lambda state: state.has("Campfire", player) and state.has_bottle_mc(player)) + set_rule(world.get_location("What a Deal!", player), lambda state: True) + set_rule(world.get_location("Uneasy Alliance", player), lambda state: state.has_diamond_pickaxe(player)) + set_rule(world.get_location("Diamonds!", player), lambda state: state.has("Progressive Tools", player, 2) and state.has_iron_ingots(player)) + set_rule(world.get_location("A Terrible Fortress", player), lambda state: True) # since you don't have to fight anything + set_rule(world.get_location("A Throwaway Joke", player), lambda state: True) # kill drowned + set_rule(world.get_location("Minecraft", player), lambda state: True) + set_rule(world.get_location("Sticky Situation", player), lambda state: state.has_bottle_mc(player)) + set_rule(world.get_location("Ol' Betsy", player), lambda state: state.craft_crossbow(player)) + set_rule(world.get_location("Cover Me in Debris", player), lambda state: state.has("Progressive Armor", player, 2) and + state.has("8 Netherite Scrap", player, 2) and state.has("Ingot Crafting", player) and + state.can_reach("Diamonds!", "Location", player) and state.can_reach("Hidden in the Depths", "Location", player)) + set_rule(world.get_location("The End?", player), lambda state: True) + set_rule(world.get_location("The Parrots and the Bats", player), lambda state: True) + set_rule(world.get_location("A Complete Catalogue", player), lambda state: True) # kill fish for raw + set_rule(world.get_location("Getting Wood", player), lambda state: True) + set_rule(world.get_location("Time to Mine!", player), lambda state: True) + set_rule(world.get_location("Hot Topic", player), lambda state: state.has("Ingot Crafting", player)) + set_rule(world.get_location("Bake Bread", player), lambda state: True) + set_rule(world.get_location("The Lie", player), lambda state: state.has_iron_ingots(player) and state.has("Bucket", player)) + set_rule(world.get_location("On a Rail", player), lambda state: state.has_iron_ingots(player)) + set_rule(world.get_location("Time to Strike!", player), lambda state: True) + set_rule(world.get_location("Cow Tipper", player), lambda state: True) + set_rule(world.get_location("When Pigs Fly", player), lambda state: state.fortress_loot(player) and state.has("Fishing Rod", player) and state.can_adventure(player)) # saddles in fortress chests + set_rule(world.get_location("Overkill", player), lambda state: state.can_brew_potions(player) and state.has("Progressive Weapons", player)) # strength 1, stone axe crit + set_rule(world.get_location("Librarian", player), lambda state: state.has("Enchanting", player)) + set_rule(world.get_location("Overpowered", player), lambda state: state.has("Resource Blocks", player) and state.has_gold_ingots(player)) diff --git a/worlds/minecraft/__init__.py b/worlds/minecraft/__init__.py index e69de29b..02bcba60 100644 --- a/worlds/minecraft/__init__.py +++ b/worlds/minecraft/__init__.py @@ -0,0 +1,68 @@ +from random import Random +from .Items import MinecraftItem, item_table, item_frequencies +from .Locations import exclusion_table, events_table +from .Regions import link_minecraft_structures +from .Rules import set_rules + +from BaseClasses import Region, Entrance, Location, MultiWorld, Item +from Options import minecraft_options + +client_version = (0, 3) + +def generate_mc_data(world: MultiWorld, player: int, seedname: str): + import base64, json + from Utils import output_path + + exits = ["Overworld Structure 1", "Overworld Structure 2", "Nether Structure 1", "Nether Structure 2", "The End Structure"] + data = { + 'world_seed': Random(world.rom_seeds[player]).getrandbits(32), # consistent and doesn't interfere with other generation + 'seed_name': seedname, + 'player_name': world.get_player_names(player), + 'client_version': client_version, + 'structures': {exit: world.get_entrance(exit, player).connected_region.name for exit in exits} + } + + filename = f"AP_{seedname}_P{player}_{world.get_player_names(player)}.apmc" + with open(output_path(filename), 'wb') as f: + f.write(base64.b64encode(bytes(json.dumps(data), 'utf-8'))) + +def fill_minecraft_slot_data(world: MultiWorld, player: int): + slot_data = {} + for option_name in minecraft_options: + option = getattr(world, option_name)[player] + slot_data[option_name] = int(option.value) + slot_data['client_version'] = client_version + return slot_data + +# Generates the item pool given the table and frequencies in Items.py. +def minecraft_gen_item_pool(world: MultiWorld, player: int): + + pool = [] + for item_name, item_data in item_table.items(): + for count in range(item_frequencies.get(item_name, 1)): + pool.append(MinecraftItem(item_name, item_data.progression, item_data.code, player)) + + prefill_pool = {} + prefill_pool.update(events_table) + exclusion_pools = ['hard', 'insane', 'postgame'] + for key in exclusion_pools: + if not getattr(world, f"include_{key}_advancements")[player]: + prefill_pool.update(exclusion_table[key]) + + for loc_name, item_name in prefill_pool.items(): + item_data = item_table[item_name] + location = world.get_location(loc_name, player) + item = MinecraftItem(item_name, item_data.progression, item_data.code, player) + world.push_item(location, item, collect=False) + pool.remove(item) + location.event = item_data.progression + location.locked = True + + world.itempool += pool + +# Generate Minecraft world. +def gen_minecraft(world: MultiWorld, player: int): + link_minecraft_structures(world, player) + minecraft_gen_item_pool(world, player) + set_rules(world, player) +