DLL coding thread

Presumably we would need admin permissions to do that. It doesn't look like the forum has a history of giving that to modders, though I have no idea what would happen if we ask them. It isn't a major concern for me and haven't really considered it until I read your post.

Seems like I remember we being able to delete post, as long as no one had posted after us. Anyway...

Would GC.getGameINLINE().getSorenRandNum(5, "RandomeNum") return a number between 0-4 or 0-5? I can't remember how this works, 0-4 right?
 
Would GC.getGameINLINE().getSorenRandNum(5, "RandomeNum") return a number between 0-4 or 0-5? I can't remember how this works, 0-4 right?
Look in the code to see how random numbers are generated (which are predictable random numbers btw. Otherwise network games wouldn't work).
Code:
((unsigned short)((((m_ulRandomSeed >> RANDOM_SHIFT) & MAX_UNSIGNED_SHORT) * ((unsigned long)[COLOR="Red"]usNum[/COLOR])) / (MAX_UNSIGNED_SHORT + 1)));
usNum is your input. To see the theoretically max we can get from this, we assign everything else to max:
Code:
(MAX_UNSIGNED_SHORT * usNum) / (MAX_UNSIGNED_SHORT + 1)
Or if we do it the old school math way:
Code:
65535
-----  * usNum
65536
As integer division always rounds down we will always get a result lower than usNum.

This mean giving 5 in the argument will return a number between 0 and 4.
 
Thanks for the clarification there:goodjob:

Are you working on anything M:C related? You could always help me:crazyeye: I managed to write up code so we can set up Civics to give random Growth units specified in the XML. Now I am looking into adding bonuses for having your Trading Post connected by roads (aka in the same plot group). I am contemplating the most efficient way to go about doing this. I am thinking that I could create a new array variable to CvPlotGroups so when a Trading Post is built it will add the Teams name to the plotgroup and increase the Trading Post count by +1. Basically...

Trading post built: +1 Trading post count to that player's team to plotgroup

City Destroyed: -1 count
or City at war with player: -1 count

The player gains a bonus based on the Plotgroup's player trading post count. How does that sound?

Feel free to help out on any of the planned Civic Effects, especially any complicated ones :)

I just realized I need to add code to remove Trading Post if player is at War with the City's owner.
 
Are you working on anything M:C related? You could always help me:crazyeye:
I'm currently profiling RaR. I made a gigantic map and set autoplay to 150 turns :sleep:
If I managed to speed it up, then I know it will work for M:C too. This mean I'm indirectly working on M:C.

Now I am looking into adding bonuses for having your Trading Post connected by roads (aka in the same plot group). I am contemplating the most efficient way to go about doing this. I am thinking that I could create a new array variable to CvPlotGroups so when a Trading Post is built it will add the Teams name to the plot and increase the Trading Post count by +1. Basically...
The question is what precisely do you want?

Say you need the total count of trade posts from player X and how many of those are connected to you by road. One way to figure this out is to loop all his cities and check for tradepost. If there is one, then if YOU have a plotgroup in the city plot, then it is connected to at least one of your cities. This approach has the benefit that it isn't using a cache and as such there is no risk that the cache is out of date.

If you need to know the number of trading posts in a plotgroup, then it would make sense to cache it like you said. However would it be enough to just have a count of tradeposts and not care for which player they belong to?

If there is a war, then any plots owned by the enemy will remove the plotgroup, including their cities. At least this is the plan. Now that I think about it, I'm not actually sure I tested this scenario. Anyway it is supposed to work and if it doesn't then we need to fix plotgroups, not trading posts :)

If you want tradeposts to count differently, then you need to explain yourself a bit better.

Feel free to help out on any of the planned Civic Effects, especially any complicated ones :)
We should really write outstanding tasks on the issue tracker: https://github.com/Nightinggale/Medieval_Tech/issues
If we do that, then we tell the rest of the world which tasks we plan to do, but haven't done yet. We can assign tasks to people meaning we can coordinate that we do not try to do the same at once. Also in this case you can write a bunch of subtasks for civics and I can take a look at possibly assign one or more to myself. Right now I really lack the overview of what you are doing and what needs to be done. I think it would be fine if we can work at different parts of the same task at once to join forces, but we need to organize it better than we do right now. In fact we have no coordination currently.
 
If there is a war, then any plots owned by the enemy will remove the plotgroup, including their cities. At least this is the plan. Now that I think about it, I'm not actually sure I tested this scenario.

