How to reduce pollution at all in Civ3 Conquests

Antal1987

Warlord
Joined
Sep 4, 2013
Messages
160
Location
Karelia, Russia
Hello, everyone!

Everyone knows that in Civ 3 Editor the user can set "Removes Pop. Pollution" and "Reduces Bldg. Pollution" flags to each improvement

But under certain condititions pollution remains anyway.

I've found some function in Civ III Conquests exe-file, which calculates city pollution.
Lets call it class_City::Calculate_Pollution

As it turned out, total pollution = max(0, population_pollution) + max(0, buildings_pollution)

here is pseudocode of calculating population_pollution and buildingsbuildings_pollutionpollution:

if (City.Size < General_Settings.Max_City_Size)
population_pollution = 0;
else
{
population_pollution = City.Size - General_Settings.Max_City_Size;
if(City.Has_Improvement_With_Flag(Removes_Population_Pollution))
population_pollution = 1;
}

buildings_pollution = sum{Improvement.Pollution where City.Has_Improvement(i)}
if(buildings_pollution > 0)
{
if(City.Has_Improvement_With_Flag(Removes_Population_Pollution))
buildings_pollution = 1;
}

General_Settings.Max_City_Size is a standard scenario parameter
By default it is 12. See Game Rules -> General Settings -> City Size Levels Group -> Maximum size for Level 2 (in Civ3 Editor)

In Civ3Conquests v1.22 function class_City::Calculate_Pollution has address 0x004B1CA0.
There are two hard coded constants in the function:
1) in: population_pollution = 1; Address of the constant (1) is: 0x004B1D61 (4 bytes integer)
2) in: buildings_pollution = 1; Address of the constant (1) is: 0x004B1E08 (4 bytes integer)

In Civ3 that code was duplicated in 2 separate functions (functions' names are fictitious, of course):
1) one for population_pollution calculating (class_City::Calculate_Population_Pollution); Address of the function: 0x004B1AE0; Address of the constant (1): 0x004B1B9E (4 bytes integer).
2) one for buildings_pollution calculating (class_City::Calculate_Improvements_Pollution); Address of the function: 0x004B1BD0; Address of the constant (1): 0x004B1C7B (4 bytes integer).

The game developers obviously didn't use DRY concept.

So in this way, it's enough to change these values to 0 to have zero city pollution.
Of course, the city must have a mass transition and a recycling center
 
How are you able to see any of the civ3 code?
 
How are you able to see any of the civ3 code?

I've been decompiling its' exe for last 6 months :)

I even know how to retreive internal game images like this:


I develop the trainer for Civ 3

Now I'm prepearing another thread about how the graphic system of the game works
 
If you are looking at the source code, how about looking at how to reset the strategic and luxury resource restriction so that it is possible to have more than 32 strategic and luxury resources?

Pollution is a manageable headache, as it is possible to set building to negative pollution, but the restriction to a combination of 32 strategic and luxury resources drives everyone who mods the game nuts.
 
When and where does the restrictiion appears?

I've got not mods with a lot of resources.
I'm dealing with default game: it has 26 resources (in Civ3Conquests)

There are several data structures in the game, where resources-relevant information stores.
Usually it's space corresponds to resource type count (which of course can be greater than 32)
In these cases memory blocks for it's data are allocated dynamically and there are no problems. You get items count, pointer to allocated memory and you can manipulate with the corresponding data.

But I've found at least one data field, which does't depend on resource type count;

In City class, there is a 4 bytes (32 bits) integer, used by City Form to draw available resources when the city has no connection to the capital.

In C3C this data field has offset 0x9C from City class object.
It can be found in 2 ways:
1) Each City class object has 4-char string "CITY" with offset 0x08 from object start. Therefore the value offset from "CITY" is 0x94;
2) City name string has offset 0x1E0 from object start. Therefore the value offset from city name is -0x144

Here is how that value works. The value is 32-bits integer with 1 bit for each resource type. If current city to display on City Form has no connection to the capital city, City Form starts checking the value for available resources. If a resource type has corresponding bit and it is strategic City Form renders it in the resource list or in the appropriate form (when strategic resource count > 8) like this:


I don't know what happens when the resource count becomes > 32 because I don't have appropriate mods to test it.

P.S. City Resources Dialog has only 24 places to render resource type icons.
 
