mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-06-24 15:43:13 -04:00
6366ab61d1
For the most part, solo archipelago runs seem to work fine now using the original TP apworld, but im sure there are plenty of weird issues still that need to be handled.
179 lines
6.2 KiB
C++
179 lines
6.2 KiB
C++
#include "randomizer.hpp"
|
|
|
|
#include "logic/entrance_shuffle.hpp"
|
|
#include "logic/fill.hpp"
|
|
#include "logic/flatten/flatten.hpp"
|
|
#include "logic/hints.hpp"
|
|
#include "logic/plandomizer.hpp"
|
|
#include "logic/search.hpp"
|
|
#include "logic/spoiler_log.hpp"
|
|
#include "logic/world.hpp"
|
|
#include "seedgen/config.hpp"
|
|
#include "seedgen/settings.hpp"
|
|
#include "utility/time.hpp"
|
|
|
|
#include <iostream>
|
|
|
|
#include "dusk/logging.h"
|
|
#include "dusk/archipelago/archipelago_context.hpp"
|
|
#include "dusk/ui/rando_config.hpp"
|
|
#include "dusk/randomizer/game/randomizer_context.hpp"
|
|
|
|
namespace randomizer
|
|
{
|
|
logic::world::World* Randomizer::GetWorld(int worldId /*= 1*/) {
|
|
auto worldIndex = worldId - 1;
|
|
if (worldIndex < this->_worlds.size()) {
|
|
return this->_worlds.at(worldIndex).get();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
std::optional<std::string> Randomizer::Generate()
|
|
{
|
|
try
|
|
{
|
|
GenerateWorlds();
|
|
}
|
|
catch(const std::exception& e)
|
|
{
|
|
std::cout << "============================================================" << std::endl;
|
|
std::cout << "The following exception occured: " << e.what() << std::endl;
|
|
return e.what();
|
|
}
|
|
|
|
return std::nullopt;
|
|
}
|
|
|
|
void Randomizer::GenerateTrackerWorld(bool useAntiSpoilerLog) {
|
|
auto contextHash = randomizer_GetContext().mHash;
|
|
|
|
if (!useAntiSpoilerLog) {
|
|
this->_config.LoadFromFile(GetConfigPath(), GetPrefPath());
|
|
this->_config.SetHash(contextHash);
|
|
}else {
|
|
if (contextHash.empty()) {
|
|
return;
|
|
}
|
|
|
|
std::filesystem::path seedSettings = dusk::ui::GetRandomizerSeedsPath() /
|
|
contextHash / (contextHash + " Anti-Spoiler Log.txt");
|
|
|
|
this->_config.LoadFromFile(seedSettings, GetPrefPath());
|
|
this->_config.SetHash(contextHash);
|
|
}
|
|
|
|
std::unique_ptr<logic::world::World> world = std::make_unique<logic::world::World>(1, this);
|
|
world->SetSettings(this->_config.GetSettingsList().front());
|
|
// Always use logic when building a tracker world
|
|
world->Setting("Logic Rules").SetCurrentOption("All Locations Reachable");
|
|
world->Build();
|
|
this->_worlds.emplace_back(std::move(world));
|
|
|
|
auto trackerWorld = this->_worlds.at(0).get();
|
|
trackerWorld->SetNonProgressLocations();
|
|
trackerWorld->SetTrackerNonProgressLocations();
|
|
trackerWorld->AssignAreaProperties();
|
|
trackerWorld->AssignGoalLocations();
|
|
|
|
// Cache exit form times. This *must* run before conducting the flattening search, otherwise
|
|
// the flattening search will pollute the exit timeform cache with a bunch of zeros
|
|
logic::fill::CacheExitTimeForms(this->_worlds);
|
|
|
|
// Set raw requirements for each location
|
|
FlattenSearch search = FlattenSearch(trackerWorld);
|
|
search.doSearch();
|
|
}
|
|
|
|
void Randomizer::GenerateWorlds()
|
|
{
|
|
utility::time::ScopedTimer<"Seed generation took ", std::chrono::milliseconds> timer;
|
|
this->_config.LoadFromFile(GetConfigPath(), GetPrefPath());
|
|
|
|
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())
|
|
{
|
|
try {
|
|
logic::plandomizer::LoadPlandomizerData(this->_worlds, this->_config.GetPlandomizerPath());
|
|
} catch (const std::runtime_error& e) {
|
|
throw std::runtime_error("Plandomizer Error: " + std::string(e.what()));
|
|
}
|
|
}
|
|
|
|
// 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());
|
|
}
|
|
|
|
// 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);
|
|
|
|
// Generate Hints
|
|
logic::hints::GenerateAllHints(this->_worlds);
|
|
|
|
// Write Logs
|
|
if (this->_config.IsGeneratingSpoilerLog())
|
|
{
|
|
logic::spoiler_log::GenerateSpoilerLog(this);
|
|
}
|
|
logic::spoiler_log::GenerateAntiSpoilerLog(this);
|
|
}
|
|
|
|
std::filesystem::path Randomizer::GetSeedOutputPath()
|
|
{
|
|
return this->_baseOutputPath / "seeds" / this->_config.GetHash();
|
|
}
|
|
} // namespace randomizer
|