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

Язык 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
Ссылка на комментарий

proger_Dencheek, в самом алгоритме есть логическая ошибка. При первых пяти вызовах, будет действительно выдаваться рандомные сообщения и они будут удаляться из массива aa, а массив bb будет заполнятся, до тех пор, пока все элементы aa не перекочуют в bb. Шестой вызов будет использовать массив bb, поскольку проверка

if next(aa) then

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

Поэтому используй алгоритм предложенный Gun12, он лишён данного недостатка. Про "бардак" совершенно не ясно, что ты имеешь ввиду...

P.S. И давай более внятные имена переменным, даже на этапе тестирования, это поможет избежать путаницы.

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

Рабочий вариант рандомного выбора из таблицы, свободный от любого повтора подряд одного и того же сообщения:

local messages = {"msg1","msg2","msg3","msg4","msg5"}
local tbl = {} --/ текущий список сообщений
local msg = "" --/ текущее (последнее) отправленное сообщение

function random_message()
  --/ проверяем наличие неотправленных сообщений
  if not next(tbl) then
   --/ возобновляем список доступых сообщений
   for _,v in ipairs(messages) do
      if v ~= msg then --/ исключаем последнее посланное
       table.insert(tbl,v) --/ добавляем в таблицу
      end
   end
  end
  --/ выбираем (одновременно удаляя из списка) рандомное сообщение
  msg = table.remove(tbl,math.random(#tbl))
  --/ отсылаем сообщение
  den.sms(msg)
end

 

 

Замысел был в не повторении сообщений по длине всего массива.

ColR_iT

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

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

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

Сделал упрощенный вариант, при котором за весь проход массива сообщение не повторяется не разу:

 

local tbl = {"msg1","msg2","msg3","msg4","msg5"}
local arhiv = tbl
if not next(tbl) then
 for k,v in pairs(arhiv) do
   table.insert(tbl, k, v)
 end
end
local key = math.random(#tbl)
den.sms(tbl[key])
table.remove(tbl, key)

 

За весь проход по массиву сообщения не повторяются, но когда пять раз произойдет событие, т.е. прошли по массиву, то вылетает:

LUA error: STALKER\gamedata\scripts\den.script:319: bad argument #1 to 'random' (interval is empty)

Не подскажите, в чем я ошибся?

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

proger_Dencheek, ты только всё усложнил.

В целом ход твоих мыслей, лично я понял, но ты не учёл один момент. Вот это:

local arhiv = tbl

не создаёт копию таблицы, а присваивает ссылку на таблицу, т.е. arhiv и tbl это одна и та же таблица.

Так что не изобретай велосипед и используй алгоритм Gun12, он на 101% рабочий.

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

ColR_iT, вообще Artos правильно понял замысел, нужно чтоб во время прохода по массиву, отсылались рандомно все сообщения, и чтоб они не повторялись. Если строки в массиве закончились, начинаем все заново. Скрипт от Gun12 пробовал, там отсылаются все сообщения, но они повторяются.

А если так сделать:

arhiv = {}
for k,v in pairs(tbl) do
 table.insert(arhiv, k, v)
end

, то массив скопируется?

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

proger_Dencheek, как раз таки наоборот. Алгоритм Gun12, не повторяет сообщения, а алгоритм от Artos может на третий раз выдать сообщение которое уже было первым. Это очень легко просматривается в обоих случаях.

На счёт копии - да, так будет копия.

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

ColR_iT, прочти в исходном вопросе #737 про "замысел": "... отсылается рандомное сообщение, но не тоже самое, другое сообщение ... если отправились все строки, все началось по новому кругу".

Т.о. алгоритм предложенный Gun12, имеет недостаток - при новом цикле возможны дубли, т.е. повтор последнего в цикле и первого в новом цикле, от которого избавлен вариант #742.

Второй недостаток - задавать таблицу 'исходных строк' в явном виде внутри функции далеко не всегда удобно или даже не всегда возможно. Если таблица имеет десятки строк да еще длиною в несколько слов... ох и кучеряво будет выглядеть ;-)

P.S. И не путай! Именно в варианте Gun12 возможен дубль по окончании старого цикла и в начале нового, что невозможно в предложенном мною, ни на третий , ни на какой другой раз.

 

proger_Dencheek, тебе даны два рабочих варианта. Если хочешь сделать 'по своему' - не нужно гадать или переусложнять. Да, массив скопируется, но для чего добавлять в таблицу с указанием на какую позицию ставить добавляемый элемент? Чтобы нарваться (теоретически) на ситуацию, когда получишь неиндексированный вариант массива?

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

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

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

Да ничего толком не было сказано об условии задачи. Снова из раздела "Догадайся сам".

Было сказано чтобы сообщения из таблицы не повторялись ("но не тоже самое, другое сообщение"), пока все не закончатся. А потом "все началось по новому кругу".

Ничего о пересечении кругов не говорилось.

Теперь выясняются дополнительные условия. Завтра может быть ещё что-то ...

На данный момент могу предложить альтернативный вариант. Так, для разнообразия

 

local table_messages = {'msg_1', 'msg_2', 'msg_3', 'msg_4', 'msg_5'}
local t_len = #table_messages

function random_message()
   local rnd = math.random(t_len)
   t_len = t_len==1 and #table_messages-1 or t_len-1
   table_messages[#table_messages+1] = table_messages[rnd]
   den.sms(table.remove(table_messages,rnd))
end

 

 

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

Gun12,

Нет смысла в топике по общим вопросам сетовать на отсутствие в вопросах всеобъемлющих условий

;) .

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

Да и зачем зашоривать(ся) на жестком условии? Топик все же не типа "вопрос-ответ", а как обучающий и учиться нужно не только решать жестко очерченную задачу, но и ее вариации... , подгоняя под те или иные критерии.

 

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

 

 

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

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

Ради интереса, можно ли в Lua реализовать такое, к примеру:

local n = 1
n++

 

на подобии С++?

Изменено пользователем Viнt@rь
Ссылка на комментарий

Ты начинаешь путать, реализацию с "помощью языка программирования" и реализацию по "модификации самого языка" (Lua).

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

  • Нравится 1

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

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

Viнt@rь,

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

  • Нравится 1
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

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

Доброго времени суток.

Почитав данную тему, к своему стыду так и не разобралась в одном вопросе.

Мне необходимо из строки вида 12:34 получить те части строки, в которых цифры и преобразовать в числовое значение. С последним все оказалось просто, а вот с первым не очень.

Собственно вопрос: где можно подробно узнать как разобрать строку? И где можно найти информацию о значениях символов в паттернах?

К сожаленью самостоятельно ничего не смогла найти (то ли гугл у меня бракованный, то ли руки не оттуда растут :) ).

 

 

Что-то вы товарищь malandrinus больше сообщения принимать не можете :) Т.ч поблагодарю здесь, надеюсь сильно не накажут. Большое спасибо, буду изучать.

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