I will be testing this out with my trade post deal.

If you want tradeposts to count differently, then you need to explain yourself a bit better.

Ok, I have been thinking this through. Imagine with me if you will, you open up a City Screen and at the top with all the other pertinent information about Prosperity and such you see a Trading Post icon and a number. This number represents the number of trading post connected to this City. With that number we can give the city bonuses, like extra trade points, gold per turn, extra demand, extra research, etc. This can be effected by your type of Civics as well. When you hover the mouse over the icon you get all the important information.

Even the Player's own Trading Posts can add to this, but perhaps Foreign Trading Post give bigger bonuses. So, if you are following me, what would be the best way to code this?

Edit: At some point I want the player to have a Per Turn Gold income, with expenses and maintenance cost, you know, like running a real Empire. You would have an Financial Screen you can pull up and see where all you money is going as well as what has brought you the most profits and such. Anyway, this Trading Post deal will help add to that.

We should really write outstanding tasks on the issue tracker: https://github.com/Nightinggale/Medieval_Tech/issues
If we do that, then we tell the rest of the world which tasks we plan to do, but haven't done yet. We can assign tasks to people meaning we can coordinate that we do not try to do the same at once. Also in this case you can write a bunch of subtasks for civics and I can take a look at possibly assign one or more to myself. Right now I really lack the overview of what you are doing and what needs to be done. I think it would be fine if we can work at different parts of the same task at once to join forces, but we need to organize it better than we do right now. In fact we have no coordination currently.

Ok, I will fill this in with my current list of Civics task. Yeah, we have mostly just been doing our own thing, but I know we can work together:) I also know you can code lots faster than me. Something that could take me six hours may only take you one. We can maybe make a post about this task tracker to help us better coordinate or ask questions.
 
Ok, I have been thinking this through. Imagine with me if you will, you open up a City Screen and at the top with all the other pertinent information about Prosperity and such you see a Trading Post icon and a number. This number represents the number of trading post connected to this City. With that number we can give the city bonuses, like extra trade points, gold per turn, extra demand, extra research, etc. This can be effected by your type of Civics as well. When you hover the mouse over the icon you get all the important information.

Even the Player's own Trading Posts can add to this, but perhaps Foreign Trading Post give bigger bonuses. So, if you are following me, what would be the best way to code this?
The city screen isn't important regarding performance. You can just copy the code which writes the city names in import/export. It does that by looping all cities on the map and check if their plotgroup is the same as the city in question.

As for doTurn benefits. I'm not really sure, but something tells me that we should exploit the fact that CvPlayer::doTurn() no longer loops cities to call doTurn. Instead it loops plotgroups and each plotgroup loops the cities in that plotgroup. This mean if we read the number uncached, then we only need to read it once for each plotgroup and then add the result as argument when calling each city.

In fact I think the code loops all cities to generate the list of cities in plotgroups. We could extend this to call all cities on the map to assign those to the plotgroup "cache/list" as well. Sure we would need to loop all cities on map, but only once for each player every turn. As looping all cities is actually looping all players and then loop cities owned by that player, then skipping players without the correct diplomatic relationship would greatly reduce the number of cities, which needs looping.

One easy cache to implement here would be in CvPlayer. Store how many tradeposts the player has for each player. If this number is 0, then looping that player's cities can be skipped. In fact I think this cache is the most efficient as we will need little effort (both programming time and CPU time) to keep this cache up to date and it can be used to make the code fairly quick.

Edit: At some point I want the player to have a Per Turn Gold income, with expenses and maintenance cost, you know, like running a real Empire. You would have an Financial Screen you can pull up and see where all you money is going as well as what has brought you the most profits and such. Anyway, this Trading Post deal will help add to that.
Say what you want to add to it and I should be able to make it. The domestic advisor is highly advanced and should be able to gain more pages with little effort.
 
As for doTurn benefits. I'm not really sure, but something tells me that we should exploit the fact that CvPlayer::doTurn()...

Say what you want to add to it and I should be able to make it. The domestic advisor is highly advanced and should be able to gain more pages with little effort.

Thanks for the incite, I forgot all about Players having plot groups like that. I even looked back at my Forts code and its there too, duh. I'll continue the work on this part for the moment. I posted two more "Enhancement" issues that can be worked on on the Git site, I'll post them all eventually. I am going through the additions and working on the ones that look to be the most difficult first. I like getting the hard stuff out of the way early, those two are next in line. Anyway, if you see something you'd like or wouldn't mind working on just let me know.

