Источник оригинала на английском языке:
http://mudlogs.foghaven.net/mudlogs.php?article=jmctutorial
Оригинальное название: "JMC Tutorial - Version 1.0"
Авторы оригинального текста: Derek и Jasper
Перевод: Dr.Lance, 16.06.2009 г.-29.06.2009 г., 25.10.2009 г.-14.11.2009 г.

[Оригинальный текст учебника изложен моноширинным шрифтом
без иллюстраций. Возможно, это сделано для того, чтобы
желающие могли включить текст учебника непосредственно в
справочную систему игры -- прим.пер.]

Учебник по JMC -- редакция 1.0
===============================

ВВЕДЕНИЕ:
---------
Большинство игроков выбирает для игры в MUD специализированные
MUD-клиенты. Многие из них, однако, слабо представляют реальные
возможности клиентов, которыми они пользуются. Для некоторых это
не так и важно, но кому-то этот учебник поможет поднять игру на
новый уровень. Какого бы типа игроком вы ни были, мы с удовольствием
снабдим вас информацией о том, как заставить ваш клиент работать
в полную силу.

Этот учебник посвящен, в основном, MUD-клиенту JMC, однако, многие
из обсуждаемых здесь понятий применимы к другим MUD-клиентам,
поэтому этот учебник будет полезен вам, даже если вы и не являетесь
пользователем JMC.

Вы можете бесплатно скачать JMC по адресу:
http://mudlogs.foghaven.net/clients/jmc/

[Так как для скачивания предлагается JMC версии 3.26, то вероятно,
что именно по этой версии авторы и писали этот учебник -- прим.пер.]

==============================================================

СОДЕРЖАНИЕ:
------------
1) Познакомимся с клиентом
     1.1) Разберемся с кнопками на панели инструментов
     1.2) Что такое "профиль"
     1.3) Создаем соединение с MUD через JMC
     1.4) Закрываем соединение с MUD

2) Алиасы (alias) и горячие клавиши (hotkey)
     2.1) Разберемся, чем они отличаются друг от друга
     2.2) Создание простого алиаса
     2.3) Создание простой горячей клавиши
     2.4) Удаление ненужного алиаса
     2.5) Удаление ненужной горячей клавиши

3) Цветовыделители (highlight)
     3.1) Зачем нужны цветовыделители
     3.2) Создание цветовыделителя
     3.3) Удаление ненужного цветовыделителя

4) Переменные
     4.1) Зачем нужны переменные
     4.2) Частевые переменные (partial variable)
     4.3) Создание переменной
     4.4) Используем переменную
     4.5) Удаление ненужной переменной

5) Триггеры (action)
     5.1) Что такое "триггер"
     5.2) Создание триггера
     5.3) Обеспечение безопасности триггера
     5.4) Удаление ненужного триггера

6) Подстановки (substitution)
     6.1) Что такое "подстановка" (substitute)
     6.2) Что такое "заглушка" (gag)
     6.3) Создание подстановки
     6.4) Создание заглушки
     6.5) Удаление ненужной подстановки
     6.6) Удаление ненужной заглушки

7) Команда #showme
     7.1) Для чего нужна команда #showme
     7.2) Используем команду #showme

8) Связываем изученное воедино
     8.1) Алиасы с переменными
     8.2) Алиасы, которые вызывают запуск команд

9) Дополнительные функции JMC
     9.1) Дополнительное окно для вывода информации (output window)
     9.2) Создание команды вывода информации в дополнительное окно
     9.3) Используем ячейки панели статуса
     9.4) Используем звук, чтобы привлечь внимание

10) Ведение логов
     10.1) Для чего нужно вести логи
     10.2) Пишем лог в файл
     10.3) Закрываем файл лога
     10.4) Где хранятся логи

11) Условные выражения
     11.1) Выражения с ключевым словом if (команда #if)
     11.2) Используем условные выражения
     11.3) Математика в JMC
     11.4) Используем математические выражения

12) Регулярные выражения
     12.1) Что такое "регулярные выражения" и для чего они нужны
     12.2) Создание простейших регулярных выражений
     12.3) Подробнее о регулярных выражениях

13) Заключение

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

==============================================================

1) Познакомимся с клиентом
---------------------------

1.1) Разберемся с кнопками на панели инструментов

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

-- Кнопка с открывающейся папкой (загрузить профиль) позволяет
пользователю открыть профиль, сохраненный ранее. Перед открытием
нового профиля текущий профиль будет сохранен автоматически. Вообще,
это хорошая идея -- всегда сохранять свой труд.

-- Кнопка с дискетой (сохранить профиль) нужна, чтобы сохранить
текущий профиль.

-- Кнопка с радугой (цвета) позволяет настроить цветовую гамму игры.
Можно установить цвет фона или цвет текста по умолчанию.

-- Кнопка с буквами "Ff" (шрифты) позволяет выбрать шрифт текста,
его начертание и размер.

-- Кнопка с синим гаечным ключом (настройки программы) -- для
продвинутых пользователей. Предполагается, что вы не будете
баловаться с этими настройками, пока не познакомитесь с JMC поближе.

-- Кнопка с белой коробкой (редактирование объектов JMC) позволяет
вручную настраивать алиасы, триггеры, цветовыделители и горячие
клавиши.

-- Кнопка с красным кругом (пауза) замораживает текст игры в окне JMC.

-- Кнопка с буквой "S" (добавить скрипт) -- для продвинутых
пользователей. Возможность добавить скрипты, расширяющие встроенные
возможности JMC, на разных языках программирования.

-- Кнопка с красным иксом (прервать скрипт) -- также для продвинутых
пользователей.

-- Кнопка с жучком (отладка) открывает текст скрипта в программе,
которую вы используете для отладки своих программ, например Microsoft
Development Kit (комплект разработчика программ от фирмы Microsoft).
Для продвинутых пользователей.

-- Кнопка с вопросом (о программе) дает краткую информацию о
программном продукте (то есть о JMC).

-- Все вышеперечисленные задачи могут решаться с помощью выпадающих
меню (которые обычно находятся выше кнопок). Мы рассмотрим только те
выпадающие меню, которые выполняют задачи, отличные от перечисленных.

-- Выпадающее меню View (внешний вид) имеет несколько дополнительных
функций. Пункт меню Toolbar (панель инструментов) всегда должен быть
отмечен галкой. Другие пункты этого меню -- Status bar (строка статуса)
и Output window (дополнительное окно вывода) -- могут быть включены
позже, когда вы узнаете из этого руководства, для чего они нужны и как
их можно использовать.

-- Выпадающее меню Options (настройки программы). Будет хорошей идеей
установить Scroll buffer (буфер прокрутки -- область памяти, которая
хранит содержимое части документа, которая находится за пределами
экрана) в значение 30000. Это максимум, который можно установить. Эта
цифра означает, что если вам нужно прокрутить текст игры назад, то вы
можете открутить назад на 30000 строк.

-- Выпадающее меню Help (помощь) -- поможет вам, если вы запутались в
синтаксисе командного языка или не можете вспомнить, как пользоваться
какой-либо функцией JMC. Но здесь дается только краткая информация,
которая не является исчерпывающей.

1.2) Что такое "профиль"

