Объявления

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

Герои 2 (разные версии) с плагинами

Не запускается игра? Проблемы со звуком? Где, в конце концов, взять игру, скачать патчи, приложения и карты? Как установить все это? Все проблемы обсуждаем в этом разделе
offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

Re: Герои 2 (разные версии) с плагинами

Сообщение Ben80 » 15 авг 2023, 04:35

Идея Фила в том что чем меньше разница между коэффициентом победы и броском кости, тем больше потери выигравшей стороны. Для атакующего это выполняется, а для защищающегося - нет (см. код ниже). А в Героях 2 правильно подправили (по сути они исправили баг). Имена переменных winCoefDefender и winCoefAttacker думаю крайне неудачны, поскольку это именно доля потерь - параметр для последующего вызова philAI_DamageGroup.

AlexSpl писал(а):

if ( win )
{
if ( heroAttacker )
{
advManager::GiveExperience(gpAdvManager, heroAttacker, exp2, 1);
hero::ApplyBattleWinTemps(heroAttacker);
}
*winCoefDefender = 1.0;
*winCoefAttacker = v19;
}
else
{
if ( heroAttacker )
{
heroAttacker->currMobility = 0;
hero::ApplyBattleLossTemps(heroAttacker);
}
if ( heroDefender )
hero::ApplyBattleWinTemps(heroAttacker);
*winCoefDefender = v19 * v22;
*winCoefAttacker = 1.0;
if ( *winCoefAttacker >= 1.0 && heroDefender )
advManager::GiveExperience(gpAdvManager, heroDefender, exp2, 1);
}
Вернуться к началу

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

Re: Герои 2 (разные версии) с плагинами

Сообщение Ben80 » 15 авг 2023, 05:50

AlexSpl писал(а):

Цитата:
2) Изменить кусок в philAI_QuickCombat (с оригинала выше вот на это)

Логично. Поддерживаю. probWinnerD = 1 - probWinnerA ведь?


Да, правильно, именно так и нужно делать, только мне нужно probWinnerD все-таки переименовать в dice, подводит меня это название. Настоящая probWinnerD это именно 1 - probWinnerA.

И обратите внимание на этот кусок:
Код: Выделить всё
  if(isAttackerWin && probWinnerA > 0.6)
    probDelta = (probWinnerA + 0.65) * probDelta;
  if(probDelta > 1.0)
    probDelta = 1.0;
  float casualties = (1.0 - probDelta) * (1.0 - probDelta);


Вот этого условия в Героях 1 нет, значит Фил реально пытался исправить баги в теор. битве.
Код: Выделить всё
  if(probDelta > 1.0)
    probDelta = 1.0;
Вернуться к началу

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

Re: Герои 2 (разные версии) с плагинами

Сообщение Ben80 » 15 авг 2023, 06:00

В общем, я вот этот кусок:
Код: Выделить всё
  float dice = (float)Random(0, 100) / 100.0;
  float winningDegree;

  if ( dice >= probWinnerA )
  {
    winningDegree = 1.0 - probWinnerA;
    armyWinner = armyGroupD;
  }
  else
  {
    isAttackerWin = true;
    winningDegree = probWinnerA;
    armyWinner = armyGroupA;
  }

  float probDelta;
  if(probWinnerA >= dice)
    probDelta = probWinnerA - dice;
  else
    probDelta = dice - probWinnerA;

  if(isAttackerWin && probWinnerA > 0.6)
    probDelta = (probWinnerA + 0.65) * probDelta;
  if(probDelta > 1.0)
    probDelta = 1.0;
  float casualties = (1.0 - probDelta) * (1.0 - probDelta);


меняю на этот:
Код: Выделить всё
  float dice = (float)Random(20, 80) / 100.0;
  float winningDegree;

  if ( dice >= probWinnerA )
  {
    winningDegree = 1.0 - probWinnerA;
    armyWinner = armyGroupD;
  }
  else
  {
    isAttackerWin = true;
    winningDegree = probWinnerA;
    armyWinner = armyGroupA;
  }

  float probDelta;
  if(probWinnerA >= dice)
    probDelta = probWinnerA - dice;
  else
    probDelta = dice - probWinnerA;

  if(winningDegree > 0.6)
    probDelta = (winningDegree + 0.65) * probDelta;
  if(probDelta > 1.0)
    probDelta = 1.0;
  float casualties = (1.0 - probDelta) * (1.0 - probDelta);


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

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5587
Зарегистрирован: 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)
Поблагодарили: 2185 раз.

Re: Герои 2 (разные версии) с плагинами

Сообщение AlexSpl » 15 авг 2023, 07:24

Переименовал переменные. Теперь легче следить за мыслью Фила.
Код: Выделить всё
int __thiscall philAI::QuickCombat(
        philAI *this,
        struct armyGroup *armyGroupAttacker,
        struct hero *heroAttacker,
        struct armyGroup *armyGroupDefender,
        struct hero *heroDefender,
        int townBattle,
        int town_id,
        float *casualtiesProbAttacker,
        float *casualtiesProbDefender)
{
  double module; // st7
  float module_tmp; // [esp+0h] [ebp-50h]
  int defenderPlayerId; // [esp+8h] [ebp-48h]
  float winProb; // [esp+10h] [ebp-40h]
  int a13; // [esp+14h] [ebp-3Ch] BYREF
  int a12; // [esp+18h] [ebp-38h] BYREF
  float winCoeff; // [esp+1Ch] [ebp-34h] BYREF
  int a11; // [esp+20h] [ebp-30h] BYREF
  float k; // [esp+24h] [ebp-2Ch]
  int a10; // [esp+28h] [ebp-28h] BYREF
  BOOL win; // [esp+30h] [ebp-20h]
  float delta; // [esp+38h] [ebp-18h]
  int expAttacker; // [esp+3Ch] [ebp-14h]
  int expDefender; // [esp+40h] [ebp-10h]
  float dice; // [esp+44h] [ebp-Ch]
  struct armyGroup *winnerGroup; // [esp+48h] [ebp-8h]
  int a14; // [esp+4Ch] [ebp-4h] BYREF

  expAttacker = game::ExperienceValueOfStack(gpGame, armyGroupAttacker, heroAttacker);
  expDefender = game::ExperienceValueOfStack(gpGame, armyGroupDefender, heroDefender);
  win = 0;
  winnerGroup = 0;
  if ( heroDefender )
    defenderPlayerId = heroDefender->owner_id;
  else
    defenderPlayerId = -1;
  philAI::ProbableOutcomeOfBattle(
    this,
    armyGroupAttacker,
    heroAttacker,
    armyGroupDefender,
    heroDefender,
    0,
    townBattle,
    town_id,
    defenderPlayerId,
    &winCoeff,
    &a10,
    &a11,
    &a12,
    &a13,
    &a14);
  if ( winCoeff > 0.75 )
    winCoeff = 1.0;
  dice = RandInt(0, 99) / 100.0;
  if ( dice >= winCoeff )
  {
    winProb = 1.0 - winCoeff;
    winnerGroup = armyGroupDefender;
  }
  else
  {
    win = 1;
    winProb = winCoeff;
    winnerGroup = armyGroupAttacker;
  }
  if ( dice <= winCoeff )
    module = winCoeff - dice;
  else
    module = dice - winCoeff;
  module_tmp = module;
  delta = module_tmp;
  if ( win && winCoeff > 0.6 )
    delta = delta * (winCoeff + 0.65);
  k = (1.0 - delta) * (1.0 - delta);
  if ( winProb > 0.8 && k > 0.2 )
    k = k * k;
  if ( winProb > 0.96 && (1.0 - winProb) / 2.0 < k )
    k = (1.0 - winProb) / 2.0;
  if ( win )
  {
    if ( heroAttacker )
    {
      advManager::GiveExperience(gpAdvManager, heroAttacker, expDefender, 1);
      hero::ApplyBattleWinTemps(heroAttacker);
    }
    *casualtiesProbDefender = 1.0;
    *casualtiesProbAttacker = k;
  }
  else
  {
    if ( heroAttacker )
    {
      heroAttacker->currMobility = 0;
      hero::ApplyBattleLossTemps(heroAttacker);
    }
    if ( heroDefender )
      hero::ApplyBattleWinTemps(heroAttacker);
    *casualtiesProbDefender = k * delta;
    *casualtiesProbAttacker = 1.0;
    if ( *casualtiesProbAttacker >= 1.0 && heroDefender )
      advManager::GiveExperience(gpAdvManager, heroDefender, expDefender, 1);
  }
  if ( *casualtiesProbAttacker < 1.0 )
  {
    if ( *casualtiesProbDefender >= 1.0 )
      advManager::TransferArtifacts(gpAdvManager, heroDefender, heroAttacker);
  }
  else
  {
    advManager::TransferArtifacts(gpAdvManager, heroAttacker, heroDefender);
  }
  philAI::DamageGroup(this, armyGroupAttacker, heroAttacker, heroDefender, *casualtiesProbAttacker);
  philAI::DamageGroup(this, armyGroupDefender, heroDefender, heroAttacker, *casualtiesProbDefender);
  if ( win && townBattle )
    game::ClaimTown(gpGame, town_id, giCurPlayer);
  return win;
}

