using MultiversalDiplomacy.Orders; namespace MultiversalDiplomacy.Adjudicate; /// /// Helper class for common operations shared between adjudicators. /// internal static class AdjudicatorHelpers { /// /// Invalidate all orders that do not match a predicate. /// /// A predicate that invalid orders will fail to match. /// The reason to be given for order invalidation. /// The set of orders to check. /// The list of orders that passed the predicate. /// /// A list of order validation results. Orders invalidated by the predicate will be appended /// to this list. /// public static void InvalidateIfNotMatching( Func predicate, ValidationReason reason, ref List orders, ref List invalidOrders) where OrderType : Order { ILookup results = orders.ToLookup(predicate); invalidOrders = invalidOrders .Concat(results[false].Select(order => order.Invalidate(reason))) .ToList(); orders = results[true].ToList(); } /// /// Invalidate all orders that are not of an allowed order type. /// /// The set of orders to check. /// A list of types that are allowed. /// The list of orders of allowed types. /// /// A list of order validation results. Orders of invalid types will be appended to this list. /// public static void InvalidateWrongTypes( List validOrderTypes, ref List orders, ref List invalidOrders) { List nonOrderTypes = validOrderTypes .Where(t => !t.IsSubclassOf(typeof(Order))) .ToList(); if (nonOrderTypes.Any()) { throw new ArgumentException( $"Unknown order type: {nonOrderTypes.Select(t => t.FullName).First()}"); } InvalidateIfNotMatching( order => validOrderTypes.Contains(order.GetType()), ValidationReason.InvalidOrderTypeForPhase, ref orders, ref invalidOrders); } /// /// Invalidate all orders for units not owned by the ordering power. /// /// The set of orders to check. /// The list of orders with valid targets. /// /// A list of order validation results. Orders by the wrong powers will be appended to this list. /// public static void InvalidateWrongPower( List orders, ref List validOrders, ref List invalidOrders) { InvalidateIfNotMatching( order => order switch { ConvoyOrder convoy => convoy.Power == convoy.Unit.Power, DisbandOrder disband => disband.Power == disband.Unit.Power, HoldOrder hold => hold.Power == hold.Unit.Power, MoveOrder move => move.Power == move.Unit.Power, RetreatOrder retreat => retreat.Power == retreat.Unit.Power, SupportHoldOrder support => support.Power == support.Unit.Power, SupportMoveOrder support => support.Power == support.Unit.Power, // Any order not given to a unit, by definition, cannot be given to a unit of the // wrong power _ => true, }, ValidationReason.InvalidUnitForPower, ref orders, ref invalidOrders); } }