König des Hügels - Spacewar!

64

Wenn Sie jemals Spacewar gespielt haben! Weißt du, es war ein lustiges Spiel. Wenn Sie dies nicht getan haben, wissen Sie Folgendes: Es war (und ist) eines der allerersten und wichtigsten Computerspiele. Und es macht trotzdem Spaß! Der Klon, auf dem ich aufgewachsen bin, ist dieser , der anscheinend und leider nur Windows ist. Also habe ich es neu erstellt!

Das KotH wird hier gehostet: PPCG - Spacewar! König des Hügels . Ich ermutige Sie, als Mensch gegen mindestens einen anderen Bot zu spielen, um ein Gefühl dafür zu bekommen, wie das Spiel funktioniert.

Das Spiel

  • Ein Frame entspricht 30 Millisekunden (also ungefähr 33 Frames pro Sekunde).
  • Das Feld ist 800 Pixel breit und 600 Pixel hoch.
  • Das Feld ist toroidal, was bedeutet, dass Raumschiffe und Raketen, die sich außerhalb des Feldes bewegen, auf der gegenüberliegenden Seite wieder erscheinen.
  • Es gibt zwei Raumschiffe, rot und blau.
    • Rot wird bei x = 50 und zufälligem y zwischen 50 (Feldhöhe - 50) Pixeln positioniert.
    • Blau wird bei x = (Feldbreite - 50) und zufälligem y zwischen 50 (Feldhöhe - 50) Pixeln positioniert.
    • Beide Flächen x = (Feldbreite) / 2.
  • Die verfügbaren Steuerelemente sind:
    • Drehen Sie sich nach links - 5 Grad pro Bild gegen den Uhrzeigersinn.
    • Drehen Sie nach rechts - 5 Grad pro Bild im Uhrzeigersinn.
    • Feuer-Rakete - bewegt sich mit zusätzlichen 10 Pixeln pro Bild zusätzlich zur Geschwindigkeit des Schiffes in die Richtung, in die das Schiff zeigt.
    • Feuerwehrauto - beschleunigt das Raumschiff mit 0,30 Pixel pro Frame in die Richtung, in die das Raumschiff zeigt.
    • In Hyperspace Jump teleportierst du dich zu zufälligen Koordinaten im Feld, mit einer Wahrscheinlichkeit von 25% zu explodieren. Diese zufälligen Koordinaten können auf der Sonne liegen.
  • Die Höchstgeschwindigkeit für Schiffe beträgt 15 Pixel pro Bild bei Motorleistung und 40 Pixel pro Bild bei Schwerkraftverstärkung.
    • Wenn der Motor schneller als 15 Pixel pro Bild fährt, ändert er möglicherweise nur die Richtung oder verlangsamt sich.
  • In Bezug auf Raketen:
    • Raketen bewegen sich in einer geraden Linie.
    • Raketen dürfen mit einer maximalen Schussrate von 1 pro 0,1 Sekunden abgefeuert werden.
    • Raketen haben eine Lebensdauer von 2,25 Sekunden.
    • Schiffe haben jeweils maximal 20 Raketen.
    • Raketen sind innerlich Punktpartikel.
  • In der Mitte befindet sich eine Sonne, die für Ihr Schiff äußerst gefährlich ist. Der geringste Kontakt ist tödlich. Diese Sonne zerstört auch Raketen.
  • Die Sonne hat Schwerkraft. Die resultierende Beschleunigung beträgt 5000 / (Abstand ^ 2) Pixel / Frame ^ 2, wobei der Abstand in Pixel angegeben ist. Raumschiffe und Raketen sind betroffen.
  • Beide Schiffe haben drei Angriffszonen: die Nase, den linken und den rechten Flügel.
    • Ein Schlag auf die Nase ist der sofortige Tod.
    • Ein Treffer auf einem der beiden Flügel reduziert die Drehzahl und die Motorbeschleunigung des Raumschiffs um die Hälfte.
    • Wenn beide Flügel zerstört sind, kann das Raumschiff nicht manövriert werden und kann nur Raketen abfeuern.
  • Schiffe können miteinander kollidieren.
    • Ein Nase-Nase-Aufprall ist für beide Schiffe tödlich.
    • Ein Nasenflügelschlag zerstört den Flügel.
    • Ein Flügelschlag zerstört beide Flügel.
  • Tote Schiffe sind fest und gefroren, bis sie 1 Sekunde später explodieren.
  • Nachdem mindestens ein Schiff gestorben ist, wird das Feld 3 Sekunden später zurückgesetzt. Bis dahin sind die Sonne und alle verbleibenden Raketen immer noch gefährlich.

Das ursprüngliche Spiel hat auch tödliche und unzerstörbare Asteroiden, aber ich werde diese nicht einschließen.

Die Regeln

  • Ihr Bot muss in JavaScript geschrieben sein.
  • Ihr Bot sollte seine Entscheidung auf ungefähr 10 Millisekunden beschränken. Wenn ich aufgrund Ihres Bots eine beständige Verzögerung feststelle , werde ich ihn disqualifizieren und Sie informieren, damit Sie ihn beheben können.
  • Bots haben Zugriff auf Folgendes:
    • Feldbreite und Feldhöhe
    • Sonnenstand und Radius
    • Position, Rotation, Geschwindigkeit, Form, Raketenbestand und Status im Hyperraum beider Schiffe
    • Die Position und Geschwindigkeit aller Raketen
  • Wenn Sie dazu aufgefordert werden, sollte Ihr Bot eine Liste von Zeichenfolgen zurückgeben.
    • : Diese Strings sollten Sie eine der folgenden sein turn left, turn right, fire engine, fire missile, hyperspace. Alle anderen Zeichenfolgen werden ignoriert.
    • Wenn Duplikate vorhanden sind, wird nur das erste vermerkt.
    • hyperspace hat Vorrang vor allen anderen.
    • turn leftund turn rightzur gleichen Zeit wird keine Wirkung haben.
    • fire engine hat keine Auswirkung, wenn das Schiff nur die Nase hat oder tot ist.
    • fire missile hat keine Auswirkung, wenn eine Rakete zu früh abgefeuert wurde.
  • In Abweichung vom Üblichen kann Ihr Bot das Verhalten anderer Bots ausnutzen. Ich möchte ein Metaspiel fördern.
    • Bots können nicht andere Bots emulieren. (Dh kein Gedankenlesen.)
    • Bots dürfen keine Variablen setzen, die vom Spiel- und Physikcode verwendet werden. (Dh kein Schummeln.)

Details zur Bot-Implementierung

Ich werde Ihren Bot in einer eigenen JavaScript-Datei speichern, die automatisch mit dem Dateinamen enthalten ist bot_<name>.js. Fügen Sie also keine Leerzeichen oder Zeichen ein, die dies oder die Benennung einer Funktion in JavaScript beeinträchtigen könnten. Das liegt daran, dass Sie die folgenden Funktionen definieren sollten: <name>_setup(team)und <name>_getActions(gameInfo, botVars). Weiter unten auf der Seite gibt es Textbereiche für den Userbot , die Sie bearbeiten können, um Ihren Code zu testen.

<name>_setup(team)

Mit dieser Funktion können Sie alle Variablen definieren, die Sie beibehalten möchten. teamwird entweder "red"oder sein "blue". Diese Funktion muss ein Objekt zurückgeben. Definieren Sie Variablen wie folgt:

var vars = {};
vars['example'] = "example";
return vars;

Dieses varsObjekt wird an die andere Funktion übergeben:

<name>_getActions(gameInfo, botVars)

botVarsist das Objekt, das von zurückgegeben wird <name>_setup(team). gameInfoist ein Objekt mit folgenden Variablen:

redScore
blueScore
timeLeft

fieldWidth
fieldHeight

sun_x
sun_y
sun_r //sun's radius

gravityStrength //acceleration in pixels/frame^2 at 1 pixel away from the sun's center
engineThrust    //acceleration in pixels/frame^2

speedLimit //maximum speed under engine power
maxSpeed   //maximum speed from gravity boosts

red_x
red_y
red_rot          //rotation in degrees
red_xv           //x velocity
red_yv           //y velocity
red_shape        //one of "full ship", "left wing", "right wing", "nose only"
red_missileStock //the number of missiles red has left
red_inHyperspace //true if red is in hyperspace
red_exploded     //until red explodes, it is still solid and hazardous
red_alive
// likewise for blue //

numMissiles
missiles //this is a list of objects, each with the following variables
  x
  y
  xv
  yv

Ihr Bot hat vollen Zugriff auf diese. Ich bin mir ziemlich sicher, dass Sie darauf schreiben und die ursprünglichen Variablen nicht beeinflussen können, aber tun Sie es trotzdem nicht. Anmerkung zur Drehung: Schiffe zeigen in die + y-Richtung nach unten, sodass alles, was Sie mit dem Schiff ausrichten möchten, um 90 Grad versetzt sein muss. Die positive Drehung erfolgt ebenfalls im Uhrzeigersinn.

