Forum.iFiction.Ru

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

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

Вы не зашли.

Объявление

Перечень игр КРИЛ 2018 открыт! Можно играть, оставлять комментарии и ставить оценки!

   #1
09.04.2011 19:09

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Игра пример

В примере из демонстрационной игры (http://rtads.org/man/TADSSMPL.HTM), следующая штука выходит:
Чтобы взять череп с пьедестала, нужно предварительно положить на него камень, тогда не сработает ловушка... но, если забрать только что положенный камень, ловушка так же не сработает:), ведь, по логике самого метода, при отсутствии на пьедестале объекта, вышеназванного бага, не должно быть...  Сам метод: 

Код:

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

Отредактировано Kephra (09.04.2011 19:52)

Неактивен

   #2
10.04.2011 03:05

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Re: Игра пример

У меня вопрос по поводу игры-примера для информа, (http://rinform.stormway.ru/tutor/01-Heidi.html)

Код:

 Object branch "надежн/ый толст/ый сук/" top_of_tree

Наверное такая логика у парсера, что если сказать "положить гнездо на суку/суки/сука" и т.д. парсер это схавает и положит гнездо, но только на сук

>положить гнездо на суки
Ты кладёшь птичье гнездо на надежный толстый сук.

даже если поменять в коде "сук/" на "сук" что, по теории должно отменить варианты окончания слова, но и это не помогает... Да, это всё пустяки, не стоит наверное обращать внимания, хоть и понимаю, что не каждому второму придет в голову извращаться так с объектом, но все же, если есть метод, хорошо бы его знать, и по случаю применить.

Неактивен

   #3
10.04.2011 17:13

yandexx
Z-машина (+42, -3)
Откуда: Санкт-Петербург
Зарегистрирован: 01.06.2007
Сообщений: 393
Вебсайт

Русский Информ
Информ Discord

Re: Игра пример

Kephra написал:

У меня вопрос по поводу игры-примера для информа...

Слеши в имени объекта используются только при выводе названия.
При вводе же рассматриваются ключевые слова указанные в перечислении name, с различными окончаниями. В обоих случаях учитывается род объекта (male, female, neuter, plural).

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

Собственно как задано стандартное поведение в библиотеке (cAcc -- аккузатив, винительный падеж):

! "положи"/"клади"/"вставь"/"поместить"/"сунуть"
Verb    'лож'
    'класт' 'клад'
    'став'
    'мест' 'мещ'
    'сов' 'су'
                * cAcc_multiheld            -> Drop
                * cAcc_multiexcept 'в'/'во' cAcc_noun    -> Insert
                * 'в'/'во' cAcc_noun cAcc_multiexcept    -> Insert reverse
                * cAcc_multiexcept 'внутрь' cGen_noun    -> Insert
                * 'внутрь' cGen_noun cAcc_multiexcept    -> Insert reverse
                * cAcc_multiexcept 'на' cAcc_noun    -> PutOn
                * 'на' cAcc_noun cAcc_multiexcept    -> PutOn reverse;

Неактивен

   #4
10.04.2011 19:25

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

Re: Игра пример

Kephra написал:

В примере из демонстрационной игры (http://rtads.org/man/TADSSMPL.HTM), следующая штука выходит:
Чтобы взять череп с пьедестала, нужно предварительно положить на него камень, тогда не сработает ловушка... но, если забрать только что положенный камень, ловушка так же не сработает:), ведь, по логике самого метода, при отсутствии на пьедестале объекта, вышеназванного бага, не должно быть...  Сам метод: 

Код:

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

Kephra, еще раз призываю выслать мне код на мыло. Я честным образом скачал ту самую демо-игру из раздела игр сайта RTADS: http://rtads.org/man/GOLDSKLR.zip - оно пашет именно так, как надо, т. е. если положить камень на пьедестал, а потом убрать и взять золотой череп, ловушка срабатывает.

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

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

Неактивен

   #5
10.04.2011 19:38

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Re: Игра пример

uux написал:

Kephra, еще раз призываю выслать мне код на мыло. Я честным образом скачал ту самую демо-игру из раздела игр сайта RTADS: http://rtads.org/man/GOLDSKLR.zip - оно пашет именно так, как надо, т. е. если положить камень на пьедестал, а потом убрать и взять золотой череп, ловушка срабатывает.

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

>Пещера
    взять камень
Взят.

>Пещера
    положить на пьедестал
(мелкий камень)
Готово.

>Пещера
    взять череп
Взят.

>Пещера
    взять камень
Взят.

>Пещера
    инв
У тебя имеется:
   золотой череп
   мелкий камень

>Пещера
    smile

Отредактировано Kephra (10.04.2011 19:39)

Неактивен

   #6
10.04.2011 19:40

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Re: Игра пример

uux написал:

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

Спасибо, интересно, я поработаю с ним, если возникнут вопросы, обязательно задам:).

