ロケットボットKOTH


11

ロケットボット

年は3024です。人々は戦争で危険にさらすにはリソースが不足しているため、戦闘はロボットに移行しました。あなたの仕事は、他に類を見ないボットを構築することです。誰のロケットが敵に破壊を降らせ、入ってくるすべての脅威を撃ち落とします。

ゲームプレイ

ボット

ゲームプレイは10x15グリッドで行われます。ボットは下端から外れており、グリッドのスポット6、7、8に3つのスロットがあります。対戦相手はグリッドの一番上にあり、3つのスロットがあなたの真向かいにあります。

ロケット

これらのスロットのいずれかから、スロットが破壊されていないと仮定してロケットを発射できます。ロケットは、作成時に与えられる方向のリストで構成され、一度発射されると、これらの方向は変更できません。毎ターン、ロケットはリストの一番上を消費し、その方向に移動します。ロケットは同時に移動します。2つのロケットが同じタイルで終わる場合、両方とも爆発します。ロケットがコマンドを使い果たすと、爆発します。ロケットが燃料を使い果たすと、100回移動した後に爆発します。ロケットが爆発すると、5ターンの間そのタイルにとどまり、そこに移動する他のロケットも爆発します。

注: 同時移動のため、2つのロケットが同じタイルで両方のターンを終了しない限り、2つのロケットは爆発することなく互いに通過できます。

ゴール

各試合の目標は、対戦相手のスロットを破壊することです。ロケットは、お持ちのどのライブスロットからでも発射でき、発射前に指定されたパスが与えられます。1ターンごとにロケットを発射します。つまり、ロケットが2回移動してから、別のロケットを発射できます。決闘は200ターン、または1つのボットスロットがすべて破壊されるまで続きます。

得点

試合の終わりに、あなたはあなたが持っている各ライブスロットに対して1ポイントを獲得し、あなたが破壊した各対戦相手スロットに対して1ポイントを獲得します。つまり、ゼロサムゲームであり、各試合で6ポイントが与えられます。

ラウンドロビンが実行され、各ボットが1つずつ互いにボットに向かいます。ボットがRNGを使用する場合、各対戦は1000デュエルになります。

実装

コンテストのコードは、https//github.com/Cain93/RocketBotsにあります。

提出ごとにBotクラスを拡張する必要があります。fireRocketメソッドをオーバーライドする必要があります。このメソッドはRocket[][]、ゲームボードを表すRocketsのグリッド配列を受け取ります。あなたは、常にスポットのスロットに、グリッドの下部に位置しています[-1][6][-1][7][-1][8]。グリッドでは、空いているスポットはで表されnullます。タイル内にロケットが存在する場合、disフィールドにアクセスすることでロケットが誰であるかを特定できます。「^」はロケット、「v」は対戦相手です。

ロケットの指示を与える整数のLinkedListを返す必要があります。上に移動するには、0を使用します。上下に移動するには、1を使用し、右に2を使用します。ロケットは、整数を押した順に移動します。たとえば、次のコードはロケットを数回転上方向に移動させ、数回転ジグザグにしてから爆発させます。

LinkedList<Integer> moves = new LinkedList<Integer>();

moves.push(0);
moves.push(0);
moves.push(0);
moves.push(1);
moves.push(7);
moves.push(1);
moves.push(7);

ロケットを発射するスロットを変更するには、curSlotフィールドを変更します。0は一番左のスロット、2は一番右のスロットです。スロットが破壊されているかどうかを確認するには、を使用しますgetSlot(int slotNumber)

ロケットがスロットのターンを終了すると、そのスロットは破壊されます。ロケットを手動で爆発させる必要はありません。

注:ロケットは発射されたスロットの位置に出現しますが、衝突が評価される前に一度移動します。したがって、スロット0からロケットを発射し、最初の動きが正しい場合(2)、自分の中央のスロットを破壊します。ただし、上下(1)は安全な動きです。

ボットに名前を付ける場合は、name()メソッドをオーバーライドします。

ボットは決闘ごとに再構築されるため、静的変数はリセットされます。

幸運を!

あなたのロケットが真に飛んで、あなたの敵がくすぶっている金属片に過ぎないように。

ヒント:

