Объявления

Друзья, если не получается зарегистрироваться, напишите на почту vdv_forever@bk.ru.
Я оторву свою задницу от всех дел и обязательно Вас активирую! :smile10:
Добро пожаловать на геройский форум! :smile25:

Улучшение ИИ

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2184 раз.

Re: Улучшение ИИ

Сообщение AlexSpl » 08 май 2020, 14:10

Возможно. Но я не встречал код, который бы использовал старое значение ST0. Обычно блок FPU-инструкций начинается с fld/fild. А аргументы (float и double), как и положено, передаются через стек.

Вот эту функцию неплохо бы разобрать:

Код: Выделить всё
int __userpurge sub_00423C80@<eax>(int a1@<ecx>, double a2@<st0>, int a3, _Hero_ *DHero, _Hero_ *AHero)
{
  int v5; // ebx
  signed int v7; // edi
  int v8; // esi
  int v9; // ecx
  int v10; // [esp+Ch] [ebp+8h]

  v5 = a1;
  if ( !*(_DWORD *)(a1 + 64) )
    return 0;
  v7 = *(_DWORD *)(a3 + 12);
  if ( v7 > 5 )
    v7 = 5;
  v8 = SpellTable_Offset->AIValue[*(_DWORD *)(a3 + 4) + 34 * *(_DWORD *)a3];
  CalcSpellDamagePercentage(*(_DWORD *)a3, *(_DWORD *)(a1 + 4), DHero, AHero);
  __asm { fstp    [ebp+AHero]; Store Real and Pop }
  v10 = *(_DWORD *)(v5 + 64) * v7 * v8;
  __asm
  {
    fild    [ebp+arg_0]; Load Integer
    fstp    [ebp+arg_0]; Store Real and Pop
    fld     [ebp+arg_0]; Load Real
    fmul    [ebp+AHero]; Multiply Real
    fdiv    ds:dbl_0063AC30; Divide Real
  }
  return _ftol(v9);
}

А именно интересно, что и откуда попадает в [ebp+AHero] после выполнения __asm { fstp [ebp+AHero]; }?

Я бы предположил, что CalcSpellDamagePercentage() возвращает совсем не __int16, а float или double, но нужна проверка :smile1:

* * *
А вот уже нормальная декомпиляция с чистой базы:
Код: Выделить всё
int __thiscall sub_423C80(_DWORD *this, _DWORD *a2, int a3, int a4)
{
  _DWORD *v4; // ebx
  signed __int64 v5; // rax
  signed int v6; // edi
  int v7; // esi
  int v8; // edx
  float v10; // [esp+Ch] [ebp+8h]
  float v11; // [esp+14h] [ebp+10h]

  v4 = this;
  if ( this[16] )
  {
    v6 = a2[3];
    if ( v6 > 5 )
      v6 = 5;
    v7 = *((_DWORD *)off_687FA8 + a2[1] + 34 * *a2 + 26);
    v8 = this[1];
    v11 = sub_44A1A0(a3, a4);
    v10 = (double)(v4[16] * v6 * v7);
    v5 = (signed __int64)(v10 * v11 / 500.0);
  }
  else
  {
    LODWORD(v5) = 0;
  }
  return v5;
}
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

Re: Улучшение ИИ

Сообщение Ben80 » 08 май 2020, 14:50

У Игрика (при использовании названия функции из работы Сава) это выглядит так:

Код: Выделить всё
//----- (00423C80) --------------------------------------------------------
int __userpurge AI_CalcBattleStack_GetCastSpellValue@<dx:ax>(int mon_id@<ecx>, int spell, _Hero_ *heroD, _Hero_ *heroA)
{
  int v4; // ebx
  double result; // rax
  int v6; // edi
  int v7; // esi
  float a2b; // [esp+Ch] [ebp+8h]
  float chance; // [esp+14h] [ebp+10h]

  v4 = mon_id;
  if ( *(_DWORD *)(mon_id + 64) )
  {
    v6 = *(_DWORD *)(spell + 12);
    if ( v6 > 5 )
      v6 = 5;
    v7 = o_Spell->AIValue[*(_DWORD *)(spell + 4) + 34 * *(_DWORD *)spell];
    chance = GetSpell_ToCreatureChance(*(_DWORD *)spell, *(_DWORD *)(mon_id + 4), heroD, heroA);
    a2b = (long double)(*(_DWORD *)(v4 + 64) * v6 * v7);
    *(_QWORD *)&result = (signed __int64)(a2b * chance / 500.0);
  }
  else
  {
    LODWORD(result) = 0;
  }
  return result;
}
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2184 раз.

Re: Улучшение ИИ

Сообщение AlexSpl » 08 май 2020, 14:54

Я бы повыкидывал все long double, (signed) __int64, rax и т.п. вещи, нехарактерные для 32-битного компилятора VC++. Очевидно же, что в оригинальном коде и близко их не было.

