Перейти к контенту
Malandrinus

Язык Lua. Общие вопросы программирования

Рекомендуемые сообщения

С чего начинать и где взять.

 

Установка Lua:
http://www.amk-team.ru/forum/index.php?showtopic=11584&p=629106

 

Руководство «Программирование на языке Lua», третье издание:
http://www.amk-team.ru/forum/index.php?showtopic=11584&p=905308

Изменено пользователем Kirgudu
Ссылка на комментарий

Не знаю, насколько это актуально, но я часто использовала в последних своих изысканиях по сталкеру (но это относится к ЛУА в целом) следующее свойство: ключами и значениями у таблиц в ЛУА может быть что угодно. В качестве ключей можно использовать другие таблицы или функции! Это было откровение, и оказалось удобно. :)

 

Еще одним хорошим методом увеличения гибкости кода является использование безымянных функций, в частности, когда их передаешь как аргумент в другие функции. (Был уже пример, как я понимаю, - итератор). Получается неплохое такое приближение к полиморфизму в С++ (учитывая, что с помощью метатаблиц в ЛУА можно сымитировать классы и их поведение). Или, например, можно написать итератор по таблице, который будет выполнять функции, хранящиеся в таблицах-значениях, в зависимости от других значений этих таблиц или даже ключа (или выполнять ключ, если он является функцией). В общем - гибкость бешеная. Код, обычно, сокращался раза в 2-3. Есть только минус - отлаживать гораздо сложнее :)

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

Зачем? В зависимости от надобности.

Пример был даже приведен. У меня было, например, одно место, где использовалась очередь колбеков - таблица, в которой ключ являлся ссылкой на функцию, а значением была таблица, передаваемая этой функции. Вполне удобно оказалось - заранее составляем таблицу, потом просто используем. Так программировалось поведение в рейде, при изменении условий, очередь перестраивалась заново. Своеобразный планировщик получался.

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

Без кода, принцип:

 

Есть некая непись, она составляет рейд, причем в каждой точке (ключевой) планирует некое действие (например - отдельную схему, выполнение квеста и т.п.).

Действие - функция (у меня подставлялась в экшн), а параметры - "настройка действия" (типа надо пойти и найти такой-то предмет, отыграть такую-то анимацию и бляблябля).

В результате я получала для непися таблицу с парами "функция - параметры". Ну и непись отправляется под схему.

При смене состояния (непись дошел до цели, например) делается next из таблицы, пишется в переменные (self.четотам, например). В эвалюаторе/экшене просто выполняется сохраненная функция с параметрами. В результате получается разнообразное поведение, в зависимости от того, что происходит вокруг непися и на контрольных точках. А схема - одна. Ну и никаких захардкоденых графов.

Когда таблица "исчерпана", рейд завершается и непись возвращается в исходную (ну или какую выберет) точку.

------

Поздно, я уже ответила

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

xStream

Спасибо за ценную информацию :)

 

_____

 

Кто знает, возможно ли в луа делать таблицы из интервалов? Допустим у меня есть число от 1 до 100 и 10 каких то значений.

Я хочу составить таблицу так, чтобы в зависимости от числа, выбиралось определённое значение. Тоесть если чсло равно от 1 до 10, то берётся значение 1 и так дале...

 

Делать через if не очень хочется.

 

Вот такой код нужно упростить:

 

 local num = math.random(1,100)

if num <= 10 then return -2000 end
if num >  10 and <= 20 then return -1500 end
if num >  20 and <= 30 then return -1000 end
if num >  30 and <= 40 then return  -500 end
if num >  40 and <= 50 then return     0 end
if num >  50 and <= 60 then return   500 end
if num >  60 and <= 70 then return  1000 end
if num >  70 and <= 80 then return  1500 end
if num >  80 and <= 90 then return  2000 end
if num >  90 then return  2500 end

return 0

Изменено пользователем *Shoker*

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

Ссылка на комментарий

Мне кажется, здесь проще всего составить функцию, в данном конкретном случае: деление на 10, получение целой части, отнимание 5, умножение на 500, обрезание с помощью min & max

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

