Rei da Colina - Guerra Espacial!


64

Se você já jogou Spacewar! , você sabe que foi um jogo divertido. Caso contrário, saiba disso: foi (e é) um dos primeiros e mais importantes jogos de computador. E ainda é divertido! O clone em que cresci é este , que é, aparentemente e infelizmente, apenas o Windows. Então eu o recriei!

O KotH está hospedado aqui: PPCG - Spacewar! Rei da colina . Convido você a jogar como humano contra pelo menos um outro bot para ter uma ideia de como o jogo funciona.

O jogo

  • Um quadro tem 30 milissegundos (portanto, cerca de 33 quadros por segundo).
  • O campo tem 800 pixels de largura e 600 pixels de altura.
  • O campo é toroidal, o que significa que naves espaciais e mísseis que se movem para fora do campo reaparecem no lado oposto.
  • Existem duas naves espaciais, vermelha e azul.
    • O vermelho é posicionado em x = 50 e y aleatoriamente entre 50, (altura do campo - 50) pixels.
    • O azul está posicionado em x = (largura do campo - 50) e y aleatório entre 50, (altura do campo - 50) pixels.
    • Ambas as faces x = (largura do campo) / 2.
  • Os controles disponíveis são:
    • Vire à esquerda - 5 graus por quadro no sentido anti-horário.
    • Vire à direita - 5 graus por quadro no sentido horário.
    • Míssil de fogo - viaja a 10 pixels extras por quadro, além da velocidade do navio, na direção em que o navio estava apontando.
    • Motor de incêndio - acelera a nave espacial em 0,30 pixels por quadro na direção em que a nave está apontando.
    • Salto no hiperespaço - teleporta-se para algumas coordenadas aleatórias no campo, com 25% de chance de explodir. Essas coordenadas aleatórias podem estar em cima do sol.
  • A velocidade máxima para navios é de 15 pixels por quadro sob potência do motor e 40 pixels por quadro quando aumentados pela gravidade.
    • Ao viajar mais de 15 pixels por quadro, o impulso do motor pode mudar de direção ou diminuir a velocidade.
  • Em relação aos mísseis:
    • Mísseis viajam em linha reta.
    • Mísseis podem ser disparados a uma taxa máxima de 1 por 0,1 segundos.
    • Os mísseis têm uma vida útil de 2,25 segundos.
    • Os navios têm no máximo 20 mísseis cada.
    • Mísseis são partículas pontuais internamente.
  • Há um sol no centro que é extremamente perigoso para o seu navio. O menor contato é fatal. Este sol também destrói mísseis.
  • O sol tem gravidade. A aceleração resultante é de 5000 / (distância ^ 2) pixels / quadro ^ 2, onde a distância está em pixels. Naves espaciais e mísseis são afetados.
  • Ambos os navios têm três zonas de ataque: o nariz, a asa esquerda e a asa direita.
    • Um golpe no nariz é a morte instantânea.
    • Um golpe em qualquer uma das asas reduz a taxa de giro da nave espacial e a aceleração do motor pela metade.
    • Se ambas as asas são destruídas, a nave espacial não pode ser manobrada e só pode disparar mísseis.
  • Os navios podem colidir entre si.
    • Um impacto nariz-nariz é fatal para os dois navios.
    • Um impacto na asa do nariz destrói a asa.
    • Um impacto de asa destrói as duas asas.
  • Navios mortos são sólidos e congelados até explodir 1 segundo depois.
  • Após a morte de pelo menos um navio, o campo é redefinido 3 segundos depois. Até então, o sol e quaisquer outros mísseis ainda são perigosos.

O jogo original também possui asteróides mortais e indestrutíveis, mas não os incluirei.

As regras

  • Seu bot deve ser escrito em JavaScript.
  • Seu bot deve limitar sua decisão a cerca de 10 milissegundos. Se eu notar um atraso consistente por causa do seu bot , eu o desqualificarei e informarei para que você possa corrigi-lo.
  • Os bots terão acesso ao seguinte:
    • Largura e altura do campo
    • Posição e raio do sol
    • A posição, rotação, velocidade, forma, estoque de mísseis e status no hiperespaço de ambos os navios
    • A posição e velocidade de todos os mísseis
  • Quando solicitado, seu bot deve retornar uma lista de strings.
    • Essas cordas deve ser um dos seguintes: turn left, turn right, fire engine, fire missile, hyperspace. Qualquer outra string será ignorada.
    • Se houver duplicatas, somente a primeira será anotada.
    • hyperspace tem precedência sobre todos os outros.
    • turn lefte turn rightao mesmo tempo não terá efeito.
    • fire engine não terá efeito se o navio tiver apenas o nariz ou estiver morto.
    • fire missile não terá efeito se um míssil for disparado muito recentemente.
  • Em uma mudança do habitual, seu bot tem permissão para explorar o comportamento de outros bots. Eu quero incentivar um metagame.
    • Os bots não podem emular outros bots. (Ou seja, sem leitura da mente.)
    • Bots não podem definir nenhuma variável usada pelo jogo e pelo código de física. (Ou seja, sem trapaça.)

