AI founding city behavior

Hutma

Chieftain
Joined
Apr 21, 2020
Messages
22
Location
France
Hello,
I am currently creating a mod for civilization 4. In this mod the city maintenance cost from distance to the capital is reduced to almost zero. The objective is to encourage players to found cities in good locations and getting ressources even far away from their capital.
The problem is that the AI keeps on building cities close to each others like in a vanilla game.

So I try to edit de CvPlayerAI.cpp but I'm not very confident with C++.
Can you help me editing the CvPlayerAI::AI_foundValue to change to AI behavior? Which values should I change?

Thank you (I apologize for any English mistakes, it's not my native language)
 
Code:
if (iMinDistanceFactor > 1000)
            {
                //give a maximum boost of 25% for somewhat distant locations, don't go overboard.
                iMinDistanceFactor = std::min(1500, iMinDistanceFactor);
                iValue *= (1000 + iMinDistanceFactor);               
                iValue /= 2000;
            }
            else if (iMinDistanceFactor < 1000)
            {
                //this is too close so penalize again.
                iValue *= iMinDistanceFactor;
                iValue /= 1000;
                iValue *= iMinDistanceFactor;
                iValue /= 1000;
            }
            
            iValue /= 10;
            
            if (pPlot->getBonusType() != NO_BONUS)
            {
                iValue /= 2;
            }
        }
    }
    
    if (bAdvancedStart)
    {
        if (pPlot->getBonusType() != NO_BONUS)
        {
            iValue *= 70;
            iValue /= 100;
        }
    }

    pNearestCity = GC.getMapINLINE().findCity(iX, iY, ((isBarbarian()) ? NO_PLAYER : getID()));

    if (pNearestCity != NULL)
    {
        if (isBarbarian())
        {
            iValue -= (std::max(0, (8 - plotDistance(iX, iY, pNearestCity->getX_INLINE(), pNearestCity->getY_INLINE()))) * 200);
        }
        else
        {
            int iDistance = plotDistance(iX, iY, pNearestCity->getX_INLINE(), pNearestCity->getY_INLINE());
            int iNumCities = getNumCities();
            if (iDistance > 5)
            {
                iValue -= (iDistance - 5) * 500;               
            }
            else if (iDistance < 4)
            {
                iValue -= (4 - iDistance) * 2000;
            }
            iValue *= (8 + iNumCities * 4);
            iValue /= (2 + (iNumCities * 4) + iDistance);
            if (pNearestCity->isCapital())
            {
                iValue *= 150;
                iValue /= 100;
            }
            else if (getCapitalCity() != NULL)
            {
                //Provide up to a 50% boost to value (80% for adv.start)
                //for city sites which are relatively close to the core
                //compared with the most distance city from the core
                //(having a boost rather than distance penalty avoids some distortion)

I think I understand more this file now.
I think I have to modify the line "iValue -= (iDistance - 5) * 500;" and replace it with "iValue -= (iDistance - 5) * 100;" for exemple, so that iValue would be less affected by distance. Am I right or wrong?
 
The iMinDistanceFactor stuff is only used when choosing starting locations (bStartingLoc). But the
iValue -= (iDistance - 5) * 500;
is right on target, and decreasing the multiplier to 100 sounds reasonable. The else branch is also relevant; it deals with founding a city on a landmass where the AI player doesn't have any cities yet:
Code:
else
{
    pNearestCity = GC.getMapINLINE().findCity(iX, iY, ((isBarbarian()) ?
            NO_PLAYER : getID()), ((isBarbarian()) ? NO_TEAM : getTeam()),
            /*bSameArea=*/false);
    if (pNearestCity != NULL)
    {
        int iDistance = plotDistance(iX, iY, pNearestCity->getX_INLINE(), pNearestCity->getY_INLINE());
        iValue -= std::min(500 * iDistance, (8000 * iDistance) / GC.getMapINLINE().maxPlotDistance());
    }
}
I hope you're aware that you'll have to re-compile the DLL for any changes to take effect. (Just checking since you say that you're not well familiar with C++.)
 
Thank you very much for the response f1rpo, I will also modify the else branch.
I have learned a bit of C++ since yesterday and I understand it better now (a little bit better).

I am aware that I will have to recompile the DLL but I'm nut sure how to do it. I followed The Easiest Way to Compile a New DLL by Leoreth to open the file and setting up the C++ environment. But I haven't understood how to compile the dll and how to use the Makefile...
 
[...] But I haven't understood how to compile the dll and how to use the Makefile...
The makefile can be opened with any editor. Normally, it should be enough to verify that the variables on top (TOOLKIT, PSDK, YOURMOD) are set to the correct paths. If Visual Studio is installed, a double click on the .sln file should open the project, and then the F7 key can be used to start the build process. Hopefully, it'll create a new CvGameCoreDLL.dll and copy it to the YOURMOD folder. Otherwise, there should be error messages on the Visual Studio console at the bottom.
 
Thank you for taking the time to respond, you're very helpful.
Everything seems to work during the compilation, at the end of the compilation I tried to run the game and this error poped up :
Code:
Assert Failed

File:  .\.\CvGlobals.cpp
Line:  3493
Expression:  strcmp(szType, "NONE")==0 || strcmp(szType, "")==0
Message:  info type BUILDING_VERSAILLES not found, Current XML file is: xml\Buildings/CIV4BuildingInfos.xml

----------------------------------------------------------

And many other like this after. It's because I removed lots of building in the mod. Should I modify the CvGlobal.cpp (if I have to, do I have to do it with units, civics etc. also?)?
Or is there another way to go around this error and prevent other errors like this one?
 
In order to get rid of these asserts you'll want to search for all instances of this XML key in all your XML files (not sure how to do that on Windows, I think Notepad++ has a directory search feature) and remove them. If you don't really care the game will probably still start without doing that, just ignore these asserts (there's a button for that), and/or compile a Release DLL instead of a Debug DLL. There's no need to change anything in CvGlobals.cpp.
 
I disagree (slightly). Asserts are there for a reason, and if they are violated in your mod you should either check out that specific assert to see if it no longer applies, or rectify the issue. For example, here it's pointing out that your reference to BUILDING_VERSAILLES, which you presumably removed, is still showing up in your XML somewhere else. Even though it doesn't break your entire mod, there's still some issue that results from this, and you should fix it at some point. Often you are actually debugging something else of course, but in that case just choose "ignore always" to skip over that particular assert.
 
I disagree (slightly). Asserts are there for a reason, and if they are violated in your mod you should either check out that specific assert to see if it no longer applies, or rectify the issue. For example, here it's pointing out that your reference to BUILDING_VERSAILLES, which you presumably removed, is still showing up in your XML somewhere else. Even though it doesn't break your entire mod, there's still some issue that results from this, and you should fix it at some point. Often you are actually debugging something else of course, but in that case just choose "ignore always" to skip over that particular assert.
By "don't really care" I meant "it's not something you want to fix right now". IMO asserts are annoying enough (rightly so) that one eventually will fix them, but after recompiling the DLL I don't think doing that is the main objective when first trying the new DLL (especially if you're new to DLL modding).
But you're right, I wasn't really clear about this.
 
Thank you for taking the time to respond, you're very helpful.
Happy to help.
[...] compile a Release DLL instead of a Debug DLL [...]
That would be done through the configuration manager in Visual Studio; under project properties (not to be confused with solution properties). I hadn't even thought about the build configuration when I wrote to just press F7. A debug (or assert) build is helpful, but, eventually, you'll also want a release build because that runs much faster.
 
So I've been through all of the errors and now everything looks clean :)

But I'm not sure if I am going to keep this AI behavior because it cause some gameplay problems down the road.
At least I've learned a lot and this is always valuable!

Thank all of you for responding, and by the way, and thank you Leoreth for Dawn of Civilization I've had a lot of fun and good experiences with this mod.
 
Top Bottom