fix /snes <snes_interface> if interface contains spaces (which it shouldn't, but meh)
This commit is contained in:
parent
117624d611
commit
3864eb5071
|
@ -324,8 +324,10 @@ class World(object):
|
||||||
self._cached_locations = None
|
self._cached_locations = None
|
||||||
|
|
||||||
def get_unfilled_locations(self, player=None) -> list:
|
def get_unfilled_locations(self, player=None) -> list:
|
||||||
return [location for location in self.get_locations() if
|
if player is not None:
|
||||||
(player is None or location.player == player) and location.item is None]
|
return [location for location in self.get_locations() if
|
||||||
|
location.player == player and not location.item]
|
||||||
|
return [location for location in self.get_locations() if not location.item]
|
||||||
|
|
||||||
def get_filled_locations(self, player=None) -> list:
|
def get_filled_locations(self, player=None) -> list:
|
||||||
return [location for location in self.get_locations() if
|
return [location for location in self.get_locations() if
|
||||||
|
|
|
@ -66,7 +66,8 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
Palace, to allow for an alternative to firerod.
|
Palace, to allow for an alternative to firerod.
|
||||||
Vanilla: Swords are in vanilla locations.
|
Vanilla: Swords are in vanilla locations.
|
||||||
''')
|
''')
|
||||||
parser.add_argument('--goal', default=defval('ganon'), const='ganon', nargs='?', choices=['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals'],
|
parser.add_argument('--goal', default=defval('ganon'), const='ganon', nargs='?',
|
||||||
|
choices=['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'localtriforcehunt', 'crystals'],
|
||||||
help='''\
|
help='''\
|
||||||
Select completion goal. (default: %(default)s)
|
Select completion goal. (default: %(default)s)
|
||||||
Ganon: Collect all crystals, beat Agahnim 2 then
|
Ganon: Collect all crystals, beat Agahnim 2 then
|
||||||
|
@ -77,6 +78,8 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
Agahnim fights and then defeat Ganon.
|
Agahnim fights and then defeat Ganon.
|
||||||
Triforce Hunt: Places 30 Triforce Pieces in the world, collect
|
Triforce Hunt: Places 30 Triforce Pieces in the world, collect
|
||||||
20 of them to beat the game.
|
20 of them to beat the game.
|
||||||
|
Local Triforce Hunt: Places 30 Triforce Pieces in your world, collect
|
||||||
|
20 of them to beat the game.
|
||||||
''')
|
''')
|
||||||
parser.add_argument('--difficulty', default=defval('normal'), const='normal', nargs='?', choices=['normal', 'hard', 'expert'],
|
parser.add_argument('--difficulty', default=defval('normal'), const='normal', nargs='?', choices=['normal', 'hard', 'expert'],
|
||||||
help='''\
|
help='''\
|
||||||
|
|
4
Fill.py
4
Fill.py
|
@ -228,7 +228,9 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
||||||
if not gftower_trash or not world.ganonstower_vanilla[player] or world.logic[player] == 'owglitches':
|
if not gftower_trash or not world.ganonstower_vanilla[player] or world.logic[player] == 'owglitches':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
gftower_trash_count = (random.randint(15, 50) if world.goal[player] == 'triforcehunt' else random.randint(0, 15))
|
gftower_trash_count = (
|
||||||
|
random.randint(15, 50) if world.goal[player] in {'triforcehunt', 'localtriforcehunt'} else random.randint(0,
|
||||||
|
15))
|
||||||
|
|
||||||
gtower_locations = [location for location in fill_locations if 'Ganons Tower' in location.name and location.player == player]
|
gtower_locations = [location for location in fill_locations if 'Ganons Tower' in location.name and location.player == player]
|
||||||
random.shuffle(gtower_locations)
|
random.shuffle(gtower_locations)
|
||||||
|
|
3
Gui.py
3
Gui.py
|
@ -243,7 +243,8 @@ def guiMain(args=None):
|
||||||
goalFrame = Frame(drowDownFrame)
|
goalFrame = Frame(drowDownFrame)
|
||||||
goalVar = StringVar()
|
goalVar = StringVar()
|
||||||
goalVar.set('ganon')
|
goalVar.set('ganon')
|
||||||
goalOptionMenu = OptionMenu(goalFrame, goalVar, 'ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals')
|
goalOptionMenu = OptionMenu(goalFrame, goalVar, 'ganon', 'pedestal', 'dungeons', 'triforcehunt',
|
||||||
|
'localtriforcehunt', 'crystals')
|
||||||
goalOptionMenu.pack(side=RIGHT)
|
goalOptionMenu.pack(side=RIGHT)
|
||||||
goalLabel = Label(goalFrame, text='Game goal')
|
goalLabel = Label(goalFrame, text='Game goal')
|
||||||
goalLabel.pack(side=LEFT)
|
goalLabel.pack(side=LEFT)
|
||||||
|
|
36
ItemList.py
36
ItemList.py
|
@ -125,30 +125,29 @@ difficulties = {
|
||||||
}
|
}
|
||||||
|
|
||||||
def generate_itempool(world, player):
|
def generate_itempool(world, player):
|
||||||
if (world.difficulty[player] not in ['normal', 'hard', 'expert'] or world.goal[player] not in ['ganon', 'pedestal',
|
if world.difficulty[player] not in ['normal', 'hard', 'expert']:
|
||||||
'dungeons',
|
raise NotImplementedError(f"Diffulty {world.difficulty[player]}")
|
||||||
'triforcehunt',
|
if world.goal[player] not in {'ganon', 'pedestal', 'dungeons', 'triforcehunt', 'localtriforcehunt', 'crystals'}:
|
||||||
'crystals']
|
raise NotImplementedError(f"Goal {world.goal[player]}")
|
||||||
or world.mode[player] not in ['open', 'standard', 'inverted'] or world.timer[player] not in [False,
|
if world.mode[player] not in {'open', 'standard', 'inverted'}:
|
||||||
'display',
|
raise NotImplementedError(f"Mode {world.mode[player]}")
|
||||||
'timed',
|
if world.timer[player] not in {False, 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'}:
|
||||||
'timed-ohko',
|
raise NotImplementedError(f"Timer {world.mode[player]}")
|
||||||
'ohko',
|
|
||||||
'timed-countdown']):
|
|
||||||
raise NotImplementedError('Not supported yet')
|
|
||||||
if world.timer[player] in ['ohko', 'timed-ohko']:
|
if world.timer[player] in ['ohko', 'timed-ohko']:
|
||||||
world.can_take_damage[player] = False
|
world.can_take_damage[player] = False
|
||||||
|
if world.goal[player] in ['pedestal', 'triforcehunt', 'localtriforcehunt']:
|
||||||
if world.goal[player] in ['pedestal', 'triforcehunt']:
|
|
||||||
world.push_item(world.get_location('Ganon', player), ItemFactory('Nothing', player), False)
|
world.push_item(world.get_location('Ganon', player), ItemFactory('Nothing', player), False)
|
||||||
else:
|
else:
|
||||||
world.push_item(world.get_location('Ganon', player), ItemFactory('Triforce', player), False)
|
world.push_item(world.get_location('Ganon', player), ItemFactory('Triforce', player), False)
|
||||||
|
|
||||||
if world.goal[player] in ['triforcehunt']:
|
if world.goal[player] in ['triforcehunt', 'localtriforcehunt']:
|
||||||
region = world.get_region('Light World',player)
|
region = world.get_region('Light World', player)
|
||||||
|
|
||||||
loc = Location(player, "Murahdahla", parent=region)
|
loc = Location(player, "Murahdahla", parent=region)
|
||||||
loc.access_rule = lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) > state.world.treasure_hunt_count[player]
|
loc.access_rule = lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star',
|
||||||
|
player) > \
|
||||||
|
state.world.treasure_hunt_count[player]
|
||||||
region.locations.append(loc)
|
region.locations.append(loc)
|
||||||
world.dynamic_locations.append(loc)
|
world.dynamic_locations.append(loc)
|
||||||
|
|
||||||
|
@ -505,7 +504,7 @@ def get_pool_core(world, player: int):
|
||||||
pool.extend(diff.timedohko)
|
pool.extend(diff.timedohko)
|
||||||
extraitems -= len(diff.timedohko)
|
extraitems -= len(diff.timedohko)
|
||||||
clock_mode = 'countdown-ohko'
|
clock_mode = 'countdown-ohko'
|
||||||
if goal == 'triforcehunt':
|
if goal in {'triforcehunt', 'localtriforcehunt'}:
|
||||||
pool.extend(diff.triforcehunt)
|
pool.extend(diff.triforcehunt)
|
||||||
extraitems -= len(diff.triforcehunt)
|
extraitems -= len(diff.triforcehunt)
|
||||||
treasure_hunt_count = diff.triforce_pieces_required
|
treasure_hunt_count = diff.triforce_pieces_required
|
||||||
|
@ -636,7 +635,8 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
|
||||||
treasure_hunt_count = max(min(customitemarray[67], 99), 1) #To display, count must be between 1 and 99.
|
treasure_hunt_count = max(min(customitemarray[67], 99), 1) #To display, count must be between 1 and 99.
|
||||||
treasure_hunt_icon = 'Triforce Piece'
|
treasure_hunt_icon = 'Triforce Piece'
|
||||||
# Ensure game is always possible to complete here, force sufficient pieces if the player is unwilling.
|
# Ensure game is always possible to complete here, force sufficient pieces if the player is unwilling.
|
||||||
if (customitemarray[66] < treasure_hunt_count) and (goal == 'triforcehunt') and (customitemarray[68] == 0):
|
if (customitemarray[66] < treasure_hunt_count) and (goal in {'triforcehunt', 'localtriforcehunt'}) and (
|
||||||
|
customitemarray[68] == 0):
|
||||||
extrapieces = treasure_hunt_count - customitemarray[66]
|
extrapieces = treasure_hunt_count - customitemarray[66]
|
||||||
pool.extend(['Triforce Piece'] * extrapieces)
|
pool.extend(['Triforce Piece'] * extrapieces)
|
||||||
itemtotal = itemtotal + extrapieces
|
itemtotal = itemtotal + extrapieces
|
||||||
|
|
|
@ -283,7 +283,9 @@ def roll_settings(weights):
|
||||||
'fast_ganon': 'crystals',
|
'fast_ganon': 'crystals',
|
||||||
'dungeons': 'dungeons',
|
'dungeons': 'dungeons',
|
||||||
'pedestal': 'pedestal',
|
'pedestal': 'pedestal',
|
||||||
'triforce-hunt': 'triforcehunt'
|
'triforce_hunt': 'triforcehunt',
|
||||||
|
'triforce-hunt': 'triforcehunt', # deprecated, moving all goals to `_`
|
||||||
|
'local_triforce_hunt': 'localtriforcehunt'
|
||||||
}[goal]
|
}[goal]
|
||||||
ret.openpyramid = goal == 'fast_ganon'
|
ret.openpyramid = goal == 'fast_ganon'
|
||||||
|
|
||||||
|
|
8
Rom.py
8
Rom.py
|
@ -1097,7 +1097,7 @@ def patch_rom(world, rom, player, team, enemized):
|
||||||
(0x02 if 'bombs' in world.escape_assist[player] else 0x00) |
|
(0x02 if 'bombs' in world.escape_assist[player] else 0x00) |
|
||||||
(0x04 if 'magic' in world.escape_assist[player] else 0x00))) # Escape assist
|
(0x04 if 'magic' in world.escape_assist[player] else 0x00))) # Escape assist
|
||||||
|
|
||||||
if world.goal[player] in ['pedestal', 'triforcehunt']:
|
if world.goal[player] in ['pedestal', 'triforcehunt', 'localtriforcehunt']:
|
||||||
rom.write_byte(0x18003E, 0x01) # make ganon invincible
|
rom.write_byte(0x18003E, 0x01) # make ganon invincible
|
||||||
elif world.goal[player] in ['dungeons']:
|
elif world.goal[player] in ['dungeons']:
|
||||||
rom.write_byte(0x18003E, 0x02) # make ganon invincible until all dungeons are beat
|
rom.write_byte(0x18003E, 0x02) # make ganon invincible until all dungeons are beat
|
||||||
|
@ -1776,11 +1776,13 @@ def write_strings(rom, world, player, team):
|
||||||
tt['sahasrahla_quest_have_master_sword'] = Sahasrahla2_texts[random.randint(0, len(Sahasrahla2_texts) - 1)]
|
tt['sahasrahla_quest_have_master_sword'] = Sahasrahla2_texts[random.randint(0, len(Sahasrahla2_texts) - 1)]
|
||||||
tt['blind_by_the_light'] = Blind_texts[random.randint(0, len(Blind_texts) - 1)]
|
tt['blind_by_the_light'] = Blind_texts[random.randint(0, len(Blind_texts) - 1)]
|
||||||
|
|
||||||
if world.goal[player] in ['triforcehunt']:
|
if world.goal[player] in ['triforcehunt', 'localtriforcehunt']:
|
||||||
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Get the Triforce Pieces.'
|
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Get the Triforce Pieces.'
|
||||||
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
|
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
|
||||||
tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!'
|
tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!'
|
||||||
tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\ninvisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\nhidden in a hollow tree. If you bring\n%d triforce pieces, I can reassemble it." % world.treasure_hunt_count[player]
|
tt[
|
||||||
|
'murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\ninvisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\nhidden in a hollow tree. If you bring\n%d triforce pieces, I can reassemble it." % \
|
||||||
|
world.treasure_hunt_count[player]
|
||||||
elif world.goal[player] in ['pedestal']:
|
elif world.goal[player] in ['pedestal']:
|
||||||
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Your goal is at the pedestal.'
|
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Your goal is at the pedestal.'
|
||||||
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
|
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
|
||||||
|
|
8
Rules.py
8
Rules.py
|
@ -137,7 +137,10 @@ def item_name(state, location, player):
|
||||||
def global_rules(world, player):
|
def global_rules(world, player):
|
||||||
# ganon can only carry triforce
|
# ganon can only carry triforce
|
||||||
add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player)
|
add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player)
|
||||||
|
if world.goal[player] == "localtriforcehunt":
|
||||||
|
for location in world.get_locations():
|
||||||
|
if location.player != player:
|
||||||
|
forbid_item(location, 'Triforce Piece', player)
|
||||||
# determines which S&Q locations are available - hide from paths since it isn't an in-game location
|
# determines which S&Q locations are available - hide from paths since it isn't an in-game location
|
||||||
world.get_region('Menu', player).can_reach_private = lambda state: True
|
world.get_region('Menu', player).can_reach_private = lambda state: True
|
||||||
for exit in world.get_region('Menu', player).exits:
|
for exit in world.get_region('Menu', player).exits:
|
||||||
|
@ -147,7 +150,8 @@ 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('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('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('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_beam_sword(player))
|
||||||
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('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player))
|
||||||
|
|
||||||
|
|
2
Utils.py
2
Utils.py
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
__version__ = "2.2.1"
|
__version__ = "2.3.0"
|
||||||
_version_tuple = tuple(int(piece, 10) for piece in __version__.split("."))
|
_version_tuple = tuple(int(piece, 10) for piece in __version__.split("."))
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
|
@ -73,7 +73,8 @@ goals:
|
||||||
fast_ganon: 0 # Only killing Ganon is required. The hole is always open. Items may still be placed in GT, however
|
fast_ganon: 0 # Only killing Ganon is required. The hole is always open. Items may still be placed in GT, however
|
||||||
dungeons: 0 # Defeat the boss of all dungeons, including Agahnim's tower and GT (Aga 2)
|
dungeons: 0 # Defeat the boss of all dungeons, including Agahnim's tower and GT (Aga 2)
|
||||||
pedestal: 0 # Pull the Triforce from the Master Sword pedestal
|
pedestal: 0 # Pull the Triforce from the Master Sword pedestal
|
||||||
triforce-hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout the world, then turn them in to Murahadala in front of Hyrule Castle
|
triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout the worlds, then turn them in to Murahadala in front of Hyrule Castle
|
||||||
|
local_triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout your world, then turn them in to Murahadala in front of Hyrule Castle
|
||||||
tower_open: # Crystals required to open GT
|
tower_open: # Crystals required to open GT
|
||||||
'0': 8
|
'0': 8
|
||||||
'1': 7
|
'1': 7
|
||||||
|
|
Loading…
Reference in New Issue