Mini-engine progress

Made all the performance enhancements runtime configurable. So now we have ini settings, in case my buggy code is too buggy.

Spoiler ini :
INI:
[CV4MINIENGINE_PERF_ENHANCED_DLL]

; Enables fixes for city updates, plot grouping, pathfinder usage, and enables the FAStar heuristic update. These fixes are important for testing.
GeneralFixes = 1

; Enables the fast vectorised pathfinder. This is a large bug-prone pile of code, but is so much faster than FAStar. Benefits from AVX-512. Only used for AI units.
VectorisedPathfinder = 1

; Enables fast vectorised evaluation of found values. This is a large bug-prone pile of code, but is so much faster than uncached scalar found value evaluation. Benefits from AVX-512. This option should not change game state checksums.
VectorisedFoundValues = 1

; Enables the blockwise union-find-based plot group system. This is a large bug-prone pile of code, but is so much faster than the original CvPlotGroup system. This option should not change game state checksums.
BlockwisePlotGroupSystem = 1

; Enables parallel unit updates for barbarians only. This is a large bug-prone pile of code, but makes gigantic maps much more practical when you have barbs enabled. Will parallelise "simple" unit AI and fallback to serial for everything else. This option only has an effect if VectorisedPathfinder is enabled.
ParallelBarbarianUnitUpdate = 1

; For gigantic maps, especially on Deity, barbs can easily exceed unit ID allocation capacity. This works around that by capping barbs to 4000.
HardCapBarbSpawns = 1

; Enables a small parallel city update. Only does AI_updateRouteToCity for now. This option should not change game state checksums.
CvCity_doTurnParallel = 1

; This option should not change game state checksums.
Faster_CvCityAI_AI_updateRouteToCity = 1

; A faster algorithm for computing the simple path step distance between plots. This option should not change game state checksums.
Fast_CvMap_calculatePathDistance = 1

; Relaxes "group cycle" ordering for AI, to speed up this function.
Fast_CvPlayer_updateGroupCycle = 1

; Basic whole-map parallel loop. This option should not change game state checksums.
Parallel_CvPlayer_countUnimprovedBonuses = 1

; Avoid doing things that only a human player cares about. This option should not change game state checksums.
Skip_AI_CvPlayer_doWarnings = 1

; Parallel loop over cities. Also calls CvMap::calculatePathDistance in parallel. This option should not change game state checksums.
Parallel_CvPlayerAI_AI_findTargetCity = 1

; Use a caching system to accelerate queries. This option should not change game state checksums.
Fast_CvPlayerAI_AI_calculateStolenCityRadiusPlots = 1

; Basic whole-map parallel loop. This option should not change game state checksums.
Parallel_CvPlayerAI_AI_updateCitySites = 1

; Use a fast flood-fill algorithm. This option should not change game state checksums.
Fast_CvPlot_updateIrrigated = 1

; Cache this value. This option should not change game state checksums.
Fast_CvPlot_isCoastalLand = 1

; Use a faster flood-fill algorithm to count plots instead of FAStar. Only has an effect if BlockwisePlotGroupSystem is disabled. This option should not change game state checksums.
Fast_CvPlotGroup_recalculatePlots = 1

; This AI procedure expects a short path, so use a path limit. This option should not change game state checksums, unless VectorisedPathfinder is enabled.
PathLimit_CvSelectionGroup_groupAttack = 1

; Use a caching system to accelerate queries. This option should not change game state checksums.
Fast_CvTeamAI_AI_calculateAdjacentLandPlots = 1

; Trivial path limit. This option should not change game state checksums, unless VectorisedPathfinder is enabled.
PathLimit_CvUnitAI_AI_group = 1

; Trivial path limit. This option should not change game state checksums, unless VectorisedPathfinder is enabled.
PathLimit_CvUnitAI_AI_guardCityMinDefender = 1

; Trivial path limit. This option should not change game state checksums, unless VectorisedPathfinder is enabled.
PathLimit_CvUnitAI_AI_guardCity = 1

; Whole-map parallel loop with distance sort and path limit.
Parallel_CvUnitAI_AI_guardBonus = 1

; Whole-map parallel loop with distance sort and path limit.
Parallel_CvUnitAI_AI_guardFort = 1

; Non-trivial path limit.
PathLimit_CvUnitAI_AI_spreadReligion = 1