Возник вопрос. Почему такая асимметричность (и какой вариант есть баг: с умножением на delta или без):

Код: Выделить всё
if ( heroAttacker )
{
  advManager::GiveExperience(gpAdvManager, heroAttacker, expDefender, 1);
  hero::ApplyBattleWinTemps(heroAttacker);
}
*casualtiesProbDefender = 1.0;
*casualtiesProbAttacker = k;


Код: Выделить всё
if ( heroDefender )
  hero::ApplyBattleWinTemps(heroAttacker);
*casualtiesProbDefender = k * delta;
*casualtiesProbAttacker = 1.0;
if ( *casualtiesProbAttacker >= 1.0 && heroDefender )
  advManager::GiveExperience(gpAdvManager, heroDefender, expDefender, 1);

В Двойке множитель delta убран, как Вы выяснили. Нужен ли он в Героях 1? Мне кажется, легче пропустить умножение, чем дописать лишнее. Единственная причина асимметричности между нападающей армией и защищающейся, которую я себе могу представить, это право первого хода*. В этом плане стороны немножко несимметричны.

*) А право первого хода всё-таки нужно учитывать. В Героях 1 и 2 летающие отряды могут перемещаться по всему полю боя, и если такой отряд будет ходить первым, а при прочих равных, первым будет ходить отряд нападающей стороны, то он очень сильно может навредить защищающейся стороне (например, нанеся сокрушительный удар по отряду стрелков и заблокировав их, т.е. отняв их основное преимущество). Так что перекос оправдан, и я думаю, нужно как-то отразить право первого хода в алгоритме QuickBattle.
Вернуться к началу

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

Re: Герои 2 (разные версии) с плагинами

Сообщение Ben80 » 15 авг 2023, 08:01

AlexSpl писал(а):

*) А право первого хода всё-таки нужно учитывать. В Героях 1 и 2 летающие отряды могут перемещаться по всему полю боя, и если такой отряд будет ходить первым, а при прочих равных, первым будет ходить отряд нападающей стороны, то он очень сильно может навредить защищающейся стороне (например, нанеся сокрушительный удар по отряду стрелков и заблокировав их, т.е. отняв их основное преимущество). Так что перекос оправдан, и я думаю, нужно как-то отразить право первого хода в алгоритме QuickBattle.


Я думаю, на данном этапе можно остановиться с детализацией. Если уж уточнять, то много чего. Например, при игре против нежити стеку Крестоносцев можно добавить нехилый бонусный вес. Летающим отрядам или быстрым пешеходам можно дать бонус против стрелков, стрелкам - бонус против медленных пешеходов, медленным пешеходам - бонус против летунов. То есть смотреть кого, сколько, и исходя из этого рассчитывать. Но это уже работа над теор. битвами уровнем выше, так сказать, чем вот эта.
Последний раз редактировалось Ben80 15 авг 2023, 08:09, всего редактировалось 1 раз.
Вернуться к началу

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

Re: Герои 2 (разные версии) с плагинами

Сообщение Ben80 » 15 авг 2023, 08:04

Определился с изменениями в philAI_ProbableOutcomeOfBattle.
Было:
Код: Выделить всё
  if(*probWinnerA >= 0.08 )
  {
    if(*probWinnerA >= 0.12 )
    {
      if(*probWinnerA >= 0.2 )
      {
        if(*probWinnerA >= 0.3 )
        {
          if(*probWinnerA < 0.4 )
            *probWinnerA -= 0.02;
        }
        else
        {
          *probWinnerA -= 0.04;
        }
      }
      else
      {
        *probWinnerA -= 0.05;
      }
    }
    else
    {
      *probWinnerA -= 0.07000000000000001;
    }
  }
  else
  {
    probWinnerA = 0;
  }

  *probableApproxCasualtiesA = (1.0 - *probWinnerA) * simpleStrengthA;
  *probableApproxCasualtiesD = *probWinnerA * simpleStrengthD;
  *probablePreciseCasualtiesA = (1.0 - *probWinnerA * *probWinnerA) * simpleStrengthA;
  *probablePreciseCasualtiesD = (1.0 - (1 - *probWinnerA)*(1 - *probWinnerA)) * simpleStrengthD;


Стало:
Код: Выделить всё
  if(*probWinnerA >= 0.08 )
  {
    if(*probWinnerA >= 0.12 )
    {
      if(*probWinnerA >= 0.2 )
      {
        if(*probWinnerA >= 0.3 )
        {
          if(*probWinnerA < 0.4 )
            *probWinnerA -= 0.02;
        }
        else
        {
          *probWinnerA -= 0.04;
        }
      }
      else
      {
        *probWinnerA -= 0.05;
      }
    }
    else
    {
      *probWinnerA -= 0.07;
    }
  }
  else
  {
    probWinnerA = 0;
  }
 
  if(*probWinnerA <= 0.92 )
  {
    if(*probWinnerA <= 0.88 )
    {
      if(*probWinnerA <= 0.8 )
      {
        if(*probWinnerA <= 0.7 )
        {
          if(*probWinnerA > 0.6 )
            *probWinnerA += 0.02;
        }
        else
        {
          *probWinnerA += 0.04;
        }
      }
      else
      {
        *probWinnerA += 0.05;
      }
    }
    else
    {
      *probWinnerA += 0.07;
    }
  }
  else
  {
    probWinnerA = 0;
  } 

  *probableApproxCasualtiesA = (1.0 - *probWinnerA) * simpleStrengthA;
  *probableApproxCasualtiesD = *probWinnerA * simpleStrengthD;
 
  float winnerDegree;
  int probablePreciseCasualtiesLoser;
  int probablePreciseCasualtiesWinner;

  if(probWinnerA > 0.5)
    winnerDegree = probWinnerA;
  else
    winnerDegree = 1 - probWinnerA;
 
  *probablePreciseCasualtiesWinner = (1.0 - *winnerDegree * *winnerDegree) * simpleStrengthA;
  *probablePreciseCasualtiesLoser = (1.0 - (1 - *winnerDegree)*(1 - *winnerDegree)) * simpleStrengthD;
 
  if(probWinnerA > 0.5)
  {
    probablePreciseCasualtiesA = probablePreciseCasualtiesWinner;
    probablePreciseCasualtiesD = probablePreciseCasualtiesLoser;
  }
  else
  {
    probablePreciseCasualtiesA = probablePreciseCasualtiesLoser;
    probablePreciseCasualtiesD = probablePreciseCasualtiesWinner;
  }
 


При этом что в оригинале, что у меня в случае например probWinnerA = 0.5 прогнозируемые потери у обеих сторон по 75% (а не по 100%) - ну да и ладно, это не критично - главное что относительные проценты потерь (одной стороны относительно другой) будут находиться более-менее корректно.
Полностью распутать и привести в логичный вид хитросплетения теоретических битв Фила не вышло :smile12: , но в целом получилось неплохо, думаю.
Вернуться к началу

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

Re: Герои 2 (разные версии) с плагинами

Сообщение Ben80 » 15 авг 2023, 10:30

Хотя вообще-то я неправ ("зарапартовался") - все эти сложности лишние:
Код: Выделить всё
  *probablePreciseCasualtiesWinner = (1.0 - *winnerDegree * *winnerDegree) * simpleStrengthA;
  *probablePreciseCasualtiesLoser = (1.0 - (1 - *winnerDegree)*(1 - *winnerDegree)) * simpleStrengthD;
 
  if(probWinnerA > 0.5)
  {
    probablePreciseCasualtiesA = probablePreciseCasualtiesWinner;
    probablePreciseCasualtiesD = probablePreciseCasualtiesLoser;
  }
  else
  {
    probablePreciseCasualtiesA = probablePreciseCasualtiesLoser;
    probablePreciseCasualtiesD = probablePreciseCasualtiesWinner;
  }


В оригинальном коде корректно и симметрично относительно атакующего и защищающегося. Однако чисто по результатам моего небольшого исследования с мат.ожиданиями можно предложить небольшую корректировку (если вообще кто-то верит, что здесь уместно говорить о какой-то точности):
Код: Выделить всё
*probableApproxCasualtiesA = (1.0 - *probWinnerA) * simpleStrengthA;
*probableApproxCasualtiesD = *probWinnerA * simpleStrengthD;
*probablePreciseCasualtiesA = (1.0 - *probWinnerA * *probWinnerA) * simpleStrengthA;
*probablePreciseCasualtiesD = (1.0 - (1 - *probWinnerA)*(1 - *probWinnerA)) * simpleStrengthD;

if(probWinnerA > 0.85)
  *probablePreciseCasualtiesA = (*probablePreciseCasualtiesA + *probableApproxCasualtiesA) / 2;
if(probWinnerA < 0.15)
  *probablePreciseCasualtiesD = (*probablePreciseCasualtiesD + *probableApproxCasualtiesD) / 2;


***

Просто замена
Код: Выделить всё
float dice = (float)Random(0, 100) / 100.0;


на
Код: Выделить всё
float dice = (float)Random(20, 80) / 100.0;


не могла пройти бесследно - расклады несколько изменились.
Вернуться к началу

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

Re: Герои 2 (разные версии) с плагинами

Сообщение Ben80 » 15 авг 2023, 11:27

AlexSpl писал(а):

В Двойке множитель delta убран, как Вы выяснили. Нужен ли он в Героях 1? Мне кажется, легче пропустить умножение, чем дописать лишнее.


Нет смысла гадать на кофейной гуще. Множитель delta там по смыслу просто не нужен. Я понимаю, что вам интересно относиться к реверсингу Героев как к небольшому приключению или детективу, но иногда все достаточно очевидно.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5587
Зарегистрирован: 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)
Поблагодарили: 2185 раз.

Re: Герои 2 (разные версии) с плагинами

Сообщение AlexSpl » 15 авг 2023, 22:35

Цитата:
В оригинальном коде корректно и симметрично относительно атакующего и защищающегося. Однако чисто по результатам моего небольшого исследования с мат.ожиданиями можно предложить небольшую корректировку (если вообще кто-то верит, что здесь уместно говорить о какой-то точности)

Главное, чтобы в реальной игре результаты теоретической битвы улучшились. Нужно протестировать на нейтралах и героях с разным соотношением сил (с каждым нейтральным отрядом/героем боёв 10 хотя бы провести), составить табличку: старый QuickCombat/новый QuickCombat/автобой/человек. Тогда и будет видно, стал ли AI хоть чуточку эффективнее или нет.
Вернуться к началу

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

Re: Герои 2 (разные версии) с плагинами

Сообщение Ben80 » 16 авг 2023, 03:54

AlexSpl писал(а):

Главное, чтобы в реальной игре результаты теоретической битвы улучшились. Нужно протестировать на нейтралах и героях с разным соотношением сил (с каждым нейтральным отрядом/героем боёв 10 хотя бы провести), составить табличку: старый QuickCombat/новый QuickCombat/автобой/человек. Тогда и будет видно, стал ли AI хоть чуточку эффективнее или нет.


Правдоподобнее, вы хотите сказать ? И потом, разве не важно соответствие результатов битвы (по потерям) и прогнозу ИИ перед битвой ? И, кстати, если уж этим заниматься, то также нужно протестировать как для атакующего героя, так и для защищающегося героя, отдельно.
Я вчера сделал просто - рассчитал мат. ожидания потерь для случая probWinnerA = 0.9 и для случая probWinnerA = 0.7, то есть для каждого случая рассмотрел результаты для разных возможных значений dice с шагом 0.1 и усреднил - так и получил мат. ожидание.
А вообще у меня всегда была склонность слишком доверять прикидочным и не очень системным расчетам. Не говоря уже о том, что никогда не умел хорошо оформлять результаты, в отличие от вас, например.

***
По поводу предложенной мною поправки:
Код: Выделить всё
if(probWinnerA > 0.85)
  *probablePreciseCasualtiesA = (*probablePreciseCasualtiesA + *probableApproxCasualtiesA) / 2;
if(probWinnerA < 0.15)
  *probablePreciseCasualtiesD = (*probablePreciseCasualtiesD + *probableApproxCasualtiesD) / 2;


Имеет ли она какую-то "математическую связь" с алгоритмом для расчета потерь (после броска dice и тд) ? Нет, не имеет. Почему была выбрана именно такая поправка ? Исключительно за простоту - нет никаких дополнительных сложных манипуляций с probWinnerA с использованием, например, функции SQRT или чего-либо еще. Ну и естественно потому что поправка улучшает результаты для больших значений probWinnerA (0.9 и более) - то есть улучшает соответствие между прогнозом перед битвой и мат. ожиданиями потерь в случае использования float dice = (float)Random(20, 80) / 100.0 !!!

***

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

***

Да, и еще раз про функцию мю(N) - она загубит на корню любые благие начинания с теоретическими битвами. Если нужны хорошие теор. битвы - выпиливание мю(N) и небольшая корректировка fight value существ - неизбежно.
Вернуться к началу

Пред.След.

Вернуться в Техническая часть

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1