Приручаем ZoG (Часть 1: Волки и Козленок)

  • Tutorial
Волки и Козленок В предыдущей статье я рассказывал об уникальном, на мой взгляд, проекте Zillions of Games. Как я и обещал, я начинаю небольшой цикл учебных статей по описанию возможностей декларативного языка, предназначенного для разработки новых (и описания уже существующих) игр, в рамках этого проекта.

Для того чтобы не загромождать изложение излишними (на этом этапе) подробностями, я выбрал для реализации очень простую игру. Я играл в нее в детстве. Она называется «Волки и Козленок». Правила следующие: Волки (черные фигуры) — ходят на одну клетку по диагонали, только вперед. Козленок (белая фигура) — также ходит на одну клетку по диагонали, но в любую сторону. Задача белых — пройти на любую из четырех клеток своего цвета последней горизонтали. Задача черных — лишить белых возможности хода.

Поскольку на стандартной шахматной доске 8x8 черные побеждают элементарно, используем для игры доску 9x9 клеток. Эта игра очень простая (и нравится детям). При правильной игре, белые всегда побеждают.

Язык описания правил (ZRF) очень напоминает LISP. Как и в LISP-е, очень важно следить за балансом открывающихся и закрывающихся скобок (в противном случае, игра просто не загрузится). Также как и в LISP-е, комментарии начинаются с символа точки с запятой и продолжаются до конца строки.

; *****************************************************************
; *** Волки и Козленок
; *****************************************************************

(version "2.0")

Здесь, в комментарии, мы кратко описываем игру и указываем версию Zillions of Games, на которой она должна работать. На более младшей версии «движка» игра не запустится.

В ZRF, активно используются макросы. Они довольно просты, но могут использовать параметры. Следующая запись, представляет собой макрос, описывающий единственно возможный в нашей игре ход — на одну клетку в указанном направлении:

(define checker-shift ($1 (verify empty?) add))

При использовании в коде записи:

(checker-shift ???)

Макрос раскрывается следующим образом:

(??? (verify empty?) add)

Смысл передаваемого параметра и всей этой записи я объясню ниже. Пока, нам важно понимать, что макросы спасают нас от большого количества писанины и связанной с ней возможностью ошибок в описании.

Далее описывается доска. Ее описание также принято выносить в макрос:

(define board-defs
  (image "images\gluk\Board.bmp")
  (grid
     (start-rectangle 2 2 48 48)
     (dimensions
         ("a/b/c/d/e/f/g/h/i" (48 0)) ; files
         ("9/8/7/6/5/4/3/2/1" (0 48)) ; ranks
     )
     (directions (nw -1 -1) (ne 1 -1) (se 1 1) (sw -1 1))
  )
  (symmetry Black (ne sw) (sw ne) (nw se) (se nw))
  (zone (name goals) (players White) (positions b9 d9 f9 h9) )
)

Смысл описания image понятен — это имя файла рисунка, загружаемого для отображения доски. Далее следует описание квадратной доски (grid). Следует заметить, что возможности ZRF не ограничиваются описанием прямоугольных досок. Используя этот язык, можно описывать треугольные и шестиугольные доски, можно описывать многомерные доски, вплоть до 5-ти измерений, можно «склеивать» края доски, определяя ее топологию и т.д. Мы не будем сейчас на этом останавливаться. Подробности таких описаний можно найти в chm-файле, описывающем язык ZRF (поставляемом вместе с игрой), а также в огромном количестве уже реализованных игр на всевозможных досках.

Для нашей игры важны три ключевые фразы описания grid: start-rectangle описывает каким образом доска «накладывается» на загруженный рисунок. Фраза dimensions — описывает измерения (у нас их два). Строки в начале описания каждого измерения важны — они описывают порядок нумерации клеток (определяя, таким образом, систему координат). Следующий далее параметр определяет, каким образом «линейка» измерения накладывается на доску. Следует сказать, что при использовании изображения доски, разработанного самостоятельно, могут возникнуть сложности с подбором этих числовых значений, а также значений, указанных в start-rectangle. Может потребоваться множество попыток, для того, чтобы изображения фигур попадали в нужные места на изображении доски.

Следующая, очень важная фраза (directions) определяет направления, в которых могут двигаться фигуры. Мы определяем четыре направления — северо-запад (nw), северо-восток (ne), юго-запад (sw) и юго-восток (se). Фразой symmetry, мы определяем правила, по которым эти направления преобразуются для черного игрока.

Последняя строка (zone) — определяет набор клеток, который мы будет использовать далее, при определении условия победы Белых.

