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

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

Раунд 1: до начала

Проект

Песочница

Раунд 1

Раунд 2

Финал

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

18 декабря 18:57: ardt2 написал комментарий в посте Языковые пакеты
18 декабря 18:22: Counterbalance написал комментарий в посте Языковые пакеты
18 декабря 17:12: httpps написал комментарий в посте Языковые пакеты
18 декабря 16:51: Kill.La.Kill написал комментарий в посте Правила
18 декабря 15:55: alkozel написал комментарий в посте Языковые пакеты
18 декабря 15:18: imsohate написал комментарий в посте Языковые пакеты
18 декабря 14:34: AlexeyN написал комментарий в посте Local runner
18 декабря 14:03: Flutter написал комментарий в посте Local runner
18 декабря 13:42: Ne0 написал комментарий в посте Языковые пакеты
18 декабря 13:39: AlexKol написал комментарий в посте Правила

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

Telegram-чат

 

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

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

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

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

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

Скачайте Local runner

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

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

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

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

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

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

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

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

Простая стратегия, пытающаяся ударить по мячу как можно раньше, причем необязательно в ворота, главное — в сторону противника!

При этом мы не будем учитывать какие либо столкновения, а также координату y — стратегия будет использовать в основном 2d геометрию.


use model::*; use strategy::Strategy; const EPS: f64 = 1e-5; // Константы, взятые из документации const BALL_RADIUS: f64 = 2.0; const ROBOT_MAX_RADIUS: f64 = 1.05; const MAX_ENTITY_SPEED: f64 = 100.0; const ROBOT_MAX_GROUND_SPEED: f64 = 30.0; const ROBOT_MAX_JUMP_SPEED: f64 = 15.0; #[derive(Default)] pub struct MyStrategy; // Нам понадобится работа с 2d векторами #[derive(Copy, Clone, Debug)] struct Vec2 { x: f64, y: f64, } impl Vec2 { fn new(x: f64, y: f64) -> Self { Self { x, y } } // Нахождение длины вектора fn len(&self) -> f64 { (self.x * self.x + self.y * self.y).sqrt() } // Нормализация вектора (приведение длины к 1) fn normalize(self) -> Self { self * (1.0 / self.len()) } } // Операция - для векторов impl std::ops::Sub for Vec2 { type Output = Self; fn sub(self, b: Self) -> Self { Self::new(self.x - b.x, self.y - b.y) } } // Операция + для векторов impl std::ops::Add for Vec2 { type Output = Self; fn add(self, b: Self) -> Self { Self::new(self.x + b.x, self.y + b.y) } } // Операция умножения вектора на число impl std::ops::Mul<f64> for Vec2 { type Output = Self; fn mul(self, k: f64) -> Self { Self::new(self.x * k, self.y * k) } } // Определение общего интерфейса для робота и мяча trait Entity { // Нахождение позиции объекта в плоскости XZ fn position(&self) -> Vec2; // Нахождение скорости объекта в плоскости XZ fn velocity(&self) -> Vec2; } // Реализация интерфейса Entity для робота impl Entity for Robot { fn position(&self) -> Vec2 { Vec2::new(self.x, self.z) } fn velocity(&self) -> Vec2 { Vec2::new(self.velocity_x, self.velocity_z) } } // Реализация интерфейса Entity для мяча impl Entity for Ball { fn position(&self) -> Vec2 { Vec2::new(self.x, self.z) } fn velocity(&self) -> Vec2 { Vec2::new(self.velocity_x, self.velocity_z) } } // Код стратегии impl Strategy for MyStrategy { fn act(&mut self, me: &Robot, rules: &Rules, game: &Game, action: &mut Action) { // Наша стратегия умеет играть только на земле // Поэтому, если мы не касаемся земли, будет использовать нитро // чтобы как можно быстрее попасть обратно на землю if !me.touch { *action = Action { target_velocity_x: 0.0, target_velocity_y: -MAX_ENTITY_SPEED, target_velocity_z: 0.0, jump_speed: 0.0, use_nitro: true, }; return; } const JUMP_TIME: f64 = 0.2; const MAX_JUMP_HEIGHT: f64 = 3.0; // Если при прыжке произойдет столкновение с мячом, и мы находимся // с той же стороны от мяча, что и наши ворота, прыгнем, тем самым // ударив по мячу сильнее в сторону противника let mut jump = ((me.x - game.ball.x).powi(2) + (me.y - game.ball.y).powi(2) + (me.z - game.ball.z).powi(2)) .sqrt() < BALL_RADIUS + ROBOT_MAX_RADIUS && me.z < game.ball.z; // Так как роботов несколько, определим нашу роль - защитник, или нападающий // Нападающим будем в том случае, если есть дружественный робот, // находящийся ближе к нашим воротам let mut is_attacker = game.robots.len() == 2; for robot in &game.robots { if robot.is_teammate && robot.id != me.id { if robot.position().y < me.position().y { is_attacker = true; } } } if is_attacker { // Стратегия нападающего: // Просимулирем примерное положение мяча в следующие 10 секунд, с точностью 0.1 секунда for i in 1..100 { let t = i as f64 * 0.1; let ball_pos = game.ball.position() + game.ball.velocity() * t; // Если мяч не вылетит за пределы арены // (произойдет столкновение со стеной, которое мы не рассматриваем), // и при этом мяч будет находится ближе к вражеским воротам, чем робот, if ball_pos.y > me.position().y && ball_pos.x.abs() < (rules.arena.width / 2.0) && ball_pos.y.abs() < (rules.arena.depth / 2.0) { // Посчитаем, с какой скоростью робот должен бежать, // Чтобы прийти туда же, где будет мяч, в то же самое время let delta_pos = Vec2::new(ball_pos.x, ball_pos.y) - Vec2::new(me.position().x, me.position().y); let need_speed = delta_pos.len() / t; // Если эта скорость лежит в допустимом отрезке if 0.5 * ROBOT_MAX_GROUND_SPEED < need_speed && need_speed < ROBOT_MAX_GROUND_SPEED { // То это и будет наше текущее действие let target_velocity = Vec2::new(delta_pos.x, delta_pos.y).normalize() * need_speed; *action = Action { target_velocity_x: target_velocity.x, target_velocity_y: 0.0, target_velocity_z: target_velocity.y, jump_speed: if jump { ROBOT_MAX_JUMP_SPEED } else { 0.0 }, use_nitro: false, }; return; } } } } // Стратегия защитника (или атакующего, не нашедшего хорошего момента для удара): // Будем стоять посередине наших ворот let mut target_pos = Vec2::new(0.0, -(rules.arena.depth / 2.0) + rules.arena.bottom_radius); // Причем, если мяч движется в сторону наших ворот if game.ball.velocity().y < -EPS { // Найдем время и место, в котором мяч пересечет линию ворот let t = (target_pos.y - game.ball.position().y) / game.ball.velocity().y; let x = game.ball.position().x + game.ball.velocity().x * t; // Если это место - внутри ворот if x.abs() < (rules.arena.goal_width / 2.0) { // То пойдем защищать его target_pos.x = x; } } // Установка нужных полей для желаемого действия let target_velocity = Vec2::new( target_pos.x - me.position().x, target_pos.y - me.position().y, ) * ROBOT_MAX_GROUND_SPEED; *action = Action { target_velocity_x: target_velocity.x, target_velocity_y: 0.0, target_velocity_z: target_velocity.y, jump_speed: if jump { ROBOT_MAX_JUMP_SPEED } else { 0.0 }, use_nitro: false, } } }


PlayerDark

PlayerDark

Миасс

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

17.12.2018 1:35:56
m4shell

В разделе языковые пакеты написано : “Скачайте пакет для любимого языка программирования со страницы языковые пакеты. Поддерживаются C++, Java, C#, Pascal, Python2, Python3 и Ruby.”

Но пакет для Python 2 не выложен. Будет ли поддержка второго Питона?

17.12.2018 12:22:38
nekromant322

Есть какой-нибудь пример MyStrategy на Java? Самый просто и очевидный, для самых тупых

17.12.2018 21:13:22
DonRumata

DonRumata

Saint Petersburg State Polytechnic University

Есть какой-нибудь пример MyStrategy на Java? Самый просто и очевидный, для самых тупых

Приведенный на Rust’е пример относительно несложно перенести, сегодня занимался этим же для плюсов. Не могу сказать, что сильно в плюсах разбираюсь, а Rust вообще увидел впервые в жизни, но сильно много времени это у меня не заняло. Дольше возился с подключением виндовой библиотеки для сокетов.

17.12.2018 22:12:59
Scarlet

Я чего-то не понимаю. Перевёл этот пример на C++, а роботы большую часть игр на месте стоят, а в некоторых активно двигаются (http://russianaicup.ru/game/view/773, http://russianaicup.ru/game/view/847). Попробовал игры создавать с одними и теми же версиями - тоже самое: в одной обе стороны стоят, в другой с одной стороны стоят, с другой играют (http://russianaicup.ru/game/view/733, http://russianaicup.ru/game/view/1202). Как может стратегия так по-разному себя вести? К сожалению, локалраннер x86 не подвезли, репитер тоже, поэтому отлаживаться пока можно только наугад, заливая на сайт.

18.12.2018 9:14:44