Данный файл является частью Руководства по TADS для авторов игр.
Copyright © 1987, 1996 Майкл Дж. Робертс (Michael J. Roberts). Все права защищены.

Руководство было преобразовано в формат HTML Н. К. Гайем (N. K. Guy), компания tela design.

Перевод руководства на русский язык - Валентин Коптельцев


Глава первая


Демонстрационная игра

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

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


Простейшая игра

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

Если хотите попробовать запустить данную игру, создайте файл с приведенным ниже текстом программы при помощи интегрированной среды разработки TADS (TADS Workbench) либо с применением любого текстового редактора. Если вы используете текстовый процессор (типа Word), позволяющий форматировать текст, вам может потребоваться использование специальной команды или опции для сохранения текста в виде простого текстового файла без специальных кодов форматирования; за подробными инструкциями обратитесь к документации по вашему текстовому редактору. В тот же каталог, в котором разместили файл игры, распакуйте также файлы из архива библиотек RTADS.

  /* Это просто комментарий, такой же, как, например, в языке Си */
#define USE_HTML_STATUS             /* Определение, необходимое для правильного форматирования переноса строк в HTML-TADS */
#include <advr.t>             /* включить файл с основными определениями объектов для текстовых квестов (русская версия) */
#include <generator.t>              /* включить файл с генератором падежных форм - доступен, начиная с версии 26 библиотек RTADS */
#include <stdr.t>                  /* включить файл определений стандартных функций, вызываемых при старте (русская версия) */
#include <errorru.t>              /* включить файл с русскими сообщениями об ошибках */

  startroom: room                     /* по умолчанию, игра начинается в комнате с названием startroom */
    sdesc = "У пещеры"              /* краткое опиание комнаты (от английского Short DESCription) */
    ldesc = "Ты стоишь на ярко освещенном месте прямо рядом с большой, темной и мрачной
            пещерой, лежащей к северу. "
    north = cave                 /* Комната под названием "cave" находится к северу */
  ;

  cave: room
    sdesc = "Пещера"
    ldesc = "Ты находишься внутри темной и затхлой пещеры. Солнечный свет прорывается
            через проход, расположенный к югу. "
    south = startroom
  ;

Для запуска примера используйте команду Compile and Run (скомпилировать и запустить игру) в меню Build (компилирование) программы TADS Workbench. Если по каким-то причинам вы в TADS Workbench работать не хотите или не можете, скомпилируйте текстовый файл с использованием программы TC32 - консольного компилятора TADS, и запустите получившийся файл при помощи плеера HTML-TADS либо консольного проигрывателя TR32 из командной строки. Если вы назвали ваш файл с примером игры "mygame.t", то в большинстве операционных систем вы сможете скомпилировать его командой

  tc32 mygame

и запустить игру при помощи команды

  tr32 mygame

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

Теперь рассмотрим наш пример построчно.

Первая строка является "заклинанием", указывающем системе способ форматирования параграфов при выводе описаний локаций. Чтобы лучше понять назначение этой инструкции, попробуйте ее стереть, сохранить файл и скомпилировать игру заново. Строка оказывает влияние только на мультимедийный интерпретатор HTML TADS, консольный интерпретатор "не заметит" разницы.

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

Во второй строке расположена инструкция #include, которая включает в вашу программу внешний файл с исходным кодом. Файл под названием advr.t представляет собой набор основных определений, общих для большинства текстовых квестов. Вы сможете применять их в большинстве игр с минимальными изменениями. Включив файл advr.t в вашу программу, вы избавляете себя от забот по реализации распознавания большого числа служебных слов, глаголов (таких, как "взять", "север" и т. д.), а также по определению многих объектных классов (подробнее о них см. далее).

Третья строка включает в текст игры файл generator.t из состава дистрибутива RTADS. Это - встроенный в систему генератор падежных форм, о его назначении будет рассказано далее. Данный функционал доступен, начиная с 26 версии библиотек RTADS. Если вы по какой-либо причине работаете с более старой версией библиотек, данную строку необходимо исключить.

Строка, содержащая инструкцию #include stdr.t, аналогична предыдущей; файл stdr.t содержит дополнительные стандартные определения. Причина, по которой эти определения помещены в отдельный файл, состоит в том, что эти определения, в отличие от помещенных в advr.t, почти наверняка будут отличаться для каждой конкретной игры. Когда вы достигнете завершающей стадии написания и отладки игры, вы, как правило, замените стандартные определения файла stdr.t на свои собственные (например, вы скорее всего захотите изменить стандартную функцию init файла stdr.t на свою собственную версию, которая будет отображать текстовую заставку, соответствующую вашей игре). Тем не менее стандартные определения в stdr.t вполне подойдут на начальных стадиях разработки игры.

Инструкция #include <errorru.t> аналогичным образом включает файл, определяющий русскоязычные сообщения об ошибках. Без этой инструкции все сообщения об ошибках вашей игры (например, в случае использования неизвестных игре слов) будут выводиться по-английски. Заметим, что файлы advr.t, stdr.t, generator.t и errorru.t входят в состав русскоязычной версии TADS - RTADS (собственно, они представляют собой расширение стандартного TADS). В англоязычном TADS первым двум файлам соответствуют adv.t и std.t, англоязычные сообщения "встроены" в систему, а в генераторе падежных форм нет надобности (в связи с большей простотой английского языка). Поэтому при написании англоязычной игры раздел программы, "отвечающий" за использование стандартных определений, выглядел бы так:

  #include <adv.t> 
  #include <std.t> 

Следующей строкой - startroom: room - вы сообщаете компилятору, что вами определена комната (объект room) с названием "startroom". С точки зрения языка TADS, само по себе слово "room" ничего не значит, однако в ранее включенном нами файле advr.t содержится определение объекта room. Комната (room) - это один из упомянутых нами ранее объектных классов.

Далее определяется атрибут sdesc для этой комнаты. Этот атрибут представляет собой краткое описание (от английского Short DESCription); для комнаты оно отображается всякий раз, когда игрок в нее заходит. Следующая строка определяет атрибут ldesc - полное (или "длинное") описание (от английского Long DESCription); обычно оно отображается, когда игрок заходит в комнату впервые, либо когда он запрашивает полное описание комнаты командой "осмотреться". Наконец, атрибут north указывает, что игрок, находясь в комнате startroom, может перейти в другую комнату, под названием cave, набрав команду "север".

Немного терминологии: startroom и cave - это объекты, относящиеся к классу room; sdesc, ldesc, north, и т. п. являются свойствами соответствующих объектов. В контексте программирования в TADS объектом называется поименованная сущность, определенная аналогично startroom; любой объект принадлежит какому-либо классу, который определяет "поведение" объекта (его реакции на команды игрока), а также данные, которые содержит объект. Учтите, в дальнейшем мы будем обращаться с терминологией достаточно вольно, и будем использовать слово "объект" в том же значении, что и игрок - а именно, для обращения к некоей вещи в игре, с которой игрок может взаимодействовать. На самом деле любой предмет, который воспринимается игроком в качестве объекта, имеет представление в программе в виде объекта TADS (а иногда и нескольких); в то же время программа на TADS почти всегда будет содержать ряд объектов, с которыми игрок взаимодействовать непосредственно не сможет (например, комнаты или локации - под этим термином мы будем понимать любое место в игровом мире, которое может посетить игрок).

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

TADS предлагает иной стиль программирования, чем те, с которыми вы встречались прежде. Этот стиль требует некоторого привыкания, но в процессе работы вы заметите, что он особенно эффективен для написания приключенческих игр и заметно упрощает работу. Большинство языков программирования являются "процедурно-ориентированными"; вы указываете ряд инструкций, выполняемых компьютером последовательно. С другой стороны, TADS предлагает так называемый "декларативный" подход; вы предоставляете системе описания объектов. Хотя программы TADS и содержит процедурные участки кода с последовательным выполнением инструкций, программа в целом не имеет начала и конца.

(Примечание переводчика: данное руководство писалось в начале 1990-х годов, когда имевшиеся на рынке среды разработки (языки программирования) как раз и предлагали структуру программы как жесткую последовательность инструкций. В настоящее время пользователи в массе своей гораздо лучше подготовлены к идее программы как набора отдельных обработчиков и определений, поскольку ее использует большинство современных сред разработки, ориентированных на создание именно диалоговых приложений (Visual C, Delphi, Visual Basic...) Разумеется, эти "отдельные" обработчики связаны между собой в ту самую "жесткую последовательность инструкций", но эти связи скрыты от программиста, и он избавлен от большей части рутинной работы по их организации. Совпадение концепций (или стилей) программирования здесь не случайно, поскольку приключенческая игра - это, безусловно, также диалоговое приложение. Подробнее об этом см. в следующем абзаце.)

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


