Zer0Galaxy
-
Публикации
1 220 -
Зарегистрирован
-
Посещение
-
Победитель дней
189
Сообщения, опубликованные пользователем Zer0Galaxy
-
-
Символы и спецсимволы в шаблоне можно объединять в наборы (сеты). Для этого несколько символов заключаются в квадратные скобки. Набор замещает собой один из символов, входящих в его состав. Например, вот такой набор [%d%p] замещает цифру или знак препинания. А такой [_%w] - букву, цифру или символ подчеркивания. Порядок символов, в котором они идут в наборе значения не имеет.
Теперь мы можем найти в строке значение переменной y даже если оно будет отрицательным или сопровождаться знаком +
s:match('y=[%+%-]?%d+')
Знаки % перед + и - говорят о том, что это не спецсимволы, а обычные + и -
Знак ? после набора указывает на то, что + или - могут отсутствовать.
А вот такой шаблон
s:match('y=[%+%-%d]%d*%.?%d*')
позволит найти число в формате с десятичной точкой.
Если набор начинается с символа ^ , то такой набор интерпретируется как "всё кроме указанных символов".
-
4
-
-
Вы наверняка подумали, а зачем искать в строке значение переменной y, если для поиска нужно знать значение этой переменной? Как быть если значение y заранее не известно? Чаще всего так и происходит. Тогда в шаблон вместо цифр необходимо подставить специальные символы. В нашем случае это %d.
s:match('y=%d%d')
Спецсимволы в шаблоне заменяют собой другие символы. Спецсимволов припоминаю несколько:
%a - заменяют все буквы
%d - все цифры
%w - буквы и цифры
%p - знаки препинания
%s - пробел
.(точка) - любой символ
%. - символ "точка"
Спецсимволов чуть больше, но остальные не столь актуальны.
Надеюсь, понятно, что функция s:match('y=%d%d') будет искать в строке s подстроку состоящую из символов 'y=' и еще каких то двух цифр. Именно эту подстроку она и вернет. Если найдет.
А вдруг мы не знаем из скольки символов состоит значение переменной y. В этом случае на помощь приходят модификаторы. Модификаторы это такие спецсимволы, которые изменяют количество символа за которым стоят в шаблоне.
Вот такие я знаю модификаторы:
+ - соответствует одному или более повторений символа;
* - соответствует нулю или более повторений;
- - соответствует нулю или более повторений. В отличии от модификатора * возвращает строку минимально возможной длины, но так, что бы она соответствовала шаблону;
? - соответствует нулю или одному символу.
Если мы знаем, что значение переменной y состоит из какого то количества цифр (но не менее одной), следует применить модификатор +
s:match('y=%d+')
Эта функция будет искать в строке s подстроку состоящую из символов 'y=' и какого то количества цифр. Причем вернет подстроку максимально возможной длины, т.е. 'y=' и все цифры следующие за знаком равенства.
Продолжение следует ...
-
5
-
-
- Я умею читать чужие мысли!
- А я умею читать чужие регулярные выражения!
- Ты победил
Люди, которые программируют приложения, связанные с обменом по сети rednet или сохранением на диск, часто сталкиваются с необходимостью преобразования массива данных различных типов в строку и последующим его восстановлением. Под массивом я подразумеваю не отдельно взятую таблицу, а несколько переменных, которые нужно упаковать в одну строку. Самый простой но не самый лучший способ решить эту задачу - поместить все необходимые данные в таблицу и воспользоваться функциями serialize, unserialize из библиотеки textutilse. О недостатках такого способа я уже когда-то говорил и сегодня повторяться не буду. А расскажу о том, как эту проблему решаю я. Предположим нам необходимо упаковать в одну строку значения нескольких переменных (x, y, z). Причем строка должна содержать не только значения переменных, но и информацию о том, что это за переменные. Думаю с упаковкой ни у кого больших проблем не возникнет. Сделать это можно, к примеру, так: s='x='..x..' y='..y..' z='..z В результате мы получим строку, которая содержит имена наших переменных и их значения, отделенные от имен знаками равенства. 'x=10 y=11 z=12' Вроде просто. Но как из этой строки извлечь заложенную в нее информацию, а именно имена и значения? Конечно, можно написать большой и сложный алгоритм посимвольного разбора строки. К счастью, вся скучная работа уже сделана за нас и поставленную задачу мы можем выполнить буквально в одно действие. Я говорю о функциях match и gmatch из библиотеки string. Назначение этих функций - поиск шаблона в строке. К примеру, в строке s, которую я привел выше, я хочу найти подстроку 'y=11'. Для этого я вызываю функцию s:match('y=11') которая и вернет мне искомую подстроку, если она там есть. Параметр 'y=11' будем называть шаблоном. Если шаблон в строке не найден, функция вернет nil. Правда здорово?
-
6
-
-
Если роутер С накрылся, до роутера D вообще ничего не дойдетвсё просто.
-
Предположим, мы имеем вот такую сетьвес можно не использовать
Как видим, возможны два маршрута от роутера 1 к роутеру 3. Вес одного из них равен 2, а другого - 3. Естественно выбран будет наиболее короткий маршрут с наименьшим весом. Но что случится если второй роутер выйдет из строя?
Прежний маршрут станет недоступным и на какое то время связь прервется. Но к счастью есть старение маршрута. И через пять минут, когда он не обновится, его вес станет равным трем. А еще через пять и вовсе четырем. Вот тут то и стрельнет длинный маршрут, который продолжает обновляться.
-
1
-
-
Теперь по поводу адресации. Адресация в реализованной сети трехуровневая. Это значит, что ip-адрес, возвращаемый функцией getIP, складывается из трех составляющих. Вот пример адреса, который может вернуть getIP
white.snow.33
где: white - имя сегмента сети, snow - имя роутера, 33 - id компьютера.
Что такое сегмент? Для уменьшения размеров таблиц маршрутизации вся сеть делится на сегменты. Роутер хранит маршруты не ко всем роутерам сети, а к сегментам и к роутерам в своем сегменте.
Пример: предположим в сети сотня роутеров. Без сегментации каждому роутеру пришлось бы хранить сто маршрутов. Если сеть разбить на десять сегментов, в таблице маршрутизации каждого роутера будет девять маршрутов на соседние сегменты и десять маршрутов на роутеры своего сегмента. И того - 19.
На данный момент реализован только один сегмент - белый. Но планируется еще как минимум шесть.
А на счет помощи. Основные технические вопросы касающиеся доставки пакетов решены. Необходимо дальнейшее развитие сети. Наполнение web-серверов, создание электронной почты, чатов и т.д. Можешь подумать как перевести всё это дело на OpenComputers. И конечно актуальным является вопрос русификации.
-
Сеть работает следующим образом. Имеется ряд роутеров, на данный момент семь штук. Каждый роутер имеет статическую таблицу маршрутизации, которая хранится в файле на диске роутера. Обычно она содержит только собственный ip-адрес роутера, но могут быть и исключения. После запуска роутеры начинают с определенным периодом (сейчас 5 минут) обмениваться своими маршрутами. Маршруты, полученные от другого роутера, сохраняются в ОЗУ. Каждый маршрут в таблице имеет параметр, который я называю "вес". Статические маршруты (загруженные из файла) имеют нулевой вес. Динамические - увеличивают свой вес на 1 при каждой передаче от роутера к роутеру. Т.е. если маршрут получен от соседнего роутера он будет иметь вес равный 1, если через одного то - 2. И т.д. Прежде чем добавить динамический маршрут, роутер сравнивает его вес с уже имеющимся в своей таблице и сохраняет маршрут с наименьшим весом. Это сделано для того, что бы хранить в таблице только самые короткие маршруты.
Кроме того, маршруты подвержены старению. Если маршрут в течении периода не обновился, его вес увеличивается на единицу. Таким образом появляется шанс у более длинного, но более надежного маршрута. Благодаря этому сеть, хоть и не сразу, но восстанавливается в случае отключения одного из роутеров.
-
3
-
-
Предлагаю потестировать WEB-сервер, созданный на базе Craftnet.
Для доступа к серверу вам понадобится уже упоминавшаяся библиотека функций (pastebin get FJqsDgZP ip) и конечно же браузер (pastebin get Gn6ki1TH browser). Браузер нужно запускать на цветном компьютере, оснащенном беспроводным модемом.
После запуска браузера кликаем на белую строку ввода адреса и вводим адрес пока единственного сайта (white.poem).
[ATTACH]118[/ATTACH]
Если всё сделано правильно, вы сможете ознакомиться с несколькими шедеврами мировой поэзии.
-
На сервере 164 успешно прошла тестирование глобальная сеть Craftnet.
Если вы знаете и используете API rednet, вас должна заинтересовать возможность связать между собой компьютеры, находящиеся на расстоянии гораздо дальше чем 64 блока.
Что для этого нужно? Два или более компьютеров, оборудованных беспроводными модемами и находящихся в зоне покрытия Craftnet. Расстояние между ними значения не имеет.
На данный момент зона покрытия имеет радиус порядка 600 блоков с центром в районе спауна.
Как этим пользоваться?
На каждый компьютер загружаем пакет функций для работы с Craftnet
Функций всего четыре. Вот они:
open() - инициализирует беспроводной модем. В отличии от стандартного rednet.open, не требует указывать сторону, на которой расположен модем. Возвращает true в случае удачной инициализации
getIP() - регистрирует компьютер в сети. Возвращает строку с адресом. Этот адрес понадобится другому компьютеру, если он захочет нам что то передать. Функции open и getIP достаточно вызвать один раз.
send(ip, mess) - передает сообщение mess компьютеру с адресом ip. Аналог функции rednet.send, только адрес не число, а строка, полученная функцией getIP.
receive([timeout]) - переводит компьютер в режим приема сообщений. Аналог функции rednet.receive. Необязательный параметр timeout, как и раньше, задает максимальное время ожидания. Возвращает 1) принятое сообщение 2) ip отправителя 3) ip получателя.
Выражаю признательность игроку Neo за идеи, высказанные при обсуждении структуры сети.
Rednet: предел - 64 блока;
Craftnet: бесконечность - не предел.
-
5
-
-
В прошлый раз мы научились создавать объекты в lua и вызывать их методы. Нами был создан класс ClassA (хорошо, не класс, а объект-прототип), имеющий одно поле (Name) и два метода (Metod1, Metod2). Были созданы два экземпляра объектов и вызваны их методы.
Сегодня мы попытаемся создать наследника от ClassA, добавим ему еще одно поле, унаследуем один из методов без изменений, а второй переопределим.
Так же как и класс-родитель, наследник изначально представляет собой пустую таблицу:
ClassB={} ClassB.__index=ClassB setmetatable(ClassB,ClassA)После выполнения setmetatable, ClassB внешне будет представлять собой точную копию ClassA, т. е. унаследует все его методы.Изменения начнем с конструктора
function ClassB:new(_Name,_Size) local obj=ClassA:new(_Name) obj.Size=_Size setmetatable(obj,self) print('Constructor ClassB for '..obj.Name) return obj endКаковы отличия в конструкторах родителя и наследника? Как видим, для создания объекта наследник использует конструктор родителя, а не создает объект «с нуля». Это конечно не обязательно, но такова классика. Другое отличие — новое поле, которое будет хранить воображаемый размер нашего объекта.Переходим к методам. Metod1, как и договаривались оставляем нетронутым, а вот Metod2 переопределим.
function ClassB:Metod2() ClassA.Metod2(self) --inherited print('Metod2 of ClassB for '..self.Name..'. Size is '..self.Size) endТут я показал как из метода объекта-наследника вызвать метод объекта-родителя. Но это тоже при необходимости.Вот собственно и всё.
Помимо ранее созданных объектов ClassA, создаем еще два экземпляра нового объекта
objects={} for i = 1,2 do objects[i] = ClassA:new('Object#'..i) end for i = 3,4 do objects[i] = ClassB:new('Object#'..i, i*i) endИ посмотрим что получилосьfor i=1,4 do objects[i]:Metod1() objects[i]:Metod2() endУ меня получилось вот что:[ATTACH]116[/ATTACH]
Обращаю внимание, что для объектов 3 и 4 конструктор и Metod2 выполняются дважды — сначала от ClassA, затем от ClassB.
Мы рассмотрели такие особенности ООП как наследование и полиморфизм. А вот как реализовать на lua сокрытие данных объекта от доступа извне (по моему, это называется инкапсуляцией) я пока не знаю. Если знаете — пишите.
Для тех кто все таки решил попробовать себя в объектно-ориентированном программировании, напоминаю — следите за пунктуацией. Имя поля отделяем точкой, имя метода — двоеточием. Это важно.
-
4
-
-
В данной статье я хотел бы показать, как можно применять объектно-ориентированный подход при программировании на lua. Если Вы ранее не сталкивались с ООП в других языках, статья вряд ли станет Вам полезной ибо не предназначена для обучения объектно-ориентированному мышлению, а лишь приводит пример реализации объектов.
Lua не относится к объектно-ориентированным языкам, поскольку не содержит стандартных механизмов создания и использования объектов. Но lua-таблица является настолько гибким инструментом, что позволяет реализовать практически любую структуру, присущую другим языкам. В том числе и объекты.
Прежде чем создавать экземпляры объекта, необходимо описать соответствующий ему класс.
ClassA={} ClassA.__index=ClassAПо большому счету, называть это классом нельзя, поскольку класс — это абстракция, служащая шаблоном для создания объекта. Сдесь же мы имеем дело с вполне реальной таблицей. Поэтому ClassA будем называть объектом-прототипом.Как видите, я не описал никаких полей объекта-прототипа т. к. в отличии от таких языков как Delphi и C++, поля таблицы в lua можно описывать когда угодно, а не только при создании таблицы. Поля будем прописывать в конструкторе класса при создании экземпляра объекта. Единственное поле __index содержит указатель на сам класс. Это нужно будет для правильной работы оператора self.
Создадим конструктор:
function ClassA:new(_Name) local obj={Name = _Name} setmetatable(obj,self) print('Constructor ClassA for '..obj.Name) return obj endЧто делает конструктор?Строка 1. Создает экземпляр теперь уже объекта, описывает поля объекта и присваивает полям начальные значения.
Строка 2. Переопределяет метатаблицу вновь созданного объекта, в результате чего объект получает доступ к методам класса. Методов пока нет, но они будут описаны позже.
Строка 3. Это необязательная строка. Я ее сюда вставил для демонстрации работы конструктора.
Строка 4. Возвращает созданный объект.
Теперь создадим парочку методов:
function ClassA:Metod1() print('Metod1 of ClassA for '..self.Name) end function ClassA:Metod2() print('Metod2 of ClassA for '..self.Name) endЗачем два? В дальнейшем один из них будет наследован, а другой перекрыт методом наследника.И так, мы создали объект-прототип. Пора создавать экземпляры объекта. Экземпляры будем хранить в таблице objects. Для создания экземпляра вызываем конструктор
objects={} for i = 1,2 do objects[i] = ClassA:new('Object#'..i) endСмотрим что получилось
for i=1,2 do objects[i]:Metod1() objects[i]:Metod2() endВот программа в полном сборе.
ClassA={} ClassA.__index=ClassA function ClassA:new(_Name) local obj={Name = _Name} setmetatable(obj,self) print('Constructor ClassA for '..obj.Name) return obj end function ClassA:Metod1() print('Metod1 of ClassA for '..self.Name) end function ClassA:Metod2() print('Metod2 of ClassA for '..self.Name) end objects={} for i = 1,2 do objects[i] = ClassA:new('Object#'..i) end for i=1,2 do objects[i]:Metod1() objects[i]:Metod2() endЕсли все сделано правильно, после запуска программы Вы должны наблюдать вот такие сообщения:
[ATTACH]115[/ATTACH]
В следующий раз я расскажу о наследовании методов объекта и их полиморфизме.
-
2
-
-
Это что, реальная статистика? Интересно, откуда оно берет данные? Неужели подавляющее большинство форумчан старше 45? И где 1,2% женщин? Что-то я ни одной не видел. Что такое глубина просмотра?Статистика нашего сайта по возрастам:
-
Вот, как то так:
local user={} -- Описываем класс user user.__index=user -- это обязательно -- Это метод класса function user:register(login0, password0) self.login = login0 self.password = password0 end -- Это конструктор класса function user:new() local obj={login = '', password = ''} -- создаем новый объект setmetatable(obj,self) -- наделяем его свойствами класса return obj -- возвращаем полученный объект end users={} --тут будем хранить элементы класса for i = 1,5 do -- для создания элемента класса вызываем конструктор users[i] = user:new() -- можно было бы совместить new и register ... print('<'..users[i].login..'>') -- print что бы было видно, что прога работает. -- вызываем метод вновь созданного объекта users[i]:register('login' .. i,'password' .. i) end -- смотрим что получилось for i=1,5 do print(users[i].login,' ',users[i].password) end-
1
-
-
У тебя будет создан массив users с пятью элементами, каждый из которых является указателем на один и тот же объект user.local i for i = 1,5 do users[i] = user -- чувствую вот тут бред уже пишу... print(users[i].name) -- print что бы было видно, что прога работает. endПопробуй как нибудь вот так
function NewUser() local obj={login = '', password = ''} return obj end for i = 1,5 do users[i] = NewUser() -- чувствую вот тут бред уже пишу... print(users[i].login) -- print что бы было видно, что прога работает. endА чтобы такая конструкция работала
users[i]:register('login' .. tostring(i),'password' .. tostring(i))нужно метатаблицу переопределять. Вспомню как это делать - выложу.Да, и объявлять локальной переменную цикла не обязательно. Она и так будет локальной
-
На сколько я понял, алгоритм А* предполагает, что карта черепахе известна. Если черепаха сама ее строила, тогда понятно. А если нет, тогда как?
-
Так это же готовая прога построения лабиринта для войны роботов Алекса. Я что то подобное писал, но не такое многофункциональное. Вот только пользоваться флопинетом при наличии реднета это не серьезно. Могу помочь, если есть трудности.
И еще. Как на счет следующих вопросов?
1. построения одного объекта сразу несколькими черепахами
2. сканирование готового объекта для сохранения в память
Оформление видео - десять из десяти
-
1
-
-
Я полагал, что когда черепаха "умирает", то она умирает и куда то подниматься уже некому. Другое дело, сможет ли она издать предсмертный писк, что бы ее сородичи узнали и пошли мстить?Контроль боевых потерь: Когда черепаха"умирает" она поднимается например на 10 блоков вверх и зависает там до конца боя реагируя только на команду окончания сего
-
Такая проблема: пытаюсь присоединить монитор к системнику и просто вываливаюсь из майкрафта, без всяких сообщений. Тоже происходит при попытке зайти в терминал робота. Мод качал с официального сайта
-
Никуда не пропадал. В РК регулярно бываюZer,ты куда пропал??
-
Вопрос: ресурсы, которыми ведется торговля, будут садминены или добыты игровыми средствами?
А по поводу цен, по моему, цены должны определяться не столько редкостью и полезностью сколько спросом и предложением. Например, если все сдают уголь и берут алмазы, цена на уголь должна падать, а на алмазы расти. Может даже автоматически. Иначе, если не будет отрицательной обратной связи, можем получить финансовый перекос. Начальные же цены действительно нужно установить исходя из соображений нужности и сложности добычи. Эх, нет у меня экономического образования...
-
Semoro, что тебе известно о русификации СС? Если много, давай тему создадим.
-
Для начала нужно поселиться на сервере недалеко друг от друга и создать небольшую сеть из 3-4 роутеров. По мере необходимости наращивать.Могу присоединится в качестве программиста
К сожалению, я не смогу в ближайшее время появляться на игровом сервере и буду участвовать только из оффлайна. Часто бываю в РК, все вопросы можно туда.
Вот ПО роутера, которое должно запускаться из стартапа
Таблица маршрутизации - статическая. Ее нужно поместить в файл rtable в корне диска. Пример таблицы
first self second 8 third 9 fourth 9
Первая колонка - имя подсети, вторая - id по которому будет переправляться пакет на данную подсеть. Если во второй колонке self - значит это собственное имя роутера.Набор функций для хоста
У Neo есть задумка динамической маршрутизации, но я пока не видел достаточно эффективной реализации.
-
О структуре ip-адреса и таблицах маршрутизации в сети rednet (окончание)
Чтобы все сказанное мной выше не казалось безжизненной теорией приведу пример работающих функций, которые могут помочь в нахождении роутером пути для передачи пакета.
Первая из них loadTable(filename) предназначена для загрузки таблицы маршрутизации из файла.
function loadTable(filename) local rTable={} local file=fs.open(filename,'r') if not file then error('Can not open file '..filename) end local line=file.readLine() while line do local path,id=line:match('^%s-([_%w%.]+)%s+(%d+)') if path then id=tonumber(id) local t=rTable for k in path:gmatch('([_%w]+)%.') do write(k..'.') if not t[k] then t[k]={} elseif type(t[k])=='number' then t[k]={[0]=t[k]} end t=t[k] end local k=path:match('([_%w]+)$') t[k]=id print(k,'=',id) end line=file.readLine() end file.close() return rTable endВ качестве параметра функция принимает строку, содержащую путь к файлу. Возвращает таблицу, в которой данные из файла упакованы в виде удобном для использования. Вызывается один раз в начале работы ПО роутера.Вторая функция trace(t,path)
function trace(t,ip) ip=ip..'.' for k in ip:gmatch('([_%w]+)%.') do if not t[k] then return tonumber(k) end if type(t[k])=='table' then t=t[k] else return t[k] end end return t[0] endпринимает два параметра: t — таблица, полученная после вызова функции loadTable; ip – строка, содержащая ip-адрес хоста-приемника. Возвращает функция число — id компьютера (хоста или следующего роутера) на который следует передать пакет.Привожу скриншот работы этих функций для таблицы маршрутизации со следующим содержимым:
A.first 7 A.first.self 7 A.first.v_pupkin 13 A.second 8 A.third 9 A.fourth 9 B 8 C 9
-
О структуре ip-адреса и таблицах маршрутизации в сети rednet (продолжение)
А теперь предположим, что наши соседи из другой деревни построили сеть аналогичную нашей. И мы связали эти две сети в одну при помощи цепочки повторителей.
На рисунке изображены все имеющиеся в наличии роутеры и только два из всех возможных хостов. Наша деревня отмечена буквой А, соседняя — буквой В.
Как теперь должна должна выглядеть таблица маршрутизации роутера first, чтобы пакет, предназначенный для деревни В был направлен в нужном направлении?
Как я говорил выше, роутер должен знать пути ко всем остальным роутерам сети. Значит ли это, что в таблице должны быть прописаны пути к роутерам 15, 16, 17 и 18 для каждого в отдельности? Но ведь они все лежат в одном направлении и есть смысл выделить их в одну группу — группу В. А роутеры first, second, third и fourth соответственно в группу А.
Таким образом ip-адрес теперь будет состоять из трех составляющих: адрес группы, адрес роутера и адрес хоста. Такая сеть будет трехуровневой. Привожу пример таблицы маршрутизации роутера first:
A.first.self 10 – Это что бы отличать свои хосты от чужих
A.first.v_pupkin 13 – Уже извеcтный нам хост Васи Пупкина
A.second 8 – Пакеты на роутер second
A.third 9 – Пакеты на роутер third
A.fourth 9 – Пакеты на роутер fourth шлем через роутер third
B 8 – Пакеты для роутеров группы В шлем через роутер second
Разбор адреса производится в следующем порядке. Анализируется первая составляющая ip-адреса. Если это В — отправляем пакет на id 8. Если нет, анализируем вторую составляющую. Если это second, third или fourth — отправляем пакет на соответствующий id. Если нет, анализируем третью составляющую. Если третья составляющая прописана в таблице — отправляем пакет на соответствующий id. Если нет, интерпритируем третью составляющую как число и отправляем пакет на этот id. Если составляющая адреса не обнаружена в таблице, то такой пакет считается ошибочным и игнорируется.
В принципе, таким же образом можно построить четырех- и более уровневую сеть. Но я думаю, мы пока ограничимся тремя уровнями. Если не двумя.
Окончание следует.
-
1
-