Detalhes da implementação do bot

Eu armazenarei seu bot em seu próprio arquivo JavaScript automaticamente incluído, com o nome do arquivo bot_<name>.js. Portanto, não coloque espaços ou caracteres que possam interferir nisso ou nomear uma função em JavaScript. Isso porque você deve definir as seguintes funções: <name>_setup(team)e <name>_getActions(gameInfo, botVars). Mais abaixo na página, existem áreas de texto para o userbot , que você pode editar para testar seu código.

<name>_setup(team)

Esta função é para você definir quaisquer variáveis ​​que deseja persistir. teamserá ou "red"ou "blue". Esta função deve retornar um objeto. Defina variáveis ​​da seguinte forma:

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

Este varsobjeto será passado para a outra função:

<name>_getActions(gameInfo, botVars)

botVarsé o objeto retornado por <name>_setup(team). gameInfoé um objeto que contém as seguintes variáveis:

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

Seu bot tem acesso total a eles. Tenho certeza de que você pode escrever nelas e não afetar as variáveis ​​originais, mas não faça isso de qualquer maneira. Uma observação sobre as rotações: os navios apontam na direção + y, para baixo, para que qualquer coisa que você queira alinhar com o navio precisa ser deslocada em 90 graus. Além disso, a rotação positiva é no sentido horário.

Esta função deve retornar uma lista de strings, representando as ações do seu bot. Por exemplo ["turn right","thrust"],. Mais detalhes sobre isso estão na seção Regras .

detalhes adicionais

Você também pode fazer uso do seguinte:

LineIntersection(L1, L2)

L1 e L2 são matrizes de dois elementos de matrizes de dois elementos. Isto é, L1 := [[x1,y1],[x2,y2]]e L2 := [[u1,v1],[u2,v2]]. Esta função calcula a intersecção de duas linhas e devolve este: [[x,y], [a,b]]. [x,y]são as coordenadas do ponto de interseção e [a,b]são um par de relações que expressam a distância em cada linha que o ponto de interseção está. Como em, a = 0.25significaria que o ponto de intersecção é um quarto do caminho a partir [x1,y1]de [x2,y2], e da mesma forma para b. Se não houver interseção, uma matriz vazia será retornada.

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

Estas são as coordenadas dos polígonos dos navios. Para facilitar a obtenção das coordenadas atuais, você também pode usar ...

getShipCoords(<color>)

getShipCoords("red")retornará as coordenadas atuais dos vértices do navio de Red, e também para getShipCoords("blue")Blue. Essas coordenadas estão em uma lista assim: [[x1,y1],[x2,y2],[x3,y3],...]. Os polígonos são implicitamente fechados, portanto há uma linha entre o primeiro e o último par de coordenadas.

Você não pode acessar ou alterar quaisquer outras variáveis ​​ou funções em uso pelo jogo / site. E definitivamente não dê o mesmo nome às suas funções. Não prevejo que isso seja um problema, mas se o seu bot quebrar o código do jogo, essa é uma possibilidade. Não há registro ou captura de exceções.

Ganhando

  • Todo par de bots deve ser jogado pelo menos 10 vezes, nos dois sentidos. (Portanto, pelo menos 20 jogos no total.)
  • Procure ter as maiores taxas de ganhos / perdas em geral . Se seu bot se sai super bem contra um outro bot, mas perde contra os outros três, isso não é tão bom quanto vencer dois e perder contra dois (como regra geral).
  • Para cada bot, as razões (vitórias + 1) / (perdas + 1) serão calculadas e, em seguida, a média e o desvio padrão dessas relações serão calculados. Uma média mais alta terá prioridade e, caso as médias estejam dentro de 1 unidade uma da outra, a variação menor terá prioridade.
  • A pontuação começará dentro de uma semana a partir de hoje ou após três dias sem novos envios. Isso é para que eu não precise repetir nenhum emparelhamento de bots.