Определение предметов в игре

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

pedestal: surface, fixeditem
   sdesc = "пьедестал"
   rdesc = "пьедестала"
   ddesc = "пьедесталу"
   vdesc = "пьедестал"
   tdesc = "пьедесталом"
   pdesc = "пьедестале"
   noun = 'пьедестал' 'пьедестала' 'пьедесталу' 'пьедесталом' 'пьедестале'
          'пьедесталу#d' 'пьедесталом#t' 'постамент' 'постамента' 'постаменту' 
          'постаментом' 'постаменте' 'постаменту#d' 'постаментом#t'
   isHim = true
   location = cave
;

goldSkull: item
   sdesc = "золотой череп"
   rdesc = "золотого черепа"
   ddesc = "золотому черепу"
   vdesc = "золотой череп"
   tdesc = "золотым черепом"
   pdesc = "золотом черепе"
   noun = 'череп' 'черепа' 'черепу' 'черепом' 'черепу#d' 'черепом#t' 'черепе' 
   adjective = 'золотой' 'золотого' 'золотому' 'золотым' 'золотом' 'золотому#d' 
               'золотым#t'
   isHim = true
   location = pedestal
;

Итак, мы определили два новых объекта, pedestal и goldSkull.

Объект pedestal относится сразу к двум классам, surface и fixeditem. Это означает, что он содержит свойства обоих классов; в случае конфликта свойств (т. е. если для обоих классов определено свойство с одним и тем же названием) приоритет имеет класс surface, поскольку в списке классов объекта он стоит первым. Объекты класса surface ("поверхность") позволяют класть на них другие объекты; объекты класса fixeditem ("неберущиеся" объекты) нельзя взять и носить с собой. Обратите внимание, что для объектов класса surface по умолчанию определено подробное описание (свойство ldesc), перечисляющее лежащие на них объекты.

Объект goldSkull относится к классу item ("предмет") - общему классу объектов без каких-либо специальных свойств.

Специально для русского языка дополнительно определяются атрибуты rdesc, ddesc, vdesc, tdesc и pdesc, которые просто представляют собой краткое описание объекта соответственно в родительном, дательном, винительном, творительном и предложном падежах.

Так как игрок может непосредственно взаимодействовать с этими объектами, игроку необходимы слова, чтобы обращаться к ним. Именно эти слова и определяются свойствами noun (существительное) и adjective (прилагательное). Для всех объектов, с которыми игрок может взаимодействовать, в свойстве noun должно быть определено хотя бы одно слово. (Для русского языка необходимо, кроме того, определить все падежные формы существительных и прилагательных, а также "продублировать" формы слов в дательном и творительном, а в некоторых случаях - и в родительным падежах с добавлением суффиксов, соответственно, "#d", "#t" и "#r". Это связано с особенностями работы TADS с падежами. Подробнее об этом будет рассказано далее в документации.) Обратите внимание, что для объекта pedestal определены два существительных (со всеми падежными формами); отдельные слова в списке разделяются просто пробелом. Для объектов могут также быть определены прилагательные; они служат для дополнительного различения объектов, если они используют одинаковые существительные. (Например, если бы в нашем примере наряду с золотым черепом присутствовал бы серебряный, для него надо было бы определить прилагательное "серебряный" с падежными формами). Хорошим стилем считается, когда игра "понимает" все слова, которые она использует для описания объекта; поэтому, описывая предмет как "золотой череп", следует позаботиться о том, чтобы игра понимала команды игрока типа "взять золотой череп".

Здесь у нас возникает тонкий момент. Обратите внимание, что для свойства sdesc и других текст заключен в двойные кавычки, в то время как свойства noun и adjective используют одинарные кавычки. Лексические свойства (существительные, прилагательные, глаголы, предлоги и артикли) всегда используют только одинарные кавычки. Почти во всех других свойствах будут использоваться двойные кавычки. Разница состоит в том, что строка, заключенная в двойные кавычки, выводится на экран всякий раз, когда происходит ее выполнение системой, в то время как текст в одинарных кавычках представляет собой строковое значение, которое можно обрабатывать (изменять) внутри программы. По принятым в TADS правилам строки, заключенные в двойные кавычки, автоматически выводятся на экран; это связано с тем, что в текстовых квестах большая часть текста выводится на экран без какой-либо дополнительной обработки. (Обратите внимание, что речь здесь идет именно о двойной кавычке, которой соответствует отдельный символ на клавиатуре, а не о двух одинарных кавычках, следующих подряд).

Если вы используете библиотеки RTADS версии 26 или более поздней, то можете существенно сократить определения для кратких описаний и лексических свойств - встроенный в систему генератор падежных форм сам создаст недостающие определения. Для наших черепа с пьедесталом определения запишутся следующим образом (более подробно работа с генератором будет описана ниже):

pedestal: surface, fixeditem
   desc = 'пьедестал/1м'
   noun = 'пьедестал/1м' 'постамент/1м'
   isHim = true
   location = cave
;

goldSkull: item
   desc = 'золотой/1мп череп/1м'
   noun = 'череп/1м'
   adjective = 'золотой/1мп'
   isHim = true
   location = pedestal
;

Свойство isHim, равное true, означает, что соответствующий предмет имеет мужской род. Для предметов женского рода необходимо определять атрибут isHer, равный true, а для среднего рода ни один из этих атрибутов определять не нужно.

Оба определенных нами новых объекта имеют еще одно дополнительное свойство - location (местоположение). Это свойство просто определяет объект, содержащий определяемый объект. В случае объекта pedestal содержащим его объектом является комната cave; для goldSkull, поскольку он находится на объекте pedestal, местоположением является именно pedestal. (Обратите внимание, что на данном уровне рассмотрения система не различает объекты, находящиеся внутри и на поверхности других объектов. Это, в частности, означает, что объект не может одновременно быть объектом surface (поверхностью) и container (контейнером).)


Использование генератора падежных форм

Начиная с 26-й версии системных библиотек в составе RTADS появился генератор падежных форм, позволяющий сделать определения лексических свойств объектов гораздо менее громоздкими и сократить объем ручного ввода текста. Вместо свойств sdesc, rdesc и т. д. достаточно будет определить свойство desc, а для лексических свойств noun и adjective - всего по одной форме для каждого используемого синонима.

Генератор анализирует строковые значения и динамически создает при запуске игры необходимые словоформы. Чтобы сообщить генератору о том, что требуется обработка, в строковое значение следует включить символ "/". После него указываются флаги, содержащие информацию о числе, роде и других свойствах слова. Используются следующие флаги:

Флаги, указывающие на число:
"1" - единственное число;
"2" - множественное число (нельзя использовать вместе с предыдущим флагом).
Флаги, указывающие на род:
"m" (латинская) или "м" (русская) - мужской род;
"f" или "ж" - женский род;
"n" или "с" (русская) - средний род. Вместо этого флага можно указать одновременно флаги "м" и "ж".
Флаги, указывающие на часть речи:
"a" (латинская) или "п" - указывает на то, что данное слово является прилагательным (adjective);
"у" (русская) - указывает на то, что данное слово является существительным (если вообще не указывать флаг, указывающий на часть речи, слово в любом случае будет трактоваться как существительное, поэтому данный флаг практически не используется).
Дополнительные флаги:
"i" или "о" (русская) - указывает на то, что слово обозначает одушевленный (animated) объект;
"u" или "д" - указывает на ударное (accentuated) окончание слова. Вместо указания данного флага можно написать в окончании прописную букву;
"-" - указывает, что слово не должно склоняться; как правило, задается для существительных-определений в сочетаниях вида "голова жирафа".

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

флаги "1" и "2";

флаги "м" и "с", а также "ж" и "с";

флаги "п" и "у";

флаг "-" и флаги числа, рода и дополнительные.

В качестве примера приведем определение тестового объекта из файла generator.t.

testobj: item
desc='странный/1мп предмет/1м из иного/п- мира/п-'
adjective = 'плоский/1м'  'акульи/2'
noun='воблы/2ж' 'крюки/м2' 'рука/1ж' 'вилы/2' 'щепочка/1ж' 'быстрая/п1ж' 'блоха/ж' 'муравьИ/2ом'
;


Как добиться нужных реакций от предметов

