LttP: Move more functionality into ALttPItem from Item
LttP: More efficiently build !hint entrance info LttP: More efficiently check for and build Big Bomb Shop playthrough path
This commit is contained in:
parent
de4775b0c8
commit
de567cc701
|
@ -808,10 +808,6 @@ class Region(object):
|
|||
return False
|
||||
|
||||
def can_fill(self, item: Item):
|
||||
inside_dungeon_item = item.locked_dungeon_item
|
||||
if inside_dungeon_item:
|
||||
return self.dungeon.is_dungeon_item(item) and item.player == self.player
|
||||
|
||||
return True
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -973,15 +969,24 @@ class Location():
|
|||
class Item():
|
||||
location: Optional[Location] = None
|
||||
world: Optional[MultiWorld] = None
|
||||
code: Optional[str] = None # an item with ID None is called an Event, and does not get written to multidata
|
||||
game: str = "Generic"
|
||||
type: str = None
|
||||
never_exclude = False # change manually to ensure that a specific nonprogression item never goes on an excluded location
|
||||
# change manually to ensure that a specific non-progression item never goes on an excluded location
|
||||
never_exclude = False
|
||||
|
||||
# need to find a decent place for these to live and to allow other games to register texts if they want.
|
||||
pedestal_credit_text: str = "and the Unknown Item"
|
||||
sickkid_credit_text: Optional[str] = None
|
||||
magicshop_credit_text: Optional[str] = None
|
||||
zora_credit_text: Optional[str] = None
|
||||
fluteboy_credit_text: Optional[str] = None
|
||||
code: Optional[str] = None # an item with ID None is called an Event, and does not get written to multidata
|
||||
|
||||
# hopefully temporary attributes to satisfy legacy LttP code, proper implementation in subclass ALttPItem
|
||||
smallkey: bool = False
|
||||
bigkey: bool = False
|
||||
map: bool = False
|
||||
compass: bool = False
|
||||
|
||||
def __init__(self, name: str, advancement: bool, code: Optional[int], player: int):
|
||||
self.name = name
|
||||
|
@ -1008,51 +1013,6 @@ class Item():
|
|||
def __hash__(self):
|
||||
return hash((self.name, self.player))
|
||||
|
||||
@property
|
||||
def crystal(self) -> bool:
|
||||
return self.type == 'Crystal'
|
||||
|
||||
@property
|
||||
def smallkey(self) -> bool:
|
||||
return self.type == 'SmallKey'
|
||||
|
||||
@property
|
||||
def bigkey(self) -> bool:
|
||||
return self.type == 'BigKey'
|
||||
|
||||
@property
|
||||
def map(self) -> bool:
|
||||
return self.type == 'Map'
|
||||
|
||||
@property
|
||||
def compass(self) -> bool:
|
||||
return self.type == 'Compass'
|
||||
|
||||
@property
|
||||
def dungeon_item(self) -> Optional[str]:
|
||||
if self.game == "A Link to the Past" and self.type in {"SmallKey", "BigKey", "Map", "Compass"}:
|
||||
return self.type
|
||||
|
||||
@property
|
||||
def shuffled_dungeon_item(self) -> bool:
|
||||
dungeon_item_type = self.dungeon_item
|
||||
if dungeon_item_type:
|
||||
return {"SmallKey" : self.world.keyshuffle,
|
||||
"BigKey": self.world.bigkeyshuffle,
|
||||
"Map": self.world.mapshuffle,
|
||||
"Compass": self.world.compassshuffle}[dungeon_item_type][self.player]
|
||||
return False
|
||||
|
||||
@property
|
||||
def locked_dungeon_item(self) -> bool:
|
||||
dungeon_item_type = self.dungeon_item
|
||||
if dungeon_item_type:
|
||||
return not {"SmallKey" : self.world.keyshuffle,
|
||||
"BigKey": self.world.bigkeyshuffle,
|
||||
"Map": self.world.mapshuffle,
|
||||
"Compass": self.world.compassshuffle}[dungeon_item_type][self.player]
|
||||
return False
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
|
|
46
Main.py
46
Main.py
|
@ -249,20 +249,21 @@ def main(args, seed=None):
|
|||
for player in range(1, world.players + 1):
|
||||
checks_in_area[player]["Total"] = 0
|
||||
|
||||
for location in [loc for loc in world.get_filled_locations() if type(loc.address) is int]:
|
||||
main_entrance = get_entrance_to_region(location.parent_region)
|
||||
if location.game != "A Link to the Past":
|
||||
checks_in_area[location.player]["Light World"].append(location.address)
|
||||
elif location.parent_region.dungeon:
|
||||
dungeonname = {'Inverted Agahnims Tower': 'Agahnims Tower',
|
||||
'Inverted Ganons Tower': 'Ganons Tower'} \
|
||||
.get(location.parent_region.dungeon.name, location.parent_region.dungeon.name)
|
||||
checks_in_area[location.player][dungeonname].append(location.address)
|
||||
elif main_entrance.parent_region.type == RegionType.LightWorld:
|
||||
checks_in_area[location.player]["Light World"].append(location.address)
|
||||
elif main_entrance.parent_region.type == RegionType.DarkWorld:
|
||||
checks_in_area[location.player]["Dark World"].append(location.address)
|
||||
checks_in_area[location.player]["Total"] += 1
|
||||
for location in world.get_filled_locations():
|
||||
if type(location.address) is int:
|
||||
main_entrance = get_entrance_to_region(location.parent_region)
|
||||
if location.game != "A Link to the Past":
|
||||
checks_in_area[location.player]["Light World"].append(location.address)
|
||||
elif location.parent_region.dungeon:
|
||||
dungeonname = {'Inverted Agahnims Tower': 'Agahnims Tower',
|
||||
'Inverted Ganons Tower': 'Ganons Tower'} \
|
||||
.get(location.parent_region.dungeon.name, location.parent_region.dungeon.name)
|
||||
checks_in_area[location.player][dungeonname].append(location.address)
|
||||
elif main_entrance.parent_region.type == RegionType.LightWorld:
|
||||
checks_in_area[location.player]["Light World"].append(location.address)
|
||||
elif main_entrance.parent_region.type == RegionType.DarkWorld:
|
||||
checks_in_area[location.player]["Dark World"].append(location.address)
|
||||
checks_in_area[location.player]["Total"] += 1
|
||||
|
||||
oldmancaves = []
|
||||
takeanyregions = ["Old Man Sword Cave", "Take-Any #1", "Take-Any #2", "Take-Any #3", "Take-Any #4"]
|
||||
|
@ -497,14 +498,15 @@ def create_playthrough(world):
|
|||
{str(location): get_path(state, location.parent_region) for sphere in collection_spheres for location in
|
||||
sphere if location.player == player})
|
||||
if player in world.get_game_players("A Link to the Past"):
|
||||
for path in dict(world.spoiler.paths).values():
|
||||
if any(exit_path == 'Pyramid Fairy' for (_, exit_path) in path):
|
||||
if world.mode[player] != 'inverted':
|
||||
world.spoiler.paths[str(world.get_region('Big Bomb Shop', player))] = \
|
||||
get_path(state,world.get_region('Big Bomb Shop', player))
|
||||
else:
|
||||
world.spoiler.paths[str(world.get_region('Inverted Big Bomb Shop', player))] = \
|
||||
get_path(state,world.get_region('Inverted Big Bomb Shop', player))
|
||||
# If Pyramid Fairy Entrance needs to be reached, also path to Big Bomb Shop
|
||||
# Maybe move the big bomb over to the Event system instead?
|
||||
if any(exit_path == 'Pyramid Fairy' for path in world.spoiler.paths.values() for (_, exit_path) in path):
|
||||
if world.mode[player] != 'inverted':
|
||||
world.spoiler.paths[str(world.get_region('Big Bomb Shop', player))] = \
|
||||
get_path(state, world.get_region('Big Bomb Shop', player))
|
||||
else:
|
||||
world.spoiler.paths[str(world.get_region('Inverted Big Bomb Shop', player))] = \
|
||||
get_path(state, world.get_region('Inverted Big Bomb Shop', player))
|
||||
|
||||
# we can finally output our playthrough
|
||||
world.spoiler.playthrough = {"0": sorted([str(item) for item in world.precollected_items if item.advancement])}
|
||||
|
|
2
Utils.py
2
Utils.py
|
@ -13,7 +13,7 @@ class Version(typing.NamedTuple):
|
|||
build: int
|
||||
|
||||
|
||||
__version__ = "0.1.6"
|
||||
__version__ = "0.1.7"
|
||||
version_tuple = tuplize_version(__version__)
|
||||
|
||||
import builtins
|
||||
|
|
|
@ -29,4 +29,49 @@ class ALttPItem(Item):
|
|||
self.zora_credit_text = zora_credit
|
||||
self.magicshop_credit_text = witch_credit
|
||||
self.fluteboy_credit_text = flute_boy_credit
|
||||
self._hint_text = hint_text
|
||||
self._hint_text = hint_text
|
||||
|
||||
@property
|
||||
def crystal(self) -> bool:
|
||||
return self.type == 'Crystal'
|
||||
|
||||
@property
|
||||
def smallkey(self) -> bool:
|
||||
return self.type == 'SmallKey'
|
||||
|
||||
@property
|
||||
def bigkey(self) -> bool:
|
||||
return self.type == 'BigKey'
|
||||
|
||||
@property
|
||||
def map(self) -> bool:
|
||||
return self.type == 'Map'
|
||||
|
||||
@property
|
||||
def compass(self) -> bool:
|
||||
return self.type == 'Compass'
|
||||
|
||||
@property
|
||||
def dungeon_item(self) -> Optional[str]:
|
||||
if self.game == "A Link to the Past" and self.type in {"SmallKey", "BigKey", "Map", "Compass"}:
|
||||
return self.type
|
||||
|
||||
@property
|
||||
def shuffled_dungeon_item(self) -> bool:
|
||||
dungeon_item_type = self.dungeon_item
|
||||
if dungeon_item_type:
|
||||
return {"SmallKey" : self.world.keyshuffle,
|
||||
"BigKey": self.world.bigkeyshuffle,
|
||||
"Map": self.world.mapshuffle,
|
||||
"Compass": self.world.compassshuffle}[dungeon_item_type][self.player]
|
||||
return False
|
||||
|
||||
@property
|
||||
def locked_dungeon_item(self) -> bool:
|
||||
dungeon_item_type = self.dungeon_item
|
||||
if dungeon_item_type:
|
||||
return not {"SmallKey" : self.world.keyshuffle,
|
||||
"BigKey": self.world.bigkeyshuffle,
|
||||
"Map": self.world.mapshuffle,
|
||||
"Compass": self.world.compassshuffle}[dungeon_item_type][self.player]
|
||||
return False
|
|
@ -62,6 +62,7 @@ class ALTTPWorld(World):
|
|||
world.difficulty_requirements[player] = difficulties[world.difficulty[player]]
|
||||
|
||||
def create_regions(self):
|
||||
# noinspection PyAttributeOutsideInit
|
||||
self.rom_name_available_event = threading.Event()
|
||||
|
||||
player = self.player
|
||||
|
|
Loading…
Reference in New Issue