Codémon, ich wähle dich!


55

Ihr freundlicher Nachbar, Doktor Tree, hat Ihnen gerade drei magische Kreaturen namens Codémon geschenkt. In der nahe gelegenen Stadt Colorville gibt es ein Kampfturnier. Bist du der Beste, wie es noch niemand war?

Überblick

Dies ist ein Kampfturnier. Jeder Spieler kontrolliert ein Team von drei Monstern und das Ziel ist es, das andere Team auszuschalten (zu töten). Es gibt 100 Runden mit Punkten für Siege und Unentschieden. Das Team mit den meisten Punkten gewinnt!

Monster

Ein Codémon ist ein kompliziertes kleines Wesen. Es stehen fünf Typen (Elemente) zur Auswahl, drei Statistiken und drei Bewegungsslots.

Typen

Jedem Codémon ist ein Typ zugeordnet. Die fünf Typen sind Normal, Hellsichtig, Feuer, Wasser und Gras. Jeder hat seine Stärken und Schwächen. Der Schaden basiert auf der folgenden Tabelle:

Typenschild

Die Zahlen sind Schadensmultiplikatoren. Beispielsweise hat feuerangreifendes Wasser einen Modifikator von 0,5 (halber Schaden), während feuerangreifendes Gras verdoppelt wird (2).

Statistiken

Jedes Monster hat drei Statistiken, die seine Kampffähigkeiten bestimmen. Angriff erhöht den Schaden, den er verursacht. Verteidigung verringert den Schaden. Die Geschwindigkeit erlaubt es, sich vor denjenigen mit niedrigerer Geschwindigkeit zu bewegen.

Jedes Monster hat einen Startwert von 50 für jeden Wert und ein Maximum von 100. Wenn du deine Monster erstellst, kannst du 80 zusätzliche Punkte ( für jeden Wert) zuweisen . Denken Sie daran, dass kein einzelner Wert über 100 hinausgehen kann. Sie könnten also eine Verteilung von 100/80/50, 90/80/60 oder 65/65/100 haben, aber 120/50/60 ist illegal. Jedes Team mit illegalen Statistiken wird disqualifiziert. Sie sind nicht erforderlich verwenden , um alle 80 Punkte, aber Sie sollten wahrscheinlich nicht mit dem Minimum 50/50/50 gehen.

Sie könnten HP auch als Statistik betrachten, aber jedes Codémon verfügt über nicht veränderbare 100 HP. Wenn HP auf Null fällt, können sie nicht mehr weiterkämpfen. HP werden vor jedem Kampf auf 100 aufgefüllt.

Bewegt

Jedes Monster kennt drei Kampfzüge. Die drei gewählten müssen verschieden sein, also kein Schlag / Schlag / Schlag.

Es gibt 15 Züge, drei von jedem Typ. Jeder Typ hat einen direkten Angriff, einen schwächeren Angriff mit einem Effekt und einen einzigen Effektzug.

id  name        type    power   uses    usable  effect

0   Punch       N       20      -       NFWG
1   Heal        N        0      3       NFWG    Heals 50 HP
2   Slow        N       10      5       NFWG    Enemy speed x0.8
3   Pain        P       20      -       PFWG
4   Sleep       P        0      3       PFWG    No enemy action until wake
5   Weaken      P       10      5       PFWG    Enemy Atk x0.8
6   Fireball    F       20      -       NPFW
7   Burn        F        0      3       NPFW    Enemy -10 HP each turn
8   Sharpen     F       10      5       NPFW    Own Atk x1.25
9   Watergun    W       20      -       NPWG    
10  Confuse     W        0      3       NPWG    Enemy may strike itself (10 power)
11  Shield      W       10      5       NPWG    Own Def x1.25
12  Vine        G       20      -       NPFG
13  Poison      G        0      3       NPFG    Enemy -5xTurns HP each turn
14  Sap         G       10      5       NPFG    Enemy Def x0.8

typebezieht sich auf die Art des Umzugs. powerist seine Schlagkraft. usesGibt an, wie oft es pro Kampf verwendet werden kann ( -unbegrenzt). usablezeigt an, von welchen Typen es verwendet werden kann (zum Beispiel kann einem psychischen Typ kein Schlag gegeben werden, da es keinen gibt P). effectzeigt, welche Auswirkungen die Bewegungen haben. Es besteht eine 75% ige Chance, dass jeder Effekt wirkt, mit Ausnahme von Heilen, das immer wirkt.

Bei Effekten, die die Werte eines Monsters ändern, können die Effekte gestapelt werden . Zum Beispiel kann die zweimalige Verwendung von Schwächen den Angriff deines Gegners auf 0,64 verringern. Effekte, die die Werte eines Monsters nicht ändern (Schlaf, Brennen usw.) , werden nicht gestapelt .

Schlaf versetzt den Gegner in den Schlaf, mit einer Wahrscheinlichkeit von 60%, zu Beginn jeder Runde aufzuwachen. Schlafende Monster werden keine Maßnahmen ergreifen.

Verbrennung fügt dem Gegner am Ende jedes Spielzugs 10 HP zu, wenn er aktiv ist . Gift wirkt ähnlich, nimmt aber mit jeder Runde mehr zu. In der ersten Runde sind es 5 und danach erhält es 5 pro Runde. Ab dem vierten Spielzug sind es also 20 Schadenspunkte. Dies sind Pauschalschäden, die weder vom Monstertyp noch von Boni abhängig sind.

Verwirrung kann dazu führen, dass ein Monster selbst angreift, anstatt das zu tun, was ihm befohlen wurde. Dieser Angriff hat Stärke 10 und eine Chance von 30%, dass er in einem bestimmten Zug ausgeführt wird.

Um klar zu sein, die Effekte dauern bis zum Ende des Kampfes (außer Schlaf, wie oben erwähnt).

Moves erhalten außerdem eine um 20% erhöhte Kraft, wenn sie von einem Monster des entsprechenden Typs verwendet werden. Zum Beispiel wird ein Grasmonster, das Vine verwendet, verstärkt, während es Punch nicht verwendet.

Geheime Statistiken

Die Werte und der Typ (aber nicht die Züge) jedes Monsters sind öffentlich bekannt. Ihre Gegner können sehen, gegen was sie kämpfen, um die beste Aktion zu wählen. Es gibt jedoch auch versteckte Boni.

Insbesondere erhalten Sie nach jeweils zwei Kämpfen einen "Bonus" -Statpunkt für jedes Monster in Ihrem Team. Punkte werden an alle Monster vergeben, die tot oder lebendig sind, Gewinner oder Verlierer. Sie können dies jeder der drei Statistiken zuweisen, die Sie auswählen. Du kannst sie nicht auf ein einzelnes Monster stapeln. jedes Monster bekommt man jedes Mal. Diese Punkte sind immun gegen die 100-Grenze. Da es 100 Kampfrunden geben wird, bedeutet dies, dass Sie einen einzigen Wert von bis zu 149 erhalten können, wenn Sie alle Ihre Boni darauf verteilen. Auch hier sieht der Gegner nur Ihre "Basis" -Statistiken. Je weiter Sie sich im Turnier befinden, desto weiter entfernt sich sein Wissen von der Wahrheit.

Schlacht

Der Kampf findet zwischen Dreierteams statt, von denen jeweils eines aktiv ist. Zu Beginn wird dir die gegnerische Mannschaft gezeigt und du wirst gefragt, welches Monster dein erster "aktiver" Spieler sein soll.

Danach erfolgt der Wechsel mit folgenden Schritten:

  • Switch: Obligatorische Monsterschalter finden statt (falls vorhanden)
  • Wähle Kampfhandlung
  • Schalter: Alle optionalen Monsterschalter (ausgewählt als Kampfaktion) werden ausgeführt
  • Schlaf-Check: Chance, aus dem Schlaf aufzuwachen
  • Angriff 1: Wenn möglich, verwendet das schnellere Monster seinen ausgewählten Zug
  • Angriff 2: Falls möglich, verwendet das andere Monster seinen ausgewählten Zug
  • Effektschaden: Füge lebenden Monstern Verbrennungs- / Giftschaden zu

"Schneller" bedeutet das Monster mit der höheren Geschwindigkeit. Wenn beide Geschwindigkeitsstatistiken gleich sind, wird dies durch PRNG-Münzwurf bei jeder Umdrehung ausgewählt.

Am Ende jedes Spielzugs, in dem dein aktives Monster stirbt, wirst du aufgefordert, ein neues aktives Monster zu wählen. Du kannst auch aktive Monster während deines Zuges wechseln (vorausgesetzt, du hast mehr als ein Lebendiges). Wenn Sie in diesem Zug wechseln, werden Sie in diesem Zug keinen Kampfzug ausführen.

Monster werden nicht "verarbeitet", wenn sie inaktiv sind. Dies bedeutet, dass sie keinen Brand- / Giftschaden erleiden, dass sich keine Giftmarken ansammeln, dass sie nicht aus dem Schlaf erwachen usw. Beim Umschalten werden keine Effekte entfernt oder geändert . Dies ist nicht das andere Monster-Kampfspiel. Wenn Sie mit erhöhtem und verbranntem Angriff ausschalten, bleiben diese beim Wiedereinschalten erhalten.

Effektschaden entsteht, egal ob du deinen aktiven Gegner tötest oder nicht. Auf diese Weise können Mitglieder beider Teams in einem Zug sterben.

Wenn einem Team die verwendbaren Monster ausgehen, verlieren sie. Wenn beide Teams im selben Zug ausscheiden, ist es ein Unentschieden. Wenn der Kampf 1000 Runden dauert, ist es ein Unentschieden.

Die Formel zur Ermittlung des Schadens lautet:

floor((effAttack / effDefense) * movePower * typeMultiplier * moveBoost)

effAttackund effDefensesind die effektiven Werte für die Monster. Ein effektiver Angriff wird erzielt, indem Attacke und Bonusattacke addiert und dann (mit 0,8 oder 1,25) multipliziert werden, wenn Effekte dies ändern. Denken Sie daran, dass diese Effekte gestapelt werden können.

Der Schaden kann nur 0 sein, wenn der Typmodifikator 0 ist (Normal <-> Hell) oder die Bewegungskraft 0 ist (Heilen, Brennen usw.). Andernfalls wird das Minimum bei 1 durchgesetzt.

Turnier

Turniere dauern 100 Runden. In jeder Runde werden die Teams nach dem Zufallsprinzip gemischt und gepaart. Bei einer ungeraden Anzahl von Mannschaften erhält der übrig gebliebene Spieler einen Abschied (Punktestand als Gleichstand). Wenn Sie einen Kampf gewinnen, erhalten Sie 2 Punkte, Unentschieden sind 1 wert und verlieren nichts. Das Team mit den meisten Punkten am Ende gewinnt!

Wenn Teams unentschieden sind, findet ein Turnier statt, bei dem nur die Teams den ersten Platz belegen, um die Reihenfolge der Tiebreaker zu bestimmen.

Protokoll

Die Steuerung sendet Ihrem Programm einen von vier Befehlen. Das erste Zeichen bestimmt den Befehlstyp, ggf. mit folgenden Daten.

Ihr Programm akzeptiert den Befehl als Argument und antwortet innerhalb einer Sekunde auf STDOUT . Bleiben Sie nicht am Leben und hören Sie STDIN, es wird nicht da sein. Jeder Befehl erzeugt einen neuen Prozess.

Sie können Daten / Status auf die Festplatte schreiben. Platzieren Sie alle Dateien in einem Unterordner mit demselben Namen wie Ihr Team. Schreiben Sie nicht mehr als 32 Kilobyte Daten, sonst werden Sie disqualifiziert. Die Daten bleiben zwischen den Runden erhalten, werden jedoch zwischen den Turnieren gelöscht.

Befehle

Teamdaten

Diese wird einmal zu Beginn des Turniers gesendet, um Ihre Mannschaft anzumelden. Ihre Antwort sollte konstant sein und sich nicht von Turnier zu Turnier unterscheiden.

Abfrage:

T

Antwort:

name|member0|member1|member2

nameist eine Zeichenfolge mit Ihrem Teamnamen. Bitte verwenden Sie nur alphanumerische Zeichen, um das Parsen zu vereinfachen. memberNist eine Mitgliedszeichenfolge, die die Details der einzelnen Monster angibt:

Mitgliedsstring:

name:typeid:attack:defense:speed:moveid0:moveid1:moveid2

Auch hier ist 'name' eine Zeichenfolge, diesmal mit dem Namen dieses Monsters. typeidist sein Typ. Typ-IDs sind in der in der obigen Tabelle angegebenen Reihenfolge angegeben, mit Normal = 0 und Grass = 4.

Die nächsten drei Felder sind Ihre Basisstatistiken. Beachten Sie die im Abschnitt "Statistiken" oben beschriebenen Grenzwerte.

Die letzten drei sind die Züge deines Monsters. IDs werden in der obigen Verschiebungstabelle angezeigt.

Eine Beispielantwort auf Teamdaten könnte folgendermaßen aussehen:

DummyTeam|DummyA:0:50:60:70:0:1:2|DummyB:0:50:60:70:0:1:2|DummyC:0:50:60:70:0:1:2

Jedes Team, das hier Müll, falsch formatierte oder illegale Daten zurücksendet, wird erst teilnehmen, wenn dies behoben ist.

Wählen Sie Aktiv

Dies wird zu Beginn jedes Kampfes gesendet und wenn ein Monster stirbt und gewechselt werden muss.

Abfrage:

C#battleState

battleStatezeigt den Stand der aktuellen Schlacht. Tragen Sie mich hier, es ist hässlich:

yourTeamState#theirTeamState

Wo XteamStatesieht es aus wie:

name:activeSlot|member0state|member1state|member2state

activeSlotzeigt welches Monster gerade aktiv ist (0-2). Die Mitgliedstaaten kommen in zwei Varianten. Wenn es Ihr Team ist, gibt es zusätzliche Informationen. Damit,

Dein memberXstate:

name:id:attack:defense:speed:hp:typeid:poisonedturns:moveCount0:moveCount1:moveCount2:bonusAttack:bonusDefense:bonusSpeed:effectid:effectid:effectid

Ihr memberXstate:

name:id:attack:defense:speed:hp:typeid:poisonedturns:effectid:effectid:effectid

idDies ist einfach eine Ganzzahl, mit der Sie Monster verfolgen können, wenn Sie sie nicht verwenden möchten name.

attack:defense:speedsind deine Basisstatistiken .

poisonedturns sagt dir, für wie viele Runden du vergiftet wurdest.

moveCountXgibt an, wie viele Nutzungen Sie für jeden Zug übrig haben. Wenn 0, kann es nicht verwendet werden. Bei unbegrenzten Zügen ist dies negativ.

bonus(stat) ist die Anzahl der Bonuspunkte, die Sie für jede Statistik vergeben haben.

effectidist eine Liste mit Effekten variabler Größe, die auf dein Monster angewendet wurden. Es wird kein Trailing geben:Die Zeichenfolge , unabhängig davon, ob aktive Effekte vorhanden sind oder nicht. Wenn gestapelte Effekte vorhanden sind, werden sie in der Liste als mehrere Effekte angezeigt.

Die Effekt-IDs sind:

0  NONE           (should not appear, internal use)
1  POISON
2  CONFUSION 
3  BURN 
4  SLEEP 
5  HEAL           (should not appear, internal use)
6  ATTACK_UP
7  ATTACK_DOWN
8  DEFENSE_UP
9  DEFENSE_DOWN
10 SPEED_DOWN

Antwort:

memberSlot

Die einzige Antwort, die benötigt wird, ist eine einzelne Zahl von 0,1,2, die angibt, welches Mitglied aktiv sein soll. Dies muss ein Mitglied sein, das kämpfen kann. Senden Sie nicht zurück, 1wenn Mitglied 1 tot ist.

Kampfhandlung

In jeder Runde musst du entscheiden, was zu tun ist.

Abfrage:

A#battleState

Das battleStatehier ist genau wie oben beschrieben.

Antwort:

Senden Sie den Slot, in dem sich der Move befindet, zurück, um einen Move auszuführen. Wenn ich beispielsweise Slot 0 einen 0Punch zugewiesen habe, wird beim Senden ein Punch ausgeführt.

Um zu einem anderen Mitglied zu wechseln, senden Sie den Steckplatz des Mitglieds plus zehn . Also, um zu Mitglied 2 zu wechseln, senden Sie 12.

Alles, was nicht in [0,1,2,10,11,12] enthalten ist, wird als ungültig betrachtet und hat in dieser Runde keine Aktion zur Folge.

Bonus Stats

Nach jeweils zwei Kämpfen erhalten Sie einen geheimen Bonuspunkt für jedes Teammitglied.

Abfrage:

B#yourTeamState

Ihr Teamstatus ist derselbe wie oben gezeigt. Lassen Sie mich das nicht wiederholen.

Antwort:

stat0:stat1:stat2

Ihre Antwort gibt an, welche Statistik für jedes Teammitglied erhöht werden soll. Angriff ist 0, Verteidigung ist 1, Geschwindigkeit ist 2.

Um also die Geschwindigkeit des Mitglieds, den Angriff des Mitglieds zwei und die Verteidigung des Mitglieds drei zu erhöhen, würden Sie antworten mit:

2:0:1

Regler

Der Controller befindet sich auf BitBucket: https://Geobits@bitbucket.org/Geobits/codemon.git

Wirf einfach alle kompilierten Klassendateien, Einreichungen und die player.conf in einen Ordner und starte sie.

Die Hauptklasse des Controllers heißt Tournament. Verwendung ist:

java Tournament [LOG_LEVEL]

Log-Level von 0-4 geben ansteigende Informationen. Stufe 0 führt das Turnier im Hintergrund aus und gibt nur die Ergebnisse aus, wobei Stufe 3 die einzelnen Kommentare enthält. Stufe 4 ist die Debug-Ausgabe.

Sie können dem Turnier Einsendungen hinzufügen in players.confFügen Sie einfach die Befehlszeilenzeichenfolge hinzu, die zum Ausführen des Programms erforderlich ist, eine pro Zeile. Zeilen, die mit beginnen, #sind Kommentare.

Fügen Sie in Ihren Beitrag den Befehl, den ich zu meinem hinzufügen muss players.conf, sowie alle Kompilierungsschritte (falls erforderlich) ein.

Eingeschlossen ist ein Dummy-Team, das sich aus allen normalen Mitgliedern mit den drei normalen Zügen zusammensetzt. Sie wählen Züge nach dem Zufallsprinzip und haben schreckliche Statistiken. Viel Spaß beim Prügeln.

