King of the Hill - Spacewar!


64

Se hai mai giocato a Spacewar! , sai che è stato un gioco divertente. Se non lo hai fatto, sappi questo: è stato (ed è) uno dei primissimi e più importanti giochi per computer. Ed è ancora divertente! Il clone su cui sono cresciuto è questo , che è, apparentemente e sfortunatamente, solo Windows. Così l'ho ricreato!

Il KotH è ospitato qui: PPCG - Spacewar! Il re della collina . Ti incoraggio a giocare come umano contro almeno un altro robot per avere un'idea di come funziona il gioco.

Il gioco

  • Un frame è di 30 millisecondi (quindi circa 33 frame al secondo).
  • Il campo è largo 800 pixel e alto 600 pixel.
  • Il campo è toroidale, il che significa che le astronavi e i missili che si muovono fuori dal campo riappaiono sul lato opposto.
  • Ci sono due astronavi, rosso e blu.
    • Il rosso è posizionato su x = 50 e y casuale tra 50, (altezza del campo - 50) pixel.
    • Il blu è posizionato su x = (larghezza del campo - 50) e y casuale tra 50, (altezza del campo - 50) pixel.
    • Entrambe le facce x = (larghezza del campo) / 2.
  • I controlli disponibili sono:
    • Girare a sinistra - 5 gradi per fotogramma in senso antiorario.
    • Girare a destra - 5 gradi per fotogramma in senso orario.
    • Missile antincendio: viaggia a 10 pixel in più per fotogramma in aggiunta alla velocità della nave, nella direzione in cui puntava la nave.
    • Autopompa antincendio: accelera l'astronave di 0,30 pixel per frame nella direzione in cui punta l'astronave.
    • Salto nell'iperspazio: si teletrasporta su alcune coordinate casuali sul campo, con una probabilità del 25% di esplodere. Queste coordinate casuali possono essere in cima al sole.
  • La velocità massima per le navi è di 15 pixel per frame sotto la potenza del motore e 40 pixel per frame quando potenziata per gravità.
    • Quando si viaggia più velocemente di 15 pixel per frame, la spinta del motore può solo cambiare direzione o rallentare.
  • Per quanto riguarda i missili:
    • I missili viaggiano in linea retta.
    • I missili possono essere lanciati alla velocità massima di 1 per 0,1 secondi.
    • I missili hanno una durata di 2,25 secondi.
    • Le navi hanno un massimo di 20 missili ciascuno.
    • I missili sono particelle di punti internamente.
  • Al centro c'è un sole estremamente pericoloso per la tua nave. Il minimo contatto è fatale. Questo sole distrugge anche i missili.
  • Il sole ha gravità. L'accelerazione risultante è 5000 / (distanza ^ 2) pixel / frame ^ 2, dove la distanza è in pixel. Navi spaziali e missili sono interessati.
  • Entrambe le navi hanno tre zone di attacco: il naso, l'ala sinistra e l'ala destra.
    • Un colpo al naso è la morte istantanea.
    • Un colpo su entrambe le ali riduce della metà la velocità di virata dell'astronave e l'accelerazione del motore.
    • Se entrambe le ali vengono distrutte, l'astronave non può essere manovrata e può sparare solo missili.
  • Le navi possono scontrarsi.
    • Un impatto naso-naso è fatale per entrambe le navi.
    • Un impatto al naso distrugge l'ala.
    • Un impatto ala-ala distrugge entrambe le ali.
  • Le navi morte sono solide e congelate fino a quando non esplodono 1 secondo dopo.
  • Dopo la morte di almeno una nave, il campo viene ripristinato 3 secondi dopo. Fino ad allora, il sole e tutti i missili rimanenti sono ancora pericolosi.

Il gioco originale ha anche asteroidi mortali e indistruttibili, ma non includerò quelli.

Le regole

  • Il tuo bot deve essere scritto in JavaScript.
  • Il tuo bot dovrebbe limitare la sua decisione a circa 10 millisecondi. Se noto un ritardo costante a causa del tuo bot , lo squalificherò e ti farò sapere in modo da poterlo correggere.
  • I robot avranno accesso a quanto segue:
    • Larghezza e altezza del campo
    • Posizione e raggio del sole
    • Posizione, rotazione, velocità, forma, stock di missili e stato nell'iperspazio di entrambe le navi
    • La posizione e la velocità di tutti i missili
  • Quando richiesto, il bot dovrebbe restituire un elenco di stringhe.
    • Queste stringhe dovrebbero essere uno dei seguenti: turn left, turn right, fire engine, fire missile, hyperspace. Qualsiasi altra stringa verrà ignorata.
    • Se ci sono duplicati, verrà notato solo il primo.
    • hyperspace ha la precedenza su tutti gli altri.
    • turn lefte turn rightallo stesso tempo non avrà alcun effetto.
    • fire engine non avrà alcun effetto se la nave ha solo il naso o è morta.
    • fire missile non avrà alcun effetto se un missile è stato sparato troppo di recente.
  • In cambio del solito, al tuo bot è permesso sfruttare il comportamento di altri robot. Voglio incoraggiare un metagame.
    • I robot non possono emulare altri robot. (Vale a dire, nessuna lettura della mente.)
    • I robot non possono impostare alcuna variabile utilizzata dal gioco e dal codice fisico. (Cioè, niente imbrogli.)

