sm64ex: Various Features (#790)

* sm64ex: Course and Secret Randomizer

* sm64ex: Allow higher star door costs, raise minimum amount of stars, deprecate ExtraStars

* sm64ex: Support setting MIPS costs

* sm64ex: Safeguard MIPS Costs
This commit is contained in:
Yussur Mustafa Oraji 2022-07-25 18:39:31 +02:00 committed by GitHub
parent e6635cdd77
commit c3ff201b90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 235 additions and 150 deletions

View File

@ -272,7 +272,7 @@ Super Mario 64:
StrictCapRequirements: true
StrictCannonRequirements: true
StarsToFinish: 70
ExtraStars: 30
AmountOfStars: 70
DeathLink: true
BuddyChecks: true
AreaRandomizer: true

View File

@ -182,26 +182,50 @@ loc100Coin_table = {
"RR: 100 Coins": 3626104
}
locPSS_table = {
"The Princess's Secret Slide Block": 3626126,
"The Princess's Secret Slide Fast": 3626127,
}
locSA_table = {
"The Secret Aquarium": 3626161
}
locBitDW_table = {
"Bowser in the Dark World Red Coins": 3626105,
"Bowser in the Dark World Key": 3626178
}
locTotWC_table = {
"Tower of the Wing Cap Switch": 3626181,
"Tower of the Wing Cap Red Coins": 3626140
}
locCotMC_table = {
"Cavern of the Metal Cap Switch": 3626182,
"Cavern of the Metal Cap Red Coins": 3626133
}
locVCutM_table = {
"Vanish Cap Under the Moat Switch": 3626183,
"Vanish Cap Under the Moat Red Coins": 3626147
}
locBitFS_table = {
"Bowser in the Fire Sea Red Coins": 3626112,
"Bowser in the Fire Sea Key": 3626179
}
#Secret Stars and Stages
locWMotR_table = {
"Wing Mario Over the Rainbow": 3626154
}
locBitS_table = {
"Bowser in the Sky Red Coins": 3626119
}
#Secret Stars found inside the Castle
locSS_table = {
"Bowser in the Sky Red Coins": 3626119,
"The Princess's Secret Slide Block": 3626126,
"The Princess's Secret Slide Fast": 3626127,
"Cavern of the Metal Cap Red Coins": 3626133,
"Tower of the Wing Cap Red Coins": 3626140,
"Vanish Cap Under the Moat Red Coins": 3626147,
"Wing Mario Over the Rainbow": 3626154,
"The Secret Aquarium": 3626161,
"Toad (Basement)": 3626168,
"Toad (Second Floor)": 3626169,
"Toad (Third Floor)": 3626170,
@ -209,15 +233,10 @@ locSS_table = {
"MIPS 2": 3626172
}
#Caps
locCap_table = {
"Tower of the Wing Cap Switch": 3626181,
"Cavern of the Metal Cap Switch": 3626182,
"Vanish Cap Under the Moat Switch": 3626183
}
# Correspond to 3626000 + course index * 7 + star index, then secret stars, then keys, then 100 Coin Stars
location_table = {**locBoB_table,**locWhomp_table,**locJRB_table,**locCCM_table,**locBBH_table, \
**locHMC_table,**locLLL_table,**locSSL_table,**locDDD_table,**locSL_table, \
**locWDW_table,**locTTM_table,**locTHI_table,**locTTC_table,**locRR_table, \
**loc100Coin_table,**locBitDW_table,**locBitFS_table,**locSS_table,**locCap_table}
**loc100Coin_table,**locPSS_table,**locSA_table,**locBitDW_table,**locTotWC_table, \
**locCotMC_table, **locVCutM_table, **locBitFS_table, **locWMotR_table, **locBitS_table, \
**locSS_table}

View File

@ -1,5 +1,5 @@
import typing
from Options import Option, DefaultOnToggle, Range, Toggle, DeathLink
from Options import Option, DefaultOnToggle, Range, Toggle, DeathLink, Choice
class EnableCoinStars(DefaultOnToggle):
"""Disable to Ignore 100 Coin Stars. You can still collect them, but they don't do anything"""
@ -16,19 +16,31 @@ class StrictCannonRequirements(DefaultOnToggle):
class FirstBowserStarDoorCost(Range):
"""How many stars are required at the Star Door to Bowser in the Dark World"""
range_start = 0
range_end = 20
range_end = 50
default = 8
class BasementStarDoorCost(Range):
"""How many stars are required at the Star Door in the Basement"""
range_start = 0
range_end = 50
range_end = 70
default = 30
class SecondFloorStarDoorCost(Range):
"""How many stars are required to access the third floor"""
range_start = 0
range_end = 50
range_end = 90
default = 50
class MIPS1Cost(Range):
"""How many stars are required to spawn MIPS the first time"""
range_start = 0
range_end = 40
default = 15
class MIPS2Cost(Range):
"""How many stars are required to spawn MIPS the secound time. Must be bigger or equal MIPS1Cost"""
range_start = 0
range_end = 80
default = 50
class StarsToFinish(Range):
@ -38,15 +50,19 @@ class StarsToFinish(Range):
range_end = 100
default = 70
class ExtraStars(Range):
"""How many stars exist beyond those set for StarsToFinish"""
range_start = 0
range_end = 50
default = 50
class AmountOfStars(Range):
"""How many stars exist. Disabling 100 Coin Stars removes 15 from the Pool. At least max of any Cost set"""
range_start = 35
range_end = 120
default = 120
class AreaRandomizer(Toggle):
"""Randomize Entrances to Courses"""
display_name = "Course Randomizer"
class AreaRandomizer(Choice):
"""Randomize Entrances"""
display_name = "Entrance Randomizer"
alias_false = 0
option_Off = 0
option_Courses_Only = 1
option_Courses_and_Secrets = 2
class BuddyChecks(Toggle):
"""Bob-omb Buddies are checks, Cannon Unlocks are items"""
@ -60,13 +76,15 @@ sm64_options: typing.Dict[str,type(Option)] = {
"AreaRandomizer": AreaRandomizer,
"ProgressiveKeys": ProgressiveKeys,
"EnableCoinStars": EnableCoinStars,
"AmountOfStars": AmountOfStars,
"StrictCapRequirements": StrictCapRequirements,
"StrictCannonRequirements": StrictCannonRequirements,
"FirstBowserStarDoorCost": FirstBowserStarDoorCost,
"BasementStarDoorCost": BasementStarDoorCost,
"SecondFloorStarDoorCost": SecondFloorStarDoorCost,
"MIPS1Cost": MIPS1Cost,
"MIPS2Cost": MIPS2Cost,
"StarsToFinish": StarsToFinish,
"ExtraStars": ExtraStars,
"death_link": DeathLink,
"BuddyChecks": BuddyChecks,
}

View File

@ -4,150 +4,168 @@ from .Locations import SM64Location, location_table, locBoB_table, locWhomp_tabl
locBBH_table, \
locHMC_table, locLLL_table, locSSL_table, locDDD_table, locSL_table, \
locWDW_table, locTTM_table, locTHI_table, locTTC_table, locRR_table, \
locBitDW_table, locBitFS_table, locSS_table, locCap_table
locPSS_table, locSA_table, locBitDW_table, locTotWC_table, locCotMC_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"]
"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 list of strings for quick reference for Painting IDs (NOT warp node IDs!)
sm64paintings = ["BOB", "WF", "JRB", "CCM", "BBH", "HMC", "LLL", "SSL", "DDD", "SL", "WDW", "TTM", "THI Tiny", "THI Huge", "TTC", "RR"]
# 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)))))
def create_regions(world: MultiWorld, player: int):
regSS = Region("Menu", RegionType.Generic, "Castle Area", player, world)
locSS_names = [name for name, id in locSS_table.items()]
locSS_names += [name for name, id in locCap_table.items()]
regSS.locations += [SM64Location(player, loc_name, location_table[loc_name], regSS) for loc_name in locSS_names]
create_default_locs(regSS, locSS_table, player)
world.regions.append(regSS)
regBoB = Region("Bob-omb Battlefield", RegionType.Generic, "Bob-omb Battlefield", player, world)
locBoB_names = [name for name, id in locBoB_table.items()]
regBoB.locations += [SM64Location(player, loc_name, location_table[loc_name], regBoB) for loc_name in locBoB_names]
regBoB = create_region("Bob-omb Battlefield", player, world)
create_default_locs(regBoB, locBoB_table, player)
if (world.EnableCoinStars[player].value):
regBoB.locations.append(SM64Location(player, "BoB: 100 Coins", location_table["BoB: 100 Coins"], regBoB))
world.regions.append(regBoB)
regWhomp = Region("Whomp's Fortress", RegionType.Generic, "Whomp's Fortress", player, world)
locWhomp_names = [name for name, id in locWhomp_table.items()]
regWhomp.locations += [SM64Location(player, loc_name, location_table[loc_name], regWhomp) for loc_name in
locWhomp_names]
regWhomp = create_region("Whomp's Fortress", player, world)
create_default_locs(regWhomp, locWhomp_table, player)
if (world.EnableCoinStars[player].value):
regWhomp.locations.append(SM64Location(player, "WF: 100 Coins", location_table["WF: 100 Coins"], regWhomp))
world.regions.append(regWhomp)
regJRB = Region("Jolly Roger Bay", RegionType.Generic, "Jolly Roger Bay", player, world)
locJRB_names = [name for name, id in locJRB_table.items()]
regJRB.locations += [SM64Location(player, loc_name, location_table[loc_name], regJRB) for loc_name in locJRB_names]
regJRB = create_region("Jolly Roger Bay", player, world)
create_default_locs(regJRB, locJRB_table, player)
if (world.EnableCoinStars[player].value):
regJRB.locations.append(SM64Location(player, "JRB: 100 Coins", location_table["JRB: 100 Coins"], regJRB))
world.regions.append(regJRB)
regCCM = Region("Cool, Cool Mountain", RegionType.Generic, "Cool, Cool Mountain", player, world)
locCCM_names = [name for name, id in locCCM_table.items()]
regCCM.locations += [SM64Location(player, loc_name, location_table[loc_name], regCCM) for loc_name in locCCM_names]
regCCM = create_region("Cool, Cool Mountain", player, world)
create_default_locs(regCCM, locCCM_table, player)
if (world.EnableCoinStars[player].value):
regCCM.locations.append(SM64Location(player, "CCM: 100 Coins", location_table["CCM: 100 Coins"], regCCM))
world.regions.append(regCCM)
regBBH = Region("Big Boo's Haunt", RegionType.Generic, "Big Boo's Haunt", player, world)
locBBH_names = [name for name, id in locBBH_table.items()]
regBBH.locations += [SM64Location(player, loc_name, location_table[loc_name], regBBH) for loc_name in locBBH_names]
regBBH = create_region("Big Boo's Haunt", player, world)
create_default_locs(regBBH, locBBH_table, player)
if (world.EnableCoinStars[player].value):
regBBH.locations.append(SM64Location(player, "BBH: 100 Coins", location_table["BBH: 100 Coins"], regBBH))
world.regions.append(regBBH)
regBitDW = Region("Bowser in the Dark World", RegionType.Generic, "Bowser in the Dark World", player, world)
locBitDW_names = [name for name, id in locBitDW_table.items()]
regBitDW.locations += [SM64Location(player, loc_name, location_table[loc_name], regBitDW) for loc_name in
locBitDW_names]
regPSS = create_region("The Princess's Secret Slide", player, world)
create_default_locs(regPSS, locPSS_table, player)
world.regions.append(regPSS)
regSA = create_region("The Secret Aquarium", player, world)
create_default_locs(regSA, locSA_table, player)
world.regions.append(regSA)
regTotWC = create_region("Tower of the Wing Cap", player, world)
create_default_locs(regTotWC, locTotWC_table, player)
world.regions.append(regTotWC)
regBitDW = create_region("Bowser in the Dark World", player, world)
create_default_locs(regBitDW, locBitDW_table, player)
world.regions.append(regBitDW)
regBasement = Region("Basement", RegionType.Generic, "Basement", player, world)
regBasement = create_region("Basement", player, world)
world.regions.append(regBasement)
regHMC = Region("Hazy Maze Cave", RegionType.Generic, "Hazy Maze Cave", player, world)
locHMC_names = [name for name, id in locHMC_table.items()]
regHMC.locations += [SM64Location(player, loc_name, location_table[loc_name], regHMC) for loc_name in locHMC_names]
regHMC = create_region("Hazy Maze Cave", player, world)
create_default_locs(regHMC, locHMC_table, player)
if (world.EnableCoinStars[player].value):
regHMC.locations.append(SM64Location(player, "HMC: 100 Coins", location_table["HMC: 100 Coins"], regHMC))
world.regions.append(regHMC)
regLLL = Region("Lethal Lava Land", RegionType.Generic, "Lethal Lava Land", player, world)
locLLL_names = [name for name, id in locLLL_table.items()]
regLLL.locations += [SM64Location(player, loc_name, location_table[loc_name], regLLL) for loc_name in locLLL_names]
regLLL = create_region("Lethal Lava Land", player, world)
create_default_locs(regLLL, locLLL_table, player)
if (world.EnableCoinStars[player].value):
regLLL.locations.append(SM64Location(player, "LLL: 100 Coins", location_table["LLL: 100 Coins"], regLLL))
world.regions.append(regLLL)
regSSL = Region("Shifting Sand Land", RegionType.Generic, "Shifting Sand Land", player, world)
locSSL_names = [name for name, id in locSSL_table.items()]
regSSL.locations += [SM64Location(player, loc_name, location_table[loc_name], regSSL) for loc_name in locSSL_names]
regSSL = create_region("Shifting Sand Land", player, world)
create_default_locs(regSSL, locSSL_table, player)
if (world.EnableCoinStars[player].value):
regSSL.locations.append(SM64Location(player, "SSL: 100 Coins", location_table["SSL: 100 Coins"], regSSL))
world.regions.append(regSSL)
regDDD = Region("Dire, Dire Docks", RegionType.Generic, "Dire, Dire Docks", player, world)
locDDD_names = [name for name, id in locDDD_table.items()]
regDDD.locations += [SM64Location(player, loc_name, location_table[loc_name], regDDD) for loc_name in locDDD_names]
regDDD = create_region("Dire, Dire Docks", player, world)
create_default_locs(regDDD, locDDD_table, player)
if (world.EnableCoinStars[player].value):
regDDD.locations.append(SM64Location(player, "DDD: 100 Coins", location_table["DDD: 100 Coins"], regDDD))
world.regions.append(regDDD)
regBitFS = Region("Bowser in the Fire Sea", RegionType.Generic, "Bowser in the Fire Sea", player, world)
locBitFS_names = [name for name, id in locBitFS_table.items()]
regBitFS.locations += [SM64Location(player, loc_name, location_table[loc_name], regBitFS) for loc_name in
locBitFS_names]
regCotMC = create_region("Cavern of the Metal Cap", player, world)
create_default_locs(regCotMC, locCotMC_table, player)
world.regions.append(regCotMC)
regVCutM = create_region("Vanish Cap under the Moat", player, world)
create_default_locs(regVCutM, locVCutM_table, player)
world.regions.append(regVCutM)
regBitFS = create_region("Bowser in the Fire Sea", player, world)
create_default_locs(regBitFS, locBitFS_table, player)
world.regions.append(regBitFS)
regFloor2 = Region("Second Floor", RegionType.Generic, "Second Floor", player, world)
regFloor2 = create_region("Second Floor", player, world)
world.regions.append(regFloor2)
regSL = Region("Snowman's Land", RegionType.Generic, "Snowman's Land", player, world)
locSL_names = [name for name, id in locSL_table.items()]
regSL.locations += [SM64Location(player, loc_name, location_table[loc_name], regSL) for loc_name in locSL_names]
regSL = create_region("Snowman's Land", player, world)
create_default_locs(regSL, locSL_table, player)
if (world.EnableCoinStars[player].value):
regSL.locations.append(SM64Location(player, "SL: 100 Coins", location_table["SL: 100 Coins"], regSL))
world.regions.append(regSL)
regWDW = Region("Wet-Dry World", RegionType.Generic, "Wet-Dry World", player, world)
locWDW_names = [name for name, id in locWDW_table.items()]
regWDW.locations += [SM64Location(player, loc_name, location_table[loc_name], regWDW) for loc_name in locWDW_names]
regWDW = create_region("Wet-Dry World", player, world)
create_default_locs(regWDW, locWDW_table, player)
if (world.EnableCoinStars[player].value):
regWDW.locations.append(SM64Location(player, "WDW: 100 Coins", location_table["WDW: 100 Coins"], regWDW))
world.regions.append(regWDW)
regTTM = Region("Tall, Tall Mountain", RegionType.Generic, "Tall, Tall Mountain", player, world)
locTTM_names = [name for name, id in locTTM_table.items()]
regTTM.locations += [SM64Location(player, loc_name, location_table[loc_name], regTTM) for loc_name in locTTM_names]
regTTM = create_region("Tall, Tall Mountain", player, world)
create_default_locs(regTTM, locTTM_table, player)
if (world.EnableCoinStars[player].value):
regTTM.locations.append(SM64Location(player, "TTM: 100 Coins", location_table["TTM: 100 Coins"], regTTM))
world.regions.append(regTTM)
regTHI = Region("Tiny-Huge Island", RegionType.Generic, "Tiny-Huge Island", player, world)
locTHI_names = [name for name, id in locTHI_table.items()]
regTHI.locations += [SM64Location(player, loc_name, location_table[loc_name], regTHI) for loc_name in locTHI_names]
regTHI = create_region("Tiny-Huge Island", player, world)
create_default_locs(regTHI, 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)
regFloor3 = Region("Third Floor", RegionType.Generic, "Third Floor", player, world)
regFloor3 = create_region("Third Floor", player, world)
world.regions.append(regFloor3)
regTTC = Region("Tick Tock Clock", RegionType.Generic, "Tick Tock Clock", player, world)
locTTC_names = [name for name, id in locTTC_table.items()]
regTTC.locations += [SM64Location(player, loc_name, location_table[loc_name], regTTC) for loc_name in locTTC_names]
regTTC = create_region("Tick Tock Clock", player, world)
create_default_locs(regTTC, locTTC_table, player)
if (world.EnableCoinStars[player].value):
regTTC.locations.append(SM64Location(player, "TTC: 100 Coins", location_table["TTC: 100 Coins"], regTTC))
world.regions.append(regTTC)
regRR = Region("Rainbow Ride", RegionType.Generic, "Rainbow Ride", player, world)
locRR_names = [name for name, id in locRR_table.items()]
regRR.locations += [SM64Location(player, loc_name, location_table[loc_name], regRR) for loc_name in locRR_names]
regRR = create_region("Rainbow Ride", player, world)
create_default_locs(regRR, locRR_table, player)
if (world.EnableCoinStars[player].value):
regRR.locations.append(SM64Location(player, "RR: 100 Coins", location_table["RR: 100 Coins"], regRR))
world.regions.append(regRR)
regWMotR = create_region("Wing Mario over the Rainbow", player, world)
create_default_locs(regWMotR, locWMotR_table, player)
world.regions.append(regWMotR)
regBitS = create_region("Bowser in the Sky", player, world)
create_default_locs(regBitS, locBitS_table, player)
world.regions.append(regBitS)
def connect_regions(world: MultiWorld, player: int, source: str, target: str, rule=None):
sourceRegion = world.get_region(source, player)
@ -159,3 +177,10 @@ def connect_regions(world: MultiWorld, player: int, source: str, target: str, ru
sourceRegion.exits.append(connection)
connection.connect(targetRegion)
def create_region(name: str, player: int, world: MultiWorld) -> Region:
return Region(name, RegionType.Generic, name, player, world)
def create_default_locs(reg: Region, locs, player):
reg_names = [name for name, id in locs.items()]
reg.locations += [SM64Location(player, loc_name, location_table[loc_name], reg) for loc_name in locs]

View File

@ -1,56 +1,76 @@
from ..generic.Rules import add_rule
from .Regions import connect_regions, sm64courses, sm64paintings
from .Regions import connect_regions, sm64courses, sm64paintings, sm64secrets, sm64entrances
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 set_rules(world, player: int, area_connections):
entrance_ids = list(range(len(sm64paintings)))
destination_courses = list(range(13)) + [12,13,14] # Two instances of Destination Course THI
if world.AreaRandomizer[player]:
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
if world.AreaRandomizer[player].value == 0:
entrance_ids = list(range(len(sm64paintings + sm64secrets)))
if world.AreaRandomizer[player].value >= 1: # Some randomization is happening, randomize Courses
entrance_ids = list(range(len(sm64paintings)))
world.random.shuffle(entrance_ids)
temp_assign = dict(zip(entrance_ids,destination_courses)) # Used for Rules only
entrance_ids = entrance_ids + list(range(len(sm64paintings), len(sm64paintings) + len(sm64secrets)))
if world.AreaRandomizer[player].value == 2: # Secret Regions as well
world.random.shuffle(entrance_ids)
# 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))
# Guarantee COTMC is not mapped to HMC, cuz thats impossible
fix_reg(entrance_ids, 20, 5, swaplist, world)
# Guarantee BITFS is not mapped to DDD
fix_reg(entrance_ids, 22, 8, swaplist, world)
temp_assign = dict(zip(entrance_ids,destination_regions)) # Used for Rules only
# Destination Format: LVL | AREA with LVL = Course ID, 0-indexed, AREA = Area as used in sm64 code
area_connections.update({entrance: (destination_course*10 + 1) for entrance, destination_course in temp_assign.items()})
for i in range(len(area_connections)):
if (int(area_connections[i]/10) == 12):
# Change first occurence of course 12 (THI) to Area 2 (THI Tiny)
area_connections[i] = 12*10 + 2
break
connect_regions(world, player, "Menu", sm64courses[temp_assign[0]])
connect_regions(world, player, "Menu", sm64courses[temp_assign[1]], lambda state: state.has("Power Star", player, 1))
connect_regions(world, player, "Menu", sm64courses[temp_assign[2]], lambda state: state.has("Power Star", player, 3))
connect_regions(world, player, "Menu", sm64courses[temp_assign[3]], lambda state: state.has("Power Star", player, 3))
connect_regions(world, player, "Menu", "Bowser in the Dark World", lambda state: state.has("Power Star", player, world.FirstBowserStarDoorCost[player].value))
connect_regions(world, player, "Menu", sm64courses[temp_assign[4]], lambda state: state.has("Power Star", player, 12))
# 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)})
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", "Basement", lambda state: state.has("Basement Key", player) or state.has("Progressive Key", player, 1))
connect_regions(world, player, "Basement", sm64courses[temp_assign[5]])
connect_regions(world, player, "Basement", sm64courses[temp_assign[6]])
connect_regions(world, player, "Basement", sm64courses[temp_assign[7]])
connect_regions(world, player, "Basement", sm64courses[temp_assign[8]], lambda state: state.has("Power Star", player, world.BasementStarDoorCost[player].value))
connect_regions(world, player, "Basement", "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, "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, "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]])
connect_regions(world, player, "Second Floor", sm64courses[temp_assign[10]])
connect_regions(world, player, "Second Floor", sm64courses[temp_assign[11]])
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", "Third Floor", lambda state: state.has("Power Star", player, world.SecondFloorStarDoorCost[player].value))
connect_regions(world, player, "Third Floor", sm64courses[temp_assign[14]])
connect_regions(world, player, "Third Floor", sm64courses[temp_assign[15]])
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
#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("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("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))
@ -89,18 +109,14 @@ def set_rules(world, player: int, area_connections):
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("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 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))
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("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("Wing Mario Over the Rainbow", 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))
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))
world.completion_condition[player] = lambda state: state.can_reach("Third Floor", 'Region', player) and state.has("Power Star", player, world.StarsToFinish[player].value)
if world.MIPS1Cost[player].value > world.MIPS2Cost[player].value:
world.MIPS2Cost[player].value = world.MIPS1Cost[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))
world.completion_condition[player] = lambda state: state.can_reach("Bowser in the Sky", 'Region', player)

View File

@ -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, sm64paintings
from .Regions import create_regions, sm64courses, sm64entrances_s, sm64_internalloc_to_string, sm64_internalloc_to_regionid
from BaseClasses import Item, Tutorial, ItemClassification
from ..AutoWorld import World, WebWorld
@ -54,10 +54,10 @@ class SM64World(World):
set_rules(self.world, self.player, self.area_connections)
if self.topology_present:
# Write area_connections to spoiler log
for painting_id, destination in self.area_connections.items():
for entrance, destination in self.area_connections.items():
self.world.spoiler.set_entrance(
sm64paintings[painting_id] + " Painting",
sm64courses[destination // 10],
sm64_internalloc_to_string[entrance] + " Entrance",
sm64_internalloc_to_string[destination],
'entrance', self.player)
def create_item(self, name: str) -> Item:
@ -74,9 +74,13 @@ class SM64World(World):
def generate_basic(self):
staritem = self.create_item("Power Star")
starcount = min(self.world.StarsToFinish[self.player].value + self.world.ExtraStars[self.player].value,120)
starcount = self.world.AmountOfStars[self.player].value
if (not self.world.EnableCoinStars[self.player].value):
starcount = max(starcount - 15,self.world.StarsToFinish[self.player].value)
starcount = max(35,self.world.AmountOfStars[self.player].value-15)
starcount = max(starcount, self.world.FirstBowserStarDoorCost[self.player].value,
self.world.BasementStarDoorCost[self.player].value, self.world.SecondFloorStarDoorCost[self.player].value,
self.world.MIPS1Cost[self.player].value, self.world.MIPS2Cost[self.player].value,
self.world.StarsToFinish[self.player].value)
self.world.itempool += [staritem for i in range(0,starcount)]
mushroomitem = self.create_item("1Up Mushroom")
self.world.itempool += [mushroomitem for i in range(starcount,120 - (15 if not self.world.EnableCoinStars[self.player].value else 0))]
@ -117,6 +121,8 @@ class SM64World(World):
"FirstBowserDoorCost": self.world.FirstBowserStarDoorCost[self.player].value,
"BasementDoorCost": self.world.BasementStarDoorCost[self.player].value,
"SecondFloorCost": self.world.SecondFloorStarDoorCost[self.player].value,
"MIPS1Cost": self.world.MIPS1Cost[self.player].value,
"MIPS2Cost": self.world.MIPS2Cost[self.player].value,
"StarsToFinish": self.world.StarsToFinish[self.player].value,
"DeathLink": self.world.death_link[self.player].value,
}
@ -145,8 +151,9 @@ class SM64World(World):
def modify_multidata(self, multidata):
if self.topology_present:
er_hint_data = {}
for painting_id, destination in self.area_connections.items():
region = self.world.get_region(sm64courses[destination // 10], self.player)
for entrance, destination in self.area_connections.items():
regionid = sm64_internalloc_to_regionid[destination]
region = self.world.get_region(sm64courses[regionid], self.player)
for location in region.locations:
er_hint_data[location.address] = sm64paintings[painting_id]
er_hint_data[location.address] = sm64_internalloc_to_string[entrance]
multidata['er_hint_data'][self.player] = er_hint_data