Changed a bit the core mechanics with a slight improvement in performance

This commit is contained in:
M.Rohmer
2022-03-05 17:14:35 +01:00
parent 3a561f2d0a
commit 8316c5204a
2 changed files with 92 additions and 62 deletions
+66 -38
View File
@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace PropagationRemasteredBeta namespace PropagationRemasteredBeta
{ {
public class Human:ICloneable public class Human : ICloneable
{ {
//State values //State values
public Color SAIN_COLOR = Color.Green; public Color SAIN_COLOR = Color.Green;
@@ -34,8 +34,9 @@ namespace PropagationRemasteredBeta
{ {
get { return _state; } get { return _state; }
//We set the counter of infection whenever we set it to infected //We set the counter of infection whenever we set it to infected
set { set
_state = value; {
_state = value;
if (_state == INFECTED) { _InfectedTimeCounter = 1; } if (_state == INFECTED) { _InfectedTimeCounter = 1; }
switch (_state) switch (_state)
{ {
@@ -73,7 +74,7 @@ namespace PropagationRemasteredBeta
} }
//we dont have any constructor with only default values because the human needs his position in the field to process the infection //we dont have any constructor with only default values because the human needs his position in the field to process the infection
public void ChangeBaseColors(Color sainColor,Color infectedColor,Color immuneColor,Color deadColor) public void ChangeBaseColors(Color sainColor, Color infectedColor, Color immuneColor, Color deadColor)
{ {
SAIN_COLOR = sainColor; SAIN_COLOR = sainColor;
IMMUNE_COLOR = immuneColor; IMMUNE_COLOR = immuneColor;
@@ -81,91 +82,118 @@ namespace PropagationRemasteredBeta
INFECTED_COLOR = infectedColor; INFECTED_COLOR = infectedColor;
} }
public void Propagate(Human[,] previousTerrain, Human[,] nextTerrain, int infectiosity, int deathRate, int cureTime, Random rnd) public Human Propagate(Terrain T)
{ {
Human target; Human target;
Point location; Point location;
//target = previousTerrain[Position.X, Position.Y];
LifeTimeCounter++; LifeTimeCounter++;
if (this.State == INFECTED) if (this.State == INFECTED)
{ {
InfectedTimeCounter++; InfectedTimeCounter++;
if (rnd.Next(0, 100) <= deathRate) if (T.Rnd.Next(0, 100) <= T.DeathRate)
{ {
this.State = DEAD; State = DEAD;
nextTerrain[this.Position.X, this.Position.Y] = this;
} }
if (LifeTimeCounter >= cureTime) if (LifeTimeCounter >= T.CureTime)
{ {
this.State = IMMUNE; State = IMMUNE;
} }
else else
{ {
//we need to check if we are not in a corner //we need to check if we are not in a corner
if (Position.X > 0 && Position.Y > 0 && Position.X < (previousTerrain.GetLength(0) - 1) && Position.Y < (previousTerrain.GetLength(1) - 1)) if (Position.X > 0 && Position.Y > 0 && Position.X < (T.TerrainSize.Width - 1) && Position.Y < (T.TerrainSize.Height - 1))
{ {
//check top left //check top left
location = new Point(Position.X - 1, Position.Y + 1); location = new Point(Position.X - 1, Position.Y + 1);
target = previousTerrain[location.X, location.Y]; target = T.Population[location.X, location.Y];
CheckInfection(nextTerrain, target, infectiosity, deathRate, rnd); if (target.State == Human.SAIN)
{
T.PeopleToCheck.Add(target);
}
//check top //check top
location = new Point(Position.X, Position.Y + 1); location = new Point(Position.X, Position.Y + 1);
target = previousTerrain[location.X, location.Y]; target = T.Population[location.X, location.Y];
CheckInfection(nextTerrain, target, infectiosity, deathRate, rnd);
if (target.State == Human.SAIN)
{
T.PeopleToCheck.Add(target);
}
//check top left //check top left
location = new Point(Position.X + 1, Position.Y + 1); location = new Point(Position.X + 1, Position.Y + 1);
target = previousTerrain[location.X, location.Y]; target = T.Population[location.X, location.Y];
CheckInfection(nextTerrain, target, infectiosity, deathRate, rnd);
if (target.State == Human.SAIN)
{
T.PeopleToCheck.Add(target);
}
//check left //check left
location = new Point(Position.X - 1, Position.Y); location = new Point(Position.X - 1, Position.Y);
target = previousTerrain[location.X, location.Y]; target = T.Population[location.X, location.Y];
CheckInfection(nextTerrain, target, infectiosity, deathRate, rnd);
if (target.State == Human.SAIN)
{
T.PeopleToCheck.Add(target);
}
//check right //check right
location = new Point(Position.X + 1, Position.Y); location = new Point(Position.X + 1, Position.Y);
target = previousTerrain[location.X, location.Y]; target = T.Population[location.X, location.Y];
CheckInfection(nextTerrain, target, infectiosity, deathRate, rnd);
if (target.State == Human.SAIN)
{
T.PeopleToCheck.Add(target);
}
//check bottom left //check bottom left
location = new Point(Position.X - 1, Position.Y - 1); location = new Point(Position.X - 1, Position.Y - 1);
target = previousTerrain[location.X, location.Y]; target = T.Population[location.X, location.Y];
CheckInfection(nextTerrain, target, infectiosity, deathRate, rnd);
if (target.State == Human.SAIN)
{
T.PeopleToCheck.Add(target);
}
//check bottom //check bottom
location = new Point(Position.X, Position.Y - 1); location = new Point(Position.X, Position.Y - 1);
target = previousTerrain[location.X, location.Y]; target = T.Population[location.X, location.Y];
CheckInfection(nextTerrain, target, infectiosity, deathRate, rnd);
if (target.State == Human.SAIN)
{
T.PeopleToCheck.Add(target);
}
//check bottom right //check bottom right
location = new Point(Position.X + 1, Position.Y - 1); location = new Point(Position.X + 1, Position.Y - 1);
target = previousTerrain[location.X, location.Y]; target = T.Population[location.X, location.Y];
CheckInfection(nextTerrain, target, infectiosity, deathRate, rnd);
if (target.State == Human.SAIN)
{
T.PeopleToCheck.Add(target);
}
} }
} }
} }
return this;
} }
private void CheckInfection(Human[,] nextTerrain, Human target, int infectiosity, int deathRate, Random rnd) public Human CheckInfection(int infectiosity, Random rnd)
{ {
if (target.State == SAIN) if (rnd.Next(0, 100) <= infectiosity)
{ {
if (rnd.Next(0, 100) <= infectiosity) State = INFECTED;
{
target.State = INFECTED;
}
} }
return this;
nextTerrain[target.Position.X, target.Position.Y] = target;
} }
public object Clone() public object Clone()
{ {
Human newHuman = new Human(Position,State); Human newHuman = new Human(Position, State);
newHuman.HumanSize = HumanSize; newHuman.HumanSize = HumanSize;
newHuman.InfectedTimeCounter = InfectedTimeCounter; newHuman.InfectedTimeCounter = InfectedTimeCounter;
newHuman.LifeTimeCounter = LifeTimeCounter; newHuman.LifeTimeCounter = LifeTimeCounter;
+26 -24
View File
@@ -17,10 +17,10 @@ namespace PropagationRemasteredBeta
const int DEFAULT_INFECTION_RATE = 20; const int DEFAULT_INFECTION_RATE = 20;
const int DEFAULT_CURE_TIME = 25; const int DEFAULT_CURE_TIME = 25;
const int DEBUGGER_PLACEHOLDER = 86758;
private Human[,] _population; private Human[,] _population;
private List<Human> _peopleToCheck;
private Size _terrainSize; private Size _terrainSize;
private int _infectedProportion; private int _infectedProportion;
private int _immuneProportion; private int _immuneProportion;
private int _deathRate; private int _deathRate;
@@ -28,9 +28,6 @@ namespace PropagationRemasteredBeta
private int _cureTime; private int _cureTime;
private Bitmap _render; private Bitmap _render;
private Human[,] oldTerrain;
private Human[,] newTerrain;
private List<int> _sainCount; private List<int> _sainCount;
private List<int> _infectedCount; private List<int> _infectedCount;
private List<int> _immuneCount; private List<int> _immuneCount;
@@ -56,6 +53,8 @@ namespace PropagationRemasteredBeta
public List<int> ImmuneCount { get => _immuneCount; set => _immuneCount = value; } public List<int> ImmuneCount { get => _immuneCount; set => _immuneCount = value; }
public List<int> DeadCount { get => _deadCount; set => _deadCount = value; } public List<int> DeadCount { get => _deadCount; set => _deadCount = value; }
public int SimulationDuration { get => _simulationDuration; set => _simulationDuration = value; } public int SimulationDuration { get => _simulationDuration; set => _simulationDuration = value; }
public List<Human> PeopleToCheck { get => _peopleToCheck; set => _peopleToCheck = value; }
public Random Rnd { get => rnd; set => rnd = value; }
public Terrain(Size terrainSize, int infectedProportion, int resistantProportion, int deathRate, int infectionRate, int cureTime) public Terrain(Size terrainSize, int infectedProportion, int resistantProportion, int deathRate, int infectionRate, int cureTime)
{ {
@@ -66,10 +65,7 @@ namespace PropagationRemasteredBeta
DeathRate = deathRate; DeathRate = deathRate;
InfectionRate = infectionRate; InfectionRate = infectionRate;
CureTime = cureTime; CureTime = cureTime;
rnd = new Random(); Rnd = new Random();
oldTerrain = null;
newTerrain = null;
//all of this is for stats purposes //all of this is for stats purposes
@@ -96,13 +92,13 @@ namespace PropagationRemasteredBeta
state = Human.SAIN; state = Human.SAIN;
if (rnd.Next(0, 100) < InfectedProportion) if (Rnd.Next(0, 100) < InfectedProportion)
{ {
state = Human.INFECTED; state = Human.INFECTED;
} }
else else
{ {
if (rnd.Next(0, 100) < ImmuneProportion) if (Rnd.Next(0, 100) < ImmuneProportion)
{ {
state = Human.IMMUNE; state = Human.IMMUNE;
} }
@@ -123,7 +119,7 @@ namespace PropagationRemasteredBeta
state = Human.SAIN; state = Human.SAIN;
if (rnd.Next(0, 100) < ImmuneProportion) if (Rnd.Next(0, 100) < ImmuneProportion)
{ {
state = Human.IMMUNE; state = Human.IMMUNE;
} }
@@ -133,8 +129,8 @@ namespace PropagationRemasteredBeta
} }
} }
//we generate a single infected in a random location //we generate a single infected in a random location
int x = rnd.Next(0, TerrainSize.Width); int x = Rnd.Next(0, TerrainSize.Width);
int y = rnd.Next(0, TerrainSize.Height); int y = Rnd.Next(0, TerrainSize.Height);
Population[x, y].State = Human.INFECTED; Population[x, y].State = Human.INFECTED;
} }
@@ -146,22 +142,24 @@ namespace PropagationRemasteredBeta
InfectedCount.Add(0); InfectedCount.Add(0);
DeadCount.Add(0); DeadCount.Add(0);
oldTerrain = Population; PeopleToCheck = new List<Human>();
newTerrain = oldTerrain;
for (int width = 0; width < TerrainSize.Width; width += 1) for (int width = 0; width < TerrainSize.Width; width += 1)
{ {
//Parallel.For(0, TerrainSize.Height, height =>
for (int height = 0; height < TerrainSize.Height; height += 1) for (int height = 0; height < TerrainSize.Height; height += 1)
{ {
//we also send the random so if one day we want to add a seed feature it will also affect the transmission //we also send the random so if one day we want to add a seed feature it will also affect the transmission
if (Population[width, height].State != Human.SAIN && Population[width, height].State != Human.DEAD && Population[width, height].State != Human.IMMUNE) switch (Population[width, height].State)
{ {
Population[width, height].Propagate(oldTerrain, newTerrain, InfectionRate, DeathRate, CureTime, rnd); case Human.INFECTED:
} Population[width, height] = Population[width, height].Propagate(this);
else break;
{ default:
newTerrain[width, height] = Population[width, height]; //nothing to do
break;
} }
//only for stats purposes //only for stats purposes
switch (Population[width, height].State) switch (Population[width, height].State)
{ {
@@ -178,10 +176,14 @@ namespace PropagationRemasteredBeta
DeadCount[SimulationDuration] += 1; DeadCount[SimulationDuration] += 1;
break; break;
} }
} }//);
}
foreach (Human target in PeopleToCheck)
{
Population[target.Position.X,target.Position.Y] = target.CheckInfection(InfectionRate,Rnd);
} }
Population = newTerrain;
} }
public Bitmap Display() public Bitmap Display()