[SDK] Lead from Behind

UncutDragon

Chieftain
Joined
Sep 12, 2009
Messages
50
Location
Alberta, Canada
For BtS v 3.19 - download it here

At the core, this mod is about trying to keep valuable units safe (or at least safer ...). The standard algorithm would pick units to attack or defend based on their relative strengths. This would lead to more valuable units being picked even when it's a 'suicide mission'. It also meant that Great General's got used as healer's since otherwise they could easily be killed when moving around (even if part of a large stack).

This mod tries to make the unit choice a little more intelligent, factoring in the 'value' of the unit. Value in this context is roughly equivalent to 'rare' - units that you wouldn't generally have a lot of, so would really hate to lose.

Changes in this mod:

-Best Defender code is modified to use the actual combat odds to determine the best defender. It also evaluates the value of a unit and uses that to 'adjust' the odds to come up with a defender ranking (making them more likely to defend if they have an excellent chance of winning - less likely otherwise). The amount of the adjustment depends on the value of the unit.

-Likewise, the Best Attacker code uses combat odds and adjusts based on value.

-Some speed improvements to combat in general, and combat odds in particular. Most notably, use of a cache to store partial combat odds to reduce the computations needed. Even with the use of combat odds, stack combat (1 large stack attacking another large stack) now takes roughly half the time.

The criteria for what makes one unit 'more valuable' than another is based on: are they led by a great general? how much experience do they have? are they a unit that's limited in the number that can be produced? do they have the ability to heal? (This last one is a bit different from the others in that you can easily create a lot of healers ... but generally you'd rather leave that to a few units, seeing as only one healer/stack will actually do anything).

Source code is included under CvGameCoreDLL - just search for UncutDragon to find my changes.

You can adjust the behaviour somewhat with the Config settings in the included xml file:
Spoiler :
LFB_ENABLE - Whether to even use the new code (0-false/1-true) ... if set to false, the code will essentially work the same as it would without the mod ... only faster. It turns off all gameplay changes, as well as the combat odds cache. But it leaves in a couple other (pure) speed improvements.

LFB_BASEDONGENERAL - Whether to treat troops led by Great Generals as more valuable.

LFB_BASEDONEXPERIENCE - Whether to treat troops as more valuable based on experience. This one is a little different in that it's not a straight yes/no - rather experience is evaluated in tiers (10/20/40/80/etc).

LFB_BASEDONLIMITED - Whether to treat units that are limited in the number that can be produced (whether on a world, team, or player basis) as more valuable. This will have no real effect on BtS, as the only limited classes are non-combat (Executives and Missionaries), but can be useful when merged with other mods.

LFB_BASEDONHEALER - Whether to treat units that can heal as more valuable.

(NOTE: All the 'BASEDON' settings are actually weights - each is checked seperately, and the applicable weights added up to determine the 'value' of the unit. e.g: If LFB_BASEDONGENERAL=5 and LFB_BASEDONHEALER=2, then a unit led by a great general will be considered more valuable then a unit that can heal - on the other hand a great general than can heal is even more valuable. The LFB_BASEDONEXPERIENCE will be applied for each tier - so a unit with 80 XP is on tier 4, so is given value 4*LFB_BASEDONEXPERIENCE. The total value is used in the odds adjustment - so units get a larger adjustment the more valuable they are)

LFB_USESLIDINGSCALE - Whether to adjust the ranking based on the odds of winning. If true, units with a 99% chance of winning are unaffected - better odds than that, and they're made more likely to defend - worse odds, then less likely - and the further away from 99% you are, the greater the adjustment. If false, ranking is always reduced - the amount of adjustment is not affected by the odds, but will still vary based on the value.

LFB_USECOMBATODDS - Whether to use combat odds in the best defender/attacker calculations. Turning this off will make it use strength (similiar to the old method, but modified a bit) but still including the value adjustment. I originally put this in since using combat odds slowed things down considerably - but with the speed improvements I was able to make, combat is actually faster now than it was before. Regardless, the option is there - turning odds off will basically cut the combat time in half again (making it take approx 1/4 the existing code).

LFB_ADJUSTNUMERATOR/LFB_ADJUSTDENOMINATOR - These settings let you adjust the degree of adjustment. The actual adjustment is (odds-990)*(value*numerator/denominator)^2


Updated to v1.1 - changes:

- Fixed a bug that was causing a python exception in the best attacker code when there was no defender (only appeared if you had python exceptions enabled)

- Changed the experience valuation to use tiers (instead of 25% more than the other unit)

- Changed the odds adjustment to use the value (instead of only adjusting when more valuable) and use difference from 99% (instead of 85%)

Updated to v1.2 - changes:

- Changed value adjustment to (odds-990)*(value*numerator/denominator)^2 - numerator/denominator are config settings with a default of 1/3

- Changed best defender code to ignore value adjustment when attacker has a limit to the damage it can deal (e.g: siege engines)

- Changed best attacker code to factor in chance of withdrawing

(Basically the last two changes are to base the value adjustment on chance of living through the battle instead of chance of winning)
 
Hmm. Interesting. But doesn't this make XP farming easier?

Opinion Revised.
 
Hmm. Interesting. But doesn't this make XP farming easier?
I'm not really familiar with the term, though I can guess what you mean. (FYI I'm an old time Civ fan, new to Civ4)

