Esempio n. 1
0
def place_first_progression_item(world: MultiWorld, player: int,
                                 excluded_items: Set[str],
                                 locked_locations: List[str]):
    for item in world.precollected_items[player]:
        if item.name in starter_progression_items:
            return

    local_starter_progression_items = tuple(
        item for item in starter_progression_items
        if item not in world.non_local_items[player].value)
    non_excluded_starter_progression_locations = tuple(
        location for location in starter_progression_locations
        if location not in world.exclude_locations[player].value)

    if not local_starter_progression_items or not non_excluded_starter_progression_locations:
        return

    progression_item = world.random.choice(local_starter_progression_items)
    location = world.random.choice(non_excluded_starter_progression_locations)

    excluded_items.add(progression_item)
    locked_locations.append(location)

    item = create_item_with_correct_settings(world, player, progression_item)

    world.get_location(location, player).place_locked_item(item)
Esempio n. 2
0
def set_mission_progress_rules(world: MultiWorld, player: int):
    for (k1, v1), (k2, v2), (k3, v3), (k4, v4), (k5, v5) in \
            zip(sorted(first_mission_location_table.items()),
                sorted(second_mission_location_table.items()),
                sorted(third_mission_location_table.items()),
                sorted(fourth_mission_location_table.items()),
                sorted(fifth_mission_location_table.items())):

        if world.include_missions[player].value >= 2:
            set_rule(
                world.get_location(k2, player),
                lambda state, k1=k1: state.can_reach(k1, "Location", player))

        if world.include_missions[player].value >= 3:
            set_rule(
                world.get_location(k3, player),
                lambda state, k2=k2: state.can_reach(k2, "Location", player))

        if world.include_missions[player].value >= 4:
            set_rule(
                world.get_location(k4, player),
                lambda state, k3=k3: state.can_reach(k3, "Location", player))

        if world.include_missions[player].value >= 5:
            set_rule(
                world.get_location(k5, player),
                lambda state, k4=k4: state.can_reach(k4, "Location", player))
Esempio n. 3
0
def set_rules(world: MultiWorld, player: int):
    for i in range(1, 16):
        set_rule(
            world.get_location(
                f"IDLE for at least {int(i / 2)} minutes {30 if (i % 2) > 0 else 0} seconds",
                player),
            lambda state: state._archipidle_location_is_accessible(player, 0))

    for i in range(16, 31):
        set_rule(
            world.get_location(
                f"IDLE for at least {int(i / 2)} minutes {30 if (i % 2) > 0 else 0} seconds",
                player),
            lambda state: state._archipidle_location_is_accessible(player, 4))

    for i in range(31, 51):
        set_rule(
            world.get_location(
                f"IDLE for at least {int(i / 2)} minutes {30 if (i % 2) > 0 else 0} seconds",
                player),
            lambda state: state._archipidle_location_is_accessible(player, 10))

    for i in range(51, 101):
        set_rule(
            world.get_location(
                f"IDLE for at least {int(i / 2)} minutes {30 if (i % 2) > 0 else 0} seconds",
                player),
            lambda state: state._archipidle_location_is_accessible(player, 20))
Esempio n. 4
0
def assign_starter_item(world: MultiWorld, player: int, excluded_items: Set[str], locked_locations: List[str],
                        location: str, item_list: Tuple[str, ...]):

    item_name = world.random.choice(item_list)

    excluded_items.add(item_name)

    item = create_item_with_correct_settings(world, player, item_name)

    world.get_location(location, player).place_locked_item(item)

    locked_locations.append(location)
Esempio n. 5
0
class TestInvertedOWG(TestBase):
    def setUp(self):
        self.world = MultiWorld(1)
        args = Namespace()
        for name, option in AutoWorld.AutoWorldRegister.world_types[
                "A Link to the Past"].options.items():
            setattr(args, name, {1: option.from_any(option.default)})
        self.world.set_options(args)
        self.world.set_default_common_options()
        self.world.logic[1] = "owglitches"
        self.world.mode[1] = "inverted"
        self.world.difficulty_requirements[1] = difficulties['normal']
        create_inverted_regions(self.world, 1)
        create_dungeons(self.world, 1)
        create_shops(self.world, 1)
        link_inverted_entrances(self.world, 1)
        self.world.worlds[1].create_items()
        self.world.required_medallions[1] = ['Ether', 'Quake']
        self.world.itempool.extend(get_dungeon_item_pool(self.world))
        self.world.itempool.extend(
            ItemFactory([
                'Green Pendant', 'Red Pendant', 'Blue Pendant',
                'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2',
                'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'
            ], 1))
        self.world.get_location('Agahnim 1', 1).item = None
        self.world.get_location('Agahnim 2', 1).item = None
        self.world.precollected_items[1].clear()
        self.world.itempool.append(ItemFactory('Pegasus Boots', 1))
        mark_light_world_regions(self.world, 1)
        self.world.worlds[1].set_rules()
Esempio n. 6
0
class TestInvertedOWG(TestBase):
    def setUp(self):
        self.world = MultiWorld(1)
        self.world.logic[1] = "owglitches"
        self.world.mode[1] = "inverted"
        self.world.difficulty_requirements[1] = difficulties['normal']
        create_inverted_regions(self.world, 1)
        create_dungeons(self.world, 1)
        create_shops(self.world, 1)
        link_inverted_entrances(self.world, 1)
        generate_itempool(self.world, 1)
        self.world.required_medallions[1] = ['Ether', 'Quake']
        self.world.itempool.extend(get_dungeon_item_pool(self.world))
        self.world.itempool.extend(
            ItemFactory([
                'Green Pendant', 'Red Pendant', 'Blue Pendant',
                'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2',
                'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'
            ], 1))
        self.world.get_location('Agahnim 1', 1).item = None
        self.world.get_location('Agahnim 2', 1).item = None
        self.world.precollected_items.clear()
        self.world.itempool.append(ItemFactory('Pegasus Boots', 1))
        mark_light_world_regions(self.world, 1)
        set_rules(self.world, 1)
Esempio n. 7
0
def set_completion_rules(world: MultiWorld, player: int):
    def reachable_locations(state):
        postgame_advancements = get_postgame_advancements(
            world.required_bosses[player].current_key)
        return [
            location for location in world.get_locations()
            if location.player == player
            and location.name not in postgame_advancements
            and location.address != None and location.can_reach(state)
        ]

    def defeated_required_bosses(state):
        return (world.required_bosses[player].current_key not in {"ender_dragon", "both"} or state.has("Defeat Ender Dragon", player)) and \
            (world.required_bosses[player].current_key not in {"wither", "both"} or state.has("Defeat Wither", player))

    # 103 total advancements. Goal is to complete X advancements and then defeat the dragon.
    # There are 11 possible postgame advancements; 5 for dragon, 5 for wither, 1 shared between them
    # Hence the max for completion is 92
    egg_shards = min(world.egg_shards_required[player],
                     world.egg_shards_available[player])
    completion_requirements = lambda state: len(reachable_locations(state)) >= world.advancement_goal[player] and \
        state.has("Dragon Egg Shard", player, egg_shards)
    world.completion_condition[player] = lambda state: completion_requirements(
        state) and defeated_required_bosses(state)
    # Set rules on postgame advancements
    for adv_name in get_postgame_advancements(
            world.required_bosses[player].current_key):
        add_rule(world.get_location(adv_name, player), completion_requirements)
Esempio n. 8
0
def set_boss_gate_rules(world: MultiWorld, player: int,
                        gate_bosses: typing.Dict[int, int]):
    for x in range(len(gate_bosses)):
        if boss_has_requirement(gate_bosses[x + 1]):
            add_rule(
                world.get_location(boss_gate_set[x],
                                   player), lambda state: state.has(
                                       ItemName.knuckles_shovel_claws, player))
Esempio n. 9
0
def set_rules(world: MultiWorld, player: int):
    shapes = get_shapes(world, player)
    if world.logic[player] != 'nologic':
        from worlds.generic import Rules
        allowed_packs = world.max_science_pack[player].get_allowed_packs()
        for tech_name, technology in technology_table.items():
            # loose nodes
            location = world.get_location(tech_name, player)
            Rules.set_rule(location, technology.build_rule(allowed_packs, player))
            prequisites = shapes.get(tech_name)
            if prequisites:
                locations = {world.get_location(requisite, player) for requisite in prequisites}
                Rules.add_rule(location, lambda state,
                                                locations=locations: all(state.can_reach(loc) for loc in locations))

        # get all technologies
        world.completion_condition[player] = lambda state: all(state.has(technology, player)
                                                               for technology in advancement_technologies)
Esempio n. 10
0
def gen_items(world: MultiWorld, player: int):
    pool = []
    for item_name, item_data in item_table.items():

        item = HKItem(item_name, item_data.advancement, item_data.id, item_data.type, player=player)

        if item_data.type == "Event":
            event_location = world.get_location(item_name, player)
            world.push_item(event_location, item)
            event_location.event = True
            event_location.locked = True
            if item.name == "King's_Pass":
                world.push_precollected(item)
        elif item_data.type == "Cursed":
            if world.CURSED[player]:
                pool.append(item)
            else:
                # fill Focus Location with Focus and add it to start inventory as well.
                event_location = world.get_location(item_name, player)
                world.push_item(event_location, item)
                event_location.event = True
                event_location.locked = True
                world.push_precollected(item)

        elif item_data.type == "Fake":
            pass
        elif item_data.type in not_shufflable_types:
            location = world.get_location(item_name, player)
            world.push_item(location, item)
            location.event = item.advancement
            location.locked = True
        else:
            target = option_to_type_lookup[item.type]
            shuffle_it = getattr(world, target)
            if shuffle_it[player]:
                pool.append(item)
            else:
                location = world.get_location(item_name, player)
                world.push_item(location, item)
                location.event = item.advancement
                location.locked = True
                logger.debug(f"Placed {item_name} to vanilla for player {player}")

    world.itempool += pool