; Rearranges logic to perform less pathfinding.
Faster_CvUnitAI_AI_construct = 1

; Loop over units instead of plots.
Faster_CvUnitAI_AI_protect = 1

; Perform a localised search instead of a whole-map loop. This is an approximation of the original exploration AI.
Localised_CvUnitAI_AI_explore = 1

; Perform a flood-fill to find reachable plots instead of using a pathfinder.
Localised_CvUnitAI_AI_exploreRange = 1

; Sorts cities by distance and use a path limit.
Faster_CvUnitAI_AI_targetCity = 1

; Trivial path limit. This option should not change game state checksums, unless VectorisedPathfinder is enabled.
PathLimit_CvUnitAI_AI_targetBarbCity = 1

; Non-trivial parallelisation  of privateer AI. May not be all that effective. Privateer pathing is almost worst case scenario.
Parallel_CvUnitAI_AI_pirateBlockade = 1

; Whole-map parallel loop to filter pathing targets.
Parallel_CvUnitAI_AI_improveBonus = 1

; Sorts cities by distance and use a path limit.
Faster_CvUnitAI_AI_retreatToCity = 1

; Sorts cities by distance and use a path limit.
PathLimit_CvUnitAI_AI_trade = 1

; Trivial path limit. This option should not change game state checksums, unless VectorisedPathfinder is enabled.
PathLimit_CvUnitAI_AI_getEspionageTargetValue = 1

; Sorts cities by distance and use a path limit.
PathLimit_CvUnitAI_AI_moveToStagingCity = 1

; Sorts cities by distance and use a path limit.
Faster_CvUnitAI_AI_pillage = 1

So I expect the release configurations will be "Strict"/"Vanilla", "PerfEnhanced AVX2", and "PerfEnhanced AVX-512", where the vanilla version does not have any enhancements compiled in and should yield the same game state checksum as the Firaxis DLL.

Even with all that though, turn times still reach 26-33s at T660+ on a 5x Huge map. To optimise further, one would need to: get rid of plot revealed python event (only BUG Event Signs uses it), use approximate pathfinding, parallel unit AI for most units, and parallel city updates. Pathfinding is currently about 40-60% of main thread time, so even if pathing was instant, you still wouldn't have fast turn times. Will need fully parallel AI, which is almost a DLL rewrite.

So, gigantic maps take too long to practically AI autoplay test from start to end.

But Huge Marathon with 18 players takes about 9 minutes from start to end. Finished at turn 765. Huge 5x would take, like, an hour or two. But things might be different if a human was playing, as you'd be busy reducing the number of AI units. Better get around to it by a few hundred turns though.
 
But Huge Marathon with 18 players takes about 9 minutes from start to end. Finished at turn 765. Huge 5x would take, like, an hour or two.
Wow! Amazing! 😍🤩
 
3dfb55aad54797770e4680579a7dbc6291dbba1d433f26e4e3170ced9f08fa24.jpg
 
It linked.
2025y08m31d - Cv4MiniEngine Linux.png

One mess of a cmake file though.

What I'll probably do is keep my VS project around and have the cmake file for people who dare to build it on Linux. It will not be a totally smooth experience as you need to build SFML3 and you need to manually install Python 2.7. The build script will also patch the old version of pybind11 to make it work.

Native File Dialogs does not support pure console, which is all I have in WSL, so I'll probably throw together a basic console file browser.

The next stumbling blocks will be file system case sensitivity and I'll have to use ANSI console input instead of Win32 console input. *And BUG mod. It has platform specifics.
 
Last edited:
2025y09m06d - Cv4MiniEngine BUG Linux.png

BUG Mod on Linux. Seems to start up at least. Uses CvAltRoot and patches BugPath.initRootFolder. Naturally, I can just call into my own engine to get the user profile directory. But BUG, *unpatched, still goes on trying to access the Windows registry on Linux. Maybe the BUG devs could add Linux support?

Anyway, if game checksums match and I can play a game on Linux, then release will soon be approaching. Will probably release with GPL licence, but, FAStar. What am I going to do with that. Either I'll stick it in it's own repository and give it a questionable use at your own risk licence, or I'll accept somebody else's FAStar. Well, if 2K nukes FAStar and not the entire DLL containing all their code, then it's not the end of the world. An exact FAStar reimplementation is merely a nice thing to have for testing.
 