В принципе можно и так, но хорошо бы найти решение не тока для "конкретного" случая, ибо уже пару раз сталкивался с такой необходимостью, и приходилось через if-ы действовать...

Как я понял, в LUA похожего интервального решения не предусмотрено.

Может помимо if-ов есть ещё какие то варианты.

 

ЗЫ: Случайно ошибся в функции, после and не написал num, но на суть вопроса не влияет.

Изменено пользователем *Shoker*

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

Ссылка на комментарий

Честно, не встречался ни один язык с "выборками интервалами". То, что тебе надо - поиск по массиву.

В терминах ЛУА можно составить таблицу, каждый элемент которой содержит минимум и максимум, и значение. А там уж бегать по нему, пока не попадется нужное.

Или, как я выше писала, ключ - функция, которая вернет тру или фалс; если тру, берем значение и останавливаем перебор. Это более универсальное решение

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

malandrinus, полностью солидарен с высказанным. Та же таблица умножения является универсальной, но только сам человек может исходя из потребностей брать из нее то, что ему нужно.

Выше приведенный пример банально укладывается в простейшее:

local MyFunc = function() return math.random(-4,5)*500 end

Меняя цифирьки - получаем условную универсальность.

В конце концов задача любого кода в первую очередь дать результат и дать быстро, а красота/компактность/... - все же вторичны. Универсальность как раз относится к вторичным критериям и тем более, как правило, в противоречиях со скоротью получения результата.

Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Честно говоря, считаю, что "прятать" логику - очень дурной тон. Я про оператор индексации. В С++ схожая ситуация, но там оно более очевидно и потому используется широко. Типизированный язык как никак.

А вот спрятанный алгоритм поиска введет в недоумение не-автора. Что при работе в команде зачастую - очень нехорошо.

Согласна с Артосом: лучшее - враг хорошего. Быстрее и проще решить частный случай, чем клепать универсальный, никому не нужный код, который использован то будет всего пару раз. И в то же время, если код пишется в команде, то про красивость и ясность забывать нельзя - сэкономишь на одном, потеряешь на другом.

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

xStream, работа кодера в команде конечно же имеет свои особености и критерии. Хотя ... и времена команд практически прошли (в Сталкере) и в основном работа или одиночек или строго параллельно кодер+моделлер+дизайнер+ ... Т.е. один никак не мешает другому.

Забывать о ясности и даже красивости кода при его публикации (ведь моды - публичный продукт) никогда конечно не стОит, но и приносить оптимизацию/скорость в угоду 'рюшечкам' так же не разумно. Чаще всего, функция/блок/модуль должны быть не изнутри понятны, а ясна/понятна/и проста суть их применения для других, т.е. точки входа/выхода.

В общем все должно быть в меру, разумном сочетании и в обязательной привязке к контексту задачи. И упражнения в изощренности кода и в его упрощенности - вредны при их передозировке (эти слова для *Shoker*'а, дабы не замудрился ...). :-)

(сорри за оффтопик)

Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

[offtopic]

Ну как бы никто не спорит :) Я немножко увлеклась "жизненным" примером: у меня 3 подчиненных, так что работать в команде надо уметь.

Я придерживаюсь довольно строгих правил и требую от других того же (code guideline). Получается пока довольно эффективно. Начиная от именования переменных, до самодокументирования кода.

Так что вопрос о "единственно верном способе программирования" явно выходит за рамки этого топика, да и ненужно это. А вот использовать возможности языка тогда, когда это не вредит ни красоте, ни скорости, ни гибкости - вай нот?

[/offtopic]

 

Кстати, вспомнился вопрос оптимизации - зачастую лучше потратить память и выиграть в скорости, создавая временные, часто используемые, контейнеры и переменные. Это в тему топика.

Тогда и не придется заниматься экономией на циклах (30% быстрее и т.п.), так как итерация по 100 элементам - совершенно не то же самое, что по 10 000, к примеру.