What about increasing the number of civilizations above 32 (31 playable + 1 barbarian)? Or allowing more than 256 total buildings and wonders? Or more than 5 culture groups?

You may have found the Grail, here.
 
Wow, nice work! Since you're able to access the code, there's something you might be able to fix for a start, the so called "Submarine bug". Invisible units should usually be ignored by those that cannot detect them, even if that means that they might end up in the same spot (like a sub beneath a battleship). It doesn't work anymore since C3C, though. Due to this bug, placing your subs anywhere where other civs could be travelling might result in an unwanted decleration of war. If you could find what causes this (and hopefully fix it), that'd be great. :)
 
What about increasing the number of civilizations above 32 (31 playable + 1 barbarian)? Or allowing more than 256 total buildings and wonders? Or more than 5 culture groups?

You may have found the Grail, here.

Civilizations' limit

Civilizations (Game players including AI) are stored in hard-coded place. There is a class object (class_Leader) per each player (up to 32). So Civ count cannot be increased.

class objects can be found by 4-char string "LEAD", which has offset: 0x08;

In C3C Civilizations are stored at 0x00A52E58. The data has structure (in C++ code):
class_Leader Civilizations[32];
class object has size: 0x20E4;
So Civ with ID=1 (the Player) has address: 0x00A54F3C

Improvements' limit

Max Improvement count are also hardcoded. Here is the structure, which stores info about cities improvements being built:
00000000 class_City_Improvements struc ; (sizeof=0x44)
00000000 Base class_Base ?
0000001C Improvements db 32 dup(?)
0000003C Count dd ?
00000040 Aligned_Capacity dd ?
00000044 class_City_Improvements ends

Improvements array (offset 0x1C) represents improvements bits. There is 1 bit per improvement: 1 - Improvement was built, 2 - wasn't
it's size is 0x20 bytes. So, there are only 0x20 * 8 = 0x100 (256) available bits for storing improvements.

class_City_Improvements objects can be found in memory by 4-char string "BITM" with offset 0x08. There are 2 such objects per City object.
Common structure is:
00000000 class_City struc ; (sizeof=0x544)
...
00000258 Improvements_1 class_City_Improvements ?
0000029C Improvements_2 class_City_Improvements ?
...
00000544 class_City ends

City objects can be found by 4-char string "CITY" with offset 0x08;
Only 1-st object of class_City_Improvements class stores proper information. 2-nd one only dublicates it (don't use it).

Culture groups' limit
Culture group count is also hard-coded (numbers 5 and 10 appears every time). In addition, there are only 520 possible citizen face images provided. And it must be 1 image per combination <culture group (5 values), era (4 values), gender (2 values), citizen mood type (4 values)> (See \Art\SmallHeads\popHeads.pcx).
heads coordinates are also hard-coded.
 
Wow, nice work! Since you're able to access the code, there's something you might be able to fix for a start, the so called "Submarine bug". Invisible units should usually be ignored by those that cannot detect them, even if that means that they might end up in the same spot (like a sub beneath a battleship). It doesn't work anymore since C3C, though. Due to this bug, placing your subs anywhere where other civs could be travelling might result in an unwanted decleration of war. If you could find what causes this (and hopefully fix it), that'd be great. :)

Actually, I don't have origin sources. I only have decompilted source codes (some of them are perfectly clear, some ain't)

I've never faces such bug. And I can test only C3C. If you give me prepared save-game for C3C v1.22 I'd test it and maybe would find a place(s) in sources to be correct.
 
Antal1987, welcome at CFC. :band:[party],

your posts are very interesting and remember me to the famous Skyer2, who gave the brilliant Noraze-Patch to the Civ-community.

As Ares posted, the fix of the submarine bug would be one of the most important fixes that are necessairy for C3C. The submarine bug was fixed with patch v1.16f of Civ3 Vanilla (You no longer declare war by accidentally passing over a hidden submarine), but later came back again in C3C (at present I´m not sure, if the bug came back still in Civ 3 PtW).

Another real important fix would be the never working function of the C3C Editor 1.03 to turn off all waste and corruption in the governments register of the editor (this function was not included in the C3C editor 1.00).
 
Another real important fix would be the never working function of the C3C Editor 1.03 to turn off all waste and corruption in the governments register of the editor (this function was not included in the C3C editor 1.00).

