Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f539e24ddb | ||
|
|
78dd5c65fc |
@@ -0,0 +1 @@
|
|||||||
|
* text=auto
|
||||||
@@ -32,8 +32,6 @@ weights/
|
|||||||
/output/
|
/output/
|
||||||
/enemizer/
|
/enemizer/
|
||||||
|
|
||||||
base2current.json
|
|
||||||
|
|
||||||
resources/user/*
|
resources/user/*
|
||||||
!resources/user/.gitkeep
|
!resources/user/.gitkeep
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -1,13 +1,14 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
|
||||||
import logging
|
import logging
|
||||||
import textwrap
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import textwrap
|
||||||
|
|
||||||
from AdjusterMain import adjust
|
from AdjusterMain import adjust
|
||||||
from Rom import get_sprite_from_name
|
from Rom import get_sprite_from_name
|
||||||
|
|
||||||
|
|
||||||
class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter):
|
class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter):
|
||||||
|
|
||||||
def _get_help_string(self, action):
|
def _get_help_string(self, action):
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import logging
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import bps.apply
|
import bps.apply
|
||||||
@@ -8,9 +8,9 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
raise Exception('Could not load BPS module')
|
raise Exception('Could not load BPS module')
|
||||||
|
|
||||||
from Utils import output_path
|
|
||||||
from Rom import LocalRom, apply_rom_settings
|
from Rom import LocalRom, apply_rom_settings
|
||||||
from source.tools.BPS import bps_read_vlv
|
from source.tools.BPS import bps_read_vlv
|
||||||
|
from Utils import output_path
|
||||||
|
|
||||||
|
|
||||||
def adjust(args):
|
def adjust(args):
|
||||||
|
|||||||
+35
-15
@@ -2,7 +2,7 @@ import base64
|
|||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from collections import OrderedDict, Counter, deque, defaultdict
|
from collections import Counter, OrderedDict, defaultdict, deque
|
||||||
from enum import Enum, IntEnum, unique
|
from enum import Enum, IntEnum, unique
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -10,12 +10,18 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
from enum import IntFlag as FastEnum
|
from enum import IntFlag as FastEnum
|
||||||
|
|
||||||
from source.classes.BabelFish import BabelFish
|
|
||||||
from Utils import int16_as_bytes
|
|
||||||
from Tables import normal_offset_table, spiral_offset_table, multiply_lookup, divisor_lookup
|
|
||||||
from RoomData import Room
|
from RoomData import Room
|
||||||
|
from source.classes.BabelFish import BabelFish
|
||||||
from source.dungeon.RoomObject import RoomObject
|
from source.dungeon.RoomObject import RoomObject
|
||||||
from source.overworld.EntranceData import door_addresses
|
from source.overworld.EntranceData import door_addresses
|
||||||
|
from Tables import (
|
||||||
|
divisor_lookup,
|
||||||
|
multiply_lookup,
|
||||||
|
normal_offset_table,
|
||||||
|
spiral_offset_table,
|
||||||
|
)
|
||||||
|
from Utils import int16_as_bytes
|
||||||
|
from Versions import DRVersion, GKVersion, ORVersion
|
||||||
|
|
||||||
|
|
||||||
class World(object):
|
class World(object):
|
||||||
@@ -74,6 +80,8 @@ class World(object):
|
|||||||
self.dark_rooms = {}
|
self.dark_rooms = {}
|
||||||
self.damage_challenge = {}
|
self.damage_challenge = {}
|
||||||
self.shuffle_damage_table = {}
|
self.shuffle_damage_table = {}
|
||||||
|
self.bosses_ganon = {}
|
||||||
|
self.bosshunt_include_agas = {}
|
||||||
self.ganon_item = {}
|
self.ganon_item = {}
|
||||||
self.ganon_item_orig = {}
|
self.ganon_item_orig = {}
|
||||||
self.custom = custom
|
self.custom = custom
|
||||||
@@ -149,6 +157,8 @@ class World(object):
|
|||||||
set_player_attr('keyshuffle', 'none')
|
set_player_attr('keyshuffle', 'none')
|
||||||
set_player_attr('bigkeyshuffle', 'none')
|
set_player_attr('bigkeyshuffle', 'none')
|
||||||
set_player_attr('prizeshuffle', 'none')
|
set_player_attr('prizeshuffle', 'none')
|
||||||
|
set_player_attr('showloot', 'never')
|
||||||
|
set_player_attr('showmap', 'map')
|
||||||
set_player_attr('restrict_boss_items', 'none')
|
set_player_attr('restrict_boss_items', 'none')
|
||||||
set_player_attr('bombbag', False)
|
set_player_attr('bombbag', False)
|
||||||
set_player_attr('flute_mode', 'normal')
|
set_player_attr('flute_mode', 'normal')
|
||||||
@@ -166,6 +176,8 @@ class World(object):
|
|||||||
set_player_attr('escape_assist', [])
|
set_player_attr('escape_assist', [])
|
||||||
set_player_attr('crystals_needed_for_ganon', 7)
|
set_player_attr('crystals_needed_for_ganon', 7)
|
||||||
set_player_attr('crystals_needed_for_gt', 7)
|
set_player_attr('crystals_needed_for_gt', 7)
|
||||||
|
set_player_attr('bosses_ganon', 8)
|
||||||
|
set_player_attr('bosshunt_include_agas', False)
|
||||||
set_player_attr('ganon_item', 'silver')
|
set_player_attr('ganon_item', 'silver')
|
||||||
set_player_attr('crystals_ganon_orig', {})
|
set_player_attr('crystals_ganon_orig', {})
|
||||||
set_player_attr('crystals_gt_orig', {})
|
set_player_attr('crystals_gt_orig', {})
|
||||||
@@ -354,7 +366,7 @@ class World(object):
|
|||||||
else:
|
else:
|
||||||
if self.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'district']:
|
if self.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'district']:
|
||||||
return False
|
return False
|
||||||
elif self.goal[player] in ['crystals', 'trinity', 'ganonhunt']:
|
elif self.goal[player] in ['crystals', 'trinity', 'ganonhunt', 'bosshunt']:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
@@ -1664,8 +1676,8 @@ class Region(object):
|
|||||||
self.crystal_switch = False
|
self.crystal_switch = False
|
||||||
|
|
||||||
def can_reach(self, state):
|
def can_reach(self, state):
|
||||||
from Utils import stack_size3a
|
|
||||||
from DungeonGenerator import GenerationException
|
from DungeonGenerator import GenerationException
|
||||||
|
from Utils import stack_size3a
|
||||||
if stack_size3a() > self.world.players * 1000:
|
if stack_size3a() > self.world.players * 1000:
|
||||||
raise GenerationException(f'Infinite loop detected for "{self.name}" located at \'Region.can_reach\'')
|
raise GenerationException(f'Infinite loop detected for "{self.name}" located at \'Region.can_reach\'')
|
||||||
|
|
||||||
@@ -3072,12 +3084,9 @@ class Spoiler(object):
|
|||||||
self.doorTypes[(doorNames, player)] = OrderedDict([('player', player), ('doorNames', doorNames), ('type', type)])
|
self.doorTypes[(doorNames, player)] = OrderedDict([('player', player), ('doorNames', doorNames), ('type', type)])
|
||||||
|
|
||||||
def parse_meta(self):
|
def parse_meta(self):
|
||||||
from Main import __version__ as ERVersion
|
|
||||||
from OverworldShuffle import __version__ as ORVersion
|
|
||||||
|
|
||||||
self.startinventory = list(map(str, self.world.precollected_items))
|
self.startinventory = list(map(str, self.world.precollected_items))
|
||||||
self.metadata = {'version': ERVersion,
|
self.metadata = {'version': GKVersion,
|
||||||
'versions': {'Door':ERVersion, 'Overworld':ORVersion},
|
'versions': {'Door': DRVersion, 'Overworld': ORVersion},
|
||||||
'logic': self.world.logic,
|
'logic': self.world.logic,
|
||||||
'mode': self.world.mode,
|
'mode': self.world.mode,
|
||||||
'bombbag': self.world.bombbag,
|
'bombbag': self.world.bombbag,
|
||||||
@@ -3116,6 +3125,8 @@ class Spoiler(object):
|
|||||||
'beemizer': self.world.beemizer,
|
'beemizer': self.world.beemizer,
|
||||||
'gt_crystals': self.world.crystals_needed_for_gt,
|
'gt_crystals': self.world.crystals_needed_for_gt,
|
||||||
'ganon_crystals': self.world.crystals_needed_for_ganon,
|
'ganon_crystals': self.world.crystals_needed_for_ganon,
|
||||||
|
'ganon_bosses': self.world.bosses_ganon,
|
||||||
|
'bosshunt_include_agas': self.world.bosshunt_include_agas,
|
||||||
'ganon_item': self.world.ganon_item,
|
'ganon_item': self.world.ganon_item,
|
||||||
'open_pyramid': self.world.open_pyramid,
|
'open_pyramid': self.world.open_pyramid,
|
||||||
'accessibility': self.world.accessibility,
|
'accessibility': self.world.accessibility,
|
||||||
@@ -3126,6 +3137,8 @@ class Spoiler(object):
|
|||||||
'keyshuffle': self.world.keyshuffle,
|
'keyshuffle': self.world.keyshuffle,
|
||||||
'bigkeyshuffle': self.world.bigkeyshuffle,
|
'bigkeyshuffle': self.world.bigkeyshuffle,
|
||||||
'prizeshuffle': self.world.prizeshuffle,
|
'prizeshuffle': self.world.prizeshuffle,
|
||||||
|
'showloot': self.world.showloot,
|
||||||
|
'showmap': self.world.showmap,
|
||||||
'boss_shuffle': self.world.boss_shuffle,
|
'boss_shuffle': self.world.boss_shuffle,
|
||||||
'enemy_shuffle': self.world.enemy_shuffle,
|
'enemy_shuffle': self.world.enemy_shuffle,
|
||||||
'enemy_health': self.world.enemy_health,
|
'enemy_health': self.world.enemy_health,
|
||||||
@@ -3290,7 +3303,7 @@ class Spoiler(object):
|
|||||||
self.parse_meta()
|
self.parse_meta()
|
||||||
with open(filename, 'w') as outfile:
|
with open(filename, 'w') as outfile:
|
||||||
line_width = 35
|
line_width = 35
|
||||||
outfile.write('ALttP Overworld Randomizer - Seed: %s\n\n' % (self.world.seed))
|
outfile.write('ALttP GwaaKiwi Randomizer - Seed: %s\n\n' % (self.world.seed))
|
||||||
for k,v in self.metadata["versions"].items():
|
for k,v in self.metadata["versions"].items():
|
||||||
outfile.write((k + ' Version:').ljust(line_width) + '%s\n' % v)
|
outfile.write((k + ' Version:').ljust(line_width) + '%s\n' % v)
|
||||||
for player in range(1, self.world.players + 1):
|
for player in range(1, self.world.players + 1):
|
||||||
@@ -3305,7 +3318,7 @@ class Spoiler(object):
|
|||||||
self.parse_meta()
|
self.parse_meta()
|
||||||
with open(filename, 'w') as outfile:
|
with open(filename, 'w') as outfile:
|
||||||
line_width = 35
|
line_width = 35
|
||||||
outfile.write('ALttP Overworld Randomizer - Seed: %s\n\n' % (self.world.seed))
|
outfile.write('ALttP GwaaKiwi Randomizer - Seed: %s\n\n' % (self.world.seed))
|
||||||
for k,v in self.metadata["versions"].items():
|
for k,v in self.metadata["versions"].items():
|
||||||
outfile.write((k + ' Version:').ljust(line_width) + '%s\n' % v)
|
outfile.write((k + ' Version:').ljust(line_width) + '%s\n' % v)
|
||||||
if self.metadata['user_notes']:
|
if self.metadata['user_notes']:
|
||||||
@@ -3336,6 +3349,10 @@ class Spoiler(object):
|
|||||||
if custom['ganongoal'] and 'requirements' in custom['ganongoal']:
|
if custom['ganongoal'] and 'requirements' in custom['ganongoal']:
|
||||||
outfile.write('Ganon Requirement:'.ljust(line_width) + 'custom\n')
|
outfile.write('Ganon Requirement:'.ljust(line_width) + 'custom\n')
|
||||||
outfile.write(' %s\n' % custom['ganongoal']['goaltext'])
|
outfile.write(' %s\n' % custom['ganongoal']['goaltext'])
|
||||||
|
elif self.metadata['goal'][player] == 'bosshunt':
|
||||||
|
outfile.write('Ganon Requirement:'.ljust(line_width) + '%s bosses%s\n' %
|
||||||
|
(str(self.world.bosses_ganon[player]),
|
||||||
|
' (including both Agahnims)' if self.world.bosshunt_include_agas[player] else ''))
|
||||||
else:
|
else:
|
||||||
outfile.write('Ganon Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_ganon_orig[player]))
|
outfile.write('Ganon Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_ganon_orig[player]))
|
||||||
if custom['pedgoal'] and 'requirements' in custom['pedgoal']:
|
if custom['pedgoal'] and 'requirements' in custom['pedgoal']:
|
||||||
@@ -3390,6 +3407,8 @@ class Spoiler(object):
|
|||||||
outfile.write('Small Key Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['keyshuffle'][player])
|
outfile.write('Small Key Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['keyshuffle'][player])
|
||||||
outfile.write('Big Key Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['bigkeyshuffle'][player])
|
outfile.write('Big Key Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['bigkeyshuffle'][player])
|
||||||
outfile.write('Prize Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['prizeshuffle'][player])
|
outfile.write('Prize Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['prizeshuffle'][player])
|
||||||
|
outfile.write('Show Value of Checks:'.ljust(line_width) + '%s\n' % self.metadata['showloot'][player])
|
||||||
|
outfile.write('Show Map:'.ljust(line_width) + '%s\n' % self.metadata['showmap'][player])
|
||||||
outfile.write('Key Logic Algorithm:'.ljust(line_width) + '%s\n' % self.metadata['key_logic'][player])
|
outfile.write('Key Logic Algorithm:'.ljust(line_width) + '%s\n' % self.metadata['key_logic'][player])
|
||||||
outfile.write('\n')
|
outfile.write('\n')
|
||||||
outfile.write('Door Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['door_shuffle'][player])
|
outfile.write('Door Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['door_shuffle'][player])
|
||||||
@@ -3743,8 +3762,9 @@ world_mode = {"open": 0, "standard": 1, "inverted": 2}
|
|||||||
sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3}
|
sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3}
|
||||||
|
|
||||||
# byte 2: GGGD DFFH (goal, diff, item_func, hints)
|
# byte 2: GGGD DFFH (goal, diff, item_func, hints)
|
||||||
goal_mode = {'ganon': 0, 'pedestal': 1, 'dungeons': 2, 'triforcehunt': 3, 'crystals': 4, 'trinity': 5,
|
goal_mode = {'ganon': 0, 'pedestal': 1, 'dungeons': 2, 'triforcehunt': 3,
|
||||||
'ganonhunt': 6, 'completionist': 7, 'sanctuary': 1}
|
'crystals': 4, 'trinity': 5, 'ganonhunt': 6, 'completionist': 7,
|
||||||
|
'sanctuary': 1, 'bosshunt': 6}
|
||||||
diff_mode = {"normal": 0, "hard": 1, "expert": 2}
|
diff_mode = {"normal": 0, "hard": 1, "expert": 2}
|
||||||
func_mode = {"normal": 0, "hard": 1, "expert": 2}
|
func_mode = {"normal": 0, "hard": 1, "expert": 2}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import RaceRandom as random
|
|
||||||
|
|
||||||
|
import RaceRandom as random
|
||||||
from BaseClasses import Boss, FillError
|
from BaseClasses import Boss, FillError
|
||||||
from source.enemizer.Bossmizer import boss_adjust
|
from source.enemizer.Bossmizer import boss_adjust
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,13 @@ import argparse
|
|||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import textwrap
|
|
||||||
import shlex
|
import shlex
|
||||||
import sys
|
import sys
|
||||||
|
import textwrap
|
||||||
|
|
||||||
from source.classes.BabelFish import BabelFish
|
from source.classes.BabelFish import BabelFish
|
||||||
|
|
||||||
from Utils import update_deprecated_args
|
|
||||||
from source.classes.CustomSettings import CustomSettings
|
from source.classes.CustomSettings import CustomSettings
|
||||||
|
from Utils import update_deprecated_args
|
||||||
|
|
||||||
|
|
||||||
class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter):
|
class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter):
|
||||||
@@ -107,7 +106,7 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
ret = parser.parse_args(argv)
|
ret = parser.parse_args(argv)
|
||||||
|
|
||||||
if ret.keysanity:
|
if ret.keysanity:
|
||||||
ret.mapshuffle, ret.compassshuffle, ret.keyshuffle, ret.bigkeyshuffle = 'wild' * 4
|
ret.mapshuffle, ret.compassshuffle, ret.keyshuffle, ret.bigkeyshuffle = ['wild'] * 4
|
||||||
|
|
||||||
if ret.keydropshuffle:
|
if ret.keydropshuffle:
|
||||||
ret.dropshuffle = 'keys' if ret.dropshuffle == 'none' else ret.dropshuffle
|
ret.dropshuffle = 'keys' if ret.dropshuffle == 'none' else ret.dropshuffle
|
||||||
@@ -134,8 +133,8 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality', 'ow_shuffle',
|
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality', 'ow_shuffle',
|
||||||
'ow_terrain', 'ow_crossed', 'ow_keepsimilar', 'ow_mixed', 'ow_whirlpool', 'ow_fluteshuffle',
|
'ow_terrain', 'ow_crossed', 'ow_keepsimilar', 'ow_mixed', 'ow_whirlpool', 'ow_fluteshuffle',
|
||||||
'flute_mode', 'bow_mode', 'take_any', 'boots_hint', 'shuffle_followers',
|
'flute_mode', 'bow_mode', 'take_any', 'boots_hint', 'shuffle_followers',
|
||||||
'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'ganon_item', 'openpyramid',
|
'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'bosses_ganon', 'bosshunt_include_agas', 'ganon_item', 'openpyramid',
|
||||||
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'prizeshuffle', 'startinventory',
|
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'prizeshuffle', 'showloot', 'showmap', 'startinventory',
|
||||||
'usestartinventory', 'bombbag', 'shuffleganon', 'overworld_map', 'restrict_boss_items',
|
'usestartinventory', 'bombbag', 'shuffleganon', 'overworld_map', 'restrict_boss_items',
|
||||||
'triforce_max_difference', 'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max',
|
'triforce_max_difference', 'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max',
|
||||||
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'shuffletavern',
|
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'shuffletavern',
|
||||||
@@ -178,6 +177,8 @@ def parse_settings():
|
|||||||
"goal": "ganon",
|
"goal": "ganon",
|
||||||
"crystals_gt": "7",
|
"crystals_gt": "7",
|
||||||
"crystals_ganon": "7",
|
"crystals_ganon": "7",
|
||||||
|
"bosses_ganon": "8",
|
||||||
|
"bosshunt_include_agas": False,
|
||||||
"ganon_item": "silver",
|
"ganon_item": "silver",
|
||||||
"swords": "random",
|
"swords": "random",
|
||||||
"flute_mode": "normal",
|
"flute_mode": "normal",
|
||||||
@@ -235,6 +236,8 @@ def parse_settings():
|
|||||||
"keyshuffle": "none",
|
"keyshuffle": "none",
|
||||||
"bigkeyshuffle": "none",
|
"bigkeyshuffle": "none",
|
||||||
"prizeshuffle": "none",
|
"prizeshuffle": "none",
|
||||||
|
"showloot": "never",
|
||||||
|
"showmap": "map",
|
||||||
"keysanity": False,
|
"keysanity": False,
|
||||||
"door_shuffle": "vanilla",
|
"door_shuffle": "vanilla",
|
||||||
"intensity": 3,
|
"intensity": 3,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from typing import List
|
|||||||
|
|
||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
|
|
||||||
|
|
||||||
def _load_entries():
|
def _load_entries():
|
||||||
entries = []
|
entries = []
|
||||||
with open("data/damage_table.bin", 'rb') as stream:
|
with open("data/damage_table.bin", 'rb') as stream:
|
||||||
|
|||||||
+51
-16
@@ -1,27 +1,62 @@
|
|||||||
import RaceRandom as random
|
|
||||||
from collections import defaultdict, deque
|
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from enum import unique, Flag
|
from collections import defaultdict, deque
|
||||||
from typing import DefaultDict, Dict, List
|
from enum import Flag, unique
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
from typing import DefaultDict, Dict, List
|
||||||
|
|
||||||
from BaseClasses import RegionType, Region, Door, DoorType, Sector, CrystalBarrier, DungeonInfo, dungeon_keys
|
import RaceRandom as random
|
||||||
from BaseClasses import PotFlags, LocationType, Direction, KeyRuleType
|
from BaseClasses import (
|
||||||
|
CrystalBarrier,
|
||||||
|
Direction,
|
||||||
|
Door,
|
||||||
|
DoorType,
|
||||||
|
DungeonInfo,
|
||||||
|
KeyRuleType,
|
||||||
|
LocationType,
|
||||||
|
PotFlags,
|
||||||
|
Region,
|
||||||
|
RegionType,
|
||||||
|
Sector,
|
||||||
|
dungeon_keys,
|
||||||
|
)
|
||||||
from Doors import reset_portals
|
from Doors import reset_portals
|
||||||
from Dungeons import dungeon_regions, region_starts, standard_starts, split_region_starts
|
from DungeonGenerator import (
|
||||||
from Dungeons import dungeon_bigs, dungeon_hints
|
ExplorationState,
|
||||||
|
connect_doors,
|
||||||
|
convert_regions,
|
||||||
|
count_reserved_locations,
|
||||||
|
create_dungeon_builders,
|
||||||
|
default_dungeon_entrances,
|
||||||
|
determine_required_paths,
|
||||||
|
drop_entrances,
|
||||||
|
dungeon_drops,
|
||||||
|
dungeon_portals,
|
||||||
|
simple_dungeon_builder,
|
||||||
|
split_dungeon_builder,
|
||||||
|
valid_region_to_explore,
|
||||||
|
)
|
||||||
|
from Dungeons import (
|
||||||
|
dungeon_bigs,
|
||||||
|
dungeon_hints,
|
||||||
|
dungeon_regions,
|
||||||
|
region_starts,
|
||||||
|
split_region_starts,
|
||||||
|
standard_starts,
|
||||||
|
)
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
|
from KeyDoorShuffle import (
|
||||||
|
DoorRules,
|
||||||
|
analyze_dungeon,
|
||||||
|
build_key_layout,
|
||||||
|
determine_prize_lock,
|
||||||
|
validate_bk_layout,
|
||||||
|
validate_key_layout,
|
||||||
|
)
|
||||||
from RoomData import DoorKind, PairedDoor, reset_rooms
|
from RoomData import DoorKind, PairedDoor, reset_rooms
|
||||||
from source.dungeon.DungeonStitcher import GenerationException, generate_dungeon
|
|
||||||
from source.dungeon.DungeonStitcher import ExplorationState as ExplorationState2
|
from source.dungeon.DungeonStitcher import ExplorationState as ExplorationState2
|
||||||
from DungeonGenerator import ExplorationState, convert_regions, determine_required_paths, drop_entrances
|
from source.dungeon.DungeonStitcher import GenerationException, generate_dungeon
|
||||||
from DungeonGenerator import create_dungeon_builders, split_dungeon_builder, simple_dungeon_builder, default_dungeon_entrances
|
from Utils import kth_combination, ncr
|
||||||
from DungeonGenerator import dungeon_portals, dungeon_drops, connect_doors, count_reserved_locations
|
|
||||||
from DungeonGenerator import valid_region_to_explore
|
|
||||||
from KeyDoorShuffle import analyze_dungeon, build_key_layout, validate_key_layout, determine_prize_lock
|
|
||||||
from KeyDoorShuffle import validate_bk_layout, DoorRules
|
|
||||||
from Utils import ncr, kth_combination
|
|
||||||
|
|
||||||
|
|
||||||
def link_doors(world, player):
|
def link_doors(world, player):
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
from BaseClasses import Door, DoorType, Direction, CrystalBarrier, Portal
|
from BaseClasses import CrystalBarrier, Direction, Door, DoorType, Portal
|
||||||
from RoomData import PairedDoor
|
from RoomData import PairedDoor
|
||||||
|
|
||||||
# constants
|
# constants
|
||||||
|
|||||||
+19
-9
@@ -1,22 +1,32 @@
|
|||||||
import RaceRandom as random
|
|
||||||
import collections
|
import collections
|
||||||
import itertools
|
import itertools
|
||||||
from collections import defaultdict, deque
|
|
||||||
from functools import reduce
|
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
import operator as op
|
import operator as op
|
||||||
import time
|
import time
|
||||||
|
from collections import defaultdict, deque
|
||||||
|
from functools import reduce
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from BaseClasses import DoorType, Direction, CrystalBarrier, RegionType, Polarity, PolSlot, flooded_keys, Sector
|
import RaceRandom as random
|
||||||
from BaseClasses import Hook, hook_from_door, Door
|
from BaseClasses import (
|
||||||
from Regions import location_events, flooded_keys_reverse
|
CrystalBarrier,
|
||||||
|
Direction,
|
||||||
|
Door,
|
||||||
|
DoorType,
|
||||||
|
Hook,
|
||||||
|
Polarity,
|
||||||
|
PolSlot,
|
||||||
|
RegionType,
|
||||||
|
Sector,
|
||||||
|
flooded_keys,
|
||||||
|
hook_from_door,
|
||||||
|
)
|
||||||
from Dungeons import split_region_starts
|
from Dungeons import split_region_starts
|
||||||
|
from Regions import flooded_keys_reverse, location_events
|
||||||
from RoomData import DoorKind
|
from RoomData import DoorKind
|
||||||
|
|
||||||
from source.dungeon.DungeonStitcher import generate_dungeon_find_proposal
|
|
||||||
from source.dungeon.DungeonStitcher import GenerationException as OtherGenException
|
from source.dungeon.DungeonStitcher import GenerationException as OtherGenException
|
||||||
|
from source.dungeon.DungeonStitcher import generate_dungeon_find_proposal
|
||||||
|
|
||||||
|
|
||||||
class GraphPiece:
|
class GraphPiece:
|
||||||
@@ -2330,7 +2340,7 @@ def parallel_full_neutralization(dungeon_map, polarized_sectors, global_pole):
|
|||||||
increment_depth = True
|
increment_depth = True
|
||||||
current_depth = last_depth + 1 if increment_depth else last_depth
|
current_depth = last_depth + 1 if increment_depth else last_depth
|
||||||
finished = all([(x.polarity()+sum_polarity(solution_list[x])).is_neutral() for x in builders])
|
finished = all([(x.polarity()+sum_polarity(solution_list[x])).is_neutral() for x in builders])
|
||||||
logging.getLogger('').info(f'-Balanced solution found in {time.process_time()-start}')
|
logging.getLogger('').debug(f'-Balanced solution found in {time.process_time()-start}')
|
||||||
for builder, sectors in solution_list.items():
|
for builder, sectors in solution_list.items():
|
||||||
for sector in sectors:
|
for sector in sectors:
|
||||||
assign_sector(sector, builder, polarized_sectors, global_pole)
|
assign_sector(sector, builder, polarized_sectors, global_pole)
|
||||||
|
|||||||
@@ -3,19 +3,19 @@ if __name__ == '__main__':
|
|||||||
from source.meta.check_requirements import check_requirements
|
from source.meta.check_requirements import check_requirements
|
||||||
check_requirements(console=True)
|
check_requirements(console=True)
|
||||||
|
|
||||||
import os
|
|
||||||
import logging
|
import logging
|
||||||
import RaceRandom as random
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from source.classes.BabelFish import BabelFish
|
import RaceRandom as random
|
||||||
import source.classes.diags as diagnostics
|
import source.classes.diags as diagnostics
|
||||||
|
from CLI import get_args_priority, parse_cli
|
||||||
from CLI import parse_cli, get_args_priority
|
|
||||||
from Main import main, EnemizerError, __version__
|
|
||||||
from Rom import get_sprite_from_name
|
|
||||||
from Utils import is_bundled, close_console
|
|
||||||
from Fill import FillError
|
from Fill import FillError
|
||||||
|
from Main import EnemizerError, main
|
||||||
|
from Rom import get_sprite_from_name
|
||||||
|
from source.classes.BabelFish import BabelFish
|
||||||
|
from Utils import close_console, is_bundled
|
||||||
|
|
||||||
|
|
||||||
def start():
|
def start():
|
||||||
args = parse_cli(None)
|
args = parse_cli(None)
|
||||||
@@ -80,7 +80,7 @@ def start():
|
|||||||
break
|
break
|
||||||
except (FillError, EnemizerError, Exception, RuntimeError) as err:
|
except (FillError, EnemizerError, Exception, RuntimeError) as err:
|
||||||
failures.append((err, seed))
|
failures.append((err, seed))
|
||||||
logger.warning('%s: %s', fish.translate("cli","cli","generation.failed"), err)
|
logger.exception('Attempt %d - %s: %s', trynum, fish.translate("cli","cli","generation.failed"), err)
|
||||||
logger.info('')
|
logger.info('')
|
||||||
seed = random.randint(0, 999999999)
|
seed = random.randint(0, 999999999)
|
||||||
|
|
||||||
|
|||||||
+14
-2
@@ -13,7 +13,19 @@ def create_dungeons(world, player):
|
|||||||
dungeon.world = world
|
dungeon.world = world
|
||||||
return dungeon
|
return dungeon
|
||||||
|
|
||||||
ES = make_dungeon('Hyrule Castle', 1, None, hyrule_castle_regions, None, [ItemFactory('Small Key (Escape)', player)], [ItemFactory('Map (Escape)', player)])
|
hc_dungeon_items = ['Map (Escape)']
|
||||||
|
at_dungeon_items = []
|
||||||
|
|
||||||
|
if world.showloot[player] == 'compass':
|
||||||
|
if world.dropshuffle[player] == 'underworld' or world.pottery[player] in ['dungeon', 'reduced', 'clustered', 'nonempty', 'lottery']:
|
||||||
|
hc_dungeon_items.append('Compass (Escape)')
|
||||||
|
at_dungeon_items.append('Compass (Agahnims Tower)')
|
||||||
|
elif world.compassshuffle[player] == 'wild':
|
||||||
|
hc_dungeon_items.append('Compass (Escape)')
|
||||||
|
if world.keyshuffle[player] == 'wild':
|
||||||
|
at_dungeon_items.append('Compass (Agahnims Tower)')
|
||||||
|
|
||||||
|
ES = make_dungeon('Hyrule Castle', 1, None, hyrule_castle_regions, None, [ItemFactory('Small Key (Escape)', player)], ItemFactory(hc_dungeon_items, player))
|
||||||
EP = make_dungeon('Eastern Palace', 2, 'Armos Knights', eastern_regions, ItemFactory('Big Key (Eastern Palace)', player), [], ItemFactory(['Map (Eastern Palace)', 'Compass (Eastern Palace)'], player))
|
EP = make_dungeon('Eastern Palace', 2, 'Armos Knights', eastern_regions, ItemFactory('Big Key (Eastern Palace)', player), [], ItemFactory(['Map (Eastern Palace)', 'Compass (Eastern Palace)'], player))
|
||||||
DP = make_dungeon('Desert Palace', 3, 'Lanmolas', desert_regions, ItemFactory('Big Key (Desert Palace)', player), [ItemFactory('Small Key (Desert Palace)', player)], ItemFactory(['Map (Desert Palace)', 'Compass (Desert Palace)'], player))
|
DP = make_dungeon('Desert Palace', 3, 'Lanmolas', desert_regions, ItemFactory('Big Key (Desert Palace)', player), [ItemFactory('Small Key (Desert Palace)', player)], ItemFactory(['Map (Desert Palace)', 'Compass (Desert Palace)'], player))
|
||||||
ToH = make_dungeon('Tower of Hera', 10, 'Moldorm', hera_regions, ItemFactory('Big Key (Tower of Hera)', player), [ItemFactory('Small Key (Tower of Hera)', player)], ItemFactory(['Map (Tower of Hera)', 'Compass (Tower of Hera)'], player))
|
ToH = make_dungeon('Tower of Hera', 10, 'Moldorm', hera_regions, ItemFactory('Big Key (Tower of Hera)', player), [ItemFactory('Small Key (Tower of Hera)', player)], ItemFactory(['Map (Tower of Hera)', 'Compass (Tower of Hera)'], player))
|
||||||
@@ -24,7 +36,7 @@ def create_dungeons(world, player):
|
|||||||
IP = make_dungeon('Ice Palace', 9, 'Kholdstare', ice_regions, ItemFactory('Big Key (Ice Palace)', player), ItemFactory(['Small Key (Ice Palace)'] * 2, player), ItemFactory(['Map (Ice Palace)', 'Compass (Ice Palace)'], player))
|
IP = make_dungeon('Ice Palace', 9, 'Kholdstare', ice_regions, ItemFactory('Big Key (Ice Palace)', player), ItemFactory(['Small Key (Ice Palace)'] * 2, player), ItemFactory(['Map (Ice Palace)', 'Compass (Ice Palace)'], player))
|
||||||
MM = make_dungeon('Misery Mire', 7, 'Vitreous', mire_regions, ItemFactory('Big Key (Misery Mire)', player), ItemFactory(['Small Key (Misery Mire)'] * 3, player), ItemFactory(['Map (Misery Mire)', 'Compass (Misery Mire)'], player))
|
MM = make_dungeon('Misery Mire', 7, 'Vitreous', mire_regions, ItemFactory('Big Key (Misery Mire)', player), ItemFactory(['Small Key (Misery Mire)'] * 3, player), ItemFactory(['Map (Misery Mire)', 'Compass (Misery Mire)'], player))
|
||||||
TR = make_dungeon('Turtle Rock', 12, 'Trinexx', tr_regions, ItemFactory('Big Key (Turtle Rock)', player), ItemFactory(['Small Key (Turtle Rock)'] * 4, player), ItemFactory(['Map (Turtle Rock)', 'Compass (Turtle Rock)'], player))
|
TR = make_dungeon('Turtle Rock', 12, 'Trinexx', tr_regions, ItemFactory('Big Key (Turtle Rock)', player), ItemFactory(['Small Key (Turtle Rock)'] * 4, player), ItemFactory(['Map (Turtle Rock)', 'Compass (Turtle Rock)'], player))
|
||||||
AT = make_dungeon('Agahnims Tower', 4, 'Agahnim', tower_regions, None, ItemFactory(['Small Key (Agahnims Tower)'] * 2, player), [])
|
AT = make_dungeon('Agahnims Tower', 4, 'Agahnim', tower_regions, None, ItemFactory(['Small Key (Agahnims Tower)'] * 2, player), ItemFactory(at_dungeon_items, player))
|
||||||
GT = make_dungeon('Ganons Tower', 13, 'Agahnim2', gt_regions, ItemFactory('Big Key (Ganons Tower)', player), ItemFactory(['Small Key (Ganons Tower)'] * 4, player), ItemFactory(['Map (Ganons Tower)', 'Compass (Ganons Tower)'], player))
|
GT = make_dungeon('Ganons Tower', 13, 'Agahnim2', gt_regions, ItemFactory('Big Key (Ganons Tower)', player), ItemFactory(['Small Key (Ganons Tower)'] * 4, player), ItemFactory(['Map (Ganons Tower)', 'Compass (Ganons Tower)'], player))
|
||||||
|
|
||||||
GT.bosses['bottom'] = BossFactory('Armos Knights', player)
|
GT.bosses['bottom'] = BossFactory('Armos Knights', player)
|
||||||
|
|||||||
+360
-360
@@ -1,361 +1,361 @@
|
|||||||
Hint description:
|
Hint description:
|
||||||
|
|
||||||
Hints will appear in the following ratios across the 15 telepathic tiles that have hints and the five storyteller locations:
|
Hints will appear in the following ratios across the 15 telepathic tiles that have hints and the five storyteller locations:
|
||||||
|
|
||||||
4 hints for inconvenient entrances.
|
4 hints for inconvenient entrances.
|
||||||
4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints).
|
4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints).
|
||||||
3 hints for inconvenient item locations.
|
3 hints for inconvenient item locations.
|
||||||
5 hints for valuable items.
|
5 hints for valuable items.
|
||||||
4 junk hints.
|
4 junk hints.
|
||||||
|
|
||||||
In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following ratios will be used instead:
|
In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following ratios will be used instead:
|
||||||
|
|
||||||
5 hints for inconvenient item locations.
|
5 hints for inconvenient item locations.
|
||||||
8 hints for valuable items.
|
8 hints for valuable items.
|
||||||
7 junk hints.
|
7 junk hints.
|
||||||
|
|
||||||
In the simple, restricted shuffles, these are the ratios:
|
In the simple, restricted shuffles, these are the ratios:
|
||||||
|
|
||||||
2 hints for inconvenient entrances.
|
2 hints for inconvenient entrances.
|
||||||
1 hint for an inconvenient dungeon entrance.
|
1 hint for an inconvenient dungeon entrance.
|
||||||
4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints).
|
4 hints for random entrances (this can by coincidence pick inconvenient entrances that aren't used for the first set of hints).
|
||||||
3 hints for inconvenient item locations.
|
3 hints for inconvenient item locations.
|
||||||
5 hints for valuable items.
|
5 hints for valuable items.
|
||||||
5 junk hints.
|
5 junk hints.
|
||||||
|
|
||||||
These hints will use the following format:
|
These hints will use the following format:
|
||||||
|
|
||||||
Entrance hints go "[Entrance on overworld] leads to [interior]".
|
Entrance hints go "[Entrance on overworld] leads to [interior]".
|
||||||
|
|
||||||
Inconvenient item locations are a little more custom but amount to "[Location] has [item name]". The item name is literal and will specify which dungeon the dungeon specific items hail from (small key/big key/map/compass).
|
Inconvenient item locations are a little more custom but amount to "[Location] has [item name]". The item name is literal and will specify which dungeon the dungeon specific items hail from (small key/big key/map/compass).
|
||||||
|
|
||||||
The valuable items are of the format "[item name] can be found [location]". The item name is again literal, and the location text is taken from Ganon's silver arrow hints. Note that the way it works is that every unique valuable item that exists is considered independently, and you won't get multiple hints for the EXACT same item (so you can only get one hint for Progressive Sword no matter how many swords exist in the seed, but if swords are not progressive, you could get hints for both Master Sword and Tempered Sword). More copies of an item existing does not increase the probability of getting a hint for that particular item (you are equally likely to get a hint for a Progressive Sword as for the Hammer). Unlike the IR, item names are never obfuscated by "something unique", and there is no special bias for hints for GT Big Key or Pegasus Boots.
|
The valuable items are of the format "[item name] can be found [location]". The item name is again literal, and the location text is taken from Ganon's silver arrow hints. Note that the way it works is that every unique valuable item that exists is considered independently, and you won't get multiple hints for the EXACT same item (so you can only get one hint for Progressive Sword no matter how many swords exist in the seed, but if swords are not progressive, you could get hints for both Master Sword and Tempered Sword). More copies of an item existing does not increase the probability of getting a hint for that particular item (you are equally likely to get a hint for a Progressive Sword as for the Hammer). Unlike the IR, item names are never obfuscated by "something unique", and there is no special bias for hints for GT Big Key or Pegasus Boots.
|
||||||
|
|
||||||
Hint Locations:
|
Hint Locations:
|
||||||
|
|
||||||
Eastern Palace room before Big Chest
|
Eastern Palace room before Big Chest
|
||||||
Desert Palace bonk torch room
|
Desert Palace bonk torch room
|
||||||
Tower of Hera entrance room
|
Tower of Hera entrance room
|
||||||
Tower of Hera Big Chest room
|
Tower of Hera Big Chest room
|
||||||
Castle Tower after dark rooms
|
Castle Tower after dark rooms
|
||||||
Palace of Darkness before Bow section
|
Palace of Darkness before Bow section
|
||||||
Swamp Palace entryway
|
Swamp Palace entryway
|
||||||
Thieves' Town upstairs
|
Thieves' Town upstairs
|
||||||
Ice Palace entrance
|
Ice Palace entrance
|
||||||
Ice Palace after first drop
|
Ice Palace after first drop
|
||||||
Ice Palace tall ice floor room
|
Ice Palace tall ice floor room
|
||||||
Misery Mire cutscene room
|
Misery Mire cutscene room
|
||||||
Turtle Rock entrance
|
Turtle Rock entrance
|
||||||
Spectacle Rock cave
|
Spectacle Rock cave
|
||||||
Spiky Hint cave
|
Spiky Hint cave
|
||||||
PoD Bdlg NPC
|
PoD Bdlg NPC
|
||||||
Near PoD Storyteller (bug near bomb wall)
|
Near PoD Storyteller (bug near bomb wall)
|
||||||
Dark Sanctuary Storyteller (long room with tables)
|
Dark Sanctuary Storyteller (long room with tables)
|
||||||
Near Mire Storyteller (feather duster in winding cave)
|
Near Mire Storyteller (feather duster in winding cave)
|
||||||
SE DW Storyteller (owl in winding cave)
|
SE DW Storyteller (owl in winding cave)
|
||||||
|
|
||||||
Inconvenient entrance list:
|
Inconvenient entrance list:
|
||||||
|
|
||||||
Skull Woods Final
|
Skull Woods Final
|
||||||
Ice Palace
|
Ice Palace
|
||||||
Misery Mire
|
Misery Mire
|
||||||
Turtle Rock
|
Turtle Rock
|
||||||
Ganon's Tower
|
Ganon's Tower
|
||||||
Mimic Ledge
|
Mimic Ledge
|
||||||
SW DM Foothills Cave (mirror from upper Bumper ledge)
|
SW DM Foothills Cave (mirror from upper Bumper ledge)
|
||||||
Hammer Pegs (near purple chest)
|
Hammer Pegs (near purple chest)
|
||||||
Super Bomb cracked wall
|
Super Bomb cracked wall
|
||||||
|
|
||||||
Inconvenient location list:
|
Inconvenient location list:
|
||||||
|
|
||||||
Swamp left (two chests)
|
Swamp left (two chests)
|
||||||
Mire left (two chests)
|
Mire left (two chests)
|
||||||
Hera basement
|
Hera basement
|
||||||
Eastern Palace Big Key chest (protected by anti-fairies)
|
Eastern Palace Big Key chest (protected by anti-fairies)
|
||||||
Thieves' Town Big Chest
|
Thieves' Town Big Chest
|
||||||
Ice Palace Big Chest
|
Ice Palace Big Chest
|
||||||
Ganon's Tower Big Chest
|
Ganon's Tower Big Chest
|
||||||
Purple Chest
|
Purple Chest
|
||||||
Spike Cave
|
Spike Cave
|
||||||
Magic Bat
|
Magic Bat
|
||||||
Sahasrahla (Green Pendant)
|
Sahasrahla (Green Pendant)
|
||||||
|
|
||||||
In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following two locations are added to the inconvenient locations list:
|
In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following two locations are added to the inconvenient locations list:
|
||||||
|
|
||||||
Graveyard Cave
|
Graveyard Cave
|
||||||
Mimic Cave
|
Mimic Cave
|
||||||
|
|
||||||
Valuable Items are simply all items that are shown on the pause subscreen (Y, B, or A sections) minus Silver Arrows and plus Triforce Pieces, Magic Upgrades (1/2 or 1/4), and the Single Arrow. If key shuffle is being used, you can additionally get hints for Small Keys or Big Keys but not hints for Maps or Compasses.
|
Valuable Items are simply all items that are shown on the pause subscreen (Y, B, or A sections) minus Silver Arrows and plus Triforce Pieces, Magic Upgrades (1/2 or 1/4), and the Single Arrow. If key shuffle is being used, you can additionally get hints for Small Keys or Big Keys but not hints for Maps or Compasses.
|
||||||
|
|
||||||
While the exact verbage of location names and item names can be found in the source code, here's a copy for reference:
|
While the exact verbage of location names and item names can be found in the source code, here's a copy for reference:
|
||||||
|
|
||||||
Overworld Entrance naming:
|
Overworld Entrance naming:
|
||||||
|
|
||||||
Links House: The hero's old residence
|
Links House: The hero's old residence
|
||||||
Turtle Rock: Turtle Rock Main
|
Turtle Rock: Turtle Rock Main
|
||||||
Misery Mire: Misery Mire
|
Misery Mire: Misery Mire
|
||||||
Ice Palace: Ice Palace
|
Ice Palace: Ice Palace
|
||||||
Skull Woods Final Section: The back of Skull Woods
|
Skull Woods Final Section: The back of Skull Woods
|
||||||
Death Mountain Return Cave (West): The SW DM Foothills Cave
|
Death Mountain Return Cave (West): The SW DM Foothills Cave
|
||||||
Mimic Cave: Mimic Ledge
|
Mimic Cave: Mimic Ledge
|
||||||
Hammer Peg Cave: The rows of pegs
|
Hammer Peg Cave: The rows of pegs
|
||||||
Pyramid Fairy: The crack on the pyramid
|
Pyramid Fairy: The crack on the pyramid
|
||||||
Eastern Palace: Eastern Palace
|
Eastern Palace: Eastern Palace
|
||||||
Elder House (East): Elder House
|
Elder House (East): Elder House
|
||||||
Elder House (West): Elder House
|
Elder House (West): Elder House
|
||||||
Two Brothers House (East): Eastern Quarreling Brothers' house
|
Two Brothers House (East): Eastern Quarreling Brothers' house
|
||||||
Old Man Cave (West): The lower DM entrance
|
Old Man Cave (West): The lower DM entrance
|
||||||
Hyrule Castle Entrance (South): The ground level castle door
|
Hyrule Castle Entrance (South): The ground level castle door
|
||||||
Thieves Town: Thieves' Town
|
Thieves Town: Thieves' Town
|
||||||
Bumper Cave (Bottom): The lower Bumper Cave
|
Bumper Cave (Bottom): The lower Bumper Cave
|
||||||
Swamp Palace: Swamp Palace
|
Swamp Palace: Swamp Palace
|
||||||
Dark Death Mountain Ledge (West): The East dark DM connector ledge
|
Dark Death Mountain Ledge (West): The East dark DM connector ledge
|
||||||
Dark Death Mountain Ledge (East): The East dark DM connector ledge
|
Dark Death Mountain Ledge (East): The East dark DM connector ledge
|
||||||
Superbunny Cave (Top): The summit of dark DM cave
|
Superbunny Cave (Top): The summit of dark DM cave
|
||||||
Superbunny Cave (Bottom): The base of east dark DM
|
Superbunny Cave (Bottom): The base of east dark DM
|
||||||
Hookshot Cave: The rock on dark DM
|
Hookshot Cave: The rock on dark DM
|
||||||
Desert Palace Entrance (South): The book sealed passage
|
Desert Palace Entrance (South): The book sealed passage
|
||||||
Tower of Hera: The Tower of Hera
|
Tower of Hera: The Tower of Hera
|
||||||
Two Brothers House (West): The door near the race game
|
Two Brothers House (West): The door near the race game
|
||||||
Old Man Cave (East): The SW-most cave on west DM
|
Old Man Cave (East): The SW-most cave on west DM
|
||||||
Old Man House (Bottom): A cave with a door on west DM
|
Old Man House (Bottom): A cave with a door on west DM
|
||||||
Old Man House (Top): The eastmost cave on west DM
|
Old Man House (Top): The eastmost cave on west DM
|
||||||
Death Mountain Return Cave (East): The westmost cave on west DM
|
Death Mountain Return Cave (East): The westmost cave on west DM
|
||||||
Spectacle Rock Cave Peak: The highest cave on west DM
|
Spectacle Rock Cave Peak: The highest cave on west DM
|
||||||
Spectacle Rock Cave: The right ledge on west DM
|
Spectacle Rock Cave: The right ledge on west DM
|
||||||
Spectacle Rock Cave (Bottom): The left ledge on west DM
|
Spectacle Rock Cave (Bottom): The left ledge on west DM
|
||||||
Paradox Cave (Bottom): The right paired cave on east DM
|
Paradox Cave (Bottom): The right paired cave on east DM
|
||||||
Paradox Cave (Middle): The southmost cave on east DM
|
Paradox Cave (Middle): The southmost cave on east DM
|
||||||
Paradox Cave (Top): The east DM summit cave
|
Paradox Cave (Top): The east DM summit cave
|
||||||
Fairy Ascension Cave (Bottom): The east DM cave behind rocks
|
Fairy Ascension Cave (Bottom): The east DM cave behind rocks
|
||||||
Fairy Ascension Cave (Top): The central ledge on east DM
|
Fairy Ascension Cave (Top): The central ledge on east DM
|
||||||
Spiral Cave: The left ledge on east DM
|
Spiral Cave: The left ledge on east DM
|
||||||
Spiral Cave (Bottom): The SWmost cave on east DM
|
Spiral Cave (Bottom): The SWmost cave on east DM
|
||||||
Palace of Darkness: Palace of Darkness
|
Palace of Darkness: Palace of Darkness
|
||||||
Hyrule Castle Entrance (West): The left castle door
|
Hyrule Castle Entrance (West): The left castle door
|
||||||
Hyrule Castle Entrance (East): The right castle door
|
Hyrule Castle Entrance (East): The right castle door
|
||||||
Agahnims Tower: The sealed castle door
|
Agahnims Tower: The sealed castle door
|
||||||
Desert Palace Entrance (West): The westmost building in the desert
|
Desert Palace Entrance (West): The westmost building in the desert
|
||||||
Desert Palace Entrance (North): The northmost cave in the desert
|
Desert Palace Entrance (North): The northmost cave in the desert
|
||||||
Blinds Hideout: Blind's old house
|
Blinds Hideout: Blind's old house
|
||||||
Lake Hylia Fairy: A cave NE of Lake Hylia
|
Lake Hylia Fairy: A cave NE of Lake Hylia
|
||||||
Light Hype Fairy: The cave south of your house
|
Light Hype Fairy: The cave south of your house
|
||||||
Desert Fairy: The cave near the desert
|
Desert Fairy: The cave near the desert
|
||||||
Chicken House: The chicken lady's house
|
Chicken House: The chicken lady's house
|
||||||
Tavern North: A backdoor
|
Tavern North: A backdoor
|
||||||
Aginahs Cave: The open desert cave
|
Aginahs Cave: The open desert cave
|
||||||
Sahasrahlas Hut: The house near armos
|
Sahasrahlas Hut: The house near armos
|
||||||
Lake Hylia Shop: The cave NW Lake Hylia
|
Lake Hylia Shop: The cave NW Lake Hylia
|
||||||
Blacksmiths Hut: The old smithery
|
Blacksmiths Hut: The old smithery
|
||||||
Sick Kids House: The central house in Kakariko
|
Sick Kids House: The central house in Kakariko
|
||||||
Lost Woods Gamble: A tree trunk door
|
Lost Woods Gamble: A tree trunk door
|
||||||
Fortune Teller (Light): A building NE of Kakariko
|
Fortune Teller (Light): A building NE of Kakariko
|
||||||
Snitch Lady (East): A house guarded by a snitch
|
Snitch Lady (East): A house guarded by a snitch
|
||||||
Snitch Lady (West): A house guarded by a snitch
|
Snitch Lady (West): A house guarded by a snitch
|
||||||
Bush Covered House: A house with an uncut lawn
|
Bush Covered House: A house with an uncut lawn
|
||||||
Tavern (Front): A building with a backdoor
|
Tavern (Front): A building with a backdoor
|
||||||
Light World Bomb Hut: A Kakariko building with no door
|
Light World Bomb Hut: A Kakariko building with no door
|
||||||
Kakariko Shop: The old Kakariko shop
|
Kakariko Shop: The old Kakariko shop
|
||||||
Mini Moldorm Cave: The cave south of Lake Hylia
|
Mini Moldorm Cave: The cave south of Lake Hylia
|
||||||
Long Fairy Cave: The eastmost portal cave
|
Long Fairy Cave: The eastmost portal cave
|
||||||
Good Bee Cave: The open cave SE Lake Hylia
|
Good Bee Cave: The open cave SE Lake Hylia
|
||||||
20 Rupee Cave: The rock SE Lake Hylia
|
20 Rupee Cave: The rock SE Lake Hylia
|
||||||
50 Rupee Cave: The rock near the desert
|
50 Rupee Cave: The rock near the desert
|
||||||
Ice Rod Cave: The sealed cave SE Lake Hylia
|
Ice Rod Cave: The sealed cave SE Lake Hylia
|
||||||
Library: The old library
|
Library: The old library
|
||||||
Potion Shop: The witch's building
|
Potion Shop: The witch's building
|
||||||
Dam: The old dam
|
Dam: The old dam
|
||||||
Lumberjack House: The lumberjack house
|
Lumberjack House: The lumberjack house
|
||||||
Lake Hylia Fortune Teller: The building NW Lake Hylia
|
Lake Hylia Fortune Teller: The building NW Lake Hylia
|
||||||
Kakariko Gamble Game: The old Kakariko gambling den
|
Kakariko Gamble Game: The old Kakariko gambling den
|
||||||
Waterfall of Wishing: Going behind the waterfall
|
Waterfall of Wishing: Going behind the waterfall
|
||||||
Capacity Upgrade: The cave on the island
|
Capacity Upgrade: The cave on the island
|
||||||
Bonk Rock Cave: The rock pile near Sanctuary
|
Bonk Rock Cave: The rock pile near Sanctuary
|
||||||
Graveyard Cave: The graveyard ledge
|
Graveyard Cave: The graveyard ledge
|
||||||
Checkerboard Cave: The NE desert ledge
|
Checkerboard Cave: The NE desert ledge
|
||||||
Cave 45: The ledge south of haunted grove
|
Cave 45: The ledge south of haunted grove
|
||||||
Kings Grave: The northeastmost grave
|
Kings Grave: The northeastmost grave
|
||||||
Bonk Fairy (Light): The rock pile near your home
|
Bonk Fairy (Light): The rock pile near your home
|
||||||
Hookshot Fairy: A cave on east DM
|
Hookshot Fairy: A cave on east DM
|
||||||
Bonk Fairy (Dark): The rock pile near the old bomb shop
|
Bonk Fairy (Dark): The rock pile near the old bomb shop
|
||||||
Dark Sanctuary Hint: The dark sanctuary cave
|
Dark Sanctuary Hint: The dark sanctuary cave
|
||||||
Dark Lake Hylia Fairy: The cave NE dark Lake Hylia
|
Dark Lake Hylia Fairy: The cave NE dark Lake Hylia
|
||||||
C-Shaped House: The NE house in Village of Outcasts
|
C-Shaped House: The NE house in Village of Outcasts
|
||||||
Big Bomb Shop: The old bomb shop
|
Big Bomb Shop: The old bomb shop
|
||||||
Dark Death Mountain Fairy: The SW cave on dark DM
|
Dark Death Mountain Fairy: The SW cave on dark DM
|
||||||
Dark Lake Hylia Shop: The building NW dark Lake Hylia
|
Dark Lake Hylia Shop: The building NW dark Lake Hylia
|
||||||
Dark World Shop: The hammer sealed building
|
Dark World Shop: The hammer sealed building
|
||||||
Red Shield Shop: The fenced in building
|
Red Shield Shop: The fenced in building
|
||||||
Mire Shed: The western hut in the mire
|
Mire Shed: The western hut in the mire
|
||||||
East Dark World Hint: The dark cave near the eastmost portal
|
East Dark World Hint: The dark cave near the eastmost portal
|
||||||
Mire Hint: The cave east of the mire
|
Mire Hint: The cave east of the mire
|
||||||
Spike Cave: The ledge cave on west dark DM
|
Spike Cave: The ledge cave on west dark DM
|
||||||
Palace of Darkness Hint: The building south of Kiki
|
Palace of Darkness Hint: The building south of Kiki
|
||||||
Dark Lake Hylia Ledge Spike Cave: The rock SE dark Lake Hylia
|
Dark Lake Hylia Ledge Spike Cave: The rock SE dark Lake Hylia
|
||||||
Dark Death Mountain Shop: The base of east dark DM
|
Dark Death Mountain Shop: The base of east dark DM
|
||||||
Dark Potion Shop: The building near the catfish
|
Dark Potion Shop: The building near the catfish
|
||||||
Archery Game: The old archery game
|
Archery Game: The old archery game
|
||||||
Dark Lumberjack Shop: The northmost Dark World building
|
Dark Lumberjack Shop: The northmost Dark World building
|
||||||
Hype Cave: The cave south of the old bomb shop
|
Hype Cave: The cave south of the old bomb shop
|
||||||
Brewery: The Village of Outcasts building with no door
|
Brewery: The Village of Outcasts building with no door
|
||||||
Dark Lake Hylia Ledge Hint: The open cave SE dark Lake Hylia
|
Dark Lake Hylia Ledge Hint: The open cave SE dark Lake Hylia
|
||||||
Chest Game: The westmost building in the Village of Outcasts
|
Chest Game: The westmost building in the Village of Outcasts
|
||||||
Mire Fairy: The eastern hut in the mire
|
Mire Fairy: The eastern hut in the mire
|
||||||
Dark Lake Hylia Ledge Fairy: The sealed cave SE dark Lake Hylia
|
Dark Lake Hylia Ledge Fairy: The sealed cave SE dark Lake Hylia
|
||||||
Fortune Teller (Dark): The building NE the Village of Outcasts
|
Fortune Teller (Dark): The building NE the Village of Outcasts
|
||||||
Sanctuary: Sanctuary
|
Sanctuary: Sanctuary
|
||||||
Lumberjack Tree Cave: The cave Behind Lumberjacks
|
Lumberjack Tree Cave: The cave Behind Lumberjacks
|
||||||
Lost Woods Hideout Stump: The stump in Lost Woods
|
Lost Woods Hideout Stump: The stump in Lost Woods
|
||||||
North Fairy Cave: The cave East of Graveyard
|
North Fairy Cave: The cave East of Graveyard
|
||||||
Bat Cave Cave: The cave in eastern Kakariko
|
Bat Cave Cave: The cave in eastern Kakariko
|
||||||
Kakariko Well Cave: The cave in northern Kakariko
|
Kakariko Well Cave: The cave in northern Kakariko
|
||||||
Hyrule Castle Secret Entrance Stairs: The tunnel near the castle
|
Hyrule Castle Secret Entrance Stairs: The tunnel near the castle
|
||||||
Skull Woods First Section Door: The southeastmost skull
|
Skull Woods First Section Door: The southeastmost skull
|
||||||
Skull Woods Second Section Door (East): The central open skull
|
Skull Woods Second Section Door (East): The central open skull
|
||||||
Skull Woods Second Section Door (West): The westmost open skull
|
Skull Woods Second Section Door (West): The westmost open skull
|
||||||
Desert Palace Entrance (East): The eastern building in the desert
|
Desert Palace Entrance (East): The eastern building in the desert
|
||||||
Turtle Rock Isolated Ledge Entrance: The isolated ledge on east dark DM
|
Turtle Rock Isolated Ledge Entrance: The isolated ledge on east dark DM
|
||||||
Bumper Cave (Top): The upper Bumper Cave
|
Bumper Cave (Top): The upper Bumper Cave
|
||||||
Hookshot Cave Back Entrance: The stairs on the floating island
|
Hookshot Cave Back Entrance: The stairs on the floating island
|
||||||
|
|
||||||
Destination Entrance Naming:
|
Destination Entrance Naming:
|
||||||
|
|
||||||
Hyrule Castle: Hyrule Castle (all three entrances)
|
Hyrule Castle: Hyrule Castle (all three entrances)
|
||||||
Eastern Palace: Eastern Palace
|
Eastern Palace: Eastern Palace
|
||||||
Desert Palace: Desert Palace (all four entrances, including final)
|
Desert Palace: Desert Palace (all four entrances, including final)
|
||||||
Tower of Hera: Tower of Hera
|
Tower of Hera: Tower of Hera
|
||||||
Palace of Darkness: Palace of Darkness
|
Palace of Darkness: Palace of Darkness
|
||||||
Swamp Palace: Swamp Palace
|
Swamp Palace: Swamp Palace
|
||||||
Skull Woods: Skull Woods (any entrance including final)
|
Skull Woods: Skull Woods (any entrance including final)
|
||||||
Thieves' Town: Thieves' Town
|
Thieves' Town: Thieves' Town
|
||||||
Ice Palace: Ice Palace
|
Ice Palace: Ice Palace
|
||||||
Misery Mire: Misery Mire
|
Misery Mire: Misery Mire
|
||||||
Turtle Rock: Turtle Rock (all four entrances)
|
Turtle Rock: Turtle Rock (all four entrances)
|
||||||
Ganon's Tower: Ganon's Tower
|
Ganon's Tower: Ganon's Tower
|
||||||
Castle Tower: Agahnim's Tower
|
Castle Tower: Agahnim's Tower
|
||||||
A connector: Paradox Cave, Spectacle Rock Cave, Hookshot Cave, Superbunny Cave, Spiral Cave, Old Man Fetch Cave, Old Man House, Elder House, Quarreling Brothers' House, Bumper Cave, DM Fairy Ascent Cave, DM Exit Cave
|
A connector: Paradox Cave, Spectacle Rock Cave, Hookshot Cave, Superbunny Cave, Spiral Cave, Old Man Fetch Cave, Old Man House, Elder House, Quarreling Brothers' House, Bumper Cave, DM Fairy Ascent Cave, DM Exit Cave
|
||||||
A bounty of five items: Mini-moldorm cave, Hype Cave, Blind's Hideout
|
A bounty of five items: Mini-moldorm cave, Hype Cave, Blind's Hideout
|
||||||
Sahasrahla: Sahasrahla
|
Sahasrahla: Sahasrahla
|
||||||
A cave with two items: Mire hut, Waterfall Fairy, Pyramid Fairy
|
A cave with two items: Mire hut, Waterfall Fairy, Pyramid Fairy
|
||||||
A fairy fountain: Any healer fairy cave, either bonk cave with four fairies, the "long fairy" cave
|
A fairy fountain: Any healer fairy cave, either bonk cave with four fairies, the "long fairy" cave
|
||||||
A common shop: Any shop that sells bombs by default
|
A common shop: Any shop that sells bombs by default
|
||||||
The rare shop: The shop that sells the Red Shield by default
|
The rare shop: The shop that sells the Red Shield by default
|
||||||
The potion shop: Potion Shop
|
The potion shop: Potion Shop
|
||||||
The bomb shop: Bomb Shop
|
The bomb shop: Bomb Shop
|
||||||
A fortune teller: Any of the three fortune tellers
|
A fortune teller: Any of the three fortune tellers
|
||||||
A house with a chest: Chicken Lady's house, C-House, Brewery
|
A house with a chest: Chicken Lady's house, C-House, Brewery
|
||||||
A cave with an item: Checkerboard cave, Hammer Pegs cave, Cave 45, Graveyard Ledge cave
|
A cave with an item: Checkerboard cave, Hammer Pegs cave, Cave 45, Graveyard Ledge cave
|
||||||
A cave with a chest: Sanc Bonk Rock Cave, Cape Grave Cave, Ice Rod Cave, Aginah's Cave
|
A cave with a chest: Sanc Bonk Rock Cave, Cape Grave Cave, Ice Rod Cave, Aginah's Cave
|
||||||
The dam: Watergate
|
The dam: Watergate
|
||||||
The sick kid: Sick Kid
|
The sick kid: Sick Kid
|
||||||
The library: Library
|
The library: Library
|
||||||
Mimic Cave: Mimic Cave
|
Mimic Cave: Mimic Cave
|
||||||
Spike Cave: Spike Cave
|
Spike Cave: Spike Cave
|
||||||
A game of 16 chests: VoO chest game (for the item)
|
A game of 16 chests: VoO chest game (for the item)
|
||||||
A storyteller: The four DW NPCs who charge 20 rupees for a hint as well as the PoD Bdlg guy who gives a free hint
|
A storyteller: The four DW NPCs who charge 20 rupees for a hint as well as the PoD Bdlg guy who gives a free hint
|
||||||
A cave with some cash: 20 rupee cave, 50 rupee cave (both have thieves and some pots)
|
A cave with some cash: 20 rupee cave, 50 rupee cave (both have thieves and some pots)
|
||||||
A game of chance: Gambling game (just for cash, no items)
|
A game of chance: Gambling game (just for cash, no items)
|
||||||
A game of skill: Archery minigame
|
A game of skill: Archery minigame
|
||||||
The queen of fairies: Capacity Upgrade Fairy
|
The queen of fairies: Capacity Upgrade Fairy
|
||||||
A drop's exit: Sanctuary, LW Thieves' Hideout, Kakariko Well, Magic Bat, Useless Fairy, Uncle Tunnel, Ganon drop exit
|
A drop's exit: Sanctuary, LW Thieves' Hideout, Kakariko Well, Magic Bat, Useless Fairy, Uncle Tunnel, Ganon drop exit
|
||||||
A restock room: The Kakariko bomb/arrow restock room
|
A restock room: The Kakariko bomb/arrow restock room
|
||||||
The tavern: The Kakariko tavern
|
The tavern: The Kakariko tavern
|
||||||
The grass man: The Kakariko man with many beds
|
The grass man: The Kakariko man with many beds
|
||||||
A cold bee: The "wrong side" of Ice Rod cave where you can get a Good Bee
|
A cold bee: The "wrong side" of Ice Rod cave where you can get a Good Bee
|
||||||
Fairies deep in a cave: Hookshot Fairy
|
Fairies deep in a cave: Hookshot Fairy
|
||||||
|
|
||||||
Location naming reference:
|
Location naming reference:
|
||||||
|
|
||||||
Mushroom: in the woods
|
Mushroom: in the woods
|
||||||
Master Sword Pedestal: at the pedestal
|
Master Sword Pedestal: at the pedestal
|
||||||
Bottle Merchant: with a merchant
|
Bottle Merchant: with a merchant
|
||||||
Stumpy: with tree boy
|
Stumpy: with tree boy
|
||||||
Flute Spot: underground
|
Flute Spot: underground
|
||||||
Digging Game: underground
|
Digging Game: underground
|
||||||
Lake Hylia Island: on an island
|
Lake Hylia Island: on an island
|
||||||
Floating Island: on an island
|
Floating Island: on an island
|
||||||
Bumper Cave Ledge: on a ledge
|
Bumper Cave Ledge: on a ledge
|
||||||
Spectacle Rock: atop a rock
|
Spectacle Rock: atop a rock
|
||||||
Maze Race: at the race
|
Maze Race: at the race
|
||||||
Desert Ledge: in the desert
|
Desert Ledge: in the desert
|
||||||
Pyramid: on the pyramid
|
Pyramid: on the pyramid
|
||||||
Catfish: with a catfish
|
Catfish: with a catfish
|
||||||
Ether Tablet: at a monument
|
Ether Tablet: at a monument
|
||||||
Bombos Tablet: at a monument
|
Bombos Tablet: at a monument
|
||||||
Hobo: with the hobo
|
Hobo: with the hobo
|
||||||
Zora's Ledge: near Zora
|
Zora's Ledge: near Zora
|
||||||
King Zora: at a high price
|
King Zora: at a high price
|
||||||
Sunken Treasure: underwater
|
Sunken Treasure: underwater
|
||||||
Floodgate Chest: in the dam
|
Floodgate Chest: in the dam
|
||||||
Blacksmith: with the smith
|
Blacksmith: with the smith
|
||||||
Purple Chest: from a box
|
Purple Chest: from a box
|
||||||
Old Man: with the old man
|
Old Man: with the old man
|
||||||
Link's Uncle: with your uncle
|
Link's Uncle: with your uncle
|
||||||
Secret Passage: near your uncle
|
Secret Passage: near your uncle
|
||||||
Kakariko Well (5 items): in a well
|
Kakariko Well (5 items): in a well
|
||||||
Lost Woods Hideout: near a thief
|
Lost Woods Hideout: near a thief
|
||||||
Lumberjack Tree: in a hole
|
Lumberjack Tree: in a hole
|
||||||
Magic Bat: with the bat
|
Magic Bat: with the bat
|
||||||
Paradox Cave (7 items): in a cave with seven chests
|
Paradox Cave (7 items): in a cave with seven chests
|
||||||
Blind's Hideout (5 items): in a basement
|
Blind's Hideout (5 items): in a basement
|
||||||
Mini Moldorm Cave (5 items): near Moldorms
|
Mini Moldorm Cave (5 items): near Moldorms
|
||||||
Hype Cave (4 back chests): near a bat-like man
|
Hype Cave (4 back chests): near a bat-like man
|
||||||
Hype Cave - Generous Guy: with a bat-like man
|
Hype Cave - Generous Guy: with a bat-like man
|
||||||
Hookshot Cave (4 items): across pits
|
Hookshot Cave (4 items): across pits
|
||||||
Sahasrahla's Hut (chests in back): near the elder
|
Sahasrahla's Hut (chests in back): near the elder
|
||||||
Sahasrahla: with the elder
|
Sahasrahla: with the elder
|
||||||
Waterfall Fairy (2 items): near a fairy
|
Waterfall Fairy (2 items): near a fairy
|
||||||
Pyramid Fairy (2 items): near a fairy
|
Pyramid Fairy (2 items): near a fairy
|
||||||
Mire Shed (2 items): near sparks
|
Mire Shed (2 items): near sparks
|
||||||
Superbunny Cave (2 items): in a connection
|
Superbunny Cave (2 items): in a connection
|
||||||
Spiral Cave: in spiral cave
|
Spiral Cave: in spiral cave
|
||||||
Kakariko Tavern: in the bar
|
Kakariko Tavern: in the bar
|
||||||
Link's House: in your home
|
Link's House: in your home
|
||||||
Sick Kid: with the sick
|
Sick Kid: with the sick
|
||||||
Library: near books
|
Library: near books
|
||||||
Potion Shop: near potions
|
Potion Shop: near potions
|
||||||
Spike Cave: beyond spikes
|
Spike Cave: beyond spikes
|
||||||
Mimic Cave: in a cave of mimicry
|
Mimic Cave: in a cave of mimicry
|
||||||
Chest Game: as a game reward
|
Chest Game: as a game reward
|
||||||
Chicken House: near poultry
|
Chicken House: near poultry
|
||||||
Aginah's Cave: with Aginah
|
Aginah's Cave: with Aginah
|
||||||
Ice Rod Cave: in a frozen cave
|
Ice Rod Cave: in a frozen cave
|
||||||
Brewery: alone in a home
|
Brewery: alone in a home
|
||||||
C-Shaped House: alone in a home
|
C-Shaped House: alone in a home
|
||||||
Spectacle Rock Cave: alone in a cave
|
Spectacle Rock Cave: alone in a cave
|
||||||
King's Tomb: alone in a cave
|
King's Tomb: alone in a cave
|
||||||
Cave 45: alone in a cave
|
Cave 45: alone in a cave
|
||||||
Graveyard Cave: alone in a cave
|
Graveyard Cave: alone in a cave
|
||||||
Checkerboard Cave: alone in a cave
|
Checkerboard Cave: alone in a cave
|
||||||
Bonk Rock Cave: alone in a cave
|
Bonk Rock Cave: alone in a cave
|
||||||
Peg Cave: alone in a cave
|
Peg Cave: alone in a cave
|
||||||
Sanctuary: in Sanctuary
|
Sanctuary: in Sanctuary
|
||||||
Hyrule Castle - Boomerang Chest: in Hyrule Castle
|
Hyrule Castle - Boomerang Chest: in Hyrule Castle
|
||||||
Hyrule Castle - Map Chest: in Hyrule Castle
|
Hyrule Castle - Map Chest: in Hyrule Castle
|
||||||
Hyrule Castle - Zelda's Chest: in Hyrule Castle
|
Hyrule Castle - Zelda's Chest: in Hyrule Castle
|
||||||
Sewers - Dark Cross: in the sewers
|
Sewers - Dark Cross: in the sewers
|
||||||
Sewers - Secret Room (3 items): in the sewers
|
Sewers - Secret Room (3 items): in the sewers
|
||||||
Eastern Palace - Boss: with the Armos
|
Eastern Palace - Boss: with the Armos
|
||||||
Eastern Palace (otherwise, 5 items): in Eastern Palace
|
Eastern Palace (otherwise, 5 items): in Eastern Palace
|
||||||
Desert Palace - Boss: with Lanmolas
|
Desert Palace - Boss: with Lanmolas
|
||||||
Desert Palace (otherwise, 5 items): in Desert Palace
|
Desert Palace (otherwise, 5 items): in Desert Palace
|
||||||
Tower of Hera - Boss: with Moldorm
|
Tower of Hera - Boss: with Moldorm
|
||||||
Tower of Hera (otherwise, 5 items): in Tower of Hera
|
Tower of Hera (otherwise, 5 items): in Tower of Hera
|
||||||
Castle Tower (2 items): in Castle Tower
|
Castle Tower (2 items): in Castle Tower
|
||||||
Palace of Darkness - Boss: with Helmasaur King
|
Palace of Darkness - Boss: with Helmasaur King
|
||||||
Palace of Darkness (otherwise, 13 items): in Palace of Darkness
|
Palace of Darkness (otherwise, 13 items): in Palace of Darkness
|
||||||
Swamp Palace - Boss: with Arrghus
|
Swamp Palace - Boss: with Arrghus
|
||||||
Swamp Palace (otherwise, 9 items): in Swamp Palace
|
Swamp Palace (otherwise, 9 items): in Swamp Palace
|
||||||
Skull Woods - Bridge Room: near Mothula
|
Skull Woods - Bridge Room: near Mothula
|
||||||
Skull Woods - Boss: with Mothula
|
Skull Woods - Boss: with Mothula
|
||||||
Skull Woods (otherwise, 6 items): in Skull Woods
|
Skull Woods (otherwise, 6 items): in Skull Woods
|
||||||
Thieves' Town - Boss: with Blind
|
Thieves' Town - Boss: with Blind
|
||||||
Thieves' Town (otherwise, 7 items): in Thieves' Town
|
Thieves' Town (otherwise, 7 items): in Thieves' Town
|
||||||
Ice Palace - Boss: with Kholdstare
|
Ice Palace - Boss: with Kholdstare
|
||||||
Ice Palace (otherwise, 7 items): in Ice Palace
|
Ice Palace (otherwise, 7 items): in Ice Palace
|
||||||
Misery Mire - Boss: with Vitreous
|
Misery Mire - Boss: with Vitreous
|
||||||
Misery Mire (otherwise, 7 items): in Misery Mire
|
Misery Mire (otherwise, 7 items): in Misery Mire
|
||||||
Turtle Rock - Boss: with Trinexx
|
Turtle Rock - Boss: with Trinexx
|
||||||
Turtle Rock (otherwise, 11 items): in Turtle Rock
|
Turtle Rock (otherwise, 11 items): in Turtle Rock
|
||||||
Ganons Tower (after climb, 4 items): atop Ganon's Tower
|
Ganons Tower (after climb, 4 items): atop Ganon's Tower
|
||||||
Ganon's Tower (otherwise, 23 items): in Ganon's Tower
|
Ganon's Tower (otherwise, 23 items): in Ganon's Tower
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import RaceRandom as random
|
|
||||||
import collections
|
import collections
|
||||||
import itertools
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
@@ -6,11 +5,18 @@ import math
|
|||||||
from collections import Counter
|
from collections import Counter
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
|
|
||||||
|
import RaceRandom as random
|
||||||
from BaseClasses import CollectionState, FillError, LocationType
|
from BaseClasses import CollectionState, FillError, LocationType
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
from Regions import shop_to_location_table, retro_shops
|
from Regions import retro_shops, shop_to_location_table
|
||||||
from source.item.FillUtil import filter_locations, classify_major_items, replace_trash_item, vanilla_fallback
|
from source.item.FillUtil import (
|
||||||
from source.item.FillUtil import filter_special_locations, valid_pot_items
|
classify_major_items,
|
||||||
|
filter_locations,
|
||||||
|
filter_special_locations,
|
||||||
|
replace_trash_item,
|
||||||
|
valid_pot_items,
|
||||||
|
vanilla_fallback,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_dungeon_item_pool(world):
|
def get_dungeon_item_pool(world):
|
||||||
@@ -793,7 +799,7 @@ def sell_potions(world, player):
|
|||||||
if shop.region.name in shop_to_location_table and shop.region.name != 'Capacity Upgrade':
|
if shop.region.name in shop_to_location_table and shop.region.name != 'Capacity Upgrade':
|
||||||
loc_choices += [world.get_location(loc, player) for loc in shop_to_location_table[shop.region.name]]
|
loc_choices += [world.get_location(loc, player) for loc in shop_to_location_table[shop.region.name]]
|
||||||
locations = [loc for loc in loc_choices if not loc.item]
|
locations = [loc for loc in loc_choices if not loc.item]
|
||||||
for potion in ['Green Potion', 'Blue Potion', 'Red Potion']:
|
for potion in ['Green Potion', 'Blue Potion', 'Red Potion', 'Bee']:
|
||||||
location = random.choice(filter_locations(ItemFactory(potion, player), locations, world, potion=True))
|
location = random.choice(filter_locations(ItemFactory(potion, player), locations, world, potion=True))
|
||||||
locations.remove(location)
|
locations.remove(location)
|
||||||
p_item = next((item for item in world.itempool if item.name == potion and item.player == player), None)
|
p_item = next((item for item in world.itempool if item.name == potion and item.player == player), None)
|
||||||
@@ -1287,4 +1293,4 @@ def set_prize_drops(world, player):
|
|||||||
# saved fish prize
|
# saved fish prize
|
||||||
world.prizes[player]['fish'] = prizes.pop()
|
world.prizes[player]['fish'] = prizes.pop()
|
||||||
|
|
||||||
world.prizes[player]['enemies'] = prizes
|
world.prizes[player]['enemies'] = prizes
|
||||||
|
|||||||
@@ -5,36 +5,47 @@ if __name__ == '__main__':
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from tkinter import Tk, Button, BOTTOM, TOP, StringVar, BooleanVar, X, BOTH, RIGHT, ttk, messagebox
|
from tkinter import (
|
||||||
|
BOTH,
|
||||||
|
BOTTOM,
|
||||||
|
RIGHT,
|
||||||
|
TOP,
|
||||||
|
BooleanVar,
|
||||||
|
Button,
|
||||||
|
StringVar,
|
||||||
|
Tk,
|
||||||
|
X,
|
||||||
|
messagebox,
|
||||||
|
ttk,
|
||||||
|
)
|
||||||
|
|
||||||
from CLI import get_args_priority
|
from CLI import get_args_priority
|
||||||
from DungeonRandomizer import parse_cli
|
from DungeonRandomizer import parse_cli
|
||||||
|
from GuiUtils import set_icon
|
||||||
|
from source.classes.BabelFish import BabelFish
|
||||||
|
from source.classes.Empty import Empty
|
||||||
from source.gui.adjust.overview import adjust_page
|
from source.gui.adjust.overview import adjust_page
|
||||||
from source.gui.startinventory.overview import startinventory_page
|
from source.gui.bottom import bottom_frame, create_guiargs
|
||||||
from source.gui.custom.overview import custom_page
|
from source.gui.custom.overview import custom_page
|
||||||
from source.gui.loadcliargs import loadcliargs, loadadjustargs
|
from source.gui.loadcliargs import loadadjustargs, loadcliargs
|
||||||
from source.gui.randomize.item import item_page
|
|
||||||
from source.gui.randomize.overworld import overworld_page
|
|
||||||
from source.gui.randomize.entrando import entrando_page
|
|
||||||
from source.gui.randomize.enemizer import enemizer_page
|
|
||||||
from source.gui.randomize.dungeon import dungeon_page
|
from source.gui.randomize.dungeon import dungeon_page
|
||||||
|
from source.gui.randomize.enemizer import enemizer_page
|
||||||
|
from source.gui.randomize.entrando import entrando_page
|
||||||
|
|
||||||
#from source.gui.randomize.multiworld import multiworld_page
|
#from source.gui.randomize.multiworld import multiworld_page
|
||||||
from source.gui.randomize.gameoptions import gameoptions_page
|
from source.gui.randomize.gameoptions import gameoptions_page
|
||||||
from source.gui.randomize.generation import generation_page
|
from source.gui.randomize.generation import generation_page
|
||||||
from source.gui.bottom import bottom_frame, create_guiargs
|
from source.gui.randomize.item import item_page
|
||||||
from GuiUtils import set_icon
|
from source.gui.randomize.overworld import overworld_page
|
||||||
from Main import __version__ as ESVersion
|
from source.gui.startinventory.overview import startinventory_page
|
||||||
from OverworldShuffle import __version__ as ORVersion
|
from Versions import DRVersion, GKVersion, ORVersion
|
||||||
|
|
||||||
from source.classes.BabelFish import BabelFish
|
|
||||||
from source.classes.Empty import Empty
|
|
||||||
|
|
||||||
|
|
||||||
def check_python_version(fish):
|
def check_python_version(fish):
|
||||||
import sys
|
import sys
|
||||||
version = sys.version_info
|
version = sys.version_info
|
||||||
if version.major < 3 or version.minor < 7:
|
if version.major < 3 or version.minor < 7:
|
||||||
messagebox.showinfo("Overworld Shuffle %s (DR %s)" % (ORVersion, ESVersion), fish.translate("cli","cli","old.python.version") % sys.version)
|
messagebox.showinfo("GwaaKiwi Randomizer %s (OR %s, DR %s)" % (GKVersion, ORVersion, DRVersion), fish.translate("cli","cli","old.python.version") % sys.version)
|
||||||
|
|
||||||
|
|
||||||
# Save settings to file
|
# Save settings to file
|
||||||
@@ -83,7 +94,7 @@ def guiMain(args=None):
|
|||||||
mainWindow = Tk()
|
mainWindow = Tk()
|
||||||
self = mainWindow
|
self = mainWindow
|
||||||
|
|
||||||
mainWindow.wm_title("Overworld Shuffle %s (DR %s)" % (ORVersion, ESVersion))
|
mainWindow.wm_title("GwaaKiwi Randomizer %s (OR %s, DR %s)" % (GKVersion, ORVersion, DRVersion))
|
||||||
mainWindow.protocol("WM_DELETE_WINDOW", guiExit) # intercept when user clicks the X
|
mainWindow.protocol("WM_DELETE_WINDOW", guiExit) # intercept when user clicks the X
|
||||||
|
|
||||||
# set program icon
|
# set program icon
|
||||||
|
|||||||
+2
-1
@@ -1,10 +1,11 @@
|
|||||||
import queue
|
|
||||||
import os
|
import os
|
||||||
|
import queue
|
||||||
import threading
|
import threading
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
|
|
||||||
from Utils import local_path
|
from Utils import local_path
|
||||||
|
|
||||||
|
|
||||||
def set_icon(window):
|
def set_icon(window):
|
||||||
er16 = tk.PhotoImage(file=local_path(os.path.join("data","ER16.gif")))
|
er16 = tk.PhotoImage(file=local_path(os.path.join("data","ER16.gif")))
|
||||||
er32 = tk.PhotoImage(file=local_path(os.path.join("data","ER32.gif")))
|
er32 = tk.PhotoImage(file=local_path(os.path.join("data","ER32.gif")))
|
||||||
|
|||||||
+41
-21
@@ -1,21 +1,39 @@
|
|||||||
from collections import namedtuple, defaultdict
|
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
|
from collections import defaultdict, namedtuple
|
||||||
|
|
||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
|
|
||||||
from BaseClasses import LocationType, Region, RegionType, Shop, ShopType, Location, CollectionState, PotItem
|
|
||||||
from Regions import location_events, shop_to_location_table, retro_shops, shop_table_by_location, valid_pot_location
|
|
||||||
from Fill import FillError, fill_restrictive, get_dungeon_item_pool, track_dungeon_items, track_outside_keys
|
|
||||||
from PotShuffle import vanilla_pots
|
|
||||||
from Tables import bonk_prize_lookup
|
|
||||||
from Items import ItemFactory
|
|
||||||
|
|
||||||
from source.dungeon.EnemyList import add_drop_contents
|
|
||||||
from source.overworld.EntranceShuffle2 import exit_ids, door_addresses
|
|
||||||
from source.item.FillUtil import trash_items, pot_items
|
|
||||||
|
|
||||||
import source.classes.constants as CONST
|
import source.classes.constants as CONST
|
||||||
|
from BaseClasses import (
|
||||||
|
CollectionState,
|
||||||
|
Location,
|
||||||
|
LocationType,
|
||||||
|
PotItem,
|
||||||
|
Region,
|
||||||
|
RegionType,
|
||||||
|
Shop,
|
||||||
|
ShopType,
|
||||||
|
)
|
||||||
|
from Fill import (
|
||||||
|
FillError,
|
||||||
|
fill_restrictive,
|
||||||
|
get_dungeon_item_pool,
|
||||||
|
track_dungeon_items,
|
||||||
|
track_outside_keys,
|
||||||
|
)
|
||||||
|
from Items import ItemFactory
|
||||||
|
from PotShuffle import vanilla_pots
|
||||||
|
from Regions import (
|
||||||
|
location_events,
|
||||||
|
retro_shops,
|
||||||
|
shop_table_by_location,
|
||||||
|
shop_to_location_table,
|
||||||
|
valid_pot_location,
|
||||||
|
)
|
||||||
|
from source.dungeon.EnemyList import add_drop_contents
|
||||||
|
from source.item.FillUtil import pot_items, trash_items
|
||||||
|
from source.overworld.EntranceShuffle2 import door_addresses, exit_ids
|
||||||
|
from Tables import bonk_prize_lookup
|
||||||
|
|
||||||
#This file sets the item pools for various modes. Timed modes and triforce hunt are enforced first, and then extra items are specified per mode to fill in the remaining space.
|
#This file sets the item pools for various modes. Timed modes and triforce hunt are enforced first, and then extra items are specified per mode to fill in the remaining space.
|
||||||
#Some basic items that various modes require are placed here, including pendants and crystals. Medallion requirements for the two relevant entrances are also decided.
|
#Some basic items that various modes require are placed here, including pendants and crystals. Medallion requirements for the two relevant entrances are also decided.
|
||||||
@@ -218,12 +236,14 @@ def get_custom_array_key(item):
|
|||||||
|
|
||||||
def generate_itempool(world, player):
|
def generate_itempool(world, player):
|
||||||
if (world.difficulty[player] not in ['normal', 'hard', 'expert']
|
if (world.difficulty[player] not in ['normal', 'hard', 'expert']
|
||||||
or world.goal[player] not in ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'trinity', 'crystals',
|
or world.goal[player] not in ['ganon', 'pedestal', 'dungeons',
|
||||||
'ganonhunt', 'completionist', 'sanctuary']
|
'triforcehunt', 'trinity', 'crystals',
|
||||||
|
'ganonhunt', 'completionist', 'sanctuary',
|
||||||
|
'bosshunt']
|
||||||
or world.mode[player] not in ['open', 'standard', 'inverted']
|
or world.mode[player] not in ['open', 'standard', 'inverted']
|
||||||
or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown']
|
or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown']
|
||||||
or world.progressive not in ['on', 'off', 'random']):
|
or world.progressive not in ['on', 'off', 'random']):
|
||||||
raise NotImplementedError('Not supported yet')
|
raise NotImplementedError('Not supported yet')
|
||||||
|
|
||||||
if world.timer in ['ohko', 'timed-ohko']:
|
if world.timer in ['ohko', 'timed-ohko']:
|
||||||
world.can_take_damage[player] = False
|
world.can_take_damage[player] = False
|
||||||
@@ -361,7 +381,7 @@ def generate_itempool(world, player):
|
|||||||
|
|
||||||
items = ItemFactory(pool, player)
|
items = ItemFactory(pool, player)
|
||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
for potion in ['Green Potion', 'Blue Potion', 'Red Potion']:
|
for potion in ['Green Potion', 'Blue Potion', 'Red Potion', 'Bee']:
|
||||||
p_item = next(item for item in items if item.name == potion and item.player == player)
|
p_item = next(item for item in items if item.name == potion and item.player == player)
|
||||||
p_item.priority = True # don't beemize one of each potion
|
p_item.priority = True # don't beemize one of each potion
|
||||||
|
|
||||||
@@ -691,7 +711,7 @@ def create_farm_locations(world, player):
|
|||||||
world.dynamic_locations.append(loc)
|
world.dynamic_locations.append(loc)
|
||||||
return loc
|
return loc
|
||||||
|
|
||||||
from Rules import set_rule, add_rule, add_bunny_rule
|
from Rules import add_bunny_rule, add_rule, set_rule
|
||||||
for region in bush_bombs:
|
for region in bush_bombs:
|
||||||
loc = create_and_fill_location(region, 'Bush Drop', 'Farmable Bombs')
|
loc = create_and_fill_location(region, 'Bush Drop', 'Farmable Bombs')
|
||||||
add_bunny_rule(loc, player)
|
add_bunny_rule(loc, player)
|
||||||
@@ -1107,7 +1127,7 @@ def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt
|
|||||||
precollected_items.append('Pegasus Boots')
|
precollected_items.append('Pegasus Boots')
|
||||||
pool.remove('Pegasus Boots')
|
pool.remove('Pegasus Boots')
|
||||||
pool.extend(['Rupees (20)'])
|
pool.extend(['Rupees (20)'])
|
||||||
|
|
||||||
if want_progressives():
|
if want_progressives():
|
||||||
pool.extend(progressivegloves)
|
pool.extend(progressivegloves)
|
||||||
else:
|
else:
|
||||||
@@ -1502,7 +1522,7 @@ def make_customizer_pool(world, player):
|
|||||||
guaranteed_items.append('Ocarina (Activated)')
|
guaranteed_items.append('Ocarina (Activated)')
|
||||||
missing_items = []
|
missing_items = []
|
||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
guaranteed_items.extend(['Blue Potion', 'Green Potion', 'Red Potion'])
|
guaranteed_items.extend(['Blue Potion', 'Green Potion', 'Red Potion', 'Bee'])
|
||||||
if world.keyshuffle[player] == 'universal':
|
if world.keyshuffle[player] == 'universal':
|
||||||
guaranteed_items.append('Small Key (Universal)')
|
guaranteed_items.append('Small Key (Universal)')
|
||||||
for item in guaranteed_items:
|
for item in guaranteed_items:
|
||||||
|
|||||||
+10
-4
@@ -2,11 +2,17 @@ import itertools
|
|||||||
import logging
|
import logging
|
||||||
from collections import defaultdict, deque
|
from collections import defaultdict, deque
|
||||||
|
|
||||||
from BaseClasses import DoorType, dungeon_keys, KeyRuleType, RegionType
|
from BaseClasses import DoorType, KeyRuleType, RegionType, dungeon_keys
|
||||||
|
from DungeonGenerator import (
|
||||||
|
ExplorationState,
|
||||||
|
blind_boss_unavail,
|
||||||
|
count_locations_exclude_big_chest,
|
||||||
|
get_special_big_key_doors,
|
||||||
|
prize_or_event,
|
||||||
|
reserved_location,
|
||||||
|
)
|
||||||
|
from Dungeons import dungeon_bigs, dungeon_keys, dungeon_table
|
||||||
from Regions import location_events
|
from Regions import location_events
|
||||||
from Dungeons import dungeon_keys, dungeon_bigs, dungeon_table
|
|
||||||
from DungeonGenerator import ExplorationState, get_special_big_key_doors, count_locations_exclude_big_chest, prize_or_event
|
|
||||||
from DungeonGenerator import reserved_location, blind_boss_unavail
|
|
||||||
|
|
||||||
|
|
||||||
class KeyLayout(object):
|
class KeyLayout(object):
|
||||||
|
|||||||
@@ -1,50 +1,99 @@
|
|||||||
|
import base64
|
||||||
import copy
|
import copy
|
||||||
from itertools import zip_longest
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import RaceRandom as random
|
|
||||||
import string
|
import string
|
||||||
import time
|
import time
|
||||||
import zlib
|
import zlib
|
||||||
import base64
|
from itertools import zip_longest
|
||||||
|
|
||||||
from BaseClasses import World, CollectionState, Item, Region, Location, Shop, Entrance, Settings
|
import RaceRandom as random
|
||||||
|
from BaseClasses import (
|
||||||
|
CollectionState,
|
||||||
|
Entrance,
|
||||||
|
Item,
|
||||||
|
Location,
|
||||||
|
Region,
|
||||||
|
Settings,
|
||||||
|
Shop,
|
||||||
|
World,
|
||||||
|
)
|
||||||
from Bosses import place_bosses
|
from Bosses import place_bosses
|
||||||
|
from Doors import create_doors
|
||||||
|
from DoorShuffle import connect_portal, link_doors, link_doors_prep
|
||||||
|
from Dungeons import create_dungeons
|
||||||
|
from Fill import (
|
||||||
|
balance_money_progression,
|
||||||
|
balance_multiworld_progression,
|
||||||
|
distribute_items_restrictive,
|
||||||
|
dungeon_tracking,
|
||||||
|
ensure_good_items,
|
||||||
|
fill_dungeons_restrictive,
|
||||||
|
lock_shop_locations,
|
||||||
|
promote_dungeon_items,
|
||||||
|
sell_keys,
|
||||||
|
sell_potions,
|
||||||
|
set_prize_drops,
|
||||||
|
)
|
||||||
|
from ItemList import (
|
||||||
|
create_farm_locations,
|
||||||
|
customize_shops,
|
||||||
|
difficulties,
|
||||||
|
fill_prizes,
|
||||||
|
fill_specific_items,
|
||||||
|
follower_pickups,
|
||||||
|
generate_itempool,
|
||||||
|
shuffle_event_items,
|
||||||
|
)
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
from KeyDoorShuffle import validate_key_placement
|
from KeyDoorShuffle import validate_key_placement
|
||||||
from OverworldGlitchRules import create_owg_connections
|
from OverworldGlitchRules import create_owg_connections
|
||||||
from PotShuffle import shuffle_pots, shuffle_pot_switches
|
from OverworldShuffle import (
|
||||||
from Regions import create_regions, create_shops, mark_light_dark_world_regions, create_dungeon_regions, adjust_locations
|
create_dynamic_flute_exits,
|
||||||
|
create_dynamic_mirror_exits,
|
||||||
|
link_overworld,
|
||||||
|
update_world_regions,
|
||||||
|
)
|
||||||
from OWEdges import create_owedges
|
from OWEdges import create_owedges
|
||||||
from OverworldShuffle import link_overworld, update_world_regions, create_dynamic_flute_exits, create_dynamic_mirror_exits
|
from PotShuffle import shuffle_pot_switches, shuffle_pots
|
||||||
from Rom import patch_rom, patch_race_rom, apply_rom_settings, LocalRom, JsonRom, get_hash_string
|
from Regions import (
|
||||||
from Doors import create_doors
|
adjust_locations,
|
||||||
from DoorShuffle import link_doors, connect_portal, link_doors_prep
|
create_dungeon_regions,
|
||||||
|
create_regions,
|
||||||
|
create_shops,
|
||||||
|
mark_light_dark_world_regions,
|
||||||
|
)
|
||||||
|
from Rom import (
|
||||||
|
JsonRom,
|
||||||
|
LocalRom,
|
||||||
|
apply_rom_settings,
|
||||||
|
get_hash_string,
|
||||||
|
patch_race_rom,
|
||||||
|
patch_rom,
|
||||||
|
)
|
||||||
from RoomData import create_rooms
|
from RoomData import create_rooms
|
||||||
from Rules import set_rules
|
from Rules import set_rules
|
||||||
from Dungeons import create_dungeons
|
from source.classes.BabelFish import BabelFish
|
||||||
from Fill import distribute_items_restrictive, promote_dungeon_items, fill_dungeons_restrictive, ensure_good_items
|
|
||||||
from Fill import dungeon_tracking
|
|
||||||
from Fill import sell_potions, sell_keys, balance_multiworld_progression, balance_money_progression, lock_shop_locations, set_prize_drops
|
|
||||||
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops, fill_specific_items, create_farm_locations, shuffle_event_items, follower_pickups
|
|
||||||
from UnderworldGlitchRules import connect_hmg_entrances_regions, create_hmg_entrances_regions
|
|
||||||
from Utils import output_path, parse_player_names
|
|
||||||
|
|
||||||
from source.item.District import init_districts
|
|
||||||
from source.item.FillUtil import create_item_pool_config, massage_item_pool, district_item_pool_config, verify_item_pool_config
|
|
||||||
from source.overworld.EntranceShuffle2 import link_entrances_new
|
|
||||||
from source.tools.BPS import create_bps_from_data
|
|
||||||
from source.classes.CustomSettings import CustomSettings
|
from source.classes.CustomSettings import CustomSettings
|
||||||
from source.enemizer.DamageTables import DamageTable
|
from source.enemizer.DamageTables import DamageTable
|
||||||
from source.enemizer.Enemizer import randomize_enemies
|
from source.enemizer.Enemizer import randomize_enemies
|
||||||
|
from source.item.District import init_districts
|
||||||
|
from source.item.FillUtil import (
|
||||||
|
create_item_pool_config,
|
||||||
|
district_item_pool_config,
|
||||||
|
massage_item_pool,
|
||||||
|
verify_item_pool_config,
|
||||||
|
)
|
||||||
|
from source.overworld.EntranceShuffle2 import link_entrances_new
|
||||||
from source.rom.DataTables import init_data_tables
|
from source.rom.DataTables import init_data_tables
|
||||||
|
from source.tools.BPS import create_bps_from_data
|
||||||
version_number = '1.5.0'
|
from UnderworldGlitchRules import (
|
||||||
version_branch = '-u'
|
connect_hmg_entrances_regions,
|
||||||
__version__ = f'{version_number}{version_branch}'
|
create_hmg_entrances_regions,
|
||||||
|
)
|
||||||
from source.classes.BabelFish import BabelFish
|
from Utils import output_path, parse_player_names
|
||||||
|
from Versions import DRVersion, GKVersion, ORVersion
|
||||||
|
|
||||||
|
|
||||||
class EnemizerError(RuntimeError):
|
class EnemizerError(RuntimeError):
|
||||||
@@ -80,7 +129,7 @@ def random_ganon_item(sword_mode):
|
|||||||
|
|
||||||
def main(args, seed=None, fish=None):
|
def main(args, seed=None, fish=None):
|
||||||
check_python_version()
|
check_python_version()
|
||||||
|
|
||||||
if args.print_template_yaml:
|
if args.print_template_yaml:
|
||||||
return export_yaml(args, fish)
|
return export_yaml(args, fish)
|
||||||
|
|
||||||
@@ -122,16 +171,14 @@ def main(args, seed=None, fish=None):
|
|||||||
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
||||||
world.finish_init()
|
world.finish_init()
|
||||||
|
|
||||||
from OverworldShuffle import __version__ as ORVersion
|
|
||||||
logger.info(
|
logger.info(
|
||||||
world.fish.translate("cli","cli","app.title") + "\n",
|
world.fish.translate("cli","cli","app.title") + "\n",
|
||||||
ORVersion,
|
GKVersion,
|
||||||
"%s (%s)" % (world.seed, str(args.outputname)) if str(args.outputname).startswith('M') else world.seed,
|
"%s (%s)" % (world.seed, str(args.outputname)) if str(args.outputname).startswith('M') else world.seed,
|
||||||
Settings.make_code(world, 1) if world.players == 1 else ''
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for k,v in {"DR":__version__,"OR":ORVersion}.items():
|
for k,v in {"GK": GKVersion, "OR": ORVersion, "DR": DRVersion}.items():
|
||||||
logger.info((k + ' Version:').ljust(16) + '%s' % v)
|
logger.info((k + ' Version:').ljust(16) + '%s' % v)
|
||||||
|
|
||||||
parsed_names = parse_player_names(args.names, world.players, args.teams)
|
parsed_names = parse_player_names(args.names, world.players, args.teams)
|
||||||
world.teams = len(parsed_names)
|
world.teams = len(parsed_names)
|
||||||
@@ -142,7 +189,7 @@ def main(args, seed=None, fish=None):
|
|||||||
world.player_names[player].append(name)
|
world.player_names[player].append(name)
|
||||||
logger.info('')
|
logger.info('')
|
||||||
|
|
||||||
outfilebase = f'OR_{args.outputname if args.outputname else world.seed}'
|
outfilebase = f'GK_{args.outputname if args.outputname else world.seed}'
|
||||||
|
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
world.difficulty_requirements[player] = difficulties[world.difficulty[player]]
|
world.difficulty_requirements[player] = difficulties[world.difficulty[player]]
|
||||||
@@ -421,15 +468,13 @@ def export_yaml(args, fish):
|
|||||||
if args.seed and int(args.seed) > 0:
|
if args.seed and int(args.seed) > 0:
|
||||||
world.seed = int(args.seed)
|
world.seed = int(args.seed)
|
||||||
|
|
||||||
from OverworldShuffle import __version__ as ORVersion
|
|
||||||
logger.info(
|
logger.info(
|
||||||
world.fish.translate("cli","cli","app.title") + "\n",
|
world.fish.translate("cli","cli","app.title") + "\n",
|
||||||
ORVersion,
|
GKVersion,
|
||||||
"(%s)" % outfilebase,
|
"(%s)" % outfilebase,
|
||||||
Settings.make_code(world, 1) if world.players == 1 else ''
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for k,v in {"DR":__version__,"OR":ORVersion}.items():
|
for k,v in {"GK": GKVersion, "OR": ORVersion, "DR": DRVersion}.items():
|
||||||
logger.info((k + ' Version:').ljust(16) + '%s' % v)
|
logger.info((k + ' Version:').ljust(16) + '%s' % v)
|
||||||
|
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
@@ -470,12 +515,16 @@ def init_world(args, fish):
|
|||||||
world.keyshuffle = args.keyshuffle.copy()
|
world.keyshuffle = args.keyshuffle.copy()
|
||||||
world.bigkeyshuffle = args.bigkeyshuffle.copy()
|
world.bigkeyshuffle = args.bigkeyshuffle.copy()
|
||||||
world.prizeshuffle = args.prizeshuffle.copy()
|
world.prizeshuffle = args.prizeshuffle.copy()
|
||||||
|
world.showloot = args.showloot.copy()
|
||||||
|
world.showmap = args.showmap.copy()
|
||||||
world.bombbag = args.bombbag.copy()
|
world.bombbag = args.bombbag.copy()
|
||||||
world.flute_mode = args.flute_mode.copy()
|
world.flute_mode = args.flute_mode.copy()
|
||||||
world.bow_mode = args.bow_mode.copy()
|
world.bow_mode = args.bow_mode.copy()
|
||||||
world.crystals_ganon_orig = args.crystals_ganon.copy()
|
world.crystals_ganon_orig = args.crystals_ganon.copy()
|
||||||
world.crystals_gt_orig = args.crystals_gt.copy()
|
world.crystals_gt_orig = args.crystals_gt.copy()
|
||||||
world.ganon_item_orig = args.ganon_item.copy()
|
world.ganon_item_orig = args.ganon_item.copy()
|
||||||
|
world.bosses_ganon = {player: int(args.bosses_ganon[player]) for player in range(1, world.players + 1)}
|
||||||
|
world.bosshunt_include_agas = args.bosshunt_include_agas.copy()
|
||||||
world.owTerrain = args.ow_terrain.copy()
|
world.owTerrain = args.ow_terrain.copy()
|
||||||
world.owKeepSimilar = args.ow_keepsimilar.copy()
|
world.owKeepSimilar = args.ow_keepsimilar.copy()
|
||||||
world.owWhirlpoolShuffle = args.ow_whirlpool.copy()
|
world.owWhirlpoolShuffle = args.ow_whirlpool.copy()
|
||||||
@@ -523,7 +572,7 @@ def init_world(args, fish):
|
|||||||
world.money_balance = args.money_balance.copy()
|
world.money_balance = args.money_balance.copy()
|
||||||
|
|
||||||
# custom settings - these haven't been promoted to full settings yet
|
# custom settings - these haven't been promoted to full settings yet
|
||||||
in_progress_settings = ['force_enemy', 'free_lamp_cone']
|
in_progress_settings = ['force_enemy']
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
for setting in in_progress_settings:
|
for setting in in_progress_settings:
|
||||||
if world.customizer and world.customizer.has_setting(player, setting):
|
if world.customizer and world.customizer.has_setting(player, setting):
|
||||||
@@ -785,12 +834,16 @@ def copy_world(world):
|
|||||||
ret.keyshuffle = world.keyshuffle.copy()
|
ret.keyshuffle = world.keyshuffle.copy()
|
||||||
ret.bigkeyshuffle = world.bigkeyshuffle.copy()
|
ret.bigkeyshuffle = world.bigkeyshuffle.copy()
|
||||||
ret.prizeshuffle = world.prizeshuffle.copy()
|
ret.prizeshuffle = world.prizeshuffle.copy()
|
||||||
|
ret.showloot = world.showloot.copy()
|
||||||
|
ret.showmap = world.showmap.copy()
|
||||||
ret.bombbag = world.bombbag.copy()
|
ret.bombbag = world.bombbag.copy()
|
||||||
ret.flute_mode = world.flute_mode.copy()
|
ret.flute_mode = world.flute_mode.copy()
|
||||||
ret.bow_mode = world.bow_mode.copy()
|
ret.bow_mode = world.bow_mode.copy()
|
||||||
ret.free_lamp_cone = world.free_lamp_cone.copy()
|
ret.free_lamp_cone = world.free_lamp_cone.copy()
|
||||||
ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy()
|
ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy()
|
||||||
ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy()
|
ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy()
|
||||||
|
ret.bosses_ganon = world.bosses_ganon.copy()
|
||||||
|
ret.bosshunt_include_agas = world.bosshunt_include_agas.copy()
|
||||||
ret.ganon_item = world.ganon_item.copy()
|
ret.ganon_item = world.ganon_item.copy()
|
||||||
ret.crystals_ganon_orig = world.crystals_ganon_orig.copy()
|
ret.crystals_ganon_orig = world.crystals_ganon_orig.copy()
|
||||||
ret.crystals_gt_orig = world.crystals_gt_orig.copy()
|
ret.crystals_gt_orig = world.crystals_gt_orig.copy()
|
||||||
@@ -1012,12 +1065,16 @@ def copy_world_premature(world, player, create_flute_exits=True):
|
|||||||
ret.keyshuffle = world.keyshuffle.copy()
|
ret.keyshuffle = world.keyshuffle.copy()
|
||||||
ret.bigkeyshuffle = world.bigkeyshuffle.copy()
|
ret.bigkeyshuffle = world.bigkeyshuffle.copy()
|
||||||
ret.prizeshuffle = world.prizeshuffle.copy()
|
ret.prizeshuffle = world.prizeshuffle.copy()
|
||||||
|
ret.showloot = world.showloot.copy()
|
||||||
|
ret.showmap = world.showmap.copy()
|
||||||
ret.bombbag = world.bombbag.copy()
|
ret.bombbag = world.bombbag.copy()
|
||||||
ret.flute_mode = world.flute_mode.copy()
|
ret.flute_mode = world.flute_mode.copy()
|
||||||
ret.bow_mode = world.bow_mode.copy()
|
ret.bow_mode = world.bow_mode.copy()
|
||||||
ret.free_lamp_cone = world.free_lamp_cone.copy()
|
ret.free_lamp_cone = world.free_lamp_cone.copy()
|
||||||
ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy()
|
ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy()
|
||||||
ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy()
|
ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy()
|
||||||
|
ret.bosses_ganon = world.bosses_ganon.copy()
|
||||||
|
ret.bosshunt_include_agas = world.bosshunt_include_agas.copy()
|
||||||
ret.ganon_item = world.ganon_item.copy()
|
ret.ganon_item = world.ganon_item.copy()
|
||||||
ret.crystals_ganon_orig = world.crystals_ganon_orig.copy()
|
ret.crystals_ganon_orig = world.crystals_ganon_orig.copy()
|
||||||
ret.crystals_gt_orig = world.crystals_gt_orig.copy()
|
ret.crystals_gt_orig = world.crystals_gt_orig.copy()
|
||||||
|
|||||||
+6
-5
@@ -1,19 +1,20 @@
|
|||||||
import aioconsole
|
|
||||||
import argparse
|
import argparse
|
||||||
import asyncio
|
import asyncio
|
||||||
import colorama
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import shlex
|
import shlex
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
|
import aioconsole
|
||||||
|
import colorama
|
||||||
import websockets
|
import websockets
|
||||||
|
|
||||||
from BaseClasses import PotItem, PotFlags, LocationType
|
|
||||||
import Items
|
import Items
|
||||||
import Regions
|
|
||||||
import PotShuffle
|
import PotShuffle
|
||||||
|
import Regions
|
||||||
import source.dungeon.EnemyList as EnemyList
|
import source.dungeon.EnemyList as EnemyList
|
||||||
import source.rom.DataTables as DataTables
|
import source.rom.DataTables as DataTables
|
||||||
|
from BaseClasses import LocationType, PotFlags, PotItem
|
||||||
|
|
||||||
|
|
||||||
class ReceivedItem:
|
class ReceivedItem:
|
||||||
@@ -975,8 +976,8 @@ async def track_locations(ctx : Context, roomid, roomdata):
|
|||||||
ow_unchecked[location] = (screenid, 0x40)
|
ow_unchecked[location] = (screenid, 0x40)
|
||||||
ow_begin = min(ow_begin, screenid)
|
ow_begin = min(ow_begin, screenid)
|
||||||
ow_end = max(ow_end, screenid + 1)
|
ow_end = max(ow_end, screenid + 1)
|
||||||
from Regions import bonk_prize_table
|
|
||||||
from OWEdges import OWTileRegions
|
from OWEdges import OWTileRegions
|
||||||
|
from Regions import bonk_prize_table
|
||||||
for location, (_, flag, _, _, region_name, _) in bonk_prize_table.items():
|
for location, (_, flag, _, _, region_name, _) in bonk_prize_table.items():
|
||||||
if location not in ctx.locations_checked:
|
if location not in ctx.locations_checked:
|
||||||
if region_name in OWTileRegions:
|
if region_name in OWTileRegions:
|
||||||
|
|||||||
+11
-5
@@ -1,4 +1,3 @@
|
|||||||
import aioconsole
|
|
||||||
import argparse
|
import argparse
|
||||||
import asyncio
|
import asyncio
|
||||||
import functools
|
import functools
|
||||||
@@ -8,16 +7,23 @@ import re
|
|||||||
import shlex
|
import shlex
|
||||||
import ssl
|
import ssl
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import websockets
|
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
from BaseClasses import PotItem, PotFlags
|
import aioconsole
|
||||||
|
import websockets
|
||||||
|
|
||||||
import Items
|
import Items
|
||||||
import Regions
|
|
||||||
import PotShuffle
|
import PotShuffle
|
||||||
from MultiClient import ReceivedItem, get_item_name_from_id, get_location_name_from_address
|
import Regions
|
||||||
import source.dungeon.EnemyList as EnemyList
|
import source.dungeon.EnemyList as EnemyList
|
||||||
import source.rom.DataTables as DataTables
|
import source.rom.DataTables as DataTables
|
||||||
|
from BaseClasses import PotFlags, PotItem
|
||||||
|
from MultiClient import (
|
||||||
|
ReceivedItem,
|
||||||
|
get_item_name_from_id,
|
||||||
|
get_location_name_from_address,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
def __init__(self, socket):
|
def __init__(self, socket):
|
||||||
|
|||||||
+4
-4
@@ -1,13 +1,13 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import RaceRandom as random
|
|
||||||
|
|
||||||
|
from yaml.constructor import SafeConstructor
|
||||||
|
|
||||||
|
import RaceRandom as random
|
||||||
from DungeonRandomizer import parse_cli
|
from DungeonRandomizer import parse_cli
|
||||||
from Main import main as DRMain
|
from Main import main as DRMain
|
||||||
from source.classes.BabelFish import BabelFish
|
from source.classes.BabelFish import BabelFish
|
||||||
from yaml.constructor import SafeConstructor
|
from source.tools.MysteryUtils import get_weights, roll_settings
|
||||||
|
|
||||||
from source.tools.MysteryUtils import roll_settings, get_weights
|
|
||||||
|
|
||||||
|
|
||||||
def add_bool(self, node):
|
def add_bool(self, node):
|
||||||
|
|||||||
+3
-1
@@ -1,8 +1,10 @@
|
|||||||
|
|
||||||
from BaseClasses import OWEdge, Direction, Terrain, WorldType, PolSlot
|
|
||||||
from enum import Enum, unique
|
from enum import Enum, unique
|
||||||
|
|
||||||
|
from BaseClasses import Direction, OWEdge, PolSlot, Terrain, WorldType
|
||||||
from Utils import bidict
|
from Utils import bidict
|
||||||
|
|
||||||
|
|
||||||
@unique
|
@unique
|
||||||
class OpenStd(Enum):
|
class OpenStd(Enum):
|
||||||
Open = 0
|
Open = 0
|
||||||
|
|||||||
+34
-14
@@ -1,19 +1,32 @@
|
|||||||
import RaceRandom as random, logging, copy
|
import copy
|
||||||
|
import logging
|
||||||
from collections import OrderedDict, defaultdict
|
from collections import OrderedDict, defaultdict
|
||||||
|
|
||||||
|
import RaceRandom as random
|
||||||
|
from BaseClasses import (
|
||||||
|
Direction,
|
||||||
|
Entrance,
|
||||||
|
OWEdge,
|
||||||
|
PolSlot,
|
||||||
|
RegionType,
|
||||||
|
Terrain,
|
||||||
|
WorldType,
|
||||||
|
)
|
||||||
from DungeonGenerator import GenerationException
|
from DungeonGenerator import GenerationException
|
||||||
from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSlot, Entrance
|
from OverworldGlitchRules import create_owg_connections
|
||||||
|
from OWEdges import (
|
||||||
|
IsParallel,
|
||||||
|
OpenStd,
|
||||||
|
OWEdgeGroups,
|
||||||
|
OWEdgeGroupsTerrain,
|
||||||
|
OWExitTypes,
|
||||||
|
OWTileRegions,
|
||||||
|
parallel_links,
|
||||||
|
)
|
||||||
from Regions import mark_light_dark_world_regions
|
from Regions import mark_light_dark_world_regions
|
||||||
from source.overworld.EntranceShuffle2 import connect_simple
|
from source.overworld.EntranceShuffle2 import connect_simple
|
||||||
from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitTypes, OpenStd, parallel_links, IsParallel
|
|
||||||
from OverworldGlitchRules import create_owg_connections
|
|
||||||
from Utils import bidict
|
from Utils import bidict
|
||||||
|
|
||||||
version_number = '0.6.1.7'
|
|
||||||
# branch indicator is intentionally different across branches
|
|
||||||
version_branch = ''
|
|
||||||
|
|
||||||
__version__ = '%s%s' % (version_number, version_branch)
|
|
||||||
|
|
||||||
parallel_links_new = None # needs to be globally available, reset every new generation/player
|
parallel_links_new = None # needs to be globally available, reset every new generation/player
|
||||||
|
|
||||||
def link_overworld(world, player):
|
def link_overworld(world, player):
|
||||||
@@ -1370,8 +1383,8 @@ def update_world_regions(world, player):
|
|||||||
world.get_region(name, player).type = RegionType.LightWorld
|
world.get_region(name, player).type = RegionType.LightWorld
|
||||||
|
|
||||||
def can_reach_smith(world, player):
|
def can_reach_smith(world, player):
|
||||||
from Items import ItemFactory
|
|
||||||
from BaseClasses import CollectionState
|
from BaseClasses import CollectionState
|
||||||
|
from Items import ItemFactory
|
||||||
|
|
||||||
def explore_region(region_name, region=None):
|
def explore_region(region_name, region=None):
|
||||||
nonlocal found
|
nonlocal found
|
||||||
@@ -1426,7 +1439,7 @@ def can_reach_smith(world, player):
|
|||||||
def build_sectors(world, player):
|
def build_sectors(world, player):
|
||||||
from Main import copy_world_premature
|
from Main import copy_world_premature
|
||||||
from OWEdges import OWTileRegions
|
from OWEdges import OWTileRegions
|
||||||
|
|
||||||
# perform accessibility check on duplicate world
|
# perform accessibility check on duplicate world
|
||||||
for p in range(1, world.players + 1):
|
for p in range(1, world.players + 1):
|
||||||
world.key_logic[p] = {}
|
world.key_logic[p] = {}
|
||||||
@@ -1478,8 +1491,8 @@ def build_sectors(world, player):
|
|||||||
|
|
||||||
def build_accessible_region_list(world, start_region, player, build_copy_world=False, cross_world=False, region_rules=True, ignore_ledges=False, restrictive_follower=False):
|
def build_accessible_region_list(world, start_region, player, build_copy_world=False, cross_world=False, region_rules=True, ignore_ledges=False, restrictive_follower=False):
|
||||||
from BaseClasses import CollectionState
|
from BaseClasses import CollectionState
|
||||||
from Main import copy_world_premature
|
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
|
from Main import copy_world_premature
|
||||||
from Utils import stack_size3a
|
from Utils import stack_size3a
|
||||||
|
|
||||||
def explore_region(region_name, region=None):
|
def explore_region(region_name, region=None):
|
||||||
@@ -1552,7 +1565,14 @@ def validate_layout(world, player):
|
|||||||
}
|
}
|
||||||
|
|
||||||
# TODO: Find a better source for the below lists, original sourced was deprecated
|
# TODO: Find a better source for the below lists, original sourced was deprecated
|
||||||
from source.overworld.EntranceData import default_dungeon_connections, default_connector_connections, default_item_connections, default_shop_connections, default_drop_connections, default_dropexit_connections
|
from source.overworld.EntranceData import (
|
||||||
|
default_connector_connections,
|
||||||
|
default_drop_connections,
|
||||||
|
default_dropexit_connections,
|
||||||
|
default_dungeon_connections,
|
||||||
|
default_item_connections,
|
||||||
|
default_shop_connections,
|
||||||
|
)
|
||||||
|
|
||||||
dungeon_entrances = list(zip(*default_dungeon_connections + [('Ganons Tower', '')]))[0]
|
dungeon_entrances = list(zip(*default_dungeon_connections + [('Ganons Tower', '')]))[0]
|
||||||
connector_entrances = list(zip(*default_connector_connections))[0]
|
connector_entrances = list(zip(*default_connector_connections))[0]
|
||||||
|
|||||||
@@ -3,22 +3,33 @@ import argparse
|
|||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import RaceRandom as random
|
|
||||||
import time
|
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
import RaceRandom as random
|
||||||
from BaseClasses import World
|
from BaseClasses import World
|
||||||
from Regions import create_regions
|
|
||||||
from OverworldShuffle import link_overworld
|
|
||||||
from source.overworld.EntranceShuffle2 import link_entrances_new, 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 Rules import set_rules
|
|
||||||
from Dungeons import create_dungeons
|
from Dungeons import create_dungeons
|
||||||
from Items import ItemFactory
|
|
||||||
from ItemList import difficulties
|
from ItemList import difficulties
|
||||||
|
from Items import ItemFactory
|
||||||
from Main import create_playthrough
|
from Main import create_playthrough
|
||||||
|
from OverworldShuffle import link_overworld
|
||||||
|
from Regions import create_regions
|
||||||
|
from Rom import (
|
||||||
|
LocalRom,
|
||||||
|
apply_rom_settings,
|
||||||
|
get_sprite_from_name,
|
||||||
|
patch_rom,
|
||||||
|
write_string_to_rom,
|
||||||
|
)
|
||||||
|
from Rules import set_rules
|
||||||
|
from source.overworld.EntranceShuffle2 import (
|
||||||
|
connect_entrance,
|
||||||
|
connect_exit,
|
||||||
|
connect_two_way,
|
||||||
|
link_entrances_new,
|
||||||
|
)
|
||||||
|
|
||||||
__version__ = '0.2-dev'
|
PlandoVersion = '0.2-dev'
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
start_time = time.process_time()
|
start_time = time.process_time()
|
||||||
@@ -36,7 +47,7 @@ def main(args):
|
|||||||
|
|
||||||
random.seed(world.seed)
|
random.seed(world.seed)
|
||||||
|
|
||||||
logger.info('ALttP Plandomizer Version %s - Seed: %s\n\n', __version__, args.plando)
|
logger.info('ALttP Plandomizer Version %s - Seed: %s\n\n', PlandoVersion, args.plando)
|
||||||
|
|
||||||
world.difficulty_requirements[1] = difficulties[world.difficulty[1]]
|
world.difficulty_requirements[1] = difficulties[world.difficulty[1]]
|
||||||
|
|
||||||
|
|||||||
+3
-5
@@ -1,11 +1,9 @@
|
|||||||
import RaceRandom as random
|
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from BaseClasses import PotItem, Pot, PotFlags, CrystalBarrier, LocationType, RegionType
|
import RaceRandom as random
|
||||||
from Utils import int16_as_bytes, pc_to_snes, snes_to_pc
|
from BaseClasses import CrystalBarrier, LocationType, Pot, PotFlags, PotItem, RegionType
|
||||||
|
|
||||||
from source.dungeon.RoomObject import RoomObject, Shuffled_Pot
|
from source.dungeon.RoomObject import RoomObject, Shuffled_Pot
|
||||||
|
from Utils import int16_as_bytes, pc_to_snes, snes_to_pc
|
||||||
|
|
||||||
movable_switch_rooms = defaultdict(lambda: [],
|
movable_switch_rooms = defaultdict(lambda: [],
|
||||||
{'PoD Stalfos Basement': ['PoD Basement Ledge'],
|
{'PoD Stalfos Basement': ['PoD Basement Ledge'],
|
||||||
|
|||||||
+15
-4
@@ -1,9 +1,20 @@
|
|||||||
import collections
|
import collections
|
||||||
from Items import ItemFactory
|
|
||||||
from BaseClasses import Region, Location, Entrance, RegionType, Terrain, Shop, ShopType, LocationType, PotItem, PotFlags
|
|
||||||
from PotShuffle import key_drop_data, vanilla_pots, choose_pots, PotSecretTable
|
|
||||||
|
|
||||||
from source.dungeon.EnemyList import setup_enemy_locations, enemy_names
|
from BaseClasses import (
|
||||||
|
Entrance,
|
||||||
|
Location,
|
||||||
|
LocationType,
|
||||||
|
PotFlags,
|
||||||
|
PotItem,
|
||||||
|
Region,
|
||||||
|
RegionType,
|
||||||
|
Shop,
|
||||||
|
ShopType,
|
||||||
|
Terrain,
|
||||||
|
)
|
||||||
|
from Items import ItemFactory
|
||||||
|
from PotShuffle import PotSecretTable, choose_pots, key_drop_data, vanilla_pots
|
||||||
|
from source.dungeon.EnemyList import enemy_names, setup_enemy_locations
|
||||||
|
|
||||||
|
|
||||||
def create_regions(world, player):
|
def create_regions(world, player):
|
||||||
|
|||||||
@@ -1,50 +1,90 @@
|
|||||||
import bisect
|
import bisect
|
||||||
import collections
|
import collections
|
||||||
|
import hashlib
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
import hashlib
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
|
||||||
import Items
|
import Items
|
||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
import struct
|
|
||||||
import sys
|
|
||||||
try:
|
try:
|
||||||
import bps.apply
|
import bps.apply
|
||||||
import bps.io
|
import bps.io
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise Exception('Could not load BPS module')
|
raise Exception('Could not load BPS module')
|
||||||
|
|
||||||
from BaseClasses import ShopType, Region, Location, OWEdge, Door, DoorType, RegionType, LocationType
|
from BaseClasses import (
|
||||||
from DoorShuffle import compass_data, DROptions, boss_indicator, dungeon_portals
|
Door,
|
||||||
from Dungeons import dungeon_music_addresses, dungeon_table
|
DoorType,
|
||||||
from Regions import location_table, shop_to_location_table, retro_shops
|
Location,
|
||||||
from RoomData import DoorKind
|
LocationType,
|
||||||
from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable
|
OWEdge,
|
||||||
from Text import Uncle_texts, Ganon1_texts, Ganon_Phase_3_No_Silvers_texts, Ganon_Phase_3_No_Weakness_texts, TavernMan_texts, Sahasrahla2_texts
|
Region,
|
||||||
from Text import Triforce_texts, Blind_texts, BombShop2_texts, junk_texts
|
RegionType,
|
||||||
from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts
|
ShopType,
|
||||||
from Text import LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts
|
)
|
||||||
from Text import Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names
|
|
||||||
from Utils import local_path, int16_as_bytes, int32_as_bytes, snes_to_pc
|
|
||||||
from Items import ItemFactory, prize_item_table
|
|
||||||
from source.overworld.EntranceData import door_addresses, ow_prize_table
|
|
||||||
from source.overworld.EntranceShuffle2 import exit_ids
|
|
||||||
from OverworldShuffle import default_flute_connections, flute_data
|
|
||||||
from InitialSram import InitialSram
|
|
||||||
from DamageTable import DamageTable
|
from DamageTable import DamageTable
|
||||||
|
from DoorShuffle import DROptions, boss_indicator, compass_data, dungeon_portals
|
||||||
from source.classes.SFX import randomize_sfx, randomize_sfxinstruments, randomize_songinstruments
|
from Dungeons import dungeon_music_addresses, dungeon_table
|
||||||
from source.item.FillUtil import valid_pot_items
|
from InitialSram import InitialSram
|
||||||
|
from Items import ItemFactory, prize_item_table
|
||||||
|
from OverworldShuffle import default_flute_connections, flute_data
|
||||||
|
from Regions import location_table, retro_shops, shop_to_location_table
|
||||||
|
from RoomData import DoorKind
|
||||||
|
from source.classes.SFX import (
|
||||||
|
randomize_sfx,
|
||||||
|
randomize_sfxinstruments,
|
||||||
|
randomize_songinstruments,
|
||||||
|
)
|
||||||
from source.dungeon.EnemyList import EnemySprite, setup_enemy_dungeon_tables
|
from source.dungeon.EnemyList import EnemySprite, setup_enemy_dungeon_tables
|
||||||
from source.dungeon.RoomObject import DoorObject
|
from source.dungeon.RoomObject import DoorObject
|
||||||
from source.enemizer.Bossmizer import boss_writes
|
from source.enemizer.Bossmizer import boss_writes
|
||||||
from source.enemizer.Enemizer import write_enemy_shuffle_settings
|
from source.enemizer.Enemizer import write_enemy_shuffle_settings
|
||||||
|
from source.item.FillUtil import valid_pot_items
|
||||||
|
from source.overworld.EntranceData import door_addresses, ow_prize_table
|
||||||
|
from source.overworld.EntranceShuffle2 import exit_ids
|
||||||
|
from Text import (
|
||||||
|
Blacksmiths_texts,
|
||||||
|
Blind_texts,
|
||||||
|
BombShop2_texts,
|
||||||
|
CompressedTextMapper,
|
||||||
|
Credits,
|
||||||
|
DeathMountain_texts,
|
||||||
|
DesertPalace_texts,
|
||||||
|
FluteBoy_texts,
|
||||||
|
Ganon1_texts,
|
||||||
|
Ganon_Phase_3_No_Silvers_texts,
|
||||||
|
Ganon_Phase_3_No_Weakness_texts,
|
||||||
|
Kakariko_texts,
|
||||||
|
KingsReturn_texts,
|
||||||
|
LinksHouse_texts,
|
||||||
|
LostWoods_texts,
|
||||||
|
Lumberjacks_texts,
|
||||||
|
MagicShop_texts,
|
||||||
|
MountainTower_texts,
|
||||||
|
MultiByteTextMapper,
|
||||||
|
Sahasrahla2_texts,
|
||||||
|
Sahasrahla_names,
|
||||||
|
Sanctuary_texts,
|
||||||
|
SickKid_texts,
|
||||||
|
TavernMan_texts,
|
||||||
|
TextTable,
|
||||||
|
Triforce_texts,
|
||||||
|
Uncle_texts,
|
||||||
|
WishingWell_texts,
|
||||||
|
Zora_texts,
|
||||||
|
junk_texts,
|
||||||
|
text_addresses,
|
||||||
|
)
|
||||||
|
from Utils import int16_as_bytes, int32_as_bytes, local_path, snes_to_pc
|
||||||
|
from Versions import DRVersion, GKVersion, ORVersion
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = '76dc2d00e5dd5b925ad01574b327d364'
|
RANDOMIZERBASEHASH = '2647cc28bca3675152576dd1f5ea0bab'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -162,11 +202,12 @@ class LocalRom(object):
|
|||||||
with open(local_path('data/base2current.bps'), 'rb') as stream:
|
with open(local_path('data/base2current.bps'), 'rb') as stream:
|
||||||
bps.apply.apply_to_bytearrays(bps.io.read_bps(stream), orig_buffer, self.buffer)
|
bps.apply.apply_to_bytearrays(bps.io.read_bps(stream), orig_buffer, self.buffer)
|
||||||
|
|
||||||
# verify md5
|
if not os.getenv("SKIP_BASEROM_CHECK", False):
|
||||||
patchedmd5 = hashlib.md5()
|
# verify md5
|
||||||
patchedmd5.update(self.buffer)
|
patchedmd5 = hashlib.md5()
|
||||||
if RANDOMIZERBASEHASH != patchedmd5.hexdigest():
|
patchedmd5.update(self.buffer)
|
||||||
raise RuntimeError('Provided Base Rom unsuitable for patching. Please provide a JAP(1.0) "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc" rom to use as a base.')
|
if RANDOMIZERBASEHASH != patchedmd5.hexdigest():
|
||||||
|
raise RuntimeError('Provided Base Rom unsuitable for patching. Please provide a JAP(1.0) "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc" rom to use as a base.')
|
||||||
|
|
||||||
def write_crc(self):
|
def write_crc(self):
|
||||||
crc = (sum(self.buffer[:0x7FDC] + self.buffer[0x7FE0:]) + 0x01FE) & 0xFFFF
|
crc = (sum(self.buffer[:0x7FDC] + self.buffer[0x7FE0:]) + 0x01FE) & 0xFFFF
|
||||||
@@ -1186,7 +1227,7 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon[player] == 'Triforce Piece' else [0x0D, 0x28])
|
rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon[player] == 'Triforce Piece' else [0x0D, 0x28])
|
||||||
if world.goal[player] in ['triforcehunt', 'trinity', 'ganonhunt']:
|
if world.goal[player] in ['triforcehunt', 'trinity', 'ganonhunt']:
|
||||||
rom.write_bytes(0x180167, int16_as_bytes(world.treasure_hunt_count[player]))
|
rom.write_bytes(0x180167, int16_as_bytes(world.treasure_hunt_count[player]))
|
||||||
rom.write_byte(0x180194, 1) # Must turn in triforced pieces (instant win not enabled)
|
rom.write_byte(0x180194, 1) # Must turn in triforce pieces (instant win not enabled)
|
||||||
|
|
||||||
rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed
|
rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed
|
||||||
|
|
||||||
@@ -1215,7 +1256,6 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
rom.write_bytes(0x18016E, [0x04, 0x08, 0x10]) # Set spike cave and MM spike room Cape usage
|
rom.write_bytes(0x18016E, [0x04, 0x08, 0x10]) # Set spike cave and MM spike room Cape usage
|
||||||
rom.write_bytes(0x50563, [0x3F, 0x14]) # disable below ganon chest
|
rom.write_bytes(0x50563, [0x3F, 0x14]) # disable below ganon chest
|
||||||
rom.write_byte(0x50599, 0x00) # disable below ganon chest
|
rom.write_byte(0x50599, 0x00) # disable below ganon chest
|
||||||
rom.write_bytes(0xE9A5, [0x7E, 0x00, 0x24]) # disable below ganon chest
|
|
||||||
if world.is_pyramid_open(player):
|
if world.is_pyramid_open(player):
|
||||||
rom.initial_sram.pre_open_pyramid_hole()
|
rom.initial_sram.pre_open_pyramid_hole()
|
||||||
rom.write_byte(0x18008F, 0x01 if world.is_atgt_swapped(player) else 0x00) # AT/GT swapped
|
rom.write_byte(0x18008F, 0x01 if world.is_atgt_swapped(player) else 0x00) # AT/GT swapped
|
||||||
@@ -1261,6 +1301,8 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
# 08: Goal items collected (ie. Triforce Pieces)
|
# 08: Goal items collected (ie. Triforce Pieces)
|
||||||
# 09: Max collection rate
|
# 09: Max collection rate
|
||||||
# 0A: Custom goal
|
# 0A: Custom goal
|
||||||
|
# 0B: Reserved for Bingo
|
||||||
|
# 0C: All bosses (prize bosses + aga1 + aga2)
|
||||||
|
|
||||||
def get_goal_bytes(type):
|
def get_goal_bytes(type):
|
||||||
goal_bytes = []
|
goal_bytes = []
|
||||||
@@ -1315,6 +1357,11 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
ganon_goal += [0x02, world.crystals_needed_for_ganon[player]]
|
ganon_goal += [0x02, world.crystals_needed_for_ganon[player]]
|
||||||
elif world.goal[player] in ['ganonhunt']:
|
elif world.goal[player] in ['ganonhunt']:
|
||||||
ganon_goal += [0x88] # triforce pieces
|
ganon_goal += [0x88] # triforce pieces
|
||||||
|
elif world.goal[player] in ['bosshunt']:
|
||||||
|
if world.bosshunt_include_agas[player]:
|
||||||
|
ganon_goal += [0x0C, world.bosses_ganon[player]] # total bosses
|
||||||
|
else:
|
||||||
|
ganon_goal += [0x05, world.bosses_ganon[player]] # prize bosses
|
||||||
elif world.goal[player] in ['completionist']:
|
elif world.goal[player] in ['completionist']:
|
||||||
ganon_goal += [0x81, 0x82, 0x06, 0x07, 0x89] # AD and max collection rate
|
ganon_goal += [0x81, 0x82, 0x06, 0x07, 0x89] # AD and max collection rate
|
||||||
else:
|
else:
|
||||||
@@ -1416,6 +1463,60 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
or world.dropshuffle[player] != 'none' or world.pottery[player] not in ['none', 'cave']):
|
or world.dropshuffle[player] != 'none' or world.pottery[player] not in ['none', 'cave']):
|
||||||
rom.write_byte(0x18003A, 0x01) # show key counts on map pickup
|
rom.write_byte(0x18003A, 0x01) # show key counts on map pickup
|
||||||
|
|
||||||
|
loot_source = 0x09
|
||||||
|
if world.prizeshuffle[player] != 'none':
|
||||||
|
loot_source |= 0x10
|
||||||
|
if world.pottery[player] not in ['none', 'cave']:
|
||||||
|
loot_source |= 0x02
|
||||||
|
if world.dropshuffle[player] != 'none':
|
||||||
|
loot_source |= 0x04
|
||||||
|
rom.write_byte(0x1CFF10, loot_source)
|
||||||
|
|
||||||
|
if world.showloot[player] == 'never':
|
||||||
|
rom.write_bytes(0x1CFF08, [0x00, 0x00, 0x00, 0x00])
|
||||||
|
rom.write_byte(0x1CFF11, 0x00)
|
||||||
|
elif world.showloot[player] == 'presence':
|
||||||
|
rom.write_bytes(0x1CFF08, [0x01, 0x00, 0x00, 0x00])
|
||||||
|
rom.write_byte(0x1CFF11, 0x00)
|
||||||
|
elif world.showloot[player] == 'compass':
|
||||||
|
rom.write_bytes(0x1CFF08, [0x01, 0x00, 0x02, 0x00])
|
||||||
|
rom.write_byte(0x1CFF11, 0x01)
|
||||||
|
elif world.showloot[player] == 'always':
|
||||||
|
rom.write_bytes(0x1CFF08, [0x02, 0x00, 0x00, 0x00])
|
||||||
|
rom.write_byte(0x1CFF11, 0x00)
|
||||||
|
|
||||||
|
if world.showmap[player] == 'visited':
|
||||||
|
rom.write_bytes(0x1CFF00, [0x01, 0x00, 0x00, 0x05])
|
||||||
|
elif world.showmap[player] == 'map':
|
||||||
|
rom.write_bytes(0x1CFF00, [0x01, 0x05, 0x00, 0x05])
|
||||||
|
elif world.showmap[player] == 'always':
|
||||||
|
rom.write_bytes(0x1CFF00, [0x05, 0x00, 0x00, 0x00])
|
||||||
|
|
||||||
|
loot_icons = 0x1CF900
|
||||||
|
if world.bombbag[player]:
|
||||||
|
rom.write_byte(loot_icons + 0x52, 0x0B) # bomb bag is major
|
||||||
|
|
||||||
|
triforce_piece_ids = [0x6B, 0x6C]
|
||||||
|
if world.treasure_hunt_count[player] > 20:
|
||||||
|
for triforce_piece_id in triforce_piece_ids:
|
||||||
|
rom.write_byte(loot_icons + triforce_piece_id, 0x04)
|
||||||
|
|
||||||
|
crystal_ids = [0x20, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6]
|
||||||
|
if world.goal[player] in ['ganon', 'dungeons', 'crystals', 'trinity']:
|
||||||
|
crystal_category = 0x0D
|
||||||
|
else:
|
||||||
|
crystal_category = 0x06
|
||||||
|
for crystal_id in crystal_ids:
|
||||||
|
rom.write_byte(loot_icons + crystal_id, crystal_category)
|
||||||
|
|
||||||
|
pendant_ids = [0x37, 0x38, 0x39]
|
||||||
|
if world.goal[player] in ['pedestal', 'dungeons', 'trinity']:
|
||||||
|
pendant_category = 0x0C
|
||||||
|
else:
|
||||||
|
pendant_category = 0x06
|
||||||
|
for pendant_id in pendant_ids:
|
||||||
|
rom.write_byte(loot_icons + pendant_id, pendant_category)
|
||||||
|
|
||||||
# compasses showing dungeon count
|
# compasses showing dungeon count
|
||||||
compass_mode = 0x80 if world.compassshuffle[player] not in ['none', 'nearby'] else 0x00
|
compass_mode = 0x80 if world.compassshuffle[player] not in ['none', 'nearby'] else 0x00
|
||||||
if world.clock_mode != 'none' or world.dungeon_counters[player] == 'off':
|
if world.clock_mode != 'none' or world.dungeon_counters[player] == 'off':
|
||||||
@@ -1562,12 +1663,28 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
# b - Big Key
|
# b - Big Key
|
||||||
# a - Small Key
|
# a - Small Key
|
||||||
#
|
#
|
||||||
|
dungeon_items_menu = 0x00
|
||||||
|
|
||||||
|
if world.doorShuffle[player] not in ['vanilla', 'basic']:
|
||||||
|
dungeon_items_menu |= 0x0F
|
||||||
|
|
||||||
|
if world.keyshuffle[player] not in ['none', 'universal']:
|
||||||
|
dungeon_items_menu |= 0x01
|
||||||
|
|
||||||
|
if world.bigkeyshuffle[player] != 'none':
|
||||||
|
dungeon_items_menu |= 0x02
|
||||||
|
|
||||||
enable_menu_map_check = (world.overworld_map[player] != 'default' and world.shuffle[player] != 'vanilla') or world.prizeshuffle[player] not in ['none', 'dungeon', 'nearby']
|
enable_menu_map_check = (world.overworld_map[player] != 'default' and world.shuffle[player] != 'vanilla') or world.prizeshuffle[player] not in ['none', 'dungeon', 'nearby']
|
||||||
rom.write_byte(0x180045, ((0x01 if world.keyshuffle[player] not in ['none', 'universal'] else 0x00)
|
if world.mapshuffle[player] != 'none' or enable_menu_map_check:
|
||||||
| (0x02 if world.bigkeyshuffle[player] != 'none' else 0x00)
|
dungeon_items_menu |= 0x04
|
||||||
| (0x04 if world.mapshuffle[player] != 'none' or enable_menu_map_check else 0x00)
|
|
||||||
| (0x08 if world.compassshuffle[player] != 'none' else 0x00) # free roaming items in menu
|
if world.compassshuffle[player] != 'none':
|
||||||
| (0x10 if world.logic[player] == 'nologic' else 0))) # boss icon
|
dungeon_items_menu |= 0x08
|
||||||
|
|
||||||
|
if world.logic[player] == 'nologic' or world.goal[player] == 'bosshunt':
|
||||||
|
dungeon_items_menu |= 0x10
|
||||||
|
|
||||||
|
rom.write_byte(0x180045, dungeon_items_menu)
|
||||||
|
|
||||||
def get_reveal_bytes(itemName):
|
def get_reveal_bytes(itemName):
|
||||||
if world.prizeshuffle[player] != 'wild':
|
if world.prizeshuffle[player] != 'wild':
|
||||||
@@ -1776,30 +1893,29 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
|
|
||||||
# set rom name
|
# set rom name
|
||||||
# 21 bytes
|
# 21 bytes
|
||||||
from Main import __version__
|
|
||||||
from OverworldShuffle import __version__ as ORVersion
|
|
||||||
if rom_header:
|
if rom_header:
|
||||||
if len(rom_header) > 21:
|
if len(rom_header) > 21:
|
||||||
raise Exception('ROM header too long. Max 21 bytes, found %d bytes.' % len(rom_header))
|
raise Exception('ROM header too long. Max 21 bytes, found %d bytes.' % len(rom_header))
|
||||||
elif '|' in rom_header:
|
|
||||||
gen, seedstring = rom_header.split('|', 1)
|
|
||||||
gen = f'{gen:<3}'
|
|
||||||
seedstring = f'{int(seedstring):09}' if seedstring.isdigit() else seedstring[:9]
|
|
||||||
rom.name = bytearray(f'OR{gen}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21]
|
|
||||||
elif len(rom_header) <= 9:
|
|
||||||
seedstring = f'{int(rom_header):09}' if rom_header.isdigit() else rom_header
|
|
||||||
rom.name = bytearray(f'OR{__version__.split("-")[0].replace(".","")[0:3]}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21]
|
|
||||||
else:
|
|
||||||
rom.name = bytearray(rom_header, 'utf8')[:21]
|
|
||||||
else:
|
|
||||||
seedstring = f'{world.seed:09}' if isinstance(world.seed, int) else world.seed
|
|
||||||
rom.name = bytearray(f'OR{__version__.split("-")[0].replace(".","")[0:3]}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21]
|
|
||||||
|
|
||||||
|
if world.players > 1 and len(rom_header) <= 12:
|
||||||
|
rom.name = bytearray(f"GK_{team + 1}_{player}_{rom_header}", 'utf8')
|
||||||
|
elif len(rom_header) <= 18:
|
||||||
|
rom.name = bytearray(f"GK_{rom_header}", 'utf8')
|
||||||
|
else:
|
||||||
|
rom.name = bytearray(rom_header, 'utf8')
|
||||||
|
else:
|
||||||
|
if world.players > 1:
|
||||||
|
rom.name = bytearray(f'GK_{team + 1}_{player}_{world.seed}', 'utf8')
|
||||||
|
else:
|
||||||
|
rom.name = bytearray(f'GK_{world.seed}', 'utf8')
|
||||||
|
|
||||||
|
rom.name = rom.name[:21]
|
||||||
rom.name.extend([0] * (21 - len(rom.name)))
|
rom.name.extend([0] * (21 - len(rom.name)))
|
||||||
rom.write_bytes(0x7FC0, rom.name)
|
rom.write_bytes(0x7FC0, rom.name)
|
||||||
|
|
||||||
rom.write_bytes(0x138010, bytearray(__version__, 'utf8'))
|
rom.write_bytes(0x138010, bytearray(DRVersion, 'utf8'))
|
||||||
rom.write_bytes(0x150010, bytearray(ORVersion, 'utf8'))
|
rom.write_bytes(0x150010, bytearray(ORVersion, 'utf8'))
|
||||||
|
rom.write_bytes(0x1CEEF0, bytearray(GKVersion, 'utf8'))
|
||||||
|
|
||||||
# set player names
|
# set player names
|
||||||
for p in range(1, min(world.players, 255) + 1):
|
for p in range(1, min(world.players, 255) + 1):
|
||||||
@@ -2673,12 +2789,18 @@ def write_strings(rom, world, player, team):
|
|||||||
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." % int(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." % int(world.treasure_hunt_count[player])
|
||||||
elif world.goal[player] == 'ganonhunt':
|
elif world.goal[player] == 'ganonhunt':
|
||||||
tt['sign_ganon'] = 'Go find the Triforce pieces to beat Ganon'
|
tt['sign_ganon'] = 'Go find the Triforce pieces to beat Ganon'
|
||||||
|
elif world.goal[player] == 'bosshunt':
|
||||||
|
bosshunt_count = '%d guardian%s of %sdungeons' % \
|
||||||
|
(world.bosses_ganon[player],
|
||||||
|
'' if world.bosses_ganon[player] == 1 else 's',
|
||||||
|
'' if world.bosshunt_include_agas[player] else 'prize ')
|
||||||
|
tt['sign_ganon'] = 'To beat Ganon you must defeat %s.' % bosshunt_count
|
||||||
elif world.goal[player] == 'completionist':
|
elif world.goal[player] == 'completionist':
|
||||||
tt['sign_ganon'] = 'Ganon only respects those who have done everything'
|
tt['sign_ganon'] = 'Ganon only respects those who have done everything'
|
||||||
tt['ganon_fall_in'] = Ganon1_texts[random.randint(0, len(Ganon1_texts) - 1)]
|
tt['ganon_fall_in'] = Ganon1_texts[random.randint(0, len(Ganon1_texts) - 1)]
|
||||||
tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!'
|
tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!'
|
||||||
tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!'
|
tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!'
|
||||||
|
|
||||||
def get_custom_goal_text(type):
|
def get_custom_goal_text(type):
|
||||||
goal_text = world.custom_goals[player][type]['goaltext']
|
goal_text = world.custom_goals[player][type]['goaltext']
|
||||||
placeholder_count = goal_text.count('%d')
|
placeholder_count = goal_text.count('%d')
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from enum import Enum, unique
|
from enum import Enum, unique
|
||||||
|
|
||||||
from Tables import door_pair_offset_table
|
from Tables import door_pair_offset_table
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,18 +3,28 @@ import logging
|
|||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
import OverworldGlitchRules
|
import OverworldGlitchRules
|
||||||
from BaseClasses import CollectionState, RegionType, DoorType, Entrance, CrystalBarrier, KeyRuleType, LocationType, Terrain
|
from BaseClasses import (
|
||||||
from BaseClasses import PotFlags
|
CollectionState,
|
||||||
|
CrystalBarrier,
|
||||||
|
DoorType,
|
||||||
|
Entrance,
|
||||||
|
KeyRuleType,
|
||||||
|
LocationType,
|
||||||
|
PotFlags,
|
||||||
|
RegionType,
|
||||||
|
Terrain,
|
||||||
|
)
|
||||||
from Dungeons import dungeon_table
|
from Dungeons import dungeon_table
|
||||||
from RoomData import DoorKind
|
|
||||||
from OWEdges import OWExitTypes
|
|
||||||
from OverworldGlitchRules import overworld_glitches_rules
|
from OverworldGlitchRules import overworld_glitches_rules
|
||||||
from UnderworldGlitchRules import underworld_glitches_rules
|
from OWEdges import OWExitTypes
|
||||||
|
from RoomData import DoorKind
|
||||||
from source.logic.Rule import RuleFactory
|
|
||||||
from source.dungeon.EnemyList import EnemySprite, Sprite
|
from source.dungeon.EnemyList import EnemySprite, Sprite
|
||||||
from source.enemizer.EnemyLogic import special_rules_check, special_rules_for_region, defeat_rule_single
|
from source.enemizer.EnemyLogic import and_rule as and_rule_new
|
||||||
from source.enemizer.EnemyLogic import defeat_rule_multiple, and_rule as and_rule_new, or_rule as or_rule_new
|
from source.enemizer.EnemyLogic import defeat_rule_multiple, defeat_rule_single
|
||||||
|
from source.enemizer.EnemyLogic import or_rule as or_rule_new
|
||||||
|
from source.enemizer.EnemyLogic import special_rules_check, special_rules_for_region
|
||||||
|
from source.logic.Rule import RuleFactory
|
||||||
|
from UnderworldGlitchRules import underworld_glitches_rules
|
||||||
|
|
||||||
|
|
||||||
def set_rules(world, player):
|
def set_rules(world, player):
|
||||||
@@ -80,6 +90,15 @@ def set_rules(world, player):
|
|||||||
add_rule(world.get_location('Ganon', player), lambda state: state.has_crystals(world.crystals_needed_for_ganon[player], player))
|
add_rule(world.get_location('Ganon', player), lambda state: state.has_crystals(world.crystals_needed_for_ganon[player], player))
|
||||||
elif world.goal[player] == 'ganonhunt':
|
elif world.goal[player] == 'ganonhunt':
|
||||||
add_rule(world.get_location('Ganon', player), lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player]))
|
add_rule(world.get_location('Ganon', player), lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player]))
|
||||||
|
elif world.goal[player] == 'bosshunt':
|
||||||
|
if world.bosshunt_include_agas[player]:
|
||||||
|
add_rule(world.get_location('Ganon', player), lambda state:
|
||||||
|
state.item_count('Beat Agahnim 1', player) +
|
||||||
|
state.item_count('Beat Agahnim 2', player) +
|
||||||
|
state.item_count('Beat Boss', player) >= world.bosses_ganon[player])
|
||||||
|
else:
|
||||||
|
add_rule(world.get_location('Ganon', player), lambda state:
|
||||||
|
state.item_count('Beat Boss', player) >= world.bosses_ganon[player])
|
||||||
elif world.goal[player] == 'completionist':
|
elif world.goal[player] == 'completionist':
|
||||||
add_rule(world.get_location('Ganon', player), lambda state: state.everything(player))
|
add_rule(world.get_location('Ganon', player), lambda state: state.everything(player))
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
|
import argparse
|
||||||
|
import concurrent.futures
|
||||||
|
import multiprocessing
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import multiprocessing
|
|
||||||
import concurrent.futures
|
|
||||||
import argparse
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
cpu_threads = multiprocessing.cpu_count()
|
cpu_threads = multiprocessing.cpu_count()
|
||||||
|
|||||||
+4
-4
@@ -1,10 +1,10 @@
|
|||||||
|
import argparse
|
||||||
|
import concurrent.futures
|
||||||
|
import csv
|
||||||
|
import multiprocessing
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import multiprocessing
|
|
||||||
import concurrent.futures
|
|
||||||
import argparse
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import csv
|
|
||||||
|
|
||||||
cpu_threads = multiprocessing.cpu_count()
|
cpu_threads = multiprocessing.cpu_count()
|
||||||
py_version = f"{sys.version_info.major}.{sys.version_info.minor}"
|
py_version = f"{sys.version_info.major}.{sys.version_info.minor}"
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# -*- coding: UTF-8 -*-
|
# -*- coding: UTF-8 -*-
|
||||||
from collections import OrderedDict
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import warnings
|
import warnings
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
warnings.filterwarnings("ignore", category=SyntaxWarning)
|
warnings.filterwarnings("ignore", category=SyntaxWarning)
|
||||||
|
|
||||||
text_addresses = {'Pedestal': (0x180300, 256),
|
text_addresses = {'Pedestal': (0x180300, 256),
|
||||||
@@ -1780,7 +1781,7 @@ class TextTable(object):
|
|||||||
text['mastersword_pedestal_translated'] = CompressedTextMapper.convert("A test of strength: If you have 3 pendants, I'm yours.")
|
text['mastersword_pedestal_translated'] = CompressedTextMapper.convert("A test of strength: If you have 3 pendants, I'm yours.")
|
||||||
text['telepathic_tile_spectacle_rock'] = CompressedTextMapper.convert("{NOBORDER}\n{NOBORDER}\nUse the Mirror, or the Hookshot and Hammer, to get to Tower of Hera!")
|
text['telepathic_tile_spectacle_rock'] = CompressedTextMapper.convert("{NOBORDER}\n{NOBORDER}\nUse the Mirror, or the Hookshot and Hammer, to get to Tower of Hera!")
|
||||||
text['telepathic_tile_swamp_entrance'] = CompressedTextMapper.convert("{NOBORDER}\nDrain the floodgate to raise the water here!")
|
text['telepathic_tile_swamp_entrance'] = CompressedTextMapper.convert("{NOBORDER}\nDrain the floodgate to raise the water here!")
|
||||||
text['telepathic_tile_thieves_town_upstairs'] = CompressedTextMapper.convert("{NOBORDER}\nBlind hate's bright light.")
|
text['telepathic_tile_thieves_town_upstairs'] = CompressedTextMapper.convert("{NOBORDER}\nBlind hates bright light.")
|
||||||
text['telepathic_tile_misery_mire'] = CompressedTextMapper.convert("{NOBORDER}\nLighting 4 torches will open your way forward!")
|
text['telepathic_tile_misery_mire'] = CompressedTextMapper.convert("{NOBORDER}\nLighting 4 torches will open your way forward!")
|
||||||
text['hylian_text_2'] = CompressedTextMapper.convert("%%^= %==%\n ^ =%^=\n==%= ^^%^")
|
text['hylian_text_2'] = CompressedTextMapper.convert("%%^= %==%\n ^ =%^=\n==%= ^^%^")
|
||||||
text['desert_entry_translated'] = CompressedTextMapper.convert("Kneel before this stone, and magic will move around you.")
|
text['desert_entry_translated'] = CompressedTextMapper.convert("Kneel before this stone, and magic will move around you.")
|
||||||
@@ -2014,7 +2015,7 @@ class TextTable(object):
|
|||||||
text['thief_desert_rupee_cave'] = CompressedTextMapper.convert("So you, like, busted down my door, and are being a jerk by talking to me? Normally I would be angry and make you pay for it, but I bet you're just going to break all my pots and steal my 50 rupees.")
|
text['thief_desert_rupee_cave'] = CompressedTextMapper.convert("So you, like, busted down my door, and are being a jerk by talking to me? Normally I would be angry and make you pay for it, but I bet you're just going to break all my pots and steal my 50 rupees.")
|
||||||
text['thief_ice_rupee_cave'] = CompressedTextMapper.convert("I'm a rupee pot farmer. One day I will take over the world with my skillz. Have you met my brother in the desert? He's way richer than I am.")
|
text['thief_ice_rupee_cave'] = CompressedTextMapper.convert("I'm a rupee pot farmer. One day I will take over the world with my skillz. Have you met my brother in the desert? He's way richer than I am.")
|
||||||
text['telepathic_tile_south_east_darkworld_cave'] = CompressedTextMapper.convert("~~ dev cave ~~\n no farming\n required")
|
text['telepathic_tile_south_east_darkworld_cave'] = CompressedTextMapper.convert("~~ dev cave ~~\n no farming\n required")
|
||||||
text['cukeman'] = CompressedTextMapper.convert("Did you hear that Veetorp beat ajneb174 in a 1 on 1 race at AGDQ?")
|
text['cukeman'] = CompressedTextMapper.convert("Trans rights!")
|
||||||
text['cukeman_2'] = CompressedTextMapper.convert("You found Shabadoo, huh?\nNiiiiice.")
|
text['cukeman_2'] = CompressedTextMapper.convert("You found Shabadoo, huh?\nNiiiiice.")
|
||||||
text['potion_shop_no_cash'] = CompressedTextMapper.convert("Yo! I'm not running a charity here.")
|
text['potion_shop_no_cash'] = CompressedTextMapper.convert("Yo! I'm not running a charity here.")
|
||||||
text['kakariko_powdered_chicken'] = CompressedTextMapper.convert("Smallhacker…\n\n\nWas hiding, you found me!\n\n\nOkay, you can leave now.")
|
text['kakariko_powdered_chicken'] = CompressedTextMapper.convert("Smallhacker…\n\n\nWas hiding, you found me!\n\n\nOkay, you can leave now.")
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import functools
|
import functools
|
||||||
from BaseClasses import Entrance, DoorType, Door
|
|
||||||
from DoorShuffle import connect_simple_door
|
|
||||||
import Rules
|
import Rules
|
||||||
|
from BaseClasses import Door, DoorType, Entrance
|
||||||
|
from DoorShuffle import connect_simple_door
|
||||||
|
|
||||||
kikiskip_spots = [
|
kikiskip_spots = [
|
||||||
("Kiki Skip", "Spectacle Rock Cave (Bottom)", "Palace of Darkness Portal")
|
("Kiki Skip", "Spectacle Rock Cave (Bottom)", "Palace of Darkness Portal")
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
import fileinput
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import urllib.parse
|
||||||
|
import urllib.request
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from math import factorial
|
from hashlib import md5
|
||||||
from itertools import count
|
from itertools import count
|
||||||
import fileinput
|
from math import factorial
|
||||||
|
|
||||||
import urllib.request
|
|
||||||
import urllib.parse
|
|
||||||
import yaml
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
def int16_as_bytes(value):
|
def int16_as_bytes(value):
|
||||||
value = value & 0xFFFF
|
value = value & 0xFFFF
|
||||||
@@ -102,31 +103,13 @@ def close_console():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def make_new_base2current(old_rom='Zelda no Densetsu - Kamigami no Triforce (Japan).sfc', new_rom='working.sfc'):
|
def get_new_romhash(new_rom='working.sfc'):
|
||||||
from collections import OrderedDict
|
|
||||||
import json
|
|
||||||
import hashlib
|
|
||||||
with open(old_rom, 'rb') as stream:
|
|
||||||
old_rom_data = bytearray(stream.read())
|
|
||||||
with open(new_rom, 'rb') as stream:
|
with open(new_rom, 'rb') as stream:
|
||||||
new_rom_data = bytearray(stream.read())
|
new_rom_data = bytearray(stream.read())
|
||||||
# extend to 2 mb
|
|
||||||
old_rom_data.extend(bytearray([0x00] * (2097152 - len(old_rom_data))))
|
|
||||||
|
|
||||||
out_data = OrderedDict()
|
basemd5 = md5()
|
||||||
for idx, old in enumerate(old_rom_data):
|
|
||||||
new = new_rom_data[idx]
|
|
||||||
if old != new:
|
|
||||||
out_data[idx] = [int(new)]
|
|
||||||
for offset in reversed(list(out_data.keys())):
|
|
||||||
if offset - 1 in out_data:
|
|
||||||
out_data[offset-1].extend(out_data.pop(offset))
|
|
||||||
with open('data/base2current.json', 'wt') as outfile:
|
|
||||||
json.dump([{key: value} for key, value in out_data.items()], outfile, separators=(",", ":"))
|
|
||||||
|
|
||||||
basemd5 = hashlib.md5()
|
|
||||||
basemd5.update(new_rom_data)
|
basemd5.update(new_rom_data)
|
||||||
return "New Rom Hash: " + basemd5.hexdigest()
|
return basemd5.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def kth_combination(k, l, r):
|
def kth_combination(k, l, r):
|
||||||
@@ -768,18 +751,18 @@ class bidict(dict):
|
|||||||
super(bidict, self).__init__(*args, **kwargs)
|
super(bidict, self).__init__(*args, **kwargs)
|
||||||
self.inverse = {}
|
self.inverse = {}
|
||||||
for key, value in self.items():
|
for key, value in self.items():
|
||||||
self.inverse.setdefault(value,[]).append(key)
|
self.inverse.setdefault(value,[]).append(key)
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
if key in self:
|
if key in self:
|
||||||
self.inverse[self[key]].remove(key)
|
self.inverse[self[key]].remove(key)
|
||||||
super(bidict, self).__setitem__(key, value)
|
super(bidict, self).__setitem__(key, value)
|
||||||
self.inverse.setdefault(value,[]).append(key)
|
self.inverse.setdefault(value,[]).append(key)
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key):
|
||||||
value = self[key]
|
value = self[key]
|
||||||
self.inverse.setdefault(value,[]).remove(key)
|
self.inverse.setdefault(value,[]).remove(key)
|
||||||
if value in self.inverse and not self.inverse[value]:
|
if value in self.inverse and not self.inverse[value]:
|
||||||
del self.inverse[value]
|
del self.inverse[value]
|
||||||
super(bidict, self).__delitem__(key)
|
super(bidict, self).__delitem__(key)
|
||||||
|
|
||||||
@@ -787,12 +770,11 @@ class bidict(dict):
|
|||||||
class HexInt(int): pass
|
class HexInt(int): pass
|
||||||
|
|
||||||
def hex_representer(dumper, data):
|
def hex_representer(dumper, data):
|
||||||
import yaml
|
|
||||||
return yaml.ScalarNode('tag:yaml.org,2002:int', f"{data:#0{4}x}")
|
return yaml.ScalarNode('tag:yaml.org,2002:int', f"{data:#0{4}x}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print(make_new_base2current())
|
print("New Rom Hash:", get_new_romhash())
|
||||||
# read_entrance_data(old_rom=sys.argv[1])
|
# read_entrance_data(old_rom=sys.argv[1])
|
||||||
# room_palette_data(old_rom=sys.argv[1])
|
# room_palette_data(old_rom=sys.argv[1])
|
||||||
# extract_data_from_us_rom(sys.argv[1])
|
# extract_data_from_us_rom(sys.argv[1])
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
GKVersion = '1.0.0'
|
||||||
|
ORVersion = '0.6.1.7'
|
||||||
|
DRVersion = '1.5.0-u'
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
"""collections_extended contains a few extra basic data structures."""
|
"""collections_extended contains a few extra basic data structures."""
|
||||||
from ._compat import Collection
|
from ._compat import Collection
|
||||||
from .bags import bag, frozenbag
|
from .bags import bag, frozenbag
|
||||||
from .setlists import setlist, frozensetlist
|
|
||||||
from .bijection import bijection
|
from .bijection import bijection
|
||||||
from .range_map import RangeMap, MappedRange
|
from .range_map import MappedRange, RangeMap
|
||||||
|
from .setlists import frozensetlist, setlist
|
||||||
|
|
||||||
__version__ = '1.0.2'
|
__version__ = '1.0.2'
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ else:
|
|||||||
|
|
||||||
|
|
||||||
if sys.version_info < (3, 6):
|
if sys.version_info < (3, 6):
|
||||||
from collections import Sized, Iterable, Container
|
from collections import Container, Iterable, Sized
|
||||||
|
|
||||||
def _check_methods(C, *methods):
|
def _check_methods(C, *methods):
|
||||||
mro = C.__mro__
|
mro = C.__mro__
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""Bag class definitions."""
|
"""Bag class definitions."""
|
||||||
import heapq
|
import heapq
|
||||||
|
from collections import Hashable, MutableSet, Set
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from collections import Set, MutableSet, Hashable
|
|
||||||
|
|
||||||
from . import _compat
|
from . import _compat
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"""Class definition for bijection."""
|
"""Class definition for bijection."""
|
||||||
|
|
||||||
from collections import MutableMapping, Mapping
|
from collections import Mapping, MutableMapping
|
||||||
|
|
||||||
|
|
||||||
class bijection(MutableMapping):
|
class bijection(MutableMapping):
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
"""RangeMap class definition."""
|
"""RangeMap class definition."""
|
||||||
from bisect import bisect_left, bisect_right
|
from bisect import bisect_left, bisect_right
|
||||||
from collections import namedtuple, Mapping, MappingView, Set
|
from collections import Mapping, MappingView, Set, namedtuple
|
||||||
|
|
||||||
|
|
||||||
# Used to mark unmapped ranges
|
# Used to mark unmapped ranges
|
||||||
_empty = object()
|
_empty = object()
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
"""Setlist class definitions."""
|
"""Setlist class definitions."""
|
||||||
import random as random_
|
import random as random_
|
||||||
|
|
||||||
from collections import (
|
from collections import (
|
||||||
Sequence,
|
Hashable,
|
||||||
Set,
|
MutableSequence,
|
||||||
MutableSequence,
|
MutableSet,
|
||||||
MutableSet,
|
Sequence,
|
||||||
Hashable,
|
Set,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import _util
|
from . import _util
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
from OverworldShuffle import __version__ as OWVersion
|
|
||||||
import os
|
|
||||||
|
|
||||||
with(open(os.path.join("resources","app","meta","manifests","app_version.txt"),"w+")) as f:
|
|
||||||
f.write(OWVersion)
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import sys
|
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
sys.path.append(os.path.join(sys._MEIPASS, "ext"))
|
sys.path.append(os.path.join(sys._MEIPASS, "ext"))
|
||||||
|
|||||||
Binary file not shown.
+4
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "alttpr-python"
|
name = "alttpr-python"
|
||||||
version = "0.2.0"
|
version = "1.0.0"
|
||||||
description = "Python ALttP Randomizer"
|
description = "Python ALttP Randomizer"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.7"
|
requires-python = ">=3.7"
|
||||||
@@ -14,3 +14,6 @@ dependencies = [
|
|||||||
"pyyaml>=6.0.1",
|
"pyyaml>=6.0.1",
|
||||||
"websockets>=11.0.3",
|
"websockets>=11.0.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[tool.isort]
|
||||||
|
profile = "black"
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
"trinity",
|
"trinity",
|
||||||
"crystals",
|
"crystals",
|
||||||
"ganonhunt",
|
"ganonhunt",
|
||||||
|
"bosshunt",
|
||||||
"completionist",
|
"completionist",
|
||||||
"sanctuary"
|
"sanctuary"
|
||||||
]
|
]
|
||||||
@@ -299,6 +300,27 @@
|
|||||||
"random"
|
"random"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"bosses_ganon": {
|
||||||
|
"choices": [
|
||||||
|
"12",
|
||||||
|
"11",
|
||||||
|
"10",
|
||||||
|
"9",
|
||||||
|
"8",
|
||||||
|
"7",
|
||||||
|
"6",
|
||||||
|
"5",
|
||||||
|
"4",
|
||||||
|
"3",
|
||||||
|
"2",
|
||||||
|
"1",
|
||||||
|
"0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"bosshunt_include_agas": {
|
||||||
|
"action": "store_true",
|
||||||
|
"type": "bool"
|
||||||
|
},
|
||||||
"crystals_gt": {
|
"crystals_gt": {
|
||||||
"choices": [
|
"choices": [
|
||||||
"7",
|
"7",
|
||||||
@@ -431,6 +453,21 @@
|
|||||||
"wild"
|
"wild"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"showloot": {
|
||||||
|
"choices": [
|
||||||
|
"never",
|
||||||
|
"presence",
|
||||||
|
"compass",
|
||||||
|
"always"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"showmap": {
|
||||||
|
"choices": [
|
||||||
|
"visited",
|
||||||
|
"map",
|
||||||
|
"always"
|
||||||
|
]
|
||||||
|
},
|
||||||
"keysanity": {
|
"keysanity": {
|
||||||
"action": "store_true",
|
"action": "store_true",
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"cli": {
|
"cli": {
|
||||||
"yes": "Yes",
|
"yes": "Yes",
|
||||||
"no": "No",
|
"no": "No",
|
||||||
"app.title": "ALttP Overworld Randomizer Version %s : --seed %s --code %s",
|
"app.title": "ALttP GwaaKiwi Randomizer Version %s : --seed %s",
|
||||||
"version": "Version",
|
"version": "Version",
|
||||||
"seed": "Seed",
|
"seed": "Seed",
|
||||||
"player": "Player",
|
"player": "Player",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import os # for env vars
|
import os # for env vars
|
||||||
import stat # file statistics
|
import stat # file statistics
|
||||||
import sys # default system info
|
import sys # default system info
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import distro
|
import distro
|
||||||
except ModuleNotFoundError as e:
|
except ModuleNotFoundError as e:
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import common
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import urllib.request, ssl
|
import ssl
|
||||||
import subprocess # do stuff at the shell level
|
import subprocess # do stuff at the shell level
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
import common
|
||||||
|
|
||||||
env = common.prepare_env()
|
env = common.prepare_env()
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
# import modules
|
# import modules
|
||||||
import common # app common functions
|
import json # json manipulation
|
||||||
|
import os # for os data, filesystem manipulation
|
||||||
|
import subprocess # for running shell commands
|
||||||
|
import sys # for system commands
|
||||||
|
import traceback # for errors
|
||||||
|
|
||||||
import json # json manipulation
|
import common # app common functions
|
||||||
import os # for os data, filesystem manipulation
|
|
||||||
import subprocess # for running shell commands
|
|
||||||
import sys # for system commands
|
|
||||||
import traceback # for errors
|
|
||||||
|
|
||||||
# get env
|
# get env
|
||||||
env = common.prepare_env() # get environment variables
|
env = common.prepare_env() # get environment variables
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import common
|
import os # for env vars
|
||||||
import os # for env vars
|
import sys # for path
|
||||||
import sys # for path
|
import urllib.request # for downloads
|
||||||
import urllib.request # for downloads
|
|
||||||
from shutil import unpack_archive
|
from shutil import unpack_archive
|
||||||
|
|
||||||
|
import common
|
||||||
|
|
||||||
# only do stuff if we don't have a UPX folder
|
# only do stuff if we don't have a UPX folder
|
||||||
|
|
||||||
if not os.path.isdir(os.path.join(".","upx")):
|
if not os.path.isdir(os.path.join(".","upx")):
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import subprocess # do stuff at the shell level
|
|
||||||
import os
|
import os
|
||||||
|
import subprocess # do stuff at the shell level
|
||||||
|
|
||||||
|
|
||||||
def git_clean(clean_ignored=True, clean_user=False):
|
def git_clean(clean_ignored=True, clean_user=False):
|
||||||
excludes = [
|
excludes = [
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import common
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import subprocess # do stuff at the shell level
|
import subprocess # do stuff at the shell level
|
||||||
|
|
||||||
|
import common
|
||||||
|
|
||||||
env = common.prepare_env()
|
env = common.prepare_env()
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ import json
|
|||||||
import os
|
import os
|
||||||
import ssl
|
import ssl
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import yaml
|
|
||||||
from json.decoder import JSONDecodeError
|
from json.decoder import JSONDecodeError
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
allACTIONS = {}
|
allACTIONS = {}
|
||||||
listACTIONS = []
|
listACTIONS = []
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import install
|
|
||||||
import get_get_pip
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
import get_get_pip
|
||||||
|
import install
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(add_help=False)
|
parser = argparse.ArgumentParser(add_help=False)
|
||||||
parser.add_argument('--py', default=0)
|
parser.add_argument('--py', default=0)
|
||||||
parser.add_argument('--user', default=False, action="store_true")
|
parser.add_argument('--user', default=False, action="store_true")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
def get_py_path():
|
def get_py_path():
|
||||||
user_paths = os.environ["PATH"].split(os.pathsep)
|
user_paths = os.environ["PATH"].split(os.pathsep)
|
||||||
(python,py) = ("","")
|
(python,py) = ("","")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
import os # for env vars
|
||||||
|
from shutil import copy # file manipulation
|
||||||
|
|
||||||
import common
|
import common
|
||||||
import os # for env vars
|
|
||||||
from shutil import copy # file manipulation
|
|
||||||
|
|
||||||
env = common.prepare_env()
|
env = common.prepare_env()
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
Locate and prepare binary builds
|
Locate and prepare binary builds
|
||||||
"""
|
"""
|
||||||
# import distutils.dir_util # for copying trees
|
# import distutils.dir_util # for copying trees
|
||||||
import os # for env vars
|
import os # for env vars
|
||||||
|
from shutil import move # file manipulation
|
||||||
|
|
||||||
# import stat # for file stats
|
# import stat # for file stats
|
||||||
# import subprocess # do stuff at the shell level
|
# import subprocess # do stuff at the shell level
|
||||||
import common
|
import common
|
||||||
from shutil import move # file manipulation
|
|
||||||
|
|
||||||
env = common.prepare_env()
|
env = common.prepare_env()
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import distutils.dir_util # for copying trees
|
import distutils.dir_util # for copying trees
|
||||||
import os # for env vars
|
import os # for env vars
|
||||||
import stat # for file stats
|
import stat # for file stats
|
||||||
import subprocess # do stuff at the shell level
|
import subprocess # do stuff at the shell level
|
||||||
|
from shutil import copy, make_archive, move, rmtree # file manipulation
|
||||||
|
|
||||||
import common
|
import common
|
||||||
from git_clean import git_clean
|
from git_clean import git_clean
|
||||||
from shutil import copy, make_archive, move, rmtree # file manipulation
|
|
||||||
|
|
||||||
env = common.prepare_env() # get env vars
|
env = common.prepare_env() # get env vars
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import json
|
|||||||
import locale
|
import locale
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
class BabelFish():
|
class BabelFish():
|
||||||
def __init__(self,subpath=["resources","app","meta"],lang=None):
|
def __init__(self,subpath=["resources","app","meta"],lang=None):
|
||||||
localization_string = locale.getdefaultlocale()[0] #get set localization
|
localization_string = locale.getdefaultlocale()[0] #get set localization
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
import os
|
import os
|
||||||
import urllib.request
|
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import yaml
|
import urllib.request
|
||||||
from typing import Any
|
|
||||||
from yaml.representer import Representer
|
|
||||||
from Utils import HexInt, hex_representer
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
from yaml.representer import Representer
|
||||||
|
|
||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
from BaseClasses import LocationType, DoorType
|
from BaseClasses import DoorType, LocationType
|
||||||
from OverworldShuffle import default_flute_connections, flute_data
|
from OverworldShuffle import default_flute_connections, flute_data
|
||||||
from source.tools.MysteryUtils import roll_settings, get_weights
|
from source.tools.MysteryUtils import get_weights, roll_settings
|
||||||
|
from Utils import HexInt, hex_representer
|
||||||
|
|
||||||
|
|
||||||
class CustomSettings(object):
|
class CustomSettings(object):
|
||||||
|
|||||||
@@ -1,5 +1,20 @@
|
|||||||
from tkinter import Button, Canvas, Label, LabelFrame, Frame, PhotoImage, Scrollbar, Toplevel, LEFT, BOTTOM, X, RIGHT, TOP
|
|
||||||
import os
|
import os
|
||||||
|
from tkinter import (
|
||||||
|
BOTTOM,
|
||||||
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
TOP,
|
||||||
|
Button,
|
||||||
|
Canvas,
|
||||||
|
Frame,
|
||||||
|
Label,
|
||||||
|
LabelFrame,
|
||||||
|
PhotoImage,
|
||||||
|
Scrollbar,
|
||||||
|
Toplevel,
|
||||||
|
X,
|
||||||
|
)
|
||||||
|
|
||||||
from GuiUtils import ToolTips, set_icon
|
from GuiUtils import ToolTips, set_icon
|
||||||
from Utils import local_path
|
from Utils import local_path
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from enum import IntEnum
|
|
||||||
import random
|
import random
|
||||||
|
from enum import IntEnum
|
||||||
|
|
||||||
from Utils import int16_as_bytes, snes_to_pc
|
from Utils import int16_as_bytes, snes_to_pc
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,36 @@
|
|||||||
from tkinter import filedialog, messagebox, Button, Canvas, Label, LabelFrame, Frame, PhotoImage, Scrollbar, Toplevel, ALL, LEFT, BOTTOM, X, RIGHT, TOP, EW, NS
|
|
||||||
from glob import glob
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import shutil
|
import shutil
|
||||||
import ssl
|
import ssl
|
||||||
|
import webbrowser
|
||||||
|
from glob import glob
|
||||||
|
from tkinter import (
|
||||||
|
ALL,
|
||||||
|
BOTTOM,
|
||||||
|
EW,
|
||||||
|
LEFT,
|
||||||
|
NS,
|
||||||
|
RIGHT,
|
||||||
|
TOP,
|
||||||
|
Button,
|
||||||
|
Canvas,
|
||||||
|
Frame,
|
||||||
|
Label,
|
||||||
|
LabelFrame,
|
||||||
|
PhotoImage,
|
||||||
|
Scrollbar,
|
||||||
|
Toplevel,
|
||||||
|
X,
|
||||||
|
filedialog,
|
||||||
|
messagebox,
|
||||||
|
)
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
import webbrowser
|
|
||||||
from GuiUtils import ToolTips, set_icon, BackgroundTaskProgress
|
from GuiUtils import BackgroundTaskProgress, ToolTips, set_icon
|
||||||
from Rom import Sprite
|
from Rom import Sprite
|
||||||
from Utils import is_bundled, local_path, output_path, open_file
|
from Utils import is_bundled, local_path, open_file, output_path
|
||||||
|
|
||||||
|
|
||||||
class SpriteSelector(object):
|
class SpriteSelector(object):
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
from OverworldShuffle import __version__
|
|
||||||
OWR_VERSION = __version__
|
|
||||||
|
|
||||||
def write_appversion():
|
|
||||||
APP_VERSION = OWR_VERSION
|
|
||||||
if "-" in APP_VERSION:
|
|
||||||
APP_VERSION = APP_VERSION[:APP_VERSION.find("-")]
|
|
||||||
APP_VERSION_FILE = os.path.join(".","resources","app","meta","manifests","app_version.txt")
|
|
||||||
with open(APP_VERSION_FILE,"w") as f:
|
|
||||||
f.seek(0)
|
|
||||||
f.truncate()
|
|
||||||
f.write(APP_VERSION)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
write_appversion()
|
|
||||||
+44
-45
@@ -1,60 +1,59 @@
|
|||||||
import platform, sys, os, subprocess
|
import os
|
||||||
|
import platform
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
except ModuleNotFoundError as e:
|
except ModuleNotFoundError as e:
|
||||||
pass
|
pass
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from Main import __version__
|
from Versions import DRVersion, GKVersion, ORVersion
|
||||||
DR_VERSION = __version__
|
|
||||||
|
|
||||||
from OverworldShuffle import __version__
|
|
||||||
OWR_VERSION = __version__
|
|
||||||
|
|
||||||
PROJECT_NAME = "ALttP Overworld Randomizer"
|
|
||||||
|
|
||||||
def diagpad(str):
|
def diagpad(str):
|
||||||
return str.ljust(len(f"{PROJECT_NAME} Version") + 5,'.')
|
return str.ljust(40, '.')
|
||||||
|
|
||||||
def output():
|
def output():
|
||||||
lines = [
|
lines = [
|
||||||
f"{PROJECT_NAME} Diagnostics",
|
"ALttP GwaaKiwi Randomizer Diagnostics",
|
||||||
"=================================",
|
"=====================================",
|
||||||
diagpad("UTC Time") + str(datetime.datetime.now(datetime.UTC))[:19],
|
diagpad("UTC Time") + str(datetime.datetime.now(datetime.UTC))[:19],
|
||||||
diagpad("ALttP Door Randomizer Version") + DR_VERSION,
|
diagpad("ALttP Door Randomizer Version") + DRVersion,
|
||||||
diagpad(f"{PROJECT_NAME} Version") + OWR_VERSION,
|
diagpad("ALttP Overworld Randomizer Version") + ORVersion,
|
||||||
diagpad("Python Version") + platform.python_version()
|
diagpad("ALttP GwaaKiwi Randomizer Version") + GKVersion,
|
||||||
]
|
diagpad("Python Version") + platform.python_version(),
|
||||||
lines.append(diagpad("OS Version") + "%s %s" % (platform.system(), platform.release()))
|
]
|
||||||
if hasattr(sys, "executable"):
|
lines.append(diagpad("OS Version") + "%s %s" % (platform.system(), platform.release()))
|
||||||
lines.append(diagpad("Executable") + sys.executable)
|
if hasattr(sys, "executable"):
|
||||||
lines.append(diagpad("Build Date") + platform.python_build()[1])
|
lines.append(diagpad("Executable") + sys.executable)
|
||||||
lines.append(diagpad("Compiler") + platform.python_compiler())
|
lines.append(diagpad("Build Date") + platform.python_build()[1])
|
||||||
if hasattr(sys, "api_version"):
|
lines.append(diagpad("Compiler") + platform.python_compiler())
|
||||||
lines.append(diagpad("Python API") + str(sys.api_version))
|
if hasattr(sys, "api_version"):
|
||||||
if hasattr(os, "sep"):
|
lines.append(diagpad("Python API") + str(sys.api_version))
|
||||||
lines.append(diagpad("Filepath Separator") + os.sep)
|
if hasattr(os, "sep"):
|
||||||
if hasattr(os, "pathsep"):
|
lines.append(diagpad("Filepath Separator") + os.sep)
|
||||||
lines.append(diagpad("Path Env Separator") + os.pathsep)
|
if hasattr(os, "pathsep"):
|
||||||
lines.append("")
|
lines.append(diagpad("Path Env Separator") + os.pathsep)
|
||||||
lines.append("Packages")
|
lines.append("")
|
||||||
lines.append("--------")
|
|
||||||
'''
|
|
||||||
#this breaks when run from the .exe
|
|
||||||
reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'])
|
|
||||||
installed_packages = [r.decode() for r in reqs.split()]
|
|
||||||
for pkg in installed_packages:
|
|
||||||
pkg = pkg.split("==")
|
|
||||||
lines.append(diagpad(pkg[0]) + pkg[1])
|
|
||||||
'''
|
|
||||||
installed_packages = []
|
|
||||||
installed_packages = [str(d) for d in pkg_resources.working_set] #this doesn't work from the .exe either, but it doesn't crash the program
|
|
||||||
installed_packages.sort()
|
|
||||||
for pkg in installed_packages:
|
|
||||||
pkg = pkg.split(' ')
|
|
||||||
lines.append(diagpad(pkg[0]) + pkg[1])
|
|
||||||
|
|
||||||
return lines
|
lines.append("Packages")
|
||||||
|
lines.append("--------")
|
||||||
|
reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'])
|
||||||
|
installed_packages = [r.decode() for r in reqs.split()]
|
||||||
|
for pkg in installed_packages:
|
||||||
|
pkg = pkg.split("==")
|
||||||
|
lines.append(diagpad(pkg[0]) + pkg[1])
|
||||||
|
|
||||||
|
installed_packages = []
|
||||||
|
installed_packages = [str(d) for d in pkg_resources.working_set]
|
||||||
|
installed_packages.sort()
|
||||||
|
for pkg in installed_packages:
|
||||||
|
pkg = pkg.split(' ')
|
||||||
|
lines.append(diagpad(pkg[0]) + pkg[1])
|
||||||
|
|
||||||
|
return lines
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
raise AssertionError(f"Called main() on utility library {__file__}")
|
raise AssertionError(f"Called main() on utility library {__file__}")
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
import RaceRandom as random
|
|
||||||
import collections
|
import collections
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from BaseClasses import CrystalBarrier, DoorType, Hook, RegionType, Sector
|
import RaceRandom as random
|
||||||
from BaseClasses import hook_from_door, flooded_keys
|
from BaseClasses import (
|
||||||
from Regions import location_events, flooded_keys_reverse
|
CrystalBarrier,
|
||||||
|
DoorType,
|
||||||
|
Hook,
|
||||||
|
RegionType,
|
||||||
|
Sector,
|
||||||
|
flooded_keys,
|
||||||
|
hook_from_door,
|
||||||
|
)
|
||||||
|
from Regions import flooded_keys_reverse, location_events
|
||||||
|
|
||||||
|
|
||||||
def pre_validate(builder, entrance_region_names, split_dungeon, world, player):
|
def pre_validate(builder, entrance_region_names, split_dungeon, world, player):
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from collections import defaultdict, deque
|
|
||||||
import typing
|
import typing
|
||||||
|
from collections import defaultdict, deque
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from yaml.representer import Representer
|
from yaml.representer import Representer
|
||||||
@@ -13,9 +13,9 @@ import RaceRandom as random
|
|||||||
from BaseClasses import Location, LocationType, RegionType
|
from BaseClasses import Location, LocationType, RegionType
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
from PotShuffle import key_drop_special
|
from PotShuffle import key_drop_special
|
||||||
from Utils import snes_to_pc, pc_to_snes, int16_as_bytes
|
|
||||||
|
|
||||||
from source.overworld.EntranceData import door_addresses
|
from source.overworld.EntranceData import door_addresses
|
||||||
|
from Utils import int16_as_bytes, pc_to_snes, snes_to_pc
|
||||||
|
|
||||||
|
|
||||||
class EnemyStats:
|
class EnemyStats:
|
||||||
def __init__(self, sprite, static, drop_flag=False, prize_pack: typing.Union[tuple, int] = 0,
|
def __init__(self, sprite, static, drop_flag=False, prize_pack: typing.Union[tuple, int] = 0,
|
||||||
|
|||||||
@@ -3,9 +3,8 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
from enum import IntFlag as FastEnum
|
from enum import IntFlag as FastEnum
|
||||||
|
|
||||||
|
|
||||||
from RoomData import DoorKind, Position
|
from RoomData import DoorKind, Position
|
||||||
from source.dungeon.RoomObject import RoomObject, DoorObject
|
from source.dungeon.RoomObject import DoorObject, RoomObject
|
||||||
|
|
||||||
|
|
||||||
class Room:
|
class Room:
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
from Utils import snes_to_pc
|
from source.dungeon.EnemyList import EnemySprite, Sprite, SpriteType
|
||||||
|
from source.dungeon.RoomList import Room0006, boss_rooms, gt_boss_room
|
||||||
from source.dungeon.EnemyList import EnemySprite, SpriteType, Sprite
|
|
||||||
from source.dungeon.RoomList import boss_rooms, gt_boss_room, Room0006
|
|
||||||
from source.dungeon.RoomObject import RoomObject
|
from source.dungeon.RoomObject import RoomObject
|
||||||
from source.enemizer.SpriteSheets import required_boss_sheets
|
from source.enemizer.SpriteSheets import required_boss_sheets
|
||||||
|
from Utils import snes_to_pc
|
||||||
|
|
||||||
|
|
||||||
def get_dungeon_boss_room(dungeon_name, level):
|
def get_dungeon_boss_room(dungeon_name, level):
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
import RaceRandom as random
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from Utils import snes_to_pc
|
|
||||||
|
|
||||||
from source.dungeon.EnemyList import SpriteType, EnemySprite, sprite_translation
|
import RaceRandom as random
|
||||||
|
from source.dungeon.EnemyList import EnemySprite, SpriteType, sprite_translation
|
||||||
from source.dungeon.RoomList import Room010C
|
from source.dungeon.RoomList import Room010C
|
||||||
from source.enemizer.SpecialEnemyModes import set_mimics, write_mimic_changes
|
from source.enemizer.SpecialEnemyModes import set_mimics, write_mimic_changes
|
||||||
from source.enemizer.SpriteSheets import sub_group_choices, sheets_with_free_gfx
|
from source.enemizer.SpriteSheets import (
|
||||||
from source.enemizer.SpriteSheets import randomize_underworld_sprite_sheets, randomize_overworld_sprite_sheets
|
randomize_overworld_sprite_sheets,
|
||||||
|
randomize_underworld_sprite_sheets,
|
||||||
|
sheets_with_free_gfx,
|
||||||
|
sub_group_choices,
|
||||||
|
)
|
||||||
from source.enemizer.TilePattern import tile_patterns
|
from source.enemizer.TilePattern import tile_patterns
|
||||||
|
from Utils import snes_to_pc
|
||||||
|
|
||||||
shutter_sprites = {
|
shutter_sprites = {
|
||||||
0xb8: {0, 1, 2, 3, 4, 5}, 0xb: {4, 5, 6, 7, 8, 9}, 0x1b: {3, 4, 5}, 0x4b: {0, 3, 4}, 0x4: {9, 13, 14},
|
0xb8: {0, 1, 2, 3, 4, 5}, 0xb: {4, 5, 6, 7, 8, 9}, 0x1b: {3, 4, 5}, 0x4b: {0, 3, 4}, 0x4: {9, 13, 14},
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
from types import SimpleNamespace
|
|
||||||
from collections import Counter, defaultdict
|
from collections import Counter, defaultdict
|
||||||
|
from types import SimpleNamespace
|
||||||
|
|
||||||
from source.dungeon.EnemyList import enemy_names, SpriteType
|
|
||||||
from source.enemizer.Enemizer import randomize_underworld_rooms, randomize_overworld_enemies
|
|
||||||
from source.enemizer.SpriteSheets import randomize_underworld_sprite_sheets, randomize_overworld_sprite_sheets
|
|
||||||
from source.rom.DataTables import init_data_tables
|
|
||||||
from source.enemizer.DamageTables import DamageTable
|
|
||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
|
from source.dungeon.EnemyList import SpriteType, enemy_names
|
||||||
|
from source.enemizer.DamageTables import DamageTable
|
||||||
|
from source.enemizer.Enemizer import (
|
||||||
|
randomize_overworld_enemies,
|
||||||
|
randomize_underworld_rooms,
|
||||||
|
)
|
||||||
|
from source.enemizer.SpriteSheets import (
|
||||||
|
randomize_overworld_sprite_sheets,
|
||||||
|
randomize_underworld_sprite_sheets,
|
||||||
|
)
|
||||||
|
from source.rom.DataTables import init_data_tables
|
||||||
|
|
||||||
|
|
||||||
def calculate_odds():
|
def calculate_odds():
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ import math
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
|
|
||||||
from source.logic.Rule import RuleFactory
|
|
||||||
from source.dungeon.EnemyList import EnemySprite
|
from source.dungeon.EnemyList import EnemySprite
|
||||||
|
from source.logic.Rule import RuleFactory
|
||||||
|
|
||||||
|
|
||||||
# these are for drops only
|
# these are for drops only
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from source.dungeon.EnemyList import Sprite, EnemySprite
|
from source.dungeon.EnemyList import EnemySprite, Sprite
|
||||||
|
|
||||||
vanilla_sprites_ow = {}
|
vanilla_sprites_ow = {}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
|
from source.dungeon.EnemyList import (
|
||||||
|
EnemySprite,
|
||||||
|
SpriteType,
|
||||||
|
enemy_names,
|
||||||
|
sprite_translation,
|
||||||
|
)
|
||||||
from Utils import snes_to_pc
|
from Utils import snes_to_pc
|
||||||
|
|
||||||
from source.dungeon.EnemyList import EnemySprite, SpriteType, sprite_translation, enemy_names
|
|
||||||
|
|
||||||
change_idx_1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 13, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 31, 32, 35, 38, 65, 66, 67, 68, 70, 71, 76, 77, 78, 81, 83, 89, 91, 92, 94, 97, 100, 101, 102, 103, 104, 105, 106, 107]
|
change_idx_1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 13, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 31, 32, 35, 38, 65, 66, 67, 68, 70, 71, 76, 77, 78, 81, 83, 89, 91, 92, 94, 97, 100, 101, 102, 103, 104, 105, 106, 107]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
import logging
|
import logging
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
import RaceRandom as random
|
|
||||||
|
|
||||||
from source.dungeon.EnemyList import EnemySprite, SpriteType, enemy_names, sprite_translation, overlord_names
|
import RaceRandom as random
|
||||||
|
from source.dungeon.EnemyList import (
|
||||||
|
EnemySprite,
|
||||||
|
SpriteType,
|
||||||
|
enemy_names,
|
||||||
|
overlord_names,
|
||||||
|
sprite_translation,
|
||||||
|
)
|
||||||
from source.dungeon.RoomConstants import *
|
from source.dungeon.RoomConstants import *
|
||||||
|
|
||||||
|
|
||||||
@@ -465,10 +471,6 @@ vanilla_sheets = [
|
|||||||
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00),
|
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00),
|
||||||
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00),
|
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00),
|
||||||
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x08), (0x5D, 0x49, 0x00, 0x52), (0x55, 0x49, 0x42, 0x43),
|
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x08), (0x5D, 0x49, 0x00, 0x52), (0x55, 0x49, 0x42, 0x43),
|
||||||
(0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50),
|
|
||||||
(0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x62, 0x63, 0x50),
|
|
||||||
(0x61, 0x62, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x56, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50),
|
|
||||||
(0x61, 0x56, 0x33, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
required_boss_sheets = {EnemySprite.ArmosKnight: 9, EnemySprite.Lanmolas: 11, EnemySprite.Moldorm: 12,
|
required_boss_sheets = {EnemySprite.ArmosKnight: 9, EnemySprite.Lanmolas: 11, EnemySprite.Moldorm: 12,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import os
|
|
||||||
import json
|
|
||||||
import codecs
|
import codecs
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
directory = './EnemizerCLI.Core/tiles'
|
directory = './EnemizerCLI.Core/tiles'
|
||||||
|
|||||||
@@ -1,15 +1,31 @@
|
|||||||
from tkinter import ttk, filedialog, messagebox, StringVar, Button, Entry, Frame, Label, E, W, LEFT, RIGHT, X, BOTTOM
|
|
||||||
from AdjusterMain import adjust, patch
|
|
||||||
from argparse import Namespace
|
|
||||||
from source.classes.SpriteSelector import SpriteSelector
|
|
||||||
from source.classes.ItemGfxSelector import ItemGfxSelector
|
|
||||||
import source.gui.widgets as widgets
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
from argparse import Namespace
|
||||||
|
from tkinter import (
|
||||||
|
BOTTOM,
|
||||||
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
Button,
|
||||||
|
E,
|
||||||
|
Entry,
|
||||||
|
Frame,
|
||||||
|
Label,
|
||||||
|
StringVar,
|
||||||
|
W,
|
||||||
|
X,
|
||||||
|
filedialog,
|
||||||
|
messagebox,
|
||||||
|
ttk,
|
||||||
|
)
|
||||||
|
|
||||||
|
import source.gui.widgets as widgets
|
||||||
|
from AdjusterMain import adjust, patch
|
||||||
|
from source.classes.ItemGfxSelector import ItemGfxSelector
|
||||||
|
from source.classes.SpriteSelector import SpriteSelector
|
||||||
from Utils import output_path
|
from Utils import output_path
|
||||||
|
|
||||||
|
|
||||||
def adjust_page(top, parent, settings):
|
def adjust_page(top, parent, settings):
|
||||||
# Adjust page
|
# Adjust page
|
||||||
self = ttk.Frame(parent)
|
self = ttk.Frame(parent)
|
||||||
|
|||||||
+19
-7
@@ -1,17 +1,29 @@
|
|||||||
from tkinter import ttk, messagebox, StringVar, Button, Entry, Frame, Label, LEFT, RIGHT, X
|
|
||||||
from argparse import Namespace
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
|
from argparse import Namespace
|
||||||
|
from tkinter import (
|
||||||
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
Button,
|
||||||
|
Entry,
|
||||||
|
Frame,
|
||||||
|
Label,
|
||||||
|
StringVar,
|
||||||
|
X,
|
||||||
|
messagebox,
|
||||||
|
ttk,
|
||||||
|
)
|
||||||
|
|
||||||
|
import source.classes.constants as CONST
|
||||||
|
import source.gui.widgets as widgets
|
||||||
from CLI import parse_cli
|
from CLI import parse_cli
|
||||||
from Fill import FillError
|
from Fill import FillError
|
||||||
from Main import main, export_yaml, EnemizerError
|
from Main import EnemizerError, export_yaml, main
|
||||||
from Utils import local_path, output_path, open_file, update_deprecated_args
|
|
||||||
import source.classes.constants as CONST
|
|
||||||
from source.gui.randomize.multiworld import multiworld_page
|
|
||||||
import source.gui.widgets as widgets
|
|
||||||
from source.classes.Empty import Empty
|
from source.classes.Empty import Empty
|
||||||
|
from source.gui.randomize.multiworld import multiworld_page
|
||||||
|
from Utils import local_path, open_file, output_path, update_deprecated_args
|
||||||
|
|
||||||
|
|
||||||
def bottom_frame(self, parent, args=None):
|
def bottom_frame(self, parent, args=None):
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
from tkinter import ttk, Frame, N, E, W, LEFT, TOP, X, VERTICAL, Y
|
|
||||||
import source.gui.widgets as widgets
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from tkinter import LEFT, TOP, VERTICAL, E, Frame, N, W, X, Y, ttk
|
||||||
|
|
||||||
import source.classes.constants as CONST
|
import source.classes.constants as CONST
|
||||||
|
import source.gui.widgets as widgets
|
||||||
|
|
||||||
|
|
||||||
def custom_page(top,parent):
|
def custom_page(top,parent):
|
||||||
# Custom Item Pool
|
# Custom Item Pool
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
from source.classes.SpriteSelector import SpriteSelector as spriteSelector
|
|
||||||
from source.gui.randomize.gameoptions import set_sprite
|
|
||||||
from Rom import Sprite, get_sprite_from_name
|
|
||||||
from Utils import update_deprecated_args
|
|
||||||
import source.classes.constants as CONST
|
import source.classes.constants as CONST
|
||||||
|
from Rom import Sprite, get_sprite_from_name
|
||||||
from source.classes.BabelFish import BabelFish
|
from source.classes.BabelFish import BabelFish
|
||||||
from source.classes.Empty import Empty
|
from source.classes.Empty import Empty
|
||||||
|
from source.classes.SpriteSelector import SpriteSelector as spriteSelector
|
||||||
|
from source.gui.randomize.gameoptions import set_sprite
|
||||||
|
from Utils import update_deprecated_args
|
||||||
|
|
||||||
|
|
||||||
# Load args/settings for most tabs
|
# Load args/settings for most tabs
|
||||||
def loadcliargs(gui, args, settings=None):
|
def loadcliargs(gui, args, settings=None):
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
from tkinter import ttk, Frame, Label, E, W, LEFT, RIGHT, TOP
|
|
||||||
import source.gui.widgets as widgets
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from tkinter import LEFT, RIGHT, TOP, E, Frame, Label, W, ttk
|
||||||
|
|
||||||
|
import source.gui.widgets as widgets
|
||||||
|
|
||||||
|
|
||||||
def dungeon_page(parent):
|
def dungeon_page(parent):
|
||||||
# Dungeon Shuffle
|
# Dungeon Shuffle
|
||||||
|
|||||||
@@ -1,10 +1,27 @@
|
|||||||
from tkinter import ttk, filedialog, StringVar, Button, Entry, Frame, Label, N, E, W, LEFT, RIGHT, BOTTOM, X
|
|
||||||
import source.gui.widgets as widgets
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
from tkinter import (
|
||||||
|
BOTTOM,
|
||||||
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
Button,
|
||||||
|
E,
|
||||||
|
Entry,
|
||||||
|
Frame,
|
||||||
|
Label,
|
||||||
|
N,
|
||||||
|
StringVar,
|
||||||
|
W,
|
||||||
|
X,
|
||||||
|
filedialog,
|
||||||
|
ttk,
|
||||||
|
)
|
||||||
|
|
||||||
|
import source.gui.widgets as widgets
|
||||||
from source.classes.Empty import Empty
|
from source.classes.Empty import Empty
|
||||||
|
|
||||||
|
|
||||||
def enemizer_page(parent,settings):
|
def enemizer_page(parent,settings):
|
||||||
# Enemizer
|
# Enemizer
|
||||||
self = ttk.Frame(parent)
|
self = ttk.Frame(parent)
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
from tkinter import ttk, Frame, E, W, LEFT, RIGHT
|
|
||||||
import source.gui.widgets as widgets
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from tkinter import LEFT, RIGHT, E, Frame, W, ttk
|
||||||
|
|
||||||
|
import source.gui.widgets as widgets
|
||||||
|
|
||||||
|
|
||||||
def entrando_page(parent):
|
def entrando_page(parent):
|
||||||
# Entrance Randomizer
|
# Entrance Randomizer
|
||||||
|
|||||||
@@ -1,10 +1,25 @@
|
|||||||
from tkinter import ttk, StringVar, Button, Entry, Frame, Label, NE, NW, E, W, LEFT, RIGHT
|
|
||||||
from functools import partial
|
|
||||||
import source.classes.SpriteSelector as spriteSelector
|
|
||||||
import source.classes.ItemGfxSelector as itemGfxSelector
|
|
||||||
import source.gui.widgets as widgets
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from functools import partial
|
||||||
|
from tkinter import (
|
||||||
|
LEFT,
|
||||||
|
NE,
|
||||||
|
NW,
|
||||||
|
RIGHT,
|
||||||
|
Button,
|
||||||
|
E,
|
||||||
|
Entry,
|
||||||
|
Frame,
|
||||||
|
Label,
|
||||||
|
StringVar,
|
||||||
|
W,
|
||||||
|
ttk,
|
||||||
|
)
|
||||||
|
|
||||||
|
import source.classes.ItemGfxSelector as itemGfxSelector
|
||||||
|
import source.classes.SpriteSelector as spriteSelector
|
||||||
|
import source.gui.widgets as widgets
|
||||||
|
|
||||||
|
|
||||||
def gameoptions_page(top, parent):
|
def gameoptions_page(top, parent):
|
||||||
# Game Options
|
# Game Options
|
||||||
|
|||||||
@@ -1,11 +1,28 @@
|
|||||||
from tkinter import ttk, filedialog, StringVar, Button, Entry, Frame, Label, E, W, LEFT, X, Text, Tk, INSERT
|
|
||||||
import source.classes.diags as diagnostics
|
|
||||||
import source.gui.widgets as widgets
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
from tkinter import (
|
||||||
|
INSERT,
|
||||||
|
LEFT,
|
||||||
|
Button,
|
||||||
|
E,
|
||||||
|
Entry,
|
||||||
|
Frame,
|
||||||
|
Label,
|
||||||
|
StringVar,
|
||||||
|
Text,
|
||||||
|
Tk,
|
||||||
|
W,
|
||||||
|
X,
|
||||||
|
filedialog,
|
||||||
|
ttk,
|
||||||
|
)
|
||||||
|
|
||||||
|
import source.classes.diags as diagnostics
|
||||||
|
import source.gui.widgets as widgets
|
||||||
from source.classes.Empty import Empty
|
from source.classes.Empty import Empty
|
||||||
from Main import __version__
|
from Versions import DRVersion
|
||||||
|
|
||||||
|
|
||||||
def generation_page(parent,settings):
|
def generation_page(parent,settings):
|
||||||
# Generation Setup
|
# Generation Setup
|
||||||
@@ -148,9 +165,9 @@ def generation_page(parent,settings):
|
|||||||
"width": 120,
|
"width": 120,
|
||||||
"height": 50
|
"height": 50
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
diag = Tk()
|
diag = Tk()
|
||||||
diag.title("Door Shuffle " + __version__)
|
diag.title("Door Shuffle " + DRVersion)
|
||||||
diag.geometry(str(dims["window"]["width"]) + 'x' + str(dims["window"]["height"]))
|
diag.geometry(str(dims["window"]["width"]) + 'x' + str(dims["window"]["height"]))
|
||||||
text = Text(diag, width=dims["textarea.characters"]["width"], height=dims["textarea.characters"]["height"])
|
text = Text(diag, width=dims["textarea.characters"]["width"], height=dims["textarea.characters"]["height"])
|
||||||
text.pack()
|
text.pack()
|
||||||
|
|||||||
@@ -1,8 +1,24 @@
|
|||||||
from tkinter import messagebox, ttk, font, Button, Frame, E, W, TOP, LEFT, RIGHT, X, Y, Label
|
|
||||||
import source.gui.widgets as widgets
|
|
||||||
from source.classes.Empty import Empty
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from tkinter import (
|
||||||
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
TOP,
|
||||||
|
Button,
|
||||||
|
E,
|
||||||
|
Frame,
|
||||||
|
Label,
|
||||||
|
W,
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
font,
|
||||||
|
messagebox,
|
||||||
|
ttk,
|
||||||
|
)
|
||||||
|
|
||||||
|
import source.gui.widgets as widgets
|
||||||
|
from source.classes.Empty import Empty
|
||||||
|
|
||||||
|
|
||||||
def item_page(parent):
|
def item_page(parent):
|
||||||
# Item Randomizer
|
# Item Randomizer
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
from tkinter import ttk, StringVar, Entry, Frame, Label, N, E, W, X, LEFT
|
|
||||||
import source.gui.widgets as widgets
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from tkinter import LEFT, E, Entry, Frame, Label, N, StringVar, W, X, ttk
|
||||||
|
|
||||||
|
import source.gui.widgets as widgets
|
||||||
from source.classes.Empty import Empty
|
from source.classes.Empty import Empty
|
||||||
|
|
||||||
|
|
||||||
def multiworld_page(parent,settings):
|
def multiworld_page(parent,settings):
|
||||||
# Multiworld
|
# Multiworld
|
||||||
self = ttk.Frame(parent)
|
self = ttk.Frame(parent)
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
from tkinter import ttk, Frame, Label, W, E, NW, LEFT, RIGHT, X, Y, TOP
|
|
||||||
import source.gui.widgets as widgets
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from tkinter import LEFT, NW, RIGHT, TOP, E, Frame, Label, W, X, Y, ttk
|
||||||
|
|
||||||
|
import source.gui.widgets as widgets
|
||||||
|
|
||||||
|
|
||||||
def overworld_page(parent):
|
def overworld_page(parent):
|
||||||
# Overworld Shuffle
|
# Overworld Shuffle
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
from tkinter import ttk, Frame, N, E, W, LEFT, TOP, X, VERTICAL, Y
|
|
||||||
import source.gui.widgets as widgets
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from tkinter import LEFT, TOP, VERTICAL, E, Frame, N, W, X, Y, ttk
|
||||||
|
|
||||||
import source.classes.constants as CONST
|
import source.classes.constants as CONST
|
||||||
|
import source.gui.widgets as widgets
|
||||||
|
|
||||||
|
|
||||||
def startinventory_page(top,parent):
|
def startinventory_page(top,parent):
|
||||||
# Starting Inventory
|
# Starting Inventory
|
||||||
|
|||||||
+17
-2
@@ -1,7 +1,22 @@
|
|||||||
from tkinter import messagebox, Checkbutton, Entry, Frame, IntVar, Label, OptionMenu, Spinbox, StringVar, LEFT, RIGHT, X
|
from tkinter import (
|
||||||
from tkinter import Button
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
Button,
|
||||||
|
Checkbutton,
|
||||||
|
Entry,
|
||||||
|
Frame,
|
||||||
|
IntVar,
|
||||||
|
Label,
|
||||||
|
OptionMenu,
|
||||||
|
Spinbox,
|
||||||
|
StringVar,
|
||||||
|
X,
|
||||||
|
messagebox,
|
||||||
|
)
|
||||||
|
|
||||||
from source.classes.Empty import Empty
|
from source.classes.Empty import Empty
|
||||||
|
|
||||||
|
|
||||||
# Override Spinbox to include mousewheel support for changing value
|
# Override Spinbox to include mousewheel support for changing value
|
||||||
class mySpinbox(Spinbox):
|
class mySpinbox(Spinbox):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ from collections import deque
|
|||||||
|
|
||||||
from BaseClasses import CollectionState, RegionType
|
from BaseClasses import CollectionState, RegionType
|
||||||
from Dungeons import dungeon_table
|
from Dungeons import dungeon_table
|
||||||
from OWEdges import OWTileRegions, OWTileDistricts
|
from OWEdges import OWTileDistricts, OWTileRegions
|
||||||
|
|
||||||
|
|
||||||
class District(object):
|
class District(object):
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import RaceRandom as random
|
|
||||||
import logging
|
import logging
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from source.item.District import resolve_districts
|
import RaceRandom as random
|
||||||
from BaseClasses import PotItem, PotFlags, LocationType
|
from BaseClasses import LocationType, PotFlags, PotItem
|
||||||
from DoorShuffle import validate_vanilla_reservation
|
from DoorShuffle import validate_vanilla_reservation
|
||||||
from Dungeons import dungeon_table
|
from Dungeons import dungeon_table
|
||||||
from Items import item_table, ItemFactory
|
from Items import ItemFactory, item_table
|
||||||
from PotShuffle import vanilla_pots
|
from PotShuffle import vanilla_pots
|
||||||
|
from source.item.District import resolve_districts
|
||||||
|
|
||||||
|
|
||||||
class ItemPoolConfig(object):
|
class ItemPoolConfig(object):
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from fast_enum import FastEnum
|
from fast_enum import FastEnum
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
Build Entrypoints
|
Build Entrypoints
|
||||||
'''
|
'''
|
||||||
import json
|
import json
|
||||||
import platform
|
|
||||||
import os # for checking for dirs
|
import os # for checking for dirs
|
||||||
|
import platform
|
||||||
import re
|
import re
|
||||||
from json.decoder import JSONDecodeError
|
from json.decoder import JSONDecodeError
|
||||||
from subprocess import Popen, PIPE, STDOUT, CalledProcessError
|
from subprocess import PIPE, STDOUT, CalledProcessError, Popen
|
||||||
|
|
||||||
DEST_DIRECTORY = "."
|
DEST_DIRECTORY = "."
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ def check_requirements(console=False):
|
|||||||
logger.error('https://github.com/aerinon/ALttPDoorRandomizer/blob/DoorDev/docs/BUILDING.md')
|
logger.error('https://github.com/aerinon/ALttPDoorRandomizer/blob/DoorDev/docs/BUILDING.md')
|
||||||
else:
|
else:
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from tkinter import Tk, Label, Button, Frame
|
from tkinter import Button, Frame, Label, Tk
|
||||||
|
|
||||||
master = Tk()
|
master = Tk()
|
||||||
master.title('Error')
|
master.title('Error')
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import RaceRandom as random
|
|
||||||
import logging
|
|
||||||
import copy
|
import copy
|
||||||
|
import logging
|
||||||
|
from collections import OrderedDict, defaultdict
|
||||||
|
|
||||||
from collections import defaultdict, OrderedDict
|
import RaceRandom as random
|
||||||
from BaseClasses import RegionType
|
from BaseClasses import RegionType
|
||||||
|
|
||||||
from source.overworld.EntranceData import door_addresses
|
from source.overworld.EntranceData import door_addresses
|
||||||
|
|
||||||
|
|
||||||
@@ -857,9 +856,9 @@ def get_nearby_entrances(avail, start_region):
|
|||||||
|
|
||||||
|
|
||||||
def get_accessible_entrances(start_region, avail, assumed_inventory=[], cross_world=False, region_rules=True, exit_rules=True, include_one_ways=False, restrictive_follower=False):
|
def get_accessible_entrances(start_region, avail, assumed_inventory=[], cross_world=False, region_rules=True, exit_rules=True, include_one_ways=False, restrictive_follower=False):
|
||||||
from Main import copy_world_premature
|
|
||||||
from BaseClasses import CollectionState
|
from BaseClasses import CollectionState
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
|
from Main import copy_world_premature
|
||||||
from OverworldShuffle import build_accessible_region_list, one_way_ledges
|
from OverworldShuffle import build_accessible_region_list, one_way_ledges
|
||||||
|
|
||||||
for p in range(1, avail.world.players + 1):
|
for p in range(1, avail.world.players + 1):
|
||||||
|
|||||||
@@ -1,13 +1,28 @@
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from Utils import snes_to_pc, int24_as_bytes, int16_as_bytes, load_cached_yaml, pc_to_snes
|
from source.dungeon.EnemyList import (
|
||||||
|
EnemySprite,
|
||||||
from source.dungeon.EnemyList import EnemyTable, init_vanilla_sprites, vanilla_sprites, init_enemy_stats, EnemySprite
|
EnemyTable,
|
||||||
from source.dungeon.EnemyList import sprite_translation
|
init_enemy_stats,
|
||||||
|
init_vanilla_sprites,
|
||||||
|
sprite_translation,
|
||||||
|
vanilla_sprites,
|
||||||
|
)
|
||||||
from source.dungeon.RoomHeader import init_room_headers
|
from source.dungeon.RoomHeader import init_room_headers
|
||||||
from source.dungeon.RoomList import Room0127
|
from source.dungeon.RoomList import Room0127
|
||||||
from source.enemizer.OwEnemyList import init_vanilla_sprites_ow, vanilla_sprites_ow
|
from source.enemizer.OwEnemyList import init_vanilla_sprites_ow, vanilla_sprites_ow
|
||||||
from source.enemizer.SpriteSheets import init_sprite_sheets, init_sprite_requirements, SheetChoice
|
from source.enemizer.SpriteSheets import (
|
||||||
|
SheetChoice,
|
||||||
|
init_sprite_requirements,
|
||||||
|
init_sprite_sheets,
|
||||||
|
)
|
||||||
|
from Utils import (
|
||||||
|
int16_as_bytes,
|
||||||
|
int24_as_bytes,
|
||||||
|
load_cached_yaml,
|
||||||
|
pc_to_snes,
|
||||||
|
snes_to_pc,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def convert_area_id_to_offset(area_id):
|
def convert_area_id_to_offset(area_id):
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user