Better BUG AI

Well yeah I most certainly overdid it.
Siege units' value bonus for bombard rate is halved now, I hope that's better. I uploaded both dll-only and new package (same 04-12 file name).

So is it balanced now or do you think it needs more tweaking? Thats quite a big gameplay change and I don't know if I should stick with it or just go with game defaults.
 
The AI should no longer build too many siege units, that much I am pretty sure of. However without real testing it's difficult to judge how "good" or "bad" the currect situation is.

Spoiler :
I can however show you the code in question, I actually wanted to post it here a while ago but forgot again. The section responsible for how many siege units are build for attack city stacks is one tiny part in the CvPlayerAI::AI_unitValue() function: the higher the value of a unit, the higher the propability for it to be built.

This is the BTS 3.19 version:
Spoiler :
Code:
	case UNITAI_ATTACK_CITY:
		iFastMoverMultiplier = AI_isDoStrategy(AI_STRATEGY_FASTMOVERS) ? 4 : 1;
		
		iTempValue = ((iCombatValue * iCombatValue) / 75) + (iCombatValue / 2);
		iValue += iTempValue;
		if (GC.getUnitInfo(eUnit).isNoDefensiveBonus())
		{
			iValue -= iTempValue / 2;
		}
		if (GC.getUnitInfo(eUnit).getDropRange() > 0)
		{
			iValue -= iTempValue / 2;
		}
		if (GC.getUnitInfo(eUnit).isFirstStrikeImmune())
		{
			iValue += (iTempValue * 8) / 100;
		}		
		iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getCityAttackModifier()) / 100);
		iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getCollateralDamage()) / 400);
		iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getMoves() * iFastMoverMultiplier) / 4);
		iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getWithdrawalProbability()) / 100);
		if (!AI_isDoStrategy(AI_STRATEGY_AIR_BLITZ))
		{
			int iBombardValue = GC.getUnitInfo(eUnit).getBombardRate() * 4;
			if (iBombardValue > 0)
			{
[COLOR="Green"]				//Percentage change
				//Total Bombard == 0 : 600%
				//Total Bombard == 100 : 200%
				//Total Bombard == 200: 100%
				//Total Bombard == 300: 50%
				//Total Bombard == 400: [/COLOR]
				int iTotalBombardRate = AI_calculateTotalBombard(DOMAIN_LAND);
					if (iTotalBombardRate < 100)
					{
					iBombardValue *= 4 * (200 - iTotalBombardRate);
					iBombardValue /= 100;
				}
				else
				{
					iBombardValue *= 100;
					iBombardValue /= std::min(400, iTotalBombardRate);
				}
				iValue += iBombardValue;
			}
		}

		break;

this here would be jdog's version as of Better BTS AI 0.90j:
Spoiler :
Code:
	case UNITAI_ATTACK_CITY:
[COLOR="Green"]/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      02/24/10                                jdog5000      */
/*                                                                                              */
/* War strategy AI                                                                              */
/************************************************************************************************/
		// Effect army composition to have more collateral/bombard units[/COLOR]
		iFastMoverMultiplier = AI_isDoStrategy(AI_STRATEGY_FASTMOVERS) ? 4 : 1;
		
		iTempValue = ((iCombatValue * iCombatValue) / 75) + (iCombatValue / 2);
		iValue += iTempValue;
		if (GC.getUnitInfo(eUnit).isNoDefensiveBonus())
		{
			iValue -= iTempValue / 2;
		}
		if (GC.getUnitInfo(eUnit).getDropRange() > 0)
		{
			iValue -= iTempValue / 2;
		}
		if (GC.getUnitInfo(eUnit).isFirstStrikeImmune())
		{
			iValue += (iTempValue * 8) / 100;
		}		
		iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getCityAttackModifier()) / [B]75[/B]);
		iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getCollateralDamage()) / [B]200[/B]);
		iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getMoves() * iFastMoverMultiplier) / 4);
		iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getWithdrawalProbability()) / 100);

		if (!AI_isDoStrategy(AI_STRATEGY_AIR_BLITZ))
		{
			int iBombardValue = GC.getUnitInfo(eUnit).getBombardRate() * 8;
			if (iBombardValue > 0)
			{
				int iGoalTotalBombardRate = [B]200[/B];

				[COLOR="Green"]// Note: this also counts UNITAI_COLLATERAL units, which only play defense[/COLOR]
				int iTotalBombardRate = AI_calculateTotalBombard(DOMAIN_LAND);
				if (iTotalBombardRate < iGoalTotalBombardRate)
				{
					iBombardValue *= (2*iGoalTotalBombardRate - iTotalBombardRate);
					iBombardValue /= iGoalTotalBombardRate;
				}
				else
				{
					iBombardValue *= iGoalTotalBombardRate;
					iBombardValue /= std::min(4*iGoalTotalBombardRate, 2*iTotalBombardRate - iGoalTotalBombardRate);
				}

				iValue += iBombardValue;
			}
		}
[COLOR="Green"]/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/[/COLOR]
		break;

my version, updated:
Spoiler :
Code:
	case UNITAI_ATTACK_CITY:
[COLOR="Green"]/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      02/24/10                                jdog5000      */
/*                                                                                              */
/* War strategy AI                                                                              */
/************************************************************************************************/
		// Effect army composition to have more collateral/bombard units[/COLOR]
		iFastMoverMultiplier = AI_isDoStrategy(AI_STRATEGY_FASTMOVERS) ? 4 : 1;
		
		iTempValue = ((iCombatValue * iCombatValue) / 75) + (iCombatValue / 2);
		iValue += iTempValue;
		if (GC.getUnitInfo(eUnit).isNoDefensiveBonus())
		{
			iValue -= iTempValue / 2;
		}
		if (GC.getUnitInfo(eUnit).getDropRange() > 0)
		{
			iValue -= iTempValue / 2;
		}
		if (GC.getUnitInfo(eUnit).isFirstStrikeImmune())
		{
			iValue += (iTempValue * 8) / 100;
		}		
		iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getCityAttackModifier()) / 75);
[COLOR="Green"]/* Collateral Damage valuation moved to bombard part
		iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getCollateralDamage()) / 400);
*/[/COLOR]
		iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getMoves() * iFastMoverMultiplier) / 4);
		iValue += ((iCombatValue * GC.getUnitInfo(eUnit).getWithdrawalProbability()) / 100);
[COLOR="Green"]/*
		if (!AI_isDoStrategy(AI_STRATEGY_AIR_BLITZ))
		{
*/[/COLOR]
			if (GC.getUnitInfo(eUnit).getBombardRate() > 0 || (GC.getUnitInfo(eUnit).getCollateralDamageMaxUnits() > 0 && GC.getUnitInfo(eUnit).getCollateralDamage() > 0))
			{
				[COLOR="Green"]// Army composition needs to scale with army size, bombard unit potency[/COLOR]

				[COLOR="Green"]//modified AI_calculateTotalBombard(DOMAIN_LAND) code[/COLOR]
				int iII;
				int iTotalBombard = 0;
				int iSiegeUnits = 0;
				int iSiegeImmune = 0;
				int iTotalSiegeMaxUnits = 0;
				
				for (iII = 0; iII < GC.getNumUnitClassInfos(); iII++)
				{
					UnitTypes eLoopUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iII)));
					if (eLoopUnit != NO_UNIT)
					{
						if (GC.getUnitInfo(eLoopUnit).getDomainType() == DOMAIN_LAND)
						{
							int iClassCount = getUnitClassCount((UnitClassTypes)iII);
							int iBombardRate = GC.getUnitInfo(eLoopUnit).getBombardRate();
							
							if (iBombardRate > 0)
							{
								iTotalBombard += ((iBombardRate * iClassCount * ((GC.getUnitInfo(eLoopUnit).isIgnoreBuildingDefense()) ? 3 : 2)) / 2);
							}
							
							int iBombRate = GC.getUnitInfo(eLoopUnit).getBombRate();
							if (iBombRate > 0)
							{
								iTotalBombard += iBombRate * iClassCount;
							}
							
							int iCollateralDamageMaxUnits = GC.getUnitInfo(eLoopUnit).getCollateralDamageMaxUnits();
							if (iCollateralDamageMaxUnits > 0 && GC.getUnitInfo(eLoopUnit).getCollateralDamage() > 0)
							{
								iTotalSiegeMaxUnits += iCollateralDamageMaxUnits * iClassCount;
								iSiegeUnits += iClassCount;
							}
							else if (GC.getUnitInfo(eLoopUnit).getUnitCombatCollateralImmune((UnitCombatTypes)GC.getUnitInfo(eUnit).getUnitCombatType()))
							{
								iSiegeImmune+= iClassCount;
							}
						}
					}
				}

				int iNumOffensiveUnits = AI_totalUnitAIs(UNITAI_ATTACK_CITY) + AI_totalUnitAIs(UNITAI_ATTACK) + AI_totalUnitAIs(UNITAI_COUNTER)/2;
				int iNumDefensiveUnits = AI_totalUnitAIs(UNITAI_CITY_DEFENSE) + AI_totalUnitAIs(UNITAI_RESERVE) + AI_totalUnitAIs(UNITAI_CITY_COUNTER)/2 + AI_totalUnitAIs(UNITAI_COLLATERAL)/2;
				iSiegeUnits += (iSiegeImmune*iNumOffensiveUnits)/(iNumOffensiveUnits+iNumDefensiveUnits);

				int iMAX_HIT_POINTS = GC.getDefineINT("MAX_HIT_POINTS");

				int iCollateralDamageMaxUnitsWeight = (100 * (iNumOffensiveUnits - iSiegeUnits)) / std::max(1,iTotalSiegeMaxUnits);
				iCollateralDamageMaxUnitsWeight = std::min(100, iCollateralDamageMaxUnitsWeight);
				[COLOR="Green"]//to decrease value further for units with low damage limits:[/COLOR]
				int iCollateralDamageLimitWeight = 100*iMAX_HIT_POINTS - std::max(0, ((iMAX_HIT_POINTS - GC.getUnitInfo(eUnit).getCollateralDamageLimit()) * (100 -  iCollateralDamageMaxUnitsWeight)));
				iCollateralDamageLimitWeight /= iMAX_HIT_POINTS;

				int iCollateralValue = iCombatValue * GC.getUnitInfo(eUnit).getCollateralDamage() * GC.getDefineINT("COLLATERAL_COMBAT_DAMAGE");
				iCollateralValue /= 100;
				iCollateralValue *= std::max(100, (GC.getUnitInfo(eUnit).getCollateralDamageMaxUnits() * iCollateralDamageMaxUnitsWeight));
				iCollateralValue /= 100;
				iCollateralValue *= iCollateralDamageLimitWeight;
				iCollateralValue /= 100;
				iCollateralValue /= iMAX_HIT_POINTS;
				iValue += iCollateralValue;
				
				if (!AI_isDoStrategy(AI_STRATEGY_AIR_BLITZ) && GC.getUnitInfo(eUnit).getBombardRate() > 0)
				{
					[COLOR="Green"]/* original code
					int iBombardValue = GC.getUnitInfo(eUnit).getBombardRate() * 4;
					*/[/COLOR]
					int iBombardValue = GC.getUnitInfo(eUnit).getBombardRate() * ((GC.getUnitInfo(eUnit).isIgnoreBuildingDefense()) ? 3 : 2);
					[COLOR="Green"]//int iTotalBombardValue = 4 * iTotalBombard;[/COLOR]
					[COLOR="Green"]//int iNumBombardUnits = 2 * iTotalBombard / iBombardValue;[/COLOR]
					int iAIDesiredBombardFraction = std::max( 5, GC.getDefineINT("BBAI_BOMBARD_ATTACK_STACK_FRACTION")); [COLOR="Green"]/*default: 10*/[/COLOR]
					int iActualBombardFraction = (100 * 2 * iTotalBombard)/(iBombardValue * std::max(1, iNumOffensiveUnits));
					iActualBombardFraction = std::min(100, iActualBombardFraction);

					int iGoalTotalBombard = 200;
					int iTempBombardValue = 0;
					if (iTotalBombard < iGoalTotalBombard) [COLOR="Green"]//still less than 200 bombard points[/COLOR]
					{
						iTempBombardValue = iBombardValue * (iGoalTotalBombard + 4 * (iGoalTotalBombard - iTotalBombard));
						iTempBombardValue /= iGoalTotalBombard;
						[COLOR="Green"]//iTempBombardValue is at most (5 * iBombardValue)[/COLOR]
					}
					else
					{
						iTempBombardValue *= iGoalTotalBombard;
						iTempBombardValue /= std::min(2*iGoalTotalBombard, 2*iTotalBombard - iGoalTotalBombard);
					}

					if (iActualBombardFraction < iAIDesiredBombardFraction)
					{
						iBombardValue *= (iAIDesiredBombardFraction + 4 * (iAIDesiredBombardFraction - iActualBombardFraction));
						iBombardValue /= iAIDesiredBombardFraction;
						[COLOR="Green"]//new iBombardValue is at most (5 * old [/COLOR]iBombardValue)
					}
					else
					{
						iBombardValue *= iAIDesiredBombardFraction;
						iBombardValue /= std::max(1, iActualBombardFraction);
					}

					if (iTempBombardValue > iBombardValue)
					{
						iBombardValue = iTempBombardValue;
				}

				iValue += iBombardValue;
			}
		}
