using System.Text.RegularExpressions; using MultiversalDiplomacy.Adjudicate; using MultiversalDiplomacy.Model; using MultiversalDiplomacy.Orders; namespace MultiversalDiplomacy.Script; public class GameScriptHandler( Action WriteLine, World world, IPhaseAdjudicator adjudicator) : IScriptHandler { public string Prompt => "orders> "; public World World { get; private set; } = world; private string? CurrentPower { get; set; } = null; public List Orders { get; } = []; public ScriptResult HandleInput(string input) { if (input == "") { CurrentPower = null; return ScriptResult.Succeed(this); } if (input.StartsWith('#')) return ScriptResult.Succeed(this); // "---" submits the orders and allows queries about the outcome if (input == "---") { WriteLine("Submitting orders for adjudication"); var validation = adjudicator.ValidateOrders(World, Orders); var validOrders = validation .Where(v => v.Valid) .Select(v => v.Order) .ToList(); var adjudication = adjudicator.AdjudicateOrders(World, validOrders); var newWorld = adjudicator.UpdateWorld(World, adjudication); return ScriptResult.Succeed(new AdjudicationQueryScriptHandler( WriteLine, validation, adjudication, newWorld, adjudicator)); } // "===" submits the orders and moves immediately to taking the next set of orders // i.e. it's "---" twice if (input == "===") { WriteLine("Submitting orders for adjudication"); var validation = adjudicator.ValidateOrders(World, Orders); var validOrders = validation .Where(v => v.Valid) .Select(v => v.Order) .ToList(); var adjudication = adjudicator.AdjudicateOrders(World, validOrders); World = adjudicator.UpdateWorld(World, adjudication); WriteLine("Ready for orders"); return ScriptResult.Succeed(this); } // A block of orders for a single power beginning with "{name}:" if (World.Powers.FirstOrDefault(p => input.EqualsAnyCase($"{p}:"), null) is string power) { CurrentPower = power; return ScriptResult.Succeed(this); } // If it's not a comment, submit, or order block, assume it's an order. string orderPower; string orderText; if (CurrentPower is not null) { // In a block of orders from a power, the power was specified at the top and each line is an order. orderPower = CurrentPower; orderText = input; } else { // Outside a power block, the power is prefixed to each order. Regex re = new($"^{World.Map.PowerRegex}(?:[:])? (.*)$", RegexOptions.IgnoreCase); var match = re.Match(input); if (!match.Success) return ScriptResult.Fail($"Could not determine ordering power in \"{input}\"", this); orderPower = match.Groups[1].Value; orderText = match.Groups[2].Value; } if (OrderParser.TryParseOrder(World, orderPower, orderText, out Order? order)) { WriteLine($"Parsed {orderPower} order: {order}"); Orders.Add(order); return ScriptResult.Succeed(this); } return ScriptResult.Fail($"Failed to parse \"{orderText}\"", this); } }