diff --git a/worlds/mmbn3/Items.py b/worlds/mmbn3/Items.py index 30ec311e..7e3458c9 100644 --- a/worlds/mmbn3/Items.py +++ b/worlds/mmbn3/Items.py @@ -85,7 +85,7 @@ keyItemList: typing.List[ItemData] = [ ] subChipList: typing.List[ItemData] = [ - ItemData(0xB31018, ItemName.Unlocker, ItemClassification.useful, ItemType.SubChip, 117), + ItemData(0xB31018, ItemName.Unlocker, ItemClassification.progression, ItemType.SubChip, 117), ItemData(0xB31019, ItemName.Untrap, ItemClassification.filler, ItemType.SubChip, 115), ItemData(0xB3101A, ItemName.LockEnmy, ItemClassification.filler, ItemType.SubChip, 116), ItemData(0xB3101B, ItemName.MiniEnrg, ItemClassification.filler, ItemType.SubChip, 112), @@ -290,7 +290,9 @@ programList: typing.List[ItemData] = [ ItemData(0xB31099, ItemName.WpnLV_plus_Yellow, ItemClassification.filler, ItemType.Program, 35, ProgramColor.Yellow), ItemData(0xB3109A, ItemName.Press, ItemClassification.progression, ItemType.Program, 20, ProgramColor.White), - ItemData(0xB310B7, ItemName.UnderSht, ItemClassification.useful, ItemType.Program, 30, ProgramColor.White) + ItemData(0xB310B7, ItemName.UnderSht, ItemClassification.useful, ItemType.Program, 30, ProgramColor.White), + ItemData(0xB310E0, ItemName.Humor, ItemClassification.progression, ItemType.Program, 45, ProgramColor.Pink), + ItemData(0xB310E1, ItemName.BlckMnd, ItemClassification.progression, ItemType.Program, 46, ProgramColor.White) ] zennyList: typing.List[ItemData] = [ @@ -338,8 +340,29 @@ item_frequencies: typing.Dict[str, int] = { ItemName.zenny_800z: 2, ItemName.zenny_1000z: 2, ItemName.zenny_1200z: 2, - ItemName.bugfrag_01: 5, + ItemName.bugfrag_01: 10, + ItemName.bugfrag_10: 5 } + +item_groups: typing.Dict[str, typing.Set[str]] = { + "Key Items": {loc.itemName for loc in keyItemList}, + "Subchips": {loc.itemName for loc in subChipList}, + "Programs": {loc.itemName for loc in programList}, + "BattleChips": {loc.itemName for loc in chipList}, + "Zenny": {loc.itemName for loc in zennyList}, + "BugFrags": {loc.itemName for loc in bugFragList}, + "Navi Chips": { + ItemName.Roll_R, ItemName.RollV2_R, ItemName.RollV3_R, ItemName.GutsMan_G, ItemName.GutsManV2_G, + ItemName.GutsManV3_G, ItemName.ProtoMan_B, ItemName.ProtoManV2_B, ItemName.ProtoManV3_B, ItemName.FlashMan_F, + ItemName.FlashManV2_F, ItemName.FlashManV3_F, ItemName.BeastMan_B, ItemName.BeastManV2_B, ItemName.BeastManV3_B, + ItemName.BubblMan_B, ItemName.BubblManV2_B, ItemName.BubblManV3_B, ItemName.DesertMan_D, ItemName.DesertManV2_D, + ItemName.DesertManV3_D, ItemName.PlantMan_P, ItemName.PlantManV2_P, ItemName.PlantManV3_P, ItemName.FlamMan_F, + ItemName.FlamManV2_F, ItemName.FlamManV3_F, ItemName.DrillMan_D, ItemName.DrillManV2_D, ItemName.DrillManV3_D, + ItemName.MetalMan_M, ItemName.MetalManV2_M, ItemName.MetalManV3_M, ItemName.KingMan_K, ItemName.KingManV2_K, + ItemName.KingManV3_K, ItemName.BowlMan_B, ItemName.BowlManV2_B, ItemName.BowlManV3_B + } +} + all_items: typing.List[ItemData] = keyItemList + subChipList + chipList + programList + zennyList + bugFragList item_table: typing.Dict[str, ItemData] = {item.itemName: item for item in all_items} items_by_id: typing.Dict[int, ItemData] = {item.code: item for item in all_items} diff --git a/worlds/mmbn3/Locations.py b/worlds/mmbn3/Locations.py index 0e2a1c51..bc16c99a 100644 --- a/worlds/mmbn3/Locations.py +++ b/worlds/mmbn3/Locations.py @@ -221,7 +221,8 @@ overworlds = [ LocationData(LocationName.Hades_Boat_Dock, 0xb310ab, 0x200024c, 0x10, 0x7519B0, 223, [3]), LocationData(LocationName.WWW_Control_Room_1_Screen, 0xb310ac, 0x200024d, 0x40, 0x7596C4, 222, [3, 4]), LocationData(LocationName.WWW_Wilys_Desk, 0xb310ad, 0x200024d, 0x2, 0x759384, 229, [3]), - LocationData(LocationName.Undernet_4_Pillar_Prog, 0xb310ae, 0x2000161, 0x1, 0x7746C8, 191, [0, 1]) + LocationData(LocationName.Undernet_4_Pillar_Prog, 0xb310ae, 0x2000161, 0x1, 0x7746C8, 191, [0, 1]), + LocationData(LocationName.Serenade, 0xb3110f, 0x2000178, 0x40, 0x7B3C74, 1, [0]) ] jobs = [ @@ -240,7 +241,8 @@ jobs = [ # LocationData(LocationName.Gathering_Data, 0xb310bb, 0x2000300, 0x10, 0x739580, 193, [0]), LocationData(LocationName.Somebody_please_help, 0xb310bc, 0x2000301, 0x4, 0x73A14C, 193, [0]), LocationData(LocationName.Looking_for_condor, 0xb310bd, 0x2000301, 0x2, 0x749444, 203, [0]), - LocationData(LocationName.Help_with_rehab, 0xb310be, 0x2000301, 0x1, 0x762CF0, 192, [3]), + LocationData(LocationName.Help_with_rehab, 0xb310be, 0x2000301, 0x1, 0x762CF0, 192, [0]), + LocationData(LocationName.Help_with_rehab_bonus, 0xb3110e, 0x2000301, 0x1, 0x762CF0, 192, [3]), LocationData(LocationName.Old_Master, 0xb310bf, 0x2000302, 0x80, 0x760E80, 193, [0]), LocationData(LocationName.Catching_gang_members, 0xb310c0, 0x2000302, 0x40, 0x76EAE4, 193, [0]), LocationData(LocationName.Please_adopt_a_virus, 0xb310c1, 0x2000302, 0x20, 0x76A4F4, 193, [0]), @@ -250,7 +252,7 @@ jobs = [ LocationData(LocationName.Hide_and_seek_Second_Child, 0xb310c5, 0x2000188, 0x2, 0x75ADA8, 191, [0]), LocationData(LocationName.Hide_and_seek_Third_Child, 0xb310c6, 0x2000188, 0x1, 0x75B5EC, 191, [0]), LocationData(LocationName.Hide_and_seek_Fourth_Child, 0xb310c7, 0x2000189, 0x80, 0x75BEB0, 191, [0]), - LocationData(LocationName.Hide_and_seek_Completion, 0xb310c8, 0x2000302, 0x8, 0x7406A0, 193, [0]), + LocationData(LocationName.Hide_and_seek_Completion, 0xb310c8, 0x2000302, 0x8, 0x742D40, 193, [0]), LocationData(LocationName.Finding_the_blue_Navi, 0xb310c9, 0x2000302, 0x4, 0x773700, 192, [0]), LocationData(LocationName.Give_your_support, 0xb310ca, 0x2000302, 0x2, 0x752D80, 192, [0]), LocationData(LocationName.Stamp_collecting, 0xb310cb, 0x2000302, 0x1, 0x756074, 193, [0]), @@ -329,10 +331,7 @@ chocolate_shop = [ LocationData(LocationName.Chocolate_Shop_32, 0xb3110d, 0x20001c3, 0x01, 0x73F8FC, 181, [0]), ] -always_excluded_locations = [ - LocationName.Undernet_7_PMD, - LocationName.Undernet_7_Northeast_BMD, - LocationName.Undernet_7_Northwest_BMD, +secret_locations = { LocationName.Secret_1_Northwest_BMD, LocationName.Secret_1_Northeast_BMD, LocationName.Secret_1_South_BMD, @@ -341,19 +340,23 @@ always_excluded_locations = [ LocationName.Secret_2_Island_BMD, LocationName.Secret_3_Island_BMD, LocationName.Secret_3_BugFrag_BMD, - LocationName.Secret_3_South_BMD -] + LocationName.Secret_3_South_BMD, + LocationName.Serenade +} +location_groups: typing.Dict[str, typing.Set[str]] = { + "BMDs": {loc.name for loc in bmds}, + "PMDs": {loc.name for loc in pmds}, + "Jobs": {loc.name for loc in jobs}, + "Number Trader": {loc.name for loc in number_traders}, + "Bugfrag Trader": {loc.name for loc in chocolate_shop}, + "Secret Area": {LocationName.Secret_1_Northwest_BMD, LocationName.Secret_1_Northeast_BMD, + LocationName.Secret_1_South_BMD, LocationName.Secret_2_Upper_BMD, LocationName.Secret_2_Lower_BMD, + LocationName.Secret_2_Island_BMD, LocationName.Secret_3_Island_BMD, + LocationName.Secret_3_BugFrag_BMD, LocationName.Secret_3_South_BMD, LocationName.Serenade}, +} all_locations: typing.List[LocationData] = bmds + pmds + overworlds + jobs + number_traders + chocolate_shop scoutable_locations: typing.List[LocationData] = [loc for loc in all_locations if loc.hint_flag is not None] location_table: typing.Dict[str, int] = {locData.name: locData.id for locData in all_locations} location_data_table: typing.Dict[str, LocationData] = {locData.name: locData for locData in all_locations} - - -""" -def setup_locations(world, player: int): - # If we later include options to change what gets added to the random pool, - # this is where they would be changed - return {locData.name: locData.id for locData in all_locations} -""" diff --git a/worlds/mmbn3/Names/ItemName.py b/worlds/mmbn3/Names/ItemName.py index 677eff22..af645db9 100644 --- a/worlds/mmbn3/Names/ItemName.py +++ b/worlds/mmbn3/Names/ItemName.py @@ -173,6 +173,8 @@ class ItemName(): WpnLV_plus_White = "WpnLV+1 (White)" Press = "Press" UnderSht = "UnderSht" + Humor = "Humor" + BlckMnd = "BlckMnd" ## Currency zenny_200z = "200z" diff --git a/worlds/mmbn3/Names/LocationName.py b/worlds/mmbn3/Names/LocationName.py index 36060b12..61c64faa 100644 --- a/worlds/mmbn3/Names/LocationName.py +++ b/worlds/mmbn3/Names/LocationName.py @@ -210,6 +210,7 @@ class LocationName(): WWW_Control_Room_1_Screen = "WWW Control Room 1 Screen" WWW_Wilys_Desk = "WWW Wily's Desk" Undernet_4_Pillar_Prog = "Undernet 4 Pillar Prog" + Serenade = "Serenade" ## Numberman Codes Numberman_Code_01 = "Numberman Code 01" @@ -261,6 +262,7 @@ class LocationName(): Somebody_please_help = "Job: Somebody, please help!" Looking_for_condor = "Job: Looking for condor" Help_with_rehab = "Job: Help with rehab" + Help_with_rehab_bonus = "Job: Help with rehab bonus" Old_Master = "Job: Old Master" Catching_gang_members = "Job: Catching gang members" Please_adopt_a_virus = "Job: Please adopt a virus!" diff --git a/worlds/mmbn3/Options.py b/worlds/mmbn3/Options.py index 4ed64e3d..a127d25d 100644 --- a/worlds/mmbn3/Options.py +++ b/worlds/mmbn3/Options.py @@ -1,5 +1,5 @@ from dataclasses import dataclass -from Options import Choice, Range, DefaultOnToggle, PerGameCommonOptions +from Options import Choice, Range, DefaultOnToggle, Toggle, PerGameCommonOptions class ExtraRanks(Range): @@ -17,10 +17,17 @@ class ExtraRanks(Range): class IncludeJobs(DefaultOnToggle): """ - Whether Jobs can be included in logic. + Whether Jobs can contain progression or useful items. """ display_name = "Include Jobs" + +class IncludeSecretArea(Toggle): + """ + Whether the Secret Area (including Serenade) can contain progression or useful items. + """ + display_name = "Include Secret Area" + # Possible logic options: # - Include Number Trader # - Include Secret Area @@ -46,5 +53,6 @@ class TradeQuestHinting(Choice): class MMBN3Options(PerGameCommonOptions): extra_ranks: ExtraRanks include_jobs: IncludeJobs + include_secret: IncludeSecretArea trade_quest_hinting: TradeQuestHinting \ No newline at end of file diff --git a/worlds/mmbn3/Regions.py b/worlds/mmbn3/Regions.py index 1dc58600..286e95a1 100644 --- a/worlds/mmbn3/Regions.py +++ b/worlds/mmbn3/Regions.py @@ -135,6 +135,7 @@ regions = [ LocationName.Somebody_please_help, LocationName.Looking_for_condor, LocationName.Help_with_rehab, + LocationName.Help_with_rehab_bonus, LocationName.Old_Master, LocationName.Catching_gang_members, LocationName.Please_adopt_a_virus, @@ -349,6 +350,7 @@ regions = [ LocationName.Secret_2_Upper_BMD, LocationName.Secret_3_Island_BMD, LocationName.Secret_3_South_BMD, - LocationName.Secret_3_BugFrag_BMD + LocationName.Secret_3_BugFrag_BMD, + LocationName.Serenade ]) ] diff --git a/worlds/mmbn3/__init__.py b/worlds/mmbn3/__init__.py index 6d28b101..08165a7d 100644 --- a/worlds/mmbn3/__init__.py +++ b/worlds/mmbn3/__init__.py @@ -9,14 +9,14 @@ from BaseClasses import Item, MultiWorld, Tutorial, ItemClassification, Region, from worlds.AutoWorld import WebWorld, World from .Rom import MMBN3DeltaPatch, LocalRom, get_base_rom_path -from .Items import MMBN3Item, ItemData, item_table, all_items, item_frequencies, items_by_id, ItemType +from .Items import MMBN3Item, ItemData, item_table, all_items, item_frequencies, items_by_id, ItemType, item_groups from .Locations import Location, MMBN3Location, all_locations, location_table, location_data_table, \ - always_excluded_locations, jobs + secret_locations, jobs, location_groups from .Options import MMBN3Options from .Regions import regions, RegionName from .Names.ItemName import ItemName from .Names.LocationName import LocationName -from worlds.generic.Rules import add_item_rule +from worlds.generic.Rules import add_item_rule, add_rule class MMBN3Settings(settings.Group): @@ -57,12 +57,16 @@ class MMBN3World(World): settings: typing.ClassVar[MMBN3Settings] topology_present = False + item_name_to_id = {name: data.code for name, data in item_table.items()} location_name_to_id = {loc_data.name: loc_data.id for loc_data in all_locations} - excluded_locations: typing.List[str] + excluded_locations: typing.Set[str] item_frequencies: typing.Dict[str, int] + location_name_groups = location_groups + item_name_groups = item_groups + web = MMBN3Web() def generate_early(self) -> None: @@ -74,10 +78,11 @@ class MMBN3World(World): if self.options.extra_ranks > 0: self.item_frequencies[ItemName.Progressive_Undernet_Rank] = 8 + self.options.extra_ranks + self.excluded_locations = set() + if not self.options.include_secret: + self.excluded_locations |= secret_locations if not self.options.include_jobs: - self.excluded_locations = always_excluded_locations + [job.name for job in jobs] - else: - self.excluded_locations = always_excluded_locations + self.excluded_locations |= {job.name for job in jobs} def create_regions(self) -> None: """ @@ -140,19 +145,19 @@ class MMBN3World(World): if connection == RegionName.SciLab_Cyberworld: entrance.access_rule = lambda state: \ state.has(ItemName.CSciPas, self.player) or \ - state.can_reach(RegionName.SciLab_Overworld, "Region", self.player) + state.can_reach_region(RegionName.SciLab_Overworld, self.player) self.multiworld.register_indirect_condition(self.get_region(RegionName.SciLab_Overworld), entrance) if connection == RegionName.Yoka_Cyberworld: entrance.access_rule = lambda state: \ state.has(ItemName.CYokaPas, self.player) or \ ( - state.can_reach(RegionName.SciLab_Overworld, "Region", self.player) and + state.can_reach_region(RegionName.SciLab_Overworld, self.player) and state.has(ItemName.Press, self.player) ) self.multiworld.register_indirect_condition(self.get_region(RegionName.SciLab_Overworld), entrance) if connection == RegionName.Beach_Cyberworld: entrance.access_rule = lambda state: state.has(ItemName.CBeacPas, self.player) and\ - state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) + state.can_reach_region(RegionName.Yoka_Overworld, self.player) self.multiworld.register_indirect_condition(self.get_region(RegionName.Yoka_Overworld), entrance) if connection == RegionName.Undernet: entrance.access_rule = lambda state: self.explore_score(state) > 8 and\ @@ -198,122 +203,138 @@ class MMBN3World(World): # Set WWW ID requirements def has_www_id(state): return state.has(ItemName.WWW_ID, self.player) - self.multiworld.get_location(LocationName.ACDC_1_PMD, self.player).access_rule = has_www_id - self.multiworld.get_location(LocationName.SciLab_1_WWW_BMD, self.player).access_rule = has_www_id - self.multiworld.get_location(LocationName.Yoka_1_WWW_BMD, self.player).access_rule = has_www_id - self.multiworld.get_location(LocationName.Undernet_1_WWW_BMD, self.player).access_rule = has_www_id + add_rule(self.multiworld.get_location(LocationName.ACDC_1_PMD, self.player), has_www_id) + add_rule(self.multiworld.get_location(LocationName.SciLab_1_WWW_BMD, self.player), has_www_id) + add_rule(self.multiworld.get_location(LocationName.Yoka_1_WWW_BMD, self.player), has_www_id) + add_rule(self.multiworld.get_location(LocationName.Undernet_1_WWW_BMD, self.player), has_www_id) # Set Press Program requirements def has_press(state): return state.has(ItemName.Press, self.player) - self.multiworld.get_location(LocationName.Yoka_1_PMD, self.player).access_rule = has_press - self.multiworld.get_location(LocationName.Yoka_2_Upper_BMD, self.player).access_rule = has_press - self.multiworld.get_location(LocationName.Beach_2_East_BMD, self.player).access_rule = has_press - self.multiworld.get_location(LocationName.Hades_South_BMD, self.player).access_rule = has_press - self.multiworld.get_location(LocationName.Secret_3_BugFrag_BMD, self.player).access_rule = has_press - self.multiworld.get_location(LocationName.Secret_3_Island_BMD, self.player).access_rule = has_press + add_rule(self.multiworld.get_location(LocationName.Yoka_1_PMD, self.player), has_press) + add_rule(self.multiworld.get_location(LocationName.Yoka_2_Upper_BMD, self.player), has_press) + add_rule(self.multiworld.get_location(LocationName.Beach_2_East_BMD, self.player), has_press) + add_rule(self.multiworld.get_location(LocationName.Hades_South_BMD, self.player), has_press) + add_rule(self.multiworld.get_location(LocationName.Secret_3_BugFrag_BMD, self.player), has_press) + add_rule(self.multiworld.get_location(LocationName.Secret_3_Island_BMD, self.player), has_press) + + # Set Purple Mystery Data Unlocker access + def can_unlock(state): return state.can_reach_region(RegionName.SciLab_Overworld, self.player) or \ + state.can_reach_region(RegionName.SciLab_Cyberworld, self.player) or \ + state.can_reach_region(RegionName.Yoka_Cyberworld, self.player) or \ + state.has(ItemName.Unlocker, self.player, 8) # There are 8 PMDs that aren't in one of the above areas + add_rule(self.multiworld.get_location(LocationName.ACDC_1_PMD, self.player), can_unlock) + add_rule(self.multiworld.get_location(LocationName.Yoka_1_PMD, self.player), can_unlock) + add_rule(self.multiworld.get_location(LocationName.Beach_1_PMD, self.player), can_unlock) + add_rule(self.multiworld.get_location(LocationName.Undernet_7_PMD, self.player), can_unlock) + add_rule(self.multiworld.get_location(LocationName.Mayls_HP_PMD, self.player), can_unlock) + add_rule(self.multiworld.get_location(LocationName.SciLab_Dads_Computer_PMD, self.player), can_unlock) + add_rule(self.multiworld.get_location(LocationName.Zoo_Panda_PMD, self.player), can_unlock) + add_rule(self.multiworld.get_location(LocationName.Beach_DNN_Security_Panel_PMD, self.player), can_unlock) + add_rule(self.multiworld.get_location(LocationName.Beach_DNN_Main_Console_PMD, self.player), can_unlock) + add_rule(self.multiworld.get_location(LocationName.Tamakos_HP_PMD, self.player), can_unlock) # Set Job additional area access self.multiworld.get_location(LocationName.Please_deliver_this, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.ACDC_Overworld, "Region", self.player) and \ - state.can_reach(RegionName.ACDC_Cyberworld, "Region", self.player) + state.can_reach_region(RegionName.ACDC_Overworld, self.player) and \ + state.can_reach_region(RegionName.ACDC_Cyberworld, self.player) self.multiworld.get_location(LocationName.My_Navi_is_sick, self.player).access_rule =\ lambda state: \ state.has(ItemName.Recov30_star, self.player) self.multiworld.get_location(LocationName.Help_me_with_my_son, self.player).access_rule =\ lambda state:\ - state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) and \ - state.can_reach(RegionName.ACDC_Cyberworld, "Region", self.player) + state.can_reach_region(RegionName.Yoka_Overworld, self.player) and \ + state.can_reach_region(RegionName.ACDC_Cyberworld, self.player) self.multiworld.get_location(LocationName.Transmission_error, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) + state.can_reach_region(RegionName.Yoka_Overworld, self.player) self.multiworld.get_location(LocationName.Chip_Prices, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.ACDC_Cyberworld, "Region", self.player) and \ - state.can_reach(RegionName.SciLab_Cyberworld, "Region", self.player) + state.can_reach_region(RegionName.ACDC_Cyberworld, self.player) and \ + state.can_reach_region(RegionName.SciLab_Cyberworld, self.player) self.multiworld.get_location(LocationName.Im_broke, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) and \ - state.can_reach(RegionName.Yoka_Cyberworld, "Region", self.player) + state.can_reach_region(RegionName.Yoka_Overworld, self.player) and \ + state.can_reach_region(RegionName.Yoka_Cyberworld, self.player) self.multiworld.get_location(LocationName.Rare_chips_for_cheap, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.ACDC_Overworld, "Region", self.player) + state.can_reach_region(RegionName.ACDC_Overworld, self.player) self.multiworld.get_location(LocationName.Be_my_boyfriend, self.player).access_rule =\ lambda state: \ - state.can_reach(RegionName.Beach_Cyberworld, "Region", self.player) + state.can_reach_region(RegionName.Beach_Cyberworld, self.player) self.multiworld.get_location(LocationName.Will_you_deliver, self.player).access_rule=\ lambda state: \ - state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) and \ - state.can_reach(RegionName.Beach_Overworld, "Region", self.player) and \ - state.can_reach(RegionName.ACDC_Cyberworld, "Region", self.player) + state.can_reach_region(RegionName.Yoka_Overworld, self.player) and \ + state.can_reach_region(RegionName.Beach_Overworld, self.player) and \ + state.can_reach_region(RegionName.ACDC_Cyberworld, self.player) self.multiworld.get_location(LocationName.Somebody_please_help, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.ACDC_Overworld, "Region", self.player) + state.can_reach_region(RegionName.ACDC_Overworld, self.player) self.multiworld.get_location(LocationName.Looking_for_condor, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) and \ - state.can_reach(RegionName.Beach_Overworld, "Region", self.player) and \ - state.can_reach(RegionName.ACDC_Overworld, "Region", self.player) + state.can_reach_region(RegionName.Yoka_Overworld, self.player) and \ + state.can_reach_region(RegionName.Beach_Overworld, self.player) and \ + state.can_reach_region(RegionName.ACDC_Overworld, self.player) self.multiworld.get_location(LocationName.Help_with_rehab, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Beach_Overworld, "Region", self.player) + state.can_reach_region(RegionName.Beach_Overworld, self.player) self.multiworld.get_location(LocationName.Old_Master, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.ACDC_Overworld, "Region", self.player) and \ - state.can_reach(RegionName.Beach_Overworld, "Region", self.player) + state.can_reach_region(RegionName.ACDC_Overworld, self.player) and \ + state.can_reach_region(RegionName.Beach_Overworld, self.player) self.multiworld.get_location(LocationName.Catching_gang_members, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Yoka_Cyberworld, "Region", self.player) and \ + state.can_reach_region(RegionName.Yoka_Cyberworld, self.player) and \ state.has(ItemName.Press, self.player) self.multiworld.get_location(LocationName.Please_adopt_a_virus, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.SciLab_Cyberworld, "Region", self.player) + state.can_reach_region(RegionName.SciLab_Cyberworld, self.player) self.multiworld.get_location(LocationName.Legendary_Tomes, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Beach_Overworld, "Region", self.player) and \ - state.can_reach(RegionName.Undernet, "Region", self.player) and \ - state.can_reach(RegionName.Deep_Undernet, "Region", self.player) and \ + state.can_reach_region(RegionName.Beach_Overworld, self.player) and \ + state.can_reach_region(RegionName.Undernet, self.player) and \ + state.can_reach_region(RegionName.Deep_Undernet, self.player) and \ state.has_all({ItemName.Press, ItemName.Magnum1_A}, self.player) self.multiworld.get_location(LocationName.Legendary_Tomes_Treasure, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.ACDC_Overworld, "Region", self.player) and \ - state.can_reach(LocationName.Legendary_Tomes, "Location", self.player) + state.can_reach_region(RegionName.ACDC_Overworld, self.player) and \ + state.can_reach_location(LocationName.Legendary_Tomes, self.player) self.multiworld.get_location(LocationName.Hide_and_seek_First_Child, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) + state.can_reach_region(RegionName.Yoka_Overworld, self.player) self.multiworld.get_location(LocationName.Hide_and_seek_Second_Child, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) + state.can_reach_region(RegionName.Yoka_Overworld, self.player) self.multiworld.get_location(LocationName.Hide_and_seek_Third_Child, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) + state.can_reach_region(RegionName.Yoka_Overworld, self.player) self.multiworld.get_location(LocationName.Hide_and_seek_Fourth_Child, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) + state.can_reach_region(RegionName.Yoka_Overworld, self.player) self.multiworld.get_location(LocationName.Hide_and_seek_Completion, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) + state.can_reach_region(RegionName.Yoka_Overworld, self.player) self.multiworld.get_location(LocationName.Finding_the_blue_Navi, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Undernet, "Region", self.player) + state.can_reach_region(RegionName.Undernet, self.player) self.multiworld.get_location(LocationName.Give_your_support, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Beach_Overworld, "Region", self.player) + state.can_reach_region(RegionName.Beach_Overworld, self.player) self.multiworld.get_location(LocationName.Stamp_collecting, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.Beach_Overworld, "Region", self.player) and \ - state.can_reach(RegionName.ACDC_Cyberworld, "Region", self.player) and \ - state.can_reach(RegionName.SciLab_Cyberworld, "Region", self.player) and \ - state.can_reach(RegionName.Yoka_Cyberworld, "Region", self.player) and \ - state.can_reach(RegionName.Beach_Cyberworld, "Region", self.player) + state.can_reach_region(RegionName.Beach_Overworld, self.player) and \ + state.can_reach_region(RegionName.ACDC_Cyberworld, self.player) and \ + state.can_reach_region(RegionName.SciLab_Cyberworld, self.player) and \ + state.can_reach_region(RegionName.Yoka_Cyberworld, self.player) and \ + state.can_reach_region(RegionName.Beach_Cyberworld, self.player) self.multiworld.get_location(LocationName.Help_with_a_will, self.player).access_rule = \ lambda state: \ - state.can_reach(RegionName.ACDC_Overworld, "Region", self.player) and \ - state.can_reach(RegionName.ACDC_Cyberworld, "Region", self.player) and \ - state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) and \ - state.can_reach(RegionName.Yoka_Cyberworld, "Region", self.player) and \ - state.can_reach(RegionName.Beach_Overworld, "Region", self.player) and \ - state.can_reach(RegionName.Undernet, "Region", self.player) + state.can_reach_region(RegionName.ACDC_Overworld, self.player) and \ + state.can_reach_region(RegionName.ACDC_Cyberworld, self.player) and \ + state.can_reach_region(RegionName.Yoka_Overworld, self.player) and \ + state.can_reach_region(RegionName.Yoka_Cyberworld, self.player) and \ + state.can_reach_region(RegionName.Beach_Overworld, self.player) and \ + state.can_reach_region(RegionName.Undernet, self.player) # Set Trade quests self.multiworld.get_location(LocationName.ACDC_SonicWav_W_Trade, self.player).access_rule =\ @@ -390,6 +411,11 @@ class MMBN3World(World): self.multiworld.get_location(LocationName.Numberman_Code_31, self.player).access_rule =\ lambda state: self.explore_score(state) > 10 + #miscellaneous locations with extra requirements + add_rule(self.multiworld.get_location(LocationName.Comedian, self.player), + lambda state: state.has(ItemName.Humor, self.player)) + add_rule(self.multiworld.get_location(LocationName.Villain, self.player), + lambda state: state.has(ItemName.BlckMnd, self.player)) def not_undernet(item): return item.code != item_table[ItemName.Progressive_Undernet_Rank].code or item.player != self.player self.multiworld.get_location(LocationName.WWW_1_Central_BMD, self.player).item_rule = not_undernet self.multiworld.get_location(LocationName.WWW_1_East_BMD, self.player).item_rule = not_undernet @@ -500,24 +526,24 @@ class MMBN3World(World): Determine roughly how much of the game you can explore to make certain checks not restrict much movement """ score = 0 - if state.can_reach(RegionName.WWW_Island, "Region", self.player): + if state.can_reach_region(RegionName.WWW_Island, self.player): return 999 - if state.can_reach(RegionName.SciLab_Overworld, "Region", self.player): + if state.can_reach_region(RegionName.SciLab_Overworld, self.player): score += 3 - if state.can_reach(RegionName.SciLab_Cyberworld, "Region", self.player): + if state.can_reach_region(RegionName.SciLab_Cyberworld, self.player): score += 1 - if state.can_reach(RegionName.Yoka_Overworld, "Region", self.player): + if state.can_reach_region(RegionName.Yoka_Overworld, self.player): score += 2 - if state.can_reach(RegionName.Yoka_Cyberworld, "Region", self.player): + if state.can_reach_region(RegionName.Yoka_Cyberworld, self.player): score += 1 - if state.can_reach(RegionName.Beach_Overworld, "Region", self.player): + if state.can_reach_region(RegionName.Beach_Overworld, self.player): score += 3 - if state.can_reach(RegionName.Beach_Cyberworld, "Region", self.player): + if state.can_reach_region(RegionName.Beach_Cyberworld, self.player): score += 1 - if state.can_reach(RegionName.Undernet, "Region", self.player): + if state.can_reach_region(RegionName.Undernet, self.player): score += 2 - if state.can_reach(RegionName.Deep_Undernet, "Region", self.player): + if state.can_reach_region(RegionName.Deep_Undernet, self.player): score += 1 - if state.can_reach(RegionName.Secret_Area, "Region", self.player): + if state.can_reach_region(RegionName.Secret_Area, self.player): score += 1 return score diff --git a/worlds/mmbn3/data/bn3-ap-patch.bsdiff b/worlds/mmbn3/data/bn3-ap-patch.bsdiff index d3548b4c..d55fecad 100644 Binary files a/worlds/mmbn3/data/bn3-ap-patch.bsdiff and b/worlds/mmbn3/data/bn3-ap-patch.bsdiff differ