Открытое соревнование по программированию искусственного интеллекта

Быстрый старт

Проект

Песочница

Раунд 1

Раунд 2

Финал

Песочница на 24 декабря 2017 г.

Последние комментарии

19 апреля 07:29: mayduavongts написал комментарий в посте Быстрый старт
10 апреля 01:54: Eugene713 написал комментарий в посте Закрытие Russian AI Cup 2017
2 апреля 12:01: newpuk написал комментарий в посте Закрытие Russian AI Cup 2017
29 марта 18:31: AlexKol написал комментарий в посте Закрытие Russian AI Cup 2017
27 марта 16:47: alkozel написал комментарий в посте Закрытие Russian AI Cup 2017
24 марта 18:34: M-Mad написал комментарий в посте Закрытие Russian AI Cup 2017
1 февраля 00:30: jurifoll написал комментарий в посте Утилита Repeater
24 января 15:07: MikeWazowski написал комментарий в посте Закрытие Russian AI Cup 2017
24 января 15:01: AlexKol написал комментарий в посте Закрытие Russian AI Cup 2017
24 января 13:34: MikeWazowski написал комментарий в посте Закрытие Russian AI Cup 2017

Группа ВКонтакте

Telegram-чат

 

Ниже мы расскажем, как присоединиться к CodeWars буквально за несколько минут.

Зарегистрируйтесь

Разумеется, для участия необходимо зарегистрироваться. Мы убедительно просим всех участников использовать достоверные и полные данные о себе. Загружайте аватарки — всем интересно знать противников в лицо.

Скачайте языковой пакет

Скачайте пакет для любимого языка программирования со страницы языковые пакеты. Поддерживаются C++, Java, C#, Pascal, Python2, Python3 и Ruby. Распакуйте ZIP-архив в удобное для вас место и откройте существующий проект или создайте новый с нуля. Для некоторых IDE мы уже подготовили проекты. Возможно, вам надо будет настроить некоторые пути.

Скачайте Local runner

Local runner — это специальная версия симулятора игры для участников. Local runner предоставляет вам возможность запускать тестовые игры локально на своём компьютере. Подробнее об этом здесь.

Прочитайте документацию

В разделе Правила опубликованы официальные и полные правила, обязательно прочитайте их. Некоторые организационные моменты вы можете найти в описаниях Песочницы и этапов чемпионата (Раунд 1, Раунд 2, Финал).

Отошлите свою стратегию

Это можно сделать на странице отослать стратегию. Прежде, чем система примет вашу стратегию, она будет скомпилирована и протестирована в нескольких коротких играх. Если всё в порядке, ваша стратегия автоматически начнёт участвовать в регулярных квалификационных играх Песочницы. Внимательно изучите в секции “На что стоит обратить внимание” различные моменты, вследствие которых ваша стратегия может получить вердикт “Ошибка верификации”. Суммарное количество посылок не ограничено, однако в системе есть ограничения на слишком частую отправку стратегий, а любые попытки дестабилизировать работу системы приведут к дисквалификации. Вы можете написать свою стратегию в произвольном количестве файлов, вам нужно будет лишь упаковать всё необходимое в ZIP-архив и отослать его. Все файлы должны находиться в корне архива. К сожалению, создание пользовательских пакетов в стратегии на Java недопустимо. Помните, что в стартовом пакете вы можете менять только файл MyStrategy.${ext} (где ${ext} — расширение используемого вами языка), и даже если вы измените какой-то другой файл и тоже приложите его в архив, всё равно при тестировании он будет заменён на стандартный (кроме MyStrategy.h в C++).

На что стоит обратить внимание

  • запрещается взаимодействие с сетью, файловой системой и другими ресурсами, кроме оперативной памяти и текущего каталога, нарушители будут дисквалифицированы;
  • процессорное время работы вашей стратегии достаточно сильно ограничено (точные сведения вы можете найти в документации);
  • запускаемая стратегия не должна использовать более 256 мегабайт оперативной памяти (в это количество включается вся память, используемая запускаемым процессом);
  • если ваша стратегия превышает ограничение по времени или памяти, а также в случае ошибок исполнения (например, неожиданное падение), она перестаёт участвовать в этой игре, при этом как бы “замораживается”, то есть ваши очки не обнуляются;
  • стратегия каждого участника запускается в отдельном процессе.

Напишем простую стратегию на Java

Простейшая стратегия ничего не делает и никуда не перемещается (в этом можно убедиться, отослав код в систему):

import model.*;

public final class MyStrategy implements Strategy {
    @Override
    public void move(Player me, World world, Game game, Move move) {
    }
}

Теперь выделим наши войска и отправим их по направлению к противнику на следующем тике. Метод move примет вид:

public void move(Player me, World world, Game game, Move move) {
    if (world.getTickIndex() == 0) {
        move.setAction(ActionType.CLEAR_AND_SELECT);
        move.setRight(world.getWidth());
        move.setBottom(world.getHeight());
        return;
    }

    if (world.getTickIndex() == 1) {
        move.setAction(ActionType.MOVE);
        move.setX(world.getWidth() / 2.0D);
        move.setY(world.getHeight() / 2.0D);
    }
}

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

Теперь напишем более сложный код. Пусть наша техника атакует ближайшего видимого противника. Если противник не найден, будем просто двигаться в центр карты. Попробуйте самостоятельно разобраться, как работает приведённая далее стратегия. В коде присутствуют подробные комментарии, которые помогут вам в этом.

import model.*;

import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Stream;

@SuppressWarnings({"UnsecureRandomNumberGeneration", "FieldCanBeLocal", "unused", "OverlyLongMethod"})
public final class MyStrategy implements Strategy {
    /**
     * Список целей для каждого типа техники, упорядоченных по убыванию урона по ним.
     */
    private static final Map<VehicleType, VehicleType[]> preferredTargetTypesByVehicleType;