Esempio n. 11
0
def set_rules(world: MultiWorld, player: int):
    set_rule(world.get_location(("Tile 6"), player), lambda state: state._has_total(player, 1))
    set_rule(world.get_location(("Tile 7"), player), lambda state: state._has_total(player, 2))
    set_rule(world.get_location(("Tile 8"), player), lambda state: state._has_total(player, 3))
    set_rule(world.get_location(("Tile 9"), player), lambda state: state._has_total(player, 4))
    set_rule(world.get_location(("Tile 10"), player), lambda state: state._has_total(player, 5))
    set_rule(world.get_location(("Tile 11"), player), lambda state: state._has_total(player, 6))
    set_rule(world.get_location(("Tile 12"), player), lambda state: state._has_total(player, 7))
    set_rule(world.get_location(("Tile 13"), player), lambda state: state._has_total(player, 8))
    set_rule(world.get_location(("Tile 14"), player), lambda state: state._has_total(player, 9))
    set_rule(world.get_location(("Tile 15"), player), lambda state: state._has_total(player, 10))
    set_rule(world.get_location(("Tile 16"), player), lambda state: state._has_total(player, 11))
    set_rule(world.get_location(("Tile 17"), player), lambda state: state._has_total(player, 12))
    set_rule(world.get_location(("Tile 18"), player), lambda state: state._has_total(player, 13))
    set_rule(world.get_location(("Tile 19"), player), lambda state: state._has_total(player, 14))
    set_rule(world.get_location(("Tile 20"), player), lambda state: state._has_total(player, 15))
    set_rule(world.get_location(("Tile 21"), player), lambda state: state._has_total(player, 16))
    set_rule(world.get_location(("Tile 22"), player), lambda state: state._has_total(player, 17))
    set_rule(world.get_location(("Tile 23"), player), lambda state: state._has_total(player, 18))
    set_rule(world.get_location(("Tile 24"), player), lambda state: state._has_total(player, 19))
    set_rule(world.get_location(("Tile 25"), player), lambda state: state._has_total(player, 20))
Esempio n. 12
0
def gen_factorio(world: MultiWorld, player: int):
    static_nodes = world._static_nodes = {"automation", "logistics"}  # turn dynamic/option?
    for tech_name, tech_id in tech_table.items():
        tech_item = Item(tech_name, tech_name in advancement_technologies, tech_id, player)
        tech_item.game = "Factorio"
        if tech_name in static_nodes:
            loc = world.get_location(tech_name, player)
            loc.item = tech_item
            loc.locked = True
            loc.event = tech_item.advancement
        else:
            world.itempool.append(tech_item)
    set_rules(world, player)
Esempio n. 13
0
class TestDungeon(unittest.TestCase):
    def setUp(self):
        self.world = MultiWorld(1)
        self.starting_regions = []  # Where to start exploring
        self.remove_exits = []      # Block dungeon exits
        self.world.difficulty_requirements[1] = difficulties['normal']
        create_regions(self.world, 1)
        create_dungeons(self.world, 1)
        create_shops(self.world, 1)
        for exitname, regionname in mandatory_connections:
            connect_simple(self.world, exitname, regionname, 1)
        connect_simple(self.world, 'Big Bomb Shop', 'Big Bomb Shop', 1)
        self.world.get_region('Menu', 1).exits = []
        self.world.swamp_patch_required[1] = True
        set_rules(self.world, 1)
        generate_itempool(self.world, 1)
        self.world.itempool.extend(get_dungeon_item_pool(self.world))
        self.world.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1))

    def run_tests(self, access_pool):
        for exit in self.remove_exits:
            self.world.get_entrance(exit, 1).connected_region = self.world.get_region('Menu', 1)

        for location, access, *item_pool in access_pool:
            items = item_pool[0]
            all_except = item_pool[1] if len(item_pool) > 1 else None
            with self.subTest(location=location, access=access, items=items, all_except=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(ItemFactory(item_pool[0], 1))
                else:
                    items = ItemFactory(items, 1)
                state = CollectionState(self.world)
                state.reachable_regions[1].add(self.world.get_region('Menu', 1))
                for region_name in self.starting_regions:
                    region = self.world.get_region(region_name, 1)
                    state.reachable_regions[1].add(region)
                    for exit in region.exits:
                        if exit.connected_region is not None:
                            state.blocked_connections[1].add(exit)

                for item in items:
                    item.advancement = True
                    state.collect(item)

                self.assertEqual(self.world.get_location(location, 1).can_reach(state), access)
Esempio n. 14
0
    def stage_write_spoiler(cls, world: MultiWorld, spoiler_handle):
        hk_players = world.get_game_players(cls.game)
        spoiler_handle.write('\n\nCharm Notches:')
        for player in hk_players:
            name = world.get_player_name(player)
            spoiler_handle.write(f'\n{name}\n')
            hk_world: HKWorld = world.worlds[player]
            for charm_number, cost in enumerate(hk_world.charm_costs):
                spoiler_handle.write(f"\n{charm_names[charm_number]}: {cost}")

        spoiler_handle.write('\n\nShop Prices:')
        for player in hk_players:
            name = world.get_player_name(player)
            spoiler_handle.write(f'\n{name}\n')
            hk_world: HKWorld = world.worlds[player]
            for shop_name, unit_name in cls.shops.items():
                for x in range(1, hk_world.created_multi_locations[shop_name]+1):
                    loc = world.get_location(hk_world.get_multi_location_name(shop_name, x), player)
                    spoiler_handle.write(f"\n{loc}: {loc.item} costing {loc.cost} {unit_name}")
Esempio n. 15
0
def set_rules(world: MultiWorld, player: int, player_logic: WitnessPlayerLogic,
              locat: WitnessPlayerLocations):
    """
    Sets all rules for all locations
    """

    for location in locat.CHECK_LOCATION_TABLE:
        real_location = location

        if location in locat.EVENT_LOCATION_TABLE:
            real_location = location[:-7]

        panel = StaticWitnessLogic.CHECKS_BY_NAME[real_location]
        check_hex = panel["checkHex"]

        rule = make_lambda(check_hex, world, player, player_logic, locat)

        set_rule(world.get_location(location, player), rule)

    world.completion_condition[player] = \
        lambda state: state.has('Victory', player)
Esempio n. 16
0
class TestMinor(TestBase):
    def setUp(self):
        self.world = MultiWorld(1)
        self.world.logic[1] = "minorglitches"
        self.world.difficulty_requirements[1] = difficulties['normal']
        create_regions(self.world, 1)
        create_dungeons(self.world, 1)
        create_shops(self.world, 1)
        link_entrances(self.world, 1)
        generate_itempool(self.world, 1)
        self.world.required_medallions[1] = ['Ether', 'Quake']
        self.world.itempool.extend(get_dungeon_item_pool(self.world))
        self.world.itempool.extend(
            ItemFactory([
                'Green Pendant', 'Red Pendant', 'Blue Pendant',
                'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2',
                'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'
            ], 1))
        self.world.get_location('Agahnim 1', 1).item = None
        self.world.get_location('Agahnim 2', 1).item = None
        mark_dark_world_regions(self.world, 1)
        set_rules(self.world, 1)
Esempio n. 17
0
def set_rules(world: MultiWorld, player: int):
    total_locations = world.total_locations[
        player]  # total locations for current player
    event_location_step = 25  # set an event location at these locations for "spheres"
    divisions = total_locations // event_location_step

    if divisions:
        for i in range(
                1, divisions
        ):  # since divisions is the floor of total_locations / 25
            event_loc = world.get_location(f"Pickup{i * event_location_step}",
                                           player)
            set_rule(event_loc,
                     lambda state, i=i: state.can_reach(
                         f"ItemPickup{i * event_location_step - 1}",
                         "Location", player))
            for n in range(
                    i * event_location_step, (i + 1) * event_location_step
            ):  # we want to create a rule for each of the 25 locations per division
                if n == i * event_location_step:
                    set_rule(world.get_location(f"ItemPickup{n}", player),
                             lambda state, event_item=event_loc.item.name:
                             state.has(event_item, player))
                else:
                    set_rule(world.get_location(f"ItemPickup{n}", player),
                             lambda state, n=n: state.can_reach(
                                 f"ItemPickup{n - 1}", 'Location', player))
        for i in range(divisions * event_location_step, total_locations + 1):
            set_rule(world.get_location(f"ItemPickup{i}", player),
                     lambda state, i=i: state.can_reach(
                         f"ItemPickup{i - 1}", "Location", player))

    set_rule(
        world.get_location("Victory", player), lambda state: state.can_reach(
            f"ItemPickup{total_locations}", "Location", player))
    if world.total_revivals[player] or world.start_with_revive[player]:
        total_revivals = world.total_revivals[player] * world.total_locations[
            player] // 100
        add_rule(
            world.get_location("Victory", player), lambda state: state.has(
                "Dio's Best Friend", player, total_revivals + world.
                start_with_revive[player].value))

    world.completion_condition[player] = lambda state: state.has(
        "Victory", player)
Esempio n. 18
0
def set_rules(world: MultiWorld, player: int):
    # Check for duplicate names.
    if len(set(world.additional_lady_names[player].value)) != len(
            world.additional_lady_names[player].value):
        raise Exception(
            f"Duplicate values are not allowed in additional_lady_names.")
    if len(set(world.additional_sir_names[player].value)) != len(
            world.additional_sir_names[player].value):
        raise Exception(
            f"Duplicate values are not allowed in additional_sir_names.")

    if not world.allow_default_names[player]:
        # Check for quantity.
        name_count = len(world.additional_lady_names[player].value)
        if name_count < int(world.number_of_children[player]):
            raise Exception(
                f"allow_default_names is off, but not enough names are defined in additional_lady_names. Expected {int(world.number_of_children[player])}, Got {name_count}"
            )

        name_count = len(world.additional_sir_names[player].value)
        if name_count < int(world.number_of_children[player]):
            raise Exception(
                f"allow_default_names is off, but not enough names are defined in additional_sir_names. Expected {int(world.number_of_children[player])}, Got {name_count}"
            )

    # Chests
    if world.universal_chests[player]:
        for i in range(0, world.chests_per_zone[player]):
            set_rule(
                world.get_location(
                    f"Chest {i + 1 + (world.chests_per_zone[player] * 1)}",
                    player),
                lambda state: state.has(ItemName.boss_castle, player))
            set_rule(
                world.get_location(
                    f"Chest {i + 1 + (world.chests_per_zone[player] * 2)}",
                    player),
                lambda state: state.has(ItemName.boss_forest, player))
            set_rule(
                world.get_location(
                    f"Chest {i + 1 + (world.chests_per_zone[player] * 3)}",
                    player),
                lambda state: state.has(ItemName.boss_tower, player))
    else:
        for i in range(0, world.chests_per_zone[player]):
            set_rule(
                world.get_location(f"{LocationName.garden} - Chest {i + 1}",
                                   player),
                lambda state: state.has(ItemName.boss_castle, player))
            set_rule(
                world.get_location(f"{LocationName.tower} - Chest {i + 1}",
                                   player),
                lambda state: state.has(ItemName.boss_forest, player))
            set_rule(
                world.get_location(f"{LocationName.dungeon} - Chest {i + 1}",
                                   player),
                lambda state: state.has(ItemName.boss_tower, player))

    # Fairy Chests
    if world.universal_fairy_chests[player]:
        for i in range(0, world.fairy_chests_per_zone[player]):
            set_rule(
                world.get_location(
                    f"Fairy Chest {i + 1 + (world.fairy_chests_per_zone[player] * 1)}",
                    player),
                lambda state: state.has(ItemName.boss_castle, player))
            set_rule(
                world.get_location(
                    f"Fairy Chest {i + 1 + (world.fairy_chests_per_zone[player] * 2)}",
                    player),
                lambda state: state.has(ItemName.boss_forest, player))
            set_rule(
                world.get_location(
                    f"Fairy Chest {i + 1 + (world.fairy_chests_per_zone[player] * 3)}",
                    player),
                lambda state: state.has(ItemName.boss_tower, player))
    else:
        for i in range(0, world.fairy_chests_per_zone[player]):
            set_rule(
                world.get_location(
                    f"{LocationName.garden} - Fairy Chest {i + 1}", player),
                lambda state: state.has(ItemName.boss_castle, player))
            set_rule(
                world.get_location(
                    f"{LocationName.tower} - Fairy Chest {i + 1}", player),
                lambda state: state.has(ItemName.boss_forest, player))
            set_rule(
                world.get_location(
                    f"{LocationName.dungeon} - Fairy Chest {i + 1}", player),
                lambda state: state.has(ItemName.boss_tower, player))

    # Vendors
    if world.vendors[player] == "early":
        set_rule(world.get_location(LocationName.boss_castle, player),
                 lambda state: state._legacy_has_all_vendors(player))
    elif world.vendors[player] == "normal":
        set_rule(world.get_location(LocationName.garden, player),
                 lambda state: state._legacy_has_any_vendors(player))

    # Diaries
    for i in range(0, 5):
        set_rule(world.get_location(f"Diary {i + 6}", player),
                 lambda state: state.has(ItemName.boss_castle, player))
        set_rule(world.get_location(f"Diary {i + 11}", player),
                 lambda state: state.has(ItemName.boss_forest, player))
        set_rule(world.get_location(f"Diary {i + 16}", player),
                 lambda state: state.has(ItemName.boss_tower, player))
        set_rule(world.get_location(f"Diary {i + 21}", player),
                 lambda state: state.has(ItemName.boss_dungeon, player))

    # Scale each manor location.
    set_rule(world.get_location(LocationName.manor_left_wing_window, player),
             lambda state: state.has(ItemName.boss_castle, player))
    set_rule(world.get_location(LocationName.manor_left_wing_roof, player),
             lambda state: state.has(ItemName.boss_castle, player))
    set_rule(world.get_location(LocationName.manor_right_wing_window, player),
             lambda state: state.has(ItemName.boss_castle, player))
    set_rule(world.get_location(LocationName.manor_right_wing_roof, player),
             lambda state: state.has(ItemName.boss_castle, player))
    set_rule(world.get_location(LocationName.manor_left_big_base, player),
             lambda state: state.has(ItemName.boss_castle, player))
    set_rule(world.get_location(LocationName.manor_right_big_base, player),
             lambda state: state.has(ItemName.boss_castle, player))
    set_rule(world.get_location(LocationName.manor_left_tree1, player),
             lambda state: state.has(ItemName.boss_castle, player))
    set_rule(world.get_location(LocationName.manor_left_tree2, player),
             lambda state: state.has(ItemName.boss_castle, player))
    set_rule(world.get_location(LocationName.manor_right_tree, player),
             lambda state: state.has(ItemName.boss_castle, player))
    set_rule(world.get_location(LocationName.manor_left_big_upper1, player),
             lambda state: state.has(ItemName.boss_forest, player))
    set_rule(world.get_location(LocationName.manor_left_big_upper2, player),
             lambda state: state.has(ItemName.boss_forest, player))
    set_rule(world.get_location(LocationName.manor_left_big_windows, player),
             lambda state: state.has(ItemName.boss_forest, player))
    set_rule(world.get_location(LocationName.manor_left_big_roof, player),
             lambda state: state.has(ItemName.boss_forest, player))
    set_rule(world.get_location(LocationName.manor_left_far_base, player),
             lambda state: state.has(ItemName.boss_forest, player))
    set_rule(world.get_location(LocationName.manor_left_far_roof, player),
             lambda state: state.has(ItemName.boss_forest, player))
    set_rule(world.get_location(LocationName.manor_left_extension, player),
             lambda state: state.has(ItemName.boss_forest, player))
    set_rule(world.get_location(LocationName.manor_right_big_upper, player),
             lambda state: state.has(ItemName.boss_forest, player))
    set_rule(world.get_location(LocationName.manor_right_big_roof, player),
             lambda state: state.has(ItemName.boss_forest, player))
    set_rule(world.get_location(LocationName.manor_right_extension, player),
             lambda state: state.has(ItemName.boss_forest, player))
    set_rule(world.get_location(LocationName.manor_right_high_base, player),
             lambda state: state.has(ItemName.boss_tower, player))
    set_rule(world.get_location(LocationName.manor_right_high_upper, player),
             lambda state: state.has(ItemName.boss_tower, player))
    set_rule(world.get_location(LocationName.manor_right_high_tower, player),
             lambda state: state.has(ItemName.boss_tower, player))
    set_rule(world.get_location(LocationName.manor_observatory_base, player),
             lambda state: state.has(ItemName.boss_tower, player))
    set_rule(world.get_location(LocationName.manor_observatory_scope, player),
             lambda state: state.has(ItemName.boss_tower, player))

    # Standard Zone Progression
    set_rule(
        world.get_location(LocationName.garden, player),
        lambda state: state._legacy_has_stat_upgrades(
            player, 0.125 * state._legacy_total_stat_upgrades_count(player)
        ) and state.has(ItemName.boss_castle, player))
    set_rule(
        world.get_location(LocationName.tower, player),
        lambda state: state._legacy_has_stat_upgrades(
            player, 0.3125 * state._legacy_total_stat_upgrades_count(player)
        ) and state.has(ItemName.boss_forest, player))
    set_rule(
        world.get_location(LocationName.dungeon, player),
        lambda state: state._legacy_has_stat_upgrades(
            player, 0.5 * state._legacy_total_stat_upgrades_count(player)
        ) and state.has(ItemName.boss_tower, player))

    # Bosses
    set_rule(world.get_location(LocationName.boss_castle, player),
             lambda state: state.has(ItemName.boss_castle, player))
    set_rule(world.get_location(LocationName.boss_forest, player),
             lambda state: state.has(ItemName.boss_forest, player))
    set_rule(world.get_location(LocationName.boss_tower, player),
             lambda state: state.has(ItemName.boss_tower, player))
    set_rule(world.get_location(LocationName.boss_dungeon, player),
             lambda state: state.has(ItemName.boss_dungeon, player))
    set_rule(
        world.get_location(LocationName.fountain, player),
        lambda state: state._legacy_has_stat_upgrades(
            player, 0.625 * state._legacy_total_stat_upgrades_count(player)
        ) and state.has(ItemName.boss_castle, player) and state.has(
            ItemName.boss_forest, player) and state.has(
                ItemName.boss_tower, player) and state.has(
                    ItemName.boss_dungeon, player))

    world.completion_condition[player] = lambda state: state.has(
        ItemName.boss_fountain, player)
Esempio n. 19
0
def set_mission_upgrade_rules(world: MultiWorld, player: int):
    # Mission 1 Upgrade Requirements
    add_rule(world.get_location(LocationName.metal_harbor_1, player),
             lambda state: state.has(ItemName.sonic_light_shoes, player))
    add_rule(world.get_location(LocationName.pumpkin_hill_1, player),
             lambda state: state.has(ItemName.knuckles_shovel_claws, player))
    add_rule(world.get_location(LocationName.mission_street_1, player),
             lambda state: state.has(ItemName.tails_booster, player))
    add_rule(world.get_location(LocationName.aquatic_mine_1, player),
             lambda state: state.has(ItemName.knuckles_shovel_claws, player))
    add_rule(world.get_location(LocationName.hidden_base_1, player),
             lambda state: state.has(ItemName.tails_booster, player))
    add_rule(world.get_location(LocationName.pyramid_cave_1, player),
             lambda state: state.has(ItemName.sonic_bounce_bracelet, player))
    add_rule(
        world.get_location(LocationName.death_chamber_1, player),
        lambda state: state.has(ItemName.knuckles_shovel_claws, player) and
        state.has(ItemName.knuckles_hammer_gloves, player))
    add_rule(
        world.get_location(LocationName.eternal_engine_1, player),
        lambda state: state.has(ItemName.tails_booster, player) and state.has(
            ItemName.tails_bazooka, player))
    add_rule(
        world.get_location(LocationName.meteor_herd_1, player),
        lambda state: state.has(ItemName.knuckles_shovel_claws, player) and
        state.has(ItemName.knuckles_hammer_gloves, player))
    add_rule(
        world.get_location(LocationName.crazy_gadget_1, player),
        lambda state: state.has(ItemName.sonic_light_shoes, player) and state.
        has(ItemName.sonic_bounce_bracelet, player) and state.has(
            ItemName.sonic_flame_ring, player))
    add_rule(world.get_location(LocationName.final_rush_1, player),
             lambda state: state.has(ItemName.sonic_bounce_bracelet, player))

    add_rule(world.get_location(LocationName.egg_quarters_1, player),
             lambda state: state.has(ItemName.rouge_pick_nails, player))
    add_rule(world.get_location(LocationName.lost_colony_1, player),
             lambda state: state.has(ItemName.eggman_jet_engine, player))
    add_rule(
        world.get_location(LocationName.weapons_bed_1, player),
        lambda state: state.has(ItemName.eggman_jet_engine, player) and state.
        has(ItemName.eggman_large_cannon, player))
    add_rule(world.get_location(LocationName.security_hall_1, player),
             lambda state: state.has(ItemName.rouge_pick_nails, player))
    add_rule(world.get_location(LocationName.white_jungle_1, player),
             lambda state: state.has(ItemName.shadow_air_shoes, player))
    add_rule(
        world.get_location(LocationName.mad_space_1, player),
        lambda state: state.has(ItemName.rouge_pick_nails, player) and state.
        has(ItemName.rouge_iron_boots, player))
    add_rule(world.get_location(LocationName.cosmic_wall_1, player),
             lambda state: state.has(ItemName.eggman_jet_engine, player))

    add_rule(
        world.get_location(LocationName.cannon_core_1, player),
        lambda state: state.has(ItemName.tails_booster, player) and state.has(
            ItemName.eggman_jet_engine, player) and state.has(
                ItemName.knuckles_hammer_gloves, player) and state.has(
                    ItemName.knuckles_air_necklace, player) and state.has(
                        ItemName.sonic_bounce_bracelet, player))

    # Mission 2 Upgrade Requirements
    if world.include_missions[player].value >= 2:
        add_rule(world.get_location(LocationName.metal_harbor_2, player),
                 lambda state: state.has(ItemName.sonic_light_shoes, player))
        add_rule(world.get_location(LocationName.mission_street_2, player),
                 lambda state: state.has(ItemName.tails_booster, player))
        add_rule(world.get_location(LocationName.hidden_base_2, player),
                 lambda state: state.has(ItemName.tails_booster, player))
        add_rule(
            world.get_location(LocationName.death_chamber_2, player),
            lambda state: state.has(ItemName.knuckles_shovel_claws, player) and
            state.has(ItemName.knuckles_hammer_gloves, player))
        add_rule(
            world.get_location(LocationName.eternal_engine_2, player),
            lambda state: state.has(ItemName.tails_booster, player) and state.
            has(ItemName.tails_bazooka, player))
        add_rule(
            world.get_location(LocationName.crazy_gadget_2, player),
            lambda state: state.has(ItemName.sonic_bounce_bracelet, player))

        add_rule(world.get_location(LocationName.lost_colony_2, player),
                 lambda state: state.has(ItemName.eggman_jet_engine, player))
        add_rule(
            world.get_location(LocationName.weapons_bed_2, player),
            lambda state: state.has(ItemName.eggman_jet_engine, player) and
            state.has(ItemName.eggman_large_cannon, player))
        add_rule(world.get_location(LocationName.security_hall_2, player),
                 lambda state: state.has(ItemName.rouge_pick_nails, player))
        add_rule(world.get_location(LocationName.mad_space_2, player),
                 lambda state: state.has(ItemName.rouge_iron_boots, player))
        add_rule(world.get_location(LocationName.cosmic_wall_2, player),
                 lambda state: state.has(ItemName.eggman_jet_engine, player))

        add_rule(
            world.get_location(LocationName.cannon_core_2, player),
            lambda state: state.has(ItemName.tails_booster, player) and state.
            has(ItemName.eggman_jet_engine, player))

    # Mission 3 Upgrade Requirements
    if world.include_missions[player].value >= 3:
        add_rule(world.get_location(LocationName.city_escape_3, player),
                 lambda state: state.has(ItemName.sonic_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.wild_canyon_3, player),
            lambda state: state.has(ItemName.knuckles_shovel_claws, player) and
            state.has(ItemName.knuckles_hammer_gloves, player) and state.has(
                ItemName.knuckles_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.prison_lane_3, player),
            lambda state: state.has(ItemName.tails_booster, player) and state.
            has(ItemName.tails_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.metal_harbor_3, player),
            lambda state: state.has(ItemName.sonic_light_shoes, player) and
            state.has(ItemName.sonic_bounce_bracelet, player) and state.has(
                ItemName.sonic_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.green_forest_3, player),
            lambda state: state.has(ItemName.sonic_bounce_bracelet, player) and
            state.has(ItemName.sonic_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.pumpkin_hill_3, player),
            lambda state: state.has(ItemName.knuckles_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.mission_street_3, player),
            lambda state: state.has(ItemName.tails_booster, player) and state.
            has(ItemName.tails_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.aquatic_mine_3, player),
            lambda state: state.has(ItemName.knuckles_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.hidden_base_3, player),
            lambda state: state.has(ItemName.tails_booster, player) and state.
            has(ItemName.tails_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.pyramid_cave_3, player),
            lambda state: state.has(ItemName.sonic_bounce_bracelet, player) and
            state.has(ItemName.sonic_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.death_chamber_3, player),
            lambda state: state.has(ItemName.knuckles_mystic_melody, player)
            and state.has(ItemName.knuckles_air_necklace, player) and state.
            has(ItemName.knuckles_hammer_gloves, player))
        add_rule(
            world.get_location(LocationName.eternal_engine_3, player),
            lambda state: state.has(ItemName.tails_booster, player) and state.
            has(ItemName.tails_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.meteor_herd_3, player),
            lambda state: state.has(ItemName.knuckles_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.crazy_gadget_3, player),
            lambda state: state.has(ItemName.sonic_light_shoes, player) and
            state.has(ItemName.sonic_bounce_bracelet, player) and state.has(
                ItemName.sonic_flame_ring, player) and state.has(
                    ItemName.sonic_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.final_rush_3, player),
            lambda state: state.has(ItemName.sonic_light_shoes, player) and
            state.has(ItemName.sonic_bounce_bracelet, player) and state.has(
                ItemName.sonic_mystic_melody, player))

        add_rule(
            world.get_location(LocationName.iron_gate_3, player),
            lambda state: state.has(ItemName.eggman_mystic_melody, player) and
            state.has(ItemName.eggman_jet_engine, player) and state.has(
                ItemName.eggman_large_cannon, player))
        add_rule(
            world.get_location(LocationName.dry_lagoon_3, player),
            lambda state: state.has(ItemName.rouge_mystic_melody, player) and
            state.has(ItemName.rouge_pick_nails, player) and state.has(
                ItemName.rouge_iron_boots, player))
        add_rule(
            world.get_location(LocationName.sand_ocean_3, player),
            lambda state: state.has(ItemName.eggman_jet_engine, player) and
            state.has(ItemName.eggman_large_cannon, player))
        add_rule(
            world.get_location(LocationName.radical_highway_3, player),
            lambda state: state.has(ItemName.shadow_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.egg_quarters_3, player),
            lambda state: state.has(ItemName.rouge_mystic_melody, player) and
            state.has(ItemName.rouge_pick_nails, player) and state.has(
                ItemName.rouge_iron_boots, player))
        add_rule(
            world.get_location(LocationName.lost_colony_3, player),
            lambda state: state.has(ItemName.eggman_mystic_melody, player) and
            state.has(ItemName.eggman_jet_engine, player))
        add_rule(
            world.get_location(LocationName.weapons_bed_3, player),
            lambda state: state.has(ItemName.eggman_mystic_melody, player) and
            state.has(ItemName.eggman_jet_engine, player) and state.has(
                ItemName.eggman_large_cannon, player))
        add_rule(
            world.get_location(LocationName.security_hall_3, player),
            lambda state: state.has(ItemName.rouge_treasure_scope, player))
        add_rule(
            world.get_location(LocationName.white_jungle_3, player),
            lambda state: state.has(ItemName.shadow_air_shoes, player) and
            state.has(ItemName.shadow_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.sky_rail_3, player),
            lambda state: state.has(ItemName.shadow_air_shoes, player) and
            state.has(ItemName.shadow_mystic_melody, player))
        add_rule(
            world.get_location(LocationName.mad_space_3, player),
            lambda state: state.has(ItemName.rouge_mystic_melody, player) and
            state.has(ItemName.rouge_iron_boots, player))
        add_rule(
            world.get_location(LocationName.cosmic_wall_3, player),
            lambda state: state.has(ItemName.eggman_mystic_melody, player) and
            state.has(ItemName.eggman_jet_engine, player))
        add_rule(
            world.get_location(LocationName.final_chase_3, player),
            lambda state: state.has(ItemName.shadow_air_shoes, player) and
            state.has(ItemName.shadow_mystic_melody, player))

        add_rule(
            world.get_location(LocationName.cannon_core_3, player),
            lambda state: state.has(ItemName.tails_booster, player) and state.
            has(ItemName.eggman_mystic_melody, player) and state.has(
                ItemName.eggman_jet_engine, player) and state.has(
                    ItemName.eggman_large_cannon, player) and state.has(
                        ItemName.rouge_mystic_melody, player) and state
            .has(ItemName.knuckles_mystic_melody, player) and state.has(
                ItemName.knuckles_hammer_gloves, player) and state.has(
                    ItemName.knuckles_air_necklace, player) and state.has(
                        ItemName.sonic_bounce_bracelet, player) and state.has(
                            ItemName.sonic_light_shoes, player))

    # Mission 4 Upgrade Requirements
    if world.include_missions[player].value >= 4:
        add_rule(world.get_location(LocationName.metal_harbor_4, player),
                 lambda state: state.has(ItemName.sonic_light_shoes, player))
        add_rule(
            world.get_location(LocationName.pumpkin_hill_4, player),
            lambda state: state.has(ItemName.knuckles_shovel_claws, player))
        add_rule(world.get_location(LocationName.mission_street_4, player),
                 lambda state: state.has(ItemName.tails_booster, player))
        add_rule(
            world.get_location(LocationName.aquatic_mine_4, player),
            lambda state: state.has(ItemName.knuckles_shovel_claws, player))
        add_rule(world.get_location(LocationName.hidden_base_4, player),
                 lambda state: state.has(ItemName.tails_booster, player))
        add_rule(
            world.get_location(LocationName.pyramid_cave_4, player),
            lambda state: state.has(ItemName.sonic_bounce_bracelet, player))
        add_rule(
            world.get_location(LocationName.death_chamber_4, player),
            lambda state: state.has(ItemName.knuckles_shovel_claws, player) and
            state.has(ItemName.knuckles_hammer_gloves, player))
        add_rule(
            world.get_location(LocationName.eternal_engine_4, player),
            lambda state: state.has(ItemName.tails_booster, player) and state.
            has(ItemName.tails_bazooka, player))
        add_rule(
            world.get_location(LocationName.meteor_herd_4, player),
            lambda state: state.has(ItemName.knuckles_shovel_claws, player) and
            state.has(ItemName.knuckles_hammer_gloves, player))
        add_rule(
            world.get_location(LocationName.crazy_gadget_4, player),
            lambda state: state.has(ItemName.sonic_light_shoes, player) and
            state.has(ItemName.sonic_bounce_bracelet, player) and state.has(
                ItemName.sonic_flame_ring, player))
        add_rule(
            world.get_location(LocationName.final_rush_4, player),
            lambda state: state.has(ItemName.sonic_bounce_bracelet, player))

        add_rule(world.get_location(LocationName.egg_quarters_4, player),
                 lambda state: state.has(ItemName.rouge_pick_nails, player))
        add_rule(world.get_location(LocationName.lost_colony_4, player),
                 lambda state: state.has(ItemName.eggman_jet_engine, player))
        add_rule(
            world.get_location(LocationName.weapons_bed_4, player),
            lambda state: state.has(ItemName.eggman_jet_engine, player) and
            state.has(ItemName.eggman_large_cannon, player))
        add_rule(world.get_location(LocationName.security_hall_4, player),
                 lambda state: state.has(ItemName.rouge_pick_nails, player))
        add_rule(world.get_location(LocationName.white_jungle_4, player),
                 lambda state: state.has(ItemName.shadow_air_shoes, player))
        add_rule(
            world.get_location(LocationName.mad_space_4, player),
            lambda state: state.has(ItemName.rouge_pick_nails, player) and
            state.has(ItemName.rouge_iron_boots, player))
        add_rule(world.get_location(LocationName.cosmic_wall_4, player),
                 lambda state: state.has(ItemName.eggman_jet_engine, player))

        add_rule(
            world.get_location(LocationName.cannon_core_4, player),
            lambda state: state.has(ItemName.tails_booster, player) and state.
            has(ItemName.eggman_jet_engine, player) and state.has(
                ItemName.knuckles_hammer_gloves, player) and state.has(
                    ItemName.knuckles_air_necklace, player) and state.has(
                        ItemName.sonic_bounce_bracelet, player))

    # Mission 5 Upgrade Requirements
    if world.include_missions[player].value >= 5:
        add_rule(
            world.get_location(LocationName.city_escape_5, player),
            lambda state: state.has(ItemName.sonic_flame_ring, player) and
            state.has(ItemName.sonic_light_shoes, player))
        add_rule(
            world.get_location(LocationName.wild_canyon_5, player),
            lambda state: state.has(ItemName.knuckles_shovel_claws, player) and
            state.has(ItemName.knuckles_sunglasses, player))
        add_rule(world.get_location(LocationName.metal_harbor_5, player),
                 lambda state: state.has(ItemName.sonic_light_shoes, player))
        add_rule(
            world.get_location(LocationName.pumpkin_hill_5, player),
            lambda state: state.has(ItemName.knuckles_shovel_claws, player) and
            state.has(ItemName.knuckles_sunglasses, player))
        add_rule(
            world.get_location(LocationName.mission_street_5, player),
            lambda state: state.has(ItemName.tails_booster, player) and state.
            has(ItemName.tails_bazooka, player))
        add_rule(
            world.get_location(LocationName.aquatic_mine_5, player),
            lambda state: state.has(ItemName.knuckles_mystic_melody, player)
            and state.has(ItemName.knuckles_air_necklace, player) and state.
            has(ItemName.knuckles_sunglasses, player))
        add_rule(world.get_location(LocationName.hidden_base_5, player),
                 lambda state: state.has(ItemName.tails_booster, player))
        add_rule(
            world.get_location(LocationName.pyramid_cave_5, player),
            lambda state: state.has(ItemName.sonic_bounce_bracelet, player))
        add_rule(
            world.get_location(LocationName.death_chamber_5, player),
            lambda state: state.has(ItemName.knuckles_hammer_gloves, player)
            and state.has(ItemName.knuckles_shovel_claws, player) and state.
            has(ItemName.knuckles_mystic_melody, player) and state.has(
                ItemName.knuckles_air_necklace, player))
        add_rule(
            world.get_location(LocationName.eternal_engine_5, player),
            lambda state: state.has(ItemName.tails_booster, player) and state.
            has(ItemName.tails_bazooka, player))
        add_rule(
            world.get_location(LocationName.meteor_herd_5, player),
            lambda state: state.has(ItemName.knuckles_hammer_gloves, player)
            and state.has(ItemName.knuckles_sunglasses, player))
        add_rule(
            world.get_location(LocationName.crazy_gadget_5, player),
            lambda state: state.has(ItemName.sonic_light_shoes, player) and
            state.has(ItemName.sonic_bounce_bracelet, player) and state.has(
                ItemName.sonic_flame_ring, player))
        add_rule(
            world.get_location(LocationName.final_rush_5, player),
            lambda state: state.has(ItemName.sonic_bounce_bracelet, player))

        add_rule(world.get_location(LocationName.iron_gate_5, player),
                 lambda state: state.has(ItemName.eggman_large_cannon, player))
        add_rule(
            world.get_location(LocationName.dry_lagoon_5, player),
            lambda state: state.has(ItemName.rouge_treasure_scope, player))
        add_rule(
            world.get_location(LocationName.egg_quarters_5, player),
            lambda state: state.has(ItemName.rouge_treasure_scope, player))
        add_rule(
            world.get_location(LocationName.lost_colony_5, player),
            lambda state: state.has(ItemName.eggman_jet_engine, player) and
            state.has(ItemName.eggman_large_cannon, player))
        add_rule(
            world.get_location(LocationName.weapons_bed_5, player),
            lambda state: state.has(ItemName.eggman_jet_engine, player) and
            state.has(ItemName.eggman_large_cannon, player))
        add_rule(
            world.get_location(LocationName.security_hall_5, player),
            lambda state: state.has(ItemName.rouge_pick_nails, player) and
            state.has(ItemName.rouge_treasure_scope, player) and state.has(
                ItemName.rouge_iron_boots, player))
        add_rule(
            world.get_location(LocationName.white_jungle_5, player),
            lambda state: state.has(ItemName.shadow_air_shoes, player) and
            state.has(ItemName.shadow_flame_ring, player))
        add_rule(world.get_location(LocationName.cosmic_wall_5, player),
                 lambda state: state.has(ItemName.eggman_jet_engine, player))

        add_rule(
            world.get_location(LocationName.cannon_core_5, player),
            lambda state: state.has(ItemName.tails_booster, player) and state.
            has(ItemName.eggman_jet_engine, player) and state.has(
                ItemName.knuckles_mystic_melody, player) and state.has(
                    ItemName.knuckles_hammer_gloves, player) and state.has(
                        ItemName.knuckles_air_necklace, player) and state.has(
                            ItemName.sonic_bounce_bracelet, player))

    add_rule(
        world.get_location(LocationName.city_escape_upgrade, player),
        lambda state: state.has(ItemName.sonic_bounce_bracelet, player) and
        state.has(ItemName.sonic_flame_ring, player))
    add_rule(world.get_location(LocationName.wild_canyon_upgrade, player),
             lambda state: state.has(ItemName.knuckles_shovel_claws, player))
    add_rule(world.get_location(LocationName.prison_lane_upgrade, player),
             lambda state: state.has(ItemName.tails_bazooka, player))
    add_rule(
        world.get_location(LocationName.hidden_base_upgrade, player),
        lambda state: state.has(ItemName.tails_booster, player) and state.has(
            ItemName.tails_bazooka, player))
    add_rule(world.get_location(LocationName.eternal_engine_upgrade, player),
             lambda state: state.has(ItemName.tails_booster, player))
    add_rule(world.get_location(LocationName.meteor_herd_upgrade, player),
             lambda state: state.has(ItemName.knuckles_hammer_gloves, player))
    add_rule(world.get_location(LocationName.crazy_gadget_upgrade, player),
             lambda state: state.has(ItemName.sonic_bounce_bracelet, player))
    add_rule(world.get_location(LocationName.final_rush_upgrade, player),
             lambda state: state.has(ItemName.sonic_bounce_bracelet, player))

    add_rule(world.get_location(LocationName.iron_gate_upgrade, player),
             lambda state: state.has(ItemName.eggman_large_cannon, player))
    add_rule(world.get_location(LocationName.dry_lagoon_upgrade, player),
             lambda state: state.has(ItemName.rouge_pick_nails, player))
    add_rule(world.get_location(LocationName.sand_ocean_upgrade, player),
             lambda state: state.has(ItemName.eggman_jet_engine, player))
    add_rule(world.get_location(LocationName.radical_highway_upgrade, player),
             lambda state: state.has(ItemName.shadow_air_shoes, player))
    add_rule(
        world.get_location(LocationName.security_hall_upgrade, player),
        lambda state: state.has(ItemName.rouge_mystic_melody, player) and state
        .has(ItemName.rouge_iron_boots, player))
    add_rule(world.get_location(LocationName.cosmic_wall_upgrade, player),
             lambda state: state.has(ItemName.eggman_jet_engine, player))
Esempio n. 20
0
def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = None):
    if not baked_server_options:
        baked_server_options = get_options()["server_options"]
    if args.outputpath:
        os.makedirs(args.outputpath, exist_ok=True)
        output_path.cached_path = args.outputpath

    start = time.perf_counter()
    # initialize the world
    world = MultiWorld(args.multi)

    logger = logging.getLogger()
    world.set_seed(seed, args.race, str(args.outputname if args.outputname else world.seed))

    world.shuffle = args.shuffle.copy()
    world.logic = args.logic.copy()
    world.mode = args.mode.copy()
    world.difficulty = args.difficulty.copy()
    world.item_functionality = args.item_functionality.copy()
    world.timer = args.timer.copy()
    world.goal = args.goal.copy()
    world.open_pyramid = args.open_pyramid.copy()
    world.boss_shuffle = args.shufflebosses.copy()
    world.enemy_health = args.enemy_health.copy()
    world.enemy_damage = args.enemy_damage.copy()
    world.beemizer_total_chance = args.beemizer_total_chance.copy()
    world.beemizer_trap_chance = args.beemizer_trap_chance.copy()
    world.timer = args.timer.copy()
    world.countdown_start_time = args.countdown_start_time.copy()
    world.red_clock_time = args.red_clock_time.copy()
    world.blue_clock_time = args.blue_clock_time.copy()
    world.green_clock_time = args.green_clock_time.copy()
    world.dungeon_counters = args.dungeon_counters.copy()
    world.triforce_pieces_available = args.triforce_pieces_available.copy()
    world.triforce_pieces_required = args.triforce_pieces_required.copy()
    world.shop_shuffle = args.shop_shuffle.copy()
    world.shuffle_prizes = args.shuffle_prizes.copy()
    world.sprite_pool = args.sprite_pool.copy()
    world.dark_room_logic = args.dark_room_logic.copy()
    world.plando_items = args.plando_items.copy()
    world.plando_texts = args.plando_texts.copy()
    world.plando_connections = args.plando_connections.copy()
    world.required_medallions = args.required_medallions.copy()
    world.game = args.game.copy()
    world.player_name = args.name.copy()
    world.enemizer = args.enemizercli
    world.sprite = args.sprite.copy()
    world.glitch_triforce = args.glitch_triforce  # This is enabled/disabled globally, no per player option.

    world.set_options(args)
    world.set_item_links()
    world.state = CollectionState(world)
    logger.info('Archipelago Version %s  -  Seed: %s\n', __version__, world.seed)

    logger.info("Found World Types:")
    longest_name = max(len(text) for text in AutoWorld.AutoWorldRegister.world_types)
    numlength = 8
    for name, cls in AutoWorld.AutoWorldRegister.world_types.items():
        if not cls.hidden:
            logger.info(f"  {name:{longest_name}}: {len(cls.item_names):3} "
                        f"Items (IDs: {min(cls.item_id_to_name):{numlength}} - "
                        f"{max(cls.item_id_to_name):{numlength}}) | "
                        f"{len(cls.location_names):3} "
                        f"Locations (IDs: {min(cls.location_id_to_name):{numlength}} - "
                        f"{max(cls.location_id_to_name):{numlength}})")

    AutoWorld.call_stage(world, "assert_generate")

    AutoWorld.call_all(world, "generate_early")

    logger.info('')

    for player in world.player_ids:
        for item_name, count in world.start_inventory[player].value.items():
            for _ in range(count):
                world.push_precollected(world.create_item(item_name, player))

    for player in world.player_ids:
        if player in world.get_game_players("A Link to the Past"):
            # enforce pre-defined local items.
            if world.goal[player] in ["localtriforcehunt", "localganontriforcehunt"]:
                world.local_items[player].value.add('Triforce Piece')

            # Not possible to place pendants/crystals out side of boss prizes yet.
            world.non_local_items[player].value -= item_name_groups['Pendants']
            world.non_local_items[player].value -= item_name_groups['Crystals']

        # items can't be both local and non-local, prefer local
        world.non_local_items[player].value -= world.local_items[player].value

    logger.info('Creating World.')
    AutoWorld.call_all(world, "create_regions")

    logger.info('Creating Items.')
    AutoWorld.call_all(world, "create_items")

    logger.info('Calculating Access Rules.')
    if world.players > 1:
        for player in world.player_ids:
            locality_rules(world, player)
        group_locality_rules(world)
    else:
        world.non_local_items[1].value = set()
        world.local_items[1].value = set()

    AutoWorld.call_all(world, "set_rules")

    for player in world.player_ids:
        exclusion_rules(world, player, world.exclude_locations[player].value)
        world.priority_locations[player].value -= world.exclude_locations[player].value
        for location_name in world.priority_locations[player].value:
            world.get_location(location_name, player).progress_type = LocationProgressType.PRIORITY

    AutoWorld.call_all(world, "generate_basic")

    # temporary home for item links, should be moved out of Main
    for group_id, group in world.groups.items():
        def find_common_pool(players: Set[int], shared_pool: Set[str]):
            classifications = collections.defaultdict(int)
            counters = {player: {name: 0 for name in shared_pool} for player in players}
            for item in world.itempool:
                if item.player in counters and item.name in shared_pool:
                    counters[item.player][item.name] += 1
                    classifications[item.name] |= item.classification

            for player in players.copy():
                if all([counters[player][item] == 0 for item in shared_pool]):
                    players.remove(player)
                    del(counters[player])

            if not players:
                return None, None

            for item in shared_pool:
                count = min(counters[player][item] for player in players)
                if count:
                    for player in players:
                        counters[player][item] = count
                else:
                    for player in players:
                        del(counters[player][item])
            return counters, classifications

        common_item_count, classifications = find_common_pool(group["players"], group["item_pool"])
        if not common_item_count:
            continue

        new_itempool = []
        for item_name, item_count in next(iter(common_item_count.values())).items():
            for _ in range(item_count):
                new_item = group["world"].create_item(item_name)
                # mangle together all original classification bits
                new_item.classification |= classifications[item_name]
                new_itempool.append(new_item)

        region = Region("Menu", RegionType.Generic, "ItemLink", group_id, world)
        world.regions.append(region)
        locations = region.locations = []
        for item in world.itempool:
            count = common_item_count.get(item.player, {}).get(item.name, 0)
            if count:
                loc = Location(group_id, f"Item Link: {item.name} -> {world.player_name[item.player]} {count}",
                               None, region)
                loc.access_rule = lambda state, item_name = item.name, group_id_ = group_id, count_ = count: \
                    state.has(item_name, group_id_, count_)

                locations.append(loc)
                loc.place_locked_item(item)
                common_item_count[item.player][item.name] -= 1
            else:
                new_itempool.append(item)

        itemcount = len(world.itempool)
        world.itempool = new_itempool

        while itemcount > len(world.itempool):
            items_to_add = []
            for player in group["players"]:
                if group["replacement_items"][player]:
                    items_to_add.append(AutoWorld.call_single(world, "create_item", player,
                                                                group["replacement_items"][player]))
                else:
                    items_to_add.append(AutoWorld.call_single(world, "create_filler", player))
            world.random.shuffle(items_to_add)
            world.itempool.extend(items_to_add[:itemcount - len(world.itempool)])

    if any(world.item_links.values()):
        world._recache()
        world._all_state = None

    logger.info("Running Item Plando")

    for item in world.itempool:
        item.world = world

    distribute_planned(world)

    logger.info('Running Pre Main Fill.')

    AutoWorld.call_all(world, "pre_fill")

    logger.info(f'Filling the world with {len(world.itempool)} items.')

    if world.algorithm == 'flood':
        flood_items(world)  # different algo, biased towards early game progress items
    elif world.algorithm == 'balanced':
        distribute_items_restrictive(world)

    AutoWorld.call_all(world, 'post_fill')

    if world.players > 1:
        balance_multiworld_progression(world)

    logger.info(f'Beginning output...')
    outfilebase = 'AP_' + world.seed_name

    output = tempfile.TemporaryDirectory()
    with output as temp_dir:
        with concurrent.futures.ThreadPoolExecutor(world.players + 2) as pool:
            check_accessibility_task = pool.submit(world.fulfills_accessibility)

            output_file_futures = [pool.submit(AutoWorld.call_stage, world, "generate_output", temp_dir)]
            for player in world.player_ids:
                # skip starting a thread for methods that say "pass".
                if AutoWorld.World.generate_output.__code__ is not world.worlds[player].generate_output.__code__:
                    output_file_futures.append(
                        pool.submit(AutoWorld.call_single, world, "generate_output", player, temp_dir))

            def get_entrance_to_region(region: Region):
                for entrance in region.entrances:
                    if entrance.parent_region.type in (RegionType.DarkWorld, RegionType.LightWorld, RegionType.Generic):
                        return entrance
                for entrance in region.entrances:  # BFS might be better here, trying DFS for now.
                    return get_entrance_to_region(entrance.parent_region)

            # collect ER hint info
            er_hint_data = {player: {} for player in world.get_game_players("A Link to the Past") if
                            world.shuffle[player] != "vanilla" or world.retro_caves[player]}

            for region in world.regions:
                if region.player in er_hint_data and region.locations:
                    main_entrance = get_entrance_to_region(region)
                    for location in region.locations:
                        if type(location.address) == int:  # skips events and crystals
                            if lookup_vanilla_location_to_entrance[location.address] != main_entrance.name:
                                er_hint_data[region.player][location.address] = main_entrance.name

            checks_in_area = {player: {area: list() for area in ordered_areas}
                              for player in range(1, world.players + 1)}

            for player in range(1, world.players + 1):
                checks_in_area[player]["Total"] = 0

            for location in world.get_filled_locations():
                if type(location.address) is int:
                    main_entrance = get_entrance_to_region(location.parent_region)
                    if location.game != "A Link to the Past":
                        checks_in_area[location.player]["Light World"].append(location.address)
                    elif location.parent_region.dungeon:
                        dungeonname = {'Inverted Agahnims Tower': 'Agahnims Tower',
                                       'Inverted Ganons Tower': 'Ganons Tower'} \
                            .get(location.parent_region.dungeon.name, location.parent_region.dungeon.name)
                        checks_in_area[location.player][dungeonname].append(location.address)
                    elif location.parent_region.type == RegionType.LightWorld:
                        checks_in_area[location.player]["Light World"].append(location.address)
                    elif location.parent_region.type == RegionType.DarkWorld:
                        checks_in_area[location.player]["Dark World"].append(location.address)
                    elif main_entrance.parent_region.type == RegionType.LightWorld:
                        checks_in_area[location.player]["Light World"].append(location.address)
                    elif main_entrance.parent_region.type == RegionType.DarkWorld:
                        checks_in_area[location.player]["Dark World"].append(location.address)
                    checks_in_area[location.player]["Total"] += 1

            oldmancaves = []
            takeanyregions = ["Old Man Sword Cave", "Take-Any #1", "Take-Any #2", "Take-Any #3", "Take-Any #4"]
            for index, take_any in enumerate(takeanyregions):
                for region in [world.get_region(take_any, player) for player in
                               world.get_game_players("A Link to the Past") if world.retro_caves[player]]:
                    item = world.create_item(
                        region.shop.inventory[(0 if take_any == "Old Man Sword Cave" else 1)]['item'],
                        region.player)
                    player = region.player
                    location_id = SHOP_ID_START + total_shop_slots + index

                    main_entrance = get_entrance_to_region(region)
                    if main_entrance.parent_region.type == RegionType.LightWorld:
                        checks_in_area[player]["Light World"].append(location_id)
                    else:
                        checks_in_area[player]["Dark World"].append(location_id)
                    checks_in_area[player]["Total"] += 1

                    er_hint_data[player][location_id] = main_entrance.name
                    oldmancaves.append(((location_id, player), (item.code, player)))

            FillDisabledShopSlots(world)

            def write_multidata():
                import NetUtils
                slot_data = {}
                client_versions = {}
                games = {}
                minimum_versions = {"server": AutoWorld.World.required_server_version, "clients": client_versions}
                slot_info = {}
                names = [[name for player, name in sorted(world.player_name.items())]]
                for slot in world.player_ids:
                    player_world: AutoWorld.World = world.worlds[slot]
                    minimum_versions["server"] = max(minimum_versions["server"], player_world.required_server_version)
                    client_versions[slot] = player_world.required_client_version
                    games[slot] = world.game[slot]
                    slot_info[slot] = NetUtils.NetworkSlot(names[0][slot - 1], world.game[slot],
                                                           world.player_types[slot])
                for slot, group in world.groups.items():
                    games[slot] = world.game[slot]
                    slot_info[slot] = NetUtils.NetworkSlot(group["name"], world.game[slot], world.player_types[slot],
                                                           group_members=sorted(group["players"]))
                precollected_items = {player: [item.code for item in world_precollected if type(item.code) == int]
                                      for player, world_precollected in world.precollected_items.items()}
                precollected_hints = {player: set() for player in range(1, world.players + 1 + len(world.groups))}


                for slot in world.player_ids:
                    slot_data[slot] = world.worlds[slot].fill_slot_data()

                def precollect_hint(location):
                    entrance = er_hint_data.get(location.player, {}).get(location.address, "")
                    hint = NetUtils.Hint(location.item.player, location.player, location.address,
                                         location.item.code, False, entrance, location.item.flags)
                    precollected_hints[location.player].add(hint)
                    if location.item.player not in world.groups:
                        precollected_hints[location.item.player].add(hint)
                    else:
                        for player in world.groups[location.item.player]["players"]:
                            precollected_hints[player].add(hint)

                locations_data: Dict[int, Dict[int, Tuple[int, int, int]]] = {player: {} for player in world.player_ids}
                for location in world.get_filled_locations():
                    if type(location.address) == int:
                        assert location.item.code is not None, "item code None should be event, " \
                                                               "location.address should then also be None"
                        locations_data[location.player][location.address] = \
                            location.item.code, location.item.player, location.item.flags
                        if location.name in world.start_location_hints[location.player]:
                            precollect_hint(location)
                        elif location.item.name in world.start_hints[location.item.player]:
                            precollect_hint(location)
                        elif any([location.item.name in world.start_hints[player]
                                  for player in world.groups.get(location.item.player, {}).get("players", [])]):
                            precollect_hint(location)

                multidata = {
                    "slot_data": slot_data,
                    "slot_info": slot_info,
                    "names": names,  # TODO: remove around 0.2.5 in favor of slot_info
                    "games": games,  # TODO: remove around 0.2.5 in favor of slot_info
                    "connect_names": {name: (0, player) for player, name in world.player_name.items()},
                    "remote_items": {player for player in world.player_ids if
                                     world.worlds[player].remote_items},
                    "remote_start_inventory": {player for player in world.player_ids if
                                               world.worlds[player].remote_start_inventory},
                    "locations": locations_data,
                    "checks_in_area": checks_in_area,
                    "server_options": baked_server_options,
                    "er_hint_data": er_hint_data,
                    "precollected_items": precollected_items,
                    "precollected_hints": precollected_hints,
                    "version": tuple(version_tuple),
                    "tags": ["AP"],
                    "minimum_versions": minimum_versions,
                    "seed_name": world.seed_name
                }
                AutoWorld.call_all(world, "modify_multidata", multidata)

                multidata = zlib.compress(pickle.dumps(multidata), 9)

                with open(os.path.join(temp_dir, f'{outfilebase}.archipelago'), 'wb') as f:
                    f.write(bytes([3]))  # version of format
                    f.write(multidata)

            multidata_task = pool.submit(write_multidata)
            if not check_accessibility_task.result():
                if not world.can_beat_game():
                    raise Exception("Game appears as unbeatable. Aborting.")
                else:
                    logger.warning("Location Accessibility requirements not fulfilled.")

            # retrieve exceptions via .result() if they occurred.
            multidata_task.result()
            for i, future in enumerate(concurrent.futures.as_completed(output_file_futures), start=1):
                if i % 10 == 0 or i == len(output_file_futures):
                    logger.info(f'Generating output files ({i}/{len(output_file_futures)}).')
                future.result()

        if args.spoiler > 1:
            logger.info('Calculating playthrough.')
            create_playthrough(world)

        if args.spoiler:
            world.spoiler.to_file(os.path.join(temp_dir, '%s_Spoiler.txt' % outfilebase))

        zipfilename = output_path(f"AP_{world.seed_name}.zip")
        logger.info(f'Creating final archive at {zipfilename}.')
        with zipfile.ZipFile(zipfilename, mode="w", compression=zipfile.ZIP_DEFLATED,
                             compresslevel=9) as zf:
            for file in os.scandir(temp_dir):
                zf.write(file.path, arcname=file.name)

    logger.info('Done. Enjoy. Total Time: %s', time.perf_counter() - start)
    return world
