Roi de la colline - Spacewar!


64

Si vous avez déjà joué à Spacewar! , vous savez que c'était un jeu amusant. Sinon, sachez ceci: c’était (et est) l’un des tout premiers et des plus importants jeux d’ordinateur. Et c'est toujours amusant! Le clone sur lequel j'ai grandi est celui-ci , qui n'est, apparemment et malheureusement, que sous Windows. Alors je l'ai recréé!

Le KotH est hébergé ici: PPCG - Spacewar! Roi de la colline . Je vous encourage à jouer en tant qu’être humain contre au moins un autre bot pour avoir une idée du fonctionnement du jeu.

Le jeu

  • Une image correspond à 30 millisecondes (soit environ 33 images par seconde).
  • Le champ mesure 800 pixels de large et 600 pixels de haut.
  • Le champ est toroïdal, ce qui signifie que les vaisseaux spatiaux et les missiles qui se déplacent à l'extérieur du champ réapparaissent de l'autre côté.
  • Il y a deux vaisseaux spatiaux, rouge et bleu.
    • Le rouge est positionné à x = 50 et le y aléatoire entre 50 pixels (hauteur du champ - 50).
    • Le bleu est positionné à x = (largeur de champ - 50) et y aléatoire entre 50 (hauteur de champ - 50) pixels.
    • Les deux faces x = (largeur du champ) / 2.
  • Les contrôles disponibles sont:
    • Tournez à gauche - 5 degrés par image dans le sens antihoraire.
    • Tourner à droite - 5 degrés par image dans le sens des aiguilles d'une montre.
    • Missile anti-feu - parcourt 10 pixels supplémentaires par image, en plus de la vitesse du navire, dans la direction indiquée par celui-ci.
    • Fire engine - accélère le vaisseau spatial à 0,30 pixel par image dans la direction indiquée par le vaisseau spatial.
    • Saut hyperespace: téléporte sur des coordonnées aléatoires sur le terrain, avec 25% de chances d’exploser. Ces coordonnées aléatoires peuvent être au-dessus du soleil.
  • La vitesse maximale des navires est de 15 pixels par image sous la puissance du moteur et de 40 pixels par image lorsque la gravité est renforcée.
    • Lorsque la vitesse de déplacement dépasse 15 pixels par image, la poussée du moteur peut uniquement changer de direction ou ralentir.
  • En ce qui concerne les missiles:
    • Les missiles se déplacent en ligne droite.
    • Les missiles peuvent être lancés à une cadence maximale de 1 toutes les 0,1 secondes.
    • Les missiles ont une durée de vie de 2,25 secondes.
    • Les navires ont chacun un maximum de 20 missiles.
    • Les missiles sont des particules ponctuelles internes.
  • Il y a un soleil au centre même qui est extrêmement dangereux pour votre navire. Le moindre contact est fatal. Ce soleil détruit aussi les missiles.
  • Le soleil a la gravité. L'accélération résultante est de 5000 / (distance ^ 2) pixels / image ^ 2, où la distance est exprimée en pixels. Les vaisseaux spatiaux et les missiles sont touchés.
  • Les deux navires ont trois zones d’attaque: le nez, l’aile gauche et l’aile droite.
    • Un coup sur le nez est la mort instantanée.
    • Un coup sur l'une ou l'autre aile réduit de moitié le taux de virage et l'accélération du moteur du vaisseau spatial.
    • Si les deux ailes sont détruites, le vaisseau spatial ne peut pas être manœuvré et ne peut tirer que des missiles.
  • Les navires peuvent entrer en collision les uns avec les autres.
    • Un impact nez-nez est fatal pour les deux navires.
    • Un impact de nez-aile détruit l'aile.
    • Un impact d'aile détruit les deux ailes.
  • Les navires morts sont solides et gelés jusqu'à ce qu'ils explosent 1 seconde plus tard.
  • Après la mort d'au moins un navire, le champ est réinitialisé 3 secondes plus tard. Jusque-là, le soleil et tous les missiles restants sont toujours dangereux.

Le jeu original a aussi des astéroïdes mortels et indestructibles, mais je ne les inclurai pas.

Les règles

  • Votre bot doit être écrit en JavaScript.
  • Votre bot devrait limiter sa décision à environ 10 millisecondes. Si je remarque un décalage constant à cause de votre bot , je le disqualifie et vous le fais savoir afin que vous puissiez le réparer.
  • Les robots auront accès aux éléments suivants:
    • Largeur et hauteur du champ
    • Position et rayon du soleil
    • La position, la rotation, la vitesse, la forme, le stock de missiles et l'état dans l'hyperespace des deux navires
    • La position et la vitesse de tous les missiles
  • Lorsque vous y êtes invité, votre bot doit renvoyer une liste de chaînes.
    • Ces chaînes devraient être l' un des éléments suivants: turn left, turn right, fire engine, fire missile, hyperspace. Toute autre chaîne sera ignorée.
    • S'il y a des doublons, seul le premier sera noté.
    • hyperspace a priorité sur tous les autres.
    • turn leftet turn righten même temps n'aura aucun effet.
    • fire engine n'aura aucun effet si le navire n'a que le nez ou est mort.
    • fire missile n'aura aucun effet si un missile a été tiré trop récemment.
  • Contrairement à l'habitude, votre bot est autorisé à exploiter le comportement des autres robots. Je veux encourager un métagame.
    • Les bots ne peuvent pas imiter d'autres bots. (Ie, pas de lecture de l'esprit.)
    • Les robots ne peuvent définir aucune variable utilisée par le code du jeu et de la physique. (C'est-à-dire, pas de triche.)

Détails d'implémentation du bot

Je vais stocker votre bot dans son propre fichier JavaScript qui est automatiquement inclus, avec le nom du fichier bot_<name>.js. Donc, ne mettez pas d'espaces ou de caractères qui pourraient interférer avec cela ou pour nommer une fonction en JavaScript. C'est parce que vous devez définir les fonctions suivantes: <name>_setup(team)et <name>_getActions(gameInfo, botVars). Plus bas dans la page, il existe des zones de texte pour l' utilisateur , que vous pouvez modifier pour tester votre code.

<name>_setup(team)

Cette fonction vous permet de définir les variables que vous souhaitez conserver. teamsera soit "red"ou "blue". Cette fonction doit retourner un objet. Définissez les variables comme suit:

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

Cet varsobjet sera transmis à l'autre fonction:

<name>_getActions(gameInfo, botVars)

botVarsest l'objet renvoyé par <name>_setup(team). gameInfoest un objet contenant les variables suivantes:

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

Votre bot a un accès complet à ceux-ci. Je suis sûr que vous pouvez leur écrire sans affecter les variables d'origine, mais ne le faites pas quand même. Remarque sur les rotations: les navires pointent dans la direction + y, vers le bas, de sorte que tout ce que vous souhaitez aligner sur le navire doit être décalé de 90 degrés. En outre, la rotation positive est dans le sens des aiguilles d'une montre.

Cette fonction doit renvoyer une liste de chaînes, représentant les actions de votre bot. Par exemple, ["turn right","thrust"]. Plus de détails à ce sujet se trouvent dans la section Règles .

Détails supplémentaires

Vous pouvez également utiliser les éléments suivants:

LineIntersection(L1, L2)

L1 et L2 sont des tableaux à deux éléments de tableaux à deux éléments. C'est, L1 := [[x1,y1],[x2,y2]]et L2 := [[u1,v1],[u2,v2]]. Cette fonction calcule l'intersection de deux lignes et renvoie ceci: [[x,y], [a,b]]. [x,y]sont les coordonnées du point d'intersection et [a,b]sont une paire de ratios qui expriment la distance le long de chaque ligne du point d'intersection. Comme dans, a = 0.25cela signifierait que le point d'intersection est à un quart du chemin de [x1,y1]à [x2,y2], et de même pour b. S'il n'y a pas d'intersection, un tableau vide est renvoyé.

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]]
};

Ce sont les coordonnées des polygones des navires. Pour obtenir plus facilement les coordonnées actuelles, vous pouvez également utiliser ...

getShipCoords(<color>)

getShipCoords("red")renverra les coordonnées actuelles des sommets du vaisseau de Red, ainsi que pour getShipCoords("blue")et Blue. Ces coordonnées sont dans une liste comme ceci: [[x1,y1],[x2,y2],[x3,y3],...]. Les polygones étant implicitement fermés, il y a une ligne entre la première et la dernière paire de coordonnées.

Vous ne pouvez pas accéder ni modifier aucune autre variable ou fonction utilisée par le jeu / site web. Et ne nommez pas vos fonctions de la même manière. Je ne prévois pas que ce sera un problème, mais si votre bot casse le code du jeu, c'est une possibilité. Il n'y a pas de journalisation ou de capture d'exceptions.

Gagnant

  • Chaque paire de robots doit être jouée au moins 10 fois, dans les deux sens. (Donc, au moins 20 jeux au total.)
  • Essayez d’obtenir les ratios de gains / pertes les plus élevés au total . Si votre bot réussit très bien contre un autre, mais perd contre les trois autres, ce n'est pas aussi bon que de gagner contre deux et de perdre contre deux (en règle générale).
  • Pour chaque bot, les ratios (gains + 1) / (pertes + 1) seront calculés, puis la moyenne et l'écart type de ces ratios seront calculés. Une moyenne plus élevée sera prioritaire, et si les moyennes sont à moins d'une unité les unes des autres, la variance la plus faible aura la priorité.
  • La notation commencera soit dans une semaine à compter d’aujourd’hui, soit après trois jours sans nouvelle soumission. C'est pour que je n'ai pas à répéter les paires de robots.

Surtout, amusez-vous!


Classement (2016-01-08 05:15):

#   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

Note: Ceci est sujet à changement car je lance plus de jeux. De plus, l'ordre des rangs 9-13 me dérange, je peux donc modifier la méthode de notation pour mieux correspondre à l'intuition de la manière dont elle devrait être classée.

(Les moyennes et les écarts-types ont été arrondis à trois chiffres décimaux. De plus, cela Hyperdevrait être, HYPERmais cela gâchera la mise en évidence.: P)


Des scores? ....
ev3commander

Est-ce qu'il enregistre les exceptions interceptées?
TheNumberOne

1
Vous devez spécifier que l'appel LineIntersectionsur des segments ne se croisant pas renvoie un tableau vide.
LegionMammal978

1
Je pense que je l'ai fait!
ev3commander

3
@CrazyPython: Je contesterais les deux premiers en considérant que j'avais copié un jeu, mais le troisième est exactement ce que je voulais. Merci! : D
El'endia Starman

Réponses:


12

Helios

Ce bot est le centre de l'univers, ou du moins il le pense. La première chose qu'il fait est de corriger une grave erreur et de se placer au centre du système de coordonnées. Puis il tourne n'importe quoi autour de lui.

Il n'aime pas l'autre (faux) soleil, il essaie donc de s'en tenir à l'écart. De plus, il n'aime pas les autres robots, il tire donc dessus s'il est bien placé.

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;
}

1
Je pense que c'est l'un de mes robots préférés jusqu'à présent. C'est étonnamment bon!
El'endia Starman

@ El'endiaStarman, j'ai mis à jour le bot.
Sleafar

Votre mise à jour est maintenant en ligne!
El'endia Starman

Cela fonctionne très bien contre OrbitBot :)
TheNumberOne

1
@ Soaku Je pense que la principale différence entre ce bot et la plupart des autres est que ce bot vise son adversaire avant de tirer.
Sleafar

9

SunAvoider