Весь код (триггеры, алиасы, подстановки и т.д.) записывается в
профиль. Пока не определено иное, все это попадает в профиль "по
умолчанию" (default). Хорошим решением будет сохранять в профиль "по
умолчанию" все универсальное, что может использоваться всеми вашими
персонажами. Затем, каждый раз при создании нового профиля достаточно
будет открыть профиль "по умолчанию", нажать на кнопку создания нового
профиля -- при этом JMC спросит вас, хотите ли вы загрузить в
создаваемый профиль код текущего профиля. Этот универсальный для разных
персонажей код, хранящийся в профиле "по умолчанию", должен быть
полезен для любого вашего профиля. Такой сборник универсальных кодов не
является чем-то абсолютно необходимым, но иметь его при себе очень
удобно. Для разных классов персонажей можно написать специализированные
профили. Например, вы можете задать команду "b" (bash - сбить) для
профиля персонажа класса "воин" и ту же команду "b" (backstab - удар
кинжалом сзади) для профиля персонажа класса "вор". Если вам пока
непонятны эти объяснения, не отчаивайтесь, все станет яснее, когда вы
начнете писать свой код для своих профилей.

1.3) Создаем соединение с MUD через JMC

Что хорошего в том, чтобы владеть MUD-клиентом и не знать, как создать
соединение с любимым MUD? Полагаю, что многие из читателей этого
справочника играют в MUD под названием "Arctic", поэтому и использую
этот MUD в примере.

КОМАНДА: #connect
СИНТАКСИС: #connect адрес_сервера_игры номер_порта

ПРИМЕР: #connect mud.arctic.org 2700

После ввода этой команды на экране появится тот же текст, который
появляется, если вы пользуетесь простым Telnet-клиентом. Очевидно, что
каждый раз вводить такую длинную команду для входа в игру вам быстро
надоест, поэтому будет удобно написать простой алиас, помогающий
избавиться от этой проблемы. Что такое "алиас" -- я объясню позже, а
сейчас просто введите следующее:

#alias {z} {#connect mud.arctic.org 2700}

Теперь, введя букву "z", вы подключитесь к MUD под названием "Arctic".

1.4) Закрываем соединение с MUD

Если по какой-либо причине вам требуется разорвать соединение
с MUD, в который вы играете в данный момент, вы можете ввести:

КОМАНДА: #zap
СИНТАКСИС: #zap

Ввод команды #zap инициирует закрытие соединения с игрой. Не буду
рассказывать детально, в каких случаях может понадобиться эта
команда, но она срабатывает хорошо, если требуется очистить очередь
из множества команд, наспамленных вами же и создающих лаг (задержку
реакции сервера игры на ваши команды) в неподходящий момент.

2) Алиасы (alias) и горячие клавиши (hotkey)
--------------------------------------------

2.1) Разберемся, чем они отличаются друг от друга

Обе эти функции очень полезны. Сам я предпочитаю пользоваться
алиасами во всех случаях, но некоторые люди жить не могут без горячих
клавиш. Обе рассматриваемые функции похожи друг на друга тем, что
являются быстрым способом ввода длинных команд. Отличие в том, что
алиасы все же требуют набора нескольких символов и нажатия клавиши
Enter перед тем, как команды будут переданы в игру. Горячая клавиша
же сработает сразу, как только вы нажмете соответствующую клавишу.
В тех редких случаях, когда я пользовался горячими клавишами, это
были функциональные клавиши (F1-F12). На самом деле, в качестве
горячей можно использовать любую клавишу, но использование обычных
буквенных клавиш в качестве горячих -- не самая удачная идея. Можно
пользовать в качестве горячей клавиши клавиши вроде тильды (~) или
комбинации клавиш, например "CTRL+A".

2.2) Создание простого алиаса

КОМАНДА: #alias
СИНТАКСИС: #alias {короткое имя-текст для вызова} {полный текст команд}

ПРИМЕР: #alias {ввт} {взять все труп}

Теперь, когда вы убьете моба, все, что нужно сделать, чтобы ограбить
его труп, это ввести "ввт". Такие сокращения (алиасы) позволяют нам
стать намного быстрее, особенно, если вы делаете много опечаток или
чувствуете себя неуверенно с длинными командами вроде
"к !магическая стрела! мышь".

2.3) Создание простой горячей клавиши

КОМАНДА: #hotkey
СИНТАКСИС: #hotkey {клавиша} {полный текст команд}

ПРИМЕР: #hotkey {F1} {взять все труп}

Аналог примера с алиасом. Теперь, когда вы убьете моба, чтобы ограбить
его труп, достаточно нажать на клавишу F1.

2.4) Удаление ненужного алиаса

КОМАНДА: #unalias
СИНТАКСИС: #unalias {короткое имя-текст для вызова}

ПРИМЕР: #unalias {ввт}

Теперь алиас, который мы создали ранее, будет удален. Удалять алиасы
также можно, вызвав специальный диалог кнопкой с белой коробкой на
панели инструментов (редактирование объектов JMC), далее -- вкладка
"Алиасы" (Aliases), выбрать алиас "ввт", кликнуть мышью кнопку
"Удалить" (Remove), хотя лично я нахожу такой путь слишком длинным и
оттого нудным. Я предпочитаю первый способ.

2.5) Удаление ненужной горячей клавиши

КОМАНДА: #unhotkey
СИНТАКСИС: #unhotkey {клавиша}

ПРИМЕР: #unhotkey {F1}

Теперь горячая клавиша, которую мы создали ранее, будет удалена.
Удалять горячие клавиши можно также способом, описанным выше, только в
диалоге выбирается вкладка "Горячие клавиши" (Hotkeys) вместо "Алиасы"
(Aliases).

3) Цветовыделители (highlight)
------------------------------

3.1) Зачем нужны цветовыделители

Многие знают, что использование цветов в игре помогает отличать друг от
друга игроков и предметы, монстров и тому подобное, и что это
цветоделение очень удобно. Если вы раньше не пользовались цветами
стандарта консоли ANSI (кратко -- цвета ANSI) и вы играете, к примеру,
в MUD под названием "Arctic", предлагаю вам ввести команду "opt ansi"
[в русском MUD под названием "Былины" аналогом этой команды будет "цвет
полный" -- прим.пер.]. Сначала у вас будет немного рябить в глазах, но
побегав в игре с цветами ANSI подольше, вы от этого уже не откажетесь.
JMC поддерживает цвета стандарта консоли ANSI. Имена некоторых
персонажей в игре или какая-то информация от сервера игры могут для вас
быть важнее других имен или другой информации и поэтому мы не хотели бы
пропустить их в потоке текста. Выделение такой информации цветом --
один из способов не пропустить ее.

3.2) Создание цветовыделителя

КОМАНДА: #highlight
СИНТАКСИС: #highlight {цвет} {информация для выделения цветом}

ПРИМЕР: #highlight {green} {Петр}

Теперь каждый раз, когда в потоке текста от сервера игры вам попадется
имя "Петр", оно будет автоматически выделено зеленым (green) цветом.
Однако, нужно иметь ввиду, что из-за того, что, к примеру, в слове
"Петрович" тоже присутствует "Петр", часть слова "Петрович" тоже будет
выделена зеленым.

Узнать, какие цвета для выделения текста вам доступны, можно, нажав
кнопку с радугой на панели инструментов JMC. Вот список цветов, которые
точно там будут (кроме этих там могут быть и другие цвета):

ЦВЕТА: yellow (желтый), red (красный), green (зеленый),
       brown (коричневый), blue (синий), magenta (пурпурный),
       cyan (голубой), light red (ярко-красный),
       light green (ярко-зеленый), light blue (ярко-синий),
       light cyan (ярко-голубой), light magenta (ярко-пурпурный)

3.3) Удаление ненужного цветовыделителя

КОМАНДА: #unhighlight
СИНТАКСИС: #unhighlight {информация для выделения цветом}

ПРИМЕР: #unhighlight {Петр}

