Add depth tracking to decision resolution
This commit is contained in:
parent
23a826c815
commit
c0a9330d2e
|
@ -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)
|
||||||
|
{
|
||||||
|
return decision.Resolved ? false : decision switch
|
||||||
{
|
{
|
||||||
IsDislodged d => ResolveIsUnitDislodged(d, world, decisions),
|
IsDislodged d => ResolveIsUnitDislodged(d, world, decisions, depth + 1),
|
||||||
HasPath d => ResolveDoesMoveHavePath(d, world, decisions),
|
HasPath d => ResolveDoesMoveHavePath(d, world, decisions, depth + 1),
|
||||||
GivesSupport d => ResolveIsSupportGiven(d, world, decisions),
|
GivesSupport d => ResolveIsSupportGiven(d, world, decisions, depth + 1),
|
||||||
HoldStrength d => ResolveHoldStrength(d, world, decisions),
|
HoldStrength d => ResolveHoldStrength(d, world, decisions, depth + 1),
|
||||||
AttackStrength d => ResolveAttackStrength(d, world, decisions),
|
AttackStrength d => ResolveAttackStrength(d, world, decisions, depth + 1),
|
||||||
DefendStrength d => ResolveDefendStrength(d, world, decisions),
|
DefendStrength d => ResolveDefendStrength(d, world, decisions, depth + 1),
|
||||||
PreventStrength d => ResolvePreventStrength(d, world, decisions),
|
PreventStrength d => ResolvePreventStrength(d, world, decisions, depth + 1),
|
||||||
DoesMove d => ResolveDoesUnitMove(d, world, decisions),
|
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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue