Java - Splix.io - Король Земли

  • Автор темы MrPorter
  • Обновлено
  • 22, Oct 2024
  • #1

Ты предприимчивая точка который хочет увеличить земли под своим контролем. Это довольно просто: выйдите за пределы своей нынешней земли и вернитесь на свою землю, и все, что находится в этой петле, теперь принадлежит вам. Но есть одна загвоздка. Если какая-то другая точка каким-то образом найдет вашу петлю и пересечет ее, вы умрете.

Если вы еще не пробовали, зайдите на Splix.io и попробуйте игру. Используйте клавиши со стрелками, чтобы контролировать свое движение.

гифка

java - Splix.io - Король земли

Кредит: http://splix.io/

Особенности

Все игроки начинают со случайных позиций на доске 200x200. (Оставляю за собой право изменить это :). У вас будет определенное количество ходов, чтобы набрать как можно больше очков. Баллы подсчитываются по:

  • Количество убитых вами игроков, умноженное на 300
  • Количество земли, которой вы владеете в конце раунда

Это поднимает вопрос о том, что другие могут украсть вашу землю. Если они начнут петлю, пересекающую часть вашей земли, они смогут претендовать на нее. Если вы умрете во время раунда, вы потеряете все очки за этот раунд.

В каждом раунде участвует случайно выбранная группа игроков (максимум 5 уникальных игроков) (возможны изменения). Каждый игрок участвует в равном количестве раундов. Итоговый результат вашего бота определяется его средним баллом за игру. Каждая игра состоит из 2000 ходов (также возможны изменения). Все боты делают свои ходы одновременно.

Случаи смерти

Голова

java - Splix.io - Король земли

Оба игрока умирают, когда сталкиваются головой. Это по-прежнему верно, даже когда оба игрока находятся на краю своего пространства.

java - Splix.io - Король земли

Однако, когда только один из игроков находится на своей земле, другой игрок умирает.

java - Splix.io - Король земли

Линия Креста

java - Splix.io - Король земли

В этом случае умирает только фиолетовый игрок.

Нельзя переступать свою линию.

java - Splix.io - Король земли

Выход из доски

java - Splix.io - Король земли

Если игрок попытается покинуть доску, он умрет и потеряет все очки.

Область захвата

Игрок захватит территорию, когда у него появится след и он снова войдет на свою землю.

java - Splix.io - Король земли

Красный цвет заполняет пространство между двумя красными линиями. Единственный случай, когда игрок не заполняет поле, — это когда другой игрок находится внутри цикла. Чтобы внести ясность, это применимо только тогда, когда в курсе событий сам другой игрок, а не только принадлежащая ему земля. Игрок может захватить землю у другого человека. Если игрок не может заполнить область, окруженную своим следом, след преобразуется в обычную землю. Если игрок внутри петли приземления другого игрока умирает, область в этой петле заполняется. Каждый раз, когда игрок умирает, доска снова просматривается в поисках области, которую можно заполнить.

Детали контроллера

Контроллер здесь. Она очень похожа на оригинальную игру, но в нее были внесены небольшие изменения, чтобы лучше подходить для KotH, а также по техническим причинам. Он построен с @НатанМеррилл's Библиотека КотХКомм, а также при существенной помощи @NathanMerrill. Пожалуйста, сообщите мне о любых ошибках, которые вы обнаружите в контроллере в чат. Чтобы соответствовать KotHComm, я использовал коллекции Eclipse во всем контроллере, но ботов можно писать только с использованием библиотеки Java Collections.

Все упаковано в убержар на упаковке. страница релизов на github. Чтобы использовать его, загрузите его и прикрепите к своему проекту, чтобы можно было использовать его для автозаполнения (инструкции по IntelliJ, Затмение). Чтобы проверить свои материалы, вы запускаете jar с помощью

 
 +------+--------------+-----------+