意図的にロケットを爆発させて爆発を起こすことは、相手のロケットを撃ち落とそうとするよりも簡単に防御する方法です。

ボットの例

package bots;

import java.util.LinkedList;

import mechanics.*;




public class SimpleBot extends Bot {

    public String name(){
        return "Simple";
    }

    public LinkedList<Integer> fireRocket(Rocket[][] g){

        LinkedList<Integer> l = new LinkedList<Integer>();
        for(int i = 0; i < 12; i++){
            l.push(0);
        }
        return l;
    }

}

スコア

6-24のスコア

Simple: 900
Zigzagoon: 3654
Wall-E: 3606
Tortoise: 2248
3 Shot: 2334
HatTrickBot: 4287
Sniper: 2973
SideShooter: 2491
Terminator: 4835
StraightShot: 3378
Defender: 4570
MoreDakka: 4324

順序は問題ではないので、任意のボットは、RNGのを使用する場合、固定して、その後、私は対戦あたり1000倍にランニングを増加します
カイン

1
対戦相手のスロットが破壊されているかどうかを確認する方法はありますか?getSlot(int)はスロット専用ですよね?
かてんきょう

1
@Cain破壊されたスロットにロケットを発射できないようにするのは面白いかもしれません:3
かてんきょう

1
@Manuそれはバグではありません、あなたはあなたの側からボードを見ているので、左のスロットは相対的です
かてんきょう

1
申し訳ありませんが、そのバグはすでに修正済みです。プッシュするのを忘れていました。
カイン

回答:


3

ディフェンダー

ディフェンダーは新しいタイプのディフェンスを使用します:ロケットスロットの前をパトロールしています。これは、ロケットが5回転ではなく100回転(爆発のような)生きるため、大きな利点があります。

package bots;

import java.util.LinkedList;
import mechanics.*;

public class Defender extends Bot {
    int turn = 0;

    @Override
    public String name() {
        return "Defender";
    }

    @Override
    public LinkedList<Integer> fireRocket(Rocket[][] grid) {
        LinkedList<Integer> command = new LinkedList<Integer>();
        for (int i = 0; i < 3; i++) {
            if ((grid[0][6+i] == null || grid[0][6+i].getDis().equals("v")) && (grid[1][6+i] == null || grid[1][6+i].getDis().equals("v")) && getSlot(i)) {
                curSlot = i;
                command.push(0);
                for (int j = 0; j < 50; j++) {
                    command.push(0);
                    command.push(4);
                }
                break;
            }
        }

        if (command.isEmpty()) {
            if ((grid[0][9] == null || grid[0][9].getDis().equals("v")) && (grid[0][10] == null || grid[0][10].getDis().equals("v")) && (grid[1][10] == null || grid[1][10].getDis().equals("v")) && getSlot(2)) {
                curSlot = 2;
                command.push(1);
                command.push(1);
                command.push(4);
                for (int i = 0; i < 50; i++) {
                    command.push(6);
                    command.push(2);
                }
            } else if ((grid[0][5] == null || grid[0][5].getDis().equals("v")) && (grid[0][4] == null || grid[0][4].getDis().equals("v")) && (grid[1][4] == null || grid[1][4].getDis().equals("v")) && getSlot(0)) {
                curSlot = 0;
                command.push(7);
                command.push(7);
                command.push(4);
                for (int i = 0; i < 50; i++) {
                    command.push(2);
                    command.push(6);
                }
            }

        }

        if (command.isEmpty()) {
            if (turn % 2 == 0 && getSlot(0)){
                curSlot = 0;
                command.push(7);
                command.push(7);
                for (int i = 0; i < 7; i++) {
                    command.push(0);
                }
                command.push(2);
                for (int i = 0; i < 2; i++) {
                    if (Math.random() < 0.2) command.push(2);
                }
                command.push(1);
            } else {
                curSlot = 2;
                command.push(1);
                command.push(1);
                for (int i = 0; i < 7; i++) {
                    command.push(0);
                }
                command.push(6);
                for (int i = 0; i < 2; i++) {
                    if (Math.random() < 0.5) command.push(6);
                }
                command.push(7);
            }
        }

        turn++;
        return command;
    }
}

うわ+1。素晴らしいボット。しかし、あなたが言うように、ボットが反対側にあるときはうまくプレイできません。
-Spikatrix

