Forum.iFiction.Ru

iFiction.Ru · ifHub · FAQ · IFWiki · QSP · URQ · INSTEAD · AXMA

форум об interactive fiction, текстовых приключенческих играх и всём таком...

Вы не зашли.

   #1
08.01.2011 14:17

soflot
Участник
Откуда: Киев, Украина
Зарегистрирован: 23.11.2007
Сообщений: 27
Вебсайт

[[ ни дня без строчки ]]

разговоры: говорить, спросить про ... , рассказать про ...

Разбираюсь с RTADS, хочу сделать чтобы с персонажем можно было хоть немного поговорить.
Насколько я понял, "Говорить" выдаёт Actor.talkdesc. Там можно проверять какие-нибудь значения и выдавать разные фразы, но нельзя выбрать заданную тему разговора (т.е. "говорить с Джеком про забор")

Я не совсем разобрался как спрашивать о чём-то. Я знаю что вызывается Actor.askWord(word, lst) и внутри можно сравнивать переданный параметр word с какими-то значениями и выдавать нужные фразы. (например,  "спросить Джека про забор", а потом проверять if(word='забор'){...}    ), если слово распознано то return true а если не распознано то return nil, и тогда выведется "я ничего про это не знаю"
Или может быть надо использовать Actor.verDoAskAbout(actor, io) ?

Насчёт "рассказать про" вообще мало понятно, я понял только что вызывается Actor.verDoTellAbout(actor, io), где io - это тот объект, про который мы хотим рассказать.

Подскажите пожалуйста, как правильно использовать "спросить" и "рассказать" в RTADS?
Что предпочтительнее для "спросить" - askWord или verDoAskAbout?
Почему нет аналога askWord для "рассказать"? (а если есть, то как называется?)
Не получается использовать слова, не связанные с объектами. Т.е. если в описании локации есть "гора", но нет такого объекта, то нельзя спросить персонажа про гору, даже если проверять  if(word='гора'), т.к. до эого участка ничего не дойдёт, парсер сразу выдаст  что не знает слова "гора". Это так и задумано, надо делать что-то вроде FloatingItem чтобы про этот объект можно было спросить или рассказаь?
Есть ли какие-нибудь статьи по разговорам в TADS/RTADS, или хорошо документированные исходники игр с разговорами?

Неактивен

   #2
08.01.2011 17:05

soflot
Участник
Откуда: Киев, Украина
Зарегистрирован: 23.11.2007
Сообщений: 27
Вебсайт

[[ ни дня без строчки ]]

Re: разговоры: говорить, спросить про ... , рассказать про ...

Почитал ещё мануал по RTADS, нашёл про "Диалог с актерами". Стало понятнее, но там мало, всё равно остались вопросы:
какой из методов предпочтительнее - Actor.askWord или Actor.doAskAbout?
Использование слов без соответствующих объектов
какие есть хорошо документированные исходники игр с разговорами?

Не совсем понятно что должно быть в verDoTellAbout, а что в doTellAbout. По идее в verDoTellAbout идёт верификация, проверяются какие-то условия и какие-то неверные действия отклоняются. Но неясно как отклонять а как пропускать - то ли return true, то ли pass verDoTellAbout...
И как вообще идеологически правильно использовать эти 2 метода? первым отделять грубые ошибки, а во втором уже проверять какие-то специфические условия? Можете привести какие-нибудь примеры?

Неактивен

   #3
09.01.2011 09:03

uux
Участник (+690, -42)
Откуда: Москва
Зарегистрирован: 02.12.2006
Сообщений: 1543

Re: разговоры: говорить, спросить про ... , рассказать про ...

Ох... Сначала пару общих слов, а потом постараюсь ответить на конкретные вопросы.

Если не вдаваться в подробности, то основная последовательность вызовов глагольных методов-верификаторов и действий (для случая, когда есть и "прямой", и "косвенный" объект - типа, "спросить прямой объект о косвенном объекте") в TADS следующая:

Код:

 dobj.verDoГлагол(actor, iobj)
 iobj.verIoГлагол(actor)
 iobj.ioГлагол(actor, dobj)

Здесь actor - это объект, соответствующий актеру, выполняющему команду (чаще всего главному персонажу), dobj - "прямой" объект, iobj - "косвенный" объект, Глагол - префикс, соответствующий глаголу. Для команды "спросить волщшебника о телевизоре" этот префикс будет "AskAbout", актером (actor) будет объект Me, соответствующий ГП. Пусть волшебнику в коде игры соответствует объект Wizard, а телевизору - TV. Тогда "умолчальная" последовательность вызовов методов-обработчиков команды будет выглядеть так:

Код:

Wizard.verDoAskAbout(Me, TV)
TV.verIoAskAbout(Me)
TV.ioAskAbout(Me, Wizard)