Verschiedene Regeln

  • Sie dürfen keine externen Ressourcen lesen oder darauf schreiben (außer in Ihrem eigenen Unterordner, bis zu 32 kB, wie oben angegeben).

  • Ihre Mannschaft muss "blind" in das Turnier einsteigen. Das bedeutet, dass Sie die Quelle anderer Leute nicht analysieren können, um herauszufinden, was ein bestimmtes Team / Monster in einer bestimmten Situation tun wird. Sie können die Züge / Statistiken Ihres Gegners analysieren und den Verlauf des Turniers verfolgen, diese Informationen jedoch nicht fest einkodieren.

  • Stören Sie nicht andere Prozesse / Einreichungen. Kein Aufrufen, Verwenden von Reflektion, um an ihre Daten zu gelangen usw. Lege dich nicht mit meinem Computer an. Versuche es einfach nicht. Dies liegt in meinem Ermessen. Zuwiderhandlungen können von der zukünftigen Einreise ausgeschlossen werden.

  • Die Teilnehmer sind auf maximal zwei Einsendungen beschränkt. Wenn Sie mehr einreichen, erziele ich nur die ersten beiden eingereichten Punkte. Wenn Sie einen widerrufen möchten, löschen Sie ihn.

  • Einträge dürfen nicht nur existieren, um andere Einträge zu unterstützen. Sie dürfen auch nicht versuchen, andere Teilnehmer indirekt zu disqualifizieren (z. B. indem Sie DQ-Spielern, die versuchen, dies auf die Festplatte zu schreiben, einen Teamnamen mit 27 Millionen Zeichen geben). Jede Einreichung sollte spielen, um für sich zu gewinnen.

  • Ihr Programm kann maximal einen untergeordneten Prozess gleichzeitig erzeugen (insgesamt Nachkommen, nicht direkt). Sowohl der Hauptprozess als auch alle untergeordneten Prozesse müssen direkt nach der Ausgabe beendet werden. Stellen Sie in jedem Fall sicher, dass Sie die Zeitüberschreitung nicht überschreiten.

  • Das Turnier findet auf meinem Computer statt, auf dem Ubuntu mit einem Intel i7 3770K-Prozessor ausgeführt wird.

Ergebnisse

Dies sind die Ergebnisse der aktuellen Spieler. Es ist sehr eng zwischen den Top-Konkurrenten und ich denke darüber nach, die Anzahl der Runden auf 500 zu erhöhen (und den Abstand der Bonuspunkte entsprechend anzupassen). Irgendwelche Einwände, Kommentare?

------- Final Results -------

158     Happy3Campers
157     LittleKid
71      InsideYourHead
68      HardenedTrio
46      BitterRivals

Vollständige Play-by-Play-Ergebnisse auf Google Drive


62
Ich möchte der Beste sein / Wie kein Code jemals war / Nicht zum Absturz zu bringen ist mein Test / Debuggen ist meine Sache! / Ich werde über das LAN reisen / Scripting weit und breit / Ich versuche es schwer zu verstehen / Warum mein BIOS nicht funktioniert! / Codémon, du und ich / Golfen fürs Auge / Codémon, du bist mein bester Freund / Nach Programmende! / Codémon, a lang so true / Keine Segfaults werden uns durchziehen / Du unterrichtest mich und ich unterrichte dich / Codémon, du musst sie alle Golf spielen!
Kaz Wolfe

1
Anstatt die Runden auf 500 zu erhöhen, wäre es schön, wenn eine Runde aus jedem bestehen würde, der gegen jeden kämpft. Also nicht mehr byes für eine ungerade Anzahl von Konkurrenten und es wäre sichergestellt, dass die Matchpaare fair und gleichmäßig verteilt sind.
foobar

@foobar Ich wollte das vermeiden, weil es die Kämpfe mit n^2statt skaliert n. Bei nur 7 Teilnehmern und 100 Runden sind das 2100 Gefechte (300 wie sie sind und 1500 mit 500 Runden). Es wird nur schlimmer, wenn mehr Einträge eingehen. Ich könnte die Anzahl der Runden reduzieren, aber ich zögere, dies aufgrund der inhärenten Variabilität (insbesondere in Bezug auf den Status) zu tun, und ein Vielfaches von 50 (für Bonuspunkte) ist einfacher.
Geobits

Benötigt diese Herausforderung kein Update? :)
GholGoth21

@ GholGoth21 Ja, ich glaube schon. Ich komme heute wahrscheinlich nicht dazu, aber vielleicht morgen oder am nächsten Tag. Pingen Sie mich im Chat an, wenn Sie bis Donnerstag nicht auf dem neuesten Stand sind oder wenn Sie möchten.
Geobits

Antworten:


16

Glückliche 3 Camper - PHP

Ein Haufen Feiglinge, die es mögen, die Gegner mit schwächenden Zaubersprüchen zu betäuben und ihnen beim Verrotten zuzusehen.

EDIT : Herr Lumpy wurde streng bestraft und wird keine schlechten Worte mehr sagen


PraktischPraktischGrass - atk:50 def:99 spd:81 Confuse Poison Heal

Ein giftiger armloser Biber, der gerne Menschen mit problematischen Händedrucks verwirrt


FlippyFlippyWater - atk:50 def:99 spd:81 Confuse Burn Heal

Ein Bulletin-Board-Veteran mit einem Faible für langweilige Gespräche und Flammenkriege.


NussigNussigFire - atk:50 def:99 spd:81 Burn Poison Heal

Massenvernichtungswaffen sind seine Lieblingssüßigkeiten.


KlumpigKlumpigPhp - lines:500 clarity:05 spd:01 Gather Guess Store

Dank seines fast zweistelligen IQ und seines phänomenalen Gedächtnisses kann Lumpy feindliche Bewegungen erraten. Meistens.


Strategie

Die Strategie besteht darin, Gegner so schnell wie möglich vergiften, verbrennen und verwirren zu lassen.
Der Schlaf wurde nicht genutzt, da er weniger mächtig zu sein schien als die drei oben genannten Zaubersprüche.
Verwirrung ist auf lange Sicht tödlich, da sie Angriffe um 30% reduziert (sowohl Schaden verursachend als auch Zauberwirkend), Heiler davon abhält, sich selbst zu heilen, und schwere Schläger schwer verletzt (ein Monster mit 50 Def / 100 Atk fügt sich selbst 20 Schadenspunkte zu ).

Sobald ein Feind gründlich eingeklebt ist, sehen meine Camper, wie er brutzelt, verfault und sich zu Tode schlägt.

Hohe Verteidigung und Heilung werden eingesetzt, um den während der Qualen eintreffenden Schaden zu mindern.

Während meine 3 Camper kämpfen, beobachtet der magische Hirsch Lumpy die Feinde bei jeder Bewegung und schafft es manchmal, sie zu identifizieren. Die Informationen werden an unsere Kämpfer zurückgesandt, die ihr Bestes geben, um sie auszunutzen.

Nach der Verteidigung ist die Geschwindigkeit der wichtigste Punkt, den es zu verbessern gilt.
Initiative ist entscheidend, um Heilung anzuwenden, bevor der nächste Schlag kommt.

Attack wird überhaupt nicht verwendet.

Sind Zauber die ultimative Waffe?

Zaubersprüche wie Gift, Verbrennung und Verwirrung entziehen sich der allgemeinen Rock / Paper / Scissor-Logik anderer Angriffe.

Sobald ein Monster betroffen ist, verliert es auch dann HP, wenn der Zauberwirker tot ist. Es ist, als würde der Geist des Zaubernden ihn immer wieder angreifen.
Außerdem wird Gift schnell stärker als ein voll ausgebuffter massiver Angriff (über 50 Punkte nach 5 Runden).

Die Lebenserwartung eines vergifteten und verbrannten Monsters überschreitet auch bei 3 Heilungen nicht 8 Runden.

Wie Martins Bots zu zeigen scheinen, ist die Spielbalance ziemlich gut.
Es ist im Grunde eine Initiative, die das Gleichgewicht zwischen reinen Zaubernden und reinen Angreifern bestimmen wird.

Der Code

Mit aufrufen php campers.php

Es ist ein hässliches Durcheinander, aber ehrlich gesagt hilft das Interface auch nicht.

Nachdem ein entsprechend aggressiver Wettbewerb aufgetaucht war, setzte ich meine lang geplanten feindlichen Schachzüge um.
Das Analysieren von Angriffen erfordert verschiedene Kunstflug-Abzüge und die dauerhafte Speicherung des Zustands der letzten Runde, was einen vollständigen Krieg mit der paranoiden Controller-Schnittstelle bedeutet.
Es ist kein hübsches Zeug und auch kein sechsbeiniger Hase, aber es macht einen adäquaten Job.

<?php

// ============================================================================
// Game
// ============================================================================
class G {
    static $code_type = array ("Normal", "Psychic", "Fire", "Water", "Grass", "?", "self"); 
    static $code_move = array    ("Punch", "Heal", "Slow", "Pain", "Sleep", "Weaken", "Fireball", "Burn", "Sharpen", "Watergun", "Confuse", "Shield", "Vine", "Poison", "Sap", "?", "self", "pass");
    static $move_uses = array (1000,3,5,1000,3,5,1000,3,5,1000,3,5,1000,3,5,   2000,2000);
    static $move_type      = array (0,0,0,1,1,1,2,2,2,3,3,3,4,4,4, 5,5,5);
    static $move_dmg       = array (20,0,10,20,0,10,20,0,10,20,0,10,20,0,10,  20,10,0);
    static $move_forbidden = array (1,1,1,0,0,0,4,4,4,2,2,2,3,3,3);
    static $code_effect = array ("N", "Poison", "Confuse", "Burn", "Sleep", "H", "Sharpen", "Weaken", "Shield", "Sap", "Slow"); 
    static $decode_type, $decode_move, $decode_effect;
    static $damage_multiplier = array (
        array (2, 0, 1, 1, 1, 0),
        array (0, 2, 1, 1, 1, 0),
        array (1, 1,.5, 2,.5, 0),
        array (1, 1,.5,.5, 2, 0),
        array (1, 1, 2,.5,.5, 0),
        array (2, 2, 2, 2, 2,-1),
        array (9, 9, 9, 9, 9, 9, 1));
    static $atk_score = array ("Poison"=> 1002, "Confuse"=>1001, "Burn"=>1000);
    static $status_field = "atk:def:spd:hp:type:Pturns";
    static $all_moves, $strong_moves, $medium_moves, $effect_moves, $possible_moves;

    function init()
    {
        self::$status_field = explode (":", self::$status_field);
        foreach (array ("type", "move", "effect") as $table) self::${"decode_$table"} = array_flip (self::${"code_$table"});
        foreach (self::$code_move as $c=>$m)
        {
            if ($m == "?") break;
            self::$all_moves[] = new Move($m);
            if (self::$move_uses[$c] >  5) self::$strong_moves[] = $m;
            if (self::$move_uses[$c] == 5) self::$medium_moves[] = $m;
            if (self::$move_uses[$c] == 3) self::$effect_moves[] = $m;
            for ($type = 0 ; $type != 5 ; $type++) if ((self::$move_uses[$c] >  5) && (self::$move_forbidden[$c] != $type)) self::$possible_moves[$type][] = $m;
        }
    }

    function __construct ($name, $team)
    {
        $this->turn = 0;
        $this->name = $name;
        $this->team = $team;
        $this->results_pending = false;
    }

    function parse_team ($tpack, $own_team)
    {
        $pack = explode ("|", $tpack);
        list ($name,$active) = explode (":", array_shift($pack));
        if ($own_team)
        {
            $team = $this->team;
        }
        else
        {
            if (!isset($this->enemies[$name])) $this->enemies[$name] = new Team(array (new Monster (), new Monster (), new Monster ()));
            $team = $this->foes = $this->enemies[$name];
        }
        $team->active = $active;
        foreach ($pack as $i=>$mpack) $team->monster[$i]->parse_monster ($own_team, $mpack);
    }

    function choose_active ()
    {
        // detect start of round
        $team = $this->team;
        $foes = $this->foes;
        foreach ($team->monster as $i=>$m) if ($m->hp > 0) $candidate[$i] = $m;
        if (count ($candidate) == 3)
        {
            $this->results_pending = false;
            $this->round++;

            // reinitialize all monsters
            foreach (array($team, $foes) as $t)
            foreach ($t->monster as $m)
                $m->start_round();

            // guess initial opponent
            $opponent = $foes->initial_opponent();
        }
        else
        {
            $this->analyze_last_round();
            $opponent = $foes->active();
        }
        return $this->do_switch ($opponent);
    }

    function choose_attacker ($foe)
    {
        foreach ($this->team->monster as $i=>$m) if ($m->can_attack($foe)) $candidate[$i] = $m;
        if (isset($candidate))
        {
            uasort ($candidate, function ($a,$b) use ($foe) { return ($a->atk_score != $b->atk_score) ? $b->atk_score - $a->atk_score : $b->life_expectancy($foe) - $a->life_expectancy($foe); });
            return key($candidate);
        }
        return -1;
    }

    function do_switch ($foe)
    {
        $replacement = $this->choose_attacker ($foe);
        if ($replacement < 0)
        {
            $candidate =  $this->team->monster;
            uasort ($candidate, function ($a,$b) use ($foe) { return $b->life_expectancy($foe) - $a->life_expectancy($foe); });
            $replacement = key($candidate);
        }

        $this->old_own = $this->team->monster[$replacement];
        $this->old_own->attack = "pass";
        return $replacement;
    }

    function choose_action ()
    {
        $this->analyze_last_round();
        $own = $this->team->active();
        $foe = $this->foes->active();
        $this->old_own = $own;

        if ($own->hp <= $own->max_damage($foe) && $own->can_do ("Heal")) return $own->execute("Heal");
        if ($attack = $own->can_attack($foe)) return $own->execute($attack);
        if ($own->hp <= 50 && $own->can_do ("Heal")) return $own->execute("Heal");

        return 10 + $this->do_switch ($foe);    
    }

    function choose_bonus()
    {
        foreach ($this->team->monster as $m)
        {
            if ($m->spd_b == 0) { $m->spd_b++; $res[] = 2; }
            else                { $m->def_b++; $res[] = 1; }
        }
        return implode (":", $res);
    }

    function parse ($parts)
    {
        self::parse_team ($parts[1], true);
        self::parse_team ($parts[2], false);    
    }

    function analyze_last_round()
    {
        if ($this->results_pending)
        {
            $this->results_pending = false;

            $foes = $this->foes;
            $foe = null;
            foreach ($foes->monster as $m) if ($m->hp != $m->old->hp) $foe = $m;
            if ($foe === null) $foe = $foes->monster[$foes->active];

            $this->old_own->guess_attack($foe);
        }
    }

    function process ($line)
    {
        $parts = explode ("#", $line);
        switch ($parts[0])
        {
        case "T": // register for tournament
            echo "$this->name|$this->team";
            break;
        case "C": // designate active monster
            $this->parse ($parts);
            echo $this->choose_active();
            break;
        case "A": // choose round action
            $this->parse ($parts);
            echo $this->choose_action();

            // save current state
            foreach (array($this->team, $this->foes) as $t)
            foreach ($t->monster as $m)
            {
                unset ($m->old);
                $m->old = clone ($m);
            }
            $this->results_pending = true;
            break;
        case "B": // distribute stat bonus
            echo $this->choose_bonus();
            break;
        }

    }
}
G::init();

// ============================================================================
// Move
// ============================================================================
class Move {
    function __construct ($move)
    {
        $this->register($move);
    }

    function register ($move)
    {
        $this->type = G::$decode_move[$move];
        $this->reinit();
    }

    function reinit()
    {
        $this->uses = G::$move_uses[$this->type];
    }

    function __tostring() { return G::$code_move[$this->type]."($this->uses)"; }
}

// ============================================================================
// Monster
// ============================================================================
class Monster { 
    function __construct ($name="?", $type="?", $atk=100, $def=100, $spd=100, $m0="?", $m1="?", $m2="?")
    {
        $this->name = $name;
        $this->type = G::$decode_type[$type];
        $this->atk  = $atk;
        $this->def  = $def;
        $this->spd  = $spd;
        $this->hp   = 100;
        $this->move = array (new Move($m0), new Move($m1), new Move($m2));
        $this->atk_b = 0;
        $this->def_b = 0;
        $this->spd_b = 0;
        foreach (G::$code_effect as $e) $this->$e = 0;
    }

    function __tostring ()
    {
        return implode (":", array (
            $this->name,
            $this->type,
            $this->atk,
            $this->def,
            $this->spd,
            $this->move[0]->type,
            $this->move[1]->type,
            $this->move[2]->type));
    }

    function start_round()
    {
        foreach ($this->move as $m) $m->reinit();
    }

    function parse_monster ($own_team, $spack)
    {
        $pack = explode (":", $spack);
        $name = array_shift ($pack); // get name
        array_shift ($pack); // skip id
        if ($this->name == "?") $this->name = $name; // get paranoid
        else if ($this->name != $name) die ("expected $this->name, got $name");

        // store updated values
        foreach (G::$status_field as $var) $this->$var = array_shift ($pack);
        if ($own_team)
        {
            foreach ($this->move as $m) $m->new_count = array_shift($pack);
            $pack = array_slice ($pack, 3); // these are maintained internally
        }
        $var = array();
        foreach ($pack as $e) @$var[G::$code_effect[$e]]++; 
        foreach (G::$code_effect as $e) $this->$e = @$var[$e]+0;
    }

    function damage_recieved ($attack, $foe=null)
    {
        if ($attack == "self") $foe = $this;
        $a = G::$decode_move[$attack];
        $type = G::$move_type[$a];
        $dmg = g::$move_dmg[$a];

        if ($dmg == 0) return 0;

        $atk = ($foe ->atk+$foe ->atk_b) * pow (.8, ($foe ->Weaken - $foe ->Sharpen));
        $def = ($this->def+$this->def_b) * pow (.8, ($this->Sap    - $this->Shield ));

        $boost = ($foe->type == $type) ? 1.2 : 1;
        return max (floor ($dmg * $atk / $def * $boost * G::$damage_multiplier[$this->type][$type]), 1);
    }

    function guess_attack_from_effect ($attacks)
    {
        foreach ($attacks as $status) if ($this->$status != $this->old->$status) return $status;
        return "?";
    }

    function guess_attack_from_damage ($foe, $damages)
    {
        $select = array();
        foreach (G::$possible_moves[$foe->type] as $attack)
        {
            $dmg = $this->damage_recieved ($attack, $foe);
            foreach ($damages as $damage) if ($damage != 0 && abs ($dmg/$damage-1) < 0.1) $select[$attack] = 1;
        }
        $res = array();
        foreach ($select as $a=>$x) $res[] = $a;
        return $res;
    }