Неактивен

   #7
10.04.2011 20:01

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

Re: Игра пример

Kephra написал:

...

Ну, мыло я оставлял на форуме RTADS,  но по ЛС тоже вс получил;).

Да, то, что Вы описываете - так оно действительно и должно работать;). Я так подозреваю, что преувеличенный примитивизЬм примера - часть оригинальной задумки. Чтобы ловушка срабатывала и при снятии камня с пьедестала, надо доработать метод doTake камня... задание для самостоятельной работы;), помощь в которой, если она понадобится, Вам конечно же окажут;).

Неактивен

   #8
10.04.2011 20:02

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Re: Игра пример

yandexx написал:

Слеши в имени объекта используются только при выводе названия.
При вводе же рассматриваются ключевые слова указанные в перечислении name, с различными окончаниями. В обоих случаях учитывается род объекта (male, female, neuter, plural).

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

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

Неактивен

   #9
10.04.2011 20:13

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Re: Игра пример

uux написал:

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

Я об этом подумал сразу же как увидел "баг", но, если в комнате лежит еще несколько камней, и других объектов, в сумме может набраться до 10/20 объектов в игре немного большей игры-примера, не прописывать же в самом деле для каждого, один и тот же метод? Куда логичнее прописать метод для пьедестала, и тогда можно оставлять на нём любой объект и ловушка не сработает, но и в этом случае имеется "баг", если заменить череп спичечным коробком, пёрышком, или дохлой блошкой smile и тогда, ловушка так же не сработает... Или в ТАДС можно задать объекту, свойство веса?

upd
Я кажется понял, можно для пьедестала прописать метод, в котором перечислить по своему усмотрению, те объекты, которыми можно заменить череп... но как это сделать?smile Ладно, я попытаюсь сам дойти.

Отредактировано Kephra (10.04.2011 21:21)

Неактивен

   #10
11.04.2011 20:54

yandexx
Z-машина (+42, -3)
Откуда: Санкт-Петербург
Зарегистрирован: 01.06.2007
Сообщений: 393
Вебсайт

Русский Информ
Информ Discord

Re: Игра пример

Kephra написал:

yandexx написал:

Слеши в имени объекта используются только при выводе названия.
При вводе же рассматриваются ключевые слова указанные в перечислении name, с различными окончаниями. В обоих случаях учитывается род объекта (male, female, neuter, plural).

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

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

Когда падеж не важен, то всё и так работает. Но вот, например, код из моей игры Робото, где определён нестандартный глагол:

Verb 'маз' ! (на)мазать
    * cAcc_noun -> Smear
    * cIns_noun cAcc_noun -> Smear             ! вазелином что-то
    * cAcc_noun cIns_noun -> Smear reverse        ! что-то вазелином
    * cAcc_noun 'на' cAcc_noun -> Smear            ! вазелин на что-то
    * cAcc_noun 'по' cDat_noun -> Smear;        ! вазелин по чему-то

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

