Increasing Number of Workable City Plots

Strand

Chieftain
Joined
May 3, 2006
Messages
7
I've been trying off and on for about a week now to increase the workable plot area of a city (beyond the fat cross). My goal is to make all plots within the city cultural area workable.

I haven't had a whole lot of success in my attempt. Any help would be appreciated, I'll toss up some leads for those of you that might want to look in on this.

Code:
CvDefines.h

// The following #defines should not be moddable...

...

#define NUM_CITY_PLOTS				(21)
#define CITY_HOME_PLOT				(0)
#define CITY_PLOTS_RADIUS			(2)
#define CITY_PLOTS_DIAMETER			((CITY_PLOTS_RADIUS*2) + 1)
It seems to me that these are the numbers I want to be working with, but no amount of fiddling will get them to comply. Here are the numbers I've been working with:

Radius - 3
Plots - 37

Radius - 4
Plots - 57

Radius - 5
Plots - 81
 
Hello Strand,

I've had some success in this area. Currently I can get the Ai to select any city square within a radius of 3. However, the yields of the square are always the same no matter what type of terrain or improvement it has: 2 food, 2 trade, and 1 hammer. I'm still looking at it and I'm sure I'll get it eventually but some things in real life have taken my time lately. I'll post my progress here so others can work on it in the meantime.

First, you are wrong about the number of squares in a 3-radius city. A 3-radius city has 45 squares. Draw it out on paper and you will see. So, that gives us the following in CvDefines.h

Code:
#define DIRECTION_DIAMETER										((DIRECTION_RADIUS * 2) + 1)
#define NUM_CITY_PLOTS												(45)//(21) // RogerBacon
#define CITY_HOME_PLOT												(0)
#define CITY_PLOTS_RADIUS											(3)//(2) // RogerBacon
#define CITY_PLOTS_DIAMETER										((CITY_PLOTS_RADIUS*2) + 1)

Next, in CvGlobals.cpp you need to change an array to make it big enough to hold the extra city squares. I'll post the code as well as the original code I commented out.

Code:
int aaiXYCityPlot[CITY_PLOTS_DIAMETER][CITY_PLOTS_DIAMETER] =
	{
		{-1, 38, 39, 40, 41, 42, -1,},

		{36, 37, 17, 18, 19, 43, 44,},

		{35, 16, 6, 7, 8, 20, 21,},

		{34, 15, 5, 0, 1, 9, 22,},

		{33, 14, 4, 3, 2, 10, 23,},

		{32, 31, 13, 12, 11, 25, 24,},

		{-1, 30, 29, 28, 27, 26, -1,}
	}; //RogerBacon

	/*int aaiXYCityPlot[CITY_PLOTS_DIAMETER][CITY_PLOTS_DIAMETER] =
	{
		{-1, 17, 18, 19, -1,},

		{16, 6, 7, 8, 20,},

		{15, 5, 0, 1, 9,},

		{14, 4, 3, 2, 10,},

		{-1, 13, 12, 11, -1,}
	};*/

I believe that was all I did to get the 3-radius working, albeit without the game recognizing the type of terrain in those 3-radius squares.

You'll also need to find the controls that set the zoom distance when you go to the city scree so that you can actually select those extended squares. In the default only the bottom squares are visible. It shouldn't be too hard but, like I said, I've been busy with RL. :(

Roger Bacon
 
Thanks RogerBacon! I had been looking for some sort of plot list and just could not figure out how they were numbering them at all. Thanks for pointing out where they're doing that.

A radius 3 city only has 37 plots. Start up a game and use the world editor to give a city enough culture to be size 3. It will indeed only have 37. There are 3 plots missing from each corner at that size, not just 1. The rest of my numbers up above are correct as well, as I did ineed draw this all out on paper. ;)

Anyway. I got this whole thing working with your help. You changed the array for aaiXYCityPlot but never for the 3 preceeding arrays directly above it that used NUM_CITY_PLOTS as their size. At least you didn't post any code for those arrays. Here we go.

