Version 0.82 discussion thread

Greatly reduced AI spies pillaging random improvements
- AI spies will now go after bonus tiles, very rarely target non-bonus improvements

In a recent game of mine the AI destroyed mature Towns around my capital several times forcing me to ramp up espionage a bit and place spies around to attempt to block them. Being on marathon the turns required to regrow the towns had a nice sting for my beuracracy capital.

I found this to be quite annoying at the least, and effective to an extent, and am wondering if Mature Towns are given higher priority than other non-bonus improvements or how they compare to bonuses priority wise.

Love all your work jdog, thanks a ton!

EDIT to clarify this was with a prior version not .82 and I am wondering if we will still see it happen
 
Wow what mapscript and what mapsize is that, Poppis? Looks awesome! :goodjob:

I had a look at the city and I can't think of a reasonable explanation for that governor behaviour.

It's a huge size PerfectWorld2. And yeah, it turned out pretty unique, having the old world continent split in half by a wall of peaks.

Anyway, I don't know anything about modding, but I was wondering if the road on the non-riversiade tile has anything to do with it:

- AI now considers value of mine/lumbermill + railroad when picking tile improvements whether railroad is in place or not

Maybe the AI thinks the non-riverside tile is better since you can railroad it, even thou I don't even have the railroad tech yet...
 
Maybe the AI thinks the non-riverside tile is better since you can railroad it, even thou I don't even have the railroad tech yet...

That's a pretty decent guess IMO. But I won't speculate. Probably need to wait for jdog's comment.
 
Maybe the AI thinks the non-riverside tile is better since you can railroad it, even thou I don't even have the railroad tech yet...
You don't need to have a road in a tile for being able to railroad it.....

My guess would probably be that the governor is simply skimming out the coin in the calculation for what configuration gets more hammers... as it has a tie, it probaly chooses the first one he gets ( dunno, this is pure speculation :p )
 
I've actually added in a UNITAI_MEDIC. But I think that if a modder isn't going to add a dedicated medic unit to the game, it's better not to use it as the default for any unit because then it will only do medic activities. Having a unit be changed to UNITAI_MEDIC when it promotes itself with a medic promotion makes sense though.

Planetfall has code for UnitAI switching upon promotion picking.
 
If you want to ruin a city with EP, an easy way is:

1. Destroy anti-EP buildings
2. Pick health or happy to attack (probably health since they'll have culture slider up).
3. Destroy all relevant buildings and poison water/foment. For health this is granary/aqueduct/harbor/hospital/grocer type buildings. Combined with poisoning water, it is actually possible to lock a city at pop 1 this way. From there you can pick off some culture buildings too (the biggies mostly) and if that city isn't very, very close to winning culture already, it isn't going to do so. A 1 pop city with 0 food surplus does not have the makings of generating a lot of anything.
 
How would I go about finding out whether or not techdiffusion is active and working? And in case I find out it doesn't, how do I enable it?
 
How would I go about finding out whether or not techdiffusion is active and working? And in case I find out it doesn't, how do I enable it?

Tech diffusion is active by default in better bts ai. It is activated or deactivated in the global defines .xml file. You could test by starting a new game and running with 100% gold for a few hundred turns. You should find that you eventually accumulate a few free beakers in techs you have not researched, if you open borders with lots of technologically superior AIs.
 
The dev version of 0.82 didn't have it on by default in the xml, but changing the TECH_DIFFUSION_ENABLE value to 1 (I hope that is what activates it) and TECH_DIFFUSION_WELFARE_THRESHOLD to 100 (which should have the effect that even the tech leader can get free beakers if other civs know a tech he doesn't, right?) never had any visible effects for me either.
My problem isn't so much that it doesn't work, it probably does all it should, I just don't see it. I'm probably looking in the wrong place, or it is well hidden ..
Then again I probably didn't see the "adjustment to research rate based on how many civs you have met which already know a tech" from plain BTS either..
 
My problem isn't so much that it doesn't work, it probably does all it should, I just don't see it. I'm probably looking in the wrong place, or it is well hidden ..

A way I notice its functioning is when AI civs refuse to trade for a tech I have because they would have nothing to gain, while having No Tech Brokering activated.
 
How would I go about finding out whether or not techdiffusion is active and working? And in case I find out it doesn't, how do I enable it?

