Add depth tracking to decision resolution

This commit is contained in:
Jaculabilis 2022-11-06 21:51:45 -08:00
parent 23a826c815
commit c0a9330d2e
1 changed files with 53 additions and 36 deletions

View File

@ -286,7 +286,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
foreach (AdjudicationDecision decision in decisions.Values) foreach (AdjudicationDecision decision in decisions.Values)
{ {
// This will noop without progress if the decision is already resolved // This will noop without progress if the decision is already resolved
progress |= ResolveDecision(decision, world, decisions); progress |= ResolveDecision(decision, world, decisions, depth: 0);
} }
} while (progress); } while (progress);
@ -384,27 +384,37 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
return updated; return updated;
} }
/// <summary>
/// Attempt to resolve an adjudication decision.
/// </summary>
/// <returns>
/// If any adjudication was further determined, returns true. If nothing was further determined, returns false.
/// </returns>
private bool ResolveDecision( private bool ResolveDecision(
AdjudicationDecision decision, AdjudicationDecision decision,
World world, World world,
MovementDecisions decisions) MovementDecisions decisions,
=> decision.Resolved ? false : decision switch int depth)
{ {
IsDislodged d => ResolveIsUnitDislodged(d, world, decisions), return decision.Resolved ? false : decision switch
HasPath d => ResolveDoesMoveHavePath(d, world, decisions), {
GivesSupport d => ResolveIsSupportGiven(d, world, decisions), IsDislodged d => ResolveIsUnitDislodged(d, world, decisions, depth + 1),
HoldStrength d => ResolveHoldStrength(d, world, decisions), HasPath d => ResolveDoesMoveHavePath(d, world, decisions, depth + 1),
AttackStrength d => ResolveAttackStrength(d, world, decisions), GivesSupport d => ResolveIsSupportGiven(d, world, decisions, depth + 1),
DefendStrength d => ResolveDefendStrength(d, world, decisions), HoldStrength d => ResolveHoldStrength(d, world, decisions, depth + 1),
PreventStrength d => ResolvePreventStrength(d, world, decisions), AttackStrength d => ResolveAttackStrength(d, world, decisions, depth + 1),
DoesMove d => ResolveDoesUnitMove(d, world, decisions), DefendStrength d => ResolveDefendStrength(d, world, decisions, depth + 1),
PreventStrength d => ResolvePreventStrength(d, world, decisions, depth + 1),
DoesMove d => ResolveDoesUnitMove(d, world, decisions, depth + 1),
_ => throw new NotSupportedException($"Unknown decision type: {decision.GetType()}") _ => throw new NotSupportedException($"Unknown decision type: {decision.GetType()}")
}; };
}
private bool ResolveIsUnitDislodged( private bool ResolveIsUnitDislodged(
IsDislodged decision, IsDislodged decision,
World world, World world,
MovementDecisions decisions) MovementDecisions decisions,
int depth)
{ {
bool progress = false; bool progress = false;
@ -413,7 +423,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
if (decision.Order is MoveOrder moveOrder) if (decision.Order is MoveOrder moveOrder)
{ {
DoesMove move = decisions.DoesMove[moveOrder]; DoesMove move = decisions.DoesMove[moveOrder];
progress |= ResolveDecision(move, world, decisions); progress |= ResolveDecision(move, world, decisions, depth + 1);
// If this unit received a move order and the move is successful, it cannot be // If this unit received a move order and the move is successful, it cannot be
// dislodged. // dislodged.
@ -437,7 +447,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
foreach (MoveOrder dislodger in decision.Incoming) foreach (MoveOrder dislodger in decision.Incoming)
{ {
DoesMove move = decisions.DoesMove[dislodger]; DoesMove move = decisions.DoesMove[dislodger];
progress |= ResolveDecision(move, world, decisions); progress |= ResolveDecision(move, world, decisions, depth + 1);
// If at least one invader will move, this unit is dislodged. // If at least one invader will move, this unit is dislodged.
if (move.Outcome == true) if (move.Outcome == true)
@ -465,7 +475,8 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
private bool ResolveDoesMoveHavePath( private bool ResolveDoesMoveHavePath(
HasPath decision, HasPath decision,
World world, World world,
MovementDecisions decisions) MovementDecisions decisions,
int depth)
{ {
bool progress= false; bool progress= false;
@ -494,7 +505,8 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
private bool ResolveIsSupportGiven( private bool ResolveIsSupportGiven(
GivesSupport decision, GivesSupport decision,
World world, World world,
MovementDecisions decisions) MovementDecisions decisions,
int depth)
{ {
bool progress = false; bool progress = false;
@ -504,7 +516,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
foreach (MoveOrder cut in decision.Cuts) foreach (MoveOrder cut in decision.Cuts)
{ {
AttackStrength attack = decisions.AttackStrength[cut]; AttackStrength attack = decisions.AttackStrength[cut];
progress |= ResolveDecision(attack, world, decisions); progress |= ResolveDecision(attack, world, decisions, depth + 1);
// If at least one attack has a nonzero minimum, the support decision can be resolved // If at least one attack has a nonzero minimum, the support decision can be resolved
// to false. // to false.
@ -524,7 +536,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
// Support is also cut if the unit is dislodged. // Support is also cut if the unit is dislodged.
IsDislodged dislodge = decisions.IsDislodged[decision.Order.Unit]; IsDislodged dislodge = decisions.IsDislodged[decision.Order.Unit];
progress |= ResolveDecision(dislodge, world, decisions); progress |= ResolveDecision(dislodge, world, decisions, depth + 1);
if (dislodge.Outcome == true) if (dislodge.Outcome == true)
{ {
progress |= decision.Update(false); progress |= decision.Update(false);
@ -546,7 +558,8 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
private bool ResolveHoldStrength( private bool ResolveHoldStrength(
HoldStrength decision, HoldStrength decision,
World world, World world,
MovementDecisions decisions) MovementDecisions decisions,
int depth)
{ {
bool progress = false; bool progress = false;
@ -561,7 +574,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
if (decision.Order is MoveOrder move) if (decision.Order is MoveOrder move)
{ {
DoesMove moves = decisions.DoesMove[move]; DoesMove moves = decisions.DoesMove[move];
progress |= ResolveDecision(moves, world, decisions); progress |= ResolveDecision(moves, world, decisions, depth + 1);
progress |= decision.Update( progress |= decision.Update(
moves.Outcome != false ? 0 : 1, moves.Outcome != false ? 0 : 1,
moves.Outcome == true ? 0 : 1); moves.Outcome == true ? 0 : 1);
@ -575,7 +588,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
foreach (SupportHoldOrder support in decision.Supports) foreach (SupportHoldOrder support in decision.Supports)
{ {
GivesSupport givesSupport = decisions.GivesSupport[support]; GivesSupport givesSupport = decisions.GivesSupport[support];
progress |= ResolveDecision(givesSupport, world, decisions); progress |= ResolveDecision(givesSupport, world, decisions, depth + 1);
if (givesSupport.Outcome == true) min += 1; if (givesSupport.Outcome == true) min += 1;
if (givesSupport.Outcome != false) max += 1; if (givesSupport.Outcome != false) max += 1;
} }
@ -587,13 +600,14 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
private bool ResolveAttackStrength( private bool ResolveAttackStrength(
AttackStrength decision, AttackStrength decision,
World world, World world,
MovementDecisions decisions) MovementDecisions decisions,
int depth)
{ {
bool progress = false; bool progress = false;
// If there is no path, the attack strength is zero. // If there is no path, the attack strength is zero.
var hasPath = decisions.HasPath[decision.Order]; var hasPath = decisions.HasPath[decision.Order];
progress |= ResolveDecision(hasPath, world, decisions); progress |= ResolveDecision(hasPath, world, decisions, depth + 1);
if (hasPath.Outcome == false) if (hasPath.Outcome == false)
{ {
progress |= decision.Update(0, 0); progress |= decision.Update(0, 0);
@ -609,7 +623,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
: null; : null;
if (destMoveAway != null) if (destMoveAway != null)
{ {
progress |= ResolveDecision(destMoveAway, world, decisions); progress |= ResolveDecision(destMoveAway, world, decisions, depth + 1);
} }
if (// In any case here, there will have to be a unit at the destination with an order, if (// In any case here, there will have to be a unit at the destination with an order,
// which means that destOrder will have to be populated. Including this in the if // which means that destOrder will have to be populated. Including this in the if
@ -638,7 +652,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
{ {
if (support.Unit.Power == destPower) continue; if (support.Unit.Power == destPower) continue;
GivesSupport givesSupport = decisions.GivesSupport[support]; GivesSupport givesSupport = decisions.GivesSupport[support];
progress |= ResolveDecision(givesSupport, world, decisions); progress |= ResolveDecision(givesSupport, world, decisions, depth + 1);
if (givesSupport.Outcome == true) min += 1; if (givesSupport.Outcome == true) min += 1;
if (givesSupport.Outcome != false) max += 1; if (givesSupport.Outcome != false) max += 1;
} }
@ -658,7 +672,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
foreach (SupportMoveOrder support in decision.Supports) foreach (SupportMoveOrder support in decision.Supports)
{ {
GivesSupport givesSupport = decisions.GivesSupport[support]; GivesSupport givesSupport = decisions.GivesSupport[support];
progress |= ResolveDecision(givesSupport, world, decisions); progress |= ResolveDecision(givesSupport, world, decisions, depth + 1);
if (support.Unit.Power != destPower && givesSupport.Outcome == true) min += 1; if (support.Unit.Power != destPower && givesSupport.Outcome == true) min += 1;
if (givesSupport.Outcome != false) max += 1; if (givesSupport.Outcome != false) max += 1;
} }
@ -676,7 +690,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
foreach (SupportMoveOrder support in decision.Supports) foreach (SupportMoveOrder support in decision.Supports)
{ {
GivesSupport givesSupport = decisions.GivesSupport[support]; GivesSupport givesSupport = decisions.GivesSupport[support];
progress |= ResolveDecision(givesSupport, world, decisions); progress |= ResolveDecision(givesSupport, world, decisions, depth + 1);
if (givesSupport.Outcome == true) min += 1; if (givesSupport.Outcome == true) min += 1;
if (givesSupport.Outcome != false) max += 1; if (givesSupport.Outcome != false) max += 1;
} }
@ -688,7 +702,8 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
private bool ResolveDefendStrength( private bool ResolveDefendStrength(
DefendStrength decision, DefendStrength decision,
World world, World world,
MovementDecisions decisions) MovementDecisions decisions,
int depth)
{ {
bool progress = false; bool progress = false;
@ -699,7 +714,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
foreach (SupportMoveOrder support in decision.Supports) foreach (SupportMoveOrder support in decision.Supports)
{ {
GivesSupport givesSupport = decisions.GivesSupport[support]; GivesSupport givesSupport = decisions.GivesSupport[support];
progress |= ResolveDecision(givesSupport, world, decisions); progress |= ResolveDecision(givesSupport, world, decisions, depth + 1);
if (givesSupport.Outcome == true) min += 1; if (givesSupport.Outcome == true) min += 1;
if (givesSupport.Outcome != false) max += 1; if (givesSupport.Outcome != false) max += 1;
} }
@ -711,13 +726,14 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
private bool ResolvePreventStrength( private bool ResolvePreventStrength(
PreventStrength decision, PreventStrength decision,
World world, World world,
MovementDecisions decisions) MovementDecisions decisions,
int depth)
{ {
bool progress = false; bool progress = false;
// If there is no path, the prevent strength is zero. // If there is no path, the prevent strength is zero.
var hasPath = decisions.HasPath[decision.Order]; var hasPath = decisions.HasPath[decision.Order];
progress |= ResolveDecision(hasPath, world, decisions); progress |= ResolveDecision(hasPath, world, decisions, depth + 1);
if (hasPath.Outcome == false) if (hasPath.Outcome == false)
{ {
progress |= decision.Update(0, 0); progress |= decision.Update(0, 0);
@ -741,7 +757,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
foreach (SupportMoveOrder support in decision.Supports) foreach (SupportMoveOrder support in decision.Supports)
{ {
GivesSupport givesSupport = decisions.GivesSupport[support]; GivesSupport givesSupport = decisions.GivesSupport[support];
progress |= ResolveDecision(givesSupport, world, decisions); progress |= ResolveDecision(givesSupport, world, decisions, depth + 1);
if (givesSupport.Outcome == true) min += 1; if (givesSupport.Outcome == true) min += 1;
if (givesSupport.Outcome != false) max += 1; if (givesSupport.Outcome != false) max += 1;
} }
@ -763,13 +779,14 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
private bool ResolveDoesUnitMove( private bool ResolveDoesUnitMove(
DoesMove decision, DoesMove decision,
World world, World world,
MovementDecisions decisions) MovementDecisions decisions,
int depth)
{ {
bool progress = false; bool progress = false;
// Resolve the move's attack strength. // Resolve the move's attack strength.
AttackStrength attack = decisions.AttackStrength[decision.Order]; AttackStrength attack = decisions.AttackStrength[decision.Order];
progress |= ResolveDecision(attack, world, decisions); progress |= ResolveDecision(attack, world, decisions, depth + 1);
// In a head to head battle, the threshold for the attack strength to beat is the opposing // In a head to head battle, the threshold for the attack strength to beat is the opposing
// defend strength. Outside a head to head battle, the threshold is the destination's hold // defend strength. Outside a head to head battle, the threshold is the destination's hold
@ -777,7 +794,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
NumericAdjudicationDecision defense = decision.OpposingMove != null NumericAdjudicationDecision defense = decision.OpposingMove != null
? decisions.DefendStrength[decision.OpposingMove] ? decisions.DefendStrength[decision.OpposingMove]
: decisions.HoldStrength[decision.Order.Point]; : decisions.HoldStrength[decision.Order.Point];
progress |= ResolveDecision(defense, world, decisions); progress |= ResolveDecision(defense, world, decisions, depth + 1);
// If the attack doesn't beat the defense, resolve the move to false. // If the attack doesn't beat the defense, resolve the move to false.
if (attack.MaxValue <= defense.MinValue) if (attack.MaxValue <= defense.MinValue)
@ -791,7 +808,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
foreach (MoveOrder order in decision.Competing) foreach (MoveOrder order in decision.Competing)
{ {
PreventStrength prevent = decisions.PreventStrength[order]; PreventStrength prevent = decisions.PreventStrength[order];
progress |= ResolveDecision(prevent, world, decisions); progress |= ResolveDecision(prevent, world, decisions, depth + 1);
// If attack doesn't beat the prevent, resolve the move to false. // If attack doesn't beat the prevent, resolve the move to false.
if (attack.MaxValue <= prevent.MinValue) if (attack.MaxValue <= prevent.MinValue)
{ {