Splix.io-キングオブザランド


37

あなたは、その支配下にある土地を増やしたいと思う進取の気性のある人です。これは非常に簡単です-現在の土地の外に出て、あなたの土地にループバックすると、そのループ内のすべてがあなたのものになります。しかし、キャッチがあります。他のドットが何らかの方法でループを見つけて交差すると、死にます。

まだ試していない場合は、Splix.ioにアクセスしてゲームを試してください。矢印キーを使用して、動きを制御します。

GIF

ここに画像の説明を入力してください

クレジット:http : //splix.io/

仕様

すべてのプレイヤーは、200x200ボード上のランダムな位置から始まります。(私はこれを変更する権利を留保します:)。可能な限り多くのポイントを集めるために、一定量の動きがあります。ポイントは以下によって集計されます:

  • 殺したプレイヤーの数は300回
  • ラウンド終了時に所有する土地の量

これは、他の人があなたの土地を盗むことができるというポイントをもたらします。彼らがあなたの土地の一部と交差するループを開始した場合、彼らはそれを主張することができます。ラウンド中に死亡した場合、そのラウンドのすべてのポイントを失います。

各ラウンドには、ランダムに選択されたプレーヤーのグループ(最大5人のユニークなプレーヤー)がいます(変更される場合があります)。すべてのプレイヤーが同数のラウンドに参加します。ボットの最終スコアは、ゲームごとの平均スコアによって決まります。各ゲームは2000ターンで構成されています(変更される場合もあります)。すべてのボットは同時に動きます。

死亡例

頭突き

頭尻

両方のプレイヤーが頭を突き合わせて死ぬ。これは、両方のプレーヤーが自分のスペースの端にいる場合でも、まだ当てはまります。

頭尻

ただし、自分の土地にプレイヤーが1人しかいない場合、他のプレイヤーは死亡します。

ここに画像の説明を入力してください

ラインクロス

ここに画像の説明を入力してください

この場合、紫色のプレイヤーのみが死亡します。

独自のラインを越えることはできません。

ここに画像の説明を入力してください

ボードを終了する

プレーヤーがボードを離れる

プレイヤーがボードから退出しようとすると、死亡してすべてのポイントを失います。

撮影エリア

プレイヤーは、トレイルがあるときにエリアをキャプチャし、自分の土地に再び入ります。

ここに画像の説明を入力してください

赤は2本の赤い線の間を塗りつぶします。プレーヤーが記入しない唯一のケースは、別のプレーヤーがループ内にいる場合です。明確にするために、これは自分が所有する土地だけでなく、他のプレイヤー自身がループにいるときにのみ適用されます。プレイヤーは他の人の土地を占領できます。プレイヤーがトレイルに囲まれたエリアを埋めることができない場合、トレイルは通常の土地に直接変換されます。他のプレイヤーの土地ループ内のプレイヤーが死亡した場合、そのループ内の領域は塗りつぶされます。プレイヤーが死亡するたびに、ボードは埋めることができるエリアを再検査されます。

コントローラーの詳細

コントローラーはこちらです。元のゲームと非常によく似ていますが、KotHおよび技術的な理由により適したものにするために、小さな変更が加えられています。@NathanMerrillKotHCommライブラリ使用して構築されており、@ NathanMerrill多大な支援も受けています。チャットルームのコントローラーで見つかったバグをお知らせください。KotHCommとの一貫性を保つため、コントローラー全体でEclipseコレクションを使用しましたが、ボットはJavaコレクションライブラリのみを使用して作成できます。

すべてがgithubリリースページの uberjarにパッケージ化されています。使用するには、ダウンロードしてプロジェクトに添付し、オートコンプリートに使用できるようにします(IntelliJの指示、Eclipse)。送信をテストするには、を使用してjarを実行しjava -jar SplixKoTH-all.jar -d path\to\submissions\folderます。にpath\to\submissions\folderという名前のサブフォラーがあることを確認し、javaそこにすべてのファイルを配置します。ボットでパッケージ名を使用しないでください(KotHCommでは可能ですが、もう少し面倒です)。すべてのオプションを表示するには、を使用します--help。すべてのボットをロードするには、を使用します--question-id 126815

ボットを書く