| Rank | Name         |     Score |
+------+--------------+-----------+
|    1 | ImNotACoward | 8940444.0 |
|    2 | TrapBot      |  257328.0 |
|    3 | HunterBot    |  218382.0 |
+------+--------------+-----------+
 
. Ensure that [BotName], Java // this is a header // any explanation you want [BotName].java // filename, in the codeblock [code] имеет подпапку с именем java -jar SplixKoTH-all.jar -q 126815 , and to place all your files there. Do not use package names in your bots (although it may be possible with KotHComm, it's just a bit more trouble). To see all options, use -h . Чтобы загрузить всех ботов, используйте --help .

Написание бота

Чтобы начать писать бота, необходимо расширить 4 .

  • int
    • Здесь вы решаете, какой ход должен сделать ваш бот. Не должен возвращать ноль.
  • -c
    • Получите --thread-count версия true . Useful for comparing your bot to the board.

boolean

  • Ценности
    • -m (х = 1; у = 0)
    • --multi-thread (х = -1; у = 0)
    • --test-bot (х = 0; у = 1)
    • -g (х = 0; у = -1)
  • --gui
    • Получите int который вы получите, если повернете налево.
  • -r
    • Получите --random-seed что вы получите, если повернете направо.

126815

Это класс, где вы получаете доступ к доске. Вы можете либо получить локальный вид (20x20) доски с показанными позициями игроков, либо глобальный вид (всю доску) только с информацией о том, кто владеет и претендует на позиции на доске. Здесь вы также получите свою позицию.

  • int
    • Узнайте размер доски.
  • -q
    • Получите глобальную карту доски.
  • --question-id
    • То же, что java , except that it is limited to a 20x20 area around your player, and that it shows player positions.
  • -d
    • Получите позицию вашего игрока. Использовать как --directory .
  • String
    • Получите свою позицию на доске. Использование: -t

--test-bot

500 only provides access to the number of turns left in the game through int .

-i

  • --iterations
    • Получите makeMove version of who is claiming a point - claiming = a trail.
  • --gui
    • Узнайте, кому принадлежит точка.
  • random_bot
    • Если игрок находится в этой точке, верните его скрытую версию. Работает только в SplixKoTH-all.jar .

int cartesianDistance(Point2D other)

В отличие от других классов здесь, maxY is contained in the KotHComm library. y

  • Point2D wrapY(int maxY)
  • maxX
  • x
  • Point2D wrapX(int maxX)
  • Point2D moveY(int y)
  • Point2D moveX(int x)
    • Оберните int getY() value to be within the range of int getX() .
  • Point2D(int x, int y)
    • Оберните com.nmerrill.kothcomm.game.maps.Point2D value to be within the range of Point2D .
  • Point2D
    • Это означает, сколько ходов потребуется игроку, чтобы переместиться из точки А в точку Б.

Поддержка Clojure

Компилятор Clojure поставляется в комплекте с getLocal() , so you can use Clojure for your bot! Refer to my HiddenPlayer getWhosOnSpot() чтобы увидеть, как его использовать.

Отладка бота

Контроллер поставляется с отладчиком, помогающим тестировать стратегии. Чтобы запустить его, запустите jar с помощью команды HiddenPlayer getOwner() option.

Чтобы прикрепить отладчик к вашей банке, следуйте эти инструкции для IntelliJ или эти инструкции для Eclipse (версия Eclipse не проверена).

java - Splix.io - Король земли

Если вы используете отладчик со своим кодом, вы можете использовать его, чтобы визуализировать то, что видит ваш бот. Установите точку останова в начале HiddenPlayer on your bot, and ensure that it only pauses the current thread. Next, click the start button on the UI and step through your code.

java - Splix.io - Король земли

Теперь, чтобы собрать все это воедино:

Запуск ботов

Чтобы запускать своих ботов вместе с другими, вам нужно запустить jar на странице релизов. Вот список флагов:

  • HiddenPlayer getClaimer() ( ReadOnlySplixPoint ) <= int getRemainingIterations() (default ReadOnlyGame )
    • Укажите количество игр для запуска.
  • ReadOnlyGame ( Point2D mypos = getSelfPosition(board) ) <= Point2D getSelfPosition(ReadOnlyBoard)
    • Запускайте только те игры, в которые включен бот.
  • board.getPosition(this) ( Point2D getPosition(SplixPlayer me) ) <= Путь
    • Каталог, из которого будут отправляться материалы. Используйте это для запуска своих ботов. Убедитесь, что ваши боты находятся в подпапке пути с именем getGlobal() .
  • MutableMap<com.nmerrill.kothcomm.game.maps.Point2D,ReadOnlySplixPoint> getView() ( MutableMap<com.nmerrill.kothcomm.game.maps.Point2D,ReadOnlySplixPoint> getGlobal() ) <= SquareRegion getBounds() (only use ReadOnlyBoard )
    • Загрузите и скомпилируйте другие материалы с сайта.
  • Direction ( Direction RightTurn() ) <= Direction (defaults to a random number)
    • Дайте начальное значение бегуну, чтобы боты, использующие случайный код, могли воспроизводить результаты.
  • Direction leftTurn() ( South )
    • Запустите пользовательский интерфейс отладчика вместо запуска турнира. Лучше всего использовать с North .
  • West ( East ) <= enum Direction (default this )
    • Запустите турнир в многопоточном режиме. Это обеспечивает более быстрый результат, если ваш компьютер имеет несколько ядер.
  • HiddenPlayer ( HiddenPlayer getThisHidden() ) <= Direction makeMove(ReadOnlyGame game, ReadOnlyBoard board) (default SplixPlayer )
    • Количество потоков, которые будут выполняться, если разрешена многопоточность.
  • --question-id 126815 ( --help )
    • Напечатайте справочное сообщение, подобное этому.

Чтобы запустить все материалы на этой странице, используйте java .

Форматирование вашего сообщения

Чтобы контроллер мог загружать всех ботов, вам следует следовать этому формату.

path\to\submissions\folder

Кроме того, не используйте объявление пакета.


Табло

java -jar SplixKoTH-all.jar -d path\to\submissions\folder

Пожалуйста, дайте мне знать, если какая-либо часть правил неясна или если вы обнаружите какие-либо ошибки в контроллере в чат.

Веселиться!

#царь горы #java

MrPorter


Рег
21 Nov, 2005

Тем
79

Постов
220

Баллов
625
  • 26, Oct 2024
  • #2

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

}
 
||answer||

ТрапБот, Java

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])

Это, пожалуй, самый простой бот. Все, что он делает, это обводит край доски, сгибая его, чтобы снизить риск быть убитым.

 

Lastofangels


Рег
29 May, 2006

Тем
61

Постов
219

Баллов
544
  • 26, Oct 2024
  • #3

случайный_бот, Clojure

Это СлучайныйБот, но мне пришлось придерживаться соглашений об именах, и некоторые проблемы не позволяют мне использовать дефис в имени, поэтому господствует подчеркивание! Direction fn returns a vec with the first item being the make-move вы хотите переехать, а второе — это состояние, которое вы хотите вернуть вам на следующем ходу. Не используйте никакие внешние атомы, поскольку этот код может запускать несколько игр параллельно.

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

HunterBot, Java

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

Один из самых простых ботов. Он ищет на игровом поле места, где можно убить других, и следует по кратчайшему пути, чтобы добраться до позиции для убийства. Если он находится за пределами своей территории, он будет совершать случайные движения, пока не появится еще одна возможность убить другого игрока. У него есть некоторая логика, которая не позволяет ему переехать себя, и когда все остальные игроки мертвы, он возвращается в свой дом. Вернувшись домой, он просто идет на небольшую площадь.

 

Fenek Fox


Рег
07 Dec, 2020

Тем
81

Постов
203

Баллов
618
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно