RTADS

Материал из IFВики
Перейти к навигации Перейти к поиску
RTADS
Тип Парсерные платформы
Разработчик(и) Андрей Гранкин, автор документации Валентин Коптельцев
Языки интерфейса Русский
Операционные системы Windows, Android, macOS, GNU/Linux и другие.
Написано на TADS 2
Язык разработки TADS 2
Читаемые форматы файлов Исходный код TADS 2 (*.t), Игры TADS 2 (*.gam), Внешние ресурсы TADS 2 (*.rs?)
Создаваемые форматы файлов Игры TADS 2 (*.gam), Внешние ресурсы TADS 2 (*.rs?), Исполняемые файлы (*.exe)
Дата первого выпуска 13 сентября 2002
Последняя версия TADS 2.5.11 русский релиз 27
Дата последней версии 8 октября 2011
Состояние
Лицензия Собственный вариант freeware
Сайт rtads.org


RTADS — это локализованная на русский язык известная платформа TADS 2 (Text Adventure Development System], на что и указывает буква «R» (Russian) в её названии. Локализация произведена Андреем Гранкиным в 2002 году и активно дорабатывалась в последующие годы. Также используется написание (R)TADS, которое, как правило, применяется в случаях, когда языковая специфика не имеет существенного значения и обсуждаемые вопросы справедливы как в отношении оригинальной, так и в отношении локализованной версии.

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

Данная статья посвящена преимущественно особенностям RTADS, специфичным для русского языка, поэтому для получения общей информации о платформе в целом следует также ознакомиться с основной статьёй про TADS 2.

История

(Данный раздел посвящён истории платформы RTADS, построенной на базе TADS 2. Для получения информации об истории оригинальной платформы см. основную статью «TADS: История».)

Впервые с текстовыми играми Андрей Гранкин познакомился в 1992 году на компьютере Spectrum. Впрочем, по его собственному признанию, ни одну из тех игр пройти ему в свои 9 лет не удалось из-за недостаточных знаний английского языка, однако они оставили у него ощущение больших скрытых богатств, и с тех пор его неодолимо тянуло ко всем играм изобилующим текстом. Следующим знаковым этапом приобщения Андрея Гранкина к текстовым играм стало его знакомство с Rogue-подобной игрой NetHack в 1999 году, в отношении которой он даже предпринимал серьёзные попытки перевода на русский, а затем и с играми класса MUD. Именно после них он стал целенаправленно интересоваться вопросом однопользовательских игр с текстовым вводом, и однажды, случайно увидев игру «Зомби 1 - Бегство», понял, что это то, что надо, хотя и в неудачной реализации:


«...я, наконец, догадался, что должен существовать целый жанр текстовых игр, и вышел на поиски именно их. В интернете по этому поводу нашёлся сайт Кащея, с играми, ужасающими сильнее, чем любые Зомби. ТяпЛяп, тогда уже существовавший, загружаться отказался. Зато по ссылкам я вышел на Inforcom'овские игры и с удовольствием играл в них около полугода. Когда же они надоели, а было это в июне 2002 года, мне захотелось самому написать нечто подобное. Неделя экспериментов с Inform'ом завершилась частичным переводом библиотек, созданием пары комнат с описаниями и вещами на русском, а также заваленным экзаменом. Что печально, ни один интерпретатор так и не позволил вводить русские буквы, удивлённо высвечивая вместо них вопросительные знаки. Пришлось забросить это начинание, и вернуться к учёбе.

В конце августа, досада от предыдущей неудачи развеялась и я решился попытаться ещё разок, на этот раз уже с системой ТАДС. Опыты оказались удачными, система прекрасно понимала русский без каких-либо настроек. Работа пошла быстрыми темпами, так как в это время Москва стала задыхаться в дыме лесных пожаров, и целых две недели я почти никуда не выходил по вечерам, а всё свободное время мучил файл под названием adv.t. Возможно я бы всё же не закончил это дело, если бы не наткнулся снова на сайт ТяпЛяп, и не узнал что Заикин Павел также занимается этим переводом. Обнаружилось, что этого события давно ждут и подобные попытки уже совершались ранее. В страхе что меня опередят, в следующую неделю я не только завершил перевод, но и написал экспериментальную игрушку, призванную показать все возможности системы. 13 сентября я выложил свои труды на сайт и объявил об этом общественности, от которой примерно через неделю начали приходить одобрительные отзывы. Так началась история этого проекта...»

Впрочем, некоторое время спустя Андрей Гранкин всё же снова вернулся к переводу и платформы Inform, пролоббировав в Windows Frotz доработки, необходимые для поддержки русского ввода, а также сделав базовый перевод стандартной библиотеки Inform и написав тестовую игру, что в последствие и стало основой проекта RInform Дениса Гаева (подробнее см. «RInform: История»). Впрочем, основные усилия им всё же тратились именно на проект RTADS.

На 2002-2003 годы пришёлся наиболее активный этап разработки RTADS, когда шла основная работа по адаптации стандартной библиотеки к специфике русского языка. Менее чем за полтора года был выпущен 21 релиз, за счёт которых в итоге удалось достигнуть высокого уровня синтаксического анализа русскоязычных команд и процедурной генерации описаний с учётом лексических параметров игровых объектов, превосходившего все альтернативные русскоязычные платформы и самодельные парсерные движки, существовавшие на тот момент.

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

