I can confirm that the code works (except that in your case the number of minions following the general in death will be between 0 and nVariableKilled+nMinKilled-1, since you pass nVariableKilled+nMinKilled to the Random() function:
int nNumber = Random(GetLocalInt(OBJECT_SELF, "nVariableKilled") + GetLocalInt(OBJECT_SELF, "nMinKilled"));
You need to move the second closing parenthesis after nVariableKilled, as follows:
int nNumber = Random(GetLocalInt(OBJECT_SELF, "nVariableKilled")) + GetLocalInt(OBJECT_SELF, "nMinKilled");
That way, the number of minions to destroy will be between nMinKilled and nMinKilled+nVariableKilled-1, since Random() will return a number between 0 and nVariableKilled-1, which will be added to nMinKilled.
Here's the code I tried (same as yours, the only difference with yours being the correction above and the addition of some SendMessageToPC statement to show what happens):
/*****************************
Experimental script
Return of the Exile
Andy
15.01.2015
////////////////////////////
When we fight the generals in the Plane of Knowledge, there will be an absurd number of undeads around. Around 60 in totals.
But when one of the generals dies, a random number of these minions will go with him.
***************************/
//Script by 4760 :)
void main()
{
int nInt=1;
string sInt;
SendMessageToPC(GetFirstPC(), GetName(OBJECT_SELF));
string sBoss = GetLocalString(OBJECT_SELF, "sBoss");
int nNumber = Random(GetLocalInt(OBJECT_SELF, "nVariableKilled")) + GetLocalInt(OBJECT_SELF, "nMinKilled");
object oMinion;
int nTotal = GetLocalInt(OBJECT_SELF, "nTotal");
SendMessageToPC(GetFirstPC(), sBoss+" killed, " + IntToString(nNumber) + " out of " + IntToString(nTotal) + " die with him!");
effect eExplosion = EffectNWN2SpecialEffectFile( "fx_kos_power_spell");
ApplyEffectToObject(DURATION_TYPE_INSTANT, eExplosion, OBJECT_SELF);
while (nInt<=nNumber)
{
sInt = IntToString(nInt);
oMinion = GetObjectByTag(sBoss+sInt);
if (GetCurrentHitPoints(oMinion) > 0)
{
object oSound = GetNearestObjectByTag("so_pl_gen_death");
SoundObjectPlay(oSound);
DestroyObject(oMinion);
SendMessageToPC(GetFirstPC(), "Killed so far: " + IntToString(nInt));
nInt++;
}
else nTotal--;
// are there any minions left?
if (nTotal <= nNumber) break; //no, exit the loop
}
}
Ah, there's another difference: I moved the special effect out of the loop so it's only executed once, and not each time a minion dies.
And here are the results:


So the problem (if not only coming from the Random() function) probably comes from the variables. Here's a quick tutorial on how to do it (you may not need it, but it could be useful to others anyway):
1) In the creature's properties, at the very last line, click on the ... button at the end:

2) This will open a window similar to the one below:

3) Click on the "Add" button to get the window below:

In the "Name" field, put the variable name (in our case, sBoss, nVariableKilled, nMinKilled or nTotal)
For sBoss, put the name of the general in the ValueString field. For the other three variables, as they're integer, put the values in the ValueInt field:

4) In the end, you should get this:

If that's what you did, the next thing to check is if the tags of the general's minions match the pattern sBoss+number. In the example above, the general's tag being "c_rat", the twelve minions should have tags between "c_rat1" and "c_rat12".