XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Ответ
 
Anufis

offline
Опыт: 6,290
Активность:
Оптимизация перебора типа юнитов
Есть способы как-нибудь этот перебор по-человечески сделать(через БД какую-нибудь или еще как)?

Код:
nothing MobStartAI(unit u,code AICode,real time) {
    timer t=CreateTimer()
    integer id=GetHandleId(u)
    SaveReal(udg_h,id,139,udg_time)
    SaveTimerHandle(udg_h,id,55,t)
    SaveUnitHandle(udg_h,GetHandleId(t),1,u)
    TimerStart(t,time,true,AICode)
    t=null
}

nothing AI(unit u) {
  integer id=GetUnitTypeId(u)
  if id=='h053' then //вурдалонище
    MobStartAI(u,function AIVurdalonishe,1.)
    return
  elseif id=='h055' then //большой папенькин сынок
    MobStartAI(u,function AIBigDaddySon,1.)
    return
  elseif id=='h056' then //поганище
    MobStartAI(u,function AIPoganishe,1.)
    return
  elseif id=='h054' || id=='h04Q' then //унылое поганище,скелет-отморозок
    MobStartAI(u,function AIIceSkeleton,1.)
    return
  elseif id=='h00L' then //Мясник
    MobStartAI(u,function AIButcher,1.)
    return
  elseif id=='h00E' || id=='h057' || id=='h05A' || id=='h05I' || id=='h00E' || id=='h05W' then //Зомби,зомбопес,папенькин сынок,заряженный сынок,зомби,вурдалак
    MobStartAI(u,function AISkeleton2,1.)
    return
  elseif id=='h06P' || id=='h08L' || id=='h08S' || id=='h007' || id=='h00B' || id=='h04N' then //инфернал,энт,тень,скелет,крепкий скелет,гигантский скелет
    MobStartAI(u,function AISkeleton2,1.)
    return
  elseif id=='h0AF' //ранкор
    MobStartAI(u,function AISkeleton4,1.)
    return
  elseif id=='h0B3'  || id=='h0BH' then //робот со свалки,кобольд-работник
    MobStartAI(u,function AISkeleton2,1.)
    return
  elseif id=='h05S' then //веселый сундучок
    MobStartAI(u,function AIFunnyChest,1.)
    return
  elseif id=='h05T' then //проклятое сокровище
    MobStartAI(u,function AICursedTreasure,1.)
    return
  elseif id=='h05U' then //скелет-рыцарь
    MobStartAI(u,function AISkeletonKnight,1.)
    return
  elseif id=='h05V' then //пехотинец
    MobStartAI(u,function AIFootman,1.)
    return
  elseif id=='h00N' then //некромант
    MobStartAI(u,function AINecromancer,0.99)
    return
  elseif id=='h02T' || id=='h06L' then //огненный элементаль
    MobStartAI(u,function AIFireElemental,1.)
    return
  elseif id=='h02V' || id=='h06M' then //рдд огненный элементаль
    MobStartAI(u,function AIFireElementalRanged,1.)
    return
  elseif id=='h04R' then //скелет-блокиратор
    MobStartAI(u,function AISkeleton2,1.)
    return
  elseif id=='h06B' then //банши
    MobStartAI(u,function AIBanshee,1.)
    return
  elseif id=='h06O' then //злой кровожад
    MobStartAI(u,function AIBloodWanter2,1.)
    return
  elseif id=='h00P' then //кровожад
    MobStartAI(u,function AIBloodWanter,1.)
    return
  elseif id=='h06Q' then //брутальный демон
    MobStartAI(u,function AIBrutalDemon,1.)
    return
  elseif id=='h04Q' then //скелет-отморозок
    MobStartAI(u,function AIIceSkeleton,1.)
    return
  elseif id=='h00O' then //адская гончая
    MobStartAI(u,function AIHellHound,1.5)
    return
  elseif id=='h07B' then //суккуб
    MobStartAI(u,function AISuccubus,1.)
    return
  elseif id=='h07C' then //пустынник
    MobStartAI(u,function AIHermit,1.)
    return
  elseif id=='h07D' then //машина смерти
    MobStartAI(u,function AIMachineOfDeath,1.)
    return
  elseif id=='h07E' then //разрушитель
    MobStartAI(u,function AIDestroyer,1.)
    return
  elseif id=='h06N' then//адский зверь
    MobStartAI(u,function AISkeleton4,1.)
    return
  elseif id=='h080' || id=='h081' then//дух воды, малый дух воды
    MobStartAI(u,function AIWaterElemental,1.)
    return
  elseif id=='h082' then//огр-воитель
    MobStartAI(u,function AIOgreWarrior,1.)
    return
  elseif id=='h083' then//огр-маг
    MobStartAI(u,function AIOgreMage,1.)
    return
  elseif id=='h08J' then//пантера
    MobStartAI(u,function AIPanther,1.)
    return
  elseif id=='h091' then//дварф-стрелок
    MobStartAI(u,function AIDwarfSniper,1.)
    return
  elseif id=='h098' then//дварф-громила
    MobStartAI(u,function AIDwarf,1.)
    return
  elseif id=='h096' then//малая кислотная радость
    MobStartAI(u,function AISmallPoisonHappiness,1.)
    return
  elseif id=='h097' then//большая кислотная радость
    MobStartAI(u,function AIBigPoisonHappiness,1.)
    return
  elseif id=='h09B' then//пушка
    MobStartAI(u,function AICannon14,1.)
    return
  elseif id=='h01A' then//лошадка
    MobStartAI(u,function AIHorse,1.)
    return
  elseif id=='h0AI' then//нурглинг
    MobStartAI(u,function AINurgling,1.)
    return
  elseif id=='h0AH' then//штопаный кабан
    MobStartAI(u,function AITatteredBoar,1.)
    return
  elseif id=='h0AG' then//большой ранкор
    MobStartAI(u,function AIBigRankor,1.)
    return
  elseif id=='h0AJ' then//мегапод
    MobStartAI(u,function AIMegapod,1.)
    return
  elseif id=='h02E' then//гигантский сгусток крови
    MobStartAI(u,function AI_L15_BigBloodMass,1.)
    return
  elseif id=='h02J' then//странный труп
    MobStartAI(u,function AIDeadman,2.)
    return
  elseif id=='H06R' then//булсбум
    MobStartAI(u,function AIBossL2,1.)
    return
  elseif id=='h0BI' then//наездник на крысе
    MobStartAI(u,function AIKoboldRider,1.)
    return
  endif
}
Старый 09.05.2014, 11:56
DioD

offline
Опыт: 45,134
Активность:
хеш таблица же.
еще можно сказать ассоциативный массив.
или нет, можно сказать бинарный свичкейс.
даю подсказку 'ABCD' это число, которые попадает в границы 32 бита.
Старый 09.05.2014, 14:09
nvc123
new status
offline
Опыт: 59,284
Активность:
боже спаси мои глаза
nvc123 добавил:
кстати
адик точно попадёт в ад
Старый 09.05.2014, 14:24
Anufis

offline
Опыт: 6,290
Активность:
Цитата:
Сообщение от DioD
хеш таблица же.

Проблема в том, что я не осведомлен, как code сохранять в хеш-таблицу и вижу тут 2 варианта
1. потестить через triggeraction
2. иметь ассоциативный массив для строк названий функций и их потом исполнять(но тут надо будет учесть, чтобы оптимизитор не портил имена этих функций)
В общем сделаю через 2 вариант.
Старый 09.05.2014, 14:26
nvc123
new status
offline
Опыт: 59,284
Активность:
Anufis,сама структура кода не правильна у тебя
вместо кучи функций лучше сделать 1 но с разными данными(то есть просто передаём индекс параллельных массивов)
Старый 09.05.2014, 14:49
quq_CCCP
Я белый и пушистый!
offline
Опыт: 93,279
Активность:
Anufis:
Проблема в том, что я не осведомлен, как code сохранять в хеш-таблицу и вижу тут 2 варианта
Юзай SaveStr и ExecuteFunc + глобальные переменные...
Старый 09.05.2014, 15:06
DioD

