5dplomacy/MultiversalDiplomacy/Script/GameScriptHandler.cs

100 lines
3.6 KiB
C#
Raw Normal View History

using System.Text.RegularExpressions;
2024-08-28 14:41:23 +00:00
using MultiversalDiplomacy.Adjudicate;
2024-08-18 04:24:59 +00:00
using MultiversalDiplomacy.Model;
using MultiversalDiplomacy.Orders;
2024-08-18 04:24:59 +00:00
namespace MultiversalDiplomacy.Script;
public class GameScriptHandler(
Action<string> WriteLine,
World world,
IPhaseAdjudicator adjudicator,
bool strict = false)
: IScriptHandler
2024-08-18 04:24:59 +00:00
{
public string Prompt => "orders> ";
2024-08-18 04:24:59 +00:00
public World World { get; private set; } = world;
/// <summary>
/// Whether unsuccessful commands should terminate the script.
/// </summary>
public bool Strict { get; } = strict;
private string? CurrentPower { get; set; } = null;
public List<Order> Orders { get; } = [];
2024-08-18 04:24:59 +00:00
public IScriptHandler? HandleInput(string input)
{
if (input == "") {
CurrentPower = null;
return this;
}
2024-08-21 16:47:13 +00:00
if (input.StartsWith('#')) return this;
2024-08-18 04:24:59 +00:00
// "---" submits the orders and allows queries about the outcome
2024-08-18 04:24:59 +00:00
if (input == "---") {
2024-08-28 21:10:41 +00:00
WriteLine("Submitting orders for adjudication");
2024-08-28 14:41:23 +00:00
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);
2024-09-01 04:54:28 +00:00
return new AdjudicationQueryScriptHandler(WriteLine, validation, newWorld, adjudicator, Strict);
}
// "===" submits the orders and moves immediately to taking the next set of orders
// i.e. it's "---" twice
if (input == "===") {
2024-08-28 21:10:41 +00:00
WriteLine("Submitting orders for adjudication");
2024-08-28 14:41:23 +00:00
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);
2024-08-28 21:10:41 +00:00
WriteLine("Ready for orders");
2024-08-28 14:41:23 +00:00
return this;
2024-08-18 04:24:59 +00:00
}
// 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 this;
}
2024-08-25 04:26:10 +00:00
// 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) {
2024-08-28 21:10:41 +00:00
WriteLine($"Could not determine ordering power in \"{input}\"");
2024-08-25 04:26:10 +00:00
return Strict ? null : this;
}
orderPower = match.Groups[1].Value;
orderText = match.Groups[2].Value;
}
2024-08-18 04:24:59 +00:00
2024-08-27 03:23:28 +00:00
if (OrderParser.TryParseOrder(World, orderPower, orderText, out Order? order)) {
2024-08-28 21:10:41 +00:00
WriteLine($"Parsed {orderPower} order: {order}");
Orders.Add(order);
2024-08-26 15:39:42 +00:00
return this;
}
2024-08-28 21:10:41 +00:00
WriteLine($"Failed to parse \"{orderText}\"");
2024-08-25 04:26:10 +00:00
return Strict ? null : this;
}
2024-08-18 04:24:59 +00:00
}