Dettagli di implementazione del bot

Conserverò il tuo bot nel suo file JavaScript che viene automaticamente incluso, con il nome del file bot_<name>.js. Quindi non inserire spazi o caratteri che potrebbero interferire con questo o con la denominazione di una funzione in JavaScript. Questo perché dovresti definire le seguenti funzioni: <name>_setup(team)e <name>_getActions(gameInfo, botVars). Più in basso nella pagina, esistono textareas per userbot , che è possibile modificare per testare il codice.

<name>_setup(team)

Questa funzione consente di definire tutte le variabili che si desidera persistere. teamsarà o "red"o "blue". Questa funzione deve restituire un oggetto. Definire le variabili in questo modo:

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

Questo varsoggetto verrà passato all'altra funzione:

<name>_getActions(gameInfo, botVars)

botVarsè l'oggetto restituito da <name>_setup(team). gameInfoè un oggetto contenente le seguenti variabili:

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

Il tuo bot ha pieno accesso a questi. Sono abbastanza sicuro che puoi scrivergli e non influenzare le variabili originali, ma non farlo comunque. Una nota sulle rotazioni: le navi puntano nella direzione + y, verso il basso, quindi tutto ciò che si desidera allineare con la nave deve essere spostato di 90 gradi. Inoltre, la rotazione positiva è in senso orario.

Questa funzione deve restituire un elenco di stringhe, che rappresentano le azioni del bot. Ad esempio ["turn right","thrust"],. Maggiori dettagli su questo sono nella sezione Regole .

dettagli aggiuntivi

È inoltre possibile utilizzare quanto segue:

LineIntersection(L1, L2)

L1 e L2 sono matrici a due elementi di matrici a due elementi. Cioè, L1 := [[x1,y1],[x2,y2]]e L2 := [[u1,v1],[u2,v2]]. Questa funzione calcola l'intersezione di due linee e restituisce questo: [[x,y], [a,b]]. [x,y]sono le coordinate del punto di intersezione ed [a,b]è una coppia di rapporti che esprimono quanto lontano è lungo ogni linea il punto di intersezione. Come in, a = 0.25significherebbe che il punto di intersezione è un quarto della strada da [x1,y1]a [x2,y2], e allo stesso modo per b. Se non c'è intersezione, viene restituita una matrice vuota.

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

Queste sono le coordinate dei poligoni delle navi. Per semplificare il recupero delle coordinate correnti, puoi anche utilizzare ...

getShipCoords(<color>)

getShipCoords("red")restituirà le coordinate correnti dei vertici della nave di Red, e allo stesso modo per getShipCoords("blue")e Blue. Queste coordinate sono in una lista in questo modo: [[x1,y1],[x2,y2],[x3,y3],...]. I poligoni sono implicitamente chiusi, quindi esiste una linea tra la prima e l'ultima coppia di coordinate.

Non è possibile accedere o alterare altre variabili o funzioni in uso dal gioco / sito Web. E sicuramente non nominare le tue funzioni allo stesso modo. Non prevedo che questo sarà un problema, ma se il tuo bot rompe il codice di gioco, questa è una possibilità. Non vi è alcuna registrazione o rilevazione di eccezioni.

vincente

  • Ogni abbinamento di robot deve essere giocato almeno 10 volte, in entrambi i modi. (Quindi, almeno 20 giochi in totale.)
  • Cerca di avere il più alto rapporto vincite / perdite nel complesso . Se il tuo bot fa molto bene contro un altro bot, ma perde contro gli altri tre, non è buono come vincere contro due e perdere contro due (come regola generale).
  • Per ogni bot, verranno calcolati i rapporti (vittorie + 1) / (perdite + 1), quindi verranno calcolate la media e la deviazione standard di questi rapporti. Una media più alta avrà la priorità e, nel caso in cui le medie siano entro 1 unità l'una dall'altra, la varianza inferiore avrà la priorità.
  • Il punteggio inizierà tra una settimana da oggi o dopo tre giorni senza nuovi invii. Questo è quindi non devo ripetere l'associazione dei bot.

