optimize sweep_for_events, some has_ functions and some minor things

This commit is contained in:
Fabian Dill 2020-08-22 19:19:29 +02:00
parent cac5795e01
commit b5048d99b9
5 changed files with 36 additions and 34 deletions

View File

@ -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):

View File

@ -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)

View File

@ -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
View File

@ -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')]:

View File

@ -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