Bomberman codenjoy — как играть?

В принципе, игровой сервер доступен сейчас в целях ознакомления http://codenjoy.com/codenjoy-contest

В чем суть игры?

Надо написать своего бота для героя, который обыграет других ботов по очкам. Все играют на одном поле. Герой может передвигаться по свободным ячейкам во все четыре стороны.

Герой может так же поставить бомбу. Бомба взорвется через 5 тиков (секунд). Взрывной волной бомбы можно зацепить обитателей поля. Все, кто был задет - исчезает. Подорваться можно и на своей и на чужой бомбе.

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

Каждый разрушенный объект на поле (бомбермен, митчопер, разрушаемые стенки) тут же восстанавлиается в другом месте. Если пострадал бомбермен, ему зачисляются штрафные очки -50.

Бомбермен, от бомбы которого произошли разрушения на карте получит бонусные очки: за разрушаемую стенку +10, за митчопера +100, за другого бомбермена +1000.

Очки суммируются. Побеждает игрок с большим числом очков (до условленного времени).

Итак, игрок регистрируется на сервере, указывая свой email

Далее необходимо подключиться из кода к серверу через вебсокеты. Это Maven проект и подойдет он дял игры на JVM языках. Как его запустить смотри в корне README.txt

Для других языков придется написать свой клиент (а после пошарить с нами на почту: apofig@gmail.com)

Адрес для подключения к игре на сервере http://codenjoy.com:

ws://tetrisj.jvmhost.net:12270/codenjoy-contest/ws?user=email

Адрес для подключения к игре на сервере, развернутом в локальной сети:

ws://server_ip:8080/codenjoy-contest/ws?user=email

Тут email - имейл, указанынй при регистрации на сервере.

После подключения клиент будет регулярно (каждую секунду) получать строку символов — с закодированным состоянием поля. Формат таков

^board=(.*)$

с помощью этого regexp можно выкусить строку доски. Вот пример строки от сервера:

board=☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼ #   # #  #♥#  #  #  &        #☼☼♥☼♥☼♥☼#☼ ☼ ☼ ☼ ☼♥☼ ☼ ☼#☼#☼♥☼#☼#☼☼#♥♥  ♥#   # #♥   # ♥#          ☼☼ ☼ ☼#☼ ☼♥☼ ☼ ☼#☼ ☼ ☼ ☼ ☼&☼ ☼ ☼ ☼☼     ♥          # #            ☼☼ ☼ ☼ ☼ ☼♥☼ ☼ ☼♥☼#☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼☼#       # #       ☺& 2  #  #  #☼☼#☼♥☼ ☼#☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼#☼ ☼ ☼ ☼☼#  # ♥#               # ♥   #  ☼☼ ☼ ☼#☼#☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼#☼ ☼☼   #♥ #      #                 ☼☼ ☼ ☼ ☼ ☼♥☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼#☼☼     ## #     #   # #   ♥      ☼☼ ☼ ☼♥☼ ☼ ☼#☼ ☼#☼ ☼ ☼♥☼ ☼ ☼ ☼ ☼ ☼☼       #♥       #      ## # ###☼☼ ☼ ☼ ☼#☼ ☼ ☼#☼ ☼ ☼#☼#☼&☼ ☼ ☼ ☼ ☼☼       #       #    ♣# #     ♥ ☼☼ ☼ ☼ ☼♥☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼#☼ ☼☼        ## ## ♥             # #☼☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼☼                   &    ###  ##☼☼ ☼ ☼ ☼ ☼ ☼ ☼#☼ ☼#☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼☼                   ♥ ##        ☼☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼♥☼#☼ ☼ ☼ ☼☼     ##         &#         #   ☼☼ ☼ ☼ ☼#☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼#☼ ☼ ☼ ☼ ☼☼   #   #         #     # &     ☼☼♥☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼#☼#☼ ☼☼  #                    ##   &  ☼☼ ☼ ☼ ☼ ☼ ☼#☼ ☼ ☼ ☼ ☼ ☼ ☼#☼ ☼#☼ ☼☼ #    # &        #       #     ☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼

Длинна строки равна площади поля. Если вставить символ переноса строки каждые sqrt(length(string)) символов, то получится читабельное изображение поля.

☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼
☼ #   # #  #♥#  #  #  &        #☼
☼♥☼♥☼♥☼#☼ ☼ ☼ ☼ ☼♥☼ ☼ ☼#☼#☼♥☼#☼#☼
☼#♥♥  ♥#   # #♥   # ♥#          ☼
☼ ☼ ☼#☼ ☼♥☼ ☼ ☼#☼ ☼ ☼ ☼ ☼&☼ ☼ ☼ ☼
☼     ♥          # #            ☼
☼ ☼ ☼ ☼ ☼♥☼ ☼ ☼♥☼#☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼
☼#       # #       ☺& 2  #  #  #☼
☼#☼♥☼ ☼#☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼#☼ ☼ ☼ ☼
☼#  # ♥#               # ♥   #  ☼
☼ ☼ ☼#☼#☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼#☼ ☼
☼   #♥ #      #                 ☼
☼ ☼ ☼ ☼ ☼♥☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼#☼
☼     ## #     #   # #   ♥      ☼
☼ ☼ ☼♥☼ ☼ ☼#☼ ☼#☼ ☼ ☼♥☼ ☼ ☼ ☼ ☼ ☼
☼       #♥       #      ## # ###☼
☼ ☼ ☼ ☼#☼ ☼ ☼#☼ ☼ ☼#☼#☼&☼ ☼ ☼ ☼ ☼
☼       #       #    ♣# #     ♥ ☼
☼ ☼ ☼ ☼♥☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼#☼ ☼
☼        ## ## ♥             # #☼
☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼
☼                   &    ###  ##☼
☼ ☼ ☼ ☼ ☼ ☼ ☼#☼ ☼#☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼
☼                   ♥ ##        ☼
☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼♥☼#☼ ☼ ☼ ☼
☼     ##         &#         #   ☼
☼ ☼ ☼ ☼#☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼#☼ ☼ ☼ ☼ ☼
☼   #   #         #     # &     ☼
☼♥☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼ ☼#☼#☼ ☼
☼  #                    ##   &  ☼
☼ ☼ ☼ ☼ ☼ ☼#☼ ☼ ☼ ☼ ☼ ☼ ☼#☼ ☼#☼ ☼
☼ #    # &        #       #     ☼
☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼

Первый символ строки соответствует ячейке расположенной в левом верхнем углу и имеет координату [0, 0]. В этом примере — позиция бомбермена (символ ☺) — [19,7].

Расшифровка символов на рисунке ниже

public enum Element {

    /// This is your Bomberman
    BOMBERMAN('☺'),             // this is what he usually looks like
    BOMB_BOMBERMAN('☻'),        // this is if he is sitting on own bomb
    DEAD_BOMBERMAN('Ѡ'),        // oops, your Bomberman is dead (don't worry, he will appear
                                // somewhere in next move)
                                // you're getting -200 for each death

    /// this is other players Bombermans
    OTHER_BOMBERMAN('♥'),       // this is what other Bombermans looks like
    OTHER_BOMB_BOMBERMAN('♠'),  // this is if player just set the bomb
    OTHER_DEAD_BOMBERMAN('♣'),  // enemy corpse (it will disappear shortly, right on the next move)
                                // if you've done it you'll get +1000

    /// the bombs
    BOMB_TIMER_5('5'),          // after bomberman set the bomb, the timer starts (5 tacts)
    BOMB_TIMER_4('4'),          // this will blow up after 4 tacts
    BOMB_TIMER_3('3'),          // this after 3
    BOMB_TIMER_2('2'),          // two
    BOMB_TIMER_1('1'),          // one
    BOOM('҉'),                  // Boom! this is what is bomb does, everything that is destroyable
                                // got destroyed