Soprattutto, buon divertimento!


Classifica (08/01/2016 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

Nota: questo è soggetto a modifiche quando corro più giochi. Inoltre, l'ordinamento dei gradi 9-13 mi dà fastidio, quindi potrei modificare il metodo di punteggio per abbinare meglio la propria intuizione su come dovrebbero essere classificati.

(Le medie e le deviazioni standard sono state arrotondate a tre cifre decimali. Inoltre, Hyperdovrebbe essere HYPERma ciò incasina l'evidenziazione.: P)


Qualche punteggio? ....
ev3commander il

Registra le eccezioni rilevate?
TheNumberOne

1
È necessario specificare che la chiamata LineIntersectionsu segmenti non intersecanti restituisce una matrice vuota.
LegionMammal978,

1
Penso di averlo fatto!
ev3commander il

3
@CrazyPython: disputerei i primi due considerando che ho praticamente copiato un gioco, ma il terzo è esattamente quello che volevo. Grazie! : D
El'endia Starman il

Risposte:


12

Helios

Questo robot è il centro dell'universo, o almeno pensa di esserlo. La prima cosa che fa è correggere un grave errore e posizionarsi al centro del sistema di coordinate. Quindi ruota tutto intorno a se stesso.

Non gli piace l'altro (falso) sole, quindi cerca di starne lontano. Inoltre non gli piacciono gli altri robot, quindi li spara, se si trova in una buona posizione di tiro.

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
Penso che questo sia uno dei miei robot preferiti finora. È sorprendentemente buono!
El'endia Starman il

@ El'endiaStarman Ho apportato alcuni aggiornamenti al bot.
Sleafar,

Il tuo aggiornamento è ora attivo!
El'endia Starman,

Funziona molto bene contro OrbitBot :)
TheNumberOne,

1
@Soaku Penso che la differenza principale tra questo bot e la maggior parte degli altri sia che questo bot punta sul suo avversario prima di sparare.
Sleafar,

9

SunAvoider

Questo cerca solo di stare lontano dal sole. Lo fa abbastanza bene ... fino a quando non viene distrutta una o entrambe le ali, quindi di solito è solo una questione di tempo prima che cada.

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

EdgeCase

Vola a tutta velocità lontano dal sole verso il bordo della mappa! Quando si trova puntato verso il sole, inizierà a sparare mentre si gira per tornare al limite. Entra anche nell'iperspazio quando sta per colpire il sole.

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

Questo bot è ora attivo! Inoltre, questo è stato sorprendentemente facile sopravvivere contro. Probabilmente ha a che fare con il modo in cui non spammano i missili ovunque come alcuni degli altri. : P
El'endia Starman,

7

OrbitBot

Attualmente non ha targeting o prevenzione delle collisioni . Cerca di orbitare attorno al sole.

Modifica: ora entra nell'iperspazio quando l'impatto è imminente.

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

Il tuo bot è stato aggiunto.
Conor O'Brien,

Il tuo aggiornamento è ora attivo!
El'endia Starman il

5

RighthandedSpasms

Il nome è piuttosto descrittivo. Scegli turn rightcon 0,5 probabilità, fire enginecon 0,5 probabilità e fire missilecon 0,8 probabilità. Sorprendentemente difficile, soprattutto perché è davvero imprevedibile.

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

Questa sfida aveva bisogno di un bot casuale. Punti bonus per il golfismo?

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

Freddo! (A proposito, il mio bot ha vinto 13-7. Non di molto, considerando che ho perso 9-1 una volta, ma questo è un sacco di punti in totale. 20 punti in 90 secondi!)
ev3commander

@ BlockCoder1392 è un bot casuale;)
Conor O'Brien il

4

Ingegnere

Ama usare l'iperspazio quando è in pericolo. Per vedere la sua vera potenza, apri la console del tuo browser e digita overideHyperspace = 0;. Se dimentichi il punto e virgola, otterrai ASI per Natale.

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

SprayAndPray

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

Spara selvaggiamente in ogni direzione. Non è molto efficace!


Questo bot è ora attivo!
El'endia Starman,

3

Kamikaze

Non molto competitivo ma ho pensato che sarebbe stato divertente! Vola dritto verso l'avversario mentre spara.

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

Il tuo bot è stato aggiunto!
Conor O'Brien,

Terribile contro l'avversario Dodger ... Legato con PanicAttack ...
noɥʇʎԀʎzɐɹƆ

2

UhhIDKWhatToCallThisBot