    static {
        preferredTargetTypesByVehicleType = new EnumMap<>(VehicleType.class);

        preferredTargetTypesByVehicleType.put(VehicleType.FIGHTER, new VehicleType[] {
                VehicleType.HELICOPTER, VehicleType.FIGHTER
        });

        preferredTargetTypesByVehicleType.put(VehicleType.HELICOPTER, new VehicleType[] {
                VehicleType.TANK, VehicleType.ARRV, VehicleType.HELICOPTER, VehicleType.IFV, VehicleType.FIGHTER
        });

        preferredTargetTypesByVehicleType.put(VehicleType.IFV, new VehicleType[] {
                VehicleType.HELICOPTER, VehicleType.ARRV, VehicleType.IFV, VehicleType.FIGHTER, VehicleType.TANK
        });

        preferredTargetTypesByVehicleType.put(VehicleType.TANK, new VehicleType[] {
                VehicleType.IFV, VehicleType.ARRV, VehicleType.TANK, VehicleType.FIGHTER, VehicleType.HELICOPTER
        });
    }

    private Random random;

    private TerrainType[][] terrainTypeByCellXY;
    private WeatherType[][] weatherTypeByCellXY;

    private Player me;
    private World world;
    private Game game;
    private Move move;

    private final Map<Long, Vehicle> vehicleById = new HashMap<>();
    private final Map<Long, Integer> updateTickByVehicleId = new HashMap<>();
    private final Queue<Consumer<Move>> delayedMoves = new ArrayDeque<>();

    /**
     * Основной метод стратегии, осуществляющий управление армией. Вызывается каждый тик.
     *
     * @param me    Информация о вашем игроке.
     * @param world Текущее состояние мира.
     * @param game  Различные игровые константы.
     * @param move  Результатом работы метода является изменение полей данного объекта.
     */
    @Override
    public void move(Player me, World world, Game game, Move move) {
        initializeStrategy(world, game);
        initializeTick(me, world, game, move);

        if (me.getRemainingActionCooldownTicks() > 0) {
            return;
        }

        if (executeDelayedMove()) {
            return;
        }

        move();

        executeDelayedMove();
    }

    /**
     * Инциализируем стратегию.
     * <p>
     * Для этих целей обычно можно использовать конструктор, однако в данном случае мы хотим инициализировать генератор
     * случайных чисел значением, полученным от симулятора игры.
     */
    private void initializeStrategy(World world, Game game) {
        if (random == null) {
            random = new Random(game.getRandomSeed());

            terrainTypeByCellXY = world.getTerrainByCellXY();
            weatherTypeByCellXY = world.getWeatherByCellXY();
        }
    }

    /**
     * Сохраняем все входные данные в полях класса для упрощения доступа к ним, а также актуализируем сведения о каждой
     * технике и времени последнего изменения её состояния.
     */
    private void initializeTick(Player me, World world, Game game, Move move) {
        this.me = me;
        this.world = world;
        this.game = game;
        this.move = move;

        for (Vehicle vehicle : world.getNewVehicles()) {
            vehicleById.put(vehicle.getId(), vehicle);
            updateTickByVehicleId.put(vehicle.getId(), world.getTickIndex());
        }

        for (VehicleUpdate vehicleUpdate : world.getVehicleUpdates()) {
            long vehicleId = vehicleUpdate.getId();

            if (vehicleUpdate.getDurability() == 0) {
                vehicleById.remove(vehicleId);
                updateTickByVehicleId.remove(vehicleId);
            } else {
                vehicleById.put(vehicleId, new Vehicle(vehicleById.get(vehicleId), vehicleUpdate));
                updateTickByVehicleId.put(vehicleId, world.getTickIndex());
            }
        }
    }

    /**
     * Достаём отложенное действие из очереди и выполняем его.
     *
     * @return Возвращает {@code true}, если и только если отложенное действие было найдено и выполнено.
     */
    private boolean executeDelayedMove() {
        Consumer<Move> delayedMove = delayedMoves.poll();
        if (delayedMove == null) {
            return false;
        }

        delayedMove.accept(move);
        return true;
    }