Since this only applies to defense, and only makes your valuable (more experienced) units defend only if they're much stronger than the attacker, I wouldn't see that being a big concern. It would only help if you're defending against an opponent who has weaker units - and of course once you take some damage, you're likely no longer twice as strong, so wouldn't be picked to defend against the next unit.

It would be most effective vs barbarians - but then there's a limit to the XP you can gain from them anyway. It might actually work against you there, as it would keep picking the more experienced unit to defend ... who can't gain any more XP from them anyway.
 
where do I add this in the code?
Great job by the way.
 
where do I add this in the code?
Great job by the way.
Thanks!

It goes in CvUnit.cpp, method isBetterDefenderThan. I included the line after my changes to help in finding the location (it was more useful than the line before) - so just search for:
if (iOurDefense == iTheirDefense)
and paste my code above that.

I also updated the zip file to include CvUnit.cpp, so you can get the changes that way as well (although I see that put it under moderation again ... so at the moment you actually can't download it at all :( ... but should be up again soon!)
 
When aare you going to be putting it up for download?
 
I'll keep checking to see when it comes up.
 
Mmh, nice idea :goodjob:.
But i'm with Affores, it could maybe be easy exploited.
I tend to see it the other way around ... being able to send a single unit against a stack just to kill the general (or highly promoted unit) is the exploit. (Unless of course you're implementing an 'Assasin' or 'Sniper' or something along that line).

Yes, if you're defending a town against waves of enemies, in time you'll get a few high level units as the low level ones keep getting killed off (and presumably replaced). But to me that's more realistic, and (more importantly) more fun. And the high level units can still be killed with an unlucky battle, or just too many attackers. It just means they can't be 'executed' by a single unit (unless you're REALLY unlucky :eek:).

But to each their own - maybe I'll look at adding some flags so it be configured a bit for individual preferences (it'll be a good thing to learn how to do anyway ;)).
 
I tend to see it the other way around ... being able to send a single unit against a stack just to kill the general (or highly promoted unit) is the exploit.

mmhh...also a good point.

But to each their own - maybe I'll look at adding some flags so it be configured a bit for individual preferences (it'll be a good thing to learn how to do anyway ;)).

Keep on the good work :goodjob:.
 
Very cool component. I will definatly add this to LoR.

UncutDragon you should check out the History of Three Kingdoms mod. They can really use some help from proficient C++ programmers, and they have modified basic Civ4 battle mechanics into a superior Legion System I think you'd enjoy tinkering with.
 
Its up now!!!!!!!!!!! Yay!!
 
My 2 cents...

In martial arts, there is a tendency for teacher or higher level fighter to allow lesser fighter to take blows before going into battle themselves. Helps to exhaust the enemy before experienced fighter goes in and finish things off with a spectacle :lol:.

I like this modcomp, btw. If AI uses this one with high success, this will definitely make for a challenging fight for conquest! :lol:
 
hm... is this strengthening units being led by a Great General or the enemy who is fighting a stack with units being led by a Great General? :confused:
 
Very cool component. I will definatly add this to LoR.

UncutDragon you should check out the History of Three Kingdoms mod. They can really use some help from proficient C++ programmers
Thanks - and I'm planning to give LoR a try, so it'll be nice to have my changes already in there! :D

As for HoTK, for now at least I'd rather stay 'freelance' - I have some things I'm interested in working on (and of course limited time to do it). But maybe sometime down the road.

If AI uses this one with high success, this will definitely make for a challenging fight for conquest! :lol:
Yes, it'll be interesting to see how it affects the AI - it should happen automatically really, so I'd think they'd benefit as well, but time will tell.

hm... is this strengthening units being led by a Great General or the enemy who is fighting a stack with units being led by a Great General? :confused:
Neither - It doesn't really change the strength of anyone. While the code may look like it's adjusting the defenders strength, it's only for the purpose of determining who should defend. The actual battle is handled elsewhere, and my code doesn't touch that.

Unless you're refering to the long term effect of units gaining more experience? In that case, it would be to the benefit of the defender in that particular battle ... in a war it would really depend on circumstances.
 
This is actually quite a cool idea. And it's also not entirely unrealistic or ahistorical, to keep your best units off the frontline and let some cannonfodder units take the brunt of the attack, and then send in the reserve to ward off the attackers.

One important question: If I select a unit to attack a stack, the game will let me know who is going to be the defender in the stack, before I execute the attack. Is this information still shown correctly?
 
One important question: If I select a unit to attack a stack, the game will let me know who is going to be the defender in the stack, before I execute the attack. Is this information still shown correctly?
Yes, it works the same as before.

For the benefit of any who don't know: select a unit and mouse over the defending stack, and it'll show the units in the order (from top to bottom) that they would defend (against that particular unit). Plus the unit shown graphically (on the map) to represent the stack will be the first defender.
 
Updated to v0.2 (which means download is unavailable again ... until it goes through moderation again)

There was a serious bug with selecting non-combat units - combat strength is zero, which caused a divide by zero and CTD. :blush: The new version is save-game compatible though, so if you already started a game, just unzip the new version and you should be fine.

I also added a number of config settings - including LFB_USESLIDINGSCALE. This may be useful for those worried about XP Farming - turning it off will make valuable units always less likely to defend, regardless of how strong (or weak) the attacker is.
 
Top Bottom