#include #include #include #include "../extern/args.hpp" #include "AIResolver.hpp" #include "BuildData/BuildItems.hpp" #include "BuildData/BuildMoves.hpp" #include "BuildData/BuildNatures.hpp" #include "BuildData/BuildSpecies.hpp" #include "BuildData/BuildTypes.hpp" #include "BuildData/GrowthRatesBuilder.hpp" #include "Runner.hpp" static const char* ScriptsPath = nullptr; int main(int argc, char** argv) { args::ArgumentParser parser("PkmnLib AI Runner.", ""); args::HelpFlag help(parser, "help", "Display this help menu", {'h', "help"}); std::string workingDirectory; std::string typesFile = "Types.csv"; std::string naturesFile = "Natures.csv"; std::string pokemonFile = "Pokemon.json"; std::string moveFile = "Moves.json"; std::string itemsFile = "Items.json"; std::string growthRatesFile = "GrowthRates.json"; std::string scriptsPath = "Scripts"; args::HelpFlag helpFlag(parser, "help", "Display this help menu", {'h', "help"}); args::ValueFlag workingDirFlag(parser, "Working Directory", "Which work directory to use.", {"workdir"}); args::ValueFlag runsFlag(parser, "Runs", "How many battle to runs.", {"runs", 'r'}, 1000); args::ValueFlag ai1Flag(parser, "AI 1", "What AI to use for side 1.", {"ai1", '1'}, "depthsearch"); args::ValueFlag ai2Flag(parser, "AI 2", "What AI to use for side 2.", {"ai2", '2'}, "naive"); try { parser.ParseCLI(argc, argv); } catch (args::Help) { std::cout << parser; return 0; } catch (args::ParseError e) { std::cerr << e.what() << std::endl; std::cerr << parser; return 1; } catch (args::ValidationError e) { std::cerr << e.what() << std::endl; std::cerr << parser; return 1; } if (workingDirFlag) { workingDirectory = args::get(workingDirFlag); } if (!workingDirectory.empty()) { chdir(std::filesystem::path(workingDirectory).c_str()); } auto* typesLibrary = BuildTypes::Build(typesFile); auto* natureLibrary = BuildNatures::Build(naturesFile); auto* movesLibrary = BuildMoves::Build(moveFile, typesLibrary); auto* speciesLibrary = BuildSpecies::BuildLibrary(pokemonFile, typesLibrary, movesLibrary); auto* itemsLibrary = BuildItems::Build(itemsFile); auto* growthRates = GrowthRatesBuilder::Build(growthRatesFile); ScriptsPath = scriptsPath.c_str(); if (typesLibrary == nullptr || speciesLibrary == nullptr || natureLibrary == nullptr || movesLibrary == nullptr || itemsLibrary == nullptr || growthRates == nullptr) { return 1; } auto settings = new PkmnLib::Library::LibrarySettings(100, 4, 4096); auto staticLibrary = new PkmnLib::Library::PokemonLibrary(settings, speciesLibrary, movesLibrary, itemsLibrary, growthRates, typesLibrary, natureLibrary); auto scriptResolver = PkmnLib::Battling::BattleLibrary::CreateScriptResolver(); auto battleLib = new PkmnLib::Battling::BattleLibrary( staticLibrary, new PkmnLib::Battling::StatCalculator(), new PkmnLib::Battling::DamageLibrary(), new PkmnLib::Battling::ExperienceLibrary(), scriptResolver, new PkmnLib::Battling::MiscLibrary()); scriptResolver->Initialize(battleLib); auto asScriptResolver = dynamic_cast(scriptResolver); for (const auto& dirEntry : std::filesystem::recursive_directory_iterator(ScriptsPath)) { if (dirEntry.is_directory()) continue; if (dirEntry.path().parent_path().stem() == "Interfaces") continue; if (dirEntry.path().extension() != ".as") continue; std::ifstream in(dirEntry.path()); std::string contents((std::istreambuf_iterator(in)), std::istreambuf_iterator()); asScriptResolver->CreateScript(dirEntry.path().c_str(), contents.c_str()); } asScriptResolver->FinalizeModule(); auto ai1 = AIResolver::Resolve(ArbUt::StringView(ai1Flag.Get().c_str(), ai1Flag.Get().size())); auto ai2 = AIResolver::Resolve(ArbUt::StringView(ai2Flag.Get().c_str(), ai1Flag.Get().size())); try { Runner::Run(battleLib, ai1, ai2, runsFlag.Get()); } catch (ArbUt::Exception& e) { std::cout << std::endl; std::cout << "Exception with message: " << std::endl << e.what() << std::endl << e.GetStacktrace(10) << std::endl; return 1; } delete battleLib; delete ai1; delete ai2; return 0; }