1.2.0 additions.

I haven't finished yet!
This commit is contained in:
Alexander Yakovlev 2010-07-27 08:25:15 +00:00
parent 080f4a515e
commit 09b3396edf

View file

@ -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()./
Переход в диалог осуществляется как переход на сцену: