AND2 and SVN Bug Reports - A New Dawn 2 ONLY

I agree it is working (as in, I see it modifies my science output in games) but I agree with others that have had some strange experiences. Possibly you are right in that this is as designed. However I would like to take a look at the source code to verify this for myself... Where in the source exactly is tech diffusion?


Here's the code, in red the part I've modified, although it's still experimental

Spoiler :
Code:
int CvPlayer::calculateResearchModifier(TechTypes eTech) const
{
	int iModifier = 100;

	if (NO_TECH == eTech)
	{
		return iModifier;
	}

	int iKnownCount = 0;
	int iPossibleKnownCount = 0;

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      07/27/09                                jdog5000      */
/*                                                                                              */
/* Tech Diffusion                                                                               */
/************************************************************************************************/
	if( !GC.getGameINLINE().isOption(GAMEOPTION_NO_TECH_DIFFUSION) )
	{
		double knownExp = 0.0;
		// Tech flows better through open borders
		for (int iI = 0; iI < MAX_CIV_TEAMS; iI++)
		{
			if (GET_TEAM((TeamTypes)iI).isAlive())
			{
				if (GET_TEAM((TeamTypes)iI).isHasTech(eTech))
				{
					if (GET_TEAM(getTeam()).isHasMet((TeamTypes)iI))
					{
						knownExp += 0.5;

						if( GET_TEAM(getTeam()).isOpenBorders((TeamTypes)iI) || GET_TEAM((TeamTypes)iI).isVassal(getTeam()) )
						{
							knownExp += 1.5;
						}
						else if( GET_TEAM(getTeam()).isAtWar((TeamTypes)iI) || GET_TEAM(getTeam()).isVassal((TeamTypes)iI) )
						{
							knownExp += 0.5;
						}
					}
				}
			}
		}

		int techDiffMod = GC.getTECH_DIFFUSION_KNOWN_TEAM_MODIFIER();
		if (knownExp > 0.0)
		{
			iModifier += techDiffMod - (int)(techDiffMod * pow(0.85, knownExp) + 0.5);
		}

		// Tech flows downhill to those who are far behind
		int iTechScorePercent = GET_TEAM(getTeam()).getBestKnownTechScorePercent();
		int iWelfareThreshold = GC.getTECH_DIFFUSION_WELFARE_THRESHOLD();
		if( iTechScorePercent < iWelfareThreshold )
		{
			if( knownExp > 0.0 )
			{
				iModifier += (GC.getTECH_DIFFUSION_WELFARE_MODIFIER() * (iWelfareThreshold - iTechScorePercent));	

[COLOR="Red"]				if (iTechScorePercent < (iWelfareThreshold/8))		//45° attempt at making a better tech diffusion code; still to be modified probably from here
					{
					iModifier += (GC.getTECH_DIFFUSION_WELFARE_MODIFIER() * (iWelfareThreshold - iTechScorePercent))*10;		
					}
				else if ((iTechScorePercent < (iWelfareThreshold/5))	&& (iTechScorePercent >= (iWelfareThreshold/8)))		
					{
					iModifier += (GC.getTECH_DIFFUSION_WELFARE_MODIFIER() * (iWelfareThreshold - iTechScorePercent))*6;
					}
				else if ((iTechScorePercent < (iWelfareThreshold/4))	&& (iTechScorePercent >= (iWelfareThreshold/5)))			
					{
					iModifier += (GC.getTECH_DIFFUSION_WELFARE_MODIFIER() * (iWelfareThreshold - iTechScorePercent))*4;	
					}
				else if ((iTechScorePercent < (iWelfareThreshold/2))	&& (iTechScorePercent >= (iWelfareThreshold/4)))				
					{
					iModifier += (GC.getTECH_DIFFUSION_WELFARE_MODIFIER() * (iWelfareThreshold - iTechScorePercent))*2;					
					}
				else if ((iTechScorePercent >= (iWelfareThreshold/4)) && (iTechScorePercent < iWelfareThreshold ))						 //to here
					{
					iModifier += (GC.getTECH_DIFFUSION_WELFARE_MODIFIER() * (iWelfareThreshold - iTechScorePercent));					
					}   
			}
// 45° attempt to make tech diffusion scalable with difficulty level for human players (empyrical attempt) from here			
			for (int iI = 0; iI < MAX_CIV_TEAMS; iI++)
			{
				if (GET_TEAM((TeamTypes)iI).isHuman())
				{
					iModifier *= 2;
					iModifier /= (3+ getHandicapType());
				}	
			}
//to here	[/COLOR]		
		}
	}
	else
	{
		// Default BTS code
		for (int iI = 0; iI < MAX_CIV_TEAMS; iI++)
		{
			if (GET_TEAM((TeamTypes)iI).isAlive())
			{
				if (GET_TEAM(getTeam()).isHasMet((TeamTypes)iI))
				{
					if (GET_TEAM((TeamTypes)iI).isHasTech(eTech))
					{
						iKnownCount++;
					}
				}

				iPossibleKnownCount++;
			}
		}

		if (iPossibleKnownCount > 0)
		{
			iModifier += (GC.getDefineINT("TECH_COST_TOTAL_KNOWN_TEAM_MODIFIER") * iKnownCount) / iPossibleKnownCount;
		}
	}

	int iPossiblePaths = 0;
	int iUnknownPaths = 0;

	for (int iI = 0; iI < GC.getNUM_OR_TECH_PREREQS(); iI++)
	{
		if (GC.getTechInfo(eTech).getPrereqOrTechs(iI) != NO_TECH)
		{
			if (!(GET_TEAM(getTeam()).isHasTech((TechTypes)(GC.getTechInfo(eTech).getPrereqOrTechs(iI)))))
			{
				iUnknownPaths++;
			}

			iPossiblePaths++;
		}
	}

	FAssertMsg(iPossiblePaths >= iUnknownPaths, "The number of possible paths is expected to match or exceed the number of unknown ones");

	if( iPossiblePaths > iUnknownPaths )
	{
		iModifier += GC.getTECH_COST_FIRST_KNOWN_PREREQ_MODIFIER();
		iPossiblePaths--;
		iModifier += (iPossiblePaths - iUnknownPaths) * GC.getTECH_COST_KNOWN_PREREQ_MODIFIER();
	}

	// AIAndy: It causes a tech cost increase instead now
	//iModifier -= GC.getEraInfo((EraTypes)GC.getTechInfo(eTech).getEra()).getTechCostModifier();
	
	// AIAndy: Such hard coded changes should not be in the DLL like that. If such an adaption of tech rate to game option is desired, it should be in a global def at least.
	/*if( GC.getGameINLINE().isOption(GAMEOPTION_START_AS_MINORS)
	&& (GC.getGameINLINE().getStartEra() == 0) )
	{
		switch(GC.getTechInfo(eTech).getEra())
		{
			case 0:
			iModifier += 5;
			break;

			case 1:
			iModifier += 20;
			break;

			case 2:
			iModifier += 10;
			break;
		}
		if(GC.getGameINLINE().isOption(GAMEOPTION_NO_TECH_TRADING))
		{
			iModifier += 10;
		} else if(GC.getGameINLINE().isOption(GAMEOPTION_NO_TECH_BROKERING))
		{
			iModifier += 5;
		}
		
	}*/

	// AIAndy: It causes a tech cost increase instead now
	//iModifier -= GC.getTECH_COST_MODIFIER();

	return std::max(1,iModifier);
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
}