    function guess_attack ($foe)
    {
        $attempt = G::$decode_move[$this->old->attack];
        $success = ($this->old->attack == "pass");
        foreach ($this->move as $m)
        {
            if ($m->type == $attempt)
            {
                if ($m->new_count == $m->uses-1)
                {
                    $m->uses--;
                    $success = true;
                }
                break;
            }
        }

        $possible = array();
        $attack = $this->guess_attack_from_effect (array("Burn", "Confuse", "Poison", "Sleep", "Slow", "Weaken", "Sap"));
        if ($attack == "?") $attack = $foe->guess_attack_from_effect (array("Sharpen", "Shield"));
        if ($attack == "?")
        {
            $foe_damage = $this->old->hp - $this->hp - (10 * $this->Burn + 5 * $this->Pturns*$this->Poison);
            if ($this->old->attack == "Heal" && $success) $foe_damage += 50;
            $possible_dmg[] = $foe_damage;
            //;!;if ($this->Confuse) $possible_dmg[] = $foe_damage + $this->damage_recieved ("self");
            $possible = $this->guess_attack_from_damage ($foe, $possible_dmg);
            if (count ($possible) == 1) $attack = $possible[0];
        }
        if ($attack == "?")
        {
            $own_damage = $foe->old->hp - $foe->hp 
                        - (10 * $foe->Burn + 5 * $foe->Pturns*$foe->Poison)
                        + $foe->damage_recieved ($this->attack);
            if (abs ($own_damage/50+1) < 0.1) $attack = "Heal";
        }
        if ($attack != "?")
        {
            $type = G::$decode_move[$attack];
            if ($attack != "?")
            {
                foreach ($foe->move as $m) if ($m->type == $type) goto found_old;
                foreach ($foe->move as $m) if ($m->type == 15) { $m->register($attack); goto found_new; }
            }
            found_new:
            found_old:
        }
    }

    function max_damage($foe)
    {
        $dmg = 0;
        foreach ($foe->move as $m) $dmg = max ($dmg, $this->damage_recieved (G::$code_move[$m->type], $foe));
        return $dmg;
    }

    function expected_damage ($foe)
    {
        return $this->max_damage($foe) + 10 * $this->Burn + 5 * ($this->Pturns+1);
    }

    function life_expectancy ($foe)
    {
        $hp = $this->hp;
        $poison = $this->Pturns;
        $heal = $this->can_do ("Heal");
        $dmg = $this->max_damage($foe);
        for ($turn = 0 ; $hp > 0 && $turn < 10; $turn++)
        {
            $hp -= 10 * $this->Burn + 5 * $poison;
            if ($poison > 0) $poison++;
            $hp -= $dmg;
            if ($hp <= 0 && $heal > 0) { $hp+=50; $heal--; }
        }
        return 100 * $turn + $this->hp;
    }

    function can_attack ($foe)
    {
        $attack = false;
        if ($this->hp > 0)
        {
            if      (!$foe->Poison  && $this->can_do ("Poison" )) $attack = "Poison";
            else if (!$foe->Confuse && $this->can_do ("Confuse")) $attack = "Confuse";
            else if (!$foe->Burn    && $this->can_do ("Burn"   )) $attack = "Burn";
        }
        $this->atk_score = ($attack === false) ? 0 : G::$atk_score[$attack];
        return $attack;
    }

    function can_do($move)
    {
        $type = G::$decode_move[$move];
        foreach ($this->move as $m) if ($m->type == $type && $m->uses > 0) return $m->uses;
        return false;
    }

    function execute($move)
    {
        $type = G::$decode_move[$move];
        foreach ($this->move as $i=>$m) if ($m->type == $type) 
        { 
            if ($m->uses > 0)
            {
//;!;               $m->uses--;
                $this->attack = $move;
            }
            else $this->attack = "pass";
            return $i; 
        }
        die ("$this asked to perform $move, available ".implode(",", $this->move));
    }
}

// ============================================================================
// Team
// ============================================================================
class Team {
    function __construct ($members)
    {
        $this->monster = $members;
    }

    function __tostring()
    {
        return implode ("|", $this->monster);
    }

    function active ()
    {
        return $this->monster[$this->active];
    }

    function initial_opponent()
    {
        return $this->monster[0];
    }
}

// ============================================================================
// main
// ============================================================================
$input = $argv[1];

$team_name = "H3C";
$mem_file = "$team_name/memory.txt";
$trc_file = "$team_name/trace.txt";
if (!file_exists($team_name)) mkdir($team_name, 0777, true) or die ("could not create storage directory '$team_name'");
if ($input == "T") array_map('unlink', glob("$team_name/*.txt"));

if (file_exists($mem_file)) $game = unserialize (file_get_contents ($mem_file));
else
{
    $team = new Team (
        array (
            new Monster ("Handy" , "Grass" , 50, 99, 81, "Confuse", "Poison", "Heal"),
            new Monster ("Nutty" , "Fire"  , 50, 99, 81, "Burn"   , "Poison", "Heal"),
            new Monster ("Flippy", "Water" , 50, 99, 81, "Confuse" , "Burn" , "Heal")));
    $game = new G($team_name,$team);
}

$game->process ($input);
file_put_contents ($mem_file, serialize($game));

Ergebnisse

LittleKid ist immer noch bedrohlich, aber mein Trio hat seine giftigen Freaks mit ziemlicher Sicherheit besiegt.

Martins Bots sind durch ihre mangelnde Initiative zum Scheitern verurteilt, und eine Erhöhung ihrer Geschwindigkeit würde eine Verringerung des Angriffs erfordern, was ihre Schadensbegrenzung verringern würde.

Die neuen Konkurrenten von Planet JavaScript stehen dem Team im Zweikampf in nichts nach, schneiden aber im Vergleich zu anderen Konkurrenten schlechter ab. Sie helfen tatsächlich dabei, LittleKids Punktzahl zu senken :).

So wie es scheint, bleiben meine kuscheligen Freunde Könige des Hügels - fürs Erste ...

170             H3C
158             Nodemon
145             LittleKid
55              InsideYourHead
42              HardenedTrio
30              BitterRivals

Und ich habe auch kein PHP auf meinem. Ich würde allerdings erwarten, dass Sie den Boden mit den Metapoden abwischen, da sie eine langsame Strategie verfolgen und sich zu Tode vergiften würden.
Sp3000,

... * und * knusprig gebrannt: D. Das ist das Problem mit komplizierten Regeln: Es ist sehr wahrscheinlich, dass eine dominante Strategie entsteht. Da es keinen Schutz gegen diese Zauber gibt, könnten sie Codémons dicker Mann und kleiner Junge sein.

Ich würde es eher mit einem nicht-transitiven Spiel wie Schere, Papier, Stein vergleichen - da die Effekte eine Weile dauern, sollte ein Full-Attack-Team in der Lage sein, Sie
auszuschalten

2
Ja, das habe ich mir vorgestellt, sobald ich kein Heilmittel für Poison and Burn mehr sehe. Vielen Dank, dass Sie meinen Traum zum Leben erweckt haben.
Nur die Hälfte des

1
Das ist Mr. Lumpy, der seine Verwirrung zum Ausdruck bringt, wenn er mehr als 3 verschiedene Angriffe desselben Gegners entdeckt :). Ich habe eine fast vollständige feste Version, aber ich bin gerade in der Mitte einer anderen Sache, daher wird die Korrektur in etwa einem Tag veröffentlicht.

7

HardenedTrio, Python 3

Da war Geobits nett genug, uns zu geben zwei Einsendungen , dachte ich, ich würde etwas Dummes für die erste : P

Die Partei ist drei Codemon (Metapod1, Metapod2, Metapod3) mit den gleichen Statistiken und Bewegungen:

  • 80 Angriff, 100 Verteidigung, 50 Geschwindigkeit
  • Punch, Heilen, Schild Harden

Alle Bonuspunkte werden auch der Verteidigung zugewiesen.


from collections import namedtuple
import sys

BattleState = namedtuple("BattleState", ["us", "them"])
TeamState = namedtuple("TeamState", ["name", "active", "members"])
MemberState = namedtuple("MemberState", ["name", "id", "attack", "defense", "speed", "hp",
                                         "typeid", "poisonedturns", "otherstats"])

def parse_battle_state(state):
    return BattleState(*map(parse_team_state, state.split("#")))

def parse_team_state(state):
    na, *members = state.split("|")
    name, active = na.split(":")
    return TeamState(name, int(active), list(map(parse_member_state, members)))

def parse_member_state(state):
    name, id_, attack, defense, speed, hp, typeid, poisonedturns, *rest = state.split(":")
    return MemberState(name, int(id_), float(attack), float(defense), float(speed),
                       float(hp), int(typeid), int(poisonedturns), rest)

command = sys.argv[1].strip()

if command.startswith("T"):
    print("HardenedTrio|Metapod1:0:80:100:50:0:1:11|"
          "Metapod2:0:80:100:50:0:1:11|Metapod3:0:80:100:50:0:1:11")

elif command.startswith("C"):
    battle_state = parse_battle_state(command[2:])

    for i, codemon in enumerate(battle_state.us.members):
        if codemon.hp > 0:
            print(i)
            break

elif command.startswith("A"):
    battle_state = parse_battle_state(command[2:])
    current_codemon = battle_state.us.members[battle_state.us.active]

    if current_codemon.hp < 50 and int(current_codemon.otherstats[1]) > 0:
        print(1) # Heal up if low

    elif int(current_codemon.otherstats[2]) > 0:
        print(2) # Harden!

    else:
        print(0) # Punch!

elif command.startswith("B"):
    print("1:1:1")

Laufen Sie mit

py -3 <filename>

(oder mit python/ python3statt pyje nach Installation)



1
@FryAmTheEggman Metapod, HARDEN!
Sp3000,

Ich versuche, Ihren Code zu lesen, bin aber bei verwirrt int(current_codemon.otherstats[1])>0. Das ist wahr, wenn er einen Statuseffekt hat? Und er benutzt Harden nur, wenn er zwei Statuseffekte hat?
Mooing Duck

@MooingDuck Für dein Codemon hast du moveCounts vor dem effectids, also prüft es, ob es noch Harden verwenden kann. Ich bin beim Parsen faul geworden, weshalb es dort hineingelaufen ist.
Sp3000,