Acima de tudo, divirta-se!


Classificação (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: Isso está sujeito a alterações à medida que eu corro mais jogos. Além disso, a ordenação das fileiras 9 a 13 me incomoda, então posso ajustar o método de pontuação para melhor corresponder à intuição de como devem ser classificadas.

(As médias e os desvios-padrão foram arredondados para três dígitos decimais. Além disso, Hyperdeve ser, HYPERmas isso atrapalha o destaque.: P)


Alguma pontuação? ...
ev3commander

Registra exceções capturadas?
TheNumberOne

11
Você deve especificar que a chamada LineIntersectionem segmentos sem interseção retorne uma matriz vazia.
usar o seguinte

11
Eu acho que fiz isso!
ev3commander

3
@CrazyPython: Eu disputaria os dois primeiros, considerando que basicamente copiei um jogo, mas o terceiro é exatamente o que eu queria. Obrigado! : D
El'endia Starman

Respostas:


12

Helios

Esse bot é o centro do universo, ou pelo menos ele pensa que é. A primeira coisa que ele faz é corrigir um erro grave e se colocar no centro do sistema de coordenadas. Então ele gira qualquer coisa ao seu redor.

Ele não gosta do outro sol (falso) e, portanto, tenta ficar longe dele. Ele também não gosta de outros bots, portanto atira neles, se estiver em uma boa posição de 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;
}

11
Acho que este é um dos meus bots favoritos até agora. É surpreendentemente bom!
El'endia Starman 27/12/2015

@ El'endiaStarman Fiz algumas atualizações no bot.
Sleafar

Sua atualização já está ativa!
El'endia Starman

Isso funciona muito bem contra o OrbitBot :)
TheNumberOne

11
@Sakaku Eu acho que a principal diferença entre esse bot e a maioria dos outros é que esse bot visa o oponente antes de disparar.
Sleafar

9

SunAvoider

Este apenas tenta ficar longe do sol. Faz tão bem ... até que uma ou ambas as asas sejam destruídas, geralmente é apenas uma questão de tempo até que caia.

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

Voa a toda velocidade, longe do sol, em direção à borda do mapa! Quando se vê apontado para o sol, começa a disparar enquanto se afasta para voltar à borda. Ele também entra no hiperespaço quando está prestes a atingir o sol.

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

Este bot já está ativo! Além disso, este era surpreendentemente fácil de sobreviver. Provavelmente tem a ver com a forma como ele não envia mísseis em todos os lugares, como alguns dos outros. : P
El'endia Starman

7

OrbitBot

Atualmente, não há segmentação ou prevenção de colisões . Ele tenta orbitar o sol.

Edit: Agora entra no hiperespaço quando o impacto é iminente.

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

Seu bot foi adicionado.
Conor O'Brien

Sua atualização já está ativa!
El'endia Starman 26/12/2015

5

Espasmos para a direita

O nome é bastante descritivo. Escolhe turn rightcom probabilidade 0,5, fire enginecom probabilidade 0,5 e fire missilecom probabilidade 0,8. Surpreendentemente difícil, principalmente porque é realmente imprevisível.

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

Esse desafio precisava de um bot aleatório. Pontos de bônus por golfiness?

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

Legal! (By the way, o meu bot ganhou 13-7 Não. Por muito, considerando que eu perdi 9-1 uma vez, mas isso é um monte de pontos no total 20 pontos em 90 segundos.!)
ev3commander

@ BlockCoder1392 que é um bot aleatório;)
Conor O'Brien

4

Engenheiro

Gosta de usar o hiperespaço quando em perigo. Para ver seu verdadeiro poder, abra o console do seu navegador e digite overideHyperspace = 0;. Se você esquecer o ponto e vírgula, receberá o ASI no Natal.

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

Espalhe e reze

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

Incêndios descontroladamente em todas as direções. Não é muito eficaz!


Este bot já está ativo!
El'endia Starman 24/12/2015

3

Kamikaze

Não é muito competitivo, mas achei que seria divertido! Apenas voa direto em direção ao oponente durante o disparo.

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

Seu bot foi adicionado!
Conor O'Brien

Terrível contra o OpponentDodger ... Amarrado com PanicAttack ... #
26215

2

UhhIDKWhatToCallThisBot

Apenas coisas aleatórias.

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

o que há com a golficidade enigmática?
18716

2