Неактивен

   #11
12.04.2011 05:31

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

Re: Игра пример

Kephra написал:

uux написал:

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

Я об этом подумал сразу же как увидел "баг", но, если в комнате лежит еще несколько камней, и других объектов, в сумме может набраться до 10/20 объектов в игре немного большей игры-примера, не прописывать же в самом деле для каждого, один и тот же метод? Куда логичнее прописать метод для пьедестала, и тогда можно оставлять на нём любой объект и ловушка не сработает, но и в этом случае имеется "баг", если заменить череп спичечным коробком, пёрышком, или дохлой блошкой smile и тогда, ловушка так же не сработает... Или в ТАДС можно задать объекту, свойство веса?

Да, свойство веса задать можно. (Собственно, оно уже определено в стандартной библиотеке - называется weight). Кроме того, можно определить метод один раз для одного объекта, а потом делать остальные его наследниками.

Kephra написал:

upd
Я кажется понял, можно для пьедестала прописать метод, в котором перечислить по своему усмотрению, те объекты, которыми можно заменить череп... но как это сделать?smile Ладно, я попытаюсь сам дойти.

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

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

 спойлер…

Неактивен

   #12
30.08.2018 02:18

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Re: Игра пример

Код:

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

Нафига эта проверка self.location <> pedestal ??? Как это вообще понять умом человеческим?
Всё и так работает без этого, если оставить проверку только на камень. Пробовал брать череп, выбрасывать из инвентаря на пол, поднимал его и снова ставил на пьедестал, потом снова брал. Брал с камнем на пьедестале и без него, в последнем случае погибал как надо. Во всех остальных случаях так же всё работало.

UPD

Ааааа... всё, понял. Если камень не на пьедестале, а череп на полу и если поднять его, то сработает die() без self.location <> pedestal. Одно не понятно что это за стрелочки больше-меньше? Они эквивалентны оператору «!=» в Си?

Отредактировано Kephra (30.08.2018 02:40)

Неактивен

   #13
30.08.2018 03:10

Nikita
Модератор (+333, -117)
Зарегистрирован: 29.10.2016
Сообщений: 108

Re: Игра пример

Kephra написал:

Одно не понятно что это за стрелочки больше-меньше? Они эквивалентны оператору «!=» в Си?

Да, <> - это неравно. В принципе, != TADS тоже понимает, так что можно использовать и этот оператор.

Синтаксис языка описан в главе 5.

Вообще в "Золотом черепе" этот пазл реализован не лучшим образом. Во-первых, смещение черепа лучше регистрировать через метод moveInto в его объекте (это любое изменение location, а не только взятие предмета в руки), а во-вторых, там проблемы с физикой процесса, так как потом булыжник можно забрать и ничего не произойдёт. Но это всё пока вам не важно.

Неактивен

   #14
30.08.2018 04:15

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Re: Игра пример

Nikita написал:

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

Я сделал так:

Код:

moveInto(self) =
   {
      if (smallRock.location = pedestal)
      {
         pass doTake;

      }
      else
      {
         "Едва ты успеваешь поднять череп,
          как из стен вылетает целая туча
          отравленных стрел! Ты пытаешься
          увернуться от них, но их слишком
          много!";
         die();
      }
   }

И теперь без «self.location <> pedestal» если взять череп с пола при отсутствии камня на пьедестале, die() не срабатывает. Так код выглядит намного лучше: смотрю и радуюсь smile.

UPD

Что такое метод русским языком? Технически, это функция?

UPD

Да согласно мануалу: метод эта функция, только он является частью объекта и самостоятельно (вне объекта) не используется, в отличии от функции.

Отредактировано Kephra (30.08.2018 12:44)

Неактивен

   #15
30.08.2018 15:10

Nikita
Модератор (+333, -117)
Зарегистрирован: 29.10.2016
Сообщений: 108

Re: Игра пример

