mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-05-31 17:01:36 -04:00
more clean up
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "entrance.hpp"
|
||||
#include "requirement.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <list>
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include <iterator>
|
||||
|
||||
BitVector::BitVector(std::list<int> bits)
|
||||
BitVector::BitVector(const std::list<int>& bits)
|
||||
{
|
||||
for (auto& i : bits)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
|
||||
// Forward Declarations (we have a lot here)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user