[Core] Item plando early locations (and non-early locations) (#1228)
This commit is contained in:
parent
774581b7ba
commit
93a354cd81
85
Fill.py
85
Fill.py
|
@ -683,6 +683,17 @@ def distribute_planned(world: MultiWorld) -> None:
|
||||||
else:
|
else:
|
||||||
warn(warning, force)
|
warn(warning, force)
|
||||||
|
|
||||||
|
swept_state = world.state.copy()
|
||||||
|
swept_state.sweep_for_events()
|
||||||
|
reachable = frozenset(world.get_reachable_locations(swept_state))
|
||||||
|
early_locations: typing.Dict[int, typing.List[str]] = collections.defaultdict(list)
|
||||||
|
non_early_locations: typing.Dict[int, typing.List[str]] = collections.defaultdict(list)
|
||||||
|
for loc in world.get_unfilled_locations():
|
||||||
|
if loc in reachable:
|
||||||
|
early_locations[loc.player].append(loc.name)
|
||||||
|
else: # not reachable with swept state
|
||||||
|
non_early_locations[loc.player].append(loc.name)
|
||||||
|
|
||||||
# TODO: remove. Preferably by implementing key drop
|
# TODO: remove. Preferably by implementing key drop
|
||||||
from worlds.alttp.Regions import key_drop_data
|
from worlds.alttp.Regions import key_drop_data
|
||||||
world_name_lookup = world.world_name_lookup
|
world_name_lookup = world.world_name_lookup
|
||||||
|
@ -698,7 +709,39 @@ def distribute_planned(world: MultiWorld) -> None:
|
||||||
if 'from_pool' not in block:
|
if 'from_pool' not in block:
|
||||||
block['from_pool'] = True
|
block['from_pool'] = True
|
||||||
if 'world' not in block:
|
if 'world' not in block:
|
||||||
block['world'] = False
|
target_world = False
|
||||||
|
else:
|
||||||
|
target_world = block['world']
|
||||||
|
|
||||||
|
if target_world is False or world.players == 1: # target own world
|
||||||
|
worlds: typing.Set[int] = {player}
|
||||||
|
elif target_world is True: # target any worlds besides own
|
||||||
|
worlds = set(world.player_ids) - {player}
|
||||||
|
elif target_world is None: # target all worlds
|
||||||
|
worlds = set(world.player_ids)
|
||||||
|
elif type(target_world) == list: # list of target worlds
|
||||||
|
worlds = set()
|
||||||
|
for listed_world in target_world:
|
||||||
|
if listed_world not in world_name_lookup:
|
||||||
|
failed(f"Cannot place item to {target_world}'s world as that world does not exist.",
|
||||||
|
block['force'])
|
||||||
|
continue
|
||||||
|
worlds.add(world_name_lookup[listed_world])
|
||||||
|
elif type(target_world) == int: # target world by slot number
|
||||||
|
if target_world not in range(1, world.players + 1):
|
||||||
|
failed(
|
||||||
|
f"Cannot place item in world {target_world} as it is not in range of (1, {world.players})",
|
||||||
|
block['force'])
|
||||||
|
continue
|
||||||
|
worlds = {target_world}
|
||||||
|
else: # target world by slot name
|
||||||
|
if target_world not in world_name_lookup:
|
||||||
|
failed(f"Cannot place item to {target_world}'s world as that world does not exist.",
|
||||||
|
block['force'])
|
||||||
|
continue
|
||||||
|
worlds = {world_name_lookup[target_world]}
|
||||||
|
block['world'] = worlds
|
||||||
|
|
||||||
items: block_value = []
|
items: block_value = []
|
||||||
if "items" in block:
|
if "items" in block:
|
||||||
items = block["items"]
|
items = block["items"]
|
||||||
|
@ -735,6 +778,17 @@ def distribute_planned(world: MultiWorld) -> None:
|
||||||
for key, value in locations.items():
|
for key, value in locations.items():
|
||||||
location_list += [key] * value
|
location_list += [key] * value
|
||||||
locations = location_list
|
locations = location_list
|
||||||
|
|
||||||
|
if "early_locations" in locations:
|
||||||
|
locations.remove("early_locations")
|
||||||
|
for player in worlds:
|
||||||
|
locations += early_locations[player]
|
||||||
|
if "non_early_locations" in locations:
|
||||||
|
locations.remove("non_early_locations")
|
||||||
|
for player in worlds:
|
||||||
|
locations += non_early_locations[player]
|
||||||
|
|
||||||
|
|
||||||
block['locations'] = locations
|
block['locations'] = locations
|
||||||
|
|
||||||
if not block['count']:
|
if not block['count']:
|
||||||
|
@ -770,38 +824,11 @@ def distribute_planned(world: MultiWorld) -> None:
|
||||||
for placement in plando_blocks:
|
for placement in plando_blocks:
|
||||||
player = placement['player']
|
player = placement['player']
|
||||||
try:
|
try:
|
||||||
target_world = placement['world']
|
worlds = placement['world']
|
||||||
locations = placement['locations']
|
locations = placement['locations']
|
||||||
items = placement['items']
|
items = placement['items']
|
||||||
maxcount = placement['count']['target']
|
maxcount = placement['count']['target']
|
||||||
from_pool = placement['from_pool']
|
from_pool = placement['from_pool']
|
||||||
if target_world is False or world.players == 1: # target own world
|
|
||||||
worlds: typing.Set[int] = {player}
|
|
||||||
elif target_world is True: # target any worlds besides own
|
|
||||||
worlds = set(world.player_ids) - {player}
|
|
||||||
elif target_world is None: # target all worlds
|
|
||||||
worlds = set(world.player_ids)
|
|
||||||
elif type(target_world) == list: # list of target worlds
|
|
||||||
worlds = set()
|
|
||||||
for listed_world in target_world:
|
|
||||||
if listed_world not in world_name_lookup:
|
|
||||||
failed(f"Cannot place item to {target_world}'s world as that world does not exist.",
|
|
||||||
placement['force'])
|
|
||||||
continue
|
|
||||||
worlds.add(world_name_lookup[listed_world])
|
|
||||||
elif type(target_world) == int: # target world by slot number
|
|
||||||
if target_world not in range(1, world.players + 1):
|
|
||||||
failed(
|
|
||||||
f"Cannot place item in world {target_world} as it is not in range of (1, {world.players})",
|
|
||||||
placement['force'])
|
|
||||||
continue
|
|
||||||
worlds = {target_world}
|
|
||||||
else: # target world by slot name
|
|
||||||
if target_world not in world_name_lookup:
|
|
||||||
failed(f"Cannot place item to {target_world}'s world as that world does not exist.",
|
|
||||||
placement['force'])
|
|
||||||
continue
|
|
||||||
worlds = {world_name_lookup[target_world]}
|
|
||||||
|
|
||||||
candidates = list(location for location in world.get_unfilled_locations_for_players(locations,
|
candidates = list(location for location in world.get_unfilled_locations_for_players(locations,
|
||||||
worlds))
|
worlds))
|
||||||
|
|
|
@ -56,6 +56,9 @@ list of specific locations both in their own game or in another player's game.
|
||||||
* Multi Placement uses a plando block to place multiple items in multiple locations until either list is exhausted.
|
* Multi Placement uses a plando block to place multiple items in multiple locations until either list is exhausted.
|
||||||
* `items` defines the items to use, each with a number for the amount. Using `true` instead of a number uses however many of that item are in your item pool.
|
* `items` defines the items to use, each with a number for the amount. Using `true` instead of a number uses however many of that item are in your item pool.
|
||||||
* `locations` is a list of possible locations those items can be placed in.
|
* `locations` is a list of possible locations those items can be placed in.
|
||||||
|
* Some special location group names can be specified:
|
||||||
|
* `early_locations` will add all sphere 1 locations (locations logically reachable only with your starting inventory)
|
||||||
|
* `non_early_locations` will add all locations beyond sphere 1 (locations that require finding at least one item before they become logically reachable)
|
||||||
* Using the multi placement method, placements are picked randomly.
|
* Using the multi placement method, placements are picked randomly.
|
||||||
|
|
||||||
* `count` can be used to set the maximum number of items placed from the block. The default is 1 if using `item` and False if using `items`
|
* `count` can be used to set the maximum number of items placed from the block. The default is 1 if using `item` and False if using `items`
|
||||||
|
|
Loading…
Reference in New Issue