В этой части мы рассмотрим исключительно назначение модуля Main и всех его объектов. В конце сделаем небольшую шпаргалку для быстрого запоминания и поиска необходимых классов и их свойств. Минимум вырезок из модуля и максимум понимания и структуризации.
Классы
В библиотеке Main.tml есть всего 5 классов (класс состояние я не беру в расчёт, т.к. он так и не был описан):
нечто_видимое
Основной класс. В нём описаны всего 2 свойства: полное_описание и уже_осмотрено. Служат они для вывода полного описания объекта только при первом осмотре. Нам надо задавать только полное_описание. уже_осмотрено в большинстве случаев трогать не стоит.
От класса нечто_видимое так или иначе наследуются все другие классы в модулях Main.tml и Containers.tml. Так-что у всех объектов, унаследованных от классов стандартной библиотеки, будет свойство полное_описание. Если его не задать, то при первом осмотре полное описание выводиться не будет, а будет выведено обычное описание.
место, предмет, персонаж
Сначала рассмотрим пересекающиеся свойства и методы этих трёх классов, а потом разберём уникальные свойства для каждого класса по отдельности.
title/наименование - специальное свойство. Есть не только у этих классов, но и у всех объектов вообще. Для предмета и места свойство title по умолчанию задано, как программное имя красным шрифтом. Для персонажа оно задано более гибко и меняется в зависимости от ситуации.
Таким образом, если наш объект унаследован от класса предмет или место, то мы переопределяем у него свойство title, а если от класса персонаж, то не трогаем. Как менять наименование персонажей мы увидим при рассмотрении свойства по_имени.
описание - это обычное описание. Отображается, если полное_описание уже выводилось или не задано. Обычное описание должно быть короче, чем полное. В классах уже задано стандартное значение этого свойства, но его желательно переопределять для каждого объекта. Примеры стандартных описаний:
"это некоторое место - пещера"
"это обычная ложка"
"гоблин выглядит как обычно"
Согласитесь, что такие описания навряд-ли понравятся игроку.
st_описание - выводит описание и дополнительные приписки, свои для каждого класса:
Для места - это список предметов и персонажей, присутствующих в локации и вывод меню (если задано):
Это некоторое место - пещера. На земле лежит кусок проволоки. С потолка бьёт луч света. В углу стоит старый гоблин.
1. Север - расщелина в стене
2. Юг - маленькое отверстие над камнем
Для предмета - состояние предмета, заданное функцией fn_состояние(). Эта функция позволяет задавать состояние предмета в скобочках. Вот пример:
include "Main.tml" уникальное крышка_закрыта { this.состояние = "крышка закрыта" } уникальное горит { this.состояние = "горит" } уникальное лампа { cls = предмет title = "ламп%; НдСиЖр; Ип; ИпЕч=а; РпЕч=ы; ДпЕч=е; ВпЕч=у; ТпЕч=ой; ПпЕч=е; ИпМч=ы; РпМч=; ДпМч=ам; ВпМч=ы; ТпМч=ами; ПпМч=ах" this + крышка_закрыта this + горит }
При осмотре лампы мы видим:
> осм лампу
Это обычная лампа (крышка закрыта и горит)
На самом деле весь остальной функционал состояний описан в других модулях, поэтому отложим пока эту функцию до следующих частей.
Для персонажа - вывод предметов, находящихся снаружи персонажа:
Гоблин выглядит как обычно. В руке он держит заколдованный тесак.
В общем st_описание отображает более развёрнутое описание, собирая его из различных описаний других объектов. Стандартное значение довольно хорошо справляется с этой задачей, поэтому переопределять его в унаследованных объектах не требуется.
предлог, пред_в, пред_из - предлоги, необходимые при генерации текстов. предлог используется для описания текущего состояния: "находится в комнате", "лежит в коробке", "есть у гоблина". пред_в - для помещения чего-либо в объект: "вошёл в комнату", "положил в коробку", "дал гоблину". пред_из - при изъятия чего-либо из объекта: "вышел из комнаты", "взял из коробки", "взял у гоблина".
Свойства заданы для места и персонажа. В классе предмет отсутствуют.
В месте заданы такие значения по умолчанию:
предлог = "в" //находится в комнате
пред_в = "в" //вошел в комнату
пред_из = "из" //вышел из комнаты
Необходимо переопределять, если ваша локация требует других предлогов. Например "поляна": "находится на поляне", "зашёл на поляну", "ушёл с поляны"
В персонаже заданы такие:
предлог= "у" //находится у персонажа
пред_в = "" //дал персонажу
пред_из = "у" //взял у персонажа
Тоже переопределяются по требованию. (примеров не придумал )
В предмете не заданы по умолчанию, т.к. предполагается, что в предмет нельзя класть объекты. В модуле Containers.tml содержатся такие классы как контейнер и поверхность, унаследованные от класса предмет, которые обрабатывают вложенные объекты. В них и заданы эти предлоги.
для_чего, из_чего, чей - свойства для правильного парсинга и генерации текстов. Отсутствуют у класса персонаж, т.к. крайне редко используется ("человек для экспериментов", "три с половиной человека крови" (сосуд для вампиров), "раб барышни". Во всех этих случаях можно задать персонажа как предмет).
Употребление видно из комментариев:
для_чего = нет //склад для запчастей
из_чего = нет //склад запчастей
чей = нет //дом рудокопа
для_чего = нет //ложечка для сахара
из_чего = нет //моток веревки
чей = нет //кирка рудокопа
для_чего - свойство пока не поддерживается стандартной библиотекой. Не используем.
из_чего - можно задать как лексему (из_чего = "пес%; НдСи; Ип; ИпЕч=ок; РпЕч=ка; ДпЕч=ку; ВпЕч=ок; ТпЕч=ком; ПпЕч=ке"), так и объект (из_чего = песок)
чей - свойство, требующее указания самого объекта (чей = рудокоп). Указание лексемы (чей = "рудокоп%; ОдСи; Ип; Ип=; Рп=а; Дп=у; Вп=а; Тп=ом; Пп=е") приводит к ошибке "object x string!".
Теперь рассмотрим каждый класс по отдельности:
место
У места остались нетронутыми всего 2 свойства и 1 метод:
можно_войти - используется для фильтра в действии "вошел". Т.е. если задать можно_войти = нет, то нельзя будет попасть в локацию по команде "войди в пещеру", "иди к пещере" и пр.
По умолчанию равно да (true). Переопределяется при необходимости.
здесь - лексема для обработки команд "осмотрись здесь". Не меняем.
OnEnter() - предопределённый метод, срабатывающий при входе персонажа, управляемого игроком, в локацию.
По умолчанию выводит название локации жёлтым цветом и описание локации. Можно переопределить, если требуется задать дополнительные эффекты (музыка, звуки и др.).
предмет
показывать_в_инвентаре - строка, отображаемая при осмотре инвентаря персонажа.
Вполне нормально определена по умолчанию:
> инв
У рудокопа есть лампа, мешок и кирка.
но можно и переопределить (показывать_в_инвентаре = "старая кирка, которая с трудом влезла в карман"):
> инв
У рудокопа есть лампа, мешок и старая кирка, которая с трудом влезла в карман.
снаружи_персонажа - строка, которая описывает предмет из инвентаря при осмотре персонажа. Не определена по умолчанию, но при переопределении даёт интересные эффекты:
лампа.снаружи_персонажа = "в руке болтается лампа" кирка.снаружи_персонажа = "из кармана наполовину торчит старая кирка. Интересно, как {this.pos:лич_мест} её туда {засунул*this.pos}?"
> осмотри рудокопа
рудокоп выглядит как обычно, в руке болтается лампа и из кармана наполовину торчит старая кирка. Интересно, как он её туда засунул?
Если снаружи_персонажа не задано, то при осмотре персонажа предмет из инвентаря себя ни как не отображает.
Задаётся по вкусу.
предмет_по_месту - строка, которая выводится в описании локации при перечислении объектов в ней. Значение по умолчанию генерирует фразу общего вида:
Это некоторое место - склад. Здесь есть лампа, здесь есть мешок и здесь есть ящик.
поэтому в объектах я рекомендую переопределять это свойство на более внятное:
Это некоторое место - склад. На полу стоит лампа, в стороне лежит мешок и в углу стоит ящик из под инструментов.
Но здесь есть одна тонкость. Если предмет можно перемещать, то могут возникнуть казусы. Например, если рудокоп вынесет лампу из склада на лужайку и поставит её на землю, то описание:
Тихая лужайка, заросшая травой по пояс. На полу стоит лампа.
может сбить с толку или рассмешить игрока.
Поэтому, если предмет не перемещаем, то смело меняйте свойство предмет_по_месту на любое своё, а если предмет можно переместить, то тоже меняйте свойство, но будьте предельно аккуратны.
можно_взять - логическое свойство. Если "да", то персонажи смогут брать предмет и класть его где захотят. По умолчанию задано "нет".
Задаётся по надобности.
это и лич_мест - лексемы, учавствующие в обработке команд и генерации фраз. Заданы по умолчанию. Переопределять не требуется.
fn_состояние() - метод, генерирующий список состояний для добавления в скобочки при описании предмета (помните "Это обычная лампа (крышка закрыта и горит)"?). Переопределять не надо.
CalcKey(Key) - рассчитывает переменную часть морфологического ключа объекта. Достаточно хорошо справляется со своей задачей. Трогать не будем.
ChkClsName(Round,iRound,iForm,oRound,oForm) - метод для решения неоднозначностей по классовым именам объектов. Тоже универсален. Не изменяем.
можно_поместить(Предлог,Что) и можно_изъять(Предлог,Что) - два смежных метода для проверки помещения и извлечения из предмета других объектов. Объекты класса предмет по умолчанию не могут содержать в себе другие объекты. Для этого служат унаследованные от класса предмет классы контейнер, поверхность и др., которые описаны в модуле Containers.tml. В них и переопределяются более подробно эти методы. В классе предмет же они всегда запрещают действие и возвращают строку формата "Рудокоп не может положить лампу в мешок.".
Если вы хотите, чтобы в ваши предметы можно было помещать другие объекты, то проще унаследовать их от других классов контейнер или поверхность (которые мы изучим при рассмотрении модуля Containers.tml), чем самим обрабатывать эти функции.
В общем эти методы мы не трогаем.
персонаж
персонаж_по_месту - аналогично предмет_по_месту. Выводится при описании локации, в которой находится персонаж. Переопределяем.
по_имени - замена свойства title. У объектов класса персонаж нельзя трогать title, чтобы не порушить систему местоимений. Вместо этого мы определяем свойство по_имени. Всегда задаём.
Род - ключ, обозначающий род персонажа. По умолчанию мужской ("Мр"). Не забывайте переопределять его у своих персонажей!
обращение_к - ключ, определяющий, как к персонажу будут обращаться. Может принимать три значения: "Ты", "Вы" или "Мы":
"Ты взял ключ"
"Вы взяли ключ"
"Мы взяли ключ" - очень редкий вариант ("Мы, Николай II")
По умолчанию задано "Ты". При необходимости меняем.
лич_мест, возвр_мест, прит_мест, прит_возвр_мест - лексемы, описывающие словоизменение местоимений. Не меняем.
притяжательное - сложная лексема, связывающая вместе другие лексемы местоимений. Не трогаем.
прит_прил - притяжательное прилагательное. По умолчанию не задано, т.к. должно определяться в наследниках. Например, для мамы прит_прил будет равно "мамин%; Пи; ИпНд; ИпЕчМр=; РпЕчМр=ого; ДпЕчМр=ому; ВпЕчОдМр=ого; ВпЕчНдМр=; ТпЕчМр=ым; ПпЕчМр=ом; ИпЕчЖр=а; РпЕчЖр=ой; ДпЕчЖр=ой; ВпЕчЖр=у; ТпЕчЖр=ой; ПпЕчЖр=ой; ИпЕчСр=о; РпЕчСр=ого; ДпЕчСр=ому; ВпЕчСр=о; ТпЕчСр=ым; ПпЕчСр=ом; ИпМч=ы; РпМч=ых; ДпМч=ым; ВпМчОд=ых; ВпМчНд=ы; ТпМч=ыми; ПпМч=ых".
Позволяет обращаться к объектам через притяжательное прилагательное. Например, если в комнате есть мама и папа, и у обоих в руках по коньфете, то что-бы взять коньфету у мамы можно написать "взять мамину коньфету".
Желательно задавать для всех персонажей, если возможно (для "рудокопа", например, это проблематично).
CalcKey(Key) и ChkClsName(Round,iRound,iForm,oRound,oForm) - аналогичны методам предмета. Не меняем.
ChkMoveObj(From,To) - проверка перемещения персонажа из From в To.
BefMoveObj(From,To) - перед перемещением персонажа из From в To.
AftMoveObj(From,To) - после удачного перемещения персонажа из From в To.
Переопределяются очень редко.
свобода_воли(Объект,Место,Прочее) - метод, позволяющий персонажам по своему реагировать на различные действия и команды.
Если вы не хотите, чтобы ваши NPS (несобственные персонажи) как марионетки выполняли все команды, которые им прикажут, то переопределите этот метод для них, например вот так:
свобода_воли(Объект) { switch(act) //выполняемые зеркалом действия case(осмотрел) return да case(осмотрелся) return да case(сказал) return да //действия, которые зеркало отказывается делать case(инвентарь) this > "да у меня даже полочки нет, какой инвентарь?" case(взял) this > "и чем же я по твоему должно взять {Объект*Вп}?" case() this > "мы, волшебные зеркала, такого не делаем!" return нет //отказ }
По умолчанию определено так, что все NPS выполняют всё, что им прикажут, а главный герой запрашивает у игрока: сделать ли то, что ему приказывают?
Скорей всего придётся переопределять для всех несобственных персонажей.
может_не_дать(Объект), не_дал(Объект), может_не_взять(Объект), не_взял(Объект) - методы для проверки в действии "взял" и "дал".
может_не_дать(Объект) - если метод вернёт строку, ГГ не будет пытаться брать Объект у this
не_дал(Объект) - если метод вернёт да, ГГ не сможет взять Объект у this
может_не_взять(Объект) - если метод вернёт строку, ГГ не будет пытаться давать Объект this
не_взял(Объект) - если метод вернёт да, ГГ не сможет дать Объект this
Рассмотрим примеры:
> зеркало, возьми лампу
и чем же я по твоему должно взять лампу?
Здесь сработал метод свобода_воли, т.к. мы приказываем зеркалу сделать что-то.
> дай зеркалу лампу
Здесь сначала вызывается метод может_не_взять(лампа) для зеркала, и если он возвращает строку, то ГГ не даёт лампу зеркалу. Если может_не_взять вернул пустое значение, то вызывается метод не_взял(лампа). И если он вернёт да, то ГГ опять-же не даёт лампу.
То-же самое с методами может_не_дать(Объект) и не_дал(Объект), реагирующих на команду "> возьми у зеркала деньги".
По умолчанию они соглашаются брать/давать объекты.
Если честно, то не вижу смысла в дублировании этих методов.
Итак, свобода_воли обрабатывает слова (когда мы словами просим зеркало что-либо сделать), а 4 остальных метода обрабатывают действия (когда мы пытаемся что-либо отобрать или всучить зеркалу).
декорация
Малюсенькая надстройка над классом предмет, переопределяющая 2 свойства:
описание - выводит более подходящее для декорации описание ("Лучь света - это просто декорация. Он здесь находится лишь для красоты."), но всё-равно требует переопределения.
предмет_по_месту - по умолчанию пустая строка, что предполагает описывать декорации в описании самой локации, где они находятся.
Не переопределяется.
Вот мы и описали все свойства и методы. Теперь соберём их в кучку и сделаем шпаргалку, что-бы быстрее освоиться с классами модуля Main.tml:
Ментальные
В модуле описаны 5 слов в объектах mental: выглядит, видит, держит, находится, обычный.
Их мы можем использовать в построении предложений не описывая заново. Например:
"В пещере {находится*this} {обычный*this} {this} и {держит*this} в руках свечу."
Предлоги
Так-же описаны предлоги в, из, к, о, под, с. Они используются автоматически.
Функции
очистить_лексему(Obj) - функция для очистки лексем, возвращаемых парсером
check_keys(keyA, keyB, keys) - вспомогательная функция для сравнения ключей
проверка_прил(Прил,Сущ,ЧегоЧье) - функция для проверки согласованности прилагательных
здесь_или_у_тебя(Flag) - возвращает "здесь", если Flag=нет и "у <местоимение>", если Flag=да.
Действия и фразы
Ещё модуль обрабатывает следующие действия:
осмотрелся
осмотрел
инвентарь
вошел
взял
положил
дал
сказал
и фразу команда
Отредактировано Alexandr (2010-09-04 20:00:12)