From 7028323a80cebfbc2fa67926bce4fb5d16ae7e7f Mon Sep 17 00:00:00 2001 From: Markus Birth Date: Thu, 29 Jan 2009 23:44:45 +0100 Subject: [PATCH] Initial import --- Einwohner.cs | 72 +++++++++++++++++++++++ FastPixel.cs | 139 +++++++++++++++++++++++++++++++++++++++++++++ Output.cs | 16 ++++++ Output_CLI.cs | 112 ++++++++++++++++++++++++++++++++++++ Output_GUI.cs | 148 ++++++++++++++++++++++++++++++++++++++++++++++++ Position.cs | 19 +++++++ Program.cs | 29 ++++++++++ Settings.cs | 41 ++++++++++++++ Spielfeld.cs | 38 +++++++++++++ Spielfigur.cs | 37 ++++++++++++ Spielflaeche.cs | 83 +++++++++++++++++++++++++++ Typliste.cs | 7 +++ Vampir.cs | 72 +++++++++++++++++++++++ vampi.csproj | 89 +++++++++++++++++++++++++++++ vampi.sln | 20 +++++++ 15 files changed, 922 insertions(+) create mode 100644 Einwohner.cs create mode 100644 FastPixel.cs create mode 100644 Output.cs create mode 100644 Output_CLI.cs create mode 100644 Output_GUI.cs create mode 100644 Position.cs create mode 100644 Program.cs create mode 100644 Settings.cs create mode 100644 Spielfeld.cs create mode 100644 Spielfigur.cs create mode 100644 Spielflaeche.cs create mode 100644 Typliste.cs create mode 100644 Vampir.cs create mode 100644 vampi.csproj create mode 100644 vampi.sln diff --git a/Einwohner.cs b/Einwohner.cs new file mode 100644 index 0000000..afd2345 --- /dev/null +++ b/Einwohner.cs @@ -0,0 +1,72 @@ +using System; + +namespace vampi +{ + class Einwohner : Spielfigur { + + private static int count = 0; + public static int Count { + get { return Einwohner.count; } + } + private bool infected = false; + public bool Infected { + get { return this.infected; } + } + public static int legalSexAge = Settings.humanLegalSexAge; + public static int vampireConversionRate = Settings.humanVampireConversionPercent; + + public Einwohner(Spielfeld sfeld) + : base(sfeld) { + this.typ = Typliste.EINWOHNER; + this.maxAge = Settings.humanMaxAge; + this.age = Program.random.Next(0, Settings.humanMaxInitAge); + Einwohner.count++; + } + + public void infect() { + if (this.infected) + return; + this.infected = true; + if (this.age < this.maxAge - Settings.humanInfectedMaxAge) this.age = this.maxAge - Settings.humanInfectedMaxAge; + } + + public override void die() { + Einwohner.count--; + if (this.infected) { + int rvalue = Program.random.Next(0, 100); + if (rvalue <= Einwohner.vampireConversionRate) { + new Vampir(this.sfeld); + return; + } + } + base.die(); + } + + public override void runStep() { + base.runStep(); + + if (this.infected && !Settings.humanInfectedCanReproduceWithNormal) return; + + // search for constraints (empty field, partner to mate > 10 yrs) + Spielfeld birthplace = null; + bool mateFound = false; + for (int i = 1; i <= 8; i++) { + Spielfeld neighbor = this.sfeld.getNachbarfeld(i); + if (neighbor != null && neighbor.Sfigur != null) { + if (neighbor.Sfigur.Typ == Typliste.EINWOHNER) { + if (neighbor.Sfigur.Age >= Einwohner.legalSexAge && (Settings.humanNormalCanReproduceWithInfected || !((Einwohner)neighbor.Sfigur).Infected)) { + mateFound = true; + } + } + } else if (neighbor != null && neighbor.Sfigur == null) { + birthplace = neighbor; + } + } + // reproduce! + if (mateFound && birthplace != null) { + new Einwohner(birthplace); + } + + } + } +}//namespace diff --git a/FastPixel.cs b/FastPixel.cs new file mode 100644 index 0000000..ed56cda --- /dev/null +++ b/FastPixel.cs @@ -0,0 +1,139 @@ +using System; +using System.Drawing; +using System.Drawing.Imaging; + +class FastPixel { + private byte[] rgbValues; + private BitmapData bmpData; + private IntPtr bmpPtr; + private bool locked = false; + + private bool _isAlpha = false; + private Bitmap _bitmap; + private int _width; + private int _height; + + public int Width { + get { return this._width; } + } + + public int Height { + get { return this._height; } + } + + public bool IsAlphaBitmap { + get { return this._isAlpha; } + } + + public Bitmap Bitmap { + get { return this._bitmap; } + } + + public FastPixel(Bitmap bitmap) { + if (bitmap.PixelFormat == (bitmap.PixelFormat | PixelFormat.Indexed)) + throw new Exception("Cannot lock an Indexed image."); + + this._bitmap = bitmap; + this._isAlpha = (this.Bitmap.PixelFormat == (this.Bitmap.PixelFormat | PixelFormat.Alpha)); + this._width = bitmap.Width; + this._height = bitmap.Height; + } + + public void Lock() { + if (this.locked) + throw new Exception("Bitmap already locked."); + + Rectangle rect = new Rectangle(0, 0, this.Width, this.Height); + this.bmpData = this.Bitmap.LockBits(rect, ImageLockMode.ReadWrite, this.Bitmap.PixelFormat); + this.bmpPtr = this.bmpData.Scan0; + + int bytes; + if (this.IsAlphaBitmap) { + bytes = (this.Width * this.Height) * 4; + } else { + bytes = (this.Width * this.Height) * 3; + } + this.rgbValues = new byte[bytes]; + System.Runtime.InteropServices.Marshal.Copy(this.bmpPtr, rgbValues, 0, this.rgbValues.Length); + this.locked = true; + } + + public void Unlock(bool setPixels) { + if (!this.locked) + throw new Exception("Bitmap not locked."); + + // Copy the RGB values back to the bitmap; + if (setPixels) + System.Runtime.InteropServices.Marshal.Copy(this.rgbValues, 0, this.bmpPtr, this.rgbValues.Length); + + // Unlock the bits.; + this.Bitmap.UnlockBits(bmpData); + this.locked = false; + } + + public void Clear(Color colour) { + if (!this.locked) + throw new Exception("Bitmap not locked."); + + if (this.IsAlphaBitmap) { + for (int index = 0; index < this.rgbValues.Length; index += 4) { + this.rgbValues[index] = colour.B; + this.rgbValues[index + 1] = colour.G; + this.rgbValues[index + 2] = colour.R; + this.rgbValues[index + 3] = colour.A; + } + } else { + for (int index = 0; index < this.rgbValues.Length; index += 3) { + this.rgbValues[index] = colour.B; + this.rgbValues[index + 1] = colour.G; + this.rgbValues[index + 2] = colour.R; + } + } + } + + public void SetPixel(Point location, Color colour) { + this.SetPixel(location.X, location.Y, colour); + } + + public void SetPixel(int x, int y, Color colour) { + if (!this.locked) + throw new Exception("Bitmap not locked."); + + if (this.IsAlphaBitmap) { + int index = ((y * this.Width + x) * 4); + this.rgbValues[index] = colour.B; + this.rgbValues[index + 1] = colour.G; + this.rgbValues[index + 2] = colour.R; + this.rgbValues[index + 3] = colour.A; + } else { + int index = ((y * this.Width + x) * 3); + this.rgbValues[index] = colour.B; + this.rgbValues[index + 1] = colour.G; + this.rgbValues[index + 2] = colour.R; + } + } + + public Color GetPixel(Point location) { + return this.GetPixel(location.X, location.Y); + } + + public Color GetPixel(int x, int y) { + if (!this.locked) + throw new Exception("Bitmap not locked."); + + if (this.IsAlphaBitmap) { + int index = ((y * this.Width + x) * 4); + int b = this.rgbValues[index]; + int g = this.rgbValues[index + 1]; + int r = this.rgbValues[index + 2]; + int a = this.rgbValues[index + 3]; + return Color.FromArgb(a, r, g, b); + } else { + int index = ((y * this.Width + x) * 3); + int b = this.rgbValues[index]; + int g = this.rgbValues[index + 1]; + int r = this.rgbValues[index + 2]; + return Color.FromArgb(r, g, b); + } + } +} \ No newline at end of file diff --git a/Output.cs b/Output.cs new file mode 100644 index 0000000..36d162d --- /dev/null +++ b/Output.cs @@ -0,0 +1,16 @@ +// Output.cs created with MonoDevelop at 4:40 PM 1/29/2009 +// @author mbirth + +using System; + +namespace vampi { + public abstract class Output { + public bool requestAbort = false; + + public Output() { + } + + public virtual void doOutput() { + } + } +} diff --git a/Output_CLI.cs b/Output_CLI.cs new file mode 100644 index 0000000..79d1029 --- /dev/null +++ b/Output_CLI.cs @@ -0,0 +1,112 @@ +// Output_CLI.cs created with MonoDevelop at 5:34 PM 1/29/2009 +// @author mbirth + +using System; + +namespace vampi { + public class Output_CLI : Output { + + public Output_CLI() { + Console.BackgroundColor = ConsoleColor.Black; + //Console.CursorVisible = false; + Console.SetWindowSize(1, 1); + /* + Console.SetBufferSize(Console.LargestWindowWidth, Console.LargestWindowHeight); + Console.SetWindowSize(Console.LargestWindowWidth, Console.LargestWindowHeight); + */ + if (System.Environment.OSVersion.Platform.ToString() != "Unix") { + Console.SetBufferSize(Settings.size + 2, Settings.size + 8); + Console.SetWindowSize(Settings.size + 2, Settings.size + 8); + } + Console.Title = "Vampi CLI --- ©2008 Markus Birth, FA76"; + Console.Clear(); + } + + ~Output_CLI() { + Console.Read(); + } + + public override void doOutput() { + this.drawGameMap(); + this.drawStatistics(); + } + + public void testSpielfeld() { + Position pos; + Spielfeld nachbarfeld; + + //Schleife ueber alle Spielfelder + for (int y = 1; y <= Settings.size; y++) { + for (int x = 1; x <= Settings.size; x++) { + pos.x = x; + pos.y = y; + + Console.SetCursorPosition(x, y); + Console.BackgroundColor = ConsoleColor.Green; + Console.Write(' '); + + //Schleife ueber alle Nachbarfelder eines Spielfeldes + for (int lage = 1; lage <= 8; lage++) { + nachbarfeld = Program.sflaeche.getSpielfeld(pos).getNachbarfeld(lage); + + if (nachbarfeld != null) { //Nachbarfeld existiert + Console.SetCursorPosition(nachbarfeld.Pos.x, nachbarfeld.Pos.y); + + Console.BackgroundColor = ConsoleColor.Red; + Console.Write(' '); + + Console.SetCursorPosition(nachbarfeld.Pos.x, nachbarfeld.Pos.y); + + System.Threading.Thread.Sleep(10); + + Console.BackgroundColor = ConsoleColor.Gray; + Console.Write(' '); + } + } + Console.SetCursorPosition(x, y); + Console.BackgroundColor = ConsoleColor.Gray; + Console.Write(' '); + }//for + }//for + } + + public void drawGameMap() { + Position pos; + Console.SetCursorPosition(0, 0); + for (pos.y = 1; pos.y <= Settings.size; pos.y++) { + for (pos.x = 1; pos.x <= Settings.size; pos.x++) { + Spielfigur sf = Program.sflaeche.getSpielfeld(pos).Sfigur; + + if (sf == null) //Spielfeld leer + Console.BackgroundColor = Settings.colorEmpty; + else { //Spielfeld besetzt + switch (sf.Typ) { + case Typliste.EINWOHNER: + if (((Einwohner)sf).Infected) + Console.BackgroundColor = Settings.colorHumanInfected; + else + Console.BackgroundColor = Settings.colorHuman; + break; + case Typliste.VAMPIR: + Console.BackgroundColor = Settings.colorVampire; + break; + }//switch + }//else + Console.Write(' '); + }//for + Console.WriteLine(); + }//for + Console.ResetColor(); + } + + public void drawStatistics() { + int Ecount = Einwohner.Count; // sflaeche.countTypeOccurrences(Typliste.EINWOHNER); + int Vcount = Vampir.Count; // sflaeche.countTypeOccurrences(Typliste.VAMPIR); + Console.WriteLine("\n" + String.Format("Steps Done: {0:D5} ", Program.AnzSimDone)); + Console.WriteLine(String.Format("Einwohner: {0:D} / Vampire: {1:D} ", Ecount, Vcount)); + Console.WriteLine(String.Format("Verhältnis Vampire/Einwohner = 1/{0:N5} ", (double)Ecount / Vcount)); + Console.WriteLine(String.Format("Bedeckung: {0:N5} %", (double)(Ecount + Vcount) / Settings.size*Settings.size * 100) + " "); + } + + } +} diff --git a/Output_GUI.cs b/Output_GUI.cs new file mode 100644 index 0000000..a8b389a --- /dev/null +++ b/Output_GUI.cs @@ -0,0 +1,148 @@ +// Output_GUI.cs created with MonoDevelop at 6:00 PM 1/29/2009 +// @author mbirth + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; + +namespace vampi { + + public class Output_GUI : Output { + const int statsHeight = 45; + double scale = 1; + Form f = new Form(); + FastPixel fp; + Graphics fg; + Bitmap field; + Bitmap stats; + + public Output_GUI() { + field = new Bitmap(Settings.size, Settings.size, System.Drawing.Imaging.PixelFormat.Format24bppRgb); + stats = new Bitmap(300, Output_GUI.statsHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb); + fp = new FastPixel(field); + fg = Graphics.FromHwnd(f.Handle); + fg.InterpolationMode = InterpolationMode.NearestNeighbor; + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + f.Text = "Vampi GUI --- ©2008 Markus Birth, FA76"; + + // attach some events + f.Closing += new System.ComponentModel.CancelEventHandler(FormClosing); // fires when "X" clicked + f.Resize += new EventHandler(FormResize); // fires while resizing + f.ResizeEnd += new EventHandler(FormResize); // fires after finish resizing or moving window + + // clear gameField with emptyColor + Graphics g = Graphics.FromImage(this.field); + g.Clear(Settings.guiColorEmpty); + g.Dispose(); + + fg.Clear(Color.White); // clear window background + calculateScale(); + f.Show(); + } + + ~Output_GUI() { + fg.Dispose(); + f.Dispose(); + } + + public void FormClosing(object sender, System.ComponentModel.CancelEventArgs e) { + requestAbort = true; + f.Hide(); + } + + public void calculateScale() { + scale = (double)(Math.Min(f.ClientSize.Height - Output_GUI.statsHeight, f.ClientSize.Width) / Settings.size); + } + + public void FormResize(object sender, EventArgs e) { + calculateScale(); + fg = Graphics.FromHwnd(f.Handle); + fg.InterpolationMode = InterpolationMode.NearestNeighbor; + fg.Clear(Color.White); + } + + public override void doOutput() { + this.drawGameMap(); + if (Program.AnzSimDone % 2 == 0) this.drawStatistics(); + Application.DoEvents(); + } + + protected Color getGradient(Color[] gradientMap, double percent) { + int mapSteps = gradientMap.GetLength(0)-1; + double percSteps = 100/(double)mapSteps; + int bestMatch = (int)(percent/percSteps); + if (percent/percSteps == Math.Floor(percent/percSteps)) return gradientMap[bestMatch]; + int curStep = (int)Math.Floor(percent/percSteps); + if (curStep == gradientMap.GetLength(0)-1) curStep--; + Color left = gradientMap[curStep]; + double leftPerc = curStep*percSteps; + Color right = gradientMap[curStep+1]; + double rightPerc = (curStep+1)*percSteps; + + percent = (percent-leftPerc) * (100/(rightPerc-leftPerc)); + + Color final = Color.FromArgb(getPercentage(left.R, right.R, percent), getPercentage(left.G, right.G, percent), getPercentage(left.B, right.B, percent)); + + return final; + } + + protected Color getGradient(Color fixedColor, double percent) { + return fixedColor; + } + + protected byte getPercentage(byte col1, byte col2, double percent) { + return (byte)(col1 + (col2-col1)*percent/100); + } + + public void drawGameMap() { + fp.Lock(); + Position pos; + Color c = Color.Black; + for (pos.y = 1; pos.y <= Settings.size; pos.y++) { + for (pos.x = 1; pos.x <= Settings.size; pos.x++) { + Spielfigur sf = Program.sflaeche.getSpielfeld(pos).Sfigur; + + if (sf == null) c = Settings.guiColorEmpty; //Spielfeld leer + else { //Spielfeld besetzt + switch (sf.Typ) { + case Typliste.EINWOHNER: + if (((Einwohner)sf).Infected) + c = getGradient(Settings.guiColorHumanInfected, 100-(double)(sf.Age-Settings.humanMaxAge+Settings.humanInfectedMaxAge)*100/(double)Settings.humanInfectedMaxAge); + else + c = getGradient(Settings.guiColorHuman, 100-(double)sf.Age*100/(double)Settings.humanMaxAge); + break; + case Typliste.VAMPIR: + c = getGradient(Settings.guiColorVampire, 100-(double)sf.Age*100/(double)Settings.vampireMaxAge); + break; + } + } + fp.SetPixel(pos.x-1, pos.y-1, c); + } + } + fp.Unlock(true); + fg.DrawImage(this.field, 0, Output_GUI.statsHeight, (int)(Settings.size * this.scale), (int)(Settings.size * this.scale)); + f.Update(); + } + + public void drawStatistics() { + if (!f.Visible) this.requestAbort = true; + Graphics g = Graphics.FromImage(this.stats); + g.Clear(Color.White); + int lineSpc = 10; + + int Ecount = Einwohner.Count; // sflaeche.countTypeOccurrences(Typliste.EINWOHNER); + int Vcount = Vampir.Count; // sflaeche.countTypeOccurrences(Typliste.VAMPIR); + g.DrawString(String.Format("Steps Done: {0:D5}", Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 0); + g.DrawString(String.Format(String.Format("Einwohner: {0:D} / Vampire: {1:D}", Ecount, Vcount), Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 1*lineSpc); + g.DrawString(String.Format(String.Format("Verhältnis Vampire/Einwohner = 1/{0:N5}", (double)Ecount / Vcount), Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 2*lineSpc); + g.DrawString(String.Format(String.Format("Bedeckung: {0:N5} %", (double)(Ecount + Vcount) / (Settings.size*Settings.size) * 100), Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 3*lineSpc); + g.Dispose(); + g = Graphics.FromHwnd(f.Handle); + g.DrawImageUnscaled(this.stats, 0, 0); + g.Dispose(); + } + } +} diff --git a/Position.cs b/Position.cs new file mode 100644 index 0000000..7cba167 --- /dev/null +++ b/Position.cs @@ -0,0 +1,19 @@ +using System; + +namespace vampi { + public struct Position { + public int x; + public int y; + + public Position(int x, int y) { + this.x = x; + this.y = y; + } + + public Position(Position pos) { + this.x = pos.x; + this.y = pos.y; + } + } + +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..3d8be8b --- /dev/null +++ b/Program.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Timers; + +namespace vampi { + class Program { + private static int anz_sim = 100000; + private static int anz_sim_done = 0; + public static int AnzSimDone { + get { return Program.anz_sim_done; } + } + public static Random random = new Random(); + public static Spielflaeche sflaeche = new Spielflaeche(Settings.size, Settings.coveragePercent, Settings.vampireRatio); + + static void Main(string[] args) { + Output output = new Output_GUI(); + + for (anz_sim_done=0; anz_sim_done < anz_sim; anz_sim_done++) { + if (anz_sim_done % Settings.drawEveryNthStep == 0) { + output.doOutput(); + } + if (output.requestAbort) break; + sflaeche.simulateStep(); + } + }//Main + }//class +}//namespace diff --git a/Settings.cs b/Settings.cs new file mode 100644 index 0000000..55a8d2f --- /dev/null +++ b/Settings.cs @@ -0,0 +1,41 @@ +using System; +using System.Drawing; + +namespace vampi { + public abstract class Settings { + public const int size = 43; + public const int coveragePercent = 77; + public const int vampireRatio = 3; + public const int drawEveryNthStep = 1; + + public const ConsoleColor colorHuman = ConsoleColor.Green; + public const ConsoleColor colorHumanInfected = ConsoleColor.DarkMagenta; + public const ConsoleColor colorVampire = ConsoleColor.Red; + public const ConsoleColor colorEmpty = ConsoleColor.Gray; + + public static Color[] guiColorHuman = {Color.FromArgb(0, 60, 0), Color.LimeGreen}; + public static Color[] guiColorHumanInfected = {Color.FromArgb(60, 0, 60), Color.DarkMagenta}; + public static Color[] guiColorVampire = {Color.FromArgb(60, 0, 0), Color.Red}; + public static Color guiColorEmpty = Color.Gray; + + public static Font guiFont = new Font("sans-serif", 8); + public static Brush guiFontBrush = Brushes.Black; + + public const int humanLegalSexAge = 10; + public const int humanVampireConversionPercent = 5; + public const int humanMaxInitAge = 10; + public const int humanMaxAge = 80; + public const int humanInfectedMaxAge = 20; + public const bool humanInfectedCanReproduceWithNormal = false; + public const bool humanNormalCanReproduceWithInfected = false; + + public const int vampireInitialFill = 100; + public const int vampireMaxInitAge = 60; + public const int vampireMaxAge = 500; + public const int vampireDecreaseFillPerStep = 3; + public const int vampireIncreaseFillPerBite = 1; + public const bool vampireInfectOnlyOneHuman = false; + public const bool vampireInfectOneOrMoreHumans = false; + + } +} diff --git a/Spielfeld.cs b/Spielfeld.cs new file mode 100644 index 0000000..5f36802 --- /dev/null +++ b/Spielfeld.cs @@ -0,0 +1,38 @@ +using System; + +namespace vampi +{ + public class Spielfeld { + private Position pos; + private Spielflaeche sflaeche; + private Spielfigur sfigur = null; + private int[] mx = {-1, 0, 1, 1, 1, 0, -1, -1}; + private int[] my = {-1, -1, -1, 0, 1, 1, 1, 0}; + + public Spielfigur Sfigur { + get { return this.sfigur; } + set { this.sfigur = value; } + } + + public Position Pos { + get { return pos; } + } + + public Spielfeld(Position pos, Spielflaeche sflaeche) { + this.pos = pos; + this.sflaeche = sflaeche; + } + + public Spielfeld getNachbarfeld(int lage) { + return this.sflaeche.getSpielfeld(this.getNachbarpos(lage)); + } + + private Position getNachbarpos(int lage) { + Position nachbarpos = new Position(this.pos); + nachbarpos.x += mx[lage - 1]; + nachbarpos.y += my[lage - 1]; + return nachbarpos; + } + + } +} diff --git a/Spielfigur.cs b/Spielfigur.cs new file mode 100644 index 0000000..658b9d1 --- /dev/null +++ b/Spielfigur.cs @@ -0,0 +1,37 @@ +using System; + +namespace vampi +{ + public abstract class Spielfigur { + protected Spielfeld sfeld; + protected int typ; + protected int maxAge = 80; + protected int age = -1; + public int Age { + get { return this.age; } + } + + public int Typ { + get { return this.typ; } + } + + public Spielfigur(Spielfeld sfeld) { + sfeld.Sfigur = this; + this.sfeld = sfeld; + } + + public virtual void runStep() { + if (this.age != -1) { + this.age++; + if (this.age >= this.maxAge) { + this.die(); + } + } + } + + public virtual void die() { + this.sfeld.Sfigur = null; + } + } + +} \ No newline at end of file diff --git a/Spielflaeche.cs b/Spielflaeche.cs new file mode 100644 index 0000000..0b675bd --- /dev/null +++ b/Spielflaeche.cs @@ -0,0 +1,83 @@ +using System; + +namespace vampi { + public class Spielflaeche { + private Spielfeld[,] sfeld_2dim; + private int groesse; + public int Groesse { + get { return sfeld_2dim.GetLength(0) * sfeld_2dim.GetLength(1); } + } + + public Spielflaeche(int groesse) { + this.groesse = groesse; + sfeld_2dim = new Spielfeld[groesse, groesse]; + for (int i = 0; i < groesse; i++) { + for (int j = 0; j < groesse; j++) { + sfeld_2dim[i, j] = new Spielfeld(new Position(i+1, j+1), this); + } + } + } + + public Spielflaeche(int groesse, int initBedeckung, int initVerhaeltnis) : this(groesse) { + initSpielfeld(initBedeckung, initVerhaeltnis); + } + + private void initSpielfeld(int initBedeckung, int initVerhaeltnis) { + // INFO: Andere Idee: Spielfeld linear befüllen, danach alle Felder durchgehen + // und das aktuelle Feld jeweils mit einem zufälligen Feld tauschen + int feldX, feldY; + int bedeckung = this.groesse * this.groesse * initBedeckung / 100; // groesse^2 * Prozent + int vampire = (int)Math.Round((double)bedeckung / (initVerhaeltnis+1)); // Felder / (Verhaeltnis+1) + + for (int i = bedeckung; i > 0; i--) { + // find an empty, random field + do { + feldX = Program.random.Next(0, this.groesse); + feldY = Program.random.Next(0, this.groesse); + } while (this.sfeld_2dim[feldX, feldY].Sfigur != null); + + // first set all vampires then set inhabitants + if (vampire > 0) { + new Vampir(this.sfeld_2dim[feldX, feldY]); + vampire--; + } else { + new Einwohner(this.sfeld_2dim[feldX, feldY]); + } + } + } + + public Spielfeld getSpielfeld(Position pos) { + if (pos.x > this.groesse) + pos.x -= this.groesse; // should be 1 + if (pos.x < 1) + pos.x += this.groesse; // should be this.groesse + + if (pos.y > this.groesse || pos.y < 1) { + // y-direction doesn't wrap + return null; + } + + return sfeld_2dim[pos.x-1, pos.y-1]; + } + + public int countTypeOccurrences(int typ) { + int result = 0; + for (int i = 0; i < this.groesse; i++) { + for (int j = 0; j < this.groesse; j++) { + if (this.sfeld_2dim[i, j].Sfigur != null && this.sfeld_2dim[i, j].Sfigur.Typ == typ) + result++; + } + } + return result; + } + + public void simulateStep() { + for (int i = 0; i < this.groesse; i++) { + for (int j = 0; j < this.groesse; j++) { + if (this.sfeld_2dim[i, j].Sfigur != null) + this.sfeld_2dim[i, j].Sfigur.runStep(); + } + } + } + } +} diff --git a/Typliste.cs b/Typliste.cs new file mode 100644 index 0000000..97ce6d3 --- /dev/null +++ b/Typliste.cs @@ -0,0 +1,7 @@ +namespace vampi +{ + public abstract class Typliste { + public const int EINWOHNER = 1; + public const int VAMPIR = 2; + } +} diff --git a/Vampir.cs b/Vampir.cs new file mode 100644 index 0000000..ef13d29 --- /dev/null +++ b/Vampir.cs @@ -0,0 +1,72 @@ +using System; + +namespace vampi +{ + class Vampir : Spielfigur { + + private static int count = 0; + public static int Count { + get { return Vampir.count; } + } + private int filler = Settings.vampireInitialFill; + + public Vampir(Spielfeld sfeld) + : base(sfeld) { + this.typ = Typliste.VAMPIR; + this.maxAge = Settings.vampireMaxAge; + this.age = Program.random.Next(0, Settings.vampireMaxInitAge); + Vampir.count++; + } + + public override void die() { + base.die(); + Vampir.count--; + } + + public override void runStep() { + base.runStep(); + this.filler -= Settings.vampireDecreaseFillPerStep; + if (this.filler <= 0) { + this.die(); + return; + } + + // count humans around me + int humans = 0; + for (int i = 1; i <= 8; i++) { + Spielfeld neighbor = this.sfeld.getNachbarfeld(i); + if (neighbor != null && neighbor.Sfigur != null) { + if (neighbor.Sfigur.Typ == Typliste.EINWOHNER) { + if (Settings.vampireInfectOnlyOneHuman) { + humans++; + } else { + ((Einwohner)neighbor.Sfigur).infect(); + this.filler += Settings.vampireIncreaseFillPerBite; + // humans is still 0, so runStep() will return after this + } + } + } + } + + if (humans == 0) + return; + + // randomly infect one human + int infect = Program.random.Next(0, humans); + + for (int i = 1; i <= 8; i++) { + Spielfeld neighbor = this.sfeld.getNachbarfeld(i); + if (neighbor != null && neighbor.Sfigur != null && neighbor.Sfigur.Typ == Typliste.EINWOHNER) { + if (infect == 0) { + ((Einwohner)neighbor.Sfigur).infect(); + this.filler += Settings.vampireIncreaseFillPerBite; + if (!Settings.vampireInfectOneOrMoreHumans) break; + } else { + infect--; + } + } + } + } // runStep() + } + +} \ No newline at end of file diff --git a/vampi.csproj b/vampi.csproj new file mode 100644 index 0000000..04a6597 --- /dev/null +++ b/vampi.csproj @@ -0,0 +1,89 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {5B1E4D8C-3337-4F8F-B90C-B70FB70F3DFA} + Exe + Properties + vampi + vampi + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + Exe + vampi + vampi + false + true + . + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + Exe + vampi + true + vampi + false + true + . + + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vampi.sln b/vampi.sln new file mode 100644 index 0000000..eec1f74 --- /dev/null +++ b/vampi.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vampi", "vampi.csproj", "{5B1E4D8C-3337-4F8F-B90C-B70FB70F3DFA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5B1E4D8C-3337-4F8F-B90C-B70FB70F3DFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B1E4D8C-3337-4F8F-B90C-B70FB70F3DFA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B1E4D8C-3337-4F8F-B90C-B70FB70F3DFA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B1E4D8C-3337-4F8F-B90C-B70FB70F3DFA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal