Discussion in 'Bugs and Crashes' started by velosepappe, Sep 8, 2011.

1. ### velosepappeChieftain

Joined:
Mar 2, 2005
Messages:
141
I'm sure the retreat chance has been discussed many times before in other mods. Many mods add too many increase retreat chance promotions which leads to some units being unable to be destroyed because retreat chances are 100%.

I know this is not really a hot topic but this just came to mind again, something I have thought of a long time ago. Instead of making retreat chances additive: like 4 promotions of 15% chance retreat-> 60% retreat, one could make each promotion have an extra possibility of retreat if retreat is checked during combat. For example 4 promotions of 15% retreat: Check first retreat= 15% chance, if not retreated check second retreat= 15%chance and so on. In fact these 4 checks should not be made seperately at all. The formula for the total chance of retreat in this case is: 1-(1-0.15)*(1-0.15)*(1-0.15)*(1-0.15).

In this way it is never possible to have a total chance of retreat equal to 100% except if at least one promotion gives a 100% retreat chance. I dont think if this is hard to program, if nobody has the time to program this someone could lead me to the code for retreat chance so I can make the changes.
Also this would remove any problems with retreat chances being larger than 100% if there were any, because this should be impossible.

What do you guys think?

2. ### KoshlingVorlon

Joined:
Apr 11, 2011
Messages:
9,254
It would be in line with what I have done to make food threshold/storage modifiers multiplicative with basically the same reasons. Modifiers to retreat are less widespread however, so the design burden of keeping totals below 100% with the addative system is less than it was for the food modifiers. None the less, I agree that it's likely a good idea (just not quite as urgent as it was for food)

3. ### velosepappeChieftain

Joined:
Mar 2, 2005
Messages:
141
You made them multiplicative? Never occured to me but good job!

The reason why the retreat promotions are less widespread is probably because they were cut back much earlier due to the 100% retreat problem.

4. ### velosepappeChieftain

Joined:
Mar 2, 2005
Messages:
141
I've looked around in the code and done this:

Code:
`double m_iExtraWithdrawal;`
in CvUnit.h changed m_iExtraWithdrawal from int to double to avoud rounding errors
Code:
`m_iExtraWithdrawal = 1.0;`
in CvUnit.cpp
Code:
```int CvUnit::getExtraWithdrawal() const
{
/************************************************************************************************/
/* Afforess	                  Start		 03/1/10                       Coded By: KillMePlease   */
/*                                                                                              */
/* Great Commanders                                                                             */
/************************************************************************************************/
if (!isCommander()) //this is not a commander
{
CvUnit* pCommander = getCommander();
if (pCommander != NULL)
return	100-round((1-m_iExtraWithdrawal) * (1-pCommander->getExtraWithdrawal()/100)*100);
}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
return 100-(int)round((1-m_iExtraWithdrawal) *100);
}

void CvUnit::changeExtraWithdrawal(int iChange)
{
m_iExtraWithdrawal *= (1-iChange/100);
FAssert(getExtraWithdrawal() <= 100);
}```
Also in CvUnit.cpp. What this does is apply the formula in my first post in CvUnit::changeExtraWithdrawal(int iChange). The result is in fact the chance that the unit will not withdraw, the chance that it will withdraw is 1-m_iExtraWithdrawal. iChange is the % chance of withdrawal due to a promotion (I guess).

In CvUnit::getExtraWithdrawal() I calculate the chance of withdrawal in % with an eventual commander. Of course the double has to be cast to an int, which I hope I did it in the right way: (int)round(...).

Code:
```int CvUnit::withdrawalProbability() const
{
if (getDomainType() == DOMAIN_LAND && plot()->isWater())
{
return 0;
}
/************************************************************************************************/
/* Afforess	                  Start		 04/02/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
return std::min(100, std::max(0, 100-(int)round((100-m_pUnitInfo->getWithdrawalProbability()) * (100-getExtraWithdrawal())/100)));
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

}```
Also in CvUnit.cpp. Finally the retreat chance inherent to the unit has to be 'multiplied' with the promotion retreat chance. I havent been able to compile yet, what compiler could I use, I only have dev-C++. Maybe you can give me a link to a tutorial, or possibly try it yourself.

5. ### KoshlingVorlon

Joined:
Apr 11, 2011
Messages:
9,254
See this link for a guide to what you need to build the DLL : http://forums.civfanatics.com/showthread.php?t=405444

I tried with VC2005 and VS2010 (both of which I already had via my day-job) and there are library compability issues with both, so regardless of what you already have, stick with the freebie VC2008 the thread suggests.

In terms of your proposed code changes, it all looks plausible. In the case of the retreat modifier you're seeking to change, you should get away with the simple calculation you suggest in changeExtraWithdrawl() (that code doesn't work if changes can be applied and removed, as they can with most modifers, because it won't handle a positive iChange followed by the same negative one getting back to the start point). For withdrawal chance modifiers though, I can't see any way you'll ever lose one that you get, so that doesn't matter (see the food threshold code for another way to do it that copes with that - basically I just transform to natural logarithm space in which the calculation you want is linear so adding and subtracting balances, and the log of the actual modifier is what gets persisted).

The only change I would recommend making is to rename m_iExtraWithdrawal to m_fExtraWithdrawal, both for consistency reasons (most of the code uses Hungarian naming conventions), and because changing the type of a tagged entity in the save file without changing its name might not be handled correctly (I'm not sure off hand).

6. ### EldrinFalChieftain

Joined:
Mar 22, 2011
Messages:
926
Does the Surround and Destroy option reduce the chances for withdraw if the unit is adjacent to enemy units? If not, that would seem to make sense.