/// <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>>(); } } }
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); } }
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; }