    /**
     * Основная логика нашей стратегии.
     */
    private void move() {
        // Каждые 180 тиков ...
        if (world.getTickIndex() % 180 == 0) {
            // ... для каждого типа техники ...
            for (VehicleType vehicleType : VehicleType.values()) {
                VehicleType[] targetTypes = preferredTargetTypesByVehicleType.get(vehicleType);

                // ... если этот тип может атаковать ...
                if (targetTypes == null || targetTypes.length == 0) {
                    continue;
                }

                // ... получаем центр формации ...
                double x = streamVehicles(
                        Ownership.ALLY, vehicleType
                ).mapToDouble(Vehicle::getX).average().orElse(Double.NaN);

                double y = streamVehicles(
                        Ownership.ALLY, vehicleType
                ).mapToDouble(Vehicle::getY).average().orElse(Double.NaN);

                // ... получаем центр формации противника или центр мира ...
                double targetX = Arrays.stream(targetTypes).map(
                        targetType -> streamVehicles(
                                Ownership.ENEMY, targetType
                        ).mapToDouble(Vehicle::getX).average().orElse(Double.NaN)
                ).filter(Double::isFinite).findFirst().orElseGet(
                        () -> streamVehicles(
                                Ownership.ENEMY
                        ).mapToDouble(Vehicle::getX).average().orElse(world.getWidth() / 2.0D)
                );

                double targetY = Arrays.stream(targetTypes).map(
                        targetType -> streamVehicles(
                                Ownership.ENEMY, targetType
                        ).mapToDouble(Vehicle::getY).average().orElse(Double.NaN)
                ).filter(Double::isFinite).findFirst().orElseGet(
                        () -> streamVehicles(
                                Ownership.ENEMY
                        ).mapToDouble(Vehicle::getY).average().orElse(world.getHeight() / 2.0D)
                );

                // .. и добавляем в очередь отложенные действия для выделения и перемещения техники.
                if (!Double.isNaN(x) && !Double.isNaN(y)) {
                    delayedMoves.add(move -> {
                        move.setAction(ActionType.CLEAR_AND_SELECT);
                        move.setRight(world.getWidth());
                        move.setBottom(world.getHeight());
                        move.setVehicleType(vehicleType);
                    });

                    delayedMoves.add(move -> {
                        move.setAction(ActionType.MOVE);
                        move.setX(targetX - x);
                        move.setY(targetY - y);
                    });
                }
            }

            // Также находим центр формации наших БРЭМ ...
            double x = streamVehicles(
                    Ownership.ALLY, VehicleType.ARRV
            ).mapToDouble(Vehicle::getX).average().orElse(Double.NaN);

            double y = streamVehicles(
                    Ownership.ALLY, VehicleType.ARRV
            ).mapToDouble(Vehicle::getY).average().orElse(Double.NaN);

            // .. и отправляем их в центр мира.
            if (!Double.isNaN(x) && !Double.isNaN(y)) {
                delayedMoves.add(move -> {
                    move.setAction(ActionType.CLEAR_AND_SELECT);
                    move.setRight(world.getWidth());
                    move.setBottom(world.getHeight());
                    move.setVehicleType(VehicleType.ARRV);
                });

                delayedMoves.add(move -> {
                    move.setAction(ActionType.MOVE);
                    move.setX(world.getWidth() / 2.0D - x);
                    move.setY(world.getHeight() / 2.0D - y);
                });
            }

            return;
        }

        // Если ни один наш юнит не мог двигаться в течение 60 тиков ...
        if (streamVehicles(Ownership.ALLY).allMatch(
                vehicle -> world.getTickIndex() - updateTickByVehicleId.get(vehicle.getId()) > 60
        )) {
            // ... находим центр нашей формации ...
            double x = streamVehicles(Ownership.ALLY).mapToDouble(Vehicle::getX).average().orElse(Double.NaN);
            double y = streamVehicles(Ownership.ALLY).mapToDouble(Vehicle::getY).average().orElse(Double.NaN);

            // ... и поворачиваем её на случайный угол.
            if (!Double.isNaN(x) && !Double.isNaN(y)) {
                delayedMoves.add(move -> {
                    move.setAction(ActionType.CLEAR_AND_SELECT);
                    move.setRight(world.getWidth());
                    move.setBottom(world.getHeight());
                });

                delayedMoves.add(move -> {
                    move.setAction(ActionType.ROTATE);
                    move.setX(x);
                    move.setY(y);
                    move.setAngle(random.nextBoolean() ? StrictMath.PI : -StrictMath.PI);
                });
            }
        }
    }

    private Stream<Vehicle> streamVehicles(Ownership ownership, VehicleType vehicleType) {
        Stream<Vehicle> stream = vehicleById.values().stream();

        switch (ownership) {
            case ALLY:
                stream = stream.filter(vehicle -> vehicle.getPlayerId() == me.getId());
                break;
            case ENEMY:
                stream = stream.filter(vehicle -> vehicle.getPlayerId() != me.getId());
                break;
            default:
        }

        if (vehicleType != null) {
            stream = stream.filter(vehicle -> vehicle.getType() == vehicleType);
        }

        return stream;
    }

    private Stream<Vehicle> streamVehicles(Ownership ownership) {
        return streamVehicles(ownership, null);
    }

    private Stream<Vehicle> streamVehicles() {
        return streamVehicles(Ownership.ANY);
    }

    private enum Ownership {
        ANY,

        ALLY,

        ENEMY
    }
}

Понятно, что это не самая эффективная стратегия и шансов выиграть у неё немного, но это всего-лишь пример. Удачи!

P.S. Здесь вы можете найти неофициальную версию стратегии «Быстрый старт» на языке C#.



amurushkin

amurushkin

ХНУРЭ (бывш. ХИРЭ, ХТУРЭ)

так все же как задается движение? через координаты или относительное смещение? если через смещение, то почему в первом случае стратегия едет ровно до середины экрана и останавливается, а не продолжает движение?

07.11.2017 23:47:24
Dfire

Dfire

КРОК

А вы гарантируете hash и equals для Unit и Vehicle ?

07.11.2017 23:59:24
serlis

serlis

Харьковский НУ им. Каразина

amurushkin

amurushkin

ХНУРЭ (бывш. ХИРЭ, ХТУРЭ)

так все же как задается движение? через координаты или относительное смещение? если через смещение, то почему в первом случае стратегия едет ровно до середины экрана и останавливается, а не продолжает движение?

Вы указываете максимальное смещение (если указать пол карты, то вы как-раз доедите до середины)

08.11.2017 0:24:35
Nemzs1337

Nemzs1337

Университет ИТМО

А можно поинтересоваться, с чем связано отсутствие метода “Получить всю технику вне тумана войны”? Это ведь достаточно неудобно работать с обновлениями техники

09.11.2017 21:51:05
GreenTea

GreenTea

ISDDesign

Nemzs1337

Nemzs1337

Университет ИТМО

А можно поинтересоваться, с чем связано отсутствие метода “Получить всю технику вне тумана войны”? Это ведь достаточно неудобно работать с обновлениями техники

Техники очень много и передавать всю информацию о ней каждый тик было бы накладно. Поэтому передается только изменяемая часть состояния. Вы можете сами в коде вести актуальный список юнитов и обновлять его - это не сложно реализовать.

09.11.2017 22:31:07
tyamgin

tyamgin

Симферополь

Я правильно понимаю, что вы не рекомендуете хранить объекты модели с предыдущих тиков, но сами же храните их в карте vehicleById?

09.11.2017 23:15:04
Jeners

