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)
 | 
			
		||||
                                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)
 | 
			
		||||
            new_locations = len(reachable_events) > checked_locations
 | 
			
		||||
            checked_locations = len(reachable_events)
 | 
			
		||||
 | 
			
		||||
    def has(self, item, player: int, count: int = 1):
 | 
			
		||||
        return self.prog_items[item, player] >= count
 | 
			
		||||
| 
						 | 
				
			
			@ -532,9 +528,8 @@ 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
 | 
			
		||||
        for crystalnumber in range(1, 8):
 | 
			
		||||
            found += self.prog_items[f"Crystal {crystalnumber}", player]
 | 
			
		||||
            if found >= count:
 | 
			
		||||
                return True
 | 
			
		||||
        return False
 | 
			
		||||
| 
						 | 
				
			
			@ -546,15 +541,16 @@ 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
 | 
			
		||||
        for bottlename in item_name_groups["Bottles"]:
 | 
			
		||||
            found += self.prog_items[bottlename, player]
 | 
			
		||||
            if found >= bottles:
 | 
			
		||||
                return True
 | 
			
		||||
        return False
 | 
			
		||||
| 
						 | 
				
			
			@ -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