AI Flexible difficulty

Joined
Jun 7, 2008
Messages
6,123
Location
Just wonder...
I'm tweaking this option, especially iAIResearchPercent in handicapinfo, which we recently discovered was not working as intended.
Problem now is that when using flexible AI, right from the start some civs have their difficulty increased while other have it decreased, but they mostly keep their handicap level forever. So if Holy Roman is first in score and gets up to Deity level, they start falling behind in score but they always keep Deity. Same for other smaller civs which go down to Settler and keep it almost forever.
In general, it looks like handicap is globally increasing. In my current game, Byzantium was rocketing from Noble to Immortal in first 60-80 turns over 600 (they were leading score table). Now it's turn 275 and they're 16th over 25 civs and still they have Immortal level. I think that's absurd.
IIRC they change level when they are outside 1 standard deviation from the average. Maybe we should change this. Or we should grant some "grace" period at the start of the game; I've seen AI going up from Noble to Deity in ancient era only and not going down from there anymore. I've tried with Blitz gamespeed only but I think slower gamespeeds would make things worse...

Edit: by the way, I think there's something else wrong with Flexible AI. Are we sure about how it works? I mean, if you look at HandicapInfo there's a set of values which are AI specific: iAIGrowthPercent, iAIResearchPercent, iAITrainPercent, etc. Those values mimic their iGrowthPercent, iResearchPercent, iTrainPercent, etc counterparts in other xml files. This is done because if you don't use Flexible AI, AI always play at Noble. Hence when you select harder handicap levels (Prince, Monarch and up), to make things harder for human players some AI values are set to make things easier for them; iAIGrowthPercent, iAIResearchPercent, iAITrainPercent, etc are making things easier for AI if you (human player) are on Monarch. But what happens when you use Flexible AI Difficulty? Does AI always read those values? Because if it does, when AI moves up from Noble to Prince, iAIGrowthPercent, iAIResearchPercent, iAITrainPercent, etc. are making things easier (not harder!) for that given AI. Unless I'm missing something, we have to completely change handicap levels and how AI uses them with or without Flexible AI.
 
This is why I'm not sure about how it works; this part is in cvplayer.cpp, for example

