キングオブザヒル-スペースウォー!


64

Spacewarを プレイしたことがあるなら、あなたはそれが楽しいゲームだったことを知っています。まだ知らない場合は、これを知ってください。これは、非常に最初で最も重要なコンピューターゲームの1つでした(現在もそうです)。そして、それはまだ楽しいです!私が育ったクローンはこれで、明らかに残念なことにWindowsのみです。だから私はそれを再作成しました!

KotHはここでホストされています:PPCG-Spacewar!キングオブザヒルゲームがどのように機能するかを把握するために、少なくとも1つの他のボットに対して人間としてプレイすることをお勧めします。

ゲーム

  • 1フレームは30ミリ秒です(したがって、約33フレーム/秒)。
  • フィールドは幅800ピクセル、高さ600ピクセルです。
  • フィールドはトロイダルです。つまり、フィールドの外側に移動する宇宙船とミサイルが反対側に再び現れます。
  • 赤と青の2つの宇宙船があります。
    • 赤はx = 50に配置され、ランダムなyは50(フィールドの高さ-50)ピクセルの間です。
    • 青はx =(フィールド幅-50)に配置され、ランダムなyは50(フィールド高さ-50)ピクセルです。
    • 両面x =(フィールド幅)/ 2。
  • 使用可能なコントロールは次のとおりです。
    • 左折-フレームごとに反時計回りに5度。
    • 右折-フレームごとに時計回りに5度。
    • 発射ミサイル-船の速度に加えて、フレームが10ピクセル余分に、船が指している方向に移動します。
    • 消防車-宇宙船が指している方向にフレームあたり0.30ピクセルで宇宙船を加速します。
    • ハイパースペースジャンプ-フィールド内のランダムな座標にテレポートし、25%の確率で爆発します。これらのランダムな座標は、太陽の上にある場合があります。
  • 船の最高速度は、エンジン出力のもとでフレームあたり15ピクセル、重力ブースト時のフレームあたり40ピクセルです。
    • フレームあたり15ピクセルよりも速く移動する場合、エンジンの推力は方向を変えるか、減速するだけです。
  • ミサイルについて:
    • ミサイルは直線で移動します。
    • ミサイルは、0.1秒に1回の割合で発射できます。
    • ミサイルの寿命は2.25秒です。
    • 船にはそれぞれ最大20個のミサイルがあります。
    • ミサイルは内部的に点粒子です。
  • あなたの船にとって非常に危険な太陽がまさに中心にあります。わずかな接触は致命的です。この太陽はミサイルも破壊します。
  • 太陽には重力があります。結果の加速度は5000 /(距離^ 2)ピクセル/フレーム^ 2で、距離はピクセル単位です。宇宙船とミサイルが影響を受けます。
  • どちらの船にも3つのストライクゾーンがあります。機首、左翼、右翼です。
    • 鼻に当たると即死します。
    • どちらかの翼にヒットすると、宇宙船の回転速度とエンジンの加速が半分に減少します。
    • 両方の翼が破壊された場合、宇宙船は操縦できず、ミサイルのみを発射できます。
  • 船同士が衝突する場合があります。
    • 鼻と鼻の衝突は、両方の船にとって致命的です。
    • 鼻翼の衝撃により、翼が破壊されます。
    • 翼と翼の衝突により、両方の翼が破壊されます。
  • 死んだ船は固く、1秒後に爆発するまで凍結します。
  • 少なくとも1隻の船が死亡した後、フィールドは3秒後にリセットされます。それまでは、太陽と残っているミサイルはまだ危険です。

元のゲームには致命的で破壊不可能な小惑星もありますが、それらは含めません。

ルール

  • ボットはJavaScriptで作成する必要があります。
  • ボットは、その決定を約10ミリ秒に制限する必要があります。ボットが原因で一貫した遅延に気付いた場合は、失格とし、修正できるようお知らせします。
  • ボットは次のものにアクセスできます。
    • フィールド幅とフィールド高さ
    • 太陽の位置と半径
    • 両方の船の位置、回転、速度、形状、ミサイルのストック、およびハイパースペース内のステータス
    • すべてのミサイルの位置と速度
  • プロンプトが表示されたら、ボットは文字列のリストを返します。
    • これらの文字列は、次のいずれかでなければなりません:turn leftturn rightfire enginefire missilehyperspace。その他の文字列は無視されます。
    • 重複がある場合は、最初のもののみが記録されます。
    • hyperspace 他のすべてよりも優先されます。
    • turn leftそしてturn right同時に効果がありません。
    • fire engine 船が機首のみを持っているか、死んでいる場合は効果がありません。
    • fire missile ミサイルがあまりにも最近発射された場合は効果がありません。
  • 通常からの変更では、ボットは他のボットの動作を悪用できます。メタゲームを奨励したいです。
    • ボット他のボットをエミュレートすることはできません。(つまり、心を読むことはありません。)
    • ボット、ゲームおよび物理コードで使用される変数を設定できません。(つまり、不正行為はありません。)

