Core: Attribute per slot random directly to the World and discourage using MultiWorld's random (#1649)
* add a random object to the World * use it in The Messenger * the worlds don't exist until the end of set options * set seed in lttp tests * use world.random for shop shuffle
This commit is contained in:
parent
6a88d5aa79
commit
a6ba185c55
|
@ -81,6 +81,7 @@ class MultiWorld():
|
|||
|
||||
random: random.Random
|
||||
per_slot_randoms: Dict[int, random.Random]
|
||||
"""Deprecated. Please use `self.random` instead."""
|
||||
|
||||
class AttributeProxy():
|
||||
def __init__(self, rule):
|
||||
|
@ -242,6 +243,7 @@ class MultiWorld():
|
|||
setattr(self, option_key, getattr(args, option_key, {}))
|
||||
|
||||
self.worlds[player] = world_type(self, player)
|
||||
self.worlds[player].random = self.per_slot_randoms[player]
|
||||
|
||||
def set_item_links(self):
|
||||
item_links = {}
|
||||
|
|
|
@ -203,6 +203,9 @@ class World(metaclass=AutoWorldRegister):
|
|||
location_names: ClassVar[Set[str]]
|
||||
"""set of all potential location names"""
|
||||
|
||||
random: random.Random
|
||||
"""This world's random object. Should be used for any randomization needed in world for this player slot."""
|
||||
|
||||
zip_path: ClassVar[Optional[pathlib.Path]] = None
|
||||
"""If loaded from a .apworld, this is the Path to it."""
|
||||
__file__: ClassVar[str]
|
||||
|
|
|
@ -14,6 +14,7 @@ from worlds import AutoWorld
|
|||
class TestDungeon(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.multiworld = MultiWorld(1)
|
||||
self.multiworld.set_seed(None)
|
||||
args = Namespace()
|
||||
for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items():
|
||||
setattr(args, name, {1: option.from_any(option.default)})
|
||||
|
|
|
@ -15,6 +15,7 @@ from worlds import AutoWorld
|
|||
class TestInverted(TestBase):
|
||||
def setUp(self):
|
||||
self.multiworld = MultiWorld(1)
|
||||
self.multiworld.set_seed(None)
|
||||
args = Namespace()
|
||||
for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items():
|
||||
setattr(args, name, {1: option.from_any(option.default)})
|
||||
|
|
|
@ -15,6 +15,7 @@ class TestInvertedBombRules(unittest.TestCase):
|
|||
|
||||
def setUp(self):
|
||||
self.multiworld = MultiWorld(1)
|
||||
self.multiworld.set_seed(None)
|
||||
self.multiworld.mode[1] = "inverted"
|
||||
args = Namespace
|
||||
for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items():
|
||||
|
|
|
@ -16,6 +16,7 @@ from worlds import AutoWorld
|
|||
class TestInvertedMinor(TestBase):
|
||||
def setUp(self):
|
||||
self.multiworld = MultiWorld(1)
|
||||
self.multiworld.set_seed(None)
|
||||
args = Namespace()
|
||||
for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items():
|
||||
setattr(args, name, {1: option.from_any(option.default)})
|
||||
|
|
|
@ -17,6 +17,7 @@ from worlds import AutoWorld
|
|||
class TestInvertedOWG(TestBase):
|
||||
def setUp(self):
|
||||
self.multiworld = MultiWorld(1)
|
||||
self.multiworld.set_seed(None)
|
||||
args = Namespace()
|
||||
for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items():
|
||||
setattr(args, name, {1: option.from_any(option.default)})
|
||||
|
|
|
@ -16,6 +16,7 @@ from worlds import AutoWorld
|
|||
class TestMinor(TestBase):
|
||||
def setUp(self):
|
||||
self.multiworld = MultiWorld(1)
|
||||
self.multiworld.set_seed(None)
|
||||
args = Namespace()
|
||||
for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items():
|
||||
setattr(args, name, {1: option.from_any(option.default)})
|
||||
|
|
|
@ -17,6 +17,7 @@ from worlds import AutoWorld
|
|||
class TestVanillaOWG(TestBase):
|
||||
def setUp(self):
|
||||
self.multiworld = MultiWorld(1)
|
||||
self.multiworld.set_seed(None)
|
||||
args = Namespace()
|
||||
for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items():
|
||||
setattr(args, name, {1: option.from_any(option.default)})
|
||||
|
|
|
@ -15,6 +15,7 @@ from worlds import AutoWorld
|
|||
class TestVanilla(TestBase):
|
||||
def setUp(self):
|
||||
self.multiworld = MultiWorld(1)
|
||||
self.multiworld.set_seed(None)
|
||||
args = Namespace()
|
||||
for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items():
|
||||
setattr(args, name, {1: option.from_any(option.default)})
|
||||
|
|
|
@ -75,13 +75,12 @@ FIGURINES: Dict[str, ShopData] = {
|
|||
def shuffle_shop_prices(world: MessengerWorld) -> Tuple[Dict[str, int], Dict[str, int]]:
|
||||
shop_price_mod = world.multiworld.shop_price[world.player].value
|
||||
shop_price_planned = world.multiworld.shop_price_plan[world.player]
|
||||
local_random: Random = world.multiworld.per_slot_randoms[world.player]
|
||||
|
||||
shop_prices: Dict[str, int] = {}
|
||||
figurine_prices: Dict[str, int] = {}
|
||||
for item, price in shop_price_planned.value.items():
|
||||
if not isinstance(price, int):
|
||||
price = local_random.choices(list(price.keys()), weights=list(price.values()))[0]
|
||||
price = world.random.choices(list(price.keys()), weights=list(price.values()))[0]
|
||||
if "Figurine" in item:
|
||||
figurine_prices[item] = price
|
||||
else:
|
||||
|
@ -90,7 +89,7 @@ def shuffle_shop_prices(world: MessengerWorld) -> Tuple[Dict[str, int], Dict[str
|
|||
remaining_slots = [item for item in [*SHOP_ITEMS, *FIGURINES] if item not in shop_price_planned.value]
|
||||
for shop_item in remaining_slots:
|
||||
shop_data = SHOP_ITEMS.get(shop_item, FIGURINES.get(shop_item))
|
||||
price = local_random.randint(shop_data.min_price, shop_data.max_price)
|
||||
price = world.random.randint(shop_data.min_price, shop_data.max_price)
|
||||
adjusted_price = min(int(price * shop_price_mod / 100), 5000)
|
||||
if "Figurine" in shop_item:
|
||||
figurine_prices[shop_item] = adjusted_price
|
||||
|
|
|
@ -102,7 +102,7 @@ class MessengerWorld(World):
|
|||
# make a list of all notes except those in the player's defined starting inventory, and adjust the
|
||||
# amount we need to put in the itempool and precollect based on that
|
||||
notes = [note for note in NOTES if note not in self.multiworld.precollected_items[self.player]]
|
||||
self.multiworld.per_slot_randoms[self.player].shuffle(notes)
|
||||
self.random.shuffle(notes)
|
||||
precollected_notes_amount = NotesNeeded.range_end - \
|
||||
self.multiworld.notes_needed[self.player] - \
|
||||
(len(NOTES) - len(notes))
|
||||
|
@ -129,7 +129,7 @@ class MessengerWorld(World):
|
|||
filler_pool = dict(list(FILLER.items())[2:]) if remaining_fill < 10 else FILLER
|
||||
itempool += [self.create_item(filler_item)
|
||||
for filler_item in
|
||||
self.multiworld.random.choices(
|
||||
self.random.choices(
|
||||
list(filler_pool),
|
||||
weights=list(filler_pool.values()),
|
||||
k=remaining_fill
|
||||
|
|
Loading…
Reference in New Issue