mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-06-07 19:31:19 -04:00
Wrap generator in Randomizer class
This commit is contained in:
@@ -1389,8 +1389,6 @@ set(DUSK_FILES
|
||||
src/dusk/randomizer/logic/flatten/flatten.hpp
|
||||
src/dusk/randomizer/logic/flatten/simplify_algebraic.cpp
|
||||
src/dusk/randomizer/logic/flatten/simplify_algebraic.hpp
|
||||
src/dusk/randomizer/logic/generate.cpp
|
||||
src/dusk/randomizer/logic/generate.hpp
|
||||
src/dusk/randomizer/logic/item.cpp
|
||||
src/dusk/randomizer/logic/item.hpp
|
||||
src/dusk/randomizer/logic/item_pool.cpp
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "search.hpp"
|
||||
#include "world.hpp"
|
||||
#include "../randomizer.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
@@ -10,15 +11,12 @@
|
||||
namespace randomizer::logic::area
|
||||
{
|
||||
|
||||
int LocationAccess::_idCounter = 0;
|
||||
int Area::_idCounter = 0;
|
||||
|
||||
LocationAccess::LocationAccess(randomizer::logic::location::Location* loc,
|
||||
const randomizer::logic::requirement::Requirement& req,
|
||||
Area* area):
|
||||
_loc(loc), _req(std::move(req)), _area(area)
|
||||
{
|
||||
this->_id = this->_idCounter++;
|
||||
this->_id = area->GetWorld()->GetRandomizer()->GetNewLocAccID();
|
||||
}
|
||||
|
||||
randomizer::logic::location::Location* LocationAccess::GetLocation() const
|
||||
@@ -63,7 +61,7 @@ namespace randomizer::logic::area
|
||||
|
||||
Area::Area(const std::string& name, randomizer::logic::world::World* world): _name(name), _world(world)
|
||||
{
|
||||
this->_id = this->_idCounter++;
|
||||
this->_id = world->GetRandomizer()->GetNewAreaID();
|
||||
}
|
||||
|
||||
std::string Area::GetName() const
|
||||
|
||||
@@ -36,8 +36,6 @@ namespace randomizer::logic::area
|
||||
int GetID() const;
|
||||
|
||||
private:
|
||||
static int _idCounter;
|
||||
|
||||
int _id = -1;
|
||||
randomizer::logic::location::Location* _loc = nullptr;
|
||||
randomizer::logic::requirement::Requirement _req;
|
||||
@@ -97,8 +95,6 @@ namespace randomizer::logic::area
|
||||
void AssignHintRegionsAndDungeonLocations();
|
||||
|
||||
private:
|
||||
static int _idCounter;
|
||||
|
||||
int _id = -1;
|
||||
std::string _name = "";
|
||||
std::string _hardAssignedRegion = "";
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
#include "generate.hpp"
|
||||
|
||||
#include "entrance_shuffle.hpp"
|
||||
#include "fill.hpp"
|
||||
#include "flatten/flatten.hpp"
|
||||
#include "plandomizer.hpp"
|
||||
#include "search.hpp"
|
||||
#include "spoiler_log.hpp"
|
||||
#include "../seedgen/config.hpp"
|
||||
#include "../seedgen/settings.hpp"
|
||||
#include "../utility/log.hpp"
|
||||
#include "../utility/time.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace randomizer::logic::generate
|
||||
{
|
||||
randomizer::logic::world::WorldPool GenerateWorlds()
|
||||
{
|
||||
randomizer::utility::time::ScopedTimer<"Seed generation took ", std::chrono::milliseconds> timer;
|
||||
randomizer::seedgen::config::Config config;
|
||||
config.LoadFromFile(SETTINGS_PATH, PREFERENCES_PATH);
|
||||
|
||||
randomizer::utility::platform::Log(std::string("Seed: ") + config.GetSeed());
|
||||
|
||||
randomizer::logic::world::WorldPool worlds = {};
|
||||
GenerateRandomizer(config, worlds);
|
||||
|
||||
return std::move(worlds);
|
||||
}
|
||||
|
||||
void GenerateRandomizer(randomizer::seedgen::config::Config& config, randomizer::logic::world::WorldPool& worlds)
|
||||
{
|
||||
randomizer::seedgen::config::SeedRNG(config, true, false);
|
||||
// Set the hash now before anything else random is decided. This allows us to show the hash for a seed
|
||||
// before generating it later
|
||||
auto hash = config.GetHash();
|
||||
randomizer::utility::platform::Log(std::string("Hash: ") + hash);
|
||||
|
||||
// Build all worlds
|
||||
int worldId = 1;
|
||||
for (const auto& settings : config.GetSettingsList())
|
||||
{
|
||||
std::unique_ptr<randomizer::logic::world::World> world = std::make_unique<randomizer::logic::world::World>(worldId++);
|
||||
world->SetSettings(settings);
|
||||
world->ResolveRandomSettings();
|
||||
world->ResolveConflictingSettings();
|
||||
world->Build();
|
||||
worlds.emplace_back(std::move(world));
|
||||
}
|
||||
|
||||
// Give each world a pointer to the world pool
|
||||
for (auto& world : worlds)
|
||||
{
|
||||
world->SetWorlds(&worlds);
|
||||
}
|
||||
|
||||
// Process Plando Data for all worlds
|
||||
if (config.IsUsingPlandomizer())
|
||||
{
|
||||
randomizer::logic::plandomizer::LoadPlandomizerData(worlds, config.GetPlandomizerPath());
|
||||
}
|
||||
|
||||
// Pre Entrance Shuffle Tasks
|
||||
for (auto& world : worlds)
|
||||
{
|
||||
world->PerformPreEntranceShuffleTasks();
|
||||
}
|
||||
|
||||
randomizer::utility::platform::Log("Shuffling Entrances...");
|
||||
for (auto& world : worlds)
|
||||
{
|
||||
randomizer::logic::entrance_shuffle::ShuffleWorldEntrances(world.get(), worlds);
|
||||
}
|
||||
|
||||
// Post Entrance Shuffle Tasks
|
||||
for (auto& world : worlds)
|
||||
{
|
||||
world->PerformPostEntranceShuffleTasks();
|
||||
}
|
||||
randomizer::logic::fill::CacheExitTimeForms(worlds);
|
||||
|
||||
// Flattening isn't used for anything yet, but flattens down the requirements for
|
||||
// each location and entrance into a single statement. This will be useful for hints and could potentially
|
||||
// be used to speed up the fill algorithm (but the fill algorithm is already pretty fast, so we'd only gain maybe like
|
||||
// 0.2 seconds back or something)
|
||||
randomizer::utility::platform::Log("Flattening...");
|
||||
FlattenSearch search = FlattenSearch(worlds.at(0).get());
|
||||
search.doSearch();
|
||||
|
||||
randomizer::utility::platform::Log("Filling Worlds...");
|
||||
randomizer::logic::fill::FillWorlds(worlds);
|
||||
|
||||
// Post Fill Tasks
|
||||
for (auto& world : worlds)
|
||||
{
|
||||
world->PerformPostFillTasks();
|
||||
}
|
||||
|
||||
// Generate Playthrough
|
||||
randomizer::logic::search::GeneratePlaythrough(&worlds);
|
||||
|
||||
// TODO: Generate Hints
|
||||
|
||||
// Write Logs
|
||||
if (config.IsGeneratingSpoilerLog())
|
||||
{
|
||||
randomizer::logic::spoiler_log::GenerateSpoilerLog(worlds, config);
|
||||
}
|
||||
randomizer::logic::spoiler_log::GenerateAntiSpoilerLog(worlds, config);
|
||||
}
|
||||
} // namespace randomizer::logic::generate
|
||||
@@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "world.hpp"
|
||||
#include "../seedgen/config.hpp"
|
||||
|
||||
namespace randomizer::logic::generate
|
||||
{
|
||||
/**
|
||||
* @brief Generates a complete randomizer seed
|
||||
*
|
||||
* @param worlds The list of worlds for the generated randomizer seed
|
||||
* @return the worldpool which was generated
|
||||
*/
|
||||
randomizer::logic::world::WorldPool GenerateWorlds();
|
||||
|
||||
/**
|
||||
* @brief Generates a complete randomizer seed with the provided config
|
||||
*
|
||||
* @param config The configuration to use for this seed
|
||||
* @param worlds The list of worlds for the generated randomizer seed
|
||||
* @return 0 if no errors. 1 if there were errors
|
||||
*/
|
||||
void GenerateRandomizer(randomizer::seedgen::config::Config& config, randomizer::logic::world::WorldPool& worlds);
|
||||
} // namespace randomizer::logic::generate
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "search.hpp"
|
||||
|
||||
#include "world.hpp"
|
||||
#include "../randomizer.hpp"
|
||||
#include "../utility/general.hpp"
|
||||
#include "../utility/platform.hpp"
|
||||
|
||||
@@ -520,11 +521,12 @@ namespace randomizer::logic::search
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void GeneratePlaythrough(randomizer::logic::world::WorldPool* worlds)
|
||||
void GeneratePlaythrough(randomizer::Randomizer* randomizer)
|
||||
{
|
||||
auto& worlds = randomizer->GetWorlds();
|
||||
LOG_TO_DEBUG("Generating Playthrough");
|
||||
// Generate Initial Playthrough
|
||||
auto playthroughSearch = Search::Playthrough(worlds);
|
||||
auto playthroughSearch = Search::Playthrough(&worlds);
|
||||
playthroughSearch.SearchWorlds();
|
||||
|
||||
auto& playthroughSpheres = playthroughSearch._playthroughSpheres;
|
||||
@@ -542,7 +544,7 @@ namespace randomizer::logic::search
|
||||
}
|
||||
|
||||
// Remove all items from locations that are not part of the playthrough set
|
||||
for (const auto& world : *worlds)
|
||||
for (const auto& world : worlds)
|
||||
{
|
||||
for (const auto& location : world->GetAllLocations())
|
||||
{
|
||||
@@ -567,7 +569,7 @@ namespace randomizer::logic::search
|
||||
|
||||
// If the game is beatable, temporarily take this item away and erase the location from the playthrough
|
||||
// locations
|
||||
if (GameBeatable(worlds))
|
||||
if (GameBeatable(&worlds))
|
||||
{
|
||||
tempEmptyLocations[location] = itemAtLocation;
|
||||
playthroughLocationsSet.erase(location);
|
||||
@@ -581,7 +583,7 @@ namespace randomizer::logic::search
|
||||
|
||||
// Generate a new playthrough search incase some spheres were flattened by the previous generation having access
|
||||
// to extra items
|
||||
auto newSearch = Search::Playthrough(worlds);
|
||||
auto newSearch = Search::Playthrough(&worlds);
|
||||
newSearch.SearchWorlds();
|
||||
|
||||
// Now do the same process for entrances to pare down the entrance playthrough
|
||||
@@ -594,7 +596,7 @@ namespace randomizer::logic::search
|
||||
for (const auto& entrance : sphereCopy)
|
||||
{
|
||||
auto connectedArea = entrance->Disconnect();
|
||||
if (GameBeatable(worlds))
|
||||
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());
|
||||
@@ -636,8 +638,8 @@ namespace randomizer::logic::search
|
||||
// Remove any empty spheres
|
||||
newSearch.RemoveEmptySpheres();
|
||||
|
||||
worlds->at(0)->SetPlaythroughSpheres(newSearch._playthroughSpheres);
|
||||
worlds->at(0)->SetEntranceSpheres(newSearch._entranceSpheres);
|
||||
randomizer->GetPlaythroughSpheres() = newSearch._playthroughSpheres;
|
||||
randomizer->GetEntranceSpheres() = newSearch._entranceSpheres;
|
||||
}
|
||||
|
||||
bool GameBeatable(randomizer::logic::world::WorldPool* worlds, const randomizer::logic::item_pool::ItemPool& items /* = {} */)
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
#include <optional>
|
||||
|
||||
// Forward Declarations (we have a lot here)
|
||||
namespace randomizer
|
||||
{
|
||||
class Randomizer;
|
||||
}
|
||||
|
||||
namespace randomizer::logic::world
|
||||
{
|
||||
class World;
|
||||
@@ -156,6 +161,6 @@ namespace randomizer::logic::search
|
||||
*/
|
||||
std::optional<std::string> VerifyLogic(randomizer::logic::world::WorldPool* worlds,
|
||||
const randomizer::logic::item_pool::ItemPool& items = {});
|
||||
void GeneratePlaythrough(randomizer::logic::world::WorldPool* worlds);
|
||||
void GeneratePlaythrough(randomizer::Randomizer* randomizer);
|
||||
bool GameBeatable(randomizer::logic::world::WorldPool* worlds, const randomizer::logic::item_pool::ItemPool& items = {});
|
||||
} // namespace randomizer::logic::search
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "spoiler_log.hpp"
|
||||
|
||||
#include "entrance_shuffle.hpp"
|
||||
#include "../randomizer.hpp"
|
||||
#include "../utility/file.hpp"
|
||||
#include "../utility/platform.hpp"
|
||||
#include "../utility/yaml.hpp"
|
||||
@@ -28,23 +29,23 @@ namespace randomizer::logic::spoiler_log
|
||||
return entrance->GetAlias() + ": " + spaces + replacement->GetAliasFrom();
|
||||
}
|
||||
|
||||
void LogBasicInfo(std::ofstream& log, randomizer::seedgen::config::Config& config, randomizer::logic::world::WorldPool& worlds)
|
||||
void LogBasicInfo(std::ofstream& log, randomizer::Randomizer* randomizer)
|
||||
{
|
||||
log << "Dusk Randomizer Version: " << "1.0.0" << std::endl;
|
||||
log << "Seed: " << config.GetSeed() << std::endl;
|
||||
log << "Seed: " << randomizer->GetConfig().GetSeed() << std::endl;
|
||||
|
||||
// TODO: Setting string
|
||||
|
||||
log << "Hash: " << config.GetHash() << std::endl;
|
||||
log << "Hash: " << randomizer->GetConfig().GetHash() << std::endl;
|
||||
}
|
||||
|
||||
void LogSettings(std::ofstream& log, randomizer::seedgen::config::Config& config, randomizer::logic::world::WorldPool& worlds)
|
||||
void LogSettings(std::ofstream& log, randomizer::Randomizer* randomizer)
|
||||
{
|
||||
log << std::endl << "# Settings" << std::endl;
|
||||
log << YAML::Dump(config.SettingsToYaml()) << std::endl;
|
||||
log << YAML::Dump(randomizer->GetConfig().SettingsToYaml()) << std::endl;
|
||||
}
|
||||
|
||||
void GenerateSpoilerLog(randomizer::logic::world::WorldPool& worlds, randomizer::seedgen::config::Config& config)
|
||||
void GenerateSpoilerLog(randomizer::Randomizer* randomizer)
|
||||
{
|
||||
randomizer::utility::platform::Log("Generating Spoiler Log");
|
||||
|
||||
@@ -54,11 +55,14 @@ namespace randomizer::logic::spoiler_log
|
||||
randomizer::utility::file::create_directories(LOGS_PATH);
|
||||
}
|
||||
|
||||
auto& config = randomizer->GetConfig();
|
||||
auto& worlds = randomizer->GetWorlds();
|
||||
|
||||
std::string filepath = std::string(LOGS_PATH) + config.GetHash() + " Spoiler Log.txt";
|
||||
std::ofstream spoilerLog;
|
||||
spoilerLog.open(filepath);
|
||||
|
||||
LogBasicInfo(spoilerLog, config, worlds);
|
||||
LogBasicInfo(spoilerLog, randomizer);
|
||||
|
||||
// Gather worlds with starting inventories
|
||||
std::list<randomizer::logic::world::World*> worldswithStartingInventories = {};
|
||||
@@ -87,7 +91,7 @@ namespace randomizer::logic::spoiler_log
|
||||
|
||||
// Get name lengths for pretty formatting
|
||||
size_t longestNameLength = 0;
|
||||
for (const auto& sphere : worlds.at(0)->GetPlaythroughSpheres())
|
||||
for (const auto& sphere : randomizer->GetPlaythroughSpheres())
|
||||
{
|
||||
for (const auto& location : sphere)
|
||||
{
|
||||
@@ -98,7 +102,7 @@ namespace randomizer::logic::spoiler_log
|
||||
// Print playthrough
|
||||
int sphereNum = 0;
|
||||
spoilerLog << std::endl << "Playthrough:" << std::endl;
|
||||
for (auto& sphere : worlds.at(0)->GetPlaythroughSpheres())
|
||||
for (auto& sphere : randomizer->GetPlaythroughSpheres())
|
||||
{
|
||||
sphereNum += 1;
|
||||
spoilerLog << " Sphere " << sphereNum << ":" << std::endl;
|
||||
@@ -111,7 +115,7 @@ namespace randomizer::logic::spoiler_log
|
||||
|
||||
// Get name lengths for pretty formatting
|
||||
longestNameLength = 0;
|
||||
for (const auto& sphere : worlds.at(0)->GetEntranceSpheres())
|
||||
for (const auto& sphere : randomizer->GetEntranceSpheres())
|
||||
{
|
||||
for (const auto& entrance : sphere)
|
||||
{
|
||||
@@ -125,7 +129,7 @@ namespace randomizer::logic::spoiler_log
|
||||
{
|
||||
spoilerLog << std::endl << "Entrance Playthrough:" << std::endl;
|
||||
}
|
||||
for (auto& sphere : worlds.at(0)->GetEntranceSpheres())
|
||||
for (auto& sphere : randomizer->GetEntranceSpheres())
|
||||
{
|
||||
sphereNum += 1;
|
||||
if (sphere.empty())
|
||||
@@ -220,14 +224,14 @@ namespace randomizer::logic::spoiler_log
|
||||
// TODO: Hints
|
||||
|
||||
// Log Settings
|
||||
LogSettings(spoilerLog, config, worlds);
|
||||
LogSettings(spoilerLog, randomizer);
|
||||
|
||||
spoilerLog.close();
|
||||
|
||||
randomizer::utility::platform::Log("Wrote spoiler log to " + filepath);
|
||||
}
|
||||
|
||||
void GenerateAntiSpoilerLog(randomizer::logic::world::WorldPool& worlds, randomizer::seedgen::config::Config& config)
|
||||
void GenerateAntiSpoilerLog(randomizer::Randomizer* randomizer)
|
||||
{
|
||||
// Create logs folder if it doesn't exist
|
||||
if (!randomizer::utility::file::dirExists(LOGS_PATH))
|
||||
@@ -235,11 +239,11 @@ namespace randomizer::logic::spoiler_log
|
||||
randomizer::utility::file::create_directories(LOGS_PATH);
|
||||
}
|
||||
|
||||
std::string filepath = std::string(LOGS_PATH) + config.GetHash() + " Anti-Spoiler Log.txt";
|
||||
std::string filepath = std::string(LOGS_PATH) + randomizer->GetConfig().GetHash() + " Anti-Spoiler Log.txt";
|
||||
std::ofstream antiSpoilerLog;
|
||||
antiSpoilerLog.open(filepath);
|
||||
|
||||
LogBasicInfo(antiSpoilerLog, config, worlds);
|
||||
LogSettings(antiSpoilerLog, config, worlds);
|
||||
LogBasicInfo(antiSpoilerLog, randomizer);
|
||||
LogSettings(antiSpoilerLog, randomizer);
|
||||
}
|
||||
} // namespace randomizer::logic::spoiler_log
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "world.hpp"
|
||||
#include "../seedgen/config.hpp"
|
||||
// Forward Declarations
|
||||
namespace randomizer
|
||||
{
|
||||
class Randomizer;
|
||||
}
|
||||
|
||||
namespace randomizer::logic::spoiler_log
|
||||
{
|
||||
void GenerateSpoilerLog(randomizer::logic::world::WorldPool& worlds, randomizer::seedgen::config::Config& config);
|
||||
void GenerateAntiSpoilerLog(randomizer::logic::world::WorldPool& worlds, randomizer::seedgen::config::Config& config);
|
||||
void GenerateSpoilerLog(randomizer::Randomizer* randomizer);
|
||||
void GenerateAntiSpoilerLog(randomizer::Randomizer* randomizer);
|
||||
} // namespace randomizer::logic::spoiler_log
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
|
||||
#include "search.hpp"
|
||||
#include "../randomizer.hpp"
|
||||
#include "../utility/exception.hpp"
|
||||
#include "../utility/file.hpp"
|
||||
#include "../utility/general.hpp"
|
||||
@@ -17,12 +18,9 @@
|
||||
|
||||
namespace randomizer::logic::world
|
||||
{
|
||||
int World::_eventIdCounter = 0;
|
||||
|
||||
World::World(const int& id)
|
||||
{
|
||||
this->_id = id;
|
||||
}
|
||||
World::World(const int& id, randomizer::Randomizer* randomizer) :
|
||||
_id(id), _randomizer(randomizer)
|
||||
{}
|
||||
|
||||
int World::GetID() const
|
||||
{
|
||||
@@ -36,9 +34,13 @@ namespace randomizer::logic::world
|
||||
{
|
||||
return this->_settings;
|
||||
}
|
||||
void World::SetWorlds(WorldPool* worlds)
|
||||
void World::SetRandomizer(Randomizer* randomizer)
|
||||
{
|
||||
_worlds = worlds;
|
||||
this->_randomizer = randomizer;
|
||||
}
|
||||
Randomizer* World::GetRandomizer() const
|
||||
{
|
||||
return this->_randomizer;
|
||||
}
|
||||
|
||||
void World::ResolveRandomSettings()
|
||||
@@ -773,8 +775,8 @@ namespace randomizer::logic::world
|
||||
|
||||
// Check if the game is beatable, set dungeon as required if so. If the dungeon is not required and barren
|
||||
// unrequired dungeons is on, then set all the locations in the unrequired dungeon as nonprogress.
|
||||
auto completeItemPool = randomizer::logic::item_pool::GetCompleteItemPool(*(this->_worlds));
|
||||
if (!randomizer::logic::search::GameBeatable(this->_worlds, completeItemPool))
|
||||
auto completeItemPool = randomizer::logic::item_pool::GetCompleteItemPool(this->_randomizer->GetWorlds());
|
||||
if (!randomizer::logic::search::GameBeatable(&(this->_randomizer->GetWorlds()), completeItemPool))
|
||||
{
|
||||
dungeon->SetRequired(true);
|
||||
}
|
||||
@@ -1123,7 +1125,7 @@ namespace randomizer::logic::world
|
||||
// Add the event if it doesn't exist yet
|
||||
if (!this->_eventIndexes.contains(eventName))
|
||||
{
|
||||
auto index = this->_eventIdCounter++;
|
||||
auto index = this->_randomizer->GetNewEventID();
|
||||
this->_eventIndexes.emplace(eventName, index);
|
||||
this->_eventNames.emplace(index, eventName);
|
||||
LOG_TO_DEBUG("Event \"" + eventName + "\" was assigned eventIndex " + std::to_string(index));
|
||||
@@ -1151,24 +1153,4 @@ namespace randomizer::logic::world
|
||||
}
|
||||
return settings.GetMap().at(settingName);
|
||||
}
|
||||
|
||||
void World::SetPlaythroughSpheres(const std::list<std::list<randomizer::logic::location::Location*>>& playthroughSpheres)
|
||||
{
|
||||
this->_playthroughSpheres = playthroughSpheres;
|
||||
}
|
||||
|
||||
std::list<std::list<randomizer::logic::location::Location*>> World::GetPlaythroughSpheres() const
|
||||
{
|
||||
return this->_playthroughSpheres;
|
||||
}
|
||||
|
||||
void World::SetEntranceSpheres(const std::list<std::list<randomizer::logic::entrance::Entrance*>>& entranceSpheres)
|
||||
{
|
||||
this->_entranceSpheres = entranceSpheres;
|
||||
}
|
||||
|
||||
std::list<std::list<randomizer::logic::entrance::Entrance*>> World::GetEntranceSpheres() const
|
||||
{
|
||||
return this->_entranceSpheres;
|
||||
}
|
||||
} // namespace randomizer::logic::world
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
#include <iostream>
|
||||
|
||||
// Forward Declarations
|
||||
namespace randomizer
|
||||
{
|
||||
class Randomizer;
|
||||
}
|
||||
|
||||
namespace randomizer::logic::search
|
||||
{
|
||||
class Search;
|
||||
@@ -32,12 +37,13 @@ namespace randomizer::logic::world
|
||||
class World
|
||||
{
|
||||
public:
|
||||
World(const int& id);
|
||||
World(const int& id, randomizer::Randomizer* randomizer);
|
||||
|
||||
int GetID() const;
|
||||
void SetSettings(const randomizer::seedgen::settings::Settings& settings);
|
||||
const randomizer::seedgen::settings::Settings& GetSettings() const;
|
||||
void SetWorlds(WorldPool* worlds);
|
||||
void SetRandomizer(Randomizer* randomizer);
|
||||
Randomizer* GetRandomizer() const;
|
||||
|
||||
/**
|
||||
* @brief Resolves all remaining random settings within a specific world
|
||||
@@ -133,16 +139,10 @@ namespace randomizer::logic::world
|
||||
std::string GetEventName(const int& eventIndex);
|
||||
|
||||
randomizer::seedgen::settings::Setting& Setting(const std::string& settingName);
|
||||
void SetPlaythroughSpheres(const std::list<std::list<randomizer::logic::location::Location*>>& playthroughSpheres);
|
||||
std::list<std::list<randomizer::logic::location::Location*>> GetPlaythroughSpheres() const;
|
||||
void SetEntranceSpheres(const std::list<std::list<randomizer::logic::entrance::Entrance*>>& entranceSpheres);
|
||||
std::list<std::list<randomizer::logic::entrance::Entrance*>> GetEntranceSpheres() const;
|
||||
|
||||
private:
|
||||
int _id = -1;
|
||||
|
||||
static int _eventIdCounter; // Needs to be shared for events across all worlds
|
||||
int _entranceIdCounter = 0; // Specific for this world
|
||||
int _entranceIdCounter = 0;
|
||||
|
||||
randomizer::seedgen::settings::Settings _settings;
|
||||
std::map<std::string, std::unique_ptr<randomizer::logic::item::Item>> _itemTable = {};
|
||||
@@ -159,14 +159,10 @@ namespace randomizer::logic::world
|
||||
randomizer::logic::item_pool::ItemPool _startingItemPool = {};
|
||||
std::unordered_map<randomizer::logic::entrance::Entrance*, int> _exitTimeFormCache = {};
|
||||
|
||||
// Playthroughs will be stored in world 0 for convenience
|
||||
std::list<std::list<randomizer::logic::location::Location*>> _playthroughSpheres = {};
|
||||
std::list<std::list<randomizer::logic::entrance::Entrance*>> _entranceSpheres = {};
|
||||
|
||||
// Plandomizer Data
|
||||
std::unordered_map<randomizer::logic::location::Location*, randomizer::logic::item::Item*> _plandomizerLocations = {};
|
||||
std::unordered_map<randomizer::logic::entrance::Entrance*, randomizer::logic::entrance::Entrance*> _plandomizerEntrances = {};
|
||||
|
||||
WorldPool* _worlds = nullptr;
|
||||
Randomizer* _randomizer = nullptr;
|
||||
};
|
||||
} // namespace randomizer::logic::world
|
||||
|
||||
@@ -58,5 +58,6 @@ string(LENGTH "${CMAKE_SOURCE_DIR}/" SOURCE_PATH_SIZE)
|
||||
set(GAME_COMPILE_DEFS ${GAME_COMPILE_DEFS} SOURCE_PATH_SIZE=${SOURCE_PATH_SIZE})
|
||||
set(GAME_LIBS ${GAME_LIBS} yaml-cpp::yaml-cpp zlib base64pp)
|
||||
|
||||
make_directory("${CMAKE_BINARY_DIR}/randomizer")
|
||||
# Put data files together for easier manipulation
|
||||
# file(COPY "${CMAKE_SOURCE_DIR}/src/dusk/randomizer/data/" DESTINATION "${CMAKE_BINARY_DIR}/randomizer/data/" REGEX "^.*example.*$" EXCLUDE) # World, macros, and location info
|
||||
|
||||
@@ -1,29 +1,116 @@
|
||||
#include "randomizer.hpp"
|
||||
|
||||
#include "logic/generate.hpp"
|
||||
#include "logic/entrance_shuffle.hpp"
|
||||
#include "logic/fill.hpp"
|
||||
#include "logic/flatten/flatten.hpp"
|
||||
#include "logic/plandomizer.hpp"
|
||||
#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>
|
||||
|
||||
int randomizerMain()
|
||||
namespace randomizer
|
||||
{
|
||||
try
|
||||
int Randomizer::Generate()
|
||||
{
|
||||
#ifdef LOGIC_TESTS
|
||||
randomizer::test::test::RunTests();
|
||||
try
|
||||
{
|
||||
GenerateWorlds();
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
std::cout << "============================================================" << std::endl;
|
||||
std::cout << "The following exception occured: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
auto worlds = randomizer::logic::generate::GenerateWorlds();
|
||||
#endif
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
std::cout << "============================================================" << std::endl;
|
||||
std::cout << "The following exception occured: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
void Randomizer::GenerateWorlds()
|
||||
{
|
||||
utility::time::ScopedTimer<"Seed generation took ", std::chrono::milliseconds> timer;
|
||||
this->_worlds.clear();
|
||||
this->_config.LoadFromFile(SETTINGS_PATH, PREFERENCES_PATH);
|
||||
|
||||
utility::platform::Log(std::string("Seed: ") + this->_config.GetSeed());
|
||||
|
||||
seedgen::config::SeedRNG(this->_config, true, false);
|
||||
// Set the hash now before anything else random is decided. This allows us to show the hash for a seed
|
||||
// before generating it later
|
||||
auto hash = this->_config.GetHash();
|
||||
utility::platform::Log(std::string("Hash: ") + hash);
|
||||
|
||||
// Build all worlds
|
||||
int worldId = 1;
|
||||
for (const auto& settings : this->_config.GetSettingsList())
|
||||
{
|
||||
std::unique_ptr<logic::world::World> world = std::make_unique<logic::world::World>(worldId++, this);
|
||||
world->SetSettings(settings);
|
||||
world->ResolveRandomSettings();
|
||||
world->ResolveConflictingSettings();
|
||||
world->Build();
|
||||
this->_worlds.emplace_back(std::move(world));
|
||||
}
|
||||
|
||||
// Process Plando Data for all worlds
|
||||
if (this->_config.IsUsingPlandomizer())
|
||||
{
|
||||
logic::plandomizer::LoadPlandomizerData(this->_worlds, this->_config.GetPlandomizerPath());
|
||||
}
|
||||
|
||||
// Pre Entrance Shuffle Tasks
|
||||
for (auto& world : this->_worlds)
|
||||
{
|
||||
world->PerformPreEntranceShuffleTasks();
|
||||
}
|
||||
|
||||
utility::platform::Log("Shuffling Entrances...");
|
||||
for (auto& world : this->_worlds)
|
||||
{
|
||||
logic::entrance_shuffle::ShuffleWorldEntrances(world.get(), this->_worlds);
|
||||
}
|
||||
|
||||
// Post Entrance Shuffle Tasks
|
||||
for (auto& world : this->_worlds)
|
||||
{
|
||||
world->PerformPostEntranceShuffleTasks();
|
||||
}
|
||||
logic::fill::CacheExitTimeForms(this->_worlds);
|
||||
|
||||
// Flattening isn't used for anything yet, but flattens down the requirements for
|
||||
// each location and entrance into a single statement. This will be useful for hints and could potentially
|
||||
// be used to speed up the fill algorithm (but the fill algorithm is already pretty fast, so we'd only gain maybe like
|
||||
// 0.2 seconds back or something)
|
||||
utility::platform::Log("Flattening...");
|
||||
FlattenSearch search = FlattenSearch(this->_worlds.at(0).get());
|
||||
search.doSearch();
|
||||
|
||||
utility::platform::Log("Filling Worlds...");
|
||||
logic::fill::FillWorlds(this->_worlds);
|
||||
|
||||
// Post Fill Tasks
|
||||
for (auto& world : this->_worlds)
|
||||
{
|
||||
world->PerformPostFillTasks();
|
||||
}
|
||||
|
||||
// Generate Playthrough
|
||||
logic::search::GeneratePlaythrough(this);
|
||||
|
||||
// TODO: Generate Hints
|
||||
|
||||
// Write Logs
|
||||
if (this->_config.IsGeneratingSpoilerLog())
|
||||
{
|
||||
logic::spoiler_log::GenerateSpoilerLog(this);
|
||||
}
|
||||
logic::spoiler_log::GenerateAntiSpoilerLog(this);
|
||||
}
|
||||
} // namespace randomizer
|
||||
|
||||
@@ -1,3 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
int randomizerMain();
|
||||
#include "logic/world.hpp"
|
||||
|
||||
namespace randomizer
|
||||
{
|
||||
class Randomizer
|
||||
{
|
||||
public:
|
||||
explicit Randomizer() = default;
|
||||
|
||||
/**
|
||||
* @brief Generates a complete randomizer seed
|
||||
*
|
||||
* @return 0 if no errors. 1 if there were errors
|
||||
*/
|
||||
int Generate();
|
||||
void GenerateWorlds();
|
||||
|
||||
auto& GetConfig() { return this->_config; }
|
||||
auto& GetWorlds() { return this->_worlds; }
|
||||
|
||||
int GetNewEventID() { return ++(this->_eventIdCounter); }
|
||||
int GetNewAreaID() { return ++(this->_areaIdCounter); }
|
||||
int GetNewLocAccID() { return ++(this->_locAccIdCounter); }
|
||||
|
||||
auto& GetPlaythroughSpheres() { return this->_playthroughSpheres; }
|
||||
auto& GetEntranceSpheres() { return this->_entranceSpheres; }
|
||||
private:
|
||||
seedgen::config::Config _config{};
|
||||
logic::world::WorldPool _worlds{};
|
||||
|
||||
int _eventIdCounter{};
|
||||
int _areaIdCounter{};
|
||||
int _locAccIdCounter{};
|
||||
|
||||
// Playthrough data
|
||||
std::list<std::list<logic::location::Location*>> _playthroughSpheres{};
|
||||
std::list<std::list<logic::entrance::Entrance*>> _entranceSpheres{};
|
||||
};
|
||||
} // namespace randomizer
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "test.hpp"
|
||||
|
||||
#include "../logic/generate.hpp"
|
||||
#include "../logic/world.hpp"
|
||||
#include "../randomizer.hpp"
|
||||
#include "../utility/string.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
@@ -23,11 +22,12 @@ namespace randomizer::test::test
|
||||
std::cout << "Testing " << testName << std::endl;
|
||||
|
||||
try {
|
||||
randomizer::logic::generate::GenerateWorlds();
|
||||
randomizer::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:" << std::endl;
|
||||
std::cout << "Error Message: " << std::endl;
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace randomizer::utility::log
|
||||
#ifdef RANDO_ERROR_LOG
|
||||
output.open(LOG_PATH);
|
||||
output << "Program opened " << randomizer::utility::time::ProgramTime::getDateStr(); // time string ends with \n
|
||||
output << "Twilight Princess HD Randomizer Version " << RANDOMIZER_VERSION << std::endl;
|
||||
output << "Dusk Randomizer Version " << RANDOMIZER_VERSION << std::endl;
|
||||
output << std::endl << std::endl;
|
||||
#endif
|
||||
}
|
||||
@@ -77,7 +77,7 @@ namespace randomizer::utility::log
|
||||
{
|
||||
output.open(LOG_PATH);
|
||||
output << "Program opened " << randomizer::utility::time::ProgramTime::getDateStr(); // time string ends with \n
|
||||
output << "Twilight Princess HD Randomizer Version " << RANDOMIZER_VERSION << std::endl;
|
||||
output << "Dusk Randomizer Version " << RANDOMIZER_VERSION << std::endl;
|
||||
output << std::endl << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
|
||||
#if RANDOMIZER_ONLY
|
||||
#include "dusk/randomizer/randomizer.hpp"
|
||||
#include "dusk/randomizer/test/test.hpp"
|
||||
#endif
|
||||
|
||||
// --- GLOBALS ---
|
||||
@@ -288,7 +289,12 @@ static const char* CalculateConfigPath() {
|
||||
int game_main(int argc, char* argv[]) {
|
||||
|
||||
#if RANDOMIZER_ONLY
|
||||
randomizerMain();
|
||||
#ifdef LOGIC_TESTS
|
||||
randomizer::test::test::RunTests();
|
||||
#else
|
||||
randomizer::Randomizer rando{};
|
||||
rando.Generate();
|
||||
#endif
|
||||
exit(0);
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user