Splix.io - Vua của đất


37

Bạn là một dấu chấm táo bạo muốn tăng đất dưới sự kiểm soát của nó. Điều này khá đơn giản - đi ra ngoài vùng đất hiện tại của bạn và quay trở lại vùng đất của bạn và mọi thứ trong vòng lặp đó đều thuộc sở hữu của bạn. Nhưng có một nhược điểm. Nếu một số dấu chấm khác bằng cách nào đó tìm thấy vòng lặp của bạn và vượt qua nó, bạn sẽ chết.

Nếu bạn chưa thử nó, hãy truy cập Splix.io và thử một trò chơi. Sử dụng các phím mũi tên để kiểm soát chuyển động của bạn.

QUÀ TẶNG

nhập mô tả hình ảnh ở đây

Tín dụng: http://splix.io/

Cụ thể

Tất cả người chơi bắt đầu ở các vị trí ngẫu nhiên trên một bảng 200x200. (Tôi bảo lưu quyền thay đổi điều này :). Bạn sẽ có một số lượng di chuyển nhất định để tích lũy số điểm lớn nhất có thể. Điểm được tính bằng:

  • Số lượng người chơi bạn đã giết 300 lần
  • Số lượng đất bạn sở hữu vào cuối vòng

Điều này đưa ra quan điểm rằng những người khác có thể đánh cắp đất của bạn. Nếu họ bắt đầu một vòng lặp giao với một số vùng đất của bạn, họ có thể yêu cầu nó. Nếu bạn chết trong vòng, bạn mất tất cả điểm cho vòng đó.

Mỗi vòng có một nhóm người chơi được chọn ngẫu nhiên (tối đa 5 người chơi duy nhất) (có thể thay đổi). Mỗi người chơi tham gia vào một số vòng bằng nhau. Điểm cuối cùng của bot của bạn được xác định bằng điểm trung bình trên mỗi trò chơi. Mỗi trò chơi bao gồm 2000 lượt (cũng có thể thay đổi). Tất cả các bot thực hiện di chuyển của họ cùng một lúc.

Trường hợp tử vong

Đầu mông

đầu mông

Cả hai người chơi đều chết khi họ chổng mông vào nhau. Điều này vẫn đúng ngay cả khi cả hai người chơi đang ở rìa không gian của họ.

đầu mông

Tuy nhiên, khi chỉ có một người chơi ở trong vùng đất của mình, người chơi kia sẽ chết.

nhập mô tả hình ảnh ở đây

Ngã tư đường

nhập mô tả hình ảnh ở đây

Trong trường hợp này, chỉ có người chơi màu tím chết.

Bạn không thể vượt qua dòng của riêng bạn.

nhập mô tả hình ảnh ở đây

Ra khỏi bảng

người chơi đi ra khỏi bảng

Nếu một người chơi cố gắng thoát khỏi bảng, anh ta sẽ chết và mất tất cả điểm.

Khu vực chụp

Một người chơi sẽ chiếm được khu vực khi anh ta có một dấu vết và anh ta lại vào vùng đất của mình.

nhập mô tả hình ảnh ở đây

Màu đỏ lấp đầy ở giữa hai vạch đỏ. Trường hợp duy nhất mà người chơi không điền vào là khi người chơi khác ở trong vòng lặp. Để rõ ràng, điều này chỉ áp dụng khi bản thân người chơi khác ở trong vòng lặp, không chỉ là đất thuộc sở hữu của anh ta. Một người chơi có thể chiếm đất từ ​​người khác. Nếu người chơi không thể điền vào khu vực được bao quanh bởi đường mòn của mình, đường mòn được chuyển đổi trực tiếp sang đất bình thường. Nếu người chơi bên trong vòng lặp hạ cánh của người chơi khác chết, khu vực trong vòng lặp đó sẽ bị lấp. Mỗi khi người chơi chết, bảng sẽ được xem xét lại cho một khu vực có thể được điền vào.

Chi tiết điều khiển

Bộ điều khiển ở đây . Nó rất giống với trò chơi gốc, nhưng những thay đổi nhỏ đã được thực hiện để làm cho điều này phù hợp hơn với KotH và vì lý do kỹ thuật. Nó được xây dựng với @NathanMerrill 's thư viện KotHComm , và với sự giúp đỡ đáng kể từ @NathanMerrill là tốt. Xin vui lòng cho tôi biết bất kỳ lỗi nào bạn tìm thấy trong bộ điều khiển trong phòng trò chuyện . Để phù hợp với KotHComm, tôi đã sử dụng các bộ sưu tập Eclipse trong toàn bộ bộ điều khiển, nhưng các bot có thể được viết chỉ bằng thư viện Bộ sưu tập Java.

Tất cả mọi thứ được đóng gói trong một uberjar trên trang phát hành github . Để sử dụng nó, hãy tải xuống và đính kèm nó vào dự án của bạn để bạn có thể sử dụng nó để tự động phàn nàn (hướng dẫn cho IntelliJ , Eclipse ). Để kiểm tra bài nộp của bạn, bạn chạy jar với java -jar SplixKoTH-all.jar -d path\to\submissions\folder. Đảm bảo rằng path\to\submissions\foldercó một bộ lọc con được đặt tên javavà để đặt tất cả các tệp của bạn ở đó. Không sử dụng tên gói trong bot của bạn (mặc dù điều này có thể xảy ra với KotHComm, nhưng nó chỉ gây rắc rối hơn một chút). Để xem tất cả các tùy chọn, sử dụng --help. Để tải tất cả các bot, sử dụng --question-id 126815.

Viết bot

Để bắt đầu viết bot, bạn phải mở rộng SplixPlayer.

  • Direction makeMove(ReadOnlyGame game, ReadOnlyBoard board)
    • Đây là nơi bạn quyết định di chuyển mà bạn muốn bot của bạn thực hiện. Không được trả về null.
  • HiddenPlayer getThisHidden()
    • Lấy HiddenPlayerphiên bản của this. Hữu ích để so sánh bot của bạn với hội đồng quản trị.

enum Direction

  • Giá trị
    • East (x = 1; y = 0)
    • West (x = -1; y = 0)
    • North (x = 0; y = 1)
    • South (x = 0; y = -1)
  • Direction leftTurn()
    • Nhận được những Directiongì bạn sẽ nhận được nếu bạn rẽ trái.
  • Direction RightTurn()
    • Có được những Directiongì bạn sẽ nhận được nếu bạn rẽ phải.

ReadOnlyBoard

Đây là lớp nơi bạn truy cập bảng. Bạn có thể có được chế độ xem cục bộ (20x20) của bảng với các vị trí người chơi được hiển thị hoặc chế độ xem toàn cầu (toàn bộ bảng) chỉ với thông tin về người sở hữu và yêu cầu các vị trí trên bảng. Đây cũng là nơi bạn có được vị trí của bạn.

  • SquareRegion getBounds()
    • Lấy kích thước của bảng.
  • MutableMap<com.nmerrill.kothcomm.game.maps.Point2D,ReadOnlySplixPoint> getGlobal()
    • Nhận một bản đồ toàn cầu của hội đồng quản trị.
  • MutableMap<com.nmerrill.kothcomm.game.maps.Point2D,ReadOnlySplixPoint> getView()
    • Tương tự như getGlobal(), ngoại trừ việc nó bị giới hạn trong khu vực 20x20 xung quanh trình phát của bạn và nó hiển thị các vị trí của người chơi.
  • Point2D getPosition(SplixPlayer me)
    • Nhận vị trí của người chơi của bạn. Sử dụng như board.getPosition(this).
  • Point2D getSelfPosition(ReadOnlyBoard)
    • Nhận vị trí của bạn trên bảng. Sử dụng:Point2D mypos = getSelfPosition(board)

ReadOnlyGame