Edit:

Possibly a way to reduce confusion would be to split up the beakers shown on the top left of the HUD. Maybe show the base science beakers + tech diffusion beakers? Having the base beakers include tech diffusion makes it hard to tell if my science output is good or not, as I can't tell what my base numbers are. To be clear, this is just a visual change, not a mechanic change.

You're right, that could be a good idea, I'm working on it.
 
Possibly a way to reduce confusion would be to split up the beakers shown on the top left of the HUD. Maybe show the base science beakers + tech diffusion beakers? Having the base beakers include tech diffusion makes it hard to tell if my science output is good or not, as I can't tell what my base numbers are. To be clear, this is just a visual change, not a mechanic change.

I've made a quick change. Would something like this be ok?
Financial Advisor always shows total research. :)
If someone has other suggestion on the new text, I can change it. For example I'm thinking of removing that "and" or changing the text to "from Tech Diffusion".

Edit: now I need to understand why I get tech diffusion help even when I'm researching a new tech that nobody else has discovered.
Edit 2: to anyone experiencing a tech cost INCREASE, please upload a save so that I can check. Are you 100% sure it doesn't depend on changing era (becasue that's WAD)?
 

Attachments

  • techdiff.jpg
    techdiff.jpg
    289.4 KB · Views: 58
I can upload a save later tonight when I'm at my computer if I can figure out how, but I'm positive it's not due to era changes, my last 2 games I noticed it on Masonry and on Bronze Working, before the era changes. And in my case it's a decrease in research I'm producing per turn, not an increase in cost of the techs.

