Move decision classes out of the movement adjudicator

This commit is contained in:
Jaculabilis 2022-03-24 09:22:13 -07:00
parent d2ec79647a
commit 36ea621782
12 changed files with 188 additions and 159 deletions

View File

@ -0,0 +1,12 @@
namespace MultiversalDiplomacy.Adjudicate.Decision;
/// <summary>
/// Base class for adjudication decisions. The decision-based adjudication algorithm is based
/// on DATC section 5 and "The Math of Adjudication" by Lucas Kruijswijk, respectively found at
/// http://web.inter.nl.net/users/L.B.Kruijswijk/#5 and
/// http://uk.diplom.org/pouch/Zine/S2009M/Kruijswijk/DipMath_Chp1.htm
/// </summary>
public abstract class AdjudicationDecision
{
public abstract bool Resolved { get; }
}

View File

@ -0,0 +1,17 @@
using MultiversalDiplomacy.Orders;
namespace MultiversalDiplomacy.Adjudicate.Decision;
public class AttackStrength : NumericAdjudicationDecision
{
public MoveOrder Order { get; }
public List<SupportMoveOrder> Supports { get; }
public MoveOrder? OpposingMove { get; }
public AttackStrength(MoveOrder order, IEnumerable<SupportMoveOrder> supports, MoveOrder? opposingMove = null)
{
this.Order = order;
this.Supports = supports.ToList();
this.OpposingMove = opposingMove;
}
}

View File

@ -0,0 +1,24 @@
namespace MultiversalDiplomacy.Adjudicate.Decision;
public abstract class BinaryAdjudicationDecision : AdjudicationDecision
{
public bool? Outcome { get; private set; } = null;
public override bool Resolved => this.Outcome != null;
public bool Update(bool outcome)
{
if (this.Outcome == null)
{
this.Outcome = outcome;
return true;
}
if (this.Outcome != outcome)
{
string name = this.GetType().Name;
throw new ArgumentException(
$"Cannot reverse adjudication of {name} from {this.Outcome} to {outcome}");
}
return false;
}
}

View File

@ -0,0 +1,15 @@
using MultiversalDiplomacy.Orders;
namespace MultiversalDiplomacy.Adjudicate.Decision;
public class DefendStrength : NumericAdjudicationDecision
{
public MoveOrder Order { get; }
public List<SupportMoveOrder> Supports { get; }
public DefendStrength(MoveOrder order, IEnumerable<SupportMoveOrder> supports)
{
this.Order = order;
this.Supports = supports.ToList();
}
}

View File

@ -0,0 +1,17 @@
using MultiversalDiplomacy.Orders;
namespace MultiversalDiplomacy.Adjudicate.Decision;
public class DoesMove : BinaryAdjudicationDecision
{
public MoveOrder Order { get; }
public MoveOrder? OpposingMove { get; }
public List<MoveOrder> Competing { get; }
public DoesMove(MoveOrder order, MoveOrder? opposingMove, IEnumerable<MoveOrder> competing)
{
this.Order = order;
this.OpposingMove = opposingMove;
this.Competing = competing.ToList();
}
}

View File

@ -0,0 +1,15 @@
using MultiversalDiplomacy.Orders;
namespace MultiversalDiplomacy.Adjudicate.Decision;
public class GivesSupport : BinaryAdjudicationDecision
{
public SupportOrder Order { get; }
public List<MoveOrder> Cuts { get; }
public GivesSupport(SupportOrder order, IEnumerable<MoveOrder> cuts)
{
this.Order = order;
this.Cuts = cuts.ToList();
}
}

View File

@ -0,0 +1,13 @@
using MultiversalDiplomacy.Orders;
namespace MultiversalDiplomacy.Adjudicate.Decision;
public class HasPath : BinaryAdjudicationDecision
{
public MoveOrder Order { get; }
public HasPath(MoveOrder order)
{
this.Order = order;
}
}

View File

@ -0,0 +1,18 @@
using MultiversalDiplomacy.Model;
using MultiversalDiplomacy.Orders;
namespace MultiversalDiplomacy.Adjudicate.Decision;
public class HoldStrength : NumericAdjudicationDecision
{
public Province Province { get; }
public UnitOrder? Order { get; }
public List<SupportHoldOrder> Supports { get; }
public HoldStrength(Province province, UnitOrder? order = null)
{
this.Province = province;
this.Order = order;
this.Supports = new();
}
}

View File

@ -0,0 +1,15 @@
using MultiversalDiplomacy.Orders;
namespace MultiversalDiplomacy.Adjudicate.Decision;
public class IsDislodged : BinaryAdjudicationDecision
{
public UnitOrder Order { get; }
public List<MoveOrder> Incoming { get; }
public IsDislodged(UnitOrder order, IEnumerable<MoveOrder> incoming)
{
this.Order = order;
this.Incoming = incoming.ToList();
}
}

View File

@ -0,0 +1,24 @@
namespace MultiversalDiplomacy.Adjudicate.Decision;
public abstract class NumericAdjudicationDecision : AdjudicationDecision
{
public int MinValue { get; private set; } = 0;
public int MaxValue { get; private set; } = 99;
public override bool Resolved => this.MinValue == this.MaxValue;
public bool Update(int min, int max)
{
if (min < this.MinValue || max > this.MaxValue)
{
string name = this.GetType().Name;
throw new ArgumentException(
$"Cannot reverse adjudication of {name} from ({this.MinValue},{this.MaxValue})"
+ $" to ({min},{max})");
}
bool updated = this.MinValue != min || this.MaxValue != max;
this.MinValue = min;
this.MaxValue = max;
return updated;
}
}

