Hack in Spanish
This commit is contained in:
3
CLI.py
3
CLI.py
@@ -26,7 +26,7 @@ def parse_arguments(argv, no_defaults=False):
|
|||||||
# get settings
|
# get settings
|
||||||
settings = get_settings()
|
settings = get_settings()
|
||||||
|
|
||||||
fish = BabelFish()
|
fish = BabelFish(lang=settings["lang"] if "lang" in settings else "en")
|
||||||
|
|
||||||
# we need to know how many players we have first
|
# we need to know how many players we have first
|
||||||
parser = argparse.ArgumentParser(add_help=False)
|
parser = argparse.ArgumentParser(add_help=False)
|
||||||
@@ -102,6 +102,7 @@ def parse_arguments(argv, no_defaults=False):
|
|||||||
def get_settings():
|
def get_settings():
|
||||||
# set default settings
|
# set default settings
|
||||||
settings = {
|
settings = {
|
||||||
|
"lang": "en",
|
||||||
"retro": False,
|
"retro": False,
|
||||||
"mode": "open",
|
"mode": "open",
|
||||||
"logic": "noglitches",
|
"logic": "noglitches",
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import operator as op
|
|||||||
import time
|
import time
|
||||||
from enum import unique, Flag
|
from enum import unique, Flag
|
||||||
|
|
||||||
|
from source.classes.BabelFish import BabelFish
|
||||||
|
import CLI as cli
|
||||||
|
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from BaseClasses import RegionType, Door, DoorType, Direction, Sector, CrystalBarrier
|
from BaseClasses import RegionType, Door, DoorType, Direction, Sector, CrystalBarrier
|
||||||
from Regions import key_only_locations
|
from Regions import key_only_locations
|
||||||
@@ -305,6 +308,9 @@ def pair_existing_key_doors(world, player, door_a, door_b):
|
|||||||
# paired_door.pair = False
|
# paired_door.pair = False
|
||||||
|
|
||||||
def within_dungeon(world, player):
|
def within_dungeon(world, player):
|
||||||
|
settings = cli.get_settings()
|
||||||
|
fish = BabelFish(lang=settings["lang"] if "lang" in settings else "en")
|
||||||
|
|
||||||
fix_big_key_doors_with_ugly_smalls(world, player)
|
fix_big_key_doors_with_ugly_smalls(world, player)
|
||||||
overworld_prep(world, player)
|
overworld_prep(world, player)
|
||||||
entrances_map, potentials, connections = determine_entrance_list(world, player)
|
entrances_map, potentials, connections = determine_entrance_list(world, player)
|
||||||
@@ -326,7 +332,7 @@ def within_dungeon(world, player):
|
|||||||
start = time.process_time()
|
start = time.process_time()
|
||||||
for builder in world.dungeon_layouts[player].values():
|
for builder in world.dungeon_layouts[player].values():
|
||||||
shuffle_key_doors(builder, world, player)
|
shuffle_key_doors(builder, world, player)
|
||||||
logging.getLogger('').info('Key door shuffle time: %s', time.process_time()-start)
|
logging.getLogger('').info('%s: %s', fish.translate("cli","cli","keydoor.shuffle.time"), time.process_time()-start)
|
||||||
smooth_door_pairs(world, player)
|
smooth_door_pairs(world, player)
|
||||||
|
|
||||||
|
|
||||||
@@ -347,6 +353,11 @@ def handle_split_dungeons(dungeon_builders, recombinant_builders, entrances_map)
|
|||||||
|
|
||||||
|
|
||||||
def main_dungeon_generation(dungeon_builders, recombinant_builders, connections_tuple, world, player):
|
def main_dungeon_generation(dungeon_builders, recombinant_builders, connections_tuple, world, player):
|
||||||
|
settings = cli.get_args_priority(None, None, None)
|
||||||
|
if "load" in settings:
|
||||||
|
settings = settings["load"]
|
||||||
|
fish = BabelFish(lang=settings["lang"] if "lang" in settings else "en")
|
||||||
|
|
||||||
entrances_map, potentials, connections = connections_tuple
|
entrances_map, potentials, connections = connections_tuple
|
||||||
enabled_entrances = {}
|
enabled_entrances = {}
|
||||||
sector_queue = deque(dungeon_builders.values())
|
sector_queue = deque(dungeon_builders.values())
|
||||||
@@ -366,7 +377,7 @@ def main_dungeon_generation(dungeon_builders, recombinant_builders, connections_
|
|||||||
sector_queue.append(builder)
|
sector_queue.append(builder)
|
||||||
last_key = builder.name
|
last_key = builder.name
|
||||||
else:
|
else:
|
||||||
logging.getLogger('').info('Generating dungeon: %s', builder.name)
|
logging.getLogger('').info('%s: %s', fish.translate("cli","cli","generating.dungeon"), builder.name)
|
||||||
ds = generate_dungeon(builder, origin_list_sans_drops, split_dungeon, world, player)
|
ds = generate_dungeon(builder, origin_list_sans_drops, split_dungeon, world, player)
|
||||||
find_new_entrances(ds, connections, potentials, enabled_entrances, world, player)
|
find_new_entrances(ds, connections, potentials, enabled_entrances, world, player)
|
||||||
ds.name = name
|
ds.name = name
|
||||||
@@ -501,7 +512,7 @@ def shuffle_dungeon(world, player, start_region_names, dungeon_region_names):
|
|||||||
for door in get_doors(world, world.get_region(name, player), player):
|
for door in get_doors(world, world.get_region(name, player), player):
|
||||||
ugly_regions[door.name] = 0
|
ugly_regions[door.name] = 0
|
||||||
available_doors.append(door)
|
available_doors.append(door)
|
||||||
|
|
||||||
# Loop until all available doors are used
|
# Loop until all available doors are used
|
||||||
while len(available_doors) > 0:
|
while len(available_doors) > 0:
|
||||||
# Pick a random available door to connect, prioritizing ones that aren't blocked.
|
# Pick a random available door to connect, prioritizing ones that aren't blocked.
|
||||||
@@ -713,6 +724,9 @@ def cross_dungeon(world, player):
|
|||||||
|
|
||||||
|
|
||||||
def assign_cross_keys(dungeon_builders, world, player):
|
def assign_cross_keys(dungeon_builders, world, player):
|
||||||
|
settings = cli.get_settings()
|
||||||
|
fish = BabelFish(lang=settings["lang"] if "lang" in settings else "en")
|
||||||
|
|
||||||
start = time.process_time()
|
start = time.process_time()
|
||||||
total_keys = remaining = 29
|
total_keys = remaining = 29
|
||||||
total_candidates = 0
|
total_candidates = 0
|
||||||
@@ -792,7 +806,7 @@ def assign_cross_keys(dungeon_builders, world, player):
|
|||||||
dungeon.small_keys = []
|
dungeon.small_keys = []
|
||||||
else:
|
else:
|
||||||
dungeon.small_keys = [ItemFactory(dungeon_keys[name], player)] * actual_chest_keys
|
dungeon.small_keys = [ItemFactory(dungeon_keys[name], player)] * actual_chest_keys
|
||||||
logging.getLogger('').info('Cross Dungeon: Key door shuffle time: %s', time.process_time()-start)
|
logging.getLogger('').info('%s: %s', fish.translate("cli","cli","keydoor.shuffle.time.crossed"), time.process_time()-start)
|
||||||
|
|
||||||
|
|
||||||
def reassign_boss(boss_region, boss_key, builder, gt, world, player):
|
def reassign_boss(boss_region, boss_key, builder, gt, world, player):
|
||||||
@@ -948,15 +962,18 @@ def calc_used_dungeon_items(builder):
|
|||||||
|
|
||||||
|
|
||||||
def find_valid_combination(builder, start_regions, world, player, drop_keys=True):
|
def find_valid_combination(builder, start_regions, world, player, drop_keys=True):
|
||||||
|
settings = cli.get_settings()
|
||||||
|
fish = BabelFish(lang=settings["lang"] if "lang" in settings else "en")
|
||||||
|
|
||||||
logger = logging.getLogger('')
|
logger = logging.getLogger('')
|
||||||
logger.info('Shuffling Key doors for %s', builder.name)
|
logger.info('%s %s', fish.translate("cli","cli","shuffling.keydoors"), builder.name)
|
||||||
# find valid combination of candidates
|
# find valid combination of candidates
|
||||||
if len(builder.candidates) < builder.key_doors_num:
|
if len(builder.candidates) < builder.key_doors_num:
|
||||||
if not drop_keys:
|
if not drop_keys:
|
||||||
logger.info('No valid layouts for %s with %s doors', builder.name, builder.key_doors_num)
|
logger.info('No valid layouts for %s with %s doors', builder.name, builder.key_doors_num)
|
||||||
return False
|
return False
|
||||||
builder.key_doors_num = len(builder.candidates) # reduce number of key doors
|
builder.key_doors_num = len(builder.candidates) # reduce number of key doors
|
||||||
logger.info('Lowering key door count because not enough candidates: %s', builder.name)
|
logger.info('%s: %s', fish.translate("cli","cli","lowering.keys.candidates"), builder.name)
|
||||||
combinations = ncr(len(builder.candidates), builder.key_doors_num)
|
combinations = ncr(len(builder.candidates), builder.key_doors_num)
|
||||||
itr = 0
|
itr = 0
|
||||||
start = time.process_time()
|
start = time.process_time()
|
||||||
@@ -976,7 +993,7 @@ def find_valid_combination(builder, start_regions, world, player, drop_keys=True
|
|||||||
if not drop_keys:
|
if not drop_keys:
|
||||||
logger.info('No valid layouts for %s with %s doors', builder.name, builder.key_doors_num)
|
logger.info('No valid layouts for %s with %s doors', builder.name, builder.key_doors_num)
|
||||||
return False
|
return False
|
||||||
logger.info('Lowering key door count because no valid layouts: %s', builder.name)
|
logger.info('%s: %s', fish.translate("cli","cli","lowering.keys.layouts"), builder.name)
|
||||||
builder.key_doors_num -= 1
|
builder.key_doors_num -= 1
|
||||||
if builder.key_doors_num < 0:
|
if builder.key_doors_num < 0:
|
||||||
raise Exception('Bad dungeon %s - 0 key doors not valid' % builder.name)
|
raise Exception('Bad dungeon %s - 0 key doors not valid' % builder.name)
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ from functools import reduce
|
|||||||
import operator as op
|
import operator as op
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
from source.classes.BabelFish import BabelFish
|
||||||
|
import CLI as cli
|
||||||
|
|
||||||
from BaseClasses import DoorType, Direction, CrystalBarrier, RegionType, Polarity, Sector, PolSlot, flooded_keys
|
from BaseClasses import DoorType, Direction, CrystalBarrier, RegionType, Polarity, Sector, PolSlot, flooded_keys
|
||||||
from Regions import key_only_locations, dungeon_events, flooded_keys_reverse
|
from Regions import key_only_locations, dungeon_events, flooded_keys_reverse
|
||||||
from Dungeons import dungeon_regions
|
from Dungeons import dungeon_regions
|
||||||
@@ -1094,6 +1097,11 @@ def simple_dungeon_builder(name, sector_list):
|
|||||||
|
|
||||||
|
|
||||||
def create_dungeon_builders(all_sectors, world, player, dungeon_entrances=None):
|
def create_dungeon_builders(all_sectors, world, player, dungeon_entrances=None):
|
||||||
|
settings = cli.get_args_priority(None, None, None)
|
||||||
|
if "load" in settings:
|
||||||
|
settings = settings["load"]
|
||||||
|
fish = BabelFish(lang=settings["lang"] if "lang" in settings else "en")
|
||||||
|
|
||||||
logger = logging.getLogger('')
|
logger = logging.getLogger('')
|
||||||
logger.info('Shuffling Dungeon Sectors')
|
logger.info('Shuffling Dungeon Sectors')
|
||||||
if dungeon_entrances is None:
|
if dungeon_entrances is None:
|
||||||
@@ -1149,7 +1157,7 @@ def create_dungeon_builders(all_sectors, world, player, dungeon_entrances=None):
|
|||||||
# polarity:
|
# polarity:
|
||||||
if not global_pole.is_valid(dungeon_map):
|
if not global_pole.is_valid(dungeon_map):
|
||||||
raise NeutralizingException('Either free location/crystal assignment is already globally invalid - lazy dev check this earlier!')
|
raise NeutralizingException('Either free location/crystal assignment is already globally invalid - lazy dev check this earlier!')
|
||||||
logger.info('-Balancing Doors')
|
logger.info(fish.translate("cli","cli","balance.doors"))
|
||||||
assign_polarized_sectors(dungeon_map, polarized_sectors, global_pole, logger)
|
assign_polarized_sectors(dungeon_map, polarized_sectors, global_pole, logger)
|
||||||
# the rest
|
# the rest
|
||||||
assign_the_rest(dungeon_map, neutral_sectors, global_pole)
|
assign_the_rest(dungeon_map, neutral_sectors, global_pole)
|
||||||
@@ -1435,8 +1443,13 @@ def sum_polarity(sector_list):
|
|||||||
|
|
||||||
|
|
||||||
def assign_polarized_sectors(dungeon_map, polarized_sectors, global_pole, logger):
|
def assign_polarized_sectors(dungeon_map, polarized_sectors, global_pole, logger):
|
||||||
|
settings = cli.get_args_priority(None, None, None)
|
||||||
|
if "load" in settings:
|
||||||
|
settings = settings["load"]
|
||||||
|
fish = BabelFish(lang=settings["lang"] if "lang" in settings else "en")
|
||||||
|
|
||||||
# step 1: fix polarity connection issues
|
# step 1: fix polarity connection issues
|
||||||
logger.info('--Basic Traversal')
|
logger.info(fish.translate("cli","cli","basic.traversal"))
|
||||||
unconnected_builders = identify_polarity_issues(dungeon_map)
|
unconnected_builders = identify_polarity_issues(dungeon_map)
|
||||||
while len(unconnected_builders) > 0:
|
while len(unconnected_builders) > 0:
|
||||||
for name, builder in unconnected_builders.items():
|
for name, builder in unconnected_builders.items():
|
||||||
@@ -1524,10 +1537,15 @@ def assign_polarized_sectors(dungeon_map, polarized_sectors, global_pole, logger
|
|||||||
|
|
||||||
|
|
||||||
def polarity_step_3(dungeon_map, polarized_sectors, global_pole, logger):
|
def polarity_step_3(dungeon_map, polarized_sectors, global_pole, logger):
|
||||||
|
settings = cli.get_args_priority(None, None, None)
|
||||||
|
if "load" in settings:
|
||||||
|
settings = settings["load"]
|
||||||
|
fish = BabelFish(lang=settings["lang"] if "lang" in settings else "en")
|
||||||
|
|
||||||
builder_order = list(dungeon_map.values())
|
builder_order = list(dungeon_map.values())
|
||||||
random.shuffle(builder_order)
|
random.shuffle(builder_order)
|
||||||
for builder in builder_order:
|
for builder in builder_order:
|
||||||
logger.info('--Balancing %s', builder.name)
|
logger.info('%s %s', fish.translate("cli","cli","balancing"), builder.name)
|
||||||
while not builder.polarity().is_neutral():
|
while not builder.polarity().is_neutral():
|
||||||
candidates = find_neutralizing_candidates(builder, polarized_sectors)
|
candidates = find_neutralizing_candidates(builder, polarized_sectors)
|
||||||
valid, sectors = False, None
|
valid, sectors = False, None
|
||||||
@@ -1832,8 +1850,13 @@ def assign_the_rest(dungeon_map, neutral_sectors, global_pole):
|
|||||||
|
|
||||||
|
|
||||||
def split_dungeon_builder(builder, split_list):
|
def split_dungeon_builder(builder, split_list):
|
||||||
|
settings = cli.get_args_priority(None, None, None)
|
||||||
|
if "load" in settings:
|
||||||
|
settings = settings["load"]
|
||||||
|
fish = BabelFish(lang=settings["lang"] if "lang" in settings else "en")
|
||||||
|
|
||||||
logger = logging.getLogger('')
|
logger = logging.getLogger('')
|
||||||
logger.info('Splitting Up Desert/Skull')
|
logger.info(fish.translate("cli","cli","splitting.up") + ' ' + 'Desert/Skull')
|
||||||
candidate_sectors = dict.fromkeys(builder.sectors)
|
candidate_sectors = dict.fromkeys(builder.sectors)
|
||||||
global_pole = GlobalPolarity(candidate_sectors)
|
global_pole = GlobalPolarity(candidate_sectors)
|
||||||
|
|
||||||
@@ -1848,6 +1871,11 @@ def split_dungeon_builder(builder, split_list):
|
|||||||
|
|
||||||
|
|
||||||
def balance_split(candidate_sectors, dungeon_map, global_pole):
|
def balance_split(candidate_sectors, dungeon_map, global_pole):
|
||||||
|
settings = cli.get_args_priority(None, None, None)
|
||||||
|
if "load" in settings:
|
||||||
|
settings = settings["load"]
|
||||||
|
fish = BabelFish(lang=settings["lang"] if "lang" in settings else "en")
|
||||||
|
|
||||||
logger = logging.getLogger('')
|
logger = logging.getLogger('')
|
||||||
# categorize sectors
|
# categorize sectors
|
||||||
crystal_switches, crystal_barriers, neutral_sectors, polarized_sectors = categorize_sectors(candidate_sectors)
|
crystal_switches, crystal_barriers, neutral_sectors, polarized_sectors = categorize_sectors(candidate_sectors)
|
||||||
@@ -1860,7 +1888,7 @@ def balance_split(candidate_sectors, dungeon_map, global_pole):
|
|||||||
# blue barriers
|
# blue barriers
|
||||||
assign_crystal_barrier_sectors(dungeon_map, crystal_barriers, global_pole)
|
assign_crystal_barrier_sectors(dungeon_map, crystal_barriers, global_pole)
|
||||||
# polarity:
|
# polarity:
|
||||||
logger.info('-Re-balancing ' + next(iter(dungeon_map.keys())) + ' et al')
|
logger.info(fish.translate("cli","cli","re-balancing") + ' ' + next(iter(dungeon_map.keys())) + ' et al')
|
||||||
assign_polarized_sectors(dungeon_map, polarized_sectors, global_pole, logger)
|
assign_polarized_sectors(dungeon_map, polarized_sectors, global_pole, logger)
|
||||||
# the rest
|
# the rest
|
||||||
assign_the_rest(dungeon_map, neutral_sectors, global_pole)
|
assign_the_rest(dungeon_map, neutral_sectors, global_pole)
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import textwrap
|
|||||||
import shlex
|
import shlex
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from CLI import parse_arguments
|
from source.classes.BabelFish import BabelFish
|
||||||
|
|
||||||
|
from CLI import parse_arguments, get_args_priority
|
||||||
from Main import main
|
from Main import main
|
||||||
from Rom import get_sprite_from_name
|
from Rom import get_sprite_from_name
|
||||||
from Utils import is_bundled, close_console
|
from Utils import is_bundled, close_console
|
||||||
@@ -17,6 +19,11 @@ from Fill import FillError
|
|||||||
def start():
|
def start():
|
||||||
args = parse_arguments(None)
|
args = parse_arguments(None)
|
||||||
|
|
||||||
|
settings = get_args_priority(None, None, None)
|
||||||
|
if "load" in settings:
|
||||||
|
settings = settings["load"]
|
||||||
|
fish = BabelFish(lang=settings["lang"] if "lang" in settings else "en")
|
||||||
|
|
||||||
if is_bundled() and len(sys.argv) == 1:
|
if is_bundled() and len(sys.argv) == 1:
|
||||||
# for the bundled builds, if we have no arguments, the user
|
# for the bundled builds, if we have no arguments, the user
|
||||||
# probably wants the gui. Users of the bundled build who want the command line
|
# probably wants the gui. Users of the bundled build who want the command line
|
||||||
@@ -52,10 +59,10 @@ def start():
|
|||||||
for _ in range(args.count):
|
for _ in range(args.count):
|
||||||
try:
|
try:
|
||||||
main(seed=seed, args=args)
|
main(seed=seed, args=args)
|
||||||
logger.info('Finished run %s', _+1)
|
logger.info('%s %s', fish.translate("cli","cli","finished.run"), _+1)
|
||||||
except (FillError, Exception, RuntimeError) as err:
|
except (FillError, Exception, RuntimeError) as err:
|
||||||
failures.append((err, seed))
|
failures.append((err, seed))
|
||||||
logger.warning('Generation failed: %s', err)
|
logger.warning('%s: %s', fish.translate("cli","cli","generation.failed"), err)
|
||||||
seed = random.randint(0, 999999999)
|
seed = random.randint(0, 999999999)
|
||||||
for fail in failures:
|
for fail in failures:
|
||||||
logger.info('%s seed failed with: %s', fail[1], fail[0])
|
logger.info('%s seed failed with: %s', fail[1], fail[0])
|
||||||
|
|||||||
68
Main.py
68
Main.py
@@ -8,6 +8,9 @@ import random
|
|||||||
import time
|
import time
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
|
from source.classes.BabelFish import BabelFish
|
||||||
|
import CLI as cli
|
||||||
|
|
||||||
from BaseClasses import World, CollectionState, Item, Region, Location, Shop
|
from BaseClasses import World, CollectionState, Item, Region, Location, Shop
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
from KeyDoorShuffle import validate_key_placement
|
from KeyDoorShuffle import validate_key_placement
|
||||||
@@ -34,6 +37,11 @@ def main(args, seed=None):
|
|||||||
|
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
|
|
||||||
|
settings = cli.get_args_priority(None, None, None)
|
||||||
|
if "load" in settings:
|
||||||
|
settings = settings["load"]
|
||||||
|
fish = BabelFish(lang=settings["lang"] if "lang" in settings else "en")
|
||||||
|
|
||||||
# initialize the world
|
# initialize the world
|
||||||
world = World(args.multi, args.shuffle, args.door_shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, args.accessibility, args.shuffleganon, args.retro, args.custom, args.customitemarray, args.hints)
|
world = World(args.multi, args.shuffle, args.door_shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, args.accessibility, args.shuffleganon, args.retro, args.custom, args.customitemarray, args.hints)
|
||||||
logger = logging.getLogger('')
|
logger = logging.getLogger('')
|
||||||
@@ -62,7 +70,14 @@ def main(args, seed=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)}
|
||||||
|
|
||||||
logger.info('ALttP Door Randomizer Version %s - Seed: %s\n', __version__, world.seed)
|
logger.info(
|
||||||
|
'%s %s %s - %s: %s\n',
|
||||||
|
fish.translate("cli","cli","app.title"),
|
||||||
|
fish.translate("cli","cli","version"),
|
||||||
|
__version__,
|
||||||
|
fish.translate("cli","cli","seed"),
|
||||||
|
world.seed
|
||||||
|
)
|
||||||
|
|
||||||
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)
|
||||||
@@ -95,7 +110,7 @@ def main(args, seed=None):
|
|||||||
create_rooms(world, player)
|
create_rooms(world, player)
|
||||||
create_dungeons(world, player)
|
create_dungeons(world, player)
|
||||||
|
|
||||||
logger.info('Shuffling the World about.')
|
logger.info(fish.translate("cli","cli","shuffling.world"))
|
||||||
|
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
if world.mode[player] != 'inverted':
|
if world.mode[player] != 'inverted':
|
||||||
@@ -103,7 +118,7 @@ def main(args, seed=None):
|
|||||||
else:
|
else:
|
||||||
link_inverted_entrances(world, player)
|
link_inverted_entrances(world, player)
|
||||||
|
|
||||||
logger.info('Shuffling dungeons')
|
logger.info(fish.translate("cli","cli","shuffling.dungeons"))
|
||||||
|
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
link_doors(world, player)
|
link_doors(world, player)
|
||||||
@@ -111,21 +126,21 @@ def main(args, seed=None):
|
|||||||
mark_light_world_regions(world, player)
|
mark_light_world_regions(world, player)
|
||||||
else:
|
else:
|
||||||
mark_dark_world_regions(world, player)
|
mark_dark_world_regions(world, player)
|
||||||
logger.info('Generating Item Pool.')
|
logger.info(fish.translate("cli","cli","generating.itempool"))
|
||||||
|
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
generate_itempool(world, player)
|
generate_itempool(world, player)
|
||||||
|
|
||||||
logger.info('Calculating Access Rules.')
|
logger.info(fish.translate("cli","cli","calc.access.rules"))
|
||||||
|
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
set_rules(world, player)
|
set_rules(world, player)
|
||||||
|
|
||||||
logger.info('Placing Dungeon Prizes.')
|
logger.info(fish.translate("cli","cli","placing.dungeon.prizes"))
|
||||||
|
|
||||||
fill_prizes(world)
|
fill_prizes(world)
|
||||||
|
|
||||||
logger.info('Placing Dungeon Items.')
|
logger.info(fish.translate("cli","cli","placing.dungeon.items"))
|
||||||
|
|
||||||
shuffled_locations = None
|
shuffled_locations = None
|
||||||
if args.algorithm in ['balanced', 'vt26'] or any(list(args.mapshuffle.values()) + list(args.compassshuffle.values()) +
|
if args.algorithm in ['balanced', 'vt26'] or any(list(args.mapshuffle.values()) + list(args.compassshuffle.values()) +
|
||||||
@@ -139,9 +154,17 @@ def main(args, seed=None):
|
|||||||
for player in range(1, world.players+1):
|
for player in range(1, world.players+1):
|
||||||
for key_layout in world.key_layout[player].values():
|
for key_layout in world.key_layout[player].values():
|
||||||
if not validate_key_placement(key_layout, world, player):
|
if not validate_key_placement(key_layout, world, player):
|
||||||
raise RuntimeError("Keylock detected: %s (Player %d)" % (key_layout.sector.name, player))
|
raise RuntimeError(
|
||||||
|
"%s: %s (%s %d)" %
|
||||||
|
(
|
||||||
|
fish.translate("cli","cli","keylock.detected"),
|
||||||
|
key_layout.sector.name,
|
||||||
|
fish.translate("cli","cli","player"),
|
||||||
|
player
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
logger.info('Fill the world.')
|
logger.info(fish.translate("cli","cli","fill.world"))
|
||||||
|
|
||||||
if args.algorithm == 'flood':
|
if args.algorithm == 'flood':
|
||||||
flood_items(world) # different algo, biased towards early game progress items
|
flood_items(world) # different algo, biased towards early game progress items
|
||||||
@@ -160,14 +183,14 @@ def main(args, seed=None):
|
|||||||
distribute_items_restrictive(world, True)
|
distribute_items_restrictive(world, True)
|
||||||
|
|
||||||
if world.players > 1:
|
if world.players > 1:
|
||||||
logger.info('Balancing multiworld progression.')
|
logger.info(fish.translate("cli","cli","balance.multiworld"))
|
||||||
balance_multiworld_progression(world)
|
balance_multiworld_progression(world)
|
||||||
|
|
||||||
# if we only check for beatable, we can do this sanity check first before creating the rom
|
# if we only check for beatable, we can do this sanity check first before creating the rom
|
||||||
if not world.can_beat_game():
|
if not world.can_beat_game():
|
||||||
raise RuntimeError('Cannot beat game. Something went terribly wrong here!')
|
raise RuntimeError(fish.translate("cli","cli","cannot.beat.game"))
|
||||||
|
|
||||||
logger.info('Patching ROM.')
|
logger.info(fish.translate("cli","cli","patching.rom"))
|
||||||
|
|
||||||
outfilebase = 'DR_%s' % (args.outputname if args.outputname else world.seed)
|
outfilebase = 'DR_%s' % (args.outputname if args.outputname else world.seed)
|
||||||
|
|
||||||
@@ -191,8 +214,8 @@ def main(args, seed=None):
|
|||||||
if not args.jsonout:
|
if not args.jsonout:
|
||||||
rom = LocalRom.fromJsonRom(rom, args.rom, 0x400000)
|
rom = LocalRom.fromJsonRom(rom, args.rom, 0x400000)
|
||||||
else:
|
else:
|
||||||
logging.warning("EnemizerCLI not found at:" + args.enemizercli)
|
logging.warning(fish.translate("cli","cli","enemizer.not.found") + ': ' + args.enemizercli)
|
||||||
logging.warning("No Enemizer options will be applied until this is resolved.")
|
logging.warning(fish.translate("cli","cli","enemizer.nothing.applied"))
|
||||||
|
|
||||||
if args.race:
|
if args.race:
|
||||||
patch_race_rom(rom)
|
patch_race_rom(rom)
|
||||||
@@ -246,7 +269,7 @@ def main(args, seed=None):
|
|||||||
world.spoiler.to_file(output_path('%s_Spoiler.txt' % outfilebase))
|
world.spoiler.to_file(output_path('%s_Spoiler.txt' % outfilebase))
|
||||||
|
|
||||||
if not args.skip_playthrough:
|
if not args.skip_playthrough:
|
||||||
logger.info('Calculating playthrough.')
|
logger.info(fish.translate("cli","cli","calc.playthrough"))
|
||||||
create_playthrough(world)
|
create_playthrough(world)
|
||||||
|
|
||||||
if args.jsonout:
|
if args.jsonout:
|
||||||
@@ -254,8 +277,8 @@ def main(args, seed=None):
|
|||||||
elif args.create_spoiler and not args.skip_playthrough:
|
elif args.create_spoiler and not args.skip_playthrough:
|
||||||
world.spoiler.to_file(output_path('%s_Spoiler.txt' % outfilebase))
|
world.spoiler.to_file(output_path('%s_Spoiler.txt' % outfilebase))
|
||||||
|
|
||||||
logger.info('Done. Enjoy.')
|
logger.info(fish.translate("cli","cli","done"))
|
||||||
logger.info('Total Time: %s', time.perf_counter() - start)
|
logger.info('%s: %s', fish.translate("cli","cli","total.time"), time.perf_counter() - start)
|
||||||
|
|
||||||
# print_wiki_doors_by_room(dungeon_regions,world,1)
|
# print_wiki_doors_by_room(dungeon_regions,world,1)
|
||||||
|
|
||||||
@@ -391,6 +414,11 @@ def copy_dynamic_regions_and_locations(world, ret):
|
|||||||
|
|
||||||
|
|
||||||
def create_playthrough(world):
|
def create_playthrough(world):
|
||||||
|
settings = cli.get_args_priority(None, None, None)
|
||||||
|
if "load" in settings:
|
||||||
|
settings = settings["load"]
|
||||||
|
fish = BabelFish(lang=settings["lang"] if "lang" in settings else "en")
|
||||||
|
|
||||||
# create a copy as we will modify it
|
# create a copy as we will modify it
|
||||||
old_world = world
|
old_world = world
|
||||||
world = copy_world(world)
|
world = copy_world(world)
|
||||||
@@ -401,7 +429,7 @@ def create_playthrough(world):
|
|||||||
collection_spheres = []
|
collection_spheres = []
|
||||||
state = CollectionState(world)
|
state = CollectionState(world)
|
||||||
sphere_candidates = list(prog_locations)
|
sphere_candidates = list(prog_locations)
|
||||||
logging.getLogger('').debug('Building up collection spheres.')
|
logging.getLogger('').debug(fish.translate("cli","cli","building.collection.spheres"))
|
||||||
while sphere_candidates:
|
while sphere_candidates:
|
||||||
state.sweep_for_events(key_only=True)
|
state.sweep_for_events(key_only=True)
|
||||||
state.sweep_for_crystal_access()
|
state.sweep_for_crystal_access()
|
||||||
@@ -424,7 +452,7 @@ def create_playthrough(world):
|
|||||||
if not sphere:
|
if not sphere:
|
||||||
logging.getLogger('').debug('The following items could not be reached: %s', ['%s (Player %d) at %s (Player %d)' % (location.item.name, location.item.player, location.name, location.player) for location in sphere_candidates])
|
logging.getLogger('').debug('The following items could not be reached: %s', ['%s (Player %d) at %s (Player %d)' % (location.item.name, location.item.player, location.name, location.player) for location in sphere_candidates])
|
||||||
if any([world.accessibility[location.item.player] != 'none' for location in sphere_candidates]):
|
if any([world.accessibility[location.item.player] != 'none' for location in sphere_candidates]):
|
||||||
raise RuntimeError('Not all progression items reachable. Something went terribly wrong here.')
|
raise RuntimeError(fish.translate("cli","cli","cannot.reach.progression"))
|
||||||
else:
|
else:
|
||||||
old_world.spoiler.unreachables = sphere_candidates.copy()
|
old_world.spoiler.unreachables = sphere_candidates.copy()
|
||||||
break
|
break
|
||||||
@@ -478,7 +506,7 @@ def create_playthrough(world):
|
|||||||
|
|
||||||
logging.getLogger('').debug('Calculated final sphere %i, containing %i of %i progress items.', len(collection_spheres), len(sphere), len(required_locations))
|
logging.getLogger('').debug('Calculated final sphere %i, containing %i of %i progress items.', len(collection_spheres), len(sphere), len(required_locations))
|
||||||
if not sphere:
|
if not sphere:
|
||||||
raise RuntimeError('Not all required items reachable. Something went terribly wrong here.')
|
raise RuntimeError(fish.translate("cli","cli","cannot.reach.required"))
|
||||||
|
|
||||||
# store the required locations for statistical analysis
|
# store the required locations for statistical analysis
|
||||||
old_world.required_locations = [(location.name, location.player) for sphere in collection_spheres for location in sphere]
|
old_world.required_locations = [(location.name, location.player) for sphere in collection_spheres for location in sphere]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"lang": {},
|
||||||
"create_spoiler": {
|
"create_spoiler": {
|
||||||
"action": "store_true",
|
"action": "store_true",
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
|
|||||||
@@ -1,5 +1,46 @@
|
|||||||
{
|
{
|
||||||
|
"cli": {
|
||||||
|
"app.title": "ALttP Door Randomizer",
|
||||||
|
"version": "Version",
|
||||||
|
"seed": "Seed",
|
||||||
|
"player": "Player",
|
||||||
|
"shuffling.world": "Shuffling the World about",
|
||||||
|
"shuffling.dungeons": "Shuffling dungeons",
|
||||||
|
"basic.traversal": "--Basic Traversal",
|
||||||
|
"generating.dungeon": "Generating dungeon",
|
||||||
|
"shuffling.keydoors": "Shuffling Key doors for",
|
||||||
|
"lowering.keys.candidates": "Lowering key door count because not enough candidates",
|
||||||
|
"lowering.keys.layouts": "Lowering key door count because no valid layouts",
|
||||||
|
"keydoor.shuffle.time": "Key door shuffle time",
|
||||||
|
"keydoor.shuffle.time.crossed": "Cross Dungeon: Key door shuffle time",
|
||||||
|
"generating.itempool": "Generating Item Pool",
|
||||||
|
"calc.access.rules": "Calculating Access Rules",
|
||||||
|
"placing.dungeon.prizes": "Placing Dungeon Prizes",
|
||||||
|
"placing.dungeon.items": "Placing Dungeon Items",
|
||||||
|
"keylock.detected": "Keylock detected",
|
||||||
|
"fill.world": "Fill the world",
|
||||||
|
"balance.doors": "-Balancing Doors",
|
||||||
|
"re-balancing": "-Re-balancing",
|
||||||
|
"balancing": "--Balancing",
|
||||||
|
"splitting.up": "Splitting Up",
|
||||||
|
"balance.multiworld": "Balancing multiworld progression",
|
||||||
|
"cannot.beat.game": "Cannot beat game! Something went terribly wrong here!",
|
||||||
|
"cannot.reach.progression": "Not all progression items reachable. Something went terribly wrong here.",
|
||||||
|
"cannot.reach.required": "Not all required items reachable. Something went terribly wrong here.",
|
||||||
|
"patching.rom": "Patching ROM",
|
||||||
|
"calc.playthrough": "Calculating playthrough",
|
||||||
|
"done": "Done. Enjoy.",
|
||||||
|
"total.time": "Total Time",
|
||||||
|
"finished.run": "Finished run",
|
||||||
|
"generation.failed": "Generation failed",
|
||||||
|
"generation.fail.rate": "Generation fail rate",
|
||||||
|
"generation.success.rate": "Generation success rate",
|
||||||
|
"enemizer.not.found": "Enemizer not found at",
|
||||||
|
"enemizer.nothing.applied": "No Enemizer options will be applied until this is resolved.",
|
||||||
|
"building.collection.spheres": "Building up collection spheres"
|
||||||
|
},
|
||||||
"help": {
|
"help": {
|
||||||
|
"lang": [ "App Language, if available, defaults to English" ],
|
||||||
"create_spoiler": [ "Output a Spoiler File" ],
|
"create_spoiler": [ "Output a Spoiler File" ],
|
||||||
"logic": [
|
"logic": [
|
||||||
"Select Enforcement of Item Requirements. (default: %(default)s)",
|
"Select Enforcement of Item Requirements. (default: %(default)s)",
|
||||||
|
|||||||
25
resources/app/cli/lang/es.json
Normal file
25
resources/app/cli/lang/es.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"cli": {
|
||||||
|
"app.title": "ALttP Puerta Aleatorizador",
|
||||||
|
"version": "Versión",
|
||||||
|
"seed": "Número",
|
||||||
|
"player": "Player",
|
||||||
|
"shuffling.world": "Barajando el Mundo",
|
||||||
|
"shuffling.dungeons": "Barajando Mazmorras",
|
||||||
|
"balance.doors": "-Equilibriando Puertas",
|
||||||
|
"re-balancing": "-Reequilibriando",
|
||||||
|
"balancing": "--Equilibriando",
|
||||||
|
"splitting.up": "División",
|
||||||
|
"basic.traversal": "--Recorrido Básico",
|
||||||
|
"generating.dungeon": "Generando mazmorra",
|
||||||
|
"shuffling.keydoors": "Barajando Puertas Clave para",
|
||||||
|
"placing.dungeon.prizes": "Placing Dungeon Prizes",
|
||||||
|
"placing.dungeon.items": "Placing Dungeon Items",
|
||||||
|
"keylock.detected": "Bloqueo de Teclas detectado",
|
||||||
|
"fill.world": "Llenar el Mundo",
|
||||||
|
"patching.rom": "Parchear ROM",
|
||||||
|
"calc.playthrough": "Cálculo de Juego",
|
||||||
|
"generation.failed": "Generación Fallida",
|
||||||
|
"enemizer.not.found": "Enemizer no encontrado en"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,7 +34,8 @@ class BabelFish():
|
|||||||
with open(langs_filename,encoding="utf-8") as f: #open it
|
with open(langs_filename,encoding="utf-8") as f: #open it
|
||||||
self.lang_defns[lang][key[:key.rfind(os.sep)].replace(os.sep,'.')] = json.load(f) #save translation definitions
|
self.lang_defns[lang][key[:key.rfind(os.sep)].replace(os.sep,'.')] = json.load(f) #save translation definitions
|
||||||
else:
|
else:
|
||||||
print(langs_filename + " not found for translation!")
|
pass
|
||||||
|
# print(langs_filename + " not found for translation!")
|
||||||
|
|
||||||
def translate(self, domain="", key="", subkey=""): #three levels of keys
|
def translate(self, domain="", key="", subkey=""): #three levels of keys
|
||||||
# start with nothing
|
# start with nothing
|
||||||
|
|||||||
Reference in New Issue
Block a user