Jeners

Москва

А почему нельзя было реализовать обновление массива данных о юнитах по средствам API? Ну т.е. хранить данные об объектах в теле некоего класса, автоматически их туда добавлять, ну и обновлять “по ходу пьесы” т.е. по сути реализовать то что, требуется реализовать от участников, но при этом чтобы оно было изначально вшито в API? Просто не совсем понятны телодвижения в этом направлении

09.11.2017 23:54:52
GS_Aero

GS_Aero

ИП

amurushkin

amurushkin

ХНУРЭ (бывш. ХИРЭ, ХТУРЭ)

так все же как задается движение? через координаты или относительное смещение? если через смещение, то почему в первом случае стратегия едет ровно до середины экрана и останавливается, а не продолжает движение?

Т.к. это вектор, то будет смещение на длину вектора.

10.11.2017 16:26:34
GS_Aero

GS_Aero

ИП

GS_Aero

GS_Aero

ИП

Т.к. это вектор, то будет смещение на длину вектора.

Блин, не так. В базовом примере указан вектор: Move.setAction(ActionType::MOVE); Move.setX(MyWorld->getWidth() / 2.0); Move.setY(MyWorld->getHeight() / 2.0); Смещаемся на половину размера карты, т.е. до середины.

10.11.2017 16:50:17
third112

“Теперь напишем более сложный код”. Этот 2й пример только на Яве :( ИМХО в руководстве он должен быть переведен на все поддерживаемые языковые пакеты, иначе они будут в неравных условиях.

11.11.2017 14:26:53
mrsergkr

mrsergkr

КемГУ

“Теперь напишем более сложный код”. Этот 2й пример только на Яве :( ИМХО в руководстве он должен быть переведен на все поддерживаемые языковые пакеты, иначе они будут в неравных условиях.

Я потратил часа полтора на то, чтобы переписать эту стратегию на c++. Это при том, что у меня знаний практически нет. Нормальный программист потратит ещё меньше времени. Так что ни о каком неравенстве речи не идет.

11.11.2017 17:43:32
mrsergkr

mrsergkr

КемГУ

tyamgin

tyamgin

Симферополь

Я правильно понимаю, что вы не рекомендуете хранить объекты модели с предыдущих тиков, но сами же храните их в карте vehicleById?

Если я не ошибаюсь, то говорили про объекты Player, World, Game и Move.

11.11.2017 17:47:29
alkozel

alkozel

Калужский филиал ГУ СДА при Спецстрое России

Люди добрые, помогите. Изучаю Java, не получается отсортировать поток хотя бы по координате x. Запутался в компараторах и ламбда-выражениях. Покажите простой пример. Спасибо

11.11.2017 17:59:19
third112
mrsergkr

mrsergkr

КемГУ

Я потратил часа полтора на то, чтобы переписать эту стратегию на c++. Это при том, что у меня знаний практически нет. Нормальный программист потратит ещё меньше времени. Так что ни о каком неравенстве речи не идет.

Если у Вас нет знаний, то почему Вы думаете, что перевели верно?

11.11.2017 18:24:15
alkozel

alkozel

Калужский филиал ГУ СДА при Спецстрое России

alkozel

alkozel

Калужский филиал ГУ СДА при Спецстрое России

Люди добрые, помогите. Изучаю Java, не получается отсортировать поток хотя бы по координате x. Запутался в компараторах и ламбда-выражениях. Покажите простой пример. Спасибо

вроде разобрался stream.sorted(Comparator.comparing(Vehicle::getX))

11.11.2017 18:38:30
Dimon777

Dimon777

Тула

При попытке отослать даже тестовую стратегию (ту, что написана в руководстве) идёт ошибка компиляции: MyStrategy.cpp: In member function ‘virtual void MyStrategy::move(const model::Player&, const model::World&, const model::Game&, model::Move&)’: MyStrategy.cpp:10:16: error: ‘ACTION_CLEAR_AND_SELECT’ was not declared in this scope move.setAction(ACTION_CLEAR_AND_SELECT); ^~~~~~~~~~~~~~~~~~~~~~~ MyStrategy.cpp:16:16: error: ‘ACTION_MOVE’ was not declared in this scope move.setAction(ACTION_MOVE); ^~~~~~~~~~~)

11.11.2017 18:46:23
Sanda

Sanda

JetBrains

Dimon777

Dimon777

Тула

При попытке отослать даже тестовую стратегию (ту, что написана в руководстве) идёт ошибка компиляции: MyStrategy.cpp: In member function ‘virtual void MyStrategy::move(const model::Player&, const model::World&, const model::Game&, model::Move&)’: MyStrategy.cpp:10:16: error: ‘ACTION_CLEAR_AND_SELECT’ was not declared in this scope move.setAction(ACTION_CLEAR_AND_SELECT); ^~~~~~~~~~~~~~~~~~~~~~~ MyStrategy.cpp:16:16: error: ‘ACTION_MOVE’ was not declared in this scope move.setAction(ACTION_MOVE); ^~~~~~~~~~~)

Попробуйте обновить языковой пакет

11.11.2017 18:54:21
Dimon777

Dimon777

Тула

Sanda

Sanda

JetBrains

Попробуйте обновить языковой пакет

тестовую стратегию отправлял не файлом, а вставив код в форму…

11.11.2017 18:57:00
infsega

infsega

Align Technology Inc

“Теперь напишем более сложный код”. Этот 2й пример только на Яве :( ИМХО в руководстве он должен быть переведен на все поддерживаемые языковые пакеты, иначе они будут в неравных условиях.

Наоборот, пока переписываешь код на свой язык, понимаешь, к чему он вообще :)

11.11.2017 18:57:24
Dimon777

Dimon777

Тула

Dimon777

Dimon777

Тула

тестовую стратегию отправлял не файлом, а вставив код в форму…

