284 lines
12 KiB
C#
284 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
|
|
namespace PropagationRemasteredBeta
|
|
{
|
|
public class Terrain
|
|
{
|
|
const int DEFAULT_SIZE = 1000;
|
|
const int DEFAULT_INFECTED_PROPORTION = 10;
|
|
const int DEFAULT_IMMUNE_PROPORTION = 10;
|
|
const int DEFAULT_DEATH_RATE = 5;
|
|
const int DEFAULT_INFECTION_RATE = 20;
|
|
const int DEFAULT_CURE_TIME = 25;
|
|
|
|
const int DEBUGGER_PLACEHOLDER = 86758;
|
|
|
|
private Human[,] _population;
|
|
private Size _terrainSize;
|
|
private int _infectedProportion;
|
|
private int _immuneProportion;
|
|
private int _deathRate;
|
|
private int _infectionRate;
|
|
private int _cureTime;
|
|
private Bitmap _render;
|
|
|
|
private Human[,] Grid;
|
|
|
|
private List<Human> _oldSainPeoples;
|
|
private List<Human> _oldInfectedPeoples;
|
|
private List<Human> _oldImmunesPeoples;
|
|
private List<Human> _oldDeadPeoples;
|
|
|
|
private List<Human> _sainPeoples;
|
|
private List<Human> _infectedPeoples;
|
|
private List<Human> _immunesPeoples;
|
|
private List<Human> _deadPeoples;
|
|
|
|
private int _simulationDuration;
|
|
|
|
/*Used for debugging*/
|
|
public int DRAWED_ELEMENTS;
|
|
|
|
private Random _rnd;
|
|
public Human[,] Population { get => _population; set => _population = value; }
|
|
public Size TerrainSize { get => _terrainSize; private set => _terrainSize = value; }
|
|
public int InfectedProportion { get => _infectedProportion; private set => _infectedProportion = value; }
|
|
public int ImmuneProportion { get => _immuneProportion; private set => _immuneProportion = value; }
|
|
public int DeathRate { get => _deathRate; private set => _deathRate = value; }
|
|
public int InfectionRate { get => _infectionRate; private set => _infectionRate = value; }
|
|
public int CureTime { get => _cureTime; set => _cureTime = value; }
|
|
public Bitmap Render { get => _render; set => _render = value; }
|
|
public List<Human> SainPeoples { get => _sainPeoples; set => _sainPeoples = value; }
|
|
public List<Human> InfectedPeoples { get => _infectedPeoples; set => _infectedPeoples = value; }
|
|
public List<Human> ImmunesPeoples { get => _immunesPeoples; set => _immunesPeoples = value; }
|
|
public List<Human> DeadPeoples { get => _deadPeoples; set => _deadPeoples = value; }
|
|
public int SimulationDuration { get => _simulationDuration; set => _simulationDuration = value; }
|
|
public Random Rnd { get => _rnd; set => _rnd = value; }
|
|
public List<Human> OldSainPeoples { get => _oldSainPeoples; set => _oldSainPeoples = value; }
|
|
public List<Human> OldInfectedPeoples { get => _oldInfectedPeoples; set => _oldInfectedPeoples = value; }
|
|
public List<Human> OldImmunesPeoples { get => _oldImmunesPeoples; set => _oldImmunesPeoples = value; }
|
|
public List<Human> OldDeadPeoples { get => _oldDeadPeoples; set => _oldDeadPeoples = value; }
|
|
|
|
public Terrain(Size terrainSize, int infectedProportion, int resistantProportion, int deathRate, int infectionRate, int cureTime)
|
|
{
|
|
Population = new Human[terrainSize.Width, terrainSize.Height];
|
|
TerrainSize = terrainSize;
|
|
InfectedProportion = infectedProportion;
|
|
ImmuneProportion = resistantProportion;
|
|
DeathRate = deathRate;
|
|
InfectionRate = infectionRate;
|
|
CureTime = cureTime;
|
|
Rnd = new Random();
|
|
|
|
Grid = null;
|
|
|
|
SainPeoples = new List<Human>();
|
|
InfectedPeoples = new List<Human>();
|
|
ImmunesPeoples = new List<Human>();
|
|
DeadPeoples = new List<Human>();
|
|
|
|
OldSainPeoples = new List<Human>();
|
|
OldInfectedPeoples = new List<Human>();
|
|
OldImmunesPeoples = new List<Human>();
|
|
OldDeadPeoples = new List<Human>();
|
|
|
|
SimulationDuration = -1;
|
|
|
|
}
|
|
public Terrain() : this(new Size(DEFAULT_SIZE, DEFAULT_SIZE), DEFAULT_INFECTED_PROPORTION, DEFAULT_IMMUNE_PROPORTION, DEFAULT_DEATH_RATE, DEFAULT_INFECTION_RATE, DEFAULT_CURE_TIME)
|
|
{
|
|
//empty
|
|
}
|
|
public void Generate()
|
|
{
|
|
//That is the basic method to scan trough the entire field
|
|
for (int width = 0; width < TerrainSize.Width; width += 1)
|
|
{
|
|
for (int height = 0; height < TerrainSize.Height; height += 1)
|
|
{
|
|
int state;
|
|
|
|
state = Human.SAIN;
|
|
|
|
if (Rnd.Next(0, 100) < InfectedProportion)
|
|
{
|
|
state = Human.INFECTED;
|
|
}
|
|
else
|
|
{
|
|
if (Rnd.Next(0, 100) < ImmuneProportion)
|
|
{
|
|
state = Human.IMMUNE;
|
|
}
|
|
}
|
|
|
|
AddHuman(new Point(width, height), state);
|
|
}
|
|
}
|
|
}
|
|
public void GenerateOneForAll()
|
|
{
|
|
for (int width = 0; width < TerrainSize.Width; width += 1)
|
|
{
|
|
for (int height = 0; height < TerrainSize.Height; height += 1)
|
|
{
|
|
int state;
|
|
|
|
if (Rnd.Next(0, 100) < ImmuneProportion)
|
|
{
|
|
state = Human.IMMUNE;
|
|
}
|
|
else
|
|
{
|
|
state = Human.SAIN;
|
|
}
|
|
AddHuman(new Point(width, height), state);
|
|
}
|
|
}
|
|
//we generate a single infected in a random location
|
|
int x = Rnd.Next(0, TerrainSize.Width);
|
|
int y = Rnd.Next(0, TerrainSize.Height);
|
|
AddHuman(new Point(x, y), Human.INFECTED);
|
|
}
|
|
public void AddHuman(Point position,int state)
|
|
{
|
|
//filling population
|
|
Population[position.X, position.Y] = new Human(new Point(position.X, position.Y), state);
|
|
switch (state)
|
|
{
|
|
case Human.SAIN:
|
|
SainPeoples.Add(Population[position.X, position.Y]);
|
|
break;
|
|
case Human.IMMUNE:
|
|
ImmunesPeoples.Add(Population[position.X, position.Y]);
|
|
break;
|
|
case Human.INFECTED:
|
|
InfectedPeoples.Add(Population[position.X, position.Y]);
|
|
break;
|
|
case Human.DEAD:
|
|
DeadPeoples.Add(Population[position.X, position.Y]);
|
|
break;
|
|
default:
|
|
SainPeoples.Add(Population[position.X, position.Y]);
|
|
break;
|
|
}
|
|
}
|
|
public List<Human> CopyPopulations(List<Human> ListToCopy)
|
|
{
|
|
List<Human> ListToCopyInto = new List<Human>(ListToCopy.Count);
|
|
foreach (Human h in ListToCopy)
|
|
{
|
|
ListToCopyInto.Add((Human)h.Clone());
|
|
}
|
|
return ListToCopyInto;
|
|
}
|
|
public void Refresh()
|
|
{
|
|
OldDeadPeoples = CopyPopulations(DeadPeoples);
|
|
OldInfectedPeoples = CopyPopulations(InfectedPeoples);
|
|
OldSainPeoples = CopyPopulations(SainPeoples);
|
|
OldImmunesPeoples = CopyPopulations(ImmunesPeoples);
|
|
|
|
DeadPeoples = new List<Human>(OldDeadPeoples.Count);
|
|
ImmunesPeoples = new List<Human>(OldImmunesPeoples.Count);
|
|
SainPeoples = new List<Human>(OldSainPeoples.Count);
|
|
InfectedPeoples = new List<Human>(OldInfectedPeoples.Count);
|
|
|
|
//used for stats and curing
|
|
SimulationDuration++;
|
|
foreach (Human individual in OldInfectedPeoples)
|
|
{
|
|
InfectedPeoples.Add(individual);
|
|
individual.Propagate(this);
|
|
}
|
|
foreach (Human individual in OldImmunesPeoples)
|
|
{
|
|
ImmunesPeoples.Add(individual);
|
|
}
|
|
foreach (Human individual in OldSainPeoples)
|
|
{
|
|
SainPeoples.Add(individual);
|
|
}
|
|
foreach (Human individual in OldDeadPeoples)
|
|
{
|
|
DeadPeoples.Add(individual);
|
|
}
|
|
}
|
|
|
|
public Bitmap Display()
|
|
{
|
|
DRAWED_ELEMENTS = 0;
|
|
Render = new Bitmap(TerrainSize.Width, TerrainSize.Height);
|
|
using (Graphics gr = Graphics.FromImage(Render))
|
|
{
|
|
//this is an attempt to save time, we display the dominant color in the all bitmap and only change the others.
|
|
int dominantState = Human.SAIN;
|
|
//we check that it is not the first frame and by default we expect the first frame to be dominantly sain people
|
|
if (InfectedPeoples.Count() > 0)
|
|
{
|
|
int infecteds = InfectedPeoples.Count() - 1;
|
|
int sain = SainPeoples.Count() - 1;
|
|
int immune = ImmunesPeoples.Count() - 1;
|
|
int deaths = DeadPeoples.Count() - 1;
|
|
|
|
if (infecteds > sain && infecteds > immune && infecteds > deaths)
|
|
{
|
|
//the dominant color is the infected one
|
|
dominantState = Human.INFECTED;
|
|
}
|
|
if (immune > sain && immune > infecteds && immune > deaths)
|
|
{
|
|
//the dominant color is the infected one
|
|
dominantState = Human.IMMUNE;
|
|
}
|
|
if (deaths > sain && deaths > infecteds && deaths > immune)
|
|
{
|
|
//the dominant color is the infected one
|
|
dominantState = Human.DEAD;
|
|
}
|
|
}
|
|
//as Color object cannot be a constant we cannot use Human.SAIN_COLOR we need to use a fully constructed human
|
|
Human sample = new Human(new Point(-1, -1), Human.DEAD);
|
|
switch (dominantState)
|
|
{
|
|
case Human.SAIN:
|
|
gr.FillRectangle(new SolidBrush(sample.SAIN_COLOR), new Rectangle(new Point(0, 0), new Size(Render.Width, Render.Height)));
|
|
break;
|
|
case Human.IMMUNE:
|
|
gr.FillRectangle(new SolidBrush(sample.IMMUNE_COLOR), new Rectangle(new Point(0, 0), new Size(Render.Width, Render.Height)));
|
|
break;
|
|
case Human.INFECTED:
|
|
gr.FillRectangle(new SolidBrush(sample.INFECTED_COLOR), new Rectangle(new Point(0, 0), new Size(Render.Width, Render.Height)));
|
|
break;
|
|
case Human.DEAD:
|
|
gr.FillRectangle(new SolidBrush(sample.DEATH_COLOR), new Rectangle(new Point(0, 0), new Size(Render.Width, Render.Height)));
|
|
break;
|
|
default:
|
|
gr.FillRectangle(new SolidBrush(sample.SAIN_COLOR), new Rectangle(new Point(0, 0), new Size(Render.Width, Render.Height)));
|
|
break;
|
|
}
|
|
for (int width = 0; width < TerrainSize.Width; width += 1)
|
|
{
|
|
for (int height = 0; height < TerrainSize.Height; height += 1)
|
|
{
|
|
Human individual = Population[width, height];
|
|
if (individual.State != dominantState)
|
|
{
|
|
Color c = individual.Sprite;
|
|
gr.FillRectangle(new SolidBrush(c), new Rectangle(individual.Position, individual.HumanSize));
|
|
DRAWED_ELEMENTS++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return Render;
|
|
}
|
|
}
|
|
}
|