-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathRandomSettingsGenerator.py
162 lines (133 loc) · 6.76 KB
/
RandomSettingsGenerator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
""" Run this script to roll a random settings seed! """
import sys
import os
import traceback
import argparse
import update_randomizer as ur
ur.check_python()
ur.check_version()
from utils import cleanup
import rsl_tools as tools
import roll_settings as rs
global_override_fname = None
# Please set the weights file you with to load
WEIGHTS = "RSL" # The default Random Settings League Season 7 weights
# Every setting with even weights
# WEIGHTS = "full-random"
# Provide your own weights file. If the specified file does not exist, this will create it
# WEIGHTS = "my_weights.json"
# global_override_fname = "multiworld_override.json"
# global_override_fname = "ddr_override.json"
# global_override_fname = "beginner_override.json"
# global_override_fname = "coop_override.json"
if global_override_fname is not None:
global_override_fname = os.path.join("weights", global_override_fname)
# Handle all uncaught exceptions with logging
def error_handler(errortype, value, trace):
""" Custom error handler to write errors to file """
if LOG_ERRORS:
with open("ERRORLOG.TXT", 'w') as errout:
traceback.print_exception(errortype, value, trace, file=errout)
traceback.print_exception(errortype, value, trace, file=sys.stdout)
if errortype == tools.RandomizerError:
sys.exit(3)
sys.excepthook = error_handler
def range_limited_int_type(arg):
""" Type function for argparse - a positive int """
try:
i = int(arg)
except ValueError:
raise argparse.ArgumentTypeError("Must be an integer")
if i < 1:
raise argparse.ArgumentTypeError("Argument must be > 0")
return i
def get_command_line_args():
""" Parse the command line arguements """
global LOG_ERRORS
LOG_ERRORS = True
parser = argparse.ArgumentParser()
parser.add_argument("--no_seed", action="store_true",
help="Suppresses the generation of a patch file.")
parser.add_argument("--override", help="Use the specified weights file over the default RSL weights.")
parser.add_argument("--worldcount", type=range_limited_int_type, default=1,
help="Generate a seed with more than 1 world.")
parser.add_argument("--check_new_settings", action="store_true",
help="When the version updates, run with this flag to find changes to settings names or new settings.")
parser.add_argument("--no_log_errors", action="store_true", default=False,
help="Only show errors in the console, don't log them to a file.")
parser.add_argument("--plando_filename_base", default="random_settings",
help="First part of the file names for the generated plandomizer files.")
parser.add_argument("--stress_test", type=range_limited_int_type, default=1, dest="seed_count",
help="Generate the specified number of seeds for benchmarking.")
parser.add_argument("--benchmark", action="store_true",
help="Compare the specified weights file to spoiler log empirical data.")
parser.add_argument("--plando_retries", type=range_limited_int_type, default=5,
help="Retry limit for generating a plando file.")
parser.add_argument("--rando_retries", type=range_limited_int_type, default=3,
help="Retry limit for running the randomizer with a given settings plando.")
args = parser.parse_args()
# Parse weights override file
if args.override is not None:
if global_override_fname is not None:
raise RuntimeError("RSL GENERATOR ERROR: PROVIDING MULTIPLE SETTINGS WEIGHT OVERRIDES IS NOT SUPPORTED.")
if args.override != '-':
override_path = os.path.join(os.getcwd(), args.override)
if not os.path.isfile(override_path):
raise FileNotFoundError(f"RSL GENERATOR ERROR: CANNOT FIND SPECIFIED OVERRIDE FILE IN DIRECTORY:\n{override_path}")
# Parse args
LOG_ERRORS = not args.no_log_errors
# Condense everything into a dict
return {
"no_seed": args.no_seed,
"worldcount": args.worldcount,
"override_fname": args.override or global_override_fname,
"check_new_settings": args.check_new_settings,
"plando_filename_base": args.plando_filename_base,
"seed_count": args.seed_count,
"benchmark": args.benchmark,
"plando_retries": args.plando_retries,
"rando_retries": args.rando_retries
}
def main():
""" Roll a random settings seed """
args = get_command_line_args()
# If we only want to check for new/changed settings
if args["check_new_settings"]:
_, _, rslmultis, rslweights = rs.load_weights_file("weights/rsl_season7.json")
tools.check_for_setting_changes(rslweights, rs.generate_balanced_weights(None))
return
# If we only want to benchmark weights
if args["benchmark"]:
weight_options, weight_multiselect, weight_dict, start_with = rs.generate_weights_override(WEIGHTS, args["override_fname"])
tools.benchmark_weights(weight_options, weight_dict, weight_multiselect)
return
for i in range(args["seed_count"]):
if args["seed_count"] > 1:
print("Rolling test seed", i + 1, "...")
if LOG_ERRORS:
# Clean up error log from previous run, if any
cleanup('ERRORLOG.TXT')
plandos_to_cleanup = []
for i in range(args["plando_retries"]):
plando_filename = rs.generate_plando(WEIGHTS, args["override_fname"], args["no_seed"], args["plando_filename_base"])
if args["no_seed"]:
break
plandos_to_cleanup.append(plando_filename)
completed_process = tools.generate_patch_file(plando_filename=plando_filename, worldcount=args["worldcount"], max_retries=args["rando_retries"])
if completed_process.returncode == 0:
break
plandos_to_cleanup.remove(plando_filename)
if os.path.isfile(os.path.join('data', plando_filename)):
if not os.path.isdir('failed_settings'):
os.mkdir('failed_settings')
os.rename(os.path.join('data', plando_filename), os.path.join('failed_settings', plando_filename))
with open(os.path.join('failed_settings', plando_filename+'_errlog'), 'w+') as failed_err_msg:
failed_err_msg.write(completed_process.stderr)
if i == args["plando_retries"]-1 and completed_process.returncode != 0:
raise tools.RandomizerError(completed_process.stderr)
if not args["no_seed"]:
print(completed_process.stderr.split("Patching ROM")[-1])
for plando_filename in plandos_to_cleanup:
cleanup(os.path.join('data', plando_filename))
if __name__ == "__main__":
main()