Esempio n. 21
0
def set_rules(world: MultiWorld, player: int):

    # Act 1 Card Draws
    set_rule(world.get_location("Card Draw 1", player), lambda state: True)
    set_rule(world.get_location("Card Draw 2", player), lambda state: True)
    set_rule(world.get_location("Card Draw 3", player), lambda state: True)
    set_rule(world.get_location("Card Draw 4", player), lambda state: state._spire_has_relics(player, 1))
    set_rule(world.get_location("Card Draw 5", player), lambda state: state._spire_has_relics(player, 1))

    # Act 1 Relics
    set_rule(world.get_location("Relic 1", player), lambda state: state._spire_has_cards(player, 1))
    set_rule(world.get_location("Relic 2", player), lambda state: state._spire_has_cards(player, 2))
    set_rule(world.get_location("Relic 3", player), lambda state: state._spire_has_cards(player, 2))

    # Act 1 Boss Event
    set_rule(world.get_location("Act 1 Boss", player), lambda state: state._spire_has_cards(player, 3) and state._spire_has_relics(player, 2))

    # Act 1 Boss Rewards
    set_rule(world.get_location("Rare Card Draw 1", player), lambda state: state.has("Beat Act 1 Boss", player))
    set_rule(world.get_location("Boss Relic 1", player), lambda state: state.has("Beat Act 1 Boss", player))

    # Act 2 Card Draws
    set_rule(world.get_location("Card Draw 6", player), lambda state: state.has("Beat Act 1 Boss", player))
    set_rule(world.get_location("Card Draw 7", player), lambda state: state.has("Beat Act 1 Boss", player))
    set_rule(world.get_location("Card Draw 8", player), lambda state: state.has("Beat Act 1 Boss", player) and state._spire_has_cards(player, 6) and state._spire_has_relics(player, 3))
    set_rule(world.get_location("Card Draw 9", player), lambda state: state.has("Beat Act 1 Boss", player) and state._spire_has_cards(player, 6) and state._spire_has_relics(player, 4))
    set_rule(world.get_location("Card Draw 10", player), lambda state: state.has("Beat Act 1 Boss", player) and state._spire_has_cards(player, 7) and state._spire_has_relics(player, 4))

    # Act 2 Relics
    set_rule(world.get_location("Relic 4", player), lambda state: state.has("Beat Act 1 Boss", player) and state._spire_has_cards(player, 7) and state._spire_has_relics(player, 2))
    set_rule(world.get_location("Relic 5", player), lambda state: state.has("Beat Act 1 Boss", player) and state._spire_has_cards(player, 7) and state._spire_has_relics(player, 2))
    set_rule(world.get_location("Relic 6", player), lambda state: state.has("Beat Act 1 Boss", player) and state._spire_has_cards(player, 7) and state._spire_has_relics(player, 3))

    # Act 2 Boss Event
    set_rule(world.get_location("Act 2 Boss", player), lambda state: state.has("Beat Act 1 Boss", player) and state._spire_has_cards(player, 7) and state._spire_has_relics(player, 4) and state.has("Boss Relic", player))

    # Act 2 Boss Rewards
    set_rule(world.get_location("Rare Card Draw 2", player), lambda state: state.has("Beat Act 2 Boss", player))
    set_rule(world.get_location("Boss Relic 2", player), lambda state: state.has("Beat Act 2 Boss", player))

    # Act 3 Card Draws
    set_rule(world.get_location("Card Draw 11", player), lambda state: state.has("Beat Act 2 Boss", player))
    set_rule(world.get_location("Card Draw 12", player), lambda state: state.has("Beat Act 2 Boss", player))
    set_rule(world.get_location("Card Draw 13", player), lambda state: state.has("Beat Act 2 Boss", player) and state._spire_has_relics(player, 4))
    set_rule(world.get_location("Card Draw 14", player), lambda state: state.has("Beat Act 2 Boss", player) and state._spire_has_relics(player, 4))
    set_rule(world.get_location("Card Draw 15", player), lambda state: state.has("Beat Act 2 Boss", player) and state._spire_has_relics(player, 4))

    # Act 3 Relics
    set_rule(world.get_location("Relic 7", player), lambda state: state.has("Beat Act 2 Boss", player) and state._spire_has_relics(player, 4))
    set_rule(world.get_location("Relic 8", player), lambda state: state.has("Beat Act 2 Boss", player) and state._spire_has_relics(player, 5))
    set_rule(world.get_location("Relic 9", player), lambda state: state.has("Beat Act 2 Boss", player) and state._spire_has_relics(player, 5))
    set_rule(world.get_location("Relic 10", player), lambda state: state.has("Beat Act 2 Boss", player) and state._spire_has_relics(player, 5))

    # Act 3 Boss Event
    set_rule(world.get_location("Act 3 Boss", player), lambda state: state.has("Beat Act 2 Boss", player) and state._spire_has_relics(player, 7) and state.has("Boss Relic", player, 2))

    # Act 3 Boss Rewards
    set_rule(world.get_location("Rare Card Draw 3", player), lambda state: state.has("Beat Act 3 Boss", player))
    set_rule(world.get_location("Boss Relic 3", player), lambda state: state.has("Beat Act 3 Boss", player))

    set_rule(world.get_location("Heart Room", player), lambda state: state.has("Beat Act 3 Boss", player))