В период 2004-2007 годов, в течение которых было выпущено всего 3 релиза, продолжалась уже менее интенсивная доработка RTADS, заключавшаяся в точечных усовершенствованиях и исправлениях отдельных ошибок. К этому моменту уже появилась версия платформы Inform, адаптированная для русского языка, — RInform, базировавшаяся на наработках того же Андрея Гранкина, но функционально она уступала RTADS из-за большого числа ошибок, принципиально более примитивной реализации работы с падежами, а также общего отставания функциональности Inform от TADS. Однако RTADS проигрывал RInform в скорости разработки, так как не имел встроенного генератора падежных форм и требовал ручного прописывания всех падежей каждого слова вручную.

Для решения проблемы необходимости указывать все словоформы вручную Андреем Гранкиным ещё в 2002-2003 годах было разработано специальное приложение «Генератор падежных форм». Оно позволяло в графическом интерфейсе указать свойства объекта, форму его названия в именительном падеже и задать ключевые лексические параметры (род, число, часть речи и пр.), после чего осуществлялась автоматическая генерация кода объекта на языке программирования TADS 2 со всеми падежными формами. Частично это решало проблему, но всё же заставляло разработчика работать параллельно в двух приложениях: редакторе кода и «Генераторе падежных форм». Существовал и альтернативный инструмент «Генератор склонений» от Алексея Салихова, тоже написанный в 2002-2003 годах, но он также не решал проблему встраивания процесса генерации падежных словоформ напрямую в код. Существенно позже в 2008 году появилось решение от Gesperid через предпроцессорный генератор словоформ, автоматически обрабатывавший исходный код и добавлявший в него необходимые свойства и значения свойств объектов, однако к тому моменту уже был почти готов встроенный генератор.

Осознавая проблему громоздкости процесса разработки, Андрей Гранкин в итоге портировал все лексические алгоритмы и словарь исключений из «Генератора падежных форм» на язык TADS и оформил это отдельной библиотекой generator.t, интегрировавшейся с платформой, и 1 октября 2008 года выпустил 25 релиз RTADS, в котором была реализована встроенная функциональность генерации падежных словоформ. Начиная с этой версии RTADS, разработчики получили возможность быстро описывать названия игровых объектов прямо в коде без необходимости указывать их формы для всех падежей (подробнее см. примеры двух листингов в разделе «Создание предмета»).

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

К 2017 году Валентином Коптельцевым была завершена работа по переводу на русский язык официального руководства с рядом дополнений, относящихся к специфики разработки русскоязычных игр и к дополнительной специфики стандартной библиотеки RTADS по сравнению с TADS 2.

Принципы технологии

(Данный раздел посвящён специфичным для русского перевода особенностям платформы RTADS, построенной на базе TADS 2. Для получения информации об общих технических особенностях см. разделы основной статьи «TADS: Принципы технологии» и «TADS: Основные возможности».)

Платформа (R)TADS состоит из двух основных частей: инфраструктуры в виде компилятора, интерпретатора и различных инструментов разработки, а также стандартной библиотеки, в которой содержатся суперклассы, базовые объекты и функции для построения игрового мира и обработки пользовательских команд. Основная адаптация TADS 2 для русского языка, формирующая платформу RTADS, относится к переводу и доработке стандартной библиотеки, поэтому разработка игр на RTADS в целом аналогична разработке игр на TADS 2, просто к исходному коду проекта подключается не оригинальная англоязычная библиотека, а её русскоязычный аналог. На определённом этапе в инфраструктурную часть TADS 2 вносились некоторые доработки, ориентированные на реализацию возможностей, необходимых для RTADS, но при условии использования достаточно современного компилятора и интерпретатора это не будет иметь никакого значения (для подробностей о минимально необходимых версиях см. раздел «Переносимость»).

Оригинальная стандартная библиотека TADS 2 включает файлы adv.t и std.t. Русскоязычная же стандартная библиотека RTADS содержит их переведённые и адаптированные версии, а также несколько дополнительных модулей:

  • advr.t - переведённая версия adv.t с определениями стандартных классов, объектов и функций, в том числе новых функций, специально предназначенных для работы с русским языком.
  • stdr.t - переведённая версия std.t с определением объектов и функций, обычно требующих модификации для конкретной игры.
  • generator.t - библиотека встроенного генератора падежных форм.
  • errorru.t - библиотека, переопределяющая стандартные сообщения об ошибках синтаксического анализа команд.
  • extendr.t - библиотека дополнений к системе.
  • menu.t - библиотека для написания менюшных игр, например, с её помощью написана игра «Глубина».

Также существует модуль spellchecker для автоисправления ошибок при вводе команд, написанный Михаилом Гранкиным, который раньше включался в официальный комплект поставки RTADS, но в последствие был из него исключён и теперь поставляется отдельно. Однако в advr.t сохранён интерфейс для его подключения.

Дополнительная библиотека gameinfo.t, которая отвечает за автоматическое создание файла библиографического описания игры по стандарту Договора Бабеля, , , содержащаяся в комплекте поставки TADS 2 не имеет языковых зависимостей и может быть использована в RTADS в своём оригинальном виде.

Отличия RTADS от TADS 2

Несмотря на то, что проект RTADS начинался как перевод TADS 2, в конечном счёте, вместе с переводом и неизбежной адаптацией основной функциональности стандартной библиотеки для русского языка, Андреем Гранкиным в платформу был внедрён ряд усовершенствований и дополнений, расширяющих и её общую функциональность по сравнению с оригиналом. В частности:

  • В RTADS добавлено более десяти «глаголов», отсутствующих в стандартной библиотеке TADS 2, которые относятся как к сервисным возможностям платформы, типа включения или отключения показа ссылок или включения и отключения уведомлений об изменении счёта, так и к новым возможностям взаимодействия с игровым миром, типа опорожнения контейнеров за один ход или дополнительных вариантов взаимодействия с персонажами игры.
  • В стандартной библиотеке RTADS определён ряд дополнительных классов для описания модели мира, которых нет в TADS 2, например, классы для удалённых предметов, типа луны или звёзд, или неосязаемых объектов, типа запахов или голосов в голове.
  • В стандартной библиотеке RTADS также определён ряд дополнительных функций общего назначения, которых нет в TADS 2, например, функции для получения в качестве строки значения свойства или метода, являющегося директивой вывода текста на экран с подавлением этого самого вывода, или функции для группового перемещения объектов из одного контейнера в другой.
  • В RTADS выполнен ряд доработок модели мира с целью её большей логичности и консистентности, например, реализована гибкая обработка директивы «все» с различными «глаголами» или усовершенствован механизм взятия и бросания предметов с целью создания условий для более сложной обработки этих операций.
  • В синтаксический анализатор RTADS добавлена поддержка команд-комментариев (строк, начинающихся со знака звёздочки («*») или больше («>»)), посредством которых можно записывать ввод только в файл транскрипта, адресуя их разработчику игры.
  • В состав RTADS входит написанная Андреем Гранкиным библиотека menu.t, позволяющая писать менюшные игры в интерфейсе на базе схемы <BANNER>.

Вместе с этим и общая локализация стандартной библиотеки не ограничивается простым переводом игровых сообщений, а включает создание целой группы специальных функций, позволяющих реализовать автоматическое склонение именных частей речи по родам, числам и лицам, автоматическое спряжение глаголов в зависимости от изменения этих параметров, а также динамическое изменение окончания в практически любом слове в зависимости от прочих условий, например, окончаний существительного в зависимости от связанного с ним количественного числительного. В отличие от RInform, где локализация выполнена без динамической адаптации игровых сообщений к изменению родов и чисел и поэтому строится на фиксированных гендеронезависимых фразах, RTADS позволяет очень гибко подстраивать любое сообщение к изменением лексических параметров объектов (подробнее см. раздел «Автоматическое склонение и спряжение в игровых сообщениях»).

Переносимость

Система TADS доступна на большом числе различных операционных систем: Acorn RISC OS (только интерпретатор), AmigaOS, Android, Atari ST/TT/Falcon, BeOS R5, DECStation, EPOC/Psion, iOS, Kindle (Touch, Paperwhite и Voyage), Linux, macOS/Macintosh, MorphOS, MS-DOS (в т.ч. для защищённого режима, а также версия для GO32), NeXT, OpenBSD, OS/2, PocketPC и PocketPC 2002 (процессоры ARM, MIPS и SH3), SGI Iris/Indigo, SunOS & Sun 3, Symbian Series 80, Unix, все версии Windows. Кроме того, существуют реализации интерпретатора TADS 2 на Java и JavaScript.

На очень маломощных системах (старые ПК, наладонники) интерпретаторы могут не работать из-за нехватки оперативной памяти и производительности. Кроме того, современные версии RTADS используют функциональность, которая появилась только в TADS версии 2.5.8, вышедшей 12 июня 2004 года, поэтому на интерпретаторах, построенных на более старом ядре, игры не будут воспроизводиться корректным образом (за исключением нескольких очень старых, собранных на RTADS релиз 17 от 15 июня 2003 года и ниже). Для современных операционных систем рекомендуемыми интерпретаторами TADS являются HTML TADS (Windows), QTads (Windows, macOS, GNU/Linux), Fabularium (Android).

Разработчикам же следует учитывать, что для компиляции игры с использованием встроенного генератора падежных форм следует применять компилятор TADS не ниже 2.5.9 от 12 сентября 2004 года. Более ранние версии также могут применяться, но лишь для сборки проекта без использования генератора.

Наиболее полный перечень инструментов разработки и интерпретаторов TADS для различных операционных систем можно посмотреть в соответствующем разделе IF Archive, а также на официальной странице загрузки TADS 2.

Технические возможности

Возможности парсера для игроков

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

RTADS поддерживает обработку команд из одного действия («глагола»), из действия и объекта, а также из действия и двух объектов, например, «встать», «взять ключ», «открыть дверь ключом» соответственно. При этом, возможно связывание частей команды при помощи различных предлогов, обозначение объектов или действий более чем одним словом, использование названий объектов в разных падежных формах, а также использование в качестве объекта не только предмета из игрового мира, но и числа или строки текста в кавычках, например, для команд типа «повернуть переключатель микроволновки на 5» или «напечатать "привет" на клавиатуре».

Можно отдавать команды другим персонажам игры, обращаясь к ним и через запятую называя команду, например, «трактирщик, дай мне водки».

Синтаксический анализатор RTADS способен разрешать различные неоднозначности посредством уточняющих вопросов, например, при обращении к объекту по слову «медаль» при наличии нескольких медалей, будет выводиться вопрос: «Когда Вы писали "медаль", то имели в виду: золотую медаль, серебряную медаль или бронзовую медаль?» В таких случаях можно:

  1. Вводить новую команду, если игрок передумал осуществлять данное действие;
  2. Заново полностью ввести команду с использованием более точной формулировки;
  3. Кратко ответить на заданный вопрос, указав уникальное свойство одного из объектов, например, «золотую», если игрока интересует конкретный из этих объектов;
  4. Кратко ответить на заданный вопрос при помощи слова «любую» (в любом числе и роде), если для игрока не существенно, к какому именно объекту из перечисленных применять команду и это можно сделать просто с первым из списка;
  5. Кратко ответить на заданный вопрос при помощи слова «все», если игрок хочет применить команду ко всем перечисленным объектам.

Схожим образом работают уточнения при поэтапном вводе команд, например:


>спросить
Кого ты хочешь спросить?
>полицейского
О чем ты хочешь спросить этого персонажа?
>о преступнике

(Эквивалентно вводу «спросить полицейского о преступнике».)

В отдельных случаях игра может автоматически дополнять команды при поэтапном вводе, если отсутствует неоднозначность, например, в локации находится только один персонаж, которого можно о чём-то спрашивать. Однако у разработчика есть возможность реализовать разные реакции на одно и то же действие без объекта, с одним объектом или с двумя объектами. В этом случае без точного ввода команды игрок может сразу получать соответствующую реакцию и не видеть уточняющего вопроса для варианта команды с бо́льшим числом объектов (подробнее см. четвёртый листинг в разделе «Создание новых «глаголов»»).

В стандартном варианте игрок имеет возможность последовательно отменять выполненные действия посредством команды «отмена», как бы отматывая события назад, а также повторно выполнять последнее осуществлённое действие командой «повтор». Кроме того, он может быстро, не отвлекаясь от интерфейса игры, выполнить сохранение в файл с конкретным названием или же быстро загрузить игру из какого-то файла, например, «сохранить "уровень 1"» или «загрузить "уровень 1"».

Реализован ряд приёмов для ввода составных команд и команд с дополнительной логикой:

  1. Объединение нескольких команд с разными действиями посредством точки, запятой или союза «и», например, «открыть ящик. взять гранату, дёрнуть чеку и бросить гранату в танк».
  2. Применение одного действия к нескольким конкретным объектам посредством запятой или союза «и», например, «взять ручку, бумагу и книгу».
  3. Применение действия к первому доступному объекту из нескольких похожих без дополнительных уточнений при помощи слова «любой» (в любом числе и роде), например, при наличии красного и синего флага «взять любой флаг».
  4. Применение действия ко всем доступным объектам при помощи обобщающего слова «всё» с возможностью исключить отдельные объекты при помощи слова «кроме», например, «взять всё» или «взять всё кроме денег».
  5. Обращение к последнему упомянутому в предыдущих командах объекту посредством соответствующих местоимений, например, «осмотреть дверь, осмотреть замок, отпереть его, открыть её». Чтобы не задумываться над правильным родом местоимения и гарантировано обратиться к последнему упомянутому объекту, можно обращаться к нему как к абстрактному «этому», например, «взять это». Также местоимением множественного числа можно обозначить не только единичный объект, но целый список объектов, если с ним осуществлялось взаимодействие в предыдущих командах, например, «взять все и осмотреть их» (действие из команды с местоимением «их» будет применено сразу ко всем объектам, к которым ранее удалось обратиться при помощи местоимения «все»).
  6. Неполный ввод названий, когда достаточно ввести минимум шесть первых букв названия объекта, например, «включить синхро» вместо «включить синхрофазотрон».
  7. Использование сокращённых названий распространённых действий, например, «о» вместо «осмотреть», «ю» вместо «идти на юг», «вкл» вместо «включить», «п» вместо «повтор» и так далее (полный перечень можно найти в справочных руководствах).

Все вышеперечисленные 7 приёмов облегчения ввода команд могут комбинироваться друг с другом, например, «взять всё кроме молотка, лопаты и лома. положить их на любую электротележку, вкл электр и залезть на неё».

Примеры кода и возможностей платформы для разработчиков

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

// Так выглядит однострочный комментарий, игнорирующийся компилятором.
/*
А так выглядит многострочный (блочный) комментарий,
игнорирующийся компилятором.
*/

Сортировка методом пузырька

Язык программирования (R)TADS имеет развитые алгоритмические возможности и поддерживает основные конструкции и типы данных, характерные для языков общего назначения, что позволяет просто и компактно реализовывать достаточно сложные алгоритмы, не отвлекаясь на странные с точки зрения прикладного программирования особенности синтаксиса, систему типов и модель работы с памятью, встречающиеся у альтернативных ИЛ-платформ. Кроме того, он содержит ряд возможностей из области синтаксического сахара, ориентированных на специфику текстовых игр, например, упрощённый вывод текста на экран из любого места программы или специальную конструкцию внедрения логических выражений, вызовов отдельных функций, значений переменных или возвращаемых значений функций в выводимый на экран текст без необходимости описывать такие операции отдельно и затем делать конкатенацию. Хотя в явном виде операции конкатенации (как модифицирующей, так и немодифицирующей) в (R)TADS также доступны в полной мере, в отличие от некоторых альтернативных платформ, например, (R)Inform, где этому препятствует архаичная модель работы с памятью.

Листинг:


local i := 1, n := 10, a := [];
"Исходный список:";
for(i; i <= n; i++)
{
	a += rand(100);
	" <<a[i]>>";
}
for(i := 1; i <= n - 1; i++)
{
	local j := 1, f := true;
	for(j; j <= n - i; j++)
	{
		if(a[j] > a[j + 1])
		{
			local t := a[j];
			a[j] := a[j + 1];
			a[j + 1] := t;
			f := nil;
		}
	}
	if(f)
		break;
}
"\nОтсортированный список:";
for(i := 1; i <= n; i++)
{
	" <<a[i]>>";
}

Возможный вариант вывода:


Исходный список: 14 8 86 71 1 58 64 90 72 42
Отсортированный список: 1 8 14 42 58 64 71 72 86 90

Создание локации

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

Листинг:


hallway: room // определение объекта локации
	sdesc = "Передняя" // название локации, отображающееся в статусной строке
// описание локации с возможностью перемещения по доступным направлениям
		// с помощью клика по ссылкам, которые игрок может включать и отключать,
		// и с возможностью выполнить по клику взаимодействие с другими объектами
	ldesc = "Прихожая с <<displayLink('осмотреть коврик', 'ковриком')>> на полу.
		На <<displayLink('идти на север', 'севере')>> выход на улицу, 
		а на <<displayLink('идти на юг', 'юге')>> проход в гостиную. "
	listendesc = "Из гостиной слышны громкие голоса. " // реакция на "прислушаться"
	north = street // свойство, определяющее направление перемещения на север
	// метод, обрабатывающий попытку перемещения на юг
	south =
	{
		// Если не вытерты ноги (свойство isDirty объекта игрока возвращает true),
		// то перемещение в текущем направлении блокируется
		if(parserGetMe().isDirty)
		{
			"Воспитанный человек сначала должен вытереть ноги. "; // вывод на экран
			return nil; // возвращается nil для обозначения невозможности перемещения
		}
		else
			return livingRoom; // возвращается локация, в которую произойдёт перемещение
	}
	out = self.north // обработка направления "выйти", перенаправляющея на north
	in = self.south // обработка направления "войти", перенаправляющея на south
;

Создание предмета

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

Листинг с ручным указанием словоформ:


book: readable
	sdesc = "книга" // название в именительном падеже
	rdesc = "книги" // название в родительном падеже
	ddesc = "книге" // название в дательном падеже
	vdesc = "книгу" // название в винительном падеже
	tdesc = "книгой" // название в творительном падеже
	pdesc = "книге" // название в предложном падеже
// (можно задать и местный падеж (mdesc), например, для слов типа "лес")
	ldesc = "Толстая книга в кожаном переплёте. " // реакция на "осмотреть"
	readdesc = "Чукча не читатель, чукча — писатель. " // реакция на "читать"
	doSynonym('Read') = 'Open' // приравнивание "открыть" к "читать"
	// все словоформы всех названий объекта в виде существительных
	noun = 'книга' 'книги' 'книге' 'книгу' 'книгой' 'книге#d' 'книгой#t'
		'переплет' 'переплета' 'переплету' 'переплетом' 'переплете' 'переплету#d' 'переплетом#t'
	// все словоформы всех названий объекта в виде прилагательных
	adjective = 'толстая' 'толстой' 'толстую'
		'кожаный' 'кожаного' 'кожаному' 'кожаным' 'кожаном'
	isHer = true // признак женского рода
	location = table // место расположения
;

Листинг с автоматизированным заполнением словоформ через встроенный падежный генератор:


book: readable
	desc = 'книга/1ж' // автогенерация всех падежных форм названия
	ldesc = "Толстая книга в кожаном переплёте. "
	readdesc = "Чукча не читатель, чукча — писатель. "
	doSynonym('Read') = 'Open'
	// автогенерация всех падежных форм остальных названий в виде существительных,
// не охваченных свойством desc
	noun = 'переплет/1м'
	// автогенерация всех падежных форм остальных названий в виде прилагательных,
	// не охваченных свойством desc
	adjective = 'толстая/1жп' 'кожаный/1мп'
	isHer = true
	location = table
;

Примечание:

В функциональном отношении оба вышеприведённых варианта кода эквивалентны и обеспечивают возможность обращения к объекту и его именования платформой в правильной грамматической форме с учётом изменения слов по падежам. Генератор падежных форм RTADS справляется с подавляющим большинством случаев, в том числе имея механизмы обработки несклоняемых слов или одушевлённых существительных и их прилагательных, у которых в мужском роде начинается расхождение форм именительного и винительного падежей. Ручное указание словоформ может понадобиться в редких ситуациях сложных имён собственных и некоторых слов, имеющих специфические правила склонения. В этом случае как раз можно использовать ручное указание всех необходимых словоформ, для соблюдения правильного построения фраз. При желании, механизмы генератора падежных форм и прямого указания словоформ можно комбинировать внутри одного объекта. Практика написания реальных проектов показывает, что в среднем авторы сталкиваются с необходимостью ручного указания словоформ хотя бы для одного объекта далеко не в каждой игре, поэтому генератор падежных форм является достаточно надёжным механизмом, на который можно рассчитывать в достаточной мере. Автоматическая генерация падежных форм происходит однократно на этапе компиляции игры, поэтому использование соответствующих инструкций никак не сказывается на производительности кода при исполнении.