Like I mentioned, I never coded in Trading Post being removed in times of war, but I found the missionary code to have exactly what I need. It checks for war and if the city can no longer have the player's mission it burnsMission(). I just piggy backed on that code and "burnt" my trading post as well. We can just use that code to remove any variable that should be removed this way.

I'll keep that in mind about the Domestic Advisor, good to know:goodjob:
 
Turns out the doTurn was easier than I thought. I worked up the code in CvCities doTurn below...

Code:
if (!isNative())
	{
		int iLoop;
		for (int iPlayer = 0; iPlayer < MAX_PLAYERS; ++iPlayer)
		{
			CvPlayer& kPlayer = GET_PLAYER((PlayerTypes)iPlayer);
			for (CvCity* pLoopCity = kPlayer.firstCity(&iLoop); pLoopCity != NULL; pLoopCity = kPlayer.nextCity(&iLoop))
			{
				if (pLoopCity->isTradePostBuilt(getTeam()))
				{
					if (isConnectedTo(pLoopCity))
					{
						//Add Bonuses here
					}
				}
			}
		}
	}

I had forgot about the "isConnectedTo" function. That is the main point with plotgroups, to see if one plot is connected to another through routes. This code works great and we can add what ever checks we need and what ever effects.

Edit: I added the isConnectedTo() function to CvCities. You had the functions in the header file already.
 
Turns out the doTurn was easier than I thought. I worked up the code in CvCities doTurn below...
I looked at the code I wrote when implementing plotgroups and I think the best place to write this code is CvPlayer::doCities().

