Gold from Hammer Overflow

Dresden

Emperor
Joined
Jul 10, 2008
Messages
1,081
I've run some tests on Lexad's request to no longer count production modifers on gold from production overflow. The change itself is the addition of the two green lines below in CvCity::popOrder(). You may note that this is from the part where training units is handled; similar additions would be made for building and project construction within the same function. The logic used is essentially the same as that used in CvCity::changeOverflowProduction() to undo the modifiers on hammer overflow.
Code:
[COLOR="Green"]			iLostProduction *= 100;
			iLostProduction /= std::max(1, getBaseYieldRateModifier(YIELD_PRODUCTION, getProductionModifier(eTrainUnit)));[/COLOR]
			int iProductionGold = ((iLostProduction * GC.getDefineINT("MAXED_UNIT_GOLD_PERCENT")) / 100);


Here is my test situation: A city with base production of 50 hammers, 50 overflow hammers, and various modifers building a 28-hammer unit (Explorer on a Normal speed game).



The change keeps the overflow gold much less than if the city had built wealth which should remove most of the exploitability but you still get something for your lost hammers.

Note that chopping can still gain extra money. In the same scenario with 3 Math-fueled forest chops (90 total hammers) the results are:



This change always results in a 1:1 hammer-to-gold conversion from the chops (all the tests got 90 gold more than the previous scenario) so while you can still get extra money over what wealth would have gotten you, it's not a particularly efficient use of a forest chop and again should limit exploitability.

I'm liking this change. Thoughts?
 
I'm afraid this is too harsh punishment for building cheap stuff in high hammer cities with big modifiers compared to building Wealth directly (what Roland Johansen explained). Why not only remove those extra modifiers which would not apply for building Wealth (resources and traits and wonders for buildings and spaceship parts; Police State, HE, Military Academy, {Drydocks} for {water} units) and keep the generic modifiers in (Forge, Factory, Shale Plant, Bureaucracy, State Property)? I mean wouldn't Factories help me get more money out of my trees?

Not sure about it and haven't tested it, but would this work?:
[pre]iLostProduction *= getBaseYieldRateModifier(YIELD_PRODUCTION, 0);
iLostProduction /= std::max(1, getBaseYieldRateModifier(YIELD_PRODUCTION, getProductionModifier(eTrainUnit)));[/pre]
So when chopping protective walls with stone and a Forge in my Bureau Capital gives me overflow for a iLostProduction of 100 :hammers:, this would be reduced to 100*175/375 = 46 :gold: instead of 26 :gold:.

OT: Why do your Explorers cost only 28:hammers:, aren't they 40:hammers:? Haven't build one in a while...
 
I'm afraid this is too harsh punishment for building cheap stuff in high hammer cities with big modifiers compared to building Wealth directly (what Roland Johansen explained). Why not only remove those extra modifiers which would not apply for building Wealth (resources and traits and wonders for buildings and spaceship parts; Police State, HE, Military Academy, {Drydocks} for {water} units) and keep the generic modifiers in (Forge, Factory, Shale Plant, Bureaucracy, State Property)? I mean wouldn't Factories help me get more money out of my trees?
The factories are multiplying your chops for the actual production and so they are already indirectly increasing the gold because of it. Note on the example that when a factory is part of the equation the overflow gold goes from 22 to 36 or from 36 to 40 in the non-chop case. Since you can't chop directly into wealth, having only a 1:1 hammer:gold ratio on the additional overflow added by the chops doesn't much bother me.

continued... said:
Not sure about it and haven't tested it, but would this work?:

iLostProduction *= getBaseYieldRateModifier(YIELD_PRODUCTION, 0);

iLostProduction /= std::max(1, getBaseYieldRateModifier(YIELD_PRODUCTION, getProductionModifier(eTrainUnit)));
Doesn't seem to make a difference. Using that gives me the same results as using
Code:
iLostProduction *= 100;

continued... said:
So when chopping protective walls with stone and a Forge in my Bureau Capital gives me overflow for a iLostProduction of 100 :hammers:, this would be reduced to 100*175/375 = 46 :gold: instead of 26 :gold:.
I would agree to try it that way if I can find a reasonable way to implement it without hardcoding a bunch of stuff. Unfortunately, there's no version of CvCity::getProductionModifier() which accepts a process type so it might take some work.
EDIT: Wasn't as hard to do as I expected. I'll test it this way. Personally I like the cheapskate idea but as long as it stays under the Wealth amount, the exploitability should be gone and that's my primary concern. Chops are still a small worry though.