I think the changed display method for diffusion is great.
 
. And in my case it's a decrease in research I'm producing per turn, not an increase in cost of the techs.

I'm looking at the code, you might be right. Strange that wasn't noticed before, I'm looking into it.
 
Mmmmmmm, I guess I've found the problem with tech diffusion.
There's a part of the code, which works when Tech Diffusion is on, which gives as output an iModifier value which is multiplicative, i.e. it helps you produce more science from x to (for example) 110% of x. That part should always be >100% because there's no point in making tech diffusion giving you 90% of your current science output. But there's another part of the modifier which looks like it was made for being additive, meaning that you get your current x research + a certain y amount.

Code:
	int iPossiblePaths = 0;
	int iUnknownPaths = 0;

	for (int iI = 0; iI < GC.getNUM_OR_TECH_PREREQS(); iI++)
	{
		if (GC.getTechInfo(eTech).getPrereqOrTechs(iI) != NO_TECH)
		{
			if (!(GET_TEAM(getTeam()).isHasTech((TechTypes)(GC.getTechInfo(eTech).getPrereqOrTechs(iI)))))
			{
				iUnknownPaths++;
			}

			iPossiblePaths++;
		}
	}

	FAssertMsg(iPossiblePaths >= iUnknownPaths, "The number of possible paths is expected to match or exceed the number of unknown ones");

	if( iPossiblePaths > iUnknownPaths )
	{
		iModifier += GC.getTECH_COST_FIRST_KNOWN_PREREQ_MODIFIER();
		iPossiblePaths--;
		iModifier += (iPossiblePaths - iUnknownPaths) * GC.getTECH_COST_KNOWN_PREREQ_MODIFIER();
	}

From a quick look I guess this part is the one responsible for speeding up your research when you are the first to get a tech. Problem is that these two parts are combined in the same iModifier, which is the one displayed in the main interface. Hence that "tech diffusion" score displayed in my previous screenshot isn't actually only tech diffusion. Rather, it is tech diffusion + that additional help.
This means that either I remove that part of the code (using tech diffusion, it's not necessary IMO) or I leave it there but we need to change the text "Tech Diffusion" that I've introduced in my previous screenshot in the upper left corner of the screen. This is because if you're researching a tech that no one else already has, that last part of the code gives you some help anyway and hence that "tech diffusion score" is different from 0, which is strange because you shouldn't get help if no one else has that tech.
Looks odd to me that you get help for being the first to discover a tech; that helps leading civs and not civs falling back in techs as Tech Diffusion is supposed to do.
I don't get why that TECH_COST_FIRST_KNOWN_PREREQ_MODIFIER works even when Tech Diffusion is off, although it's a part of Tech Diffusion code (at least it looks so, looking at CvGlobals.cpp, where it's listed under Tech Diffusion code).

Edit: I think I'll go with the first choice of removing the above code. I think it's a leftover from some older version. I guess AIAndy removed part of the code when TechDiffusion was reworked a long time ago, but forgot to remove that part.
 
The possible paths is vanilla BTS code. Even the vanilla game tries to help out a tiny bit. It's really barely noticeable though, and I will not cry if you remove it.

I am reviewing the tech diffusion code from BBAI and I feel it has some flaws. I will post a copy of the function with an explanation of improvements.
 
The possible paths is vanilla BTS code. Even the vanilla game tries to help out a tiny bit. It's really barely noticeable though, and I will not cry if you remove it.

I am reviewing the tech diffusion code from BBAI and I feel it has some flaws. I will post a copy of the function with an explanation of improvements.

You're right, but that code was modified anyway from vanilla BTS; I've checked the original dll and it's slightly different. From that point in the post above until the end of the function, iModifier was being scaled up to 100 in the past and I think that was because it was supposed to reduce tech costs, while in fact the new code is meant to increase science output.
If you can get your hand at the code, you're more than welcome! :)
 
Ok here is my proposed code for the function, it's a fairly big rewrite:

http://pastie.org/pastes/9098627/text?key=imxprrp5w4gsdgp5ysnbrw

Basically the old code had 2 big problems. The tech diffusion from known teams with the tech did not scale for map size. Imagine that I know 5 players with a tech, and have open borders with all. knownExp would be 10 after checking all the teams. Since TECH_DIFFUSION_KNOWN_TEAM_MODIFIER is 70 in the XML, I would receive a free 56% modifier for research for knowing those 5 players. Now assume every single of those 5 players has a rebellion and a splinter civilization forms. I only meet 2 of the 5 new civs. There are now 10 total civs, occupying the same exact space as the 5 previous. Under the old BBAI code, my modifier is now 63%. I have not expanded the area I have explored. The world population is the same. There are not any more cities. In fact, I know LESS about the world than before, as 30% of the area that I had explored is under the control of unmet nations. But my modifier rose. That is flawed logic.

I changed the code to take into account the total teams in the game and balance for this. This was my first change.

My 2nd change was to rewrite the code for the tech welfare (for far behind civs). I noticed 45* tried to increase the welfare to help far behind civs, but it was rather convoluted and long. I rewrote this to be more similar to the tech diffusion modifier. To understand how my change works, take this scenario:

I am researching a tech, and my best tech score percent is 70 (I am 30% behind the world leaders). The TECH_DIFFUSION_WELFARE_THRESHOLD in the XML is 90. So 70 < 90, and I get free tech welfare. The amount is controlled by how far behind I am. The power function is an exponential, so that means the farther behind, the more free beakers I get. If we change the TECH_DIFFUSION_WELFARE_MODIFIER from 70 to 500 (please do this if you use my code 45*) then the amount of welfare I receive is:

500 - (500 * (0.98 ^ (90 - 70))) OR 177%.

If I was 50% behind I would have a modifier of 277%. If I was 11% behind (minimum to receive tech welfare) I would only get an additional modifier of 10%. This is a much cleaner, fluid result than previously. Before, 45* if/else statements resulted in a linear step function, rather than a curved exponential.

Reminder: If you use my code out of the box change TECH_DIFFUSION_WELFARE_MODIFIER in TechDiffusion_GlobalDefines.xml to 500!!!
 
Ok here is my proposed code for the function, it's a fairly big rewrite:

http://pastie.org/pastes/9098627/text?key=imxprrp5w4gsdgp5ysnbrw

Basically the old code had 2 big problems. The tech diffusion from known teams with the tech did not scale for map size. Imagine that I know 5 players with a tech, and have open borders with all. knownExp would be 10 after checking all the teams. Since TECH_DIFFUSION_KNOWN_TEAM_MODIFIER is 70 in the XML, I would receive a free 56% modifier for research for knowing those 5 players. Now assume every single of those 5 players has a rebellion and a splinter civilization forms. I only meet 2 of the 5 new civs. There are now 10 total civs, occupying the same exact space as the 5 previous. Under the old BBAI code, my modifier is now 63%. I have not expanded the area I have explored. The world population is the same. There are not any more cities. In fact, I know LESS about the world than before, as 30% of the area that I had explored is under the control of unmet nations. But my modifier rose. That is flawed logic.

I changed the code to take into account the total teams in the game and balance for this. This was my first change.

My 2nd change was to rewrite the code for the tech welfare (for far behind civs). I noticed 45* tried to increase the welfare to help far behind civs, but it was rather convoluted and long. I rewrote this to be more similar to the tech diffusion modifier. To understand how my change works, take this scenario:

I am researching a tech, and my best tech score percent is 70 (I am 30% behind the world leaders). The TECH_DIFFUSION_WELFARE_THRESHOLD in the XML is 90. So 70 < 90, and I get free tech welfare. The amount is controlled by how far behind I am. The power function is an exponential, so that means the farther behind, the more free beakers I get. If we change the TECH_DIFFUSION_WELFARE_MODIFIER from 70 to 500 (please do this if you use my code 45*) then the amount of welfare I receive is:

500 - (500 * (0.98 ^ (90 - 70))) OR 177%.

If I was 50% behind I would have a modifier of 277%. If I was 11% behind (minimum to receive tech welfare) I would only get an additional modifier of 10%. This is a much cleaner, fluid result than previously. Before, 45* if/else statements resulted in a linear step function, rather than a curved exponential.

Reminder: If you use my code out of the box change TECH_DIFFUSION_WELFARE_MODIFIER in TechDiffusion_GlobalDefines.xml to 500!!!

I'll quickly try your code now before going to sleep, and I'll try it better tomorrow. I'm sure it's definetely better than mine. I know my code was really clunky, it was meant as a temporary solution to civs falling behind more than 2 eras.
The only problem I see with your function is that it's not scaled by handicap. That way AI always get the same help for whatever difficulty level (as human players do). Shouldn't we scale it by handicap level? I've made such an attempt in my old code because people were complaining about that. I haven't tried your new code yet, so I can't say if there will be the same problem.
 
45°38'N-13°47'E;13185070 said:
I'll quickly try your code now before going to sleep, and I'll try it better tomorrow. I'm sure it's definetely better than mine. I know my code was really clunky, it was meant as a temporary solution to civs falling behind more than 2 eras.
The only problem I see with your function is that it's not scaled by handicap. That way AI always get the same help for whatever difficulty level (as human players do). Shouldn't we scale it by handicap level? I've made such an attempt in my old code because people were complaining about that. I haven't tried your new code yet, so I can't say if there will be the same problem.

Oh yes I saw that. Unless playtesting reveals it is necessary, I think handicap scaling is redundant. Tech costs are already part of the handicap XMLs. So then, Tech modifiers don't need to be.
 
Well, from a quick try it looks like your code is awesome. :worship:
Tomorrow I'll run some deeper test but I have no doubts it will work like a charm; I know you're light-years ahead of what I can do. :hatsoff:
 
45°38'N-13°47'E;13185084 said:
Well, from a quick try it looks like your code is awesome. :worship:
Tomorrow I'll run some deeper test but I have no doubts it will work like a charm; I know you're light-years ahead of what I can do. :hatsoff:

Goody. I was coding blind so I had to check all my math out by hand. The HUD change is pretty close to what I wanted. It looks like you have two spaces between "and " and the # of beakers. Also I would just abbreviate Tech Diffusion as "TD".

Also, when TD is 0, the text should not show at all. I haven't seen your code, but I just wanted to make sure you weren't wasting screen space with a "+0" ;)
 
So it's working as designed that my tech income randomly shoots up during the early middle ages(from, say, 90~ to 700) for certain techs?
It's just weird that I'd be able to research smithing in 4 turns but feudalism takes 111. Seems like getting ahead in tech with diffusion on would be very difficult because even if you struggle hard to get ahead, it makes it really easy for anyone else to catch up(and also IMO the medieval techs are a bit off on the scale, overpriced compared to the techs immediate prior).

Just my two cents.
 
Since we're on Tech' Diffusion... does the crazy scaling mechanism not bother anyone else?
I think I'd prefer that tech' diffusion were implemented similarly to the tech' learning from captured cities: that is, if you're a long way behind, you get some free beakers added each turn to tech's which are known by other civ's with whom you have contact. In this way you'd be able to judge the trades accurately, and you wouldn't have to open the science advisor to see how long a tech' will take to research. This also seems more intuitive to me: my civ' would start learning about the technology through contact with other civ's even if I didn't apply my own scientists to study it.
Additionally, one would no longer have to click around in the tech' tree to see which tech' is the most efficient to research (because at present, the beakers produced jumps around so wildly when selecting different tech's), and the graph of GDP wouldn't have crazy spikes corresponding to times of inflated beaker production. Finally, the time (number of turns) taken to research things wouldn't appear to vary as wildly as ciadude2 noted above, because you'd see that you had already partly-researched earlier tech's which other Civ's have known for a while, even before you dedicate your own scientists to the cause, so it'd be immediately clear why you'll get smithing in just four (more) turns (because you already know a lot about it), while Feudalism is totally unknown if no-one you've spoken to knows about it either.

Is this possible to implement? Intuitively, without studying the code, I would guess that it would be simpler than the scaling mechanism currently used, but of course I may well be off-base there.

(Thanks for all the development time you put in, by the way, developers).

Cheers. A.
 
Tech diffusion is being reworked, I'm testing Afforess new code and I think it's working. I'll release it after some test. Also tech costs are being reworked a bit, especially middle age I think.
 
Goody. I was coding blind so I had to check all my math out by hand. The HUD change is pretty close to what I wanted. It looks like you have two spaces between "and " and the # of beakers. Also I would just abbreviate Tech Diffusion as "TD".

Also, when TD is 0, the text should not show at all. I haven't seen your code, but I just wanted to make sure you weren't wasting screen space with a "+0" ;)

I've not written the python code yet, but that's how it's supposed to work. :)
 
Since we're on Tech' Diffusion... does the crazy scaling mechanism not bother anyone else?

Crazy scaling? Tech Diffusion is supposed to make tech research faster for techs that other civs already have. That requires tech research to scale. I mean, if you don't like the concept...you can disable it in the game options.

Additionally, one would no longer have to click around in the tech' tree to see which tech' is the most efficient to research (because at present, the beakers produced jumps around so wildly when selecting different tech's), and the graph of GDP wouldn't have crazy spikes corresponding to times of inflated beaker production. Finally, the time (number of turns) taken to research things wouldn't appear to vary as wildly as ciadude2 noted above, because you'd see that you had already partly-researched earlier tech's which other Civ's have known for a while, even before you dedicate your own scientists to the cause, so it'd be immediately clear why you'll get smithing in just four (more) turns (because you already know a lot about it), while Feudalism is totally unknown if no-one you've spoken to knows about it either.

I think you're basically asking for tech diffusion to influence the tech research cost rather than the tech research output. That makes sense to me, and I do kinda agree with it. I think you can argue both ways are valid, BUT influencing the cost rather than the research output has the advantage of not inflating the output of your GDP, beakers, etc.

It might be better to move the code into the cost part of the calculations and show how much cheaper the tech is due to diffusion on the hud instead.

This would probably mean moving the tech diffusion code to "int CvTeam::getResearchCost(TechTypes eTech) const". Possibly add a separate CvTeam function to calculate the TechDiffusion modifier, use that in getResearchCost and expose it to python too, so you can use it on the hud...

Thoughts 45*?

45°38'N-13°47'E;13185684 said:
I've not written the python code yet, but that's how it's supposed to work. :)

Sounds good.
 
I think you're basically asking for tech diffusion to influence the tech research cost rather than the tech research output. That makes sense to me, and I do kinda agree with it. I think you can argue both ways are valid, BUT influencing the cost rather than the research output has the advantage of not inflating the output of your GDP, beakers, etc.

It might be better to move the code into the cost part of the calculations and show how much cheaper the tech is due to diffusion on the hud instead.

Thoughts 45*?

I kind of agree, I mean, I also think it's better to reduce tech costs instead of inflating research output, but I think the current method is working good for the moment. Also, I think I remember that it worked that way (reducing tech costs), but for some reason it was changed from a certain point. I wonder if the previous method was causing some troubles and that's why it was changed to increase science output.
 
Ok, TD is being displayed correctly now. I've done some test this morning and it works good enough, but I have to balance differently tech costs in different eras. I'll tune down a bit costs in classical era and cut it down substantially in Medieval Era and maybe Renaissance. One thing I've noticed is that civs that are falling back a lot (usually small civs), still lag behind of more than 1 era. I'd like to avoid that if possible: in my test there was a 4 city civ (against 10-15 cities civs) that was entering Medieval Era while I was halfway through Renaissance. But it could depend on tech cost, I'll let you know how it works when I change techs costs per era.
 
Thanks, I didn't mean to sound quite so harsh in my comment.
RoMAND is the only mod I play for Civ IV and you're doing a fantastic job. I was just confused by the problem with the tech when I updated lol.
 
Back
Top Bottom