Code:
for (int iPlotGroup = 0; iPlotGroup < getNumPlotgroups(); iPlotGroup++)
{
	/* init var code */

	[COLOR="Red"]// here we place the bonus counting code[/COLOR]

	// do turn and collect info from all cities in plotgroup
	for (int iCity = 0; iCity < getNumCitiesInPlotgroup(iPlotGroup); iCity++)
We add the result of the bonus count as an argument to CvCity::doTurn(). This way we loop once for each plotgroup instead of once for each city. Presumably once the game is big enough for performance to matter, then you will have several cities in each plotgroup.

isConnectedTo() can still be used. We know that all cities in a plotgroup are connected meaning it is good enough to just check if the loop city is connected to the first city in the plotgroup.
Code:
CvCity* pCity = getCity(iPlotGroup, 0);

I think the player should have a counter for how many trading posts he has in each player. This mean we can break the loop for each player once the number has been reached. This in turn allows us to completely skip players without trading posts. I assume that is often the majority. However skipping unneeded loop iterations isn't critical and can be added later. In fact I think it would be good to have in a separate commit as it makes bug hunting easier.
 
// here we place the bonus counting code

Ok, I am attemting to follow you. For the counting code we would do a

Code:
iaTradingpostcount[MAX_PLAYERS]
Loop Players
    loop Player getNumCitiesInPlotgroup(iPlotGroup)
        CvCity* pCity = Player.getCity(iPlotGroup, loopcount)
                if pCity has tradingpost for team
                    iaTradingpostcount[Player]++

Does that look right?
 
Not quite what I meant. We place iaTradingpostcount[MAX_PLAYERS] in CvPlayer and keep it up to date with the number of trading posts.

Code:
int iTradePosts = 0
CvCity* groupCity = getCity(iPlotGroup, 0)
Loop Players (ePlayer)
[COLOR="red"]    if (iaTradingpostcount[ePlayer] > 0)
        int iFound = 0[/COLOR]
        loop ePlayer's cities
            if pCity has tradingpost for team
                if isConnectedTo(groupCity)
                    iTradePosts++
               [COLOR="Red"] iFound++
                if (iFound == iaTradingpostcount[ePlayer])
                    break city loop (no more tradepost with this player[/COLOR]
The red code is to end loops prematurely because the cache detects no more tradeposts. It will work without that code and I think we should add the red code later.

You should be aware that getCity(iPlotGroup, iCity) is likely not doing what you think it is doing.
It will get a pointer to the pointer at index iCity in plotgroup iPlotGroup. However iPlotGroup isn't plotgroupID, but rather a number from 0 to (num plotgroups for player). This mean plotgroup 4 for one player could be plotgroup 7 for another when using this cache.


I started wondering if we could use the cache for other players and I don't think we can. Imagine this scenario:
We have a road crossing several borders. It goes like this (letters are players)
A-B1-C-B2
As you can see B is split into two. This mean if B has open borders with C, it will have one plotgroup. If C is closed, then it will have two plotgroups.
A has open borders with B and tradeposts in all B cities.
If A has open borders with C, then there is one plotgroup covering all of B, but if C is closed, then only B1 can be reached.

if A uses B's cache and only B has open borders with C, then A will incorrectly gain access to B2.

Looks like there is no choice but to check for current player's plotgroups by looping all other cities.
 
You should be aware that getCity(iPlotGroup, iCity) is likely not doing what you think it is doing.

That is what I was thinking, but I misunderstood what you was saying.

I'll work it out one way or another. Thanks for the input. I have been wanting to work with plotgroups and this is good experience for me.
 
I pushed the latest changes to the Civic Screen branch. I know the code could use some refining but it works and you can see what I am wanting to accomplish.

To give you an idea, I added two new variables to cities that keep up with the Connected Yield Bonuses so they can be displayed in help text (Decress = Civics)..
attachment.php


There is at least 5 places where the code needs updated, hopefully that is all.

  1. When a route is added or changed
  2. When a Trading Post is built
  3. When a Mission is built
  4. When a Trading Post or Mission is destroyed (times of War)
  5. And when Civics are changed

Each of those places calls the new resetConnectedYieldBonus() function. I know my coding isn't the most optimal so if you feel the need to modify it then do so.

I finally realized that you can not get a city by just it's ID you need the player also. I coded in the ability of players to store Cities they have a Network with but I figured this uses to much memory so I didn't employ it yet. We could do a vector and an a array to store player and city IDs, but I will let you scrutinize my code before I make any more changes.

At the moment the City bonuses are the only info saved. They should not change unless the 5 events happen and that should not happen inside a saved game:scan:

The new City function cycles all living players that have a Trading Post or Mission, checks their cities, then the City checks if it is connected to one that qualifies. All of this only happens if the player has the appropriate Civic.

I have filled out the Task list on Git a bunch more. I have assigned myself two of the tasks but the rest are open.

PS We should add "Trade Relations" as a prerequisite for these effects as well, or put it as an option in the XML.
 

Attachments

  • ConnectedBonus.jpg
    ConnectedBonus.jpg
    44.3 KB · Views: 210
Two issues...

I found an infinite loop in the below code and fixed it with the latest Civic Effect push. It was funny, while looking over the code I thought, "hmm, shouldn't that be opposite" then forgot about it, then was hit with a hang up, and was like, hmm, I think I know what is causing that :D

I swapped the code in red, like add immigrants should be push.back.

Code:
// add immigrants on the dock
while (m_iNumDocksNextUnits > m_aDocksNextUnits.size())
{
	[COLOR="Red"]m_aDocksNextUnits.pop_back();[/COLOR]
}

// remove immigrants from the dock
while (m_iNumDocksNextUnits < m_aDocksNextUnits.size())
{
	[COLOR="Red"]m_aDocksNextUnits.push_back(pickBestImmigrant());[/COLOR]
}
Ok, I was wanting to add Civic Help Text to the CvGameTextMgr for the getAllowedUnitClassImmigration() effect, but, I have no idea how to do that. I first assumed m_jaAllowedUnitClassImmigration was an array of all UnitClasses but not so, so my below code did nothing. I do not know what to do with this as I do not know how to get the size of the array, other than adding a new function for this in CvInfos.cpp (that may work) so if you can help me here that be great...

Spoiler :
Code:
 for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
    {
		//if (kCivicInfo.getAllowedUnitClassImmigration(iI) > 0)
  //      {
  //          for (int i = 0; i < GC.getNumUnitInfos(); ++i)
  //          {
  //              CvUnitInfo& kUnitInfo = GC.getUnitInfo((UnitTypes) i);
  //              if (kUnitInfo.getUnitClassType() == (UnitClassTypes)iI)
  //              {
  //                  bool bShowUnit = true;
  //                  if (eCivilization != NO_CIVILIZATION)
  //                  {
  //                      UnitTypes eUnit = (UnitTypes) GC.getCivilizationInfo(eCivilization).getCivilizationUnits((UnitClassTypes)iI);
  //                      if (eUnit != (UnitTypes) i)
  //                      {
  //                          bShowUnit = false;
  //                      }
  //                  }
  //                  if (bShowUnit)
  //                  {
  //                      szHelpText.append(NEWLINE);
  //                      szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_PREVENT_UNITCLASS_IMMIGRATION", kUnitInfo.getDescription()));
  //                  }
  //                  //break;
  //              }
  //          }
  //      }

Also, I had to adjust the updateInventionEffectCache() because it was only designed for Techs, not Civics also. Before I figured out what all was going on I moved m_iCityPlotFoodBonus to work just like vanilla code with a changeCityPlotFoodBonus(int iChange), it's the easiest way I know how to do this and it works :)

I was wondering if it wouldn't be more efficent to add an "updateImmigrantsOnDock()" function for just the Immigration effects, so you can just update that when necessary. Also, I moved almost all the changeIdeasResearched() to processCivics so that Civics would be added to ideas researched and turned on and off when necessary.

Could we just add a new boolean to processCivics that checks if the InventionEffectCache needs updated, instead of updating every time a tech or civic is added? Not like this code gets called often though so may not be necessary.
 
Ok, so I made one bug regarding dock size changes :hammer2:

m_ja_bAllowedUnitsImmigration stores allowed UnitTypes, not classes. The same goes for m_ja_bAllowedUnits. This way it caches both units allowed by civics and units allowed by civilization XML in one go, heavily reducing the need for a bunch of runtime checks.

JustInTimeArray.h has a bunch of useful member functions. I believe the one you are looking for is length(). Using this function mean array and loop will never disagree on length.
Why isn't that function const btw :confused:
 
Ok, so I made one bug regarding dock size changes :hammer2:

As many times as you have pointed out my blunders I just had to sit for a while and watch the little hammer pound away on that head, mostly glad it wasn't mine;):lmao:

JustInTimeArray.h has a bunch of useful member functions. I believe the one you are looking for is length(). Using this function mean array and loop will never disagree on length.
Why isn't that function const btw :confused:

Hmm, I seen the length() function before but still, not sure how to use it in my code with
getAllowedUnitClassImmigration(iI). Do I need to like I said, make a new function in CvInfos.cpp just to get the length()?
 
As many times as you have pointed out my blunders I just had to sit for a while and watch the little hammer pound away on that head, mostly glad it wasn't mine;):lmao:
I think you are confusing me with Mary Poppins. I'm not practically perfect in every way. I do make bugs once in a while, specially when I write something and then tell other people to test it. There is a reason why it needs testing ;)

It tells quite a bit about you that you get entertained by a looping gif. If nothing else, then you might like slap-stick comedy :lol:

Hmm, I seen the length() function before but still, not sure how to use it in my code with
getAllowedUnitClassImmigration(iI). Do I need to like I said, make a new function in CvInfos.cpp just to get the length()?
That would be silly. I think I misunderstood you as I was talking of the player allowed cache. Now I took a closer look at what you actually did and it's a civic info code only. I don't actually see the problem. Maybe the problem is that you commented out the code :p

Code:
UnitClassArray<int> m_jaAllowedUnitClassImmigration;
This one works on UnitClassTypes. The last half of JustInTimeArray.h tells which array types are available and length if allocated. In this case
Code:
template<class T>
class UnitClassArray: public JustInTimeArray<T>
{
public:
	UnitClassArray() : JustInTimeArray<T>(JIT_ARRAY_UNIT_CLASS, [B]GC.getNumUnitClassInfos()[/B]){};
	UnitClassArray(T eDefault) : JustInTimeArray<T>(JIT_ARRAY_UNIT_CLASS, [B]GC.getNumUnitClassInfos()[/B], eDefault){};
};
Adding more array types is just a matter of copying this code and edit length and name. I do that from time to time and other people are allowed to do that too. JIT_ARRAY_UNIT_CLASS is just an ID from an enum in the top of the same file. That ID is only used in CvPlayer::updateInventionEffectCacheSingleArray().

I do have a few comments on the code, which is likely just confusing naming. iI and i aren't good variable names. iUnit and iUnitClass would be better. iI is defined elsewhere. It looks like Firaxis preferred to reuse the loop variables in multiple loops. However it helps the compiler if you declare the int each time like for (int iI = 0;. You looks for positive kCivicInfo.getAllowedUnitClassImmigration and then you print TXT_KEY_CIVIC_PREVENT_UNITCLASS_IMMIGRATION. Negative allow prevents and positive enables. All of this are minor and shouldn't prevent the code from working.

Also, I had to adjust the updateInventionEffectCache() because it was only designed for Techs, not Civics also. Before I figured out what all was going on I moved m_iCityPlotFoodBonus to work just like vanilla code with a changeCityPlotFoodBonus(int iChange), it's the easiest way I know how to do this and it works :)
:aargh:
I have local modifications to those lines as well. Now I will get a conflict. Well that happens and I actually planned that change as well.

EDIT: why change m_iCityPlotFoodBonus? It worked just fine as far as I'm aware and there is a reason why I changed it in the first place. By not having the cache in the savegame, we will be free to modify the XML and then load a savegame and it will be updated. By saving the cache, savegames will not update to changed XML settings and we will have a less stable XML testing setup. I had a plan to remove XML settings from savegames as much as possible to make it easier to modify XML.

As for simplicity, what you removed couldn't be simpler. It sets the variable to a default value, then it loops all civics and modifies the variable according to the player owned civics. Think about it.
Code:
m_iCityPlotFoodBonus = 0;
for (int iCivic = 0; iCivic < GC.getNumCivicInfos(); ++iCivic)
{
	CvCivicInfo& kCivicInfo = GC.getCivicInfo((CivicTypes) iCivic);
	if (getIdeasResearched((CivicTypes) iCivic) > 0)
	{
		m_iCityPlotFoodBonus += kCivicInfo.getCenterPlotFoodBonus();
Removing all code not relevant to this feature we end up with this. m_iCityPlotFoodBonus ends up being the combined value of all owned civics' getCenterPlotFoodBonus(). Splitting this into multiple functions and saving the result is actually way more complex.

Also I screwed up merging the conflict and lost my local changes to the file. From now on I merge only after making backups :wallbash:
EDIT2: no loss anyway. I just told VC++ not to reload CvPlayer.cpp and I could copy the modified code. I take that as a warning and a close call for code loss.

Could we just add a new boolean to processCivics that checks if the InventionEffectCache needs updated, instead of updating every time a tech or civic is added? Not like this code gets called often though so may not be necessary.
I have been thinking something like that as the function has grown to do much more than originally intended. I'm not sure what would be best as starting to avoid calls would add the risk of not calling when needed.

Maybe something like adding a CvCivicInfo pointer as argument and if it isn't NULL, then it can optionally skip stuff. For instance if m_jaAllowedUnitClassImmigration contains just 0s, then m_jaAllowedUnitClassImmigration.isAllocated() will be false. This mean we only update the cache if isAllocated() is true. Everything should update if the civic pointer is NULL because that would be on game load.

I think right now we should just focus on getting the civic stuff to work. We can worry about such optimization later.
 
While working on growth unit change, I encountered something I didn't plan for. When gaining a new one, it will call ConvertUnits() where each of the old units will have a 75% chance of converting into the new one.

  1. it isn't in my redesign plan and doesn't fit well
  2. why is 75% hardcoded?
  3. why 75% and now say 100%?
  4. why convert at all?
Right now I'm thinking of ignoring this and as such removing this undocumented feature.

Later we could do something like this:
Generate a list of what units can upgrade to, based on civics. During CvUnit::doTurn(), there is a certain chance that the unit will upgrade, kind of like educating from a school, except timeframe is random. It will be a bit like how Leonardo's workshop in freeciv upgrades one unit each turn instead of all at once like the official civ did at the time I tried freeciv, except my proposed approach will upgrade each unit at a random time and unrelated to the other units. This mean we can end up with settings where statistically 50% of the units will be upgraded within say 20 turns, regardless of you having 2 or 200 of them. It will scale with empire size and it also mean a civic change will not happen overnight.

We can then add "upgrade units" for each civic and use this not only for growth units, but also other units. We can for instance make an upgrade from criminal to serf with a specific civic if we like. Serfs can then also have an upgrade group, meaning the system can set up chains. Each enable can then be an int rather than just ±1 and we can add those to get the upgrade chance.

Alternatively a unit can gain points each turn to increase the upgrade chance like it is done in RaR.
 
  1. it isn't in my redesign plan and doesn't fit well
  2. why is 75% hardcoded?
  3. why 75% and now say 100%?
  4. why convert at all?

All very good questions. I wrote this code all those years ago and I am not sure what I was thinking. I could have been working on a feature as you describe, but never actually finished it. If I "hardcoded" numbers then it was defiantly something I was testing out as I will do that while testing.

Right now I'm thinking of ignoring this and as such removing this undocumented feature.

In this instance that would be the appropriate protocol :D:scan:
 
Back
Top Bottom