Kephra написал:

Я сделал так:

Нет, это не совсем верно:

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

Во-вторых, команда pass передаёт обработку указанному методу объекта родителя. То есть мы в текущем объекте модифицировали какой-то метод, а потом хотим, чтобы в остальном он отработал по стандартной схеме, и для этого как раз и вызываем его по pass. Однако вы модифицируете метод moveInto, то есть перемещение объекта, но дальше передаёте обработку в doTake, то есть метод взятия, тогда как перемещаться череп может не только из-за взятия его в руки, а например, из-за перекладывания на пол. Как раз командой "положить череп на пол" исходная реализация пазла и ломается. В общем если модифицируем moveInto, то и дальше по pass передаём обработку тоже в moveInto.

В итоге, должно быть так:

Код:

moveInto(obj) =
{
    // В момент передвижения череп на пьедестале, но камня на нём нет
    if(self.location = pedestal && smallRock.location != pedestal)
    {
        "Бла-бла-бла. ";
        die();
    }
    // moveInto работает дальше как обычно
    pass moveInto;
}

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

Неактивен

   #16
30.08.2018 17:26

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Re: Игра пример

Nikita написал:

Нет, это не совсем верно:

Да, это СОВСЕМ не верно. Даже не знаю, как я вчера смог взять череп с пьедестала (было 4 часа бессонного утра), когда уже сегодня на этом моменте игра бесконечно зациклилась — видимо на pass doTake — и сообщения «Взят (череп)» посыпались на экран, пока интерпретатор не понял, что происходит, и не выдал сообщение об ошибке.

Отредактировано Kephra (30.08.2018 17:27)

Неактивен

   #17
30.08.2018 20:50

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Re: Игра пример

Nikita написал:

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

Я не совсем понимаю как работает этот метод. Зачем вообще передавать что-то в него? Это же функция? Как в «doTake» так и в «moveInto» можно передать любой локальный, нейтральный, пустой объект вида «asdasd», но если этого не сделать, интерпретатор при срабатывании такого метода, выдаст ошибку. Но дело в том, что совершенно неважно что я туда впишу. Однако в мануале-то «actor» используют в качестве аргумента «doTake», зачем это делать, — не понятно, но поясняется следующее: «Определение атрибута doTake использует в качестве аргумента персонаж (actor), который пытается взять объект.» и «Система вызывает doTake каждый раз, когда игрок пытается взять объект.» Эти оба пояснения в документации следуют друг за другом. Каждое, говорит совершенно о разных вещах, но воспринимается как — об одном. Думается, будто надо использовать исключительно тот аргумент с которым будет взаимодействовать объект (в нашел случае золотой череп с актером). Иначе, ничего не будет работать. Но это не так, поэтому пояснение: «Определение атрибута doTake использует в качестве аргумента персонаж (actor), который пытается взять объект.» — даёт ложное представление, причем не объясняется зачем это делать.

Отредактировано Kephra (30.08.2018 21:41)

Неактивен

   #18
30.08.2018 22:45

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

Re: Игра пример

Kephra написал:

Однако в мануале-то «actor» используют в качестве аргумента «doTake», зачем это делать, — не понятно, но поясняется следующее: «Определение атрибута doTake использует в качестве аргумента персонаж (actor), который пытается взять объект.» и «Система вызывает doTake каждый раз, когда игрок пытается взять объект.» Эти оба пояснения в документации следуют друг за другом. Каждое, говорит совершенно о разных вещах, но воспринимается как — об одном. Думается, будто надо использовать исключительно тот аргумент с которым будет взаимодействовать объект (в нашел случае золотой череп с актером). Иначе, ничего не будет работать. Но это не так, поэтому пояснение: «Определение атрибута doTake использует в качестве аргумента персонаж (actor), который пытается взять объект.» — даёт ложное представление, причем не объясняется зачем это делать.

