/// <summary> /// Findet alle Spielelemente innerhalb des Sichtkreis der gegebenen Wanze. /// </summary> /// <remarks> /// Die Simulation legt ein Gitter mit der maximalen Sichtweite der Wanzen als /// Seitenlänge an und benutzt diese Methode auf dieser Instanz zum Finden von /// Ameisen. In dieses Gitter werden nur Ameisen einsortiert. /// </remarks> /// <param name="bug">Die Referenzwanze.</param> /// <returns>Eine Liste von Ameisen.</returns> public List <T> FindAnts(CoreBug bug) { // Speichert alle gefundenen Ameisen. List <T> ants = new List <T>(); // Bestimme die Zelle in der die übergebene Wanze sich befindet. int col = bug.CoordinateBase.X / sideLength; int row = bug.CoordinateBase.Y / sideLength; // Betrachte die Zelle und die acht Zellen daneben. for (int c = -1; c <= 1; c++) { if (col + c >= 0 && col + c < columns) { for (int r = -1; r <= 1; r++) { if (row + r >= 0 && row + r < rows) { List <T> cell = cells[col + c, row + r]; for (int i = 0; i < cell.Count; i++) { int distance = CoreCoordinate.BestimmeEntfernungI(bug.CoordinateBase, cell[i].CoordinateBase); if (distance <= sideLength) { ants.Add(cell[i]); } } } } } } return(ants); }
/// <summary> /// Bestimmt die Entfernung zweier Koordinaten auf dem Spielfeld in der /// internen Einheit ohne Beachtung der Radien. /// </summary> /// <param name="k1">Koordinate 1.</param> /// <param name="k2">Koordinate 2.</param> /// <returns>Die Entfernung.</returns> internal static int BestimmeEntfernungDerMittelpunkteI(CoreCoordinate k1, CoreCoordinate k2) { double deltaX = k1.x - k2.x; double deltaY = k1.y - k2.y; return((int)Math.Round(Math.Sqrt(deltaX * deltaX + deltaY * deltaY))); }
/// <summary> /// Erzeugt eine neue Instanz der Markierung-Klasse. /// </summary> /// <param name="koordinate">Die Koordinate der Markierung.</param> /// <param name="endgröße">Die Ausbreitung der Markierung in Schritten. /// </param> /// <param name="colonyId">ID des Volkes</param> internal CoreMarker(CoreCoordinate koordinate, int endgröße, int colonyId) { this.colonyId = colonyId; Id = neueId++; this.koordinate = koordinate; // Volumen der kleinsten Markierung (r³ * PI/2) ermitteln (Halbkugel) double baseVolume = Math.Pow(SimulationSettings.Custom.MarkerSizeMinimum, 3) * (Math.PI / 2); // Korrektur für größere Markierungen baseVolume *= 10f; // Gesamtvolumen über die volle Zeit ermitteln double totalvolume = baseVolume * SimulationSettings.Custom.MarkerMaximumAge; // Maximale Markergröße ermitteln int maxSize = (int)Math.Pow(4 * ((totalvolume - baseVolume) / Math.PI), 1f / 3f); // Gewünschte Zielgröße limitieren (Min Markersize, Max MaxSize) this.endgröße = Math.Max(SimulationSettings.Custom.MarkerSizeMinimum, Math.Min(maxSize, endgröße)); // Volumen für die größte Markierung ermitteln int diffRadius = this.endgröße - SimulationSettings.Custom.MarkerSizeMinimum; double diffVolume = Math.Pow(diffRadius, 3) * (Math.PI / 4); // Lebenszeit bei angestrebter Gesamtgröße ermitteln totalAge = (int)Math.Floor(totalvolume / (baseVolume + diffVolume)); Aktualisieren(); }
/// <summary> /// Erzeugt eine neue Instanz der Koordinate-Struktur ausgehend von einer /// bestehenden Koordinate. /// </summary> /// <param name="k">Die bestehende Koordinate.</param> /// <param name="deltaX">Der X-Wert relativ zu der Koordinate.</param> /// <param name="deltaY">Der Y-Wert relativ zu der Koordinate.</param> internal CoreCoordinate(CoreCoordinate k, int deltaX, int deltaY) { x = k.x + deltaX; y = k.y + deltaY; radius = k.radius; richtung = k.richtung; }
/// <summary> /// Bestimmt die Richtung von einer Koordinate auf dem Spielfeld zu einer /// anderen. /// </summary> /// <param name="k1">Die Start Koordinate.</param> /// <param name="k2">Die Ziel Koordinate.</param> /// <returns>Die Richtung.</returns> internal static int BestimmeRichtung(CoreCoordinate k1, CoreCoordinate k2) { int richtung = (int)Math.Round(Math.Atan2(k2.Y - k1.Y, k2.X - k1.X) * 180d / Math.PI); if (richtung < 0) { richtung += 360; } return(richtung); }
/// <summary> /// Entfernt abgelaufene Markierungen und erzeugt neue Markierungen. /// </summary> /// <param name="colony">betroffenes Volk</param> private static void aktualisiereMarkierungen(CoreColony colony) { // TODO: Settings berücksichtigen // Markierungen aktualisieren und inaktive Markierungen löschen. List <CoreMarker> gemerkteMarkierungen = new List <CoreMarker>(); foreach (CoreMarker markierung in colony.Marker) { if (markierung.IstAktiv) { markierung.Aktualisieren(); } else { gemerkteMarkierungen.Add(markierung); } } gemerkteMarkierungen.ForEach(delegate(CoreMarker marker) { colony.Insects.ForEach(delegate(CoreInsect insect) { CoreAnt ant = insect as CoreAnt; if (ant != null) { ant.SmelledMarker.Remove(marker); } }); }); colony.Marker.Remove(gemerkteMarkierungen); // Neue Markierungen überprüfen und hinzufügen. gemerkteMarkierungen.Clear(); colony.NewMarker.ForEach(delegate(CoreMarker newMarker) { bool zuNah = false; foreach (CoreMarker markierung in colony.Marker) { int entfernung = CoreCoordinate.BestimmeEntfernungDerMittelpunkteI (markierung.CoordinateBase, newMarker.CoordinateBase); if (entfernung < SimulationSettings.Custom.MarkerDistance * PLAYGROUND_UNIT) { zuNah = true; break; } } if (!zuNah) { colony.Marker.Add(newMarker); } }); colony.NewMarker.Clear(); }
/// <summary> /// Prüft ob eine Ameise ein Obsstück sieht. /// </summary> /// <param name="ameise">betroffene Ameise</param> private void ameiseUndObst(CoreAnt ameise) { for (int i = 0; i < Playground.Fruits.Count; i++) { CoreFruit obst = Playground.Fruits[i]; int entfernung = CoreCoordinate.BestimmeEntfernungI(ameise.CoordinateBase, obst.CoordinateBase); if (ameise.ZielBase != obst && entfernung <= ameise.SichtweiteI) { PlayerCall.Spots(ameise, obst); } } }
/// <summary> /// Prüft ob eine Ameise einen Zuckerhaufen sieht. /// </summary> /// <param name="ant">betroffene Ameise</param> private void ameiseUndZucker(CoreAnt ant) { for (int i = 0; i < Playground.SugarHills.Count; i++) { CoreSugar sugar = Playground.SugarHills[i]; int entfernung = CoreCoordinate.BestimmeEntfernungI(ant.CoordinateBase, sugar.CoordinateBase); if (ant.ZielBase != sugar && entfernung <= ant.SichtweiteI) { PlayerCall.Spots(ant, sugar); } } }
/// <summary> /// Bestimmt die Entfernung zweier Koordinaten auf dem Spielfeld in der /// internen Einheit. /// </summary> /// <param name="k1">Koordinate 1.</param> /// <param name="k2">Koordinate 2.</param> /// <returns>Die Entfernung.</returns> internal static int BestimmeEntfernungI(CoreCoordinate k1, CoreCoordinate k2) { double deltaX = k1.x - k2.x; double deltaY = k1.y - k2.y; int entfernung = (int)Math.Round(Math.Sqrt(deltaX * deltaX + deltaY * deltaY)); entfernung = entfernung - k1.radius - k2.radius; if (entfernung < 0) { return(0); } return(entfernung); }
/// <summary> /// Findet alle Spielelemente innerhalb des gegebenen Sichtkreis des gegebenen Spielelements. /// </summary> /// <param name="coordinate">Das Referenzspielelement.</param> /// <param name="maximumDistance">Die maximale Entfernung.</param> /// <returns>Eine nach Entfernung sortierte Liste von Spielelementen.</returns> public List <T> FindSorted(ICoordinate coordinate, int maximumDistance) { // Speichert alle gefundenen Tupel (Spielelement, Entfernung). List <Tupel> tupels = new List <Tupel>(); // Bestimme die Zelle in der das übergebene Spielelement sich befindet. int col = coordinate.CoordinateBase.X / sideLength; int row = coordinate.CoordinateBase.Y / sideLength; // Betrachte die Zelle und die acht Zellen daneben. for (int c = -1; c <= 1; c++) { if (col + c >= 0 && col + c < columns) { for (int r = -1; r <= 1; r++) { if (row + r >= 0 && row + r < rows) { List <T> cell = cells[col + c, row + r]; for (int i = 0; i < cell.Count; i++) { if (cell[i].Equals(coordinate)) { continue; } int distance = CoreCoordinate.BestimmeEntfernungI(coordinate.CoordinateBase, cell[i].CoordinateBase); if (distance <= maximumDistance) { tupels.Add(new Tupel(cell[i], distance)); } } } } } } // Sortiere die Tupel und gib die Spielelemente zurück. tupels.Sort(comparer); List <T> elements = new List <T>(tupels.Count); for (int i = 0; i < tupels.Count; i++) { elements.Add((T)tupels[i].Element); } return(elements); }
/// <summary> /// Findet die Markierung, die die gegebene Ameise noch nicht gerochen hat /// und die der Ameise am nächsten liegt. /// </summary> /// <remarks> /// Die Simulation legt ein Gitter mit dem maximalen Radius einer Markierung als /// Seitenlänge an und benutzt diese Methode auf dieser Instanz zum Finden von /// Markierungen. In dieses Gitter werden nur Markierungen einsortiert. /// </remarks> /// <param name="ant">Die Referenzameise.</param> /// <returns>Eine Markierung.</returns> public CoreMarker FindMarker(CoreAnt ant) { CoreMarker nearestMarker = null; int nearestMarkerDistance = int.MaxValue; // Bestimme die Zelle in der die übergebene Ameise sich befindet. int col = ant.CoordinateBase.X / sideLength; int row = ant.CoordinateBase.Y / sideLength; // Betrachte die Zelle und die acht Zellen daneben. for (int c = -1; c <= 1; c++) { if (col + c >= 0 && col + c < columns) { for (int r = -1; r <= 1; r++) { if (row + r >= 0 && row + r < rows) { List <T> cell = cells[col + c, row + r]; // Betrachte alle Markierungen in der aktuellen Zelle. for (int i = 0; i < cell.Count; i++) { CoreMarker marker = cell[i] as CoreMarker; Debug.Assert(marker != null); // Bestimme die Entfernung der Mittelpunkte und der Kreise. int distance = CoreCoordinate.BestimmeEntfernungDerMittelpunkteI(ant.CoordinateBase, marker.CoordinateBase); int circleDistance = distance - ant.CoordinateBase.Radius - marker.CoordinateBase.Radius; // Die neue Markierung wurde noch nicht gerochen und // liegt näher als die gemerkte. if (circleDistance <= 0 && distance < nearestMarkerDistance && !ant.SmelledMarker.Contains(marker)) { nearestMarkerDistance = distance; nearestMarker = marker; } } } } } } return(nearestMarker); }
/// <summary> /// Gets the nearest ant hill. /// </summary> /// <returns></returns> public CoreAnthill GetNearestCoreAntHill() { int aktuelleEntfernung; int gemerkteEntfernung = int.MaxValue; CoreAnthill gemerkterBau = null; foreach (CoreAnthill bau in colony.AntHills) { aktuelleEntfernung = CoreCoordinate.BestimmeEntfernungI(CoordinateBase, bau.CoordinateBase); if (aktuelleEntfernung < gemerkteEntfernung) { gemerkterBau = bau; gemerkteEntfernung = aktuelleEntfernung; } } return(gemerkterBau); }
/// <summary> /// Lässt das Insekt Zucker von einem Zuckerhaufen nehmen. /// </summary> /// <param name="zucker">Zuckerhaufen</param> internal void NimmBase(CoreSugar zucker) { if (!NimmBefehleEntgegen) { return; } int entfernung = CoreCoordinate.BestimmeEntfernungI(CoordinateBase, zucker.CoordinateBase); if (entfernung <= SimulationEnvironment.PLAYGROUND_UNIT) { int menge = Math.Min(MaximaleLastBase - aktuelleLast, zucker.Menge); AktuelleLastBase += menge; zucker.Menge -= menge; } else { Thread.Sleep(0); } }
/// <summary> /// Lässt das Insekt zum nächsten Bau gehen. /// </summary> internal void GeheZuBauBase() { if (!NimmBefehleEntgegen) { return; } int aktuelleEntfernung; int gemerkteEntfernung = int.MaxValue; CoreAnthill gemerkterBau = null; foreach (CoreAnthill bau in colony.AntHills) { aktuelleEntfernung = CoreCoordinate.BestimmeEntfernungI(CoordinateBase, bau.CoordinateBase); if (aktuelleEntfernung < gemerkteEntfernung) { gemerkterBau = bau; gemerkteEntfernung = aktuelleEntfernung; } } GeheZuZielBase(gemerkterBau); }
/// <summary> /// Removes fruit from list. /// </summary> /// <param name="colony">winning colony</param> private void removeFruit(CoreColony colony) { //List<CoreFruit> gemerktesObst = new List<CoreFruit>(); for (int j = 0; j < Playground.Fruits.Count; j++) { CoreFruit obst = Playground.Fruits[j]; for (int i = 0; i < colony.AntHills.Count; i++) { CoreAnthill bau = colony.AntHills[i]; if (bau != null) { int entfernung = CoreCoordinate.BestimmeEntfernungI(obst.CoordinateBase, bau.CoordinateBase); if (entfernung <= PLAYGROUND_UNIT) { //gemerktesObst.Add(obst); // Löschen colony.Statistik.CollectedFood += obst.Menge; colony.Statistik.CollectedFruits++; obst.Menge = 0; for (int z = 0; z < obst.TragendeInsekten.Count; z++) { CoreInsect insect = obst.TragendeInsekten[z]; if (insect != null) { insect.GetragenesObstBase = null; insect.AktuelleLastBase = 0; insect.RestStreckeI = 0; insect.RestWinkelBase = 0; insect.GeheZuBauBase(); } } obst.TragendeInsekten.Clear(); Playground.EntferneObst(obst); j--; } } } } }
/// <summary> /// Erzeugt eine neue Instanz der Markierung-Klasse. /// </summary> /// <param name="koordinate">Die Koordinate der Markierung.</param> /// <param name="ausbreitung">Die Ausbreitung der Markierung in Schritten. /// </param> /// <param name="colonyId">ID des Volkes</param> internal CoreMarker(CoreCoordinate koordinate, int ausbreitung, int colonyId) { this.colonyId = colonyId; Id = neueId++; this.koordinate = koordinate; maximalAlter = SimulationSettings.Custom.MarkerMaximumAge; if (ausbreitung < 0) { ausbreitung = 0; } else { if (ausbreitung > SimulationSettings.Custom.MarkerRangeMaximum) { ausbreitung = SimulationSettings.Custom.MarkerRangeMaximum; } maximalAlter = maximalAlter * SimulationSettings.Custom.MarkerSizeMinimum / (SimulationSettings.Custom.MarkerSizeMinimum + ausbreitung); } this.ausbreitung = ausbreitung * SimulationEnvironment.PLAYGROUND_UNIT; Aktualisieren(); }
/// <summary> /// Lässt das Insekt ein Obststück nehmen. /// </summary> /// <param name="obst">Das Obststück.</param> internal void NimmBase(CoreFruit obst) { if (!NimmBefehleEntgegen) { return; } if (GetragenesObstBase == obst) { return; } if (GetragenesObstBase != null) { LasseNahrungFallenBase(); } int entfernung = CoreCoordinate.BestimmeEntfernungI(CoordinateBase, obst.CoordinateBase); if (entfernung <= SimulationEnvironment.PLAYGROUND_UNIT) { BleibStehenBase(); GetragenesObstBase = obst; obst.TragendeInsekten.Add(this); AktuelleLastBase = colony.Last[CasteIndexBase]; } }
/// <summary> /// Berechnet die Bewegung des Insekts. /// </summary> internal void Bewegen() { reached = false; // Insekt dreht sich. if (restWinkel != 0) { // Zielwinkel wird erreicht. if (Math.Abs(restWinkel) < colony.Drehgeschwindigkeit[CasteIndexBase]) { koordinate.Richtung += restWinkel; restWinkel = 0; } // Insekt dreht sich nach rechts. else if (restWinkel >= colony.Drehgeschwindigkeit[CasteIndexBase]) { koordinate.Richtung += colony.Drehgeschwindigkeit[CasteIndexBase]; RestWinkelBase -= colony.Drehgeschwindigkeit[CasteIndexBase]; } // Insekt dreht sich nach links. else if (restWinkel <= -colony.Drehgeschwindigkeit[CasteIndexBase]) { koordinate.Richtung -= colony.Drehgeschwindigkeit[CasteIndexBase]; RestWinkelBase += colony.Drehgeschwindigkeit[CasteIndexBase]; } } // Insekt geht. else if (restStreckeI > 0) { if (GetragenesObstBase == null) { int strecke = Math.Min(restStreckeI, aktuelleGeschwindigkeitI); restStreckeI -= strecke; zurückgelegteStreckeI += strecke; koordinate.X += SimulationEnvironment.Cos[strecke, koordinate.Richtung]; koordinate.Y += SimulationEnvironment.Sin[strecke, koordinate.Richtung]; } } // Insekt geht auf Ziel zu. else if (ziel != null) { int entfernungI; if (ZielBase is CoreMarker) { entfernungI = CoreCoordinate.BestimmeEntfernungDerMittelpunkteI(koordinate, ziel.CoordinateBase); } else { entfernungI = CoreCoordinate.BestimmeEntfernungI(koordinate, ziel.CoordinateBase); } reached = entfernungI <= SimulationEnvironment.PLAYGROUND_UNIT; if (!reached) { int richtung = CoreCoordinate.BestimmeRichtung(koordinate, ziel.CoordinateBase); // Ziel ist in Sichtweite oder Insekt trägt Obst. if (entfernungI < colony.SichtweiteI[CasteIndexBase] || getragenesObst != null) { restStreckeI = entfernungI; } // Ansonsten Richtung verfälschen. else { richtung += RandomBase.Next(-18, 18); restStreckeI = colony.SichtweiteI[CasteIndexBase]; } dreheInRichtung(richtung); } } // Koordinaten links begrenzen. if (koordinate.X < 0) { koordinate.X = -koordinate.X; if (koordinate.Richtung > 90 && koordinate.Richtung <= 180) { koordinate.Richtung = 180 - koordinate.Richtung; } else if (koordinate.Richtung > 180 && koordinate.Richtung < 270) { koordinate.Richtung = 540 - koordinate.Richtung; } } // Koordinaten rechts begrenzen. else if (koordinate.X > colony.BreiteI) { koordinate.X = colony.BreiteI2 - koordinate.X; if (koordinate.Richtung >= 0 && koordinate.Richtung < 90) { koordinate.Richtung = 180 - koordinate.Richtung; } else if (koordinate.Richtung > 270 && koordinate.Richtung < 360) { koordinate.Richtung = 540 - koordinate.Richtung; } } // Koordinaten oben begrenzen. if (koordinate.Y < 0) { koordinate.Y = -koordinate.Y; if (koordinate.Richtung > 180 && koordinate.Richtung < 360) { koordinate.Richtung = 360 - koordinate.Richtung; } } // Koordinaten unten begrenzen. else if (koordinate.Y > colony.HöheI) { koordinate.Y = colony.HöheI2 - koordinate.Y; if (koordinate.Richtung > 0 && koordinate.Richtung < 180) { koordinate.Richtung = 360 - koordinate.Richtung; } } }
/// <summary> /// Lässt das Insekt von der aktuellen Position aus die angegebene /// Entfernung in Schritten entgegen der Richtung zu einer Quelle gehen. /// Wenn die Quelle ein Insekt eines anderen Volkes ist, befindet sich das /// Insekt auf der Flucht. /// </summary> /// <param name="quelle">Die Quelle.</param> /// <param name="entfernung">Die Entfernung in Schritten.</param> internal void GeheWegVonBase(ICoordinate quelle, int entfernung) { DreheInRichtungBase(CoreCoordinate.BestimmeRichtung(this, quelle) + 180); GeheGeradeausBase(entfernung); }
/// <summary> /// Dreht das Insekt in die Richtung des angegebenen Ziels. /// </summary> /// <param name="ziel">Ziel</param> internal void DreheZuZielBase(ICoordinate ziel) { DreheInRichtungBase(CoreCoordinate.BestimmeRichtung(this, ziel)); }
/// <summary> /// Erzeugt eine neue Instant der Punkt-Struktur aus einer Koordinate. /// </summary> /// <param name="koordinate">Die Koordinate.</param> public Punkt(CoreCoordinate koordinate) { X = koordinate.X / SimulationEnvironment.PLAYGROUND_UNIT; Y = koordinate.Y / SimulationEnvironment.PLAYGROUND_UNIT; Radius = koordinate.Radius / SimulationEnvironment.PLAYGROUND_UNIT; }
/// <summary> /// Berechnet einen neuen Spielschritt /// </summary> /// <returns>Zustandskopie des Simulationsstandes nachdem der Schritt ausgeführt wurde</returns> /// <throws>RuleViolationException</throws> /// <throws>Exception</throws> public void Step(SimulationState simulationState) { currentRound++; #region Food removeSugar(); spawnSugar(); spawnFruit(); #endregion #region Bugs Bugs.Grids[0].Clear(); for (int i = 0; i < Teams.Length; i++) { for (int j = 0; j < Teams[i].Colonies.Length; j++) { Bugs.Grids[0].Add(Teams[i].Colonies[j].Insects); } } // Lasse die Wanzen von der Spiel Befehle entgegen nehmen. //foreach (CoreBug wanze in Bugs.Insects) { // wanze.NimmBefehleEntgegen = true; //} // Schleife über alle Wanzen. for (int bugIndex = 0; bugIndex < Bugs.Insects.Count; bugIndex++) { CoreBug bug = Bugs.Insects[bugIndex] as CoreBug; Debug.Assert(bug != null); bug.NimmBefehleEntgegen = true; // Finde Ameisen in Angriffsreichweite. List <CoreInsect> ants = Bugs.Grids[0].FindAnts(bug); // Bestimme wie der Schaden auf die Ameisen verteilt wird. if (ants.Count >= SimulationSettings.Custom.BugAttack) { // Es sind mehr Ameisen in der SpielUmgebung als die Wanze // Schadenpunke verteilen kann. Daher werden den Ameisen am // Anfang der Liste jeweils ein Energiepunkt abgezogen. for (int index = 0; index < SimulationSettings.Custom.BugAttack; index++) { ants[index].AktuelleEnergieBase--; //((Ameise)ameisen[i]).WirdAngegriffen(wanze); PlayerCall.UnderAttack((CoreAnt)ants[index], bug); if (ants[index].AktuelleEnergieBase <= 0) { ants[index].colony.EatenInsects.Add(ants[index]); } } } else if (ants.Count > 0) { // Bestimme die Energie die von jeder Ameise abgezogen wird. // Hier können natürlich Rundungsfehler auftreten, die die Wanze // abschwächen, die ignorieren wir aber. int schaden = SimulationSettings.Custom.BugAttack / ants.Count; for (int index = 0; index < ants.Count; index++) { ants[index].AktuelleEnergieBase -= schaden; //((Ameise)ameisen[i]).WirdAngegriffen(wanze); PlayerCall.UnderAttack((CoreAnt)ants[index], bug); if (ants[index].AktuelleEnergieBase <= 0) { ants[index].colony.EatenInsects.Add(ants[index]); } } } // Während eines Kampfes kann die Wanze sich nicht bewegen. if (ants.Count > 0) { continue; } // Bewege die Wanze. bug.Bewegen(); if (bug.RestStreckeBase == 0) { bug.DreheInRichtungBase(random.Next(360)); bug.GeheGeradeausBase(random.Next(160, 320)); } bug.NimmBefehleEntgegen = false; } // Verhindere, daß ein Spieler einer gesichteten Wanze Befehle gibt. //for(int i = 0; i < Bugs.Insects.Count; i++) { // CoreBug wanze = Bugs.Insects[i] as CoreBug; // if(wanze != null) { // wanze.NimmBefehleEntgegen = false; // } //} #endregion #region Ants // Loop through all teams. for (int teamIndex = 0; teamIndex < Teams.Length; teamIndex++) { // Loop through all colonies in that team. for (int colonyIndex = 0; colonyIndex < Teams[teamIndex].Colonies.Length; colonyIndex++) { CoreColony colony = Teams[teamIndex].Colonies[colonyIndex]; // Leere alle Buckets. for (int casteIndex = 0; casteIndex < colony.AnzahlKasten; casteIndex++) { colony.Grids[casteIndex].Clear(); } // Fülle alle Buckets, aber befülle keinen Bucket doppelt. for (int casteIndex = 0; casteIndex < colony.AnzahlKasten; casteIndex++) { if (colony.Grids[casteIndex].Count == 0) { colony.Grids[casteIndex].Add(Bugs.Insects); for (int j = 0; j < Teams.Length; j++) { for (int i = 0; i < Teams[j].Colonies.Length; i++) { CoreColony v = Teams[j].Colonies[i]; colony.Grids[casteIndex].Add(v.Insects); } } } } // Schleife über alle Ameisen. for (int antIndex = 0; antIndex < colony.Insects.Count; antIndex++) { CoreAnt ameise = colony.Insects[antIndex] as CoreAnt; Debug.Assert(ameise != null); // Finde und Zähle die Insekten im Sichtkreis der Ameise. CoreBug wanze; CoreAnt feind; CoreAnt freund; CoreAnt teammember; int bugCount, enemyAntCount, colonyAntCount, casteAntCount, teamAntCount; colony.Grids[ameise.CasteIndexBase].FindAndCountInsects( ameise, out wanze, out bugCount, out feind, out enemyAntCount, out freund, out colonyAntCount, out casteAntCount, out teammember, out teamAntCount); ameise.BugsInViewrange = bugCount; ameise.ForeignAntsInViewrange = enemyAntCount; ameise.FriendlyAntsInViewrange = colonyAntCount; ameise.FriendlyAntsFromSameCasteInViewrange = casteAntCount; ameise.TeamAntsInViewrange = teamAntCount; // Bewege die Ameise. ameise.Bewegen(); #region Reichweite // Ameise hat ihre Reichweite überschritten. if (ameise.ZurückgelegteStreckeI > colony.ReichweiteI[ameise.CasteIndexBase]) { ameise.AktuelleEnergieBase = 0; colony.VerhungerteInsekten.Add(ameise); continue; } // Ameise hat ein Drittel ihrer Reichweite zurückgelegt. else if (ameise.ZurückgelegteStreckeI > colony.ReichweiteI[ameise.CasteIndexBase] / 3) { if (ameise.IstMüdeBase == false) { ameise.IstMüdeBase = true; PlayerCall.BecomesTired(ameise); } } #endregion #region Kampf // Rufe die Ereignisse auf, falls die Ameise nicht schon ein // entsprechendes Ziel hat. if (wanze != null && !(ameise.ZielBase is CoreBug)) { PlayerCall.SpotsEnemy(ameise, wanze); } if (feind != null && !(ameise.ZielBase is CoreAnt) || (ameise.ZielBase is CoreAnt && ((CoreAnt)ameise.ZielBase).colony == colony)) { PlayerCall.SpotsEnemy(ameise, feind); } if (freund != null && !(ameise.ZielBase is CoreAnt) || (ameise.ZielBase is CoreAnt && ((CoreAnt)ameise.ZielBase).colony != colony)) { PlayerCall.SpotsFriend(ameise, freund); } if (teammember != null && !(ameise.ZielBase is CoreAnt) || (ameise.ZielBase is CoreAnt && ((CoreAnt)ameise.ZielBase).colony != colony)) { PlayerCall.SpotsTeamMember(ameise, teammember); } // Kampf mit Wanze. if (ameise.ZielBase is CoreBug) { CoreBug k = (CoreBug)ameise.ZielBase; if (k.AktuelleEnergieBase > 0) { int entfernung = CoreCoordinate.BestimmeEntfernungI(ameise.CoordinateBase, ameise.ZielBase.CoordinateBase); if (entfernung < SimulationSettings.Custom.BattleRange * PLAYGROUND_UNIT) { k.AktuelleEnergieBase -= ameise.AngriffBase; if (k.AktuelleEnergieBase <= 0) { Bugs.EatenInsects.Add(k); colony.Statistik.KilledBugs++; ameise.BleibStehenBase(); } } } else { ameise.ZielBase = null; } } // Kampf mit feindlicher Ameise. else if (ameise.ZielBase is CoreAnt) { CoreAnt a = (CoreAnt)ameise.ZielBase; if (a.colony != colony && a.AktuelleEnergieBase > 0) { int entfernung = CoreCoordinate.BestimmeEntfernungI(ameise.CoordinateBase, ameise.ZielBase.CoordinateBase); if (entfernung < SimulationSettings.Custom.BattleRange * PLAYGROUND_UNIT) { PlayerCall.UnderAttack(a, ameise); a.AktuelleEnergieBase -= ameise.AngriffBase; if (a.AktuelleEnergieBase <= 0) { a.colony.BeatenInsects.Add(a); colony.Statistik.KilledAnts++; ameise.BleibStehenBase(); } } } else { ameise.ZielBase = null; } } #endregion // Prüfe ob die Ameise an ihrem Ziel angekommen ist. if (ameise.AngekommenBase) { ameiseUndZiel(ameise); } // Prüfe ob die Ameise einen Zuckerhaufen oder ein Obststück sieht. ameiseUndZucker(ameise); if (ameise.GetragenesObstBase == null) { ameiseUndObst(ameise); } // Prüfe ob die Ameise eine Markierung bemerkt. ameiseUndMarkierungen(ameise); if (ameise.ZielBase == null && ameise.RestStreckeBase == 0) { PlayerCall.Waits(ameise); } PlayerCall.Tick(ameise); } removeAnt(colony); spawnAnt(colony); aktualisiereMarkierungen(colony); removeFruit(colony); } } #endregion #region Bugs again removeBugs(); healBugs(); spawnBug(); #endregion bewegeObstUndInsekten(); erzeugeZustand(simulationState); }
/// <summary> /// Erzeugt eine neue Instanz der Bau-Klasse. /// <param name="x">X-Koordinate</param> /// <param name="y">Y.Koordinate</param> /// <param name="radius">Radius</param> /// <param name="colonyId">Volk ID</param> /// </summary> internal CoreAnthill(int x, int y, int radius, int colonyId) { this.colonyId = colonyId; Id = neueId++; koordinate = new CoreCoordinate(x, y, radius); }
/// <summary> /// Entfernt abgelaufene Markierungen und erzeugt neue Markierungen. /// </summary> /// <param name="colony">betroffenes Volk</param> private static void aktualisiereMarkierungen(CoreColony colony) { // TODO: Settings berücksichtigen // Markierungen aktualisieren und inaktive Markierungen löschen. List <CoreMarker> gemerkteMarkierungen = new List <CoreMarker>(); foreach (CoreMarker markierung in colony.Marker) { if (markierung.IstAktiv) { markierung.Aktualisieren(); } else { gemerkteMarkierungen.Add(markierung); } } gemerkteMarkierungen.ForEach(delegate(CoreMarker marker) { colony.Insects.ForEach(delegate(CoreInsect insect) { CoreAnt ant = insect as CoreAnt; if (ant != null) { ant.SmelledMarker.Remove(marker); } }); }); //for(int i = 0; i < gemerkteMarkierungen.Count; i++) { // CoreMarker markierung = gemerkteMarkierungen[i]; // for(int j = 0; j < volk.Insects.Count; j++) { // CoreAnt ameise = volk.Insects[j] as CoreAnt; // if(ameise != null) { // ameise.GerocheneMarkierungen.Remove(markierung); // } // } //} colony.Marker.Remove(gemerkteMarkierungen); // Neue Markierungen überprüfen und hinzufügen. gemerkteMarkierungen.Clear(); colony.NewMarker.ForEach(delegate(CoreMarker newMarker) { bool zuNah = false; //for(int i = 0; i < volk.Marker.Count; i++) { // CoreMarker marker = volk.Marker[i]; // if(marker != null) { // int distance = // CoreCoordinate.BestimmeEntfernungDerMittelpunkteI // (marker.Coordinate, newMarker.Coordinate); // if(distance < SimulationSettings.Settings.MarkerDistance * SPIELFELD_EINHEIT) { // zuNah = true; // break; // } // } //} foreach (CoreMarker markierung in colony.Marker) { int entfernung = CoreCoordinate.BestimmeEntfernungDerMittelpunkteI (markierung.CoordinateBase, newMarker.CoordinateBase); if (entfernung < SimulationSettings.Custom.MarkerDistance * PLAYGROUND_UNIT) { zuNah = true; break; } } if (!zuNah) { colony.Marker.Add(newMarker); } }); //foreach (CoreMarker neueMarkierung in volk.NewMarker) { // bool zuNah = false; // foreach (CoreMarker markierung in volk.Marker) { // int entfernung = // CoreCoordinate.BestimmeEntfernungDerMittelpunkteI // (markierung.Coordinate, neueMarkierung.Coordinate); // if (entfernung < SimulationSettings.Settings.MarkerDistance * SPIELFELD_EINHEIT) { // zuNah = true; // break; // } // } // if (!zuNah) { // volk.Marker.Add(neueMarkierung); // } //} colony.NewMarker.Clear(); }
/// <summary> /// Findet die Wanze, die feindliche Ameise und die befreundete Ameise mit der /// geringsten Entfernung innerhalb des Sichtkreis der gegebenen Ameise und /// zählt die Anzahl an Wanzen, feindlichen und befreundeten Ameisen im Sichtkreis. /// </summary> /// <remarks> /// Wird für Ameisen verwendet. Die Simulation legt für jeden vorkommenden Sichtradius /// eine eigenes Gitter an und benutzt diese Methode auf der passenden Instanz zum Finden /// von Insekten. Die Seitenlänge dieses Gitters ist also der Sichradius der Ameise. /// In diese Gitter werden Wanzen und Ameisen einsortiert. /// </remarks> /// <param name="ant">Die Referenzameise.</param> /// <param name="nearestBug">Eine Wanze.</param> /// <param name="bugCount">Die Anzahl an Wanzen.</param> /// <param name="nearestEnemyAnt">Eine feindliche Ameise.</param> /// <param name="enemyAntCount">Die Anzahl an feindlichen Ameisen.</param> /// <param name="nearestColonyAnt">Eine befreundete Ameise.</param> /// <param name="colonyAntCount">Die Anzahl an befreundeten Ameisen.</param> /// <param name="casteAntCount">Die Anzahl an befreundeten Ameisen der selben Kaste.</param> public void FindAndCountInsects(CoreAnt ant, out CoreBug nearestBug, out int bugCount, out CoreAnt nearestEnemyAnt, out int enemyAntCount, out CoreAnt nearestColonyAnt, out int colonyAntCount, out int casteAntCount, out CoreAnt nearestTeamAnt, out int teamAntCount) { // Die nächstliegenden gefundenen Wanzen und Ameisen. nearestBug = null; nearestEnemyAnt = null; nearestColonyAnt = null; nearestTeamAnt = null; // Die Entfernungen zu den nächstliegenden gefundenen Wanzen und Ameisen. int nearestBugDistance = int.MaxValue; int nearestEnemyAntDistance = int.MaxValue; int nearestColonyAntDistance = int.MaxValue; int nearestTeamAntDistance = int.MaxValue; // Die Anzahlen der gefundenen Wanzen und Ameisen. bugCount = 0; enemyAntCount = 0; colonyAntCount = 0; casteAntCount = 0; teamAntCount = 0; // Bestimme die Zelle in der die übergebene Ameise sich befindet. int col = ant.CoordinateBase.X / sideLength; int row = ant.CoordinateBase.Y / sideLength; // Betrachte die Zelle und die acht Zellen daneben. for (int c = -1; c <= 1; c++) { if (col + c >= 0 && col + c < columns) { for (int r = -1; r <= 1; r++) { if (row + r >= 0 && row + r < rows) { // Betrachte alle Insekten in der aktuellen Zelle. List <T> cell = cells[col + c, row + r]; for (int i = 0; i < cell.Count; i++) { CoreInsect insect = cell[i] as CoreInsect; Debug.Assert(insect != null); if (insect == ant) { continue; } // Vergleiche die Entfernung zum aktuellen Insekt mit der // Sichtweite der Ameise bzw. der Seitenlänge des Gitters. int distance = CoreCoordinate.BestimmeEntfernungI(ant.CoordinateBase, insect.CoordinateBase); if (distance > sideLength) { continue; } // Selbes Volk. Die Abfrage "insect is CoreAnt" ist unnötig. if (insect.colony == ant.colony) { colonyAntCount++; if (insect.CasteIndexBase == ant.CasteIndexBase) { casteAntCount++; } // Die neue Ameise liegt näher als die gemerkte. if (distance < nearestColonyAntDistance) { nearestColonyAntDistance = distance; nearestColonyAnt = (CoreAnt)insect; } } // Selbes Team. else if (insect.colony.Team == ant.colony.Team) { teamAntCount++; // Die neue Ameise liegt näher als die gemerkte. if (distance < nearestTeamAntDistance) { nearestTeamAntDistance = distance; nearestTeamAnt = (CoreAnt)insect; } } // Wanze. else if (insect is CoreBug) { bugCount++; // Die neue Wanze liegt näher als die gemerkte. if (distance < nearestBugDistance) { nearestBugDistance = distance; nearestBug = (CoreBug)insect; } } // Feindliche Ameise. else { enemyAntCount++; // Die neue Ameise liegt näher als die gemerkte. if (distance < nearestEnemyAntDistance) { nearestEnemyAntDistance = distance; nearestEnemyAnt = (CoreAnt)insect; } } } } } } } }
/// <summary> /// Der abstrakte Nahrung-Basiskonstruktor. /// </summary> /// <param name="x">Die X-Position der Koordinate auf dem Spielfeld.</param> /// <param name="y">Die Y-Position der Koordinate auf dem Spielfeld.</param> /// <param name="menge">Die Anzahl der Nahrungspunkte.</param> internal CoreFood(int x, int y, int menge) { Id = neueId++; koordinate = new CoreCoordinate(x, y); Menge = menge; }