1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

Specific Bug Reports

Discussion in 'Civ4 - Better AI' started by Iustus, Jan 25, 2007.

  1. sjodster

    sjodster Chieftain

    Joined:
    Mar 29, 2010
    Messages:
    96
    There is an undocumented change in CvPlayerAI::AI_calculateTotalBombard(DomainTypes eDomain) circa line 20152. Code was added that gives an extra 50% value to bombard units that ignore building defense.

    Original BTS code:

    Code:
    			if (iBombardRate > 0)
    			{
    				iTotalBombard += iBombardRate * getUnitClassCount((UnitClassTypes)iI);
    			}
    			
    
    BetterAI code:

    Code:
    				if (iBombardRate > 0)
    				{
    					if( GC.getUnitInfo(eLoopUnit).isIgnoreBuildingDefense() )
    					{
    						iBombardRate *= 3;
    						iBombardRate /= 2;
    					}
    
    					iTotalBombard += iBombardRate * getUnitClassCount((UnitClassTypes)iI);
    				}
    
     
  2. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    ad City Razing: I believe it was no bug, the AI really is not supposed to use the leaderhead's razeprob on cities that have a closeness > 0. The madness should at least be heavily reduced, that massive razing hurts too much.

    (bullai r105)

    related: I got an access violation here:
    Code:
                     pCity->doTask(TASK_RAZE);
                     logBBAI("    Player %d (%S) decides to to raze city %S!!!", getID(), getCivilizationDescription(0), pCity->getName().GetCString() );
    The reason is simple: the city no longer exist when you try to get the CString of its name. Reversing the order fixes that.


    Everything you said is correct. Only one comment: reserve and collateral are both defender roles too.
    But even if that wasn't so, (pLoopPlot->getNumVisibleEnemyDefenders(this) > 0) makes the other check obsolete and even costs the same.
    I also vote for the complete removal of the entire
    if (pLoopPlot->isVisibleEnemyUnit(this) || (pLoopPlot->isCity() && AI_potentialEnemy(pLoopPlot->getTeam(), pLoopPlot)))
    (functionally identical, less code, (minimally) better performance)


    That's just a different style. jdog doesn't want to have incomplete code blocks between start and END.
     
  3. Cybah

    Cybah Emperor

    Joined:
    Jun 22, 2007
    Messages:
    1,480
  4. kernok

    kernok Warlord

    Joined:
    Dec 7, 2005
    Messages:
    161
    Location:
    paris
    Hi guys

    First of all: thank you for this incredible mod, it's a must have really.
    I don't know if this "bug" has been discussed here before neither if it's really a bug but here it is:
    During my last BetterAI game I've signed a pact of defense with mighty Portugal. After a couple of turns Mayas decided to run a war against my lusitanians friends. I've been naturaly involved in this war thus the pact of defense worked well but... as the war was being declared the pact was being removed in the same time!
    Is this normal?
     
  5. EmperorFool

    EmperorFool Deity

    Joined:
    Mar 2, 2007
    Messages:
    9,633
    Location:
    Mountain View, California
    Yes, the pact means that should either partner be attacked, the other will DoW the attacker. Any DoW by either partner on any player automatically dissolves the pact. Your retaliatory DoW--necessitated by the pact itself--caused the pact to be canceled.
     
  6. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    If you want to keep your Defensive Pacts you can edit BBAI_Game_Options_GlobalDefines.xml: set BBAI_DEFENSIVE_PACT_BEHAVIOR to 1.
     
  7. kernok

    kernok Warlord

    Joined:
    Dec 7, 2005
    Messages:
    161
    Location:
    paris
    Thank you for your reponses guys!
    So you think PoD should break itself automatically in case of one or other civ involved in the pact declaring a war to another civ (I suppose this is what you call "DoW")?
    Thus it has been a specific change made in Better AI mod?

    Anyway my guess is that if you think it's not a bug and it's better to have it this way... so do I!;)
     
  8. EmperorFool

    EmperorFool Deity

    Joined:
    Mar 2, 2007
    Messages:
    9,633
    Location:
    Mountain View, California
    The normal game without BetterAI breaks defensive pacts when either member makes an aggressive move, a declaration of war (DoW). This is not a bug, nor is it changed by BetterAI normally.

    BetterAI does add an option to allow a defensive pact to remain in place when a member DoWs in response to the other member being attacked, and I think there's a third option to allow DPs to survive even preemptive strikes.
     
  9. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    targetSize calculation for cities is a bit broken.

    original:
    Code:
    	int iHealth = goodHealth() - badHealth();
    	int iTargetSize = std::min(iGoodTileCount, getPopulation()+(happyLevel()-unhappyLevel()));
    	iTargetSize = std::min(iTargetSize, 1 + getPopulation() + iHealth);
    Better AI:
    Code:
    	int iHealth = goodHealth() - badHealth();
    [COLOR="Green"]/************************************************************************************************/
    /* BETTER_BTS_AI_MOD                      08/30/09                                jdog5000      */
    /*                                                                                              */
    /* City AI                                                                                      */
    /************************************************************************************************/[/COLOR]
    	int iTargetSize = iGoodTileCount;
    
    	if( getEspionageHealthCounter() > 0 )
    	{
    		iTargetSize = std::min(iTargetSize, 2+ getPopulation());
    	}
    	else
    	{
    		iTargetSize = std::min(iTargetSize, 2 + getPopulation() + (iHealth)/2);
    	}
    
    	if( iTargetSize < getPopulation() )
    	{
    		iTargetSize = std::max(iTargetSize, getPopulation() - (AI_countWorkedPoorTiles()/2));
    	}
    	
    	[COLOR="Green"]// Target city size should not be perturbed by espionage, other short term effects[/COLOR]
    	if( getEspionageHappinessCounter() > 0 )
    	{
    		iTargetSize = std::min(iTargetSize, getPopulation());
    	}
    	else
    	{
    		iTargetSize = std::min(iTargetSize, getPopulation()+(happyLevel()-unhappyLevel()));
    	}
    [COLOR="Green"]/************************************************************************************************/
    /* BETTER_BTS_AI_MOD                       END                                                  */
    /************************************************************************************************/[/COLOR]
    What I think is right:
    Code:
    	int iHealth = goodHealth() - badHealth();
    [COLOR="Green"]/********************************************************************************/
    /*	Better Evaluation							09.03.2010		Fuyu		    */
    /********************************************************************************/[/COLOR]
    	[COLOR="Gray"]int iHappyAdjust = 0;[/COLOR] [COLOR="Green"]// <-Don't redefine these variables where are already defined.[/COLOR]
    	[COLOR="Gray"]int iHealthAdjust = 0;[/COLOR] [COLOR="Green"]// <-Don't redefine these variables where are already defined.[/COLOR]
    	if (getProductionBuilding() != NO_BUILDING)
    	{
    		iHappyAdjust += getAdditionalHappinessByBuilding(getProductionBuilding());
    		iHealthAdjust += getAdditionalHealthByBuilding(getProductionBuilding());
    	}
    [COLOR="Green"]/********************************************************************************/
    /*	BE	END																		*/
    /********************************************************************************/
    /************************************************************************************************/
    /* BETTER_BTS_AI_MOD                      09/02/10                         jdog5000 & Fuyu      */
    /*                                                                                              */
    /* City AI                                                                                      */
    /************************************************************************************************/[/COLOR]
    	int iTargetSize = iGoodTileCount;
    
    	[COLOR="Green"][s]//iTargetSize = std::min(iTargetSize, 2 + getPopulation() + goodHealth() - badHealth() + getEspionageHealthCounter() + std::max(0, iHealthAdjust));[/s][/COLOR]
    	iTargetSize -= std::max(0, (iTargetSize - (1 + getPopulation() + goodHealth() - badHealth() + getEspionageHealthCounter() + std::max(0, iHealthAdjust))) / 2);
    	
    	if( iTargetSize < getPopulation() )
    	{
    		iTargetSize = std::max(iTargetSize, getPopulation() - (AI_countWorkedPoorTiles()/2));
    	}
    	
    	[COLOR="Green"]// Target city size should not be perturbed by espionage, other short term effects[/COLOR]
    	iTargetSize = std::min(iTargetSize, getPopulation() + (happyLevel() - unhappyLevel() + getEspionageHappinessCounter() + std::max(0, iHappyAdjust)));
    [COLOR="Green"]/************************************************************************************************/
    /* BETTER_BTS_AI_MOD                       END                                                  */
    /************************************************************************************************/[/COLOR]
    Once again it was Afforess how noticed that the AI isn't focusing enough on city growth, I believe that might have been one reason.
     
  10. Ninja2

    Ninja2 Great Engineer

    Joined:
    Nov 17, 2005
    Messages:
    1,142
    Location:
    Denmarkia
    Is anyone collecting these issues and updating BBAI?
     
  11. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    I am collecting everything and updating Better BUG AI, which will supersede replace Better BTS AI for a while at least if no one else picks up Better BTS AI, now that jdog left with very little intentions to come back won't be available again anytime soon.
     
  12. Afforess

    Afforess The White Wizard

    Joined:
    Jul 31, 2007
    Messages:
    12,239
    Location:
    Austin, Texas
    Fuyu, there is a function that computes the target city size (called from CvGameTextMgr), so it would be nice to update that function, and call it instead of repeating the same code in 3 places in CvCityAI.
     
  13. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    Yes I noticed and replaced one of these occurances. For updateBestPlotBuild I left it was it is though, since this function goes to greater length to calculate H/Hadjust values than the standard AI_getTargetSize().
     
  14. EmperorFool

    EmperorFool Deity

    Joined:
    Mar 2, 2007
    Messages:
    9,633
    Location:
    Mountain View, California
    Wow, really? I am out of town this weekend and it's sad to hear this? Is this a Civ5 things or a "i'm done with kidding thing?
     
  15. Lord Tirian

    Lord Tirian Erratic Poster

    Joined:
    Nov 30, 2007
    Messages:
    2,724
    Location:
    Liverpool, UK
    It's neither - it's Real Life (TM) eating his free time; see here.

    Cheers, LT.
     
  16. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    I might have missed/ignored the "this fall" part but the rest of his post was so formal it just sounded like a resignation letter. But I hope I'm wrong and that he'll be back in winter.
     
  17. Cybah

    Cybah Emperor

    Joined:
    Jun 22, 2007
    Messages:
    1,480
    Someone really should continue his work in the meanwhile.
     
  18. Cybah

    Cybah Emperor

    Joined:
    Jun 22, 2007
    Messages:
    1,480
    There are some really stupid war decisions in the current version, especially within the first rounds. I've seen the AI "rushing" with 2 archers and failing. The AI should have at least X power before any war get declared against anyone.

    Can someone take a look at it?
     
  19. Afforess

    Afforess The White Wizard

    Joined:
    Jul 31, 2007
    Messages:
    12,239
    Location:
    Austin, Texas
    I agree. The AI seemed to try to start a war wayyy too early. I added some code to block it. Feel free to nitpick it:

    Code:
    void CvTeamAI::AI_doWar()
    {
    ...
    	// if no war plans, consider starting one!
    	if (getAnyWarPlanCount(true) == 0 || iEnemyPowerPercent < 45)
    	{
    		bool bAggressive = GC.getGameINLINE().isOption(GAMEOPTION_AGGRESSIVE_AI);
    /************************************************************************************************/
    /* Afforess	                  Start		 07/27/10                                               */
    /*                                                                                              */
    /* Avoid War when there is plenty of room left                                                  */
    /************************************************************************************************/
    		if (GET_PLAYER(getLeaderID()).getCurrentEra() < GC.getNumEraInfos() / 2)
    		{
    			if (GET_PLAYER(getLeaderID()).getNumCities() < GC.getMapINLINE().getWorldSize() + 1)
    			{
    				return;
    			}
    			CvCity* pCapital = GET_PLAYER(getLeaderID()).getCapitalCity();
    			//bool bEarlyGame = (100 * GC.getGameINLINE().getElapsedGameTurns()) / std::max(1, GC.getGameINLINE().getEstimateEndTurn()) < 20;
    			int iAverage = GC.getMapINLINE().getGridWidthINLINE() + GC.getMapINLINE().getGridHeightINLINE() / 2;
    			bool bPrimaryArea = true;
    			if (pCapital != NULL)
    				bPrimaryArea = AI_isPrimaryArea(pCapital->area());
    			int iThreshold = bAggressive ? 40 : 30;
    			if (pCapital != NULL)
    			{
    				if (GC.getMapINLINE().percentUnoccupiedLand(true, true, true, bPrimaryArea ? pCapital->area() : NULL, /*bEarlyGame ?  */iAverage / 5/* : -1*/, bPrimaryArea ? pCapital->plot() : NULL) > iThreshold)
    				{
    					return;
    				}
    			}
    		}
    /************************************************************************************************/
    /* Afforess	                     END                                                            */
    /************************************************************************************************/		
    		int iFinancialTroubleCount = 0;
    		int iDaggerCount = 0;
    ...
    }
    
    Which requires a new function in CvMap:

    Code:
    /************************************************************************************************/
    /* Afforess	                  Start		 07/27/10                                               */
    /*                                                                                              */
    /*                                                                                              */
    /************************************************************************************************/
    int CvMap::percentUnoccupiedLand(bool bExcludeWater, bool bIncludeBarbarian, bool bExcludePeaks, CvArea* pArea, int iRange, CvPlot* pRangeFromPlot)
    {
    	int iNumTiles = 0;
    	int iNumTilesValid = 0;
    	for (int iI = 0; iI < numPlotsINLINE(); iI++)
    	{
    		CvPlot* pLoopPlot = plotByIndexINLINE(iI);
    		if (!pLoopPlot->isWater() || !bExcludeWater)
    		{
    			if (pArea == NULL || pLoopPlot->area() == pArea)
    			{
    				if (!pLoopPlot->isPeak() || !bExcludePeaks)
    				{
    					if ((iRange == -1 || pRangeFromPlot == NULL) || (plotDistance(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), pRangeFromPlot->getX_INLINE(), pRangeFromPlot->getY_INLINE()) <= iRange))
    					{
    						iNumTiles++;
    						if (pLoopPlot->getOwnerINLINE() == NO_PLAYER || (bIncludeBarbarian && pLoopPlot->getOwnerINLINE() == BARBARIAN_PLAYER))
    						{
    							iNumTilesValid++;
    						}
    					}
    				}
    			}
    		}
    	}
    	if (iNumTiles > 0)
    	{
    		GC.getGame().logMsg("%d Tiles were in %d Range, out of %d total in range tiles", iNumTilesValid, iRange, iNumTiles);
    		return (iNumTilesValid * 100) / iNumTiles;
    	}
    	return 0;
    }		
    /************************************************************************************************/
    /* Afforess	                     END                                                            */
    /************************************************************************************************/

    CvMap.h

    Code:
    /************************************************************************************************/
    /* Afforess	                  Start		 07/27/10                                               */
    /*                                                                                              */
    /*                                                                                              */
    /************************************************************************************************/
    	int percentUnoccupiedLand(bool bExcludeWater = true, bool bIncludeBarbarian = false, bool bExcludePeaks = true, CvArea* pArea = NULL, int iRange = -1, CvPlot* pRangeFromPlot = NULL);
    /************************************************************************************************/
    /* Afforess	                     END                                                            */
    /************************************************************************************************/
     
  20. Cybah

    Cybah Emperor

    Joined:
    Jun 22, 2007
    Messages:
    1,480
    Thanks, here is another code that differs from AND:

    (cvteam.cpp)

    PHP:
    DenialTypes CvTeamAI::AI_embassyTrade(TeamTypes eTeam) const
    ...
    if (
    eAttitude <= GC.getLeaderHeadInfo(kLoopPlayer.getPersonalityType()).getOpenBordersRefuseAttitudeThreshold())

    AD:

    PHP:
    DenialTypes CvTeamAI::AI_embassyTrade(TeamTypes eTeam) const
    ...
    if (
    eAttitude <= GC.getLeaderHeadInfo(kLoopPlayer.getPersonalityType()).getEmbassyRefuseAttitudeThreshold())
     

Share This Page