public World(ushort initialHealthy, ushort initialSick, float timeScale, bool singleCore, List <Pipeline> pipelines) { // Using 2/3 of the computer cores. The other 1/3 is used for UI // rendering, server handling, your OS, etc. // Remove the arithmetic below and watch your computer INCENERATE. var calculatedOptimalCores = Environment.ProcessorCount * 2 / 3; if (singleCore || calculatedOptimalCores < 1) { this.NumberOfCores = 1; } else { this.NumberOfCores = calculatedOptimalCores; } this.initialHealthy = initialHealthy; this.initialSick = initialSick; this.timeScale = timeScale; this.SimState = SimulationState.PAUSED; this.pipelines = pipelines; /* Create different entity managers */ regionManagers = new Region[NumberOfCores]; int deltaX = World.MaxCoords.X / NumberOfCores; List <EntityOnMap <AbstractEntity> > population = new List <EntityOnMap <AbstractEntity> >(); // Populate the initially healthy population if (outOfBoundsLock.WaitOne()) { for (ushort _ = 0; _ < initialHealthy; _++) { var p = new Point(rnd.Next(0, MaxCoords.X), rnd.Next(0, MaxCoords.Y)); var entity_constructed = new HealthyEntity(); outOfBoundsPopulationHealthy.Add(new EntityOnMap <HealthyEntity>(p, entity_constructed)); } // Populate the initially sick population for (ushort _ = 0; _ < initialSick; _++) { var p = new Point(rnd.Next(0, MaxCoords.X), rnd.Next(0, MaxCoords.Y)); var entity_constructed = new SickEntity(); outOfBoundsPopulationSick.Add(new EntityOnMap <SickEntity>(p, entity_constructed)); } outOfBoundsLock.ReleaseMutex(); } else { throw new InvalidOperationException("The initial mutex was already locked!"); } for (int i = 0; i < NumberOfCores; i++) { int localMaxX = i * deltaX + deltaX; int localMinX = i * deltaX; regionManagers[i] = new Region( (Point point) => MustLeave(point, localMaxX, localMinX), (List <EntityOnMap <SickEntity> > entitiesSick, List <EntityOnMap <HealthyEntity> > entitiesHealthy) => SyncResource(entitiesSick, entitiesHealthy, i) ); } }
public override PipelineReturnData pushThrough(List <EntityOnMap <SickEntity> > currentSick, List <EntityOnMap <HealthyEntity> > currentHealthy, ulong timeDeltaMs) { // Make entities sick if they need to /* * NOTE: Because the timeScale parameter removes "frames" * and possible intersections (no interpolation is being * done as it's quite intensive to do at real time), * the code tries to compensate by increasing the radius. * Because we don't want everyone to become sick immediately, * then linear scaling is not possible. Using this * (https://www.desmos.com/calculator/7agyg8rqqz) for * trying out some things. */ var toBeSick = currentHealthy .Where(h => { // Only keep entries that are intersecting with sick people return(currentSick .Any(s => EntityOnMap <SickEntity> .IsIntersecting( s.location, radius, h.location, radius) )); }) .Select((x, idx) => { // Covert to sick entities var sickEntity = SickEntity.ConvertToSick(x.entity); var sickMapItem = EntityConverterUtility <HealthyEntity, SickEntity> .ConvertInnerEntities(x, sickEntity); return(sickMapItem); }) .Aggregate((new List <ulong>(), new List <EntityOnMap <SickEntity> >()), (aggregate, item) => { aggregate.Item1.Add(item.ID); aggregate.Item2.Add(item); return(aggregate); }) .ToTuple(); return(new PipelineReturnData { newHealthy = currentHealthy.Where(x => !toBeSick.Item1.Contains(x.ID)).ToList(), newSick = currentSick.Concat(toBeSick.Item2).ToList(), }); }
public override PipelineReturnData pushThrough(List <EntityOnMap <SickEntity> > currentSick, List <EntityOnMap <HealthyEntity> > currentHealthy, ulong timeDeltaMs) { var newHealthy = currentSick .Where(x => ((SickEntity)x.entity).recovery >= 1f) .Aggregate(new Tuple <List <EntityOnMap <HealthyEntity> >, List <ulong> >(new List <EntityOnMap <HealthyEntity> >(), new List <ulong>()), (aggregate, x) => { var healthyEntity = SickEntity.ConvertToHealthy(x.entity); var sickMapItem = EntityConverterUtility <SickEntity, HealthyEntity> .ConvertInnerEntities(x, healthyEntity); aggregate.Item1.Add(sickMapItem); aggregate.Item2.Add(sickMapItem.ID); return(aggregate); }).ToValueTuple(); return(new PipelineReturnData { newHealthy = currentHealthy.Concat(newHealthy.Item1).ToList(), newSick = currentSick.Where(x => !newHealthy.Item2.Contains(x.ID)).ToList(), }); }