diff --git a/worlds/sm64ex/Options.py b/worlds/sm64ex/Options.py index d9a877df2b3..60ec4bbe13c 100644 --- a/worlds/sm64ex/Options.py +++ b/worlds/sm64ex/Options.py @@ -1,5 +1,6 @@ import typing -from Options import Option, DefaultOnToggle, Range, Toggle, DeathLink, Choice +from dataclasses import dataclass +from Options import DefaultOnToggle, Range, Toggle, DeathLink, Choice, PerGameCommonOptions, OptionSet from .Items import action_item_table class EnableCoinStars(DefaultOnToggle): @@ -114,35 +115,37 @@ class StrictMoveRequirements(DefaultOnToggle): if Move Randomization is enabled""" display_name = "Strict Move Requirements" -def getMoveRandomizerOption(action: str): - class MoveRandomizerOption(Toggle): - """Mario is unable to perform this action until a corresponding item is picked up. - This option is incompatible with builds using a 'nomoverando' branch.""" - display_name = f"Randomize {action}" - return MoveRandomizerOption - - -sm64_options: typing.Dict[str, type(Option)] = { - "AreaRandomizer": AreaRandomizer, - "BuddyChecks": BuddyChecks, - "ExclamationBoxes": ExclamationBoxes, - "ProgressiveKeys": ProgressiveKeys, - "EnableCoinStars": EnableCoinStars, - "StrictCapRequirements": StrictCapRequirements, - "StrictCannonRequirements": StrictCannonRequirements, - "StrictMoveRequirements": StrictMoveRequirements, - "AmountOfStars": AmountOfStars, - "FirstBowserStarDoorCost": FirstBowserStarDoorCost, - "BasementStarDoorCost": BasementStarDoorCost, - "SecondFloorStarDoorCost": SecondFloorStarDoorCost, - "MIPS1Cost": MIPS1Cost, - "MIPS2Cost": MIPS2Cost, - "StarsToFinish": StarsToFinish, - "death_link": DeathLink, - "CompletionType": CompletionType, -} - -for action in action_item_table: - # HACK: Disable randomization of double jump - if action == 'Double Jump': continue - sm64_options[f"MoveRandomizer{action.replace(' ','')}"] = getMoveRandomizerOption(action) +class EnableMoveRandomizer(Toggle): + """Mario is unable to perform some actions until a corresponding item is picked up. + This option is incompatible with builds using a 'nomoverando' branch. + Specific actions to randomize can be specified in the YAML.""" + display_name = "Enable Move Randomizer" + +class MoveRandomizerActions(OptionSet): + """Which actions to randomize when Move Randomizer is enabled""" + display_name = "Randomized Moves" + # HACK: Disable randomization for double jump + valid_keys = [action for action in action_item_table if action != 'Double Jump'] + default = valid_keys + +@dataclass +class SM64Options(PerGameCommonOptions): + area_rando: AreaRandomizer + buddy_checks: BuddyChecks + exclamation_boxes: ExclamationBoxes + progressive_keys: ProgressiveKeys + enable_coin_stars: EnableCoinStars + enable_move_rando: EnableMoveRandomizer + move_rando_actions: MoveRandomizerActions + strict_cap_requirements: StrictCapRequirements + strict_cannon_requirements: StrictCannonRequirements + strict_move_requirements: StrictMoveRequirements + amount_of_stars: AmountOfStars + first_bowser_star_door_cost: FirstBowserStarDoorCost + basement_star_door_cost: BasementStarDoorCost + second_floor_star_door_cost: SecondFloorStarDoorCost + mips1_cost: MIPS1Cost + mips2_cost: MIPS2Cost + stars_to_finish: StarsToFinish + death_link: DeathLink + completion_type: CompletionType diff --git a/worlds/sm64ex/Regions.py b/worlds/sm64ex/Regions.py index a493281ec3f..333e2df3a97 100644 --- a/worlds/sm64ex/Regions.py +++ b/worlds/sm64ex/Regions.py @@ -2,6 +2,7 @@ from enum import Enum from BaseClasses import MultiWorld, Region, Entrance, Location +from .Options import SM64Options from .Locations import SM64Location, location_table, locBoB_table, locWhomp_table, locJRB_table, locCCM_table, \ locBBH_table, \ locHMC_table, locLLL_table, locSSL_table, locDDD_table, locSL_table, \ @@ -78,7 +79,7 @@ class SM64Region(Region): sm64_entrances_to_level = {**sm64_paintings_to_level, **sm64_secrets_to_level } sm64_level_to_entrances = {**sm64_level_to_paintings, **sm64_level_to_secrets } -def create_regions(world: MultiWorld, player: int): +def create_regions(world: MultiWorld, options: SM64Options, player: int): regSS = Region("Menu", player, world, "Castle Area") create_default_locs(regSS, locSS_table) world.regions.append(regSS) @@ -88,7 +89,7 @@ def create_regions(world: MultiWorld, player: int): "BoB: Mario Wings to the Sky", "BoB: Behind Chain Chomp's Gate", "BoB: Bob-omb Buddy") bob_island = create_subregion(regBoB, "BoB: Island", "BoB: Shoot to the Island in the Sky", "BoB: Find the 8 Red Coins") regBoB.subregions = [bob_island] - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(regBoB, "BoB: 100 Coins") regWhomp = create_region("Whomp's Fortress", player, world) @@ -96,7 +97,7 @@ def create_regions(world: MultiWorld, player: int): "WF: Fall onto the Caged Island", "WF: Blast Away the Wall") wf_tower = create_subregion(regWhomp, "WF: Tower", "WF: To the Top of the Fortress", "WF: Bob-omb Buddy") regWhomp.subregions = [wf_tower] - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(regWhomp, "WF: 100 Coins") regJRB = create_region("Jolly Roger Bay", player, world) @@ -104,12 +105,12 @@ def create_regions(world: MultiWorld, player: int): "JRB: Blast to the Stone Pillar", "JRB: Through the Jet Stream", "JRB: Bob-omb Buddy") jrb_upper = create_subregion(regJRB, 'JRB: Upper', "JRB: Red Coins on the Ship Afloat") regJRB.subregions = [jrb_upper] - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(jrb_upper, "JRB: 100 Coins") regCCM = create_region("Cool, Cool Mountain", player, world) create_default_locs(regCCM, locCCM_table) - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(regCCM, "CCM: 100 Coins") regBBH = create_region("Big Boo's Haunt", player, world) @@ -118,7 +119,7 @@ def create_regions(world: MultiWorld, player: int): bbh_third_floor = create_subregion(regBBH, "BBH: Third Floor", "BBH: Eye to Eye in the Secret Room") bbh_roof = create_subregion(bbh_third_floor, "BBH: Roof", "BBH: Big Boo's Balcony", "BBH: 1Up Block Top of Mansion") regBBH.subregions = [bbh_third_floor, bbh_roof] - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(regBBH, "BBH: 100 Coins") regPSS = create_region("The Princess's Secret Slide", player, world) @@ -141,7 +142,7 @@ def create_regions(world: MultiWorld, player: int): hmc_red_coin_area = create_subregion(regHMC, "HMC: Red Coin Area", "HMC: Elevate for 8 Red Coins") hmc_pit_islands = create_subregion(regHMC, "HMC: Pit Islands", "HMC: A-Maze-Ing Emergency Exit", "HMC: 1Up Block above Pit") regHMC.subregions = [hmc_red_coin_area, hmc_pit_islands] - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(hmc_red_coin_area, "HMC: 100 Coins") regLLL = create_region("Lethal Lava Land", player, world) @@ -149,7 +150,7 @@ def create_regions(world: MultiWorld, player: int): "LLL: 8-Coin Puzzle with 15 Pieces", "LLL: Red-Hot Log Rolling") lll_upper_volcano = create_subregion(regLLL, "LLL: Upper Volcano", "LLL: Hot-Foot-It into the Volcano", "LLL: Elevator Tour in the Volcano") regLLL.subregions = [lll_upper_volcano] - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(regLLL, "LLL: 100 Coins") regSSL = create_region("Shifting Sand Land", player, world) @@ -159,7 +160,7 @@ def create_regions(world: MultiWorld, player: int): ssl_upper_pyramid = create_subregion(regSSL, "SSL: Upper Pyramid", "SSL: Inside the Ancient Pyramid", "SSL: Stand Tall on the Four Pillars", "SSL: Pyramid Puzzle") regSSL.subregions = [ssl_upper_pyramid] - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(regSSL, "SSL: 100 Coins") regDDD = create_region("Dire, Dire Docks", player, world) @@ -167,7 +168,7 @@ def create_regions(world: MultiWorld, player: int): "DDD: The Manta Ray's Reward", "DDD: Collect the Caps...") ddd_moving_poles = create_subregion(regDDD, "DDD: Moving Poles", "DDD: Pole-Jumping for Red Coins") regDDD.subregions = [ddd_moving_poles] - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(ddd_moving_poles, "DDD: 100 Coins") regCotMC = create_region("Cavern of the Metal Cap", player, world) @@ -184,7 +185,7 @@ def create_regions(world: MultiWorld, player: int): regSL = create_region("Snowman's Land", player, world) create_default_locs(regSL, locSL_table) - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(regSL, "SL: 100 Coins") regWDW = create_region("Wet-Dry World", player, world) @@ -193,7 +194,7 @@ def create_regions(world: MultiWorld, player: int): "WDW: Secrets in the Shallows & Sky", "WDW: Bob-omb Buddy") wdw_downtown = create_subregion(regWDW, "WDW: Downtown", "WDW: Go to Town for Red Coins", "WDW: Quick Race Through Downtown!", "WDW: 1Up Block in Downtown") regWDW.subregions = [wdw_top, wdw_downtown] - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(wdw_top, "WDW: 100 Coins") regTTM = create_region("Tall, Tall Mountain", player, world) @@ -202,7 +203,7 @@ def create_regions(world: MultiWorld, player: int): ttm_top = create_subregion(ttm_middle, "TTM: Top", "TTM: Scale the Mountain", "TTM: Mystery of the Monkey Cage", "TTM: Mysterious Mountainside", "TTM: Breathtaking View from Bridge") regTTM.subregions = [ttm_middle, ttm_top] - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(ttm_top, "TTM: 100 Coins") create_region("Tiny-Huge Island (Huge)", player, world) @@ -214,7 +215,7 @@ def create_regions(world: MultiWorld, player: int): "THI: 1Up Block THI Large near Start", "THI: 1Up Block Windy Area") thi_large_top = create_subregion(thi_pipes, "THI: Large Top", "THI: Make Wiggler Squirm") regTHI.subregions = [thi_pipes, thi_large_top] - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(thi_large_top, "THI: 100 Coins") regFloor3 = create_region("Third Floor", player, world) @@ -225,7 +226,7 @@ def create_regions(world: MultiWorld, player: int): ttc_upper = create_subregion(ttc_lower, "TTC: Upper", "TTC: Timed Jumps on Moving Bars", "TTC: The Pit and the Pendulums") ttc_top = create_subregion(ttc_upper, "TTC: Top", "TTC: Stomp on the Thwomp", "TTC: 1Up Block at the Top") regTTC.subregions = [ttc_lower, ttc_upper, ttc_top] - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(ttc_top, "TTC: 100 Coins") regRR = create_region("Rainbow Ride", player, world) @@ -235,7 +236,7 @@ def create_regions(world: MultiWorld, player: int): rr_cruiser = create_subregion(regRR, "RR: Cruiser", "RR: Cruiser Crossing the Rainbow", "RR: Somewhere Over the Rainbow") rr_house = create_subregion(regRR, "RR: House", "RR: The Big House in the Sky", "RR: 1Up Block On House in the Sky") regRR.subregions = [rr_maze, rr_cruiser, rr_house] - if (world.EnableCoinStars[player].value): + if options.enable_coin_stars: create_locs(rr_maze, "RR: 100 Coins") regWMotR = create_region("Wing Mario over the Rainbow", player, world) diff --git a/worlds/sm64ex/Rules.py b/worlds/sm64ex/Rules.py index cc2b52f0f12..72016b4f401 100644 --- a/worlds/sm64ex/Rules.py +++ b/worlds/sm64ex/Rules.py @@ -3,6 +3,7 @@ from BaseClasses import MultiWorld from ..generic.Rules import add_rule, set_rule from .Locations import location_table +from .Options import SM64Options from .Regions import connect_regions, SM64Levels, sm64_level_to_paintings, sm64_paintings_to_level,\ sm64_level_to_secrets, sm64_secrets_to_level, sm64_entrances_to_level, sm64_level_to_entrances from .Items import action_item_table @@ -24,7 +25,7 @@ def fix_reg(entrance_map: Dict[SM64Levels, str], entrance: SM64Levels, invalid_r swapdict[entrance], swapdict[rand_entrance] = rand_region, old_dest swapdict.pop(entrance) -def set_rules(world, player: int, area_connections: dict, star_costs: dict, move_rando_bitvec: int): +def set_rules(world, options: SM64Options, player: int, area_connections: dict, star_costs: dict, move_rando_bitvec: int): randomized_level_to_paintings = sm64_level_to_paintings.copy() randomized_level_to_secrets = sm64_level_to_secrets.copy() valid_move_randomizer_start_courses = [ @@ -32,19 +33,19 @@ def set_rules(world, player: int, area_connections: dict, star_costs: dict, move "Big Boo's Haunt", "Lethal Lava Land", "Shifting Sand Land", "Dire, Dire Docks", "Snowman's Land" ] # Excluding WF, HMC, WDW, TTM, THI, TTC, and RR - if world.AreaRandomizer[player].value >= 1: # Some randomization is happening, randomize Courses + if options.area_rando >= 1: # Some randomization is happening, randomize Courses randomized_level_to_paintings = shuffle_dict_keys(world,sm64_level_to_paintings) # If not shuffling later, ensure a valid start course on move randomizer - if world.AreaRandomizer[player].value < 3 and move_rando_bitvec > 0: + if options.area_rando < 3 and move_rando_bitvec > 0: swapdict = randomized_level_to_paintings.copy() invalid_start_courses = {course for course in randomized_level_to_paintings.values() if course not in valid_move_randomizer_start_courses} fix_reg(randomized_level_to_paintings, SM64Levels.BOB_OMB_BATTLEFIELD, invalid_start_courses, swapdict, world) fix_reg(randomized_level_to_paintings, SM64Levels.WHOMPS_FORTRESS, invalid_start_courses, swapdict, world) - if world.AreaRandomizer[player].value == 2: # Randomize Secrets as well + if options.area_rando == 2: # Randomize Secrets as well randomized_level_to_secrets = shuffle_dict_keys(world,sm64_level_to_secrets) randomized_entrances = {**randomized_level_to_paintings, **randomized_level_to_secrets} - if world.AreaRandomizer[player].value == 3: # Randomize Courses and Secrets in one pool + if options.area_rando == 3: # Randomize Courses and Secrets in one pool randomized_entrances = shuffle_dict_keys(world, randomized_entrances) # Guarantee first entrance is a course swapdict = randomized_entrances.copy() @@ -67,7 +68,7 @@ def set_rules(world, player: int, area_connections: dict, star_costs: dict, move area_connections.update({int(entrance_lvl): int(sm64_entrances_to_level[destination]) for (entrance_lvl,destination) in randomized_entrances.items()}) randomized_entrances_s = {sm64_level_to_entrances[entrance_lvl]: destination for (entrance_lvl,destination) in randomized_entrances.items()} - rf = RuleFactory(world, player, move_rando_bitvec) + rf = RuleFactory(world, options, player, move_rando_bitvec) connect_regions(world, player, "Menu", randomized_entrances_s["Bob-omb Battlefield"]) connect_regions(world, player, "Menu", randomized_entrances_s["Whomp's Fortress"], lambda state: state.has("Power Star", player, 1)) @@ -199,7 +200,7 @@ def set_rules(world, player: int, area_connections: dict, star_costs: dict, move # Bowser in the Sky rf.assign_rule("BitS: Top", "CL+TJ | CL+SF+LG | MOVELESS & TJ+WK+LG") # 100 Coin Stars - if world.EnableCoinStars[player]: + if options.enable_coin_stars: rf.assign_rule("BoB: 100 Coins", "CANN & WC | CANNLESS & WC & TJ") rf.assign_rule("WF: 100 Coins", "GP | MOVELESS") rf.assign_rule("JRB: 100 Coins", "GP & {JRB: Upper}") @@ -225,9 +226,9 @@ def set_rules(world, player: int, area_connections: dict, star_costs: dict, move world.completion_condition[player] = lambda state: state.can_reach("BitS: Top", 'Region', player) - if world.CompletionType[player] == "last_bowser_stage": + if options.completion_type == "last_bowser_stage": world.completion_condition[player] = lambda state: state.can_reach("BitS: Top", 'Region', player) - elif world.CompletionType[player] == "all_bowser_stages": + elif options.completion_type == "all_bowser_stages": world.completion_condition[player] = lambda state: state.can_reach("Bowser in the Dark World", 'Region', player) and \ state.can_reach("BitFS: Upper", 'Region', player) and \ state.can_reach("BitS: Top", 'Region', player) @@ -262,14 +263,14 @@ class RuleFactory: class SM64LogicException(Exception): pass - def __init__(self, world, player, move_rando_bitvec): + def __init__(self, world, options: SM64Options, player: int, move_rando_bitvec: int): self.world = world self.player = player self.move_rando_bitvec = move_rando_bitvec - self.area_randomizer = world.AreaRandomizer[player].value > 0 - self.capless = not world.StrictCapRequirements[player] - self.cannonless = not world.StrictCannonRequirements[player] - self.moveless = not world.StrictMoveRequirements[player] or not move_rando_bitvec > 0 + self.area_randomizer = options.area_rando > 0 + self.capless = not options.strict_cap_requirements + self.cannonless = not options.strict_cannon_requirements + self.moveless = not options.strict_move_requirements or not move_rando_bitvec > 0 def assign_rule(self, target_name: str, rule_expr: str): target = self.world.get_location(target_name, self.player) if target_name in location_table else self.world.get_entrance(target_name, self.player) diff --git a/worlds/sm64ex/__init__.py b/worlds/sm64ex/__init__.py index e6a6e42c76a..0e944aa4ab4 100644 --- a/worlds/sm64ex/__init__.py +++ b/worlds/sm64ex/__init__.py @@ -3,7 +3,7 @@ import json from .Items import item_table, action_item_table, cannon_item_table, SM64Item from .Locations import location_table, SM64Location -from .Options import sm64_options +from .Options import SM64Options from .Rules import set_rules from .Regions import create_regions, sm64_level_to_entrances, SM64Levels from BaseClasses import Item, Tutorial, ItemClassification, Region @@ -40,7 +40,7 @@ class SM64World(World): area_connections: typing.Dict[int, int] - option_definitions = sm64_options + options_dataclass = SM64Options number_of_stars: int move_rando_bitvec: int @@ -49,38 +49,36 @@ class SM64World(World): def generate_early(self): max_stars = 120 - if (not self.multiworld.EnableCoinStars[self.player].value): + if (not self.options.enable_coin_stars): max_stars -= 15 self.move_rando_bitvec = 0 - for action, itemid in action_item_table.items(): - # HACK: Disable randomization of double jump - if action == 'Double Jump': continue - if getattr(self.multiworld, f"MoveRandomizer{action.replace(' ','')}")[self.player].value: + if self.options.enable_move_rando: + for action in self.options.move_rando_actions.value: max_stars -= 1 - self.move_rando_bitvec |= (1 << (itemid - action_item_table['Double Jump'])) - if (self.multiworld.ExclamationBoxes[self.player].value > 0): + self.move_rando_bitvec |= (1 << (action_item_table[action] - action_item_table['Double Jump'])) + if (self.options.exclamation_boxes > 0): max_stars += 29 - self.number_of_stars = min(self.multiworld.AmountOfStars[self.player].value, max_stars) + self.number_of_stars = min(self.options.amount_of_stars, max_stars) self.filler_count = max_stars - self.number_of_stars self.star_costs = { - 'FirstBowserDoorCost': round(self.multiworld.FirstBowserStarDoorCost[self.player].value * self.number_of_stars / 100), - 'BasementDoorCost': round(self.multiworld.BasementStarDoorCost[self.player].value * self.number_of_stars / 100), - 'SecondFloorDoorCost': round(self.multiworld.SecondFloorStarDoorCost[self.player].value * self.number_of_stars / 100), - 'MIPS1Cost': round(self.multiworld.MIPS1Cost[self.player].value * self.number_of_stars / 100), - 'MIPS2Cost': round(self.multiworld.MIPS2Cost[self.player].value * self.number_of_stars / 100), - 'StarsToFinish': round(self.multiworld.StarsToFinish[self.player].value * self.number_of_stars / 100) + 'FirstBowserDoorCost': round(self.options.first_bowser_star_door_cost * self.number_of_stars / 100), + 'BasementDoorCost': round(self.options.basement_star_door_cost * self.number_of_stars / 100), + 'SecondFloorDoorCost': round(self.options.second_floor_star_door_cost * self.number_of_stars / 100), + 'MIPS1Cost': round(self.options.mips1_cost * self.number_of_stars / 100), + 'MIPS2Cost': round(self.options.mips2_cost * self.number_of_stars / 100), + 'StarsToFinish': round(self.options.stars_to_finish * self.number_of_stars / 100) } # Nudge MIPS 1 to match vanilla on default percentage - if self.number_of_stars == 120 and self.multiworld.MIPS1Cost[self.player].value == 12: + if self.number_of_stars == 120 and self.options.mips1_cost == 12: self.star_costs['MIPS1Cost'] = 15 - self.topology_present = self.multiworld.AreaRandomizer[self.player].value + self.topology_present = self.options.area_rando def create_regions(self): - create_regions(self.multiworld, self.player) + create_regions(self.multiworld, self.options, self.player) def set_rules(self): self.area_connections = {} - set_rules(self.multiworld, self.player, self.area_connections, self.star_costs, self.move_rando_bitvec) + set_rules(self.multiworld, self.options, self.player, self.area_connections, self.star_costs, self.move_rando_bitvec) if self.topology_present: # Write area_connections to spoiler log for entrance, destination in self.area_connections.items(): @@ -107,7 +105,7 @@ def create_items(self): # Power Stars self.multiworld.itempool += [self.create_item("Power Star") for i in range(0,self.number_of_stars)] # Keys - if (not self.multiworld.ProgressiveKeys[self.player].value): + if (not self.options.progressive_keys): key1 = self.create_item("Basement Key") key2 = self.create_item("Second Floor Key") self.multiworld.itempool += [key1, key2] @@ -116,7 +114,7 @@ def create_items(self): # Caps self.multiworld.itempool += [self.create_item(cap_name) for cap_name in ["Wing Cap", "Metal Cap", "Vanish Cap"]] # Cannons - if (self.multiworld.BuddyChecks[self.player].value): + if (self.options.buddy_checks): self.multiworld.itempool += [self.create_item(name) for name, id in cannon_item_table.items()] # Moves self.multiworld.itempool += [self.create_item(action) @@ -124,7 +122,7 @@ def create_items(self): if self.move_rando_bitvec & (1 << itemid - action_item_table['Double Jump'])] def generate_basic(self): - if not (self.multiworld.BuddyChecks[self.player].value): + if not (self.options.buddy_checks): self.multiworld.get_location("BoB: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock BoB")) self.multiworld.get_location("WF: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock WF")) self.multiworld.get_location("JRB: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock JRB")) @@ -136,7 +134,7 @@ def generate_basic(self): self.multiworld.get_location("THI: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock THI")) self.multiworld.get_location("RR: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock RR")) - if (self.multiworld.ExclamationBoxes[self.player].value == 0): + if (self.options.exclamation_boxes == 0): self.multiworld.get_location("CCM: 1Up Block Near Snowman", self.player).place_locked_item(self.create_item("1Up Mushroom")) self.multiworld.get_location("CCM: 1Up Block Ice Pillar", self.player).place_locked_item(self.create_item("1Up Mushroom")) self.multiworld.get_location("CCM: 1Up Block Secret Slide", self.player).place_locked_item(self.create_item("1Up Mushroom")) @@ -174,8 +172,8 @@ def fill_slot_data(self): return { "AreaRando": self.area_connections, "MoveRandoVec": self.move_rando_bitvec, - "DeathLink": self.multiworld.death_link[self.player].value, - "CompletionType": self.multiworld.CompletionType[self.player].value, + "DeathLink": self.options.death_link.value, + "CompletionType": self.options.completion_type.value, **self.star_costs }