Определение класса и функции, динамическое создание объектов

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

Листинг:


class cartridge: item // определение класса патрона
	sdesc = "патрон"
	rdesc = "патрона"
	ddesc = "патрону"
	vdesc = "патрон"
	tdesc = "патроном"
	pdesc = "патроне"
	ldesc = "Патрон калибра 7,62. "
	weight = 0 // вес предмета в игровом мире
	bulk = 0 // размер предмета в игровом мире
	isEquivalent = true // признак неразличимых (эквивалентных) объектов
	rpluraldesc = "патронов" // одна из форм множественного числа предмета
	noun = 'патрон' 'патрона' 'патрону' 'патроном' 'патроне' 'патрону#d' 'патроном#t'
		'патроны' 'патронов' 'патронам' 'патронами' 'патронах' 'патронам#d' 'патронами#t'
	adjective = 'калибра#r'
	isHim = true // признак мужского рода
;

/*
* Определение функции, создающей заданное количество патронов.
* Первым обязательным аргументом принимает число патронов для создания,
* а вторым необязательным может принять локацию, в которую их нужно поместить.
* При единственном аргументе помещает созданные патроны в инвентарь персонажа игрока.
*/
cartridgeGenerator: function(n, ...)
{
	local loc, i := 1, obj;
	if(argcount > 1)
		loc := getarg(2);
	else
		loc := parserGetMe();
	for(i; i <= n; i++)
	{
		obj := new cartridge; // создание нового объекта класса cartridge
		obj.moveInto(loc); // перемещение объекта в целевую локацию
	}
}

Примечания:

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

Для неразличимых объектов платформа автоматически генерирует грамматически правильное описание, а также заменяет в нём длинные составные числительные на числа. Возможные варианты вывода:


Ты видишь здесь патрон.
Ты видишь здесь два патрона.
Ты видишь здесь пятнадцать патронов.
Ты видишь здесь 31 патрон.
Ты видишь здесь 43 патрона.
Ты видишь здесь 57 патронов.

Автоматическое склонение и спряжение в игровых сообщениях

Платформа RTADS предоставляет широкие возможности по созданию игровых сообщений, в которых будет выполняться автоматическое склонение именных частей речи и спряжение глаголов в зависимости от лексических особенностей тех или иных объектов игры. Это позволяет создавать универсальные шаблоны фраз, не беспокоясь о нейтральности формулировки в отношении рода или числа. Данная функциональность активно используется в стандартной библиотеке RTADS, поэтому разработчику не требуется заботиться о корректности тех или иных игровых сообщений для предметов и персонажей с разным родом или числом, а при создании собственных игровых сообщений он также может сделать их универсальными при помощи тех же функций. Кроме того, разработчик имеет возможность конфигурированием нескольких параметров поменять род главного героя или его число (изменив таким образом обращение к нему с «ты» на «вы»), или же вообще реализовать игровое повествование от первого или третьего лица. Игровые сообщения в этом случае будут автоматически подстраиваться и автору практически не придётся об этом задумываться.

Листинг:


/*
* Определение функции, выводящей описание атаки с автоматическим склонением.
* В качестве аргументов она принимает объект атакующего персонажа,
* объект атакумемого персонажа и объём нанесённого ущерба в виде числа.
*/
attackDescription: function(aggressor, victim, damage)
{
	"<<ZAG(aggressor, &sdesc)>> <<glok(aggressor, 'ударя')>> <<victim.vdesc>>,
		нанося ущерб в <<damage>> единиц<<numok(damage, 'у', 'ы', '')>> здоровья. ";
	switch(damage/3)
	{
		case 0:
			"Да уж... Ударил<<iao(aggressor)>> как девочка. ";
			break;
		case 1:
			"О! Неплохо так вмазал<<iao(aggressor)>>! ";
			break;
		default:
			"Ого! Вот так отоварил<<iao(aggressor)>>! ";
	}
}

Возможные варианты вывода:


Ты ударяешь разбойников, нанося ущерб в 1 единицу здоровья. Да уж... Ударил как девочка.
Разбойники ударяют стражника, нанося ущерб в 5 единиц здоровья. О! Неплохо так вмазали!
Чудовище ударяет стражника, нанося ущерб в 10 единиц здоровья. Ого! Вот так отоварило!
Ведьма ударяет тебя, нанося ущерб в 4 единицы здоровья. О! Неплохо так вмазала!

Создание новых «глаголов»

Стандартная библиотека платформы имеет более сотни предопределённых «глаголов», которые покрывают все типовые взаимодействия с игровым миром, традиционные для парсерных игр. Однако особенности сюжета или геймплея часто обуславливают необходимость добавления новых «глаголов» или модификации уже имеющихся. (R)TADS позволяет практически неограниченно расширять их перечень в игре, поддерживая команды в виде простых действий, действий в отношении объекта и действий в отношении объекта (прямого) с помощью объекта (косвенного). Одно и то же действие может работать как по одной схеме, так одновременно и по двум или всем трём схемам.

Листинг создания нового «глагола» как простого действия:


xyzzyVerb: deepverb // определение объекта "глагола"
	verb = 'xyzzy' 'ксиззи' 'ксиззить' 'чняян' 'эюяяэ' // все названия действия
	sdesc = "XYZZY" // название действия для уточнений (здесь формальность)
	// метод реакции на ввод команды с названием действия
	action(actor) =
	{
		"— Ну XYZZY — это такое ретро... — <<glok(actor, 2, 1, 'слыш')>> <<actor.sdesc>> усталый голос откуда-то сверху. ";
	}
;

Листинг создания нового «глагола» как действия в отношении прямого объекта:


scratchVerb: deepverb
	verb = 'почесать' 'почеши' 'почешите' 'чесать' 'чеши' 'чешите'
	sdesc = "почесать"
// свойство с определением названия "глагола", по которому к нему можно будет
	// обращаться и которое определяет название его методов в прямых объектах
	doAction = 'Scratch'
;

// модификация корневого класса для добавления общей реакции на новый "глагол"
modify thing
	// общее обнуление метода-верификатора, чтобы можно было чесать абсолютно всё
	verDoScratch(actor) = {}
	// метод обработки действия в отношении объекта (срабатывает внутри объекта)
	doScratch(actor) =
	{
		"<<ZAG(actor, &sdesc)>> с хрустом почесал<<iao(actor)>> <<self.vdesc>>. ";
	}
;

Листинг создания нового «глагола» как действия в отношении прямого объекта при помощи косвенного объекта:


shootVerb: deepverb
	verb = 'стрелять' 'стреляй' 'стреляйте' 'стрелять в' 'стреляй в' 'стреляйте в'
		'стрелять во' 'стреляй во' 'стреляйте во'
	// (vopr и sdesc формируют уточняющий вопрос "В кого ты хочешь стрелять?",
	// а prepDefault и pred предлоги "из" и "в" для уточнения
	// в отношении косвенного объекта: "Из чего ты хочешь стрелять в это?"
	vopr = "В кого "
	sdesc = "стрелять"
	prepDefault = fromPrep
	pred = inPrep
	// свойство, описывающее дополнительные предлоги
	// для обработки команды с другим порядком слов
	dispprep = ['в', 'во']
	// свойство, по сути аналогичное doAction, но для данного типа "глаголов"
	ioAction(fromPrep) = 'ShootFrom'
;

modify thing
	// по умолчанию блокирование верификатором данного действия в отношении объекта
	// (срабатывает в прямом объекте)
	verDoShootFrom(actor, io) =
	{
		"Стрельба в <<self.vdesc>> ничего полезного не принесёт. ";
	}
	// по умолчанию блокирование верификатором данного действия при помощи объекта
	// (срабатывает в косвенном объекте)
	verIoShootFrom(actor) =
	{
		"<<ZAG(self, &sdesc)>> не предназначен<<yao(self)>> для стрельбы. ";
	}
;

Примечание:

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

Возможные варианты ввода и вывода:


>стрелять в зайца из зонтика
Зонтик не предназначен для стрельбы.
>стрелять из зонтика в зайца
Зонтик не предназначен для стрельбы.
>стрелять в землю
Из чего ты хочешь стрелять в это?
>из карабина
Стрельба в землю ничего полезного не принесёт.
>стрелять из карабина
В кого ты хочешь стрелять?
>в землю
Стрельба в землю ничего полезного не принесёт.
>стрелять
В кого ты хочешь стрелять?
>в землю
Из чего ты хочешь стрелять в это?
>из карабина
Стрельба в землю ничего полезного не принесёт.

Листинг создания нового «глагола» с комбинированным вариантом применения действия:


wavingVerb: deepverb
	verb = 'помахать' 'помаши' 'помашите' 'махать' 'маши' 'машите'
	vopr = "Кому "
	sdesc = "помахать"
	action(actor) =
	{
		"<<ZAG(actor, &sdesc)>> помахал<<iao(actor)>>. ";
	}
	doAction = 'Waving'
	ioAction(withPrep) = 'WavingWith'
;

modify thing
	verDoWaving(actor) = {}
	doWaving(actor) =
	{
		"<<ZAG(actor, &sdesc)>> помахал<<iao(actor)>> <<self.ddesc>>. ";
	}
	verDoWavingWith(actor, io) = {}
	verIoWavingWith(actor) =
	{
		// проверка нахождения объекта в инвентаре персонажа
		if(not actor.isCarrying(self))
			"<<ZAG(actor, &sdesc)>> не <<glok(actor, 1, 2, 'нес')>> <<self.rdesc>>! ";
		else
			self.verifyRemove(actor); // доп. верификация доступности действия с объектом
	}
	ioWavingWith(actor, dobj) =
	{
		"<<ZAG(actor, &sdesc)>> помахал<<iao(actor)>> <<dobj.ddesc>> <<self.tdesc>>. ";
	}
;

Возможные варианты ввода и вывода:


>махать
Ты помахал.
>помахать лоцману
Ты помахал лоцману.
>махать лоцману флажком
Ты помахал лоцману флажком.
>махать флажком лоцману
Ты помахал лоцману флажком.
>махать флажком
Кому ты хочешь помахать?
>лоцману
Ты помахал лоцману флажком.
>махать лоцману мачтой
Ты не несёшь мачты!

Создание отдельной области на экране

(R)TADS при работе в интерфейсе с поддержкой HTML TADS позволяет делить экран на произвольные области — так называемые баннеры — и управлять ими отдельно: выводить туда какой-то текст или картинку, менять только в них шрифт или фон и так далее. Это позволяет менять вид интерфейса, отходя от традиционного телетайпного стиля парсерных игр. Вместе с этим, при должных усилиях разработчика, такая игра может сохранить полную проходимость и эргономичность интерфейса в обычном текстовом режиме без поддержки HTML TADS.