Code:
	if (!isHuman() && !isBarbarian())
	{
		iThreshold *= [COLOR="Red"]GC.getHandicapInfo(GC.getGameINLINE().[/COLOR]getHandicapType()).getAIGrowthPercent();
		iThreshold /= 100;

Does that code get only human handicap and applies that modifier to AI only? If so, there should be no problem. Or does it get every single player's handicap? I think not, but if it does, then we have the problem described above.

Either way, the problem about persistent handicap level remains but we have to look somewhere else for what is causing it.
 
This part:

Code:
if (!isHuman() && !isBarbarian())

Means the code only takes effect for non-barbarian AI's (basically any civilization that you can meet).

This code:
Code:
GC.getGameINLINE().getHandicapType()

Gets the average handicap type of all humans (or if there is only 1 human player, their handicap type).

So putting it all together, it is modifying the threshold for non-barbarian AI's by the value specified as the AIGrowthPercent in the average human difficulty level.
 
This part:

Code:
if (!isHuman() && !isBarbarian())

Means the code only takes effect for non-barbarian AI's (basically any civilization that you can meet).

This code:
Code:
GC.getGameINLINE().getHandicapType()

Gets the average handicap type of all humans (or if there is only 1 human player, their handicap type).

So putting it all together, it is modifying the threshold for non-barbarian AI's by the value specified as the AIGrowthPercent in the average human difficulty level.

So this means that Flexible AI isn't affected at all by these lines. Then what is Flexible AI changing in terms of values? We've seen how it affects research in the other thread. But when AI goes up from Noble to Prince, how does this affect units or buildings production?

Let's have a look at handicapinfo, for Noble:

Code:
		<HandicapInfo>
			<Type>HANDICAP_NOBLE</Type>
			<Description>TXT_KEY_HANDICAP_NOBLE</Description>
			<Help>TXT_KEY_HANDICAP_NOBLE_HELP</Help>
			<iFreeWinsVsBarbs>2</iFreeWinsVsBarbs>
			<iAnimalAttackProb>85</iAnimalAttackProb>
			<iStartingLocPercent>40</iStartingLocPercent>
			<iAdvancedStartPointsMod>100</iAdvancedStartPointsMod>
			<iGold>0</iGold>
			<iFreeUnits>10</iFreeUnits>
			<iUnitCostPercent>50</iUnitCostPercent>
			<iResearchPercent>90</iResearchPercent>
			<iDistanceMaintenancePercent>100</iDistanceMaintenancePercent>
			<iNumCitiesMaintenancePercent>100</iNumCitiesMaintenancePercent>
			<iMaxNumCitiesMaintenance>25</iMaxNumCitiesMaintenance>
			<iColonyMaintenancePercent>100</iColonyMaintenancePercent>
			<iMaxColonyMaintenance>200</iMaxColonyMaintenance>
			<iCorporationMaintenancePercent>100</iCorporationMaintenancePercent>
			<iCivicUpkeepPercent>80</iCivicUpkeepPercent>
			<iInflationPercent>85</iInflationPercent>
			<iHealthBonus>2</iHealthBonus>
			<iHappyBonus>4</iHappyBonus>
			<iRevolutionIndexPercent>100</iRevolutionIndexPercent>
			<iAttitudeChange>-1</iAttitudeChange>
			<iNoTechTradeModifier>70</iNoTechTradeModifier>
			<iTechTradeKnownModifier>0</iTechTradeKnownModifier>
			<iUnownedTilesPerGameAnimal>30</iUnownedTilesPerGameAnimal>
			<iUnownedTilesPerBarbarianUnit>35</iUnownedTilesPerBarbarianUnit> <!-- was 55   -->
			<iUnownedWaterTilesPerBarbarianUnit>275</iUnownedWaterTilesPerBarbarianUnit> <!-- was 275   -->
			<iUnownedTilesPerBarbarianCity>75</iUnownedTilesPerBarbarianCity>  <!-- was 100   -->
			<iBarbarianCreationTurnsElapsed>20</iBarbarianCreationTurnsElapsed>  <!-- was 25   -->
			<iBarbarianCityCreationTurnsElapsed>25</iBarbarianCityCreationTurnsElapsed>  <!-- was 30   -->
			<iBarbarianCityCreationProb>7</iBarbarianCityCreationProb>
			<iAnimalBonus>-40</iAnimalBonus>
			<iBarbarianBonus>-10</iBarbarianBonus>
			<iAIAnimalBonus>-40</iAIAnimalBonus>
			<iAIBarbarianBonus>-25</iAIBarbarianBonus>
			<iStartingDefenseUnits>0</iStartingDefenseUnits>
			<iStartingWorkerUnits>0</iStartingWorkerUnits>
			<iStartingExploreUnits>0</iStartingExploreUnits>
			<iAIStartingUnitMultiplier>0</iAIStartingUnitMultiplier>
			<iAIStartingDefenseUnits>0</iAIStartingDefenseUnits>
			<iAIStartingWorkerUnits>0</iAIStartingWorkerUnits>
			<iAIStartingExploreUnits>0</iAIStartingExploreUnits>
			<iBarbarianDefenders>2</iBarbarianDefenders>
			<iAIDeclareWarProb>100</iAIDeclareWarProb>
			<iAIWorkRateModifier>0</iAIWorkRateModifier>
			<iAIGrowthPercent>45</iAIGrowthPercent>
			<iAIResearchPercent>80</iAIResearchPercent>  <!-- was 80 -->
			<iAITrainPercent>90</iAITrainPercent>
			<iAIWorldTrainPercent>100</iAIWorldTrainPercent>
			<iAIConstructPercent>100</iAIConstructPercent>
			<iAIWorldConstructPercent>100</iAIWorldConstructPercent>
			<iAICreatePercent>100</iAICreatePercent>
			<iAIWorldCreatePercent>100</iAIWorldCreatePercent>
			<iAICivicUpkeepPercent>100</iAICivicUpkeepPercent>
			<iAIUnitCostPercent>100</iAIUnitCostPercent>
			<iAIUnitSupplyPercent>50</iAIUnitSupplyPercent>
			<iAIUnitUpgradePercent>50</iAIUnitUpgradePercent>
			<iAIInflationPercent>47</iAIInflationPercent>
			<iAIWarWearinessPercent>60</iAIWarWearinessPercent>
			<iAIPerEraModifier>0</iAIPerEraModifier>
			<iAIAdvancedStartPercent>100</iAIAdvancedStartPercent>
			<Goodies>
				<GoodyType>GOODY_HIGH_GOLD</GoodyType>
				<GoodyType>GOODY_HIGH_GOLD</GoodyType>
				<GoodyType>GOODY_HIGH_GOLD</GoodyType>
				<GoodyType>GOODY_LOW_GOLD</GoodyType>
				<GoodyType>GOODY_LOW_GOLD</GoodyType>
				<GoodyType>GOODY_LOW_GOLD</GoodyType>
				<GoodyType>GOODY_LOW_GOLD</GoodyType>
				<GoodyType>GOODY_MAP</GoodyType>
				<GoodyType>GOODY_MAP</GoodyType>
				<GoodyType>GOODY_WARRIOR</GoodyType>
				<GoodyType>GOODY_WARRIOR</GoodyType>
				<GoodyType>GOODY_SCOUT</GoodyType>
				<GoodyType>GOODY_EXPERIENCE</GoodyType>
				<GoodyType>GOODY_EXPERIENCE</GoodyType>
				<GoodyType>GOODY_HEALING</GoodyType>
				<GoodyType>GOODY_TECH</GoodyType>
				<GoodyType>GOODY_TECH</GoodyType>
				<GoodyType>GOODY_BARBARIANS_WEAK</GoodyType>
				<GoodyType>GOODY_BARBARIANS_WEAK</GoodyType>
				<GoodyType>GOODY_BARBARIANS_STRONG</GoodyType>
			</Goodies>
			<FreeTechs/>
			<AIFreeTechs/>
		</HandicapInfo>

Looking at these values, production times for units/buildings aren't changed at all when AI handicap level changes. And iAI---values aren't changed either, since they relay on humans average handicap: if you don't use human flexible difficulty, those values remain at their default level (i.e. difficulty you've chosen at the start of the game). So what is Flexible AI really changing? From what I can see, only research.
 
Just a thought, are you applying human levels to the AI preformance, or is it, AI levels are "Harder" at higher ratings, and easier at lower ratings.

i.e. An immortal AI, has research bonuses, production etc.

An AI at noble level has no bonuses

At settler level, they start even further behind, in research levels etc.

So they would scale in reverse, or does flexible AI account for this leveling.
 
I agree. This seems to make AI flexible difficulty fundamentally flawed as it stands now.

One idea would be to make the AI use the inverse difficulty level values when accessing AIXXXPercent values. That means where an AI might be "Prince" level, it is using "Warlord" level AI percent values. Otherwise it uses the normal Prince values. This could be coded in the DLL without requiring a large XML rewrite.
 
I agree. This seems to make AI flexible difficulty fundamentally flawed as it stands now.

One idea would be to make the AI use the inverse difficulty level values when accessing AIXXXPercent values. That means where an AI might be "Prince" level, it is using "Warlord" level AI percent values. Otherwise it uses the normal Prince values. This could be coded in the DLL without requiring a large XML rewrite.
OK, I'll do that
 
Ok, I think I'm mostly done but I have to run some test yet.
To tell the truth, what I've done for most iAIxxxxxx variables is (example on AIWarWearinessPercent)

Code:
	if (!isHuman() && GC.getGame().isModderGameOption(MODDERGAMEOPTION_AI_USE_FLEXIBLE_DIFFICULTY))
	{
		iWarWearinessPercentAnger *= 100;
		iWarWearinessPercentAnger /= GC.getHandicapInfo(getHandicapType()).getAIWarWearinessPercent();
	}

so instead of multiplaying for the "opposite" handicap level factor, I'm dividing for the same handicap level factor. This way if human players are using flexible difficulty too and human and AI both have the same handicap level, there's no penalty and no advantage for either of them. Of course if you're not using Flexible AI, this part is ignored and xml values work as before.
 
Well, I'm still testing but I see a problem with Flexible AI; right now handicap level increases for AI when they're above 1 std deviation from the average and it decreases when they're below 1 std deviation. Problem is that even by heavily tweaking handicapinfo, top civs usually keep their hard level and remain there, while bottom civs usually go down to settler but they're never able to keep the pace of other civs in terms of total score, hence they always keep their settler level. I'm wondering if this is what we want; or if we could maybe prefer that a top civ which reaches Deity should somehow see its score reduced so that it can lower its handicap level again. Right now, it's almost impossible for a civ which reaches Monarch or above to get back to Noble or lower; they should lose most of their score until they are 1 std deviation below average to get back from Monarch to Prince and it's really almost impossible. I've tried by allowing a switch to a lower handicap level when said civ is below 1/2 std deviation and it's a bit better but I'm not sure if it's the right way. What if we make it so that if you're above 1/2 std deviation you play on Prince, 1 std dev Monarch, 3/2 std deviation Emperor and so on? This way if you've been up to Monarch but you get back to an average score, you'll get back to noble instead of keeping Monarch (which is what's happening now). What do you think (Afforess especially)?
 
I think right now Flexible Difficulty for AI is completely broken and probably unworkable and I would just suggest you leave it alone. I have a few thoughts on how I might rewrite it to actually work... but it will take some time.
 
I think right now Flexible Difficulty for AI is completely broken and probably unworkable and I would just suggest you leave it alone. I have a few thoughts on how I might rewrite it to actually work... but it will take some time.
OK, I'll try some small changes that are probably working good enough, they will only affect players using Flexible AI. But we'll try a deeper fixing at another time.
 
I've seen you've updated the flexAI code; I was going down a different route and it was working but now I'm trying your code to see if your changes are better. What I can see straight away, is that research is in general slower when using flexAI. I've noticed this behaviour even with my test code so I've introduced a new globaldefine that has to be used in int CvTeam::getResearchCost only when FlexAI is active:

Code:
	if (GC.getGame().isModderGameOption(MODDERGAMEOPTION_AI_USE_FLEXIBLE_DIFFICULTY))
	{
		iCost *= GC.getDefineINT("FLEX_AI_RATIO", 60);	
		iCost /= 100;
	}

By the way, what is following part of the code doing in your changes?

Code:
HandicapTypes eStandardDifficulty = (HandicapTypes)GC.getDefineINT("STANDARD_HANDICAP");

Edit: probably 60 for FLEX_AI_RATIO is too much for your code, but it was the correct value with my own. I'm still testing the latest revision to check if we might need this tag too.

Edit2: something else I've changed in my test code was to change how difficulty changes in relation to average score; my idea was:
- score above average+1 std dev --> difficulty increases
- score between (average+1 std dev) and (average-1/2 std dev) AND handicap > Noble --> difficulty decreases
- score between (average+1 std dev) and (average-1/2 std dev) AND handicap < Noble --> difficulty increases
- score below average-1/2 std dev --> difficulty decreases

I've chosen 1/2 std dev below average instead of 1 std dev because I've noticed that otherwise game is generally increasing difficulty on average while moving to more recent eras. Also I've changed how difficulty changes because I was seeing Deity civs falling behind a lot and keeping Deity (they won't ever fall behind a 2-3 cities civ, no matter their handicap). How does it sound? When I'm finishing testing your new code, I'll do more test by integrating this part of my code to see how it goes.

Edit3: with my code if a deity civ falls back to average score, instead of staying @deity, it slowly gets back to noble; which is good because if it stays on deity, other civs on lower levels which will become more powerful will always stay ahead even when they reach deity because they will have the same level hence erasing any penalty for being on top of the score.
 
45°38'N-13°47'E;13489448 said:
I've seen you've updated the flexAI code; I was going down a different route and it was working but now I'm trying your code to see if your changes are better. What I can see straight away, is that research is in general slower when using flexAI.

Human or AI? Flexible AI difficulty has no effect on humans.



45°38'N-13°47'E;13489448 said:
I've noticed this behaviour even with my test code so I've introduced a new globaldefine that has to be used in int CvTeam::getResearchCost only when FlexAI is active:

Code:
	if (GC.getGame().isModderGameOption(MODDERGAMEOPTION_AI_USE_FLEXIBLE_DIFFICULTY))
	{
		iCost *= GC.getDefineINT("FLEX_AI_RATIO", 60);	
		iCost /= 100;
	}

That seems like a bad solution.

45°38'N-13°47'E;13489448 said:
By the way, what is following part of the code doing in your changes?

Code:
HandicapTypes eStandardDifficulty = (HandicapTypes)GC.getDefineINT("STANDARD_HANDICAP");

It returns HANDICAP_NOBLE, it's a global define put in by the Firaxis developers. It is the difficulty level the AI start out at. You could have just checked the global defines to find it.

