From 814b1dd2726b24f60c8dedc1b7c4f869e07ec62c Mon Sep 17 00:00:00 2001 From: Tacoman369 <90735287+Tacoman369@users.noreply.github.com> Date: Sat, 31 May 2025 14:34:46 -0500 Subject: [PATCH 1/4] Update fill.cpp - Add variable used when filling SSH & OSH with non repeatable items (NRI) - Add check to stop warning about too many items and not enough locations for SSH & OSH NRI - Add check to stop placement from attempting to continue after all locations were filled in SSH & OSH NRI situation - Changes SSH & OSH NRI Fill from FastFill to AssumedFill to prevent softlocks and item placement issues --- source/fill.cpp | 179 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 126 insertions(+), 53 deletions(-) diff --git a/source/fill.cpp b/source/fill.cpp index 2d7c4f0..eebe27c 100644 --- a/source/fill.cpp +++ b/source/fill.cpp @@ -24,6 +24,7 @@ using namespace Logic; using namespace Settings; static bool placementFailure = false; +static bool NoRepeatOnTokens = false; static void RemoveStartingItemsFromPool() { for (ItemKey startingItem : StartingInventory) { @@ -377,23 +378,30 @@ static void FastFill(std::vector items, std::vector locati static void AssumedFill(const std::vector& items, const std::vector& allowedLocations, bool setLocationsAsHintable = false) { if (items.size() > allowedLocations.size()) { - printf("\x1b[2;2HERROR: MORE ITEMS THAN LOCATIONS IN GIVEN LISTS"); - PlacementLog_Msg("Items:\n"); - for (const ItemKey item : items) { - PlacementLog_Msg("\t"); - PlacementLog_Msg(ItemTable(item).GetName().GetEnglish()); - PlacementLog_Msg("\n"); + //If Tokensanity is on and RepeatableItemsOnTokens is off + //Don't display this message + if (NoRepeatOnTokens) { + //do nothing here to not display the message } - PlacementLog_Msg("\nAllowed Locations:\n"); - for (const LocationKey loc : allowedLocations) { - PlacementLog_Msg("\t"); - PlacementLog_Msg(Location(loc)->GetName()); - PlacementLog_Msg("\n"); + else { + printf("\x1b[2;2HERROR: MORE ITEMS THAN LOCATIONS IN GIVEN LISTS"); + PlacementLog_Msg("Items:\n"); + for (const ItemKey item : items) { + PlacementLog_Msg("\t"); + PlacementLog_Msg(ItemTable(item).GetName().GetEnglish()); + PlacementLog_Msg("\n"); + } + PlacementLog_Msg("\nAllowed Locations:\n"); + for (const LocationKey loc : allowedLocations) { + PlacementLog_Msg("\t"); + PlacementLog_Msg(Location(loc)->GetName()); + PlacementLog_Msg("\n"); + } + PlacementLog_Write(); + placementFailure = true; + return; } - PlacementLog_Write(); - placementFailure = true; - return; - } + } //If No Logic fast fill everything if (Settings::Logic.Is(LogicSetting::LOGIC_NONE)) { @@ -414,7 +422,7 @@ static void AssumedFill(const std::vector& items, const std::vector itemsToPlace = items; + std::vectoritemsToPlace = items; //copy all not yet placed advancement items so that we can apply their effects for the fill algorithm //std::vector itemsToNotPlace = FilterFromPool(ItemPool, [](const ItemKey i) { @@ -427,9 +435,9 @@ static void AssumedFill(const std::vector& items, const std::vector& items, const std::vector& items, const std::vectorIsRepeatable()) && ItemTable(item).IsReusable() ){ - //unsuccessfulPlacement = true; - CitraPrint("Attemting to place repeatable item in non repeatable spot in AssumedFill"); - PlacementLog_Msg("\n Attempted to place " + ItemTable(item).GetName().GetEnglish() + " at " + Location(selectedLocation)->GetName()); + + //If Tokensanity is on and RepeatableItemsOnTokens is off + //Only place non repeatable items + if (NoRepeatOnTokens){ + //If the item is repeatable put it back and try again + if (ItemTable(item).IsReusable() ) { + CitraPrint("Attempting to place Repeatable Item in SSH/OSH Location"); + PlacementLog_Msg("\n Attempted to place Repeatable Item in SSH/OSH Loaction"); itemsToPlace.push_back(item); } - else { - PlaceItemInLocation(selectedLocation, item); - //PlacementLog_Msg("Placed " + ItemTable(item).GetName().GetEnglish() + " at " + Location(selectedLocation)->GetName()); - //CitraPrint("Placed " + ItemTable(item).GetName().GetEnglish() + " at " + Location(selectedLocation)->GetName()); - attemptedLocations.push_back(selectedLocation); - - //This tells us the location went through the randomization algorithm - //to distinguish it from locations which did not or that the player already - //knows - if (setLocationsAsHintable) { - Location(selectedLocation)->SetAsHintable(); + else { + //Else place it and keep going + PlaceItemInLocation(selectedLocation, item); + attemptedLocations.push_back(selectedLocation); + //This tells us the location went through the randomization algorithm + //to distinguish it from locations which did not or that the player already + //knows + if (setLocationsAsHintable) { + Location(selectedLocation)->SetAsHintable(); + } + + //If ALR is off, then we check beatability after placing the item. + //If the game is beatable, then we can stop placing items with logic. + if (!LocationsReachable) { + playthroughBeatable = false; + Logic::LogicReset(); + GetAccessibleLocations(allLocations, SearchMode::CheckBeatable); + if (playthroughBeatable) { + FastFill(itemsToPlace, GetAllEmptyLocations(), true); + return; + } + } } - - //If ALR is off, then we check beatability after placing the item. - //If the game is beatable, then we can stop placing items with logic. - if (!LocationsReachable) { - playthroughBeatable = false; - Logic::LogicReset(); - GetAccessibleLocations(allLocations, SearchMode::CheckBeatable); - if (playthroughBeatable) { - FastFill(itemsToPlace, GetAllEmptyLocations(), true); - return; + } + else { + //place the item within one of the allowed locations accounting for if this item needs to be able to be obtained more than once and if location allows that + //the only situation we don't want is a non repeatable location with a reusable item + if ( !(Location(selectedLocation)->IsRepeatable()) && ItemTable(item).IsReusable() ){ + //unsuccessfulPlacement = true; + CitraPrint("Attemting to place repeatable item in non repeatable spot in AssumedFill"); + PlacementLog_Msg("\n Attempted to place " + ItemTable(item).GetName().GetEnglish() + " at " + Location(selectedLocation)->GetName()); + itemsToPlace.push_back(item); + } + else { + PlaceItemInLocation(selectedLocation, item); + //PlacementLog_Msg("Placed " + ItemTable(item).GetName().GetEnglish() + " at " + Location(selectedLocation)->GetName()); + //CitraPrint("Placed " + ItemTable(item).GetName().GetEnglish() + " at " + Location(selectedLocation)->GetName()); + attemptedLocations.push_back(selectedLocation); + + //This tells us the location went through the randomization algorithm + //to distinguish it from locations which did not or that the player already + //knows + if (setLocationsAsHintable) { + Location(selectedLocation)->SetAsHintable(); + } + + //If ALR is off, then we check beatability after placing the item. + //If the game is beatable, then we can stop placing items with logic. + if (!LocationsReachable) { + playthroughBeatable = false; + Logic::LogicReset(); + GetAccessibleLocations(allLocations, SearchMode::CheckBeatable); + if (playthroughBeatable) { + FastFill(itemsToPlace, GetAllEmptyLocations(), true); + return; + } } } } @@ -817,20 +872,38 @@ int Fill() { } //Then if repeatable items on tokens is off -- fill token spots with nonrepeatable items if (Tokensanity && !RepeatableItemsOnTokens){ - //Get all nonrepeatable items - std::vector remainingNonRepeatItemPool = FilterAndEraseFromPool(ItemPool, [](const ItemKey i) {return ItemTable(i).IsReusable() == false;}); + //Set Variable to not mess with fill algorithm + NoRepeatOnTokens = true; + //Get SSH locations std::vector SwampSkullLocations = FilterFromPool(allLocations, [](const LocationKey loc) {return Location(loc)->IsCategory(Category::cSwampSkulltula);}); - //CitraPrint("Starting Assumed Fill on Swamp Locations"); - //fill skulltula spots with them - FastFill(remainingNonRepeatItemPool, SwampSkullLocations); + //Get NonRepeatItems + std::vector NonRepeatItems = FilterAndEraseFromPool(ItemPool, [](const ItemKey i) {return !ItemTable(i).IsReusable();}); + //fill SSH spots with nonrepeatableitems + //CitraPrint("Items in NonRepeatItems:\n"); + //PlacementLog_Msg("Items in NonRepeatItems:\n"); + //for (ItemKey item : NonRepeatItems) { + // CitraPrint(ItemTable(item).GetName().GetEnglish() + "\n"); + // PlacementLog_Msg(ItemTable(item).GetName().GetEnglish() + "\n"); + // } + AssumedFill(NonRepeatItems, SwampSkullLocations, true); + //Get OSH locations std::vector OceanSkullLocations = FilterFromPool(allLocations, [](const LocationKey loc1) {return Location(loc1)->IsCategory(Category::cOceanSkulltula);}); - //CitraPrint("Starting Assumed Fill on Ocean Locations"); - FastFill(remainingNonRepeatItemPool, OceanSkullLocations); + //Get NonRepeatItems + std::vector NonRepeatItems2 = FilterAndEraseFromPool(ItemPool, [](const ItemKey i) {return !ItemTable(i).IsReusable();}); + //CitraPrint("Items in NonRepeatItems2:\n"); + //PlacementLog_Msg("Items in NonRepeatItems2:\n"); + //for (ItemKey item : NonRepeatItems2) { + // CitraPrint(ItemTable(item).GetName().GetEnglish() + "\n"); + // PlacementLog_Msg(ItemTable(item).GetName().GetEnglish() + "\n"); + // } + //fill OSH spots with NonRepeatableItems + AssumedFill(NonRepeatItems2, OceanSkullLocations, true); + //Set Variable back to false to go back to normal filling + NoRepeatOnTokens = false; - //CitraPrint("Adding RemainingNonRepeatItems back to main ItemPool"); - AddElementsToPool(ItemPool, remainingNonRepeatItemPool); //Then Place Anju & Kafei Items in spots accessable on Day 1, this should prevent situations where you cant get an item in time for its use + //Do this before continuing as the pool of accessable locations is smaller after filling all skulltula locations std::vector day1Locations = FilterFromPool(allLocations, [](const LocationKey loc) {return Location(loc)->IsCategory(Category::cDayOne);}); std::vector anjukafeiitems = FilterAndEraseFromPool(ItemPool, [](const ItemKey i) {return ItemTable(i).GetItemType() == ITEMTYPE_QUEST;}); AssumedFill(anjukafeiitems, day1Locations,true); From c3a346504a7671f760f2bd2b67e9fb615364f0b8 Mon Sep 17 00:00:00 2001 From: Tacoman369 <90735287+Tacoman369@users.noreply.github.com> Date: Sat, 31 May 2025 14:46:53 -0500 Subject: [PATCH 2/4] Update fill.cpp fixed spaces to appease phlex --- source/fill.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/fill.cpp b/source/fill.cpp index eebe27c..82326d8 100644 --- a/source/fill.cpp +++ b/source/fill.cpp @@ -422,7 +422,7 @@ static void AssumedFill(const std::vector& items, const std::vectoritemsToPlace = items; + std::vector itemsToPlace = items; //copy all not yet placed advancement items so that we can apply their effects for the fill algorithm //std::vector itemsToNotPlace = FilterFromPool(ItemPool, [](const ItemKey i) { @@ -515,7 +515,7 @@ static void AssumedFill(const std::vector& items, const std::vector Date: Sat, 31 May 2025 16:50:53 -0500 Subject: [PATCH 3/4] Update fill.cpp Adjust all AssumedFIll calls to have locationshintable be true --- source/fill.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/fill.cpp b/source/fill.cpp index 82326d8..6090e8e 100644 --- a/source/fill.cpp +++ b/source/fill.cpp @@ -602,7 +602,7 @@ std::vector rewards = FilterAndEraseFromPool(ItemPool, [](const ItemKey } } else if (ShuffleRewards.Is((u8)RewardShuffleSetting::REWARDSHUFFLE_ANYWHERE)){ - AssumedFill(rewards, allLocations); + AssumedFill(rewards, allLocations, true); } } @@ -656,12 +656,12 @@ static void RandomizeOwnDungeon(const Dungeon::DungeonInfo* dungeon) { } //randomize boss key and small keys together for even distribution - AssumedFill(dungeonItems, dungeonLocations); + AssumedFill(dungeonItems, dungeonLocations, true); //randomize map and compass separately since they're not progressive if (MapsAndCompasses.Is((u8)MapsAndCompassesSetting::MAPSANDCOMPASSES_OWN_DUNGEON) && dungeon->GetMap() != NONE && dungeon->GetCompass() != NONE) { auto dungeonMapAndCompass = FilterAndEraseFromPool(ItemPool, [dungeon](const ItemKey i) { return i == dungeon->GetMap() || i == dungeon->GetCompass();}); - AssumedFill(dungeonMapAndCompass, dungeonLocations); + AssumedFill(dungeonMapAndCompass, dungeonLocations, true); } } From 22866e1f08065ef479c7ee52fd6ff1a2e832db8f Mon Sep 17 00:00:00 2001 From: Tacoman369 <90735287+Tacoman369@users.noreply.github.com> Date: Sat, 31 May 2025 16:54:08 -0500 Subject: [PATCH 4/4] Update Z3DR --- Z3DR | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Z3DR b/Z3DR index 98a8c38..bfdb49e 160000 --- a/Z3DR +++ b/Z3DR @@ -1 +1 @@ -Subproject commit 98a8c38d17d2b7de7c1a3a0c8d9643a2ac2b9d93 +Subproject commit bfdb49ea79bcc139bf7622b68b1c3c4ec23d908b