sm64ex: Refactor Regions (#2546)
Refactors region code to remove references to course index. There were bugs somewhere, but I dont know where tbh. This fixes them but leaves logic otherwise intact, and much cleaner to look at as there's one list less to take care of. Additionally, this fixes stopping the clock from Big Boos Haunt.
This commit is contained in:
parent
229a263131
commit
530617c9a7
|
@ -5,26 +5,43 @@ from .Locations import SM64Location, location_table, locBoB_table, locWhomp_tabl
|
|||
locHMC_table, locLLL_table, locSSL_table, locDDD_table, locSL_table, \
|
||||
locWDW_table, locTTM_table, locTHI_table, locTTC_table, locRR_table, \
|
||||
locPSS_table, locSA_table, locBitDW_table, locTotWC_table, locCotMC_table, \
|
||||
locVCutM_table, locBitFS_table, locWMotR_table, locBitS_table, locSS_table
|
||||
locVCutM_table, locBitFS_table, locWMotR_table, locBitS_table, locSS_table
|
||||
|
||||
# List of all courses, including secrets, without BitS as that one is static
|
||||
sm64courses = ["Bob-omb Battlefield", "Whomp's Fortress", "Jolly Roger Bay", "Cool, Cool Mountain", "Big Boo's Haunt",
|
||||
"Hazy Maze Cave", "Lethal Lava Land", "Shifting Sand Land", "Dire, Dire Docks", "Snowman's Land",
|
||||
"Wet-Dry World", "Tall, Tall Mountain", "Tiny-Huge Island", "Tick Tock Clock", "Rainbow Ride",
|
||||
"The Princess's Secret Slide", "The Secret Aquarium", "Bowser in the Dark World", "Tower of the Wing Cap",
|
||||
"Cavern of the Metal Cap", "Vanish Cap under the Moat", "Bowser in the Fire Sea", "Wing Mario over the Rainbow"]
|
||||
# sm64paintings is dict of entrances, format LEVEL | AREA
|
||||
sm64_level_to_paintings = {
|
||||
91: "Bob-omb Battlefield",
|
||||
241: "Whomp's Fortress",
|
||||
121: "Jolly Roger Bay",
|
||||
51: "Cool, Cool Mountain",
|
||||
41: "Big Boo's Haunt",
|
||||
71: "Hazy Maze Cave",
|
||||
221: "Lethal Lava Land",
|
||||
81: "Shifting Sand Land",
|
||||
231: "Dire, Dire Docks",
|
||||
101: "Snowman's Land",
|
||||
111: "Wet-Dry World",
|
||||
361: "Tall, Tall Mountain",
|
||||
132: "Tiny-Huge Island (Tiny)",
|
||||
131: "Tiny-Huge Island (Huge)",
|
||||
141: "Tick Tock Clock",
|
||||
151: "Rainbow Ride"
|
||||
}
|
||||
sm64_paintings_to_level = { painting: level for (level,painting) in sm64_level_to_paintings.items() }
|
||||
# sm64secrets is list of secret areas, same format
|
||||
sm64_level_to_secrets = {
|
||||
271: "The Princess's Secret Slide",
|
||||
201: "The Secret Aquarium",
|
||||
171: "Bowser in the Dark World",
|
||||
291: "Tower of the Wing Cap",
|
||||
281: "Cavern of the Metal Cap",
|
||||
181: "Vanish Cap under the Moat",
|
||||
191: "Bowser in the Fire Sea",
|
||||
311: "Wing Mario over the Rainbow"
|
||||
}
|
||||
sm64_secrets_to_level = { secret: level for (level,secret) in sm64_level_to_secrets.items() }
|
||||
|
||||
# sm64paintings is list of entrances, format LEVEL | AREA. String Reference below
|
||||
sm64paintings = [91,241,121,51,41,71,221,81,231,101,111,361,132,131,141,151]
|
||||
sm64paintings_s = ["BOB", "WF", "JRB", "CCM", "BBH", "HMC", "LLL", "SSL", "DDD", "SL", "WDW", "TTM", "THI Tiny", "THI Huge", "TTC", "RR"]
|
||||
# sm64secrets is list of secret areas
|
||||
sm64secrets = [271, 201, 171, 291, 281, 181, 191, 311]
|
||||
sm64secrets_s = ["PSS", "SA", "BitDW", "TOTWC", "COTMC", "VCUTM", "BitFS", "WMOTR"]
|
||||
|
||||
sm64entrances = sm64paintings + sm64secrets
|
||||
sm64entrances_s = sm64paintings_s + sm64secrets_s
|
||||
sm64_internalloc_to_string = dict(zip(sm64paintings+sm64secrets, sm64entrances_s))
|
||||
sm64_internalloc_to_regionid = dict(zip(sm64paintings+sm64secrets, list(range(13)) + [12,13,14] + list(range(15,15+len(sm64secrets)))))
|
||||
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):
|
||||
regSS = Region("Menu", player, world, "Castle Area")
|
||||
|
@ -137,11 +154,13 @@ def create_regions(world: MultiWorld, player: int):
|
|||
regTTM.locations.append(SM64Location(player, "TTM: 100 Coins", location_table["TTM: 100 Coins"], regTTM))
|
||||
world.regions.append(regTTM)
|
||||
|
||||
regTHI = create_region("Tiny-Huge Island", player, world)
|
||||
create_default_locs(regTHI, locTHI_table, player)
|
||||
regTHIT = create_region("Tiny-Huge Island (Tiny)", player, world)
|
||||
create_default_locs(regTHIT, locTHI_table, player)
|
||||
if (world.EnableCoinStars[player].value):
|
||||
regTHI.locations.append(SM64Location(player, "THI: 100 Coins", location_table["THI: 100 Coins"], regTHI))
|
||||
world.regions.append(regTHI)
|
||||
regTHIT.locations.append(SM64Location(player, "THI: 100 Coins", location_table["THI: 100 Coins"], regTHIT))
|
||||
world.regions.append(regTHIT)
|
||||
regTHIH = create_region("Tiny-Huge Island (Huge)", player, world)
|
||||
world.regions.append(regTHIH)
|
||||
|
||||
regFloor3 = create_region("Third Floor", player, world)
|
||||
world.regions.append(regFloor3)
|
||||
|
|
|
@ -1,77 +1,84 @@
|
|||
from ..generic.Rules import add_rule
|
||||
from .Regions import connect_regions, sm64courses, sm64paintings, sm64secrets, sm64entrances
|
||||
from .Regions import connect_regions, sm64_level_to_paintings, sm64_paintings_to_level, sm64_level_to_secrets, sm64_entrances_to_level, sm64_level_to_entrances
|
||||
|
||||
def fix_reg(entrance_ids, reg, invalidspot, swaplist, world):
|
||||
if entrance_ids.index(reg) == invalidspot: # Unlucky :C
|
||||
swaplist.remove(invalidspot)
|
||||
rand = world.random.choice(swaplist)
|
||||
entrance_ids[invalidspot], entrance_ids[rand] = entrance_ids[rand], entrance_ids[invalidspot]
|
||||
swaplist.append(invalidspot)
|
||||
swaplist.remove(rand)
|
||||
def shuffle_dict_keys(world, obj: dict) -> dict:
|
||||
keys = list(obj.keys())
|
||||
values = list(obj.values())
|
||||
world.random.shuffle(keys)
|
||||
return dict(zip(keys,values))
|
||||
|
||||
def set_rules(world, player: int, area_connections):
|
||||
destination_regions = list(range(13)) + [12,13,14] + list(range(15,15+len(sm64secrets))) # Two instances of Destination Course THI. Past normal course idx are secret regions
|
||||
secret_entrance_ids = list(range(len(sm64paintings), len(sm64paintings) + len(sm64secrets)))
|
||||
course_entrance_ids = list(range(len(sm64paintings)))
|
||||
if world.AreaRandomizer[player].value >= 1: # Some randomization is happening, randomize Courses
|
||||
world.random.shuffle(course_entrance_ids)
|
||||
def fix_reg(entrance_ids, entrance, destination, swapdict, world):
|
||||
if entrance_ids[entrance] == destination: # Unlucky :C
|
||||
rand = world.random.choice(swapdict.keys())
|
||||
entrance_ids[entrance], entrance_ids[swapdict[rand]] = rand, entrance_ids[entrance]
|
||||
swapdict[rand] = entrance_ids[entrance]
|
||||
swapdict.pop(entrance)
|
||||
|
||||
def set_rules(world, player: int, area_connections: dict):
|
||||
randomized_level_to_paintings = sm64_level_to_paintings.copy()
|
||||
randomized_level_to_secrets = sm64_level_to_secrets.copy()
|
||||
if world.AreaRandomizer[player].value == 1: # Some randomization is happening, randomize Courses
|
||||
randomized_level_to_paintings = shuffle_dict_keys(world,sm64_level_to_paintings)
|
||||
if world.AreaRandomizer[player].value == 2: # Randomize Secrets as well
|
||||
world.random.shuffle(secret_entrance_ids)
|
||||
entrance_ids = course_entrance_ids + secret_entrance_ids
|
||||
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
|
||||
world.random.shuffle(entrance_ids)
|
||||
randomized_entrances = shuffle_dict_keys(world,randomized_entrances)
|
||||
# Guarantee first entrance is a course
|
||||
swaplist = list(range(len(entrance_ids)))
|
||||
if entrance_ids.index(0) > 15: # Unlucky :C
|
||||
rand = world.random.randint(0,15)
|
||||
entrance_ids[entrance_ids.index(0)], entrance_ids[rand] = entrance_ids[rand], entrance_ids[entrance_ids.index(0)]
|
||||
swaplist.remove(entrance_ids.index(0))
|
||||
swapdict = { entrance: level for (level,entrance) in randomized_entrances }
|
||||
if randomized_entrances[91] not in sm64_paintings_to_level.keys(): # Unlucky :C (91 -> BoB Entrance)
|
||||
rand = world.random.choice(sm64_paintings_to_level.values())
|
||||
randomized_entrances[91], randomized_entrances[swapdict[rand]] = rand, randomized_entrances[91]
|
||||
swapdict[rand] = randomized_entrances[91]
|
||||
swapdict.pop("Bob-omb Battlefield")
|
||||
# Guarantee COTMC is not mapped to HMC, cuz thats impossible
|
||||
fix_reg(entrance_ids, 20, 5, swaplist, world)
|
||||
fix_reg(randomized_entrances, "Cavern of the Metal Cap", "Hazy Maze Cave", swapdict, world)
|
||||
# Guarantee BITFS is not mapped to DDD
|
||||
fix_reg(entrance_ids, 22, 8, swaplist, world)
|
||||
if entrance_ids.index(22) == 5: # If BITFS is mapped to HMC...
|
||||
fix_reg(entrance_ids, 20, 8, swaplist, world) # ... then dont allow COTMC to be mapped to DDD
|
||||
temp_assign = dict(zip(entrance_ids,destination_regions)) # Used for Rules only
|
||||
fix_reg(randomized_entrances, "Bowser in the Fire Sea", "Dire, Dire Docks", swapdict, world)
|
||||
if randomized_entrances[191] == "Hazy Maze Cave": # If BITFS is mapped to HMC...
|
||||
fix_reg(randomized_entrances, "Cavern of the Metal Cap", "Dire, Dire Docks", swapdict, world) # ... then dont allow COTMC to be mapped to DDD
|
||||
|
||||
# Destination Format: LVL | AREA with LVL = LEVEL_x, AREA = Area as used in sm64 code
|
||||
area_connections.update({sm64entrances[entrance]: destination for entrance, destination in zip(entrance_ids,sm64entrances)})
|
||||
area_connections.update({entrance_lvl: 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()}
|
||||
|
||||
connect_regions(world, player, "Menu", sm64courses[temp_assign[0]]) # BOB
|
||||
connect_regions(world, player, "Menu", sm64courses[temp_assign[1]], lambda state: state.has("Power Star", player, 1)) # WF
|
||||
connect_regions(world, player, "Menu", sm64courses[temp_assign[2]], lambda state: state.has("Power Star", player, 3)) # JRB
|
||||
connect_regions(world, player, "Menu", sm64courses[temp_assign[3]], lambda state: state.has("Power Star", player, 3)) # CCM
|
||||
connect_regions(world, player, "Menu", sm64courses[temp_assign[4]], lambda state: state.has("Power Star", player, 12)) # BBH
|
||||
connect_regions(world, player, "Menu", sm64courses[temp_assign[16]], lambda state: state.has("Power Star", player, 1)) # PSS
|
||||
connect_regions(world, player, "Menu", sm64courses[temp_assign[17]], lambda state: state.has("Power Star", player, 3)) # SA
|
||||
connect_regions(world, player, "Menu", sm64courses[temp_assign[19]], lambda state: state.has("Power Star", player, 10)) # TOTWC
|
||||
connect_regions(world, player, "Menu", sm64courses[temp_assign[18]], lambda state: state.has("Power Star", player, world.FirstBowserStarDoorCost[player].value)) # BITDW
|
||||
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))
|
||||
connect_regions(world, player, "Menu", randomized_entrances_s["Jolly Roger Bay"], lambda state: state.has("Power Star", player, 3))
|
||||
connect_regions(world, player, "Menu", randomized_entrances_s["Cool, Cool Mountain"], lambda state: state.has("Power Star", player, 3))
|
||||
connect_regions(world, player, "Menu", randomized_entrances_s["Big Boo's Haunt"], lambda state: state.has("Power Star", player, 12))
|
||||
connect_regions(world, player, "Menu", randomized_entrances_s["The Princess's Secret Slide"], lambda state: state.has("Power Star", player, 1))
|
||||
connect_regions(world, player, "Menu", randomized_entrances_s["The Secret Aquarium"], lambda state: state.has("Power Star", player, 3))
|
||||
connect_regions(world, player, "Menu", randomized_entrances_s["Tower of the Wing Cap"], lambda state: state.has("Power Star", player, 10))
|
||||
connect_regions(world, player, "Menu", randomized_entrances_s["Bowser in the Dark World"], lambda state: state.has("Power Star", player, world.FirstBowserStarDoorCost[player].value))
|
||||
|
||||
connect_regions(world, player, "Menu", "Basement", lambda state: state.has("Basement Key", player) or state.has("Progressive Key", player, 1))
|
||||
|
||||
connect_regions(world, player, "Basement", sm64courses[temp_assign[5]]) # HMC
|
||||
connect_regions(world, player, "Basement", sm64courses[temp_assign[6]]) # LLL
|
||||
connect_regions(world, player, "Basement", sm64courses[temp_assign[7]]) # SSL
|
||||
connect_regions(world, player, "Basement", sm64courses[temp_assign[8]], lambda state: state.has("Power Star", player, world.BasementStarDoorCost[player].value)) # DDD
|
||||
connect_regions(world, player, "Hazy Maze Cave", sm64courses[temp_assign[20]]) # COTMC
|
||||
connect_regions(world, player, "Basement", sm64courses[temp_assign[21]]) # VCUTM
|
||||
connect_regions(world, player, "Basement", sm64courses[temp_assign[22]], lambda state: state.has("Power Star", player, world.BasementStarDoorCost[player].value) and
|
||||
state.can_reach("DDD: Board Bowser's Sub", 'Location', player)) # BITFS
|
||||
connect_regions(world, player, "Basement", randomized_entrances_s["Hazy Maze Cave"])
|
||||
connect_regions(world, player, "Basement", randomized_entrances_s["Lethal Lava Land"])
|
||||
connect_regions(world, player, "Basement", randomized_entrances_s["Shifting Sand Land"])
|
||||
connect_regions(world, player, "Basement", randomized_entrances_s["Dire, Dire Docks"], lambda state: state.has("Power Star", player, world.BasementStarDoorCost[player].value))
|
||||
connect_regions(world, player, "Hazy Maze Cave", randomized_entrances_s["Cavern of the Metal Cap"])
|
||||
connect_regions(world, player, "Basement", randomized_entrances_s["Vanish Cap under the Moat"])
|
||||
connect_regions(world, player, "Basement", randomized_entrances_s["Bowser in the Fire Sea"], lambda state: state.has("Power Star", player, world.BasementStarDoorCost[player].value) and
|
||||
state.can_reach("DDD: Board Bowser's Sub", 'Location', player))
|
||||
|
||||
connect_regions(world, player, "Menu", "Second Floor", lambda state: state.has("Second Floor Key", player) or state.has("Progressive Key", player, 2))
|
||||
|
||||
connect_regions(world, player, "Second Floor", sm64courses[temp_assign[9]]) # SL
|
||||
connect_regions(world, player, "Second Floor", sm64courses[temp_assign[10]]) # WDW
|
||||
connect_regions(world, player, "Second Floor", sm64courses[temp_assign[11]]) # TTM
|
||||
connect_regions(world, player, "Second Floor", sm64courses[temp_assign[12]]) # THI Tiny
|
||||
connect_regions(world, player, "Second Floor", sm64courses[temp_assign[13]]) # THI Huge
|
||||
connect_regions(world, player, "Second Floor", randomized_entrances_s["Snowman's Land"])
|
||||
connect_regions(world, player, "Second Floor", randomized_entrances_s["Wet-Dry World"])
|
||||
connect_regions(world, player, "Second Floor", randomized_entrances_s["Tall, Tall Mountain"])
|
||||
connect_regions(world, player, "Second Floor", randomized_entrances_s["Tiny-Huge Island (Tiny)"])
|
||||
connect_regions(world, player, "Second Floor", randomized_entrances_s["Tiny-Huge Island (Huge)"])
|
||||
connect_regions(world, player, "Tiny-Huge Island (Tiny)", "Tiny-Huge Island (Huge)")
|
||||
connect_regions(world, player, "Tiny-Huge Island (Huge)", "Tiny-Huge Island (Tiny)")
|
||||
|
||||
connect_regions(world, player, "Second Floor", "Third Floor", lambda state: state.has("Power Star", player, world.SecondFloorStarDoorCost[player].value))
|
||||
|
||||
connect_regions(world, player, "Third Floor", sm64courses[temp_assign[14]]) # TTC
|
||||
connect_regions(world, player, "Third Floor", sm64courses[temp_assign[15]]) # RR
|
||||
connect_regions(world, player, "Third Floor", sm64courses[temp_assign[23]]) # WMOTR
|
||||
connect_regions(world, player, "Third Floor", "Bowser in the Sky", lambda state: state.has("Power Star", player, world.StarsToFinish[player].value)) # BITS
|
||||
connect_regions(world, player, "Third Floor", randomized_entrances_s["Tick Tock Clock"])
|
||||
connect_regions(world, player, "Third Floor", randomized_entrances_s["Rainbow Ride"])
|
||||
connect_regions(world, player, "Third Floor", randomized_entrances_s["Wing Mario over the Rainbow"])
|
||||
connect_regions(world, player, "Third Floor", "Bowser in the Sky", lambda state: state.has("Power Star", player, world.StarsToFinish[player].value))
|
||||
|
||||
#Special Rules for some Locations
|
||||
add_rule(world.get_location("BoB: Mario Wings to the Sky", player), lambda state: state.has("Cannon Unlock BoB", player))
|
||||
|
|
|
@ -5,7 +5,7 @@ from .Items import item_table, cannon_item_table, SM64Item
|
|||
from .Locations import location_table, SM64Location
|
||||
from .Options import sm64_options
|
||||
from .Rules import set_rules
|
||||
from .Regions import create_regions, sm64courses, sm64entrances_s, sm64_internalloc_to_string, sm64_internalloc_to_regionid
|
||||
from .Regions import create_regions, sm64_level_to_entrances
|
||||
from BaseClasses import Item, Tutorial, ItemClassification
|
||||
from ..AutoWorld import World, WebWorld
|
||||
|
||||
|
@ -55,8 +55,8 @@ class SM64World(World):
|
|||
# Write area_connections to spoiler log
|
||||
for entrance, destination in self.area_connections.items():
|
||||
self.multiworld.spoiler.set_entrance(
|
||||
sm64_internalloc_to_string[entrance] + " Entrance",
|
||||
sm64_internalloc_to_string[destination],
|
||||
sm64_level_to_entrances[entrance] + " Entrance",
|
||||
sm64_level_to_entrances[destination],
|
||||
'entrance', self.player)
|
||||
|
||||
def create_item(self, name: str) -> Item:
|
||||
|
@ -182,8 +182,7 @@ class SM64World(World):
|
|||
if self.topology_present:
|
||||
er_hint_data = {}
|
||||
for entrance, destination in self.area_connections.items():
|
||||
regionid = sm64_internalloc_to_regionid[destination]
|
||||
region = self.multiworld.get_region(sm64courses[regionid], self.player)
|
||||
region = self.multiworld.get_region(sm64_level_to_entrances[destination], self.player)
|
||||
for location in region.locations:
|
||||
er_hint_data[location.address] = sm64_internalloc_to_string[entrance]
|
||||
er_hint_data[location.address] = sm64_level_to_entrances[entrance]
|
||||
multidata['er_hint_data'][self.player] = er_hint_data
|
||||
|
|
Loading…
Reference in New Issue