continued... said:
OT: Why do your Explorers cost only 28:hammers:, aren't they 40:hammers:? Haven't build one in a while...
My testing has been on a Normal Speed Modern Era start. The Era change seems to cut it by about 1/3.
 
New test results expanding the previous example by adding the situation of undoing only those modifiers that wouldn't apply to wealth. Sorry that it's an image again, but I really need to see it in table format :p

 
Doesn't seem to make a difference. Using that gives me the same results as using
Code:
iLostProduction *= 100;

Just tested it and iLostProduction *= getBaseYieldRateModifier(YIELD_PRODUCTION, 0); worked fine for me :dunno:.
What did you do instead to remove the non-generic modifiers?

I like your tables!
So the chops *do* get multiplied by the generic modifiers now. I really prefer it that way, otherwise there would be a discrepancy between the Overflow2Gold conversion for hammers from chops and hammers from whips (whip hammers are immediately applied to the build item).

A different thing bothered me though:
I was reproducing your scenario with a city building 28:hammers: Explorers with 50 base hammers and 50 overflow hammers.
I was surprised to see the all of the 50 overflow hammers carried over to the next turn after completing an Explorer. I was under the impression that overflow should be capped at the cost of the current build item which would only allow for 28 hammers of overflow and all the rest converted to gold?

the code CvCity:: popOrder:
Code:
[SIZE="3"]// max overflow is the value of the item produced (to eliminate prebuild exploits)
iOverflow = getUnitProduction(eTrainUnit) - iProductionNeeded;
int iMaxOverflow = std::[COLOR="Red"][B]max[/B][/COLOR](iProductionNeeded, getCurrentProductionDifference(false, false));
int iLostProduction = std::max(0, iOverflow - iMaxOverflow);[/SIZE]

Is this another bug? Changing the max to min limits the overflow to 28 hammers! Same for Buildings and Projects...
 
Just tested it and iLostProduction *= getBaseYieldRateModifier(YIELD_PRODUCTION, 0); worked fine for me :dunno:.
What did you do instead to remove the non-generic modifiers?
I use
Code:
iLostProduction *= getBaseYieldRateModifier(YIELD_PRODUCTION);
For whatever reason, having that second argument was causing a return of 100 all the time. The one-argument version seems much more reliable and I copied it from.... somewhere that made sense at the time.

A different thing bothered me though:
I was reproducing your scenario with a city building 28:hammers: Explorers with 50 base hammers and 50 overflow hammers.
I was surprised to see the all of the 50 overflow hammers carried over to the next turn after completing an Explorer. I was under the impression that overflow should be capped at the cost of the current build item which would only allow for 28 hammers of overflow and all the rest converted to gold?

the code CvCity:: popOrder:
Code:
[SIZE="3"]// max overflow is the value of the item produced (to eliminate prebuild exploits)
iOverflow = getUnitProduction(eTrainUnit) - iProductionNeeded;
int iMaxOverflow = std::[COLOR="Red"][B]max[/B][/COLOR](iProductionNeeded, getCurrentProductionDifference(false, false));
int iLostProduction = std::max(0, iOverflow - iMaxOverflow);[/SIZE]

Is this another bug? Changing the max to min limits the overflow to 28 hammers! Same for Buildings and Projects...
Don't be confused by the misleading comment. It has used max() since at least vanilla 1.61 and the actual behavior is capping at the larger of (a) cost of the item or (b) how many (base) hammers the city produces. I think that's a perfectly reasonable cap and see no reason to mess with it.

Vanilla 1.61 CvCity:: popOrder():
Code:
			// max overflow is the value of the item produced (to eliminate prebuild exploits)
			iOverflow = min(getUnitProduction(eTrainUnit) - iProductionNeeded, [COLOR="Green"][B]max[/B](iProductionNeeded, getCurrentProductionDifference(false, false))[/COLOR]);
 
After giving it some thoughts, I agree that max() makes sense here. Changing it to min() would seriously spoil production via whip overflow in high food, low base hammers cities. So yes, don't mess with it :goodjob:.

I now see how the comment makes sense too -- it's for the early game when base hammers per turn < item cost. Say your city has 14 base :hammers: and you are researching Aesthetics. You build a Chariot, an Archer, a Warrior and a Scout until 1 turn to completion each, timing it so that no hammers are lost due to decay and that you can begin completing the builds 4 turns before finishing Aesthetics. This would give you a 4 turn head start on the Parthenon via accumulating the unlimited increasing overflow for the 4 units (even more if you decide to whip some of them) ...
 
Great! Thanx, guys, I hope this goes into official release along with your other fixes/
 
Top Bottom