using System.CommandLine; using System.CommandLine.Parsing; using System.Reflection; using PkmnLib.Dynamic.AI; using Serilog; namespace AIRunner; internal static class Program { private static List? _availableAIs; private static Task Main(string[] args) { Log.Logger = new LoggerConfiguration().MinimumLevel.Debug().WriteTo.Console().CreateLogger(); Log.Information("Starting AI Runner..."); _availableAIs = AppDomain.CurrentDomain.GetAssemblies().SelectMany(assembly => assembly.GetTypes()) .Where(type => type.IsSubclassOf(typeof(PokemonAI)) && !type.IsAbstract).Select(Activator.CreateInstance) .Cast().ToList(); var testCommand = new Command("test", "Run two AIs against each other") { new Option("--ai1") { Description = "The name of the first AI script to run against the second AI.", Required = true, Validators = { ValidateAI }, }, new Option("--ai2") { Description = "The name of the second AI script to run against the first AI.", Required = true, Validators = { ValidateAI }, }, new Option("--battles") { Description = "The number of battles to run between the two AIs.", Required = false, DefaultValueFactory = _ => 100, Validators = { result => { if (result.GetValueOrDefault() <= 0) { result.AddError("--battles must be a positive integer."); } }, }, }, }; testCommand.SetAction(result => { var ai1Name = result.GetRequiredValue("--ai1"); var ai2Name = result.GetRequiredValue("--ai2"); var ai1 = _availableAIs!.First(a => string.Equals(a.Name, ai1Name, StringComparison.InvariantCultureIgnoreCase)); var ai2 = _availableAIs!.First(a => string.Equals(a.Name, ai2Name, StringComparison.InvariantCultureIgnoreCase)); return TestCommandRunner.RunTestCommand(ai1, ai2, result.GetRequiredValue("--battles")); }); var rootCommand = new RootCommand("PkmnLib.NET AI Runner") { testCommand, }; rootCommand.Description = "A tool to run AI scripts against each other in Pokémon battles."; var parseResult = rootCommand.Parse(args); return parseResult.InvokeAsync(); static void ValidateAI(OptionResult result) { var aiName = result.GetValueOrDefault(); if (string.IsNullOrWhiteSpace(aiName)) { result.AddError("must be a non-empty string."); return; } var ai = _availableAIs!.FirstOrDefault(a => a.Name == aiName); if (ai == null) { result.AddError( $"AI '{aiName}' not found. Available AIs: {string.Join(", ", _availableAIs!.Select(a => a.Name))}"); } } } }