Splix.io - Ülkenin kralı


37

Sen kontrolü altındaki toprağı büyütmek isteyen girişimci bir nokta . Bu oldukça basittir - şu anki arazinizin dışına çıkın ve kendi ülkenize geri dönün ve bu ilmeğindeki her şey artık size aittir. Ama bir çekişme var. Eğer başka bir nokta bir şekilde döngünüzü bulup geçerse, ölürsünüz.

Henüz denemediyseniz, Splix.io'ya gidin ve bir oyun deneyin. Hareketlerinizi kontrol etmek için ok tuşlarını kullanın.

GIF

görüntü tanımını buraya girin

Kredi: http://splix.io/

Ayrıntılı Bilgiler

Tüm oyuncular 200x200'lük bir tahtada rastgele pozisyonlarda başlar. (Bunu değiştirme hakkını saklı tutarım :). Mümkün olan en fazla puan toplamak için belirli miktarda hamle yapacaksınız. Puanlar tarafından hesaplanır:

  • Öldürdüğünüz oyuncu sayısı 300
  • Tur sonunda sahip olduğunuz arazi miktarı

Bu, başkalarının toprağınızı çalabileceği noktasını ortaya çıkarır. Ülkenizden bazılarıyla kesişen bir döngü başlatırlarsa, talep edebilirler. Tur boyunca ölürseniz, o tur için tüm puanları kaybedersiniz.

Her turda rastgele seçilen bir oyuncu grubu vardır (en fazla 5 benzersiz oyuncu) (değişebilir). Her oyuncu eşit sayıda yarışmaya katılır. Botunuzun final puanı, oyun başına ortalama puanı ile belirlenir. Her oyun 2000 turdan oluşur (ayrıca değişebilir). Tüm botlar aynı anda hareketlerini yapıyor.

Ölüm vakası

Kafa popo

kafa kıçı

Her iki oyuncu da birbirlerine vurduğunda ölür. Bu, her iki oyuncu da kendi alanın kenarında olduğunda bile geçerlidir.

kafa kıçı

Ancak, oyunculardan sadece biri topraklarındayken, diğer oyuncu ölür.

görüntü tanımını buraya girin

Çizgi çapraz

görüntü tanımını buraya girin

Bu durumda, sadece mor oyuncu ölür.

Kendi çizgini geçemezsin.

görüntü tanımını buraya girin

Kuruldan çıkma

oyuncu tahtadan gidiyor

Bir oyuncu tahtadan çıkmaya çalışırsa, ölür ve tüm puanlarını kaybeder.

Yakalama alanı

Bir oyuncu, izi kaldığında alanı ele geçirir ve tekrar kendi topraklarına girer.

görüntü tanımını buraya girin

Kırmızı, iki kırmızı çizginin arasına girer. Bir oyuncunun doldurmadığı tek durum, başka bir oyuncunun döngünün içinde olduğu durumdur. Açık olmak gerekirse, bu yalnızca diğer oyuncunun kendisi döngüdeyken geçerlidir, sadece kendisine ait arazi değildir. Bir oyuncu başka bir kişiden arazi alabilir. Bir oyuncu parkurunun etrafındaki alanı dolduramazsa, parkur doğrudan normal topraklara dönüştürülür. Başka bir oyuncu toprak döngüsünün içindeki oyuncu ölürse, bu döngüdeki alan doldurulur. Bir oyuncu her öldüğünde, tahta doldurulabilecek bir alan için yeniden incelenir.

Denetleyici ayrıntıları

Kontrolör burada . Orijinal oyuna çok benzer, ancak bunu KotH ve teknik nedenlerle daha uygun hale getirmek için küçük değişiklikler yapıldı. O ile inşa edilmiştir @NathanMerrill 'ın KotHComm kütüphanesinde ve @NathanMerrill gelen önemli yardımıyla da. Lütfen bana sohbet odasındaki kumanda cihazında bulduğunuz hataları bildirin . KotHComm ile tutarlı olmak için, denetleyici boyunca Eclipse koleksiyonlarını kullandım, ancak botlar yalnızca Java Koleksiyonlar kütüphanesini kullanarak yazılabilir.

Her şey github bültenleri sayfasındaki bir uberjar içinde paketlenir . Kullanmak için indirin ve projenize ekleyin, böylece otomatik tamamlama için kullanabilirsiniz ( IntelliJ , Eclipse için talimatlar ). Gönderilerinizi test etmek için, küpü birlikte çalıştırın java -jar SplixKoTH-all.jar -d path\to\submissions\folder. path\to\submissions\folderBunun adında bir alt klasör olduğundan emin olun javave tüm dosyalarınızı oraya yerleştirin. Paket isimlerinizi botlarınızda kullanmayın (KotHComm ile mümkün olsa da, sadece biraz daha fazla sorun). Tüm seçenekleri görmek için kullanın --help. Tüm botları yüklemek için kullanın --question-id 126815.