Unfortunatelly, I don't investigate other exe-files, only C3C. Another exe means completely different source-code database to be created.

However I've already had that problem some times.
So, here are integer values of corruption and wate radio button group
FFFFFFFF ; enum CorruptionAndWasteTypes
FFFFFFFF CWT_Minimal = 0
FFFFFFFF CWT_Nuisance = 1
FFFFFFFF CWT_Problematic = 2
FFFFFFFF CWT_Rampant = 3
FFFFFFFF CWT_Catastrophic = 4
FFFFFFFF CWT_Communal = 5
FFFFFFFF CWT_Off = 6

I don't know why but now I've got no corruption. It becames 0 after I reduced all pollution strictly to 0 (by the patch I've described at the top) (current Gov is democracy, government scenario properties were not modified).

I'm gonna continue investigating that issue.
 
I don't know why but now I've got no corruption. It becames 0 after I reduced all pollution strictly to 0 (by the patch I've described at the top) (current Gov is democracy, government scenario properties were not modified).

That´s an interesting side effect. :)

I'm gonna continue investigating that issue.
:clap::clap:
 
The limit I always wondered about and assumed was hardcoded is the two tile minimum distance from an existing city to building a new one.

And that is possible (I hope it's not raping yet, but it's dirty :mischief: ):




The secret is inside the following function:
int __thiscall class_Map::Check_City(class_Map *this, int X, int Y, int CivID, int a5)

class_Map * this - class object of Map, which cointains tiles
X and Y - coordinates of settler unit
CivID - Civilization ID of that Unit
a5 - some flag, I dunno wtf is that

Function address in C3C: 0x005F3090

It returns integer value as result of checking possibility of city foundation.
Here are some of its' result values:
0 - City can be built
2 - When X and Y are the coordinates of some city, or when it belong to barbarian camp, or its' tile is a territory of another Civilization
5 - City cannot be built (the appropriate command button disappears).
The function checks tile's [X, Y] neighbours (8 tiles around) for existed cities. If a city is located right at neighbourhood it returns 5.

So the hack is very simple. You just need to change the constant (5) to 0;
In C3C it's address: 0x005F3223;
 
I am following your work with much interest! I cannot offer any help because I do not understand coding but I will cheer you on in your discoveries. This may open some new possibilities for C3C.
 
This is great news!:goodjob: Especially the pollution-bug is annoying. Is the "fix" achieved by means of a Hex-editor, or is it necessary to decompile, modify and compile?

Regarding the submarine-bug: When the human player tries to move a unit onto the same tile as a rival invisible unit, a "this would trigger a war"-message appears making war avoidable. When AI does the same, however, war is triggered - both towards the human player and amongst the various AI-civs. For me, this bug is not the worst, since I use it to vary my games. If I want an extremly volatile world, I make the invisible units (I have many of them) without hidden nationality, and war breaks out constantly. When I want a somewhat more peaceful game, I give the invisible units hidden nationality, and war is not triggered when they are stumbled upon. This is at least how the game works on my computer...

Looking forward to more discoveries. Thank you and well done!

Jorsalfare
 
This is great news!:goodjob: Especially the pollution-bug is annoying. Is the "fix" achieved by means of a Hex-editor, or is it necessary to decompile, modify and compile?

Actually I just published memory addresses of game hard_coded constants to be modified properly.
Every Exe-file is loaded into virtual memory. C3C is loaded at constant position. So it's enough to edit and assembly the proper code in debugger. I use ollydbg 2.0.
Or you can just modify corresponding values using such tools as Cheat Engine or ArtMoney.

Now I've made 1-st patch: see
 
Cities in every tile would be a great mess and a dirty trick to play on the AI. What I wondered was if the minimum space between cities could be increased. If the game checks the spaces around the settler, could that radius be expanded to 24 or 48?
 
Cities in every tile would be a great mess and a dirty trick to play on the AI. What I wondered was if the minimum space between cities could be increased. If the game checks the spaces around the settler, could that radius be expanded to 24 or 48?

No. Game checks settler's tile neighbourhood. It is 8 tile around the current one. Coordinates are defined by offsets like (0; -2), (1, 1), etc...

So there cannot be any trick...
 
Antal1987, it´s amazing how much knowledge you have about the functions inside
C3C ! Bravo! :):goodjob:
 
Top Bottom