Celui-ci essaie juste de rester à l'écart du soleil. C’est tellement bien… jusqu’à ce qu’une ou deux ailes soient détruites, il ne faut en général qu’une question de temps avant qu’elle tombe.

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;
}

9

Cas particulier

Vole à toute vitesse loin du soleil vers le bord de la carte! Quand il se trouvera dirigé vers le soleil, il commencera à tirer tout en se tournant pour revenir au bord. Il entre également dans l'hyperespace lorsqu'il est sur le point de frapper le soleil.

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;
}

Ce bot est maintenant en direct! En outre, il était étonnamment facile de survivre contre celui-ci. Cela tient probablement à la manière dont il ne spamme pas les missiles partout, comme certains autres. : P
El'endia Starman

7

OrbitBot

N'a actuellement aucun ciblage ou évitement de collision . Il essaie de tourner autour du soleil.

Edit: passe maintenant dans l’hyperespace lorsque l’impact est imminent.

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;
}

Votre bot a été ajouté.
Conor O'Brien

Votre mise à jour est maintenant en ligne!
El'endia Starman

5

Spasmes Droite

Le nom est assez descriptif. Choisit turn rightavec une probabilité de 0,5, fire engineavec une probabilité de 0,5 et fire missileavec une probabilité de 0,8. Étonnamment difficile, principalement parce que c'est vraiment imprévisible.

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;
}

5

RandUmmm

Ce défi avait besoin d'un bot aléatoire. Des points bonus pour les golfeuses?

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();
}

Cool! (Soit dit en passant, mon bot a gagné 13-7 Non. Par beaucoup, étant donné que je perdais 9-1 fois, mais c'est un grand nombre de points au total 20 points en 90 secondes.!)
ev3commander

@ BlockCoder1392 il est un bot au hasard;)
Conor O'Brien

4

Ingénieur

Aime utiliser l'hyperespace en cas de danger. Pour voir sa véritable puissance, ouvrez la console de votre navigateur et tapez overideHyperspace = 0;. Si vous oubliez le point-virgule, vous obtiendrez l'ASI pour Noël.

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;
}

3

Vaporiser et prier

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;
}

Tire sauvagement dans toutes les directions. Ce n'est pas très efficace!


Ce bot est maintenant en direct!
El'endia Starman

3

Kamikaze

Pas très compétitif mais je pensais que ce serait amusant! Il vole tout droit vers son adversaire pendant le tir.

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;
}

Votre bot a été ajouté!
Conor O'Brien

Terrible against OpponentDodger ... à égalité avec PanicAttack ...
noɥʇʎԀʎzɐɹƆ

2

UhhIDKWhatToCallThisBot

Juste des trucs aléatoires.

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;
}

quoi de neuf avec le golfiness cryptique?
nozɐɹƆ

2

OpposantDodger

LANCEZ-VOUS DE MON OPPOSANT !!!

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;}  

Merci à user81655 pour du code!


Ce bot est maintenant en direct!
El'endia Starman

2

Espion

L'histoire

Le prototype de ce bot était un bot qui avait deux modes: le mode fou et le mode normal. Quand il était en mode fou, il restait là pendant un nombre constant de ticks. Il y avait une probabilité constante d'entrer en mode fou. Il a également hyperspacé quand il était près du soleil. En mode fou, il visait l'autre bot et tirait constamment. En mode normal, il s'est envolé de l'autre bot sans tirer.

