SM64 logic fixes and ER handling (#488)
* SM64: add painting name to location hints if area randomizer * SM64: fix BitFS access logic Using can_reach regions in an entrance's logic is unsafe because reachable_regions won't be updated if no progression locations are reached. can_reach location is safe. * SM64: rework logic for correctness and consistency - BoB Mario Wings to the Sky is extremely difficult with cap and no cannon, will never be required - DDD Collect the Caps no longer requires metal cap except on strict cap - Cavern of the Metal Cap red coins no longer requires metal cap except on strict cap - CCM, TTM, WDW cannons added on strict cannons for their expected stars - BoB 100 coins requires cap or cannon if both are strict, since only 99 coins are available otherwise * SM64: write entrances to spoiler log * SM64: tweak format of WDW cannon rules
This commit is contained in:
parent
517e72f442
commit
40a08d0d84
|
@ -4,7 +4,7 @@ from .Regions import connect_regions, sm64courses
|
||||||
|
|
||||||
def set_rules(world, player: int, area_connections):
|
def set_rules(world, player: int, area_connections):
|
||||||
courseshuffle = list(range(len(sm64courses)))
|
courseshuffle = list(range(len(sm64courses)))
|
||||||
if world.AreaRandomizer[player].value:
|
if world.AreaRandomizer[player]:
|
||||||
world.random.shuffle(courseshuffle)
|
world.random.shuffle(courseshuffle)
|
||||||
area_connections.update({index: value for index, value in enumerate(courseshuffle)})
|
area_connections.update({index: value for index, value in enumerate(courseshuffle)})
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ def set_rules(world, player: int, area_connections):
|
||||||
connect_regions(world, player, "Basement", sm64courses[area_connections[7]])
|
connect_regions(world, player, "Basement", sm64courses[area_connections[7]])
|
||||||
connect_regions(world, player, "Basement", sm64courses[area_connections[8]], lambda state: state.has("Power Star", player, 30))
|
connect_regions(world, player, "Basement", sm64courses[area_connections[8]], lambda state: state.has("Power Star", player, 30))
|
||||||
connect_regions(world, player, "Basement", "Bowser in the Fire Sea", lambda state: state.has("Power Star", player, 30) and
|
connect_regions(world, player, "Basement", "Bowser in the Fire Sea", lambda state: state.has("Power Star", player, 30) and
|
||||||
state.can_reach("Dire, Dire Docks", 'Region', player))
|
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, "Menu", "Second Floor", lambda state: state.has("Second Floor Key", player) or state.has("Progressive Key", player, 2))
|
||||||
|
|
||||||
|
@ -38,48 +38,57 @@ def set_rules(world, player: int, area_connections):
|
||||||
|
|
||||||
#Special Rules for some Locations
|
#Special Rules for some Locations
|
||||||
add_rule(world.get_location("Tower of the Wing Cap Switch", player), lambda state: state.has("Power Star", player, 10))
|
add_rule(world.get_location("Tower of the Wing Cap Switch", player), lambda state: state.has("Power Star", player, 10))
|
||||||
add_rule(world.get_location("Cavern of the Metal Cap Switch", player), lambda state: state.can_reach("Hazy Maze Cave",'Region',player))
|
add_rule(world.get_location("Cavern of the Metal Cap Switch", player), lambda state: state.can_reach("Hazy Maze Cave", 'Region', player))
|
||||||
add_rule(world.get_location("Vanish Cap Under the Moat Switch", player), lambda state: state.can_reach("Basement", 'Region', player))
|
add_rule(world.get_location("Vanish Cap Under the Moat Switch", player), lambda state: state.can_reach("Basement", 'Region', player))
|
||||||
|
|
||||||
|
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("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("Metal Cap", player) and
|
add_rule(world.get_location("DDD: Collect the Caps...", player), lambda state: state.has("Vanish Cap", player))
|
||||||
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))
|
||||||
add_rule(world.get_location("DDD: Pole-Jumping for Red 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("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("WDW: Quick Race Through Downtown!", player), lambda state: state.has("Vanish Cap", player))
|
||||||
if (world.StrictCapRequirements[player].value):
|
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))
|
||||||
|
|
||||||
|
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("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("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("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: 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("Vanish Cap Under the Moat Red Coins", player), lambda state: state.has("Vanish Cap", player))
|
||||||
if (world.StrictCannonRequirements[player].value):
|
add_rule(world.get_location("Cavern of the Metal Cap Red Coins", player), lambda state: state.has("Metal Cap", player))
|
||||||
add_rule(world.get_location("BoB: Mario Wings to the Sky", player), lambda state: state.has("Cannon Unlock BoB", 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("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("JRB: Blast to the Stone Pillar", player), lambda state: state.has("Cannon Unlock JRB", player))
|
||||||
if (world.AreaRandomizer[player].value):
|
add_rule(world.get_location("CCM: Wall Kicks Will Work", player), lambda state: state.has("Cannon Unlock CCM", player))
|
||||||
add_rule(world.get_location("WDW: Quick Race Through Downtown!", player), lambda state: state.has("Cannon Unlock WDW", player))
|
add_rule(world.get_location("TTM: Blast to the Lonely Mushroom", player), lambda state: state.has("Cannon Unlock TTM", player))
|
||||||
add_rule(world.get_location("WDW: Go to Town for Red Coins", player), lambda state: state.has("Cannon Unlock WDW", player))
|
if world.StrictCapRequirements[player] and world.StrictCannonRequirements[player]:
|
||||||
if (world.StrictCapRequirements and world.StrictCannonRequirements[player].value):
|
# Ability to reach the floating island. Need some of those coins to get 100 coin star as well.
|
||||||
add_rule(world.get_location("BoB: Mario Wings to the Sky", player), lambda state: state.has("Cannon Unlock BoB", player) or state.has("Wing Cap", player))
|
|
||||||
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: 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))
|
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("RR: Somewhere Over the Rainbow", player), lambda state: state.has("Cannon Unlock RR", 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
|
#Rules for Secret Stars
|
||||||
add_rule(world.get_location("Bowser in the Sky Red Coins", player), lambda state: state.can_reach("Third Floor",'Region',player) and state.has("Power Star", player, world.StarsToFinish[player].value))
|
add_rule(world.get_location("Bowser in the Sky Red Coins", player), lambda state: state.can_reach("Third Floor", 'Region',player) and state.has("Power Star", player, world.StarsToFinish[player].value))
|
||||||
add_rule(world.get_location("The Princess's Secret Slide Block", player), lambda state: state.has("Power Star", player, 1))
|
add_rule(world.get_location("The Princess's Secret Slide Block", player), lambda state: state.has("Power Star", player, 1))
|
||||||
add_rule(world.get_location("The Princess's Secret Slide Fast", player), lambda state: state.has("Power Star", player, 1))
|
add_rule(world.get_location("The Princess's Secret Slide Fast", player), lambda state: state.has("Power Star", player, 1))
|
||||||
add_rule(world.get_location("Cavern of the Metal Cap Red Coins", player), lambda state: state.can_reach("Cavern of the Metal Cap Switch", 'Location', player) and state.has("Metal Cap", player))
|
add_rule(world.get_location("Cavern of the Metal Cap Red Coins", player), lambda state: state.can_reach("Cavern of the Metal Cap Switch", 'Location', player))
|
||||||
add_rule(world.get_location("Tower of the Wing Cap Red Coins", player), lambda state: state.can_reach("Tower of the Wing Cap Switch", 'Location', player))
|
add_rule(world.get_location("Tower of the Wing Cap Red Coins", player), lambda state: state.can_reach("Tower of the Wing Cap Switch", 'Location', player))
|
||||||
add_rule(world.get_location("Vanish Cap Under the Moat Red Coins", player), lambda state: state.can_reach("Vanish Cap Under the Moat Switch", 'Location', player))
|
add_rule(world.get_location("Vanish Cap Under the Moat Red Coins", player), lambda state: state.can_reach("Vanish Cap Under the Moat Switch", 'Location', player))
|
||||||
add_rule(world.get_location("Wing Mario Over the Rainbow", player), lambda state: state.can_reach("Third Floor", 'Region', player) and state.has("Wing Cap", player))
|
add_rule(world.get_location("Wing Mario Over the Rainbow", player), lambda state: state.can_reach("Third Floor", 'Region', player) and state.has("Wing Cap", player))
|
||||||
add_rule(world.get_location("The Secret Aquarium", player), lambda state: state.has("Power Star", player, 3))
|
add_rule(world.get_location("The Secret Aquarium", player), lambda state: state.has("Power Star", player, 3))
|
||||||
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 (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 (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))
|
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))
|
||||||
add_rule(world.get_location("MIPS 1", player), lambda state: state.can_reach("Basement",'Region',player) and state.has("Power Star", player, 15))
|
add_rule(world.get_location("MIPS 1", player), lambda state: state.can_reach("Basement", 'Region', player) and state.has("Power Star", player, 15))
|
||||||
add_rule(world.get_location("MIPS 2", player), lambda state: state.can_reach("Basement",'Region',player) and state.has("Power Star", player, 50))
|
add_rule(world.get_location("MIPS 2", player), lambda state: state.can_reach("Basement", 'Region', player) and state.has("Power Star", player, 50))
|
||||||
|
|
||||||
world.completion_condition[player] = lambda state: state.can_reach("Third Floor",'Region',player) and state.has("Power Star", player, world.StarsToFinish[player].value)
|
world.completion_condition[player] = lambda state: state.can_reach("Third Floor", 'Region', player) and state.has("Power Star", player, world.StarsToFinish[player].value)
|
||||||
|
|
|
@ -5,7 +5,7 @@ from .Items import item_table, cannon_item_table, SM64Item
|
||||||
from .Locations import location_table, SM64Location
|
from .Locations import location_table, SM64Location
|
||||||
from .Options import sm64_options
|
from .Options import sm64_options
|
||||||
from .Rules import set_rules
|
from .Rules import set_rules
|
||||||
from .Regions import create_regions
|
from .Regions import create_regions, sm64courses
|
||||||
from BaseClasses import Region, RegionType, Entrance, Item, MultiWorld
|
from BaseClasses import Region, RegionType, Entrance, Item, MultiWorld
|
||||||
from ..AutoWorld import World
|
from ..AutoWorld import World
|
||||||
|
|
||||||
|
@ -39,6 +39,13 @@ class SM64World(World):
|
||||||
def set_rules(self):
|
def set_rules(self):
|
||||||
self.area_connections = {}
|
self.area_connections = {}
|
||||||
set_rules(self.world, self.player, self.area_connections)
|
set_rules(self.world, self.player, self.area_connections)
|
||||||
|
if self.topology_present:
|
||||||
|
# Write area_connections to spoiler log
|
||||||
|
for painting_id, course_id in self.area_connections.items():
|
||||||
|
self.world.spoiler.set_entrance(
|
||||||
|
sm64courses[painting_id] + " Painting",
|
||||||
|
sm64courses[course_id],
|
||||||
|
'entrance', self.player)
|
||||||
|
|
||||||
def create_item(self, name: str) -> Item:
|
def create_item(self, name: str) -> Item:
|
||||||
item_id = item_table[name]
|
item_id = item_table[name]
|
||||||
|
@ -110,3 +117,12 @@ class SM64World(World):
|
||||||
filename = f"AP_{self.world.seed_name}_P{self.player}_{self.world.get_file_safe_player_name(self.player)}.apsm64ex"
|
filename = f"AP_{self.world.seed_name}_P{self.player}_{self.world.get_file_safe_player_name(self.player)}.apsm64ex"
|
||||||
with open(os.path.join(output_directory, filename), 'w') as f:
|
with open(os.path.join(output_directory, filename), 'w') as f:
|
||||||
json.dump(data, f)
|
json.dump(data, f)
|
||||||
|
|
||||||
|
def modify_multidata(self, multidata):
|
||||||
|
if self.topology_present:
|
||||||
|
er_hint_data = {}
|
||||||
|
for painting_id, course_id in self.area_connections.items():
|
||||||
|
region = self.world.get_region(sm64courses[course_id], self.player)
|
||||||
|
for location in region.locations:
|
||||||
|
er_hint_data[location.address] = sm64courses[painting_id]
|
||||||
|
multidata['er_hint_data'][self.player] = er_hint_data
|
||||||
|
|
Loading…
Reference in New Issue