Generalized auxiliary parameters in is_req_active()
Posted: Mon Feb 15, 2021 7:05 pm
A post mostly about the developer's side. The function is_req_active(), that stays behind all the requirements system, has now uncomfortably many parameters. Additionally to target player, city, unit and tile, there are other local parameters that specify objects in relation to which the requirement is calculated: other player, output type, building, specialist, unit type, action. And we can't introduce a requirement that e.g. select a specific tech to reduce its cost for some player without reworking a buttload of code that requires all these parameters and none else.
The idea is that selecting parameters never are supplied all at once for any requirement vector. E.g. "specialist" is used only for non-worker citizens' output effects, and "building" and "output_type" never go along. So, let the function, additionally to the four main parameters, have only three unspecific ones:
int index - for output type [for turn-break activities] and action number [for actions],
void *subjrel - for other player [generally] and specialist [for citizen iterator],
void *typerel - for building [for building iterator] and unit type [generally].
For cities in action enablers both unit types and buildings are possible, but not simultaneously (the city's production), so we can resolve it with an index-dependent requirement "ProductionKind".
Introduction of such a system will require a buttload of work once but will probably serve Freeciv project as long as it uses current requirement vector encoded rules (the system has many flaws main of which is inopacity of what is on the input but I doubt jumping from it to anything but natural language interpreted rules is genuinely possible). Seven parameters is what an average natural intellect operates with, some compound values should be constructed and passed if we ever need more. For example, a player-ranged effect of a reduced tech cost may easily use this system supplying tech as either subjrel or typerel, what fits the semantics better (?); or we can use extra id in index to fully describe the ability of building a specific extra in an action enabler, and it will require only local code changes.
The buggy matter is casting of void pointers, but we can do one thing to mostly remove the danger at least for a softmodder (a.k.a. ruleset author): each function that reads a requirement vector from file goes with a specifier on what role each variable parameter is used in, and there is a filter on requirements that throws up an error when you use a wrong requirement.
The idea is that selecting parameters never are supplied all at once for any requirement vector. E.g. "specialist" is used only for non-worker citizens' output effects, and "building" and "output_type" never go along. So, let the function, additionally to the four main parameters, have only three unspecific ones:
int index - for output type [for turn-break activities] and action number [for actions],
void *subjrel - for other player [generally] and specialist [for citizen iterator],
void *typerel - for building [for building iterator] and unit type [generally].
For cities in action enablers both unit types and buildings are possible, but not simultaneously (the city's production), so we can resolve it with an index-dependent requirement "ProductionKind".
Introduction of such a system will require a buttload of work once but will probably serve Freeciv project as long as it uses current requirement vector encoded rules (the system has many flaws main of which is inopacity of what is on the input but I doubt jumping from it to anything but natural language interpreted rules is genuinely possible). Seven parameters is what an average natural intellect operates with, some compound values should be constructed and passed if we ever need more. For example, a player-ranged effect of a reduced tech cost may easily use this system supplying tech as either subjrel or typerel, what fits the semantics better (?); or we can use extra id in index to fully describe the ability of building a specific extra in an action enabler, and it will require only local code changes.
The buggy matter is casting of void pointers, but we can do one thing to mostly remove the danger at least for a softmodder (a.k.a. ruleset author): each function that reads a requirement vector from file goes with a specifier on what role each variable parameter is used in, and there is a filter on requirements that throws up an error when you use a wrong requirement.