Имя "Петр", которое, благодаря команде из прошлой главы, выделялось
цветом, теперь будет выводиться цветом по умолчанию. Можно удалить
ненужный цветовыделитель и с помощью кнопки с белой коробкой на панели
инструментов JMC -- в открывшемся диалоге выбрать вкладку HighLights
(Цветовыделители), выбрать ненужный цветовыделитель в списке, нажать
кнопку Remove (Удалить) справа.

4) Переменные
--------------

4.1) Зачем нужны переменные

У переменных есть множество применений. С их помощью можно хранить
значения, которые позже использовать для различных вычислений. В
переменной можно хранить имя какого-нибудь триггера или алиаса, либо
нам просто может понадобиться заполнитель (placeholder) в
строке-шаблоне, соответствующий любому сочетанию символов
строки-оригинала.

4.2) Частевые переменные (partial variable)

Это в своей основе те же заполнители, что были упомянуты выше. Эти
переменные не определяются пользователем, они встроенные и
соответствуют любому сочетанию символов строки-оригинала. Обращение к
частевым переменным производится по их именам, которые состоят из знака
процента и цифры, то есть %0, %1, %2, ..., %9 -- всего их десять.

Предположим, MUD (в данном случае -- игровой сервер), в который мы
играем, может выдавать строки-оригиналы такого вида:

          Ворон прилетел с юга.

Используя частевую переменную (заполнитель), мы можем написать такую
строку-шаблон:

          %0 прилетел с юга.

Так как частевая переменная %0 соответствует в данном случае любому
сочетанию символов, находящемуся в строке-оригинале в части слева от
символов " прилетел с юга.", то кто бы ни прилетел с юга -- ворон,
Бэтмен, Петя, Мерилин Монро -- наша строка-шаблон будет соответствовать
строке-оригиналу.

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

Также эти переменные могут понадобиться для того, чтобы сделать наши
алиасы и подстановки (substitution) более гибкими.

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

Используем предыдущий пример:

          Ворон прилетел с юга.

Сделаем нашу строку-шаблон более универсальной:

          %0 прилетел с %1

Теперь мы можем встроить полученную строку-шаблон в цветовыделитель:

          #highlight {green} {%0 прилетел с %1}

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

Можно сделать алиас более универсальным, добавив в него цель-параметр
(target). Например, в случае, когда вы хотите открыть некий контейнер,
взять все из него и закрыть его, вы введете команды, похожие на
следующие:

          открыть сумка
          взять все сумка
          закрыть сумка

Чтобы автоматизировать эту операцию, создаем алиас так, как рассказано
в главе выше, посвященной алиасам, то есть вводим:

          #alias {вв} {открыть сумка; взять все сумка; закрыть сумка}

Теперь, когда вы введете "вв", произойдет то же самое, что и при вводе
трех команд выше. Точка с запятой здесь используется как разделитель
команд; с помощью разделителя команд можно расположить несколько команд
в одной строке.

Далее предположим, что мы хотим изменить этот алиас так, чтобы он
работал с любым контейнером. Это можно сделать следующим образом:

          #alias {вв %0} {открыть %0; взять все %0; закрыть %0}

Теперь мы можем вводить команды, подобные следующим:

          вв сумка
          вв сундук
          вв кошелек

...и наш алиас срабатывает с любым из этих контейнеров.

Только помните, что частевые переменные (%0 или %5 или %3 и т.п.)
должны использоваться не в любом порядке, а так, чтобы соответствовать
следующим друг за другом кускам текста.

4.3) Создание переменной

Кроме частевых, в JMC есть обычные переменные, то есть такие, которые
пользователь определяет сам и которые содержат определенные значения,
нужные нам.

КОМАНДА: #variable
СИНТАКСИС: #variable {имя переменной} {значение переменной}

ПРИМЕР: #variable {оружие} {копье}

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

4.4) Используем переменную

Все это прекрасно, но что полезного приносят обычные переменные,
определенные пользователем, то есть нами? Итак, чтобы получить значение
переменной (например, определенной в предыдущей главе), нужно поставить
символ "$" перед именем переменной, тогда JMC поймет, откуда извлечь
значение.

Давайте введем такую команду:

          вооружиться $оружие

В результате JMC отобразит на экране и пошлет на игровой сервер
следующее:

          вооружиться копье

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

Заметьте, что если бы вы перед последним примером не создали б
переменную $оружие, на игровой сервер была бы отправлена точно такая
последовательность символов, как вы написали, то есть "вооружиться
$оружие"; то же самое верно и для любых других выражений с переменными,
которые вы пишете для отсылки на игровой сервер.

Перед использованием переменной убедитесь, что ваша переменная
существует и ей присвоено какое-либо значение!

4.5) Удаление ненужной переменной

КОМАНДА: #unvariable
СИНТАКСИС: #unvariable {имя переменной}

ПРИМЕР: #unvariable {оружие}

Переменной с именем "оружие" больше не существует и ее значение
("копье") также стерто.

5) Триггеры (action)
--------------------

5.1) Что такое "триггер"

"Действия" (actions), также известные под названием "триггеры",
представляют собой команду (последовательность команд), которая будет
автоматически запущена на исполнение, когда от игрового сервера будет
получена определенная в триггере строка. Триггеры запускают команды на
исполнение без участия игрока.

5.2) Создание триггера

КОМАНДА: #action
СИНТАКСИС: #action {событие} {действия, которые будут выполнены}

ПРИМЕР: #action {0% отдал концы. Мир праху его!} {взять монеты труп}

Теперь, когда кто-либо погибнет в одной комнате с нашим персонажем, наш
клиент для игры в MUD автоматически пошлет на игровой сервер команду
"взять монеты труп". Этот триггер будет срабатывать, кто бы ни отдал
концы, так как %0 -- заполнитель (то есть соответствует любой
последовательности символов; смотри о заполнителях главу 4
"Переменные").

5.3) Обеспечение безопасности триггера

Любой, кто играл в MUD, знаком с таким явлением, как попытки некоторых
игроков навредить персонажам других игроков (жертвам) с помощью
собственных триггеров жертв. То есть когда другие игроки (либо,
изредка, какое-то неучтенное вами при написании триггера событие)
заставляют ваши триггеры срабатывать в такой момент (или таким
образом), когда (как) вам этого совсем не нужно. Такое употребление во
зло ваших же триггеров может закончиться для вашего персонажа утратой
экипировки, денег, а то и смертью. Все это означает, что умение писать
безопасные триггера является для игрока в MUD необходимостью. Приведем
несколько очень важных примеров, которые помогут понять, почему
триггеры могут быть небезопасны для ваших персонажей. Предположим, вы
всего лишь хотите, чтобы триггер срабатывал, когда появляется строка:

          Петя отдал концы. Мир праху его!

Напишите какой-нибудь триггер специально для этого события. Чем
универсальнее триггеры вы пишете, тем больше проблем может встать перед
вами при срабатывании триггера.

С помощью специального символа-якоря можно улучшить безопасность
триггера. Просто введите символ "^" в начале строки, определенной в
триггере как событие, при котором триггер срабатывает -- это убережет
триггер от криков игроков (и некоторых других вещей), которые содержат
текст, от которого ваши триггеры срабатывают. Однако, этим приемом
можно пользоваться только тогда, когда сочетание символов, от которого
срабатывает триггер, располагается в игре с самого начала строки.
Давайте разберемся, что это означает.

          Петя отдал концы. Мир праху его!