(Чуть подробнее о порядке вызова методов можно почитать в обзорной документации: http://www.rtads.org/man/OVERVIEW.HTM, в разделе "Когда выполняются методы?"

Еще более подробная информация содержится в главе "Последовательность синтаксического анализа" http://www.rtads.org/man/TADSPASE.HTM, но ее новичку лучше не читать в принципе, чтобы не запутаться, да и опытным авторам содержащаяся там информация нужна не очень часто.)

Но вернемся к нашему примеру.

Прежде всего бросается в глаза следующее: метод doAskAbout по умолчанию вызываться не будет. Вероятно, такой подход наиболее удобен для широко распространенных команд с двумя объектами (типа "положить кирпич в коробку". Однако для команд "спросить о", "рассказать о", конечно, удобнее, когда разбор осуществляется в "прямом" объекте (поскольку он соответствует тому персонажу, с которым собираются пообщаться). С этой целью в стандартной библиотеке advr.t явным образом прописан вызов этого метода (в определении класса thing):

Код:

ioAskAbout(actor, dobj) =
{
 dobj.doAskAbout(actor, self);
}

self, напомню - это псевдообъект - ссылка на самого себя (т. е. для нашего объекта TV он примет значение TV).

Замечу также, что метод doAskAbout можно было бы назвать как угодно - хоть просто Ask, хоть вообще Abrakadabra. Просто выбранное название хорошо ложится в общую идеологию наименований методов, принятую в TADS.

Методы-верификаторы служат для того, чтобы отсечь заведомо невозможные действия. Если проверка дала отрицательный результат, дальнейшие методы в цепочке не вызываются. Критерием успешности проверки является отсутствие вывода на экран. На мой взгляд, это прямо-таки гениальная находка Майкла Робертса. Хорошими демонстрационными примерами являются как раз соответствующие верификаторы для класса thing, потомками которого являются все остальные предметы и персонажи в любой игре на TADS. По умолчанию для большинства объектов в игре принята следующая модель поведения: спрашивать о них можно, без ограничений, их же самих ни о чем спросить нельзя. Таким образом, соответствующий "прямой" метод-верификатор для "умолчального" объекта будет запрещать общение в любом случае (просто выводя фразу на экран)

Код:

verDoAskAbout(actor, io) =
{
 "<<ZAG(self,&sdesc)>> <<glok(self,'хранить')>> молчание. ";
}

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

Код:

verIoAskAbout(actor) = {}

В TADS (и RTADS) методы-обработчики AskAbout доработаны в классе movableActor (родительском для всех персонажей в игре) так, чтобы облегчить реализацию команды "спросить о". Там из метода doAskAbout осуществляется вызов askWord, который проверяет, есть ли у персонажа подходящий ответ на ту или иную тему. Если есть, данный метод выводит это сообщение и возвращает true, если нет, возвращает nil, и doAskAbout благодаря этому "понимает", что надо вывести ответ по умолчанию.

Коротенько об остальных "коммуникационных" глаголах.

"Рассказать о": этот глагол также предполагает использование в команде "прямого" и "косвенного" объекта. Все, что сказано про обработчики для "спросить о", верно и для него, за одним исключением: Майкл Робертс облегчил себе жизнь, не став затачивать "персонажный" класс movableActor под использование этого
глагола, ограничившись выбором такого сообщения в верификаторе verIoAskAbout класса thing, которое подошло бы и для неодушевленных, и для одушевленных предметов (упомянутый Вами раздел мануала содержит в этом отношении дезинформацию;). Обойти это несложно: в определении своего объекта-персонажа просто скопипейстить методы verDoAskAbout, doAskAbout, askWord и disavow из метода movableActor, переименовав их, соответственно, в verDoTellAbout, doTellAbout, tellWord и distvow (для последних двух методов названия могут быть произвольными) и, конечно, не забыть поправить соответствующие вызовы.

"Говорить с": в стандартной библиотеке реализован как глагол только с "прямым" объектом (т. е. можно "говорить с персонажем" вообще, но нельзя
"говорить с персонажем про жизнь"). На первых порах можно (и даже лучше) пока его не трогать. Если очень хочется реализовать "говорить с... о...", то ИМХО проще всего добиться этого, добавив "говорить" в качестве синонима в tellVerb (однако тут тоже есть свои подводные камни).

На конкретные вопросы постараюсь ответить вечером - сейчас мне нужно убегать. Надеюсь, не очень Вас загрузил;).

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

Отредактировано uux (09.01.2011 09:06)

Неактивен

   #4
09.01.2011 19:15

uux
Участник (+690, -42)
Откуда: Москва
Зарегистрирован: 02.12.2006
Сообщений: 1543

Re: разговоры: говорить, спросить про ... , рассказать про ...

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

Подскажите пожалуйста, как правильно использовать "спросить" и "рассказать" в RTADS?

Ну, надеюсь, мы с Вами в конце концов разберемся;).