Diese Funktion muss eine Liste von Zeichenfolgen zurückgeben, die die Aktionen Ihres Bots darstellen. Zum Beispiel ["turn right","thrust"]. Weitere Details dazu finden Sie im Abschnitt Regeln .

Zusätzliche Details

Sie können auch Folgendes verwenden:

LineIntersection(L1, L2)

L1 und L2 sind Zwei-Element-Arrays von Zwei-Element-Arrays. Das ist L1 := [[x1,y1],[x2,y2]]und L2 := [[u1,v1],[u2,v2]]. Diese Funktion berechnet den Schnittpunkt von zwei Linien und gibt diese: [[x,y], [a,b]]. [x,y]sind die Koordinaten des Schnittpunkts und [a,b]sind ein Paar Verhältnisse, die ausdrücken, wie weit entlang jeder Linie der Schnittpunkt ist. Wie in, a = 0.25würde bedeuten, dass der Schnittpunkt ein Viertel des Weges von [x1,y1]nach ist [x2,y2], und ebenso für b. Wenn es keine Schnittmenge gibt, wird ein leeres Array zurückgegeben.

window["shipShapes"]

var shipShapes = {
    'full ship': [[-8,16],[0,-8],[8,16]],
    'left wing': [[-8,16],[0,-8],[4,4],[0,8],[0,16]],
    'right wing':[[-4,4],[0,-8],[8,16],[0,16],[0,8]],
    'nose only': [[-4,4],[0,-8],[4,4],[0,8]]
};

Dies sind die Koordinaten der Schiffspolygone. Um das Abrufen der aktuellen Koordinaten zu vereinfachen, können Sie auch ...

getShipCoords(<color>)

getShipCoords("red")Liefert die aktuellen Koordinaten der Eckpunkte von Rotes Schiff und ebenso für getShipCoords("blue")und Blau. Diese Koordinaten sind in einer Liste wie folgt: [[x1,y1],[x2,y2],[x3,y3],...]. Polygone sind implizit geschlossen, sodass zwischen dem ersten und dem letzten Koordinatenpaar eine Linie besteht.

Sie dürfen nicht auf andere Variablen oder Funktionen zugreifen oder diese ändern, die von dem Spiel / der Website verwendet werden. Und nenne deine Funktionen definitiv nicht gleich. Ich glaube nicht, dass dies ein Problem sein wird, aber wenn Ihr Bot den Spielcode bricht, ist dies eine Möglichkeit. Es werden keine Ausnahmen protokolliert oder abgefangen.

Gewinnen

  • Jede Paarung von Bots muss mindestens 10 Mal in beide Richtungen gespielt werden. (Also mindestens 20 Spiele insgesamt.)
  • Richten Sie die höchste Gewinn / Verlust - Verhältnisse haben insgesamt . Wenn Ihr Bot gegen einen anderen sehr gut abschneidet, aber gegen die anderen drei verliert, ist das nicht so gut wie gegen zwei zu gewinnen und gegen zwei zu verlieren (als allgemeine Faustregel).
  • Für jeden Bot werden die Verhältnisse (Gewinne + 1) / (Verluste + 1) berechnet, dann werden der Mittelwert und die Standardabweichung dieser Verhältnisse berechnet. Ein höherer Mittelwert hat Priorität, und falls die Mittelwerte innerhalb einer Einheit voneinander liegen, hat die niedrigere Varianz Priorität.
  • Die Wertung beginnt entweder in einer Woche ab heute oder nach drei Tagen ohne neue Einreichungen. Dies ist so, dass ich keine Paarung von Bots wiederholen muss.

Vor allem viel Spaß!


Bestenliste (08.01.2016, 05:15 Uhr):

#   Name                       Mean      StdDev
1.  Helios                     13.625    6.852
2.  EdgeCase                    8.335    8.155
3.  OpponentDodger              8.415    8.186
4.  OrbitBot                    5.110    6.294
5.  SunAvoider                  5.276    6.772
6.  DangitBobby                 3.320    4.423
7.  SprayAndPray                3.118    4.642
8.  Engineer                    3.903    6.315
9.  RighthandedSpasms           1.805    2.477
10. AttackAndComeBack           2.521    2.921
11. PanicAttack                 2.622    3.102
12. FullSpeedAhead              2.058    3.295
13. UhhIDKWhatToCallThisBot     2.555    3.406
14. MissilesPlusScore           0.159    0.228
15. Hyper                       0.236    0.332
16. RandUmmm                    0.988    1.329
17. Kamikaze                    0.781    1.793

Hinweis: Dies kann sich ändern, wenn ich mehr Spiele spiele. Außerdem stört mich die Reihenfolge der Ränge 9 bis 13, so dass ich die Bewertungsmethode anpassen kann, um der Intuition besser zu entsprechen, wie sie eingestuft werden sollten.

(Mittelwerte und Standardabweichungen wurden auf drei Dezimalstellen gerundet. Außerdem Hypersollte das HYPERaber die Hervorhebung durcheinander bringen.: P)

El'endia Starman
quelle
Irgendwelche Punkte? ....
ev3commander
Werden gefangene Ausnahmen protokolliert?
TheNumberOne
1
Sie sollten angeben, dass beim Aufrufen LineIntersectionvon nicht überlappenden Segmenten ein leeres Array zurückgegeben wird.
LegionMammal978
1
Ich glaube, ich habe es geschafft!
ev3commander
3
@ CrazyPython: Ich würde die ersten beiden bestreiten, wenn ich bedenke, dass ich im Grunde ein Spiel kopiert habe, aber das dritte ist genau das, was ich wollte. Vielen Dank! : D
El'endia Starman

Antworten:

12

Helios

Dieser Bot ist das Zentrum des Universums, oder zumindest denkt er, dass er es ist. Zuerst korrigiert er einen schwerwiegenden Fehler und stellt sich in die Mitte des Koordinatensystems. Dann dreht er alles um sich herum.

Er mag die andere (falsche) Sonne nicht, deshalb versucht er, sich von ihr fernzuhalten. Er mag auch keine anderen Bots, deshalb schießt er auf sie, wenn er sich in einer guten Schussposition befindet.

function Helios_setup(team) {
    var botVars = {};
    botVars.myPrefix = team + "_";
    botVars.enemyPrefix = team == "red" ? "blue_" : "red_";
    return botVars;
}