Эта строка-событие, полученная от игрового сервера, запустит ваш
триггер, если, к примеру, произойдет одно из следующих событий:

          Вова сказал вам: "Петя отдал концы. Мир праху его!"
          Аристарх закричал: "Петя отдал концы. Мир праху его!"
          Света завопила: "Петя отдал концы. Мир праху его!"

Если же вы определите вашу строку-событие так:

          ^Петя отдал концы. Мир праху его!

То ваш триггер сработает только тогда, когда персонаж по имени "Петя"
действительно отдаст концы, а не когда об этом кто-то завопит.

Если же мы определим строку-событие триггера так:

          ^Мир праху его!

То наш триггер сработает только тогда, когда игровой сервер выдаст в
точности строку:

          Мир праху его!

До тех пор, пока этого не случится, символ-якорь удержит триггер от
срабатывания, кто бы там что ни кричал.

Использование в триггерах частевых переменных (о частевых переменных
смотрите главу 4 "Переменные") делает обеспечение безопасности
триггеров намного сложнее. Эти переменные в триггерах используются
также, как в подстановках (о "подстановках" смотрите главу 6) и
алиасах.

Давайте рассмотрим строку-событие:

          Тут 432 монеты.

Мы можем создать триггер, который при возникновении такого события
будет автоматически делить кучку монет среди членов группы:

          #action {Тут %0 монеты.} {разделить %0}

Этот триггер помогает автоматизировать достаточно тривиальную задачу и
одновременно ставит перед игроком проблему -- этот триггер также
сработает на следующую строку-событие:

          Петя сказал: "Тут 4000;quit; монет."

При срабатывании по этому событию созданный выше триггер разделит 4000
монет и выведет вас из игры, а все из-за того, что триггер не привязан
к началу строки. Усовершенствуем этот триггер:

          #action {^Тут %0 монеты.} {разделить %0}

Эта версия сработает, только если строка-событие будет начинаться с
последовательности символов "Тут ".

Проблема может возникнуть даже при использовании символа-якоря "^",
если вы будете использовать его неправильно. Предположим, вы создаете
триггер, благодаря которому вы сможете приследовать кого-либо, когда он
покидает комнату:

          #action {^%0 ушел на %1.} {%1}

Вы можете думать, что раз вы использовали символ "^" перед
строкой-событием, то триггер для вас безопасен. Но это не так. Частевые
переменные %0, %1 и так далее, как уже писалось выше, соответствуют
ЛЮБОЙ последовательности символов между соответствующими частями
строки-оригинала. Положим, от игрового сервера пришла строка-событие:

          Петя сказал: "Мышь ушла на запад".
         ^^----------------^
         |        |__________
         |                  |
        Это начало строки.  |
                            |
                   Этой части строки соответствует %0.
                   Ошибка автора триггера в том, что он
                   считает, что %0 соответствует лишь
                   одному слову.

Как залатать прореху в безопасности триггера для данного случая? Есть
три вещи, которые можно сделать:
1) Отправить все триггеры в мусорное ведро.
2) Переделать триггер так, чтобы в строке-событии первой всегда шла
часть, которая является простым текстом, а не частевой переменной.
3) Воспользоваться для написания триггеров регулярными выражениями,
которые будут описаны позже, в главе 12 "Регулярные выражения".

5.4) Удаление ненужного триггера

КОМАНДА: #unaction
СИНТАКСИС: #unaction {событие}

ПРИМЕР: #unaction {^%0 отдал концы! Мир праху его!}

Теперь, если кто-то отдаст концы, то ваш клиент для игры в MUD
автоматически не выполнит команд, заданных вами при создании этого
триггера. Еще один способ удалить триггер -- нажатием кнопки с белой
коробкой на панели инструментов JMC вызвать диалог, выбрать вкладку
"Actions", выбрать в списке ненужный триггер и нажать на кнопку
"Remove" справа.

6) Подстановки (substitution)
-----------------------------

6.1) Что такое "подстановка" (substitute)

Всем игрокам довольно быстро надоедают некоторые из стандартных
сообщений при игре в MUD. Было бы замечательно, если бы можно было б
настроить игру так, чтобы вместо стандартных сообщений мы видели что-то
более интересное или смешное. Кроме этого, было бы очень удобно как-то
выделять наиболее важные сообщения. Мы уже рассмотрели цветовыделители
(глава 3), которые являются одним из методов выделения. Подстановки --
еще один из таких методов. Также можно комбинировать эти два метода,
чтобы выделить нечто наиболее важное.

6.2) Что такое "заглушка" (gag)

Вдобавок к надоедливым стандартным сообщениям при игре в MUD есть такие
сообщения, которые мы вообще не желаем видеть. Возможность избавиться
от некой бесполезной информации может очень помочь нам сосредоточиться
на действительно насущных задачах в игре. Если вы вспомнили сейчас
подобные случаи, то теперь вы можете "заглушить" этот нежелательный
текст.

6.3) Создание подстановки

КОМАНДА: #substitute
СИНТАКСИС: #substitute {оригинальный текст} {желаемый текст}

ПРИМЕР: #substitute {Мощнейшим ударом %0 заставил вас растянуться на
земле.} {----> %0 <---- СБИЛ ВАС !!!}

Примечание к примеру: несмотря на то, что здесь, в тексте учебника,
часть команды перенесена на следующую строку, вы должны в командной
строке клиента для игры в MUD ввести весь текст команды в одной строке.

Теперь, каждый раз, когда от игрового севера придет сообщение:

          Мощнейшим ударом Мелькор заставил вас растянуться на земле.

Вместо него вы увидите:

          ----> Мелькор <---- СБИЛ ВАС !!!

6.4) Создание заглушки

КОМАНДА: #gag
СИНТАКСИС: #gag {текст, который нужно заглушить}

ПРИМЕР: #gag {Вы не видите ничего необычного.}

Если мы, к примеру, введем команду "scan" (оглядеться) в MUD под
названием "Arctic", то довольно часто будем получать следующее (если
вокруг не видно ничего необычного):

          Вы посмотрели на север:
          Вы не видите ничего необычного.
          Вы посмотрели на восток:
          Вы не видите ничего необычного.
          Вы посмотрели на юг:
          Вы не видите ничего необычного.
          Вы посмотрели на запад:
          Вы не видите ничего необычного.
          Вы посмотрели вверх:
          Вы не видите ничего необычного.
          Вы посмотрели вниз:
          Вы не видите ничего необычного.

Но после создания нашей заглушки (пример выше), когда мы введем команду
"scan", то увидим следующее:

          Вы посмотрели на север:
          Вы посмотрели на восток:
          Вы посмотрели на юг:
          Вы посмотрели на запад:
          Вы посмотрели вверх:
          Вы посмотрели вниз:

6.5) Удаление ненужной подстановки

КОМАНДА: #unsubstitute
СИНТАКСИС: #unsubstitute {строка, на которую была создана подстановка}

ПРИМЕР: #unsubstitute {Мощнейшим ударом %0 заставил вас растянуться на
земле.}

Теперь, когда мы получим от игрового сервера такую строку, мы ее и
увидим, в точно таком же виде, как и до подстановки.

6.6) Удаление ненужной заглушки

КОМАНДА: #ungag
СИНТАКСИС: #ungag {текст, который глушился}

ПРИМЕР: #ungag {Вы не видите ничего необычного.}

Теперь это сообщение снова будет показываться, к примеру, когда вы
введете команду "scan" в MUD под названием "Arctic".

7) Команда #showme
-------------------

7.1) Для чего нужна команда #showme