OpponentDodger

Afaste-se de mim oponente !!!

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

Obrigado a user81655 por algum código!


Este bot já está ativo!
El'endia Starman 25/12/2015

2

Espião

A história

O protótipo desse bot era um bot que tinha dois modos: modo louco e modo normal. Quando estava no modo louco, ficava lá por um número constante de carrapatos. Havia uma probabilidade constante de entrar no modo louco. Também hiperespaçou quando estava perto do sol. No modo louco, ele apontou para o outro bot e disparou constantemente. No modo normal, ele voou para longe do outro bot, não disparando.

Apertei esse protótipo para que ele estivesse no modo louco, se e somente se o inimigo estivesse perto o suficiente. Então eu tive uma ideia maluca: e se ele continuasse no modo louco? Após algumas experiências (eu adicionei fazendo o bot disparar aleatoriamente quando estava no modo normal), encontrei um novo bot para vencer todos os bot, menos o Helios. Este é o meu código no final deste processo, mas antes da limpeza.

Eu escrevi meu bot inteiro na área de texto KotH ou no embelezador JS. (Usei brevemente o editor Atom durante a limpeza - mas por duas linhas de código)

O bot

Este bot contém muitos códigos emprestados de outros bots. Ele inverte o código do Kamikaze para fugir do outro bot em vez de executá-lo e leva o código do EdgeCase para hiperespaçamento quando está perto do sol.

Seu arqui-inimigo é Helios. Sendo o único fora e conversas longas com um martini.

Ele foge do outro robô com 70% de chance de disparar um míssil e hiperespaços quando está perto do sol. Tão simples como isso. Sim.

Edit: Eu testei meu bot com o novo código e ele falha em todos os outros bot. Estou trabalhando para consertá-lo. Acabei de confirmar que isso é apenas para o meu novo bot.

O código

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

O misc

Nota: Eu posso ter quebrado alguma coisa ao limpar o código porque não testei o bot depois de limpar o código.

Também é muito, muito melhor do que todos os meus outros bots - na verdade, venceu todos os outros bot, exceto Helios (editar) , SetCourseFor30Degrees e OrbitBot! Está ligado ao SunAvoider.

Nota lateral: sou péssimo em javascript, não sei por quê.


@ El'endiaStarman, coloque o bot em pausa; Preciso consertar meu bot - a versão limpa é muito pior que a versão impura.
noɥʇʎԀʎzɐɹƆ

Tudo bem, deixe-me saber quando estiver consertado.
El'endia Starman 18/07/19

@ El'endiaStarman Fiz uma coisa e depois funcionou novamente. Depuração, você sabe! (ainda não feito)
noɥʇʎԀʎzɐɹƆ 18/07/2016

@ El'endiaStarman ... e pronto!
noɐɹƆzɐɹƆ 18/07/2016

Este bot já está ativo!
El'endia Starman

1

AttackAndComeBack

Em vez de girar, ele entra na parte superior e sai na parte inferior (retornando na parte superior), disparando muito rapidamente. Geralmente evita o sol.

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

Este bot já está ativo!
El'endia Starman 26/12/2015

1

Velocidade máxima a frente

Sempre aciona os motores e os mísseis sem virar. Às vezes dura surpreendentemente muito tempo antes de atingir o sol.

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

Não é tão ruim quanto eu pensava ...
noɐɹƆzɐɹƆ

Este bot já está ativo!
El'endia Starman 26/12/2015

1

Ataque de pânico

Tem 50% de chance de disparar e 80% de chance de virar à esquerda; mas se não virar à esquerda, vire à direita. Depois que ficar sem mísseis, o tempo acabará parando devido ao sol.

EDIT: Adicionado alguma lógica para não disparar quando o inimigo está vivo, porque ele pode ser morto por seus próprios mísseis.

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

Este bot já está ativo!
El'endia Starman

@ El'endiaStarman Atualize-o novamente
noɥʇʎԀʎzɐɹƆ

Sua atualização já está ativa!
El'endia Starman 26/12/2015

1

DangitBobby

Bobby Hill não se importa com o que os outros pensam sobre ele - ele está bastante contente em andar preguiçosamente pelo campo e esperar pacientemente que seu oponente fique sem vapor antes de atacar como uma cobra "rouca".

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

    }
}

"Essa é a minha bolsa! Eu não sei você!"


Este bot já está ativo!
El'endia Starman 27/12/2015

1

Franco atirador