J'ai peaufiné ce prototype pour qu'il soit en mode fou si et seulement si l'ennemi était suffisamment proche. Ensuite, j'ai eu une idée folle: et si cela restait seulement en mode fou? Après quelques expériences (j'ai ajouté que le bot se mettait à feu de manière aléatoire quand il était en mode normal), je trouvais un nouveau bot qui battait tous les bots sauf Helios. Ceci est mon code à la fin de ce processus, mais avant le nettoyage.

J'ai écrit tout mon bot dans le KotH textarea ou le JS Beautifier. (J'ai brièvement utilisé l'éditeur Atom lors du nettoyage - mais pour deux lignes de code similaires)

Le bot

Ce bot contient beaucoup de code emprunté à d'autres robots. Il retourne le code de Kamikaze pour qu’il fuie l’autre bot au lieu de s’exécuter sur l’autre, et il prend le code d’EdgeCase pour une accélération extrême quand il est proche du soleil.

Son arc némésis est Helios. C'est l'intrus et de longues conversations avec un martini.

Il s'enfuit de l'autre bot avec 70% de chances de tirer un missile et d'hyperspaces lorsqu'il est proche du soleil. Aussi simple que cela. Oui.

Edit: J'ai testé mon bot avec le nouveau code et il échoue pour tous les autres. Je travaille sur le réparer. Je viens de confirmer que ce n'est que pour mon nouveau bot.

Le 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;
}

Le misc

Remarque: j'ai peut-être cassé quelque chose lors du nettoyage du code car je n'ai pas testé le bot après le nettoyage du code.

C'est aussi bien meilleur que tous mes autres robots - il bat tous les autres, sauf Helios (edit) , SetCourseFor30Degrees et OrbitBot! Il est lié à SunAvoider.

Note latérale: Je suis horrible en javascript, je ne sais pas pourquoi.


@ El'endiaStarman s'il vous plaît mettez le bot en direct en pause; Je dois réparer mon bot - la version nettoyée est tellement pire que la version malpropre.
nozɐɹƆ

D'accord, laissez-moi savoir quand c'est réglé.
El'endia Starman

@ El'endiaStarman J'ai fait une chose et puis ça a encore fonctionné. Le débogage, vous savez! (pas encore fait)
nozɐɹƆ

@ El'endiaStarman ... et c'est fait!
nozɐɹƆ

Ce bot est maintenant en direct!
El'endia Starman

1

AttackAndComeBack

Au lieu de tourbillonner, il entre par le haut et sort par le bas (en revenant par le haut) en tirant très rapidement. Évite généralement le soleil.

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;
}

Ce bot est maintenant en direct!
El'endia Starman

1

Pleine vitesse

Tire toujours les moteurs et les missiles sans jamais tourner. Parfois dure étonnamment longtemps avant de frapper le soleil.

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;
}

Pas aussi mauvais que je pensais ...
nozɐɹƆ

Ce bot est maintenant en direct!
El'endia Starman

1

PanicAttack

A 50% de chances de tirer et 80% de chance de tourner à gauche; mais s'il ne tourne pas à gauche, il tournera à droite. Après avoir manqué de missiles, le temps finira par le faire s'arrêter à cause du soleil.

EDIT: Ajout d'une certaine logique pour ne pas tirer lorsque l'ennemi est en vie, car il pourrait être tué par ses propres missiles.

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;
}

Ce bot est maintenant en direct!
El'endia Starman

@ El'endiaStarman S'il vous plaît mettre à jour à nouveau
noɥʇʎԀʎzɐɹƆ

Votre mise à jour est maintenant en ligne!
El'endia Starman

1

DangitBobby

Bobby Hill se fiche de ce que les autres pensent de lui - il est plutôt content de balancer paresseusement sur le terrain et d'attendre patiemment que son adversaire s'essouffle avant de frapper comme un cobra "husky".

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');
        }

    }
}

"C’est mon sac! Je ne vous connais pas!"


Ce bot est maintenant en direct!
El'endia Starman

1

Tireur d'élite

Je joue un peu avec la prédiction pour créer un robot tireur d’élite qui snipe ses ennemis. Mon javascript est trop volumineux pour tenir dans une réponse, donc voici un lien, bot_Sniper .


Finalement, j'ai pu tester ce bot et malheureusement, cela ralentit vraiment le jeu. C'est assez agité, vous devez donc rendre votre code plus rapide en quelque sorte.
El'endia Starman

La prochaine fois, vous devriez l'afficher dans un service tel que [GitHub Gists] (gist.github.com) conçu pour le code.
nozɐɹƆ

