using AntMe.Deutsch; using System; using System.CodeDom; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using AntMe.Simulation; namespace AntMe.Player.BrainArmyAnts { /// /// Diese Datei enthält die Beschreibung für deine Ameise. Die einzelnen Code-Blöcke /// (Beginnend mit "public override void") fassen zusammen, wie deine Ameise in den /// entsprechenden Situationen reagieren soll. Welche Befehle du hier verwenden kannst, /// findest du auf der Befehlsübersicht im Wiki (http://wiki.antme.net/de/API1:Befehlsliste). /// /// Wenn du etwas Unterstützung bei der Erstellung einer Ameise brauchst, findest du /// in den AntMe!-Lektionen ein paar Schritt-für-Schritt Anleitungen. /// (http://wiki.antme.net/de/Lektionen) /// [Spieler( Volkname = "BrainArmyAnts", // Hier kannst du den Namen des Volkes festlegen Vorname = "Joshua Priebsch,", // An dieser Stelle kannst du dich als Schöpfer der Ameise eintragen Nachname = "Sebastian Seedorf" // An dieser Stelle kannst du dich als Schöpfer der Ameise eintragen )] /// Kasten stellen "Berufsgruppen" innerhalb deines Ameisenvolkes dar. Du kannst hier mit /// den Fähigkeiten einzelner Ameisen arbeiten. Wie genau das funktioniert kannst du der /// Lektion zur Spezialisierung von Ameisen entnehmen (http://wiki.antme.net/de/Lektion7). [Kaste( Name = "Sammler", // Name der Berufsgruppe AngriffModifikator = -1, // Angriffsstärke einer Ameise DrehgeschwindigkeitModifikator = -1, // Drehgeschwindigkeit einer Ameise EnergieModifikator = -1, // Lebensenergie einer Ameise GeschwindigkeitModifikator = 2, // Laufgeschwindigkeit einer Ameise LastModifikator = 2, // Tragkraft einer Ameise ReichweiteModifikator = -1, // Ausdauer einer Ameise SichtweiteModifikator = 0 // Sichtweite einer Ameise ), Kaste( Name = "Erkunder", // Name der Berufsgruppe AngriffModifikator = -1, // Angriffsstärke einer Ameise DrehgeschwindigkeitModifikator = -1, // Drehgeschwindigkeit einer Ameise EnergieModifikator = -1, // Lebensenergie einer Ameise GeschwindigkeitModifikator = 1, // Laufgeschwindigkeit einer Ameise LastModifikator = -1, // Tragkraft einer Ameise ReichweiteModifikator = 1, // Ausdauer einer Ameise SichtweiteModifikator = 2 // Sichtweite einer Ameise ), Kaste( Name = "Krieger", // Name der Berufsgruppe AngriffModifikator = 2, // Angriffsstärke einer Ameise DrehgeschwindigkeitModifikator = 0, // Drehgeschwindigkeit einer Ameise EnergieModifikator = 1, // Lebensenergie einer Ameise GeschwindigkeitModifikator = 0, // Laufgeschwindigkeit einer Ameise LastModifikator = -1, // Tragkraft einer Ameise ReichweiteModifikator = -1, // Ausdauer einer Ameise SichtweiteModifikator = -1 // Sichtweite einer Ameise )] public class BrainArmyAntsKlasse : Basisameise { private static Bau bau = null; private static readonly Random rand = new Random(); private static readonly List VorkZuckers = new List(); private static readonly List RemovedZuckers = new List(); private static readonly List VorkObsts = new List(); private static readonly List VorkFeinde = new List(); private static int GestorbeneAmeisen = 0; private static int GetoeteteAmeisen = 0; private Spielobjekt _z; private Insekt _aktuellerFeind; #region Kasten /// /// Jedes mal, wenn eine neue Ameise geboren wird, muss ihre Berufsgruppe /// bestimmt werden. Das kannst du mit Hilfe dieses Rückgabewertes dieser /// Methode steuern. /// Weitere Infos unter http://wiki.antme.net/de/API1:BestimmeKaste /// /// Anzahl Ameisen pro Kaste /// Name der Kaste zu der die geborene Ameise gehören soll public override string BestimmeKaste(Dictionary anzahl) { int count = 0; foreach(KeyValuePair entry in anzahl) { count += entry.Value; } if (anzahl["Krieger"] < 6 || anzahl["Sammler"] > anzahl["Krieger"] * (GetoeteteAmeisen/(GestorbeneAmeisen+1))) return "Krieger"; if (anzahl["Sammler"] > anzahl["Erkunder"] * 20) return "Erkunder"; // Gibt den Namen der betroffenen Kaste zurück. return "Sammler"; } #endregion #region Fortbewegung /// /// Wenn die Ameise keinerlei Aufträge hat, wartet sie auf neue Aufgaben. Um dir das /// mitzuteilen, wird diese Methode hier aufgerufen. /// Weitere Infos unter http://wiki.antme.net/de/API1:Wartet /// public override void Wartet() { } /// /// Erreicht eine Ameise ein drittel ihrer Laufreichweite, wird diese Methode aufgerufen. /// Weitere Infos unter http://wiki.antme.net/de/API1:WirdM%C3%BCde /// public override void WirdMüde() { } /// /// Wenn eine Ameise stirbt, wird diese Methode aufgerufen. Man erfährt dadurch, wie /// die Ameise gestorben ist. Die Ameise kann zu diesem Zeitpunkt aber keinerlei Aktion /// mehr ausführen. /// Weitere Infos unter http://wiki.antme.net/de/API1:IstGestorben /// /// Art des Todes public override void IstGestorben(Todesart todesart) { foreach (ObstTraeger obstTraeger in VorkObsts) { obstTraeger.AmeiseEntfernen(this); } if (todesart == Todesart.Besiegt) { GestorbeneAmeisen++; } } /// /// Diese Methode wird in jeder Simulationsrunde aufgerufen - ungeachtet von zusätzlichen /// Bedingungen. Dies eignet sich für Aktionen, die unter Bedingungen ausgeführt werden /// sollen, die von den anderen Methoden nicht behandelt werden. /// Weitere Infos unter http://wiki.antme.net/de/API1:Tick /// public override void Tick() { if (ZurückgelegteStrecke*2+2 > Reichweite) { SchrittBau(); return; } if (Kaste == "Sammler") { if (AktuelleLast > 0) { SchrittBau(); } else { _z = BestimmeZiel(); if (_z == null) { GeheGeradeaus(10); if (rand.Next(50) == 0) DreheUmWinkel(60); } else { SchrittZiel(_z); } } } else if (Kaste == "Krieger") { //SprüheMarkierung(5, 10); _z = BestimmeZiel(); if (_z == null) { GeheGeradeaus(10); if (rand.Next(50) == 0) DreheUmWinkel(60); } else { SchrittZiel(_z); } } else { GeheGeradeaus(); //SprüheMarkierung(4, 30); } } #endregion #region Nahrung /// /// Sobald eine Ameise innerhalb ihres Sichtradius einen Apfel erspäht wird /// diese Methode aufgerufen. Als Parameter kommt das betroffene Stück Obst. /// Weitere Infos unter "http://wiki.antme.net/de/API1:Sieht(Obst)" /// /// Das gesichtete Stück Obst public override void Sieht(Obst obst) { ObstHinzufügen(obst); } /// /// Sobald eine Ameise innerhalb ihres Sichtradius einen Zuckerhügel erspäht wird /// diese Methode aufgerufen. Als Parameter kommt der betroffene Zuckerghügel. /// Weitere Infos unter "http://wiki.antme.net/de/API1:Sieht(Zucker)" /// /// Der gesichtete Zuckerhügel public override void Sieht(Zucker zucker) { ZuckerHinzufügen(zucker); ZuckerEntfernen(); } /// /// Hat die Ameise ein Stück Obst als Ziel festgelegt, wird diese Methode aufgerufen, /// sobald die Ameise ihr Ziel erreicht hat. Ab jetzt ist die Ameise nahe genug um mit /// dem Ziel zu interagieren. /// Weitere Infos unter "http://wiki.antme.net/de/API1:ZielErreicht(Obst)" /// /// Das erreichte Stück Obst public override void ZielErreicht(Obst obst) { if (Kaste == "Sammler") { Nimm(obst); } } /// /// Hat die Ameise eine Zuckerhügel als Ziel festgelegt, wird diese Methode aufgerufen, /// sobald die Ameise ihr Ziel erreicht hat. Ab jetzt ist die Ameise nahe genug um mit /// dem Ziel zu interagieren. /// Weitere Infos unter "http://wiki.antme.net/de/API1:ZielErreicht(Zucker)" /// /// Der erreichte Zuckerhügel public override void ZielErreicht(Zucker zucker) { if (Kaste == "Sammler") { Nimm(zucker); ZuckerEntfernen(); } } #endregion #region Kommunikation /// /// Markierungen, die von anderen Ameisen platziert werden, können von befreundeten Ameisen /// gewittert werden. Diese Methode wird aufgerufen, wenn eine Ameise zum ersten Mal eine /// befreundete Markierung riecht. /// Weitere Infos unter "http://wiki.antme.net/de/API1:RiechtFreund(Markierung)" /// /// Die gerochene Markierung public override void RiechtFreund(Markierung markierung) { } /// /// So wie Ameisen unterschiedliche Nahrungsmittel erspähen können, entdecken Sie auch /// andere Spielelemente. Entdeckt die Ameise eine Ameise aus dem eigenen Volk, so /// wird diese Methode aufgerufen. /// Weitere Infos unter "http://wiki.antme.net/de/API1:SiehtFreund(Ameise)" /// /// Erspähte befreundete Ameise public override void SiehtFreund(Ameise ameise) { } /// /// So wie Ameisen unterschiedliche Nahrungsmittel erspähen können, entdecken Sie auch /// andere Spielelemente. Entdeckt die Ameise eine Ameise aus einem befreundeten Volk /// (Völker im selben Team), so wird diese Methode aufgerufen. /// Weitere Infos unter "http://wiki.antme.net/de/API1:SiehtVerb%C3%BCndeten(Ameise)" /// /// Erspähte verbündete Ameise public override void SiehtVerbündeten(Ameise ameise) { } #endregion #region Kampf /// /// So wie Ameisen unterschiedliche Nahrungsmittel erspähen können, entdecken Sie auch /// andere Spielelemente. Entdeckt die Ameise eine Ameise aus einem feindlichen Volk, /// so wird diese Methode aufgerufen. /// Weitere Infos unter "http://wiki.antme.net/de/API1:SiehtFeind(Ameise)" /// /// Erspähte feindliche Ameise public override void SiehtFeind(Ameise ameise) { /*if (Kaste == "Sammler") { */FeindHinzufügen(ameise);/* } else */if (Kaste == "Krieger" && Koordinate.BestimmeEntfernung(this, ameise) < 4) { GreifeAn(ameise); } } /// /// So wie Ameisen unterschiedliche Nahrungsmittel erspähen können, entdecken Sie auch /// andere Spielelemente. Entdeckt die Ameise eine Wanze, so wird diese Methode aufgerufen. /// Weitere Infos unter "http://wiki.antme.net/de/API1:SiehtFeind(Wanze)" /// /// Erspähte Wanze public override void SiehtFeind(Wanze wanze) { } /// /// Es kann vorkommen, dass feindliche Lebewesen eine Ameise aktiv angreifen. Sollte /// eine feindliche Ameise angreifen, wird diese Methode hier aufgerufen und die /// Ameise kann entscheiden, wie sie darauf reagieren möchte. /// Weitere Infos unter "http://wiki.antme.net/de/API1:WirdAngegriffen(Ameise)" /// /// Angreifende Ameise public override void WirdAngegriffen(Ameise ameise) { } /// /// Es kann vorkommen, dass feindliche Lebewesen eine Ameise aktiv angreifen. Sollte /// eine Wanze angreifen, wird diese Methode hier aufgerufen und die Ameise kann /// entscheiden, wie sie darauf reagieren möchte. /// Weitere Infos unter "http://wiki.antme.net/de/API1:WirdAngegriffen(Wanze)" /// /// Angreifende Wanze public override void WirdAngegriffen(Wanze wanze) { } #endregion #region Eigene private Spielobjekt BestimmeZiel() { ZuckerEntfernen(); ObstEntfernen(); FeindEntfernen(); var entfernung = int.MaxValue; Spielobjekt s = null; if (Kaste == "Sammler") { foreach (ObstTraeger obstTraeger in VorkObsts) { if (obstTraeger.IstTraeger(this)) return obstTraeger.Obst; } foreach (var obst in VorkObsts) { var neu = Koordinate.BestimmeEntfernung(this, obst.Obst); if (s != null && neu >= entfernung || neu >= Reichweite / 3 || !obst.BrauchtNochTraeger()) continue; //Ich verstehe das "z != null &&" nicht s = obst.Obst; entfernung = neu; } foreach (var zucker in VorkZuckers) { var neu = Koordinate.BestimmeEntfernung(this, zucker); if (s != null && neu >= entfernung || neu >= Reichweite / 3) continue; s = zucker; entfernung = neu; } if (s is Obst) { VorkObsts.Find(o => o.Obst == s).AmeiseHinzufügen(this); } } else if(Kaste == "Krieger") { if (_aktuellerFeind != null) { var neu = Koordinate.BestimmeEntfernung(this, _aktuellerFeind); if (!(neu >= Reichweite / 3 && (Angriff == 0 || _aktuellerFeind.Angriff > 0 && _aktuellerFeind.AktuelleEnergie / Angriff < AktuelleEnergie / _aktuellerFeind.Angriff))) return s; } foreach (var feind in VorkFeinde) { var neu = Koordinate.BestimmeEntfernung(this, feind); if (s != null && neu >= entfernung || neu >= Reichweite / 3) continue; if (Angriff==0 || feind.Angriff>0 && feind.AktuelleEnergie/Angriff < AktuelleEnergie/feind.Angriff) continue; if (rand.Next(6)<1) s = feind; entfernung = neu; } _aktuellerFeind = (Insekt) s; } return s; } private void SchrittZiel(Spielobjekt ziel) { var dist = Koordinate.BestimmeEntfernung(this, ziel); var angle = Koordinate.BestimmeRichtung(this, ziel); if (Math.Abs(angle-Richtung) > 10) DreheInRichtung(angle); DreheZuZiel(ziel); if (dist > 2) GeheGeradeaus(dist/3*2); else GeheZuZiel(ziel); } private void SchrittBau() { if (bau == null) { GeheZuBau(); bau = (Bau) Ziel; BleibStehen(); } var dist = Koordinate.BestimmeEntfernung(this, bau); var angle = Koordinate.BestimmeRichtung(this, bau); if (Math.Abs(angle-Richtung) > 10) DreheInRichtung(angle); if (dist > 4) GeheGeradeaus(dist-2); else GeheZuZiel(bau); } private static void ZuckerHinzufügen(Zucker zucker) { if (zucker.Menge > 100 && !VorkZuckers.Contains(zucker) && RemovedZuckers.All(z => z != zucker.Id)) { VorkZuckers.Add(zucker); } } private static void ObstHinzufügen(Obst obst) { if (VorkObsts.All(o => o.Obst != obst)) { VorkObsts.Add(new ObstTraeger(obst)); } } private static void FeindHinzufügen(Ameise feind) { if (feind.AktuelleEnergie > 0 && !VorkFeinde.Contains(feind)) { VorkFeinde.Add(feind); } } private static void ZuckerEntfernen()//Zucker zucker { for (int i = 0; i < VorkZuckers.Count; ) { var zucker = VorkZuckers[i]; if (zucker.Menge > 0) { i++; } else { if (VorkZuckers.Contains(zucker)) { VorkZuckers.Remove(zucker); } if (!RemovedZuckers.Contains(zucker.Id)) { RemovedZuckers.Add(zucker.Id); } } } } private static void ObstEntfernen() { for (int i = 0; i < VorkObsts.Count; ) { var obst = VorkObsts[i]; if (obst.Obst.Menge > 0) { i++; } else { VorkObsts.Remove(obst); } } } private static void FeindEntfernen() { for (int i = 0; i < VorkFeinde.Count; ) { var feind = VorkFeinde[i]; if (feind.AktuelleEnergie > 0) { i++; } else { VorkFeinde.Remove(feind); GetoeteteAmeisen++; } } } #endregion } public class ObstTraeger { public Obst Obst; private readonly List ameisen; public ObstTraeger(Obst obst) { Obst = obst; ameisen = new List(); } public bool BrauchtNochTraeger() { return ameisen.Count < 10; } public void AmeiseHinzufügen(BrainArmyAntsKlasse ameise) { if (!IstTraeger(ameise)) ameisen.Add(ameise); } public void AmeiseEntfernen(BrainArmyAntsKlasse ameise) { ameisen.Remove(ameise); } public bool IstTraeger(BrainArmyAntsKlasse ameise) { return ameisen.Contains(ameise); } } }