[COLOR="Green"]/*
		}
*/
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/[/COLOR]
		break;
 
I tried running the game with a debug dll but didn't even make it to the main menu, so there goes my ambition to actually hunt down bugs on my own in a more sophisticated manner than just playing until meeting a reproducable CTD and starting to randomly guess the cause afterwards.
I might be doing something wrong when compiling, so if there's someone who can provide me with a debug dll that actually works, it would be appreciated. I'm using Visual Studio 2003 as is, maybe a different environment can produce a working debug dll?

At any rate, I uploaded a new version yesterday:
* 1 Better AI revision, 2 for BUG and 3 for BULL.

Better BUG AI 0.90r (2010-04-23) @ mediafire
 
Hi, love this mod. But how do I get the Blue Marble mod working together with this? When I run BTS without the better bug AI, the blue marble mod is loaded. But when I use the better Bug AI shortcut to run BTS, I don't see the blue marble mod.
 
If it's just Blue Marble, setting NoCustomAssets to 0 in Better BUG AI .ini might work. I have no experience what that though.

edit: This will break some functionality if you also have an old BUG version (older than 4.4) installed in your CostumAssets!
 
It works. Thanks a lot for your help. It'd be nice if you can package Blue Marble into your mod pack, since it's so popular.
 
That will definitely never happen, I can't even access the art files without actually installing and I know installing doesn't just add customassets but also changes original game files. I have neither the intention nor the ability to add any of that special funcitonality to my installer, and while art files only might be possible, I simply don't want to, as it would greatly increase total file size, and even more importantly because I don't like and therefore don't use Blue Marble.
 
I simply don't want to, as it would greatly increase total file size, and even more importantly because I don't like and therefore don't use Blue Marble.

It makes sense about the extra file size, but what is there not to like about blue marble? It looks fantastic.
 
I've been assuming Blue Marble and BAT would both slow down the game, possibly considerably, so that's why I appreciate having BUG and Better AI without the graphics enhancements. Am I wrong about the speed loss?

I'm using a dual core processor PC but nothing special in my graphics hardware and when I get to the late game with 6 AI civs and me, things get slow as it is.
 
It makes sense about the extra file size, but what is there not to like about blue marble? It looks fantastic.

It's a matter of taste. I used it for a while to see what the fuss was about and then thankfully went back to a set of graphics where I didn't have to doublecheck whether that was a jungle or a forest every now and then. (Yeah, might have just been my system and/or graphics card and/or detail level, but the point is, some people do prefer the default graphics.)
 
In my case I'm pretty sure it's the graphics card, or rather the lack thereof. It just looks awful here, dark and grainy, and terrain is not as easy to make out.

In other news, Better AI r549 is called version 1.00a - looks like someone is pretty confident about recent changes; and there I was about to worry if our alphabet had enough letters for the 0.90 releases since we got as far as r with revision 548.
I hope I can merge in those changes tomorrow.
 
Thanks! When I copied your Assets over to BAT 2.2a's Assets (even after deleting BAT's Python folder, I noticed a bunch of your files that have an older date than BAT does. I only copied over your files that were newer. A bunch of these files are graphic .dds files, green bar, red bar, yellow bar, etc. but there are others also. I think sometimes it may just be that files copied from SVN have the copy date?

Is this anything you can comment on?
 
I can't say anything about art file dates, my art files come directly from BUG or BULL SVN, and I hope those files are the same as the one used in BAT. In any case, BAT should have all art files my mod has (plus a whole lot more), no need to copy over anything there iirc. The files should be identical.
 
[To merge Better BUG AI with BAT, install BAT, delete its Assets\Python\ folder and then copy Better BUG AI Assets over Bat Assets, overwriting all files that are included in both packs. see Combining Better BUG AI and BAT]
I finished comparing all Assets files that are present in both this mod and in BAT 2.2a.
  • Art: all files are identical.
  • Python: obviously, Better BUG AI files are newer.
  • Config: same
  • XML: there is one file where you should probably leave the one from BAT: XML\Units\CIV4UnitInfos.xml - it has bigger unit groups (back it up before overwriting or retrieve it again from the installer afterwards).
    BAT's XML\GameInfo\CIV4EraInfos.xml has an additional era "Futuristic", not sure if that's important - I guess not though, at least not without a tech of that era.
BAT's dll comes with the Global Warming mod, which is not present in Better BUG AI but GlobalDefinesAlt.xml disables all GW anyway.

-------------------
BULL & BUG updated:
Better BUG AI 1.00a (2010-05-05) @ mediafire
 
Very nice of you to look into the details of this. I have a feeling that BAT's CIV4EraInfos.xml and CIV4UnitInfos.xml files have to do with the Varietas Delectat within BAT.

CIV4UnitInfos.xml is a problem i think.

BAT has unit graphic changes and you have unit statistic changes so that would need a special merge, probably something you don't want to entertain as BETTER BUG AI is not really BETTER BAT AI.
 
EraInfos: Since there are no "Futuristic" techs here, overwriting does no harm.
Units: Overwriting will lose some UnitMeshGroups changes but that won't really matter for gameplay.

edit: 28 people downloaded the file and no one reported that I messed up the EraInfo merge? .. anyway fixed.
 

Attachments

  • Merged xml files for BAT + Better BUG AI.zip
    36.8 KB · Views: 930
Holy cr.p. Extremely nice of you to do this. I just grabbed your zip and will install those merged files. I was trying out WinMerge myself but I don't understand it properly yet.

There is one more duplicate BAT and Better BUG AI file but it is just the art for the roads. BAT has a road graphics XML file,

CIV4RouteModeslInfos

so I think I will just use the one from the original VD mod. I've been posting about some of this merge business over in the BUG forum.
It doesn't make sense to not use a Better AI, and yours is almost seamless with BAT, except for some of the difference I am discussing.
Thanks for your mod btw. It is to hard to use the original better AI because it's DLL wipes out the BULL changes and yours does not.
 
There are a lot more duplicate files but just like most of them, CIV4RouteModelInfos.xml files are identical in BAT and in Better BUG AI.

edit: For the new BUG bug fix (r2212) just download the new AttitudeUtil.py to your Better BUG AI\Assets\Python\BUG\ folder (overwrite).
 
Top Bottom