Команда #showme может быть применена множеством способов. Вы можете
использовать ее, чтобы предупреждать себя о каких-либо событиях; можно
использовать ее для поиска ошибок в ваших скриптах или чтобы показать
себе некое полезное сообщение. Давай прямо сейчас разберемся, как
пользоваться этой командой в простых задачах. К сложным перейдем
позднее.

7.2) Используем команду #showme

КОМАНДА: #showme
СИНТАКСИС: #showme {цвет (необязательно указывать)} {текст сообщения}

ПРИМЕРЫ: #alias {тест} {#showme {ПРИВЕТ, ДРУГ!}}
         #alias {тест} {#showme {green} {ПРИВЕТ, ДРУГ!}}

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

Замечание к примеру: это первый пример, в котором мы комбинируем больше
одного объекта JMC в одном выражении. Это очень простой пример, который
очень хорошо подходит для иллюстрации такого комбинирования.

Теперь, каждый раз, когда мы будем вводить алиас "тест", мы будем
получать сообщение:

          ПРИВЕТ, ДРУГ!

Очевидно, что для команды #showme не существует команды-отмены. В
данном случае, если нам не нужен алиас, созданный в примере, достаточно
удалить этот алиас, как описано в главе 2 этого учебника, после чего и
сообщение "ПРИВЕТ, ДРУГ!" перестанет появляться.

8) Связываем изученное воедино
-------------------------------

8.1) Алиасы с переменными

На данный момент мы изучили основные объекты JMC. Теперь будет полезно
узнать, как использовать эти объекты совместно друг с другом. Давайте
рассмотрим несколько простейших примеров, как это можно делать; более
сложные примеры рассмотрим позднее.

Итак, переменные бывают очень полезны, но какой же это гемор -- вводить
каждый раз что-то вроде:

          #variable {оружие} {меч}

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

Для того, чтобы выполнять эту операцию быстро, можно использовать в одной
команде одновременно алиасы и переменные (комбинирование нескольких
объектов JMC в одной команде уже рассматривалось в главе 7). Например, мы
можем сделать следующее:

#alias {усторужие %0} {#variable {оружие} {%%0};
#showme {green} {Теперь оружие установлено в $оружие}}

Примечание к примеру: несмотря на то, что здесь, в тексте учебника, вторая
часть команды перенесена на другую строку, вы должны вводить эту команду
в одну строку, без переносов. Также приглядитесь к символу ";". Как уже
упоминалось в главе 4, он называется разделителем команд. Он используется для
того, чтобы можно было разместить несколько команд в одной строке, а также
разделитель команд действует как заменитель перевода каретки (клавиша Enter).
Для чего здесь нужна команда #showme? Она используется для информирования
пользователя об изменении переменной "оружие", то есть для отладки нашего
примера (о возможности использования #showme при отладке говорилось в
главе 7). Если сообщение команды #showme не появится, мы поймем -- что-то
пошло не так, значит нужно проверить синтаксис команды.

Также обратите внимание на конструкцию "%%0". Дополнительный символ
процента "%" сложно объяснить. Для начинающих: число символов процента "%"
определяется в зависимости от того, к переменной какого уровня мы хотим
обратиться. Поясню на примере.

Одна из второстепенных команд, доступных в JMC -- #loop, которая реализует
в JMC циклы (ранее мы ее не обсуждали).

КОМАНДА: #loop
СИНТАКСИС: #loop {А,Б} {%0.что-нибудь}

Первые скобки содержат список из двух чисел -- А и Б. Вторые скобки содержат
какой-нибудь текст для передачи на игровой сервер с использованием частевой
переменной %0. Команда #loop запускает цикл с количеством итераций Б.
Счетчик тикает по единичке от А до Б. Текущее значение счетчика содержится
в частевой переменной %0.

ПРИМЕР:

     #loop {1,4} {взять все %0.труп}

В результате на игровой сервер будут посланы команды:

     взять все 1.труп
     взять все 2.труп
     взять все 3.труп
     взять все 4.труп

Теперь, когда мы умеем пользоваться командой #loop, давайте предположим,
что мы хотим сделать цикл из примера более гибким, так, чтобы он мог
срабатывать на любом контейнере (вспомните алиас "вв" из главы 4.2).
Для этого скомбинируем в одной команде алиас и цикл:

     #alias {вв %0} {#loop {1,4} {взять все %0.%%0}}

Команда #loop помещена внутрь команды #alias (то есть в этой сложной
команде есть два уровня -- внутренний (или "нижний") уровень команды #loop
и внешний (или "верхний") уровень команды #alias). Теоретически уровней
может быть и больше двух. На каждом уровне частевая переменная %0 содержит
разные значения: на верхнем -- название контейнера, на нижнем -- текущее
значение счетчика. Поэтому, чтобы JMC смог различить значение частевой
переменной %0 верхнего и нижнего уровней, мы ставим разное количество
символов процента "%". Чем больше символов процента "%", тем на более
высокого уровня частевую переменную мы ссылаемся.

Теперь введем, к примеру:

     вв сундук

Тогда на игровой сервер уйдет следующее:

     взять все 1.сундук
     взять все 2.сундук
     взять все 3.сундук
     взять все 4.сундук

Если вы только начали осваивать премудрости игры в многопользовательских
мирах, то все эти объяснения могут вам показаться заковыристыми.
Не опускайте руки, пройдет немного времени и вы поймете, что все это
не так уж и сложно.

8.2) Алиасы, которые вызывают запуск команд

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

Мы уже говорили о запуске команд с помощью алиасов. Приведем еще один
короткий пример:

#alias {ограблениевкл} {#action {%0 умер! Мир праху его.} {взять все.монеты труп}}

#alias {ограблениевыкл} {#unaction {%0 умер! Мир праху его.}}

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

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

ПРИМЕР:

#alias {ограблениевкл} {{#action {%0 умер! Мир праху его.}
{взять все.монеты труп}; #action {^Кучка стальных монет.} {взять все.монеты}}

#alias {ограблениевыкл} {#unaction {%0 умер! Мир праху его.};
#unaction {^Кучка стальных монет.}}

Приведенные здесь примеры очень просты, но, уловив их суть, вы сможете
создавать более сложные скрипты, например, для PK (Player's Kill --
охота на персонажей других игроков и их убийство и (или) грабеж).
В начале главы вы хотели иметь некий инструмент, с помощью которого
в определенный момент вы бы смогли очень быстро создавать ряд неких
триггеров и также быстро их выключать. Включающие-выключающие алиасы --
это именно то, что вам требуется.

9) Дополнительные функции JMC
------------------------------

9.1) Дополнительное окно для вывода информации (output window)

Если вы -- новый пользователь JMC и впервые запускаете эту программу, то,
скорее всего, на экране появится и дополнительное окно для вывода информации,
а вы не будете знать, для чего оно нужно. Ведь, на первый взгляд, это большое
уродливое окошко всего лишь отнимает место вверху экрана. Но, на самом деле,
это окошко может быть очень полезным. Если вы поспешили закрыть его, не беда.
Чтобы снова его открыть, нужно всего лишь войти в выпадающее меню View
(внешний вид) и выбрать пункт "Output window". После этого вы сможете
передвигать это окно и изменять его размеры так, как вам нравится.

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

9.2) Создание команды для вывода информации в дополнительное окно

КОМАНДА: #output
СИНТАКСИС: #output {цвет (необязательно указывать)} {текст для вывода}

ПРИМЕР: #output {green} {БУУ!}

Введите команду из примера. Вы увидите, что в дополнительном окне
появилась зеленая надпись "БУУ!". Если у вас создана переменная $оружие,
которая содержит название оружия, которым вы вооружены, и вы хотите
вывести сообщение об этом оружии в дополнительное окно, то можно ввести
следующую команду:

#output (red) (ГЛАВНОЕ ОРУЖИЕ: $оружие)

Сама по себе такая команда почти бесполезна. Однако, в комбинации с
триггерами она может принести огромную пользу. Представьте, что вы идете
из одной зоны в другую и друг сообщает вам нечто важное. Вы можете запросто
пропустить сообщение друга в потоке спама (текста с описанием комнат,
криков игроков и т.п.).

Чтобы отфильтровать более важные сообщения от общего потока текста,
давайте используем комбинацию триггера и вывода в дополнительное окно:

#action {%0 сказал вам '%1} {#output {white} {%0 сказал вам '%1}}

"Но здесь же опечатка?!" - скажете вы. Нет. Вы можете спросить: "А почему
бы не сделать так?":

#action {%0 сказал вам '%1'} {#output {white} {%0 сказал вам '%1'}}
                          ^
                          |
На самом деле, эта заключающая кавычка вызовет проблему. Частевая
переменная %1 в этом случае будет соответствовать куску текста ДО
заключающей кавычки, а текст после нее не будет учтен. Например, кто-то
прислал вам сообщение:

Лорд Сот сказал вам: 'Впереди - 'Логово дракона'. Лучше пошли на восток.'

Вот, что будет выведено в дополнительное окно, если в команде использована
заключающая кавычка:

Лорд Сот сказал вам: 'Впереди - '

Без заключающей кавычки, как мы сделали сначала, частевая переменная %1
будет соответствовать всему сообщению, несмотря на возможные вложенные
кавычки, и сообщение будет полностью выведено в дополнительное окно.

Таким образом, в дополнительное окно можно отфильтровывать статистику группы,
сообщения согруппников, вопли, крики и т.п., то есть все, что вы пожелаете.
Дополнительное окно -- это что-то вроде фокуса, в котором вы выделяете для
себя главное из потока разнообразного текста, бегущего в главном окне.

9.3) Используем ячейки панели состояния

Для начала выясним, что такое ячейки панели состояния и где они находятся.

Ячейки панели состояния -- это три маленьких окна черного или серого цвета,
предназначенные для вывода разнообразных сигналов и сообщений. Эти ячейки
размещены в нижнем правом углу окна JMC, слева от трех окон-иконок и
индикатора ON/OFF.

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

КОМАНДА: #status
СИНТАКСИС: #status {номер ячейки: 1,2,3} {сообщение} {цвет (необязательно
указывать)}

ПРИМЕР: #status {1} {БУУ!} {green}

Приведем пример, от которого больше пользы. Вот как можно отслеживать,
имеет ли ваш паладин достаточно сил в данный момент для того, чтобы
применить умение "Возложить" или нет:

#action {^Вы возложили ваши руки на %0 и произнесли молитву.}
{#status {1} {ВОЗЛОЖИТЬ: ИСТРАЧЕНО} {yellow}}

#action {^Вы почувствовали, что в ваши руки возвратилась сила, позволяющая
вам исцелять.} {#status {1} {ВОЗЛОЖИТЬ: ВОССТАНОВЛЕНО} {green}}

Давайте рассмотрим действие этих команд подробнее. Очевидно, что когда
паладин только что использовал свое умение "Возложить", он не может сразу же
использовать его еще раз. Приходится ждать определенное количество тиков
перед тем, как паладин снова сможет использовать это свое умение. Как только
сила для умения восстановится, игра выдаст указанное в триггере сообщение.
Вероятно, здесь вы подумали: "Хорошо, если я получу сообщение, зачем мне
нужно еще одно сообщение в ячейке состояния?". К примеру, если вы находитесь
в середине яростного сражения и получите это сообщение, то очень легко можете
его пропустить. Либо вы можете его просто забыть. Сообщение в ячейке
состояния послужит вам напоминанием и в какой-то момент поможет сохранить
кому-нибудь жизнь.

9.4) Используем звук как предупреждающий сигнал

Многие подумают, что эта возможность почти бесполезна. Однако некоторые
из нас могут и из этого извлечь пользу. К примеру, к концу второй подряд
бессонной ночи игрок может находиться в полусонном состоянии. Узнать о том,
что случилось нечто важное, ему будет намного легче, если его об этом
предупредит звуковой сигнал.

КОМАНДА: #bell
СИНТАКСИС: #bell
ПРИМЕР: #action {^Мощнейшим ударом %0 заставил вас растянуться на земле.} {#bell}

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

10) Ведение логов
------------------

10.1) Чем полезно ведение логов

Когда мы исследуем новую зону или хотим знать, как добраться до зоны,
куда нас постоянно таскает лидер, удобно иметь текстовую версию всех
событий в игре, чтобы позже можно было проанализировать ее. Также
иногда хочется сохранить записи о самых больших и интересных битвах
между игроками. На все эти случаи JMC имеет команду для ведения
логов в текстовых файлах.

Пожалуйста, заметьте, что пока JMC не умеет писать в лог ваши подстановки
или сообщения от команды #showme, или текст, выводящийся в дополнительное
окно. То, что пишется в файлы логов, есть в точности то, что приходит
от игрового сервера, без изменений.

10.2) Запуск записи лога в файл

Сделать это очень просто. Когда у вас появляется желание начать писать
лог прохождения зоны, вы, очевидно, захотите дать этому логу определенное
имя, чтобы в будущем можно было бы быстро отыскать этот лог среди других.
Приведем пример:

#log {Подземелье.txt}

После ввода этой команды в правом нижнем углу окна JMC во втором
окне-иконке появится значок открытой папки, который показывает, что файл
лога открыт и лог пишется в файл.

10.3) Закрываем файл лога

Нет нужды постоянно писать лог или писать все в один файл. Поэтому,
после того, как зона пройдена или битва закончилась, файл лога можно
закрыть. Чтобы сделать это, от вас НЕ ТРЕБУЕТСЯ указывать имя файла
лога. Нужно просто ввести:

#log

Эта команда закроет текущий файл лога.

10.4) Где хранятся логи

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

ЗАМЕЧАНИЕ: у команды записи логов в файлы имеется параметр, определяющий
два способа записи лога в файл: overwrite (запись поверх старого лога)
и append (запись добавлением к старому логу). Если этот параметр
не указывать, лог пишется способом overwrite. При этом, если вы начинаете
писать лог в файл с таким именем, которое уже имеет ранее записанный файл,
то старый лог будет стерт, а поверх него будет записан новый лог. При
использовании способа append в случае совпадения названий файлов логов
новый лог будет записан в файл со старым логом, сразу после окончания
старого лога. Вот как использовать эти способы:

#log Подземелье.txt append
#log Подземелье.txt overwrite

Еще раз: overwrite -- это значение по умолчанию и его не обязательно
вводить.

11) Условные выражения
-----------------------

11.1) Выражения с ключевым словом if (команда #if)

Выражения с ключевым словом if -- очень удобная штука. Они позволяют
нам запускать какие-то действия только при наступлении определенных
обстоятельств. Также такие выражения известны как "условные выражения".
Помните, что JMC поддерживает только числовые сравнения.

11.2) Используем условные выражения

КОМАНДА: #if
СИНТАКСИС: #if {указанное здесь -- правда} {команды к исполнению}

Перед разбором примеров нужно пояснить несколько вещей. Во-первых, мы
должны знать, как связывать несколько объектов JMC друг с другом. Это,
конечно, актуально и для других глав этого учебника, но здесь это
особенно важно. Ниже мы рассмотрим некоторые операторы сравнения и
различия между ними, вплоть до самых незначительных.

Вы можете делать прямые сравнения, которые обозначаются символами:
 < > <= >= == !=
(меньше, больше, меньше или равно, больше или равно, равно, не равно).

ПРИМЕРЫ:

#if {$деньги >= 50} {разделить монеты}
#if {$жизнь < 20} {зачитать свиток возврата}
#if {$уровень == 30} {веселиться;выход;4;мойпароль}
#if {$ПК != 20} {вопить}

Замечание: часто встречается ошибка при применении оператора "равно" --
вместо "==" люди пишут "=". Это неправильно. В языках программирования
одиночный символ "=" используется в качестве оператора присвоения
значения переменной, поэтому в качестве оператора "равно" решили
использовать двойной знак "==".

В условных выражениях можно использовать оператор "И" (обозначается
как "&&"):

#if {$ПКразрешен == 1 && $деньги == 0} {рычать}

Также можно использовать оператор "ИЛИ" (обозначается "||"):

#if {$естьавтоматически == 1 || $голод == 1} {есть все}

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

#alias {ограблениевкл} {#variable {ограбление} {1}}
#alias {ограблениевыкл} {#variable {ограбление} {0}}

Введите: ограблениевкл

#action {%0 отдал концы! Мир праху его.} {#if {$ограбление == 1}
{взять все.монеты труп}}

Теперь, из-за того, что мы сначала установили переменную "ограбление"
в 1 ("включили"), когда моб или персонаж умирает, наш персонаж
автоматически крадет монеты с трупа умершего. Если мы введем команду
"ограблениевыкл", то наш персонаж перестанет автоматически грабить
трупы, так как переменная "ограбление" уже не будет равна 1 и условие
в триггере перестанет срабатывать.

11.3) Математика в JMC

Математика в JMC может оказаться немного не тем, что вы ожидаете.
Однако, для любого, кто имеет хотя бы небольшой опыт программирования,
не будет слишком сложным приспособиться. Тем, кто раньше не
программировал, будет немного труднее. Основная концепция математики
в JMC аналогична концепции целочисленной математики в языках
программирования. Например, если мы будем делить 3 на 5, то получим
в результате 0. Тогда как в обычной математике результат будет равен 0.6.
Мы не будем расписывать вам здесь формулы, но поймите, что вы можете
обойти эту проблему, применив перед делением умножение, чтобы сделать
значения подходящими для целочисленного деления.

11.4) Используем математические выражения

КОМАНДА: #math
СИНТАКСИС: #math {переменная для результата} {матем.выражение}

ПРИМЕР:

#variable {всего_монет} {0}
#action {^Тут %0 монет.} {#math {всего_монет} {$всего_монет + %%0}}
#alias {украдено монет} {jmc.Showme {yellow} {ВСЕГО МОНЕТ УКРАДЕНО:
$всего_монет}}

На первый взгляд все это выглядит немного путано, но давайте разберемся,
что происходит. Первое, что мы делаем -- это создаем переменную для
хранения общего количества украденных монет и устанавливаем ее в ноль.
Затем мы создаем триггер для сообщения, которое выдает игра после того,
как нашему персонажу удалось выбить из врага немного монет. Этот триггер
выполняет математические вычисления. Итак, после ключевого слова #math
в фигурных скобках мы указываем переменную для результата
математического выражения, а затем указываем само это математическое
выражение. Здесь вы можете воскликнуть: "Минуточку! В этом математическом
выражении используется та же самая переменная, в которой мы храним
результат этого самого выражения". Причина этого в том, что мы хотим,
чтобы при каждом вычислении выражения новый результат вычисления
записывался поверх старого и тем самым затирал бы его. В последней
части примера мы создаем алиас, который просто выводит общее количество
украденных монет на экран. Давайте поглядим, как это работает:

99H 99V 99X 99C:N> Тут 10 монет.
99H 99V 99X 99C:N> украдено монет
ВСЕГО МОНЕТ УКРАДЕНО: 10

12) Регулярные выражения
--------------------------

12.1) Что такое "регулярные выражения" и для чего они нужны

В предыдущих главах нам было довольно неудобно создавать триггеры на
определенный текст, приходящий от игрового сервера и было достаточно
сложно сообразить, каким образом сконструировать подходящий под этот
текст шаблон, чтобы триггер сработал. Кроме этого, те возможности JMC,
которые нам были известны ранее для подстройки триггеров под
определенный текст от игрового сервера, как мы узнали, имеют множество
прорех с точки зрения безопасности.

Вместо использования частевых переменных вроде %0, %3 и т.д., JMC
позволяет нам использовать совершенно другой метод подстройки триггеров
под целевой текст от игрового сервера -- это использование
"регулярных выражений" ("Regular Expressions" или кратко -- "RegEx").
Это очень точный и очень гибкий метод описания целевого текста.

12.2) Создание простейших регулярных выражений

Регулярные выражения в основном используются в триггерах (#action).

СИНТАКСИС: #action {/регулярное выражение/} {действия, которые будут
выполнены}

Символы косой черты ("/") обозначают начало и конец регулярного
выражения. Например:

#action {/Уличный кот самодовольно урчит/} {к !огненный шторм! кот}

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