ReadOnlyGamechỉ cung cấp quyền truy cập vào số lượt còn lại trong trò chơi thông qua int getRemainingIterations().

ReadOnlySplixPoint

  • HiddenPlayer getClaimer()
    • Lấy HiddenPlayerphiên bản của người đang yêu cầu một điểm - yêu cầu = một dấu vết.
  • HiddenPlayer getOwner()
    • Nhận người sở hữu một điểm.
  • HiddenPlayer getWhosOnSpot()
    • Nếu người chơi được định vị vào thời điểm này, hãy trả lại phiên bản ẩn của nó. Chỉ hoạt động trong getLocal().

Point2D

Không giống như các lớp khác ở đây, Point2Dđược chứa trong thư viện KotHComm.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)
    • Bọc xgiá trị trong phạm vi maxX.
  • Point2D wrapY(int maxY)
    • Bọc ygiá trị trong phạm vi maxY.
  • int cartesianDistance(Point2D other)
    • Điều này có nghĩa là người chơi sẽ mất bao nhiêu lượt để chuyển từ điểm a sang điểm b.

Hỗ trợ Clojure

Trình biên dịch Clojure được gói cùng với SplixKoTH-all.jar, vì vậy bạn có thể sử dụng Clojure cho bot của mình! Tham khảo của tôirandom_bot để xem làm thế nào để sử dụng nó.

Gỡ lỗi một bot

Bộ điều khiển đi kèm với trình gỡ lỗi để giúp kiểm tra các chiến lược. Để bắt đầu, hãy chạy jar với--gui tùy chọn.

Để đính kèm trình gỡ lỗi vào jar của bạn, hãy làm theo các hướng dẫn sau cho IntelliJ hoặc các hướng dẫn này cho Eclipse (phiên bản Eclipse chưa được kiểm tra).

nhập mô tả hình ảnh ở đây

Nếu bạn đang sử dụng trình gỡ lỗi với mã của mình, bạn có thể sử dụng công cụ này để giúp trực quan hóa những gì bot của bạn đang nhìn thấy. Đặt điểm dừng ở đầu makeMovebot của bạn và đảm bảo rằng nó chỉ tạm dừng luồng hiện tại. Tiếp theo, nhấp vào nút bắt đầu trên giao diện người dùng và chuyển qua mã của bạn.

nhập mô tả hình ảnh ở đây

Bây giờ, để kết hợp tất cả lại với nhau:

Chạy bot

Để chạy bot của bạn với người khác, bạn cần chạy jar trên trang phát hành. Dưới đây là danh sách các cờ:

  • --iterations( -i) <= int(mặc định500 )
    • Chỉ định số lượng trò chơi để chạy.
  • --test-bot( -t) <=String
    • Chỉ chạy các trò chơi mà bot được bao gồm trong.
  • --directory( -d) <= Đường dẫn
    • Các thư mục để chạy đệ trình từ. Sử dụng điều này để chạy bot của bạn. Đảm bảo rằng các bot của bạn nằm trong thư mục con của đường dẫn có tên java.
  • --question-id( -q) <= int(chỉ sử dụng 126815)
    • Tải về và biên dịch các bài nộp khác từ trang web.
  • --random-seed( -r) <= int(mặc định là số ngẫu nhiên)
    • Đưa hạt giống cho người chạy để các bot sử dụng ngẫu nhiên có thể có kết quả được sao chép.
  • --gui( -g)
    • Chạy trình gỡ lỗi ui thay vì chạy một giải đấu. Sử dụng tốt nhất với --test-bot.
  • --multi-thread( -m) <= boolean(mặc địnhtrue )
    • Chạy một tournoment trong chế độ đa luồng. Điều này cho phép kết quả nhanh hơn nếu máy tính của bạn có nhiều lõi.
  • --thread-count( -c) <= int(mặc định4 )
    • Số lượng luồng để chạy nếu đa luồng được cho phép.
  • --help( -h)
    • In một thông điệp trợ giúp tương tự như thế này.

