more clean up

This commit is contained in:
gymnast86
2026-04-11 23:01:46 -07:00
parent 98b492bd89
commit 4e25db0f20
27 changed files with 167 additions and 207 deletions
+3 -7
View File
@@ -5,7 +5,6 @@
#include "../randomizer.hpp"
#include <algorithm>
#include <iostream>
#include <unordered_set>
namespace randomizer::logic::area
@@ -128,8 +127,7 @@ namespace randomizer::logic::area
void Area::RemoveExit(entrance::Entrance* exit)
{
auto removed = std::remove_if(this->_exits.begin(), this->_exits.end(), [&](const auto& e) { return e.get() == exit; });
this->_exits.erase(removed, this->_exits.end());
std::erase_if(this->_exits, [&](const auto& e) { return e.get() == exit; });
}
void Area::AddEntrance(entrance::Entrance* entrance)
@@ -139,8 +137,7 @@ namespace randomizer::logic::area
void Area::RemoveEntrance(entrance::Entrance* entrance)
{
auto removed = std::remove(this->_entrances.begin(), this->_entrances.end(), entrance);
this->_entrances.erase(removed, this->_entrances.end());
std::erase(this->_entrances, entrance);
}
std::list<entrance::Entrance*> Area::GetEntrances() const
@@ -234,8 +231,7 @@ namespace randomizer::logic::area
// hint regions, filter out the dungeon ones.
const auto& dungeons = this->GetWorld()->GetDungeonTable();
std::set<std::string> dungeonRegions = {};
std::copy_if(hintRegions.begin(),
hintRegions.end(),
std::ranges::copy_if(hintRegions,
std::inserter(dungeonRegions, dungeonRegions.begin()),
[&](const auto& hintRegion) { return dungeons.contains(hintRegion); });
// If we have less dungeons than total hint regions, we have at least one overworld hint region
+1
View File
@@ -3,6 +3,7 @@
#include "entrance.hpp"
#include "requirement.hpp"
#include <memory>
#include <set>
#include <list>
+13 -21
View File
@@ -108,8 +108,7 @@ namespace randomizer::logic::entrance_shuffle
doors.pop_back();
auto coupledDoorItr =
std::find_if(doors.begin(),
doors.end(),
std::ranges::find_if(doors,
[&](const auto& door) { return door->IsPrimary() == mainDoor->IsPrimary(); });
auto coupledDoor = *coupledDoorItr;
@@ -145,13 +144,9 @@ namespace randomizer::logic::entrance_shuffle
// Remove Hyrule Castle if it's not being shuffled
if (world->Setting("Randomize Dungeon Entrances") != "On + Hyrule Castle")
{
auto& dungeonPool = entrancePools[Type::DUNGEON];
auto removed = std::remove_if(
dungeonPool.begin(),
dungeonPool.end(),
[](const auto& entrance)
{ return entrance->GetOriginalName() == "Castle Town North Inside Barrier -> Hyrule Castle Entrance"; });
dungeonPool.erase(removed, dungeonPool.end());
std::erase_if(entrancePools[Type::DUNGEON], [](const auto& entrance) {
return entrance->GetOriginalName() == "Castle Town North Inside Barrier -> Hyrule Castle Entrance";
});
}
if (world->Setting("Decouple Entrances") == "On")
@@ -215,11 +210,9 @@ namespace randomizer::logic::entrance_shuffle
const auto& mixedPools = world->GetSettings().GetMixedEntrancePools();
bool excludeOverworldReverse =
world->Setting("Decouple Entrances") == "Off" &&
std::any_of(
mixedPools.begin(),
mixedPools.end(),
[](const auto& pool)
{ return randomizer::utility::container::ElementInContainer(pool, "Overworld"); }); /*Overworld in a mixed pool*/
std::ranges::any_of(mixedPools, [](const auto& pool) {
return randomizer::utility::container::ElementInContainer(pool, "Overworld");
}); /*Overworld in a mixed pool*/
entrancePools[Type::OVERWORLD] =
world->GetShuffleableEntrances(Type::OVERWORLD, /*onlyPrimary = */ excludeOverworldReverse);
}
@@ -311,10 +304,9 @@ namespace randomizer::logic::entrance_shuffle
EntrancePool spawnPool = {};
auto world = entrancePool[0]->GetWorld();
// Get all the entrances of these types to use as spawn targets
for (const auto& type : {Type::SPAWN, Type::INTERIOR, Type::CAVE, Type::OVERWORLD, Type::GROTTO})
for (const auto& typeForSpawn : {Type::SPAWN, Type::INTERIOR, Type::CAVE, Type::OVERWORLD, Type::GROTTO})
{
auto entrances = world->GetShuffleableEntrances(type);
for (const auto& entrance : entrances)
for (const auto& entrance : world->GetShuffleableEntrances(typeForSpawn))
{
auto newTarget = entrance->GetNewTarget();
spawnPool.push_back(newTarget);
@@ -669,7 +661,7 @@ namespace randomizer::logic::entrance_shuffle
return false;
}
void CheckEntrancesCompatibility(Entrance* entrance, Entrance* target)
void CheckEntrancesCompatibility(const Entrance* entrance, const Entrance* target)
{
if (entrance->GetReverse() && entrance->GetReverse() == target->GetReplaces())
{
@@ -743,9 +735,9 @@ namespace randomizer::logic::entrance_shuffle
auto sphereZeroSearch = search::Search::SphereZero(&worlds);
sphereZeroSearch.SearchWorlds();
const auto& foundLocations = sphereZeroSearch._visitedLocations;
auto numSphereZeroLocations = std::count_if(foundLocations.begin(),
foundLocations.end(),
[](const auto& location) { return location->IsProgression(); });
const auto numSphereZeroLocations = std::ranges::count_if(foundLocations, [](const auto& location) {
return location->IsProgression();
});
// If there are no sphere zero locations available and we didn't find an accessible disconnected exit, then this world will not
// be valid. Often times when many entrances are randomized we won't find any locations, but will find accessible disconnected
@@ -33,7 +33,8 @@ namespace randomizer::logic::entrance_shuffle
std::unordered_map<entrance::Entrance*, entrance::Entrance*>& rollbacks,
const item_pool::ItemPool& completeItemPool);
void CheckEntrancesCompatibility(entrance::Entrance* entrance, entrance::Entrance* target);
void CheckEntrancesCompatibility(const entrance::Entrance* entrance,
const entrance::Entrance* target);
void ChangeConnections(entrance::Entrance* entrance, entrance::Entrance* target);
void RestoreConnections(entrance::Entrance* entrance, entrance::Entrance* target);
void ConfirmReplacement(entrance::Entrance* entrance, entrance::Entrance* target);
+38 -43
View File
@@ -37,15 +37,15 @@ namespace randomizer::logic::fill
// Place remaining major items in progress locations
auto majorItems =
randomizer::utility::container::FilterAndEraseFromVector(itemPool, [](const auto& item) { return item->IsMajor(); });
utility::container::FilterAndEraseFromVector(itemPool, [](const auto& item) { return item->IsMajor(); });
auto progressLocations =
randomizer::utility::container::FilterFromVector(locationPool,
utility::container::FilterFromVector(locationPool,
[](const auto& location) { return location->IsProgression(); });
AssumedFill(worlds, majorItems, itemPool, progressLocations);
// Place Minor items in progression locations if possible
auto minorItems =
randomizer::utility::container::FilterAndEraseFromVector(itemPool, [](const auto& item) { return item->IsMinor(); });
utility::container::FilterAndEraseFromVector(itemPool, [](const auto& item) { return item->IsMinor(); });
FastFill(minorItems, progressLocations);
// If there are still minor items left, add them back to the main item pool
@@ -80,11 +80,11 @@ namespace randomizer::logic::fill
if (retries <= 0)
{
std::string errorMsg = "Ran out of retries while attempting to place the following items:\n";
int count = itemsToPlacePool.size() > 5 ? 5 : itemsToPlacePool.size();
const auto count = itemsToPlacePool.size() > 5 ? 5 : itemsToPlacePool.size();
for (int i = 0; i < count; i++)
{
auto& item = itemsToPlacePool[i];
const auto& item = itemsToPlacePool[i];
errorMsg += "- " + item->GetName() + "\n";
}
@@ -99,7 +99,7 @@ namespace randomizer::logic::fill
retries -= 1;
unsuccessfulPlacement = false;
randomizer::utility::random::ShufflePool(itemsToPlacePool);
utility::random::ShufflePool(itemsToPlacePool);
auto itemsToPlace = itemsToPlacePool;
location::LocationPool rollbacks = {};
@@ -109,7 +109,7 @@ namespace randomizer::logic::fill
auto itemToPlace = itemsToPlace.back();
itemsToPlace.pop_back();
randomizer::utility::random::ShufflePool(allowedLocations);
utility::random::ShufflePool(allowedLocations);
location::Location* spotToFill = nullptr;
// Assume we have all the items which haven't been played yet, except the one we're about to place
@@ -147,14 +147,10 @@ namespace randomizer::logic::fill
}
// If any of the LocationAccess spots evaluate to complete, then we can place an item here
if (std::any_of(locAccList.begin(),
locAccList.end(),
[&](const auto& la)
{
return canChooseAnyLocation ||
requirement::EvaluateLocationRequirement(&search, la) ==
requirement::EvalSuccess::COMPLETE;
}))
if (std::ranges::any_of(locAccList, [&](const auto& la) {
return canChooseAnyLocation ||
requirement::EvaluateLocationRequirement(&search, la) == requirement::EvalSuccess::COMPLETE;
}))
{
spotToFill = location;
break;
@@ -191,7 +187,7 @@ namespace randomizer::logic::fill
void FastFill(item_pool::ItemPool& itemsToPlace, location::LocationPool allowedLocations)
{
auto emptyLocations =
randomizer::utility::container::FilterFromVector(allowedLocations,
utility::container::FilterFromVector(allowedLocations,
[](const auto& location) { return location->IsEmpty(); });
if (itemsToPlace.size() > emptyLocations.size())
@@ -200,14 +196,14 @@ namespace randomizer::logic::fill
<< " Locations: " << emptyLocations.size() << std::endl;
}
randomizer::utility::random::ShufflePool(emptyLocations);
utility::random::ShufflePool(emptyLocations);
for (auto& location : emptyLocations)
{
if (itemsToPlace.empty())
{
break;
}
location->SetCurrentItem(randomizer::utility::random::PopRandomElement(itemsToPlace));
location->SetCurrentItem(utility::random::PopRandomElement(itemsToPlace));
}
}
@@ -233,7 +229,7 @@ namespace randomizer::logic::fill
// pool of locations and have to be found in the intro. We also include the lantern, shadow crystal, and progressive
// fishing rod because those items can lock prologue locations also.
auto& itemPool = world->GetItemPool();
auto prologueItems = randomizer::utility::container::FilterAndEraseFromVector(
auto prologueItems = utility::container::FilterAndEraseFromVector(
itemPool,
[](const auto& item)
{
@@ -258,14 +254,14 @@ namespace randomizer::logic::fill
location::LocationPool goalLocations = {};
// Filter out goal locations
goalLocations = randomizer::utility::container::FilterFromVector(
goalLocations = utility::container::FilterFromVector(
allLocations,
[](const auto& location) { return location->IsGoalLocation() && location->IsEmpty(); });
// Filter out goal items
std::set<std::string> goalItemNames = {"Progressive Mirror Shard", "Progressive Fused Shadow"};
auto goalItems = randomizer::utility::container::FilterAndEraseFromVector(
auto goalItems = utility::container::FilterAndEraseFromVector(
world->GetItemPool(),
[&](const auto& item) { return goalItemNames.contains(item->GetName()); });
@@ -286,7 +282,7 @@ namespace randomizer::logic::fill
{
// Filter hint signs out of dungeon locations
auto dungeonLocations = dungeon->GetLocations();
randomizer::utility::container::FilterAndEraseFromVector(dungeonLocations,
utility::container::FilterAndEraseFromVector(dungeonLocations,
[](const auto& location)
{ return location->HasCategories("Hint Sign"); });
@@ -298,7 +294,7 @@ namespace randomizer::logic::fill
// Small Keys
if (world->Setting("Small Keys") == "Own Dungeon")
{
auto smallKeys = randomizer::utility::container::FilterAndEraseFromVector(
auto smallKeys = utility::container::FilterAndEraseFromVector(
world->GetItemPool(),
[&](const auto& item)
{
@@ -313,7 +309,7 @@ namespace randomizer::logic::fill
// Big Keys
if (world->Setting("Big Keys") == "Own Dungeon")
{
auto bigKeys = randomizer::utility::container::FilterAndEraseFromVector(world->GetItemPool(),
auto bigKeys = utility::container::FilterAndEraseFromVector(world->GetItemPool(),
[&](const auto& item)
{ return item == dungeon_->GetBigKey(); });
auto completeItemPool = item_pool::GetCompleteItemPool(worlds);
@@ -323,7 +319,7 @@ namespace randomizer::logic::fill
// Place maps and compasses last with fast fill since they're junk items
if (world->Setting("Maps and Compasses") == "Own Dungeon")
{
auto mapsCompasses = randomizer::utility::container::FilterAndEraseFromVector(
auto mapsCompasses = utility::container::FilterAndEraseFromVector(
world->GetItemPool(),
[&](const auto& item) { return item == dungeon_->GetCompass() || item == dungeon_->GetDungeonMap(); });
auto completeItemPool = item_pool::GetCompleteItemPool(worlds);
@@ -345,7 +341,7 @@ namespace randomizer::logic::fill
// Filter out goal items
std::set<std::string> goalItemNames = {"Progressive Mirror Shard", "Progressive Fused Shadow"};
auto goalItems = randomizer::utility::container::FilterAndEraseFromVector(
auto goalItems = utility::container::FilterAndEraseFromVector(
world->GetItemPool(),
[&](const auto& item) { return goalItemNames.contains(item->GetName()); });
@@ -390,7 +386,7 @@ namespace randomizer::logic::fill
// Add small keys to the pool if small keys are any dungeon
if (world->Setting("Small Keys") == "Any Dungeon")
{
auto smallKeys = randomizer::utility::container::FilterAndEraseFromVector(
auto smallKeys = utility::container::FilterAndEraseFromVector(
world->GetItemPool(),
[&](const auto& item)
{
@@ -398,32 +394,31 @@ namespace randomizer::logic::fill
(dungeon_->GetName() == "Snowpeak Ruins" &&
(item->GetName() == "Ordon Pumpkin" || item->GetName() == "Ordon Cheese"));
});
std::copy(smallKeys.begin(), smallKeys.end(), std::back_inserter(anyDungeonItems));
std::ranges::copy(smallKeys, std::back_inserter(anyDungeonItems));
}
// Add big keys to the pool if big keys are any dungeon
if (world->Setting("Big Keys") == "Any Dungeon")
{
auto bigKeys = randomizer::utility::container::FilterAndEraseFromVector(
auto bigKeys = utility::container::FilterAndEraseFromVector(
world->GetItemPool(),
[&](const auto& item) { return item == dungeon_->GetBigKey(); });
std::copy(bigKeys.begin(), bigKeys.end(), std::back_inserter(anyDungeonItems));
std::ranges::copy(bigKeys, std::back_inserter(anyDungeonItems));
}
// Add maps and compasses to the pool if maps and compasses are any dungeon
if (world->Setting("Maps and Compasses") == "Any Dungeon")
{
auto mapsCompasses = randomizer::utility::container::FilterAndEraseFromVector(
auto mapsCompasses = utility::container::FilterAndEraseFromVector(
world->GetItemPool(),
[&](const auto& item) { return item == dungeon_->GetCompass() || item == dungeon_->GetDungeonMap(); });
std::copy(mapsCompasses.begin(), mapsCompasses.end(), std::back_inserter(anyDungeonItems));
std::ranges::copy(mapsCompasses, std::back_inserter(anyDungeonItems));
}
// Add this dungeon's locations to the anyDungeonLocations pool. If this is a nonbarren dungeon, only include
// locations which are still progression. If it's a barren dungeon, include all the locations
auto dungeonLocations = dungeon->GetLocations();
std::copy_if(dungeonLocations.begin(),
dungeonLocations.end(),
std::ranges::copy_if(dungeonLocations,
std::back_inserter(anyDungeonLocations),
[&](const auto& location) { return dungeon->ShouldBeBarren() || location->IsProgression(); });
}
@@ -439,7 +434,7 @@ namespace randomizer::logic::fill
item_pool::ItemPool overworldItems = {};
location::LocationPool overworldLocations = world->GetAllLocations();
// Filter out any nonprogress locations
randomizer::utility::container::FilterAndEraseFromVector(overworldLocations,
utility::container::FilterAndEraseFromVector(overworldLocations,
[](const auto& location) { return !location->IsProgression(); });
for (const auto& [dungeonName, dungeon] : world->GetDungeonTable())
@@ -452,7 +447,7 @@ namespace randomizer::logic::fill
// Add small keys to the pool if small keys are overworld
if (world->Setting("Small Keys") == "Overworld")
{
auto smallKeys = randomizer::utility::container::FilterAndEraseFromVector(
auto smallKeys = utility::container::FilterAndEraseFromVector(
world->GetItemPool(),
[&](const auto& item)
{
@@ -460,32 +455,32 @@ namespace randomizer::logic::fill
(dungeonName_ == "Snowpeak Ruins" &&
(item->GetName() == "Ordon Pumpkin" || item->GetName() == "Ordon Cheese"));
});
std::copy(smallKeys.begin(), smallKeys.end(), std::back_inserter(overworldItems));
std::ranges::copy(smallKeys, std::back_inserter(overworldItems));
}
// Add big keys to the pool if big keys are overworld
if (world->Setting("Big Keys") == "Overworld")
{
auto bigKeys = randomizer::utility::container::FilterAndEraseFromVector(world->GetItemPool(),
auto bigKeys = utility::container::FilterAndEraseFromVector(world->GetItemPool(),
[&](const auto& item)
{ return item == dungeon_->GetBigKey(); });
std::copy(bigKeys.begin(), bigKeys.end(), std::back_inserter(overworldItems));
std::ranges::copy(bigKeys, std::back_inserter(overworldItems));
}
// Add maps and compasses to the pool if maps and compasses are overworld
if (world->Setting("Maps and Compasses") == "Overworld")
{
auto mapsCompasses = randomizer::utility::container::FilterAndEraseFromVector(
auto mapsCompasses = utility::container::FilterAndEraseFromVector(
world->GetItemPool(),
[&](const auto& item) { return item == dungeon_->GetCompass() || item == dungeon_->GetDungeonMap(); });
std::copy(mapsCompasses.begin(), mapsCompasses.end(), std::back_inserter(overworldItems));
std::ranges::copy(mapsCompasses, std::back_inserter(overworldItems));
}
// Remove this dungeon's locations from the overworldLocations pool
overworldLocations = randomizer::utility::container::FilterFromVector(
overworldLocations = utility::container::FilterFromVector(
overworldLocations,
[&](const auto& location)
{ return !randomizer::utility::container::ElementInContainer(dungeon_->GetLocations(), location); });
{ return !utility::container::ElementInContainer(dungeon_->GetLocations(), location); });
}
// Place the dungeon items in the overworld locations
+3 -2
View File
@@ -18,9 +18,10 @@ namespace randomizer::logic::fill
*
* @param worlds The worlds to fill with items
* @param itemsToPlacePool The pool of items which we want to place
* @param itemsNotYetPlaced The pool of items which aren't placed yet, but will be later. This is important for the assumed
* fill algorithm since we need to assume we have these items.
* @param itemsNotYetPlaced The pool of items which aren't placed yet, but will be later.
* This is important for the assumed fill algorithm since we need to assume we have these items.
* @param allowedLocations Locations where items in itemsToPlacePool are allowed to be filled.
* @param worldToFill A specific world to fill. If -1 (default), then all worlds are considered
*/
void AssumedFill(world::WorldPool& worlds,
item_pool::ItemPool& itemsToPlacePool,
+1 -1
View File
@@ -5,7 +5,7 @@
#include <iterator>
BitVector::BitVector(std::list<int> bits)
BitVector::BitVector(const std::list<int>& bits)
{
for (auto& i : bits)
{
+1 -1
View File
@@ -12,7 +12,7 @@ class BitVector
{
public:
BitVector() = default;
BitVector(std::list<int>);
explicit BitVector(const std::list<int>& bits);
bool isEmpty() const;
std::set<int> ints() const;
+10 -7
View File
@@ -1,30 +1,33 @@
#include "flatten.hpp"
#include <ranges>
#include "../world.hpp"
FlattenSearch::FlattenSearch(randomizer::logic::world::World* world_)
{
world = world_;
for (auto& [name, area] : world->GetAreaTable())
for (const auto& area : world->GetAreaTable() | std::views::values)
{
for (auto& exit : area->GetExits())
for (const auto& exit : area->GetExits())
{
auto visit = visitor(exit, this);
visitReq(exit->GetRequirement(), visit, world);
}
for (auto& event : area->GetEvents())
for (const auto& event : area->GetEvents())
{
auto visit = visitor(event, this);
visitReq(event->GetRequirement(), visit, world);
}
}
auto root = world->GetRootArea();
const auto root = world->GetRootArea();
// Start with all formtimes at the root, false for everything else
auto formTimes = randomizer::logic::requirement::FormTime::ALL_FORM_AND_DAY_TIMES;
formTimes.push_back(randomizer::logic::requirement::FormTime::TWILIGHT);
for (const auto& [areaName, area] : world->GetAreaTable())
for (const auto& area : world->GetAreaTable() | std::views::values)
{
for (const auto& formTime : formTimes)
{
@@ -73,7 +76,7 @@ void FlattenSearch::doSearch()
}
std::unordered_map<std::string, std::list<randomizer::logic::area::LocationAccess*>> itemLocations = {};
for (auto& [name, area] : world->GetAreaTable())
for (const auto& area : world->GetAreaTable() | std::views::values)
{
for (auto& locAccess : area->GetLocations())
{
@@ -97,7 +100,7 @@ void FlattenSearch::doSearch()
for (auto& [locName, accessList] : itemLocations)
{
auto expr = DNF::False();
for (auto& locAcc : accessList)
for (const auto& locAcc : accessList)
{
for (const auto& formTime : formTimes)
{
+5 -3
View File
@@ -7,9 +7,11 @@ namespace randomizer::logic::item
Importance ImportanceFromStr(const std::string& str)
{
std::unordered_map<std::string, Importance> importances = {{"Major", Importance::MAJOR},
{"Minor", Importance::MINOR},
{"Junk", Importance::JUNK}};
const std::unordered_map<std::string, Importance> importances = {
{"Major", Importance::MAJOR},
{"Minor", Importance::MINOR},
{"Junk", Importance::JUNK}
};
if (!importances.contains(str))
{
+2 -2
View File
@@ -369,13 +369,13 @@ namespace randomizer::logic::item_pool
return initialJunkPool;
}
ItemPool GetCompleteItemPool(world::WorldPool& worlds)
ItemPool GetCompleteItemPool(const world::WorldPool& worlds)
{
ItemPool completeItemPool = {};
for (const auto& world : worlds)
{
auto& worldItemPool = world->GetItemPool();
std::copy(worldItemPool.begin(), worldItemPool.end(), std::back_inserter(completeItemPool));
std::ranges::copy(worldItemPool, std::back_inserter(completeItemPool));
}
return completeItemPool;
+1 -1
View File
@@ -38,5 +38,5 @@ namespace randomizer::logic::item_pool
std::map<std::string, int> GetInitialJunkPool();
ItemPool GetCompleteItemPool(world::WorldPool& worlds);
ItemPool GetCompleteItemPool(const world::WorldPool& worlds);
} // namespace randomizer::logic::item_pool
+1 -1
View File
@@ -7,7 +7,7 @@ namespace randomizer::logic::location
{
Location::Location(const int& id,
const std::string& name,
std::unordered_set<std::string> categories,
const std::unordered_set<std::string>& categories,
world::World* world,
item::Item* originalItem,
const bool& goalLocation,
+1 -1
View File
@@ -24,7 +24,7 @@ namespace randomizer::logic::location
public:
Location(const int& id,
const std::string& name,
std::unordered_set<std::string> categories,
const std::unordered_set<std::string>& categories,
world::World* world,
item::Item* originalItem,
const bool& goalLocation,
+19 -32
View File
@@ -3,13 +3,11 @@
#include "search.hpp"
#include "world.hpp"
#include "../utility/container.hpp"
#include "../utility/general.hpp"
#include "../utility/log.hpp"
#include "../utility/string.hpp"
#include <algorithm>
#include <ranges>
#include <iostream>
namespace randomizer::logic::requirement
{
@@ -467,14 +465,14 @@ namespace randomizer::logic::requirement
// For each deeper expression, parse it and add it as an argument to the
// Requirement
for (auto& reqStr : splitLogicStr)
for (auto& newReqStr : splitLogicStr)
{
// Get rid of parenthesis surrounding each deeper expression
if (reqStr[0] == '(')
if (newReqStr[0] == '(')
{
reqStr = reqStr.substr(1, reqStr.length() - 2);
newReqStr = newReqStr.substr(1, newReqStr.length() - 2);
}
req._args.push_back(ParseRequirementString(reqStr, world, forceLogic));
req._args.push_back(ParseRequirementString(newReqStr, world, forceLogic));
}
}
@@ -484,7 +482,6 @@ namespace randomizer::logic::requirement
}
// If we've reached req point, we weren't able to determine a logical operator within the expression
throw std::runtime_error("Could not determine logical operator type from expression: \"" + reqStr + "\"");
return req;
}
bool EvaluateSimpleRequirement(const Requirement& req, world::World* world)
@@ -503,16 +500,14 @@ namespace randomizer::logic::requirement
return false;
case Type::OR:
return std::any_of(
req._args.begin(),
req._args.end(),
return std::ranges::any_of(
req._args,
[&](const auto& arg)
{ return EvaluateSimpleRequirement(std::get<Requirement>(arg), world); });
case Type::AND:
return std::all_of(
req._args.begin(),
req._args.end(),
return std::ranges::all_of(
req._args,
[&](const auto& arg)
{ return EvaluateSimpleRequirement(std::get<Requirement>(arg), world); });
@@ -543,7 +538,6 @@ namespace randomizer::logic::requirement
default:
return false;
}
return false;
}
bool EvaluateRequirementAtFormTime(const Requirement& req,
@@ -566,16 +560,14 @@ namespace randomizer::logic::requirement
return false;
case Type::OR:
return std::any_of(
req._args.begin(),
req._args.end(),
return std::ranges::any_of(
req._args,
[&](const auto& arg)
{ return EvaluateRequirementAtFormTime(std::get<Requirement>(arg), search, formTime, world); });
case Type::AND:
return std::all_of(
req._args.begin(),
req._args.end(),
return std::ranges::all_of(
req._args,
[&](const auto& arg)
{ return EvaluateRequirementAtFormTime(std::get<Requirement>(arg), search, formTime, world); });
@@ -613,9 +605,8 @@ namespace randomizer::logic::requirement
case Type::GOLDEN_BUGS:
count = std::get<int>(req._args[0]);
return std::count_if(search->_ownedItems.begin(),
search->_ownedItems.end(),
[](const auto& item) { return item->IsGoldenBug(); }) >= count;
return std::ranges::count_if(search->_ownedItems,
[](const auto& ownedItem) { return ownedItem->IsGoldenBug(); }) >= count;
case Type::HEARTS:
count = std::get<int>(req._args[0]);
@@ -626,8 +617,8 @@ namespace randomizer::logic::requirement
case Type::DUNGEONS_COMPLETED:
count = std::get<int>(req._args[0]);
return std::ranges::count_if(search->_ownedEvents, [&](int eventId){
std::list<std::string> dungeonCompletionEvents = {
return std::ranges::count_if(search->_ownedEvents, [&](const int eventId) {
const std::list<std::string> dungeonCompletionEvents = {
"Can Complete Forest Temple",
"Can Complete Goron Mines",
"Can Complete Lakebed Temple",
@@ -763,15 +754,12 @@ namespace randomizer::logic::requirement
return EvalSuccess::NONE;
}
auto& exitFormTimeCache = exit->GetWorld()->GetExitTimeFormCache();
auto parentArea = exit->GetParentArea();
auto parentAreaFormTime = search->_areaFormTime[parentArea];
const auto parentArea = exit->GetParentArea();
const auto parentAreaFormTime = search->_areaFormTime[parentArea];
// Check each form time individually and spread the ones which succeed. If any of them pass, set the evaluation success
// to partial.
auto evalSuccess = EvalSuccess::NONE;
const auto& formTimes = FormTime::ALL_FORM_TIMES;
for (const auto& formTime : formTimes)
for (const auto& formTime : FormTime::ALL_FORM_TIMES)
{
if (formTime & parentAreaFormTime)
{
@@ -781,7 +769,6 @@ namespace randomizer::logic::requirement
}
}
}
return EvalSuccess::NONE;
}
+1 -1
View File
@@ -1,6 +1,5 @@
#pragma once
#include <memory>
#include <string>
#include <variant>
#include <vector>
@@ -108,6 +107,7 @@ namespace randomizer::logic::requirement
* for checking settings when reading them in from, for example, startflags.yaml
*
* @param req - The simple requirement
* @param world - The world this requirement is for
* @return true if the requirment holds, false otherwise
*/
bool EvaluateSimpleRequirement(const Requirement& req, world::World* world);
+26 -33
View File
@@ -6,6 +6,7 @@
#include "../utility/platform.hpp"
#include <fstream>
#include <iostream>
namespace randomizer::logic::search
{
@@ -85,7 +86,7 @@ namespace randomizer::logic::search
this->_newThingsFound = false;
// Add an empty sphere if we're generating the playthrough or tracker spheres
if (randomizer::utility::general::IsAnyOf(this->_searchMode,
if (utility::general::IsAnyOf(this->_searchMode,
SearchMode::GENERATE_PLAYTHROUGH,
SearchMode::TRACKER_SPHERES))
{
@@ -100,7 +101,7 @@ namespace randomizer::logic::search
this->_newThingsFound = false;
this->ProcessEvents();
this->ProcessExits();
} while (this->_newThingsFound && randomizer::utility::general::IsAnyOf(this->_searchMode,
} while (this->_newThingsFound && utility::general::IsAnyOf(this->_searchMode,
SearchMode::GENERATE_PLAYTHROUGH,
SearchMode::TRACKER_SPHERES));
@@ -142,7 +143,7 @@ namespace randomizer::logic::search
// If the exit is successful
auto evalSuccess = requirement::EvaluateExitRequirement(this, exit);
if (randomizer::utility::general::IsAnyOf(evalSuccess,
if (utility::general::IsAnyOf(evalSuccess,
requirement::EvalSuccess::COMPLETE,
requirement::EvalSuccess::PARTIAL))
{
@@ -188,7 +189,7 @@ namespace randomizer::logic::search
this->_newThingsFound = true;
// If we're calculating spheres, then process this location later for accurate sphere calculation. Otherwise
// process it now for slightly faster searching
if (randomizer::utility::general::IsAnyOf(this->_searchMode,
if (utility::general::IsAnyOf(this->_searchMode,
SearchMode::GENERATE_PLAYTHROUGH,
SearchMode::TRACKER_SPHERES))
{
@@ -251,21 +252,17 @@ namespace randomizer::logic::search
// If we're generating the playthrough or just checking for beatability, then we can stop searching early if we've
// found all world's game winning items
if (randomizer::utility::general::IsAnyOf(this->_searchMode, SearchMode::GENERATE_PLAYTHROUGH, SearchMode::GAME_BEATABLE) &&
if (utility::general::IsAnyOf(this->_searchMode, SearchMode::GENERATE_PLAYTHROUGH, SearchMode::GAME_BEATABLE) &&
location->GetCurrentItem()->IsGameWinningItem())
{
if (std::count_if(this->_ownedItems.begin(),
this->_ownedItems.end(),
[](const auto& item) { return item->IsGameWinningItem(); }) == this->_worlds->size())
if (std::ranges::count_if(this->_ownedItems, [](const auto& item) {
return item->IsGameWinningItem();
}) == this->_worlds->size())
{
if (this->_searchMode == SearchMode::GENERATE_PLAYTHROUGH)
{
auto& lastSphere = this->_playthroughSpheres.back();
lastSphere.erase(
std::remove_if(lastSphere.begin(),
lastSphere.end(),
[](const auto& location) { return !location->GetCurrentItem()->IsGameWinningItem(); }),
lastSphere.end());
std::erase_if(lastSphere,[](const auto& loc) { return !loc->GetCurrentItem()->IsGameWinningItem(); });
}
this->_isBeatable = true;
}
@@ -355,7 +352,7 @@ namespace randomizer::logic::search
void Search::AddExitToEntranceSpheres(entrance::Entrance* exit)
{
if (randomizer::utility::general::IsAnyOf(this->_searchMode,
if (utility::general::IsAnyOf(this->_searchMode,
SearchMode::GENERATE_PLAYTHROUGH,
SearchMode::TRACKER_SPHERES) &&
exit->IsShuffled())
@@ -402,8 +399,8 @@ namespace randomizer::logic::search
}
else
{
itemItr++; // Only incremement if we don't erase
entranceItr++;
++itemItr; // Only incremement if we don't erase
++entranceItr;
}
}
}
@@ -448,7 +445,7 @@ namespace randomizer::logic::search
// Make edge connections defined by events
for (const auto& event : area->GetEvents())
{
auto color = this->_ownedEvents.contains(event->GetEventIndex()) ? "blue" : "red";
color = this->_ownedEvents.contains(event->GetEventIndex()) ? "blue" : "red";
auto eventName = world->GetEventName(event->GetEventIndex());
worldGraph << "\t\"" << eventName << "\"[label=<" << eventName << "> shape=\"plain\" fontcolor=\"" << color
<< "\"];";
@@ -460,7 +457,7 @@ namespace randomizer::logic::search
{
if (exit->GetConnectedArea())
{
auto color = this->_successfulExits.contains(exit) ? "black" : "red";
color = this->_successfulExits.contains(exit) ? "black" : "red";
worldGraph << "\t\"" << areaName << "\" -> \"" << exit->GetConnectedArea()->GetName()
<< "\"[dir=forward color=\"" << color << "\"]";
}
@@ -470,7 +467,7 @@ namespace randomizer::logic::search
for (const auto& locAccess : area->GetLocations())
{
auto location = locAccess->GetLocation();
auto color = this->_visitedLocations.contains(location) ? "black" : "red";
color = this->_visitedLocations.contains(location) ? "black" : "red";
worldGraph << "\t\"" << location->GetName() << "\"[label=<" << location->GetName() << ":<br/>"
<< location->GetCurrentItem()->GetName() << "> shape=\"plain\" fontcolor=\"" << color << "\"];";
worldGraph << "\t\"" << areaName << "\" -> \"" << location->GetName() << "\"[dir=forward color=\"" << color
@@ -495,9 +492,9 @@ namespace randomizer::logic::search
if (world->Setting("Logic Rules") == "All Locations Reachable")
{
auto numlocationsReached =
std::count_if(search._visitedLocations.begin(),
search._visitedLocations.end(),
[&](const auto& location) { return location->GetWorld() == world.get(); });
std::ranges::count_if(search._visitedLocations, [&](const auto& location) {
return location->GetWorld() == world.get();
});
auto allLocations = world->GetAllLocations(/*includeNonItemLocations = */ true);
if (numlocationsReached != allLocations.size())
@@ -530,7 +527,7 @@ namespace randomizer::logic::search
return std::nullopt;
}
void GeneratePlaythrough(randomizer::Randomizer* randomizer)
void GeneratePlaythrough(Randomizer* randomizer)
{
auto& worlds = randomizer->GetWorlds();
LOG_TO_DEBUG("Generating Playthrough");
@@ -565,7 +562,7 @@ namespace randomizer::logic::search
}
}
randomizer::utility::platform::Log("Paring down playthrough");
utility::platform::Log("Paring down playthrough");
// Pare down the playthrough in reverse order so we're paring it down from highest to lowest sphere.
// This way, lower sphere items will be prioritized for the playthrough
playthroughSpheres.reverse();
@@ -601,6 +598,7 @@ namespace randomizer::logic::search
for (auto& sphere : entranceSpheres)
{
// Make a copy to avoid iterator invalidation
auto sphereCopy = sphere;
for (const auto& entrance : sphereCopy)
{
@@ -608,7 +606,7 @@ namespace randomizer::logic::search
if (GameBeatable(&worlds))
{
// If the game is still beatable then this entrance is not required
sphere.erase(std::remove(sphere.begin(), sphere.end(), entrance), sphere.end());
sphere.remove(entrance);
nonRequiredEntrances[entrance] = connectedArea;
}
else
@@ -634,14 +632,9 @@ namespace randomizer::logic::search
// Erase all locations not in the playthrough locations set
for (auto& sphere : newSearch._playthroughSpheres)
{
auto sphereCopy = sphere;
for (const auto& location : sphereCopy)
{
if (!playthroughLocationsSet.contains(location))
{
sphere.erase(std::remove(sphere.begin(), sphere.end(), location), sphere.end());
}
}
sphere.remove_if([&](const auto& location) {
return !playthroughLocationsSet.contains(location);
});
}
// Remove any empty spheres
-1
View File
@@ -8,7 +8,6 @@
#include <vector>
#include <list>
#include <memory>
#include <iostream>
#include <optional>
// Forward Declarations (we have a lot here)
+10 -10
View File
@@ -12,19 +12,19 @@
namespace randomizer::logic::spoiler_log
{
std::string SpoilerFormatLocation(location::Location* location, const size_t& longestNameLength)
std::string SpoilerFormatLocation(const location::Location* location, const size_t& longestNameLength)
{
auto numSpaces = longestNameLength - location->GetName().length();
std::string spaces(numSpaces, ' ');
const auto numSpaces = longestNameLength - location->GetName().length();
const std::string spaces(numSpaces, ' ');
return location->GetName() + ": " + spaces + location->GetCurrentItem()->GetName();
}
std::string SpoilerFormatEntrance(entrance::Entrance* entrance, const size_t& longestNameLength)
std::string SpoilerFormatEntrance(const entrance::Entrance* entrance, const size_t& longestNameLength)
{
auto numSpaces = longestNameLength - entrance->GetAlias().length();
std::string spaces(numSpaces, ' ');
auto replacement = entrance->GetReplaces();
const auto numSpaces = longestNameLength - entrance->GetAlias().length();
const std::string spaces(numSpaces, ' ');
const auto replacement = entrance->GetReplaces();
return entrance->GetAlias() + ": " + spaces + replacement->GetAliasFrom();
}
@@ -205,9 +205,9 @@ namespace randomizer::logic::spoiler_log
mixedPools.pop_front();
}
spoilerLog << " " << typeStr << ":" << std::endl;
std::sort(entrancePool.begin(),
entrancePool.end(),
[](auto& e1, auto& e2) { return e1->GetID() < e2->GetID(); });
std::ranges::sort(entrancePool, [](auto& e1, auto& e2) {
return e1->GetID() < e2->GetID();
});
for (const auto& entrance : entrancePool)
{
// Ignore entrances that are impossible
+8 -8
View File
@@ -844,9 +844,9 @@ namespace randomizer::logic::world
}
auto allItemLocations = this->GetAllLocations();
int numEmptyLocations = std::count_if(allItemLocations.begin(),
allItemLocations.end(),
[](const auto& location) { return location->IsEmpty(); });
const auto numEmptyLocations = std::ranges::count_if(allItemLocations, [](const auto& location) {
return location->IsEmpty();
});
// Create a copy of the real pool we just made. When adding junk items we want to add all the items from the junk pool
// once if possible, then if there's more space left pick randomly from the full pool
@@ -873,7 +873,7 @@ namespace randomizer::logic::world
void World::SetSearchStartingProperties(search::Search* search) const
{
// Set the root area to have all player forms and times of day (necessary for entrance rando validation)
auto root = this->GetRootArea();
const auto root = this->GetRootArea();
search->_areaFormTime[root] = requirement::FormTime::ALL;
}
@@ -885,10 +885,10 @@ namespace randomizer::logic::world
void World::FinalizeBottleContents()
{
// Replace 3 bottles with other bottle contents we currently use.
auto bottleWithGreatFairiesTears = this->GetItem("Bottle with Great Fairies Tears");
auto bottleWithHalfMilk = this->GetItem("Bottle with Half Milk");
auto bottleWithLanternOil = this->GetItem("Bottle with Lantern Oil");
auto emptyBottle = this->GetItem("Empty Bottle");
const auto bottleWithGreatFairiesTears = this->GetItem("Bottle with Great Fairies Tears");
const auto bottleWithHalfMilk = this->GetItem("Bottle with Half Milk");
const auto bottleWithLanternOil = this->GetItem("Bottle with Lantern Oil");
const auto emptyBottle = this->GetItem("Empty Bottle");
item_pool::ItemPool bottlePool = {bottleWithGreatFairiesTears,
bottleWithHalfMilk,
bottleWithLanternOil,
-3
View File
@@ -8,7 +8,6 @@
#include "requirement.hpp"
#include "../seedgen/settings.hpp"
#include "../utility/container.hpp"
#include "../utility/log.hpp"
#include <unordered_map>
@@ -16,8 +15,6 @@
#include <vector>
#include <memory>
#include <iostream>
// Forward Declarations
namespace randomizer
{
-2
View File
@@ -7,10 +7,8 @@
#include "logic/search.hpp"
#include "logic/spoiler_log.hpp"
#include "logic/world.hpp"
#include "test/test.hpp"
#include "seedgen/config.hpp"
#include "seedgen/settings.hpp"
#include "utility/log.hpp"
#include "utility/time.hpp"
#include <iostream>
+7 -7
View File
@@ -56,20 +56,20 @@ namespace randomizer::seedgen::config
bool IsUsingPlandomizer() const { return this->_isUsingPlandomizer; }
bool IsGeneratingSpoilerLog() const { return this->_isGeneratingSpoilerLog; }
void resetDefaultSettings();
void resetDefaultPreferences(const bool& paths = false);
void LoadFromFile(const fspath& filePath,
// void resetDefaultSettings();
// void resetDefaultPreferences(const bool& paths = false);
void LoadFromFile(const fspath& settingsPath,
const fspath& preferencesPath,
const bool& createNewIfNotFound = true,
const bool& createIfNotFound = true,
const bool& allowRewrite = true);
YAML::Node SettingsToYaml();
YAML::Node PreferencesToYaml();
void WriteSettingsToFile(const fspath& filePath);
void WritePreferencesToFile(const fspath& preferencesPath);
void WriteToFile(const fspath& filePath, const fspath& preferencesPath) const;
// void WriteToFile(const fspath& filePath, const fspath& preferencesPath) const;
PermalinkError loadPermalink(std::string b64permalink);
std::string getPermalink(const bool& internal = false) const;
// PermalinkError loadPermalink(std::string b64permalink);
// std::string getPermalink(const bool& internal = false) const;
/**
* @brief Returns the hash for the config. If the hash is an empty string, then a new one will be generated.
+6 -9
View File
@@ -92,21 +92,18 @@ namespace randomizer::seedgen::seed
std::string GenerateSeed()
{
std::string adjective1, adjective2, noun;
adjective1 = adjectives[rand() % adjectives.size()];
adjective2 = adjectives[rand() % adjectives.size()];
noun = nouns[rand() % nouns.size()];
const std::string adjective1 = adjectives[rand() % adjectives.size()];
const std::string adjective2 = adjectives[rand() % adjectives.size()];
const std::string noun = nouns[rand() % nouns.size()];
return adjective1 + adjective2 + noun;
}
std::string GenerateHash()
{
std::string noun1, noun2, noun3;
noun1 = randomizer::utility::random::RandomElement(nouns);
noun2 = randomizer::utility::random::RandomElement(nouns);
noun3 = randomizer::utility::random::RandomElement(nouns);
const std::string noun1 = utility::random::RandomElement(nouns);
const std::string noun2 = utility::random::RandomElement(nouns);
const std::string noun3 = utility::random::RandomElement(nouns);
return noun1 + " " + noun2 + " " + noun3;
}
+4 -6
View File
@@ -1,7 +1,6 @@
#include "settings.hpp"
#include "../utility/log.hpp"
#include "../utility/platform.hpp"
#include "../utility/container.hpp"
#include "../utility/file.hpp"
#include "../utility/random.hpp"
@@ -10,7 +9,6 @@
#include <unordered_map>
#include <algorithm>
#include <iostream>
#include <memory>
namespace randomizer::seedgen::settings
@@ -54,16 +52,16 @@ namespace randomizer::seedgen::settings
// The logic expression of a setting replaces spaces with underscores,
// and removes apostraphes and parenthesis
auto logicName = name;
std::replace(logicName.begin(), logicName.end(), ' ', '_');
randomizer::utility::str::Erase(logicName, "'", ")", "(");
std::ranges::replace(logicName, ' ', '_');
utility::str::Erase(logicName, "'", ")", "(");
this->_logicName = logicName;
// Same for logic expressions of options for this setting
for (const auto& option : options)
{
auto logicOption = option;
std::replace(logicOption.begin(), logicOption.end(), ' ', '_');
randomizer::utility::str::Erase(logicOption, "'", ")", "(");
std::ranges::replace(logicOption, ' ', '_');
utility::str::Erase(logicOption, "'", ")", "(");
this->_logicOptions.push_back(logicOption);
}
}
+1 -1
View File
@@ -136,7 +136,7 @@ namespace randomizer::seedgen::settings
const bool& IsUsingRandomOption() const { return this->_isUsingRandomOption; }
SettingInfo* GetInfo() const { return this->_info; }
const std::string& GetCustomOption() const { return this->_customOption; }
void SetCustomOption(const std::string& newCustomOption);
// void SetCustomOption(const std::string& newCustomOption);
void ResolveIfRandom();
bool operator==(const char* optionName) const;
+3 -3
View File
@@ -14,7 +14,7 @@ namespace randomizer::test::test
{
if (entry.path().generic_string().ends_with("settings.yaml"))
{
auto pathFolders = randomizer::utility::str::Split(entry.path().generic_string(), '/');
auto pathFolders = utility::str::Split(entry.path().generic_string(), '/');
auto& testName = pathFolders[pathFolders.size() - 2];
std::filesystem::remove(SETTINGS_PATH);
std::filesystem::copy_file(entry, SETTINGS_PATH);
@@ -22,13 +22,13 @@ namespace randomizer::test::test
std::cout << "Testing " << testName << std::endl;
try {
randomizer::Randomizer r{};
Randomizer r{};
r.GenerateWorlds();
}
catch(const std::exception& e) {
std::cout << "Test \"" << testName << "\" failed! Failed settings saved to " << SETTINGS_PATH << std::endl;
std::cout << "Error Message: " << e.what() << std::endl;
throw e;
throw;
}
std::filesystem::remove(SETTINGS_PATH);