implement Range option type

This commit is contained in:
Fabian Dill 2021-06-08 14:15:23 +02:00
parent 4b5ac3f926
commit adda0eff4a
4 changed files with 42 additions and 30 deletions

View File

@ -94,12 +94,8 @@ def main(args, seed=None):
world.compassshuffle = args.compassshuffle.copy() world.compassshuffle = args.compassshuffle.copy()
world.keyshuffle = args.keyshuffle.copy() world.keyshuffle = args.keyshuffle.copy()
world.bigkeyshuffle = args.bigkeyshuffle.copy() world.bigkeyshuffle = args.bigkeyshuffle.copy()
world.crystals_needed_for_ganon = { world.crystals_needed_for_ganon = args.crystals_ganon.copy()
player: world.random.randint(0, 7) if args.crystals_ganon[player] == 'random' else int( world.crystals_needed_for_gt = args.crystals_gt.copy()
args.crystals_ganon[player]) for player in range(1, world.players + 1)}
world.crystals_needed_for_gt = {
player: world.random.randint(0, 7) if args.crystals_gt[player] == 'random' else int(args.crystals_gt[player])
for player in range(1, world.players + 1)}
world.open_pyramid = args.open_pyramid.copy() world.open_pyramid = args.open_pyramid.copy()
world.boss_shuffle = args.shufflebosses.copy() world.boss_shuffle = args.shufflebosses.copy()
world.enemy_shuffle = args.enemy_shuffle.copy() world.enemy_shuffle = args.enemy_shuffle.copy()

View File

@ -632,14 +632,12 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
# fast ganon + ganon at hole # fast ganon + ganon at hole
ret.open_pyramid = get_choice('open_pyramid', weights, 'goal') ret.open_pyramid = get_choice('open_pyramid', weights, 'goal')
ret.crystals_gt = prefer_int(get_choice('tower_open', weights)) ret.crystals_gt = Options.Crystals.from_any(get_choice('tower_open', weights)).value
ret.crystals_ganon = Options.Crystals.from_any(get_choice('ganon_open', weights)).value
ret.crystals_ganon = prefer_int(get_choice('ganon_open', weights))
extra_pieces = get_choice('triforce_pieces_mode', weights, 'available') extra_pieces = get_choice('triforce_pieces_mode', weights, 'available')
ret.triforce_pieces_required = int(get_choice('triforce_pieces_required', weights, 20)) ret.triforce_pieces_required = Options.TriforcePieces.from_any(get_choice('triforce_pieces_required', weights)).value
ret.triforce_pieces_required = min(max(1, int(ret.triforce_pieces_required)), 90)
# sum a percentage to required # sum a percentage to required
if extra_pieces == 'percentage': if extra_pieces == 'percentage':
@ -647,7 +645,7 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
ret.triforce_pieces_available = int(round(ret.triforce_pieces_required * percentage, 0)) ret.triforce_pieces_available = int(round(ret.triforce_pieces_required * percentage, 0))
# vanilla mode (specify how many pieces are) # vanilla mode (specify how many pieces are)
elif extra_pieces == 'available': elif extra_pieces == 'available':
ret.triforce_pieces_available = int(get_choice('triforce_pieces_available', weights, 30)) ret.triforce_pieces_available = Options.TriforcePieces.from_any(get_choice('triforce_pieces_available', weights)).value
# required pieces + fixed extra # required pieces + fixed extra
elif extra_pieces == 'extra': elif extra_pieces == 'extra':
extra_pieces = max(0, int(get_choice('triforce_pieces_extra', weights, 10))) extra_pieces = max(0, int(get_choice('triforce_pieces_extra', weights, 10)))
@ -655,11 +653,7 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
# change minimum to required pieces to avoid problems # change minimum to required pieces to avoid problems
ret.triforce_pieces_available = min(max(ret.triforce_pieces_required, int(ret.triforce_pieces_available)), 90) ret.triforce_pieces_available = min(max(ret.triforce_pieces_required, int(ret.triforce_pieces_available)), 90)
shuffle_slots = get_choice('shop_shuffle_slots', weights, '0') ret.shop_shuffle_slots = Options.TriforcePieces.from_any(get_choice('shop_shuffle_slots', weights)).value
if str(shuffle_slots).lower() == "random":
ret.shop_shuffle_slots = random.randint(0, 30)
else:
ret.shop_shuffle_slots = int(shuffle_slots)
ret.shop_shuffle = get_choice('shop_shuffle', weights, '') ret.shop_shuffle = get_choice('shop_shuffle', weights, '')
if not ret.shop_shuffle: if not ret.shop_shuffle:

View File

@ -1,5 +1,6 @@
from __future__ import annotations from __future__ import annotations
import typing import typing
import random
class AssembleOptions(type): class AssembleOptions(type):
@ -108,6 +109,29 @@ class Choice(Option):
return cls(data) return cls(data)
return cls.from_text(str(data)) return cls.from_text(str(data))
class Range(Option):
range_start = 0
range_end = 1
def __init__(self, value: typing.Union[str, int]):
self.value: typing.Union[str, int] = value
@classmethod
def from_text(cls, text: str) -> Range:
if text.lower() == "random":
return cls(random.randint(cls.range_start, cls.range_end))
number = int(text)
if number < cls.range_start:
raise Exception(f"{number} is lower than minimum {cls.range_start} for option {cls.__name__}")
elif number > cls.range_end:
raise Exception(f"{number} is higher than maximum {cls.range_end} for option {cls.__name__}")
else:
return cls(number)
@classmethod
def from_any(cls, data: typing.Any) -> Range:
if type(data) == int:
return cls(data)
return cls.from_text(str(data))
class OptionNameSet(Option): class OptionNameSet(Option):
default = frozenset() default = frozenset()
@ -173,18 +197,17 @@ class Accessibility(Choice):
option_beatable = 2 option_beatable = 2
class Crystals(Choice): class Crystals(Range):
# can't use IntEnum since there's also random range_start = 0
option_0 = 0 range_end = 7
option_1 = 1
option_2 = 2
option_3 = 3
option_4 = 4
option_5 = 5
option_6 = 6
option_7 = 7
option_random = -1
class TriforcePieces(Range):
range_start = 1
range_end = 90
class ShopShuffleSlots(Range):
range_start = 0
range_end = 30
class WorldState(Choice): class WorldState(Choice):
option_standard = 1 option_standard = 1

View File

@ -206,11 +206,10 @@ def parse_arguments(argv, no_defaults=False):
0-7: Number of crystals needed 0-7: Number of crystals needed
''') ''')
parser.add_argument('--crystals_gt', default=defval('7'), const='7', nargs='?', parser.add_argument('--crystals_gt', default=defval('7'), const='7', nargs='?',
choices=['random', '0', '1', '2', '3', '4', '5', '6', '7'], choices=['0', '1', '2', '3', '4', '5', '6', '7'],
help='''\ help='''\
How many crystals are needed to open GT. For inverted mode How many crystals are needed to open GT. For inverted mode
this applies to the castle tower door instead. (default: %(default)s) this applies to the castle tower door instead. (default: %(default)s)
Random: Picks a random value between 0 and 7 (inclusive).
0-7: Number of crystals needed 0-7: Number of crystals needed
''') ''')
parser.add_argument('--open_pyramid', default=defval('auto'), help='''\ parser.add_argument('--open_pyramid', default=defval('auto'), help='''\