Это применительно и к сталкеру. Была мода в свое время пробегать по всем ИДшникам игровым с 1 до 65к, проще сделать один раз и составить таблицу, откуда удалять элементы и добавлять их туда уже по колбекам регистрации/разрегистрации. Это просто пример и мое имхо. Возможно, я отстала от жизни.

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

xStream, к сожалению, времена идут но ... новички как ранее начинают, как правило с итераций по 65К таблицам ...

Но это уже вопрос больше из области 'не хочу учиться, а хочу жениться', т.е. не уча азы и наработанное - сразу выдать на гора 'свой мод'.

Насчет отдельных таблиц - конечно же решение верное, но ... и не напасешься порой таблиц на все про все и не все в таблице учтешь.

Например тот же офф-лайн-алайф из АМК. Локаций немало, объектов и их типов куча, событий мониторится тоже не раз-два ... Все коллбэками не охватить, тем более на постоянно пополняемых кодах модов. А сканировать все же нужно.

Тут недавно про 'coroutine' GUN12 нам всем напомнил, и вышел довольно неплохой промежуточный вариант распределенного сканирования:

Вот это на апдейте у актора:

local iPrgScan =  25  --/ периодичность сканирования Зоны (25ms => ~15 минут)

function OnUpdate(uo,delta)
  --/ непрерывное циклическое сканирование локаций по всему диапазону ID объектов (1...65534)
  if coroutine.status(CoScan) == 'suspended' then --/ статус сопрограммы: приостановлена?
    local bFlg,Result = coroutine.resume(CoScan, iPrgScan) --/ (пере)запуск сопрограммы
    if not bFlg then --/ ошибка при выполнении сопрограммы
      printf("OnUpdate:Error_CoScan=[%s]:<%s>", Result, "Error!")
    end
  end
end

А это основа сорограммы:

local tOAMain,tTmpMain = {},{} --/ дин.массив основных объектов (используется в m_news.script)
local tOwners,tTmpOwn  = {},{} --/ дин.массив владельцев предметов

local CoScan = coroutine.create( --/ сопрограмма сканирования объектов игры
  function(iTimeLimit) --/ функция сканирования объектов игры с ограничением времени работы
--    log("%s:CoScan:TimeLimit=[%s]:[%s]", sModule, iTimeLimit, ">") --/#~#
    local oPTimer,iTimeStop,soObj = nil,nil,nil
    local iCurID = 65535 --/ начальный ID
    while true do
      if iCurID >= 65534 then --/ проверка: цикл закончен (или предустановка)?
        --coroutine.yield(iCurID) --/ приостановка (опционально)
        if iCurID == 65534 then
          tOAMain,tOwners = tTmpMain,tTmpOwn --/ обновляем основные массивы
          log("%s:CoScan:Owners=[%s]:Time=[%s]%s", sModule, GetSizeTable(tOwners), Get_StrTime(), "") --/#~#
          --Print_Tables_OffLineAlife() --/#~# for Debug
        end
        --/ предустановки для нового цикла:
        tTmpMain,tTmpOwn = {},{} --/ временные массивы
        iCurID = 0 --/ начальный ID (опускаем 0-actor)
        iTimeStop = iTimeLimit --/ начальная установка для таймера
        oPTimer = profile_timer() --/ (пере)создаем объект таймера
      end
      iCurID = iCurID +1 --/ переход к следующему ID
      soObj = sim:object(iCurID) --/ очередной серверный объект игры
      if soObj then --/ объект в игре? ('пустышки' пропускаются и таймером)
        oPTimer:start() --/ старт таймера (на продолжение)
        --/ -- обработка объекта ----------------
        this.Build_TableObj(soObj,iCurID)
        --/ -------------------------------------
        oPTimer:stop() --/ (при)остановка таймера
        if oPTimer:time() > iTimeStop then --/ проверка: не закончен ли лимит времени?
          coroutine.yield(iCurID) --/ приостановка цикла
          iTimeStop = oPTimer:time() + iTimeLimit --/ обновляем для текущего подцикла сканирования
        end
      end
    end
    printf("%s:DoScan:<Error!>")
    return 65535 --/>
  end
)