    /// walls
    WALL('☼'),                  // indestructible wall - it will not fall from bomb
    DESTROY_WALL('#'),          // this wall could be blowed up
    DESTROYED_WALL('H'),        // this is how broken wall looks like, it will dissapear on next move
                                // if it's you did it - you'll get +10 points.

    /// meatchoppers
    MEAT_CHOPPER('&'),          // this guys runs over the board randomly and gets in the way all the time
                                // if it will touch bomberman - it will die
                                // you'd better kill this piece of ... meat, you'll get +100 point for it
    DEAD_MEAT_CHOPPER('x'),     // this is chopper corpse

    /// a void
    NONE(' ');                 // this is the only place where you can move your Bomberman

Игра пошаговая, каждую секунду сервер посылает твоему клиенту (боту) состояние обновленного поля на текущий момент и ожидает ответа команды герою. За следующую секунду игрок должен успеть дать команду герою. Если не успел — герой стоит на месте.

Команд несколько: UP, DOWN, LEFT, RIGHT – приводят к движению героя в заданном направлении на 1 клетку; ACT - просверлить оставить бомбу на месте героя. Команды движения можно комбинировать с командой ACT, разделяя их через запятую. Порядок (LEFT, ACT) или (ACT, LEFT) - имеет значение, либо двигаемся влево и там ставим бомбу, либо ставим бомбу а затем тикаем влево. Если игрок будет использовать только одну команду ACT, то бомба установится под героем без его перемещения на поле.

Первая задача – написать websocket клиента, который подключится к серверу. Затем заставить героя слушаться команды. Таким образом, игрок подготовится к основной игре. Основная задача – вести осмысленную игру и победить.

Сейчас реализованы клиенты для игры для некоторых языков программирования (java, javascript, objective-c, c++, python, c#) Другие языки в процессе написания (спасибо игрокам-активистам!).

Слишком много форы клиентский код не дает играющим, поскольку в этом коде еще надо разобраться, но там реализована логика общения с сервером + некоторое высокоуровневое апи для работы с доской (что уже приятно)

Point getBomberman() — позиция моего бомбера на доске
Collection<Point> getOtherBombermans() — позиции всех остальных бомберов (противников) на доске
boolean isMyBombermanDead() — жив ли мой бомбер
boolean isAt(int x, int y, Element element) — находится ли в позиции  x, y заданный элемент?
boolean isAt(int x, int y, Collection<Element> elements) — находится ли в позиции  x, y что-нибудь из заданного набора
boolean isNear(int x, int y, Element element) — есть ли вокруг клеточки с координатой x,y заданный элемент
boolean isBarrierAt(int x, int y) — есть ли препятствие в клеточке x, y
int countNear(int x, int y, Element element) — сколько элементов заданного типа есть вокруг клетки с x, y
Element getAt(int x, int y) — возвращает элемент в текущей клетке
int boardSize() — возвращает размер доски
Collection<Point> getBarriers() — координаты всех объектов препятствующих движению
Collection<Point> getMeatChoppers() — координаты всех чудиков которые могут убить бомбера
Collection<Point> getWalls() — координаты всех бетонных стен
Collection<Point> getDestroyWalls() — координаты всех кирпичных стен (их можно разрушать)
Collection<Point> getBombs() — координаты всех бомб
Collection<Point> getFutureBlasts() — координаты потенциально опасных мест, где бомба может разорваться. (бомба взрывается на N {решим перед началом игры} клеточек в стороны: вверх, вниз, вправо, влево)
Тут:
Point  - координата x, y
Collection — набор нескольких объектов
Element — тип элемента на доске 

Игра с открытым исходным кодом. Для реализации своей игры, исправления ошибок в текущей и внесения других правок необходимо для начала форкнуть проект. В корне репозитория есть описание в файле Readme.md - там описано, что делать дальше.

По возникающим вопросам, пиши в skype:alexander.baglay или на почту apofig@gmail.com