Solo cose a caso.

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

che succede con il golfismo criptico?
noɥʇʎԀʎzɐɹƆ

2

OpponentDodger

ARRIVARE DA ME OPPONENTE !!!

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

Grazie a user81655 per un po 'di codice!


Questo bot è ora attivo!
El'endia Starman il

2

Spiare

La storia

Il prototipo di questo bot era un bot che aveva due modalità: modalità folle e modalità normale. Quando era in modalità folle, è rimasto lì per un numero costante di zecche. C'era una probabilità continua di entrare in modalità folle. Ha anche iperspaziato quando era vicino al sole. In modalità folle, mirava all'altro robot e sparava costantemente. In modalità normale, volava via dall'altro robot, non sparando.

Ho modificato quel prototipo in modo che fosse in modalità folle se e solo se il nemico fosse abbastanza vicino. Poi ho avuto un'idea folle: e se fosse rimasta solo in modalità folle? Dopo un po 'di sperimentazione (ho aggiunto di far sparare il robot in modo casuale quando era in modalità normale) ho trovato un nuovo bot che batteva ogni bot tranne Helios. Questo è il mio codice alla fine di questo processo, ma prima di ripulire.

Ho scritto il mio intero bot nella textarea di KotH o nel beautifier di JS. (Ho usato brevemente l'editor Atom durante la pulizia, ma per due righe di codice simili)

Il robot

Questo bot contiene molto codice preso in prestito da altri bot. Capovolge il codice da Kamikaze per scappare dall'altro bot invece di eseguire l'altro bot e prende il codice da EdgeCase per l'iperspazio quando è vicino al sole.

La sua arco nemesi è Helios. È quello strano fuori e lunghe chiacchierate con un martini.

Scappa dall'altro robot con una probabilità del 70% di sparare un missile e iperspazi quando è vicino al sole. Così semplice. Sì.

Modifica: ho testato il mio bot con il nuovo codice e non funziona per tutti gli altri bot. Sto lavorando per risolverlo. Ho appena confermato che questo è solo per il mio nuovo bot.

Il codice

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

Il misc

Nota: potrei aver rotto qualcosa durante la pulizia del codice perché non ho testato il bot dopo aver ripulito il codice.

È anche molto molto meglio di tutti gli altri miei robot - in realtà ha battuto tutti gli altri bot ad eccezione di Helios (modifica) , SetCourseFor30Degrees e OrbitBot! Si lega a SunAvoider.

Nota a margine: sono orribile su JavaScript, non so perché.


@ El'endiaStarman, per favore, metti il ​​bot in pausa; Devo riparare il mio bot - la versione ripulita è molto peggio della versione sporca.
noɥʇʎԀʎzɐɹƆ

Bene, fammi sapere quando è stato risolto.
El'endia Starman,

@ El'endiaStarman Ho fatto una cosa e poi ha funzionato di nuovo. Debugging, lo sai! (non ancora fatto)
noɥʇʎԀʎzɐɹƆ

@ El'endiaStarman ... ed è fatta!
noɥʇʎԀʎzɐɹƆ

Questo bot è ora attivo!
El'endia Starman,

1

AttackAndComeBack

Invece di turbinare, entra in alto ed esce in basso (tornando in alto), sparando molto rapidamente. Evita generalmente il sole.

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

Questo bot è ora attivo!
El'endia Starman,

1

Avanti tutta

Spara sempre sia i motori che i missili senza mai girare. A volte dura sorprendentemente molto prima di colpire il sole.

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

Non male come pensavo ...
noɥʇʎԀʎzɐɹƆ

Questo bot è ora attivo!
El'endia Starman,

1

Attacco di panico

Ha una probabilità del 50% di sparare e una probabilità dell'80% di svoltare a sinistra; ma se non gira a sinistra, gira a destra. Dopo che ha esaurito i missili, il tempo alla fine lo farà fermare a causa del sole.

EDIT: Aggiunta della logica per non sparare quando il nemico è vivo perché potrebbe essere ucciso dai suoi stessi missili.

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

Questo bot è ora attivo!
El'endia Starman il

@ El'endiaStarman Ti preghiamo di aggiornarlo di nuovo
noɥʇʎԀʎzɐɹƆ

Il tuo aggiornamento è ora attivo!
El'endia Starman,

1

DangitBobby

A Bobby Hill non importa cosa pensano gli altri di lui - è abbastanza contento di dondolarsi pigramente in campo e aspettare pazientemente che il suo avversario finisca di fumare prima di colpire come 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');
        }

    }
}

"QUESTA È LA MIA BORSA! NON TI CONOSCO!"


Questo bot è ora attivo!
El'endia Starman il

1

Cecchino

Ho giocato con la previsione per un po 'per creare un robot cecchino che colpisce i suoi nemici. Il mio javascript è troppo grande per adattarsi a una risposta, quindi ecco un link, bot_Sniper .


Finalmente sono riuscito a provare questo bot e, sfortunatamente, rallenta davvero il gioco. È piuttosto instabile, quindi in qualche modo devi rendere il tuo codice più veloce.
El'endia Starman,

La prossima volta, dovresti pubblicarlo in un servizio come [GitHub Gists] (gist.github.com) progettato per il codice.
noɥʇʎԀʎzɐɹƆ

Prova a ottimizzare il tuo codice; Scommetto che è davvero un ottimo robot considerando quanto dura. Puoi provare a inserire alcune variabili o funzioni.
noɥʇʎԀʎzɐɹƆ

Hai anche un po 'di codice duplicato - penso che avresti molto da guadagnare pubblicando il tuo bot per la revisione del codice , nello scambio di stack.
noɥʇʎԀʎzɐɹƆ

È inoltre possibile definire le funzioni inserite in Actions () nell'ambito esterno, in modo che l'interprete non debba analizzarlo ogni volta che si esegue Actions (). Dovresti anche provare a profilare il tuo codice per accelerarlo.
noɥʇʎԀʎzɐɹƆ

1

SmartArrow

Come Arrow, ma intelligente

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

Questo bot è ora attivo!
El'endia Starman,

1

Kamikaze-

Inoltre non progettato per essere competitivo. Solo per divertimento. Iperspaziale vicino al sole e insegue il giocatore senza sparare proiettili. È divertente guardare questo bot inseguire una versione disarmata di Spy, ma sfortunatamente non puoi avere più di un robot utente.

El'endia: mai considerato l'aggiunta di più di 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;
}

Ho appena preso il codice di Kamikaze + e mi sono sbarazzato della parte di lancio del missile.


Probabilmente non aggiungerò questo bot poiché avevamo già un altro bot Kamikaze e preferirei non avere tre robot kamikaze. Inoltre, questo è più banale degli altri due.
El'endia Starman,

@ El'endiaStarman quindi sto richiedendo più userbot - il campo del secondo codice può essere un predefinito espandibile nascosto
noɥʇʎԀʎzɐɹƆ

0

MissilesPlusScore

Qualche strana idea che mi è venuta in mente che prende il valore assoluto della differenza dei punteggi e usa un elenco di mosse in modo casuale basato sul modo di gioco. Funziona bene contro i robot con una strategia, ma fallisce contro le tempeste di missili. Anche il mio primo .

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

L'iperspazio è freddo !!!!!!!!!!!!!!!!

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

Basato sulle coordinate, sorprendentemente 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;
}

Entrambi questi robot sono attivi.
El'endia Starman il

Dovresti invece pubblicare più risposte.
noɥʇʎԀʎzɐɹƆ

Se mai aggiungi un altro bot, per favore ping me così so che l'hai fatto. Il tuo terzo bot è ora attivo.
El'endia Starman,

0

SetCourseFor30Degrees

Non ho idea del perché il capitano sia così insistente nell'impostare la nave su una rotta di 30 gradi, ma ehi, come umile guardiamarina, chi sei tu a mettere in discussione? Almeno ti è stato dato il permesso di evitare il sole! E ti è permesso sparare i missili ... semplicemente non puoi mirare ...

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

Questo bot è ora attivo!
El'endia Starman,

0

Freccia

Insegui semplicemente il suo nemico, l'iperspazio quando è in pericolo e inattivo quando il suo nemico è morto.

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

Questo bot è ora attivo!
El'endia Starman,

@ El'endiaStarman Ho aggiornato il bot
TuxCrafting il

L'aggiornamento è ora online! Non molto però. : P
El'endia Starman,

0

Kamikaze +

Non progettato per essere competitivo. Solo per divertimento. Tecnicamente, fa l'opposto di Spy: insegue il giocatore, iperspazio quando è vicino al sole, lancia missili il 70% delle volte. Voglio solo vedere KamikazePlus che insegue Spy e Spy scappando come un pazzo.

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

In pratica, ho appena preso il codice di Spy e girato "a sinistra" e "a destra".


Questo bot è ora attivo! E sì, è divertente guardare KamikazePlus inseguire Spy. : P
El'endia Starman,

@ El'endiaStarman Trovo che sia divertente guardare KamikazePlus combattere senza proiettili e overideHyperspace = 0;; continuano a mancare quando provano ad andare l'un l'altro.
noɥʇʎԀʎzɐɹƆ
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.