Plando support for OW edges

This commit is contained in:
codemann8
2021-08-16 22:50:03 -05:00
parent 323235ba26
commit 8ff463b5c7
3 changed files with 123 additions and 71 deletions

View File

@@ -164,8 +164,6 @@ def link_overworld(world, player):
connected_edges = [] connected_edges = []
connect_custom(world, connected_edges, player)
# layout shuffle # layout shuffle
if world.owShuffle[player] == 'vanilla' and not world.owCrossed[player]: if world.owShuffle[player] == 'vanilla' and not world.owCrossed[player]:
# vanilla transitions # vanilla transitions
@@ -208,6 +206,8 @@ def link_overworld(world, player):
for exitname, destname in test_connections: for exitname, destname in test_connections:
connect_two_way(world, exitname, destname, player, connected_edges) connect_two_way(world, exitname, destname, player, connected_edges)
connect_custom(world, connected_edges, player)
trimmed_groups = remove_reserved(world, trimmed_groups, connected_edges, player) trimmed_groups = remove_reserved(world, trimmed_groups, connected_edges, player)
groups = reorganize_groups(world, trimmed_groups, player) groups = reorganize_groups(world, trimmed_groups, player)
@@ -321,7 +321,15 @@ def link_overworld(world, player):
def connect_custom(world, connected_edges, player): def connect_custom(world, connected_edges, player):
if hasattr(world, 'custom_overworld') and world.custom_overworld[player]: if hasattr(world, 'custom_overworld') and world.custom_overworld[player]:
for edgename1, edgename2 in world.custom_overworld[player]: for edgename1, edgename2 in world.custom_overworld[player]:
if edgename1 in connected_edges or edgename2 in connected_edges:
owedge1 = world.check_for_owedge(edgename1, player)
owedge2 = world.check_for_owedge(edgename2, player)
if owedge1.dest is not None and owedge1.dest.name == owedge2.name:
continue # if attempting to connect a pair that was already connected earlier, allow it to continue
raise RuntimeError('Invalid plando connection: rule violation based on current settings')
connect_two_way(world, edgename1, edgename2, player, connected_edges) connect_two_way(world, edgename1, edgename2, player, connected_edges)
if world.owKeepSimilar[player]: #TODO: If connecting an edge that belongs to a similar pair, the remaining edges need to get connected automatically
continue
def connect_simple(world, exitname, regionname, player): def connect_simple(world, exitname, regionname, player):
world.get_entrance(exitname, player).connect(world.get_region(regionname, player)) world.get_entrance(exitname, player).connect(world.get_region(regionname, player))

175
Plando.py
View File