Để chạy tất cả các bài nộp trên trang này, sử dụng java -jar SplixKoTH-all.jar -q 126815.

Định dạng bài viết của bạn

Để đảm bảo rằng bộ điều khiển có thể tải xuống tất cả các bot, bạn nên làm theo định dạng này.

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

Ngoài ra, không sử dụng khai báo gói.


Bảng điểm

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

Vui lòng cho tôi biết nếu bất kỳ phần nào của quy tắc không rõ ràng hoặc nếu bạn tìm thấy bất kỳ lỗi nào trong bộ điều khiển trong phòng trò chuyện .

Chúc vui vẻ!


Này, điều này cuối cùng đã được đăng! Tôi đã tự hỏi: D
MD XF

Bạn đã chờ đợi bao lâu rồi? ;) Bạn có kế hoạch nộp?
J Atkin

Tôi không biết liệu tôi có thể giải quyết một thử thách như thế này hay không, vì tôi chủ yếu viết các chương trình bằng tiếng esolang. Nhưng tôi đã nhìn thấy nó trong hộp cát và nó trông giống như một thử thách lớn!
MD XF

@hyperneutrino Tôi đã xem bản chỉnh sửa, nó có thực sự làm phiền bạn không? Sự đúng đắn về chính trị không ở đâu trong nội dung của bài đăng này, và nó hoàn toàn chính xác về ngữ pháp tiếng Anh ...
J Atkin

2
0.o thế giới nhỏ bé? Tôi biết (của) nhà phát triển của splix.io. (Tweet này @ anh ấy)
CAD97

Câu trả lời:


2

ImNotACoward, Java

Bot này là một chuyên gia sinh tồn hèn nhát . Nếu không có kẻ thù ở gần, anh ta đòi một phần đất. Nếu vòng lặp của người chơi khác có thể đạt được một cách an toàn, anh ta đâm người chơi khác ở phía sau đấu với người chơi khác trong một trận đấu tay đôi. Nếu người chơi khác không thể bị tấn công an toàn, anh ta chạy trốn thực hiện một cuộc rút lui chiến lược đến vùng đất của mình.

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

Bẫy, 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];
    }
}

Đây có lẽ là bot đơn giản nhất. Tất cả những gì nó làm là vạch ra rìa của bảng, nhân đôi chính nó để giảm nguy cơ bị giết.


Thật tuyệt khi thấy bạn đã sử dụng Bộ sưu tập Eclipse. Có một giao diện Cặp trong EC. Bạn có thể sử dụng Tuples.pair () để lấy ví dụ Ghép đôi. Ngoài ra còn có một lớp PrimitiveTuples nếu một hoặc cả hai giá trị trong cặp là nguyên thủy.
Donald Raab

1

Random_bot, Clojure

Đây là RandomBot , nhưng tôi đã phải tuân theo các quy ước đặt tên và một số vấn đề ngăn tôi sử dụng dấu gạch nối trong tên, vì vậy nhấn mạnh sự trị vì! Các make-movefn trả về một vec với mục đầu tiên là Directionbạn muốn di chuyển trong, và lần thứ hai là trạng thái mà bạn muốn được thông qua lại với bạn vào lần lượt tiếp theo. Không sử dụng bất kỳ nguyên tử bên ngoài nào, vì mã này có thể chạy song song nhiều trò chơi.

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

}

Một trong những bot cơ bản nhất. Nó tìm kiếm bảng để tìm những điểm khác để giết người khác, và nó sẽ đi theo con đường ngắn nhất có thể để đến vị trí giết người. Nếu nó ở ngoài lãnh thổ của nó, nó sẽ thực hiện các bước di chuyển ngẫu nhiên cho đến khi nó có một lối mở khác để giết một người chơi khác. Nó có một số logic để ngăn chặn nó chạy qua chính nó, và khi tất cả những người chơi khác đã chết, nó sẽ quay trở về nhà của nó. Khi về nhà nó chỉ đi trong một hình vuông nhỏ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.