Специальные символы обычно обозначаются обратной косой чертой ("\").
Вот некоторые из специальных символов: \w, \d, \s (это самые
общеизвестные).

\w - любой алфавитный символ, не являющийся пробЕльным (примеры: любая
     буква, любая цифра или символ подчеркивания "_");
\s - любой пробЕльный символ (примеры: пробел, символ табуляции);
\d - любая цифра (примеры: 0, 1, 2 и т.д.).

Кроме обратной косой черты ("\") в регулярных выражениях есть и другие
обозначения -- например, символы "+" и "*". В отличие от обратной косой
черты, которая ставится в начале специального символа, эти обозначения
могут ставится после каких-либо символов.

"+" - означает, что символ, после которого стоит это обозначение,
      появится в строке-оригинале в этом месте один или более раз подряд;
"*" - означает, что символ, после которого стоит это обозначение, либо
      вообще не появится в строке-оригинале в этом месте, либо появится
      один или более раз подряд.

Хорошо, посмотрим теперь, как это все используется. Давайте рассмотрим
очередной пример:

#action {/Тут \d+ монет/} {завопить}
              ^^^
               |
Этот шаблон соответствует любому количеству любых цифр, идущих подряд
(без десятичной точки). Спецсимвол \d означает любую цифру, а обозначаение
"+" после этого спецсимвола означает, как уже было сказано выше, появление
в строке-оригинале символа, после которого идет это обозначение, один
или более раз подряд.

А вот что нужно писать, если мы хотим подстроить триггер под кого-то,
входящего в комнату:

     #action {/\w+ пришел с \w+/} {зачитать свиток возврата}

Методами, которые мы рассматривали ранее, мы не могли описать такой
триггер так, чтобы он учитывал только персонажей с именами, состоящими
из одного слова, а не из двух, трех и т.д. Этот пример с регулярным
выражением учитывает только прибытие в комнату персонажей с однословными
именами: последовательность \w+ будет соответствовать, например,
персонажу с именем "Петя", но не мобу "Горный козел", так как
словосочетание "Горный козел" содержит пробельный символ -- пробел,
разделяющий наименование "Горный козел" на два слова.

Теперь, чтобы выделить из целевого текста некую содержащуюся в нем
информацию (как мы делали, используя частевые переменные %0, %1 и т.д.)
для дальнейшего использования, достаточно ограничить эту инфомацию
круглыми скобками:

#action {/Тут (\d+) монет/} {разделить %0}

Этот триггер сработает при появлении целевого текста от игрового сервера,
причем информация, соответствующая последовательности \d+, выделенной
круглыми скобками в шаблоне, будет сохранена в частевой переменной %0
и деньги будут поделены между членами группы по команде "разделить"
во второй части триггера.

Последовательное применение выделения информации круглыми скобками
в одной строке-шаблоне триггера поместит эту информацию в частевые
переменные %1, %2 и т.д., чтобы можно было использовать эту информацию
во второй части триггера:

     #action {/(\w+) пришел с (\w+)/} {ггруппа %0 пришел с %1!!}

Точно также, как при использовании частевых переменных в строке-шаблоне,
мы можем обеспечить безопасность нашего триггера с помощью специального
символа-якоря "^":

     #action {/^(\w+) пришел с (\w+)/} {ггруппа %0 пришел с %1!!}

Все это хорошо и прекрасно, но триггеры, написанные нами ранее с
применением частевых переменных, справлялись с этими задачами не хуже.
Чем же лучше использование регулярных выражений? Способ с регулярными
выражениями более гибок. Предположим, нам требуется триггер, срабатывающий
на строку, содержащую подряд 2 пробела, 4-6 букв, 2 цифры, 6 пробелов
и еще одну цифру. Пишем следующее:

     #action {/\s\s\w{4,6}\d\d\s{6}\d/} {завопить}

Задача, которая казалась невыполнимой, решается легко и элегантно.

Замечание: обозначение вида {а,б} работает подобно "*" или "+", за тем
исключением, что здесь задается диапазон, от "а" до "б" -- число раз,
которое может появится символ, после которого стоит это обозначение,
в целевой строке. В приведенном примере мы задаем число возможных
повторений символа \w в целевой строке от 4 до 6 раз.

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

Для этого можно использовать еще один спецсимвол, который применяется,
чтобы обозначить в шаблоне что угодно: буквы, пробелы, цифры. Этот
спецсимвол - точка ".".

Предположим, мы хотим выделить из целевой строки имя любого моба,
прибывающего с запада:

#action {/^(.+) пришел с запада./} {крикнуть %0 здесь!}

Таким манером мы выделили последовательность из 1 или более любых
символов и сохранили ее в частевой переменной %0, которую использовали
во второй части триггера. Но что это за точка в конце предложения?
В общем-то, она сработает и здесь, так как будет соответствовать точке,
которая ставится в конце целевой строки.

Некоторые символы, вроде "[", "]", "\", "(", ")", нельзя найти в целевой
строке триггера, полученной от игрового сервера, просто указав их как
обычные символы в строке-шаблоне триггера. Если же вы попытаетесь это
сделать, то получите сообщение об ошибке, так как интерпретатор
регулярных выражений посчитает их за служебные символы команд, а не за
простой текст от игрового сервера. Что же делать, если все таки вам
понадобится подстроить триггер под текст с такими символами? Поместите
перед такими (служебными) символами символ обратной косой черты "\":

\] - такое обозначение в строке-шаблоне будет соответствовать символу "]"
     в строке-оригинале, полученной от игрового сервера;
\. - аналогично - такое обозначение в строке-шаблоне будет соответствовать
     символу "." в строке-оригинале, полученной от игрового сервера.

Вспомните обратную косую черту в обозначениях спецсимволов типа \s, \w,
\d - это и было сделано, чтобы JMC не путал обычные буквы "s", "w", "d"
со спецсимволами.

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

     У вас 4141(6951) стальных монет.

Это можно сделать следующим образом:

     #action {У вас (\d+)\((\d+)\) стальных монет\.} {завопить}

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

12.3) Подробнее о регулярных выражениях

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

Обозначение: []
Квадратными скобками в регулярных выражениях обозначают начало и конец
контейнера, содержащего все варианты символа, который может появиться
в этом месте строки-оригинала, полученной от игрового сервера.

Предположим, от игрового сервера получена следующая строка:

     Фотонный реактор подготовлен: Д

Вот как можно подстроить наш триггер под эту строку:

     #action {/Фотонный реактор подготовлен: [ДН]/} {завопить}

Этот триггер сработает, если после двоеточия появится либо "Д",
либо "Н", но не сработает, если появится "д", либо "н", либо какой-то
другой символ. Если информацию о готовности реактора нужно сохранить
в частевой переменной, можно окружить квадратные скобки круглыми, как
мы делали ранее: ([ДН]).

Обозначение: {#} или {#,#}
Как вы видели в предыдущей главе, такое обозначение определяет диапазон
количества раз, какое целевой символ может повториться подряд в этом
месте строки-оригинала, полученной от игрового сервера.

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

     Боеприпасы[XXXXXXXXXX----]

Предположим, вы хотите получить звуковой сигнал, когда на прогрессоре
боеприпаса останется 2-3 деления. Это можно настроить так:

     #action {/Боеприпасы\[X{2,3}\-+\]/} {#beep}

Замечание: квадратные скобки в этом примере предваряются символом
обратной косой черты, чтобы дать понять JMC, что это не служебные
символы, а символы строки-оригинала от игрового сервера. Точно также
на всякий случай символ дефиса тоже предварен символом обратной косой
черты (так как я не уверен, является ли он служебным символом). Символ
"+" после символа дефиса означает, как уже говорилось ранее, что символ
дефиса может появиться в строке-оригинале один и более раз. Наконец,
если бы вы хотели, к примеру, получить звуковой сигнал, когда на
прогрессоре останется точно 3 деления, достаточно было бы в
строке-шаблоне указать обозначение "{3}".

Обозначение: \b
Это еще один спецсимвол, который расшифровывается как "граница"
(по-английски "border"). Предположим, вы хотите подстроить ваш триггер
под игрока с именем "Бам", но не с именем "Бамбук". Это можно сделать
так:

     #action {/Бам\b.* стоит здесь./} {улыбнуться Бам}

Замечание: обозначение ".*" соответствует любому тексту между обозначением
границы и словами "стоит здесь".

К примеру, этот триггер сработает на следующие строки-оригиналы:

     Бам, могучий кендер, стоит здесь.
     Бам, мужчина-кендер, стоит здесь.
     Бам стоит здесь.

Но не сработает на вот эту строку-оригинал:

     Бамбук стоит здесь.

Символ-граница, по существу, не соответствует ни одному из символов
строки-оригинала, а также не соответствует ни одному из символов знаков
препинания или из пробЕльных символов.

Еще одна интересная особенность регулярных выражений -- это символ
вертикальной черты "|". Он нужен для задания списков альтернатив. Он
действует аналогично символу "||" ("или") в языках программирования.
Например, можно настроить триггер следующим образом:

#action {^Здесь стоит дерево, увешанное спелыми (яблоками|апрельсинами).}
{обобрать дерево}

Этот триггер сработает на строки:

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

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

13) Заключение
---------------

Программирование с помощью командного языка JMC -- это очень большая тема.
Этот учебник лишь обеспечивает вас базовыми знаниями об инструментах,
которые можно использовать в клиентах для игры в текстовых
многопользовательских мирах. Клиент для таких игр -- это очень гибкая
штука, но его мощь, в конце концов, зависит, в основном, от силы
воображения игрока. Надеемся, что вы сможете скомбинировать все те приемы,
о которых здесь было рассказано, чтобы вы смогли выстроить свои собственные
уникальные профили, которые в итоге и помогут вам получить от игры больше
удовольствия.

Замечания по учебнику можно высказать в специальной теме форума.

 

Русский !МАД-коннектор
The Russian MUD Connector
mudconnector.su

This site is powered by the TWiki collaboration platform Copyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.