You don't seem to understand my code. I wrote a comment in CvPlayer explaining how it works.

Code:
//Afforess AI Flexible Difficulty Start
		if (GC.getGameINLINE().isModderGameOption(MODDERGAMEOPTION_AI_USE_FLEXIBLE_DIFFICULTY))
		{
			HandicapTypes eStandardDifficulty = (HandicapTypes)GC.getDefineINT("STANDARD_HANDICAP");
			if (isWorldUnitClass(eUnitClass))
			{
				//When the AI handicap is less than standard, AIWorldTrainPercent increases (meant to make human difficulty lower), this reverses that effect
				//Ex: AI is at Chieftian difficulty AIWorldTrainPercent is 130, Noble is 100, so 100 - (130 - 100) = 70, which makes production faster
				iProductionNeeded *= std::max(50, 100 - (GC.getHandicapInfo(getHandicapType()).getAIWorldTrainPercent() - GC.getHandicapInfo(eStandardDifficulty).getAIWorldTrainPercent()));
				iProductionNeeded /= 100;
			}
			else
			{
				iProductionNeeded *= std::max(50, 100 - (GC.getHandicapInfo(getHandicapType()).getAITrainPercent() - GC.getHandicapInfo(eStandardDifficulty).getAITrainPercent()));
				iProductionNeeded /= 100;
			}
			
		}
		//Afforess AI Flexible Difficulty End
 
Human or AI? Flexible AI difficulty has no effect on humans.

AI of course. Try with autoplay and you'll see what I mean.


That seems like a bad solution.

I know, but I haven't come up with a better one.

It returns HANDICAP_NOBLE, it's a global define put in by the Firaxis developers. It is the difficulty level the AI start out at. You could have just checked the global defines to find it.

Very good; sorry, I was just making a quick comparison between your code and mine and I haven't thought about checking global defines. I don't have very much free time these days so I've definetely been to quick to check properly.

You don't seem to understand my code. I wrote a comment in CvPlayer explaining how it works.

Code:
//Afforess AI Flexible Difficulty Start
		if (GC.getGameINLINE().isModderGameOption(MODDERGAMEOPTION_AI_USE_FLEXIBLE_DIFFICULTY))
		{
			HandicapTypes eStandardDifficulty = (HandicapTypes)GC.getDefineINT("STANDARD_HANDICAP");
			if (isWorldUnitClass(eUnitClass))
			{
				//When the AI handicap is less than standard, AIWorldTrainPercent increases (meant to make human difficulty lower), this reverses that effect
				//Ex: AI is at Chieftian difficulty AIWorldTrainPercent is 130, Noble is 100, so 100 - (130 - 100) = 70, which makes production faster
				iProductionNeeded *= std::max(50, 100 - (GC.getHandicapInfo(getHandicapType()).getAIWorldTrainPercent() - GC.getHandicapInfo(eStandardDifficulty).getAIWorldTrainPercent()));
				iProductionNeeded /= 100;
			}
			else
			{
				iProductionNeeded *= std::max(50, 100 - (GC.getHandicapInfo(getHandicapType()).getAITrainPercent() - GC.getHandicapInfo(eStandardDifficulty).getAITrainPercent()));
				iProductionNeeded /= 100;
			}
			
		}
		//Afforess AI Flexible Difficulty End

Same as above, you're right, sorry I didn't check the comment. But I think my points still stand: global difficulty is still increasing and by the time you reach modern era most of the top civs are always the same throughout the game and they're at Deity. Then there are some more civs which are almost at the top of the score which have Warlord but obviously quickly going up to Deity. And there are some civs below average (position around 20/30 on the scoreboard, IIRC in my game) which are still on deity, because very small civs are still lowering the average score and hence those civs on deity are still above (average - 1 std dev) although being below average. And this is why I had to use that trick above to "rescale" research; if civs reaching the top positions in the scoreboard go up to deity and never come down, research is being slowed down a lot, so that you reach industrial era on turn 400/600 which is way too late (Medieval was around 280/600 instead of usual 220-240/600). Do you have any other suggestion to prevent this? I think that my proposed system

- score above average+1 std dev --> difficulty increases
- score between (average+1 std dev) and (average-1/2 std dev) AND handicap > Noble --> difficulty decreases
- score between (average+1 std dev) and (average-1/2 std dev) AND handicap < Noble --> difficulty increases
- score below average-1/2 std dev --> difficulty decreases