Что предпочтительнее для "спросить" - askWord или verDoAskAbout?
какой из методов предпочтительнее - Actor.askWord или Actor.doAskAbout?

Ох... Когда я переводил этот кусок мануала (шесть лет назад), я бы однозначно ответил, что askWord. Сейчас я в этом менее уверен, и вот почему.

Разбор вопроса на основе лексики (askWord) хорош тем, что позволяет не зацикливаться на конкретном объекте. Т. е. если, скажем, главный персонаж (ГП) общается с актером, который держит в руках ключ, а в игре есть несколько ключей (золотой, серебряный и т. п.), то понятно, что когда игрок вводит "спросить актера о ключе", он ожидает, что тот ответит именно про тот, который у него в руках. О существовании других ключей он может и не знать. Так вот, при работе со словарем мы просто проверяем слово "ключ" и не зацикливаемся на том, сколько еще ключей у нас в игре. Что самое замечательное - если мы задним числом (уже отладив общение с персонажем) добавляем в игру еще один ключ, логика работы не нарушается.

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

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

В общем, однозначного решения нет. Сейчас мое мнение таково: если у Вас небольшая игра с минимальным (а в идеале вообще отсутствующим) перекрытием объектов по лексике, лучше напрямую сравнивать объекты в doAskAbout. По мере увеличения количества лексически однородных объектов в игре метод с askWord становится все более привлекательным.

Почему нет аналога askWord для "рассказать"? (а если есть, то как называется?)

Об этом см. мой предыдущий пост - Майкл Робертс просто облегчил себе жизнь.

Не получается использовать слова, не связанные с объектами. Т.е. если в описании локации есть "гора", но нет такого объекта, то нельзя спросить персонажа про гору, даже если проверять  if(word='гора'), т.к. до эого участка ничего не дойдёт, парсер сразу выдаст  что не знает слова "гора". Это так и задумано, надо делать что-то вроде FloatingItem чтобы про этот объект можно было спросить или рассказаь?

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

Есть ли какие-нибудь статьи по разговорам в TADS/RTADS, или хорошо документированные исходники игр с разговорами?

На русском языке статей не знаю. Исходник игры с разговорами наверняка есть у ГрАнда ("Дримор"), там есть очень словоохотливые персонажи;).

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

Не совсем понятно что должно быть в verDoTellAbout, а что в doTellAbout. По идее в verDoTellAbout идёт верификация, проверяются какие-то условия и какие-то неверные действия отклоняются. Но неясно как отклонять а как пропускать - то ли return true, то ли pass verDoTellAbout... -

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

И как вообще идеологически правильно использовать эти 2 метода? первым отделять грубые ошибки, а во втором уже проверять какие-то специфические условия? Можете привести какие-нибудь примеры?

Общий принцип: метод-верификатор отсекает грубые ошибки (например, попытку взять fixedItem), метод-действие выполняет команду (меняет состояние переменных в игре). Промежуточные варианты (например, попытка взять предмет, когда руки заняты) - на усмотрение автора. Самое главное правило - метод-верификатор не должен ничего менять в игре (присваивать переменные, перемещать объекты и т. п.). Связано это с тем, что верификаторы используются системой при "разруливании" неоднозначных команд (т. е. когда игра пытается сама определить, какой из объектов c одинаковой лексикой игрок имел в виду в своей команде - типа, золотой ключ или серебряный). При этом данные методы вызываются втихую (т. е. с отключенным выводом на экран). Если верификатор совершает какое-то действие, меняющее состояние игры, игрок об этом ничего не узнает и впоследствии будет сильно поражен, когда, скажем, его любимый меч куда-то исчезнет из инвентаря. К тому же (говорю из собственного горького опыта;) докопаться до причины подобных багов - занятие нетривиальное.

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

Отредактировано uux (09.01.2011 19:17)

Неактивен

   #5
10.01.2011 23:26

soflot
Участник
Откуда: Киев, Украина
Зарегистрирован: 23.11.2007
Сообщений: 27
Вебсайт

[[ ни дня без строчки ]]

Re: разговоры: говорить, спросить про ... , рассказать про ...

Спасибо, uux, мне этого пока достаточно.
Особенно спасибо за уточнение насчёт "отклоняете Вы посредством вывода сообщения на экран, а пропускаете - тем, что ничего не выводите.". Я бы до такого вряд ли бы додумался сам.
Я думаю этого всего мне вполне хватит чтобы реализовать задуманное.

Неактивен

Powered by PunBB
© copyright 2001–2018 iFiction.Ru