(define game-defs
   (board
      (board-defs)
   )
   (board-setup
      (White (WC e2) )
      (Black (BC b9 d9 f9 h9) )
   )
   (win-condition (White) (absolute-config WC (goals)))
   (loss-condition (White Black) stalemated)
)

В этом макросе, мы определяем условия игры. Фразой board задается ранее определенная нами доска (макрос board-defs раскрывается). В board-setup определяются начальные позиции игроков, после чего, фразами win-condition и loss-condition определяются условия победы и поражения для игроков. Условием победы для Белых мы определяем прохождение в ранее определенную нами зону, а условием поражения, для обеих сторон, отсутствие возможности сделать очередной ход.

Осталось определить игру:

(game
   (title "Волки и Козленок")
   (description "Провести белую фишку на последнюю горизонталь")
   (players White Black)
   (turn-order White Black)
   (game-defs)
   (piece
      (name WC)
      (image White "images\gluk\W.bmp")
      (description "Козленок")
      (help "Ходит на 1 клетку по диагонали вперед и назад")
      (moves
         (checker-shift ne)
         (checker-shift nw)
         (checker-shift se)
         (checker-shift sw)
      )
   )
   (piece
      (name BC)
      (image Black "images\gluk\B.bmp")
      (description "Волк")
      (help "Ходит на 1 клетку по диагонали только вперед")
      (moves
         (checker-shift ne)
         (checker-shift nw)
      )
   )
)

Большинство из определений здесь интуитивно понятны. Стоит остановиться лишь на нескольких моментах. Фраза players описывает тех самых игроков White и Black, которых мы уже использовали ранее. Игроков может быть больше двух, а в головоломках может быть определен один игрок (имеется даже возможность определить игрока делающего случайные ходы, но это тема для отдельного разговора). Фраза turn-order определяет порядок очередности хода для игроков (он также может отличаться от простого чередования хода двух игроков).

Далее, после описания настроек игры (game-defs), следует описание фигур, используемых в игре (piece). Большинство описаний в них также понятны. В разделе moves перечисляются все возможные для фигуры ходы. Именно здесь мы используем макрос checker-shift, о котором говорили в самом начале. Как легко видеть, в качестве параметра, ему передается возможное направление движения фигуры. В результате развертывания макроса, получается что-то наподобие следующего:

( ne
  (verify empty?)
  add
)

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

Новая игра готова. Желающие могут загрузить ее из репозитория на GitHub.

Важная ремарка
Внимание: для того, чтобы запустить этот код, вам потребуется, каким либо образом, разлочить ядро Zillions of Games (например — купить серийный номер)

Поделиться публикацией

Похожие публикации

Комментарии 9
    +4
    Скачал, установил через Wine. Мне теперь нужно заплатить 25 баксов, чтобы я мог попробовать загрузить ваш код?
      –3
      Можно не платить, ваше дело. Тут каждый решает за себя
        +2
        Тут дело не в деньгах. Таким подходом разработчики заставляют покупать «кота в мешке». Не дается возможности поиграться, хотя бы 3 дня( к примеру). После 3-х дней каждый сам может для себя решить интересно/необходимо/полезно это для него или нет. Я понимаю когда покупаю, к примеру, VisualStudio, за что я плачу денежку, и что с помощью этого инструмента возможно написать приложение, которое потом можно «монетезировать». Какой прок от этого инструмента? Если прока нет, за своё любопытство, за «просто так» я не готов заплатить, и забросить через 3 дня.
          –2
          Демка бесплатная (и не ограничена по времени). В ней поставляется достаточное количество игр, для того чтобы не «покупать кота в мешке», а делать свой выбор осмысленно. На счет прока, каждый, опять-же решает сам. Я для себя прок вижу. Кстати, с покупкой серийника никаких проблем не было, сервис функционирует.
            +2
            Вы наверное меня не поняли.
            В ней поставляется достаточное количество игр

            Вы же в статье пишите не о том, как играть в игры, а о том как их создавать. Играть мне не интересно, мне интересно было бы ощутить процесс разработки, а этого как раз в демо-версии и нет.
            Если не секрет в чем прок?
              –1
              Прок для меня — писать новые игры (бесплатные в любом смысле).
              Прок от статьи — рассказать, как писать новые игры, для тех, кто решил, что прок есть
                0
                Я имею в виду, что я не планирую, что мне это занятие будет приносить прибыль. Я рассматриваю эту разработку исключительно как развлечение. То что ядро платное — несколько печально, поскольку уменьшает возможную аудиторию, но я с этим поделать ничего не могу.
                  +1
                  Как-то несправедливо заминусовали вас в комментариях, спасибо за статью.
                    0
                    Дело прошлое. Вам спасибо.

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

    Самое читаемое