offline
Опыт: 45,134
Активность:
я тут сделал данную конструкцию но для себя и на яве, вот код:
	static public int[] Key2Value = new int[256];
	public static void Initialize()
	{
		Arrays.fill(Key2Value, 1488);
		Key2Value['0'] = 0;
		Key2Value['1'] = 1;
		Key2Value['2'] = 2;
		Key2Value['3'] = 3;
		Key2Value['4'] = 4;
		Key2Value['5'] = 5;
		Key2Value['6'] = 6;
		Key2Value['7'] = 7;
		Key2Value['8'] = 8;
		Key2Value['9'] = 9;
		Key2Value['m'] = 60;
		Key2Value['h'] = 3600;
		Key2Value['d'] = 86400;
	}
	
	public static long ProcessDelay(String Input)
	{
		byte[] RawData = Input.getBytes();
		
		int buffer   = 0;
		int brate    = 1;
		int multiply = 0;
		int result   = 0;
		int temp     = 0;
		int step     = RawData.length-1;
		
		
		for(;;)
		{
			temp = Key2Value[RawData[step]];
			
			if (temp == 1488) return -1;
			
			if (temp > 10)
			{
				if (multiply != 0)
				{
					result+= buffer * multiply;
				}
				multiply = temp;
				buffer = 0;
				brate = 1;
			}
			else
			{
				buffer+= temp * brate;
				brate*= 10;
			}
			
			step--;
			
			if (step == -1)
			{
				result+= buffer * multiply;
				return result;
			}
		}
	}
	
	static public void main(String[] args) throws Throwable {
		Initialize();
		System.out.println(ProcessDelay("1m1h1d"));
Тоже самое что у вас, один в один.
Старый 10.05.2014, 12:23
adic3x

offline
Опыт: 108,439
Активность:
Я знаю как оптимизировать: убрать все return.
Старый 10.05.2014, 21:19
ScorpioT1000
Работаем
online
Опыт: отключен
есть три вида преобразования множества значений (маппинг):
  1. сквозное. это самый идеальный вариант - когда из исходного значения можно получить конечное с помощью математической функции, не затрагивая остальные значения
  2. база данных. когда по исходному значению мы обращаемся к ячейке с доп. информацией по конечному значению
  3. брут форс - полный перебор, самый дерьмовый способ, хорош только когда у вас совсем мало записей и некогда это разгребать. это то, что у тебя сейчас
Старый 11.05.2014, 01:22
Anufis

offline
Опыт: 6,290
Активность:
Вопрос собственно в том, как это реализовать через ассоциативный массив.
Проблемы:
code array запрещены, в хеш-таблицу code не сохраняется, хранить массив строк и экзекутить функции через ExecuteFunc не хочется, потому что мне кажется, что оптимизатор покорежит названия этих функций(скажем вместо моих AI1,AI2,AI3,AI4, ... AI100 будет что-то другое и ExecuteFunc просто не найдет нужных функций).

И есть еще нормальный вариант - это 1 функция, которая просто для типа юнита из хеш-таблицы будет брать набор команд, скажем
1. атаковать ближайшего врага в радиусе 1200
2. применить приказ absorb на случайного врага в радиусе 600
иначе попытаться перейти к ближайшему противнику в радиусе 3000
Юнитов в карте не будет больше 60 одновременно, периодичность таймера - 1 секунда. Так что в принципе это не должно дать сильного удара по производительности.

Anufis добавил:
Впринципе, то, что я наваял сейчас, и решает все проблемы.
Код:
library AIUniversal initializer Init uses AIFunc

//AIStart(footman)

private hashtable HH
//привязка по типу юнита
//0-количество приказов
//1-периодичность
//100+i - тип цели (инт)
/*
  1 - ближайший враг
  2 - случайный враг
  3 - самый дальний враг
  4 - случайный союзник
*/
//200+i - радиус (реал)
//300+i - приказ (строка)
//400+i - тип цели для приказа
/*
  1 - виджет
  2 - без цели
  3 - точка
*/

nothing AddAICommand(integer utyp,integer index,integer ttype,real radius,string order,integer ordertype) {
  SaveInteger(HH,utyp,100+index,ttype)
  SaveReal(HH,utyp,200+index,radius)
  SaveStr(HH,utyp,300+index,order)
  SaveInteger(HH,utyp,400+index,ordertype)
  if LoadInteger(HH,utyp,0)<index then
    SaveInteger(HH,utyp,0,index)
  endif
}

boolean AIUniversalOrder(unit u,integer typ,real radius,string order,integer ordertype) {
  unit target=null
  if typ==1 then
    target=AIFindNearestTarget(u,radius)
  elseif typ==2 then
    target=AIFindRandomTarget(u,radius)
  elseif typ==3 then
    target=AIFindFurthestTarget(u,radius)
  elseif typ==4 then
    target=null//AIFindRandomAlly(u,radius)
  endif
  if target!=null then
    if ordertype==1 then
      IssueTargetOrder(u,order,target)
    elseif ordertype==2 then
      IssueImmediateOrder(u,order)
    else
      IssuePointOrder(u,order,GetWidgetX(target),GetWidgetY(target))
    endif
    return true
  endif
  return false
}

nothing AIUniversal() {
    timer t=GetExpiredTimer()
    integer tid=GetHandleId(t)
    unit u=LoadUnitHandle(udg_h,tid,1)
    integer i=1
    integer typ=GetUnitTypeId(u)
    integer n=LoadInteger(HH,typ,0)
    boolean result=false
    if GetWidgetLife(u)<=0. then
      FlushChildHashtable(udg_h,tid)
      DestroyTimer(t)
    else
      loop
        exitwhen i<n
        result=result || AIUniversalOrder(u,LoadInteger(HH,typ,100+i),LoadReal(HH,typ,200+i),LoadStr(HH,t  yp,300+i),LoadInteger(HH,typ,400+i))
        i++
      endloop
      if not result then
        AIUniversalOrder(u,LoadInteger(HH,typ,100+n),LoadReal(HH,typ,200+n),LoadStr(HH,t  yp,300+n),LoadInteger(HH,typ,400+n))
      endif
    endif
    t=null
    u=null
}

nothing AIStart(unit u) {
    timer t=CreateTimer()
    integer id=GetHandleId(u)
    real time=LoadReal(HH,GetUnitTypeId(u),1)
    if time==0. then
      time=1.
    endif
    SaveReal(udg_h,id,139,udg_time)
    SaveTimerHandle(udg_h,id,55,t)
    SaveUnitHandle(udg_h,GetHandleId(t),1,u)
    TimerStart(t,time,true,function AIUniversal)
    t=null
}

nothing AIStop(unit u) {
    integer id=GetHandleId(u)
    timer t=LoadTimerHandle(udg_h,id,55)
    FlushChildHashtable(udg_h,GetHandleId(t))
    DestroyTimer(t)
    RemoveSavedHandle(udg_h,id,55)
    t=null
}

nothing AIUniversalAI1() {
  AddAICommand('hfoo',1,1,1200.,"attack",1)
  AddAICommand('hfoo',2,1,6000.,"move",3)
}

private nothing Init() {
  HH=InitHashtable()
  ExecuteFunc("AIUniversalAI1")
}

endlibrary

Отредактировано Anufis, 11.05.2014 в 15:20.
Старый 11.05.2014, 15:14
quq_CCCP
Я белый и пушистый!
offline
Опыт: 93,279
Активность:
Anufis:
оптимизатор покорежит названия этих функций
Не порежит, во первых в твиках есть настройки что нужно исключить при оптимизации... во вторых оптимизатор не трогает названия функций вроде a b c в ax bx cy и тп, просто пропуская их, а назвать функции так же как оптимизатор тебе ничего не мешает...
Старый 11.05.2014, 15:43
DioD

offline
Опыт: 45,134
Активность:
потому что мне кажется
креститься пора!
"мне кажется что если кинуть яблок вверх оно не упадёт"
а ты кидал яблоко
"нет не кидал, ведь оно не упадёт и я останусь без яблока"
ты дебил?
"репор штраф ты меня троллишь"
Старый 11.05.2014, 19:18
adic3x

offline
Опыт: 108,439
Активность:
потому что мне кажется, что оптимизатор покорежит названия этих функций
Меняются название только у public и private, без этих префиксов не меняются. Более того, я в свое время просто переводит равкод в строку и делал ExecuteFunc ("s"+I2S(GetSpellAbilityId()));.
1 - ближайший враг
2 - случайный враг
3 - самый дальний враг
4 - случайный союзник
Избегайте неявные идентификаторы. Используйте enum в cJass и константы в vJass.
Старый 11.05.2014, 21:57
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 02:43.