Skip to content

Conversation

@Philiquaz
Copy link
Contributor

WIP because I haven't written all the rule-parsing or tested it yet.

Greatly expands on previous PR #15 by introducing a rule system to define more categories of minimum separation rules other than "any city" and "any foreign city"

Rule system intended to include support for identifying cities by varying criteria, terrain by criterias, resources and units, and so forth. My hope is the "target" types can be reused down the road when defining rules for other gameplay modifications.

Rules can define minimum and maximum counts (with existing min-separation type rules having a maximum of 0, for example), have 3 metrics to mix+match (including euclidean now [uses a 100x multiplier to give configs some precision]) and support for enabling or disabling by researched techs.

Hopefully this creates enough rule conditions to create all sorts of weird and wonderful scenarios. Zones of settlement denial, only settle with grain nearby, and so forth.

Assistance with writing the parsers would be appreciated, since it's rather dull the motivation to finish might be a bit lacking.

@maxpetul
Copy link
Owner

My ultimate plan for this sort of thing, allowing the game rules to be modified in weird or complex ways, is to integrate Lua with the program and then allow rules to be scripted in Lua. I hope to start on that in earnest before too long, after R26 is done if nothing else comes up. So I wouldn't recommend spending effort on complex pseudo-scripting languages for custom rules when that sort of thing will become obsolete soon (I hope).

@Philiquaz
Copy link
Contributor Author

Philiquaz commented Nov 24, 2025

A lua engine would be quite helpful. Are there not any performance concerns? I suppose with this example, iterating over the map once when checking for a single unit isn't so bad, but the rules could get quite complicated, particularly for other cases. And extra so for some purposes, like possible tweaks to map generation.
But taken at face, of course, this means this PR just stands for a potential list of things to expose.

I don't know if you intend to just rawdog the memory accesses, but I will say the sheer ease I was able to crack open this repo and introduce new things was not much more than having to deal with lua (bless you so much), and reinstallation is seemingly trivial. So introducing lua should serve to actually make things more usable to more users, which means there's probably more work than you think in just adding data and options to your API (just in my experience of "we'll add a lua engine to do some modding")

The other half of generifying things is actually opening up more hook locations. I've already started thinking of game-of-life-ifying roads by giving them a max-3 1-range chebyshev rule (and maybe a max-5 or max-6 2 range rule) haha, but that's going to require some ghidra work and hook magic, and I've not dug into that yet. Is there a shared ghidra server mapping out the exe?
I also didn't pay much attention to the actual hook mechanism, other than seeing we've got a bunch of patch_ function declarations and a generated list of mapped function addresses. So actually making use of any newly mapped function I wouldn't know about either.

@maxpetul
Copy link
Owner

I intend to use LuaJIT so the performance of the Lua code itself should be pretty good. There will still be friction at the interface between Lua and C, and to minimize that I intend to call into Lua only when necessary. In other words, it will be possible to patch functions like it is right now, just with a Lua instead of C replacement, and the mod will only redirect calls into Lua if a replacement is defined. There could still be performance issues, though, for example I'm counting on LuaJIT to be able to access the C structs and functions from Lua without much overhead.

I'd like to convert Civ3Conquests.h into something usable from Lua but I'm not sure the best way to go about that. I tried a few years ago to write a Python script to convert it automatically but decided ultimately that it wasn't a good approach. A straightforward translation of the header file wouldn't give a good interface and trying to make it more abstract while translating wasn't really feasible with a script. I'd like to continue using AI this time. I think converting the interface is a good job for an AI since it's a job that's too mindless to interest me but not so mindless that it could be done by a Python script.

My Lua work so far is on the integrate_lua branch. I've built out just enough to port over the disorder warning feature, the Lua code for it is here: https://github.com/maxpetul/C3X/blob/integrate_lua/script.lua. I'm quite happy with it, you can do things like for citizen in city:Citizens() to loop over citizens more easily than in C, and civ3.ShowPopup simplifies what would be several function calls in C.

There's no shared Ghidra server exactly, the way I've been doing things so far is I send my Ghidra project to anyone who asks. If you want it, email me. There are a lot of methods I've found in the GOG EXE that aren't listed in civ_prog_objects.csv.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants