MasterGH Опубликовано 10 ноября, 2016 Поделиться Опубликовано 10 ноября, 2016 Russian AI Cup — соревнование по программированию искусственного интеллекта Скрытый текст Russian AI Cup — открытое соревнование по программированию искусственного интеллекта. Попробуйте свои силы в программировании игровой стратегии! Это просто, наглядно и весело! Чемпионат пятого Russian AI Cup называется CodeWizards. Вам предстоит программировать искусственный интеллект для управления волшебником. Ваши стратегии будут соревноваться между собой в Песочнице и чемпионате. Вы можете использовать любой из языков программирования: С++, Java, C#, Python, Pascal или Ruby. Песочница уже открыта. Удачи! К участию в соревновании приглашаются как начинающие программисты — студенты и школьники, так и профессионалы. Написать свою стратегию совсем просто: достаточно базовых навыков программирования. Расписание чемпионата Песочница: с 7 ноября до 25 декабря открыта для всех желающих; первая и четвертая недели будут проходить в режиме бета-тестирования, в эти периоды возможны нестабильная работа системы и существенные изменения в правилах. Раунд 1: 26–27 ноября. Раунд 2: 10-11 декабря. Финал: 17-18 декабря. Начните с Быстрого старта. Написать простейшую стратегию совсем несложно! Пример " Наш волшебник определённым образом выбирает себе дорожку и двигается по ней в направлении базы противника. При этом, если у него осталось мало здоровья, он должен отступить и подлечиться. Попробуйте самостоятельно разобраться, как работает приведённая далее стратегия. В коде присутствуют подробные комментарии, которые помогут вам в этом. " Скрытый текст import model.*; import java.util.*; public final class MyStrategy implements Strategy { private static final double WAYPOINT_RADIUS = 100.0D; private static final double LOW_HP_FACTOR = 0.25D; /** * Ключевые точки для каждой линии, позволяющие упростить управление перемещением волшебника. * <p> * Если всё хорошо, двигаемся к следующей точке и атакуем противников. * Если осталось мало жизненной энергии, отступаем к предыдущей точке. */ private final Map<LaneType, Point2D[]> waypointsByLane = new EnumMap<>(LaneType.class); private Random random; private LaneType lane; private Point2D[] waypoints; private Wizard self; private World world; private Game game; private Move move; /** * Основной метод стратегии, осуществляющий управление волшебником. * Вызывается каждый тик для каждого волшебника. * * @param self Волшебник, которым данный метод будет осуществлять управление. * @param world Текущее состояние мира. * @param game Различные игровые константы. * @param move Результатом работы метода является изменение полей данного объекта. */ @Override public void move(Wizard self, World world, Game game, Move move) { initializeStrategy(self, game); initializeTick(self, world, game, move); // Постоянно двигаемся из-стороны в сторону, чтобы по нам было сложнее попасть. // Считаете, что сможете придумать более эффективный алгоритм уклонения? Попробуйте! ;) move.setStrafeSpeed(random.nextBoolean() ? game.getWizardStrafeSpeed() : -game.getWizardStrafeSpeed()); // Если осталось мало жизненной энергии, отступаем к предыдущей ключевой точке на линии. if (self.getLife() < self.getMaxLife() * LOW_HP_FACTOR) { goTo(getPreviousWaypoint()); return; } LivingUnit nearestTarget = getNearestTarget(); // Если видим противника ... if (nearestTarget != null) { double distance = self.getDistanceTo(nearestTarget); // ... и он в пределах досягаемости наших заклинаний, ... if (distance <= self.getCastRange()) { double angle = self.getAngleTo(nearestTarget); // ... то поворачиваемся к цели. move.setTurn(angle); // Если цель перед нами, ... if (StrictMath.abs(angle) < game.getStaffSector() / 2.0D) { // ... то атакуем. move.setAction(ActionType.MAGIC_MISSILE); move.setCastAngle(angle); move.setMinCastDistance(distance - nearestTarget.getRadius() + game.getMagicMissileRadius()); } return; } } // Если нет других действий, просто продвигаемся вперёд. goTo(getNextWaypoint()); } /** * Инциализируем стратегию. * <p> * Для этих целей обычно можно использовать конструктор, однако в данном случае мы хотим инициализировать генератор * случайных чисел значением, полученным от симулятора игры. */ private void initializeStrategy(Wizard self, Game game) { if (random == null) { random = new Random(game.getRandomSeed()); double mapSize = game.getMapSize(); waypointsByLane.put(LaneType.MIDDLE, new Point2D[]{ new Point2D(100.0D, mapSize - 100.0D), random.nextBoolean() ? new Point2D(600.0D, mapSize - 200.0D) : new Point2D(200.0D, mapSize - 600.0D), new Point2D(800.0D, mapSize - 800.0D), new Point2D(mapSize - 600.0D, 600.0D) }); waypointsByLane.put(LaneType.TOP, new Point2D[]{ new Point2D(100.0D, mapSize - 100.0D), new Point2D(100.0D, mapSize - 400.0D), new Point2D(200.0D, mapSize - 800.0D), new Point2D(200.0D, mapSize * 0.75D), new Point2D(200.0D, mapSize * 0.5D), new Point2D(200.0D, mapSize * 0.25D), new Point2D(200.0D, 200.0D), new Point2D(mapSize * 0.25D, 200.0D), new Point2D(mapSize * 0.5D, 200.0D), new Point2D(mapSize * 0.75D, 200.0D), new Point2D(mapSize - 200.0D, 200.0D) }); waypointsByLane.put(LaneType.BOTTOM, new Point2D[]{ new Point2D(100.0D, mapSize - 100.0D), new Point2D(400.0D, mapSize - 100.0D), new Point2D(800.0D, mapSize - 200.0D), new Point2D(mapSize * 0.25D, mapSize - 200.0D), new Point2D(mapSize * 0.5D, mapSize - 200.0D), new Point2D(mapSize * 0.75D, mapSize - 200.0D), new Point2D(mapSize - 200.0D, mapSize - 200.0D), new Point2D(mapSize - 200.0D, mapSize * 0.75D), new Point2D(mapSize - 200.0D, mapSize * 0.5D), new Point2D(mapSize - 200.0D, mapSize * 0.25D), new Point2D(mapSize - 200.0D, 200.0D) }); switch ((int) self.getId()) { case 1: case 2: case 6: case 7: lane = LaneType.TOP; break; case 3: case 8: lane = LaneType.MIDDLE; break; case 4: case 5: case 9: case 10: lane = LaneType.BOTTOM; break; default: } waypoints = waypointsByLane.get(lane); // Наша стратегия исходит из предположения, что заданные нами ключевые точки упорядочены по убыванию // дальности до последней ключевой точки. Сейчас проверка этого факта отключена, однако вы можете // написать свою проверку, если решите изменить координаты ключевых точек. /*Point2D lastWaypoint = waypoints[waypoints.length - 1]; Preconditions.checkState(ArrayUtils.isSorted(waypoints, (waypointA, waypointB) -> Double.compare( waypointB.getDistanceTo(lastWaypoint), waypointA.getDistanceTo(lastWaypoint) )));*/ } } /** * Сохраняем все входные данные в полях класса для упрощения доступа к ним. */ private void initializeTick(Wizard self, World world, Game game, Move move) { this.self = self; this.world = world; this.game = game; this.move = move; } /** * Данный метод предполагает, что все ключевые точки на линии упорядочены по уменьшению дистанции до последней * ключевой точки. Перебирая их по порядку, находим первую попавшуюся точку, которая находится ближе к последней * точке на линии, чем волшебник. Это и будет следующей ключевой точкой. * <p> * Дополнительно проверяем, не находится ли волшебник достаточно близко к какой-либо из ключевых точек. Если это * так, то мы сразу возвращаем следующую ключевую точку. */ private Point2D getNextWaypoint() { int lastWaypointIndex = waypoints.length - 1; Point2D lastWaypoint = waypoints[lastWaypointIndex]; for (int waypointIndex = 0; waypointIndex < lastWaypointIndex; ++waypointIndex) { Point2D waypoint = waypoints[waypointIndex]; if (waypoint.getDistanceTo(self) <= WAYPOINT_RADIUS) { return waypoints[waypointIndex + 1]; } if (lastWaypoint.getDistanceTo(waypoint) < lastWaypoint.getDistanceTo(self)) { return waypoint; } } return lastWaypoint; } /** * Действие данного метода абсолютно идентично действию метода {@code getNextWaypoint}, если перевернуть массив * {@code waypoints}. */ private Point2D getPreviousWaypoint() { Point2D firstWaypoint = waypoints[0]; for (int waypointIndex = waypoints.length - 1; waypointIndex > 0; --waypointIndex) { Point2D waypoint = waypoints[waypointIndex]; if (waypoint.getDistanceTo(self) <= WAYPOINT_RADIUS) { return waypoints[waypointIndex - 1]; } if (firstWaypoint.getDistanceTo(waypoint) < firstWaypoint.getDistanceTo(self)) { return waypoint; } } return firstWaypoint; } /** * Простейший способ перемещения волшебника. */ private void goTo(Point2D point) { double angle = self.getAngleTo(point.getX(), point.getY()); move.setTurn(angle); if (StrictMath.abs(angle) < game.getStaffSector() / 4.0D) { move.setSpeed(game.getWizardForwardSpeed()); } } /** * Находим ближайшую цель для атаки, независимо от её типа и других характеристик. */ private LivingUnit getNearestTarget() { List<LivingUnit> targets = new ArrayList<>(); targets.addAll(Arrays.asList(world.getBuildings())); targets.addAll(Arrays.asList(world.getWizards())); targets.addAll(Arrays.asList(world.getMinions())); LivingUnit nearestTarget = null; double nearestTargetDistance = Double.MAX_VALUE; for (LivingUnit target : targets) { if (target.getFaction() == Faction.NEUTRAL || target.getFaction() == self.getFaction()) { continue; } double distance = self.getDistanceTo(target); if (distance < nearestTargetDistance) { nearestTarget = target; nearestTargetDistance = distance; } } return nearestTarget; } /** * Вспомогательный класс для хранения позиций на карте. */ private static final class Point2D { private final double x; private final double y; private Point2D(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } public double getDistanceTo(double x, double y) { return StrictMath.hypot(this.x - x, this.y - y); } public double getDistanceTo(Point2D point) { return getDistanceTo(point.x, point.y); } public double getDistanceTo(Unit unit) { return getDistanceTo(unit.getX(), unit.getY()); } } } Скрытый текст Данное соревнование предоставляет вам возможность проверить свои навыки программирования, создав искусственный интеллект (стратегию), управляющий волшебником в специальном игровом мире. Правила соревнования базируются на популярном в мире компьютерных игр жанре MOBA. В каждой игре вам будет противостоять пять стратегий других игроков. В то же время, у вас будет четыре союзника. Пять стратегий, находящиеся на одной стороне, составляют фракцию: Академию или Отступников. Основной командной целью этих пяти игроков является уничтожение базы противоположной фракции. Основной персональной целью каждого волшебника является сбор максимально возможного количества баллов. Звание победителя игры, а также все остальные места распределяются в соответствии с количеством набранных баллов. Игроку начисляются баллы, если его волшебник наносит урон, уничтожает или просто находится рядом во время смерти юнита другой фракции, а также за некоторые другие действия. Всем игрокам фракции начисляется значительное количество баллов в случае достижения основной командной цели. Правила игры практически полностью соответствуют классическим канонам жанра. Фракционные базы соединены тремя дорожками (верхней, центральной и нижней), в промежутках между которыми находятся лесные массивы. На самих дорожках находятся охранные башни: по 2 на дорожку от каждой фракции. Таким образом, в начале игры на карте присутствует 14 строений. С определённым периодом база каждой фракции генерирует 3 одинаковых отряда приспешников («миньонов») волшебников: по одному на каждую дорожку. Они сразу же устремляются по своей дорожке в направлении базы противоположной фракции, атакуя всех противников на пути. Турнир проводится в несколько этапов, которым предшествует квалификация в Песочнице. Песочница — соревнование, которое проходит на протяжении всего чемпионата. В рамках каждого этапа игроку соответствует некоторое значение рейтинга — показателя того, насколько успешно его стратегия участвует в играх. В Раунде 1 вам предстоит изучить правила игры и освоить базовое управление волшебником. В каждой игре данного этапа примет участие 10 игроков, которые будут распределены по двум фракциям. В данном режиме волшебникам доступны только удар посохом и заклинание «Магическая ракета», а количество жизненной энергии всех строений составляет половину от нормального. Коэффициент повреждения при случайном попадании по дружественному волшебнику равен 25%. Независимо от этапа чемпионата, волшебник не может нанести урон дружественным миньонам и строениям. Раунд 1, как и все последующие этапы, состоит из двух частей, между которыми будет небольшой перерыв (с возобновлением работы Песочницы), который позволит улучшить свою стратегию. Для игр в каждой части выбирается последняя стратегия, отправленная игроком до начала этой части. Игры проводятся волнами. В каждой волне каждый игрок участвует ровно в одной игре. Количество волн в каждой части определяется возможностями тестирующей системы, но гарантируется, что оно не будет меньше десяти. 300 участников с наиболее высоким рейтингом пройдут в Раунд 2. Также в Раунд 2 будет проведён добор 60 участников с наибольшим рейтингом в Песочнице (на момент начала Раунда 2) из числа тех, кто не прошёл по итогам Раунда 1. В Раунде 2 вам предстоит улучшить свои навыки управления волшебником, а также изучить механику получения волшебником новых уровней и изучения им умений. Правильный подход к выбору и использованию умений является ключом к победе в данном этапе. Компоновка игр осуществляется аналогично Раунду 1. Строения в данном этапе имеют нормальное количество жизненной энергии, а коэффициент повреждения при случайном попадании по дружественному волшебнику равен 50%. Дополнительно усложняет задачу то, что после подведения итогов Раунда 1 часть слабых стратегий будет отсеяна и вам придётся противостоять более сильным соперникам. По итогам Раунда 2 лучшие 50 стратегий попадут в Финал. Также в Финал будет проведен добор 10 участников с наибольшим рейтингом в Песочнице (на момент начала Финала) из числа тех, кто не прошёл в рамках основного турнира. Финал является самым серьёзным этапом. После отбора, проведённого по итогам двух первых этапов, останутся сильнейшие. И в каждой игре вам придётся сойтись лицом к лицу с одним из них. Именно так. Для управления пятью волшебниками одной фракции будет запущено 5 экземпляров вашей стратегии. Для управления пятью волшебниками противоположной фракции будет запущено 5 экземпляров стратегии оппонента. Коэффициент повреждения при случайном попадании по дружественному волшебнику равен 100%. Для определения победителя баллы, набранные всеми волшебниками каждой из фракций, будут просуммированы. В остальном правила игры не будут отличаться от правил Раунда 2. Система проведения Финала имеет свои особенности. Этап по-прежнему делится на две части, однако они уже не будут состоять из волн. В каждой части этапа будут проведены игры между всеми парами участников Финала. Если позволит время и возможности тестирующей системы, операция будет повторена. Russian AI Cup — крупнейший в России ежегодный чемпионат по программированию искусственного интеллекта и третье по счёту открытое соревнование для талантливых IT-специалистов, являющееся частью стратегии Mail.Ru Group по формированию и развитию конкурентной в мировых масштабах российской IT-индустрии. В рамках этой серии соревнований также проводятся: Russian Code Cup — крупнейшая в России ежегодная олимпиада по спортивному программированию, проходящая под эгидой Mail.Ru Group. Это «гоночная трасса» для самых быстрых умов, на которой можно проверить свои навыки в состязании с сильнейшими соперниками и заявить о себе на всю IT-среду. В первом Russian Code Cup приняли участие более 3000 человек. Задачи для участников и техническую часть олимпиады вместе с Mail.Ru Group обеспечивают эксперты Санкт-Петербургского национального исследовательского университета информационных технологий, механики и оптики (СПбНИУ ИТМО). Russian Design Cup — это открытый конкурс как для сильных, так и для начинающих дизайнеров и проектировщиков интерфейсов. Задачи, разработанные специалистами IT-отрасли, ждут тех, кто хочет показать свои способности в дизайне и готов это доказать в честной борьбе с участниками из разных городов. Задачи для Russian Design Cup будут похожи на те, с которыми команды дизайнеров Mail.Ru Group регулярно сталкиваются в реальной жизни. В 2014 году Mail.Ru Group запустила ещё одно соревнование: Russian Developers Cup. Russian Developers Cup — конкурс, нацеленный на создание эффективных команд для разработки оригинальных проектов: от идеи до рабочего прототипа. В ходе конкурса участники смогут не только заявить о своей уникальной идее, но и получить советы и помощь IT сообщества, а также собрать свою команду для успешной разработки и возможной реализации проекта за пределами чемпионата и привлечь к своему проекту внимание инвесторов. Призовой фонд чемпионата 2014 года составил $18000. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения