55import logging
66import random
77import secrets
8+ import warnings
89from argparse import Namespace
910from collections import Counter , deque
1011from collections .abc import Collection , MutableSequence
@@ -438,12 +439,27 @@ def get_entrance(self, entrance_name: str, player: int) -> Entrance:
438439 def get_location (self , location_name : str , player : int ) -> Location :
439440 return self .regions .location_cache [player ][location_name ]
440441
441- def get_all_state (self , use_cache : bool , allow_partial_entrances : bool = False ,
442+ def get_all_state (self , use_cache : bool | None = None , allow_partial_entrances : bool = False ,
442443 collect_pre_fill_items : bool = True , perform_sweep : bool = True ) -> CollectionState :
443- cached = getattr (self , "_all_state" , None )
444- if use_cache and cached :
445- return cached .copy ()
446-
444+ """
445+ Creates a new CollectionState, and collects all precollected items, all items in the multiworld itempool, those
446+ specified in each worlds' `get_pre_fill_items()`, and then sweeps the multiworld collecting any other items
447+ it is able to reach, building as complete of a completed game state as possible.
448+
449+ :param use_cache: Deprecated and unused.
450+ :param allow_partial_entrances: Whether the CollectionState should allow for disconnected entrances while
451+ sweeping, such as before entrance randomization is complete.
452+ :param collect_pre_fill_items: Whether the items in each worlds' `get_pre_fill_items()` should be added to this
453+ state.
454+ :param perform_sweep: Whether this state should perform a sweep for reachable locations, collecting any placed
455+ items it can.
456+
457+ :return: The completed CollectionState.
458+ """
459+ if __debug__ and use_cache is not None :
460+ # TODO swap to Utils.deprecate when we want this to crash on source and warn on frozen
461+ warnings .warn ("multiworld.get_all_state no longer caches all_state and this argument will be removed." ,
462+ DeprecationWarning )
447463 ret = CollectionState (self , allow_partial_entrances )
448464
449465 for item in self .itempool :
@@ -456,8 +472,6 @@ def get_all_state(self, use_cache: bool, allow_partial_entrances: bool = False,
456472 if perform_sweep :
457473 ret .sweep_for_advancements ()
458474
459- if use_cache :
460- self ._all_state = ret
461475 return ret
462476
463477 def get_items (self ) -> List [Item ]:
@@ -706,6 +720,12 @@ def all_done() -> bool:
706720 sphere .append (locations .pop (n ))
707721
708722 if not sphere :
723+ if __debug__ :
724+ from Fill import FillError
725+ raise FillError (
726+ f"Could not access required locations for accessibility check. Missing: { locations } " ,
727+ multiworld = self ,
728+ )
709729 # ran out of places and did not finish yet, quit
710730 logging .warning (f"Could not access required locations for accessibility check."
711731 f" Missing: { locations } " )
@@ -1150,13 +1170,13 @@ def __init__(self, region_manager: MultiWorld.RegionManager):
11501170 self .region_manager = region_manager
11511171
11521172 def __getitem__ (self , index : int ) -> Location :
1153- return self ._list . __getitem__ ( index )
1173+ return self ._list [ index ]
11541174
11551175 def __setitem__ (self , index : int , value : Location ) -> None :
11561176 raise NotImplementedError ()
11571177
11581178 def __len__ (self ) -> int :
1159- return self ._list . __len__ ( )
1179+ return len ( self ._list )
11601180
11611181 def __iter__ (self ):
11621182 return iter (self ._list )
@@ -1170,8 +1190,8 @@ def copy(self):
11701190
11711191 class LocationRegister (Register ):
11721192 def __delitem__ (self , index : int ) -> None :
1173- location : Location = self ._list . __getitem__ ( index )
1174- self ._list . __delitem__ ( index )
1193+ location : Location = self ._list [ index ]
1194+ del self ._list [ index ]
11751195 del (self .region_manager .location_cache [location .player ][location .name ])
11761196
11771197 def insert (self , index : int , value : Location ) -> None :
@@ -1182,8 +1202,8 @@ def insert(self, index: int, value: Location) -> None:
11821202
11831203 class EntranceRegister (Register ):
11841204 def __delitem__ (self , index : int ) -> None :
1185- entrance : Entrance = self ._list . __getitem__ ( index )
1186- self ._list . __delitem__ ( index )
1205+ entrance : Entrance = self ._list [ index ]
1206+ del self ._list [ index ]
11871207 del (self .region_manager .entrance_cache [entrance .player ][entrance .name ])
11881208
11891209 def insert (self , index : int , value : Entrance ) -> None :
@@ -1430,27 +1450,43 @@ def hint_text(self) -> str:
14301450
14311451
14321452class ItemClassification (IntFlag ):
1433- filler = 0b0000
1453+ filler = 0b00000
14341454 """ aka trash, as in filler items like ammo, currency etc """
14351455
1436- progression = 0b0001
1456+ progression = 0b00001
14371457 """ Item that is logically relevant.
14381458 Protects this item from being placed on excluded or unreachable locations. """
14391459
1440- useful = 0b0010
1460+ useful = 0b00010
14411461 """ Item that is especially useful.
14421462 Protects this item from being placed on excluded or unreachable locations.
14431463 When combined with another flag like "progression", it means "an especially useful progression item". """
14441464
1445- trap = 0b0100
1465+ trap = 0b00100
14461466 """ Item that is detrimental in some way. """
14471467
1448- skip_balancing = 0b1000
1468+ skip_balancing = 0b01000
14491469 """ should technically never occur on its own
14501470 Item that is logically relevant, but progression balancing should not touch.
1451- Typically currency or other counted items. """
1452-
1453- progression_skip_balancing = 0b1001 # only progression gets balanced
1471+
1472+ Possible reasons for why an item should not be pulled ahead by progression balancing:
1473+ 1. This item is quite insignificant, so pulling it earlier doesn't help (currency/etc.)
1474+ 2. It is important for the player experience that this item is evenly distributed in the seed (e.g. goal items) """
1475+
1476+ deprioritized = 0b10000
1477+ """ Should technically never occur on its own.
1478+ Will not be considered for priority locations,
1479+ unless Priority Locations Fill runs out of regular progression items before filling all priority locations.
1480+
1481+ Should be used for items that would feel bad for the player to find on a priority location.
1482+ Usually, these are items that are plentiful or insignificant. """
1483+
1484+ progression_deprioritized_skip_balancing = 0b11001
1485+ """ Since a common case of both skip_balancing and deprioritized is "insignificant progression",
1486+ these items often want both flags. """
1487+
1488+ progression_skip_balancing = 0b01001 # only progression gets balanced
1489+ progression_deprioritized = 0b10001 # only progression can be placed during priority fill
14541490
14551491 def as_flag (self ) -> int :
14561492 """As Network API flag int."""
@@ -1498,6 +1534,10 @@ def useful(self) -> bool:
14981534 def trap (self ) -> bool :
14991535 return ItemClassification .trap in self .classification
15001536
1537+ @property
1538+ def deprioritized (self ) -> bool :
1539+ return ItemClassification .deprioritized in self .classification
1540+
15011541 @property
15021542 def filler (self ) -> bool :
15031543 return not (self .advancement or self .useful or self .trap )
0 commit comments