diff --git a/MultiversalDiplomacy/Adjudicate/Decision/AdjudicationDecision.cs b/MultiversalDiplomacy/Adjudicate/Decision/AdjudicationDecision.cs new file mode 100644 index 0000000..2e365e1 --- /dev/null +++ b/MultiversalDiplomacy/Adjudicate/Decision/AdjudicationDecision.cs @@ -0,0 +1,12 @@ +namespace MultiversalDiplomacy.Adjudicate.Decision; + +/// +/// 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 +/// +public abstract class AdjudicationDecision +{ + public abstract bool Resolved { get; } +} diff --git a/MultiversalDiplomacy/Adjudicate/Decision/AttackStrength.cs b/MultiversalDiplomacy/Adjudicate/Decision/AttackStrength.cs new file mode 100644 index 0000000..ca9dc9d --- /dev/null +++ b/MultiversalDiplomacy/Adjudicate/Decision/AttackStrength.cs @@ -0,0 +1,17 @@ +using MultiversalDiplomacy.Orders; + +namespace MultiversalDiplomacy.Adjudicate.Decision; + +public class AttackStrength : NumericAdjudicationDecision +{ + public MoveOrder Order { get; } + public List Supports { get; } + public MoveOrder? OpposingMove { get; } + + public AttackStrength(MoveOrder order, IEnumerable supports, MoveOrder? opposingMove = null) + { + this.Order = order; + this.Supports = supports.ToList(); + this.OpposingMove = opposingMove; + } +} diff --git a/MultiversalDiplomacy/Adjudicate/Decision/BinaryAdjudicationDecision.cs b/MultiversalDiplomacy/Adjudicate/Decision/BinaryAdjudicationDecision.cs new file mode 100644 index 0000000..65e6084 --- /dev/null +++ b/MultiversalDiplomacy/Adjudicate/Decision/BinaryAdjudicationDecision.cs @@ -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; + } +} diff --git a/MultiversalDiplomacy/Adjudicate/Decision/DefendStrength.cs b/MultiversalDiplomacy/Adjudicate/Decision/DefendStrength.cs new file mode 100644 index 0000000..b51532f --- /dev/null +++ b/MultiversalDiplomacy/Adjudicate/Decision/DefendStrength.cs @@ -0,0 +1,15 @@ +using MultiversalDiplomacy.Orders; + +namespace MultiversalDiplomacy.Adjudicate.Decision; + +public class DefendStrength : NumericAdjudicationDecision +{ + public MoveOrder Order { get; } + public List Supports { get; } + + public DefendStrength(MoveOrder order, IEnumerable supports) + { + this.Order = order; + this.Supports = supports.ToList(); + } +} diff --git a/MultiversalDiplomacy/Adjudicate/Decision/DoesMove.cs b/MultiversalDiplomacy/Adjudicate/Decision/DoesMove.cs new file mode 100644 index 0000000..c093871 --- /dev/null +++ b/MultiversalDiplomacy/Adjudicate/Decision/DoesMove.cs @@ -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 Competing { get; } + + public DoesMove(MoveOrder order, MoveOrder? opposingMove, IEnumerable competing) + { + this.Order = order; + this.OpposingMove = opposingMove; + this.Competing = competing.ToList(); + } +} diff --git a/MultiversalDiplomacy/Adjudicate/Decision/GivesSupport.cs b/MultiversalDiplomacy/Adjudicate/Decision/GivesSupport.cs new file mode 100644 index 0000000..d0095f5 --- /dev/null +++ b/MultiversalDiplomacy/Adjudicate/Decision/GivesSupport.cs @@ -0,0 +1,15 @@ +using MultiversalDiplomacy.Orders; + +namespace MultiversalDiplomacy.Adjudicate.Decision; + +public class GivesSupport : BinaryAdjudicationDecision +{ + public SupportOrder Order { get; } + public List Cuts { get; } + + public GivesSupport(SupportOrder order, IEnumerable cuts) + { + this.Order = order; + this.Cuts = cuts.ToList(); + } +} diff --git a/MultiversalDiplomacy/Adjudicate/Decision/HasPath.cs b/MultiversalDiplomacy/Adjudicate/Decision/HasPath.cs new file mode 100644 index 0000000..71f49fe --- /dev/null +++ b/MultiversalDiplomacy/Adjudicate/Decision/HasPath.cs @@ -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; + } +} diff --git a/MultiversalDiplomacy/Adjudicate/Decision/HoldStrength.cs b/MultiversalDiplomacy/Adjudicate/Decision/HoldStrength.cs new file mode 100644 index 0000000..35d1d46 --- /dev/null +++ b/MultiversalDiplomacy/Adjudicate/Decision/HoldStrength.cs @@ -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 Supports { get; } + + public HoldStrength(Province province, UnitOrder? order = null) + { + this.Province = province; + this.Order = order; + this.Supports = new(); + } +} diff --git a/MultiversalDiplomacy/Adjudicate/Decision/IsDislodged.cs b/MultiversalDiplomacy/Adjudicate/Decision/IsDislodged.cs new file mode 100644 index 0000000..f5cdf62 --- /dev/null +++ b/MultiversalDiplomacy/Adjudicate/Decision/IsDislodged.cs @@ -0,0 +1,15 @@ +using MultiversalDiplomacy.Orders; + +namespace MultiversalDiplomacy.Adjudicate.Decision; + +public class IsDislodged : BinaryAdjudicationDecision +{ + public UnitOrder Order { get; } + public List Incoming { get; } + + public IsDislodged(UnitOrder order, IEnumerable incoming) + { + this.Order = order; + this.Incoming = incoming.ToList(); + } +} diff --git a/MultiversalDiplomacy/Adjudicate/Decision/NumericAdjudicationDecision.cs b/MultiversalDiplomacy/Adjudicate/Decision/NumericAdjudicationDecision.cs new file mode 100644 index 0000000..05e0681 --- /dev/null +++ b/MultiversalDiplomacy/Adjudicate/Decision/NumericAdjudicationDecision.cs @@ -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; + } +} diff --git a/MultiversalDiplomacy/Adjudicate/Decision/PreventStrength.cs b/MultiversalDiplomacy/Adjudicate/Decision/PreventStrength.cs new file mode 100644 index 0000000..4a5ed2e --- /dev/null +++ b/MultiversalDiplomacy/Adjudicate/Decision/PreventStrength.cs @@ -0,0 +1,17 @@ +using MultiversalDiplomacy.Orders; + +namespace MultiversalDiplomacy.Adjudicate.Decision; + +public class PreventStrength : NumericAdjudicationDecision +{ + public MoveOrder Order { get; } + public List Supports { get; } + public MoveOrder? OpposingMove { get; } + + public PreventStrength(MoveOrder order, IEnumerable supports, MoveOrder? opposingMove = null) + { + this.Order = order; + this.Supports = supports.ToList(); + this.OpposingMove = opposingMove; + } +} diff --git a/MultiversalDiplomacy/Adjudicate/MovementPhaseAdjudicator.cs b/MultiversalDiplomacy/Adjudicate/MovementPhaseAdjudicator.cs index 4d5411a..0799d0a 100644 --- a/MultiversalDiplomacy/Adjudicate/MovementPhaseAdjudicator.cs +++ b/MultiversalDiplomacy/Adjudicate/MovementPhaseAdjudicator.cs @@ -1,3 +1,4 @@ +using MultiversalDiplomacy.Adjudicate.Decision; using MultiversalDiplomacy.Model; using MultiversalDiplomacy.Orders; @@ -8,165 +9,6 @@ namespace MultiversalDiplomacy.Adjudicate; /// public class MovementPhaseAdjudicator : IPhaseAdjudicator { - /// - /// 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 - /// - 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 Incoming { get; } - - public IsDislodged(UnitOrder order, IEnumerable 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 Cuts { get; } - - public GivesSupport(SupportOrder order, IEnumerable cuts) - { - this.Order = order; - this.Cuts = cuts.ToList(); - } - } - - private class HoldStrength : NumericAdjudicationDecision - { - public Province Province { get; } - public UnitOrder? Order { get; } - public List 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 Supports { get; } - public MoveOrder? OpposingMove { get; } - - public AttackStrength(MoveOrder order, IEnumerable supports, MoveOrder? opposingMove = null) - { - this.Order = order; - this.Supports = supports.ToList(); - this.OpposingMove = opposingMove; - } - } - - private class DefendStrength : NumericAdjudicationDecision - { - public MoveOrder Order { get; } - public List Supports { get; } - - public DefendStrength(MoveOrder order, IEnumerable supports) - { - this.Order = order; - this.Supports = supports.ToList(); - } - } - - private class PreventStrength : NumericAdjudicationDecision - { - public MoveOrder Order { get; } - public List Supports { get; } - public MoveOrder? OpposingMove { get; } - - public PreventStrength(MoveOrder order, IEnumerable 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 Competing { get; } - - public DoesMove(MoveOrder order, MoveOrder? opposingMove, IEnumerable competing) - { - this.Order = order; - this.OpposingMove = opposingMove; - this.Competing = competing.ToList(); - } - } - private class Decisions { public Dictionary IsDislodged { get; }