update Options system, preparing for integration

This commit is contained in:
Fabian Dill 2020-10-24 06:43:35 +02:00
parent 1d58f54101
commit 68a1070237
1 changed files with 112 additions and 50 deletions

View File

@ -1,86 +1,142 @@
from __future__ import annotations from __future__ import annotations
from enum import IntEnum, auto, Enum import typing
class Toggle(IntEnum): class AssembleOptions(type):
off = 0 def __new__(cls, name, bases, attrs):
on = 1 options = attrs["options"] = {}
name_lookup = attrs["name_lookup"] = {}
for base in bases:
options.update(base.options)
name_lookup.update(name_lookup)
new_options = {name[7:].lower(): option_id for name, option_id in attrs.items() if
name.startswith("option_")}
attrs["name_lookup"].update({option_id: name for name, option_id in new_options.items()})
options.update(new_options)
#apply aliases, without name_lookup
options.update({name[6:].lower(): option_id for name, option_id in attrs.items() if
name.startswith("alias_")})
return super(AssembleOptions, cls).__new__(cls, name, bases, attrs)
class Option(metaclass=AssembleOptions):
value: int
name_lookup: typing.Dict[int, str]
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)
class Toggle(Option):
option_false = 0
option_true = 1
def __init__(self, value: int):
self.value = value
@classmethod @classmethod
def from_text(cls, text: str) -> Toggle: def from_text(cls, text: str) -> Toggle:
if text.lower() in {"off", "0", "false", "none", "null", "no"}: if text.lower() in {"off", "0", "false", "none", "null", "no"}:
return Toggle.off return cls(0)
else: else:
return Toggle.on return cls(1)
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
else:
return self.value > other
def get_option_name(self):
return bool(self.value)
class Choice(Option):
def __init__(self, value: int):
self.value: int = value
class Choice(IntEnum):
@classmethod @classmethod
def from_text(cls, text: str) -> Choice: def from_text(cls, text: str) -> Choice:
for option in cls:
if option.name == text.lower(): for optionname, value in cls.options.items():
return option if optionname == text.lower():
return cls(value)
raise KeyError( raise KeyError(
f'Could not find option "{text}" for "{cls.__name__}", known options are {", ".join(f"{option.name}" for option in cls)}') f'Could not find option "{text}" for "{cls.__name__}", '
f'known options are {", ".join(f"{option}" for option in cls.name_lookup.values())}')
class Logic(Choice): class Logic(Choice):
no_glitches = auto() option_no_glitches = 0
no_logic = auto() option_minor_glitches = 1
option_overworld_glitches = 2
option_no_logic = 4
alias_owg = 2
class Goal(Choice): class Goal(Choice):
ganon = auto() option_ganon = 0
fast_ganon = auto() option_fast_ganon = 1
all_dungeons = auto() option_all_dungeons = 2
pedestal = auto() option_pedestal = 3
triforce_hunt = auto() option_triforce_hunt = 4
class Accessibility(Choice): class Accessibility(Choice):
locations = auto() option_locations = 0
items = auto() option_items = 1
beatable = auto() option_beatable = 2
class Crystals(Enum): class Crystals(Choice):
# can't use IntEnum since there's also random # can't use IntEnum since there's also random
C0 = 0 option_0 = 0
C1 = 1 option_1 = 1
C2 = 2 option_2 = 2
C3 = 3 option_3 = 3
C4 = 4 option_4 = 4
C5 = 5 option_5 = 5
C6 = 6 option_6 = 6
C7 = 7 option_7 = 7
Random = -1 option_random = -1
@staticmethod
def from_text(text: str) -> Crystals:
for option in Crystals:
if str(option.value) == text.lower():
return option
return Crystals.Random
class WorldState(Choice): class WorldState(Choice):
standard = auto() option_standard = 1
open = auto() option_open = 0
retro = auto() option_inverted = 2
inverted = auto()
class Bosses(Choice): class Bosses(Choice):
vanilla = auto() option_vanilla = 0
simple = auto() option_simple = 1
full = auto() option_full = 2
chaos = auto() option_chaos = 3
option_singularity = 4
class Enemies(Choice): class Enemies(Choice):
vanilla = auto() option_vanilla = 0
shuffled = auto() option_shuffled = 1
chaos = auto() option_chaos = 2
mapshuffle = Toggle mapshuffle = Toggle
@ -95,10 +151,16 @@ if __name__ == "__main__":
test = argparse.Namespace() test = argparse.Namespace()
test.logic = Logic.from_text("no_logic") test.logic = Logic.from_text("no_logic")
test.mapshuffle = mapshuffle.from_text("ON") test.mapshuffle = mapshuffle.from_text("ON")
test.hints = hints.from_text('OFF')
try: try:
test.logic = Logic.from_text("owg") test.logic = Logic.from_text("overworld_glitches_typo")
except KeyError as e:
print(e)
try:
test.logic_owg = Logic.from_text("owg")
except KeyError as e: except KeyError as e:
print(e) print(e)
if test.mapshuffle: if test.mapshuffle:
print("Mapshuffle is on") print("Mapshuffle is on")
print(f"Hints are {bool(test.hints)}")
print(test) print(test)