function Helios_getActions(gameInfo, botVars) {
    var actions = [];
    var halfPi = Math.PI / 2;
    var engageAngle = Math.PI / 8;

    var field = {};
    field.width = gameInfo.fieldWidth;
    field.height = gameInfo.fieldHeight;
    field.halfWidth = field.width / 2;
    field.halfHeight = field.height / 2;
    field.posOffsetX = field.width * 3 / 2 - gameInfo[botVars.myPrefix + "x"];
    field.posOffsetY = field.height * 3 / 2 - gameInfo[botVars.myPrefix + "y"];
    field.posAngle = (450 - gameInfo[botVars.myPrefix + "rot"]) % 360 * Math.PI / 180;
    field.posSin = Math.sin(-field.posAngle);
    field.posCos = Math.cos(-field.posAngle);
    field.movOffsetXV = -gameInfo[botVars.myPrefix + "xv"];
    field.movOffsetYV = gameInfo[botVars.myPrefix + "yv"];
    field.movAngle = Math.atan2(-field.movOffsetYV, -field.movOffsetXV);
    field.movSin = Math.sin(-field.movAngle);
    field.movCos = Math.cos(-field.movAngle);

    function zeroIfUndefined(v) {
        return v === undefined ? 0 : v;
    }

    function sqr(x) {
        return x * x
    }

    function getEntity(source, prefix) {
        var tmpX = (field.posOffsetX + zeroIfUndefined(source[prefix + "x"])) % field.width - field.halfWidth;
        var tmpY = field.halfHeight - (field.posOffsetY + zeroIfUndefined(source[prefix + "y"])) % field.height;
        var tmpXV = zeroIfUndefined(source[prefix + "xv"]);
        var tmpYV = -zeroIfUndefined(source[prefix + "yv"]);
        var e = {};
        e.posX = tmpX * field.posCos - tmpY * field.posSin;
        e.posY = tmpX * field.posSin + tmpY * field.posCos;
        e.posR = Math.sqrt(sqr(e.posX) + sqr(e.posY));
        e.posPhi = Math.atan2(e.posY, e.posX);
        e.posXV = tmpXV * field.posCos - tmpYV * field.posSin;
        e.posYV = tmpXV * field.posSin + tmpYV * field.posCos;
        e.posV = Math.sqrt(sqr(e.posXV) + sqr(e.posYV));
        e.movX = tmpX * field.movCos - tmpY * field.movSin;
        e.movY = tmpX * field.movSin + tmpY * field.movCos;
        e.movR = Math.sqrt(sqr(e.movX) + sqr(e.movY));
        e.movPhi = Math.atan2(e.movY, e.movX);
        e.movXV = (tmpXV + field.movOffsetXV) * field.movCos - (tmpYV + field.movOffsetYV) * field.movSin;
        e.movYV = (tmpXV + field.movOffsetXV) * field.movSin + (tmpYV + field.movOffsetYV) * field.movCos;
        return e;
    }

    function getShip(prefix) {
        var ship = getEntity(gameInfo, prefix);
        ship.missileStock = gameInfo[prefix + "missileStock"];
        ship.inHyperspace = gameInfo[prefix + "inHyperspace"];
        ship.exploded = gameInfo[prefix + "exploded"];
        ship.alive = gameInfo[prefix + "alive"];
        return ship;
    }

    var myShip = getShip(botVars.myPrefix);
    myShip.movAngle = (field.posAngle - field.movAngle + 3 * Math.PI) % (2 * Math.PI) - Math.PI;
    var enemyShip = getShip(botVars.enemyPrefix);
    var sun = getEntity(gameInfo, "sun_");

    enemyShip.intersectionLine = [[enemyShip.movX - enemyShip.movXV * 30, enemyShip.movY - enemyShip.movYV * 30],
            [enemyShip.movX + enemyShip.movXV * 30, enemyShip.movY + enemyShip.movYV * 30]];

    var intersection = LineIntersection([[0, 0], [Math.cos(myShip.movAngle) * 10 * 30, Math.sin(myShip.movAngle) * 10 * 30]],
            enemyShip.intersectionLine);
    if (intersection.length == 2) {
        myShip.intersection = Math.abs(intersection[1][0] / 2 + 0.5 - intersection[1][1]);
    }
    intersection = LineIntersection([[0, 0], [Math.cos(myShip.movAngle - 0.001) * 10 * 30, Math.sin(myShip.movAngle - 0.001) * 10 * 30]],
            enemyShip.intersectionLine);
    if (intersection.length == 2) {
        myShip.intersectionLeft = Math.abs(intersection[1][0] / 2 + 0.5 - intersection[1][1]);
    }
    intersection = LineIntersection([[0, 0], [Math.cos(myShip.movAngle + 0.001) * 10 * 30, Math.sin(myShip.movAngle + 0.001) * 10 * 30]],
            enemyShip.intersectionLine);
    if (intersection.length == 2) {
        myShip.intersectionRight = Math.abs(intersection[1][0] / 2 + 0.5 - intersection[1][1]);
    }

    function danger() {
        var tmp1 = sqr(sun.movXV) + sqr(sun.movYV);
        var tmp2 = tmp1 == 0 ? 0 : Math.max(0, Math.min(1, ((-sun.movX) * sun.movXV + (-sun.movY) * sun.movYV) / tmp1));
        var dis = Math.sqrt(sqr(sun.movX + tmp2 * sun.movXV) + sqr(sun.movY + tmp2 * sun.movYV));
        if (dis < 30) {
            return true;
        }
        var shipLine1 = [[-16, 8], [-16, -8]];
        var shipLine2 = [[-16, 8], [8, 0]];
        var shipLine3 = [[-16, -8], [8, 0]];
        if (gameInfo.missiles !== undefined) {
            for (var i = 0; i < gameInfo.missiles.length; i++) {
                var missile = getEntity(gameInfo.missiles[i], "");
                var missileLine = [[missile.movX + missile.movXV * 0.5, missile.movY + missile.movYV * 0.5],
                        [missile.movX + missile.movXV * 3, missile.movY + missile.movYV * 3]];
                if (LineIntersection(shipLine1, missileLine).length == 2 ||
                        LineIntersection(shipLine2, missileLine).length == 2 ||
                        LineIntersection(shipLine3, missileLine).length == 2) {
                  return true;
                }
            }
        }
        return false;
    }

    function fire() {
        return enemyShip.alive && !enemyShip.inHyperspace && myShip.intersection !== undefined &&
            myShip.intersection < 0.1 + myShip.missileStock / 200;
    }

    function evadeSun() {
        if ((sun.movPhi >= 0 && myShip.movAngle < 0) || (sun.movPhi <= 0 && myShip.movAngle > 0)) {
            actions.push("fire engine");
        }
        if (sun.movPhi > 0) {
            if (Math.abs(myShip.movAngle) < halfPi) {
                actions.push("turn right");
            } else {
                actions.push("turn left");
            }
        } else {
            if (Math.abs(myShip.movAngle) < halfPi) {
                actions.push("turn left");
            } else {
                actions.push("turn right");
            }
        }
    }

    function aim() {
        if (myShip.intersection !== undefined && myShip.intersectionLeft !== undefined && myShip.intersectionLeft < myShip.intersection) {
            actions.push("turn left");
        } else if (myShip.intersection !== undefined && myShip.intersectionRight !== undefined && myShip.intersectionRight < myShip.intersection) {
            actions.push("turn right");
        } else {
            if (enemyShip.posPhi > 0) {
                actions.push("turn left");
            } else {
                actions.push("turn right");
            }
        }
        if (myShip.posV < 2 || (enemyShip.alive && (enemyShip.movXV >= 0 || myShip.missileStock == 0))) {
            actions.push("fire engine");
        }
    }

    function brake() {
        if (myShip.movAngle > 0) {
            actions.push("turn left");
        } else {
            actions.push("turn right");
        }
        if (Math.abs(myShip.movAngle) > Math.PI * 3 / 4) {
            actions.push("fire engine");
        }
    }

    function engage() {
        if (enemyShip.missileStock > 0) {
            if ((enemyShip.posPhi > 0 && enemyShip.posPhi < engageAngle) || enemyShip.posPhi < -engageAngle) {
                actions.push("turn right");
            } else {
                actions.push("turn left");
            }
        } else {
            if (enemyShip.posPhi > 0) {
                actions.push("turn left");
            } else {
                actions.push("turn right");
            }
        }
        actions.push("fire engine");
    }

    if (myShip.alive && !myShip.inHyperspace) {
        if (danger()) {
            actions.push("hyperspace");
        }
        if (fire()) {
            actions.push("fire missile");
        }
        if (enemyShip.exploded || enemyShip.inHyperspace || sun.movR < 150 || (sun.movR < 300 && Math.abs(sun.movPhi) < Math.PI)) {
            evadeSun();
        } else if (enemyShip.posR < 300 || myShip.intersection !== undefined) {
            aim();
        } else if (myShip.posV > 10) {
            brake();
        } else {
            engage();
        }
    }

    return actions;
}
Sleafar
quelle
1
Ich denke, dies ist einer meiner Lieblingsbots. Es ist überraschend gut!
El'endia Starman
@ El'endiaStarman Ich habe ein paar Updates für den Bot gemacht.
Sleafar
Dein Update ist jetzt live!
El'endia Starman
Dies funktioniert sehr gut gegen OrbitBot :)
TheNumberOne
1
@ Soaku Ich denke, der Hauptunterschied zwischen diesem Bot und den meisten anderen ist, dass dieser Bot vor dem Schießen auf seinen Gegner zielt.
Sleafar
9

SunAvoider

Dieser versucht nur, sich von der Sonne fernzuhalten. Es macht sich so gut ... bis es einen oder beide Flügel zerstört hat, ist es normalerweise nur eine Frage der Zeit, bis es einfällt.

function SunAvoider_setup(team) {
    var botVars = {};

    botVars["color"] = team;

    return botVars;
}

function SunAvoider_getActions(gameInfo, botVars) {
    var actions = [];

    if (gameInfo[botVars["color"]+"_alive"]) {
        var shipx = gameInfo[botVars["color"]+"_x"];
        var shipy = gameInfo[botVars["color"]+"_y"];
        var sunx = gameInfo["sun_x"];
        var suny = gameInfo["sun_y"];
        var dx = shipx - sunx;
        var dy = shipy - suny;
        var dis = Math.sqrt(dx*dx+dy*dy);
        var fireEngineChance = (dis-100)/(gameInfo["fieldHeight"]/2);

        if (Math.random() > fireEngineChance){ actions.push("fire engine") }

        var ang1 = gameInfo[botVars["color"]+"_rot"]+90;
        var ang2 = Math.degrees( Math.atan2(dy, dx) );
        var angDiff = ang2 - ang1;
        if (angDiff < -180) { //http://stackoverflow.com/a/7869457/1473772
            angDiff += 360;
        } else if (angDiff > 180) {
            angDiff -= 360;
        }

        if (angDiff >= 0) {
            actions.push("turn left");
        } else if (angDiff < 0) {
            actions.push("turn right");
        }
    }

    return actions;
}
El'endia Starman
quelle
9

EdgeCase

