public void UpdateDistance(GameFormation source, GameFormation target, int rangeShift) { (var rangeBetweenFormations, var rangeReciprocal) = this.UpdateDistance(source.FormationId, target.FormationId, rangeShift); // var consoleTail = $"{Math.Abs(rangeShift)} [{rangeBetweenFormations.Value - rangeShift} >> {rangeBetweenFormations.Value}]"; // Console.WriteLine($"-- Range {(rangeShift == 0 ? "unchanged" : (rangeShift < 0 ? "decreases by " : "increases by ") + consoleTail)}"); }
private FormationDistance AddEdge(GameFormation nodeA, GameFormation nodeB, int edgeWeight) { var newEdge = new FormationDistance(nodeA, nodeB, edgeWeight); this.edges.Add(newEdge); return(newEdge); }
public FormationDistance(GameFormation source, GameFormation target, int value) { this.SourceFormationId = source.FormationId; this.SourceFormationName = source.FormationName; this.TargetFormationId = target.FormationId; this.TargetFormationName = target.FormationName; this.Value = value; }
public FormationDistance SetDistance(GameFormation nodeA, GameFormation nodeB, int distance) { var edge = this.GetOrEstablishDistance(nodeA.FormationId, nodeB.FormationId, distance); var edgeReciprocal = this.GetOrEstablishDistance(nodeB.FormationId, nodeA.FormationId, distance); edge.Value = distance; edgeReciprocal.Value = distance; return(edge); }
private Tuple <FormationDistance, FormationDistance> GetGraphState(GameFormation nodeA, GameFormation nodeB) { // No edges can exist between a Formation and itself if (nodeA.FormationId == nodeB.FormationId) { throw new InvalidOperationException($"Cannot get distance-graph data between a formation ([ID {nodeA.FormationId}] {nodeA.FormationName}) and itself ([ID {nodeB.FormationId})] {nodeB.FormationName}"); } var edge = this.GetOrEstablishDistance(nodeA, nodeB); var edgeReciprocal = this.GetOrEstablishDistance(nodeB, nodeA); return(new Tuple <FormationDistance, FormationDistance>(edge, edgeReciprocal)); }
// TODO: Move this to the distanceGraph class public int CalculateRangeShift(int currentVolley, GameFormation source, int sourceSpeed, GameFormation target) { var type = this.ManeuverType; var priority = this.Priority; var speed = Math.Max(0, sourceSpeed + GetManeuverModifier(this.Priority)); var log = $" --- Execute [{source.FormationId}]{source.FormationName} : {priority} {type} ({speed}s)"; var targetOrders = target.Orders .Where(tO => tO.Volley == currentVolley) .FirstOrDefault() ?? Constants.DefaultVolleyOrders; var targetManeuver = targetOrders.ManeuveringOrders .Where(tRO => tRO.TargetID == source.FormationId) .FirstOrDefault() ?? Constants.DefaultManeuverOrder; var opposingPriority = targetManeuver.Priority; var opposingType = targetManeuver.ManeuverType; var opposingSpeed = Math.Max(0, targetOrders.SpeedSuccesses + GetManeuverModifier(targetManeuver.Priority)); log += $" vs [{target.FormationId}]{target.FormationName} : {opposingPriority} {opposingType} ({opposingSpeed}s) "; var margin = speed - opposingSpeed; var rangeShift = 0; var successDistance = this.ManeuverType == "Close" ? -Constants.RangeShiftPerSuccess : Constants.RangeShiftPerSuccess; var maneuverTypePair = new Tuple <string, string>(this.ManeuverType, targetManeuver.ManeuverType); // Unopposed auto-successes if (maneuverTypePair.Equals(Constants.CloseVersusClose) || maneuverTypePair.Equals(Constants.WithdrawVersusWithdraw)) { // Ignore opponent's Speed successes, they will be resolved separately rangeShift = successDistance * speed; } // "True" versus test -- if active F got more successes, distance changes; otherwise not. if (maneuverTypePair.Equals(Constants.CloseVersusMaintain) || maneuverTypePair.Equals(Constants.CloseVersusWithdraw) || maneuverTypePair.Equals(Constants.WithdrawVersusClose) || maneuverTypePair.Equals(Constants.WithdrawVersusMaintain)) { rangeShift = successDistance * Math.Max(0, margin); // Ignore cases where opponent's successes were higher, they will be resolved separately (if not a Maintain already) } // Console.WriteLine(log); return(rangeShift); }
public FormationDistance GetOrEstablishDistance(int sourceId, int targetId, int establishDistance) { // Ensure valid inputs GameFormation nodeA = this.GetNodeById(sourceId); GameFormation nodeB = this.GetNodeById(targetId); if (establishDistance < 0) { throw new InvalidOperationException($"Invalid starting distance {establishDistance}: Formation distances must always be nonnegative."); } FormationDistance edge = this.GetEdge(nodeA, nodeB); FormationDistance edgeReciprocal = this.GetEdge(nodeB, nodeA); // edge-weight is equal to the edge-weight of the existing edge(s) or else the specified "establishDistance" var edgeWeight = edge != null ? edge.Value : edgeReciprocal != null ? edgeReciprocal.Value : establishDistance; // ensure both edge and its reciprocal exist edge = edge ?? this.AddEdge(nodeA, nodeB, edgeWeight); edgeReciprocal = edgeReciprocal ?? this.AddEdge(nodeB, nodeA, edgeWeight); return(edge); }
public GameUnitFormationInfo(List <GameUnit> units, int unitId, List <GameFormation> formations, int formationId) { this.unitReference = GetUnitById(units, unitId); this.formationReference = GetFormationById(formations, formationId); this.Refresh(); }
public GameUnitFormationInfo(List <GameUnit> units, int unitId, GameFormation formation) { this.unitReference = GetUnitById(units, unitId); this.formationReference = formation; this.Refresh(); }
public GameUnitFormationInfo(GameUnit unit, GameFormation formation) { this.unitReference = unit; this.formationReference = formation; this.Refresh(); }
public GameUnitFormationInfo() { this.unitReference = new GameUnit(); this.formationReference = new GameFormation(); this.Refresh(); }
/// <summary> /// Gets the current <see cref="FormationDistance" edge between two <see cref="GameFormation"/>s; /// if one does not exist, establishes a new entry of distance <see cref="Constants.DefaultStartingRange"/>/> /// </summary> /// <param name="source">A <see cref="GameFormation"/></param> /// <param name="target">A second <see cref="GameFormation"/></param> /// <returns><see cref="FormationDistance"/> between two <see cref="GameFormation"/>s specified.</returns> public FormationDistance GetOrEstablishDistance(GameFormation source, GameFormation target) { return(this.GetOrEstablishDistance(source.FormationId, target.FormationId)); }
private void SyncGraphState(FormationDistance edge, FormationDistance edgeReciprocal, GameFormation nodeA, GameFormation nodeB) { // If neither the source -> target nor target -> source distances are in the Distances graph, create them at default starting range if (edge is null && edgeReciprocal is null) { edge = this.AddEdge(nodeA, nodeB, Constants.DefaultStartingRange); edgeReciprocal = this.AddEdge(nodeB, nodeA, Constants.DefaultStartingRange); }
/// <summary> /// Find one existing <see cref="GameFormation"/> edge between two specified <see cref="GameFormation"/>s. /// </summary> /// <param name="nodeA">Desired "source" node.</param> /// <param name="nodeB">Desired "target" node.</param> /// <returns> /// The existing <see cref="FormationDistance"/> edge from <paramref name="nodeA"/> to <paramref name="nodeB"/>, or null if none exists /// </returns> /// <remarks> /// Note that this method will *not* return the reciprocal edge if one exists (although one shouldn't, if the specified edge does not). /// </remarks> private FormationDistance GetEdge(GameFormation nodeA, GameFormation nodeB) { return(this.edges.Where(e => e.SourceFormationId == nodeA.FormationId && e.TargetFormationId == nodeB.FormationId).FirstOrDefault()); }