Т.о. и эксклюзивные таблицы доступны и коллбэки их актуализируют и ... периодически каждые 10...15 минут эти таблицы освежаются просканнированным глобальным диапазоном по всем объектам, котрый не единовременно выполняется (давая лаги в игре), а размазанно по всему временному интервалу. Т.е. вариант включает в себя все достоинства известных вариантов, исключает лаги и почти исключает зависимость от 'пропущенных' недоработок коллбэков.

Будучи запущенным один раз - на протяжении всей игры периодически сканирует всю Зону по всем объектам создавая соответствующие 'тематические' таблицы. И все это практически в фоновом режиме.

Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий
и не напасешься порой таблиц на все про все и не все в таблице учтешь.

Ну так и решение то не претендует на универсальность :) это как способ "оптимизации циклов" :-D ... оптимизации архитектуры.

 

Тут недавно про 'coroutine' GUN12 нам всем напомнил, и вышел довольно неплохой промежуточный вариант распределенного сканирования:

Недурно, да. Но нити дают накладные расходы при выполнении, ну и никак не экономят процессорное время. И отлаживать тоже тяжелее. В принципе, это ж не противопоставление архитектурному решению, а просто еще одна техника. Те же апдейты актора и других - такие же по сути корутины.

 

Полагаю, топик как раз для "не новичков" и всякие техники полезны будут.

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

Имел ввиду конечно де не универсальность при создании 'таматических' таблиц, а то, что и этого порой не достаточно.

И конечно же доп. нить (тред) дает накладные расходы, не упомянуто и то, что создаются двойные таблицы (рабочая и временная), что тоже минус. Но(!) тут или иметь периодические 'быстрые' итерации по всему диапазону ID (65К) и иметь лаги, или ... размазать эти лаги во времени, чтобы их не заметно было.

Т.о. получился не обособленный 'еще один' вариант, а вариант 'симбиоз' с глобальным сканирование 65К + создание тематических (архитектурных) таблиц + распределение издержек во времени == в результате все довольны, игрок не видит лагов, кодер работает со своими таблицами, экономя другие ресурсы ... :-)

А отлаживать то как раз проще, обработка объектов в вынесенном блоке и имеет свою диагностику. Один раз написав - даже не приказался к отладке, т.к. все заработало сразу и работает как часы (да и проще просто врядли бывает, ИМХО, "ломаться" нечему).

Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Сложно, если там логика сложная и вылезло какое-нибудь переполнение стека :)

Простое и отлаживать просто, бесспорно. Все зависит от мозгов программиста - чем он наполнит это все дело :)

 

ЗЫ Завязываю оффтопить

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

Ну ... с перехватчиком Lua от alpet (ссылка) и добавленным дебагером от RvP уже и переполнения стека не так страшны и сложны в отладке как в былые времена. ;-)

(тоже и извиняюсь за некоторый оффтопик и прекращаю ... на время)

Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Ну, инструментарий появился со времени, когда я последний раз занималась сталком, - это ж замечательно! Я отстала от жизни.

Тем не менее, это инструменты, а речь шла о довольно примитивных техниках.

 

ЗЫ Все, точно завязываю :) Вернусь с чем-нить интересным, если вспомню. Просто некоторые вещи из Луа в принципе не подходят к сталкеру

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Ссылка на комментарий

xStream

Ну на оффтоп это мало похоже. Как никак "...Общие вопросы программирования" в названии темы также присутствует.

А тот, кому это нужно, извлечет не мало полезного из всего вышесказанного именно по вопросу программирования.

Ссылка на комментарий

Интересно!.. кстати...

Многоядерные CPU (2-3-4) и движок xRay 1.x.

Использует-ли xRay (реально) 3 и 4 ядра? Загружены-ли они работой?

А есть-ли у самой Lua свойства (или средства) "многоядерность"?

всё легко

Ссылка на комментарий

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

    Ни один зарегистрированный пользователь не просматривает эту страницу.

AMK-Team.ru

×
×
  • Создать...