Несмотря на все улучшения, наша игра пока по-прежнему, мягко говоря, скучновата: в ней нет ни одной загадки. Что ж, попробуем ввести несложную задачку. Предположим, что золотой череп был оставлен не просто так; тот, кто оставил его, подстроил ловушку, которая должна срабатывать, когда череп пытаются поднять с пьедестала. Чтобы реализовать эту ловушку, нам понадобится определить для объекта goldSkull метод. Методом называется свойство объекта специального типа, которое содержит исполняемый код, т. е. набор инструкций, который игра должна выполнить при обращении к этому свойству. В этом смысле метод аналогичен функции в Си или Паскале. Новый объект goldSkull, для которого определен метод, будет выглядеть так:

  goldSkull: item
   sdesc = "золотой череп"
   rdesc = "золотого черепа"
   ddesc = "золотому черепу"
   vdesc = "золотой череп"
   tdesc = "золотым черепом"
   pdesc = "золотом черепе"
   noun = 'череп' 'черепа' 'черепу' 'черепом' 'черепу#d' 'черепом#t' 'черепе' 
   adjective = 'золотой' 'золотого' 'золотому' 'золотым' 'золотом' 'золотому#d' 
               'золотым#t'
   isHim = true
   location = pedestal
   doTake(actor) =
   {
     "Едва ты успеваешь поднять череп, как из стен вылетает целая туча
      отравленных стрел! Ты пытаешься увернуться от них, но их слишком много!";
      die();
   }
;

Либо, при использовании генератора:

  goldSkull: item
   desc = 'золотой/1мп череп/1м'
   noun = 'череп/1м'
   adjective = 'золотой/1мп'
   isHim = true
   location = pedestal
   doTake(actor) =
   {
     "Едва ты успеваешь поднять череп, как из стен вылетает целая туча
      отравленных стрел! Ты пытаешься увернуться от них, но их слишком много!";
      die();
   }

Методу doTake (что расшифровывается как "direct object take" - реакция на глагол "Take" (взять) для "прямого" объекта) в качестве аргумента передается персонаж, который берет объект; так как в этой игре у нас не будет других персонажей, кроме главного (ГП) - т. е. того, за которого играет игрок, то в качестве параметра actor всегда будет передаваться ГП (по умолчанию это объект Me, определенный в файле advr.t). Пока мы просто определили этот метод таким образом, чтобы на экран выводилось сообщение (поскольку текст заключен в двойные кавычки, он сразу же выводится на экран при выполнении), после чего осуществлялся бы вызов специальной функции die (скобки после слова die указывают TADS, что речь идет именно о функции die, а не о свойстве объекта).

Не следует думать, что название метода doTake взято нами с потолка. Метод doTake объекта goldSkull вызывается программой-интерпретатором TADS всякий раз, когда игрок вводит команду "take" (взять) с объектом goldSkull в качестве "прямого" объекта (или объекта непосредственной манипуляции - подробнее об этом см. далее). Каждый введенный игроком глагол "заставляет" систему вызывать определенные методы объекта или объектов, поименованных в команде. Способ определения названий этих методов подробно описан далее в документации.

У вас может возникнуть вопрос, почему нам не понадобилось определять метод doTake для объекта goldSkull в его первоначальной редакции; вам даже могло показаться, что система сама знает, что делать, если метод doTake не определен для объекта. На самом деле метод doTake должен быть определен для всех объектов, а система не знает, что делать при его отсутствии. Однако, поскольку большинство объектов (за редким исключением - типа нашего goldSkull) будут иметь одинаковый вид метода doTake, записывать метод doTake для каждого объекта в игре было бы однообразным и утомительным занятием. Вместо этого мы используем так называемое "наследование". Определяя объект goldSkull как принадлежащий классу item, мы сообщаем TADS, что goldSkull "наследует" все определения свойств для item в дополнение к тем свойствам, которые определены непосредственно в нем самом. Класс item, определенный в файле advr.t, который был включен в текст программы в самом начале инструкцией #include, и определяет метод doTake, поэтому все-все объекты, объявленные как принадлежащие классу item, перенимают это определение. Однако когда какое-либо свойство определено как в классе item, так и в объекте goldSkull (как метод doTake в нашем примере), приоритет имеет определение объекта goldSkull - оно "заменяет" унаследованный метод.

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

smallRock: item
   sdesc = "мелкий камень"
   rdesc = "мелкого камня"
   ddesc = "мелкому камню"
   vdesc = "мелкий камень"
   tdesc = "мелким камнем"
   pdesc = "мелком камне"
   noun = 'камень' 'камня' 'камню' 'камнем' 'камне' 'камню#d' 'камнем#t'
   adjective = 'мелкий' 'мелкого' 'мелкому' 'мелким' 'мелком' 'мелкому#d' 'мелким#t'
   isHim = true
   location = cave
;

Либо, при использовании генератора падежных форм:

smallRock: item
   desc = 'мелкий/1мп камень/1м'
   noun = 'камень/1м'
   adjective = 'мелкий/1мп'
   isHim = true
   location = cave
;

А теперь изменим метод doTake объекта goldSkull.

doTake(actor) =
   {
      if (self.location <> pedestal or         /* Меня уже сняли с пьедестала? */
          smallRock.location = pedestal)       /* А может быть, камень лежит на пьедестале? */
      {
         pass doTake;			       /* Да (хотя бы одно из вышеприведенных условий */
                                               /* верно) - берем череп как обычно */
      }
      else                                     /* Нет - срабатывает ловушка! */
      {
         "Едва ты успеваешь поднять череп, 
          как из стен вылетает целая туча
          отравленных стрел! Ты пытаешься 
          увернуться от них, но их слишком 
          много!";
         die();
      }
   }

Этот новый метод doTake сначала проверяет, снят ли уже с пьедестала объект, который берут (специальный (объект self, чей метод doTake был вызван первым - в нашем случае это золотой череп); если уже снят (т. е. находится не на пьедестале), ничего не должно происходить, и мы "передаем" (инструкция pass) вызов doTake. Мы также передаем вызов, если камень лежит на пьедестале. Когда мы передаем вызов метода инструкцией pass, происходит вызов метода doTake, унаследованного нашим объектом от соответствующего класса, называемого родительским (в нашем случае это класс item). Это позволяет нам заменять методы только частично, при определенных обстоятельствах, а в остальных случаях пользоваться унаследованными методами. Если ни одно из проверяемых условий не выполняется, срабатывает ловушка - выдается сообщение о запуске отравленных стрел.

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

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

Данный пример должен дать вам самое общее представление о том, как работает программа в TADS. В следующих главах мы более подробно рассмотрим язык программирования, а также изучим все классы, определенные в advr.t. Обратите внимание на то, что в дистрибутив TADS включен исходный текст гораздо более объемной игры; в процессе чтения оставшейся части руководства вам будет полезно обращаться к нему для ознакомления с конструкциями языка. Может также оказаться, что отдельные части этой игры могут быть использованы вами в качестве образца для объектов ваших собственных игр. Кроме того, имейте в виду, что шестая глава настоящего руководства несколько более подробно описывает процесс создания игры и приводит пример построения текстового квеста большего объема; возможно, вам будет полезно обратиться к главе 6 после того, как вы немного освоитесь с TADS.

В дистрибутив входит файл под названием GOLDSKUL.T (в английском варианте; русский вариант (файл GOLDSKLR.T - версия для старых версий системных библиотек; GSKLRU26.T - для библиотек со встроенным генератором) можно найти на http://www.rtads.org), включающий данную демо-игру, в том числе и всю задачку с золотым черепом и пьедесталом в законченном виде.

Если вы компилируете файл из интегрированной среды разработки TADS (TADS Workbench) командами Compile and Run (скомпировать и запустить) или Compile for Debugging (компилировать для отладки) из меню Built (компиляция), то при запуске игры будет выводиться перечень сгенерированных словоформ. Это делается для того, чтобы автор имел возможность просмотреть этот перечень и выявить ошибки, допущенные генератором падежей (они нечасто, но встречаются). Если такие ошибки обнаружены, то для соответствующего слова падежные формы надо будет прописать вручную. Однако, если вы отправите информацию об этой ошибке автору русифицированных библиотек, в следующей их версии она будет устранена. Для того, чтобы перечень словоформ не выводился, используйте для компиляции команду Compile for Release (компилировать для релиза).




Пример всегда действеннее, чем предписание.
СЭМЮЭЛЬ ДЖОНСОН (SAMUEL JOHNSON), Расселас (1759)


Предисловие Содержание Глава вторая