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
|
return False
|
||||||
|
|
||||||
def can_fill(self, item: Item):
|
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
|
return True
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
@ -973,15 +969,24 @@ class Location():
|
||||||
class Item():
|
class Item():
|
||||||
location: Optional[Location] = None
|
location: Optional[Location] = None
|
||||||
world: Optional[MultiWorld] = 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"
|
game: str = "Generic"
|
||||||
type: str = None
|
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"
|
pedestal_credit_text: str = "and the Unknown Item"
|
||||||
sickkid_credit_text: Optional[str] = None
|
sickkid_credit_text: Optional[str] = None
|
||||||
magicshop_credit_text: Optional[str] = None
|
magicshop_credit_text: Optional[str] = None
|
||||||
zora_credit_text: Optional[str] = None
|
zora_credit_text: Optional[str] = None
|
||||||
fluteboy_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):
|
def __init__(self, name: str, advancement: bool, code: Optional[int], player: int):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -1008,51 +1013,6 @@ class Item():
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash((self.name, self.player))
|
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):
|
def __repr__(self):
|
||||||
return self.__str__()
|
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):
|
for player in range(1, world.players + 1):
|
||||||
checks_in_area[player]["Total"] = 0
|
checks_in_area[player]["Total"] = 0
|
||||||
|
|
||||||
for location in [loc for loc in world.get_filled_locations() if type(loc.address) is int]:
|
for location in world.get_filled_locations():
|
||||||
main_entrance = get_entrance_to_region(location.parent_region)
|
if type(location.address) is int:
|
||||||
if location.game != "A Link to the Past":
|
main_entrance = get_entrance_to_region(location.parent_region)
|
||||||
checks_in_area[location.player]["Light World"].append(location.address)
|
if location.game != "A Link to the Past":
|
||||||
elif location.parent_region.dungeon:
|
checks_in_area[location.player]["Light World"].append(location.address)
|
||||||
dungeonname = {'Inverted Agahnims Tower': 'Agahnims Tower',
|
elif location.parent_region.dungeon:
|
||||||
'Inverted Ganons Tower': 'Ganons Tower'} \
|
dungeonname = {'Inverted Agahnims Tower': 'Agahnims Tower',
|
||||||
.get(location.parent_region.dungeon.name, location.parent_region.dungeon.name)
|
'Inverted Ganons Tower': 'Ganons Tower'} \
|
||||||
checks_in_area[location.player][dungeonname].append(location.address)
|
.get(location.parent_region.dungeon.name, location.parent_region.dungeon.name)
|
||||||
elif main_entrance.parent_region.type == RegionType.LightWorld:
|
checks_in_area[location.player][dungeonname].append(location.address)
|
||||||
checks_in_area[location.player]["Light World"].append(location.address)
|
elif main_entrance.parent_region.type == RegionType.LightWorld:
|
||||||
elif main_entrance.parent_region.type == RegionType.DarkWorld:
|
checks_in_area[location.player]["Light World"].append(location.address)
|
||||||
checks_in_area[location.player]["Dark World"].append(location.address)
|
elif main_entrance.parent_region.type == RegionType.DarkWorld:
|
||||||
checks_in_area[location.player]["Total"] += 1
|
checks_in_area[location.player]["Dark World"].append(location.address)
|
||||||
|
checks_in_area[location.player]["Total"] += 1
|
||||||
|
|
||||||
oldmancaves = []
|
oldmancaves = []
|
||||||
takeanyregions = ["Old Man Sword Cave", "Take-Any #1", "Take-Any #2", "Take-Any #3", "Take-Any #4"]
|
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
|
{str(location): get_path(state, location.parent_region) for sphere in collection_spheres for location in
|
||||||
sphere if location.player == player})
|
sphere if location.player == player})
|
||||||
if player in world.get_game_players("A Link to the Past"):
|
if player in world.get_game_players("A Link to the Past"):
|
||||||
for path in dict(world.spoiler.paths).values():
|
# If Pyramid Fairy Entrance needs to be reached, also path to Big Bomb Shop
|
||||||
if any(exit_path == 'Pyramid Fairy' for (_, exit_path) in path):
|
# Maybe move the big bomb over to the Event system instead?
|
||||||
if world.mode[player] != 'inverted':
|
if any(exit_path == 'Pyramid Fairy' for path in world.spoiler.paths.values() for (_, exit_path) in path):
|
||||||
world.spoiler.paths[str(world.get_region('Big Bomb Shop', player))] = \
|
if world.mode[player] != 'inverted':
|
||||||
get_path(state,world.get_region('Big Bomb Shop', player))
|
world.spoiler.paths[str(world.get_region('Big Bomb Shop', player))] = \
|
||||||
else:
|
get_path(state, world.get_region('Big Bomb Shop', player))
|
||||||
world.spoiler.paths[str(world.get_region('Inverted Big Bomb Shop', player))] = \
|
else:
|
||||||
get_path(state,world.get_region('Inverted Big Bomb Shop', player))
|
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
|
# we can finally output our playthrough
|
||||||
world.spoiler.playthrough = {"0": sorted([str(item) for item in world.precollected_items if item.advancement])}
|
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
|
build: int
|
||||||
|
|
||||||
|
|
||||||
__version__ = "0.1.6"
|
__version__ = "0.1.7"
|
||||||
version_tuple = tuplize_version(__version__)
|
version_tuple = tuplize_version(__version__)
|
||||||
|
|
||||||
import builtins
|
import builtins
|
||||||
|
|
|
@ -29,4 +29,49 @@ class ALttPItem(Item):
|
||||||
self.zora_credit_text = zora_credit
|
self.zora_credit_text = zora_credit
|
||||||
self.magicshop_credit_text = witch_credit
|
self.magicshop_credit_text = witch_credit
|
||||||
self.fluteboy_credit_text = flute_boy_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]]
|
world.difficulty_requirements[player] = difficulties[world.difficulty[player]]
|
||||||
|
|
||||||
def create_regions(self):
|
def create_regions(self):
|
||||||
|
# noinspection PyAttributeOutsideInit
|
||||||
self.rom_name_available_event = threading.Event()
|
self.rom_name_available_event = threading.Event()
|
||||||
|
|
||||||
player = self.player
|
player = self.player
|
||||||
|
|
Loading…
Reference in New Issue