Fliegt mit voller Geschwindigkeit von der Sonne weg zum Rand der Karte! Wenn es auf die Sonne gerichtet ist, beginnt es zu schießen, während es sich abwendet, um zum Rand zurückzukehren. Es tritt auch in den Hyperraum ein, wenn es im Begriff ist, die Sonne zu treffen.

function EdgeCase_setup(team) {
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}

function EdgeCase_getActions(gameInfo, botVars) {
  var actions = [];

  // Get our ship's position
  var rotation, x, y, opponentAlive;
  if(botVars.color == "red") {
    rotation = gameInfo.red_rot;
    x = gameInfo.red_x;
    y = gameInfo.red_y;
    opponentAlive = gameInfo.blue_alive;
  }
  else if(botVars.color == "blue") {
    rotation = gameInfo.blue_rot;
    x = gameInfo.blue_x;
    y = gameInfo.blue_y;
    opponentAlive = gameInfo.red_alive;
  }

  // Calculate our rotation compared to the sun in degrees
  var sunX = gameInfo.sun_x,
      sunY = gameInfo.sun_y,
      angle = Math.atan2(sunY - y, sunX - x) * 180 / Math.PI,
      rotationToSun = (rotation - angle + 360) % 360;

  // Check if we need to hyperspace to avoid the sun
  var rX = x - sunX,
      rY = y - sunY,
      distanceFromSun = Math.sqrt(rX * rX + rY * rY) - gameInfo.sun_r;
  if(distanceFromSun < 30) actions.push("hyperspace");
  else {

    // Turn away from the sun
    if(rotationToSun > 90 && rotationToSun < 270) {
      actions.push("turn right");
    }
    else actions.push("turn left");

    // Fire engines if we're pointing away from the sun
    if(rotationToSun > 180) {
      actions.push("fire engine");
    }

    // If we shoot while our opponent's dead we can only kill ourself
    else if(opponentAlive) actions.push("fire missile");
  }

  return actions;
}
user81655
quelle
Dieser Bot ist jetzt live! Auch dieser war überraschend leicht zu überleben. Hat wahrscheinlich damit zu tun, dass es nicht überall wie bei einigen anderen Raketen spammt. : P
El'endia Starman
7

OrbitBot

Derzeit gibt es keine Ausrichtungs- oder Kollisionsvermeidung . Es versucht, die Sonne zu umkreisen.

Bearbeiten: Geht jetzt in den Hyperraum, wenn ein Aufprall unmittelbar bevorsteht.

function OrbitBot_setup(team) {
  var botVars = {};

  botVars.color = team;
  return botVars;
}


function OrbitBot_getActions(gameInfo, botVars) {
  var actions = [];

  function getVar(name) {
    return gameInfo[botVars.color + "_" + name];
  }

  function getEnemyVar(name) {
    var eColor;
    if (botVars.color == 'blue') {
        eColor = 'red';
    } else {
        eColor = 'blue';
    }
    return gameInfo[eColor + "_" + name];
  }

  function distance(x1, y1, x2, y2) {
    return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
  }

  function toroidDistance(x1, y1, x2, y2) {
    dx = Math.abs(x1 - x2);
        while (dx > gameInfo.fieldWidth) {
        dx -= gameInfo.fieldWidth;
    }
    dx = Math.min(dx, gameInfo.fieldWidth - dx);
    dy = Math.abs(y1 - y2);
        while (dx > gameInfo.fieldHeight) {
        dx -= gameInfo.fieldHeight;
    }
    dy = Math.min(dy, gameInfo.fieldHeight - dy);
    return Math.sqrt(dx*dx+dy*dy);
  }

  function angleDistance(theta1, theta2) {
    var d = theta1 - theta2;
    while (d < 0 || d > Math.PI) {
      if (d < 0) {
        d += Math.PI * 2;
      }
      if (d > Math.PI * 2) {
        d -= Math.PI * 2;
      } else if (d > Math.PI) {
        d = Math.PI * 2 - d;
      }
    }
    return d;
  }

  function toRad(degrees) {
    return degrees / 180 * Math.PI;
  }

  function cap(x, y, limit) {
    var r = x*x+y*y;
    if (r < limit * limit) {
        r = Math.sqrt(r);
        x = x * r / limit;
      y = y * r / limit;
    }
    return [x,y];
  }

  var shape = getVar('shape');

  if (shape != 'nose only') {
    var broken = shape != 'full ship';
    var sunX = gameInfo.sun_x,
      sunY = gameInfo.sun_y,
      sunG = gameInfo.gravityStrength;

    function desirability(x, y, vx, vy) {     //Borrowed from a useless bot.
      var lowest = distance(x, y, sunX, sunY) - 5;
      var missiles = gameInfo.missiles;
      for (var i = 0; i < missiles.length; i++) {
        var mx = missiles[i].x + missiles[i].xv / 2;
        var my = missiles[i].y + missiles[i].yv / 2;
        lowest = Math.min(lowest, toroidDistance(x, y, mx, my) - distance(0, 0, missiles[i].xv, missiles[i].yv));
      }
      return lowest - 16;
    }

    var x = getVar("x"),
      y = getVar("y"),
      vx = getVar("xv"),
      vy = getVar("yv");

    function desirabilityByAcceleration(ax, ay) {//Borrowed from a useless bot.
        var x1 = x,
            y1 = y,
          vx1 = vx,
          vy1 = vy;
      var speed = distance(0,0,vx1,vy1);
      var limit = Math.max(gameInfo.speedLimit, speed);

      vx1 += ax;
      vy1 += ay;
      var temp = cap(vx1, vy1, limit);
      vx1 = temp[0];
      vy1 = temp[1];


      var dx = x1 - sunX;
      var dy = y1 - sunY;
      var dis = Math.sqrt(dx*dx+dy*dy);
      if (dis > 5){
        var force = sunG / (dis * dis);
      } else {
        var force = sunG /5;
      }
      vx1 -= force*dx/dis;
      vy1 -= force*dy/dis;

      var temp = cap(vx1, vy1, 40);
      vx1 = temp[0];
      vy1 = temp[1];

      x1 += vx1;
      y1 += vy1;

      return desirability(x1, y1, vx1, vy1);
    }

    var r = distance(sunX, sunY, x, y);
    var theta = Math.atan((y - sunY) / (x - sunX));

    var sunA = sunG/r/r,
            sunAx = -Math.cos(theta) * sunA,
        sunAy = -Math.sin(theta) * sunA;

    var dv = Math.sqrt(sunG / r);
    var dvx = -dv * Math.sin(theta);
    var dvy = dv * Math.cos(theta);
    if (distance(-dvx, -dvy, vx, vy) < distance(dvx, dvy, vx, vy)) {
      dvx = -dvx;
      dvy = -dvy;
    }

    var dax = dvx - vx;
    var day = dvy - vy;

    var dAngle = Math.atan(day / dax);
    if (dax < 0) {
        dAngle += Math.PI;
    }
    var cAngle = toRad(getVar('rot') - 90);
    var dLeft = angleDistance(cAngle - toRad(broken ? 2.5 : 5), dAngle);
    var dRight = angleDistance(cAngle + toRad(broken ? 2.5 : 5), dAngle);
    var dNeither = angleDistance(cAngle, dAngle);
    if (dLeft < dRight && dLeft < dNeither) {
      actions.push('turn left');
    } else if (dRight < dLeft && dRight < dNeither) {
      actions.push('turn right');
    }

    var cax = Math.cos(cAngle) * (broken ? .15 : .3);
    var cay = Math.sin(cAngle) * (broken ? .15 : .3);

    var ax = 0;
    var ay = 0;

    if (distance(cax, cay, dax, day) < distance(0, 0, dax, day)) {
      actions.push('fire engine');
      ax = cax;
      ay = cay;
    }

    if (desirabilityByAcceleration(ax, ay) <= 16) {
        actions.push('hyperspace');
    }

  }

  return actions;
}
Die Nummer eins
quelle
Dein Bot wurde hinzugefügt.
Conor O'Brien
Dein Update ist jetzt live!
El'endia Starman
5

RighthandedSpasms

Der Name ist ziemlich aussagekräftig. Wählt turn rightmit einer Wahrscheinlichkeit von 0,5, fire enginemit einer Wahrscheinlichkeit von 0,5 und fire missilemit einer Wahrscheinlichkeit von 0,8. Überraschend schwierig, vor allem, weil es wirklich unvorhersehbar ist.

function RighthandedSpasms_setup(team) {
    var botVars = {};

    botVars["color"] = team;

    return botVars;
}

function RighthandedSpasms_getActions(gameInfo, botVars) {
    var actions = [];

    if (gameInfo[botVars["color"]+"_alive"]) {
        if (Math.random() > 0.5) { actions.push("turn right") }
        if (Math.random() > 0.5) { actions.push("fire engine") }
        if (Math.random() > 0.8) { actions.push("fire missile") }
    }

    return actions;
}
El'endia Starman
quelle
5

RandUmmm

