Skip to content

Commit

Permalink
Refactoring logic.
Browse files Browse the repository at this point in the history
  • Loading branch information
Tranquilite0 committed Jun 9, 2024
1 parent 9b727fe commit c954776
Show file tree
Hide file tree
Showing 8 changed files with 601 additions and 600 deletions.
3 changes: 1 addition & 2 deletions worlds/soulblazer/Client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@
from .Names import Addresses, ItemID, MapID
from .Names.ArchipelagoID import BASE_ID, LAIR_ID_OFFSET, NPC_REWARD_OFFSET
from .Locations import (
SoulBlazerLocationData,
address_for_location,
all_locations_table,
LocationType,
chest_table,
npc_reward_table,
lair_table,
)
from .Items import SoulBlazerItemData, all_items_table
from .Items import all_items_table
from .Util import encode_string, is_bit_set, Rectangle
from .Lair import LairData, unpack_lair_data
from .Entity import EntityData, unpack_entity_data
Expand Down
511 changes: 257 additions & 254 deletions worlds/soulblazer/Items.py

Large diffs are not rendered by default.

609 changes: 304 additions & 305 deletions worlds/soulblazer/Locations.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion worlds/soulblazer/Names/Addresses.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@
NPC_REWARD_TABLE_SIZE = 0x08
PLAYER_NAME = 0x001B92 + WRAM_START
PLAYER_NAME_SIZE = 0x09
PLAYER_CURRENT_HEALTH = 0x001B88 + WRAM_START # TODO: use this for deathlink
PLAYER_CURRENT_HEALTH = 0x001B88 + WRAM_START # TODO: use this for deathlink?
CURRENT_MAP_ID = 0x001C6A + WRAM_START
RX_STATUS = 0x001DA0 + WRAM_START
RX_INCREMENT = RX_STATUS + 1
Expand Down
31 changes: 10 additions & 21 deletions worlds/soulblazer/Regions.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,12 +425,8 @@ class ExitData(NamedTuple):
"""The destination region name."""
has_all: List[str] = []
"""List of item names, all of which are required to use this exit."""
# TODO: Might need to refactor this data structure if any location has multiple 'any' dependencies
# TODO: if the only any ends up being swords/magic then change this to flag instead?
has_any: List[str] = []
"""List of item names, where only one are required to use this exit."""
# TODO: May have to refactor data structure if location reachable requirements are needed
rule_flag: RuleFlag = RuleFlag.NONE
"""Optional rule flag assotiated with this exit."""


exits_for_region: Dict[str, List[ExitData]] = {
Expand Down Expand Up @@ -498,11 +494,7 @@ class ExitData(NamedTuple):
RegionName.MOUNTAIN_HUB_NORTH_SLOPE: [
ExitData(RegionName.LAYNOLE, [ItemName.MUSHROOMSHOES]),
ExitData(RegionName.LUNE, [NPCName.GIRL3, NPCName.GRANDPA4, NPCName.GRANDPA_LUNE, ItemName.LUCKYBLADE]),
ExitData(
RegionName.MOUNTAIN_KING,
[NPCName.BOY, NPCName.GRANDPA3, NPCName.MOUNTAIN_KING],
[NPCName.BOY_MUSHROOM_SHOES, NPCName.GRANDPA],
),
ExitData(RegionName.MOUNTAIN_KING, rule_flag=RuleFlag.MOUNTAIN_KING),
ExitData(
RegionName.NOME,
[NPCName.GIRL3, NPCName.GRANDPA4, NPCName.MUSHROOM2, NPCName.GRANDPA5, NPCName.MOUNTAIN_KING, NPCName.NOME],
Expand Down Expand Up @@ -559,8 +551,7 @@ class ExitData(NamedTuple):
ExitData(
RegionName.DEATHTOLL,
[ItemName.SOULARMOR, ItemName.SOULBLADE, ItemName.PHOENIX],
[],
RuleFlag.PHOENIX_CUTSCENE,
RuleFlag.MOUNTAIN_KING,
)
],
}
Expand Down Expand Up @@ -597,19 +588,17 @@ class ExitData(NamedTuple):
def get_rule_for_exit(data: ExitData, player: int) -> Callable[[CollectionState], bool]:
"""Returns the access rule for the given exit."""

if not data.has_all and not data.has_any:
flag_rule = rule_for_flag[data.rule_flag]

def rule_simple(state: CollectionState) -> bool:
return rule_for_flag[data.rule_flag](state, player)
if not data.has_all:

return rule_simple
def rule(state: CollectionState) -> bool:
return flag_rule(state, player)

return rule

def rule(state: CollectionState) -> bool:
return (
rule_for_flag[data.rule_flag](state, player)
and state.has_all(data.has_all, player)
and (not data.has_any or state.has_any(data.has_any, player))
)
return flag_rule(state, player) and state.has_all(data.has_all, player)

return rule

Expand Down
4 changes: 2 additions & 2 deletions worlds/soulblazer/Rom.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
from worlds.AutoWorld import World
from worlds.Files import APDeltaPatch
from .Names import Addresses, ItemID
from .Items import SoulBlazerItem, SoulBlazerItemData
from .Locations import SoulBlazerLocation, LocationType, SoulBlazerLocationData
from .Items import SoulBlazerItem
from .Locations import SoulBlazerLocation, LocationType
from .patches import get_patch_bytes

if TYPE_CHECKING:
Expand Down
40 changes: 26 additions & 14 deletions worlds/soulblazer/Rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ class RuleFlag(IntEnum):
"""
HAS_STONES = auto()
"""Requires the necessary number of stones. Adjustable via option."""
PHOENIX_CUTSCENE = auto()
MOUNTAIN_KING = auto()
"""
Requires the Phoenix cutscene:
Access to the Mountain King
Requires the Mountain King check and (Phoenix cutscene):
Path to the Mountain King
Both Dancing Grandmas
The 3 Red-Hot Items
"""
Expand Down Expand Up @@ -94,8 +94,28 @@ def has_stones(state: CollectionState, player: int) -> bool:
return state.has_group("stones", player, count)


def has_phoenix_cutscene(state: CollectionState, player: int) -> bool:
return state.can_reach_location(NPCRewardName.MOUNTAIN_KING, player)
def mountain_king_access(state: CollectionState, player: int) -> bool:
return (
# This first region check is only needed if a way of selectively opening worlds is discovered.
# state.can_reach_region(RegionName.MOUNTAIN_HUB_NORTH_SLOPE) and

# Two paths that lead to the hall of the mountain king
state.has_any([NPCName.BOY_MUSHROOM_SHOES, NPCName.GRANDPA], player)
and state.has_all(
[
NPCName.BOY,
NPCName.GRANDPA3,
NPCName.MOUNTAIN_KING,
NPCName.DANCING_GRANDMA,
NPCName.DANCING_GRANDMA2,
ItemName.REDHOTBALL,
ItemName.REDHOTMIRROR,
ItemName.REDHOTSTICK,
],
player,
)

)


rule_for_flag = {
Expand All @@ -106,7 +126,7 @@ def has_phoenix_cutscene(state: CollectionState, player: int) -> bool:
RuleFlag.HAS_MAGIC: has_magic,
RuleFlag.HAS_SWORD: has_sword,
RuleFlag.HAS_STONES: has_stones,
RuleFlag.PHOENIX_CUTSCENE: has_phoenix_cutscene,
RuleFlag.MOUNTAIN_KING: mountain_king_access,
}

# Many locations depend on one or two NPC releases so rather than create regions to hold one location,
Expand Down Expand Up @@ -146,20 +166,12 @@ def has_phoenix_cutscene(state: CollectionState, player: int) -> bool:
NPCRewardName.MAGIC_FLARE_MERMAID: [NPCName.MERMAID_MAGIC_FLARE, NPCName.MERMAID_BUBBLE_ARMOR],
NPCRewardName.REDHOT_STICK_MERMAID: [NPCName.MERMAID_RED_HOT_STICK],
NPCRewardName.LUE: [NPCName.LUE, NPCName.DOLPHIN_SAVES_LUE, NPCName.MERMAID_PEARL],
# Logical mermaids tears. TODO: move to separate list for optional logic toggle
NPCRewardName.MERMAID_QUEEN: [NPCName.MERMAID_QUEEN],
NPCRewardName.ANGELFISH_SOUL_OF_SHIELD: [NPCName.ANGELFISH_SOUL_OF_SHIELD],
LairName.MERMAID3: [ItemName.MERMAIDSTEARS],
LairName.MERMAID_STATUE_BLESTER: [ItemName.MERMAIDSTEARS],
ChestName.DUREAN_CRITICAL_SWORD: [ItemName.MERMAIDSTEARS],
# Act 4 - Mountain of Souls
NPCRewardName.MOUNTAIN_KING: [
NPCName.DANCING_GRANDMA,
NPCName.DANCING_GRANDMA2,
ItemName.REDHOTBALL,
ItemName.REDHOTMIRROR,
ItemName.REDHOTSTICK,
],
NPCRewardName.MUSHROOM_SHOES_BOY: [NPCName.BOY_MUSHROOM_SHOES],
NPCRewardName.EMBLEM_E_SNAIL: [NPCName.SNAIL_EMBLEM_E],
# Also includes path from lune to sleeping mushroom for the two locations locked behind mushroom's dream.
Expand Down
1 change: 0 additions & 1 deletion worlds/soulblazer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from .Options import SoulBlazerOptions # the options we defined earlier
from .Items import (
SoulBlazerItem,
SoulBlazerItemData,
all_items_table,
repeatable_items_table,
create_itempool,
Expand Down

0 comments on commit c954776

Please sign in to comment.