optimize sweep_for_events, some has_ functions and some minor things
This commit is contained in:
parent
cac5795e01
commit
b5048d99b9
|
@ -5,13 +5,13 @@ from enum import Enum, unique
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
from collections import OrderedDict, Counter, deque
|
from collections import OrderedDict, Counter, deque
|
||||||
|
from typing import Union, Optional
|
||||||
|
import secrets
|
||||||
|
import random
|
||||||
|
|
||||||
from EntranceShuffle import door_addresses, indirect_connections
|
from EntranceShuffle import door_addresses, indirect_connections
|
||||||
from Utils import int16_as_bytes
|
from Utils import int16_as_bytes
|
||||||
from typing import Union, Optional
|
from Items import item_name_groups
|
||||||
|
|
||||||
import secrets
|
|
||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
class World(object):
|
class World(object):
|
||||||
|
@ -429,7 +429,7 @@ class CollectionState(object):
|
||||||
self.world = parent
|
self.world = parent
|
||||||
self.reachable_regions = {player: set() for player in range(1, parent.players + 1)}
|
self.reachable_regions = {player: set() for player in range(1, parent.players + 1)}
|
||||||
self.blocked_connections = {player: set() for player in range(1, parent.players + 1)}
|
self.blocked_connections = {player: set() for player in range(1, parent.players + 1)}
|
||||||
self.events = []
|
self.events = set()
|
||||||
self.path = {}
|
self.path = {}
|
||||||
self.locations_checked = set()
|
self.locations_checked = set()
|
||||||
self.stale = {player: True for player in range(1, parent.players + 1)}
|
self.stale = {player: True for player in range(1, parent.players + 1)}
|
||||||
|
@ -492,23 +492,19 @@ class CollectionState(object):
|
||||||
return spot.can_reach(self)
|
return spot.can_reach(self)
|
||||||
|
|
||||||
def sweep_for_events(self, key_only: bool = False, locations=None):
|
def sweep_for_events(self, key_only: bool = False, locations=None):
|
||||||
# this may need improvement
|
|
||||||
if locations is None:
|
if locations is None:
|
||||||
locations = self.world.get_filled_locations()
|
locations = self.world.get_filled_locations()
|
||||||
new_locations = True
|
new_locations = True
|
||||||
checked_locations = 0
|
|
||||||
while new_locations:
|
while new_locations:
|
||||||
reachable_events = [location for location in locations if location.event and
|
reachable_events = {location for location in locations if location.event and
|
||||||
(not key_only or (not self.world.keyshuffle[
|
(not key_only or (not self.world.keyshuffle[
|
||||||
location.item.player] and location.item.smallkey) or (not self.world.bigkeyshuffle[
|
location.item.player] and location.item.smallkey) or (not self.world.bigkeyshuffle[
|
||||||
location.item.player] and location.item.bigkey))
|
location.item.player] and location.item.bigkey))
|
||||||
and location.can_reach(self)]
|
and location.can_reach(self)}
|
||||||
for event in reachable_events:
|
new_locations = reachable_events - self.events
|
||||||
if event not in self.events:
|
for event in new_locations:
|
||||||
self.events.append(event)
|
self.events.add(event)
|
||||||
self.collect(event.item, True, event)
|
self.collect(event.item, True, event)
|
||||||
new_locations = len(reachable_events) > checked_locations
|
|
||||||
checked_locations = len(reachable_events)
|
|
||||||
|
|
||||||
def has(self, item, player: int, count: int = 1):
|
def has(self, item, player: int, count: int = 1):
|
||||||
return self.prog_items[item, player] >= count
|
return self.prog_items[item, player] >= count
|
||||||
|
@ -532,11 +528,10 @@ class CollectionState(object):
|
||||||
|
|
||||||
def has_crystals(self, count: int, player: int) -> bool:
|
def has_crystals(self, count: int, player: int) -> bool:
|
||||||
found: int = 0
|
found: int = 0
|
||||||
for itemname, itemplayer in self.prog_items:
|
for crystalnumber in range(1, 8):
|
||||||
if itemplayer == player and itemname.startswith('Crystal '):
|
found += self.prog_items[f"Crystal {crystalnumber}", player]
|
||||||
found += 1
|
if found >= count:
|
||||||
if found >= count:
|
return True
|
||||||
return True
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def can_lift_rocks(self, player: int):
|
def can_lift_rocks(self, player: int):
|
||||||
|
@ -546,17 +541,18 @@ class CollectionState(object):
|
||||||
return self.has_bottles(1, player)
|
return self.has_bottles(1, player)
|
||||||
|
|
||||||
def bottle_count(self, player: int) -> int:
|
def bottle_count(self, player: int) -> int:
|
||||||
return len(
|
found: int = 0
|
||||||
tuple(item for (item, itemplayer) in self.prog_items if itemplayer == player and item.startswith('Bottle')))
|
for bottlename in item_name_groups["Bottles"]:
|
||||||
|
found += self.prog_items[bottlename, player]
|
||||||
|
return found
|
||||||
|
|
||||||
def has_bottles(self, bottles: int, player: int):
|
def has_bottles(self, bottles: int, player: int) -> bool:
|
||||||
"""Version of bottle_count that allows fast abort"""
|
"""Version of bottle_count that allows fast abort"""
|
||||||
found: int = 0
|
found: int = 0
|
||||||
for itemname, itemplayer in self.prog_items:
|
for bottlename in item_name_groups["Bottles"]:
|
||||||
if itemplayer == player and itemname.startswith('Bottle'):
|
found += self.prog_items[bottlename, player]
|
||||||
found += 1
|
if found >= bottles:
|
||||||
if found >= bottles:
|
return True
|
||||||
return True
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def has_hearts(self, player: int, count: int) -> int:
|
def has_hearts(self, player: int, count: int) -> int:
|
||||||
|
@ -995,6 +991,9 @@ class Location(object):
|
||||||
world = self.parent_region.world if self.parent_region and self.parent_region.world else None
|
world = self.parent_region.world if self.parent_region and self.parent_region.world else None
|
||||||
return world.get_name_string_for_object(self) if world else f'{self.name} (Player {self.player})'
|
return world.get_name_string_for_object(self) if world else f'{self.name} (Player {self.player})'
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash((self.name, self.player))
|
||||||
|
|
||||||
|
|
||||||
class Item(object):
|
class Item(object):
|
||||||
|
|
||||||
|
|
2
Fill.py
2
Fill.py
|
@ -209,7 +209,7 @@ def fill_restrictive(world, base_state: CollectionState, locations, itempool, si
|
||||||
if location.item and not location.event:
|
if location.item and not location.event:
|
||||||
placements.append(location)
|
placements.append(location)
|
||||||
raise FillError(f'No more spots to place {item_to_place}, locations {locations} are invalid. '
|
raise FillError(f'No more spots to place {item_to_place}, locations {locations} are invalid. '
|
||||||
f'\nAlready placed {len(placements)}: {", ".join(placements)}')
|
f'Already placed {len(placements)}: {", ".join(placements)}')
|
||||||
|
|
||||||
world.push_item(spot_to_fill, item_to_place, False)
|
world.push_item(spot_to_fill, item_to_place, False)
|
||||||
locations.remove(spot_to_fill)
|
locations.remove(spot_to_fill)
|
||||||
|
|
2
Items.py
2
Items.py
|
@ -1,9 +1,9 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from BaseClasses import Item
|
|
||||||
|
|
||||||
|
|
||||||
def ItemFactory(items, player):
|
def ItemFactory(items, player):
|
||||||
|
from BaseClasses import Item
|
||||||
ret = []
|
ret = []
|
||||||
singleton = False
|
singleton = False
|
||||||
if isinstance(items, str):
|
if isinstance(items, str):
|
||||||
|
|
2
Rom.py
2
Rom.py
|
@ -348,6 +348,8 @@ def _populate_sprite_table():
|
||||||
if sprite.valid:
|
if sprite.valid:
|
||||||
_sprite_table[sprite.name.lower()] = sprite
|
_sprite_table[sprite.name.lower()] = sprite
|
||||||
_sprite_table[os.path.basename(file).split(".")[0].lower()] = sprite # alias for filename base
|
_sprite_table[os.path.basename(file).split(".")[0].lower()] = sprite # alias for filename base
|
||||||
|
else:
|
||||||
|
logging.debug(f"Spritefile {file} could not be loaded as a valid sprite.")
|
||||||
|
|
||||||
with concurrent.futures.ThreadPoolExecutor() as pool:
|
with concurrent.futures.ThreadPoolExecutor() as pool:
|
||||||
for dir in [local_path('data/sprites/alttpr'), local_path('data/sprites/custom')]:
|
for dir in [local_path('data/sprites/alttpr'), local_path('data/sprites/custom')]:
|
||||||
|
|
|
@ -17,17 +17,18 @@
|
||||||
# To test if your yaml is valid or not, you can use this website:
|
# To test if your yaml is valid or not, you can use this website:
|
||||||
# http://www.yamllint.com/
|
# http://www.yamllint.com/
|
||||||
|
|
||||||
description: Your Description Here # Used to describe your yaml. Useful if you have multiple files
|
description: easy template # Used to describe your yaml. Useful if you have multiple files
|
||||||
name: YourName # Your name in-game. Spaces and underscores will be replaced with dashes
|
name: YourName # Your name in-game. Spaces will be replaced with underscores and there is a 16 character limit
|
||||||
glitches_required: # Determine the logic required to complete the seed
|
glitches_required: # Determine the logic required to complete the seed
|
||||||
none: 1 # No glitches required
|
none: 1 # No glitches required
|
||||||
minor_glitches: 0 # Puts fake flipper, waterwalk, super bunny shenanigans, and etc into logic
|
minor_glitches: 0 # Puts fake flipper, waterwalk, super bunny shenanigans, and etc into logic
|
||||||
overworld_glitches: 0 # Assumes the player has knowledge of both overworld major glitches (boots clips, mirror clips) and minor glitches (fake flipper, super bunny shenanigans, water walk and etc.)
|
overworld_glitches: 0 # Assumes the player has knowledge of both overworld major glitches (boots clips, mirror clips) and minor glitches (fake flipper, super bunny shenanigans, water walk and etc.)
|
||||||
no_logic: 0 # Items are places completely at random and with no regard for logic. Your fire rod could be on Trinexx
|
no_logic: 0 # Items are places completely at random and with no regard for logic. Your fire rod could be on Trinexx
|
||||||
meta_ignore: # Nullify options specified in the meta.yaml file. Adding an option here guarantees it will not occur in your seed, even if the .yaml file specifies it
|
meta_ignore: # Nullify options specified in the meta.yaml file. Adding an option here guarantees it will not occur in your seed, even if the .yaml file specifies it
|
||||||
world_state:
|
mode:
|
||||||
- inverted # Never play inverted seeds
|
- inverted # Never play inverted seeds
|
||||||
- retro # Never play retro seeds
|
retro:
|
||||||
|
- on # Never play retro seeds
|
||||||
weapons:
|
weapons:
|
||||||
- swordless # Never play a swordless seed
|
- swordless # Never play a swordless seed
|
||||||
map_shuffle: # Shuffle dungeon maps into the world and other dungeons, including other players' worlds
|
map_shuffle: # Shuffle dungeon maps into the world and other dungeons, including other players' worlds
|
||||||
|
|
Loading…
Reference in New Issue