Skip to content

Commit 4b02f3d

Browse files
committed
Advanced Logic
1 parent d1bb6c2 commit 4b02f3d

43 files changed

Lines changed: 9736 additions & 1627 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

EntranceShuffle.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ def build_one_way_targets(world: World, types_to_include: Iterable[str], exclude
110110
('Dungeon', ('Gerudo Fortress -> Gerudo Training Ground Lobby', { 'index': 0x0008 }),
111111
('Gerudo Training Ground Lobby -> Gerudo Fortress', { 'index': 0x03A8 })),
112112

113-
('DungeonSpecial', ('Ganons Castle Grounds -> Ganons Castle Lobby', { 'index': 0x0467 }),
113+
('DungeonSpecial', ('Ganons Castle Ledge -> Ganons Castle Lobby', { 'index': 0x0467 }),
114114
('Ganons Castle Lobby -> Castle Grounds From Ganons Castle', { 'index': 0x023D })),
115115

116116
('ChildBoss', ('Deku Tree Before Boss -> Queen Gohma Boss Room', { 'index': 0x040f, 'savewarp_addresses': [ 0xB06292, 0xBC6162, 0xBC60AE ] }),
@@ -430,9 +430,8 @@ def set_entrances(worlds: list[World], savewarps_to_connect: list[tuple[Entrance
430430
savewarp.connect(savewarp.replaces.connected_region)
431431

432432
for world in worlds:
433-
if world.settings.logic_rules != 'glitched':
434-
# Set entrance data for all entrances, even those we aren't shuffling
435-
set_all_entrances_data(world)
433+
# Set entrance data for all entrances, even those we aren't shuffling
434+
set_all_entrances_data(world)
436435

437436
if worlds[0].entrance_shuffle:
438437
shuffle_random_entrances(worlds)
@@ -934,6 +933,9 @@ def validate_world(world: World, worlds: list[World], entrance_placed: Optional[
934933
CHILD_FORBIDDEN.append('Phantom Ganon Boss Room -> Forest Temple Before Boss')
935934
ADULT_FORBIDDEN.append('Phantom Ganon Boss Room -> Forest Temple Before Boss')
936935

936+
if world.settings.logic_rules != 'glitchless':
937+
CHILD_FORBIDDEN.remove('GV Carpenter Tent -> GV Fortress Side')
938+
937939
for entrance in world.get_shufflable_entrances():
938940
if entrance.shuffled:
939941
if entrance.replaces:

HintList.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def rainbow_bridge_hint_kind(world: World) -> str:
248248

249249
# Entrance hints required under certain settings
250250
conditional_entrance_always: dict[str, Callable[[World], bool]] = {
251-
'Ganons Castle Grounds -> Ganons Castle Lobby': lambda world: rainbow_bridge_hint_kind(world) == 'always',
251+
'Ganons Castle Ledge -> Ganons Castle Lobby': lambda world: rainbow_bridge_hint_kind(world) == 'always',
252252
'Ganons Castle Main -> Ganons Castle Tower': lambda world: world.settings.trials > 3 or (rainbow_bridge_hint_kind(world) == 'always' and not world.shuffle_special_dungeon_entrances),
253253
}
254254

@@ -291,7 +291,7 @@ def rainbow_bridge_hint_kind(world: World) -> str:
291291
'Twinrova Rewards': lambda world: world.settings.shuffle_dungeon_rewards not in ('vanilla', 'reward'),
292292

293293
# Conditional entrance hints
294-
'Ganons Castle Grounds -> Ganons Castle Lobby': lambda world: rainbow_bridge_hint_kind(world) != 'never',
294+
'Ganons Castle Ledge -> Ganons Castle Lobby': lambda world: rainbow_bridge_hint_kind(world) != 'never',
295295
'Ganons Castle Main -> Ganons Castle Tower': lambda world: world.settings.trials > 0 or (rainbow_bridge_hint_kind(world) != 'never' and not world.shuffle_special_dungeon_entrances),
296296
}
297297

@@ -1405,7 +1405,7 @@ def rainbow_bridge_hint_kind(world: World) -> str:
14051405
'Zoras Fountain -> Jabu Jabus Belly Beginning': ("inside #Jabu Jabu#, one can find", None, 'entrance'),
14061406
'Kakariko Village -> Bottom of the Well': ("a #village well# leads to", None, 'entrance'),
14071407

1408-
'Ganons Castle Grounds -> Ganons Castle Lobby': ("the #rainbow bridge# leads to", None, 'entrance'),
1408+
'Ganons Castle Ledge -> Ganons Castle Lobby': ("the #rainbow bridge# leads to", None, 'entrance'),
14091409
'Ganons Castle Main -> Ganons Castle Tower': ("a #castle barrier# protects the way to", "#Ganon's trials# protect the way to", 'entrance'),
14101410

14111411
'KF Links House': ("Link's House", None, 'region'),

ItemPool.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ def get_pool_core(world: World) -> tuple[list[str], dict[str, Item]]:
707707
# Gerudo Fortress Freestanding Heart Piece
708708
elif location.vanilla_item == 'Piece of Heart (Out of Logic)':
709709
shuffle_item = world.settings.shuffle_gerudo_fortress_heart_piece == 'shuffle'
710-
if world.settings.shuffle_hideout_entrances or world.settings.logic_rules == 'glitched':
710+
if world.settings.shuffle_hideout_entrances or world.settings.logic_rules == 'advanced':
711711
if world.settings.shuffle_hideout_entrances and world.settings.shuffle_gerudo_fortress_heart_piece == 'remove':
712712
item = IGNORE_LOCATION
713713
else:

Main.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from Rom import Rom
2626
from Rules import set_rules, set_shop_rules
2727
from Settings import Settings
28-
from SettingsList import logic_tricks
28+
from SettingsList import logic_tricks, advanced_logic_tricks
2929
from Spoiler import Spoiler
3030
from Utils import default_output_path, is_bundled, run_process, data_path
3131
from World import World
@@ -63,16 +63,21 @@ def resolve_settings(settings: Settings) -> Optional[Rom]:
6363
logger = logging.getLogger('')
6464

6565
old_tricks = settings.allowed_tricks
66+
old_advanced_tricks = settings.advanced_allowed_tricks
6667
settings.load_distribution()
6768

6869
# compare pointers to lists rather than contents, so even if the two are identical
6970
# we'll still log the error and note the dist file overrides completely.
70-
if old_tricks and old_tricks is not settings.allowed_tricks:
71+
if old_tricks and (old_tricks is not settings.allowed_tricks
72+
or old_advanced_tricks is not settings.advanced_allowed_tricks):
7173
logger.error('Tricks are set in two places! Using only the tricks from the distribution file.')
7274

7375
for trick in logic_tricks.values():
7476
settings.settings_dict[trick['name']] = trick['name'] in settings.allowed_tricks
7577

78+
for trick in advanced_logic_tricks.values():
79+
settings.settings_dict[trick['name']] = trick['name'] in settings.advanced_allowed_tricks
80+
7681
# we load the rom before creating the seed so that errors get caught early
7782
outputting_specific_world = settings.create_uncompressed_rom or settings.create_compressed_rom or settings.create_wad_file
7883
using_rom = outputting_specific_world or settings.create_patch_file or settings.patch_without_output
@@ -132,7 +137,7 @@ def build_world_graphs(settings: Settings) -> list[World]:
132137
logger.info('Creating Overworld')
133138

134139
# Load common json rule files (those used regardless of MQ status)
135-
if settings.logic_rules == 'glitched':
140+
if settings.logic_rules == 'advanced':
136141
path = 'Glitched World'
137142
else:
138143
path = 'World'

Messages.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,20 +1374,20 @@ def update_warp_song_text(messages: list[Message], world: World) -> None:
13741374
0x4004: 'LH Owl Flight -> Hyrule Field',
13751375
}
13761376

1377-
if world.settings.logic_rules != "glitched": # Entrances not set on glitched logic so following code will error
1378-
for id, entr in msg_list.items():
1379-
if 'warp_songs_and_owls' in world.settings.misc_hints or not world.settings.warp_songs:
1380-
destination = world.get_entrance(entr).connected_region
1381-
destination_name = HintArea.at(destination)
1382-
color = COLOR_MAP[destination_name.color]
1383-
if destination_name.preposition(True) is not None:
1384-
destination_name = f'to {destination_name}'
1385-
else:
1386-
destination_name = 'to a mysterious place'
1387-
color = COLOR_MAP['White']
1377+
#if world.settings.logic_rules != "glitched": # Entrances not set on glitched logic so following code will error
1378+
for id, entr in msg_list.items():
1379+
if 'warp_songs_and_owls' in world.settings.misc_hints or not world.settings.warp_songs:
1380+
destination = world.get_entrance(entr).connected_region
1381+
destination_name = HintArea.at(destination)
1382+
color = COLOR_MAP[destination_name.color]
1383+
if destination_name.preposition(True) is not None:
1384+
destination_name = f'to {destination_name}'
1385+
else:
1386+
destination_name = 'to a mysterious place'
1387+
color = COLOR_MAP['White']
13881388

1389-
new_msg = f"\x08\x05{color}Warp {destination_name}?\x05\40\x09\x01\x01\x1b\x05\x42OK\x01No\x05\40"
1390-
update_message_by_id(messages, id, new_msg)
1389+
new_msg = f"\x08\x05{color}Warp {destination_name}?\x05\40\x09\x01\x01\x1b\x05\x42OK\x01No\x05\40"
1390+
update_message_by_id(messages, id, new_msg)
13911391

13921392
if world.settings.owl_drops:
13931393
for id, entr in owl_messages.items():

Patches.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ def set_entrance_updates(entrances: Iterable[Entrance]) -> None:
768768
if world.settings.adult_trade_shuffle or world.settings.item_pool_value in ('plentiful', 'ludicrous'):
769769
rom.write_byte(rom.sym('CFG_ADULT_TRADE_SHUFFLE'), 0x01)
770770
move_fado_in_lost_woods(rom)
771-
if world.settings.shuffle_child_trade or world.settings.logic_rules == 'glitched':
771+
if world.settings.shuffle_child_trade or world.settings.logic_rules == 'advanced':
772772
rom.write_byte(rom.sym('CFG_CHILD_TRADE_SHUFFLE'), 0x01)
773773

774774
if world.settings.shuffle_overworld_entrances:
@@ -1801,10 +1801,7 @@ def update_scrub_text(message: bytearray, text_replacement: list[str], default_p
18011801
area = GossipText(area.text(world.settings.clearer_hints, preposition=True, use_2nd_person=True), [area.color], prefix='', capitalize=False)
18021802
compass_message = f"\x13\x75\x08You found the \x05\x41Compass\x05\x40\x01for {dungeon_name}\x05\x40!\x01The {vanilla_reward} can be found\x01{area}!\x09"
18031803
else:
1804-
if world.settings.logic_rules == 'glitched':
1805-
boss_location = world.get_location(dungeon.vanilla_boss_name)
1806-
else:
1807-
boss_location = next(filter(lambda loc: loc.type == 'Boss', world.get_entrance(f'{dungeon} Before Boss -> {dungeon.vanilla_boss_name} Boss Room').connected_region.locations))
1804+
boss_location = next(filter(lambda loc: loc.type == 'Boss', world.get_entrance(f'{dungeon} Before Boss -> {dungeon.vanilla_boss_name} Boss Room').connected_region.locations))
18081805
dungeon_reward = boss_location.item.name
18091806
compass_message = f"\x13\x75\x08You found the \x05\x41Compass\x05\x40\x01for {dungeon_name}\x05\x40!\x01It holds the \x05{COLOR_MAP[REWARD_COLORS[dungeon_reward]]}{dungeon_reward}\x05\x40!\x09"
18101807
if world.settings.shuffle_dungeon_rewards != 'dungeon':

SettingsList.py

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from Location import LocationIterator
1111
from LocationList import location_table
1212
from Models import get_model_choices
13-
from SettingsListTricks import logic_tricks
13+
from SettingsListTricks import logic_tricks, advanced_logic_tricks
1414
from SettingTypes import SettingInfo, SettingInfoStr, SettingInfoList, SettingInfoDict, Textbox, Button, Checkbutton, \
1515
Combobox, Radiobutton, Fileinput, Directoryinput, Textinput, ComboboxInt, Scale, Numberinput, MultipleSelect, \
1616
SearchBox
@@ -634,7 +634,7 @@ class SettingInfos:
634634
default = 'glitchless',
635635
choices = {
636636
'glitchless': 'Glitchless',
637-
'glitched': 'Glitched',
637+
'advanced': 'Advanced',
638638
'none': 'No Logic',
639639
},
640640
gui_tooltip = '''\
@@ -646,20 +646,20 @@ class SettingInfos:
646646
some minor tricks. Add minor tricks to consider for logic
647647
in the 'Detailed Logic' tab.
648648
649-
'Glitched': Movement-oriented glitches are likely required.
650-
No locations excluded.
649+
'Advanced': More Glitchless tricks and toggleable
650+
glitches for accessability to curate the overall difficulty
651+
level for every skill level.
651652
652653
'No Logic': Maximize randomization, All locations are
653654
considered available. MAY BE IMPOSSIBLE TO BEAT.
654655
''',
655656
disable = {
656-
'glitchless': {'settings': ['tricks_list_msg']},
657-
'glitched': {'settings': ['allowed_tricks', 'shuffle_interior_entrances', 'shuffle_hideout_entrances', 'shuffle_gerudo_fortress_heart_piece', 'shuffle_grotto_entrances',
658-
'shuffle_dungeon_entrances', 'shuffle_overworld_entrances', 'shuffle_gerudo_valley_river_exit', 'owl_drops',
659-
'warp_songs', 'spawn_positions', 'mq_dungeons_mode', 'mq_dungeons_specific',
660-
'mq_dungeons_count', 'shuffle_bosses', 'shuffle_ganon_tower', 'dungeon_shortcuts', 'deadly_bonks',
661-
'shuffle_freestanding_items', 'shuffle_pots', 'shuffle_crates', 'shuffle_beehives', 'shuffle_silver_rupees', 'shuffle_wonderitems']},
662-
'none': {'settings': ['allowed_tricks', 'logic_no_night_tokens_without_suns_song', 'reachable_locations']},
657+
'glitchless': {'settings': ['tricks_list_msg', 'advanced_allowed_tricks']},
658+
# Forcing blue fire arrows to be on, and the tcg lens setting to be off as we can do it without the lens logically
659+
# and don't care if people do 1/32
660+
'advanced': {'settings': ['tricks_list_msg', 'blue_fire_arrows', 'tcg_requires_lens'
661+
]},
662+
'none': {'settings': ['allowed_tricks', 'advanced_allowed_tricks', 'logic_no_night_tokens_without_suns_song', 'reachable_locations']},
663663
},
664664
shared = True,
665665
)
@@ -3159,8 +3159,26 @@ class SettingInfos:
31593159
and MAY be required to complete the game.
31603160
31613161
Tricks in the left column are NEVER required.
3162+
'''
3163+
)
31623164

3163-
Tricks are only relevant for Glitchless logic.
3165+
advanced_allowed_tricks = SearchBox(
3166+
gui_text = "Enable Advanced Tricks",
3167+
shared = True,
3168+
choices = {
3169+
val['name']: gui_text for gui_text, val in advanced_logic_tricks.items()
3170+
},
3171+
default = [],
3172+
gui_params = {
3173+
'choice_tooltip': {choice['name']: choice['tooltip'] for choice in advanced_logic_tricks.values()},
3174+
'filterdata': {val['name']: val['tags'] for _, val in advanced_logic_tricks.items()},
3175+
"hide_when_disabled": True,
3176+
},
3177+
gui_tooltip='''
3178+
Tricks moved to the right column are in-logic
3179+
and MAY be required to complete the game.
3180+
3181+
Tricks in the left column are NEVER required.
31643182
'''
31653183
)
31663184

@@ -3952,14 +3970,18 @@ class SettingInfos:
39523970
)
39533971

39543972
blue_fire_arrows = Checkbutton(
3955-
gui_text = 'Blue Fire Arrows',
3956-
gui_tooltip = '''\
3973+
gui_text = 'Blue Fire Arrows',
3974+
gui_tooltip = '''\
39573975
Ice arrows gain the power of blue fire.
39583976
They can be used to melt red ice
39593977
and break the mud walls in Dodongo's Cavern.
39603978
''',
3961-
default = False,
3962-
shared = True,
3979+
default = False,
3980+
disabled_default = True,
3981+
gui_params = {
3982+
"hide_when_disabled": True,
3983+
},
3984+
shared = True,
39633985
)
39643986

39653987
fix_broken_drops = Checkbutton(

0 commit comments

Comments
 (0)