А возвращает функция int в регистре eax.

Я думаю, что

Код: Выделить всё
int __userpurge AI_CalcBattleStack_GetCastSpellValue@<dx:ax>(int mon_id@<ecx>, int spell, _Hero_ *heroD, _Hero_ *heroA)

в оригинале есть

Код: Выделить всё
int __fastcall AI_CalcBattleStack_GetCastSpellValue(int mon_id, int spell, _Hero_* heroD, _Hero_* heroA)

И вообще, скептически отношусь к __userpurge :smile1:

Я думаю, декомпилятор смущает тот факт, что __ftol() возвращает два значения: в регистре eax и в регистре edx, но по факту __ftol() - это отсечение дробной части (присвоение вещественного значения целому), а edx - мусор с точки зрения программы. Если проследить вызовы __ftol(), то можно заметить, что используется только значение, переданное через eax, а edx либо перезаписывается, либо не используется.

Если бы мы реально работали с 64-разрядной арифметикой, то edx бы был нужен, а так, в Героях 3 все целые - 32-х разрядные.
Вернуться к началу

offlineRoseKavalier  
Мастер
Мастер
 
Сообщения: 331
Зарегистрирован: 23 сен 2017, 17:00
Пол: Не указан
Поблагодарили: 234 раз.

Re: Улучшение ИИ

Сообщение RoseKavalier » 08 май 2020, 15:33

Код: Выделить всё
int __thiscall AI_CalcBattleStack_GetCastSpellValue_00423C80(H3QuickBattleCreatures*this, H3AIBattleSpell *a2, H3Hero *DHero, H3Hero *AHero)


H3QuickBattleCreatures
https://github.com/RoseKavalier/H3Plugi ... .hpp#L3051

H3AIBattleSpell
Код: Выделить всё
   struct H3AIBattleSpell // ctor 4365D0
   {
      // * +0
      INT spellId;
      // * +4
      INT skillLevel; // the associated secondary skill level to the spell
      // * +8
      INT spellPower;
      // * +C
      INT spellDuration;
      // * +10
      UINT8 f_10; // {1}
      h3align _f_11[3];
      // * +14
      INT f_14; // {-1}
      // * +18
      INT f_18; // {-1}
      // * +1C
      INT f_1C; // {0}
      // * +20
      UINT8 f_20; // {0}
      h3align _f_21[3];
   };
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2184 раз.

Re: Улучшение ИИ

Сообщение AlexSpl » 08 май 2020, 15:43

Да, __thiscall, спасибо. Смотрел на sub_44A1A0. Первый аргумент в ecx, остальные - в стеке.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2184 раз.

Re: Улучшение ИИ

Сообщение AlexSpl » 08 май 2020, 16:39

Интересно, я правильно переписал функцию?

Код: Выделить всё
int __thiscall AI_CalcBattleStack_GetCastSpellValue_00423C80(H3QuickBattleCreatures* battleStack, H3AIBattleSpell* spell, H3Hero* DHero, H3Hero* AHero)
{
  int result = 0;
   
  if ( battleStack->stackPower )
  {
    int spellDuration = spell->spellDuration;
    if ( spellDuration > 5 ) spellDuration = 5;
    result = (int)(battleStack->stackPower * spellDuration * P_Spell(spell->spellId).ai_value[spell->skillLevel] *
      CalcSpellDamagePercentage(spell->spellId, battleStack->type, DHero, AHero) / 500.0);
  }
 
  return result;
}
Последний раз редактировалось AlexSpl 09 май 2020, 02:13, всего редактировалось 2 раз(а).
Вернуться к началу

offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

Re: Улучшение ИИ

Сообщение as239 » 08 май 2020, 17:02

Ух, такую бы красоту да по RMG_MonsterGenerationZoneBlocks_00541630.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2184 раз.

Re: Улучшение ИИ

Сообщение AlexSpl » 08 май 2020, 17:16

Там здоровая функция, и без теории - никак. Если бы кто статейку написал по объектам/структурам RMG :smile14: Причесать код можно, конечно, но для меня он слишком абстрактный.
Вернуться к началу

offlineRoseKavalier  
Мастер
Мастер
 
Сообщения: 331
Зарегистрирован: 23 сен 2017, 17:00
Пол: Не указан
Поблагодарили: 234 раз.

Re: Улучшение ИИ

Сообщение RoseKavalier » 08 май 2020, 17:56

Looks good @AlexSpl !
RMG_MonsterGenerationZoneBlocks_00541630 remains messy even with a lot of defined stuff, just like most RMG functions :S
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2184 раз.

Re: Улучшение ИИ

Сообщение AlexSpl » 08 май 2020, 20:03

H3AIBattleSpell is not in H3API yet?
Вернуться к началу

Пред.След.

Вернуться в Общий раздел

Кто сейчас на конференции

Сейчас этот форум просматривают: Владимир и гости: 1