Bot yazmak

Bir bot yazmaya başlamak için, uzatmanız gerekir SplixPlayer.

  • Direction makeMove(ReadOnlyGame game, ReadOnlyBoard board)
    • Botunuzun hangi hamleyi yapmasını istediğinize karar verirsiniz. Boş döndürmemelisiniz.
  • HiddenPlayer getThisHidden()
    • HiddenPlayerSürümünü alın this. Botunuzu tahta ile karşılaştırmak için kullanışlıdır.

enum Direction

  • Değerler
    • East (x = 1; y = 0)
    • West (x = -1; y = 0)
    • North (x = 0; y = 1)
    • South (x = 0; y = -1)
  • Direction leftTurn()
    • Alın Directionsize bir sola yapılmış eğer alacağı.
  • Direction RightTurn()
    • Alın Directionsize bir sağa dönüş yaptı eğer alacağı.

ReadOnlyBoard

Tahtaya eriştiğiniz sınıf budur. Tahtanın gösterilen oyuncu konumlarıyla ilgili yerel bir görünümünü (20x20) ya da yalnızca tahtanın üzerinde kimin sahip olduğunu ve hak talebinde bulunduğunu gösteren bilgileri içeren genel bir görünümü (tüm pano) elde edebilirsiniz. Burası da pozisyonunuzu aldığınız yer.

  • SquareRegion getBounds()
    • Tahtanın boyutunu alın.
  • MutableMap<com.nmerrill.kothcomm.game.maps.Point2D,ReadOnlySplixPoint> getGlobal()
    • Tahtanın global haritasını alın.
  • MutableMap<com.nmerrill.kothcomm.game.maps.Point2D,ReadOnlySplixPoint> getView()
    • Aynı şekilde getGlobal(), oynatıcınızın etrafındaki 20x20'lik bir alanla sınırlı olması ve oyuncu konumlarını göstermesi dışında.
  • Point2D getPosition(SplixPlayer me)
    • Oyuncunun pozisyonunu al. Olarak kullanın board.getPosition(this).
  • Point2D getSelfPosition(ReadOnlyBoard)
    • Tahtandaki pozisyonunu al. Kullanımı:Point2D mypos = getSelfPosition(board)

ReadOnlyGame

ReadOnlyGamesadece oyunda kalan dönüş sayısına erişim sağlar int getRemainingIterations().

ReadOnlySplixPoint

  • HiddenPlayer getClaimer()
    • HiddenPlayerBir noktayı talep eden versiyonunu alın - talep etmek = bir iz.
  • HiddenPlayer getOwner()
    • Kim bir noktaya sahip olsun.
  • HiddenPlayer getWhosOnSpot()
    • Müzikçalar bu noktaya yerleştirilmişse, gizli versiyonunu döndür. Sadece işe yarıyor getLocal().

Point2D

Buradaki diğer sınıfların aksine, Point2DKotHComm kütüphanesinde bulunur.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)
    • xDeğeri aralığında olacak şekilde sarın maxX.
  • Point2D wrapY(int maxY)
    • yDeğeri aralığında olacak şekilde sarın maxY.
  • int cartesianDistance(Point2D other)
    • Bu, bir oyuncunun a noktasından b noktasına hareket etmesinin kaç tur alacağı anlamına gelir.

Clojure desteği

Clojure derleyicisi ile birlikte gelir SplixKoTH-all.jar, böylece Clojure'u botunuz için kullanabilirsiniz! random_botNasıl kullanılacağını görmek için bana bakın .

Bir botta hata ayıklama

Kontrolör, test stratejilerine yardımcı olmak için bir hata ayıklayıcı ile birlikte gelir. Başlamak için, hazneyi --guiseçenek ile çalıştırın .

Senin kavanoza hata ayıklayıcı eklemek için takip bu talimatları intellij için veya bu talimatları Eclipse için (denenmemiş Eclipse versiyonu).

görüntü tanımını buraya girin

Kodunuzla bir hata ayıklayıcı kullanıyorsanız, botunuzun ne gördüğünü görselleştirmek için bunu kullanabilirsiniz. Botunuzun başında bir kesme noktası belirleyin makeMoveve yalnızca geçerli iş parçacığını duraklattığından emin olun. Ardından, kullanıcı arayüzündeki başlat düğmesini tıklayın ve kodunuzu girin.

görüntü tanımını buraya girin

Şimdi hepsini bir araya getirmek için:

Koşu botları