ボットの作成を開始するには、を拡張する必要がありますSplixPlayer

  • Direction makeMove(ReadOnlyGame game, ReadOnlyBoard board)
    • ここで、ボットにどの動きをさせるかを決定します。nullを返してはいけません。
  • HiddenPlayer getThisHidden()
    • HiddenPlayerバージョンを取得しthisます。ボットをボードと比較するのに便利です。

enum Direction

    • East (x = 1; y = 0)
    • West (x = -1; y = 0)
    • North (x = 0; y = 1)
    • South (x = 0; y = -1)
  • Direction leftTurn()
    • 取得Directionあなたが左折をした場合、あなたが得るだろう。
  • Direction RightTurn()
    • Direction右折した場合に得られるものを入手してください。

ReadOnlyBoard

これは、ボードにアクセスするクラスです。プレイヤーの位置が表示されたボードのローカルビュー(20x20)を取得するか、ボード上のポジションを所有および主張しているユーザーの情報のみを含むグローバルビュー(ボード全体)を取得できます。これはあなたがあなたの位置を得る場所でもあります。

  • SquareRegion getBounds()
    • ボードのサイズを取得します。
  • MutableMap<com.nmerrill.kothcomm.game.maps.Point2D,ReadOnlySplixPoint> getGlobal()
    • ボードのグローバルマップを取得します。
  • MutableMap<com.nmerrill.kothcomm.game.maps.Point2D,ReadOnlySplixPoint> getView()
    • getGlobal()プレーヤーと同じ20x20の領域に制限され、プレーヤーの位置が表示されることを除いて、と同じです。
  • Point2D getPosition(SplixPlayer me)
    • プレーヤーの位置を取得します。として使用しboard.getPosition(this)ます。
  • Point2D getSelfPosition(ReadOnlyBoard)
    • ボード上のあなたの位置を取得します。使用法:Point2D mypos = getSelfPosition(board)

ReadOnlyGame

ReadOnlyGameは、ゲームの残りのターン数へのアクセスのみを提供しますint getRemainingIterations()

ReadOnlySplixPoint

  • HiddenPlayer getClaimer()
    • HiddenPlayerポイントを主張している人のバージョンを取得します-主張=証跡。
  • HiddenPlayer getOwner()
    • ポイントの所有者を取得します。
  • HiddenPlayer getWhosOnSpot()
    • プレイヤーがこのポイントに配置されている場合、隠されたバージョンを返します。でのみ動作しgetLocal()ます。

Point2D

ここの他のクラスとは異なり、Point2DKotHCommライブラリに含まれています。com.nmerrill.kothcomm.game.maps.Point2D

  • Point2D(int x, int y)
  • int getX()
  • int getY()
  • Point2D moveX(int x)
  • Point2D moveY(int y)
  • Point2D wrapX(int maxX)
    • xの範囲内になるように値をラップしますmaxX
  • Point2D wrapY(int maxY)
    • yの範囲内になるように値をラップしますmaxY
  • int cartesianDistance(Point2D other)
    • これは、プレイヤーがポイントaからポイントbに移動するのに必要なターン数に変換されます。

Clojureのサポート

ClojureコンパイラはにバンドルされているSplixKoTH-all.jarため、ボットにClojureを使用できます。random_bot使用方法については、my を参照してください。

ボットのデバッグ

コントローラーには、戦略のテストに役立つデバッガーが付属しています。開始するには、jarを実行します--guiオプションを指定します。

あなたのjarファイルにデバッガをアタッチするには、従って、これらの命令のIntelliJのために、あるいはこれらの命令のEclipse(Eclipseのバージョンテストされていない)のために。

ここに画像の説明を入力してください

コードでデバッガーを使用している場合、これを使用してボットが見ているものを視覚化することができます。makeMoveボットの先頭にブレークポイントを設定し、現在のスレッドのみを一時停止するようにします。次に、UIの[スタート]ボタンをクリックして、コードをステップ実行します。

ここに画像の説明を入力してください

さて、すべてをまとめるには:

ボットの実行

他のユーザーとボットを実行するには、リリースページでjarを実行する必要があります。フラグのリストは次のとおりです。

  • --iterations-i)<= int(デフォルト500
    • 実行するゲームの数を指定します。
  • --test-bot-t)<=String
    • ボットが含まれているゲームのみを実行します。
  • --directory-d)<=パス
    • 送信を実行するディレクトリ。これを使用してボットを実行します。ボットがという名前のパスのサブフォルダーにあることを確認しますjava
  • --question-id-q)<= int(使用のみ126815
    • サイトから他の提出物をダウンロードしてコンパイルします。
  • --random-seed-r)<= int(デフォルトは乱数)
    • ランダムを使用するボットが結果を再現できるように、ランナーにシードを提供します。
  • --gui-g
    • トーナメントを実行する代わりに、デバッガーUIを実行します。に最適--test-botです。
  • --multi-thread-m)<= boolean(デフォルトtrue
    • マルチスレッドモードでトーナメントを実行します。これにより、コンピューターに複数のコアがある場合に、より高速な結果が得られます。
  • --thread-count-c)<= int(デフォルト4
    • マルチスレッドが許可されている場合に実行するスレッドの数。
  • --help-h
    • これに似たヘルプメッセージを出力します。

このページですべての提出を実行するには、を使用しますjava -jar SplixKoTH-all.jar -q 126815

投稿のフォーマット

コントローラーがすべてのボットをダウンロードできるようにするには、この形式に従う必要があります。

[BotName], Java                     // this is a header
                                    // any explanation you want
[BotName].java                      // filename, in the codeblock
[code]

また、パッケージ宣言を使用しないでください。


スコアボード

+------+--------------+-----------+
| Rank | Name         |     Score |
+------+--------------+-----------+
|    1 | ImNotACoward | 8940444.0 |
|    2 | TrapBot      |  257328.0 |
|    3 | HunterBot    |  218382.0 |
+------+--------------+-----------+

ルールの一部が不明確な場合、またはチャットルームのコントローラーでエラーを見つけた場合はお知らせください。

楽しむ!


ねえ、これがついに投稿されました!私は疑問に思っていました:D
MD XF

どのくらい待ちましたか?;)提出する予定はありますか?
Jアトキン

私は主にエソランでプログラムを書いているので、このような課題を解決できるかどうかはわかりません。しかし、私はサンドボックスでそれを見て、それは大きな挑戦のように見えました!
MD XF

@hyperneutrino編集を見ましたが、本当に気になりますか?...政治的正しさは、この記事の範囲ではどこにもありません、それは英語の文法完全に正しいです
Jアトキン

2
0.o小さな世界?私は、splix.ioの開発者を知っています。(彼にこれを
ツイッター

回答:


2

ImNotACoward、Java

このボットはco病者の生存の専門家です。近くに敵がいない場合、彼は土地の一部を主張します。他のプレイヤーのループに安全に到達できる場合、彼は他のプレイヤーを後ろ刺して、他のプレイヤーと決闘します。他のプレイヤーが安全に攻撃できない場合、彼は逃げて自分の土地に戦略的な退却を行います。

ImNotACoward.java
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.api.set.MutableSet;
import org.eclipse.collections.impl.factory.Lists;
import org.eclipse.collections.impl.factory.Maps;
import org.eclipse.collections.impl.factory.Sets;

import com.jatkin.splixkoth.ppcg.game.Direction;
import com.jatkin.splixkoth.ppcg.game.SplixPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.HiddenPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyBoard;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyGame;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlySplixPoint;
import com.nmerrill.kothcomm.game.maps.Point2D;
import com.nmerrill.kothcomm.game.maps.graphmaps.bounds.point2D.SquareRegion;

public class ImNotACoward extends SplixPlayer {
    private static final MutableSet<Direction> DIRECTIONS = Sets.mutable.of(Direction.values());

    private static class Board {
        public MutableSet<Point2D> allPoints = null;
        private SquareRegion globalBounds = null;
        private SquareRegion viewBounds = null;
        private MutableMap<Point2D, ReadOnlySplixPoint> global = null;
        private MutableMap<Point2D, ReadOnlySplixPoint> view = null;

        public void update(ReadOnlyBoard readOnlyBoard) {
            if (this.allPoints == null) {
                this.allPoints = readOnlyBoard.getGlobal().keysView().toSet();
                this.globalBounds = readOnlyBoard.getBounds();
            }
            this.viewBounds = readOnlyBoard.viewingArea;
            this.global = readOnlyBoard.getGlobal();
            this.view = readOnlyBoard.getView();
        }

        public boolean inBounds(Point2D point) {
            return globalBounds.inBounds(point);
        }

        public boolean inView(Point2D point) {
            return viewBounds.inBounds(point);
        }

        public ReadOnlySplixPoint getSplixPoint(Point2D point) {
            return inView(point) ? view.get(point) : global.get(point);
        }

        public MutableSet<Point2D> getNeighbors(Point2D point) {
            return DIRECTIONS.collect(d -> point.move(d.vector.getX(), d.vector.getY())).select(this::inBounds);
        }

        public MutableSet<Point2D> getNeighbors(MutableSet<Point2D> points) {
            return points.flatCollect(this::getNeighbors);
        }

        public MutableSet<Point2D> getBorders(SquareRegion region) {
            return allPoints.select(p -> region.inBounds(p) &&
                    (p.getX() == region.getLeft() || p.getX() == region.getRight() ||
                    p.getY() == region.getTop() || p.getY() == region.getBottom() ||
                    p.getX() == globalBounds.getLeft() || p.getX() == globalBounds.getRight() ||
                    p.getY() == globalBounds.getTop() || p.getY() == globalBounds.getBottom()));
        }
    }

    private class Player {
        public final HiddenPlayer hiddenPlayer;
        public MutableSet<Point2D> owned = Sets.mutable.empty();
        private MutableSet<Point2D> unowned = null;
        private MutableSet<Point2D> oldClaimed = Sets.mutable.empty();
        public MutableSet<Point2D> claimed = Sets.mutable.empty();
        private MutableSet<Point2D> oldPos = Sets.mutable.empty();
        public MutableSet<Point2D> pos = Sets.mutable.empty();

        public Player(HiddenPlayer hiddenPlayer) {
            super();
            this.hiddenPlayer = hiddenPlayer;
        }

        public void nextMove() {
            owned.clear();
            unowned = null;
            oldClaimed = claimed;
            claimed = Sets.mutable.empty();
            oldPos = pos;
            pos = Sets.mutable.empty();
        }

        public MutableSet<Point2D> getUnowned() {
            if (unowned == null) {
                unowned = board.allPoints.difference(owned);
            }
            return unowned;
        }

        public void addOwned(Point2D point) {
            owned.add(point);
        }

        public void addClaimed(Point2D point) {
            claimed.add(point);
        }

        public void setPos(Point2D point) {
            pos.clear();
            pos.add(point);
        }

        public void calcPos() {
            if (pos.isEmpty()) {
                MutableSet<Point2D> claimedDiff = claimed.difference(oldClaimed);
                if (claimedDiff.size() == 1) {
                    pos = board.getNeighbors(claimedDiff).select(p -> !claimed.contains(p) && !board.inView(p));
                } else if (!oldPos.isEmpty()) {
                    pos = board.getNeighbors(oldPos).select(p -> owned.contains(p) && !board.inView(p));
                } else {
                    pos = owned.select(p -> !board.inView(p));
                }
            }
        }
    }

    private Board board = new Board();
    private Point2D myPos = null;
    private final Player nobody = new Player(new HiddenPlayer(null));
    private final Player me = new Player(new HiddenPlayer(this));
    private MutableMap<HiddenPlayer, Player> enemies = Maps.mutable.empty();
    private MutableMap<HiddenPlayer, Player> players = Maps.mutable.of(nobody.hiddenPlayer, nobody, me.hiddenPlayer, me);
    private MutableSet<Point2D> path = Sets.mutable.empty();

    private Player getPlayer(HiddenPlayer hiddenPlayer) {
        Player player = players.get(hiddenPlayer);
        if (player == null) {
            player = new Player(hiddenPlayer);
            players.put(player.hiddenPlayer, player);
            enemies.put(player.hiddenPlayer, player);
        }
        return player;
    }

    private Direction moveToOwned() {
        MutableSet<Point2D> targets = me.owned.difference(me.pos);
        if (targets.isEmpty()) {
            return moveTo(myPos);
        } else {
            return moveTo(targets.minBy(myPos::cartesianDistance));
        }
    }

    private Direction moveTo(Point2D target) {
        return DIRECTIONS.minBy(d -> {
            Point2D p = myPos.move(d.vector.getX(), d.vector.getY());
            return !board.inBounds(p) || me.claimed.contains(p) ? Integer.MAX_VALUE : target.cartesianDistance(p);
        });
    }

    @Override
    protected Direction makeMove(ReadOnlyGame readOnlyGame, ReadOnlyBoard readOnlyBoard) {
        board.update(readOnlyBoard);
        myPos = readOnlyBoard.getPosition(this);
        path.remove(myPos);

        for (Player e : players.valuesView()) {
            e.nextMove();
        }
        for (Point2D point : board.allPoints) {
            ReadOnlySplixPoint splixPoint = board.getSplixPoint(point);
            getPlayer(splixPoint.getOwner()).addOwned(point);
            getPlayer(splixPoint.getClaimer()).addClaimed(point);
            getPlayer(splixPoint.getWhosOnSpot()).setPos(point);
        }
        for (Player e : players.valuesView()) {
            e.calcPos();
        }

        if (me.owned.contains(myPos) && path.allSatisfy(p -> me.owned.contains(p))) {
            path.clear();
        }

        if (path.isEmpty()) {
            MutableSet<Point2D> enemyPositions = enemies.valuesView().flatCollect(e -> e.pos).toSet();
            int enemyDistance = enemyPositions.isEmpty() ? Integer.MAX_VALUE :
                    enemyPositions.minBy(myPos::cartesianDistance).cartesianDistance(myPos);

            if (enemyDistance < 20) {
                MutableSet<Point2D> enemyClaimed = enemies.valuesView().flatCollect(e -> e.claimed).toSet();
                if (!enemyClaimed.isEmpty()) {
                    Point2D closestClaimed = enemyClaimed.minBy(myPos::cartesianDistance);
                    if (closestClaimed.cartesianDistance(myPos) < enemyDistance) {
                        return moveTo(closestClaimed);
                    } else if (enemyDistance < 10) {
                        return moveToOwned();
                    }
                }
            }

            if (me.owned.contains(myPos)) {
                if (!me.getUnowned().isEmpty()) {
                    Point2D target = me.getUnowned().minBy(myPos::cartesianDistance);
                    if (target.cartesianDistance(myPos) > 2) {
                        return moveTo(target);
                    }
                }

                int safeSize = Math.max(1, Math.min(enemyDistance / 6, readOnlyGame.getRemainingIterations() / 4));
                SquareRegion region = Lists.mutable
                        .of(new SquareRegion(myPos, myPos.move(safeSize, safeSize)),
                                new SquareRegion(myPos, myPos.move(safeSize, -safeSize)),
                                new SquareRegion(myPos, myPos.move(-safeSize, safeSize)),
                                new SquareRegion(myPos, myPos.move(-safeSize, -safeSize)))
                        .maxBy(r -> me.getUnowned().count(p -> r.inBounds(p)));
                path = board.getBorders(region);
            } else {
                return moveToOwned();
            }
        }

        if (!path.isEmpty()) {
            return moveTo(path.minBy(myPos::cartesianDistance));
        }

        return moveToOwned();
    }
}

1

TrapBot、Java

TrapBot.java

import com.jatkin.splixkoth.ppcg.game.Direction;
import com.jatkin.splixkoth.ppcg.game.SplixPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyBoard;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyGame;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlySplixPoint;
import com.nmerrill.kothcomm.game.maps.Point2D;
import com.nmerrill.kothcomm.game.maps.graphmaps.bounds.point2D.SquareRegion;
import javafx.util.Pair;
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.impl.factory.Lists;

import java.util.Comparator;

/**
 * Trap bot goes to the wall and traces the entirety around. Hopes that
 * the players in the middle die and that nobody challenges him. Nearly 
 * all turns are left turns.
 */
public class TrapBot extends SplixPlayer {

    /**
     * Mode when the bot is attempting to reach the wall from it's original spawn
     * location.
     */
    public static final int MODE_GOING_TO_WALL = 1;

    /**
     * Mode when we have reached the wall and are now going around the board.
     */
    public static final int MODE_FOLLOWING_WALL = 2;

    private int mode = MODE_GOING_TO_WALL;

    public static int WALL_EAST = 1;
    public static int WALL_NORTH = 2;
    public static int WALL_WEST = 3;
    public static int WALL_SOUTH = 4;


    /**
     * How long the bot would like to go before he turns around to go back home.
     */
    private static final int PREFERRED_LINE_DIST = 5;

    private int distToTravel = 0;

    private Direction lastMove = Direction.East;// could be anything that's not null
    private int lastTrailLength = 0;

    @Override
    protected Direction makeMove(ReadOnlyGame game, ReadOnlyBoard board) {
        Direction ret = null;
        MutableMap<Point2D, ReadOnlySplixPoint> view = board.getView();
        int trailLength = getTrailLength(board, view);

        if (trailLength == 0) {

            int closestWall = getClosestWall(board);
            Direction directionToWall = getDirectionToWall(closestWall);

            if (lastTrailLength != 0) {
                ret = lastMove.leftTurn();
                // move to the other half of 2 width line so we can start without shifting to the left
            }

            if (mode == MODE_GOING_TO_WALL && ret == null) {
                int distCanTravel = getDistCanTravel(
                        getSelfPosition(board), board.getBounds(), directionToWall);
                if (distCanTravel == 0) mode = MODE_FOLLOWING_WALL;
                else ret = directionToWall;
                distToTravel = distCanTravel;

            }

            if (mode == MODE_FOLLOWING_WALL && ret == null) {
                int distCanTravel = 0;
                ret = directionToWall;
                while (distCanTravel == 0) {// keep turning left until we can get somewhere
                    ret = ret.leftTurn();
                    distCanTravel = getDistCanTravel(
                            getSelfPosition(board), board.getBounds(), ret);
                }

                distToTravel = distCanTravel;
            }
        }

        // once we have started we are on auto pilot (can't run after the before block)
        else if (trailLength == distToTravel || trailLength == (distToTravel + 1))
            ret = lastMove.leftTurn();

        if (ret == null)// if we don't have a move otherwise, we must be on our trail. ret same as last time
            ret = lastMove;

        lastTrailLength = trailLength;
        lastMove = ret;
        return ret;
    }

    int getClosestWall(ReadOnlyBoard board) {
        Point2D thisPos = getSelfPosition(board);
        return Lists.mutable.of(
                new Pair<>(WALL_NORTH, board.getBounds().getTop() - thisPos.getY()),
                new Pair<>(WALL_SOUTH, thisPos.getY()), 
                new Pair<>(WALL_EAST, board.getBounds().getRight() - thisPos.getX()),
                new Pair<>(WALL_WEST, thisPos.getX())
        ).min(Comparator.comparingInt(Pair::getValue)).getKey();
    }

    /**
     * This goes around some intended behavior in the controller to get the correct result. When a player goes outside
     * his territory the land under him is converted to a trail -- on the next step of the game. So a trail length may
     * be the count of the trail locations plus one. That is what this function calculates. Depends on the whole trail
     * being contained inside the view passed to it.
     * @return
     */
    int getTrailLength(ReadOnlyBoard board, MutableMap<Point2D, ReadOnlySplixPoint> view) {
        boolean isPlayerOutsideHome = !view.get(getSelfPosition(board)).getOwner().equals(getThisHidden());
        int trailLength = view.count(rop -> rop.getClaimer().equals(getThisHidden()));
        return trailLength + (isPlayerOutsideHome? 1 : 0);
    }

    /**
     * Calculate how far we can travel in the direction before we hit the wall.
     * @return
     */
    int getDistCanTravel(Point2D currPos, SquareRegion bounds, Direction direction) {
        for (int i = 1; i <= PREFERRED_LINE_DIST; i++) {
            if (!bounds.inBounds(currPos.move(direction.vector.getX()*i, direction.vector.getY()*i)))
                return i-1;
        }
        return PREFERRED_LINE_DIST;
    }

    /**
     * Get which direction needs to be traveled to reach the specified wall.
     * Requires that neither Direction nor the values of `WALL_...` change.
     * @param targetWall
     * @return
     */
    Direction getDirectionToWall(int targetWall) {
        return Direction.values()[targetWall-1];
    }
}

これはおそらく最も単純なボットです。ボードの端をトレースアウトするだけで、殺されるリスクを減らすために倍になります。


Eclipseコレクションを使用しているのを見るのはクールです。ECにはペアインターフェイスがあります。Tuples.pair()を使用して、Pairインスタンスを取得できます。ペアの一方または両方の値がプリミティブである場合、PrimitiveTuplesクラスもあります。
ドナルドラーブ

1

random_bot、Clojure

これはRandomBotですが、命名規則に固執する必要があり、いくつかの問題により名前にハイフンを使用できないため、アンダースコアが支配的です!make-move最初の項目があることで、FN戻りVEC Directionあなたが移動すると、第二は、あなたが次のターンにあなたに戻って渡すことにしたい状態であること。このコードは複数のゲームを並行して実行している可能性があるため、外部アトムを使用しないでください。

 random_bot.clj
 (ns random-bot
     (:import
      [com.jatkin.splixkoth.ppcg.game Direction]))

 (defn make-move [game board state]
       [(rand-nth [Direction/East
                   Direction/West
                   Direction/North
                   Direction/South])
        nil])

0

HunterBot、Java

HunterBot.java

import com.jatkin.splixkoth.ppcg.game.Direction;
import com.jatkin.splixkoth.ppcg.game.SplixPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.HiddenPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyBoard;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyGame;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlySplixPoint;
import com.nmerrill.kothcomm.game.maps.Point2D;
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.api.set.ImmutableSet;
import org.eclipse.collections.impl.factory.Sets;

import java.util.Comparator;

/**
 * This bot looks for any trail points left behind by another player and sets that as his target. If the target ever
 * disappears, it will continue on in hopes that the player will return soon, or if another target appears, it will
 * go towards that one. Works best when the other player repeatedly goes in the same general direction.
 */
public class HunterBot extends SplixPlayer {

    private Point2D lastTarget;

    private Direction lastMove = Direction.East;

    @Override
    protected Direction makeMove(ReadOnlyGame game, ReadOnlyBoard board) {
        Point2D thisPos = getSelfPosition(board);
        MutableMap<Point2D, ReadOnlySplixPoint> global = board.getGlobal();
        MutableMap<Point2D, ReadOnlySplixPoint> targets = global.select((pt, rosp) ->
                !rosp.getClaimer().equals(getThisHidden()) 
                        && !rosp.getClaimer().equals(new HiddenPlayer(null)));

        if (targets.size() == 0 && lastTarget == null) {
            lastMove = lastMove.leftTurn();
            return lastMove;
        }

        Point2D target = null;
        if (targets.size() == 0) target = lastTarget;
        else target = targets.keysView().min(Comparator.comparingInt(thisPos::cartesianDistance));
        if (target.equals(thisPos)) {
            lastTarget = null;
            if (global.get(thisPos).getOwner().equals(getThisHidden())) {
                lastMove = lastMove.leftTurn();
                return lastMove;
            } else 
            // time to go home
            target = global.select((z_, x) -> getThisHidden().equals(x.getOwner())).keySet().iterator().next();

        }

        lastTarget = target;
        lastMove = makeSafeMove(target, global, board, thisPos);
        return lastMove;
    }

    private Direction makeSafeMove(Point2D targetLocation, MutableMap<Point2D, ReadOnlySplixPoint> map, ReadOnlyBoard board, Point2D currLoc) {
        Point2D dist = targetLocation.move(-currLoc.getX(), -currLoc.getY());
        ImmutableSet<Direction> possibleMoves = Sets.immutable.of(Direction.values())
                .select(x -> {
                    Point2D pos = currLoc.move(x.vector.getX(), x.vector.getY());
                    return !board.getBounds().outOfBounds(pos) && !getThisHidden().equals(map.get(pos).getClaimer());
                });
        Direction prefMove;
        if (Math.abs(dist.getX()) > Math.abs(dist.getY()))
            prefMove = getDirectionFroPoint(new Point2D(normalizeNum(dist.getX()), 0));
        else
            prefMove = getDirectionFroPoint(new Point2D(0, normalizeNum(dist.getY())));

        if (possibleMoves.contains(prefMove)) return prefMove;
        if (possibleMoves.contains(prefMove.leftTurn())) return prefMove.leftTurn();
        if (possibleMoves.contains(prefMove.rightTurn())) return prefMove.rightTurn();
        return prefMove.leftTurn().leftTurn();
    }

    private Direction getDirectionFroPoint(Point2D dir) {
        return Sets.immutable.of(Direction.values()).select(d -> d.vector.equals(dir)).getOnly();
    }

    private int normalizeNum(int n) { if (n < -1) return -1; if (n > 1) return 1; else return n;}

}

最も基本的なボットの1つ。ボードを検索して他の人を殺すための場所を探し、殺人の位置に到達するために可能な限り最短の経路をたどります。領土外にある場合、別のプレイヤーを殺すための別の空きがあるまで、ランダムに動きます。それはそれ自体で実行されることを防ぐためのいくつかのロジックを持ち、他のすべてのプレイヤーが死んだとき、それはその家に戻ります。いったん家に帰ると、小さな正方形になります。

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