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 validOrders,
ref invalidOrders);
}
}