| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | from __future__ import annotations | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  | import typing | 
					
						
							| 
									
										
										
										
											2021-06-08 14:15:23 +02:00
										 |  |  | import random | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  | class AssembleOptions(type): | 
					
						
							| 
									
										
										
										
											2021-04-14 17:51:11 +02:00
										 |  |  |     def __new__(mcs, name, bases, attrs): | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |         options = attrs["options"] = {} | 
					
						
							|  |  |  |         name_lookup = attrs["name_lookup"] = {} | 
					
						
							|  |  |  |         for base in bases: | 
					
						
							| 
									
										
										
										
											2021-06-08 21:58:11 +02:00
										 |  |  |             if hasattr(base, "options"): | 
					
						
							|  |  |  |                 options.update(base.options) | 
					
						
							|  |  |  |                 name_lookup.update(name_lookup) | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |         new_options = {name[7:].lower(): option_id for name, option_id in attrs.items() if | 
					
						
							| 
									
										
										
										
											2021-03-21 00:47:17 +01:00
										 |  |  |                        name.startswith("option_")} | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |         attrs["name_lookup"].update({option_id: name for name, option_id in new_options.items()}) | 
					
						
							|  |  |  |         options.update(new_options) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 00:47:17 +01:00
										 |  |  |         # apply aliases, without name_lookup | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |         options.update({name[6:].lower(): option_id for name, option_id in attrs.items() if | 
					
						
							|  |  |  |                         name.startswith("alias_")}) | 
					
						
							| 
									
										
										
										
											2021-04-14 17:51:11 +02:00
										 |  |  |         return super(AssembleOptions, mcs).__new__(mcs, name, bases, attrs) | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 |  |  | class AssembleCategoryPath(type): | 
					
						
							|  |  |  |     def __new__(mcs, name, bases, attrs): | 
					
						
							|  |  |  |         path = [] | 
					
						
							|  |  |  |         for base in bases: | 
					
						
							|  |  |  |             if hasattr(base, "segment"): | 
					
						
							|  |  |  |                 path += base.segment | 
					
						
							|  |  |  |         path += attrs["segment"] | 
					
						
							|  |  |  |         attrs["path"] = path | 
					
						
							|  |  |  |         return super(AssembleCategoryPath, mcs).__new__(mcs, name, bases, attrs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class RootCategory(metaclass=AssembleCategoryPath): | 
					
						
							|  |  |  |     segment = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class LttPCategory(RootCategory): | 
					
						
							|  |  |  |     segment = ["A Link to the Past"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class LttPRomCategory(LttPCategory): | 
					
						
							|  |  |  |     segment = ["rom"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FactorioCategory(RootCategory): | 
					
						
							|  |  |  |     segment = ["Factorio"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MinecraftCategory(RootCategory): | 
					
						
							|  |  |  |     segment = ["Minecraft"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  | class Option(metaclass=AssembleOptions): | 
					
						
							|  |  |  |     value: int | 
					
						
							|  |  |  |     name_lookup: typing.Dict[int, str] | 
					
						
							| 
									
										
										
										
											2021-04-03 14:47:49 +02:00
										 |  |  |     default = 0 | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         return f"{self.__class__.__name__}({self.get_option_name()})" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __hash__(self): | 
					
						
							|  |  |  |         return hash(self.value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_option_name(self): | 
					
						
							|  |  |  |         return self.name_lookup[self.value] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __int__(self): | 
					
						
							|  |  |  |         return self.value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __bool__(self): | 
					
						
							|  |  |  |         return bool(self.value) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-14 08:38:02 +01:00
										 |  |  |     @classmethod | 
					
						
							|  |  |  |     def from_any(cls, data: typing.Any): | 
					
						
							|  |  |  |         raise NotImplementedError | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | class Toggle(Option): | 
					
						
							|  |  |  |     option_false = 0 | 
					
						
							|  |  |  |     option_true = 1 | 
					
						
							| 
									
										
										
										
											2021-04-03 14:47:49 +02:00
										 |  |  |     default = 0 | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, value: int): | 
					
						
							|  |  |  |         self.value = value | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @classmethod | 
					
						
							|  |  |  |     def from_text(cls, text: str) -> Toggle: | 
					
						
							|  |  |  |         if text.lower() in {"off", "0", "false", "none", "null", "no"}: | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |             return cls(0) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return cls(1) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-14 08:38:02 +01:00
										 |  |  |     @classmethod | 
					
						
							|  |  |  |     def from_any(cls, data: typing.Any): | 
					
						
							|  |  |  |         if type(data) == str: | 
					
						
							|  |  |  |             return cls.from_text(data) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return cls(data) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |     def __eq__(self, other): | 
					
						
							|  |  |  |         if isinstance(other, Toggle): | 
					
						
							|  |  |  |             return self.value == other.value | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return self.value == other | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __gt__(self, other): | 
					
						
							|  |  |  |         if isinstance(other, Toggle): | 
					
						
							|  |  |  |             return self.value > other.value | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |             return self.value > other | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 00:47:17 +01:00
										 |  |  |     def __bool__(self): | 
					
						
							|  |  |  |         return bool(self.value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __int__(self): | 
					
						
							|  |  |  |         return int(self.value) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |     def get_option_name(self): | 
					
						
							|  |  |  |         return bool(self.value) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-19 01:00:21 +02:00
										 |  |  | class DefaultOnToggle(Toggle): | 
					
						
							|  |  |  |     default = 1 | 
					
						
							| 
									
										
										
										
											2021-04-03 14:47:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  | class Choice(Option): | 
					
						
							|  |  |  |     def __init__(self, value: int): | 
					
						
							|  |  |  |         self.value: int = value | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @classmethod | 
					
						
							|  |  |  |     def from_text(cls, text: str) -> Choice: | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |         for optionname, value in cls.options.items(): | 
					
						
							|  |  |  |             if optionname == text.lower(): | 
					
						
							|  |  |  |                 return cls(value) | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  |         raise KeyError( | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |             f'Could not find option "{text}" for "{cls.__name__}", ' | 
					
						
							|  |  |  |             f'known options are {", ".join(f"{option}" for option in cls.name_lookup.values())}') | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-14 08:38:02 +01:00
										 |  |  |     @classmethod | 
					
						
							| 
									
										
										
										
											2021-05-09 17:46:26 +02:00
										 |  |  |     def from_any(cls, data: typing.Any) -> Choice: | 
					
						
							| 
									
										
										
										
											2021-04-08 19:53:24 +02:00
										 |  |  |         if type(data) == int and data in cls.options.values(): | 
					
						
							|  |  |  |             return cls(data) | 
					
						
							|  |  |  |         return cls.from_text(str(data)) | 
					
						
							| 
									
										
										
										
											2021-03-14 08:38:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 15:39:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:58:11 +02:00
										 |  |  | class Range(Option, int): | 
					
						
							| 
									
										
										
										
											2021-06-08 14:15:23 +02:00
										 |  |  |     range_start = 0 | 
					
						
							|  |  |  |     range_end = 1 | 
					
						
							| 
									
										
										
										
											2021-06-08 15:39:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, value: int): | 
					
						
							|  |  |  |         if value < self.range_start: | 
					
						
							|  |  |  |             raise Exception(f"{value} is lower than minimum {self.range_start} for option {self.__class__.__name__}") | 
					
						
							|  |  |  |         elif value > self.range_end: | 
					
						
							|  |  |  |             raise Exception(f"{value} is higher than maximum {self.range_end} for option {self.__class__.__name__}") | 
					
						
							| 
									
										
										
										
											2021-06-08 21:58:11 +02:00
										 |  |  |         self.value = value | 
					
						
							| 
									
										
										
										
											2021-06-08 14:15:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @classmethod | 
					
						
							|  |  |  |     def from_text(cls, text: str) -> Range: | 
					
						
							| 
									
										
										
										
											2021-06-08 14:48:00 +02:00
										 |  |  |         text = text.lower() | 
					
						
							|  |  |  |         if text.startswith("random"): | 
					
						
							|  |  |  |             if text == "random-low": | 
					
						
							|  |  |  |                 return cls(int(round(random.triangular(cls.range_start, cls.range_end, cls.range_start), 0))) | 
					
						
							|  |  |  |             elif text == "random-high": | 
					
						
							|  |  |  |                 return cls(int(round(random.triangular(cls.range_start, cls.range_end, cls.range_end), 0))) | 
					
						
							| 
									
										
										
										
											2021-06-12 21:05:45 +02:00
										 |  |  |             elif text == "random-middle": | 
					
						
							|  |  |  |                 return cls(int(round(random.triangular(cls.range_start, cls.range_end), 0))) | 
					
						
							| 
									
										
										
										
											2021-06-08 14:48:00 +02:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 return cls(random.randint(cls.range_start, cls.range_end)) | 
					
						
							| 
									
										
										
										
											2021-06-08 15:39:34 +02:00
										 |  |  |         return cls(int(text)) | 
					
						
							| 
									
										
										
										
											2021-06-08 14:15:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @classmethod | 
					
						
							|  |  |  |     def from_any(cls, data: typing.Any) -> Range: | 
					
						
							|  |  |  |         if type(data) == int: | 
					
						
							|  |  |  |             return cls(data) | 
					
						
							|  |  |  |         return cls.from_text(str(data)) | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:58:11 +02:00
										 |  |  |     def __str__(self): | 
					
						
							|  |  |  |         return str(self.value) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 15:39:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 17:46:26 +02:00
										 |  |  | class OptionNameSet(Option): | 
					
						
							|  |  |  |     default = frozenset() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, value: typing.Set[str]): | 
					
						
							|  |  |  |         self.value: typing.Set[str] = value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @classmethod | 
					
						
							|  |  |  |     def from_text(cls, text: str) -> OptionNameSet: | 
					
						
							|  |  |  |         return cls({option.strip() for option in text.split(",")}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @classmethod | 
					
						
							|  |  |  |     def from_any(cls, data: typing.Any) -> OptionNameSet: | 
					
						
							|  |  |  |         if type(data) == set: | 
					
						
							|  |  |  |             return cls(data) | 
					
						
							|  |  |  |         return cls.from_text(str(data)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class OptionDict(Option): | 
					
						
							|  |  |  |     default = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, value: typing.Dict[str, typing.Any]): | 
					
						
							|  |  |  |         self.value: typing.Dict[str, typing.Any] = value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @classmethod | 
					
						
							|  |  |  |     def from_any(cls, data: typing.Dict[str, typing.Any]) -> OptionDict: | 
					
						
							|  |  |  |         if type(data) == dict: | 
					
						
							|  |  |  |             return cls(data) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             raise NotImplementedError(f"Cannot Convert from non-dictionary, got {type(data)}") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 00:29:59 +02:00
										 |  |  |     def get_option_name(self): | 
					
						
							|  |  |  |         return str(self.value) | 
					
						
							| 
									
										
										
										
											2021-05-09 17:46:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 15:39:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | class Logic(Choice): | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |     option_no_glitches = 0 | 
					
						
							|  |  |  |     option_minor_glitches = 1 | 
					
						
							|  |  |  |     option_overworld_glitches = 2 | 
					
						
							|  |  |  |     option_no_logic = 4 | 
					
						
							|  |  |  |     alias_owg = 2 | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-24 19:46:13 +02:00
										 |  |  | class Objective(Choice): | 
					
						
							|  |  |  |     option_crystals = 0 | 
					
						
							| 
									
										
										
										
											2021-03-21 00:47:17 +01:00
										 |  |  |     # option_pendants = 1 | 
					
						
							| 
									
										
										
										
											2020-10-24 19:46:13 +02:00
										 |  |  |     option_triforce_pieces = 2 | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |     option_pedestal = 3 | 
					
						
							| 
									
										
										
										
											2020-10-24 19:46:13 +02:00
										 |  |  |     option_bingo = 4 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 00:47:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | local_objective = Toggle  # local triforce pieces, local dungeon prizes etc. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-24 19:46:13 +02:00
										 |  |  | class Goal(Choice): | 
					
						
							|  |  |  |     option_kill_ganon = 0 | 
					
						
							|  |  |  |     option_kill_ganon_and_gt_agahnim = 1 | 
					
						
							|  |  |  |     option_hand_in = 2 | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 00:47:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | class Accessibility(Choice): | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |     option_locations = 0 | 
					
						
							|  |  |  |     option_items = 1 | 
					
						
							|  |  |  |     option_beatable = 2 | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 14:15:23 +02:00
										 |  |  | class Crystals(Range): | 
					
						
							|  |  |  |     range_start = 0 | 
					
						
							|  |  |  |     range_end = 7 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 15:39:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:58:11 +02:00
										 |  |  | class CrystalsTower(Crystals): | 
					
						
							| 
									
										
										
										
											2021-06-08 22:14:56 +02:00
										 |  |  |     default = 7 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:58:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class CrystalsGanon(Crystals): | 
					
						
							|  |  |  |     default = 7 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 14:15:23 +02:00
										 |  |  | class TriforcePieces(Range): | 
					
						
							| 
									
										
										
										
											2021-06-14 23:41:47 +02:00
										 |  |  |     default = 30 | 
					
						
							| 
									
										
										
										
											2021-06-08 14:15:23 +02:00
										 |  |  |     range_start = 1 | 
					
						
							|  |  |  |     range_end = 90 | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 15:39:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:58:11 +02:00
										 |  |  | class ShopItemSlots(Range): | 
					
						
							| 
									
										
										
										
											2021-06-08 14:15:23 +02:00
										 |  |  |     range_start = 0 | 
					
						
							|  |  |  |     range_end = 30 | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 15:39:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | class WorldState(Choice): | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |     option_standard = 1 | 
					
						
							|  |  |  |     option_open = 0 | 
					
						
							|  |  |  |     option_inverted = 2 | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Bosses(Choice): | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |     option_vanilla = 0 | 
					
						
							|  |  |  |     option_simple = 1 | 
					
						
							|  |  |  |     option_full = 2 | 
					
						
							|  |  |  |     option_chaos = 3 | 
					
						
							|  |  |  |     option_singularity = 4 | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Enemies(Choice): | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |     option_vanilla = 0 | 
					
						
							|  |  |  |     option_shuffled = 1 | 
					
						
							|  |  |  |     option_chaos = 2 | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:58:11 +02:00
										 |  |  | alttp_options: typing.Dict[str, type(Option)] = { | 
					
						
							|  |  |  |     "crystals_needed_for_gt": CrystalsTower, | 
					
						
							|  |  |  |     "crystals_needed_for_ganon": CrystalsGanon, | 
					
						
							|  |  |  |     "shop_item_slots": ShopItemSlots, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-19 01:00:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-14 08:38:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:58:11 +02:00
										 |  |  | hollow_knight_randomize_options: typing.Dict[str, type(Option)] = { | 
					
						
							| 
									
										
										
										
											2021-06-19 01:00:21 +02:00
										 |  |  |     "RandomizeDreamers": DefaultOnToggle, | 
					
						
							|  |  |  |     "RandomizeSkills": DefaultOnToggle, | 
					
						
							|  |  |  |     "RandomizeCharms": DefaultOnToggle, | 
					
						
							|  |  |  |     "RandomizeKeys": DefaultOnToggle, | 
					
						
							|  |  |  |     "RandomizeGeoChests": Toggle, | 
					
						
							|  |  |  |     "RandomizeMaskShards": DefaultOnToggle, | 
					
						
							|  |  |  |     "RandomizeVesselFragments": DefaultOnToggle, | 
					
						
							|  |  |  |     "RandomizeCharmNotches": Toggle, | 
					
						
							|  |  |  |     "RandomizePaleOre": DefaultOnToggle, | 
					
						
							|  |  |  |     "RandomizeRancidEggs": Toggle, | 
					
						
							|  |  |  |     "RandomizeRelics": DefaultOnToggle, | 
					
						
							|  |  |  |     "RandomizeMaps": Toggle, | 
					
						
							|  |  |  |     "RandomizeStags": Toggle, | 
					
						
							|  |  |  |     "RandomizeGrubs": Toggle, | 
					
						
							|  |  |  |     "RandomizeWhisperingRoots": Toggle, | 
					
						
							|  |  |  |     "RandomizeRocks": Toggle, | 
					
						
							|  |  |  |     "RandomizeSoulTotems": Toggle, | 
					
						
							|  |  |  |     "RandomizePalaceTotems": Toggle, | 
					
						
							|  |  |  |     "RandomizeLoreTablets": Toggle, | 
					
						
							|  |  |  |     "RandomizeLifebloodCocoons": Toggle, | 
					
						
							|  |  |  |     "RandomizeFlames": Toggle | 
					
						
							| 
									
										
										
										
											2021-03-21 00:47:17 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hollow_knight_skip_options: typing.Dict[str, type(Option)] = { | 
					
						
							|  |  |  |     "MILDSKIPS": Toggle, | 
					
						
							|  |  |  |     "SPICYSKIPS": Toggle, | 
					
						
							|  |  |  |     "FIREBALLSKIPS": Toggle, | 
					
						
							|  |  |  |     "ACIDSKIPS": Toggle, | 
					
						
							|  |  |  |     "SPIKETUNNELS": Toggle, | 
					
						
							|  |  |  |     "DARKROOMS": Toggle, | 
					
						
							|  |  |  |     "CURSED": Toggle, | 
					
						
							|  |  |  |     "SHADESKIPS": Toggle, | 
					
						
							| 
									
										
										
										
											2021-03-14 08:38:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-13 11:14:05 +02:00
										 |  |  | hollow_knight_options: typing.Dict[str, type(Option)] = {**hollow_knight_randomize_options, | 
					
						
							|  |  |  |                                                          **hollow_knight_skip_options} | 
					
						
							| 
									
										
										
										
											2021-03-14 08:38:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-03 14:47:49 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | class MaxSciencePack(Choice): | 
					
						
							|  |  |  |     option_automation_science_pack = 0 | 
					
						
							|  |  |  |     option_logistic_science_pack = 1 | 
					
						
							|  |  |  |     option_military_science_pack = 2 | 
					
						
							|  |  |  |     option_chemical_science_pack = 3 | 
					
						
							|  |  |  |     option_production_science_pack = 4 | 
					
						
							|  |  |  |     option_utility_science_pack = 5 | 
					
						
							|  |  |  |     option_space_science_pack = 6 | 
					
						
							|  |  |  |     default = 6 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_allowed_packs(self): | 
					
						
							|  |  |  |         return {option.replace("_", "-") for option, value in self.options.items() | 
					
						
							|  |  |  |                 if value <= self.value} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TechCost(Choice): | 
					
						
							|  |  |  |     option_very_easy = 0 | 
					
						
							|  |  |  |     option_easy = 1 | 
					
						
							|  |  |  |     option_kind = 2 | 
					
						
							|  |  |  |     option_normal = 3 | 
					
						
							|  |  |  |     option_hard = 4 | 
					
						
							|  |  |  |     option_very_hard = 5 | 
					
						
							|  |  |  |     option_insane = 6 | 
					
						
							|  |  |  |     default = 3 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-13 11:14:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-06 21:16:25 +02:00
										 |  |  | class FreeSamples(Choice): | 
					
						
							|  |  |  |     option_none = 0 | 
					
						
							|  |  |  |     option_single_craft = 1 | 
					
						
							|  |  |  |     option_half_stack = 2 | 
					
						
							|  |  |  |     option_stack = 3 | 
					
						
							|  |  |  |     default = 3 | 
					
						
							| 
									
										
										
										
											2021-04-03 14:47:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-13 11:14:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-03 14:47:49 +02:00
										 |  |  | class TechTreeLayout(Choice): | 
					
						
							|  |  |  |     option_single = 0 | 
					
						
							| 
									
										
										
										
											2021-04-10 03:03:46 +02:00
										 |  |  |     option_small_diamonds = 1 | 
					
						
							| 
									
										
										
										
											2021-04-10 19:34:30 +02:00
										 |  |  |     option_medium_diamonds = 2 | 
					
						
							| 
									
										
										
										
											2021-06-06 20:26:40 +02:00
										 |  |  |     option_large_diamonds = 3 | 
					
						
							|  |  |  |     option_small_pyramids = 4 | 
					
						
							|  |  |  |     option_medium_pyramids = 5 | 
					
						
							|  |  |  |     option_large_pyramids = 6 | 
					
						
							|  |  |  |     option_small_funnels = 7 | 
					
						
							|  |  |  |     option_medium_funnels = 8 | 
					
						
							|  |  |  |     option_large_funnels = 9 | 
					
						
							|  |  |  |     option_funnels = 4 | 
					
						
							|  |  |  |     alias_pyramid = 6 | 
					
						
							|  |  |  |     alias_funnel = 9 | 
					
						
							| 
									
										
										
										
											2021-04-03 14:47:49 +02:00
										 |  |  |     default = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-13 11:14:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 19:53:24 +02:00
										 |  |  | class Visibility(Choice): | 
					
						
							|  |  |  |     option_none = 0 | 
					
						
							|  |  |  |     option_sending = 1 | 
					
						
							| 
									
										
										
										
											2021-04-13 12:38:39 +02:00
										 |  |  |     default = 1 | 
					
						
							| 
									
										
										
										
											2021-04-03 14:47:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 15:39:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-06 21:11:58 +02:00
										 |  |  | class RecipeTime(Choice): | 
					
						
							|  |  |  |     option_vanilla = 0 | 
					
						
							|  |  |  |     option_fast = 1 | 
					
						
							|  |  |  |     option_normal = 2 | 
					
						
							|  |  |  |     option_slow = 4 | 
					
						
							| 
									
										
										
										
											2021-06-06 21:38:53 +02:00
										 |  |  |     option_chaos = 5 | 
					
						
							| 
									
										
										
										
											2021-04-13 11:14:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 15:39:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 17:46:26 +02:00
										 |  |  | class FactorioStartItems(OptionDict): | 
					
						
							|  |  |  |     default = {"burner-mining-drill": 19, "stone-furnace": 19} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-19 01:00:21 +02:00
										 |  |  | factorio_options: typing.Dict[str, type(Option)] = { | 
					
						
							|  |  |  |     "max_science_pack": MaxSciencePack, | 
					
						
							|  |  |  |     "tech_tree_layout": TechTreeLayout, | 
					
						
							|  |  |  |     "tech_cost": TechCost, | 
					
						
							|  |  |  |     "free_samples": FreeSamples, | 
					
						
							|  |  |  |     "visibility": Visibility, | 
					
						
							|  |  |  |     "starting_items": FactorioStartItems, | 
					
						
							|  |  |  |     "recipe_time": RecipeTime, | 
					
						
							|  |  |  |     "imported_blueprints": DefaultOnToggle, | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-05-09 17:46:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-03 14:47:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Minecraft Randomizer
Squash merge, original Commits:
* Minecraft locations, items, and generation without logic
* added id lookup for minecraft
* typing import fix in minecraft/Items.py
* fix 2
* implementing Minecraft options and hard/postgame advancement exclusion
* first logic pass (75/80)
* logic pass 2 and proper completion conditions
* added insane difficulty pool, modified method of excluding item pools for easier extension
* bump network_data_package version
* minecraft testing framework
* switch Ancient Debris to Netherite Scrap to avoid advancement triggering on receiving that item
* Testing now functions, split tests up by advancement pane, added some story tests
* Newer testing framework: every advancement gets its own function, for ease of testing
* fixed logic for The End... Again...
* changed option names to "include_hard_advancements" etc.
* village/pillager-related advancements now require can_adventure: weapon + food
* a few minecraft tests
* rename "Flint & Steel" to "Flint and Steel" for parity with in-game name
* additional MC tests
* more tests, mostly nether-related tests
* more tests, removed anvil path for Two Birds One Arrow
* include Minecraft slot data, and a world seed for each Minecraft player slot
* Added new items: ender pearls, lapis, porkchops
* All remaining Minecraft tests
* formatting of Minecraft tests and logic for better readability
* require Wither kill for Monsters Hunted
* properly removed 8 Emeralds item from item pool
* enchanting required for wither; fishing rod required for water breathing; water breathing required for elder guardian kill
* Added 12 new advancements (ported from old achievement system)
* renamed "On a Rail" for consistency with modern advancements
* tests for the new advancements
* moved slot_data generation for minecraft into worlds/minecraft/__init__.py, added logic_version to slot_data
* output minecraft options in the spoiler log
* modified advancement goal values for new advancements
* make non-native Minecraft items appear as Shovel in ALttP, and unknown-game items as Power Stars
* fixed glowstone block logic for Not Quite Nine Lives
* setup for shuffling MC structures: building ER world and shuffling regions/entrances
* ensured Nether Fortresses can't be placed in the End
* finished logic for structure randomization
* fixed nonnative items always showing up as Hammers in ALttP shops
* output minecraft structure info in the spoiler
* generate .apmc file for communication with MC client
* fixed structure rando always using the same seed
* move stuff to worlds/minecraft/Regions.py
* make output apmc file have consistent name with other files
* added minecraft bottle macro; fixed tests imports
* generalizing MC region generation
* restructured structure shuffling in preparation for structure plando
* only output structure rando info in spoiler if they are shuffled
* Force structure rando to always be off, for the stable release
* added Minecraft options to player settings
* formally added combat_difficulty as an option
* Added Ender Dragon into playthrough, cleaned up goal map
* Added new difficulties: Easy, Normal, Hard combat
* moved .apmc generation time to prevent outputs on failed generation
* updated tests for new combat logic
* Fixed bug causing generation to fail; removed Nether Fortress event since it should no longer be needed with the fix
* moved all MC-specific functions into gen_minecraft
* renamed "logic_version" to "client_version"
* bug fixes
properly flagged event locations/items with id None
moved generation back to Main.py to fix mysterious generation failures
* moved link_minecraft_regions into minecraft init, left create_regions in Main for caching
* added seed_name, player_name, client_version to apmc file
* reenabled structure shuffle
* added entrance tests for minecraft
Co-authored-by: achuang <alexander.w.chuang@gmail.com>
											
										 
											2021-05-08 07:38:57 -04:00
										 |  |  | class AdvancementGoal(Choice): | 
					
						
							|  |  |  |     option_few = 0 | 
					
						
							|  |  |  |     option_normal = 1 | 
					
						
							|  |  |  |     option_many = 2 | 
					
						
							|  |  |  |     default = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 17:46:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | class CombatDifficulty(Choice): | 
					
						
							| 
									
										
											  
											
												Minecraft Randomizer
Squash merge, original Commits:
* Minecraft locations, items, and generation without logic
* added id lookup for minecraft
* typing import fix in minecraft/Items.py
* fix 2
* implementing Minecraft options and hard/postgame advancement exclusion
* first logic pass (75/80)
* logic pass 2 and proper completion conditions
* added insane difficulty pool, modified method of excluding item pools for easier extension
* bump network_data_package version
* minecraft testing framework
* switch Ancient Debris to Netherite Scrap to avoid advancement triggering on receiving that item
* Testing now functions, split tests up by advancement pane, added some story tests
* Newer testing framework: every advancement gets its own function, for ease of testing
* fixed logic for The End... Again...
* changed option names to "include_hard_advancements" etc.
* village/pillager-related advancements now require can_adventure: weapon + food
* a few minecraft tests
* rename "Flint & Steel" to "Flint and Steel" for parity with in-game name
* additional MC tests
* more tests, mostly nether-related tests
* more tests, removed anvil path for Two Birds One Arrow
* include Minecraft slot data, and a world seed for each Minecraft player slot
* Added new items: ender pearls, lapis, porkchops
* All remaining Minecraft tests
* formatting of Minecraft tests and logic for better readability
* require Wither kill for Monsters Hunted
* properly removed 8 Emeralds item from item pool
* enchanting required for wither; fishing rod required for water breathing; water breathing required for elder guardian kill
* Added 12 new advancements (ported from old achievement system)
* renamed "On a Rail" for consistency with modern advancements
* tests for the new advancements
* moved slot_data generation for minecraft into worlds/minecraft/__init__.py, added logic_version to slot_data
* output minecraft options in the spoiler log
* modified advancement goal values for new advancements
* make non-native Minecraft items appear as Shovel in ALttP, and unknown-game items as Power Stars
* fixed glowstone block logic for Not Quite Nine Lives
* setup for shuffling MC structures: building ER world and shuffling regions/entrances
* ensured Nether Fortresses can't be placed in the End
* finished logic for structure randomization
* fixed nonnative items always showing up as Hammers in ALttP shops
* output minecraft structure info in the spoiler
* generate .apmc file for communication with MC client
* fixed structure rando always using the same seed
* move stuff to worlds/minecraft/Regions.py
* make output apmc file have consistent name with other files
* added minecraft bottle macro; fixed tests imports
* generalizing MC region generation
* restructured structure shuffling in preparation for structure plando
* only output structure rando info in spoiler if they are shuffled
* Force structure rando to always be off, for the stable release
* added Minecraft options to player settings
* formally added combat_difficulty as an option
* Added Ender Dragon into playthrough, cleaned up goal map
* Added new difficulties: Easy, Normal, Hard combat
* moved .apmc generation time to prevent outputs on failed generation
* updated tests for new combat logic
* Fixed bug causing generation to fail; removed Nether Fortress event since it should no longer be needed with the fix
* moved all MC-specific functions into gen_minecraft
* renamed "logic_version" to "client_version"
* bug fixes
properly flagged event locations/items with id None
moved generation back to Main.py to fix mysterious generation failures
* moved link_minecraft_regions into minecraft init, left create_regions in Main for caching
* added seed_name, player_name, client_version to apmc file
* reenabled structure shuffle
* added entrance tests for minecraft
Co-authored-by: achuang <alexander.w.chuang@gmail.com>
											
										 
											2021-05-08 07:38:57 -04:00
										 |  |  |     option_easy = 0 | 
					
						
							|  |  |  |     option_normal = 1 | 
					
						
							|  |  |  |     option_hard = 2 | 
					
						
							|  |  |  |     default = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 17:46:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Minecraft Randomizer
Squash merge, original Commits:
* Minecraft locations, items, and generation without logic
* added id lookup for minecraft
* typing import fix in minecraft/Items.py
* fix 2
* implementing Minecraft options and hard/postgame advancement exclusion
* first logic pass (75/80)
* logic pass 2 and proper completion conditions
* added insane difficulty pool, modified method of excluding item pools for easier extension
* bump network_data_package version
* minecraft testing framework
* switch Ancient Debris to Netherite Scrap to avoid advancement triggering on receiving that item
* Testing now functions, split tests up by advancement pane, added some story tests
* Newer testing framework: every advancement gets its own function, for ease of testing
* fixed logic for The End... Again...
* changed option names to "include_hard_advancements" etc.
* village/pillager-related advancements now require can_adventure: weapon + food
* a few minecraft tests
* rename "Flint & Steel" to "Flint and Steel" for parity with in-game name
* additional MC tests
* more tests, mostly nether-related tests
* more tests, removed anvil path for Two Birds One Arrow
* include Minecraft slot data, and a world seed for each Minecraft player slot
* Added new items: ender pearls, lapis, porkchops
* All remaining Minecraft tests
* formatting of Minecraft tests and logic for better readability
* require Wither kill for Monsters Hunted
* properly removed 8 Emeralds item from item pool
* enchanting required for wither; fishing rod required for water breathing; water breathing required for elder guardian kill
* Added 12 new advancements (ported from old achievement system)
* renamed "On a Rail" for consistency with modern advancements
* tests for the new advancements
* moved slot_data generation for minecraft into worlds/minecraft/__init__.py, added logic_version to slot_data
* output minecraft options in the spoiler log
* modified advancement goal values for new advancements
* make non-native Minecraft items appear as Shovel in ALttP, and unknown-game items as Power Stars
* fixed glowstone block logic for Not Quite Nine Lives
* setup for shuffling MC structures: building ER world and shuffling regions/entrances
* ensured Nether Fortresses can't be placed in the End
* finished logic for structure randomization
* fixed nonnative items always showing up as Hammers in ALttP shops
* output minecraft structure info in the spoiler
* generate .apmc file for communication with MC client
* fixed structure rando always using the same seed
* move stuff to worlds/minecraft/Regions.py
* make output apmc file have consistent name with other files
* added minecraft bottle macro; fixed tests imports
* generalizing MC region generation
* restructured structure shuffling in preparation for structure plando
* only output structure rando info in spoiler if they are shuffled
* Force structure rando to always be off, for the stable release
* added Minecraft options to player settings
* formally added combat_difficulty as an option
* Added Ender Dragon into playthrough, cleaned up goal map
* Added new difficulties: Easy, Normal, Hard combat
* moved .apmc generation time to prevent outputs on failed generation
* updated tests for new combat logic
* Fixed bug causing generation to fail; removed Nether Fortress event since it should no longer be needed with the fix
* moved all MC-specific functions into gen_minecraft
* renamed "logic_version" to "client_version"
* bug fixes
properly flagged event locations/items with id None
moved generation back to Main.py to fix mysterious generation failures
* moved link_minecraft_regions into minecraft init, left create_regions in Main for caching
* added seed_name, player_name, client_version to apmc file
* reenabled structure shuffle
* added entrance tests for minecraft
Co-authored-by: achuang <alexander.w.chuang@gmail.com>
											
										 
											2021-05-08 07:38:57 -04:00
										 |  |  | minecraft_options: typing.Dict[str, type(Option)] = { | 
					
						
							| 
									
										
										
										
											2021-05-09 17:46:26 +02:00
										 |  |  |     "advancement_goal": AdvancementGoal, | 
					
						
							| 
									
										
											  
											
												Minecraft Randomizer
Squash merge, original Commits:
* Minecraft locations, items, and generation without logic
* added id lookup for minecraft
* typing import fix in minecraft/Items.py
* fix 2
* implementing Minecraft options and hard/postgame advancement exclusion
* first logic pass (75/80)
* logic pass 2 and proper completion conditions
* added insane difficulty pool, modified method of excluding item pools for easier extension
* bump network_data_package version
* minecraft testing framework
* switch Ancient Debris to Netherite Scrap to avoid advancement triggering on receiving that item
* Testing now functions, split tests up by advancement pane, added some story tests
* Newer testing framework: every advancement gets its own function, for ease of testing
* fixed logic for The End... Again...
* changed option names to "include_hard_advancements" etc.
* village/pillager-related advancements now require can_adventure: weapon + food
* a few minecraft tests
* rename "Flint & Steel" to "Flint and Steel" for parity with in-game name
* additional MC tests
* more tests, mostly nether-related tests
* more tests, removed anvil path for Two Birds One Arrow
* include Minecraft slot data, and a world seed for each Minecraft player slot
* Added new items: ender pearls, lapis, porkchops
* All remaining Minecraft tests
* formatting of Minecraft tests and logic for better readability
* require Wither kill for Monsters Hunted
* properly removed 8 Emeralds item from item pool
* enchanting required for wither; fishing rod required for water breathing; water breathing required for elder guardian kill
* Added 12 new advancements (ported from old achievement system)
* renamed "On a Rail" for consistency with modern advancements
* tests for the new advancements
* moved slot_data generation for minecraft into worlds/minecraft/__init__.py, added logic_version to slot_data
* output minecraft options in the spoiler log
* modified advancement goal values for new advancements
* make non-native Minecraft items appear as Shovel in ALttP, and unknown-game items as Power Stars
* fixed glowstone block logic for Not Quite Nine Lives
* setup for shuffling MC structures: building ER world and shuffling regions/entrances
* ensured Nether Fortresses can't be placed in the End
* finished logic for structure randomization
* fixed nonnative items always showing up as Hammers in ALttP shops
* output minecraft structure info in the spoiler
* generate .apmc file for communication with MC client
* fixed structure rando always using the same seed
* move stuff to worlds/minecraft/Regions.py
* make output apmc file have consistent name with other files
* added minecraft bottle macro; fixed tests imports
* generalizing MC region generation
* restructured structure shuffling in preparation for structure plando
* only output structure rando info in spoiler if they are shuffled
* Force structure rando to always be off, for the stable release
* added Minecraft options to player settings
* formally added combat_difficulty as an option
* Added Ender Dragon into playthrough, cleaned up goal map
* Added new difficulties: Easy, Normal, Hard combat
* moved .apmc generation time to prevent outputs on failed generation
* updated tests for new combat logic
* Fixed bug causing generation to fail; removed Nether Fortress event since it should no longer be needed with the fix
* moved all MC-specific functions into gen_minecraft
* renamed "logic_version" to "client_version"
* bug fixes
properly flagged event locations/items with id None
moved generation back to Main.py to fix mysterious generation failures
* moved link_minecraft_regions into minecraft init, left create_regions in Main for caching
* added seed_name, player_name, client_version to apmc file
* reenabled structure shuffle
* added entrance tests for minecraft
Co-authored-by: achuang <alexander.w.chuang@gmail.com>
											
										 
											2021-05-08 07:38:57 -04:00
										 |  |  |     "combat_difficulty": CombatDifficulty, | 
					
						
							|  |  |  |     "include_hard_advancements": Toggle, | 
					
						
							|  |  |  |     "include_insane_advancements": Toggle, | 
					
						
							|  |  |  |     "include_postgame_advancements": Toggle, | 
					
						
							|  |  |  |     "shuffle_structures": Toggle | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-04-11 18:19:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:58:11 +02:00
										 |  |  | option_sets = ( | 
					
						
							|  |  |  |     minecraft_options, | 
					
						
							|  |  |  |     factorio_options, | 
					
						
							|  |  |  |     alttp_options, | 
					
						
							|  |  |  |     hollow_knight_options | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     import argparse | 
					
						
							| 
									
										
										
										
											2021-06-19 01:00:21 +02:00
										 |  |  |     mapshuffle = Toggle | 
					
						
							|  |  |  |     compassshuffle = Toggle | 
					
						
							|  |  |  |     keyshuffle = Toggle | 
					
						
							|  |  |  |     bigkeyshuffle = Toggle | 
					
						
							|  |  |  |     hints = Toggle | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  |     test = argparse.Namespace() | 
					
						
							|  |  |  |     test.logic = Logic.from_text("no_logic") | 
					
						
							|  |  |  |     test.mapshuffle = mapshuffle.from_text("ON") | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |     test.hints = hints.from_text('OFF') | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         test.logic = Logic.from_text("overworld_glitches_typo") | 
					
						
							|  |  |  |     except KeyError as e: | 
					
						
							|  |  |  |         print(e) | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |         test.logic_owg = Logic.from_text("owg") | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  |     except KeyError as e: | 
					
						
							|  |  |  |         print(e) | 
					
						
							|  |  |  |     if test.mapshuffle: | 
					
						
							|  |  |  |         print("Mapshuffle is on") | 
					
						
							| 
									
										
										
										
											2020-10-24 06:43:35 +02:00
										 |  |  |     print(f"Hints are {bool(test.hints)}") | 
					
						
							| 
									
										
										
										
											2020-03-18 16:15:32 +01:00
										 |  |  |     print(test) |