Botlarınızı diğerleriyle birlikte çalıştırmak için, kavanozu bültenleri sayfasında çalıştırmanız gerekir. İşte bayrakların listesi:

  • --iterations( -i) <= int(varsayılan 500)
    • Çalıştırılacak oyun sayısını belirtin.
  • --test-bot( -t) <=String
    • Sadece botun içinde bulunduğu oyunları çalıştırın.
  • --directory( -d) <= Yol
    • Gönderilerin çalıştırılacağı dizin. Botlarınızı çalıştırmak için bunu kullanın. Botlarınızın, adlandırılmış yolun bir alt klasöründe olduğundan emin olun java.
  • --question-id( -q) <= int(sadece kullanım 126815)
    • Siteden diğer gönderileri indirin ve derleyin.
  • --random-seed( -r) <= int(varsayılan olarak rasgele bir sayı)
    • Koşucuya bir tohum verin ki rasgele kullanan botlar sonuçların çoğalmasını sağlayabilir.
  • --gui( -g)
    • Bir turnuva yapmak yerine hata ayıklayıcı kullanıcı arayüzünü çalıştırın. En iyisi ile kullanılır --test-bot.
  • --multi-thread( -m) <= boolean(varsayılan true)
    • Çoklu iş parçacığı modunda bir turnuva çalıştırın. Bilgisayarınızda birden fazla çekirdek varsa, bu daha hızlı bir sonuç sağlar.
  • --thread-count( -c) <= int(varsayılan 4)
    • Çok iş parçacığına izin veriliyorsa çalıştırılacak iş parçacığı sayısı.
  • --help( -h)
    • Buna benzer bir yardım mesajı yazdırın.

Bu sayfadaki tüm gönderileri çalıştırmak için kullanın java -jar SplixKoTH-all.jar -q 126815.

Yayınınızı biçimlendirme

Kontrol cihazının tüm botları indirebilmesini sağlamak için bu formatı izlemelisiniz.

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

Ayrıca, bir paket bildirimi kullanmayın.


sayı tahtası

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

Lütfen kuralların herhangi bir bölümü net değilse veya sohbet odasında denetleyicide herhangi bir hata bulursanız bana bildirin .

İyi eğlenceler!


Hey, bu en sonunda ilan edildi! Merak ediyordum: D
MD XF

Ne kadardır bekliyorsun? ;) Göndermeyi planlıyor musunuz?
J Atkin

Genelde esolanglarda programlar yazdığım için böyle bir zorluğu çözüp çözemeyeceğimi bilmiyorum. Ama onu kum havuzunda gördüm ve çok zor oldu!
MD XF

@ hyperneutrino Düzenlemeyi gördüm, gerçekten seni rahatsız ediyor mu? Politik doğruluk bu yazının amacına uygun değil ve İngilizce dilbilgisi mükemmel derecede doğru ...
J Atkin

2
0.o dünya? Ben splix.io geliştirici (biliyorum) biliyorum. (Tweet'ledi bu @ ona)
CAD97

Yanıtlar:


2

ImNotACoward, Java

Bu bot bir korkak hayatta kalma uzmanı. Yakında hiç düşman yoksa, toprağın bir parçası olduğunu iddia eder. Başka bir oyuncunun döngüsüne güvenli bir şekilde ulaşılabilirse , arkadaki diğer oyuncuyu diğer oyuncuya düelloya sokar. Diğer oyuncuya güvenli bir şekilde saldıramazsa filolar kendi topraklarına stratejik bir geri çekilme gerçekleştirir.

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

İlginç. Çok hoş! Bunun ne kadar iyi yapılabileceğini merak ediyorum ...
J Atkin

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

Bu belki de en basit bottur. Tek yaptığı, tahtanın kenarını izlemek, öldürülme riskini azaltmak için kendi üzerine ikiye katlamak.


Eclipse koleksiyonlarını kullandığınızı görmek harika. EC'de bir Pair arayüzü var. Bir Pair örneği almak için Tuples.pair () işlevini kullanabilirsiniz. Çiftin değerlerinden biri veya her ikisi de ilkel ise, bir PrimitiveTuples sınıfı da vardır.
Donald Raab,

1

random_bot, Clojure

Bu RandomBot , ancak adlandırma kurallarına uymak zorunda kaldım ve bazı konular addaki kısa çizgiyi kullanmamı engelliyor, bu yüzden alt çizgi hüküm sürüyor! make-moveFn ilk öğe olmanın a Daha fazla döndürür Directioniçeri taşımak istediğiniz ve ikinci istediğiniz eyalet sonraki dönüşte size geri geçirilecek olan. Herhangi bir harici atom kullanmayın, çünkü bu kod paralel olarak birden fazla oyun çalıştırıyor olabilir.

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

}

En basit botlardan biri. Tahtayı başkalarını öldürecek noktalar arar ve öldürme konumuna ulaşmak için mümkün olan en kısa yolu izler. Eğer kendi bölgesi dışındaysa, başka bir oyuncuyu öldürmek için başka bir açılış yapana kadar rastgele hareketler yapacaktır. Kendi kendine geçmesini engellemek için bir mantık var ve diğer tüm oyuncular öldüğünde, evine geri dönüyor. Bir kez eve sadece küçük bir kareye gider.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.