Essayez d’optimiser votre code. Je parie que c'est un très bon bot compte tenu de sa durée. Vous pouvez essayer d’intégrer certaines variables ou fonctions.
nozɐɹƆ

Vous avez également un code en double - je pense que vous auriez beaucoup à gagner en postant votre bot à la révision du code , lors de l'échange de pile.
nozɐɹƆ

Vous pouvez également définir les fonctions que vous avez définies dans Actions () dans la portée externe, afin que l'interpréteur n'ait pas à le réparer à chaque fois que vous exécutez Actions (). Vous devriez également essayer de profiler votre code pour l'accélérer.
nozɐɹƆ

1

SmartArrow

Comme Arrow, mais intelligent

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;
}

Ce bot est maintenant en direct!
El'endia Starman

1

Kamikaze-

Aussi pas conçu pour être compétitif. Juste pour le fun. Il hyperspace à proximité du soleil et poursuit le joueur sans tirer de balles. C'est amusant de regarder ce bot chasser une version non armée de Spy, mais vous ne pouvez malheureusement pas avoir plus d'un utilisateur.

El'endia: jamais envisagé d'ajouter plus d'un userbot;)

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;
}

Je viens de prendre le code de Kamikaze + et de me débarrasser de la partie tir de missile.


Je ne vais probablement pas ajouter ce bot car nous avions déjà un autre bot kamikaze et je préférerais ne pas avoir trois robots kamikaze. En outre, celui-ci est plus trivial que les deux autres.
El'endia Starman

@ El'endiaStarman alors je demande plusieurs userbots - le champ de code du second peut être un
expandable

0

MissilesPlusScore

Une idée étrange que je suis venu avec qui prend que la valeur absolue de la différence des scores et utilise une liste de coups dans une base aléatoire de la manière de jeu. Cela fonctionne bien contre les robots avec une stratégie mais échoue contre les tempêtes de missiles. Aussi mon premier .

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 IS 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}

CoordinateInfluence

Basé sur les coordonnées, étonnamment efficace:

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;
}

Ces deux robots sont en direct.
El'endia Starman

Vous devriez poster plusieurs réponses à la place.
nozɐɹƆ

Si vous ajoutez un autre bot, envoyez-moi un ping afin que je sache que vous l'avez fait. Votre troisième bot est maintenant en ligne.
El'endia Starman

0

SetCourseFor30Degrees

Vous ne savez pas pourquoi le capitaine insiste si ardemment pour placer le navire sur une trajectoire de 30 degrés, mais bon, en tant qu'enseigne humble, qui devez-vous interroger? Au moins on vous a donné la permission d'éviter le soleil! Et vous êtes autorisé à tirer les missiles ... mais pas à les viser ...

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;
}

Ce bot est maintenant en direct!
El'endia Starman

0

Flèche

Il suffit de chasser son ennemi, l'hyperespace lorsqu'il est en danger et inactif lorsque son ennemi est mort.

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;
}

Ce bot est maintenant en direct!
El'endia Starman

@ El'endiaStarman J'ai mis à jour le bot
TuxCrafting

La mise à jour est maintenant en ligne! Pas grand chose cependant. : P
El'endia Starman le

0

Kamikaze +

Non conçu pour être compétitif. Juste pour le fun. Techniquement, c'est le contraire de Spy: chasser le joueur, hyper-espace à proximité du soleil, lancer un missile 70% du temps. Je veux juste voir KamikazePlus pourchasser Spy et Spy s'enfuyant comme un fou.

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;
}

Essentiellement, je viens de prendre le code de Spy's et d’inverser «gauche» et «droite».


Ce bot est maintenant en direct! Et oui, c'est amusant de regarder KamikazePlus pourchasser Spy. : P
El'endia Starman

@ El'endiaStarman Je trouve amusant de regarder KamikazePlus se battre sans balles et overideHyperspace = 0;; ils ne font que disparaître quand ils essaient de s’attaquer.
nozɐɹƆ
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.