Last edited:
Another event bug. CvRandomEventInterface.canTriggerImmigrantCity lacks a return statement, so it either returned False or None. And because CvCity::getTriggerValue didn't initialise the return variable, you get undefined behaviour, just like unsequenced RNG usage.

So now I'm patching these bugs with a little BTS Mod when testing the Firaxis engine, and a patch script in Cv4MiniEngine. Now both engines agree on final game state, for now, for this game.
 
Did game hash verification with some enhancements enabled. So, more fixes.

I forgot to set m_iHeuristicCost when updating FAStar heuristic values, so my fixed FAStar was never fixed this whole time. This became obvious when CvMap::calculatePathDistance started returning different values and enabling FAStar fixes didn't fix it. I'm sure this would have caused unit pathing verification issues too.

And, the vectorised found values system didn't get proper AI city site and CvArea::changeCitiesPerPlayer invalidation.

Release pending a bit of Linux play testing. But delayed as I won't be around for most of next week.

But CMake script now outputs launch scripts. Might need to look into why xml.log is so different. Probably caching.
*Yes, it was caching. Used Linux's epoch for default timestamp which is year 2174.
2025y09m12d - Cv4MiniEngine Windows Distrib.png
2025y09m12d - Cv4MiniEngine Linux Distrib.png
 
Last edited:
Awesome progress, great to see! I wonder if there would be a way to have both engines running the same game at the same time, then have the original engine call into the new engine to do the turn processing and return the results to the old engine? That way we could have the ui of the old engine but better turn times of the new? Or is this not at all how the engine could be made to work? Also I guess we could run into address space issues since old engine is still 32 bit.
 
Awesome progress, great to see! I wonder if there would be a way to have both engines running the same game at the same time, then have the original engine call into the new engine to do the turn processing and return the results to the old engine? That way we could have the ui of the old engine but better turn times of the new? Or is this not at all how the engine could be made to work? Also I guess we could run into address space issues since old engine is still 32 bit.
No, it doesn't work that way.
One of the main goals is to get rid of the 32 bit engine's limitations.
And about the UI: @Chrischn89 has already started working on the graphics side of things. Even if he won't do it all single handedly, the work HAS BEEN STARTED on it 🙂
 
Awesome progress, great to see! I wonder if there would be a way to have both engines running the same game at the same time, then have the original engine call into the new engine to do the turn processing and return the results to the old engine? That way we could have the ui of the old engine but better turn times of the new? Or is this not at all how the engine could be made to work? Also I guess we could run into address space issues since old engine is still 32 bit.
Play by email. /s

Graphical engine reimplementation would be ideal. If at all reasonable.
 
And about the UI: @Chrischn89 has already started working on the graphics side of things. Even if he won't do it all single handedly, the work HAS BEEN STARTED on it 🙂
Do we have a status update on this? Last I can find is a month old and about unpacking packed graphics. I'm way more interested in knowing any progress regarding converting the 3D files into an open format modern engines can read. My point of view is that a full engine replacement is "if it can be done", but it will change to "when it will be done" once we have 100% 3D graphics compatibility because then it becomes more of a long list of tasks to do without having tasks where it's not known if they can be done.
 
Do we have a status update on this? Last I can find is a month old and about unpacking packed graphics. I'm way more interested in knowing any progress regarding converting the 3D files into an open format modern engines can read. My point of view is that a full engine replacement is "if it can be done", but it will change to "when it will be done" once we have 100% 3D graphics compatibility because then it becomes more of a long list of tasks to do without having tasks where it's not known if they can be done.
So, having discussed this with the people that do art for AoE, the process of converting nif/kf to modern formats is possible, but they're not aware of a mass convert process, so it'll possibly be tedious.

my personal concern is an issue of chicken and egg. no art people will want to commit to that process (if no mass convert in sight) without a proof of concept of the engine ( if only to decide what the new format will be), so we need that first, with minimal graphic people's support.
 
Last edited:
So, having discussed this with the people that do art for AoE, the process of converting nif/kf to modern formats is possible, but they're not aware of a mass convert process, so it'll possibly be tedious.

