testing SDI

vicawoo

Chieftain
Joined
Feb 12, 2007
Messages
3,226
People have asserted SDI, at least the AI's SDI, (75% chance to intercept nukes) is over-effective vs tactical nukes (50% evasion from SDI).

I tried to test this in my spare time last night by creating a world builder map and giving the AI SDI, turning off locking random seeds, and giving yourself a huge number of tactical nukes. I prefer to do this than loading some existing game because it's cleaner experimentally.
However, I don't know much about using the worldbuilder and couldn't find a way to directly give the AI projects.

So does anyone know how to either
a) give an AI SDI in worldbuilder
b) in which file is the python code for SDI/nukes.

as for b), I believe I have checked the python files inside civilization iv/assets/python,
warlords/assets/python, and beyond the sword/assets/python, and I've still yet to discover most of the important "mechanics" code.
 
Your assertion about tactics having 50% evasion is incorrect. The way the code is implemented, they have a little more higher than this, I think it was 62% or around there.
 
If there's no SDI, your tactical nuke doesn't have a 50% chance of hitting. It's clear that evasion is dependent upon the SDI probability, not a means of over-writing it.
 
That 62 can be about right, yet to say that they have a 62% evasion would be not pure at all.

In fact the SDI intercepts 75% of the missiles. For ICBMs this means that 1 in 4 hits. For TacNukes this means that 1 out of 4 connects as well, despite there being an SDI. The SDI simply does nothing to prevent this. For the TacNukes that the SDI would intercept there is this exception that TacNukes can evade interception.

What does this mean for the TacNukes? 25 out of a hundred would connect because the SDI only intercepts 3 out of 4 missiles. For the other 75 out of a 100, the missiles evade the interception half of the time. This means that out of those 75 missiles that may get intercepted, 75/2 = 37.5 get through.

So how many nukes are not intercepted by the SDI? Out of the ICBMs, 1 in 4 gets through. Out of the TacNukes, 25 out of a 100 get through regardless, 37.5 out of a 100 get through regardless of the SDI trying to intercept them, and 37.5 get intercepted. This means that for TacNukes 62.5 missiles get through out of a 100. Only some of those missiles need to evade interception though because the SDI does not try shoot down every nuke.

All in all, the assertion that TacNukes have 50% evasion is correct, even though more than 50% of the TacNukes get through. This is because the SDI lets 1 out of 4 nukes through regardless.
 
If there's no SDI, your tactical nuke doesn't have a 50% chance of hitting. It's clear that evasion is dependent upon the SDI probability, not a means of over-writing it.
Evasion is independent from the SDI probability of intercepting. We must make sure we make a distinction between missiles getting through because the SDI lets 1 out of 4 through and missiles evading interception.

3 ouf of 4 tactical nukes will be shot down by the SDI. The tactical nuke has an extra trick up it's sleeve in the form of an evasion of interception. Half of those nukes that would be intercepted evade interception. The other half of the 3 out of 4 that do get intercepted will not connect.

1 out of 4 do connect regardless of there ever being an SDI, which is true for both ICBMs and for tactical nukes. These nukes do not evade interception, they were simply not shot down. The only nukes that evade interception are the 37.5% of the tactical nukes that would be shot down but connect regardless because of the 50% evasion chance.

Please note the difference between the two. Some nukes will never be shot down. They evade nothing, they simply get through. The tactical nukes that may be shot down have a 50% evasion chance each.
 
None of what you said contradicts what I said. Ending this discussion:
75% chance SDI intercepts a nuke
50% chance a tactical nuke will evade the interception once intercepted, therefore a net 62.5% chance of getting through.
That's what happens, and if anyone wants to call it a mistake, they're free to do so.

Once again, worldbuilder tests or python code.
 
It's so much clearer to use positive statements. :)

ICBM: 25% success vs SDI
Tactical: 62.5% success vs SDI

Well worth the cost of building a navy to deliver them!
 
Ok, text edited SDI in. 100 tactical nukes. Several tests, no eye raising results.

I launched from my capital, not a missile cruiser. I launched them all at once, not one by one

I've surrounded the land with peter's culture in case traversing several tiles triggers multiple interception chances.

I've given peter a bunker and an bomb shelter.

