Resource icon

C3X: EXE Mod including Bug Fixes, Stack Bombard, and Much More Release 22

So, I'm getting an issue. Sometimes (most of the time?), during combat, the game freezes, the combat finishes without any change in the display until the completion of the combat, the game operates normally until the next combat.
And have this happen wen the Task Manager is ronning (Windows 10).
 
Strength of Computer:

Intel i7-10750 2.60GHz
16 GB RAM
Nvidia GeForce RX 2060

None of these are the latest, but were top of the line 4 years ago, so perhaps lower midrange now. Although it only seems to happen later in the game... hmm, maybe time to upgrade.

"And have this happen wen the Task Manager is ronning (Windows 10)."

Not running the task manager

Is this a C3X issue? Well, I don't think C3X caused it, maybe it could help or some of the knowledgeable people on here might recognize my issue.
 
I've observed this on multiple systems and in multiple games (such as Civ3, Civ4) - if you tab out or externally address the window in some fashion, it'll get stuck non-responsively until expecting player input again (next turn). While it might not show it, it will still be working on the AI turns. I never considered it a major issue, as long as you only tab out during your own turns you won't have a problem, and even if, it's just a temporary inconvenience.
 
Is there a way to limit building or unit production based on a resource within the city limits? i.e. the resource "Space Station" within the city radius will make the building "City Shield" unbuildable.
Not that I know of, maybe there's some kind of crazy thing you can do with the editor. This sort of rule would be very easy to add through Lua by tacking an additional condition onto the game's City::can_build_improvement function.

Finally, is there a way to link cities on the same river through a trade route? What about link them only after a certain building has been built in the city?
That would be possible with effort. I suppose what I'd do is insert some code that runs after the game's normal recomputation of city connections to identify and connect cities along rivers. I'd imitate the original game logic, which isn't too complicated in this case. Basically all it does for air routes is mark each city as connected to all others with airports, for sea routes it's similar except it also tries finding a path between each pair of cities with harbors (and it's that pathfinding that takes so long). I'd do like that only instead of searching for a path, I'd flood fill outwards along all riverside tiles from each city, like the game already does for roads, and like I've already reproduced in Trade Net X. So it's doable, but honestly, I have so much already lined up that I won't get around to this any time soon.

I have not looked at the current impl, so you may have this already, but i believe that the stack limit should apply separately to air, water, military, auxiliary/artillery, immobile, and civilian units. for the last i believe this is hard to impl as the game does not have those categories.
It wouldn't be too hard to implement that in terms of counting units by category and applying the limit. The hard part would be making it nicely configurable through the INI.
 
That would be possible with effort. I suppose what I'd do is insert some code that runs after the game's normal recomputation of city connections to identify and connect cities along rivers. I'd imitate the original game logic, which isn't too complicated in this case. Basically all it does for air routes is mark each city as connected to all others with airports, for sea routes it's similar except it also tries finding a path between each pair of cities with harbors (and it's that pathfinding that takes so long). I'd do like that only instead of searching for a path, I'd flood fill outwards along all riverside tiles from each city, like the game already does for roads, and like I've already reproduced in Trade Net X. So it's doable, but honestly, I have so much already lined up that I won't get around to this any time soon.

That is fine for my purposes now. Since I'm working on a Nile scenario, my goal is to have the Nile as the only river on the map, and use an airport replacement as a way to link up the cities along the river. But I do think in the future it will be very useful to have a more robust way to achieve that, even on maps with more than one river.
 
During testing with the multiplayer tool to periodically switch to AI perspectives during an otherwise normal game (not debug) I noticed the following: AIs will enter lots of gpt deals with other AI civs, which causes at least two thirds of the AI civilisations in a given match to rapidly bankrupt themselves. You quickly get the tech leader swimming in 10k, 20k of money, while the others get down to 0 gold and negative gpt, causing repeated losses of buildings and units. Do you think something can be done about this?

In the same vein, do you think it'd be possible to make it so that bankrupt AIs at a negative gpt will never, ever sell a building? (Even if that means that bankruptcy entails fewer consequences for them.) With heavily perfumed granaries I see some AI cities build them five times in a single game, as they keep rebuilding it and selling it to bankruptcy. I think their economy would be much healthier if they just held on to all these buildings.
May I ask roughly how many deals and about how large a quantity? And is the money actually passed on to the recipient even if the donor has insufficient income to fund regular payments?

This would be easy. There's a method in the game whose job is to delete a building from a random city that's used on players when they go bankrupt. I could modify it to do nothing for AIs. As an aside, I wouldn't say players "sell" buildings when they're bankrupt because they receive nothing from the sale. The buildings are simply deleted. I mention it because that's something I noticed and changed for the aggressively_penalize_bankruptcy option. It makes more sense if the buildings are actually sold.
Having the option of easing conditions for the AI might help in part. Or go giving a free cheating amount of gold per city each turn, as is usually done in games, to help lose some of the incompetence in the AI economy.

I think the most important part of this is to determine what is merely a symptom and what is the cause of the problem with the AI economy. According to my observations, AI simply doesn't know when to stop producing units it can no longer support. Any ideas on what could be done about that?

This is probably most evident in the examples of larger maps with isolated civilizations on islands. They have no one to fight, gold at 0, buildings all sold off and the ones that are built are sold off immediately as well, but because they are able to build more units each turn than they lose via disbanding due to the cost of sustaining units, they are literally in an endless loop that is very hard to get out of. The fate of such backward civilizations is usually that a far more advanced civilization comes along with whom they come into conflict, and the more advanced civilization decimates all of their offensive forces, which ironically revives the economy of the backward civilization. Sometimes the situation is so extreme that a civilization is unable to even maintain workers and therefore has not built proper roads, so its economic capacity is completely lost. This is just an example where multiple things affecting this complex problem go wrong, because of course there are isolated island civilizations that manage to avoid this fate.

To be fair, perhaps this behavior is perfectly justified because it's part of some triggering process that outsiders can't see into and without which the AI would be unable to plan its war campaigns. Perhaps there are situations where unregulated troop production is appropriate regardless of sustainability or economic consequences especially in times of war or preparation for war. Perhaps the problem would be that some government regimes do not have large enough troop support for even basic city defense units.