спасибо, кажись разобрался

11.11.2017 19:04:32
third112
infsega

infsega

Align Technology Inc

Наоборот, пока переписываешь код на свой язык, понимаешь, к чему он вообще :)

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

11.11.2017 20:05:19
alkozel

alkozel

Калужский филиал ГУ СДА при Спецстрое России

А смысл его переписывать? С этим кодом далеко не уйдешь))

11.11.2017 20:13:53
AlexKol

AlexKol

BB

alkozel

alkozel

Калужский филиал ГУ СДА при Спецстрое России

А смысл его переписывать? С этим кодом далеко не уйдешь))

Пфф, человек 500 точно будет со стратегией из примера)

11.11.2017 20:14:59
aabzac

aabzac

БГУИР

alkozel

alkozel

Калужский филиал ГУ СДА при Спецстрое России

А смысл его переписывать? С этим кодом далеко не уйдешь))

Ну я пока загрузил код из примера и выйти с ним в 1 раунд видимо не составит труда )

11.11.2017 21:43:11
Borisov

Borisov

НИТУ "МИСиС"

 private final Queue<Consumer<Move>> delayedMoves = new ArrayDeque<>();    
 delayedMoves.add(move -> {
                move.setAction(ActionType.CLEAR_AND_SELECT);
                move.setRight(world.getWidth());
                move.setBottom(world.getHeight());
                move.setVehicleType(VehicleType.ARRV);
            });

Не подскажете, как аналогичное реализовать в C++?

13.11.2017 1:40:14
SladeThe

SladeThe

Команда Russian AI Cup

alkozel

alkozel

Калужский филиал ГУ СДА при Спецстрое России

вроде разобрался stream.sorted(Comparator.comparing(Vehicle::getX))

В данном случае лучше использовать Comparator.comparingDouble, так как он работает с примитивным типом double, а Comparator.comparing преобразует значение в объект и сравнивает уже объекты, что значительно менее эффективно.

13.11.2017 2:22:21
SladeThe

SladeThe

Команда Russian AI Cup

Borisov

Borisov

НИТУ "МИСиС"

private final Queue<Consumer> delayedMoves = new ArrayDeque<>();
delayedMoves.add(move -> { move.setAction(ActionType.CLEAR_AND_SELECT); move.setRight(world.getWidth()); move.setBottom(world.getHeight()); move.setVehicleType(VehicleType.ARRV); }); …

Не знаю, как написать именно аналогичный код, но вы можете создавать новый объект Move и помещать его в очередь, а потом доставать его и копировать все поля.

13.11.2017 2:24:13
third112

Как вообще на Паскале выделить 10 юнитов, нпр., танков и послать их в точку с заданными координатами? Пробовал по разному - не работает. Может баг? А можно 10 танков послать в 10 разных точек за 1 тик? Мануалу явно не хватает примеров таких элементарных действий. Описание API слишком формальное, много второстепенных методов и добраться до основных за ограниченное время представляется проблематичным.

13.11.2017 10:46:41
AlexKol

Как вообще на Паскале выделить 10 юнитов, нпр., танков и послать их в точку с заданными координатами? Пробовал по разному - не работает. Может баг? А можно 10 танков послать в 10 разных точек за 1 тик? Мануалу явно не хватает примеров таких элементарных действий. Описание API слишком формальное, много второстепенных методов и добраться до основных за ограниченное время представляется проблематичным.

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

13.11.2017 10:48:30
third112

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

Спасибо, уже взял. Но идей про 10 танков это не принесло

13.11.2017 10:51:51
dimir

dimir

СПбГЭТУ (ЛЭТИ)

Спасибо, уже взял. Но идей про 10 танков это не принесло

10 танков в 10 разных точек нельзя. В принципе чтобы кого-то куда послать вам понадобится два действия - выделение и движение (CLEAR_AND_SELECT, MOVE).

В идеале - сначала создаёте группы, потом когда нужно отправить куда-то группу - CLEAR_AND_SELECT(номер группы), MOVE(dx, dy)

13.11.2017 10:59:34
third112
dimir

dimir

СПбГЭТУ (ЛЭТИ)

10 танков в 10 разных точек нельзя. В принципе чтобы кого-то куда послать вам понадобится два действия - выделение и движение (CLEAR_AND_SELECT, MOVE). В идеале - сначала создаёте группы, потом когда нужно отправить куда-то группу - CLEAR_AND_SELECT(номер группы), MOVE(dx, dy)

А как выделять? Только прямоугольником? Или можно по номеру (id) танка? Как быстро получить диапазон валидных номеров? Я не понимаю: цель стратегию сделать или ребус (т.е. невнятный мануал) разгадать? Я предполагал, что 10 танков в 10 мест за раз не послать. Это обычный недостаток всех игр с большим числом юнитов, поэтому многие интересные ИИ-решания в таких играх оказываются невозможны.

13.11.2017 11:08:14
AlexKol

AlexKol

BB

dimir

dimir

СПбГЭТУ (ЛЭТИ)

10 танков в 10 разных точек нельзя. В принципе чтобы кого-то куда послать вам понадобится два действия - выделение и движение (CLEAR_AND_SELECT, MOVE). В идеале - сначала создаёте группы, потом когда нужно отправить куда-то группу - CLEAR_AND_SELECT(номер группы), MOVE(dx, dy)

Да всё можно, 10 раз последовательно добавляем. Или выделяем и берем по типу, короче вариантов много.

13.11.2017 11:08:18
Scarlet

Не путайте человека. Вопрос был про один тик. Если за один тик последовательно послать 10 танков в 10 мест (CLEAR_AND_SELECT и MOVE), то вообще ничего не случится. От слова совсем. За один тик даже один танк не послать. За один тик можно сделать одно действие (CLEAR_AND_SELECT или MOVE или др.). Так что 10 танков в 10 мест это 20 действий = 20 тиков. А если вспомнить про лимит в 12 действий на 60 тиков, то можно понять, это игра не про управление каждым танчиком, а про балланс (наконец-то, после введения ЯУ) между размерами управляемых групп и лимитом действий. Впрочем, это всё должно было стать понятно из правил.