@ Sp3000: Oh! Richtig! HAHAHA!
Mooing Duck

6

In deinem Kopf, Ruby

  • Brian : Hellseher, Angriff: 100, Verteidigung: 50, Geschwindigkeit: 80, Schmerz, Feuerball, Wasserpistole
  • Elemon1 : , Angriff: 100, Verteidigung: 50, Geschwindigkeit: 80, Feuerball, Wasserpistole, Rebe
  • Elemon2 : Hellseher , Angriff: 100, Verteidigung: 50, Geschwindigkeit: 80, Feuerball, Wasserpistole, Rebe
TEAM_SPEC = "InsideYourHead"+
            "|Brian:1:100:50:80:3:6:9"+
            "|Elemon1:1:100:50:80:6:9:12"+
            "|Elemon2:1:100:50:80:6:9:12"

def parse_battle_state request
    request.map do |team_state|
        state = {}
        parts = team_state.split '|'
        state[:active] = parts.shift.split(':')[1].to_i
        state[:monsters] = parts.map do |monster_state|
            monster = {}
            parts = monster_state.split(':')
            monster[:name] = parts[0]
            monster[:hp] = parts[5].to_i
            monster[:type] = parts[6].to_i
            monster
        end
        state
    end
end

request = ARGV[0].split '#'
case request.shift
when 'T'
    puts TEAM_SPEC
when 'C'
    battle_state = parse_battle_state request
    my_state = battle_state[0]
    puts my_state[:monsters].find_index {|monster| monster[:hp] > 0}
when 'A'
    battle_state = parse_battle_state request
    my_state, their_state = *battle_state
    my_monster = my_state[:monsters][my_state[:active]]
    their_monster = their_state[:monsters][their_state[:active]]
    puts [1,0,1,2,0][their_monster[:type]]
when 'B'
    puts '0:0:0'
end

Laufen Sie mit

ruby InsideYourHead.rb

Dies funktioniert nicht sehr gut gegen Manus Bot, schlägt aber die anderen drei. Die Team- und Monsternamen sind ziemlich zufällig ... Ich könnte sie ändern, wenn ich etwas Besseres finde

Die Strategie ist ziemlich einfach: Angriff!Alle drei Monster haben nur reine Angriffszüge und sie wählen ihren Zug basierend auf dem Monstertyp des Gegners.

Ich könnte später mit dem Einwerfen einer Heilung experimentieren.


1
Hehe das wird interessanter. Ich wusste, dass ich mich darauf verlassen kann, Martin :)

6

LittleKid, Java

Ein kleines Kind fand 3 identische Codemons und bildete sie aus. Sie sind sehr nervig mit ihren Heil- und Giftattacken. Wenn Sie nur Codémons vom normalen Typ verwenden, müssen Sie sie nicht mehr mit bestimmten Gegnern abstimmen, da Gift gegen alle Typen gut wirkt.

public class LittleKid {

    public static void main(String[] args) {
        if(args.length < 1){
            System.out.println("Geobits says you can't do this.");
            System.exit(0);
        }

        String[] sections = args[0].split("#");
        String me, them, out = "";
        switch(sections[0]){
            case "T":
                out = "LittleKid";
                out += "|Poisoner:0:80:100:50:0:1:13";
                out += "|Poisoner:0:80:100:50:0:1:13";
                out += "|Poisoner:0:80:100:50:0:1:13";
                break;
            case "B":
                out = "1:1:1";
                break;
            case "C":
                me = sections[1];
                them = sections[2];
                int pick = 0;

                if(!isAlive(me, pick)){
                    for(int i=0;i<3;i++){
                        if(isAlive(me,i))
                            pick = i;
                    }
                }

                out = String.valueOf(pick);
                break;
            case "A":
                me = sections[1];
                them = sections[2];
                int active = getActive(me);
                int enemyActive = getActive(them);
                if (getField(me, HP, active) < 50 && getField(me, MOVE1, active) != 0) {
                    out = "1";
                } else if (getEffectCount(them, POISON, enemyActive, false) < 1 && getField(me, MOVE2, active) != 0) {
                    out = "2";
                } else {
                    out = "0";
                }
                break;
            default:
                out = "Invalid query from controller.";             
        }
        System.out.println(out);
    }

    static boolean isAlive(String teamState, int who){
        return getField(teamState, HP, who) > 0;
    }

    static int getActive(String teamState){
        return Integer.parseInt(teamState.split("\\|")[0].split(":")[1]);
    }

    static int getField(String teamState, int field, int who){
        String[] fields = teamState.split("\\|")[who+1].split(":");
        return Integer.parseInt(fields[field]);
    }

    static int getEffectCount(String teamState, int effect, int who, boolean mine){
            String[] fields = teamState.split("\\|")[who+1].split(":");
            int count = 0;
            for(int i=mine?14:8;i<fields.length;i++){
                if(Integer.parseInt(fields[i]) == effect)
                    count++;
            }
            return count;
    }

    final static int ID =       1; 
    final static int ATTACK =   2; 
    final static int DEFENSE =  3; 
    final static int SPEED =    4; 
    final static int HP =       5; 
    final static int TYPE =     6;
    final static int MOVE0 =    8; 
    final static int MOVE1 =    9; 
    final static int MOVE2 =    10;

    final static int POISON =           1;
}

5
" Geobits sagt, dass du das nicht kannst ": D
Geobits

Scheint Gift ist die wahre A-Bombe in diesem Spiel :)

5

Nodémon - Javascript

Da der Status die vorherrschende Strategie zu sein scheint, konzentriert sich dieses Team auf die Geschwindigkeit, um zuerst Status wie Gift und Verwirrung auf die Gegner zu übertragen und dann mit Heilen und / oder Schlafen aufzuhören, während der Gegner verschwindet.

Ich habe kein PHP installiert, so dass dies nicht gegen die Camper getestet wurde, aber es scheint ein anständiger Konkurrent für LittleKid in meinen Versuchen zu sein (und erbitterte Rivalen zu dezimieren).

/*jshint node:true*/
'use strict';

var fs = require('fs');

var dataFile = 'Nodemon/data.json';
function getData(callback) {
  fs.readFile(dataFile, 'utf8', function(err, contents) {
    var data = {round: 0};

    if(!err) {
      data = JSON.parse(contents);
    }

    callback(data);
  });
}

function saveData(data, callback) {
  fs.mkdir('Nodemon', function() {    
    fs.writeFile(dataFile, JSON.stringify(data), callback);
  });
}

var effect = {
  poison: '1',
  confusion: '2',
  burn: '3',
  sleep: '4',
  heal: '5',
  attackUp: '6',
  attackDown: '7',
  defenseUp: '8',
  defenseDown: '9',
  speedDown: '10'
};

function parseMemberCommon(args) {
  return {
    name: args[0],
    id: args[1],
    baseAttack: +args[2],
    baseDefense: +args[3],
    baseSpeed: +args[4],
    hp: +args[5],
    typeId: args[6],
    poisonedTurns: +args[7],
    effects: args.slice(8)
  };
}

function parseOwnMember(arg) {
  var args = arg.split(':');

  var ownArgs = args.splice(8, 6);

  var member = parseMemberCommon(args);

  member.moveCount = [
    +ownArgs[0],
    +ownArgs[1],
    +ownArgs[2]
  ];

  member.bonusAttack = +ownArgs[3];
  member.bonusDefense = +ownArgs[3];
  member.bonusSpeed = +ownArgs[3];

  return member;
}

function parseOpponentMember(arg) {
  return parseMemberCommon(arg.split(':'));
}

function parseTeamStateCommon(arg, memberParse) {
  var args = arg.split(':');
  var state = {
    name: args[0],
    members: []
  };
  args = arg.substring(state.name.length + 1).split('|');
  var activeSlot = args[0];
  for(var index = 1; index < args.length; index++) {
    state.members.push(memberParse(args[index]));
  }
  state.activeMember = state.members[activeSlot];
  return state;
}

function parseOwnState(arg) {
  return parseTeamStateCommon(arg, parseOwnMember);
}

function parseOpponentState(arg) {
  return parseTeamStateCommon(arg, parseOpponentMember);
}

function parseBattleState(arg) {
  var args = arg.split('#');
  return {
    own: parseOwnState(args[0]),
    opponent: parseOpponentState(args[1])
  };
}

function teamData() {

  saveData({round:0}, function() {
    console.log('Nodemon|' + 
      'Charasaur:0:50:80:100:10:13:1|' +
      'Bulbtortle:4:50:80:100:10:13:1|' +
      'Squirtmander:1:50:80:100:10:13:4');
  });
}

function getActiveIndex(battleState) {
  for(var index = 0; index < battleState.own.members.length; index++) {
    var member = battleState.own.members[index];
    if(member.hp > 0) {
      return index;
    }
  }
}

function chooseActive(arg) {
  var battleState = parseBattleState(arg);

  getData(function(data) {
    var allFull = true;
    for(var index = 0; index < battleState.opponent.members.length; index++) {
      var member = battleState.opponent.members[index];
      if(!data.maxSpeed || member.baseSpeed > data.maxSpeed) {
        data.maxSpeed = member.baseSpeed;
      }
      if(member.hp < 100) {
        allFull = false;
      }
    }

    if(allFull) {
      data.round++;
    }

    saveData(data, function() {
      console.log(getActiveIndex(battleState));
    });    
  });
}

function useMove(moves, battleState) {
  var fighter = battleState.own.activeMember;

  for(var moveIndex = 0; moveIndex < moves.length; moveIndex++) {
    var move = moves[moveIndex];
    if(fighter.moveCount[move]) {
      return move;
    }

    for(var memberIndex = 0; memberIndex < battleState.own.members.length; memberIndex++) {
      var member = battleState.own.members[memberIndex];

      if(member.hp > 0 && member.moveCount[move] > 0) {
        return 10 + memberIndex;
      }
    }
  }

  return -1;  //do nothing
}