Still, I think a new rule (if one doesn't already exist) is needed to limit unsustainable military production in situations like:
- I have no contact with any other civilization. (I'm isolated on an island by myself.)
- I'm hopelessly technologically backward. (Something needs to change instead of making basic archers over and over again essentially until the end of the game.)
- I am the strongest of all the civilizations I know of. (The Military Advisor knows when comparing to another civilization whether our military is weak, average, or strong, so for both average and strong cases, there could be a limitation on continued troop production depending on the aggressiveness of the civilization.)

Perhaps the simplest solution would be to have a Ratio (like for artillery or bombers) between Units and Buildings (including wealth) being built in cities at the same time. When approaching the limit of supported units given by the government regime to more than 80%, the ratio would start to apply and cities would be forced to switch production from units to buildings either immediately or after the current production is complete. The encouragement only applies if the AI is already above a minimum of 1 defensive unit per city and 1 offensive unit per 2 cities. The exception would be cities with no defenders, because it would be foolish for such defenseless cities to be forced to build a building. Another exception could be situations where the AI is panicking because it has an enemy outside the city gates. If this could really be worked out in detail, there would be multiple levels of this ratio depending on the aggression level and the limit of units supported by a given government regime:
(Units / Supported Units = X%)

Aggression Level: 0
80% - ai_build_unit_ratio = 50,
90% - ai_build_unit_ratio = 30,
100% - ai_build_unit_ratio = 15,
110% - ai_build_unit_ratio = 5,
120% - ai_build_unit_ratio = 2,
150% - ai_build_unit_ratio = 1.

Aggression Level: 1
80% - ai_build_unit_ratio = 60,
90% - ai_build_unit_ratio = 40,
100% - ai_build_unit_ratio = 20,
110% - ai_build_unit_ratio = 10,
120% - ai_build_unit_ratio = 3,
150% - ai_build_unit_ratio = 1.

Aggression Level: 2
80% - ai_build_unit_ratio = 75,
90% - ai_build_unit_ratio = 50,
100% - ai_build_unit_ratio = 25,
110% - ai_build_unit_ratio = 15,
120% - ai_build_unit_ratio = 5,
150% - ai_build_unit_ratio = 2.

Aggression Level: 3
80% - ai_build_unit_ratio = 90,
90% - ai_build_unit_ratio = 75,
100% - ai_build_unit_ratio = 50,
110% - ai_build_unit_ratio = 25,
120% - ai_build_unit_ratio = 10,
150% - ai_build_unit_ratio = 5.

Aggression Level: 4
80% - ai_build_unit_ratio = 100,
90% - ai_build_unit_ratio = 80,
100% - ai_build_unit_ratio = 60,
110% - ai_build_unit_ratio = 40,
120% - ai_build_unit_ratio = 20,
150% - ai_build_unit_ratio = 10.

@SG52 I appreciate the passion. I can be quite verbose myself, but you might kill Flintlock with your tomes.
You kind of expect to run into people on the forums for a game celebrating its 24th birthday this year who aren't exactly normal and have a certain unusual passion for the cause. All I care about is pitching ideas that might interest someone enough to implement them. You never know which seemingly banal idea will turn out to be literally game-changing in terms of enjoyment of the game or quality of the experience. The very least that is expected of me is to express myself in the most organised way possible, so that it is clear that I have thought through the issue to its implications and as comprehensively as possible. Things that until recently seemed unthinkable are now within reach and one becomes curious as to how far it is possible to go. What a time to be alive and be a fan!
 
I have noticed another thing with AI money spending: When an AI has finished the tech tree and is researching future technologies, it will set its spending to 10% science, 90% luxury. This obviously leaves no room for actual tax income, and the AI will also bankrupt itself.

And furthermore: Do you believe it is possible to make AIs uninterested in buying strategic resources that they have no use for? For example in a scenario with a camel resource for camel riders in the antiquity or middle ages, but nothing using that resource beyond, AIs should probably not care very much about buying up surplus camels in the modern age. (Of course, if the unit is still trainable, that is a different story, I am thinking of it being upgraded to / rendered obsolete by a later unit which is instead available and which renders the outdated unit with the outdated resource untrainable.
 
I think the most important part of this is to determine what is merely a symptom and what is the cause of the problem with the AI economy. According to my observations, AI simply doesn't know when to stop producing units it can no longer support. Any ideas on what could be done about that?
I think the simplest solution would be to knock down the valuation, like negative perfume does, of all military units based on how far the AI is above its unit support limit. That ought to push units below buildings in its evaluation of what to build and in the extreme case could even push units below wealth. I think enforcing a ratio is a heavy-handed solution. Part of the reason I did that in the first place for artillery was simply that it was easy. The other reason is that human players often think in terms of ratio of artillery to offensive units, specifically infantry, so I thought a config setting along those lines would be intuitive. I don't think anyone thinks in terms of ratio of units to buildings, though.

I hate to harp on about Lua, but again this is something that could be easily experimented with using a little script if Lua were properly integrated. My plan after R21 was to remove, or at least try to remove, the city limit during the winter then move onto Lua in the spring. Well, I haven't even gotten around to the city limit yet because I started working instead on expanding the workable areas of cities. That ended up being much more difficult than I'd anticipated and it's still not even done yet, though I have gotten it mostly working as a proof of concept.

I have noticed another thing with AI money spending: When an AI has finished the tech tree and is researching future technologies, it will set its spending to 10% science, 90% luxury. This obviously leaves no room for actual tax income, and the AI will also bankrupt itself.
And furthermore: Do you believe it is possible to make AIs uninterested in buying strategic resources that they have no use for?
I intend to look into modifying how the AI sets its sliders at some point but haven't gotten around to it yet. I have at least found the method responsible for that in the game code. The big issue with the AI's slider usage is that it's not aggressive enough on the luxury slider but when I look into modifying it I could address that issue you mentioned too. I don't know about changing how AIs value strategic resources. It's probably possible but I haven't found where in the code the AI judges the value of resources so I can't say anything specific.
 
Just upgraded from R17 to R21 and wow there are some impressive upgrades! One thing I would love to be able to do and doesn't seem to be available yet would be creating negative requirements for buildings and units. For example to set requirements that Stock Exchange requires NOT Communism (because it makes no sense for communists to build stock exchanges); or Secret Police HQ requires NOT Democracy (because it doesn't make sense for fascists, monarchies etc. not to have access to it).
 
7 tile city radius is a huge AI buff. Just finished an almost competitive regent game. Most fun I had since I came here and optimized the fun out of the game.
 
Last edited:
Most likely referring to the latest version in GitHub:

Code:
; Controls the size of the area in which cities can work tiles. The value corresponds to cultural border expansions. For example, setting this to 1
; means cities would only be able to work tiles within their level 1 cultural borders, meaning the eight tiles neighboring the city's own
; tile. Setting to 2 gives you the game's standard rule that cities may work tiles within their level 2 cultural borders, which they attain after one
; expansion. Setting to 3 allows them to work within level 3 borders and so forth.
; Notes: (1) If you set this value >= 4, the map view on the city screen will be zoomed out when you enter it. Otherwise it's not possible to show the
; entire work area. You can zoom back in by pressing Z. (2) The next option below can limit cities' workable areas to be smaller than the radius set
; here, based on their culture. (3) This option has a minimum value of 1 and a maximum of 7.
city_work_radius = 2

Haven't tried this version myself yet though, no idea how stable the version in the branch is.
 
Flintlock updated C3X with a new update entry:

Release 22

New in this version:
- Can adjust the size of the area cities can work
--- Setting named city_work_radius, standard radius is 2, can be set 1 - 7
--- work_area_limit option allows the workable areas to be limited based on cities' cultural levels
- Option do_not_unassign_workers_from_polluted_tiles (off by default)
- Fix AI players sometimes spawning nonsensical units when hitting a unit limit
- Pressing the Z key on the city screen toggles the zoom level of the map display

Read the rest of this update entry...
 
R22 is small in terms of feature count but not in terms of effort. Expanding city work areas ended up being a lot more difficult than I thought when I started working on it. In the end it took me about a month and a half. To make a long story short, the core of the job was patching loops that must have looked something like this in the game's original source code:
C++:
for (int i = 0; i < 21; i++) {
    int dx, dy;
    neighbor_index_to_diff(i, &dx, &dy);
    Tile * tile = map.get_tile_at(city->x + dx, city->y + dy);
    // Do something with this tile...
}
It would be nice if I could have simply replaced that 21 with a larger number, for example 37 to extend the loop over a third ring, however there were two problems with that. First, the game's standard tile enumeration, defined by the function I've called neighbor_index_to_diff, doesn't line up with city cultural levels. That standard enumeration's third ring is larger than the cultural ring. In other words, if you just extend the loop to 37 tiles, you'll cover some in the fourth cultural ring without covering all in the third.

The second problem I encountered was that the number 21 in machine code was stored in an 8-bit signed integer so it could be swapped out in place with a value of only 127 at most. Specifically, the "i < 21" part of the C++ code was compiled to a three-byte comparison instruction with one byte containing the second operand, interpreted as a signed value. That created a problem for expanding the work area up to the sixth cultural ring because at that point it included 137 tiles.

The solution was to apply more complex patches to the machine code than I'd originally hoped were necessary. I replaced the comparison instructions already mentioned plus the jump instructions at the end of each loop with jumps into custom mod logic. There, space is no longer an issue. When I replace the comparison instruction, I can make it as big as I like. Then I also redirected the calls to neighbor_index_to_diff to a custom mod function that does the same thing except enumerates tiles in an order corresponding to cultural levels, i.e., for the custom function, indices 0 to 37 cover all tiles in the first three cultural rings. There were some places where the loop indices were passed to other functions so I had to intercept those calls as well in order to convert the nonstandard index to what the game expects.

I found 25 loops over the city work area that needed patching. They're pretty much what you'd expect: one loop to gather tile yields, one for when a city grows pop, one for losing pop, three for the governor managing a city, two for creating a city, three for destroying one, one for setting production (b/c of mobilization bonus), a bunch for the worker AI, a bunch for the city screen, and a bunch more I'm forgetting. Other than editing the loops there were many little issues I had to resolve, mostly related to the fact that the city screen wasn't intended to show tiles being worked so far away.

Some pics showing a work radius of 7:

Rome can work almost the entire Italian peninsula except for Sicily:
Megarome.jpg

I built Shakespeare's Theater in Tokyo and joined a bunch of workers in to create a medieval era megalopolis:
Megatokyo.jpg

Look at this crummy city the AI founded in the middle of the Sahara... wait, how is it size 12?
Crummy Elephantine.jpg


...Oh
Or is it.jpg


7 tile city radius is a huge AI buff. Just finished an almost competitive regent game. Most fun I had since I came here and optimized the fun out of the game.
It's a fun twist on the rules for sure. I've been playing test games on the Monstrosity map with a work radius of 7, min city separation of 5, and cultural border factor of 5 (so borders grow very fast). With this setup, there are no bad cities since they all have so many tiles to choose from. I think the AI benefits from that a lot as it normally wastes so many shields on useless infrastructure, but when all cities are strong, no infrastructure is completely useless, and it doesn't take long to build. The AI struggles with workers, though. You need a lot more workers when cities are so far apart and grow so quickly. I haven't tried adjusting the AI worker requirement yet, but I estimate it ought to be set to 300% at least.


One thing I would love to be able to do and doesn't seem to be available yet would be creating negative requirements for buildings and units. For example to set requirements that Stock Exchange requires NOT Communism (because it makes no sense for communists to build stock exchanges); or Secret Police HQ requires NOT Democracy (because it doesn't make sense for fascists, monarchies etc. not to have access to it).
This is the sort of thing that would be perfect for Lua.
 
Hello. Thanks to Flintlock for the great C3X mod.
C3X_22 has an interesting feature to increase the number of tiles cities can use.
I set the following values:
toggle_zoom_with_z_on_city_screen = true
city_work_radius = 3
work_area_limit = cultural-or-adjacent
Everything works fine. Setting the value to "cultural-or-adjacent" allows smaller cities to grow faster by using adjacent tiles of the next culture level.
The value "cultural-or-adjacent" theoretically allows larger cities to use tiles of culture level 4. But with "city_work_radius = 3" they can never be used.
When opening the city screen with a culture level greater than 100 (level 3), the city image is always zoomed out. To zoom in, you have to press the "z" key every time. Is there a way to fix this?
If you set the value
toggle_zoom_with_z_on_city_screen = false
then the "z" key does not work.
 
The value "cultural-or-adjacent" theoretically allows larger cities to use tiles of culture level 4. But with "city_work_radius = 3" they can never be used.
When opening the city screen with a culture level greater than 100 (level 3), the city image is always zoomed out. To zoom in, you have to press the "z" key every time. Is there a way to fix this?
That's a small oversight on my part. The only way to fix that would be to edit the mod code. To do that, go to line 448 of injected_code.c, which should be:
effective_radius += 1;
and replace it with:
effective_radius = not_above (is->current_config.city_work_radius, effective_radius + 1);
 
That's a small oversight on my part. The only way to fix that would be to edit the mod code. To do that, go to line 448 of injected_code.c, which should be:
effective_radius += 1;
and replace it with:
effective_radius = not_above (is->current_config.city_work_radius, effective_radius + 1);
Thank you. It works great.
I also noticed that with the "cultural-or-adjacent" settings, the borders of a city with culture level 1 cover the four corner tiles of culture level 3 (marked with ✔ in the picture).
Whether this is done on purpose or by accident, using the extra tiles gives small cities a better chance of growing faster.
1744528480189.png
 
@Flintlock sorry if this has already been asked, but how do we "see" what the current most desired techs for the AI are, so they we know how much to "perfume" techs to get the desired effect for them to research?
 
Whether this is done on purpose or by accident, using the extra tiles gives small cities a better chance of growing faster.
It was on purpose, those tiles are considered adjacent to the cultural area even though they only share a vertex with it. The idea behind the cultural-or-adjacent rule is that it makes it so that all tiles within your cultural borders are workable by some city. The expansion by one tile in every direction captures all tiles that the game may fill in between cultural borders. By the way, that Roman themed city screen looks pretty nice.

@Flintlock sorry if this has already been asked, but how do we "see" what the current most desired techs for the AI are, so they we know how much to "perfume" techs to get the desired effect for them to research?
There is no way to do that in the current version. It ought to be easy to program, though, so I'll try to get it done for the next version. Don't forget you can specify perfume amounts in percent now so it's less important to know the exact numbers the AI assigns things. Also, the AI's evaluation of technologies is used for trade as well as choosing research, so you can get an idea of how it much it values techs by checking how much gold it would pay for them.
 
Back
Top Bottom