Шаблоны
в Уроки
Опубликовано:
Шаблоны, которые я рассматривал до сих пор, возвращали строку, требующую дополнительной обработки. В самом деле, если функция match вернула строку 'y=11', то из этой строки необходимо выделить символы, соответствующие значению переменной. Например, вызвать функцию match еще раз. А нельзя ли обойтись одним вызовом? Оказывается можно. Делается это при помощи структуры, называемой захват (capture). Захват оформляется в виде группы символов, заключенных в круглые скобки. Если шаблон содержит захват, то он возвращает не всю совпавшую подстроку, а только захваченное значение, т.е. символы, соответствующие символам захвата.
Пример: s:match('y=(%d+)')
вернет строку не 'y=11', а '11'
Обращаю внимание, match всегда возвращает строку, даже если вы ищите число. Так что от преобразования типа tonumber никуда не деться.
Захватов в шаблоне может быть несколько. В этом случае match возвращает столько значений сколько захватов присутствует в шаблоне. Это позволяет искать сразу несколько значений в строке за один раз. Например:
s='x=10 y=11 z=12'
x,y,z=s:match('x=(%d+)%s*y=(%d+)%s*z=(%d+)')
Тут нужно быть внимательным. Во-первых, не забываем про разделители, если они есть (в примере разделителями являются символы пробел - %s). Во-вторых, следует помнить, что шаблон стреляет только тогда, когда совпал целиком. Т.е. если из трех захватов, приведенных в примере, найдены два, а третий не найден, результатом работы функции будет nil и все три переменные x,y,z будут не определены. Поэтому, если вы не уверены, что в исходной строке присутствуют все искомые значения, воспользуйтесь тремя разными поисками. Или же функцией gmatch, о которой я расскажу чуть позже.