From 814851ba60ee3b80259394f4391a0cb19d0fd53d Mon Sep 17 00:00:00 2001 From: Brad Humphrey Date: Sat, 29 Jan 2022 09:20:04 -0700 Subject: [PATCH] Don't require every item to fill --- Fill.py | 18 +++++++++++------- test/general/TestFill.py | 27 ++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/Fill.py b/Fill.py index 2a85d9ce..f9cbbc7d 100644 --- a/Fill.py +++ b/Fill.py @@ -106,20 +106,24 @@ def fill_restrictive(world: MultiWorld, base_state: CollectionState, locations, placed_item.location = location if spot_to_fill is None: - # Maybe the game can be beaten anyway? + # Can't place this item, move on to the next unplaced_items.append(item_to_place) - if world.accessibility[item_to_place.player] != 'minimal' and world.can_beat_game(): - logging.warning( - f'Not all items placed. Game beatable anyway. (Could not place {item_to_place})') - continue - raise FillError(f'No more spots to place {item_to_place}, locations {locations} are invalid. ' - f'Already placed {len(placements)}: {", ".join(str(place) for place in placements)}') + continue world.push_item(spot_to_fill, item_to_place, False) spot_to_fill.locked = lock placements.append(spot_to_fill) spot_to_fill.event = True + if len(unplaced_items) > 0 and len(locations) > 0: + # There are leftover unplaceable items and locations that won't accept them + if world.can_beat_game(): + logging.warning( + f'Not all items placed. Game beatable anyway. (Could not place {unplaced_items})') + else: + raise FillError(f'No more spots to place {unplaced_items}, locations {locations} are invalid. ' + f'Already placed {len(placements)}: {", ".join(str(place) for place in placements)}') + itempool.extend(unplaced_items) diff --git a/test/general/TestFill.py b/test/general/TestFill.py index 8341ae7e..f68e06bf 100644 --- a/test/general/TestFill.py +++ b/test/general/TestFill.py @@ -342,14 +342,14 @@ class TestFillRestrictive(unittest.TestCase): multi_world.completion_condition[player1.id] = lambda state: state.has_all( names(player1.prog_items), player1.id) - region1 = player1.generate_region(player1.menu, 5) - region2 = player1.generate_region(player1.menu, 5, lambda state: state.has_all( + player1.generate_region(player1.menu, 5) + player1.generate_region(player1.menu, 5, lambda state: state.has_all( names(items[2:7]), player1.id)) - region3 = player1.generate_region(player1.menu, 5, lambda state: state.has_all( + player1.generate_region(player1.menu, 5, lambda state: state.has_all( names(items[7:12]), player1.id)) - region4 = player1.generate_region(player1.menu, 5, lambda state: state.has_all( + player1.generate_region(player1.menu, 5, lambda state: state.has_all( names(items[12:17]), player1.id)) - region5 = player1.generate_region(player1.menu, 5, lambda state: state.has_all( + player1.generate_region(player1.menu, 5, lambda state: state.has_all( names(items[17:22]), player1.id)) locations = multi_world.get_unfilled_locations() @@ -540,6 +540,23 @@ class TestDistributeItemsRestrictive(unittest.TestCase): self.assertEqual(gen1.locations[2].item, gen2.locations[2].item) self.assertEqual(gen1.locations[3].item, gen2.locations[3].item) + def test_can_reserve_advancement_items_for_general_fill(self): + multi_world = generate_multi_world() + player1 = generate_player_data( + multi_world, 1, location_count=5, prog_item_count=5) + items = player1.prog_items + multi_world.completion_condition[player1.id] = lambda state: state.has_all( + names(items), player1.id) + + location = player1.locations[0] + location.progress_type = LocationProgressType.PRIORITY + location.item_rule = lambda item: item != items[ + 0] and item != items[1] and item != items[2] and item != items[3] + + distribute_items_restrictive(multi_world) + + self.assertEqual(location.item, items[4]) + class TestBalanceMultiworldProgression(unittest.TestCase): def assertRegionContains(self, region: Region, item: Item):