From 09b3396edff6e8d9ec5fa2a57456b1abee00a114 Mon Sep 17 00:00:00 2001 From: oreolek Date: Tue, 27 Jul 2010 08:25:15 +0000 Subject: [PATCH] 1.2.0 additions. I haven't finished yet! --- doc/manual.tex | 101 +++++++++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 41 deletions(-) diff --git a/doc/manual.tex b/doc/manual.tex index a0acdda..b8f46bd 100644 --- a/doc/manual.tex +++ b/doc/manual.tex @@ -11,7 +11,7 @@ \usepackage{makeidx} \makeindex \begin{document} -\title{Справочное пособие по INSTEAD (Относится к версиям 1.1.xx, Для версий 1.2.xx используйте официальную документацию)} +\title{Справочное пособие по INSTEAD} \author{Александр Яковлев\\oreolek@jabber.ru \and \textit{при участии Петра Косых}\\\textit{gl00my@jabber.ru}} \maketitle \tableofcontents @@ -153,7 +153,7 @@ table = obj { \index{Атрибуты!act} \verb/act/ --- это обработчик, который вызывается при действии пользователя на объект сцены. Если объект находится в инвентаре, то действие с ним будет передаваться другому обработчику --- \verb/inv/. -Настало время сделать небольшое отступление. До сих пор в примерах приводились примитивные обработчики, которые всего лишь возвращают определённую строку. В примере выше обращение к объекту вызовет банальную реакцию: интерпретатор напечатает строку <<Гм... Просто стол...>>. Хуже того: он будет отвечать тем же образом каждый раз при обращении к объекту. Это не совсем гибкий подход, поэтому STEAD позволяет определить любой атрибут объекта как функцию. Так, возможно построить такую конструкцию: +До сих пор в примерах приводились примитивные обработчики, которые всего лишь возвращают определённую строку. В примере выше обращение к объекту вызовет банальную реакцию: интерпретатор напечатает строку <<Гм... Просто стол...>>. Хуже того: он будет отвечать тем же образом каждый раз при обращении к объекту. Это не совсем гибкий подход, поэтому STEAD позволяет определить любой атрибут объекта как функцию. Так, возможно построить такую конструкцию: \begin{verbatim} apple = obj { @@ -166,8 +166,7 @@ apple = obj { end end, act = function(s) - if s._seen then - return 'Это яблоко!'; + if s._seen then return 'Это яблоко!'; else s._seen = true; return 'Я присматриваюсь и понимаю, что это --- яблоко.!'; @@ -176,32 +175,53 @@ apple = obj { }; \end{verbatim} -Иногда может понадобиться обработчик, который совершал бы некоторое действие, но не выводил никакого описания. Например: - -\begin{verbatim} -button = obj { - nam = "кнопка", - dsc = "На стене комнаты видна большая красная {кнопка}.", - act = function (s) - here().dsc = [[После того как я нажал на кнопку, комната преобразилась. Книжный шкаф куда-то исчез вместе со столом и комодом, а на его месте появился странного вида аппарат.]]; - return true; - end, -} -\end{verbatim} - -В данном случае обработчик \verb/act/ нужен для того, чтобы поменять описание комнаты, и не нужно, чтобы чтобы он выводил результат действия. Для отключения результата можно вернуть из обработчика значение \verb/true/ -- это будет означать, что действие успешно выполнено, но не требует дополнительного описания. - -Если необходимо показать, что действие невыполнимо, можно вернуть из обработчика \verb`act` значение \verb/false/ или \verb/nil/. При этом будет отображено описание по умолчанию из \verb`game.act`. - \index{Функции} -Если атрибут или обработчик оформлен как функция, то обычно первый аргумент функции \verb/(s)/ есть сам объект. В данном примере, при показе сцены будет в динамической части сцены будет текст: <<На столе что-то лежит>>. При взаимодействии с <<что-то>>, переменная \verb/_seen/ объекта \verb/apple/ будет установлена в \verb/true/, и мы увидим, что это было яблоко. +Если атрибут или обработчик оформлен как функция, то обычно первый аргумент функции \verb/(s)/ есть сам объект. В данном примере, при показе сцены будет в динамической части сцены будет текст: <<На столе что-то лежит>>. При взаимодействии со ссылкой <<что-то>>, переменная \verb/_seen/ объекта \verb/apple/ будет установлена в \verb/true/, и мы увидим, что это было яблоко. \index{Переменные} Запись \verb/s._seen/ означает, что переменная \verb/_seen/ размещена в объекте \verb/s/ (то есть, \verb/apple/). В языке Lua переменные необязательно объявлять заранее, при первом обращении к ней переменная \verb/apple._seen/ появится сама; но хорошим тоном будет заранее \textbf{проинициализировать} переменную со значением \verb/false/. Подчёркивание в имени переменной означает, что она \textbf{попадёт} в файл сохранения игры. Сохраняются все переменные, название которых начинается с большой буквы или с подчёркивания. Вы можете переопределить функцию \verb/isForSave(k)/, если вас это не устраивает. -\textbf{\textcolor{red}{Внимание!!!}} Переменные в любом случае не записываются в файл сохранения, если они не размещены в одном из перечисленных типов объектов: комната, объект, диалог, игра, игрок. +\textbf{\textcolor{red}{Внимание!!!}} Переменные в любом случае не записываются в файл сохранения, если они не размещены в одном из перечисленных типов объектов: комната, объект, диалог, игра, игрок, глобальное пространство. + +В файл сохранения могут быть записаны строки, числа, логические значения, ссылки на объекты и конструкции \verb/code/ (о них чуть ниже). + +Также вы можете определять переменные при помощи блоков \verb/var/ и \verb/global/, о которых будет рассказано позже. + +Рассмотрим другой пример: + +\begin{verbatim} +button = obj { + nam = "кнопка", + dsc = "На стене комнаты видна большая красная {кнопка}.", + act = code[[ p 'Я нажал на кнопку.' ]] +} +\end{verbatim} + +Здесь я использовал две новых конструкции: \verb/code/ и \verb/p/. Конструкция \verb/code [[ код ]]/ - это короткая форма записи для: + +\begin{verbatim} +act = function(self, ...) + код +end, +\end{verbatim} + +При этом внутри \verb/code/ определены переменные \verb/self/ -- текущий объект, \verb/arg1/, \verb/arg2/, ..., \verb/arg9/ -- параметры функции, и массив параметров \verb/args[]./ + +Также для сокращения записи нужна функция \verb/p/. Она возвращает параграф текста, заканчивая его пробелом. Всего определено три подобных функции: + +\begin{description} +\item[p] --- выводит переданный текст, заканчивая его пробелом +\item[pn] --- выводит переданный параграф, заканчивая его переводом строки +\item[pr] --- выводит переданное как есть +\end{description} + +Lua позволяет опускать скобки вокруг параметров, если параметр всего один. + +Если необходимо показать, что действие невыполнимо, можно вернуть из обработчика значение \verb/false/ или \verb/nil/. При этом будет отображено описание по умолчанию -- так, для обработчика \verb/act/ это будет \verb`game.act.` + +Обработчик должен что-то вернуть; если обработчик не возвращает ничего или возвращает \verb/false/ или \verb/nil/, то он не выполняется. \subsection{Облегчённые объекты} @@ -218,14 +238,14 @@ sside = room { return "Я подошёл к подъезду. Хм --- зайти внутрь?"; end end, - obj = {vobj(1, "подъезд", "У восточного угла находится небольшой {подъезд}.")}, + obj = {vobj("подъезд", "У восточного угла находится небольшой {подъезд}.")}, }; \end{verbatim} \index{Объекты!облегчённые!vobj} Как видим, \verb/vobj/ позволяет сделать лёгкую версию статического объекта, с которым тем не менее можно взаимодействовать (за счёт определения обработчика \verb/act/ в сцене и анализа ключа объекта). \verb/vobj/ также вызывает метод \verb/used/, при этом в качестве третьего параметра передаётся объект, воздействующий на виртуальный объект. -Синтаксис \verb/vobj/ таков: \verb/vobj(ключ, имя, описатель);,/ где ключ --- это цифра, которая будет передана обработчикам \verb.act/used. сцены как второй параметр. +Синтаксис \verb/vobj/ таков: \verb/vobj(имя, описатель)./ \index{Объекты!облегчённые!vway} Существует модификация объекта \verb/vobj/ под именем \verb/vway/. \verb/vway/ реализует ссылку. Синтаксис и пример: @@ -391,7 +411,13 @@ main = room { \index{Атрибуты!exit} \index{Атрибуты!enter} -При переходе между сценами движок вызывает обработчик \verb/exit/ из текущей сцены и \verb/enter/ той сцены, куда идёт игрок. \verb/exit/ и \verb/enter/ могут быть функциями --- тогда первый параметр это сам объект, а второй --- ссылка на комнату куда игрок хочет идти (для \verb/exit/) или из которой уходит (для \verb/enter/). Например: +\index{Атрибуты!left} +\index{Атрибуты!entered} +При переходе между сценами движок вызывает обработчик \verb/exit/ из текущей сцены и \verb/enter/ той сцены, куда идёт игрок. \verb/exit/ и \verb/enter/ могут быть функциями --- тогда первый параметр это сам объект, а второй --- ссылка на комнату куда игрок хочет идти (для \verb/exit/) или из которой уходит (для \verb/enter/). + +После перехода вызываются обработчики \verb/left/ прошлой сцены и \verb/entered/ сцены, куда перешёл игрок. + +Например: \begin{verbatim} room2 = room { @@ -414,27 +440,14 @@ room2 = room { \index{Атрибуты!tak} Как видим, обработчики могут возвращать два значения: строку и статус. В нашем примере функция \verb/exit/ вернёт \verb/false/, если игрок попытается уйти из зала в \verb/main/. \verb/false/ блокирует переход. Такая же логика работает и для \verb/enter/. Кроме того, она работает и для обработчика \verb/tak/ (о нём чуть позже). -\textbf{\textcolor{red}{Важное замечание:}} обработчик enter вызывается не при входе в комнату, а чуть раньше. Когда игрок хочет уйти в комнату, движок вызывает её обработчик enter, чтобы убедиться в том, что тот не возвращает false и переход возможен. Поэтому если вы используете \verb/here()/ в \verb/enter/, она будет указывать прежде всего --- на предыдущую комнату. Если вы передаёте enter параметр сцены, то он будет указывать всегда на текущую сцену. - \index{Функции!goto} Если требуется перейти на другую сцену автоматически, можно использовать функцию \verb/goto/ со ссылкой на сцену как параметром: \begin{verbatim} return goto('main'); +goto('main'); \end{verbatim} -Почему здесь написано \verb/return/? Дело в том, что функция \verb/goto()/ не является безусловным переходом, как можно подумать. Она возвращает описание новой сцены, поэтому почти всегда должна завершать работу обработчика таким нехитрым способом. - -\textbf{\textcolor{red}{НО: }}Если вы выполните goto из обработчика exit, то получите переполнение стека, так как goto снова и снова будет вызывать метод exit. Вы можете избавиться от этого, если вставите проверку, разрушающую рекурсию. Например: - -\begin{verbatim} -exit = function(s, t) - if t == 'dialog' then return; end - return goto('dialog'); -\end{verbatim} - -Обычно движок сам пытается разорвать рекурсию. Тем не менее, автор должен понимать, что он делает и не надеяться на автоматику. - \section{Специальные типы объектов} \subsection{Инвентарь} @@ -618,12 +631,18 @@ povardlg = dlg { \index{Функции!pon} \index{Функции!poff} \index{Функции!prem} +\index{Функции!pseen} +\index{Функции!punseen} \begin{description} \item[pon(n...)] включить фразы диалога с номерами n... (в нашем примере --- чтобы игрок мог повторно взять еду того-же вида). \item[poff(n...)] выключить фразы диалога с номерами n... -\item[prem(n...)] удалить (заблокировать) фразы диалога с номерами n... (удаление означает невозможность включения фраз. pon(n..) не приведёт к включению фраз). +\item[prem(n...)] удалить (заблокировать) фразы диалога с номерами n... Удаление означает невозможность включения фраз. \verb/pon(n..)/ не приведёт к включению фраз. +\item[pseen(n...)] вернет true, если все заданные фразы диалога видимы. +\item[punseen(n...)] вернет true, если все заданные фразы диалога невидимы. \end{description} +Если параметр \verb/n/ не указан, действие относится к текущей фразе. + Как ответ, так и реакция могут быть функциями. Вы можете закончить диалог, выполнив в реакции функцию \verb/back()./ Переход в диалог осуществляется как переход на сцену: