identifies a unit on a path segment
this is a struct instead of a class because it compares by value
 /// <summary>
 /// update player's non-live (time traveling) paths
 /// </summary>
 public void updatePast(long curTime)
 {
     if (hasNonLivePaths) {
         foreach (Path path in g.paths) {
             if (this == path.player) path.updatePast(curTime, true);
         }
         if (curTime >= g.timeSim && g.timeSim >= timeGoLiveFailedAttempt + g.updateInterval) {
             // make player's time traveling paths go live
             long timeTravelStart = long.MaxValue;
             // find earliest time that player's paths started time traveling
             foreach (Path path in g.paths) {
                 if (this == path.player && path.timeSimPast != long.MaxValue && path.segments[0].timeStart < timeTravelStart) {
                     timeTravelStart = path.segments[0].timeStart;
                 }
             }
             if (timeTravelStart != long.MaxValue) { // skip if player has no time traveling paths
                 // check if going live would lead to player ever having negative resources or going over population limit
                 timeGoLiveProblem = checkNegRsc(timeTravelStart, true);
                 if (timeGoLiveProblem < 0 && populationLimit >= 0) {
                     timeGoLiveProblem = checkPopulation(timeTravelStart);
                 }
                 if (timeGoLiveProblem >= 0) {
                     // indicate failure to go live, then return
                     timeGoLiveFailedAttempt = g.timeSim;
                     return;
                 }
                 // safe for paths to become live, so do so
                 foreach (Path path in g.paths) {
                     if (this == path.player && path.timeSimPast != long.MaxValue) {
                         List<SegmentUnit> queue = new List<SegmentUnit>();
                         SegmentUnit nonLiveChild = new SegmentUnit();
                         path.timeSimPast = long.MaxValue;
                         foreach (Segment segment in path.segments) {
                             queue.AddRange (segment.segmentUnits ());
                         }
                         while (queue.Count > 0) {
                             foreach (SegmentUnit prev in queue[0].prev ()) {
                                 if (prev.segment.path.timeSimPast != long.MaxValue) {
                                     prev.segment.path.timeSimPast = long.MaxValue;
                                     queue.Add (prev);
                                 }
                             }
                             foreach (SegmentUnit parent in queue[0].parents ()) {
                                 if (parent.segment.path.timeSimPast != long.MaxValue) {
                                     parent.segment.path.timeSimPast = long.MaxValue;
                                     queue.Add (parent);
                                 }
                             }
                             if (nonLiveChild.g == null && queue[0].children().Any ()) nonLiveChild = queue[0];
                             queue.RemoveAt (0);
                         }
                         if (nonLiveChild.g != null) g.deleteOtherPaths (new SegmentUnit[] { nonLiveChild }, true, false);
                     }
                 }
             }
             // indicate success
             hasNonLivePaths = false;
             timeGoLiveFailedAttempt = long.MinValue;
             // try again to stack paths that failed to stack in the past
             foreach (var item in goLiveStackPaths) {
                 g.addStackEvts (item.Value.ToList (), item.Key);
             }
             goLiveStackPaths = new Dictionary<int, HashSet<Path>>();
         }
     }
 }
Exemple #2
0
 private void addAncestors(SegmentUnit segmentUnit, HashSet<SegmentUnit> ancestors, HashSet<SegmentUnit> prev, HashSet<SegmentUnit> liveToNonLivePrev)
 {
     ancestors.Add (segmentUnit);
     foreach (SegmentUnit prevSegment in segmentUnit.prev ()) {
         if (segmentUnit.segment.path.timeSimPast != long.MaxValue && prevSegment.segment.path.timeSimPast == long.MaxValue) {
             liveToNonLivePrev.Add(prevSegment);
         } else {
             prev.Add (prevSegment);
         }
         addAncestors (prevSegment, ancestors, prev, liveToNonLivePrev);
     }
     foreach (SegmentUnit parent in segmentUnit.parents ()) {
         addAncestors (parent, ancestors, prev, liveToNonLivePrev);
     }
 }
Exemple #3
0
 private bool canMakePath(long time, List<Unit> units, out bool costsRsc, bool ignoreSeen = false)
 {
     costsRsc = false;
     if (units.Count == 0) return false;
     Segment segment = segmentWhen(time);
     if (segment == null) return false;
     int newUnitCount = 0;
     long[] rscCost = new long[g.rscNames.Length];
     foreach (Unit unit in units) {
         if (segment.units.Contains (unit)) {
             // unit in path already exists
             SegmentUnit segmentUnit = new SegmentUnit(segment, unit); // get parent SegmentUnit
             if (!segmentUnit.canBeUnambiguousParent (time)) return false;
             if (!ignoreSeen && !segmentUnit.unseenAfter (time)) return false;
             if (!segmentUnit.hasChildrenAfter ()) return false;
         } else if (!(time == segment.timeStart && new SegmentUnit(segment, unit).prev ().Any ())) {
             // unit in path would be new unit
             if (!canMakeUnitType (time, unit.type)) return false;
             if (unit.type.speed > 0) newUnitCount++;
             for (int i = 0; i < g.rscNames.Length; i++) {
                 rscCost[i] += unit.type.rscCost[i];
             }
         }
     }
     bool newPathIsLive = (time >= g.timeSim && timeSimPast == long.MaxValue);
     if (!newPathIsLive && !Sim.enableNonLivePaths) return false;
     if (player.populationLimit >= 0 && player.population (time) + newUnitCount > player.populationLimit) return false;
     for (int i = 0; i < g.rscNames.Length; i++) {
         if (rscCost[i] > 0 && player.resource(time, i, !newPathIsLive) < rscCost[i]) return false;
     }
     costsRsc = rscCost.Where (r => r > 0).Any ();
     return true;
 }