doTake - это не функция, а метод, причем вызываемый автоматически. В TADS для глаголов определяется набор методов-обработчиков, название которых определяется свойствами doAction и/или ioAction объекта-глагола (подробнее см. здесь: http://www.rtads.org/man/TADSEX.HTM, глава "Создание собственных глаголов"). doAction определяет название методов-обработчиков для команд в формате "глагол-существительное". Когда игрок вводит такую команду (в нашем случае, допустим, "взять череп"), интерпретатор проверяет наличие в объекте, соответствующем существительному, пары методов, которые соответствуют глаголу взять: - verDoTake (так называемый метод-верификатор) и doTake (метод-действие). (Во вводной части документации описание верификатора опущено в целях упрощения восприятия). Эти методы вызываются системой автоматически, и в качестве аргумента им передается объект-актер, выполняющий действие. Это нужно потому, что TADS позволяет игроку давать команды другим персонажам в игре, и сообщения при этом в общем случае должны быть разными. Проверка переданного методу актера позволит, например, для команды "Взять мяч" выдать сообщение "Ты взял мяч", а для "Бобик, возьми мяч" - "Бобик подхватил мяч зубами". Надеюсь, не запутал.

Неактивен

   #19
30.08.2018 22:55

Nikita
Модератор (+333, -117)
Зарегистрирован: 29.10.2016
Сообщений: 108

Re: Игра пример

Kephra написал:

Я не совсем понимаю как работает этот метод. Зачем вообще передавать что-то в него?

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

Код:

// Перемещаем объект book в/на объект table
book.moveInto(table);
// Убираем book из игрового мира в небытие, например, книгу сожгли
book.moveInto(nil);

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

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

Итак, аргумент moveInto - это объект, который в итоге станет новым значением location перемещаемого объекта, поэтому без него никуда. Ну или аргументом может быть nil, чтобы убрать объект из мира.

Kephra написал:

Как в «doTake» так и в «moveInto» можно передать любой локальный, нейтральный, пустой объект вида «asdasd», но если этого не сделать, интерпретатор при срабатывании такого метода, выдаст ошибку. Но дело в том, что совершенно неважно что я туда впишу.

Для начала, конструкция doTake(actor) означает не то, что вы в doTake передали actor, а то, что вы от движка, который отправил вам аргумент в doTake, приняли этот аргумент в виде переменной actor. Содержимое actor определяет движок, который и вызывает doTake, а вы лишь это содержимое принимаете под определённым названием.

Все методы действий, типа doTake или doOpen, в качестве аргумента принимают объект персонажа (актёра), который выполняет это действие. Отдельные методы могут принимать и дополнительный аргумент, но персонаж будет всегда. Например, игре нужно проверить, можно ли взять горячий уголёк, а для этого надо обратиться к объекту персонажа, совершающего действие, и проверить, надет ли на него объект рукавиц. Дело в том, что действия над объектами может совершать не только персонаж главного героя, но и другие персонажи игры, а также в TADS возможно реализовать переключение игры между несколькими главными героями, например, первую половину поиграли за Красную шапочку, а вторую за Серого волка. Именно поэтому надо иметь возможность чётко знать, какой именно персонаж выполняет действие, а не просто сразу тянуться к объекту Me, являющемся главным героем по умолчанию.

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

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

По умолчанию объектом главного героя, за которого мы играем, является объект Me, поэтому именно его надо модифицировать для изменения описаний и всего такого. Но поскольку главный герой в процессе игры может меняться, то для кода, который теоретически может работать в таких играх, например, это какая-то универсальная библиотека, к объекту главного героя надо обращаться через функцию parserGetMe(), возвращающую активного ГГ, например, местоположение ГГ как parserGetMe().location. Ну это так, чтобы вы не удивлялись, если это увидите в стандартной библиотеке. В своей личной игре, где точно ГГ всегда один, можно работать напрямую с Me.

Kephra написал:

поясняется следующее: «Определение атрибута doTake использует в качестве аргумента персонаж (actor), который пытается взять объект.» и «Система вызывает doTake каждый раз, когда игрок пытается взять объект.»

Первое означает, что вам в метод (атрибут) doTake прилетит в качестве аргумента объект персонажа, который берёт объект. В частности, в атрибут doTake внутри объекта черепа под именем actor прилетит объект Me, который является объектом главного героя по умолчанию.

Второе означает, что когда какой-то предмет кем-то берётся, в объекте этого предмета вызывается метод doTake. В частности, когда вы в игре пишите "взять череп", то происходит вызов doTake в объекте черепа.

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

Неактивен

   #20
31.08.2018 13:10

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Re: Игра пример

Nikita написал:

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

То есть, если Красная Шапочка возьмёт череп с пьедестала, до этого не поместив на него камень, а в методе doTake Серый Волк, то погибнет он вместо Шапочки?

Я только что в doTake для проверки вписал пьедестал. Скомпилировал. Пошел в пещеру, взял череп и не умер — все стрелы были выпущены в пьедестал smile. Поменял на «me» и умер как полагается.

Неактивен

   #21
31.08.2018 16:22

Nikita
Модератор (+333, -117)
Зарегистрирован: 29.10.2016
Сообщений: 108

Re: Игра пример

Kephra написал:

То есть, если Красная Шапочка возьмёт череп с пьедестала, до этого не поместив на него камень, а в методе doTake Серый Волк, то погибнет он вместо Шапочки?

В случае обсуждаемого кода, нет, потому что там поражение через die() не привязано к персонажу, совершающему действие Take (код die() можно посмотреть в библиотеке stdr.t). Но вот если бы мы в методе doTake делали бы нанесение ущерба персонажу с вычитанием здоровья и запрограммировали бы там жёстко Me, то в случае того, когда иной персонаж брал бы череп, ущерб всё равно наносился Me. Именно для этого в doTake, как и в любой другой метод обработки действия, всегда движок передаёт объект персонажа, чтобы можно было работать именно с ним.

Ну и ещё раз обращаю внимание, что аргумент doTake вы можете назвать не actor, а хоть abcde. Это ничего не изменит, так как это всего лишь имя локальной переменной, в которой входные данные метода будут доступны внутри его тела. Меняя имя этой переменной вы никак не влияете на то, что туда передаёт движок, а передаёт он там всегда объект персонажа. Можете в этом убедиться, добавив в метод действия вот такую строку:

Код:

    "Действие осуществляется <<actor.tdesc>>. ";

Можете менять actor в объявлении метода и в этой строке на что угодно, но данные вы не поменяете. Это, кстати, ещё один случай, для чего в любой метод действия передаётся объект персонажа. Как минимум, вы можете правильным образом на основе параметров персонажа просклонять игровое сообщение, например, дать правильное окончание рода: "Ты взял/взяла/взяло". Для этого в advr.t существует специальная функция iao(), генерирующая окончание по параметрам объекта персонажа. Соответственно Красной шапочке вы бы по объекту персонажа генерировали в игровых сообщениях окончания женского рода, а Серому волку - мужского, и не надо было бы мучатся с гендеронезависимыми формулировками всего текста.

Kephra написал:

Я только что в doTake для проверки вписал пьедестал. Скомпилировал. Пошел в пещеру, взял череп и не умер — все стрелы были выпущены в пьедестал smile. Поменял на «me» и умер как полагается.

Вместо упражнений в остроумии лучше чётче сформулируйте, что именно вам непонятно, если хотите разобраться, а не просто побалагурить на форуме.

Неактивен

   #22
31.08.2018 20:47

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Re: Игра пример

Nikita написал:

Ну и ещё раз обращаю внимание, что аргумент doTake вы можете назвать не actor, а хоть abcde. Это ничего не изменит, так как это всего лишь имя локальной переменной, в которой входные данные метода будут доступны внутри его тела. Меняя имя этой переменной вы никак не влияете на то, что туда передаёт движок, а передаёт он там всегда объект персонажа. Можете в этом убедиться, добавив в метод действия вот такую строку

Локальная переменная? Не указатель на объект?


Nikita написал:

Вместо упражнений в остроумии лучше чётче сформулируйте, что именно вам непонятно, если хотите разобраться, а не просто побалагурить на форуме.

Побалагруить!? Да я вчера весь день занимался тем, что этот череп с пьедестала туда-сюда таскал.
Вчера, я вписал pedestal в аргумент doTake, ожидая, что стрелы прилетят в него, — в случае, если не подложить камень... Так и произошло! Я взял преспокойно золотой череп, продал его, а на вырученные деньги улетел на Мальдивы smile! А потом проснулся и понял: стрелы не улетали ни в какой пьедестал. Потому что аргумент я назвал так же pedestal и все проверки в теле метода, — лежит ли камень и череп на пьедестале, — производились уже с локальной переменной pedestal, а не с оригинальным объектом pedestal. Непонятно только почему в этом случае череп можно взять с пьедестала безнаказанно, если локальная переменная pedestal имеет состояние объекта pedestal на момент, когда на пьедестале лежит только череп — то есть игрок все равно должен погибнуть, но это не происходит. Всё, надо выходить из этой пещеры, а то совсем кукухой поеду...


Код:

doTake(pedestal) =
   {
      if (smallRock.location != pedestal && self.location = pedestal)
      {
          die();
      }
      pass doTake;
   }
;

Отредактировано Kephra (02.09.2018 20:11)

Неактивен

   #23
01.09.2018 01:13

Nikita
Модератор (+333, -117)
Зарегистрирован: 29.10.2016
Сообщений: 108

Re: Игра пример

Kephra написал:

Локальная переменная? Не указатель на объект?

Аргументы функций и методов де-факто работают как локальные переменные. Ссылки-указатели в TADS 2 бывают только на функцию и свойство объекта. Если вы используете уже известный глобальный идентификатор в качестве имени локальной переменной/аргумента, то внутри блока (и вложенных в него блоков) по этому идентификатору обращение будет происходить именно к локальной сущности, но вообще это считается антипаттерном. Вопросы областей видимости и локализации аргументов освещены в главе 5.

Неактивен

   #24
02.09.2018 19:24

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Re: Игра пример

Оказывается, метод отлично себе работает без аргументов, надо только после названия не ставить скобки. Я думал они обязательны, как в Си:

Правильно

doTake =
   {
      ...
      ...
   }
;

Не правильно

doTake () =
   {
      ...
      ...
   }
;

С пустыми скобками игра не компилировалась, наверное потому что в doTake первым аргументом должен быть какой-то персонаж из игры. Но, можно и не передавать, вышеприведенным способом.

UPD

Ага, игра-то компилируется, но уже в самой игре — если взять череп, интерпритатор выдаст ошибку. Всё же, передать в атрибут actor в advr.t надо обязательно что-то.

Отредактировано Kephra (02.09.2018 21:10)

Неактивен

   #25
02.09.2018 20:25

Kephra
Участник (+1, -1)
Откуда: Украина
Зарегистрирован: 04.04.2011
Сообщений: 46

Re: Игра пример

Мне понятно, что первый аргумент в doTake это actor (смотрел код doTake в advr.t), но разве мы вот таким способом передаём???

doTake (Красная шапочка) ={
    ...
    ...
}


Это же только объявление функции/метода?

А вот так уже передаётся:

doTake (Красная шапочка, колобок, серый волк);

UPD
Или это особенность языка ТАДС? Из-за того что этот метод есть в advr.t, он работает не стандартно?

Отредактировано Kephra (02.09.2018 21:01)

Неактивен

Powered by PunBB
© copyright 2001–2018 iFiction.Ru