13.11.2017 23:03:03
dimir

dimir

СПбГЭТУ (ЛЭТИ)

Не путайте человека. Вопрос был про один тик. Если за один тик последовательно послать 10 танков в 10 мест (CLEAR_AND_SELECT и MOVE), то вообще ничего не случится. От слова совсем. За один тик даже один танк не послать. За один тик можно сделать одно действие (CLEAR_AND_SELECT или MOVE или др.). Так что 10 танков в 10 мест это 20 действий = 20 тиков. А если вспомнить про лимит в 12 действий на 60 тиков, то можно понять, это игра не про управление каждым танчиком, а про балланс (наконец-то, после введения ЯУ) между размерами управляемых групп и лимитом действий. Впрочем, это всё должно было стать понятно из правил.

Ну я так и написал в целом =)

13.11.2017 23:43:44
dimir

dimir

СПбГЭТУ (ЛЭТИ)

А как выделять? Только прямоугольником? Или можно по номеру (id) танка? Как быстро получить диапазон валидных номеров? Я не понимаю: цель стратегию сделать или ребус (т.е. невнятный мануал) разгадать? Я предполагал, что 10 танков в 10 мест за раз не послать. Это обычный недостаток всех игр с большим числом юнитов, поэтому многие интересные ИИ-решания в таких играх оказываются невозможны.

Выделять (CLEAR_AND_SELECT, ADD_TO_SELECTION, DESELECT) - ЛИБО прямоугольником (к прямоугольнику опционально добавляется тип юнитов [танк, к примеру], которых хотите выделить), ЛИБО номером группы.

13.11.2017 23:46:29
dimir

dimir

СПбГЭТУ (ЛЭТИ)

А как выделять? Только прямоугольником? Или можно по номеру (id) танка? Как быстро получить диапазон валидных номеров? Я не понимаю: цель стратегию сделать или ребус (т.е. невнятный мануал) разгадать? Я предполагал, что 10 танков в 10 мест за раз не послать. Это обычный недостаток всех игр с большим числом юнитов, поэтому многие интересные ИИ-решания в таких играх оказываются невозможны.

Если я правильно понял термин “диапазон валидных номеров”, то никак, так как выделять по id юнита нельзя, но Вы можете выбрать юнита по его id, получить его центр, вычислить прямоугольник размером 2*vehicleRadius x 2*vehicleRadius с центром в центре юнита, и отдать команду CLEAR_AND_SELECT с данным прямоугольником. И это, в общем случае, неэффективно, как заметил Scarlet в комментарии выше. Кроме случая когда вам нужно отправить одного единственного юнита куда-то там, допустим, на разведку.

13.11.2017 23:51:07
dimir

dimir

СПбГЭТУ (ЛЭТИ)

А как выделять? Только прямоугольником? Или можно по номеру (id) танка? Как быстро получить диапазон валидных номеров? Я не понимаю: цель стратегию сделать или ребус (т.е. невнятный мануал) разгадать? Я предполагал, что 10 танков в 10 мест за раз не послать. Это обычный недостаток всех игр с большим числом юнитов, поэтому многие интересные ИИ-решания в таких играх оказываются невозможны.

А ещё есть официальный Telegram канал (ссылка слева внизу), где Вам ответят на интересующие Вас вопросы гораздо быстрее.

13.11.2017 23:53:54
luckybet100

luckybet100

Москва

Помогите пожалуйста, запускаю compile_java.sh потом запускаю проект командой java -jar java-cgdk.jar, выдает такую ошибку no main manifest attribute, in java-cgdk.jar. Компилю просто самп, что делать?

16.11.2017 16:47:55
luckybet100

luckybet100

Москва

Система mac os high siera

16.11.2017 16:50:51
SladeThe

SladeThe

Команда Russian AI Cup

luckybet100

luckybet100

Москва

Помогите пожалуйста, запускаю compile_java.sh потом запускаю проект командой java -jar java-cgdk.jar, выдает такую ошибку no main manifest attribute, in java-cgdk.jar. Компилю просто самп, что делать?

У вас в манифесте JAR-файла не указан класс, запускаемый по умолчанию. Вам нужно либо изменить способ сборки JAR, либо способ запуска. Например, можно добавить ваш файл в classpath и явно указать запускаемый класс. Должно быть что-то вроде java -cp java-cgdk.jar Runner.

16.11.2017 19:12:47
dimir

dimir

СПбГЭТУ (ЛЭТИ)

SladeThe

SladeThe

Команда Russian AI Cup

У вас в манифесте JAR-файла не указан класс, запускаемый по умолчанию. Вам нужно либо изменить способ сборки JAR, либо способ запуска. Например, можно добавить ваш файл в classpath и явно указать запускаемый класс. Должно быть что-то вроде java -cp java-cgdk.jar Runner .

Ему уже в Telegram канале помогли.

16.11.2017 19:14:52
BaR5uk

BaR5uk

Карачев

Я прочитал документацию, но что-то так и не нашёл, как на каждом тике игры узнать, какими юнитами располагает моя стратегия и где они находятся. То есть, где они находятся понятно как узнать: в свойствах объекта, но как получить массив объектов с всеми юнитами?

18.11.2017 2:04:25
SladeThe

SladeThe

Команда Russian AI Cup

BaR5uk

BaR5uk

Карачев

Я прочитал документацию, но что-то так и не нашёл, как на каждом тике игры узнать, какими юнитами располагает моя стратегия и где они находятся. То есть, где они находятся понятно как узнать: в свойствах объекта, но как получить массив объектов с всеми юнитами?