Yeah, tech diffusion is a fairly hidden feature ... it's built off a hidden Civ4 feature and I haven't done anything to make it more visible. It'd be easy to add something to tech tooltips saying "Research Efficiency: 135%" or whatever for a given tech so you would know, but would that info be useful?

This information is available if you have entered the chipotle cheat code and hold down Ctrl or Shift (can't remember right now) while mousing over the scoreboard ... you'll see other information too though.

A way I notice its functioning is when AI civs refuse to trade for a tech I have because they would have nothing to gain, while having No Tech Brokering activated.

The AI says that under No Tech Brokering when it is close to getting a tech itself (where close is in fractions of beakers researched IIRC). It's better off finishing the tech so that it can then broker it. That shouldn't be related to Tech Diffusion.
 
The AI says that under No Tech Brokering when it is close to getting a tech itself (where close is in fractions of beakers researched IIRC). It's better off finishing the tech so that it can then broker it. That shouldn't be related to Tech Diffusion.

Over in the RevDCM forums, Phungus and I looked at that specific code and found that Tech Diffusion may have been altering it. The AI didn't consider how many beakers it had put into the tech, merely how far researched it had been. I don't know the differences between the Better AI Tech Diffusion and RevDCM's Tech Diffusion, so if they different, forgive me. I believe we worked up a fix over there.

Also, Jdog, I found that the AI does not correctly value buildings that unlock units. This only occurs with missionaries in base BTS, but in Mods where this occurs, it has disastrous effects. I added a switch statement which seems to really improve the AI in that respect, I'm sure you could further refine it but I thought it should be brought up. Here's the original code in CvCityAI:

Spoiler :
Code:
for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
                {
                    if (GC.getUnitInfo((UnitTypes)iI).getPrereqBuilding() == eBuilding)
                    {
                        if (kOwner.AI_totalAreaUnitAIs(area(), ((UnitAITypes)(GC.getUnitInfo((UnitTypes)iI).getDefaultUnitAIType()))) == 0)
                        {
                            iValue += iNumCitiesInArea;
                        }

                        iValue++;

                        ReligionTypes eReligion = (ReligionTypes)(GC.getUnitInfo((UnitTypes)iI).getPrereqReligion());
                        if (eReligion != NO_RELIGION)
                        {
                            //encouragement to get some minimal ability to train special units
                            if (bCulturalVictory1 || isHolyCity(eReligion) || isCapital())
                            {
                                iValue += (2 + iNumCitiesInArea);
                            }
                            
                            if (bCulturalVictory2 && GC.getUnitInfo((UnitTypes)iI).getReligionSpreads(eReligion))
                            {
                                //this gives a very large extra value if the religion is (nearly) unique
                                //to no extra value for a fully spread religion.
                                //I'm torn between huge boost and enough to bias towards the best monastery type.
                                int iReligionCount = GET_PLAYER(getOwnerINLINE()).getHasReligionCount(eReligion);
                                iValue += (100 * (iNumCities - iReligionCount)) / (iNumCities * (iReligionCount + 1));
                            }
                        }
                    }
                }

And here is my enhanced code:
Spoiler :
Code:
                for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
                {
                    if (GC.getUnitInfo((UnitTypes)iI).getPrereqBuilding() == eBuilding)
                    {
                        if (kOwner.AI_totalAreaUnitAIs(area(), ((UnitAITypes)(GC.getUnitInfo((UnitTypes)iI).getDefaultUnitAIType()))) == 0)
                        {
                            iValue += iNumCitiesInArea;
                        }

                        iValue++;
                        
                        /************************************************************************************************/
                        /* Afforess                      Start         01/06/10                                                */
                        /*                                                                                              */
                        /*                                                                                              */
                        /************************************************************************************************/
                        //This forces the AI to build neccessary buildings for units. 
                        bool bWarPlan = (GET_TEAM(getTeam()).getAnyWarPlanCount(true) > 0);
                        UnitAITypes eUnitAI = (UnitAITypes)(GC.getUnitInfo((UnitTypes)iI).getDefaultUnitAIType());
                        CvUnitInfo& kUnit = GC.getUnitInfo((UnitTypes)iI);
                        iTempValue = 0;
                        switch (eUnitAI)
                        {
                            case UNITAI_UNKNOWN:
                            break;
                            case UNITAI_ANIMAL:
                                iTempValue += kUnit.getCombat();
                                break;
                            case UNITAI_SETTLE:
                            case UNITAI_SETTLER_SEA:
                                iTempValue += 25;
                                break;
                            case UNITAI_WORKER:
                            case UNITAI_WORKER_SEA:
                                iTempValue += 10;
                                break;
                            case UNITAI_ATTACK:
                            case UNITAI_ATTACK_CITY:
                            case UNITAI_COLLATERAL:
                            case UNITAI_PILLAGE:
                            case UNITAI_RESERVE:
                            case UNITAI_COUNTER:
                            case UNITAI_CITY_DEFENSE:
                            case UNITAI_CITY_COUNTER:
                            case UNITAI_CITY_SPECIAL:
                            case UNITAI_ATTACK_SEA:
                            case UNITAI_RESERVE_SEA:
                            case UNITAI_ESCORT_SEA:
                            case UNITAI_ASSAULT_SEA:
                            case UNITAI_CARRIER_SEA:
                            case UNITAI_MISSILE_CARRIER_SEA:
                            case UNITAI_PIRATE_SEA:
                            case UNITAI_ATTACK_AIR:
                            case UNITAI_DEFENSE_AIR:
                            case UNITAI_CARRIER_AIR:
                            case UNITAI_MISSILE_AIR:
                            case UNITAI_PARADROP:
                            case UNITAI_ATTACK_CITY_LEMMING:
                                iTempValue += kUnit.getCombat() * 2;
                                if (bWarPlan)
                                    iTempValue += (kUnit.getCombat() * kUnit.getCombat() / 2);
                                break;
                            case UNITAI_EXPLORE:
                            case UNITAI_MISSIONARY:
                            case UNITAI_PROPHET:
                            case UNITAI_ARTIST:
                            case UNITAI_SCIENTIST:
                            case UNITAI_GENERAL:
                            case UNITAI_MERCHANT:
                            case UNITAI_ENGINEER:
                            case UNITAI_SPY:
                            case UNITAI_SPY_SEA:
                            case UNITAI_MISSIONARY_SEA:
                            case UNITAI_EXPLORE_SEA:
                                iTempValue += 10;
                                break;
                            case UNITAI_ICBM:
                                iTempValue += 100;
                                if (bWarPlan)
                                    //A real nuke has a nuke range of 1, so this really adds 100 more.
                                    iTempValue += kUnit.getNukeRange() * 100;
                                break;
                        }
                        iValue += iTempValue;
                        /************************************************************************************************/
                        /* Afforess                         END                                                            */
                        /************************************************************************************************/        

                        ReligionTypes eReligion = (ReligionTypes)(GC.getUnitInfo((UnitTypes)iI).getPrereqReligion());
                        if (eReligion != NO_RELIGION)
                        {
                            //encouragement to get some minimal ability to train special units
                            if (bCulturalVictory1 || isHolyCity(eReligion) || isCapital())
                            {
                                iValue += (2 + iNumCitiesInArea);
                            }
                            
                            if (bCulturalVictory2 && GC.getUnitInfo((UnitTypes)iI).getReligionSpreads(eReligion))
                            {
                                //this gives a very large extra value if the religion is (nearly) unique
                                //to no extra value for a fully spread religion.
                                //I'm torn between huge boost and enough to bias towards the best monastery type.
                                int iReligionCount = GET_PLAYER(getOwnerINLINE()).getHasReligionCount(eReligion);
                                iValue += (100 * (iNumCities - iReligionCount)) / (iNumCities * (iReligionCount + 1));
                            }
                        }
                    }
                }

This new code should have no real effect on regular BTS games, but the BTS AI should be as flexible as possible, so...
 
Over in the RevDCM forums, Phungus and I looked at that specific code and found that Tech Diffusion may have been altering it. The AI didn't consider how many beakers it had put into the tech, merely how far researched it had been. I don't know the differences between the Better AI Tech Diffusion and RevDCM's Tech Diffusion, so if they different, forgive me. I believe we worked up a fix over there.

There's a big difference between the two, in RevDCM really backwards civs get free beakers while in BBAI its simply a research rate boost. So the RevDCM version would definitely run into that problem, glad you guys fixed that!

Also, Jdog, I found that the AI does not correctly value buildings that unlock units. This only occurs with missionaries in base BTS, but in Mods where this occurs, it has disastrous effects. I added a switch statement which seems to really improve the AI in that respect, I'm sure you could further refine it but I thought it should be brought up. Here's the original code in CvCityAI:

Spoiler :
Code:
for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
                {
                    if (GC.getUnitInfo((UnitTypes)iI).getPrereqBuilding() == eBuilding)
                    {
                        if (kOwner.AI_totalAreaUnitAIs(area(), ((UnitAITypes)(GC.getUnitInfo((UnitTypes)iI).getDefaultUnitAIType()))) == 0)
                        {
                            iValue += iNumCitiesInArea;
                        }

                        iValue++;

                        ReligionTypes eReligion = (ReligionTypes)(GC.getUnitInfo((UnitTypes)iI).getPrereqReligion());
                        if (eReligion != NO_RELIGION)
                        {
                            //encouragement to get some minimal ability to train special units
                            if (bCulturalVictory1 || isHolyCity(eReligion) || isCapital())
                            {
                                iValue += (2 + iNumCitiesInArea);
                            }
                            
                            if (bCulturalVictory2 && GC.getUnitInfo((UnitTypes)iI).getReligionSpreads(eReligion))
                            {
                                //this gives a very large extra value if the religion is (nearly) unique
                                //to no extra value for a fully spread religion.
                                //I'm torn between huge boost and enough to bias towards the best monastery type.
                                int iReligionCount = GET_PLAYER(getOwnerINLINE()).getHasReligionCount(eReligion);
                                iValue += (100 * (iNumCities - iReligionCount)) / (iNumCities * (iReligionCount + 1));
                            }
                        }
                    }
                }

And here is my enhanced code:
Spoiler :
Code:
                for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
                {
                    if (GC.getUnitInfo((UnitTypes)iI).getPrereqBuilding() == eBuilding)
                    {
                        if (kOwner.AI_totalAreaUnitAIs(area(), ((UnitAITypes)(GC.getUnitInfo((UnitTypes)iI).getDefaultUnitAIType()))) == 0)
                        {
                            iValue += iNumCitiesInArea;
                        }

                        iValue++;
                        
                        /************************************************************************************************/
                        /* Afforess                      Start         01/06/10                                                */
                        /*                                                                                              */
                        /*                                                                                              */
                        /************************************************************************************************/
                        //This forces the AI to build neccessary buildings for units. 
                        bool bWarPlan = (GET_TEAM(getTeam()).getAnyWarPlanCount(true) > 0);
                        UnitAITypes eUnitAI = (UnitAITypes)(GC.getUnitInfo((UnitTypes)iI).getDefaultUnitAIType());
                        CvUnitInfo& kUnit = GC.getUnitInfo((UnitTypes)iI);
                        iTempValue = 0;
                        switch (eUnitAI)
                        {
                            case UNITAI_UNKNOWN:
                            break;
                            case UNITAI_ANIMAL:
                                iTempValue += kUnit.getCombat();
                                break;
                            case UNITAI_SETTLE:
                            case UNITAI_SETTLER_SEA:
                                iTempValue += 25;
                                break;
                            case UNITAI_WORKER:
                            case UNITAI_WORKER_SEA:
                                iTempValue += 10;
                                break;
                            case UNITAI_ATTACK:
                            case UNITAI_ATTACK_CITY:
                            case UNITAI_COLLATERAL:
                            case UNITAI_PILLAGE:
                            case UNITAI_RESERVE:
                            case UNITAI_COUNTER:
                            case UNITAI_CITY_DEFENSE:
                            case UNITAI_CITY_COUNTER:
                            case UNITAI_CITY_SPECIAL:
                            case UNITAI_ATTACK_SEA:
                            case UNITAI_RESERVE_SEA:
                            case UNITAI_ESCORT_SEA:
                            case UNITAI_ASSAULT_SEA:
                            case UNITAI_CARRIER_SEA:
                            case UNITAI_MISSILE_CARRIER_SEA:
                            case UNITAI_PIRATE_SEA:
                            case UNITAI_ATTACK_AIR:
                            case UNITAI_DEFENSE_AIR:
                            case UNITAI_CARRIER_AIR:
                            case UNITAI_MISSILE_AIR:
                            case UNITAI_PARADROP:
                            case UNITAI_ATTACK_CITY_LEMMING:
                                iTempValue += kUnit.getCombat() * 2;
                                if (bWarPlan)
                                    iTempValue += (kUnit.getCombat() * kUnit.getCombat() / 2);
                                break;
                            case UNITAI_EXPLORE:
                            case UNITAI_MISSIONARY:
                            case UNITAI_PROPHET:
                            case UNITAI_ARTIST:
                            case UNITAI_SCIENTIST:
                            case UNITAI_GENERAL:
                            case UNITAI_MERCHANT:
                            case UNITAI_ENGINEER:
                            case UNITAI_SPY:
                            case UNITAI_SPY_SEA:
                            case UNITAI_MISSIONARY_SEA:
                            case UNITAI_EXPLORE_SEA:
                                iTempValue += 10;
                                break;
                            case UNITAI_ICBM:
                                iTempValue += 100;
                                if (bWarPlan)
                                    //A real nuke has a nuke range of 1, so this really adds 100 more.
                                    iTempValue += kUnit.getNukeRange() * 100;
                                break;
                        }
                        iValue += iTempValue;
                        /************************************************************************************************/
                        /* Afforess                         END                                                            */
                        /************************************************************************************************/        

                        ReligionTypes eReligion = (ReligionTypes)(GC.getUnitInfo((UnitTypes)iI).getPrereqReligion());
                        if (eReligion != NO_RELIGION)
                        {
                            //encouragement to get some minimal ability to train special units
                            if (bCulturalVictory1 || isHolyCity(eReligion) || isCapital())
                            {
                                iValue += (2 + iNumCitiesInArea);
                            }
                            
                            if (bCulturalVictory2 && GC.getUnitInfo((UnitTypes)iI).getReligionSpreads(eReligion))
                            {
                                //this gives a very large extra value if the religion is (nearly) unique
                                //to no extra value for a fully spread religion.
                                //I'm torn between huge boost and enough to bias towards the best monastery type.
                                int iReligionCount = GET_PLAYER(getOwnerINLINE()).getHasReligionCount(eReligion);
                                iValue += (100 * (iNumCities - iReligionCount)) / (iNumCities * (iReligionCount + 1));
                            }
                        }
                    }
                }

This new code should have no real effect on regular BTS games, but the BTS AI should be as flexible as possible, so...

Wow, that's surprising ... Firaxis was pretty good about making the AI robust to mod changes, but that definitely needs help. Thanks for bringing it up.
 
I've been playing with those changes for a while, and I'm afraid that while it does seem to make the AI Building Value for the buildings rise, it does not encourage them to construct any. Doubling, even tripling the value had no real effect.

I'm afraid I simply don't understand how the AI chooses buildings to build, but however it does, it is certainly not by value alone. I would be grateful if you could add some code so the AI considers buildings these buildings, or at least point to me where in CvCityAI that those decisions are made.
 
You modified the right place, but there are a lot of other flags which determine which building types are considered when. The AI will look for a building meeting some threshold with food benefits, then health, then defense, then happy, then economy, then culture (order made up to make the point) before looking for the best building in general. So, depending on what building you're looking at exactly it might not be considered a high priority.

There are a whole bunch of BUILDINGFOCUS flags, and your building would need to cause one of those to trigger towards the beginning of the function you were editing to get built with any real priority.
 
You modified the right place, but there are a lot of other flags which determine which building types are considered when. The AI will look for a building meeting some threshold with food benefits, then health, then defense, then happy, then economy, then culture (order made up to make the point) before looking for the best building in general. So, depending on what building you're looking at exactly it might not be considered a high priority.

There are a whole bunch of BUILDINGFOCUS flags, and your building would need to cause one of those to trigger towards the beginning of the function you were editing to get built with any real priority.

Right you are. A Million thanks!

I hi-jacked BUILDINGOFOCUS_EXPERIENCE (It seemed the most appropriate) and just moved that huge for block over there. The AI started building those buildings Pronto. :)
 
Yeah, tech diffusion is a fairly hidden feature ... it's built off a hidden Civ4 feature and I haven't done anything to make it more visible. It'd be easy to add something to tech tooltips saying "Research Efficiency: 135%" or whatever for a given tech so you would know, but would that info be useful?
Useful or not, I would like to know. Making this visible is probably not within the scope of BBAI though, sounds like it would fit the BUG project more.
chipotle + scoreboard, that should be enough here.
 
Back
Top Bottom