SM update (#147)

* fixed generations failing when only bosses are unreachable

* - replaced setting maxDiff to infinity with a bool only affecting boss logics if only bosses are left to finish

* fixed failling generations when using 'fun' settings

Accessibility checks are forced to 'items' if restricted locations are used by VARIA following usage of 'fun' settings

* fixed debug logger

* removed unsupported "suits_restriction" option

* fixed generations failing when only bosses are unreachable (using a less intrusive approach for AP)

* - fixed deathlink emptying reserves

- added death_link_survive option that lets player survive when receiving a deathlink if the have non-empty reserves

* - merged death_link and death_link_survive options
This commit is contained in:
lordlou
2021-12-02 00:11:42 -05:00
committed by GitHub
parent f673dfb7cf
commit 83cfd6ec05
8 changed files with 64 additions and 27 deletions

View File

@@ -2,7 +2,7 @@ import logging
import copy
import os
import threading
from typing import Set
from typing import Set, List
logger = logging.getLogger("Super Metroid")
@@ -59,7 +59,7 @@ class SMWorld(World):
def sm_init(self, parent: MultiWorld):
if (hasattr(parent, "state")): # for unit tests where MultiWorld is instanciated before worlds
self.smbm = {player: SMBoolManager(player, parent.state.smbm[player].maxDiff) for player in parent.get_game_players("Super Metroid")}
self.smbm = {player: SMBoolManager(player, parent.state.smbm[player].maxDiff, parent.state.smbm[player].onlyBossLeft) for player in parent.get_game_players("Super Metroid")}
orig_init(self, parent)
@@ -88,6 +88,10 @@ class SMWorld(World):
if (self.variaRando.args.morphPlacement == "early"):
self.world.local_items[self.player].value.add('Morph')
if (len(self.variaRando.randoExec.setup.restrictedLocs) > 0):
self.world.accessibility[self.player] = self.world.accessibility[self.player].from_text("items")
logger.warning(f"accessibility forced to 'items' for player {self.world.get_player_name(self.player)} because of 'fun' settings")
def generate_basic(self):
itemPool = self.variaRando.container.itemPool
@@ -274,7 +278,7 @@ class SMWorld(World):
openTourianGreyDoors = {0x07C823 + 5: [0x0C], 0x07C831 + 5: [0x0C]}
deathLink = {0x277f04: [int(self.world.death_link[self.player])]}
deathLink = {0x277f04: [self.world.death_link_survive[self.player].value]}
playerNames = {}
playerNameIDMap = {}
@@ -476,17 +480,6 @@ class SMWorld(World):
item.player != self.player or
item.name != "Morph Ball"]
def post_fill(self):
# increase maxDifficulty if only bosses is too difficult to beat game
new_state = CollectionState(self.world)
for item in self.world.itempool:
if item.player == self.player:
new_state.collect(item, True)
new_state.sweep_for_events()
if (any(not self.world.get_location(bossLoc, self.player).can_reach(new_state) for bossLoc in self.locked_items)):
if (self.variaRando.randoExec.setup.services.onlyBossesLeft(self.variaRando.randoExec.setup.startAP, self.variaRando.randoExec.setup.container)):
self.world.state.smbm[self.player].maxDiff = infinity
@classmethod
def stage_fill_hook(cls, world, progitempool, nonexcludeditempool, localrestitempool, nonlocalrestitempool,
restitempool, fill_locations):
@@ -494,6 +487,22 @@ class SMWorld(World):
progitempool.sort(
key=lambda item: 1 if (item.name == 'Morph Ball') else 0)
def post_fill(self):
new_state = CollectionState(self.world)
progitempool = []
for item in self.world.itempool:
if item.player == self.player and item.advancement:
progitempool.append(item)
for item in progitempool:
new_state.collect(item, True)
bossesLoc = ['Draygon', 'Kraid', 'Ridley', 'Phantoon', 'Mother Brain']
for bossLoc in bossesLoc:
if (not self.world.get_location(bossLoc, self.player).can_reach(new_state)):
self.world.state.smbm[self.player].onlyBossLeft = True
break
def create_locations(self, player: int):
for name, id in locations_lookup_name_to_id.items():
self.locations[name] = SMLocation(player, name, id)