userbar368.png

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

Callisto,

здесь по английски

http://www.lua.org/m...nual.html#5.4.1

в русском разделе сайта Lua почему-то остуствует информация о шаблонах, но в сети имеется. К примеру здесь

http://luagml.ucoz.ru/doc/lua/c5.html

 

Задача разделения такой строки может быть решена к примеру так:

s = "12:34"
local a,b = string.match(s, "(%d+)%d+)")
print(a,

 

В строке шаблона:

"%d" - символьный класс, любая цифра

"+" - предыдущий символ 1 и более раза (соответственно, 1 и более непрерывно идущих цифр)

"()" - включение для поиска

":" - просто символ двоеточия

 

Идея с шаблонами в Lua - это примерно тоже самое, что регулярные выражения. Во многом даже синтаксис совпадает, но только упрощён сильно. Можно почитать про регулярные выражения (много где описано), чтобы понять общую идею, потом сравнить с Lua и просто понять, что от них можно там использовать.

  • Нравится 1
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

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

Наверное, сюда все-таки. Ибо торможу. Не понимаю, КАК этот код работает в соответствии с комментариями. У меня наоборот получается. level_weathers.script:

local function is_time_between(t, t1, t2) -- returns true if t1 <= t <= t2 assuming 24 hour clock
return (t1 < t2 and (t >= t1 and t <= t2))
 or (t1 > t2 and (t >= t1 or t <= t2))
end

function WeatherManager:update_times(last_idx) -- update the sliding time window indexes
self.last_time_idx = last_idx
self.next_time_idx = last_idx % #self.trans_times + 1
self.last_time = self.trans_times[self.last_time_idx]
self.next_time = self.trans_times[self.next_time_idx]
end

-- adjust time indexes so that current time is within the window that is defined by these indexes
function WeatherManager:fix_times()
self.next_time_idx = 1
repeat
 self:update_times(self.next_time_idx)
until is_time_between(self.time, self.last_time, self.next_time)
end

То есть, repeat ... until должно выполняться ПОКА время в заданном интервале. Или нет ? Снимите меня кто-нибудь с ручника.

И, кстати, код производит впечатление сильно небезопасного, почему-то.

 

malandrinus, ага, спасибо. Это я просто странного прочитал, оказывается. А паскаль - он как-то мимо меня пролетел весь.

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

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

Dennis_Chikin,

цикл until - это выполнение до тех пор, пока условие не станет истинным. until в переводе - это "до" или "пока не". Эх молодежь, Паскаль уже никто и не помнит =)

 

Вообще модуль погоды у меня вызывает содрогание. Но если в оригинале он ещё был хоть мало-мальски вменяемый, то в Атмосфире его искорёжили совершенно непередаваемым образом.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

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

local function is_time_between(t, t1, t2) -- returns true if t1 <= t <= t2 assuming 24 hour clock
return (t1 < t2 and (t >= t1 and t <= t2))
	 or (t1 > t2 and (t >= t1 or t <= t2))
end

Кстати, во втором случае, когда t1 > t2, данная функция вернёт true, если t лежит за пределами диапазона, а не внутри него.

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

Kirgudu,

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

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

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

Dennis_Chikin,

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

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

 

В этом смысле система погоды в Атмосфире не так уж и плоха. Ну надо определить промежуточные переходы между временными фреймами отдельных погодных циклов, но это само по себе не плохо. Когда всё это работает, то допускает весьма большое разнообразие погоды и немалую гибкость. Есть однако пара скверных моментов в той реализации, что я видел:

1. Переусложнённые, неочевидные и избыточные конфиги. Можно сделать лаконичнее, более понятно и управляемо.

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

 

  • Нравится 1
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

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

Некропостинг на тему удаления значений из массива:

По синтаксису языка, присвоение любой переменной значения nil, отправляет ее (именно эту переменную) на уборку. То бишь, присвоение в цикле этого значения в хоть какой таблице, приведет к удалению этого элемента из нее. Но! Если применить такое к индексированному массиву, то нарушится целостность индексов, которая соблюдается при использовании table.remove(). Так же неправильно будет работать подсчет количества элементов.

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

  • Нравится 2

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

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

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

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

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

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

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

Войти

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

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

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