Листинг:


// предварительное объевление функции для её использования как демона
invewRefresh: function;

// внедрение кода в функцию стартовой инициализации игры
replace init: function
{

	... // общий инициализирующий код

	// отрисовка баннера с инвентарём на нулевом ходе при загрузки игры
	invewRefresh(nil);
	// запуск отрисовки как демона для обновления содержимого после каждого хода
	setdaemon(invewRefresh, nil);
}

// функция, отрисовывающая баннер с перечислением объектов инвентаря текущего персонажа
invewRefresh: function(parm)
{
	// проверка наличия поддержки HTML TADS в текущем интерпретаторе
	if(systemInfo(__SYSINFO_SYSINFO) && systemInfo(__SYSINFO_HTML) = 1)
	{
		// баннер размещается вертикальной колонкой справа шириной в 10%
		// от ширины доступной части экрана с рамкой, очерчивающей его слева
		"<banner id='invew' align='right' width='10%' border>
			<br>
			<b>В инвентаре:</b>
			<br>
			<<nestlistcont(parserGetMe(), 0)>>
			<br>
			</banner>";
	}
}

Средства разработки

Разработка под платформу RTADS подразумевает использование общего инструментария TADS 2, хотя существует некоторое количество инструментов, ориентированных преимущественно именно на русскоязычное сообщество авторов игр. Инструменты разработки TADS 2 существуют под большую часть платформ, на которые портирован TADS (подробнее см. раздел «Переносимость»), но поддержкой и регулярным обновлением характеризуются лишь сборки для наиболее распространённых операционных систем. К ним относятся:

  • TADS Toolchain — набор инструментов для разработки под RTADS и TADS 2, имеющий полный комплект и англоязычных библиотек, а также специальную утилиту для облегчения процесса перевода игры. Рекомендуемый вариант для пользователей Windows, так как TADS Toolchain является единственным решением «под ключ», которое изначально включает в себя полный набор необходимых библиотек RTADS (в том числе Patcher) и всю техническую документацию, позволяя установить среду разработки в несколько нажатий и сразу приступить к написанию игры, а затем также в несколько нажатий выполнить сборку проекта с возможностью добавления ресурсов и создания исполняемого файла.
  • TADS Workbench — официальная IDE от разработчика TADS. Наиболее функциональный инструмент, позволяющий осуществлять разработку в специальном графическом интерфейсе. Предназначен для Windows, хотя существует устаревшая сборка для macOS. Входит в официальный комплект разработчика TADS 2 со встроенной документацией, а также распространяется и отдельно. Вместе с общим пакетом для разработчиков поставляются и утилиты командной строки, которые можно использовать без IDE. Для работы с RTADS требует отдельной загрузки и подключения русскоязычных библиотек, а также получения руководства RTADS из внешних источников.
  • FrobTADS — комплект утилит командной строки для выполнения всех операций по полной сборке проекта TADS. Предназначен для macOS, GNU/Linux, Unix и некоторых других. Для работы с RTADS требует отдельной загрузки и подключения русскоязычных библиотек, а также получения руководства RTADS из внешних источников.
  • TadsWrapper — специализированный интерпретатор TADS 2, содержащий минимальную среду разработки на базе утилит командной строки. Предназначен для Windows. Поставляется уже с русскоязычными библиотеками RTADS и пригоден для небольших экспериментов без сложной сборки проектов с добавлением ресурсов и получением исполняемого файла.

Последняя версия русскоязычных библиотек RTADS доступна на сайте платформы. Однако после выпуска релиза 27 от 8 октября 2011 года было реализовано несколько критических доработок платформы, на основе которых не был оперативно собран новый релиз, поэтому для полноценного использования этой версии RTADS рекомендуется также подключить комплект библиотек Patcher, включающий данные исправления (в TADS Toolchain Patcher уже включён).

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

tc32 -i libs -o game.gam main.t

(Компиляция исходника main.t в двоичный файл game.gam с использованием библиотек, расположенных в директории libs.)

Существуют специализированные редакторы для работы с TADS 2, в частности, Imaginate, Implementor и TFE (TADS File Editor).

Схемы подсветки синтаксиса языка TADS 2 существуют для таких общераспространённых редакторов как Aditor, Emacs, FAR, FED, FTE, Notepad++, TextPad, UltraEdit, Vim. Кроме того, ввиду близости синтаксиса TADS к синтаксису C в какой-то мере можно использовать и его схемы подсветки и файлы синтаксиса или режима.

Также существует проект кодогенератора «Конструктор», выполненный как программа (игра) RTADS, в которой можно специальными командами создавать объекты мира (локации и предметы), тут же тестировать их поведение путём взаимодействия с ними стандартным игровым образом, а затем отдельной командой вывести сгенерированный код, описывающий построенный мир.

Руководства и документация

Для игроков

Кроме того, по умолчанию игра на RTADS имеет встроенную справку, открываемую по команде «помощь». Некоторые авторы дополняют или переписывают данную справку, а также реализуют дополнительные подсказки или справочники команд, поэтому не стоит пренебрегать ознакомлением со встроенными справочными материалами в конкретных играх.

Для разработчиков

Ссылки

См. также