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

Report Questionable Behavior

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

  1. bestbrian

    bestbrian Just this guy, ya know?

    Joined:
    Oct 4, 2007
    Messages:
    3,344
    Location:
    NYC
    Is this the right place? Playing LoR Base Version, and the AI is still attaching GGs to Rams. Wasn't the AI altered to no longer attach GGs to Siege units? :confused:
     
  2. Cybah

    Cybah Emperor

    Joined:
    Jun 22, 2007
    Messages:
    1,480
    Well... just remove the ability to get the leader promotion from siege units.
     
  3. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    A bit late, I know :p

    5 cathegories with 5 civics each, that's 5^5=3125 possible combinations. Each of them has a culmulative effect that can easily be evaluated with some AI_civicValue-clone. But since we don't have time for that, we need to go by cathegory, select the best of the lot, and move on. The question is then, how to evalute the single civic?
    As long as one civic never has any effects that are somehow related to the effects of a different civic in a different cathegory, that's simple, and that is how AI_civicValue is written. If there is more than one civic with isNoCorporations, when selecting 2 or more all of them would get the full penalty, which is obviously not correct because the culmulative effect stays the same no matter how many isNoCorporations civics you run. Even a single civic that gives happiness from different sources would be incorrectly valuated: (2x +1:)) > (+2:))
    For the happiness/health from different sources I have a pretty elegant solution:
    I don't use AI_getH/HWeight() with a single iTempValue variable, instead I copied the code from that function to AI_civicValue and instead of using the same iHappy/iHealth value for all cities I use
    Code:
    int iHappy = pLoopCity->getAdditionalHappinessByCivic(eCivic, eBestReligion, iExtraPop, std::max(0, iMilitaryHappinessDefenders));
    Similar for health
    Code:
    int iHealth = pLoopCity->getAdditionalHealthByCivic(eCivic, iExtraPop, [COLOR="Green"]/* bVacuum*/[/COLOR] true);
    Spoiler :
    The functions
    int getAdditionalHappinessByCivic(CivicTypes eCivic, ReligionTypes eStateReligion = NO_RELIGION, int iExtraPop = 0, int iMilitaryHappinessUnits = -1) const;
    PHP:
    int CvCity::getAdditionalHappinessByCivic(CivicTypes eCivicReligionTypes eStateReligionint iExtraPopint iMilitaryHappinessUnits) const
    {
        if (
    eCivic == NO_CIVIC)
        {
            return 
    0;
        }

        
    CvCivicInfokCivic GC.getCivicInfo(eCivic);
        
    CvPlayerkOwner GET_PLAYER(getOwnerINLINE());
        if (
    eStateReligion == NO_RELIGION)
        {
            
    eStateReligion kOwner.getStateReligion();
        }
        
    int iHappy 0;
        
    int iI 0;

                
    //#1.a: Military Happiness
                
    if (kCivic.getHappyPerMilitaryUnit() != 0)
                {
                    if (
    iMilitaryHappinessUnits 0//default -1
                    
    {
                        
    iMilitaryHappinessUnits getMilitaryHappinessUnits();
                    }
                    
    iHappy += iMilitaryHappinessUnits kCivic.getHappyPerMilitaryUnit();
                }


                
    //#1.b: CivicPercentAnger and WarWearinessModifier
                
    if ((kCivic.getCivicPercentAnger() != && kOwner.getCivicPercentAnger(eCivictrue) != 0)
                    || (
    kCivic.getWarWearinessModifier() != && kOwner.getWarWearinessPercentAnger() != 0))
                {
                    
    //int CvCity::unhappyLevel(int iExtra) const
                    
    int iAngerPercent 0;

                    
    iAngerPercent += getOvercrowdingPercentAnger(iExtraPop);
                    
    iAngerPercent += getNoMilitaryPercentAnger();
                    
    iAngerPercent += getCulturePercentAnger();
                    
    iAngerPercent += getReligionPercentAnger();
                    
    iAngerPercent += getHurryPercentAnger(iExtraPop);
                    
    iAngerPercent += getConscriptPercentAnger(iExtraPop);
                    
    iAngerPercent += getDefyResolutionPercentAnger(iExtraPop);
                    
    int iOldWarWearinessAngerPercent getWarWearinessPercentAnger();
                    
    iAngerPercent += iOldWarWearinessAngerPercent;

                    for (
    iI 0iI GC.getNumCivicInfos(); iI++)
                    {
                        
    iAngerPercent += kOwner.getCivicPercentAnger((CivicTypes)iI, ((CivicTypes)iI == eCivic));
                    }

                    
    int iUnhappinessNow = ((iAngerPercent * (getPopulation() + iExtraPop)) / GC.getPERCENT_ANGER_DIVISOR());
                    
    iAngerPercent -= kOwner.getCivicPercentAnger(eCivictrue);

                    if (
    kOwner.getWarWearinessPercentAnger() != && kCivic.getWarWearinessModifier() != 0)
                    {
                        
    //int CvCity::getWarWearinessPercentAnger() const
                        
    int iNewWarWearinessAngerPercent getWarWearinessPercentAnger();

                        
    iNewWarWearinessAngerPercent *= std::max(0, (getWarWearinessModifier() + kOwner.getWarWearinessModifier() + kCivic.getWarWearinessModifier() + 100));
                        
    iNewWarWearinessAngerPercent /= 100;
                        
    iAngerPercent -= iOldWarWearinessAngerPercent;
                        
    iAngerPercent += iNewWarWearinessAngerPercent;
                    }
                    
    int iUnhappinessThen = ((iAngerPercent * (getPopulation() + iExtraPop)) / GC.getPERCENT_ANGER_DIVISOR());
                    
    iHappy += iUnhappinessNow iUnhappinessThen;
                }

                
    //#1.c: LargestCityHappiness
                
    if (kCivic.getLargestCityHappiness() != 0)
                {
                    
    //int CvCity::getLargestCityHappiness() const
                    
    if (findPopulationRank() <= GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getTargetNumCities())
                    {
                        
    iHappy += kCivic.getLargestCityHappiness();
                    }
                }

                
    //#1.d: BuildingHappinessChanges
                
    if (kCivic.isAnyBuildingHappinessChange())
                {
                    
    CvCivilizationInfokCivilization GC.getCivilizationInfo(getCivilizationType());
                    for (
    iI 0iI GC.getNumBuildingClassInfos(); iI++)
                    {
                        
    int iTempHappy kCivic.getBuildingHappinessChanges(iI);
                        if (
    iTempHappy != 0)
                        {
                            
    BuildingTypes eLoopBuilding = (BuildingTypes)kCivilization.getCivilizationBuildings(iI);
                            if (
    eLoopBuilding != NO_BUILDING)
                            {
                                
    iHappy += iTempHappy getNumBuilding(eLoopBuilding);
                            }
                        }
                    }
                }

                
    //#1.e: FeatureHappinessChanges
                
    if (kCivic.isAnyFeatureHappinessChange())
                {
                    
    CvPlotpLoopPlot;
                    for (
    iI 0iI GC.getNumFeatureInfos(); iI++)
                    {
                        
    int iTempHappy kCivic.getFeatureHappinessChanges(iI);

                        if (
    iTempHappy != 0)
                        {
                            
    int iCount 0;
                            for (
    int iJ 0iJ NUM_CITY_PLOTSiJ++)
                            {
                                
    pLoopPlot plotCity(getX_INLINE(), getY_INLINE(), iJ);

                                if (
    pLoopPlot != NULL)
                                {
                                    if (
    pLoopPlot->getFeatureType() == (FeatureTypes)iI)
                                    {
                                        
    iCount++;
                                    }
                                }
                            }
                            
    iHappy += iTempHappy iCount;
                        }
                    }
                }

                
    //#1.f: Religious Happiness
                
    if (kCivic.getStateReligionHappiness() != || kCivic.getNonStateReligionHappiness() != 0)
                {
                    for (
    iI 0iI GC.getNumReligionInfos(); iI++)
                    {
                        if (
    isHasReligion((ReligionTypes)iI))
                        {
                            if ((
    ReligionTypes)iI == eStateReligion /* redundant? -> */ && (ReligionTypes)iI != NO_RELIGION)
                            {
                                
    iHappy += kCivic.getStateReligionHappiness();
                            }
                            else
                            {
                                
    iHappy += kCivic.getNonStateReligionHappiness();
                            }
                        }
                    }
                }

        return 
    iHappy;
    }
    int getAdditionalHealthByCivic(...) const;[/PHP]


    The other problem: If the culmulative effects of two civics' effects have a certain value, then the culmulative value of the effects of the single civic's effect should be identical to that.
    ie: 2 civics both are isNoForeignTrade. The combined penalty value for that single effect they cause is a certain number. My conclusion: The penality for each of those civics therefore has to be half of the value of the combination.
    original:
    PHP:
        iValue += -((kCivic.isNoForeignTrade()) ? (iConnectedForeignCities 3) : 0);
    new (first part):
    PHP:
        //#3: Trade
        
    if (isNoForeignTrade())
        {
            if (
    kCivic.isNoForeignTrade())
            {
                if (!
    bCompleteVacuum//<- always true, I gave up on complete vacuum
                
    {
                    
    iValue -= (iConnectedForeignCities 3)/(getNoForeignTradeCount());
                }

                
    //(...etc)
    Similar for all other enabling/disabling civic properties.

    Happiness: if 2 civics give +1:) each, then each civic gets half the value a single civic would have gotten for +2:)

    That should give not just usable but correct values the the civics of a single cathegory if the civic selection in the other cathegories stays the same. Since that can't be guaranteed the loop with AI_bestCivic might have to run more than once, which might be a bit expensive but it should be ok. :p

    Before I commit that, are there any obvious flaws in my thought process?
     
  4. Afforess

    Afforess The White Wizard

    Joined:
    Jul 31, 2007
    Messages:
    12,239
    Location:
    Austin, Texas
    Not that I can see. Very interesting work.
     
  5. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    Just to let you know, I will look at it. Eventually .. I hope.

    What version of LoR? Could you enter debug mode and tell me what unitAIs the units that left the city are running?

    "Base Version"?
    The AI should no longer attach GGs to units that can't kill while attacking, like BTS siege units. If that siege unit can, the next lines are moot.

    PHP:
    if( pLoopUnit->combatLimit() == 100 )
    This check is in the SDK code (CvUnitAI::AI_lead()) was added with revision 129, date May 16th. If you're using an older version (like 0.9.8d+ which is revision 103 from March 11th) then I guess you're just not up-to-date.
     
  6. bestbrian

    bestbrian Just this guy, ya know?

    Joined:
    Oct 4, 2007
    Messages:
    3,344
    Location:
    NYC
    Admiral Armada created a Base Version of LoR that just updates things like RevDCM, BUG, and such, and doesn't add additional mods. I don't what revision he's using, but obviously, it would appear to be an older one if I'm still seeing GGs attached to Capped Rams. :)

    Thanks for the reply.
     
  7. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    Actually if you're using AA's version, tell him and let him look at it. I would have bet he used the very latest revision ..
     
  8. Axios

    Axios Warlord

    Joined:
    Oct 19, 2009
    Messages:
    126
    Location:
    Italy
    In my last two game (bot Warlord level, Hemispheres, normal size) I have noticed that AI research of "metal casting" about in 1300AD or 1500AD (too late!!!), and even when research it doesn't build forges. So it doesn't benefit of forges.

    Is it possible that BBAI 1.00 that introduced city AI -> "Buildings with negative health effects are now strongly avoided if city has health problems" have damaged metal casting research and forge creation?

    I will post detailed screenshots as soon I will login on my game pc.

    Thanks in advance for replies.
     
  9. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    If the city already has health problems then yes I'm sure forges are being avoided. Even worse in my Better BUG AI where unhealthiness can make it completely impossible for the AI to even consider constructing a building.

    edit: the relevant code is in CvCityAI::AI_buildingValueThreshold, just search down for "(iFocusFlags & BUILDINGFOCUS_HEALTHY)"
     
  10. Axios

    Axios Warlord

    Joined:
    Oct 19, 2009
    Messages:
    126
    Location:
    Italy
    Cities were not in unhealtiness. They have min +2 health before the limit.
    However there is a way to modify xml files to prioritize metal casting and forges?
    In techinfo there is an "aiweight" that is set to "0" in all techs. If I put it to "10" on "metal casting" it will be useful or not?

    If the AI doesn't build forges put themselves behind human player because they lost the +25% hammer that penalize entire production.

    Thanks for the reply.

    PS: i don't have the ability to recompile the dll because i'm not a programmer. So I can only modify my xml files.
     
  11. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    If a building is not built, then that normally means there was not enough to gain from it.
    Teching is a different issue, jdog wanted to do something for it too but it doesn't look like that's going to happen.
    Aiweight is added directly to techValue without any modifications so yes, you can use that, something like 100 should have some effect.
     
  12. Axios

    Axios Warlord

    Joined:
    Oct 19, 2009
    Messages:
    126
    Location:
    Italy
    Thanks for the reply. Regarding tech I will try to add 100 to aiweight.

    Regarding forge: +25% hammer I think is always useful.... Maybe AI evalute this bonus in a different way....

    Edit: also in CIV4BuildingInfos.xml there is an aiweight for every building.... and is set to 0 for all buildings. I try to modify it.

    At this point I think that can be a good idea try to determinate a list of aiweight for techs and buildings. It will be wonderful if we can create a common list with all personal experience.

    When I have a bit of time I will try to elaborate my list..

    Don't understand why Firaxis first and Jdog after left blank this aiweight....

    I know that doesn't exist a "perfect" path for techs and buildings but I think that a general list can help.
     
  13. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    Very hammer-poor cities will not gain many extra hammers, so the building value will be low. The building is still useful because the engineer would give +2:hammers: but I doubt the AI knows that.
     
  14. Axios

    Axios Warlord

    Joined:
    Oct 19, 2009
    Messages:
    126
    Location:
    Italy
    Yes, but I don't think that in all cities of an empire is normal that ai don't build one only forge....
     
  15. Munch

    Munch Benevolent Despot

    Joined:
    May 25, 2006
    Messages:
    2,081
    In my current game, I am at war with Gandhi, and on his coast I have a Galley ready to pillage his fishing boats, but which also happens to contain two axemen. Gandhi just moved three workers to improve a coastal tile I pillaged earlier, clearly not considering the proximity of a potentially troop-carrying naval unit. See screenshot:



    I am using my own mod, but I have not played with the code regarding decisions about moving units.
     
  16. karadoc

    karadoc AI programmer

    Joined:
    Oct 3, 2005
    Messages:
    1,568
    Location:
    Australia
    In the game I've been playing, the AI players are ridiculously slow at getting rifling. They seem to prefer to research democracy, and then research all the way to the assembly line before backfilling the techs to get rifling.

    In my opinion, rifling is a very important tech, both for defence and offense. I think it's a great mistake to leave it so late. It is especially weird because the AI seems to put a high priority on getting nationalism as soon as possible &#8212; presumably for the draft; but without rifling, drafting is no where near as powerful.
     
  17. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    @Munch: a problem with danger or danger cache. I think I've seen this reported before so I think this isn't new at least. I have to check if units that are currently cargo are never considered for plot danger at all or if this is just a caching problem.

    @karadoc: This is a known problem as well, Rifling should be interesting for all leaders but because it only has military flavor, non-militaristic peaceful leaders often skip it. You can fix this on your own by reducing flavor and adding aiweight for the technology. If something can be done on the SDK side, idk.
     
  18. nfw

    nfw King

    Joined:
    Aug 31, 2010
    Messages:
    733
    Does Better AI change the declare war logic? Ramesses has been friendly with me for the longest time, then he declared war on Justin, and a few turns later he asked me to join but I declined as I was fighting Shaka.

    Then out of the blue, a few turns after that he declared war on me, my power rating is 1.3 time of his. It wasn't a big deal as I was going to backstab him any way. This is the latest version of LoR btw and I have no vassal.

    Not the first time I have seen this either, Cyrus did the exact same thing in my previous game.
     
  19. Graptor

    Graptor Chieftain

    Joined:
    Jul 11, 2013
    Messages:
    1
    Using 1.01 which I just downloaded yesterday on otherwise Vanilla BTS, the AIs seem *really*, absurdly raze-happy. I hadn't really realized the extent of it, since most of it was happening on the other side of the map, until I invaded Suleiman and discovered that in a recent war Frederick had razed both Suleiman's capital city of Istanbul AND the smaller city that he'd built the Hanging Gardens in. This happened in 1540 A.D., and nobody even had gunpowder yet that I'm aware of.

    I retired to get a replay and went through it and counted up all the razes:

    Settings: Warlord (Stop sniggering, I'm new to Civ!) Terra, Huge, Ancient, Marathon, Tropical, Low Sealevel, Cylindrical, Standard Resources. 13 AIs, 1 Player.

    Checkboxes Enabled: Raging Barbarians, No Tech Brokering, Permanent Alliances, New Random Seed on Reload.

    Victories: Conquest, Space Race, Diplomatic.

    Anyway.

    Out of 70 total city captures, 48 of them were razed.

    It breaks down thusly:

    Barbarians Razing captured AI Player City: 14
    AI Player razing Barbarian City: 10
    AI Player razing AI Player City: 24

    Barbarian Keeping AI Player City: 1
    AI Player Keeping Barbarian City: 2
    AI Player Recapturing City from Barbarians: 1

    Player (Me) Keeping AI Player City: 15
    AI Player Re-Capturing City from Player: 1
    Player Re-Re-Capturing City from AI Player: 2 (Bloody Apostolic Palace).

    If you remove my 17 captures, and the 2 times an AI Player re-captured a city they'd lost, you end up with these statistics:

    48 of 51 times (94.118%) a city was initially captured by an AI, it was razed. Detailed Breakdown:

    Barbarians Razed 14 of 15 (93.333%) cities they captured. (Many of these are in the New World, colonization efforts there are not going well for the AIs. I'm too busy trying to take their stuff to worry about it myself.)

    AI Players razed 10 of 12 (83.333%) Barbarian cities they captured. (Both non razes were my Vassal, Izzy...who DID raze the third one she got.)

    AI Players razed 24 of 24 (100%) of cities they captured from another AI Player.

    I only had one city taken from me, by the person I took it from. In a different branch I ended up backing up to a (slightly) earlier save on (not ENTIRELY on purpose...just mostly), Cathy took two cities I'd captured from Pericles off me and razed them both.

    And they're apparently razing World Wonders and Capitals as well. Even in wars that are distinctly one sided (There was one point if I remember right where Cathy razed three cities from two civs in a row).

    Edit: Attached Replay.
     

    Attached Files:

  20. Yxklyx

    Yxklyx King

    Joined:
    May 7, 2008
    Messages:
    869
    I don't recall ever seeing this behavior but I'm running 1.02a with BTS.
     

Share This Page