Skip to content

Commit

Permalink
incomplete framework for bell logic
Browse files Browse the repository at this point in the history
  • Loading branch information
qwint committed Dec 7, 2024
1 parent 9d9e987 commit 6873cbd
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
62 changes: 61 additions & 1 deletion worlds/astalon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
# ░▓████▓▓░█████████░██░ MANY GOOD PROGRAMS AND FEW ERRORS WILL COME TO YOU
# █░▓██▓▓░███░███░██░▓░█ AS LONG AS YOU KEEP HER IN YOUR PROGRAM TO WATCH OVER IT
# ██░░▓▓▓░███░███░██░░██ INCREMENT THIS NUMBER EVERY TIME YOU SAY HI TO BUBSETTE
# ████░░░░██████████░███ hi_bubsette = 3
# ████░░░░██████████░███ hi_bubsette = 4
# ████████░░░░░░░░░░████


Expand Down Expand Up @@ -466,3 +466,63 @@ def remove(self, state: "CollectionState", item: "Item") -> bool:
if changed and getattr(self, "rules", None):
self.rules.clear_cache()
return changed


cache_characters = [c.value for c in Character]
cache_characters.append("Bell")


class AstalonLogicMixin(LogicMixin):
multiworld: MultiWorld
_astalon_cache: Dict[int, Dict[str, List[str]]]
"""cache of player: character {region} for bell logic"""

_astalon_stale: Dict[int, bool]

def init_mixin(self, multiworld) -> None:
players = multiworld.get_game_players(GAME_NAME)
self._astalon_cache = {
player: {c: {"Menu"} for c in cache_characters}
for player in players
}
self._astalon_stale = {player: True for player in players}

def copy_mixin(self, other) -> CollectionState:
players = self.multiworld.get_game_players(GAME_NAME)
other._astalon_cache = {
player: {c: self._astalon_cache[player][c].copy() for c in cache_characters}
for player in players
}
return other

def _astalon_sweep(self, player):
if not self._astalon_stale[player]:
return
self._astalon_stale[player] = False
# (region can_reach dependencies will be covered by indirect connections)
while self._hk_per_player_sweepable_entrances[player]:
# random pop but i don't really care
entrance_name = self._hk_per_player_sweepable_entrances[player].pop()
entrance = self.multiworld.get_entrance(entrance_name, player)
if entrance.parent_region in self.reachable_regions[player]:
# let normal sweep find new regions
entrance.can_reach(self)

def _astalon_character_in_region(self, character: str, parent_region: str, player: int,
target_region: Optional[str] = None) -> bool:
"""
Check if the relevant character has access to parent_region and proliferate to target_region if reachable
target_region can be omitted if evaluating a Location that does not need proliferation
call at the end of the clause otherwise state may be proliferated while the access_rule is still false
"""
if self._astalon_stale[player]:
self._astalon_sweep(player)
if not self.has(character, player):
return False
for c in ("Bell", character):
if region in self._astalon_cache[player][c]:
if target_region:
self._astalon_cache[player][c].append(target_region)
return True

return False
15 changes: 15 additions & 0 deletions worlds/astalon/regions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from enum import Enum
from typing import Dict, Tuple

from BaseClasses import Entrance, Region


class RegionName(str, Enum):
MENU = "Menu"
Expand Down Expand Up @@ -253,6 +255,19 @@ class RegionName(str, Enum):
SP_CAMPFIRE_2 = "Serpent Path - Campfire 2"


class AstalonEntrance(Entrance):
def can_reach(self, state) -> bool:
ret = super().can_reach(state)
if ret:
characters = state._astalon_cache[self.player][self.parent_region].copy()
state._astalon_cache[self.player][self.target_region] = characters
return ret


class AstalonRegion(Region):
entrance_type = AstalonEntrance


@dataclass(frozen=True)
class RegionData:
exits: Tuple[RegionName, ...] = ()
Expand Down

0 comments on commit 6873cbd

Please sign in to comment.