View File

@ -0,0 +1,17 @@
using MultiversalDiplomacy.Orders;
namespace MultiversalDiplomacy.Adjudicate.Decision;
public class PreventStrength : NumericAdjudicationDecision
{
public MoveOrder Order { get; }
public List<SupportMoveOrder> Supports { get; }
public MoveOrder? OpposingMove { get; }
public PreventStrength(MoveOrder order, IEnumerable<SupportMoveOrder> supports, MoveOrder? opposingMove = null)
{
this.Order = order;
this.Supports = supports.ToList();
this.OpposingMove = opposingMove;
}
}

View File

@ -1,3 +1,4 @@
using MultiversalDiplomacy.Adjudicate.Decision;
using MultiversalDiplomacy.Model;
using MultiversalDiplomacy.Orders;
@ -8,165 +9,6 @@ namespace MultiversalDiplomacy.Adjudicate;
/// </summary>
public class MovementPhaseAdjudicator : IPhaseAdjudicator
{
/// <summary>
/// Base class for adjudication decisions. The decision-based adjudication algorithm is based
/// on DATC section 5 and "The Math of Adjudication" by Lucas Kruijswijk, respectively found at
/// http://web.inter.nl.net/users/L.B.Kruijswijk/#5 and
/// http://uk.diplom.org/pouch/Zine/S2009M/Kruijswijk/DipMath_Chp1.htm
/// </summary>
private abstract class AdjudicationDecision
{
public abstract bool Resolved { get; }
}
private abstract class BinaryAdjudicationDecision : AdjudicationDecision
{
public bool? Outcome { get; private set; } = null;
public override bool Resolved => this.Outcome != null;
public bool Update(bool outcome)
{
if (this.Outcome == null)
{
this.Outcome = outcome;
return true;
}
if (this.Outcome != outcome)
{
string name = this.GetType().Name;
throw new ArgumentException(
$"Cannot reverse adjudication of {name} from {this.Outcome} to {outcome}");
}
return false;
}
}
private abstract class NumericAdjudicationDecision : AdjudicationDecision
{
public int MinValue { get; private set; } = 0;
public int MaxValue { get; private set; } = 99;
public override bool Resolved => this.MinValue == this.MaxValue;
public bool Update(int min, int max)
{
if (min < this.MinValue || max > this.MaxValue)
{
string name = this.GetType().Name;
throw new ArgumentException(
$"Cannot reverse adjudication of {name} from ({this.MinValue},{this.MaxValue})"
+ $" to ({min},{max})");
}
bool updated = this.MinValue != min || this.MaxValue != max;
this.MinValue = min;
this.MaxValue = max;
return updated;
}
}
private class IsDislodged : BinaryAdjudicationDecision
{
public UnitOrder Order { get; }
public List<MoveOrder> Incoming { get; }
public IsDislodged(UnitOrder order, IEnumerable<MoveOrder> incoming)
{
this.Order = order;
this.Incoming = incoming.ToList();
}
}
private class HasPath : BinaryAdjudicationDecision
{
public MoveOrder Order { get; }
public HasPath(MoveOrder order)
{
this.Order = order;
}
}
private class GivesSupport : BinaryAdjudicationDecision
{
public SupportOrder Order { get; }
public List<MoveOrder> Cuts { get; }
public GivesSupport(SupportOrder order, IEnumerable<MoveOrder> cuts)
{
this.Order = order;
this.Cuts = cuts.ToList();
}
}
private class HoldStrength : NumericAdjudicationDecision
{
public Province Province { get; }
public UnitOrder? Order { get; }
public List<SupportHoldOrder> Supports { get; }
public HoldStrength(Province province, UnitOrder? order = null)
{
this.Province = province;
this.Order = order;
this.Supports = new();
}
}
private class AttackStrength : NumericAdjudicationDecision
{
public MoveOrder Order { get; }
public List<SupportMoveOrder> Supports { get; }
public MoveOrder? OpposingMove { get; }
public AttackStrength(MoveOrder order, IEnumerable<SupportMoveOrder> supports, MoveOrder? opposingMove = null)
{
this.Order = order;
this.Supports = supports.ToList();
this.OpposingMove = opposingMove;
}
}
private class DefendStrength : NumericAdjudicationDecision
{
public MoveOrder Order { get; }
public List<SupportMoveOrder> Supports { get; }
public DefendStrength(MoveOrder order, IEnumerable<SupportMoveOrder> supports)
{
this.Order = order;
this.Supports = supports.ToList();
}
}
private class PreventStrength : NumericAdjudicationDecision
{
public MoveOrder Order { get; }
public List<SupportMoveOrder> Supports { get; }
public MoveOrder? OpposingMove { get; }
public PreventStrength(MoveOrder order, IEnumerable<SupportMoveOrder> supports, MoveOrder? opposingMove = null)
{
this.Order = order;
this.Supports = supports.ToList();
this.OpposingMove = opposingMove;
}
}
private class DoesMove : BinaryAdjudicationDecision
{
public MoveOrder Order { get; }
public MoveOrder? OpposingMove { get; }
public List<MoveOrder> Competing { get; }
public DoesMove(MoveOrder order, MoveOrder? opposingMove, IEnumerable<MoveOrder> competing)
{
this.Order = order;
this.OpposingMove = opposingMove;
this.Competing = competing.ToList();
}
}
private class Decisions
{
public Dictionary<Unit, IsDislodged> IsDislodged { get; }