Open GoogleCodeExporter opened 9 years ago
Напрашивается три разных варианта:
1. "Разбор" даной группы без создания другой:
loop
set u = FirstOfGroup(base)
exitwhen (u == null)
call GroupRemoveUnit(base, u)
// actions
endloop
2. "Перекачка" данной группы во временную и
назад:
loop
set u = FirstOfGroup(base)
exitwhen (u == null)
call GroupRemoveUnit(base, u)
call GroupAddUnit(additional, u)
endloop
loop
set u = FirstOfGroup(additional)
exitwhen (u == null)
call GroupRemoveUnit(additional, u)
call GroupAddUnit(base, u)
// actions
endloop
3. "Копирование" данной группы ForGroup-ом во
временную и циклом уже по ней:
set bj_groupAddGroupDest = additional
call ForGroup(base, function GroupAddGroupEnum)
loop
set u = FirstOfGroup(additional)
exitwhen (u == null)
call GroupRemoveUnit(additional, u)
// actions
endloop
Преимущества и недостатки:
1. "Разбор" - максимальная скорость,
уничтожает группу - наверное, самый
частый вариант
2. "Перекачка" - скорость в 2 раза меньше,
восстанавливает группу - если вдруг группа
будет нужна
3. "Копирование" - скорость в 3 раза меньше, не
изменяет группу - если группа
понадобится внезапно
Предлагаю разный синтаксис:
1. for (unit u; FromGroup(gr)) { /* action */ } //no units in
gr after this
2. for (unit u; InGroup(gr)) { /* action */ } //all units
are back
3. for (unit u; any_expression_return_group) { /* action */ } //fail safe
variant
Original comment by sbratchi...@gmail.com
on 6 Aug 2011 at 12:18
Вот у меня первый вопрос такой - возможно ли
вообще определить, содержит ли
пользовательское действие в себе чистку
группы (с помощью GroupRemoveUnit), или же не
содержит?
Если можно, тогда нужно просто сделать два
варианта обработки, один как адик сказал в
начале, с копированием во вспомогательную
группу. Другой - там где groupremoveunit, чтобы не
было "добавления ради удаления".
Да, еще чистить исходную группу крайне
нежелательно. "Исходные данные портить
нехорошо" - из-за этого получис минус на
контрольной по праку на 1м курсе =)
Например, у меня иногда после одного
использования группы идет другое. Редко, но
бывает. Но никто не знает, насколько часто
это может быть в других картах.
Original comment by evgkoc...@gmail.com
on 6 Aug 2011 at 2:46
В принципе отследить GroupRemoveUnit() можно, хотя
и ненадёжно.
А вот что делать, если GroupRemoveUnit() вызывается
с условием?
По моему мнению чаще всего группа больше не
нужна.
А третий вариант (параноидальный) - на
всякий случай, вдруг какое событие
активизируется и проверит "исходные
данные".
Различать нужна/не нужна группа толком
может только автор кода карты.
Поэтому и предложил три варианта.
Original comment by sbratchi...@gmail.com
on 6 Aug 2011 at 4:56
[deleted comment]
[deleted comment]
> 1. "Разбор" даной группы без создания
другой:
Это самый простой вариант, и да, я
планировал его сделать, но выделить как
либо синтаксисом, т.е. что бы указывать то,
что группа может быть очищена в заголовке
цикла.
> 3. "Копирование" данной группы ForGroup-ом во
временную и циклом уже по ней:
Тут вся фишка в том, что создание новых
потоков в ForGroup и GroupEnum (последнему можно
передать null в качестве фильтра и это не
вызывает утечек в новых патчах вара)
заметно быстрее этих же функции, если они
создают потоки для каждого юнита.
Спасибо ShadowDemon за тесты:
{{{
min max
156.198 163.610
// actions before script runs
set i_temp = 0
// your script here
call GroupEnumUnitsInRange(gr, 0.0, 0.0, 2000.0, null)
loop
set u = FirstOfGroup(gr)
exitwhen (u == null)
call GroupRemoveUnit(gr, u)
call GroupAddUnit(gr2, u)
set i_temp = i_temp + 1
endloop
loop
set u = FirstOfGroup(gr2)
exitwhen (u == null)
call GroupRemoveUnit(gr2, u)
call GroupAddUnit(gr, u)
endloop
//===========================
min max
147.114 150.468
function CALLBACK takes nothing returns nothing
set u_temp = GetEnumUnit()
set i_temp = i_temp + 1
endfunction
// actions before script runs
set i_temp = 0
call GroupEnumUnitsInRange(gr, 0.0, 0.0, 2000.0, null)
// your script here
call ForGroup(gr, function CALLBACK)
}}}
Ну не быстрее, но не медленнее) Одним словом
если изначально пройдемся ForGroup для
копирования - потеряем все быстродействие.
Есть еще вариант сделать ход конем - а
именно расшарить статические переменные (я
о них еще не говорил? static int i = 0 - пистаь
внутри функции) что бы они работали внутри
lambda функций - и не делать фор для группы
вообще.
> Вот у меня первый вопрос такой - возможно
ли вообще определить, содержит ли
пользовательское действие в себе чистку
группы (с помощью GroupRemoveUnit), или же не
содержит?
Есть сложности, например, я, если
передается группа и это функция - генерирую
переменную и пишу ее туда, иначе использую
передаваемую переменную. Так вот, если есть
некая функция, которая возвращает группу, и
она передается для фора - а в его теле
удаляется юнит, и в качестве группы - та же
функция - я не смогу узнать, какую группу
она вернет.
Да, трогать группу не охота, но что
поделать? Короче пока думаем, я работаю над
другими фишками.
Original comment by adi...@gmail.com
on 6 Aug 2011 at 5:15
GroupEnum... здесь ни при чём, поскольку
разбираем случай, когда группа уже есть.
В тех вариантах, когда группа создаётся
GroupEnum-ом, имеем право её "разобрать".
Именно различный синтаксис я и предлагаю,
как показано выше.
Самый медленный вариант failsafe.
Если автор укажет как ускорить - молодец.
Original comment by sbratchi...@gmail.com
on 6 Aug 2011 at 5:33
Я не гонюсь за быстродействием, и мне нужен
всего лишь цикл для групп. Неважно, что он в
2 раза медленнее на каком-то очень узком
подмножестве задач. Так что мне кажется,
что нужно просто реализовать самый простой
вариант, где используются две группы (и
который не запарывает исходную группу).
Потом в последующих релизах можно
оптимизировать сколько влезет.
Original comment by evgkoc...@gmail.com
on 7 Aug 2011 at 6:50
> Потом в последующих релизах можно
оптимизировать сколько влезет.
Иногда из-за кривого базового дизайна
потом что то оптимизануть может быть
невозможно.
Ну в целом я согласен, можно сделать
базовый "стабильный" вариант, и написать
большими и красными буквами, что он
медленный, но безопасный. И все равно, я
пока не вижу "правильного" синтаксиса,
например это:
1. for (unit u; FromGroup(gr)) { /* action */ } //no units in
gr after this
2. for (unit u; InGroup(gr)) { /* action */ } //all units
are back
3. for (unit u; any_expression_return_group) { /* action */ } //fail safe
variant
Будет приводить к путанице.
Original comment by adi...@gmail.com
on 7 Aug 2011 at 7:46
Как насчет forg(unit u; g)
Original comment by evgkoc...@gmail.com
on 7 Aug 2011 at 9:07
> Как насчет forg(unit u; g)
Точно нет, т.к. не наглядно. Вот если взять
фор (не тот что по юнитам, вообще), он
читается как "для каждого Х, который
удовлетворяет условиям У", т.е. for (unit u;
UnitIn***()) - куда логичнее, и опять же потом
можно сделать новый вариант перебора, не
ломая логику старого.
Original comment by adi...@gmail.com
on 8 Aug 2011 at 10:47
Есть еще идея место временной группы
складывать юнитов в массив, что то вроде
стека - будет быстрее... при расчете, что 8190
юнитов должно хватить всем.
Original comment by adi...@gmail.com
on 8 Aug 2011 at 12:26
Один универсальный самый лучший вариант
всё равно не существует.
Если группа больше не нужна, глупо тратить
ресурсы на её восстановление.
Если группа будет ещё нужна, её
восстановление необходимо.
Это уже два принципиально разных варианта.
Третий параноидальный не настаиваю.
Массив сгладит разницу, но принципиально
не уберёт.
Хочешь сделать качественно и
оптимизированно - делай разные варианты.
Original comment by sbratchi...@gmail.com
on 8 Aug 2011 at 2:18
Да, согласен. Тогда по синтаксису у нас
выходит:
for (unit u; UnitsInGroup(...)) {} - копируем юнитов из
основной во временную через ForGroup(), и далее
берем из временной.
for (unit u; UnitsInGroup(...); GroupRemovePickedUnit()) {} - Просто
цикл по основной группе, GroupRemovePickedUnit() -
некая псевдофункция, просто указывает
парсеру тип перебора. Почему не GroupRemoveUnit(g, u)
? Тут есть сложность, например проверить в
таком случае юнита можно, а группу сложно -
for (unit u; UnitsInGroup(GetGroup()); GroupRemoveUnit(GetGroup(), u) {} -
где group GetGroup () {return myGroup[GetRandomInt(0, 255)]} - думая
суть ясна. Вопрос только, как назвать эту
псевдофункцию? GroupRemovePickedUnit() - первое, что
пришло на ум.
Original comment by adi...@gmail.com
on 9 Aug 2011 at 6:51
А чем тебе
for (unit u; UnitsFromGroup(g)) {}
for (unit u; UnitsInGroup(g)) {}
for (unit u; (g)) {}
не нравится? Главное - только одна ";". Две
для нормального фора.
Кстати нужен способ цепляние строк внутри
фора:
for (unit u=FirstOfGroup(g); not(g==null);
(GroupRemoveUnit(g,u);u=FirstOfGroup(g)) ) {}
Original comment by sbratchi...@gmail.com
on 9 Aug 2011 at 2:05
> не нравится?
Возможной путаницей. Читается фор так:
Для каждого юнита У, удовлетворяющего
условие - ЮнитвВГруппе(Г), применить
дейтсвие.
В си в обычном форе есть также в скобочках
дополнительный аргумент, что надо сделать
потом, вот туда мы и суем это. Одним словом я
считаю это решение правильным, и уже
реализовал его)
> for (unit u=FirstOfGroup(g); not(g==null);
(GroupRemoveUnit(g,u);u=FirstOfGroup(g)) ) {}
Сомнительно.
Итого, реализовал пока так:
for (unit u; UnitsInGroup(expr)) {}
for (unit u; UnitsInGroup(expr); GroupRemovePickedUnit()) {}
Имя последней можно заменить. Ну что,
эпичный был баг, но думаю можно скоро крыть
его)
Всем спасибо за идеи и моральную поддержку.
Original comment by adi...@gmail.com
on 9 Aug 2011 at 7:12
Хозяин-барин, конечно.
Я предполагал, что for с двумя ";" можно
раскладывать в цикл loop практически без
разбора, а с одной ";" использовать для
групповых операций.
for (unit u; UnitsInGroup(expr); GroupRemovePickedUnit()) {} - пол
текста - названия псевдофункций. Много.
В си в обычном форе при необходимости
уместить две операции можно использовать
запятую.
Тут запятой нет, поэтому я предложил такой
синтаксис:
for ( (int x=0;unit u) ; (u=ar[x];(not u==null)) ; (ar[x]=null;x++) ) {}
В заголовке фора точки с запятой делят
"аргументы". Каждый "аргумент" в скобках
может быть поделен другими точками с
запятыми на несколько частей. Последняя
часть второго "аргумента" является
условием.
Не хочешь - я настаивать не буду. Просто
может быть полезным.
Original comment by sbratchi...@gmail.com
on 10 Aug 2011 at 2:12
Original issue reported on code.google.com by
adi...@gmail.com
on 6 Aug 2011 at 10:22