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 json
|
||||
from collections import OrderedDict, Counter, deque
|
||||
from typing import Union, Optional
|
||||
import secrets
|
||||
import random
|
||||
|
||||
from EntranceShuffle import door_addresses, indirect_connections
|
||||
from Utils import int16_as_bytes
|
||||
from typing import Union, Optional
|
||||
|
||||
import secrets
|
||||
import random
|
||||
from Items import item_name_groups
|
||||
|
||||
|
||||
class World(object):
|
||||
|
@ -429,7 +429,7 @@ class CollectionState(object):
|
|||
self.world = parent
|
||||
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.events = []
|
||||
self.events = set()
|
||||
self.path = {}
|
||||
self.locations_checked = set()
|
||||
self.stale = {player: True for player in range(1, parent.players + 1)}
|
||||
|
@ -492,23 +492,19 @@ class CollectionState(object):
|
|||
return spot.can_reach(self)
|
||||
|
||||
def sweep_for_events(self, key_only: bool = False, locations=None):
|
||||
# this may need improvement
|
||||
if locations is None:
|
||||
locations = self.world.get_filled_locations()
|
||||
new_locations = True
|
||||
checked_locations = 0
|
||||
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[
|
||||
location.item.player] and location.item.smallkey) or (not self.world.bigkeyshuffle[
|
||||
location.item.player] and location.item.bigkey))
|
||||
and location.can_reach(self)]
|
||||
for event in reachable_events:
|
||||
if event not in self.events:
|
||||
self.events.append(event)
|
||||
self.collect(event.item, True, event)
|
||||
new_locations = len(reachable_events) > checked_locations
|
||||
checked_locations = len(reachable_events)
|
||||
and location.can_reach(self)}
|
||||
new_locations = reachable_events - self.events
|
||||
for event in new_locations:
|
||||
self.events.add(event)
|
||||
self.collect(event.item, True, event)
|
||||
|
||||
def has(self, item, player: int, count: int = 1):
|
||||
return self.prog_items[item, player] >= count
|
||||
|
@ -532,11 +528,10 @@ class CollectionState(object):
|
|||
|
||||
def has_crystals(self, count: int, player: int) -> bool:
|
||||
found: int = 0
|
||||
for itemname, itemplayer in self.prog_items:
|
||||
if itemplayer == player and itemname.startswith('Crystal '):
|
||||
found += 1
|
||||
if found >= count:
|
||||
return True
|
||||
for crystalnumber in range(1, 8):
|
||||
found += self.prog_items[f"Crystal {crystalnumber}", player]
|
||||
if found >= count:
|
||||
return True
|
||||
return False
|
||||
|
||||
def can_lift_rocks(self, player: int):
|
||||
|
@ -546,17 +541,18 @@ class CollectionState(object):
|
|||
return self.has_bottles(1, player)
|
||||
|
||||
def bottle_count(self, player: int) -> int:
|
||||
return len(
|
||||
tuple(item for (item, itemplayer) in self.prog_items if itemplayer == player and item.startswith('Bottle')))
|
||||
found: int = 0
|
||||
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"""
|
||||
found: int = 0
|
||||
for itemname, itemplayer in self.prog_items:
|
||||
if itemplayer == player and itemname.startswith('Bottle'):
|
||||
found += 1
|
||||
if found >= bottles:
|
||||
return True
|
||||
for bottlename in item_name_groups["Bottles"]:
|
||||
found += self.prog_items[bottlename, player]
|
||||
if found >= bottles:
|
||||
return True
|
||||
return False
|
||||
|
||||
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
|
||||
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):
|
||||
|
||||
|
|
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:
|
||||
placements.append(location)
|
||||
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)
|
||||
locations.remove(spot_to_fill)
|
||||
|
|
2
Items.py
2
Items.py
|
@ -1,9 +1,9 @@
|
|||
import logging
|
||||
|
||||
from BaseClasses import Item
|
||||
|
||||
|
||||
def ItemFactory(items, player):
|
||||
from BaseClasses import Item
|
||||
ret = []
|
||||
singleton = False
|
||||
if isinstance(items, str):
|
||||
|
|
2
Rom.py
2
Rom.py
|
@ -348,6 +348,8 @@ def _populate_sprite_table():
|
|||
if sprite.valid:
|
||||
_sprite_table[sprite.name.lower()] = sprite
|
||||
_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:
|
||||
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:
|
||||
# http://www.yamllint.com/
|
||||
|
||||
description: Your Description Here # 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
|
||||
description: easy template # Used to describe your yaml. Useful if you have multiple files
|
||||
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
|
||||
none: 1 # No glitches required
|
||||
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.)
|
||||
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
|
||||
world_state:
|
||||
mode:
|
||||
- inverted # Never play inverted seeds
|
||||
- retro # Never play retro seeds
|
||||
retro:
|
||||
- on # Never play retro seeds
|
||||
weapons:
|
||||
- swordless # Never play a swordless seed
|
||||
map_shuffle: # Shuffle dungeon maps into the world and other dungeons, including other players' worlds
|
||||
|
|
Loading…
Reference in New Issue