Esempio n. 22
0
def set_advancement_rules(world: MultiWorld, player: int):

    # Retrieves the appropriate structure compass for the given entrance
    def get_struct_compass(entrance_name):
        struct = world.get_entrance(entrance_name,
                                    player).connected_region.name
        return f"Structure Compass ({struct})"

    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._mc_has_iron_ingots(player))
    set_rule(
        world.get_entrance("End Portal", player),
        lambda state: state._mc_enter_stronghold(player) and state.has(
            '3 Ender Pearls', player, 4))
    set_rule(
        world.get_entrance("Overworld Structure 1", player),
        lambda state: state._mc_can_adventure(player) and state.
        _mc_has_structure_compass("Overworld Structure 1", player))
    set_rule(
        world.get_entrance("Overworld Structure 2", player),
        lambda state: state._mc_can_adventure(player) and state.
        _mc_has_structure_compass("Overworld Structure 2", player))
    set_rule(
        world.get_entrance("Nether Structure 1", player),
        lambda state: state._mc_can_adventure(player) and state.
        _mc_has_structure_compass("Nether Structure 1", player))
    set_rule(
        world.get_entrance("Nether Structure 2", player),
        lambda state: state._mc_can_adventure(player) and state.
        _mc_has_structure_compass("Nether Structure 2", player))
    set_rule(
        world.get_entrance("The End Structure", player),
        lambda state: state._mc_can_adventure(player) and state.
        _mc_has_structure_compass("The End Structure", player))

    set_rule(world.get_location("Ender Dragon", player),
             lambda state: state._mc_can_kill_ender_dragon(player))
    set_rule(world.get_location("Wither", player),
             lambda state: state._mc_can_kill_wither(player))
    set_rule(world.get_location("Blaze Spawner", player),
             lambda state: state._mc_fortress_loot(player))

    set_rule(world.get_location("Who is Cutting Onions?", player),
             lambda state: state._mc_can_piglin_trade(player))
    set_rule(world.get_location("Oh Shiny", player),
             lambda state: state._mc_can_piglin_trade(player))
    set_rule(
        world.get_location("Suit Up", player), lambda state: state.has(
            "Progressive Armor", player) and state._mc_has_iron_ingots(player))
    set_rule(
        world.get_location("Very Very Frightening", player),
        lambda state: state.has("Channeling Book", player) and state.
        _mc_can_use_anvil(player) and state._mc_can_enchant(
            player) and state._mc_overworld_villager(player))
    set_rule(
        world.get_location("Hot Stuff", player), lambda state: state.has(
            "Bucket", player) and state._mc_has_iron_ingots(player))
    set_rule(
        world.get_location("Free the End", player),
        lambda state: state._mc_can_respawn_ender_dragon(
            player) and state._mc_can_kill_ender_dragon(player))
    set_rule(
        world.get_location("A Furious Cocktail", player),
        lambda state: state._mc_can_brew_potions(player) and state.has(
            "Fishing Rod", player) and  # Water Breathing
        state.can_reach('The Nether', 'Region', player
                        ) and  # Regeneration, Fire Resistance, gold nuggets
        state.can_reach('Village', 'Region', player
                        ) and  # Night Vision, Invisibility
        state.can_reach('Bring Home the Beacon', 'Location', player)
    )  # Resistance
    # 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._mc_can_kill_wither(
            player) and state._mc_has_diamond_pickaxe(player) and state.has(
                "Progressive Resource Crafting", player, 2))
    set_rule(
        world.get_location("Not Today, Thank You", player), lambda state: state
        .has("Shield", player) and state._mc_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._mc_has_iron_ingots(player))
    set_rule(world.get_location("Local Brewery", player),
             lambda state: state._mc_can_brew_potions(player))
    set_rule(world.get_location("The Next Generation", player),
             lambda state: state._mc_can_kill_ender_dragon(player))
    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: True)
    set_rule(
        world.get_location("This Boat Has Legs", player), lambda state:
        (state._mc_fortress_loot(player) or state._mc_complete_raid(player))
        and state.has("Saddle", 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._mc_basic_combat(player))
    set_rule(
        world.get_location("How Did We Get Here?", player),
        lambda state: state._mc_can_brew_potions(
            player) and state._mc_has_gold_ingots(player) and  # Absorption
        state.can_reach('End City', 'Region', player) and  # Levitation
        state.can_reach('The Nether', 'Region', player
                        ) and  # 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._mc_has_iron_ingots(player))
    set_rule(world.get_location("Spooky Scary Skeleton", player),
             lambda state: state._mc_basic_combat(player))
    set_rule(
        world.get_location("Two by Two",
                           player), lambda state: state._mc_has_iron_ingots(
                               player) and state._mc_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
        ._mc_craft_crossbow(player) and state._mc_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._mc_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._mc_has_iron_ingots(player))
    set_rule(
        world.get_location("Zombie Doctor", player), lambda state: state.
        _mc_can_brew_potions(player) and state._mc_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._mc_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._mc_basic_combat(player))
    set_rule(world.get_location("War Pigs", player),
             lambda state: state._mc_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.
        _mc_can_use_anvil(player) and state._mc_can_enchant(player))
    set_rule(
        world.get_location("Arbalistic", player),
        lambda state: state._mc_craft_crossbow(player) and state.has(
            "Piercing IV Book", player) and state._mc_can_use_anvil(
                player) and state._mc_can_enchant(player))
    set_rule(
        world.get_location("The End... Again...", player),
        lambda state: state._mc_can_respawn_ender_dragon(
            player) and state._mc_can_kill_ender_dragon(player))
    set_rule(world.get_location("Acquire Hardware", player),
             lambda state: state._mc_has_iron_ingots(player))
    set_rule(
        world.get_location("Not Quite \"Nine\" Lives", player),
        lambda state: state._mc_can_piglin_trade(player) and state.has(
            "Progressive Resource Crafting", player, 2))
    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._mc_basic_combat(player))
    set_rule(
        world.get_location("Hired Help", player),
        lambda state: state.has("Progressive Resource Crafting", player, 2
                                ) and state._mc_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: state.
        _mc_can_respawn_ender_dragon(player) and state._mc_has_bottle(player))
    # set_rule(world.get_location("Adventure", player), lambda state: True)
    set_rule(
        world.get_location("Monsters Hunted", player),
        lambda state: state._mc_can_respawn_ender_dragon(player) and state.
        _mc_can_kill_ender_dragon(player) and state._mc_can_kill_wither(player)
        and state.has("Fishing Rod", player))  # pufferfish for Water Breathing
    set_rule(world.get_location("Enchanter", player),
             lambda state: state._mc_can_enchant(player))
    set_rule(world.get_location("Voluntary Exile", player),
             lambda state: state._mc_basic_combat(player))
    set_rule(world.get_location("Eye Spy", player),
             lambda state: state._mc_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._mc_has_gold_ingots(player))
    set_rule(world.get_location("Postmortal", player),
             lambda state: state._mc_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._mc_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._mc_complete_raid(player))
    set_rule(world.get_location("Hidden in the Depths", player),
             lambda state: state._mc_can_brew_potions(player) and state.has(
                 "Bed", player) and state._mc_has_diamond_pickaxe(
                     player))  # bed mining :)
    set_rule(
        world.get_location("Beaconator", player),
        lambda state: state._mc_can_kill_wither(
            player) and state._mc_has_diamond_pickaxe(player) and state.has(
                "Progressive Resource Crafting", player, 2))
    set_rule(world.get_location("Withering Heights", player),
             lambda state: state._mc_can_kill_wither(player))
    set_rule(
        world.get_location("A Balanced Diet", player),
        lambda state: state._mc_has_bottle(player) and state.
        _mc_has_gold_ingots(player) and  # honey bottle; gapple
        state.has("Progressive Resource Crafting", player, 2) and state.
        can_reach('The End', 'Region', player))  # notch apple, chorus fruit
    set_rule(world.get_location("Subspace Bubble", player),
             lambda state: state._mc_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._mc_has_gold_ingots(player))
    set_rule(
        world.get_location("Bee Our Guest", player), lambda state: state.has(
            "Campfire", player) and state._mc_has_bottle(player))
    # set_rule(world.get_location("What a Deal!", player), lambda state: True)
    set_rule(
        world.get_location("Uneasy Alliance", player),
        lambda state: state._mc_has_diamond_pickaxe(player) and state.has(
            'Fishing Rod', player))
    set_rule(
        world.get_location("Diamonds!", player),
        lambda state: state.has("Progressive Tools", player, 2
                                ) and state._mc_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: state._mc_can_adventure(player))  # kill drowned
    # set_rule(world.get_location("Minecraft", player), lambda state: True)
    set_rule(
        world.get_location("Sticky Situation", player), lambda state: state.
        has("Campfire", player) and state._mc_has_bottle(player))
    set_rule(world.get_location("Ol' Betsy", player),
             lambda state: state._mc_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(
                "Progressive Resource 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("Progressive Resource Crafting", player))
    # set_rule(world.get_location("Bake Bread", player), lambda state: True)
    set_rule(
        world.get_location("The Lie", player),
        lambda state: state._mc_has_iron_ingots(player) and state.has(
            "Bucket", player))
    set_rule(world.get_location("On a Rail", player),
             lambda state: state._mc_has_iron_ingots(player) and state.has(
                 'Progressive Tools', player, 2))  # powered rails
    # 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._mc_fortress_loot(player) or state._mc_complete_raid(player)
         ) and state.has("Saddle", player) and state.has(
             "Fishing Rod", player) and state._mc_can_adventure(player))
    set_rule(world.get_location("Overkill", player),
             lambda state: state._mc_can_brew_potions(player) and
             (state.has("Progressive Weapons", player) or state.can_reach(
                 'The Nether', 'Region', player)
              ))  # strength 1 + stone axe crit OR strength 2 + wood 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._mc_has_iron_ingots(player) and state.has(
                 'Progressive Tools', player, 2) and state._mc_basic_combat(
                     player))  # mine gold blocks w/ iron pick
    set_rule(
        world.get_location("Wax On", player),
        lambda state: state._mc_has_copper_ingots(player) and state.has(
            'Campfire', player) and state.has('Progressive Resource Crafting',
                                              player, 2))
    set_rule(
        world.get_location("Wax Off", player),
        lambda state: state._mc_has_copper_ingots(player) and state.has(
            'Campfire', player) and state.has('Progressive Resource Crafting',
                                              player, 2))
    set_rule(
        world.get_location("The Cutest Predator", player),
        lambda state: state._mc_has_iron_ingots(player) and state.has(
            'Bucket', player))
    set_rule(
        world.get_location("The Healing Power of Friendship", player),
        lambda state: state._mc_has_iron_ingots(player) and state.has(
            'Bucket', player))
    set_rule(
        world.get_location("Is It a Bird?", player), lambda state: state.
        _mc_has_spyglass(player) and state._mc_can_adventure(player))
    set_rule(world.get_location("Is It a Balloon?", player),
             lambda state: state._mc_has_spyglass(player))
    set_rule(
        world.get_location("Is It a Plane?", player),
        lambda state: state._mc_has_spyglass(
            player) and state._mc_can_respawn_ender_dragon(player))
    set_rule(
        world.get_location("Surge Protector", player), lambda state: state.has(
            "Channeling Book", player) and state._mc_can_use_anvil(player) and
        state._mc_can_enchant(player) and state._mc_overworld_villager(player))
    set_rule(
        world.get_location("Light as a Rabbit", player),
        lambda state: state._mc_can_adventure(player) and state.
        _mc_has_iron_ingots(player) and state.has('Bucket', player))
    set_rule(world.get_location("Glow and Behold!", player),
             lambda state: state._mc_can_adventure(player))
    set_rule(world.get_location("Whatever Floats Your Goat!", player),
             lambda state: state._mc_can_adventure(player))
    set_rule(
        world.get_location("Caves & Cliffs", player),
        lambda state: state._mc_has_iron_ingots(player) and state.has(
            'Bucket', player) and state.has('Progressive Tools', player, 2))
    set_rule(
        world.get_location("Feels like home", player),
        lambda state: state._mc_has_iron_ingots(player) and state.has(
            'Bucket', player) and state.has('Fishing Rod', player) and
        (state._mc_fortress_loot(player) or state._mc_complete_raid(player)
         ) and state.has("Saddle", player))
    set_rule(
        world.get_location("Sound of Music", player),
        lambda state: state.can_reach("Diamonds!", "Location", player
                                      ) and state._mc_basic_combat(player))
    set_rule(
        world.get_location("Star Trader", player),
        lambda state: state._mc_has_iron_ingots(player) and state.has(
            'Bucket', player) and
        (state.can_reach("The Nether", 'Region', player) or state.can_reach(
            "Nether Fortress", 'Region', player) or state._mc_can_piglin_trade(
                player)) and  # soul sand for water elevator
        state._mc_overworld_villager(player))

    # 1.19 advancements

    # can make a cake, and can reach a pillager outposts for allays
    set_rule(world.get_location("Birthday Song", player),
             lambda state: state.can_reach("The Lie", "Location", player))
    # find allay and craft a noteblock
    set_rule(
        world.get_location("You've Got a Friend in Me", player),
        lambda state: state.has("Progressive Tools", player, 2
                                ) and state._mc_has_iron_ingots(player))
    # craft bucket and adventure to find frog spawning biome
    set_rule(
        world.get_location("Bukkit Bukkit", player),
        lambda state: state.has("Bucket", player) and state.
        _mc_has_iron_ingots(player) and state._mc_can_adventure(player))
    # I don't like this one its way to easy to get. just a pain to find.
    set_rule(
        world.get_location("It Spreads", player),
        lambda state: state._mc_can_adventure(
            player) and state._mc_has_iron_ingots(player) and state.has(
                "Progressive Tools", player, 2))
    # literally just a duplicate of It spreads.
    set_rule(
        world.get_location("Sneak 100", player),
        lambda state: state._mc_can_adventure(
            player) and state._mc_has_iron_ingots(player) and state.has(
                "Progressive Tools", player, 2))
    set_rule(
        world.get_location("When the Squad Hops into Town", player),
        lambda state: state._mc_can_adventure(player) and state.has(
            "Lead", player))
    # lead frogs to the nether and a basalt delta's biomes to find magma cubes.
    set_rule(
        world.get_location("With Our Powers Combined!", player),
        lambda state: state._mc_can_adventure(player) and state.has(
            "Lead", player))