@@ -9,6 +9,7 @@ import sys
from BaseClasses import World from BaseClasses import World
from Regions import create_regions from Regions import create_regions
from OverworldShuffle import link_overworld
from EntranceShuffle import link_entrances, connect_entrance, connect_two_way, connect_exit from EntranceShuffle import link_entrances, connect_entrance, connect_two_way, connect_exit
from Rom import patch_rom, LocalRom, write_string_to_rom, apply_rom_settings, get_sprite_from_name from Rom import patch_rom, LocalRom, write_string_to_rom, apply_rom_settings, get_sprite_from_name
from Rules import set_rules from Rules import set_rules
@@ -42,6 +43,11 @@ def main(args):
create_regions(world, 1) create_regions(world, 1)
create_dungeons(world, 1) create_dungeons(world, 1)
text_patches = []
prefill_world(world, args.plando, text_patches)
link_overworld(world, 1)
link_entrances(world, 1) link_entrances(world, 1)
logger.info('Calculating Access Rules.') logger.info('Calculating Access Rules.')
@@ -50,9 +56,7 @@ def main(args):
logger.info('Fill the world.') logger.info('Fill the world.')
text_patches = [] fill_world(world, args.plando)
fill_world(world, args.plando, text_patches)
if world.get_entrance('Dam', 1).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', 1).connected_region.name != 'Swamp Palace (Entrance)': if world.get_entrance('Dam', 1).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', 1).connected_region.name != 'Swamp Palace (Entrance)':
world.swamp_patch_required[1] = True world.swamp_patch_required[1] = True
@@ -92,75 +96,14 @@ def main(args):
return world return world
def fill_world(world, plando, text_patches): def fill_world(world, plando):
mm_medallion = 'Ether'
tr_medallion = 'Quake'
logger = logging.getLogger('') logger = logging.getLogger('')
with open(plando, 'r') as plandofile: with open(plando, 'r') as plandofile:
for line in plandofile.readlines(): for line in plandofile.readlines():
line = line.lstrip()
if line.startswith('#'): if line.startswith('#'):
continue continue
if ':' in line: elif ':' in line:
line = line.lstrip()
if line.startswith('!'):
if line.startswith('!mm_medallion'):
_, medallionstr = line.split(':', 1)
mm_medallion = medallionstr.strip()
elif line.startswith('!tr_medallion'):
_, medallionstr = line.split(':', 1)
tr_medallion = medallionstr.strip()
elif line.startswith('!mode'):
_, modestr = line.split(':', 1)
world.mode = {1: modestr.strip()}
elif line.startswith('!logic'):
_, logicstr = line.split(':', 1)
world.logic = {1: logicstr.strip()}
elif line.startswith('!goal'):
_, goalstr = line.split(':', 1)
world.goal = {1: goalstr.strip()}
elif line.startswith('!light_cone_sewers'):
_, sewerstr = line.split(':', 1)
world.sewer_light_cone = {1: sewerstr.strip().lower() == 'true'}
elif line.startswith('!light_cone_lw'):
_, lwconestr = line.split(':', 1)
world.light_world_light_cone = lwconestr.strip().lower() == 'true'
elif line.startswith('!light_cone_dw'):
_, dwconestr = line.split(':', 1)
world.dark_world_light_cone = dwconestr.strip().lower() == 'true'
elif line.startswith('!fix_trock_doors'):
_, trdstr = line.split(':', 1)
world.fix_trock_doors = {1: trdstr.strip().lower() == 'true'}
elif line.startswith('!fix_trock_exit'):
_, trfstr = line.split(':', 1)
world.fix_trock_exit = {1: trfstr.strip().lower() == 'true'}
elif line.startswith('!fix_gtower_exit'):
_, gtfstr = line.split(':', 1)
world.fix_gtower_exit = gtfstr.strip().lower() == 'true'
elif line.startswith('!fix_pod_exit'):
_, podestr = line.split(':', 1)
world.fix_palaceofdarkness_exit = {1: podestr.strip().lower() == 'true'}
elif line.startswith('!fix_skullwoods_exit'):
_, swestr = line.split(':', 1)
world.fix_skullwoods_exit = {1: swestr.strip().lower() == 'true'}
elif line.startswith('!check_beatable_only'):
_, chkbtstr = line.split(':', 1)
world.check_beatable_only = chkbtstr.strip().lower() == 'true'
elif line.startswith('!ganon_death_pyramid_respawn'):
_, gnpstr = line.split(':', 1)
world.ganon_at_pyramid = gnpstr.strip().lower() == 'true'
elif line.startswith('!save_quit_boss'):
_, sqbstr = line.split(':', 1)
world.save_and_quite_from_boss = sqbstr.strip().lower() == 'true'
elif line.startswith('!text_'):
textname, text = line.split(':', 1)
text_patches.append([textname.lstrip('!text_').strip(), 'text', text.strip()])
#temporarilly removed. New credits system not ready to handle this.
#elif line.startswith('!credits_'):
# textname, text = line.split(':', 1)
# text_patches.append([textname.lstrip('!credits_').strip(), 'credits', text.strip()])
continue
locationstr, itemstr = line.split(':', 1) locationstr, itemstr = line.split(':', 1)
location = world.get_location(locationstr.strip(), 1) location = world.get_location(locationstr.strip(), 1)
if location is None: if location is None:
@@ -172,6 +115,7 @@ def fill_world(world, plando, text_patches):
world.push_item(location, item) world.push_item(location, item)
if item.smallkey or item.bigkey: if item.smallkey or item.bigkey:
location.event = True location.event = True
#TODO: move entrance stuff to prefill_world to work like OW stuff
elif '<=>' in line: elif '<=>' in line:
entrance, exit = line.split('<=>', 1) entrance, exit = line.split('<=>', 1)
connect_two_way(world, entrance.strip(), exit.strip(), 1) connect_two_way(world, entrance.strip(), exit.strip(), 1)
@@ -182,14 +126,107 @@ def fill_world(world, plando, text_patches):
entrance, exit = line.split('<=', 1) entrance, exit = line.split('<=', 1)
connect_exit(world, exit.strip(), entrance.strip(), 1) connect_exit(world, exit.strip(), entrance.strip(), 1)
world.required_medallions[1] = (mm_medallion, tr_medallion)
# set up Agahnim Events # set up Agahnim Events
world.get_location('Agahnim 1', 1).event = True world.get_location('Agahnim 1', 1).event = True
world.get_location('Agahnim 1', 1).item = ItemFactory('Beat Agahnim 1', 1) world.get_location('Agahnim 1', 1).item = ItemFactory('Beat Agahnim 1', 1)
world.get_location('Agahnim 2', 1).event = True world.get_location('Agahnim 2', 1).event = True
world.get_location('Agahnim 2', 1).item = ItemFactory('Beat Agahnim 2', 1) world.get_location('Agahnim 2', 1).item = ItemFactory('Beat Agahnim 2', 1)
def prefill_world(world, plando, text_patches):
mm_medallion = 'Ether'
tr_medallion = 'Quake'
logger = logging.getLogger('')
with open(plando, 'r') as plandofile:
for line in plandofile.readlines():
line = line.lstrip()
if line.startswith('#'):
continue
elif line.startswith('!'):
if line.startswith('!mm_medallion'):
_, medallionstr = line.split(':', 1)
mm_medallion = medallionstr.strip()
elif line.startswith('!tr_medallion'):
_, medallionstr = line.split(':', 1)
tr_medallion = medallionstr.strip()
elif line.startswith('!mode'):
_, modestr = line.split(':', 1)
world.mode = {1: modestr.strip()}
elif line.startswith('!logic'):
_, logicstr = line.split(':', 1)
world.logic = {1: logicstr.strip()}
elif line.startswith('!goal'):
_, goalstr = line.split(':', 1)
world.goal = {1: goalstr.strip()}
elif line.startswith('!owShuffle'):
_, modestr = line.split(':', 1)
world.owShuffle = {1: modestr.strip()}
elif line.startswith('!owCrossed'):
_, modestr = line.split(':', 1)
modestr = modestr.strip().lower()
world.owCrossed = {1: True if modestr in ('true', 'yes', 'on', 'enabled') else False}
elif line.startswith('!owKeepSimilar'):
_, modestr = line.split(':', 1)
modestr = modestr.strip().lower()
world.owKeepSimilar = {1: True if modestr in ('true', 'yes', 'on', 'enabled') else False}
elif line.startswith('!light_cone_sewers'):
_, sewerstr = line.split(':', 1)
world.sewer_light_cone = {1: sewerstr.strip().lower() == 'true'}
elif line.startswith('!light_cone_lw'):
_, lwconestr = line.split(':', 1)
world.light_world_light_cone = lwconestr.strip().lower() == 'true'
elif line.startswith('!light_cone_dw'):
_, dwconestr = line.split(':', 1)
world.dark_world_light_cone = dwconestr.strip().lower() == 'true'
elif line.startswith('!fix_trock_doors'):
_, trdstr = line.split(':', 1)
world.fix_trock_doors = {1: trdstr.strip().lower() == 'true'}
elif line.startswith('!fix_trock_exit'):
_, trfstr = line.split(':', 1)
world.fix_trock_exit = {1: trfstr.strip().lower() == 'true'}
elif line.startswith('!fix_gtower_exit'):
_, gtfstr = line.split(':', 1)
world.fix_gtower_exit = gtfstr.strip().lower() == 'true'
elif line.startswith('!fix_pod_exit'):
_, podestr = line.split(':', 1)
world.fix_palaceofdarkness_exit = {1: podestr.strip().lower() == 'true'}
elif line.startswith('!fix_skullwoods_exit'):
_, swestr = line.split(':', 1)
world.fix_skullwoods_exit = {1: swestr.strip().lower() == 'true'}
elif line.startswith('!check_beatable_only'):
_, chkbtstr = line.split(':', 1)
world.check_beatable_only = chkbtstr.strip().lower() == 'true'
elif line.startswith('!ganon_death_pyramid_respawn'):
_, gnpstr = line.split(':', 1)
world.ganon_at_pyramid = gnpstr.strip().lower() == 'true'
elif line.startswith('!save_quit_boss'):
_, sqbstr = line.split(':', 1)
world.save_and_quite_from_boss = sqbstr.strip().lower() == 'true'
elif line.startswith('!text_'):
textname, text = line.split(':', 1)
text_patches.append([textname.lstrip('!text_').strip(), 'text', text.strip()])
#temporarilly removed. New credits system not ready to handle this.
#elif line.startswith('!credits_'):
# textname, text = line.split(':', 1)
# text_patches.append([textname.lstrip('!credits_').strip(), 'credits', text.strip()])
continue
elif line.startswith('$'):
edge1, edge2 = line.split('=', 1)
if world.custom_overworld is None:
world.custom_overworld = {1: []}
world.custom_overworld[1].append(edge1.strip(), edge2.strip())
#TODO: Do entrances similar to OW
elif '<=>' in line:
entrance, exit = line.split('<=>', 1)
#connect_two_way(world, entrance.strip(), exit.strip(), 1)
elif '=>' in line:
entrance, exit = line.split('=>', 1)
#connect_entrance(world, entrance.strip(), exit.strip(), 1)
elif '<=' in line:
entrance, exit = line.split('<=', 1)
#connect_exit(world, exit.strip(), entrance.strip(), 1)
world.required_medallions[1] = (mm_medallion, tr_medallion)
def start(): def start():
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)

View File

@@ -242,3 +242,10 @@ Ganons Tower - Mini Helmasaur Room - Right: Nothing
Ganons Tower - Pre-Moldorm Chest: Small Key (Ganons Tower) Ganons Tower - Pre-Moldorm Chest: Small Key (Ganons Tower)
Ganons Tower - Validation Chest: Nothing Ganons Tower - Validation Chest: Nothing
Ganon: Triforce Ganon: Triforce
# set Overworld connections (lines starting with $, separate edges with =)
!owShuffle: parallel
#!owMixed: true # Mixed OW not supported yet
!owCrossed: true
!owKeepSimilar: true
$Links House NE = Kakariko Village SE