1
かなり完璧なプレー、お祝いの言葉
カイン

6

ジグザグーン

外側のスロットは(わずかに)広くなり、前方に向かって敵のスロットに向かって戻ります。中央のスロットは、中央にジグザグパターンを撃ちます。

1ラウンド(3ターン)ごとに、防御モードになり、自分のスロットの近くでロケットが爆発します。攻撃モードのロケットはそれらの周りを回ります。あまり派手なものはなく、コンテストを立ち上げるための何かです。

package bots;import java.util.*;import mechanics.*;

public class Zigzagoon extends Bot{
    String[] evenMoves = {"7000000001","0170710170","1000000007"};
    String[] oddMoves = {"0","00","0"};
    boolean even = true;
    public String name(){return "Zigzagoon";}

    public LinkedList<Integer> fireRocket(Rocket[][] g){
        curSlot = (curSlot+1)%3;
        if(curSlot<1)even=!even;
        String[] moves = even?evenMoves:oddMoves;
        LinkedList<Integer> command = new LinkedList<Integer>();
        for(int i=0;i<moves[curSlot].length();i++)
            command.push(moves[curSlot].charAt(i)-'0');
        return command;
    }
}

修正された、ほとんどの違いは、trueまたはfalseとして開始されたかどうかに起因していました。ボットは各試合の前に再構築されるようになりました。
カイン

ああ、それは理にかなっています。変数がリセットされないことさえ考えませんでした。ありがとう:)
Geobits

5

ターミネーター

ターミネーターを紹介できて光栄です!!!

各ロケットは中央から遠く左/右に移動し、敵のスロットに戻ります。2ターンごとに、防衛ロケットがまっすぐに発射され、スロットの近くで爆​​発して保護されます。

package bots;

import java.util.LinkedList;
import mechanics.Bot;
import mechanics.Rocket;

public class Terminator extends Bot {

    int n = 0;
    String[] moves = {"000", "0111107777", "00", "0077700111", "00", "0777701111"};

    public String name() {
        return "Terminator";
    }

    @Override
    public LinkedList<Integer> fireRocket(Rocket[][] g) {
        curSlot = (n+1) % 3;

        LinkedList<Integer> commands = loadCommands(moves[n % moves.length]);
        n++;

        return commands;
    }

    protected LinkedList<Integer> loadCommands(String commands) {
        LinkedList<Integer> linkedList = new LinkedList<Integer>();

        for (int i = 0; i < commands.length(); i++) {
            linkedList.push(commands.charAt(i) - 48);
        }

        return linkedList;
    }

}

3

HatTrickBot

私はCodeBot 3用のDoubleTapBotを持っていました。彼は1ターンに2回ヒットしました。ここにHatTrickBotがあります。

ロケットがどこに落ちるかわかっていれば、ロケットの衝突を防ぐことは常に可能です。しかし、3ロケット攻撃からスロットを保護できるボットは多くないと思います。

ちなみに、はい、繰り返し切り替えてこのようなelseifを見るのは恐ろしいことです。スロットのステータスとturnConterの組み合わせごとに一意の値を使用して切り替えるためのvarを作成できました。しかし、読むのは難しいでしょう(コメントの値の意味を維持する必要があります...退屈!):)

package bots;
import java.util.LinkedList;
import mechanics.*;
/*
 * HatTrickBot always tries to destroy all the enemy slots at once
 * In order to achieve this, each slot needs extrem concentration and coordination
 * It explain why they need some turns to re-synchronized the rockets after one of them dies.
 */
public class HatTrickBot extends Bot
{
    // Default moves are at [0]
    // moves at [1] are used when there's only 2 slots remaining
    // moves  [2-4] are here for when there's only 1 slot remaining
    // it panicks, and can't establish how to fire to do a hat trick.
    // So he will just spamm every ennemy position, one at a time
    String[] rightSlot = {  "770002000020",
                            "0000000001",
                            "0000000000",
                            "0000000001",
                            "0000000011"};
    String[] midSlot   = {  "0000000000",
                            "11000060000",
                            "0000000000",
                            "0000000010",
                            "0000000700"};
    String[] leftSlot  = {  "11000060007",
                            "777702000020",
                            "0000000000",
                            "0000007000",
                            "0000077000"};
    int turnCounter=-1;
    public String name(){return "HatTrickBot";}
    public LinkedList<Integer> fireRocket(Rocket[][] g)
    {
        turnCounter=(turnCounter+1)%3;
        String[][] moves = {rightSlot,midSlot,leftSlot};
        LinkedList<Integer> ll = new LinkedList<Integer>();
        boolean slotL=getSlot(0),slotM=getSlot(1),slotR=getSlot(2);
        int movePoint=0;
        if(slotL&&slotM&&slotR)
        {
            switch(turnCounter)
            {
            case 0: curSlot=0;
                break;
            case 1: curSlot=2;
                break;
            case 2: curSlot=1;
                break;
                default:break;
            }
            movePoint=0;

        }
        else if(!slotM&&slotL&&slotR)
        {
            switch(turnCounter)
            {
            case 0: curSlot=0;
                    movePoint=0;
                break;
            case 1: curSlot=2;
                    movePoint=0;
                break;
            case 2: curSlot=0;
                    movePoint=1;
                break;
                default:break;
            }
        }
        else if(!slotL&&slotM&&slotR)
        {
            switch(turnCounter)
            {
            case 0: curSlot=0;
                    movePoint=0;
                break;
            case 1: curSlot=1;
                    movePoint=1;
                break;
            case 2: curSlot=0;
                    movePoint=1;
                break;
                default:break;
            }
        }
        else if(!slotR&&slotM&&slotL)
        {

            switch(turnCounter)
            {
            case 0: curSlot=2;
                    movePoint=1;
                break;
            case 1: curSlot=1;
                    movePoint=1;
                break;
            case 2: curSlot=1;
                    movePoint=0;
                break;
                default:break;
            }
        }
        else
        {
            if(slotR)curSlot=0;
            if(slotM)curSlot=1;
            if(slotL)curSlot=2;
            movePoint = 2+turnCounter;
        }
        for(int i=0;i<moves[curSlot][movePoint].length();i++)
            ll.push(Integer.parseInt(moves[curSlot][movePoint].charAt(i)+""));
        return ll;
    }
}

ロケット弾は1ターンおきに発射するだけなので、これは完全なハットトリックヒットにはなりません。それでも非常に効果的
カイン

@Cain Ho、2ターンごとになるのは悲しいです:/。とにかく、最初のラウンドの結果が表示され、それを改善できると思う場合は、実際のHatTrickを実行するように修正します:)
Katenkyo

fireRocket()が呼び出されるたびにロケットが2回移動します。そのため、現時点では、それらはすべて1回転ずつ互いにオフセットされています。コントローラでテストファイルを使用して、一致の視覚的表現を確認できます。
カイン

@Cain私はこれらのボットを書いたときに仕事をしていたので、仕様のみに基づいてそれらを作成しました:)
帰天峡

うわー、テストなしでそれを書いたことに感心しました、おめでとうございます。より明確にするために仕様を更新しました
カイン

2

カメ

すべての拠点を保護する場合、3つのポイントがあります。グリッドがうまくできていれば、基地は5か所からしか攻撃できません。ロケットはフィールドで5ターン続きます...

このボットは、目標を達成するためにこれらすべてを使用します。ポケット内の少なくとも50%のポイントで生き残ります。3発のロケットを発射し、それ自体を覆います

package bots;

import java.util.LinkedList;

public class Tortoise extends Bot
{
    int turnCounter=-1;
    boolean attacked=false;
    int[] moves={7,0,0,0,1};
    public String name(){return "Tortoise";}
    public LinkedList<Integer> fireRocket(Rocket[][] g)
    {
         LinkedList<Integer> rocket = new LinkedList<Integer>();
         turnCounter++;
         if(!attacked)
         {
             curSlot=turnCounter;
             for(int i=0;i<11;i++)
                 rocket.push(0);
             if(turnCounter==2)
                 attacked=true;
             return rocket;
         }
         turnCounter%=5;
         switch(turnCounter)
         {
         case 0:
         case 1:curSlot=0;break;
         case 2:curSlot=1;break;
         case 3:
         case 4:curSlot=2;break;
            default:break;
         }
         rocket.push(moves[turnCounter]);
         return rocket;
    }
}