And I've given peter 10 mech infantry, 10 jet fighters, and 10 sam infantry in case something silly like air interception or defensive power effects it. Each time peter has intercepted 30 something to low 40 something tactical nukes, as we would expect.

If anyone has some save in which they can demonstrate ridiculous interception odds, I'd like to see it.
 
I wonder if difficulty affects it? Maybe I just got unlucky. Very unlucky. 7 consecutive interceptions is ~ 1 in 1000 chance. Seeing 5x interceptions in a row in the same game (well under a 1 in 100 chance) is pretty dubious.

In theory there's nothing wrong with that, but it certainly merits a look. I apologize as I've been meaning to do this myself but have been out of civ for a few days due to wedding (not mine but in family) and shifting between locations.
 
It's a barebones setup so feel free to modify it. 2 civs, all grassland except for a moat around player 2. I did it as immortal, but it's a worldbuilder save so you can change it to whatever.

player 1 has manhatten project and sdi (in case i wanted to test ai retaliation), player 2 has sdi. player 1 has 100 nukes, which i named 1 2 ... 10 1 2 .... 20 1 2 ... 30 ... 1000 for easy reading. player 1 and 2 have 100000 gold so units don't get deleted after a few turns.

assuming you're not extremely unlucky, here's possible variables that i haven't accounted for:
the nuke went through but the graphic didn't update, and you assumed the previous result occurred again
difference in probabilities if defenders/buildings are present. Suppose mech infantry somehow help intercepting missiles. If they're all dead in the first couple of nukes, then their effect will be marginalized by the next 90 nukes.
missile cruisers
technology
some fixed seed value if you do them one by one
multiple cities
somehow the AI cheats and builds multiple instances of SDI (which doesn't make sense since it should be a binary toggling)
 
I did post it recently:
(if) SDI has 75 and evasion and tactical has 50% evasion.
Odds to intercept a tactical missile: 37% rounded round, so obsolete is correct. Dave, almost.

Spoiler :

excerpt from bool CvUnit::nuke(int iX, int iY)
Code:
for (iI = 0; iI < MAX_TEAMS; iI++)
{
	if (abTeamsAffected[iI])
	{
		if (GET_TEAM((TeamTypes)iI).getNukeInterception() > iBestInterception)
		{
			iBestInterception = GET_TEAM((TeamTypes)iI).getNukeInterception();
			eBestTeam = ((TeamTypes)iI);
		}
	}
}

iBestInterception *= (100 - m_pUnitInfo->getEvasionProbability());
iBestInterception /= 100;

setReconPlot(pPlot);

if (GC.getGameINLINE().getSorenRandNum(100, "Nuke") < iBestInterception)
{
//intercepted, messages and stuff skipped
...
	kill(true);
	return true; // Intercepted!!! (XXX need special event for this...)
}
...

setMadeAttack(true);
setAttackPlot(pPlot, false);

//memory countes (you nuked us and the like)

//war success, war weariness etc...
for (iI = 0; iI < MAX_TEAMS; iI++)
{
	if (abTeamsAffected[iI])
	{
		GET_TEAM((TeamTypes)iI).changeWarWeariness(getTeam(), 100 * GC.getDefineINT("WW_HIT_BY_NUKE"));
		GET_TEAM(getTeam()).changeWarWeariness(((TeamTypes)iI), 100 * GC.getDefineINT("WW_ATTACKED_WITH_NUKE"));
		GET_TEAM(getTeam()).AI_changeWarSuccess(((TeamTypes)iI), GC.getDefineINT("WAR_SUCCESS_NUKE"));
	}
}
....
if (isSuicide())
{
	kill(true);
}

return true;
 
double post instead of edit
note: edit function is malfunctioning badly but

* nukes do not get intercepted by air
* no multi-SDI does anything, only the best interception (i.e. 75% or 0 in the current case) is used if the nuke affects more than a single team (civ)
* there is no python code involved (on a side note, why do people use python and don't compile the C code?)
 
I did post it recently:
(if) SDI has 75 and evasion and tactical has 50% evasion.
Odds to intercept a tactical missile: 37% rounded round, so obsolete is correct. Dave, almost.

Spoiler :

except from bool CvUnit::nuke(int iX, int iY)
Code:
for (iI = 0; iI < MAX_TEAMS; iI++)
{
	if (abTeamsAffected[iI])
	{
		if (GET_TEAM((TeamTypes)iI).getNukeInterception() > iBestInterception)
		{
			iBestInterception = GET_TEAM((TeamTypes)iI).getNukeInterception();
			eBestTeam = ((TeamTypes)iI);
		}
	}
}

iBestInterception *= (100 - m_pUnitInfo->getEvasionProbability());
iBestInterception /= 100;

setReconPlot(pPlot);

if (GC.getGameINLINE().getSorenRandNum(100, "Nuke") < iBestInterception)
{
//intercepted, messages and stuff skipped
...
	kill(true);
	return true; // Intercepted!!! (XXX need special event for this...)
}
...

setMadeAttack(true);
setAttackPlot(pPlot, false);

//memory countes (you nuked us and the like)

//war success, war weariness etc...
for (iI = 0; iI < MAX_TEAMS; iI++)
{
	if (abTeamsAffected[iI])
	{
		GET_TEAM((TeamTypes)iI).changeWarWeariness(getTeam(), 100 * GC.getDefineINT("WW_HIT_BY_NUKE"));
		GET_TEAM(getTeam()).changeWarWeariness(((TeamTypes)iI), 100 * GC.getDefineINT("WW_ATTACKED_WITH_NUKE"));
		GET_TEAM(getTeam()).AI_changeWarSuccess(((TeamTypes)iI), GC.getDefineINT("WAR_SUCCESS_NUKE"));
	}
}
....
if (isSuicide())
{
	kill(true);
}

return true;

Where is this code? It's not in assets.
 
virtually no code is in assets, save for the compiled DLL, it's the C code I told, and it's written
>>bool CvUnit::nuke(int iX, int iY)
so CvUnit.cpp for you
 
Unfortunately it's pretty meaningless to discuss the length of bad luck runs without giving an estimate (or exact number if possible) of total trials performed, when testing the fairness of the binomial random variable (RNG) in use.

The easiest statistical test to perform here is the binomial test, going for at least a 95% confidence interval or preferably (IMO) a 99.7% confidence interval.

As has been discussed, for tactical nukes p = 0.625 (or more accurately it appers it is 0.62 (EDIT... 0.63. The following assumes it is 0.62.) with the way the game calls the RNG).

Suppose you perform 100 trials of a tactical nuke against an SDI (i.e. n = 100) and you observe 50 get through. The sample proportion P is 0.5.

Assuming we would say that getting 12 less than 62 or 12 more than 62 are equally as surprising, we use the two-tailed test.
Using a simple binomial calculator,
Prob(X>=62-12) = 0.0096
Prob(X<=62+12) = 0.0078

The sum of these two probabilities is about 1.74%.
Therefore you would only have about 98.26% confidence to claim the result is statistically significant and disproves the null hypothesis. Disproving the null hypothesis in this case means proving that the probability of tac nukes being shot down is not 0.62.

If this were the only test performed (i.e. not running a bunch of similar 100-trial tests and ignoring the result when it isn't surprising) it would probably convince me the RNG is not fair. I think a result of 48 out of 100 or 76 out of 100 would really seal it though.
 
PoM, nukes get intercepted for values 0(incl)-37 (excl.), so it's 37 out of 100, thus 63% collide.
 
PoM, nukes get intercepted for values 0(incl)-37 (excl.), so it's 37 out of 100, thus 63% collide.

Oh, yes. You said that before. I didn't read closely enough. :d'oh: Anyway, the idea is the same of course, and my numbers at the end of my post won't change much (maybe bump them all up by 1).

i.e. 49 or 77 out of 100 getting through would convince me something is wrong.
 
Ok, so this exonerates everything except

Spoiler getNukeInterception() :
Code:
int CyTeam::getNukeInterception()
{
	return m_pTeam ? m_pTeam->getNukeInterception() : -1;
}

and
GC.getGameINLINE().getSorenRandNum(100, "Nuke")
Spoiler getsorenrand :
Code:
CvRandom& CyGame::getSorenRand()
{
	FAssert(m_pGame);
	return (m_pGame->getSorenRand());
}

int CyGame::getSorenRandNum(int iNum, TCHAR* pszLog) 
{
	return m_pGame ? m_pGame->getSorenRandNum(iNum, pszLog) : -1;
}

if anyone can understand how such a recursive function works
 
Back
Top Bottom