В примере из демонстрационной игры (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)
Неактивен
У меня вопрос по поводу игры-примера для информа, (http://rinform.stormway.ru/tutor/01-Heidi.html)
Object branch "надежн/ый толст/ый сук/" top_of_tree
Наверное такая логика у парсера, что если сказать "положить гнездо на суку/суки/сука" и т.д. парсер это схавает и положит гнездо, но только на сук
>положить гнездо на суки
Ты кладёшь птичье гнездо на надежный толстый сук.
даже если поменять в коде "сук/" на "сук" что, по теории должно отменить варианты окончания слова, но и это не помогает... Да, это всё пустяки, не стоит наверное обращать внимания, хоть и понимаю, что не каждому второму придет в голову извращаться так с объектом, но все же, если есть метод, хорошо бы его знать, и по случаю применить.
Неактивен
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;
Неактивен
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)
Неактивен
uux написал:
Kephra, еще раз призываю выслать мне код на мыло. Я честным образом скачал ту самую демо-игру из раздела игр сайта RTADS: http://rtads.org/man/GOLDSKLR.zip - оно пашет именно так, как надо, т. е. если положить камень на пьедестал, а потом убрать и взять золотой череп, ловушка срабатывает.
У меня нет вашего мыла... я васлал иходник в ЛС, но, вы меня не так поняли, я опишу последовательность действий: берем камень, ложим на пьедестал, забираем череп, ловушка не срабатывает, обратите внимание - берем камень с пьедестала и ловушка не срабатывает, хотя на пьедестале ничего не лежит, камень и череп у нас в руках.
>Пещера
взять камень
Взят.
>Пещера
положить на пьедестал
(мелкий камень)
Готово.
>Пещера
взять череп
Взят.
>Пещера
взять камень
Взят.
>Пещера
инв
У тебя имеется:
золотой череп
мелкий камень
>Пещера
Отредактировано Kephra (10.04.2011 19:39)
Неактивен
uux написал:
И, раз уж я опять вернулся к этой теме, хочу обратить внимание еще вот на что. В RTADS имеется замечательный генератор падежных форм (файл generator.t в архиве с библиотеками), который позволяет в разы сократить рутинную работу по набиванию лексических свойств для объектов в игре. К сожалению, роль генератора пока не отражена должным образом в документации, но работа с ним достаточно подробно описана в комментариях в самом файле. И, конечно, если возникнут трудности с пониманием, Вам с удовольствием помогут;).
Спасибо, интересно, я поработаю с ним, если возникнут вопросы, обязательно задам:).
Неактивен
Kephra написал:
...
Ну, мыло я оставлял на форуме RTADS, но по ЛС тоже вс получил;).
Да, то, что Вы описываете - так оно действительно и должно работать;). Я так подозреваю, что преувеличенный примитивизЬм примера - часть оригинальной задумки. Чтобы ловушка срабатывала и при снятии камня с пьедестала, надо доработать метод doTake камня... задание для самостоятельной работы;), помощь в которой, если она понадобится, Вам конечно же окажут;).
Неактивен
yandexx написал:
Слеши в имени объекта используются только при выводе названия.
При вводе же рассматриваются ключевые слова указанные в перечислении name, с различными окончаниями. В обоих случаях учитывается род объекта (male, female, neuter, plural).
При вводе просматриваются грамматики для глаголов, заданные в библиотеке или вручную, и падеж учитывается. Однако там где он не столь важен, сработает существительное и в любом падеже.
Ага спасибо, для меня новичка, это пока сложно для понимания... но что-то, да и дошло (если верно), значит, прописать правильное падежное склонение для отдельного слова-существительного, можно, но только в соответствующей библиотеке? А если возможно, то как? Можете привести пример, именно для нашего "сука"...
Неактивен
uux написал:
надо доработать метод doTake камня... задание для самостоятельной работы;), помощь в которой, если она понадобится, Вам конечно же окажут;).
Я об этом подумал сразу же как увидел "баг", но, если в комнате лежит еще несколько камней, и других объектов, в сумме может набраться до 10/20 объектов в игре немного большей игры-примера, не прописывать же в самом деле для каждого, один и тот же метод? Куда логичнее прописать метод для пьедестала, и тогда можно оставлять на нём любой объект и ловушка не сработает, но и в этом случае имеется "баг", если заменить череп спичечным коробком, пёрышком, или дохлой блошкой и тогда, ловушка так же не сработает... Или в ТАДС можно задать объекту, свойство веса?
upd
Я кажется понял, можно для пьедестала прописать метод, в котором перечислить по своему усмотрению, те объекты, которыми можно заменить череп... но как это сделать? Ладно, я попытаюсь сам дойти.
Отредактировано Kephra (10.04.2011 21:21)
Неактивен
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 -- винительный. И поэтому введённые команды "намазать доску клеем" и "намазать клеем доску" будут восприняты правильно. Порядок существительных здесь важен -- что к чему применяется. Без указанных падежей это бы не сработало.
Неактивен
Kephra написал:
uux написал:
надо доработать метод doTake камня... задание для самостоятельной работы;), помощь в которой, если она понадобится, Вам конечно же окажут;).
Я об этом подумал сразу же как увидел "баг", но, если в комнате лежит еще несколько камней, и других объектов, в сумме может набраться до 10/20 объектов в игре немного большей игры-примера, не прописывать же в самом деле для каждого, один и тот же метод? Куда логичнее прописать метод для пьедестала, и тогда можно оставлять на нём любой объект и ловушка не сработает, но и в этом случае имеется "баг", если заменить череп спичечным коробком, пёрышком, или дохлой блошкой и тогда, ловушка так же не сработает... Или в ТАДС можно задать объекту, свойство веса?
Да, свойство веса задать можно. (Собственно, оно уже определено в стандартной библиотеке - называется weight). Кроме того, можно определить метод один раз для одного объекта, а потом делать остальные его наследниками.
Kephra написал:
upd
Я кажется понял, можно для пьедестала прописать метод, в котором перечислить по своему усмотрению, те объекты, которыми можно заменить череп... но как это сделать? Ладно, я попытаюсь сам дойти.
Немножко не так. Потому что если игрок вводит команду, в которой пьедестал не задействован (типа "взять камень"), то по умолчанию никаких методов пьедестала вызываться не будет (т. е. потребуется модифицировать метод doTake, вставив туда этот вызов принудительно).
Я бы действовал так: определил бы свойство для пьедестала, соответствующее общему весу находящихся на нем объектов (пусть называется WeightOnMe), а также свойство, соответствующее минимальному весу оставшихся предметов, при котором ловушка еще не срабатывает (MinWeight); при укладке предмета на пьедестал прибавлял бы его вес к свойству WeightOnMe, а при снятии с пьедестала - проверял, не становится ли вес меньше минимально допустимого, и в этом случае запускал бы ловушку. Пример (недоделанный) - под спойлером.
спойлер…
Неактивен
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)
Неактивен
Kephra написал:
Одно не понятно что это за стрелочки больше-меньше? Они эквивалентны оператору «!=» в Си?
Да, <> - это неравно. В принципе, != TADS тоже понимает, так что можно использовать и этот оператор.
Синтаксис языка описан в главе 5.
Вообще в "Золотом черепе" этот пазл реализован не лучшим образом. Во-первых, смещение черепа лучше регистрировать через метод moveInto в его объекте (это любое изменение location, а не только взятие предмета в руки), а во-вторых, там проблемы с физикой процесса, так как потом булыжник можно забрать и ничего не произойдёт. Но это всё пока вам не важно.
Неактивен
Nikita написал:
Вообще в "Золотом черепе" этот пазл реализован не лучшим образом. Во-первых, смещение черепа лучше регистрировать через метод moveInto в его объекте (это любое изменение location, а не только взятие предмета в руки)...
Я сделал так:
moveInto(self) = { if (smallRock.location = pedestal) { pass doTake; } else { "Едва ты успеваешь поднять череп, как из стен вылетает целая туча отравленных стрел! Ты пытаешься увернуться от них, но их слишком много!"; die(); } }
И теперь без «self.location <> pedestal» если взять череп с пола при отсутствии камня на пьедестале, die() не срабатывает. Так код выглядит намного лучше: смотрю и радуюсь .
UPD
Что такое метод русским языком? Технически, это функция?
UPD
Да согласно мануалу: метод эта функция, только он является частью объекта и самостоятельно (вне объекта) не используется, в отличии от функции.
Отредактировано Kephra (30.08.2018 12:44)
Неактивен
Kephra написал:
Я сделал так:
Нет, это не совсем верно:
Во-первых, self - это ключевое слово, которым обозначается сам объект для того, чтобы обратиться к нему из самого себя. Здесь же аргументом для метода moveInto может быть любой объект, куда мы перемещаем череп, поэтому там нужно использовать некую нейтральную локальную переменную, например, obj.
Во-вторых, команда pass передаёт обработку указанному методу объекта родителя. То есть мы в текущем объекте модифицировали какой-то метод, а потом хотим, чтобы в остальном он отработал по стандартной схеме, и для этого как раз и вызываем его по pass. Однако вы модифицируете метод moveInto, то есть перемещение объекта, но дальше передаёте обработку в doTake, то есть метод взятия, тогда как перемещаться череп может не только из-за взятия его в руки, а например, из-за перекладывания на пол. Как раз командой "положить череп на пол" исходная реализация пазла и ломается. В общем если модифицируем moveInto, то и дальше по pass передаём обработку тоже в moveInto.
В итоге, должно быть так:
moveInto(obj) = { // В момент передвижения череп на пьедестале, но камня на нём нет if(self.location = pedestal && smallRock.location != pedestal) { "Бла-бла-бла. "; die(); } // moveInto работает дальше как обычно pass moveInto; }
Однако если положить камень на пьедестал, взять череп, а потом взять и камень, то стрелы не полетят, потому что в объекте камня мы ничего не проверяем и не обрабатываем. Именно поэтому правильной реализацией было бы создание функции-демона, то есть отрабатывающей после каждого хода, которая бы проверяла, есть ли в принципе что-нибудь на пьедестале. Если нет, или оно недостаточного веса (для объектов можно задавать вес и размер), то уводить игру на поражение, а если есть, то ничего не делать. Этим мы бы охватили сразу все случаи. Просто демоны и запалы - это уже несколько более сложная тема, поэтому в этом базовом примере из документации использовать их было рано, но с точки зрения корректного моделирования мира надо делать именно так.
Неактивен
Nikita написал:
Нет, это не совсем верно:
Да, это СОВСЕМ не верно. Даже не знаю, как я вчера смог взять череп с пьедестала (было 4 часа бессонного утра), когда уже сегодня на этом моменте игра бесконечно зациклилась — видимо на pass doTake — и сообщения «Взят (череп)» посыпались на экран, пока интерпретатор не понял, что происходит, и не выдал сообщение об ошибке.
Отредактировано Kephra (30.08.2018 17:27)
Неактивен
Nikita написал:
Во-первых, self - это ключевое слово, которым обозначается сам объект для того, чтобы обратиться к нему из самого себя. Здесь же аргументом для метода moveInto может быть любой объект, куда мы перемещаем череп, поэтому там нужно использовать некую нейтральную локальную переменную, например, obj.
Я не совсем понимаю как работает этот метод. Зачем вообще передавать что-то в него? Это же функция? Как в «doTake» так и в «moveInto» можно передать любой локальный, нейтральный, пустой объект вида «asdasd», но если этого не сделать, интерпретатор при срабатывании такого метода, выдаст ошибку. Но дело в том, что совершенно неважно что я туда впишу. Однако в мануале-то «actor» используют в качестве аргумента «doTake», зачем это делать, — не понятно, но поясняется следующее: «Определение атрибута doTake использует в качестве аргумента персонаж (actor), который пытается взять объект.» и «Система вызывает doTake каждый раз, когда игрок пытается взять объект.» Эти оба пояснения в документации следуют друг за другом. Каждое, говорит совершенно о разных вещах, но воспринимается как — об одном. Думается, будто надо использовать исключительно тот аргумент с которым будет взаимодействовать объект (в нашел случае золотой череп с актером). Иначе, ничего не будет работать. Но это не так, поэтому пояснение: «Определение атрибута doTake использует в качестве аргумента персонаж (actor), который пытается взять объект.» — даёт ложное представление, причем не объясняется зачем это делать.
Отредактировано Kephra (30.08.2018 21:41)
Неактивен
Kephra написал:
Однако в мануале-то «actor» используют в качестве аргумента «doTake», зачем это делать, — не понятно, но поясняется следующее: «Определение атрибута doTake использует в качестве аргумента персонаж (actor), который пытается взять объект.» и «Система вызывает doTake каждый раз, когда игрок пытается взять объект.» Эти оба пояснения в документации следуют друг за другом. Каждое, говорит совершенно о разных вещах, но воспринимается как — об одном. Думается, будто надо использовать исключительно тот аргумент с которым будет взаимодействовать объект (в нашел случае золотой череп с актером). Иначе, ничего не будет работать. Но это не так, поэтому пояснение: «Определение атрибута doTake использует в качестве аргумента персонаж (actor), который пытается взять объект.» — даёт ложное представление, причем не объясняется зачем это делать.
doTake - это не функция, а метод, причем вызываемый автоматически. В TADS для глаголов определяется набор методов-обработчиков, название которых определяется свойствами doAction и/или ioAction объекта-глагола (подробнее см. здесь: http://www.rtads.org/man/TADSEX.HTM, глава "Создание собственных глаголов"). doAction определяет название методов-обработчиков для команд в формате "глагол-существительное". Когда игрок вводит такую команду (в нашем случае, допустим, "взять череп"), интерпретатор проверяет наличие в объекте, соответствующем существительному, пары методов, которые соответствуют глаголу взять: - verDoTake (так называемый метод-верификатор) и doTake (метод-действие). (Во вводной части документации описание верификатора опущено в целях упрощения восприятия). Эти методы вызываются системой автоматически, и в качестве аргумента им передается объект-актер, выполняющий действие. Это нужно потому, что TADS позволяет игроку давать команды другим персонажам в игре, и сообщения при этом в общем случае должны быть разными. Проверка переданного методу актера позволит, например, для команды "Взять мяч" выдать сообщение "Ты взял мяч", а для "Бобик, возьми мяч" - "Бобик подхватил мяч зубами". Надеюсь, не запутал.
Неактивен
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, где объясняются принципы объектно-ориентированного программирования и их приложение к парсерной игре.
Неактивен
Nikita написал:
По-хорошему все внутренние проверки и прочие операции, завязанные на персонажа, выполняющего действие, надо выполнять именно в отношении объекта в переменной actor, чтобы в сложных случаях не получилось, что мы уже играем за Серого волка, а последствия действий по-прежнему происходят в отношении Красной шапочки.
То есть, если Красная Шапочка возьмёт череп с пьедестала, до этого не поместив на него камень, а в методе doTake Серый Волк, то погибнет он вместо Шапочки?
Я только что в doTake для проверки вписал пьедестал. Скомпилировал. Пошел в пещеру, взял череп и не умер — все стрелы были выпущены в пьедестал . Поменял на «me» и умер как полагается.
Неактивен
Kephra написал:
То есть, если Красная Шапочка возьмёт череп с пьедестала, до этого не поместив на него камень, а в методе doTake Серый Волк, то погибнет он вместо Шапочки?
В случае обсуждаемого кода, нет, потому что там поражение через die() не привязано к персонажу, совершающему действие Take (код die() можно посмотреть в библиотеке stdr.t). Но вот если бы мы в методе doTake делали бы нанесение ущерба персонажу с вычитанием здоровья и запрограммировали бы там жёстко Me, то в случае того, когда иной персонаж брал бы череп, ущерб всё равно наносился Me. Именно для этого в doTake, как и в любой другой метод обработки действия, всегда движок передаёт объект персонажа, чтобы можно было работать именно с ним.
Ну и ещё раз обращаю внимание, что аргумент doTake вы можете назвать не actor, а хоть abcde. Это ничего не изменит, так как это всего лишь имя локальной переменной, в которой входные данные метода будут доступны внутри его тела. Меняя имя этой переменной вы никак не влияете на то, что туда передаёт движок, а передаёт он там всегда объект персонажа. Можете в этом убедиться, добавив в метод действия вот такую строку:
"Действие осуществляется <<actor.tdesc>>. ";
Можете менять actor в объявлении метода и в этой строке на что угодно, но данные вы не поменяете. Это, кстати, ещё один случай, для чего в любой метод действия передаётся объект персонажа. Как минимум, вы можете правильным образом на основе параметров персонажа просклонять игровое сообщение, например, дать правильное окончание рода: "Ты взял/взяла/взяло". Для этого в advr.t существует специальная функция iao(), генерирующая окончание по параметрам объекта персонажа. Соответственно Красной шапочке вы бы по объекту персонажа генерировали в игровых сообщениях окончания женского рода, а Серому волку - мужского, и не надо было бы мучатся с гендеронезависимыми формулировками всего текста.
Kephra написал:
Я только что в doTake для проверки вписал пьедестал. Скомпилировал. Пошел в пещеру, взял череп и не умер — все стрелы были выпущены в пьедестал . Поменял на «me» и умер как полагается.
Вместо упражнений в остроумии лучше чётче сформулируйте, что именно вам непонятно, если хотите разобраться, а не просто побалагурить на форуме.
Неактивен
Nikita написал:
Ну и ещё раз обращаю внимание, что аргумент doTake вы можете назвать не actor, а хоть abcde. Это ничего не изменит, так как это всего лишь имя локальной переменной, в которой входные данные метода будут доступны внутри его тела. Меняя имя этой переменной вы никак не влияете на то, что туда передаёт движок, а передаёт он там всегда объект персонажа. Можете в этом убедиться, добавив в метод действия вот такую строку
Локальная переменная? Не указатель на объект?
Nikita написал:
Вместо упражнений в остроумии лучше чётче сформулируйте, что именно вам непонятно, если хотите разобраться, а не просто побалагурить на форуме.
Побалагруить!? Да я вчера весь день занимался тем, что этот череп с пьедестала туда-сюда таскал.
Вчера, я вписал pedestal в аргумент doTake, ожидая, что стрелы прилетят в него, — в случае, если не подложить камень... Так и произошло! Я взял преспокойно золотой череп, продал его, а на вырученные деньги улетел на Мальдивы ! А потом проснулся и понял: стрелы не улетали ни в какой пьедестал. Потому что аргумент я назвал так же pedestal и все проверки в теле метода, — лежит ли камень и череп на пьедестале, — производились уже с локальной переменной pedestal, а не с оригинальным объектом pedestal. Непонятно только почему в этом случае череп можно взять с пьедестала безнаказанно, если локальная переменная pedestal имеет состояние объекта pedestal на момент, когда на пьедестале лежит только череп — то есть игрок все равно должен погибнуть, но это не происходит. Всё, надо выходить из этой пещеры, а то совсем кукухой поеду...
doTake(pedestal) = { if (smallRock.location != pedestal && self.location = pedestal) { die(); } pass doTake; } ;
Отредактировано Kephra (02.09.2018 20:11)
Неактивен
Kephra написал:
Локальная переменная? Не указатель на объект?
Аргументы функций и методов де-факто работают как локальные переменные. Ссылки-указатели в TADS 2 бывают только на функцию и свойство объекта. Если вы используете уже известный глобальный идентификатор в качестве имени локальной переменной/аргумента, то внутри блока (и вложенных в него блоков) по этому идентификатору обращение будет происходить именно к локальной сущности, но вообще это считается антипаттерном. Вопросы областей видимости и локализации аргументов освещены в главе 5.
Неактивен
Оказывается, метод отлично себе работает без аргументов, надо только после названия не ставить скобки. Я думал они обязательны, как в Си:
Правильно
doTake =
{
...
...
}
;
Не правильно
doTake ()
=
{
...
...
}
;
С пустыми скобками игра не компилировалась, наверное потому что в doTake первым аргументом должен быть какой-то персонаж из игры. Но, можно и не передавать, вышеприведенным способом.
UPD
Ага, игра-то компилируется, но уже в самой игре — если взять череп, интерпритатор выдаст ошибку. Всё же, передать в атрибут actor в advr.t надо обязательно что-то.
Отредактировано Kephra (02.09.2018 21:10)
Неактивен
Мне понятно, что первый аргумент в doTake это actor (смотрел код doTake в advr.t), но разве мы вот таким способом передаём???doTake (Красная шапочка) ={
...
...
}
Это же только объявление функции/метода?
А вот так уже передаётся:doTake (Красная шапочка, колобок, серый волк);
UPD
Или это особенность языка ТАДС? Из-за того что этот метод есть в advr.t, он работает не стандартно?
Отредактировано Kephra (02.09.2018 21:01)
Неактивен