Пример создания циклов с помощью DYNAMIC.
Хочу поделиться секретом, как делать удобные циклы.
В какой-нибудь локации которая инициализируется в начале прописываем нужные варианты циклов как динамический код:
Например, простой цикл по i и двойной по y и x.
$FOR_i={
i = args[0]
:labelloop_i
if i <= args[1]:
dynamic $args[3]
i+=args[2]
jump 'labelloop_i'
end
}
$FOR_xy={
y = args[0]
:labelloopxy_y
if y <= args[1]:
x = args[3]
:labelloopxy_x
if x <= args[4]:
dynamic $args[6]
x+=args[5]
jump 'labelloopxy_x'
end
y+=args[2]
jump 'labelloopxy_y'
end
}
Для простого цикла аргументы: начальное значение i, конечное значение i(включительно), шаг приращения i, код
Используем простой цикл по i:
dynamic $FOR_i, 0, 9, 1, _
{
*pl i
}
Используем вложенный цикл:
dynamic $FOR_xy, 0, 10, 2, 0, 5, 1, _
{
*pl "(<<x>>,<<y>>)"
}
Либо, если нужны еще какие-то действия в конце внутренего цикла - то используем два простых цикла по X и Y:
dynamic $FOR_y, 0, 9, 1, _
{
dynamic $FOR_x, 0, 9, 1, _
{
*p "(<<x>>,<<y>>)"
}
*pl
}
Все очень просто. Становится похоже на С++.
Но есть недостаток - из не сделать jump наружу, тоесть не прервать цикл раньше времени.
Рискну предложить некоторое усовершенствование первого (простого) варианта:
$FOR_i = {
i = args[0]
step = 1
if ARGS[2]: step = ARGS[2]
:labelloop_i
if (i <= ARGS[1] and step > 0) or (i >= ARGS[1] and step < 0):
dynamic $args[3]
i += step
jump 'labelloop_i'
end
}
Не пойму, зачем вы суёте в переменные код, который можно тиснуть на отдельной локации и вызывать через gosub.
Aleks Versus:
Не пойму, зачем вы суёте в переменные код, который можно тиснуть на отдельной локации и вызывать через gosub.
По тому что использовать локацию не так удобно. Текст локации будет плохо читаться из-за if elseif.
Это примерно как на обычном языке программирования испрользовать вообще одну функцию для всего, а внутри напихать кучу всяких условий. Так делать можно, но это будет говнокодом.
По тому что dynamic гибче, agrs[] для него свои собственные, а не единые на всю локацию.
По тому что динамический код можно написать не в отдельной локации, а по ходу выполнения другого кода.
По тому что dynamic внутри dynamic нормально работать будет, а через локации - не уверен.
Переместил обсуждение в отдельную тему.
Axil:
По тому что использовать локацию не так удобно. Текст локации будет плохо читаться из-за if elseif…
Не понимаю.
Axil:
По тому что dynamic гибче, agrs[] для него свои собственные, а не единые на всю локацию.
Не понимаю.
Axil:
По тому что динамический код можно написать не в отдельной локации, а по ходу выполнения другого кода.
Да, но ты говоришь:
Axil:
В какой-нибудь локации которая инициализируется в начале прописываем нужные варианты циклов
И ещё
Axil:
dynamic внутри dynamic нормально работать будет, а через локации - не уверен.
Для этого конкретного кода всё будет работать.
У меня возникло чувство, что мы по-разному понимаем локации.
Кажется я понял что ты не понимаешь. Ты предагаешь каждую функцию, каждый цикл с данном случае, запихнуть в отдельную локацию? Я же думал о другом варианте - локация одна, но в ней разные функции, которые разделены условиями по первому аргументу. Тоесть:
GS ‘functions’, ‘FOR_i’, 0, 9, 0
GS ‘functions’, ‘FOR_x’, 0, 9, 0
А в локации functions:
if $args[0] = ‘FOR_i’:
* * *
elseif $args[0] = ‘FOR_x’:
* * *
end
И это было-бы действительно нечитаемо и неудобно.
Но ты кажется предлогаешь делать под каждую функцию свою локацию? Так и количества локаций может не хватить и искать их неудобно. Я понимаю что физически это все один файл, но все равно воспринимаю каждую локацию как отдельный файл, ну привык думать как для обычных языков программирования.
Тут как и везде должна быть золотая середина. Все в одной локации это одна крайность. Сотни локаций под одну функию - это другая крайность. А вот завести одну локацию под часто повторяющийся динамический код - это и есть середина.
Axil,
а вон в чём дело. Забить ВСЕ циклы в переменные. Извиняюсь, неверно прочитал техническое задание. Я почему-то подумал об универсальном цикле, который потом можно использовать в любом месте игры. А ты предлагаешь просто разгрузить от повторения одинаковых по структуре циклов. Об универсальном речи не шло. Лады, согласен, способ удобный.
Теперь по коду. Не проще ли так?:
$for_i={args[0] = args[0]
:labelloop_i
if args[0] <= args[1]:
dynamic $args[3],args[0],args[1],args[2]
args[0]+=args[2]
jump 'labelloop_i'
end}
Вызов:
dynamic $for_i,0,9,1,{
*pl args[0]
}
Кстати по прерыванию цикла. Выполнение динамического кода прекрасно прерывается командой exit.
Пример:
$forONE={args[9] = args[9] & ! чтоб не потерять аргументы
:labelloop_i
if args[0] <= args[1]:
$args['result']=$dyneval($args[3],args[0],args[1],args[2])
if $args['result']='exit': $result=$args['result'] & exit
args[0]+=args[2]
jump 'labelloop_i'
end}
вызов:
dynamic $forONE,0,9,1,'if args[0]=5: $result="exit" else *pl args[0]'
Если фантазия позволяет, при использовании $dyneval при вызове цикла можно заставить его прыгать и на метку, и на локацию.
Жаль, что мне не хватило времени довести новую версию до релиза - там уже почти готовы нормальные циклы и локальные переменные.
Вот, кажется, у меня получился универсальный цикл.
Вызов процедуры:
dynamic $FOR, 'название переменной-счетчика', начальное значение счетчика, конечное значение счетчика, шаг,{
операторы в теле цикла
}
Цикл for-next
$FOR = {
dynamic '<<$ARGS[0]>> = <<ARGS[1]>>
:labelloop_<<$ARGS[0]>>
if (<<$ARGS[0]>> <= <<ARGS[2]>> and <<ARGS[3]>> > 0) or (<<$ARGS[0]>> >= <<ARGS[2]>> and <<ARGS[3]>> < 0):
<<$ARGS[4]>>
<<$ARGS[0]>> += <<ARGS[3]>>
jump "labelloop_<<$ARGS[0]>>"
end
<<$ARGS[0]>> -= <<ARGS[3]>>'
}
Поддерживается вложенность.
Пример использования:
dynamic $FOR, 'i', 0, 10, 1, {
*nl i
}
Вложенные циклы:
dynamic $FOR, 'i', 5, 10, 1, {
dynamic $FOR, 'j', 9, 2, -3, {
*nl '<<i>> <<j>>'
}
}
Можно использовать и в виде отдельной локации и вызывать через gs. Это дело вкуса.
Не исключаю возможные грабли. Было бы хорошо, если бы Nex прокомментировал.
evp,
мне хватает обычных циклов, без DYNAMIC.
А в следующей версии QSP циклы будут встроены. Так что не вижу особой необходимости что-то изобретать.
Мне не пригодится, но, может быть, кому-то другому это будет полезно.
Если бы была известна дата выхода новой версии, то изобретать не было бы необходимости.
Nex, я , вообще-то, хотел от вас услышать комментарии по ограничениям этого способа. Например, какой уровень вложенности dynamic и, соответственно, вложенных циклов допустим?
я , вообще-то, хотел от вас услышать комментарии по ограничениям этого способа
Так бы сразу и спросил :)
evp,
Максимальная вложенность выражений: 30
Впрочем, если содержимое фигурных скобок рассматривается как особая символьная строка (что вполне вероятно), то ограничение вложенности не должно действовать. Я так не вспомню, это нужно смотреть в исходниках интерпретатора, либо спрашивать у Байта.