Передавать такое количество юнитов каждый тик слишком ресурсозатратно. Поэтому полная информация о технике в мире отсутствует. В массиве new vehicles передаётся только новая техника, в vehicle updates — изменяемые поля. Вам нужно самостоятельно поддерживать актуальный список техники в мире, используя эти два массива. В “Быстром старте” есть пример, как это делать. Посмотрите метод initializeTick.

18.11.2017 2:11:34
lebed.salavat

“Implementation of the client-shell strategy in different languages may differ, but in general, not is guaranteed that for different calls to the method move as parameters to it will be passed references to the same objects. Thus, it is wrong, for example, to save references to objects world or vehicle and retrieve updated information about these objects in the following ticks, reading its fields.” - does it mean that example implementation is wrong? because it initializes terrainTypeByCellXY = world.getTerrainByCellXY(); weatherTypeByCellXY = world.getWeatherByCellXY(); only one in the game.

20.11.2017 8:52:47
kuviman

kuviman

СГУ им. Чернышевского

“Implementation of the client-shell strategy in different languages may differ, but in general, not is guaranteed that for different calls to the method move as parameters to it will be passed references to the same objects. Thus, it is wrong, for example, to save references to objects world or vehicle and retrieve updated information about these objects in the following ticks, reading its fields.” - does it mean that example implementation is wrong? because it initializes terrainTypeByCellXY = world.getTerrainByCellXY(); weatherTypeByCellXY = world.getWeatherByCellXY(); only one in the game.

It is not, since weather and terrain does not change during the game

20.11.2017 9:33:33
lebed.salavat
kuviman

kuviman

СГУ им. Чернышевского

It is not, since weather and terrain does not change during the game

yes, you right. I’ve just checked getWeatherByCellXY implementation and it returns new object (copy) of weatherByCellXY

20.11.2017 10:04:41
iamwhatiam

I don’t clearly understand how scale works. I have tried this.


if(tickIndex == 0)
{
mov->setAction(ActionType::CLEAR_AND_SELECT);
mov->setVehicleType(VehicleType::HELICOPTER);
}


if(tickIndex == 1)
{
mov->setAction(ActionType::SCALE);
mov->setX(unitPos[VehicleType::HELICOPTER].x);
mov->setY(unitPos[VehicleType::HELICOPTER].y);
mov->setFactor(10.0);
}



unitPos[VehicleType::HELICOPTER] is the point of the center of helicopter unit.

Can somebody give an example about how scale works. Thanks in advance.

21.11.2017 18:03:58
iamwhatiam

I don’t clearly understand how scale works. I have tried this. if(tickIndex == 0) { mov->setAction(ActionType::CLEAR_AND_SELECT); mov->setVehicleType(VehicleType::HELICOPTER); } if(tickIndex == 1) { mov->setAction(ActionType::SCALE); mov->setX(unitPos[VehicleType::HELICOPTER].x); …

Sorry, I have forgotten to give select rectangle. My bad :D

21.11.2017 18:14:03
GenNa

GenNa

Agilium Soft

Кто знает, какая версия руби используется для запуска стратегии на сервере?

21.11.2017 18:52:46
stulentsev

stulentsev

Москва

GenNa

GenNa

Agilium Soft

Кто знает, какая версия руби используется для запуска стратегии на сервере?

Не знаю точно какая, но jruby не из свежих. &. там еще не работает. :)

А вообще, выведи RUBY_VERSION, RUBY_PLATFORM и что там еще в stdout да и посмотри в логе.

21.11.2017 18:59:17
stulentsev

stulentsev

Москва

I don’t clearly understand how scale works. I have tried this. if(tickIndex == 0) { mov->setAction(ActionType::CLEAR_AND_SELECT); mov->setVehicleType(VehicleType::HELICOPTER); } if(tickIndex == 1) { mov->setAction(ActionType::SCALE); mov->setX(unitPos[VehicleType::HELICOPTER].x); …

That should have worked. Must be your x,y are not what you think they are. Double check that.

21.11.2017 19:05:17
SladeThe

SladeThe

Команда Russian AI Cup

stulentsev

stulentsev

Москва

Не знаю точно какая, но jruby не из свежих. &. там еще не работает. :) А вообще, выведи RUBY_VERSION, RUBY_PLATFORM и что там еще в stdout да и посмотри в логе.

Обновили JRuby до 9.1.14.0.

21.11.2017 21:35:33
MainParasit

MainParasit

Тверь

Мало информации по выбору управлению техникой. Не понимаю как мне поделить полк танков разделить в 4 группы? Как управлять группой? Кто мне расскажет? Потом я буду мать над стратегией :). Может я что-то упустил

21.11.2017 23:16:20
stulentsev

stulentsev

Москва

MainParasit

MainParasit

Тверь

Мало информации по выбору управлению техникой. Не понимаю как мне поделить полк танков разделить в 4 группы? Как управлять группой? Кто мне расскажет? Потом я буду мать над стратегией :). Может я что-то упустил

Тебе известны все координаты твоих юнитов. На стерте они стоят в ровных квадртах. Выделяй прямоугольниками на здоровье. :)

21.11.2017 23:46:35
O6e36ashenII

O6e36ashenII

Ordinus Plus

Ошибка в доке: меремещаться public static final ActionType MOVE – Приказать выделенным юнитам меремещаться в указанном направлении

23.11.2017 17:35:15
sarthak_ssg5

sarthak_ssg5

Jaypee University Noida

is there an example code for c++?

23.11.2017 21:55:22
BaR5uk

BaR5uk

Карачев