Diese Herausforderung benötigte einen zufälligen Bot. Bonuspunkte für Golflichkeit?

function RandUmmm_setup(t){
    function P(n,t,r,o,e,f,g){for(o=[e=1<<(f=n.length)];e;)for(t=e.toString(2),r=g=t.length,o[--e]=[];r;)~-t[--r]||o[e].push(n[r+f-g]);return o}var q=P(["fire missile","turn right","fire engine","turn left"]);q.pop();
    return {color:t,m:function(){return q[Math.random()*q.length|0]}};
}

function RandUmmm_getActions(g,b){
    return b.m();
}
Conor O'Brien
quelle
Cool! (By the way, mein Bot gewann 13-7 nicht. Durch viel, wenn man bedenkt ich 9-1 mal verloren, aber das ist eine Menge von Punkten in insgesamt 20 Punkte in 90 Sekunden.!)
ev3commander
@ BlockCoder1392 Es ist ein zufälliger Bot;)
Conor O'Brien
4

Techniker

Verwendet gern Hyperraum, wenn es in Gefahr ist. Öffnen Sie die Konsole Ihres Browsers und geben Sie Folgendes ein, um zu sehen, ob die Leistung stimmt overideHyperspace = 0;. Wenn Sie das Semikolon vergessen, erhalten Sie zu Weihnachten ASI.

function Engineer_setup(t){
    return{c:t,C:"red0blue".split(0)[+(t=="red")]};
}

function Engineer_getActions(gameInfo,botVars){
    var actions = [];

    function d(x1,y1,x2,y2){return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))}
    function hS(g){return d(g.sun_x,g.sun_y,g[botVars.c+"_x"],g[botVars.c+"_y"])<50}
    function enemyDist(g){return d(g[botVars.c+"_x"],g[botVars.c+"_y"],g[botVars.C+"_x"],g[botVars.C+"_y"]);}

    function hSm(g){
        // get closest missile
        var r = (g.missiles||[{x:10000,y:10000}]).reduce(function(p,c){return Math.min(d(c.x,c.y,g[botVars.c+"_x"],g[botVars.c+"_y"]),p)},Infinity);
        return r<18;
    }
    function dF(g){
        var a = Math.degrees(Math.atan2(g[botVars.C+"_y"]-g[botVars.c+"_y"],g[botVars.C+"_x"]-g[botVars.c+"_x"]));
        var tP = (g[botVars.c+"_rot"]+360-a)%360;
        return [a,tP];
    }
    function lOr(g){
        var tP = dF(g)[1];
        return 90<tP&&tP<270?"turn left":"turn right";
    }
    function thrust(g){
        return Math.abs(dF(g)-g[botVars.c+"_rot"]);
    }

    // are we too close to the sun or a missile?
    if(hS(gameInfo)||hSm(gameInfo))actions.push("hyperspace");

    // should we fire?
    if(enemyDist(gameInfo)<200)actions.push("fire missile");

    // direction function
    actions.push(lOr(gameInfo,botVars));

    if(Math.random()<.7)actions.push("fire engine");
    return actions;
}
Conor O'Brien
quelle
3

Sprühen und beten

function SprayAndPray_setup(team) {
    var botVars = {};
    botVars["color"] = team;
    return botVars;
}

function SprayAndPray_getActions(gameInfo, botVars) {
    var actions = [];

    if (gameInfo[botVars["color"]+"_alive"]) {
        actions.push("turn left");
        if (Math.random() > 0.5) { actions.push("fire engine")};
       actions.push("fire missile");
    }

    return actions;
}

Feuert wild in alle Richtungen. Es ist nicht sehr effektiv!

Jack Brounstein
quelle
Dieser Bot ist jetzt live!
El'endia Starman
3

Kamikaze

Nicht sehr wettbewerbsfähig, aber ich dachte, es würde Spaß machen! Fliegt beim Schießen einfach direkt auf den Gegner zu.

function Kamikaze_setup(team) {
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}

function Kamikaze_getActions(gameInfo, botVars) {
  var actions = [];

  // Get our ship's position
  var us, them, red = {
        rotation: gameInfo.red_rot,
        x: gameInfo.red_x,
        y: gameInfo.red_y,
        alive: gameInfo.blue_alive
      },
      blue = {
        rotation: gameInfo.blue_rot,
        x: gameInfo.blue_x,
        y: gameInfo.blue_y,
        alive: gameInfo.blue_alive
      };
  if(botVars.color == "red") {
    us = red;
    them = blue;
  }
  else if(botVars.color == "blue") {
    us = blue;
    them = red;
  }

  // Turn towards our opponent's position
  var angle = Math.degrees(Math.atan2(them.y - us.y, them.x- us.x)),
      rotationToOpponent = (us.rotation - angle + 360) % 360;
  if(rotationToOpponent > 90 && rotationToOpponent < 270) {
    actions.push("turn left");
  }
  else actions.push("turn right");

  actions.push("fire missile", "fire engine");

  return actions;
}
user81655
quelle
Dein Bot wurde hinzugefügt!
Conor O'Brien
Schrecklich gegen OpponentDodger ... Gefesselt mit PanicAttack ...
noɥʇʎԀʎzɐɹƆ
2

UhhIDKWhatToCallThisBot

Nur zufälliges Zeug.

function UhhIDKWhatToCallThisBot_setup(team) {
var botVars = {};
 botVars['t'] = 0;
botVars["color"] = team;
     return botVars;

}

function UhhIDKWhatToCallThisBot_getActions(gameInfo, botVars) {
    var actions = [];
    //when i need it: "turn left",
    //Use missiles sparingly!
    var WCID = [
    "fire engine",
     "turn right",
    "fire engine",
    "fire missile",
    "turn right",
    "fire engine"]

    if (gameInfo[botVars["color"]+"_alive"]) {
        botVars['t']++;
        actions.push(WCID[botVars[t]%(WCID.length)]);
    }
     return actions;
}
ev3commander
quelle
Was ist los mit der kryptischen Golffreudigkeit?
noɥʇʎԀʎz16
2

OpponentDodger

Geht weg von mir Opponenten !!!

function OpponentDodger_setup(t){b={};b["c"]=t;b['o']=(t=="red")?"blue":"red";return b;}function OpponentDodger_getActions(g,b){a=[];o=b["c"];j={r:g[o+"_rot"],x:g[o+"_x"],y:g[o+"_y"]};o=b["o"];p={r:g[o+"_rot"],x:g[o+"_x"],y:g[o+"_y"]};l=Math.degrees(Math.atan2(p.y-j.y,p.x-j.x)),x=(j.r-l+360)%360;if(x > 90 && x < 270)a.push("turn right");else a.push("turn left");a.push("fire engine");return a;}  

Vielen Dank an user81655 für den Code!

ev3commander
quelle
Dieser Bot ist jetzt live!
El'endia Starman
2

Spion

Die Geschichte

Der Prototyp dieses Bots war ein Bot mit zwei Modi: Verrückter Modus und Normaler Modus. Wenn es im verrückten Modus war, blieb es dort für eine konstante Anzahl von Ticks. Die Wahrscheinlichkeit, in den verrückten Modus zu wechseln, war gering. Es war auch hyperspaced, als es nah an der Sonne war. Im verrückten Modus zielte es auf den anderen Bot und schoss ständig. Im normalen Modus flog es vom anderen Bot weg und schoss nicht.

Ich habe diesen Prototyp so optimiert, dass er nur dann verrückt ist, wenn der Feind nahe genug ist. Dann hatte ich eine verrückte Idee: Was wäre, wenn es nur im verrückten Modus bleiben würde? Nach einigem Experimentieren (ich habe hinzugefügt, dass der Bot zufällig ausgelöst wird, wenn er sich im normalen Modus befindet) habe ich festgestellt, dass ich jeden Bot außer Helios mit einem neuen Bot besiegt habe. Dies ist mein Code am Ende dieses Vorgangs, aber vor dem Aufräumen.

Ich habe meinen gesamten Bot im KotH Textarea oder im JS Beautifier geschrieben. (Ich habe kurz den Atom-Editor beim Aufräumen verwendet - aber für wie zwei Codezeilen)

Der Bot

Dieser Bot enthält viel Code, der von anderen Bots entlehnt wurde. Es kippt den Code von Kamikaze, um von dem anderen Bot wegzulaufen, anstatt zu dem anderen Bot zu laufen, und es nimmt Code von EdgeCase für den Hyperraum, wenn er sich in der Nähe der Sonne befindet.

Es ist Erzfeind ist Helios. Es ist der seltsame und lange Gespräche mit einem Martini.

Es läuft vom anderen Bot weg und hat eine 70% ige Chance, eine Rakete und Hyperräume abzufeuern, wenn es sich in der Nähe der Sonne befindet. So einfach ist das. Ja.

Bearbeiten: Ich habe meinen Bot mit dem neuen Code getestet und er schlägt für jeden anderen Bot fehl. Ich arbeite daran, es zu reparieren. Ich habe gerade bestätigt, dass dies nur für meinen neuen Bot gilt.

Der Code

function Spy_setup(team) {
  // Typical setup. Nothing to see here. ;)
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}


function Spy_getActions(gameInfo, botVars) {
    var actions = [];
    var us, them, red = {
            rotation: gameInfo.red_rot,
            x: gameInfo.red_x,
            y: gameInfo.red_y,
            alive: gameInfo.blue_alive
        },
        blue = {
            rotation: gameInfo.blue_rot,
            x: gameInfo.blue_x,
            y: gameInfo.blue_y,
            alive: gameInfo.blue_alive
        };
    if (botVars.color == "red") {
        us = red;
        them = blue;
    } else if (botVars.color == "blue") {
        us = blue;
        them = red;
    }

    function distance(x1, y1, x2, y2) {
        return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }

    // Get our ship's position
    var rotation, x, y, opponentAlive;
    if (botVars.color == "red") {
        rotation = gameInfo.red_rot;
        x = gameInfo.red_x;
        y = gameInfo.red_y;
        opponentAlive = gameInfo.blue_alive;
    } else if (botVars.color == "blue") {
        rotation = gameInfo.blue_rot;
        x = gameInfo.blue_x;
        y = gameInfo.blue_y;
        opponentAlive = gameInfo.red_alive;
    }

    // Calculate our rotation compared to the sun in degrees
    var sunX = gameInfo.sun_x,
        sunY = gameInfo.sun_y,
        angle = Math.atan2(sunY - y, sunX - x) * 180 / Math.PI,
        rotationToSun = (rotation - angle + 360) % 360;

    // Check if we need to hyperspace to avoid the sun
    var rX = x - sunX,
        rY = y - sunY,
        distanceFromSun = Math.sqrt(rX * rX + rY * rY) - gameInfo.sun_r;
    if (distanceFromSun < 30) {
        actions.push("hyperspace");
        console.log("Command Module is Hyperspacing.")
    }
    if (gameInfo[botVars["color"] + "_alive"]) {
        var angle = Math.degrees(Math.atan2(them.y - us.y, them.x - us.x)),
            rotationToOpponent = (us.rotation - angle + 360) % 360;
        if (rotationToOpponent > 90 && rotationToOpponent < 270) {
            actions.push("turn right");
        } else {
            actions.push("turn left");
        };
        actions.push("fire engine");
        if (Math.random() > 0.3) {
            actions.push("fire missile")
        }

    }
    return actions;
}

Das misc

Hinweis: Möglicherweise habe ich beim Aufräumen des Codes etwas kaputt gemacht, weil ich den Bot nach dem Aufräumen des Codes nicht getestet habe.

Es ist auch viel, viel besser als alle meine anderen Bots - es schlägt tatsächlich jeden anderen Bot außer Helios (Bearbeiten) , SetCourseFor30Degrees und OrbitBot! Es knüpft an SunAvoider an.

Randnotiz: Ich bin schrecklich bei Javascript, weiß nicht warum.

noɥʇʎԀʎzɐɹƆ
quelle
@El'endiaStarman Bitte setzen Sie den Bot auf Pause; Ich muss meinen Bot reparieren - die bereinigte Version ist so viel schlechter als die unreine Version.
noɥʇʎԀʎzɥʇʎԀʎ
Okay, lass es mich wissen, wenn es repariert ist.
El'endia Starman
@ El'endiaStarman Ich habe etwas gemacht und dann hat es wieder geklappt. Debugging, wissen Sie? (noch nicht fertig)
noɥʇʎԀʎzɥʇʎԀʎ
@ El'endiaStarman ... und fertig!
noɥʇʎԀʎzɥʇʎԀʎ
Dieser Bot ist jetzt live!
El'endia Starman
1

AttackAndComeBack

Anstatt zu wirbeln, kommt es oben herein und tritt unten aus (kehrt oben zurück) und schießt sehr schnell. Vermeidet im Allgemeinen die Sonne.

function AttackAndComeBack_setup(team) {
    var botVars = {};
    botVars["color"] = team;
    return botVars;
}

function AttackAndComeBack_getActions(gameInfo, botVars) {
    var actions = [];
    actions.push("fire missile");
    if (Math.random()>0.4){actions.push("turn right");}
    else {actions.push("turn left");}
    actions.push("fire engine");
    return actions;
}
noɥʇʎԀʎzɐɹƆ
quelle
Dieser Bot ist jetzt live!
El'endia Starman
1

Vollgas voraus

Feuert immer sowohl die Triebwerke als auch die Raketen ab, ohne jemals zu drehen. Dauert manchmal überraschend lange, bevor sie auf die Sonne trifft.

function FullSpeedAhead_setup(team){
    return {color: team};
}

function FullSpeedAhead_getActions(gameInfo, botVars){
    var actions = [];

    if (gameInfo[botVars["color"]+"_alive"]) {
        actions.push("fire engine");
        actions.push("fire missile");
    }
    return actions;
}
tomulainen
quelle
Nicht so schlimm wie ich dachte ...
no --zɥʇʎԀʎ
Dieser Bot ist jetzt live!
El'endia Starman
1

Panik attacke

Hat eine 50% ige Chance zu schießen und eine 80% ige Chance nach links abzubiegen; aber wenn es nicht links abbiegt, wird es rechts abbiegen. Nachdem die Raketen aufgebraucht sind, wird es aufgrund der Sonne mit der Zeit zum Stillstand kommen.

BEARBEITEN: eine Logik hinzugefügt, um zu verhindern, dass der Feind am Leben ist, da er von seinen eigenen Raketen getötet werden kann.

function PanicAttack_setup(team) {
    var botVars = {};
    botVars["color"] = team;
    return botVars;
}

function PanicAttack_getActions(gameInfo, botVars) {
    var actions = [];
    actions.push("fire engine");
    if(botVars.color == "red") {
        var opponentAlive = gameInfo.blue_alive;
    }
    else if(botVars.color == "blue") {
        var opponentAlive = gameInfo.red_alive;
    }

    if ((Math.random()>0.5)&&opponentAlive) {
        actions.push("fire missile");
    }

    if (Math.random()>0.2) {
        actions.push("turn left");
    } else {
        actions.push("turn right");
    }

    return actions;
}
noɥʇʎԀʎzɐɹƆ
quelle
Dieser Bot ist jetzt live!
El'endia Starman
@ El'endiaStarman Bitte aktualisiere es erneut
noɥʇʎԀʎzɥʇʎԀʎ
Dein Update ist jetzt live!
El'endia Starman
1

DangitBobby

Bobby Hill ist es egal, was andere über ihn denken - er ist ziemlich zufrieden damit, träge über das Spielfeld zu schwingen und geduldig darauf zu warten, dass seinem Gegner der Dampf ausgeht, bevor er wie eine "heisere" Kobra zuschlägt.

function DangitBobby_setup(team) {
    var botVars = {};
    botVars["color"] = team;
    if (team == 'red'){
        botVars['them'] = "blue";
    }
    else{
        botVars['them'] = 'red';
    }
    return botVars;
}

function DangitBobby_getActions(gameInfo, botVars) {
    var actions = [];
    if (gameInfo[botVars["color"]+"_alive"]) {
        actions.push('turn right');
        actions.push('fire engine');
        if (gameInfo[botVars['them']+'_missileStock'] == 0){
                actions.push('fire missile');
        }

    }
}

"DAS IST MEINE GELDBEUTEL! Ich kenne dich nicht!"

John Dikeman
quelle
Dieser Bot ist jetzt live!
El'endia Starman
1

Scharfschütze

Ich habe ein bisschen mit Voraussagen gespielt, um einen Scharfschützenbot zu erschaffen, der seine Feinde abschneidet. Mein Javascript ist zu groß, um in eine Antwort zu passen. Hier ist also ein Link, bot_Sniper .

Jake Ellenberg
quelle
Endlich habe ich versucht, diesen Bot zu testen, und leider hat er das Spiel wirklich verlangsamt. Es ist ziemlich abgehackt, also musst du deinen Code irgendwie schneller machen.
El'endia Starman
Das nächste Mal sollten Sie es in einem Dienst wie [GitHub Gists] (gist.github.com) veröffentlichen, der für Code entwickelt wurde.
noɥʇʎԀʎzɥʇʎԀʎ
Versuchen Sie, Ihren Code zu optimieren. Ich wette, es ist ein wirklich guter Bot, wenn man bedenkt, wie lange es dauert. Sie können versuchen, einige Variablen oder Funktionen einzugeben.
noɥʇʎԀʎzɥʇʎԀʎ
Sie haben auch einige doppelten Code - Ich glaube , Sie viel zu veröffentlichen Ihren Bot zu gewinnen haben würde Code - Review , auf Stapelaustausch.
noɥʇʎԀʎzɐɹƆ
Sie können auch die Funktionen definieren, die Sie in Actions () außerhalb des Gültigkeitsbereichs einfügen, damit der Interpreter sie nicht jedes Mal neu analysieren muss, wenn Sie Actions () ausführen. Sie sollten auch versuchen, Ihren Code zu profilieren, um ihn zu beschleunigen.
noɥʇʎԀʎzɥʇʎԀʎ
1

SmartArrow

Wie Arrow, aber schlau

function SmartArrow_setup(team) {
    var botVars = {};
    botVars['mpref'] = team + '_';
    botVars['epref'] = team == 'red' ? 'blue_' : 'red_';
    botVars['ecolor'] = team == 'red' ? 'blue' : 'red';
    return botVars;
}

function SmartArrow_getActions(gameInfo, botVars) {
    var actions = [];
    var x = gameInfo[botVars['mpref'] + 'x'],
        y = gameInfo[botVars['mpref'] + 'y'],
        rot = gameInfo[botVars['mpref'] + 'rot']; // SmartArrow position and rotation
    var ex = gameInfo[botVars['epref'] + 'x'],
        ey = gameInfo[botVars['epref'] + 'y']; // Enemy position
    var sunx = gameInfo.sun_x,
        suny = gameInfo.sun_y; // Sun position
    var Dsunx = Math.abs(x - sunx),
        Dsuny = Math.abs(y - suny); // Sun position delta
    var dex = Math.abs(x - ex),
        dey = Math.abs(y - ey); // Enemy position delta
    var sangle = Math.degrees(Math.atan2(suny - y, sunx - x)),
        snrot = (rot - sangle + 360) % 360;
    if (Dsunx < 40 && Dsuny < 40) // If SmartArrow is too close from sun, hyperspace !
        return ['hyperspace'];
    var missiles = gameInfo.missiles;
    for (var i = 0; i < missiles.length; i++) { // Avoid all these silly missiles
        var dx = Math.abs(x - missiles[i].x),
            dy = Math.abs(y - missiles[i].y);
        if (dx < 10 && dy < 10)
            return ['hyperspace'];
    }
    if (gameInfo[botVars['epref'] + 'alive']) { // If his enemy is alive, SmartArrow try to kill him (logic)
        var angle = Math.degrees(Math.atan2(ey - y, ex - x)),
            nrot = (rot - angle + 360) % 360;
        if (nrot > 90 && nrot < 270)
            actions.push('turn left');
        else
            actions.push('turn right');
        if (nrot > 80 && nrot < 100
         && Math.random() > 0.5) actions.push('fire missile'); // If SmartArrow is in a good spot, shot this silly oponnent
        if (Math.random() > 0.5) actions.push('fire engine');
    }
    else { // Simply (try to) act like SunAvoider if his enemy is dead
        if (snrot > 90 && snrot < 270)
            actions.push('turn right');
        else
            actions.push('turn left');
        if (Dsunx < 300 && Dsuny < 300)
            actions.push('fire engine');
        if (dex < 40 && dey < 40)
            actions.push('hyperspace'); // Dying on the corpse of his opponent is dumb.
    }
    return actions;
}
TuxCrafting
quelle
Dieser Bot ist jetzt live!
El'endia Starman
1

Kamikaze-

Auch nicht wettbewerbsfähig ausgelegt.Nur zum Spaß. In der Nähe der Sonne tritt ein Hyperraum auf und der Spieler wird verfolgt, ohne dass Kugeln abgefeuert werden. Es macht Spaß zu sehen, wie dieser Bot eine unbewaffnete Version von Spy jagt, aber Sie können leider nicht mehr als einen Userbot haben.

El'endia: hat jemals darüber nachgedacht, mehr als einen Userbot hinzuzufügen;)

function KamikazePlus_setup(team) {
  // Typical setup. Nothing to see here. ;)
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}


function KamikazePlus_getActions(gameInfo, botVars) {
    var actions = [];
    var us, them, red = {
            rotation: gameInfo.red_rot,
            x: gameInfo.red_x,
            y: gameInfo.red_y,
            alive: gameInfo.blue_alive
        },
        blue = {
            rotation: gameInfo.blue_rot,
            x: gameInfo.blue_x,
            y: gameInfo.blue_y,
            alive: gameInfo.blue_alive
        };
    if (botVars.color == "red") {
        us = red;
        them = blue;
    } else if (botVars.color == "blue") {
        us = blue;
        them = red;
    }

    function distance(x1, y1, x2, y2) {
        return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }

    // Get our ship's position
    var rotation, x, y, opponentAlive;
    if (botVars.color == "red") {
        rotation = gameInfo.red_rot;
        x = gameInfo.red_x;
        y = gameInfo.red_y;
        opponentAlive = gameInfo.blue_alive;
    } else if (botVars.color == "blue") {
        rotation = gameInfo.blue_rot;
        x = gameInfo.blue_x;
        y = gameInfo.blue_y;
        opponentAlive = gameInfo.red_alive;
    }

    // Calculate our rotation compared to the sun in degrees
    var sunX = gameInfo.sun_x,
        sunY = gameInfo.sun_y,
        angle = Math.atan2(sunY - y, sunX - x) * 180 / Math.PI,
        rotationToSun = (rotation - angle + 360) % 360;

    // Check if we need to hyperspace to avoid the sun
    var rX = x - sunX,
        rY = y - sunY,
        distanceFromSun = Math.sqrt(rX * rX + rY * rY) - gameInfo.sun_r;
    if (distanceFromSun < 30) {
        actions.push("hyperspace");
        console.log("Command Module is Hyperspacing.")
    }
    if (gameInfo[botVars["color"] + "_alive"]) {
        var angle = Math.degrees(Math.atan2(them.y - us.y, them.x - us.x)),
            rotationToOpponent = (us.rotation - angle + 360) % 360;
        if (rotationToOpponent > 90 && rotationToOpponent < 270) {
            actions.push("turn left");
        } else {
            actions.push("turn right");
        };
        actions.push("fire engine");
    }
    return actions;
}

Ich habe gerade Kamikaze + 's Code genommen und das Raketenabschuss-Teil losgeworden.

noɥʇʎԀʎzɐɹƆ
quelle
Ich werde diesen Bot wahrscheinlich nicht hinzufügen, da wir bereits einen anderen Kamikaze- Bot hatten, und ich möchte lieber keine drei Kamikaze-Bots haben. Außerdem ist dieser trivialer als die beiden anderen.
El'endia Starman
@ El'endiaStarman, dann fordere ich mehrere Userbots an - das zweite Code-Feld kann standardmäßig ausgeblendet und erweiterbar sein
noɥʇʎԀʎzɐɹƆ
0

MissilesPlusScore

Irgendeine seltsame Idee, die mir einfiel, geht davon aus, dass der absolute Wert der Punktedifferenz eine Liste von Zügen in zufälliger Reihenfolge des Spiels verwendet. Es funktioniert gut gegen Bots mit einer Strategie, scheitert aber gegen Raketenstürme. Auch mein erster .

function MissilesPlusScore__setup(team) {
var botVars = {};
botVars["color"] = team;
return botVars;
}
function MissilesPlusScore_getActions(gameInfo, botVars) {
var actions = [];
var moves=["fire missile","hyperspace","turn right","turn left","fire engine","fire missile","turn right","hyperspace","turn left","fire missile","hyperspace","turn right","turn left","hyperspace","fire engine","fire missile","turn right","turn left","hyperspace","fire missile","turn right","turn left","fire engine","hyperspace","fire missile","turn right","turn left","hyperspace"];
if(gameInfo[botVars["color"]+"_alive"]){
var num=gameInfo["redScore"]-gameInfo["blueScore"];
if(num<0){num=num*-1;}
if(num===0){actions.push(moves[Math.round(Math.random()*4)]);}
else{
actions.push(moves[num+gameInfo["numMissiles"]]);
}
}
    return actions;
}

HYPER

HYPERSPACE IST COOL !!!!!!!!!!!!!!!!

function HYPER_setup(team){var botVars={};botVars["color"]=team;return botVars}function HYPER_getActions(gameInfo,botVars){var actions=[];if(gameInfo[botVars["color"]+"_alive"]){actions.push(["fire engine","fire missile","hyperspace"][Math.round(Math.random()*2)])};return actions}

Koordinateneinfluss

Basierend auf den Koordinaten, überraschend effektiv:

