Как известно, разработчики игры "Герои Меча и Магии 5", встраивая скриптовый язык Lua в своё творение, по неясным никому причинам решили обойтись без библиотек стандартных функций и не включать их в игру. Зря только в мануале от создателей Lua предупреждают: "Если Вы не включили эту библиотеку в Ваше приложение, Вам необходимо тщательно проверить, действительно ли не требуются эти возможности."
К счастью, оказалось, что некоторые функции можно написать на самом Lua, что я и сделал. Да, по эффективности и функционалу им далеко до оригиналов, но, между тем, они предоставляют массу новых возможностей.
Формат, описывающий аргументы и возвращаемые значения функций в данном руководстве выглядит так:
возвращаемые_значения = функция (параметры, [необязательные_параметры])
********** БАЗОВЫЕ ФУНКЦИИ **********
value = assert (value, [message])
Возбуждает ошибку и выводит сообщение message (по умолчанию - "assertion failed!"), если value == nil, иначе возвращает value.
error ([message])
Возбуждает ошибку и выводит сообщение message (по умолчанию - "unknown error").
vartype = type (value)
Определяет тип переменной: "nil", "number", "string", "table", "function".
vartypetable = types (values)
Создает новую таблицу, являющуюся копией переданной таблицы, где все значения заменены на строки, описывающие тип переменных (см. type).
index, element = next (table, indexprev)
Получает следующий за indexprev индекс таблицы table и соответствующее ему значение. Если indexprev == nil, то возвращает первый индекс и значение.
results = pcall (func, [...])
Вызывает функцию func с параметрами ... в защищенном режиме и возвращает результат. То есть, в случае возникновения ошибки в вызываемой функции она дальше не передается, а сообщение об ошибке не выводится, и pcall возвращает nil. Если функция завершилась без ошибок, pcall вернет результаты из функции в таблице с полем n (см. table.pack).
parsed_function = loadstring (chunk, [env])
Аналогична parse: интерпретирует переданную строку chunk как тело Lua-функции и возвращает эту функцию. Но, в отличие от parse, loadstring возвращает функцию, которая может принимать параметры как функция с неопределённым количеством параметров, то есть через таблицу arg (arg[1] - первый аргумент, arg[2] - второй, ..., arg[arg.n] - последний). Вы также можете установить одну внешнюю локальную переменную с именем env (обращение как %env). Если env - таблица, то становится возможным изменять её поля (например, %env.n = %env.n + 1), саму переменную в любом случае изменить нельзя (%env = 1 возбудит ошибку).
selected = select (index, ...)
Если index - число, то функция возвращает элемент из списка переданных аргументов ..., стоящий в указанной позиции (отрицательные числа означают отсчет с конца списка). В противном случае index должен быть строкой "#", тогда функция вернет количество переданных параметров (за исключением index).
converted = tonumber (v)
Пытается конвертировать переданное значение в число. Это возможно только если значение уже является числом или строкой, конвертируемой в число по обычным правилам. Иначе возвращает nil.
converted = tostring (v)
Конвертирует значение в строку. nil, числа и строки передаются литерально, таблицы и функции заменяются на маркеры "[table]" и "[function]" соответственно.
hideerror (hide)
Запрещает или разрешает выводить ошибки скрипта в консоль. Если параметр hide == nil или не задан, то ошибки выводятся, в противном случае - нет.
_VERSION
Строка, описывающая текущую версию Lua. На данный момент значение = "Lua 4.0"
********** ОБРАБОТКА ТАБЛИЦ **********
package = table.pack (...)
Принимает любое количество значений и возвращает их упакованные в таблицу. Таблица имеет поле n - количество элементов.
... = table.unpack (table, [i, [j]])
Распаковывает таблицу table, возвращая множество значений. i и j устанавливают индекс первого и последнего элемента таблицы, однако функция не может вернуть больше 100 значений. По умолчанию i=1, j=длине массива.
length = table.getn (table)
Если таблица table имеет поле n, то возвращает значение этого поля. Иначе возвращает длину массива - индекс последнего не-nil элемента, входящего в последовательность.
Пример:
t={2,4,8,nil,32,nil}
print(table.getn(t)) --> 3
max = table.maxn (table)
Возвращает индекс с самым большим числовым значением. Если таблица имеет поля, где индекс не является числом или строкой, возникает ошибка. Пример:
-- t из предыдущего примера
print(table.maxn(t)) --> 5
table.insert (table, value, [pos])
Вставляет значение value в таблицу в позиции pos, сдвигая вверх все вышестоящие элементы. Если pos не задано, значение вставляется в конец таблицы.
removedvalue = table.remove (table, [pos])
Удаляет элемент из позиции pos, сдвигая вниз все вышестоящие элементы. Если pos не задано, удаляет последний элемент массива. Возвращает значение удаленного поля.
table.sort (table, [comp])
Сортирует массив, используя сравнивающую функцию comp. comp должен быть функцией, которая для двух элементов должна возвращать nil, если первый больше второго. Также comp может быть строкой "<" или ">", тогда массив будет отсортирован по возрастанию или по убыванию соответственно.
joined = table.concat (table, [sep, [begin, [end]]])
Соединяет все значения массива table в строку, разделяя каждый элемент строкой sep, от элемента begin до end. Значения по умолчанию: sep="", begin=1, end=table.getn(table). Значения, входящие в этот интервал, должны быть числами или строками.
returned = table.foreach (table, function)
Вызывает функцию для каждого элемента таблицы table, передавая ей индекс и значение. Если функция возвращает какое либо значение, отличное от nil, то цикл прерывается и table.foreach возвращает это значение.
returned = table.foreachi (table, function)
Вызывает функцию для каждого элемента массива table по порядку, передавая ей числовой индекс и значение. Если функция возвращает какое либо значение, отличное от nil, то цикл прерывается и table.foreachi возвращает это значение.
table2 = table.copy(table1, [table2])
Копирует все элементы таблицы table1 в таблицу table2. Создаёт новую таблицу, если второй параметр не задан. Возвращает table2 (или новую таблицу).
В частности
list = table:copy() -- то же самое, что и table.copy(table)
создаст новую таблицу содержащую все функции таблицы table. Это делает возможным использовать таблицу в объектно-ориентированном стиле: list:insert(...), list:unpack(), list:concat(", ") и т.д.
********** РАБОТА СО СТРОКАМИ **********
charset = string.spread (string, [mode, [limit]])
Возвращает массив, где каждому элементу соответствует отдельный символ строки string. Есть возможность ограничить число обрабатываемых символов, указав третий параметр; это нужно для того, чтобы ускорить процесс, т.к. функция может заметно тормозить при обработке строк длиной более 1000 символов. По умолчанию ограничение стоит 1000, но и его можно изменить, если присвоить string.limit нужное значение. Ограничение выше нескольких тысяч с последующей обработкой длинной строки может вызвать падение игры. Таблицы можно мемоизировать для дальнейшего использования функциями библиотеки string. За это отвечает поле string.mode (и необязательный параметр mode), которое может принимать одно из строковых значений: "#*", "#+", "*", "+". Символ # означает, что при наличии нужной таблицы новая создана не будет, отсутствие этого символа означает, что каждый раз будет создаваться новая таблица символов строки. Если таблица не была найдена в буфере или режим не содержит #, создается новая. При этом она будет записана в буфер только если режим содержит +. Режим по умолчанию - "#*".
string.clearbuf ()
Очищает буфер от всех сохраненных строк.
capture, begin, end = string.match (string, pattern, [init])
Ищет строку pattern в строке string, начиная с позиции init (или начала при её отсутствии). Возвращает найденную подстроку и индексы вхождения - где начинается и где заканчивается искомая подстрока. Шаблоны поиска поддерживаются.
length = string.len (string)
Возвращает длину (количество символов) строки.
byte = string.byte (string, i)
Возвращает числовой код i-го символа строки string.
string.bytes
Таблица, содержащая 256 пар, где ключ - 1 символ, а значение - код этого символа.
string = string.char (bytetable)
Возвращает строку, в которой каждому элементу таблицы bytetable соответствует символ с этим кодом. Например:
string.char{97, 98, 99} --> "abc"
string.chars
Таблица, содержащая 256 пар, где ключ - число от 0 до 255, а значение - символ с этим кодом.
substring = string.sub (string, [begin, [end]])
Возвращает подстроку строки string, начинающуюся с символа номер begin и заканчивающийся символом номер end. Отрицательные значения интерпретируются как индексы с конца строки. Значения по умолчанию: 1 и -1, то есть вся строка.
converted, changes = string.gsub (string, pattern, repl, [max])
Заменяет все вхождения строки pattern в строку string на repl. repl должен быть таблицей, содержащей поля f, t, s. Сначала вызывается функция f с параметрами: найденная подстрока, индекс начала, индекс конца. Если поле отсутствует или функция возвращает nil, то проверяется таблица t. В качестве индекса ей передается найденная подстрока. Если поле t отсутствует или в таблице нет запрашиваемого значения, то подставляется строка s. При отсутствии строки s подстрока не изменяется. Количество производимых замен можно ограничить необязательным четвертым параметром. Функция возвращает измененную строку и количество произведённых замен.
Пример:
string.gsub("choose(_HERO, _HUT, _OWNER)", "_%u+", {t={_HERO='"'..hero..'"', _HUT=[["hut3"]], _OWNER=GetObjectOwner(hero)}}) --> 'choose("Brem", "hut3", 1)', 3
matchtable = string.gmatch (string, pattern)
Возвращает массив со всеми вхождениями шаблона pattern в строку string. Поэтому конструкция
for i, matched in string.gmatch(string, pattern) do
-- ...
end
выполнит тело цикла для всех подстрок. Если важен порядок, то стоит использовать конструкцию
local matchtable = string.gmatch(string, pattern)
for i=1,table.getn(matchtable) do
local matched = matchtable[i]
-- ...
end
Пример:
for i, objective in string.gmatch(GetAllNames(3), "%S+") do
if GetObjectiveState(objective) ~= OBJECTIVE_COMPLETED then
print("Задача \"", objective, "\" не выполнена")
end
end
********** ШАБЛОНЫ **********
Символьный класс:
Символьный класс используется, чтобы представить набор символов. Следующие комбинации позволяются в описании символьного класса:
x - Здесь x любые незарезервированные символы: ^$()%.[]*+-?. Представляет непосредственно символ x.
%a - Представляет все буквы.
%c - Представляет все спецсимволы.
%d - Представляет все цифры.
%g - Представляет все печатаемые символы, кроме пробела.
%l - Представляет все буквы в нижнем регистре.
%p - Представляет все символы пунктуации.
%s - Представляет все пробелы.
%u - Представляет все буквы в верхнем регистре.
%w - Представляет все алфавитно-цифровые символы.
%x - Представляет все шестнадцатеричные цифры.
%x - Здесь x задает любой не алфавитно-цифровой символ. Представляет символ x. Это стандартный способ экранировки управляющих спецсимволов. Лучше следить за тем, чтобы любому символу пунктуации (даже не управляющему!) предшествовал %, когда символ применен в образце.
[char-set] - Представляет класс, который является объединением всех символов в char-set. Диапазон символов может быть определен, отделяя конечные символы диапазона тире (-). Все классы %x, описанные выше, могут также использоваться как компоненты в char-set. Все другие символы в char-set представляются как есть. Например, [%w_] (или [_%w]) представляет все алфавитно-цифровые символы плюс символ подчеркивания, [0-7] представляет восьмеричные цифры, а [0-7%l%-] представляет восьмеричные цифры плюс символы строчных букв плюс символ тире. Взаимодействие между диапазонами и классами не определено. Следовательно, образцы, подобные [%a-z] или [a-%%] не имеют никакого значения.
[^char-set] - Представляет инверсию char-set, где char-set интерпретируется как выше.
Для всех классов, представляемых одиночными символами (%a, %c, ...), соответствующая прописная буква представляет дополнение класса. Например, %S представляет все не пробелы.
Определения символа, пробела и т.д. зависят от текущего региона. В частности, класс [a-z] может быть не эквивалентен %l. Вторая форма должна быть предпочтительней для переносимости. (Текущий регион - Россия [Russian_Russia.1251]).
Элемент образца:
Элементом образца может быть:
Одиночный символьный класс, который соответствует любому одиночному символу в классе.
Одиночный символьный класс, сопровождаемый *, что соответствует 0 или большему количеству повторений символов в классе. Эти элементы повторения будут всегда соответствовать самой длинной возможной последовательности.
Одиночный символьный класс, сопровождаемый +, что соответствует 1 или большему количеству повторений символов в классе. Эти элементы повторения будут всегда соответствовать самой длинной возможной последовательности.
Одиночный символьный класс, сопровождаемый ?, что соответствует 0 или 1 местонахождению символа в классе.
Шаблоны:
Шаблон представляет собой последовательность элементов образца.
********** МАТЕМАТИЧЕСКАЯ БИБЛИОТЕКА **********
modul = math.abs (num)
Возвращает модуль числа.
rem = math.fmod (x, y)
Возвращает остаток от деления x на y. В отличие от встроенной функции mod не возбуждает ошибку, если второй параметр равен нулю.
ceil = math.ceil (num)
Округляет число вверх.
floor = math.floor (num)
Округляет число вниз.
rounded = math.round (num, [precision])
Округляет число num до знака precision (или до целого). Положительные значения точности использовать не рекомендуется, из-за неточности представления самих чисел.
val = math.pow (x, y)
Возводит x в степень y. y должен быть целым числом.
val = math.root (x, root)
Вычисляет корень степени root из числа x.
intg, frac = math.modf (num)
Возвращает два значения: целую и дробную часть числа.
random = math.random ([x], [y])
Если вызвана без параметров, возвращает случайное число в промежутке [0; 1). Если передан один параметр - то возвращает случайное целое число в промежутке [1; x], если два, то в промежутке [x; y]. Работает независимо от встроенной функции random. Функция работает на линейном конгруэнтном ГПСЧ с периодом 65536.
math.randomseed (seed)
Устанавливает "зерно" генерации последовательности случайных чисел. Одинаковые зерна определяют одну и ту же последовательность. По умолчанию всегда выставлено зерно = 0.
min = math.min (arg, ...)
Возвращает минимальный из своих аргументов. Все аргументы должны быть одного типа - все числа или все строки.
max = math.max (arg, ...)
Возвращает максимальный из своих аргументов. См. примечание math.min.
rad = math.rad (deg)
Переводит угол, заданный в градусах, в радианы.
deg = math.deg (rad)
Переводит угол, заданный в радианах, в градусы.
sin = math.sin (rad)
Вычисляет синус угла, заданный в радианах.
cos = math.cos (rad)
Вычисляет косинус угла, заданный в радианах.
tg = math.tan (rad)
Вычисляет тангенс угла, заданный в радианах.
factorial = math.fact (n)
Вычисляет факториал числа n, которое должно быть целым неотрицательным.