function battleAction(arg) {
  var battleState = parseBattleState(arg);

  var fighter = battleState.own.activeMember;
  var opponent = battleState.opponent.activeMember;

  var attemptedMoves = [];

  if(opponent.effects.indexOf(effect.poison) === -1) {
    attemptedMoves.push(1);
  }

  if(opponent.effects.indexOf(effect.confusion) === -1) {
    attemptedMoves.push(0);
  }

  if(fighter.name === 'Squirtmander') {
    //sleep
    if(opponent.effects.indexOf(effect.sleep) === -1) {
      attemptedMoves.push(2);
    }
  }
  else {
    //heal
    if(fighter.hp <= 60) {
      attemptedMoves.push(2);
    }
  }

  console.log(useMove(attemptedMoves, battleState));
}

function bonusStats(arg) {
  var teamState = parseOwnState(arg);

  getData(function(data) {
    var result = '1:';

    if(data.round % 4 === 0) {
      result += '1:';
    }
    else {
      result += '2:';
    }
    if(teamState.members[2].baseSpeed + teamState.members[2].bonusSpeed > data.maxSpeed + (data.round / 2)) {
      result += '1';
    }
    else {
      result += '2';
    }
    console.log(result);
  });
}

var actions = {
  'T': teamData,
  'C': chooseActive,
  'A': battleAction,
  'B': bonusStats
};

var arg = process.argv[2];
actions[arg[0]](arg.substring(2));

Laufen Sie mit

node nodemon

PS Entschuldigung an Nodemon .


Dies eskaliert zu einem serverseitigen globalen

4

Bittere Rivalen - Java

Ein Gras / Feuer / Wasser-Team, das es mag, es zu tauschen.

Greenosaurier

Hat zumindest neutrale Abdeckung für jedermann. Hohe Geschwindigkeit, um den Mangel an Verteidigung auszugleichen.

Type: Grass
Attack:   80     Vine
Defense:  50     Punch
Speed:   100     Pain

Suchassistent

Versucht, Feinde mit geringem Angriff zu verseifen. Brennt und Feuerbälle danach.

Type: Fire
Attack:  100     Fireball
Defense:  50     Burn
Speed:    80     Sap

Schutzschild

Verwendet Schild, um die ohnehin hohe Verteidigung zu verbessern. Heilt wenn nötig.

Type: Water
Attack:   80     Watergun
Defense: 100     Shield
Speed:    50     Heal

Code

Dies ist auch im Lieferumfang des Controllers enthalten. Dies ist ein konkurrierendes Team, im Gegensatz zu DummyTeam. Der Befehl, der dafür benötigt wird, players.confist:

java BitterRivals

public class BitterRivals {

    public static void main(String[] args) {
        if(args.length < 1){
            System.out.println("You're not doing this right. Read the spec and try again.");
            System.exit(0);
        }

        String[] sections = args[0].split("#");
        String me, them, out = "";
        switch(sections[0]){
            case "T":
                out = "BitterRivals";
                out += "|Greenosaur:4:80:50:100:12:0:3";
                out += "|Searizard:2:100:50:80:6:7:14";
                out += "|Blastshield:3:80:100:50:9:11:1";
                break;
            case "B":
                out = "2:0:1";
                break;
            case "C":
                me = sections[1];
                them = sections[2];

                int pick = 0;
                switch(getField(them, TYPE, getActive(them))){
                    case 0:
                    case 1:
                    case 3:
                        pick = 0;
                        break;
                    case 2:
                        pick = 2;
                        break;
                    case 4:
                        pick = 1;
                        break;
                }

                if(!isAlive(me, pick)){
                    for(int i=0;i<3;i++){
                        if(isAlive(me,i))
                            pick = i;
                    }
                }

                out = pick + "";
                break;
            case "A":
                me = sections[1];
                them = sections[2];
                int active = getActive(me);
                int oType = getField(them, TYPE, getActive(them));
                switch(active){
                    case 0:         // Greenosaur
                        switch(oType){
                            case 0:
                            case 4:
                                out = "1";
                                break;
                            case 1:
                                out = "2";
                                break;
                            case 3:
                                out = "0";
                                break;
                            case 2:
                                if(isAlive(me, 2)){
                                    out = "12";
                                } else if(isAlive(me, 1)){
                                    out = "11";
                                } else {
                                    out = "1";
                                }
                                break;
                        }
                        break;
                    case 1:         // Searizard
                        if(oType == 3){
                            if(isAlive(me, 0)){
                                out = "10";
                                break;
                            } else if(isAlive(me, 2)){
                                out = "12";
                                break;
                            }
                            if(getEffectCount(them, BURN, getActive(them), false) < 1 && getField(me, MOVE1, active) > 0){
                                out = "1";
                            } else if(getField(me, MOVE2, active) > 0){
                                out = "2";
                            } else {
                                out = "3";
                            }                           
                        } else {
                            if(getField(them, ATTACK, getActive(them)) < 80){
                                if(getEffectCount(them, DEFENSE_DOWN, getActive(them), false) < 1 && getField(me, MOVE2, active) > 0){
                                    out = "2";
                                    break;
                                } else if(getEffectCount(them, BURN, getActive(them), false) < 1 && getField(me, MOVE1, active) > 0){
                                    out = "1";
                                    break;
                                }
                            }
                            out = "0";
                        }
                        break;
                    case 2:         // Blastshield
                        if(oType == 4){
                            if(isAlive(me, 1)){
                                out = "11";
                                break;
                            } else if(isAlive(me, 0)){
                                out = "10";
                                break;
                            }
                        }
                        if(getField(me, HP, active) < 50 && getField(me, MOVE2, active) > 0){
                            out = "2";
                        } else if(getEffectCount(me, DEFENSE_UP, active, true) < 3 && getField(me, MOVE1, active) > 0){
                            out = "1";
                        } else {
                            out = "0";
                        }
                        break;
                }
                break;
            default:
                out = "Invalid query from controller.";             
        }
        System.out.println(out);
    }

    static boolean isAlive(String teamState, int who){
        return getField(teamState, HP, who) > 0;
    }

    static int getActive(String teamState){
        return Integer.parseInt(teamState.split("\\|")[0].split(":")[1]);
    }

    static int getField(String teamState, int field, int who){
        String[] fields = teamState.split("\\|")[who+1].split(":");
        return Integer.parseInt(fields[field]);
    }

    static int getEffectCount(String teamState, int effect, int who, boolean mine){
            String[] fields = teamState.split("\\|")[who+1].split(":");
            int count = 0;
            for(int i=mine?14:8;i<fields.length;i++){
                if(Integer.parseInt(fields[i]) == effect)
                    count++;
            }
            return count;
    }

    final static int ID =       1; 
    final static int ATTACK =   2; 
    final static int DEFENSE =  3; 
    final static int SPEED =    4; 
    final static int HP =       5; 
    final static int TYPE =     6; 
    final static int PTURNS =   7; 
    final static int MOVE0 =    8; 
    final static int MOVE1 =    9; 
    final static int MOVE2 =    10; 
    final static int HA =       11; 
    final static int HD =       12; 
    final static int HS =       13; 

    final static int POISON =           1;
    final static int CONFUSION =        2;
    final static int BURN =             3;
    final static int SLEEP =            4;
    final static int ATTACK_UP =        6;
    final static int ATTACK_DOWN =      7;
    final static int DEFENSE_UP =       8;
    final static int DEFENSE_DOWN =     9;
    final static int SPEED_DOWN =       10;
}

4

Fehler 310: Zu viele Weiterleitungen - C ++

Ein bestens ausgebildetes und organisiertes Team, um den Giftverwüstungen entgegenzuwirken

Drei Wochen lang habe ich meine Codémons kaum trainiert. Ich habe mehrere Teams gebildet. Und schließlich bin ich bereit, mich dieser Herausforderung zu stellen. Um all meinen Giftgegnern zu antworten, bildete ich ein Team mit sehr unterschiedlichen Codémons, die jeweils eine bestimmte Rolle spielten.


Gegenmittel(Bild)

Type : Normal - atk:50 def:100 spd:80 - Poison/Burn/Heal

Gegengift liebt Gift. So sehr, dass ich ihn nicht davon abhalten kann, zu Giftattacken zu eilen.


Zen(Bild)

Type : Fire - atk:100 def:80 spd:50 - Poison/Vine/Heal

Zen ist ein sehr überraschendes Codemon, das alle Effekte berücksichtigt. Er zieht es vor, seinen Feinden zuzusehen, wie sie sich gegen seine Stille anstrengen und erschöpfen.


Triforce(Bild)

Type : Psychic - atk:88 def:60 spd:82 - Fireball/Watergun/Vine

Triforce ist ein klassisches Codémon, das immer kampfbereit ist. Dieser nutzt seine psychische Kraft, um die drei Elemente zu kontrollieren und so viel Schaden wie möglich zuzufügen.


Sie können das Team hier herunterladen:

Linux:

http://dl.free.fr/iHYlmTOQ2

starten mit ./Error310TMR

Windows:

http://dl.free.fr/vCyjtqo2s

starten mit ./Error310TMR.exe

Der Code ist ein vollständiges C ++ - Projekt. Ich weiß nicht, wie ich es veröffentlichen soll.

$ wc -l src/*
    165 src/BruteForce.cpp
     26 src/BruteForce.h
    349 src/Codemon.cpp
     77 src/Codemon.h
     21 src/Logger.cpp
     35 src/Logger.h
    105 src/NoTimeToExplain.cpp
     27 src/NoTimeToExplain.h
    240 src/Recoverator.cpp
     31 src/Recoverator.h
     26 src/StrManip.cpp
     16 src/StrManip.h
    303 src/Team.cpp
     68 src/Team.h
     88 src/TooManyRedirects.cpp
     24 src/TooManyRedirects.h
     87 src/Unrecoverable.cpp
     27 src/Unrecoverable.h
     59 src/enums.cpp
    119 src/enums.h
     68 src/main.cpp
   1961 total

Aber es ist sehr effektiv:

------- Final Results -------

176     Error310TMR
131     H3C
130     LittleKid
121     Nodemon
58      InsideYourHead
47      HardenedTrio
37      BitterRivals

2

Märchen

Ein ziemlich generisches Team mitten auf der Straße. Basiert auf drei Archetypen, die versuchen, ihr Ding zu machen, und wechseln, wenn sie ihr Ding überhaupt nicht machen können.

Dieses Team wurde erstellt, bevor es so aussah, als sei Gift das neue Meta. Seit ich es erstellt habe, habe ich mein Team nicht wirklich verändert. Die meiste Zeit wurde nur damit verbracht, das Parsen zu beenden. Ich konnte das Turnier noch nicht zum Laufen bringen, um es zu testen, aber es war eine ziemlich arbeitsreiche Woche. Wenn dies nicht so funktioniert, wie es bei meinen Testdaten scheint, werde ich es nach der Arbeit noch etwas aufpeppen.

#!/bin/perl
use 5.20.0;
use strict;

use constant MINE => 0;
use constant THEIRS => 1;

$_ = $ARGV[0];

if(/^T/){
    say 'FairyTale|Fairy:1:89:90:51:3:4:13|Dragon:2:100:50:80:6:1:8|Assassin:0:70:60:100:0:1:10';

} elsif(/^C#(.*)/){
    my $state = readBattleState($1);
    if($state->[MINE]->{$state->[MINE]->{slot}}{hp}){
        say $state->[MINE]->{slot};
    } elsif($state->[MINE]->{($state->[MINE]->{slot}+1)%3}{hp}){
        say (($state->[MINE]->{slot}+1)%3);
    } else {
        say (($state->[MINE]->{slot}+2)%3);
    }

} elsif(/^A#(.*)/){
    my $state = readBattleState($1);
    my @actives = (
        $state->[MINE]->{$state->[MINE]->{slot}},
        $state->[THEIRS]->{$state->[THEIRS]->{slot}}
    );
    if($state->[MINE]->{slot} == 0){
        if(!exists($actives[THEIRS]{effects}{4}) && $actives[MINE]{pp}->[1]){
            say 1;
        } elsif(!exists($actives[THEIRS]{effects}{1}) && $actives[MINE]{pp}->[2]) {
            say 2;
        } elsif(!$actives[THEIRS]{type}) {
            if($state->[MINE]->{($state->[MINE]->{slot}+1)%3}{hp} > 0){
                say (($state->[MINE]->{slot}+1)%3);
            } elsif($state->[MINE]->{($state->[MINE]->{slot}+2)%3}{hp} > 0) {
                say (($state->[MINE]->{slot}+2)%3);
            } else {
                say 0;
            }
        } else {
            say 0;
        }
    } elsif($state->[MINE]->{slot} == 1){
        if(!exists($actives[MINE]{effects}{6}) && $actives[MINE]{pp}->[2]){
            say 2;
        } elsif ($actives[MINE]{hp} > 10 && $actives[MINE]{hp} < 50 && $actives[MINE]{pp}->[1]){
            say 1;
        } else {
            say 0;
        }
    } elsif($state->[MINE]->{slot} == 2){
        if(!exists($actives[MINE]{effects}{6}) && $actives[MINE]{pp}->[2]){
            say 2;
        } elsif ($actives[MINE]{hp} > 10 && $actives[MINE]{hp} < 50 && $actives[MINE]{pp}->[1]){
            say 1;
        } elsif($actives[THEIRS]{type} == 1) {
            if($state->[MINE]->{($state->[MINE]->{slot}+1)%3}{hp} > 0){
                say (($state->[MINE]->{slot}+1)%3);
            } elsif($state->[MINE]->{($state->[MINE]->{slot}+2)%3}{hp} > 0) {
                say (($state->[MINE]->{slot}+2)%3);
            } else {
                say 0;
            }
        } else {
            say 0;
        }
    }

} elsif(/^B#(.*)/){
    my $state = readTeam($1, 1);
    say '1:0:2';
}

sub readBattleState {
    local $_ = $_[0];
    if(/^(.*?)#(.*?)$/){
        my @teams;
        $teams[0] = readTeam($1, 1);
        $teams[1] = readTeam($2, 0);
        return \@teams;
    }
}

sub readTeam {
    my $isMine = $_[1];
    local $_ = $_[0];
    if(/.*?:(?<slot>.*?)\|(.*?)\|(.*?)\|(.*?)$/){
        my %team;
        $team{slot} = $1;
        $team{0} = $isMine ? readYourMember($2) : readTheirMember($2);
        $team{1} = $isMine ? readYourMember($3) : readTheirMember($3);
        $team{2} = $isMine ? readYourMember($4) : readTheirMember($4);
        return \%team;
    }
    return 0;
}

sub readYourMember {
    local $_ = $_[0];
    if(/(?<name>.*?):(?<id>.*?):(?<atk>.*?):(?<def>.*?):(?<spd>.*?):(?<hp>.*?):(?<type>.*?):(?<poison>.*?):(?<move0>.*?):(?<move1>.*?):(?<move2>.*?):(?<batk>.*?):(?<bdef>.*?):(?<bspd>.*?)(?<effects>(?::.*)|$)/){
        my %effects = map { $_ => 1 } readEffects($+{effects});
        my %member = (
            name   => $+{name},
            id     => $+{id},
            hp     => $+{hp},
            atk    => $+{atk}+$+{batk},
            def    => $+{def}+$+{bdef},
            spd    => $+{spd}+$+{bspd},
            type   => $+{type},
            pp     => [$+{move0}, $+{move1}, $+{move2}],
            poistrn=> $+{poison},
            effects=> \%effects
        );
        return \%member;
    }
}

sub readTheirMember {
    local $_ = $_[0];
    if(/(?<name>.*?):(?<id>.*?):(?<atk>.*?):(?<def>.*?):(?<spd>.*?):(?<hp>.*?):(?<type>.*?):(?<poison>.*?)(?<effects>(?::.*)|$)/){
        my %effects = map { $_ => 1 } readEffects($+{effects});
        my %member = (
            name   => $+{name},
            id     => $+{id},
            hp     => $+{hp},
            atk    => $+{atk},
            def    => $+{def},
            spd    => $+{spd},
            type   => $+{type},
            poistrn=> $+{poison},
            effects=> \%effects
        );
        return \%member;
    }
    return 0;
}

sub readEffects {
    local $_ = $_[0];
    my @retval = /:([^:]*)/g;
    if(!@retval){
        @retval = (0);
    }
    return @retval;
}

Laufen Sie mit

perl fairytale.pl

Dieser Bot wird rausgeschmissen, weil er versucht, aktive Mitglieder auszuwählen, nachdem er zum ersten Mal gestorben ist. Es kommt nie über den ersten Kampf hinaus, den ich sehen kann.
Geobits

"Ja wirklich?" Ich dachte, ich hätte diesen Fehler schon einmal
behoben

Vergiss nicht, dass beim Ausschalten eines Codemons seine Heilpunkte auf 0 oder weniger sinken . if($state->[MINE]->{$state->[MINE]->{slot}}{hp})Ohne funktioniert die Anweisung also nicht richtig >0.
GholGoth21,

Ah ja, das würde es tun.
MezzoEmrys

0

Dummy-Team - Java

(nicht konkurrierendes CW)

Dies ist ein Dummy-Team zum Üben. Es sind alles normale Typen, die in jeder Runde zufällig zwischen ihren Zügen (Schlagen, Heilen, Langsam) wählen. Viel Spass damit.

public class DummyTeam {

    public static void main(String[] args) {
        if(args.length < 1){
            System.out.println("You need to run this from the tournament. Try to keep up.");
            System.exit(0);
        }

        String[] sections = args[0].split("#");
        String out = "";
        switch(sections[0]){
            // team data
            //      sends back all Normal types with minimum stats and Normal moves (randomized name suffixes to distinguish in tests)
            case "T":
                out = "DummyTeam";
                for(int i=0;i<3;i++)
                    out += "|Dummy"+((char)(Math.random()*26)+65) + i + ":0:50:50:50:0:1:2";
                break;
            // bonus points
            //      shoves them all in defense every time
            case "B":
                out = "1:1:1";
                break;
            // choose active
            //      picks last active if alive, otherwise loops to find first living member
            case "C":
                String[] team = sections[1].split("\\|");
                int current = Integer.parseInt(team[0].split(":")[1]);
                if(Integer.parseInt(team[current+1].split(":")[5]) > 0){
                    out = current + "";
                } else {
                    for(int i=1;i<team.length;i++){
                        if(Integer.parseInt(team[i].split(":")[5]) > 0){
                            out = (i - 1) + "";
                        }
                    }
                }               
                break;
            // choose action
            //      chooses a random move. does not check if it ran out of uses, so wastes turns quite often
            case "A":
                out = ((int)(Math.random()*3)) + "";
                break;
            default:
                out = "Invalid query from controller.";             
        }
        System.out.println(out);
    }


}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.