ボット実装の詳細

ボットをfilenameと共に自動的に含まれる独自のJavaScriptファイルに保存しますbot_<name>.js。そのため、これに干渉したり、JavaScriptの関数の名前付けに干渉したりするスペースや文字を入れないでください。それはあなたが以下の機能を定義する必要があるためだ。<name>_setup(team)<name>_getActions(gameInfo, botVars)。ページのさらに下には、ユーザーボットのテキストエリアがあり、編集してコードをテストできます。

<name>_setup(team)

この関数は、永続化する変数を定義するためのものです。またはのteamいずれ"red"かになります"blue"。この関数はオブジェクトを返す必要があります。次のように変数を定義します。

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

このvarsオブジェクトは他の関数に渡されます:

<name>_getActions(gameInfo, botVars)

botVarsはによって返されるオブジェクト<name>_setup(team)です。gameInfo以下の変数を含むオブジェクトです。

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

ボットはこれらに完全にアクセスできます。アイムかなり確信して、あなたが彼らに書き込み、元の変数に影響を与えることができないことを、とにかくそれをしません。回転に関する注意:船は+ y方向を下向きに指すので、船に合わせたいものはすべて90度オフセットする必要があります。また、正の回転は時計回りです。

この関数は、ボットのアクションを表す文字列のリストを返す必要があります。たとえば、["turn right","thrust"]。これに関する詳細は、「ルール」セクションにあります。

さらなる詳細

また、次のものを利用することもできます。

LineIntersection(L1, L2)

L1とL2は、2要素配列の2要素配列です。つまり、L1 := [[x1,y1],[x2,y2]]そしてL2 := [[u1,v1],[u2,v2]]。この関数は、2つの線の交差を計算し、これを返します[[x,y], [a,b]][x,y]は交点の座標であり、[a,b]各線に沿って交点がどれだけ離れているかを表す比率のペアです。以下のように、a = 0.25交点から道の四分の一であることを意味する[x1,y1][x2,y2]、同様にのためにb交差がない場合、空の配列が返されます。

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

これらは、船のポリゴンの座標です。現在の座標を簡単に取得するために、以下を使用することもできます...

getShipCoords(<color>)

getShipCoords("red")は、赤の船の頂点の現在の座標を返しgetShipCoords("blue")ます。同様に、青の船の座標も返します。これらの座標は次のようなリストにあります[[x1,y1],[x2,y2],[x3,y3],...]。ポリゴンは暗黙的に閉じられているため、最初と最後の座標ペアの間に線があります。

ゲーム/ウェブサイトで使用されている他の変数や機能にアクセスしたり、変更したりすることはできません。また、関数に同じ名前を付けないでください。これが問題になるとは思いませんが、ボットがゲームコードに違反する場合、それは1つの可能性です。例外のロギングまたはキャッチはありません。

勝ち

  • ボットのすべてのペアは、両方の方法で少なくとも10回プレイされるものとします。(つまり、合計20ゲーム以上です。)
  • 全体で最高の勝敗比を目指します。ボットが他の1つのボットに対して非常に優れているが、他の3つのボットに対して負けている場合、それは2つに対して勝ち、2つに対して負けている(一般的な経験則として)ほど良くはありません。
  • すべてのボットについて、比率(wins + 1)/(losses + 1)が計算され、次にこれらの比率の平均と標準偏差が計算されます。平均値が高いほど優先順位が高くなり、平均値が互いに1ユニット以内の場合、分散が低いほど優先順位が高くなります。
  • 採点は、今日から1週間以内、または新規提出なしの3日間後に開始されます。これは、ボットのペアリングを繰り返す必要がないためです。

とりわけ、楽しんでください!


