diff --git a/BaseClasses.py b/BaseClasses.py index 7b2099a1..bc1a64e6 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -785,11 +785,21 @@ class CollectionState(object): self.is_not_bunny(cave, player) ) - def has_sword(self, player): - return self.has('Fighter Sword', player) or self.has('Master Sword', player) or self.has('Tempered Sword', player) or self.has('Golden Sword', player) + def has_sword(self, player, level=1): + if level == 4: + return self.has('Golden Sword', player) + elif level == 3: + return self.has('Golden Sword', player) or self.has('Tempered Sword', player) + elif level == 2: + return self.has('Golden Sword', player) or self.has('Tempered Sword', player) or self.has('Master Sword', player) + elif level == 1: + return self.has('Golden Sword', player) or self.has('Tempered Sword', player) or self.has('Master Sword', player) or self.has('Fighter Sword', player) + return False - def has_beam_sword(self, player): - return self.has('Master Sword', player) or self.has('Tempered Sword', player) or self.has('Golden Sword', player) + def has_real_sword(self, player, level=1): + if self.world.swords[player] == 'pseudo': + return False; + return self.has_sword(player, level) def has_bomb_level(self, player, level): if self.world.swords[player] != 'bombs': @@ -853,7 +863,7 @@ class CollectionState(object): return self.has_sword(player) or self.world.swords[player] == 'bombs' def has_blunt_weapon(self, player): - return self.has_sword(player) or self.has('Hammer', player) + return self.has_real_sword(player) or self.has('Hammer', player) def has_Mirror(self, player): return self.has('Magic Mirror', player) @@ -2520,10 +2530,10 @@ or_mode = {"parallel": 1, "full": 2, "vanilla": 0} er_mode = {"vanilla": 0, "simple": 1, "restricted": 2, "full": 3, "crossed": 4, "insanity": 5, "restricted_legacy": 8, "full_legacy": 9, "madness_legacy": 10, "insanity_legacy": 11, "dungeonsfull": 7, "dungeonssimple": 6} -# byte 1: LLLW WSSR (logic, mode, sword, retro) +# byte 1: LLLW WSSS (logic, mode, sword) logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owglitches": 3, "majorglitches": 4} world_mode = {"open": 0, "standard": 1, "inverted": 2} -sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3, "bombs": 2} # fix this, kara +sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3, "bombs": 4, "pseudo": 5} # byte 2: GGGD DFFH (goal, diff, item_func, hints) goal_mode = {"ganon": 0, "pedestal": 1, "dungeons": 2, "triforcehunt": 3, "crystals": 4} @@ -2544,7 +2554,7 @@ access_mode = {"items": 0, "locations": 1, "none": 2} boss_mode = {"none": 0, "simple": 1, "full": 2, "random": 3, "chaos": 3} enemy_mode = {"none": 0, "shuffled": 1, "random": 2, "chaos": 2, "legacy": 3} -# byte 7: HHHD DP?? (enemy_health, enemy_dmg, potshuffle, ?) +# byte 7: HHHD DPR? (enemy_health, enemy_dmg, potshuffle, retro, ?) e_health = {"default": 0, "easy": 1, "normal": 2, "hard": 3, "expert": 4} e_dmg = {"default": 0, "shuffled": 1, "random": 2} @@ -2555,8 +2565,7 @@ class Settings(object): code = bytes([ (dr_mode[w.doorShuffle[p]] << 6) | (or_mode[w.owShuffle[p]] << 4) | er_mode[w.shuffle[p]], - (logic_mode[w.logic[p]] << 5) | (world_mode[w.mode[p]] << 3) - | (sword_mode[w.swords[p]] << 1) | (1 if w.retro[p] else 0), + (logic_mode[w.logic[p]] << 5) | (world_mode[w.mode[p]] << 3) | (sword_mode[w.swords[p]]), (goal_mode[w.goal[p]] << 5) | (diff_mode[w.difficulty[p]] << 3) | (func_mode[w.difficulty_adjustments[p]] << 1) | (1 if w.hints[p] else 0), @@ -2575,7 +2584,7 @@ class Settings(object): | (0x20 if w.mapshuffle[p] else 0) | (0x10 if w.compassshuffle[p] else 0) | (boss_mode[w.boss_shuffle[p]] << 2) | (enemy_mode[w.enemy_shuffle[p]]), - (e_health[w.enemy_health[p]] << 5) | (e_dmg[w.enemy_damage[p]] << 3) | (0x4 if w.potshuffle[p] else 0)]) + (e_health[w.enemy_health[p]] << 5) | (e_dmg[w.enemy_damage[p]] << 3) | (0x4 if w.potshuffle[p] else 0) | (0x2 if w.retro[p] else 0)]) return base64.b64encode(code, "+-".encode()).decode() @staticmethod diff --git a/Bosses.py b/Bosses.py index 0fb60798..ae4283d6 100644 --- a/Bosses.py +++ b/Bosses.py @@ -44,7 +44,7 @@ def MoldormDefeatRule(state, player): def HelmasaurKingDefeatRule(state, player): return (state.bomb_mode_check(player, 2) and (state.has('Hammer', player) or state.can_use_bombs(player)) and - (state.has_sword(player) or state.can_shoot_arrows(player) or state.has_bomb_level(player, 2))) + (state.has_real_sword(player) or state.can_shoot_arrows(player) or state.has_bomb_level(player, 2))) def ArrghusDefeatRule(state, player): if not state.has('Hookshot', player): @@ -112,12 +112,11 @@ def TrinexxDefeatRule(state, player): if not state.bomb_mode_check(player, 2): return False return (state.has('Hammer', player) or - state.has('Golden Sword', player) or - state.has('Tempered Sword', player) or + state.has_real_sword(player, 3) or state.has_bomb_level(player, 4) or - ((state.has('Master Sword', player) or state.has_bomb_level(player, 3)) + ((state.has_real_sword(player, 2) or state.has_bomb_level(player, 3)) and state.can_extend_magic(player, 16)) or - ((state.has_sword(player) or state.has_bomb_level(player, 2)) + ((state.has_real_sword(player) or state.has_bomb_level(player, 2)) and state.can_extend_magic(player, 32))) def AgahnimDefeatRule(state, player): diff --git a/Mystery.py b/Mystery.py index edcd1286..43fb2e87 100644 --- a/Mystery.py +++ b/Mystery.py @@ -192,6 +192,7 @@ def roll_settings(weights): 'assured': 'assured', 'vanilla': 'vanilla', 'swordless': 'swordless', + 'pseudo': 'pseudo', 'bombs': 'bombs' }[get_choice('weapons')] diff --git a/Rom.py b/Rom.py index 6fbb0173..d817a8e5 100644 --- a/Rom.py +++ b/Rom.py @@ -1060,7 +1060,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): #Work around for json patch ordering issues - write bow limit separately so that it is replaced in the patch rom.write_bytes(0x180098, [difficulty.progressive_bow_limit, overflow_replacement]) - if difficulty.progressive_bow_limit < 2 and world.swords[player] == 'swordless': + if difficulty.progressive_bow_limit < 2 and world.swords[player] in ['swordless', 'pseudo']: rom.write_bytes(0x180098, [2, overflow_replacement]) # set up game internal RNG seed @@ -1193,6 +1193,9 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_byte(0x180041, 0x01) # swordless medallions (on pads) rom.write_byte(0x180043, 0xFF) # starting sword for link rom.write_byte(0x180044, 0x01) # hammer activates tablets + elif world.swords[player] == 'pseudo': + rom.write_byte(0x18002F, 0x02) # pseudo-swords + rom.write_byte(0x18003F, 0x01) # hammer can harm ganon elif world.swords[player] == 'bombs': rom.write_byte(0x18002F, 0x01) # special bombs rom.write_byte(0x180040, 0x01) # open curtains @@ -2374,7 +2377,7 @@ def write_strings(rom, world, player, team): prog_bow_locs = world.find_items('Progressive Bow', player) distinguished_prog_bow_loc = next((location for location in prog_bow_locs if location.item.code == 0x65), None) - progressive_silvers = world.difficulty_requirements[player].progressive_bow_limit >= 2 or world.swords[player] == 'swordless' + progressive_silvers = world.difficulty_requirements[player].progressive_bow_limit >= 2 or world.swords[player] in ['swordless', 'pseudo'] if distinguished_prog_bow_loc: prog_bow_locs.remove(distinguished_prog_bow_loc) hint_phrase = hint_text(distinguished_prog_bow_loc).replace("Ganon's", "my") diff --git a/Rules.py b/Rules.py index 4f10f73c..6b7aba7f 100644 --- a/Rules.py +++ b/Rules.py @@ -191,7 +191,7 @@ def global_rules(world, player): set_rule(world.get_location('Sunken Treasure', player), lambda state: state.has('Open Floodgate', player)) set_rule(world.get_location('Dark Blacksmith Ruins', player), lambda state: state.has('Return Smith', player)) set_rule(world.get_location('Purple Chest', player), lambda state: state.has('Pick Up Purple Chest', player)) # Can S&Q with chest - set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) + set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_sword(player, 2)) set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player)) set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith @@ -340,7 +340,7 @@ def global_rules(world, player): set_rule(world.get_entrance('Mire Lobby Gap', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player)) set_rule(world.get_entrance('Mire Post-Gap Gap', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player)) set_rule(world.get_entrance('Mire Falling Bridge WN', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player)) # this is due to the fact the the door opposite is blocked - set_rule(world.get_entrance('Mire 2 NE', player), lambda state: state.bomb_mode_check(player, 1) and (state.has_sword(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player) or state.has_bomb_level(player, 1))) # need to defeat wizzrobes, bombs don't work ... + set_rule(world.get_entrance('Mire 2 NE', player), lambda state: state.bomb_mode_check(player, 1) and (state.has_real_sword(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player) or state.has_bomb_level(player, 1))) # need to defeat wizzrobes, bombs don't work ... set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player)) set_rule(world.get_entrance('Mire Left Bridge Hook Path', player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Mire Tile Room NW', player), lambda state: state.has_fire_source(player)) @@ -436,10 +436,10 @@ def global_rules(world, player): set_rule(world.get_entrance('Hera Lobby to Crystal', player), lambda state: state.can_hit_crystal(player)) set_rule(world.get_entrance('Hera Front to Crystal', player), lambda state: state.can_hit_crystal(player)) - set_rule(world.get_entrance('Hera Down Stairs Landing to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('Hera Down Stairs Landing', player), player))) # or state.has_beam_sword(player) - set_rule(world.get_entrance('Hera Up Stairs Landing to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('Hera Up Stairs Landing', player), player))) # or state.has_beam_sword(player) - set_rule(world.get_entrance('Hera Back to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # or state.has_beam_sword(player) or (state.has('Hookshot', player) and state.has('Red Boomerang', player)) - set_rule(world.get_entrance('Hera Front to Back Bypass', player), lambda state: state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Blue Boomerang', player) or state.has('Cane of Somaria', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player)) # or state.has_beam_sword(player) + set_rule(world.get_entrance('Hera Down Stairs Landing to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('Hera Down Stairs Landing', player), player))) # or state.has_sword(player, 2) + set_rule(world.get_entrance('Hera Up Stairs Landing to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('Hera Up Stairs Landing', player), player))) # or state.has_sword(player, 2) + set_rule(world.get_entrance('Hera Back to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # or state.has_sword(player, 2) or (state.has('Hookshot', player) and state.has('Red Boomerang', player)) + set_rule(world.get_entrance('Hera Front to Back Bypass', player), lambda state: state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Blue Boomerang', player) or state.has('Cane of Somaria', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player)) # or state.has_sword(player, 2) set_rule(world.get_entrance('Hera Basement Cage to Crystal', player), lambda state: state.can_hit_crystal(player)) set_rule(world.get_entrance('Hera Tridorm to Crystal', player), lambda state: state.can_hit_crystal(player)) set_rule(world.get_entrance('Hera Startile Wide to Crystal', player), lambda state: state.can_hit_crystal(player)) @@ -460,16 +460,16 @@ def global_rules(world, player): set_rule(world.get_entrance('PoD Arena Main to Ranged Crystal', player), lambda state: True) # Can always throw pots here set_rule(world.get_entrance('PoD Arena Main to Landing Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) set_rule(world.get_entrance('PoD Arena Main to Right Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) - set_rule(world.get_entrance('PoD Arena Bridge to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # or state.has_beam_sword(player) + set_rule(world.get_entrance('PoD Arena Bridge to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # or state.has_sword(player, 2) set_rule(world.get_entrance('PoD Arena Right to Ranged Crystal', player), lambda state: False) # (state.has('Cane of Somaria', player) and state.has_Boots(player)) - set_rule(world.get_entrance('PoD Arena Ledge to Ranged Crystal', player), lambda state: False) # state.has('Cane of Somaria', player) or state.has_beam_sword(player) + set_rule(world.get_entrance('PoD Arena Ledge to Ranged Crystal', player), lambda state: False) # state.has('Cane of Somaria', player) or state.has_sword(player, 2) set_rule(world.get_entrance('PoD Map Balcony to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) # or state.has('Red Boomerang', player) set_rule(world.get_entrance('PoD Bow Statue Left to Crystal', player), lambda state: state.can_hit_crystal(player)) set_rule(world.get_entrance('PoD Bow Statue Right to Ranged Crystal', player), lambda state: state.has('Cane of Somaria', player)) - set_rule(world.get_entrance('PoD Bow Statue Left to Right Bypass', player), lambda state: state.has('Cane of Somaria', player) or state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Ice Rod', player) or state.has('Fire Rod', player)) # or state.has_beam_sword(player) + set_rule(world.get_entrance('PoD Bow Statue Left to Right Bypass', player), lambda state: state.has('Cane of Somaria', player) or state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Ice Rod', player) or state.has('Fire Rod', player)) # or state.has_sword(player, 2) set_rule(world.get_entrance('PoD Dark Pegs Landing to Ranged Crystal', player), lambda state: state.has('Cane of Somaria', player)) # or state.can_use_bombs(player) or state.has('Blue boomerang', player) or state.has('Red boomerang', player) - set_rule(world.get_entrance('PoD Dark Pegs Middle to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.can_use_bombs(player) or state.has('Red Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('PoD Dark Pegs Middle', player), player))) # or state.has_beam_sword(player) - set_rule(world.get_entrance('PoD Dark Pegs Left to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # or state.has_beam_sword(player) + set_rule(world.get_entrance('PoD Dark Pegs Middle to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.can_use_bombs(player) or state.has('Red Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('PoD Dark Pegs Middle', player), player))) # or state.has_sword(player, 2) + set_rule(world.get_entrance('PoD Dark Pegs Left to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # or state.has_sword(player, 2) set_rule(world.get_entrance('PoD Dark Pegs Right to Middle Bypass', player), lambda state: state.has('Blue Boomerang', player)) set_rule(world.get_entrance('PoD Dark Pegs Middle to Left Bypass', player), lambda state: state.can_use_bombs(player)) @@ -481,7 +481,7 @@ def global_rules(world, player): set_rule(world.get_entrance('Swamp Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('Swamp Barrier', player), player)) set_rule(world.get_entrance('Swamp Crystal Switch Inner to Crystal', player), lambda state: state.can_hit_crystal(player)) - set_rule(world.get_entrance('Swamp Crystal Switch Outer to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or state.has_beam_sword(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('Swamp Crystal Switch Outer', player), player))) # It is the length of the sword, not the beam itself that allows this + set_rule(world.get_entrance('Swamp Crystal Switch Outer to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or state.has_sword(player, 2) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('Swamp Crystal Switch Outer', player), player))) # It is the length of the sword, not the beam itself that allows this set_rule(world.get_entrance('Swamp Crystal Switch Outer to Inner Bypass', player), lambda state: state.world.can_take_damage or state.has('Cape', player) or state.has('Cane of Byrna', player)) set_rule(world.get_entrance('Swamp Crystal Switch Inner to Outer Bypass', player), lambda state: state.world.can_take_damage or state.has('Cape', player) or state.has('Cane of Byrna', player)) @@ -547,10 +547,10 @@ def global_rules(world, player): set_rule(world.get_entrance('TR Pokey 2 Top to Crystal', player), lambda state: state.can_hit_crystal(player)) set_rule(world.get_entrance('TR Crystaroller Top to Crystal', player), lambda state: state.can_hit_crystal(player)) set_rule(world.get_entrance('TR Crystal Maze Start to Crystal', player), lambda state: state.can_hit_crystal(player)) - set_rule(world.get_entrance('TR Chain Chomps Bottom to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Chain Chomps Bottom', player), player))) # or state.has_beam_sword(player) - set_rule(world.get_entrance('TR Pokey 2 Bottom to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('TR Pokey 2 Bottom', player), player))) # or state.has_beam_sword(player) - set_rule(world.get_entrance('TR Crystaroller Bottom to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Crystaroller Bottom', player), player))) # or state.has_beam_sword(player) - set_rule(world.get_entrance('TR Crystaroller Middle to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Crystaroller Middle', player), player))) # or state.has_beam_sword(player) + set_rule(world.get_entrance('TR Chain Chomps Bottom to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Chain Chomps Bottom', player), player))) # or state.has_sword(player, 2) + set_rule(world.get_entrance('TR Pokey 2 Bottom to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('TR Pokey 2 Bottom', player), player))) # or state.has_sword(player, 2) + set_rule(world.get_entrance('TR Crystaroller Bottom to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Crystaroller Bottom', player), player))) # or state.has_sword(player, 2) + set_rule(world.get_entrance('TR Crystaroller Middle to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('TR Crystaroller Middle', player), player))) # or state.has_sword(player, 2) set_rule(world.get_entrance('TR Crystaroller Middle to Bottom Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Blue Boomerang', player)) set_rule(world.get_entrance('TR Crystal Maze End to Ranged Crystal', player), lambda state: state.has('Cane of Somaria', player)) # or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player) // These work by clipping the rang through the two stone blocks, which works sometimes. set_rule(world.get_entrance('TR Crystal Maze Interior to End Bypass', player), lambda state: state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Blue Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # Beam sword does NOT work @@ -584,25 +584,25 @@ def global_rules(world, player): set_rule(world.get_entrance('GT Crystal Conveyor to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) set_rule(world.get_entrance('GT Crystal Conveyor Corner to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) set_rule(world.get_entrance('GT Crystal Conveyor Corner to Left Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) - set_rule(world.get_entrance('GT Crystal Circles to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or state.has_blunt_weapon(player) or state.has('Cane of Byrna', player)) # or state.has_beam_sword(player) + set_rule(world.get_entrance('GT Crystal Circles to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or state.has_blunt_weapon(player) or state.has('Cane of Byrna', player)) # or state.has_sword(player, 2) add_key_logic_rules(world, player) # End of door rando rules. set_rule( world.get_location('Ganon', player), - lambda state: (state.has_beam_sword(player) or state.has_bomb_level(player, 3)) + lambda state: (state.has_real_sword(player, 2) or state.has_bomb_level(player, 3)) and state.has_fire_source(player) and state.has_crystals(world.crystals_needed_for_ganon[player], player) - and (state.has('Tempered Sword', player) or state.has('Golden Sword', player) or + and (state.has_real_sword(player, 3) or state.can_hit_stunned_ganon(player) or - state.has_beam_sword(player) and + state.has_real_sword(player, 2) and (state.has('Lamp', player) or state.can_extend_magic(player, 12)))) # need to light torch a sufficient amount of times set_rule( world.get_entrance('Ganon Drop', player), - lambda state: state.has_beam_sword(player) or state.has_bomb_level(player, 3)) + lambda state: state.has_real_sword(player, 2) or state.has_bomb_level(player, 3)) # need to damage ganon to get tiles to drop def bomb_rules(world, player): @@ -728,7 +728,7 @@ def default_rules(world, player): set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has('Flippers', player)) set_rule(world.get_location('Potion Shop', player), lambda state: state.has('Mushroom', player)) set_rule(world.get_location('Flute Spot', player), lambda state: state.has('Shovel', player)) - set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) + set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_sword(player, 2)) # Entrance Access set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has('Beat Agahnim 1', player)) @@ -741,7 +741,7 @@ def default_rules(world, player): set_rule(world.get_entrance('20 Rupee Cave', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Skull Woods Final Section', player), lambda state: state.has('Fire Rod', player)) set_rule(world.get_entrance('Hookshot Cave', player), lambda state: state.can_lift_rocks(player)) - set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has_sword(player) and state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock Ledge', 'Region', player)) # sword required to cast magic (!) + set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.can_use_medallions(player) and state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock Ledge', 'Region', player)) # sword required to cast magic (!) set_rule(world.get_entrance('Dark World Hammer Peg Cave', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Bonk Fairy (Dark)', player), lambda state: state.has_Boots(player)) set_rule(world.get_entrance('Misery Mire', player), lambda state: state.can_use_medallions(player) and state.has_misery_mire_medallion(player)) # sword required to cast magic (!) @@ -848,11 +848,13 @@ def default_rules(world, player): swordless_rules(world, player) if world.swords[player] == 'bombs': bomb_mode_rules(world, player) + if world.swords[player] == 'pseudo': + pseudo_sword_mode_rules(world, player) def ow_rules(world, player): if world.mode[player] != 'inverted': - set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_beam_sword(player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle + set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_sword(player, 2) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle set_rule(world.get_entrance('GT Entry Approach', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player)) set_rule(world.get_entrance('GT Entry Leave', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player) or state.world.shuffle[player] in ('restricted', 'full', 'crossed', 'insanity')) else: @@ -1012,7 +1014,6 @@ def ow_rules(world, player): set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: False) set_rule(world.get_entrance('Inverted Pyramid Entrance', player), lambda state: False) set_rule(world.get_entrance('Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player]) - set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_beam_sword(player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle set_rule(world.get_entrance('HC Area Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('HC Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) @@ -1520,10 +1521,14 @@ def bomb_mode_rules(world, player): if world.mode[player] != 'inverted': set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_bomb_level(player, 2) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle - set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock Ledge', 'Region', player)) # sword not required to use medallion for opening in swordless (!) + set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock Ledge', 'Region', player)) # sword not required to use medallion in bomb-only add_bunny_rule(world.get_entrance('Turtle Rock', player), player) add_bunny_rule(world.get_entrance('Misery Mire', player), player) +def pseudo_sword_mode_rules(world, player): + set_rule(world.get_location('Ganon', player), lambda state: state.has('Hammer', player) and state.has_fire_source(player) and state.has('Silver Arrows', player) and state.can_shoot_arrows(player) and state.has_crystals(world.crystals_needed_for_ganon[player], player)) + set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has('Hammer', player)) # need to damage ganon to get tiles to drop + std_kill_rooms = { 'Hyrule Dungeon Armory Main': ['Hyrule Dungeon Armory S', 'Hyrule Dungeon Armory ES'], # One green guard 'Hyrule Dungeon Armory Boomerang': ['Hyrule Dungeon Armory Boomerang WS'], # One blue guard diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index 7dc9d5dc..2b909889 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -34,6 +34,7 @@ "random", "assured", "swordless", + "pseudo", "bombs", "vanilla" ] diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 1c1285db..a73895c6 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -271,6 +271,7 @@ "randomizer.item.weapons.random": "Randomized", "randomizer.item.weapons.assured": "Assured", "randomizer.item.weapons.swordless": "Swordless", + "randomizer.item.weapons.pseudo": "Pseudo-Swords", "randomizer.item.weapons.bombs": "Bomb-Only", "randomizer.item.weapons.vanilla": "Vanilla",