commit 7028323a80cebfbc2fa67926bce4fb5d16ae7e7f Author: Markus Birth Date: Thu Jan 29 23:44:45 2009 +0100 Initial import 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