CvGlobals.cpp
Code:
	int aiCityPlotX[NUM_CITY_PLOTS] =
	{
		0,
		0, 1, 1, 1, 0,-1,-1,-1,
		0, 1, 2, 2, 2, 1, 0,-1,-2,-2,-2,-1,
		0, 1, 2, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -2, -1,   //  Strand
	};

	int aiCityPlotY[NUM_CITY_PLOTS] =
	{
		0,
		1, 1, 0,-1,-1,-1, 0, 1,
		2, 2, 1, 0,-1,-2,-2,-2,-1, 0, 1, 2,
		3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -2, -1, 0, 1, 2, 3,  //  Strand
	};

	int aiCityPlotPriority[NUM_CITY_PLOTS] =
	{
		0,
		1, 2, 1, 2, 1, 2, 1, 2,
		3, 4, 4, 3, 4, 4, 3, 4, 4, 3, 4, 4,
		5, 6, 7, 6, 5, 6, 7, 6, 5, 6, 7, 6, 5, 6, 7, 6,         //  Strand
	};

	int aaiXYCityPlot[CITY_PLOTS_DIAMETER][CITY_PLOTS_DIAMETER] =
	{
	    {-1, -1, 32, 33, 34, -1, -1},   //  Strand
	    {-1, 31, 17, 18, 19, 35, -1},   //  Strand
	    {30, 16, 6, 7, 8, 20, 36},      //  Strand
	    {29, 15, 5, 0, 1, 9, 21},       //  Strand
	    {28, 14, 4, 3, 2, 10, 22},      //  Strand
	    {-1, 27, 13, 12, 11, 23, -1},   //  Strand
	    {-1, -1, 26, 25, 24, -1, -1}    //  Strand
		/*{-1, 17, 18, 19, -1,},
		{16, 6, 7, 8, 20,},
		{15, 5, 0, 1, 9,},
		{14, 4, 3, 2, 10,},
		{-1, 13, 12, 11, -1,}*/
	};

So far as I can tell this works perfectly. Now I just need to change the level of zoom in the city management screen so I can increase it all the way to the fifth radius.
 
Turns out it's pretty hard to see anything zoomed far enough out to see a city with a radius of 5. 3 isn't a problem though.

GlobalDefines.xml
Code:
	<Define>
		<DefineName>CAMERA_CITY_ZOOM_IN_DISTANCE</DefineName>
		<fDefineFloatVal>4000</fDefineFloatVal>
	</Define>

The default value is 3500 and 4000 seems to work just fine. I've already forgotten where it was I saw it, but it also seems that 5000 is the point at which the zoom turns into the "Global View" and clouds start appearing. I tried messing around with that but it was still too hard to discern things at a radius of 5.
 
Hello!

I always want to do this with the city radius, but I can't.
SDK modifications are very difficult for me.
Could you send me your moded files, please?
 
Hi Strand,

I believe we are both rigth as far as # of city plots. It could be 37 or 45 it all depends on how we define the array. The formula to calculate valid plots is:
Code:
int plotCityXY(int iDX, int iDY)
{
	if ((abs(iDX) > CITY_PLOTS_RADIUS) || (abs(iDY) > CITY_PLOTS_RADIUS))
	{
		return -1;
	}
	else
	{
		return GC.getXYCityPlot((iDX + CITY_PLOTS_RADIUS), (iDY + CITY_PLOTS_RADIUS));
	}
}

So, even with the default 2-radius you could get rid of the 'fat cross' shape simply by changing the negative one's on the arrays to valid numbers and changing the NUM_CITY_PLOTS of course. I've never liked the 'fat cross' shape because it wastes squares in between the cities so I'll probably define my 3-radius cities with 45 or even 49 squares.

One thing I don't understand is the
Code:
int aiCityPlotPriority[NUM_CITY_PLOTS] =
	{
		0,
		1, 2, 1, 2, 1, 2, 1, 2,
		3, 4, 4, 3, 4, 4, 3, 4, 4, 3, 4, 4,
		5, 6, 7, 6, 5, 6, 7, 6, 5, 6, 7, 6, 5, 6, 7, 6,
	};
What is this array used for and how did you come up with these values?

dj_anion, I'll compile and post the code tonight after I get home and test it to make sure it is working.

Roger Bacon
 
That array is used for the cultural/workable priority. When two cities are close to eachother this determines which city has control of what tiles. Obviously the corners are set to go first, and the tiles that are in a direct line go last. You'll really notice this in a team game when two cities are close to eachother. When these numbers of overlap, whichever city has a lower number gets control of that tile, regardless of culture. If they both have the same number then the game uses culture.

Now it might be used for something else, but that's the first thing that struck me when I started plugging in the extra numbers for it. After checking in game it is indeed the case.

37 Plots
Code:
       6, 5, 6,     
    7, 4, 3, 4, 7,  
 6, 4, 2, 1, 2, 4, 6,
 5, 3, 1, 0, 1, 3, 5,
 6, 4, 2, 1, 2, 4, 6,
    7, 4, 3, 4, 7,  
       6, 5, 6,

45 Plots You might want to make yours look like this. Put some eights in the corners if you decide on 49. Of course it doesn't really matter. If you decide to be completely square, you might as well make each radius square a single number. That way it truly doesn't follow the fatcross rules. Of course to truly take advantage of that you'll need to change the way culture expands too.
Code:
    7, 6, 5, 6, 7,
 7, 6, 4, 3, 4, 6, 7,
 6, 4, 2, 1, 2, 4, 6,
 5, 3, 1, 0, 1, 3, 5,
 6, 4, 2, 1, 2, 4, 6,
 7, 6, 4, 3, 4, 6, 7,
    7, 6, 5, 6, 7,

It turns out I was wrong with some of my numbers. I started up a game and gave some of the cities some massive culture and it turns out that these are the correct numbers if you intend on following the default cultural expansion.

Radius - 4
Plots - 61
(Not Code. Only a visual representation of culture at that level.)
Code:
          0, 4, 0,
    0, 0, 0, 3, 0, 0, 0,
    0, 0, 0, 2, 0, 0, 0,
 0, 0, 0, 0, 1, 0, 0, 0, 0,
 4, 3, 2, 1, 0, 1, 2, 3, 4,
 0, 0, 0, 0, 1, 0, 0, 0, 0,
    0, 0, 0, 4, 0, 0, 0,
    0, 0, 0, 3, 0, 0, 0,
          0, 4, 0,

Radius - 5
Plots - 89
(Not Code. Only a visual representation of culture at that level.)
Code:
             0, 5, 0,
       0, 0, 0, 4, 0, 0, 0,
    0, 0, 0, 0, 3, 0, 0, 0, 0,
    0, 0, 0, 0, 2, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5,
 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 2, 0, 0, 0, 0,
    0, 0, 0, 0, 3, 0, 0, 0, 0,
       0, 0, 0, 4, 0, 0, 0,
             0, 5, 0,

Radius - 6 (Legendary)
Plots - 121 (Not Code. Only a visual representation of culture at that level.)
Code:
                0, 6, 0,
          0, 0, 0, 5, 0, 0, 0,
       0, 0, 0, 0, 4, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6,
 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 4, 0, 0, 0, 0,
          0, 0, 0, 5, 0, 0, 0,
                0, 6, 0,

As far as 45 being correct, I suppose you are right. You can make the dimensions of the city whatever size you wish as long as it fits inside of an array that is [DIAMETER][DIAMETER]. I was merely trying to make it conform to the current game rules as far as culture radiating from the city go. It's kind of hard to work a plot if it's not in your cultural area.

Of course some intersting cities could arise from changing things up a bit.

Radius 3, Number of Plots 21 (This code won't work without the -1s. It's purely visual)
Code:
         17, 18, 19,     
              8,        
 16,          4,         20,
 15,  7,  3,  0,  1,  5,  9,
 14,          2,         10,
              6,        
         13, 12, 11,

This could certainly make for an interesting addition to some of the mods out there.
 
Strand said:
Turns out it's pretty hard to see anything zoomed far enough out to see a city with a radius of 5. 3 isn't a problem though.

GlobalDefines.xml
Code:
	<Define>
		<DefineName>CAMERA_CITY_ZOOM_IN_DISTANCE</DefineName>
		<fDefineFloatVal>4000</fDefineFloatVal>
	</Define>

The default value is 3500 and 4000 seems to work just fine. I've already forgotten where it was I saw it, but it also seems that 5000 is the point at which the zoom turns into the "Global View" and clouds start appearing. I tried messing around with that but it was still too hard to discern things at a radius of 5.

If I'm not mistaken that line is either in the GlobalDefines.xml or the CIV4DetailManager.xml. ;)
 
dj_anion said:
Hello!

I always want to do this with the city radius, but I can't.
SDK modifications are very difficult for me.
Could you send me your moded files, please?

The mod is posted here

Roger Bacon
 
I've been dying to see something that started at 0 for the city and then went:

x 4 x
3 0 1
x 2 x

with the first expansion. The next expansion fills in the Xs. Is this possible with what you guys have accomplished?
 
woodelf said:
I've been dying to see something that started at 0 for the city and then went:

x 4 x
3 0 1
x 2 x

with the first expansion. The next expansion fills in the Xs. Is this possible with what you guys have accomplished?


I like that idea. For my mod I have made 10 different culture levels each giving 10% defense as apposed to the original 5 that gave 20% each.

Having the cities culture grow differently would definately make it much better for my mod. :)
 
Agent 009 said:
I like that idea. For my mod I have made 10 different culture levels each giving 10% defense as apposed to the original 5 that gave 20% each.

Having the cities culture grow differently would definately make it much better for my mod. :)

Maybe these experts in cultural expansion can hook us up then! ;)
 
woodelf said:
I've been dying to see something that started at 0 for the city and then went:

x 4 x
3 0 1
x 2 x

with the first expansion. The next expansion fills in the Xs. Is this possible with what you guys have accomplished?

It is indeed possible.

CvGameCoreUtils.h
Code:
// 4 | 4 | 3 | 3 | 3 | 4 | 4
// -------------------------
// 4 | 3 | 2 | 2 | 2 | 3 | 4
// -------------------------
// 3 | 2 | 1 | 1 | 1 | 2 | 3
// -------------------------
// 3 | 2 | 1 | 0 | 1 | 2 | 3
// -------------------------
// 3 | 2 | 1 | 1 | 1 | 2 | 3
// -------------------------
// 4 | 3 | 2 | 2 | 2 | 3 | 4
// -------------------------
// 4 | 4 | 3 | 3 | 3 | 4 | 4
//
// Returns the distance between plots according to the pattern above...
inline int plotDistance(int iX1, int iY1, int iX2, int iY2)													// Exposed to Python
{
	int iDX;
	int iDY;

	iDX = xDistance(iX1, iX2);
	iDY = yDistance(iY1, iY2);

	return (max(iDX, iDY) + (min(iDX, iDY) / 2));
}

The above code seems to be the deciding factor in how culture expands in the game. It might affect other things though, I have not looked into it. We can achieve your desired results if we change it to this instead:

Code:
inline int plotDistance(int iX1, int iY1, int iX2, int iY2)    // Strand
{
    int iDX;
    int iDY;
    int iD;

    iDX = xDistance(iX1, iX2);
    iDY = yDistance(iY1, iY2);
	
    iD = (max(iDX, iDY) + (min(iDX, iDY) / 2)) * 2;
	
    if(min(iDX, iDY) > 0)
        return iD;
    else
        return iD - 1;
}

Using that algorithm instead will make the culture expand like this:

Code:
          8, 7, 8,
    8, 8, 6, 5, 6, 8, 8,
    8, 6, 4, 3, 4, 6, 8,
 8, 6, 4, 2, 1, 2, 4, 6, 8,
 7, 5, 3, 1, 0, 1, 3, 5, 7,
 8, 6, 4, 2, 1, 2, 4, 6, 8,
    8, 6, 4, 3, 4, 6, 8,
    8, 8, 6, 5, 6, 8, 8,
          8, 7, 8,
 
Hmm, I tried to do this... and well I get a syntax error.

This is what it says when I try to build it:

line 199 error C2059 syntax error : ')'

This is the line it is having a problem with:

iD = (max(iDX, iDY) + (min(iDX, iDY) / 2))) * 2;


Any ideas?
 
Agent 009 said:
Hmm, I tried to do this... and well I get a syntax error.

This is what it says when I try to build it:

line 199 error C2059 syntax error : ')'

This is the line it is having a problem with:

iD = (max(iDX, iDY) + (min(iDX, iDY) / 2))) * 2;


Any ideas?
Count the brackets! The last closed one shouldn't be there.
 
The Great Apple said:
Count the brackets! The last closed one shouldn't be there.


OMG... that was his code also... ok I'll change it and see if it works the way I want it to in game. :)
 
Well it worked.

I removed that bracket as you suggested TGA, and built the .dll. Well, I then went in game to test it out.

Here's a SS of the first 4 expansions including a new city. I would have made it go further if possible, but the WB only let's me go to 1000 Culture Points.



EDIT: I messed up somehow and didn't actually copy over the original file... I edited out the original post I made here.
 
Awesome! That is exactly what I wanted as well! Can you post the actual file or is it tied up among a lot of changes?
 
woodelf said:
Awesome! That is exactly what I wanted as well! Can you post the actual file or is it tied up among a lot of changes?


Do you have the Source code and have the SDK set up and all. Cause the .dll for some reason when I compiled it came out to 4.8 MB instead of the original 3.6 MB. My version of the .dll also has TheLopez' sniper mod included in it.

If you can compile it yourself, all you need to do is edit the file that strand specified above, save and then build the .dll. Once you have it simply copying it into your mods' assets folder.

I can send you my copy of the changed file, but I fail to see the difference. It wasn't hard to do. ;)

Just find this line in CvGameCoreUtils.cpp:

inline int plotDistance(int iX1, int iY1, int iX2, int iY2)

And right under it change:

Code:
{
	int iDX;
	int iDY;

	iDX = xDistance(iX1, iX2);
	iDY = yDistance(iY1, iY2);

	return (max(iDX, iDY) + (min(iDX, iDY) / 2));
}

to this:

Code:
{
    int iDX;
    int iDY;
    int iD;

    iDX = xDistance(iX1, iX2);
    iDY = yDistance(iY1, iY2);
	
    iD = (max(iDX, iDY) + (min(iDX, iDY) / 2)) * 2;
	
    if(min(iDX, iDY) > 0)
        return iD;
    else
        return iD - 1;
}

Then save the change and build the .dll and you'll have the effect you want. ;)
 
Back
Top Bottom