2023-03-05 12:31:31 +00:00
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
|
2023-06-24 23:58:54 +00:00
|
|
|
from worlds.generic.Rules import add_rule
|
2024-11-18 01:19:26 +00:00
|
|
|
from .Locations import food_locations, shop_locations, gleeok_locations, gohma_locations
|
2023-03-05 12:31:31 +00:00
|
|
|
from .ItemPool import dangerous_weapon_locations
|
2023-03-08 10:22:14 +00:00
|
|
|
from .Options import StartingPosition
|
2023-03-05 12:31:31 +00:00
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
from . import TLoZWorld
|
|
|
|
|
|
|
|
def set_rules(tloz_world: "TLoZWorld"):
|
|
|
|
player = tloz_world.player
|
2024-01-15 03:47:32 +00:00
|
|
|
options = tloz_world.options
|
2023-03-05 12:31:31 +00:00
|
|
|
|
|
|
|
# Boss events for a nicer spoiler log play through
|
|
|
|
for level in range(1, 9):
|
2024-11-18 01:19:26 +00:00
|
|
|
boss = tloz_world.get_location(f"Level {level} Boss")
|
|
|
|
boss_event = tloz_world.get_location(f"Level {level} Boss Status")
|
2023-03-05 12:31:31 +00:00
|
|
|
status = tloz_world.create_event(f"Boss {level} Defeated")
|
|
|
|
boss_event.place_locked_item(status)
|
|
|
|
add_rule(boss_event, lambda state, b=boss: state.can_reach(b, "Location", player))
|
|
|
|
|
|
|
|
# No dungeons without weapons except for the dangerous weapon locations if we're dangerous, no unsafe dungeons
|
|
|
|
for i, level in enumerate(tloz_world.levels[1:10]):
|
|
|
|
for location in level.locations:
|
2024-01-15 03:47:32 +00:00
|
|
|
if options.StartingPosition < StartingPosition.option_dangerous \
|
2023-03-08 10:22:14 +00:00
|
|
|
or location.name not in dangerous_weapon_locations:
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location(location.name),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has_group("weapons", player))
|
2024-05-02 21:49:39 +00:00
|
|
|
# This part of the loop sets up an expected amount of defense needed for each dungeon
|
2023-03-05 12:31:31 +00:00
|
|
|
if i > 0: # Don't need an extra heart for Level 1
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location(location.name),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state, hearts=i: state.has("Heart Container", player, hearts) or
|
|
|
|
(state.has("Blue Ring", player) and
|
|
|
|
state.has("Heart Container", player, int(hearts / 2))) or
|
|
|
|
(state.has("Red Ring", player) and
|
2023-03-30 13:29:06 +00:00
|
|
|
state.has("Heart Container", player, int(hearts / 4))))
|
|
|
|
if "Pols Voice" in location.name: # This enemy needs specific weapons
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location(location.name),
|
|
|
|
lambda state: state.has_group("swords", player) or
|
|
|
|
(state.has("Bow", player) and state.has_group("arrows", player)))
|
2023-03-05 12:31:31 +00:00
|
|
|
|
|
|
|
# No requiring anything in a shop until we can farm for money
|
|
|
|
for location in shop_locations:
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location(location),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has_group("weapons", player))
|
|
|
|
|
|
|
|
# Everything from 4 on up has dark rooms
|
|
|
|
for level in tloz_world.levels[4:]:
|
|
|
|
for location in level.locations:
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location(location.name),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has_group("candles", player)
|
2024-04-27 23:49:59 +00:00
|
|
|
or (state.has("Magical Rod", player) and state.has("Book of Magic", player)))
|
2023-03-05 12:31:31 +00:00
|
|
|
|
|
|
|
# Everything from 5 on up has gaps
|
|
|
|
for level in tloz_world.levels[5:]:
|
|
|
|
for location in level.locations:
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location(location.name),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Stepladder", player))
|
|
|
|
|
2024-11-18 01:19:26 +00:00
|
|
|
# Level 4 Access
|
|
|
|
for location in tloz_world.levels[4].locations:
|
|
|
|
add_rule(tloz_world.get_location(location.name),
|
|
|
|
lambda state: state.has_any(("Raft", "Recorder"), player))
|
2023-03-05 12:31:31 +00:00
|
|
|
|
2024-11-18 01:19:26 +00:00
|
|
|
# Digdogger boss. Rework this once ER happens
|
|
|
|
add_rule(tloz_world.get_location("Level 5 Boss"),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Recorder", player))
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("Level 5 Triforce"),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Recorder", player))
|
2024-11-18 01:19:26 +00:00
|
|
|
|
|
|
|
for location in gohma_locations:
|
|
|
|
if options.ExpandedPool or "Drop" not in location:
|
|
|
|
add_rule(tloz_world.get_location(location),
|
|
|
|
lambda state: state.has("Bow", player) and state.has_group("arrows", player))
|
|
|
|
|
|
|
|
# Recorder Access for Level 7
|
|
|
|
for location in tloz_world.levels[7].locations:
|
|
|
|
add_rule(tloz_world.get_location(location.name),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Recorder", player))
|
|
|
|
|
|
|
|
for location in food_locations:
|
2024-01-15 03:47:32 +00:00
|
|
|
if options.ExpandedPool or "Drop" not in location:
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location(location),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Food", player))
|
|
|
|
|
2024-03-03 16:59:31 +00:00
|
|
|
for location in gleeok_locations:
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location(location),
|
2024-03-03 16:59:31 +00:00
|
|
|
lambda state: state.has_group("swords", player) or state.has("Magical Rod", player))
|
|
|
|
|
2024-04-27 23:49:59 +00:00
|
|
|
# Candle access for Level 8
|
|
|
|
for location in tloz_world.levels[8].locations:
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location(location.name),
|
2024-04-27 23:49:59 +00:00
|
|
|
lambda state: state.has_group("candles", player))
|
|
|
|
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("Level 8 Item (Magical Key)"),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Bow", player) and state.has_group("arrows", player))
|
2024-01-15 03:47:32 +00:00
|
|
|
if options.ExpandedPool:
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("Level 8 Bomb Drop (Darknuts North)"),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Bow", player) and state.has_group("arrows", player))
|
|
|
|
|
|
|
|
for location in tloz_world.levels[9].locations:
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location(location.name),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Triforce Fragment", player, 8) and
|
|
|
|
state.has_group("swords", player))
|
|
|
|
|
|
|
|
# Yes we are looping this range again for Triforce locations. No I can't add it to the boss event loop
|
|
|
|
for level in range(1, 9):
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location(f"Level {level} Triforce"),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state, l=level: state.has(f"Boss {l} Defeated", player))
|
|
|
|
|
|
|
|
# Sword, raft, and ladder spots
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("White Sword Pond"),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Heart Container", player, 2))
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("Magical Sword Grave"),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Heart Container", player, 9))
|
|
|
|
|
|
|
|
stepladder_locations = ["Ocean Heart Container", "Level 4 Triforce", "Level 4 Boss", "Level 4 Map"]
|
|
|
|
stepladder_locations_expanded = ["Level 4 Key Drop (Keese North)"]
|
|
|
|
for location in stepladder_locations:
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location(location),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Stepladder", player))
|
2024-01-15 03:47:32 +00:00
|
|
|
if options.ExpandedPool:
|
2023-03-05 12:31:31 +00:00
|
|
|
for location in stepladder_locations_expanded:
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location(location),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Stepladder", player))
|
|
|
|
|
2023-03-08 10:22:14 +00:00
|
|
|
# Don't allow Take Any Items until we can actually get in one
|
2024-01-15 03:47:32 +00:00
|
|
|
if options.ExpandedPool:
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("Take Any Item Left"),
|
2023-03-08 10:22:14 +00:00
|
|
|
lambda state: state.has_group("candles", player) or
|
|
|
|
state.has("Raft", player))
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("Take Any Item Middle"),
|
2023-03-08 10:22:14 +00:00
|
|
|
lambda state: state.has_group("candles", player) or
|
|
|
|
state.has("Raft", player))
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("Take Any Item Right"),
|
2023-03-08 10:22:14 +00:00
|
|
|
lambda state: state.has_group("candles", player) or
|
|
|
|
state.has("Raft", player))
|
2023-03-05 12:31:31 +00:00
|
|
|
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("Potion Shop Item Left"),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Letter", player))
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("Potion Shop Item Middle"),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Letter", player))
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("Potion Shop Item Right"),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has("Letter", player))
|
|
|
|
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("Shield Shop Item Left"),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has_group("candles", player) or
|
|
|
|
state.has("Bomb", player))
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("Shield Shop Item Middle"),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has_group("candles", player) or
|
|
|
|
state.has("Bomb", player))
|
2024-11-18 01:19:26 +00:00
|
|
|
add_rule(tloz_world.get_location("Shield Shop Item Right"),
|
2023-03-05 12:31:31 +00:00
|
|
|
lambda state: state.has_group("candles", player) or
|
2024-11-18 01:19:26 +00:00
|
|
|
state.has("Bomb", player))
|