リーダーボード(2016-01-08 05:15):

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

注:これは、より多くのゲームを実行するにつれて変更される可能性があります。さらに、ランク9から13の順序付けはわずらわしいので、スコアリング方法を調整して、ランク付け方法の直感をよりよく一致させることができます。

(平均と標準偏差は、三桁に四捨五入しHyperなければならないHYPERが、それはハイライトを台無し:P)


任意のスコア?....
ev3commander

キャッチされた例外をログに記録しますか?
TheNumberOne

1
LineIntersection交差しないセグメントを呼び出すと、空の配列が返されるように指定する必要があります。
LegionMammal978

1
やったと思う!
ev3commander

3
@CrazyPython:私は基本的にゲームをコピーしたことを考慮して最初の2つに異議を唱えますが、3つ目はまさに私が望んでいたものです。ありがとう!:D
El'endia Starman

回答:


12

ヘリオス

このボットは宇宙の中心であるか、少なくとも彼は自分だと考えています。彼が最初に行うことは、重大なエラーを修正し、座標系の中心に身を置くことです。その後、彼は自分の周りを回転させます。

彼は他の(偽の)太陽が好きではないので、彼はそれから離れようとします。彼はまた、他のボットが好きではないので、彼が良い射撃位置にいるなら、彼らを撃ちます。

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
これはこれまでの私のお気に入りのボットの1つだと思います。驚くほど良い!
エレンディアスターマン

@ El'endiaStarmanボットを更新しました。
Sleafar

アップデートが公開されました!
エレンディアスターマン

これはOrbitBotに対して非常にうまく機能します:)
TheNumberOne

1
@Soakuこのボットと他のほとんどのボットの主な違いは、このボットが撮影前に相手を狙うことだと思います。
Sleafar

9

SunAvoider

これはただ太陽から離れようとします。それは非常にうまく機能します...片方または両方の翼が破壊されるまで、それは通常それが落ちる前に時間の問題です。

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

太陽からマップの端に向かって全速力で飛行します!太陽に向かっているとわかると、射撃を開始しますが、自分自身を遠ざけて端に戻ります。また、太陽に当たる直前にハイパースペースに入ります。

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

このボットは現在公開中です!また、これは驚くほど簡単に生き残りました。おそらく、他のいくつかのミサイルのようにどこでもミサイルをスパムしない方法に関係しています。:P
エルエンディアスターマン

7

OrbitBot

現在、ターゲティングや衝突回避はありません。太陽を周回しようとします。

編集:影響が差し迫っているときにハイパースペースに入るようになりました。

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

ボットが追加されました。
コナーオブライエン

アップデートが公開されました!
エレンディアスターマン

5

右利き

名前はかなり説明的です。選択しturn right、0.5の確率でfire engine0.5の確率で、およびfire missile0.8の確率を有します。主にそれは本当に予測不可能だからです。

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

ランド

この課題にはランダムボットが必要でした。ゴルフのボーナスポイント?

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

クール!(ちなみに、私のボットは13-7を獲得していません。によって多く、私は一度9-1を失ったが、それはだ考慮たくさん合計ポイントの20ポイントを90秒で!)
ev3commander

@ BlockCoder1392それランダムボットです;)
コナーオブライエン

4

エンジニア

危険なときにハイパースペースを使用するのが好きです。真のパワーを確認するには、ブラウザのコンソールを開いてを入力しoverideHyperspace = 0;ます。セミコロンを忘れると、クリスマスにASIが届きます。

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

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

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

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

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

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

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

    if(Math.random()<.7)actions.push("fire engine");
    return actions;
}

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

あらゆる方向に乱暴に発射します。あまり効果的ではありません!


このボットは現在公開中です!
エレンディアスターマン

3

神風

それほど競争力はありませんが、楽しいと思いました!射撃中に相手に向かってまっすぐ飛んでください。

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

ボットが追加されました!
コナーオブライエン

OpponentDodgerに対するひどい... PanicAttackで結ば...
noɥʇʎԀʎzɐɹƆ

2

UhhIDKWhatToCallThisBot

ただランダムなもの。

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

謎めいたゴルフィネスはどうしたの?
noɥʇʎԀʎzɐɹƆ

2

相手ドジャー

相手から離れろ!

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

いくつかのコードを提供してくれたuser81655に感謝します!


このボットは現在公開中です!
エレンディアスターマン

