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 _oldSainPeoples; private List _oldInfectedPeoples; private List _oldImmunesPeoples; private List _oldDeadPeoples; private List _sainPeoples; private List _infectedPeoples; private List _immunesPeoples; private List _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 SainPeoples { get => _sainPeoples; set => _sainPeoples = value; } public List InfectedPeoples { get => _infectedPeoples; set => _infectedPeoples = value; } public List ImmunesPeoples { get => _immunesPeoples; set => _immunesPeoples = value; } public List DeadPeoples { get => _deadPeoples; set => _deadPeoples = value; } public int SimulationDuration { get => _simulationDuration; set => _simulationDuration = value; } public Random Rnd { get => _rnd; set => _rnd = value; } public List OldSainPeoples { get => _oldSainPeoples; set => _oldSainPeoples = value; } public List OldInfectedPeoples { get => _oldInfectedPeoples; set => _oldInfectedPeoples = value; } public List OldImmunesPeoples { get => _oldImmunesPeoples; set => _oldImmunesPeoples = value; } public List 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(); InfectedPeoples = new List(); ImmunesPeoples = new List(); DeadPeoples = new List(); OldSainPeoples = new List(); OldInfectedPeoples = new List(); OldImmunesPeoples = new List(); OldDeadPeoples = new List(); 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 CopyPopulations(List ListToCopy) { List ListToCopyInto = new List(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(OldDeadPeoples.Count); ImmunesPeoples = new List(OldImmunesPeoples.Count); SainPeoples = new List(OldSainPeoples.Count); InfectedPeoples = new List(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; } } }