ロケットは1ターンおきに発砲するだけなので、実際には2半壁しか維持できません
Cain

@カインああ、だから私は本当の避難所を持つようにそれを変更します:)
かてんきょう

2

SideShooter

最初の(右端の)タレットを介して、2つの異なる方法のいずれかで最初に撃ちます。次に、2つの異なる方法のいずれかで最後の(左端の)タレットを介して撃ちます。次に、各砲塔の前でロケットを爆発させて、2番目(中央)の砲塔で「壁」を作ります。このプロセスが繰り返されます。

ゲームが30ターン以上続くと、SideShooterは退屈して少しずつ変化します。2番目の(中央の)タレットで「壁」を作る代わりに、まっすぐに撃ちます。残りの砲塔は同じように動作します。

import java.util.LinkedList;

public class SideShooter extends Bot {

    int[] launcher = new int[]{1, 3, 2, 2, 2};
    String[] right = {"1100000077", "100000007"};
    String[] left  = {"7700000011", "700000001"}; 
    int position = -1;
    int turns = 0;

    public String name(){
        return "SideShooter";
    }

    public LinkedList<Integer> fireRocket(Rocket[][] g){
      LinkedList<Integer> directions = new LinkedList<Integer>();

      if(getSlot(0) || getSlot(1) || getSlot(2))      
          do{
              position = (position + 1) % 5;
              curSlot = launcher[position] - 1;
          }while(!getSlot(curSlot));

      if(position == 0)
      {
          String shoot = left[((int) (Math.random() * left.length))];
          for(int i=0; i < shoot.length(); i++)
              directions.push(shoot.charAt(i)-'0');
      }else if(position == 1)
      {
          String shoot = right[((int) (Math.random() * right.length))];
          for(int i=0; i < shoot.length(); i++)
              directions.push(shoot.charAt(i)-'0');
      }else
      {
          if(turns < 30)
          {
            if(position == 2 )
                directions.push(0);
            else if(position == 3)
                directions.push(1);
            else if(position == 4)
                directions.push(7);
          }else
              for(int i=0; i < 10; i++)
                  directions.push(0); 
      }
      turns ++;
      return directions;
    }

}

do...while声明は...無限ループを行う
guy777

@ guy777、そうではありません。壊れていないタレットが見つかるまでループします。
Spikatrix

OK !すべてのボット、SideShooter、その他のボットでコードを起動する2回目(どちらかわからない)はゲームを終了できません!!!
guy777

一部のゲームは完成できません。コントローラーには回転制限が必要です。
-guy777

1
@CoolGuy彼の編集を承認するために投票しました。自分で確認/テストしてください。
mbomb007

2

スナイパー

スナイパーはまずその両側をブロックしてから、まっすぐに撃ち始めます。

import java.util.LinkedList;

public class Sniper extends Bot {

    int[] launcher = new int[]{1, 3, 1, 2, 3};
    String[] moves = {"7", "1", "0000000000", "0000000000", "0000000000"}; 
    int position = -1, move = 0;

    public String name(){
        return "Sniper";
    }

    public LinkedList<Integer> fireRocket(Rocket[][] g){
        LinkedList<Integer> directions = new LinkedList<Integer>();

        if(getSlot(0) || getSlot(1) || getSlot(2))
        do{
            position = (position + 1) % launcher.length;
            curSlot = launcher[position] - 1;
        }while(!getSlot(curSlot));

        for(int i=0; i < moves[move].length(); i++)
            directions.push(moves[move].charAt(i)-'0');

        move = (move + 1) % moves.length;

        return directions;
    }

}

こちらも同じ問題であるSideShooterに関するコメントをご覧ください。
カイン

2

スリーショット

奇妙なショットが飛んできました。真の防御はありませんが、パターンはミサイルのこの奇妙なpastを通り抜けるのが難しいようなものです。(または、それがアイデアです。おそらく動作しません。)

package bots;import java.util.*;import mechanics.*;

public class ThreeShot extends Bot{
    public String name(){state = 0;return "3 Shot";}
    private int state;

    public LinkedList<Integer> fireRocket(Rocket[][] g){
        LinkedList<Integer> command = new LinkedList<Integer>();
        if(state < 2){
           state++;
           return fireLeft();
        }
        if(state < 4){
           state++;
           return fireCenter();
        }
        state=(state+1)%6;
        return fireRight();
    }
    LinkedList<Integer> fireCenter(){
        LinkedList<Integer> command = new LinkedList<Integer>();
        curSlot = 1;
        while(command.size()<90){
            command.push(1);
            command.push(7);
            command.push(6);
            command.push(1);
        }
        return command;
    }
    LinkedList<Integer> fireRight(){
        LinkedList<Integer> command = new LinkedList<Integer>();
        curSlot = 2;
        command.push(1);
        for(int i=0;i<8;i++){
            command.push(0);
        }
        command.push(7);
        return command;
    }
    LinkedList<Integer> fireLeft(){
        LinkedList<Integer> command = new LinkedList<Integer>();
        curSlot = 0;
        command.push(7);
        for(int i=0;i<8;i++){
            command.push(6);
            command.push(1);
        }
        command.push(1);
        return command;
    }
}

注意


2

ダッカ

ダッカは、停止することなく5方向に射撃します(タレットが他のミサイルによって破壊されるまで)。

import java.util.LinkedList;

public class MoreDakka extends Bot
{
    String[] moves={"70000000001", "0000000000", "0000000000", "0000000000", "1000000007"};
    int[] launcher = new int[]{0, 0, 1, 2, 2};
    int position = -1;

    public String name(){
        return "MoreDakka";
    }

    public LinkedList<Integer> fireRocket(Rocket[][] g)
    {
         LinkedList<Integer> directions = new LinkedList<Integer>();

         if(getSlot(0) || getSlot(1) || getSlot(2))
            do{
                position = (position + 1) % launcher.length;
                curSlot = launcher[position];
            }while(!getSlot(curSlot));

         for(int i=0; i < moves[position].length(); i++)
            directions.push(moves[position].charAt(i)-'0');

         return directions;
    }
}

1

ストレートショット

ちょうどそれらを発射します。

package bots;import java.util.*;import mechanics.*;

public class StraightShot extends Bot{
    public String name(){return "StraightShot";}

    public LinkedList<Integer> fireRocket(Rocket[][] g){
        LinkedList<Integer> command = new LinkedList<Integer>();
        curSlot = (curSlot+1)%3;
        for(int i=0;i<100;i++)
            command.push(0);
        return command;
    }
}

1
気付いていない場合、これは基本的にコントローラに含まれているボットの例の1つであるWaveBotと同じです。
ジオビット

@Geobitsボットの例が存在することは知りませんでした。
メガトム

サンプルボットを見やすい場所に置かないことの悪さ。私はちょうどこのエントリスタンドWaveBotを削除してみましょうつもり
カイン

1

ここに私自身のエントリがあります

WallE

オフセットロケットを発射し、エッジとセンターに壁を構築します。100ターン後、中央のスロットをターゲットに開始します。

package bots;

import java.util.LinkedList;
import java.util.Random;

import mechanics.*;


public class WallE extends Bot {

    int turn = 2;

    public String name(){
        return "Wall-E";
    }

    public LinkedList<Integer> fireRocket(Rocket[][] g){
        turn++;
        LinkedList<Integer> moves = new LinkedList<Integer>();
        curSlot = 1;
        switch(turn%4){
        case 0: 
            //Check the right wall
            if(getSlot(2)){
                curSlot = 2;
                moves.push(1);
                return moves;
            }
        case 1:
            //Check the left wall
            if(getSlot(0)){
                curSlot = 0;
                moves.push(7);
                return moves;
            }
        case 2:
            //Check the center wall
            if(getSlot(1)){
                curSlot = 1;
                moves.push(0);
                return moves;
            }
            break;
        default:
            //Fire a sneaky rocket
            Random rand = new Random();
            int direction = rand.nextInt(2);
            int back = 0;
            if(direction == 0 && getSlot(2)){ direction = 1; back = 7; curSlot = 2;}
            else{ direction = 7; back = 1; curSlot = 0; }
            moves.push(0);
            moves.push(direction);
            moves.push(direction);
            for(int i = 0; i < 5; i++){
                moves.push(0);
            }

            //Go for the center after turn 100
            if(turn > 104){
                moves.pop();
                moves.push(back);
            }
            moves.push(back);
            moves.push(back);


        }

        return moves;










    }

}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.