Функция “Отослать стратегию” сайта при отсылке архива выдаёт ошибку “Архив должен содержать только текстовые файлы, но файл MyStrategy.java таким не является.” Архив формата ZIP, пробовал архивировать его архиваторами WinRar и 7-Zip с настройками сжатия “Максимальное” и “Номальное”. Не знаю, имеет ли это значение, в архиве два файла Moves.java и MyStrategy.java. Первый в кодировке ANSI, второй — Юникод. (Сделать русские коментарии для первого файла не добрался). Неужели проблема в кодировке? Если да, то какую следует выбрать, чтобы не было проблем?

24.11.2017 13:42:02
third112

C трудом удалось посмотреть две игры: тормозит, срывается. Остальные несколько игр посмотреть не удалось. У меня свежая fedora, Intel Core i7 3.4 ГГц. С другими сайтами проблем нет. А здесь только у меня такие проблемы?

24.11.2017 16:30:59
AlexKol

C трудом удалось посмотреть две игры: тормозит, срывается. Остальные несколько игр посмотреть не удалось. У меня свежая fedora, Intel Core i7 3.4 ГГц. С другими сайтами проблем нет. А здесь только у меня такие проблемы?

Как бы сегодня раунд 1 начинается через 7.5 часов. Все тестят свои стратегии. Считайте вы в магазин перед новым годом зашли

24.11.2017 16:37:13
third112

Как бы сегодня раунд 1 начинается через 7.5 часов. Все тестят свои стратегии. Считайте вы в магазин перед новым годом зашли

Спрашиваю, потому, что хочу научиться, как делать бизнес на примере крупной компании :) Было заранее известно, когда возрастет нагрузка на сервер. На случай, если он не справится, то ведь можно было сделать зеркала на бесплатных хостингах.

25.11.2017 16:12:41
AlexKol

Спрашиваю, потому, что хочу научиться, как делать бизнес на примере крупной компании :) Было заранее известно, когда возрастет нагрузка на сервер. На случай, если он не справится, то ведь можно было сделать зеркала на бесплатных хостингах.

Да может что то случилось или тестировали и часть мощностей перевели на это. Хз.

25.11.2017 16:14:47
serf

serf

Москва

C трудом удалось посмотреть две игры: тормозит, срывается. Остальные несколько игр посмотреть не удалось. У меня свежая fedora, Intel Core i7 3.4 ГГц. С другими сайтами проблем нет. А здесь только у меня такие проблемы?

Хм, а у меня нормально все было.

25.11.2017 16:59:56
mixei4

mixei4

КГУ

Организаторы, сделайте уже зеркала на бесплатных хостингах! third112 не может участвовать из-за этого.

25.11.2017 18:35:19
NicNici

А почему если выделить группу однотипной техники и приказать ей переместиться, то в конце движения она может потерять строй? То есть взаимное расположение техники в группе измениться, произойдут некоторые смещения. При этом препятствий в виде другой техники во время движения не было.

27.11.2017 17:14:48
Yevgeny

Yevgeny

ООО Медиком МТД

А почему если выделить группу однотипной техники и приказать ей переместиться, то в конце движения она может потерять строй? То есть взаимное расположение техники в группе измениться, произойдут некоторые смещения. При этом препятствий в виде другой техники во время движения не было.

местность или погода могут влиять

27.11.2017 17:17:46
Scarlet
Yevgeny

Yevgeny

ООО Медиком МТД

местность или погода могут влиять

Местность и погода влияют только на скорость передвижения, на финальное расположение влиять не должно, после любых законченных действий оно должно совпасть с начальным. Другое дело, если новая команда пришла во время исполнения предыдущей, или, например, кто-то упёрся в препятствие, тогда новый порядок будет тот, в котором пришла команда.

27.11.2017 19:37:51
third112
mixei4

mixei4

КГУ

Организаторы, сделайте уже зеркала на бесплатных хостингах! third112 не может участвовать из-за этого.

Не участвую, т.к. никак не пойму: где тут AI?

27.11.2017 22:08:42
Zabidon

Zabidon

Blend4Web

Не участвую, т.к. никак не пойму: где тут AI?

Видимо, многие не испытывают проблем с соединением, возможно проблема в качестве вашего соединения. Работают ли у Вас другие приложения на WebGL? Дайте критерии того, что вы считаете AI, и, возможно, нам (и Вам) станет понятно, почему Вам не понятно: “где тут AI”.

27.11.2017 23:15:09
third112
Zabidon

Zabidon

Blend4Web

Видимо, многие не испытывают проблем с соединением, возможно проблема в качестве вашего соединения. Работают ли у Вас другие приложения на WebGL? Дайте критерии того, что вы считаете AI, и, возможно, нам (и Вам) станет понятно, почему Вам не понятно: “где тут AI”.

Определение AI: https://habrahabr.ru/post/337440/ При этом Элиза не AI, а имитация AI, на что указывал ее автор.

28.11.2017 14:18:38
GreenTea

GreenTea

ISDDesign

Определение AI: https://habrahabr.ru/post/337440/ При этом Элиза не AI, а имитация AI, на что указывал ее автор.

AI понятие многогранное. Написание ботов для игр - одна из граней. https://ru.wikipedia.org/wiki/%D0%91%D0%BE%D1%82_(%D0%BA%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B5_%D0%B8%D0%B3%D1%80%D1%8B)

28.11.2017 14:53:21
third112
GreenTea

GreenTea

ISDDesign

AI понятие многогранное. Написание ботов для игр - одна из граней. https://ru.wikipedia.org/wiki/%D0%91%D0%BE%D1%82_(%D0%BA%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B5_%D0%B8%D0%B3%D1%80%D1%8B )

Хотя дальше пишу про бота, определение предложил не только для ботов :)

28.11.2017 16:04:41
third112

Хотя дальше пишу про бота, определение предложил не только для ботов :)

PS Но тут, вроде, про ботов речь?

28.11.2017 16:06:10
mayduavongts

Thanks for sharing, nice post! Post really provice useful information! http://anthaison.vn/sp/may-dua-vong-tu-dong-ts/

19.04.2018 7:29:03