is working better and makes the game more balanced. Or is there any other reason why it shouldn't work?
 
45°38'N-13°47'E;13489902 said:
Same as above, you're right, sorry I didn't check the comment. But I think my points still stand: global difficulty is still increasing and by the time you reach modern era most of the top civs are always the same throughout the game and they're at Deity. Then there are some more civs which are almost at the top of the score which have Warlord but obviously quickly going up to Deity. And there are some civs below average (position around 20/30 on the scoreboard, IIRC in my game) which are still on deity, because very small civs are still lowering the average score and hence those civs on deity are still above (average - 1 std dev) although being below average. And this is why I had to use that trick above to "rescale" research; if civs reaching the top positions in the scoreboard go up to deity and never come down, research is being slowed down a lot, so that you reach industrial era on turn 400/600 which is way too late (Medieval was around 280/600 instead of usual 220-240/600). Do you have any other suggestion to prevent this? I think that my proposed system

Well I don't really see any problem. With my changes, higher difficulty levels for the AI does slow down research, construction, unit production, etc. If the AI still maintains a lead despite the higher difficulty, that's fine.
 
Well I don't really see any problem. With my changes, higher difficulty levels for the AI does slow down research, construction, unit production, etc. If the AI still maintains a lead despite the higher difficulty, that's fine.

The reason it still maintains a lead on deity is that since other civs also are on the same level (because they never go down once they reach deity), it's obvious that the handicap difference being 0 it's the same that if every civ will be on noble, except that everything goes on slower; so there's no point in having Flexible AI if handicap will always go up for some civs and always go down for some others. If civ A, B, C are on top and they reach deity they will stay there because every other civ D, E, F, when they reach the top due to an easier level, will finally reach deity and they will never get better than A, B, C. Or if they do, they won't do so much better than civs A, B and C are below average. Hence we'll end up with everyone on deity except some very small civs (probably rebels or minor civs) on settler.
 
Same game, tested with your code and with my code (I can provide savegames)
D-Deity
I-Immortal
E-Emperor
M-Monarch
P-Prince
N-Noble
W-Warlord
C-Chieftain
S-Settler

On the left, distribution of handicap level with your code, on the right with my code:

D | E
D | D (N, S vassal)
D | P
P | N
N* (human player) | D
D | E
D | N (S vassal)
W (§) | M
W (S vassal) | N
S | M
C (S vassal) | N
W | N
D | N
D | N
D | N
N | N
W | N
C | W
W | C
D (°) | S
S | S
W
C
S
C
S

As you can see in your game level is mostly Deity or Settler with a few exceptions being those civs which have stayed settler for so long that now they're raising above average and quickly moving to Warlord and higher again (until they stay 1 std dev above average). Isn't it a bit odd that (°) Deity at the end of the scoreboard? And that (§) Warlord has been a settler most of the time and now it will quickly become a Deity. Right now (modern era) 9 of 28 civs are on deity: isn't it a bit too much?
On the contrary with my proposed changes almost all levels are used. If a civ is able to stay on top on deity that's fine but if it's falling behind because other civs do better, it won't stay on deity until the end of time. Prince on third place is going up, while those Monarch civs where Immortal and going down because they're almost at average score (less than 1 std dev away).
I think your code is fine and it works, but maybe adding that scaling I've proposed

- score above average+1 std dev --> difficulty increases
- score between (average+1 std dev) and (average-1/2 std dev) AND handicap > Noble --> difficulty decreases
- score between (average+1 std dev) and (average-1/2 std dev) AND handicap < Noble --> difficulty increases
- score below average-1/2 std dev --> difficulty decreases

might do some good in terms of balancing.

Edit: 40 turns later, around 2000AD, with your code there are 10 civs on deity (up from 9), even that last one that's now almost at the bottom of the score table.
 
Go ahead and commit your changes, so I can test it myself. I can't really argue with results.
 
Go ahead and commit your changes, so I can test it myself. I can't really argue with results.

Ok, I'll do it tonight when I get back home; I'll only upload my changes on level increase/decrease. There's more I'd like to talk with you on how modifiers are being calculated in your code and in mine but I have no time now, so I won't upload that part; I'll show you what I mean after I've uploaded my changes tonight.
 
Top Bottom