Eu tenho jogado com a previsão por um tempo para criar um bot de atirador que rouba seus inimigos. Meu javascript é muito grande para caber em uma resposta, então aqui está um link, bot_Sniper .


Finalmente comecei a testar esse bot e, infelizmente, ele realmente diminui o ritmo do jogo. É bastante instável, então você precisa tornar seu código mais rápido de alguma forma.
El'endia Starman 30/03/16

Da próxima vez, você deve publicá-lo em um serviço como [GitHub Gists] (gist.github.com) projetado para código.
noɐɹƆzɐɹƆ 18/07/16

Tente otimizar seu código; Aposto que é um robô muito bom, considerando quanto tempo leva. Você pode tentar inserir algumas variáveis ​​ou funções.
noɐɹƆzɐɹƆ 18/07/2016

Você também tem algum código duplicado - acho que você teria muito a ganhar ao publicar seu bot na revisão de código , na troca de pilhas.
noɐɹƆzɐɹƆ 18/07/2016

Você também pode definir as funções que você coloca em Actions () no escopo externo, para que o intérprete não precise revisá-lo toda vez que executar Actions (). Você também deve tentar criar um perfil do seu código para acelerá-lo.
noɐɹƆzɐɹƆ 18/07/16

1

SmartArrow

Como Arrow, mas inteligente

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

Este bot já está ativo!
El'endia Starman 19/06/2016

1

Kamikaze-

Também não foi projetado para ser competitivo. Apenas por diversão. Hiperespacial quando perto do sol e persegue o jogador sem disparar balas. É divertido ver esse bot perseguir uma versão desarmada do Spy, mas você não pode ter mais de um userbot, infelizmente.

El'endia: já pensou em adicionar mais de um 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;
}

Apenas peguei o código do Kamikaze + e se livrou da parte de disparo de mísseis.


Provavelmente não adicionarei esse bot, pois já tínhamos outro bot do Kamikaze e prefiro não ter três bots do kamikaze. Além disso, este é mais trivial que os outros dois.
El'endia Starman 18/07/16

@ El'endiaStarman, então eu estou solicitando vários userbots - o segundo campo de código pode ser um expansível oculto padrão
noɥʇʎԀʎzɐɹƆ

0

MissilesPlusScore

Alguma idéia estranha que eu tive que leva o valor absoluto da diferença das pontuações e usa uma lista de movimentos aleatoriamente com base na maneira do jogo. Funciona bem contra bots com uma estratégia, mas falha contra tempestades de mísseis. Também o meu primeiro .

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 ESTÁ FRESCO !!!!!!!!!!!!!!!!

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

Baseado nas coordenadas, surpreendentemente eficaz:

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

Ambos os bots estão ativos.
El'endia Starman 27/12/2015

Você deve postar várias respostas.
noɥʇʎԀʎzɐɹƆ

Se você adicionar outro bot, faça o ping para que eu saiba. Seu terceiro bot agora está ativo.
El'endia Starman

0

SetCourseFor30Degrees

Não faço ideia por que o capitão é tão insistente em colocar o navio em um curso de 30 graus, mas ei, como um alferes humilde, quem é você para questionar? Pelo menos você recebeu permissão para evitar o sol! E você tem permissão para disparar os mísseis ... apenas não tem como apontá-los ...

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

Este bot já está ativo!
El'endia Starman

0

Seta

Simplesmente persiga seu inimigo, hiperespaça quando ele está em perigo e ocioso quando seu inimigo está 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;
}

Este bot já está ativo!
El'endia Starman 18/06/2016

@ El'endiaStarman Atualizei o bot
TuxCrafting

A atualização já está ativa! Não muito de um embora. : P
El'endia Starman

0

Kamikaze +

Não foi projetado para ser competitivo. Apenas por diversão. Tecnicamente, ele faz o oposto do Spy: persegue o jogador, hiperespaça quando está perto do sol, lança mísseis 70% do tempo. Eu só quero ver o KamikazePlus perseguindo Spy e Spy fugindo como um louco.

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

Basicamente, apenas pegou o código de Spy e virou "left" e "right".


Este bot já está ativo! E sim, é divertido assistir ao KamikazePlus perseguir o Spy. : P
El'endia Starman

@ El'endiaStarman Acho divertido assistir o KamikazePlus lutar sem balas e overideHyperspace = 0;; eles simplesmente continuam desaparecidos quando tentam ir um para o outro.
noɐɹƆzɐɹƆ 18/07/16
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.