2

スパイ

物語

このボットのプロトタイプは、クレイジーモードとノーマルモードの2つのモードを持つボットでした。クレイジーモードのときは、一定数のティックの間そこにとどまりました。クレイジーモードに入る確率は一定でした。また、太陽に近いときにハイパースペースになりました。クレイジーモードでは、他のボットを狙い、絶えず発射されました。通常モードでは、発射せずに他のボットから飛び去りました。

そのプロトタイプを微調整して、敵が十分近くにいる場合にのみクレイジーモードになるようにしました。それから私はクレイジーなアイデアを持っていました:クレイジーモードにとどまった場合はどうなりますか?いくつかの実験の後(通常モードのときにボットをランダムに発射するように追加しました)、新しいボットがHelios以外のすべてのボットを倒すことがわかりました。このは、このプロセスの最後のクリーンアップ前の私のコードです。

ボット全体をKotHテキストエリアまたはJS beautifierで作成しました。(クリーンアップするときは簡単にAtomエディターを使用しましたが、コードは2行ほどです)

ボット

このボットには、他のボットから借用した多くのコードが含まれています。他のボットに実行するのではなく、カミカゼからのコードを反転して他のボットから逃げ出し、太陽に近いときにハイパースペースのためにEdgeCaseからコードを取得します。

それは、大敵であるヘリオスです。それは奇妙なものであり、マティーニとの長いチャットです。

他のボットから逃げ出し、70%の確率でミサイルとハイパースペースを発射します。それと同じくらい簡単。うん。

編集:ボットを新しいコードでテストしましたが、他のすべてのボットでは失敗します。修正に取り組んでいます。これは私の新しいボット専用です。

コード

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

その他

注:コードのクリーンアップ後にボットをテストしなかったため、コードをクリーンアップするときに何かを壊した可能性があります。

また、他のすべてのボットよりもはるかに優れています-Helios (編集)、SetCourseFor30Degrees、およびOrbitBot を除く他のすべてのボットを実際に倒します!SunAvoiderと連携します。

サイドノート:私はjavascriptが恐ろしいのですが、理由はわかりません。


@ El'endiaStarmanは、ボットを一時停止状態にしてください。ボットを修正する必要があります-クリーンアップされたバージョンは、クリーンでないバージョンよりもはるかに悪いです。
noɥʇʎԀʎzɐɹƆ

よし、いつ修正されたか教えてください。
エレンディアスターマン

@ El'endiaStarmanあることをして、それがまた機能した。デバッグ、知ってます!(まだ行われていない)
noɥʇʎԀʎzɐɹƆ

@ El'endiaStarman ...これで完了です!
noɥʇʎԀʎzɐɹƆ

このボットは現在公開中です!
エレンディアスターマン

1

AttackAndComeBack

渦巻くのではなく、上部から入り下部から出て(上部に戻る)、非常に迅速に発火します。一般的に太陽を避けます。

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

このボットは現在公開中です!
エレンディアスターマン

1

最高速で前へ

常にエンジンとミサイルの両方を発射します。時々、太陽に当たる前に驚くほど長く続きます。

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

私は...と思ったほど悪くない
noɥʇʎԀʎzɐɹƆ

このボットは現在公開中です!
エレンディアスターマン

1

パニック発作

発砲する確率は50%、左折する確率は80%です。しかし、左に曲がらない場合は、右に曲がります。ミサイルを使い果たした後、時間が経てばやがて太陽のために停止します。

編集:敵がミサイルで殺される可能性があるため、敵が生きているときに発砲しないようにいくつかのロジックを追加しました。

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

このボットは現在公開中です!
エレンディアスターマン

@ El'endiaStarmanは再びそれを更新してください
noɥʇʎԀʎzɐɹƆ

アップデートが公開されました!
エレンディアスターマン

1

ダンギットボビー

ボビー・ヒルは他の人が彼についてどう考えているか気にしません。彼はフィールドをぐるぐると回って、「ハスキー」コブラのように打つ前に相手が蒸気を使い果たすのを辛抱強く待ちます。

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

    }
}

「それは私の財布です!あなたを知りません!」


このボットは現在公開中です!
エレンディアスターマン

1

スナイパー

彼の敵を狙撃する狙撃ボットを作成するために、私は少しの間予測で遊んでいます。私のjavascriptは大きすぎて答えに収まらないので、ここにリンク bot_Sniperがあります。


最後にこのボットのテストに乗り出しましたが、残念なことにゲームの速度が本当に遅くなります。途切れがちなので、どうにかしてコードを高速化する必要があります。
エレンディアスターマン

次回は、コード用に設計された[GitHub Gists](gist.github.com)のようなサービスに投稿する必要があります。
noɥʇʎԀʎzɐɹƆ

コードを最適化してください。どのくらいの長さかを考えると、本当に良いボットだと思います。いくつかの変数または関数をインリングしてみてください。
noɥʇʎԀʎzɐɹƆ

また、いくつかの重複コードがあります- スタック交換で、ボットをコードレビューに投稿することで得られるものがたくさんあると思います。
noɥʇʎԀʎzɐɹƆ

また、Actions()に入れた関数を外部スコープで定義することもできます。そのため、インタプリタはActions()を実行するたびに再解析する必要がありません。また、コードをプロファイリングして高速化する必要があります。
noɥʇʎԀʎzɐɹƆ

1

SmartArrow

Arrowに似ていますが、スマートです

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

このボットは現在公開中です!
エレンディアスターマン

1

神風-

また、競争力があるように設計されていません。ただ楽しみのために。太陽に近づくとハイパースペースを作り、弾丸を発射することなくプレイヤーを追いかけます。このボットが非武装バージョンのSpyを追いかけるのを見るのは楽しいですが、残念ながら、複数のユーザーボットを持つことはできません。

El'endia:これまでに複数のユーザーボットを追加することを検討しました;)

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

Kamikaze +のコードを取り、ミサイル発射部を取り除きました。


もう1つの神風ボットがすでにあるので、このボットはおそらく追加しません。3 つの神風ボットはもうありません。また、これは他の2つよりも簡単です。
エレンディアスターマン

@ El'endiaStarmanその後、複数のユーザーボットをリクエストしています-2番目のコードフィールドはデフォルトの非表示の拡張可能にすることができます
-no –zɐɹƆ

0

ミサイルズプラススコア

私が思いついたいくつかの奇妙なアイデアは、スコアの差の絶対値を取り、ゲームの方法に基づいてランダムに動きのリストを使用します。戦略のあるボットに対してはうまく機能しますが、ミサイルの嵐に対しては失敗します。また、私の最初の

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

ハイパー

HYPERSPACE IS COOL !!!!!!!!!!!!!!!!

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

CoordinateInfluence

座標に基づいて、驚くほど効果的:

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

これらのボットは両方ともライブです。
エレンディアスターマン

代わりに複数の回答を投稿する必要があります。
noɥʇʎԀʎzɐɹƆ

別のボットを追加する場合は、pingを実行してください。3番目のボットが公開されました。
エレンディアスターマン

0

SetCourseFor30Degrees

船長がなぜ30度の方向に船を設定することに執着しているのかわかりませんが、少々少なめとして、誰に質問しますか?少なくともあなたは太陽を避ける許可を与えられました!そして、あなたはミサイルを発射することが許可されています...それらを狙うことは許可されていません...

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

このボットは現在公開中です!
エレンディアスターマン

0

矢印

彼の敵を追いかけ、彼が危険にさらされているときはハイパースペースを追いかけ、彼の敵が死んでいるときは休む。

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

このボットは現在公開中です!
エレンディアスターマン

@ El'endiaStarmanボットを更新しました
-TuxCrafting

更新が公開されました!しかし、それほど多くはありません。:P
エルエンディアスターマン

0

神風+

競争力があるように設計されていません。ただ楽しみのために。技術的には、スパイとは反対のことです。プレイヤーを追いかけ、太陽に近づいたらハイパースペースを、70%の確率でミサイルを発射します。神風プラスがスパイを追いかけ、スパイが狂人のように逃げるのを見たいだけです。

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

基本的には、Spyのコードを取得し、「左」と「右」を反転させただけです。


このボットは現在公開中です!そして、はい、KamikazePlusチェイススパイを見るのは楽しいです。:P
エルエンディアスターマン

@ El'endiaStarmanカミカゼプラスが弾丸なしで自分自身と戦うのを見るのは楽しいと思いますoverideHyperspace = 0;; 彼らはお互いに行こうとすると、ただ行方不明になります。
noɥʇʎԀʎzɐɹƆ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.