function CoordinateInfluence_setup(team) {
var botVars = {};
botVars["color"] = team;
return botVars;
}
function CoordinateInfluence_getActions(gameInfo, botVars) {
var actions = [];
if (gameInfo[botVars["color"]+"_alive"]) {
if(gameInfo["blue_x"]>gameInfo["red_x"]){
if(gameInfo["blue_y"]<gameInfo["red_y"]){actions.push("turn right");}
else{actions.push("fire engine");}
}
else if(gameInfo["blue_y"]<gameInfo["red_y"]){
if(gameInfo["blue_x"]>gameInfo["red_x"]){actions.push("turn left");}
else{actions.push("fire missile");}
}
else{actions.push("hyperspace");}
}
return actions;
}
Generischer Benutzer
quelle
Beide Bots sind live.
El'endia Starman
Sie sollten stattdessen mehrere Antworten posten.
noɥʇʎԀʎzɥʇʎԀʎ
Wenn Sie jemals einen weiteren Bot hinzufügen, senden Sie mir bitte einen Ping-Befehl, damit ich weiß, dass Sie es getan haben. Ihr dritter Bot ist jetzt live.
El'endia Starman
0

SetCourseFor30Degrees

Keine Ahnung, warum der Kapitän so hartnäckig darauf besteht, das Schiff auf einen Kurs von 30 Grad zu stellen, aber hey, als bescheidener Fähnrich, wen sollten Sie in Frage stellen? Zumindest haben Sie die Erlaubnis erhalten, der Sonne auszuweichen! Und du darfst die Raketen abfeuern ... nur nicht auf sie zielen ...

function SetCourseFor30Degrees_setup(team) 
{
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}


function SetCourseFor30Degrees_getActions(gameInfo, botVars)
{
var actions = [];
var ang1 = gameInfo[botVars["color"]+"_rot"]+0;
var fireChance=0.95;
// sun avoidance
   var x = gameInfo[botVars["color"]+"_x"];
   var y = gameInfo[botVars["color"]+"_y"];
   var sunX = gameInfo["sun_x"]+0;
   var sunY = gameInfo["sun_y"]+0;
  var dx = sunX- x;
   var dy = sunY - y;
var shortRangeAvoidanceDistance = (dx * dx + dy * dy ) ;

 x = gameInfo[botVars["color"]+"_x"]+gameInfo[botVars["color"]+"_xv"]*10;
 y = gameInfo[botVars["color"]+"_y"]+gameInfo[botVars["color"]+"_yv"]*10;
 dx = sunX- x;
 dy = sunY - y;

var longRangeAvoidanceDistance = (dx * dx + dy * dy ) ;


var vel = Math.sqrt(gameInfo[botVars["color"]+"_xv"]*gameInfo[botVars["color"]+"_xv"]+
gameInfo[botVars["color"]+"_yv"]*gameInfo[botVars["color"]+"_yv"]);

var close=vel*1.5;

if (shortRangeAvoidanceDistance <= close* close)
{
  actions.push("hyperspace");
}
else
{
   if (longRangeAvoidanceDistance <= 200*200)
   {

     x = x+Math.cos((ang1-5)*Math.PI/180)*vel ;
     y = y+Math.sin((ang1-5)*Math.PI/180)*vel ;
     dx = sunX- x;
     dy = sunY - y;
     if (( dx * dx + dy * dy ) > longRangeAvoidanceDistance  )
     {
       actions.push("turn right")
     }
     else
     {
        actions.push("turn left")
     }
  }
  else
  {
    var course = botVars["color"]=="red"?30:-30;
    if (ang1>course ) {actions.push("turn left")}
    if (ang1<course ) {actions.push("turn right")}
  }
  if (Math.random() > fireChance){ actions.push("fire missile") }
  actions.push("fire engine")
}
return actions;
}
Moogie
quelle
Dieser Bot ist jetzt live!
El'endia Starman
0

Pfeil

Jage einfach seinen Feind, den Hyperraum, wenn er in Gefahr ist, und sei untätig, wenn sein Feind tot ist.

function Arrow_setup(team) {
    var botVars = {};
    botVars['mpref'] = team + '_';
    botVars['epref'] = team == 'red' ? 'blue_' : 'red_';
    return botVars;
}

function Arrow_getActions(gameInfo, botVars) {
    var actions = [];
    var x = gameInfo[botVars['mpref'] + 'x'],
        y = gameInfo[botVars['mpref'] + 'y'],
        rot = gameInfo[botVars['mpref'] + 'rot']; // My position and rotation
    var ex = gameInfo[botVars['epref'] + 'x'],
        ey = gameInfo[botVars['epref'] + 'y']; // Enemy position
    var Dsunx = Math.abs(x - gameInfo.sun_x);
    var Dsuny = Math.abs(y - gameInfo.sun_y);
    if (Dsunx < 30 && Dsuny < 30) // If Arrow is too close from sun, hyperspace !
        return ['hyperspace'];
    var missiles = gameInfo.missiles;
    for (var i = 0; i < missiles.length; i++) {
        var dx = Math.abs(x - missiles[i].x);
        var dy = Math.abs(y - missiles[i].y);
        if (dx < 10 && dy < 10)
            return ['hyperspace'];
    }
    if (gameInfo[botVars['epref'] + 'alive']) {
        var angle = Math.degrees(Math.atan2(ey - y, ex - x)),
            nrot = (rot - angle + 360) % 360;
        if (nrot > 90 && nrot < 270)
            actions.push('turn left');
        else
            actions.push('turn right');
        if (Math.random() > 0.5) actions.push('fire missile');
    }
    if (Math.random() > 0.5) actions.push('fire engine');
    return actions;
}
TuxCrafting
quelle
Dieser Bot ist jetzt live!
El'endia Starman
@ El'endiaStarman Ich habe den Bot aktualisiert
TuxCrafting
Das Update ist jetzt live! Nicht viel von einem. : P
El'endia Starman
0

Kamikaze +

Nicht darauf ausgelegt, wettbewerbsfähig zu sein. Nur zum Spaß. Technisch ist es das Gegenteil von Spy: Jagen Sie den Spieler, Hyperraum in der Nähe der Sonne, feuern Sie 70% der Zeit Raketen ab. Ich möchte KamikazePlus nur sehen, wie er Spy und Spy jagt und wie ein Verrückter davonläuft.

function KamikazePlus_setup(team) {
  // Typical setup. Nothing to see here. ;)
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}


function KamikazePlus_getActions(gameInfo, botVars) {
    var actions = [];
    var us, them, red = {
            rotation: gameInfo.red_rot,
            x: gameInfo.red_x,
            y: gameInfo.red_y,
            alive: gameInfo.blue_alive
        },
        blue = {
            rotation: gameInfo.blue_rot,
            x: gameInfo.blue_x,
            y: gameInfo.blue_y,
            alive: gameInfo.blue_alive
        };
    if (botVars.color == "red") {
        us = red;
        them = blue;
    } else if (botVars.color == "blue") {
        us = blue;
        them = red;
    }

    function distance(x1, y1, x2, y2) {
        return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }

    // Get our ship's position
    var rotation, x, y, opponentAlive;
    if (botVars.color == "red") {
        rotation = gameInfo.red_rot;
        x = gameInfo.red_x;
        y = gameInfo.red_y;
        opponentAlive = gameInfo.blue_alive;
    } else if (botVars.color == "blue") {
        rotation = gameInfo.blue_rot;
        x = gameInfo.blue_x;
        y = gameInfo.blue_y;
        opponentAlive = gameInfo.red_alive;
    }

    // Calculate our rotation compared to the sun in degrees
    var sunX = gameInfo.sun_x,
        sunY = gameInfo.sun_y,
        angle = Math.atan2(sunY - y, sunX - x) * 180 / Math.PI,
        rotationToSun = (rotation - angle + 360) % 360;

    // Check if we need to hyperspace to avoid the sun
    var rX = x - sunX,
        rY = y - sunY,
        distanceFromSun = Math.sqrt(rX * rX + rY * rY) - gameInfo.sun_r;
    if (distanceFromSun < 30) {
        actions.push("hyperspace");
        console.log("Command Module is Hyperspacing.")
    }
    if (gameInfo[botVars["color"] + "_alive"]) {
        var angle = Math.degrees(Math.atan2(them.y - us.y, them.x - us.x)),
            rotationToOpponent = (us.rotation - angle + 360) % 360;
        if (rotationToOpponent > 90 && rotationToOpponent < 270) {
            actions.push("turn left");
        } else {
            actions.push("turn right");
        };
        actions.push("fire engine");
        if (Math.random() > 0.3) {
            actions.push("fire missile")
        }

    }
    return actions;
}

Im Grunde genommen habe ich nur den Code von Spy genommen und "links" und "rechts" gewechselt.

noɥʇʎԀʎzɐɹƆ
quelle
Dieser Bot ist jetzt live! Und ja, es macht Spaß zu sehen, wie KamikazePlus Spy jagt. : P
El'endia Starman
@ El'endiaStarman Ich finde es macht Spaß zu sehen, wie KamikazePlus sich selbst ohne Kugeln bekämpft und overideHyperspace = 0;; Sie werden immer wieder vermisst, wenn sie versuchen, sich gegenseitig anzugreifen.
NoɥʇʎԀʎzɐɹƆ