mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00

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.
140 lines
12 KiB
Python
140 lines
12 KiB
Python
from ..generic.Rules import add_rule
|
|
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 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 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
|
|
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
|
|
randomized_entrances = shuffle_dict_keys(world,randomized_entrances)
|
|
# Guarantee first entrance is a course
|
|
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(randomized_entrances, "Cavern of the Metal Cap", "Hazy Maze Cave", swapdict, world)
|
|
# Guarantee BITFS is not mapped to DDD
|
|
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({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", 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", 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", 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", 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))
|
|
add_rule(world.get_location("BBH: Eye to Eye in the Secret Room", player), lambda state: state.has("Vanish Cap", player))
|
|
add_rule(world.get_location("DDD: Collect the Caps...", player), lambda state: state.has("Vanish Cap", player))
|
|
add_rule(world.get_location("DDD: Pole-Jumping for Red Coins", player), lambda state: state.can_reach("Bowser in the Fire Sea", 'Region', player))
|
|
if world.EnableCoinStars[player]:
|
|
add_rule(world.get_location("DDD: 100 Coins", player), lambda state: state.can_reach("Bowser in the Fire Sea", 'Region', player))
|
|
add_rule(world.get_location("SL: Into the Igloo", player), lambda state: state.has("Vanish Cap", player))
|
|
add_rule(world.get_location("WDW: Quick Race Through Downtown!", player), lambda state: state.has("Vanish Cap", player))
|
|
add_rule(world.get_location("RR: Somewhere Over the Rainbow", player), lambda state: state.has("Cannon Unlock RR", player))
|
|
|
|
if world.AreaRandomizer[player] or world.StrictCannonRequirements[player]:
|
|
# If area rando is on, it may not be possible to modify WDW's starting water level,
|
|
# which would make it impossible to reach downtown area without the cannon.
|
|
add_rule(world.get_location("WDW: Quick Race Through Downtown!", player), lambda state: state.has("Cannon Unlock WDW", player))
|
|
add_rule(world.get_location("WDW: Go to Town for Red Coins", player), lambda state: state.has("Cannon Unlock WDW", player))
|
|
add_rule(world.get_location("WDW: 1Up Block in Downtown", player), lambda state: state.has("Cannon Unlock WDW", player))
|
|
|
|
if world.StrictCapRequirements[player]:
|
|
add_rule(world.get_location("BoB: Mario Wings to the Sky", player), lambda state: state.has("Wing Cap", player))
|
|
add_rule(world.get_location("HMC: Metal-Head Mario Can Move!", player), lambda state: state.has("Metal Cap", player))
|
|
add_rule(world.get_location("JRB: Through the Jet Stream", player), lambda state: state.has("Metal Cap", player))
|
|
add_rule(world.get_location("SSL: Free Flying for 8 Red Coins", player), lambda state: state.has("Wing Cap", player))
|
|
add_rule(world.get_location("DDD: Through the Jet Stream", player), lambda state: state.has("Metal Cap", player))
|
|
add_rule(world.get_location("DDD: Collect the Caps...", player), lambda state: state.has("Metal Cap", player))
|
|
add_rule(world.get_location("Vanish Cap Under the Moat Red Coins", player), lambda state: state.has("Vanish Cap", player))
|
|
add_rule(world.get_location("Cavern of the Metal Cap Red Coins", player), lambda state: state.has("Metal Cap", player))
|
|
if world.StrictCannonRequirements[player]:
|
|
add_rule(world.get_location("WF: Blast Away the Wall", player), lambda state: state.has("Cannon Unlock WF", player))
|
|
add_rule(world.get_location("JRB: Blast to the Stone Pillar", player), lambda state: state.has("Cannon Unlock JRB", player))
|
|
add_rule(world.get_location("CCM: Wall Kicks Will Work", player), lambda state: state.has("Cannon Unlock CCM", player))
|
|
add_rule(world.get_location("TTM: Blast to the Lonely Mushroom", player), lambda state: state.has("Cannon Unlock TTM", player))
|
|
if world.StrictCapRequirements[player] and world.StrictCannonRequirements[player]:
|
|
# Ability to reach the floating island. Need some of those coins to get 100 coin star as well.
|
|
add_rule(world.get_location("BoB: Find the 8 Red Coins", player), lambda state: state.has("Cannon Unlock BoB", player) or state.has("Wing Cap", player))
|
|
add_rule(world.get_location("BoB: Shoot to the Island in the Sky", player), lambda state: state.has("Cannon Unlock BoB", player) or state.has("Wing Cap", player))
|
|
if world.EnableCoinStars[player]:
|
|
add_rule(world.get_location("BoB: 100 Coins", player), lambda state: state.has("Cannon Unlock BoB", player) or state.has("Wing Cap", player))
|
|
|
|
#Rules for Secret Stars
|
|
add_rule(world.get_location("Wing Mario Over the Rainbow Red Coins", player), lambda state: state.has("Wing Cap", player))
|
|
add_rule(world.get_location("Wing Mario Over the Rainbow 1Up Block", player), lambda state: state.has("Wing Cap", player))
|
|
add_rule(world.get_location("Toad (Basement)", player), lambda state: state.can_reach("Basement", 'Region', player) and state.has("Power Star", player, 12))
|
|
add_rule(world.get_location("Toad (Second Floor)", player), lambda state: state.can_reach("Second Floor", 'Region', player) and state.has("Power Star", player, 25))
|
|
add_rule(world.get_location("Toad (Third Floor)", player), lambda state: state.can_reach("Third Floor", 'Region', player) and state.has("Power Star", player, 35))
|
|
|
|
if world.MIPS1Cost[player].value > world.MIPS2Cost[player].value:
|
|
(world.MIPS2Cost[player].value, world.MIPS1Cost[player].value) = (world.MIPS1Cost[player].value, world.MIPS2Cost[player].value)
|
|
add_rule(world.get_location("MIPS 1", player), lambda state: state.can_reach("Basement", 'Region', player) and state.has("Power Star", player, world.MIPS1Cost[player].value))
|
|
add_rule(world.get_location("MIPS 2", player), lambda state: state.can_reach("Basement", 'Region', player) and state.has("Power Star", player, world.MIPS2Cost[player].value))
|
|
|
|
if world.CompletionType[player] == "last_bowser_stage":
|
|
world.completion_condition[player] = lambda state: state.can_reach("Bowser in the Sky", 'Region', player)
|
|
elif world.CompletionType[player] == "all_bowser_stages":
|
|
world.completion_condition[player] = lambda state: state.can_reach("Bowser in the Dark World", 'Region', player) and \
|
|
state.can_reach("Bowser in the Fire Sea", 'Region', player) and \
|
|
state.can_reach("Bowser in the Sky", 'Region', player)
|