my personal concern is an issue of chicken and egg. no art people will want to commit to that process (if no mass convert in sight) without a proof of concept of the engine ( if only to decide what the new format will be), so we need that first, with minimal graphic people's support.
Yes, NIFs aren't just meshes. If you want to put them in a new format, that format would have to support animations and particle systems, and whatever else is in there. Maybe you could do it if you use your engine's general scene format, but there may still be points of friction.

Using NIFs as-is shouldn't be too difficult. Especially for a proof-of-concept where you just need meshes. If you convert them, you would need something to load them anyway.
 
So, having discussed this with the people that do art for AoE, the process of converting nif/kf to modern formats is possible, but they're not aware of a mass convert process, so it'll possibly be tedious.

my personal concern is an issue of chicken and egg. no art people will want to commit to that process (if no mass convert in sight) without a proof of concept of the engine ( if only to decide what the new format will be), so we need that first, with minimal graphic people's support.
It's understandable. With all the concept ideas being proposed for pretty much everything online, odds are that most of them will never go anywhere. People join in when something starts to work and be useful. It feels like a waste of time to spend possibly months on something, which relies on somebody else doing something and then no somebody else shows up to do their part.

It would be nice to get a guide for how to convert something. On top of teaching more people how to do it, hence spread the workload on more people, knowing what needs to be done could be a help if trying to automate the process. If possible, I would strongly prefer to not include vanilla graphics and instead convert on load, which is for reasons mentioned ages ago about an engine replacement not being a replacement for buying the game. However automating the process is a concern for after having figured out how to even convert at all.

Also I'm not a huge fan of having to manually convert every single modded unit/building/whatever. That could take a while.
 
Hello again! I'm sorry that I didn't give an update any sooner (as usual lots of IRL stuff going on :cry:), nonetheless I made quite some progress as I still invest any free minute to get things off the ground:

No, it doesn't work that way.
One of the main goals is to get rid of the 32 bit engine's limitations.
And about the UI: @Chrischn89 has already started working on the graphics side of things. Even if he won't do it all single handedly, the work HAS BEEN STARTED on it 🙂
That's exacty right! My goal is to get a basic prototype going so that more talented and experienced coders can jump straight in and start playing around immediately.

Do we have a status update on this? Last I can find is a month old and about unpacking packed graphics. I'm way more interested in knowing any progress regarding converting the 3D files into an open format modern engines can read. My point of view is that a full engine replacement is "if it can be done", but it will change to "when it will be done" once we have 100% 3D graphics compatibility because then it becomes more of a long list of tasks to do without having tasks where it's not known if they can be done.
I absolutely agree with all of you that's it is a thing of "when" not "if". I still think that with Civ IVs 20th anniversary next month, people might think back of how great Civ IV actually was (and still is!) and might also start wishing for a modern remaster. It would be great if people stumbled upon what's going on here and offered to share their expertise in different fields.


So, having discussed this with the people that do art for AoE, the process of converting nif/kf to modern formats is possible, but they're not aware of a mass convert process, so it'll possibly be tedious.

my personal concern is an issue of chicken and egg. no art people will want to commit to that process (if no mass convert in sight) without a proof of concept of the engine ( if only to decide what the new format will be), so we need that first, with minimal graphic people's support.
Converting the nif/kf files isn't really the problem in my opinion. There's quite a few plugins and converters out there (thanks to the Elder Scrolls still using nifs) so that it's trivial to take those and convert the files to just about anything else. The underlying problem for an open source reimplementation is the copyright though. We can't distribute the original nor converted files that are based on the original files. That leaves us with two options: 1.) convert the files on the user's device and call them up from there (which could be either quite the complex task to automate or cumbersome for the user if he has to do it by himself) or 2.) we let the user point to a valid Civ IV installation on his system and read the original files raw and create our own data structures (or rather structures that the underlying engine can work with) inside the program.

The chicken and egg problem is exactly right, which is why I'm working on a prototype atm, to pull more people in.


Yes, NIFs aren't just meshes. If you want to put them in a new format, that format would have to support animations and particle systems, and whatever else is in there. Maybe you could do it if you use your engine's general scene format, but there may still be points of friction.

Using NIFs as-is shouldn't be too difficult. Especially for a proof-of-concept where you just need meshes. If you convert them, you would need something to load them anyway.

True!



It's understandable. With all the concept ideas being proposed for pretty much everything online, odds are that most of them will never go anywhere. People join in when something starts to work and be useful. It feels like a waste of time to spend possibly months on something, which relies on somebody else doing something and then no somebody else shows up to do their part.

It would be nice to get a guide for how to convert something. On top of teaching more people how to do it, hence spread the workload on more people, knowing what needs to be done could be a help if trying to automate the process. If possible, I would strongly prefer to not include vanilla graphics and instead convert on load, which is for reasons mentioned ages ago about an engine replacement not being a replacement for buying the game. However automating the process is a concern for after having figured out how to even convert at all.

Also I'm not a huge fan of having to manually convert every single modded unit/building/whatever. That could take a while.

100% agree!


------
Current status:
In my last post I hinted at the niftools project as my best bet for getting into those pesky nif files and indeed I've made quite good progress because of it. I've spent quite some time getting the niflib (C++ library) into the Godot project (as a GDExtension) and after fighting with linking and compilation I've finally managed to get my development pipe stable so that I could then start work on the translation layer code.

I think using the niflib library was/is absolutely worth it because it saves so much time by not having to take nif files apart on the byte level ourselves and potentially spent countless weeks of development for troubleshooting errors.

Niflib provides functions for checking a valid nif version, reading out the header section, returning an array/vector of all the "NiObjects" that an entire nif file is composed of, it can return the root node of the nif tree hierarchy and finally it can return the direct children of a given NiObject. These functions are basically all we need to read an entire file and do whatever with it.

So after I've succesfully attached the niflib library to Godot I could feed a file path string into it and with some crude code I could at least draw the most basic meshes of a nif model in Godot:


axemangodot.pngaxemannifskope.pngbombergodot.pngironcladgodot.png


Which looks pretty sweet if I can say so myself (the ironclad is an homage to your profile pic @snowern :lol: )

Initially I thought that that would be a good point to just release it and maybe more talented people could take a look at it but then I realized that the way I'm drawing those meshes is not really useful by itself since it doesn't take into account that A) the nif file hierarchy (I think the proper term is a 3D scene graph?) is composed of a multitude of different types of Nodes that can be attached to each other to create that tree, which means it is super important to keep the hierarchy intact when importing nif files

and B) if I want anyone to understand what I've coded here (and I freely admit that I'm using AI to help me figure things out), that I need to properly comment it and take into account that this all happens inside the Godot engine context, which brings another layer of complexity to it, which is probably a lot to take in at once.

So what I'm doing right now is, rewrite the crude function that draws only the meshes, so that it can read the hierarchy of a given nif file, iterate through the entire file recursively (starting at the root object), determine what type of node it is and then convert it to the corresponding Godot type node (just as a dummy for now since this will be a big undertaking for all the different types of NiNodes) and then attach each converted node to the correct parent Godot node to recreate the original tree structure.

Unfortunately I've run into a CTD while writing it, which I'm debugging right now but for optimal troubleshooting I need to figure out how to work with the debuggers of Visual Studio and Godot (which also required me to recompile the entire Godot engine code with the debug flag set, otherwise I wouldn't even get debug info from it...)

So my immediate goals are:
- comlete the rewrite of the nif load function (create a working debug pipe)
- comment the code

and once completed:
- release the GitHub repo to public

I hope to be done before the anniversary next month, as I think it would be quite fitting to release just around the the 20 year mark for our beloved game :egypt:
 
2.) we let the user point to a valid Civ IV installation on his system and read the original files raw and create our own data structures (or rather structures that the underlying engine can work with) inside the program.
IIRC that's exactly what VCMI does with Heroes3. VCMI is for 10+ years without any legal issues.
 
people might think back of how great Civ IV actually was (and still is!) and might also start wishing for a modern remaster.
There is this thread (and poll) in the Civ 7 section : Civ Remastered

The question asked is different (civ 7 graphics??? gameplay updates??? who wants these?) to what you are doing, but anyway this does show some existing interest outside of the Civ 4 section.
 
There is this thread (and poll) in the Civ 7 section : Civ Remastered

The question asked is different (civ 7 graphics??? gameplay updates??? who wants these?) to what you are doing, but anyway this does show some existing interest outside of the Civ 4 section.
While Firaxis' remaster of Civ4 could save us the hurdles of remaking the civ from scratch on a 64-bit engine, there is a great chance it will go without an SDK. And it would be so over for so many mods.
 
Back
Top Bottom