The current combat code is as follows:
// 2.9C ship combat
mapping asb, enb, en, br;
float dmg, dest;
mapping mined=([]);
mapping swept=([]);
// 3C foreach system, check for ships doing stuff
foreach(indices(d[series][game]["s"]), ixa) {
if(!mappingp(sf[ixa])) continue;
if (!mappingp(missive[ixa])) {
missive[ixa]=([]);
missive[ixa]["dest"]=([]);
missive[ixa]["sight"]=([]);
missive[ixa]["sys"]="";
} // if
mined[ixa]=0;
swept[ixa]=0;
br=([]);
en=([]);
enb=([]);
asb=([]);
// 3C for every player who has ships here
foreach(indices(sf[ixa]), ixb) {
missive[ixa]["dest"][ixb]=({});
missive[ixa]["sight"][ixb]=({});
br[ixb]=0.0;
enb[ixb]=0.0;
asb[ixb]=0.0;
// 3C foreach ship that player has here
foreach(sf[ixa][ixb], ixc)
if(mappingp(d[series][game]["f"][ixc]))
br[ixb]+=pow(d[series][game]["f"][ixc]["br"], 2.0);
if(d[series][game]["p"][ixb]["fuel_r"]<1.0)
br[ixb]*=d[series][game]["p"][ixb]["fuel_r"];
en[ixb]=({});
// 3C now check to see who is our enemy here
foreach(indices(sf[ixa]), ixc) {
if(ixb==ixc) continue;
// 2.9 changed magic number 0 to 2
if(search(indices(d[series][game]["p"][ixb]["dip"]), ixc)==-1) {
d[series][game]["p"][ixb]["dip"][ixc]=2;
d[series][game]["p"][ixb]["set_dip"][ixc]=2;
d[series][game]["p"][ixb]["missive"]+=
("\You have had first contact with "+ixc+
" in "+ixa+" (ship to ship)\
");
d[series][game]["p"][ixc]["dip"][ixb]=2;
d[series][game]["p"][ixc]["set_dip"][ixb]=2;
d[series][game]["p"][ixc]["missive"]+=
("\You have had first contact with "+ixb+
" in "+ixa+" (ship to ship)\
");
d[series][game]["history"] += "First contact between "+ixb+" and "+ixc+" in "+ixa+"\
";
}
// 2.9 changed ==0 to <3
if(d[series][game]["p"][ixb]["dip"][ixc]<3) en[ixb]+=({ixc});
}
} // 3C for everyone who has ships here
// 3C now that we've done the initial data structure, go through and
// calculate how much damage is done to each player
foreach(indices(sf[ixa]), ixb) {
foreach(en[ixb], ixc)
enb[ixb]+=br[ixc];
foreach(en[ixb], ixc)
if(enb[ixb]>0.0) asb[ixc]+=(br[ixc]/enb[ixb])*br[ixb];
}
foreach(indices(sf[ixa]), ixb) {
dest=asb[ixb]/2.0;
foreach(sf[ixa][ixb], ixc)
if(mappingp(d[series][game]["f"][ixc]))
if(pow(d[series][game]["f"][ixc]["br"], 2.0)<=dest) {
if((d[series][game]["f"][ixc]["type"]=="Minefield")) {
continue;
} // if
if(d[series][game]["f"][ixc]["type"]=="Carrier") {
if(d[series][game]["f"][ixc]["br"] > d[series]["car_loss"]) {
d[series][game]["f"][ixc]["max_br"] -= d[series]["car_loss"];
d[series][game]["f"][ixc]["br"] -= d[series]["car_loss"];
dest-=pow(d[series][game]["f"][ixc]["br"], 2.0);
br[ixb]+=pow(d[series][game]["f"][ixc]["br"], 2.0);
br[ixb]-=pow((d[series][game]["f"][ixc]["br"]+d[series]["car_loss"]), 2.0);
d[series][game]["p"][ixb]["missive"]+= ("\"
+d[series][game]["f"][ixc]["name"]+" of "+
ixb+" has taken damage.\
");
continue;
} // if
} // if carrier
missive[ixa]["dest"][ixb]+=({d[series][game]["f"][ixc]["name"]});
dest-=pow(d[series][game]["f"][ixc]["br"], 2.0);
br[ixb]-=pow(d[series][game]["f"][ixc]["br"], 2.0);
sf[ixa][ixb]-=({ixc});
d[series][game]["p"][d[series][game]["f"][ixc]["owner"]]["ship_count"]--;
d[series][game]["f"]-=([ixc:""]);
}
if(br[ixb]>0.0) {
dmg=1.0-(((asb[ixb]/2.0)+dest)/br[ixb]);
// 3C if everyone is wiped out
if(dmg<=0.0) {
foreach(sf[ixa][ixb], ixc) {
missive[ixa]["dest"][ixb]+=({d[series][game]["f"][ixc]["name"]});
if((d[series][game]["f"][ixc]["type"]=="Minefield")) {
mined[ixa]=1;
} // if
d[series][game]["p"][d[series][game]["f"][ixc]["owner"]]["ship_count"]--;
d[series][game]["f"]-=([ixc:""]);
}
if(br[ixb]>0.0) {
dmg=1.0-(((asb[ixb]/2.0)+dest)/br[ixb]);
// 3C if everyone is wiped out
if(dmg<=0.0) {
foreach(sf[ixa][ixb], ixc) {
missive[ixa]["dest"][ixb]+=({d[series][game]["f"][ixc]["name"]});
if((d[series][game]["f"][ixc]["type"]=="Minefield")) {
mined[ixa]=1;
} // if
d[series][game]["p"][d[series][game]["f"][ixc]["owner"]]["ship_count"]--;
d[series][game]["f"]-=([ixc:""]);
}
} else {
foreach(sf[ixa][ixb], ixc) {
missive[ixa]["sight"][ixb]+=({d[series][game]["f"][ixc]["name"]});
if(d[series][game]["f"][ixc]["type"]=="Minesweeper") {
swept[ixa]=1;
} // if
d[series][game]["f"][ixc]["br"]*=dmg;
}
} // 3C wiped out or not
} // 3C if there are any ships left
}
}
// 2.9C end ship combat
As you see, and as Jerome states, the only mention of fuel ratio is in the calculation of overall battle points for the fleet (sadly, this is called "br[]"). I think that in order to involve fuel ratio in the calculation of damage done to the fleet, as opposed to calculation of how much damage the fleet can deliver, the idea of each ship's Effective BP should be introduced into the (per-ship, ixc) loop which deals with DEST. Effective BP is the square of the ship's Current BR multiplied by the empire's Fuel Ratio.
I think and hope that there's no need to involve this further in the loop which administers secondary damage. This is primarily what I'm asking for a sanity check on, though of course any other comments are welcome. Here's my proposed revised code:
// 2.9C ship combat
mapping asb, enb, en, br;
float dmg, dest;
mapping mined=([]);
mapping swept=([]);
// 3C foreach system, check for ships doing stuff
foreach(indices(d[series][game]["s"]), ixa) {
if(!mappingp(sf[ixa])) continue;
if (!mappingp(missive[ixa])) {
missive[ixa]=([]);
missive[ixa]["dest"]=([]);
missive[ixa]["sight"]=([]);
missive[ixa]["sys"]="";
} // if
mined[ixa]=0;
swept[ixa]=0;
br=([]);
en=([]);
enb=([]);
asb=([]);
// 3C for every player who has ships here
foreach(indices(sf[ixa]), ixb) {
missive[ixa]["dest"][ixb]=({});
missive[ixa]["sight"][ixb]=({});
br[ixb]=0.0;
enb[ixb]=0.0;
asb[ixb]=0.0;
// 3C foreach ship that player has here
foreach(sf[ixa][ixb], ixc)
if(mappingp(d[series][game]["f"][ixc]))
br[ixb]+=pow(d[series][game]["f"][ixc]["br"], 2.0);
if(d[series][game]["p"][ixb]["fuel_r"]<1.0)
br[ixb]*=d[series][game]["p"][ixb]["fuel_r"];
en[ixb]=({});
// 3C now check to see who is our enemy here
foreach(indices(sf[ixa]), ixc) {
if(ixb==ixc) continue;
// 2.9 changed magic number 0 to 2
if(search(indices(d[series][game]["p"][ixb]["dip"]), ixc)==-1) {
d[series][game]["p"][ixb]["dip"][ixc]=2;
d[series][game]["p"][ixb]["set_dip"][ixc]=2;
d[series][game]["p"][ixb]["missive"]+=
("\You have had first contact with "+ixc+
" in "+ixa+" (ship to ship)\
");
d[series][game]["p"][ixc]["dip"][ixb]=2;
d[series][game]["p"][ixc]["set_dip"][ixb]=2;
d[series][game]["p"][ixc]["missive"]+=
("\You have had first contact with "+ixb+
" in "+ixa+" (ship to ship)\
");
d[series][game]["history"] += "First contact between "+ixb+" and "+ixc+" in "+ixa+"\
";
}
// 2.9 changed ==0 to <3
if(d[series][game]["p"][ixb]["dip"][ixc]<3) en[ixb]+=({ixc});
}
} // 3C for everyone who has ships here
// 3C now that we've done the initial data structure, go through and
// calculate how much damage is done to each player
foreach(indices(sf[ixa]), ixb) {
foreach(en[ixb], ixc)
enb[ixb]+=br[ixc];
foreach(en[ixb], ixc)
if(enb[ixb]>0.0) asb[ixc]+=(br[ixc]/enb[ixb])*br[ixb];
}
foreach(indices(sf[ixa]), ixb) {
dest=asb[ixb]/2.0;
foreach(sf[ixa][ixb], ixc) {
if(mappingp(d[series][game]["f"][ixc])) {
float effective_bp;
effective_bp = pow(d[series][game]["f"][ixc]["br"], 2.0);
if(d[series][game]["p"][ixb]["fuel_r"]<1.0)
effective_bp*=d[series][game]["p"][ixb]["fuel_r"];
if(effective_bp<=dest) {
if((d[series][game]["f"][ixc]["type"]=="Minefield")) {
continue;
} // if minefield (immune to primary damage)
if(d[series][game]["f"][ixc]["type"]=="Carrier") {
if(d[series][game]["f"][ixc]["br"] > d[series]["car_loss"]) {
d[series][game]["f"][ixc]["max_br"] -= d[series]["car_loss"];
br[ixb]-=effective_bp;
d[series][game]["f"][ixc]["br"] -= d[series]["car_loss"];
effective_bp = pow(d[series][game]["f"][ixc]["br"], 2.0);
if(d[series][game]["p"][ixb]["fuel_r"]<1.0)
effective_bp*=d[series][game]["p"][ixb]["fuel_r"];
dest-=effective_bp;
br[ixb]+=effective_bp;
d[series][game]["p"][ixb]["missive"]+= ("\"
+d[series][game]["f"][ixc]["name"]+" of "+
ixb+" has taken damage.\
");
continue;
} // if carrier has enough current br to take carrier loss
} // if carrier
missive[ixa]["dest"][ixb]+=({d[series][game]["f"][ixc]["name"]});
dest-=effective_bp;
br[ixb]-=effective_bp;
sf[ixa][ixb]-=({ixc});
d[series][game]["p"][d[series][game]["f"][ixc]["owner"]]["ship_count"]--;
d[series][game]["f"]-=([ixc:""]);
}
}
}
if(br[ixb]>0.0) {
dmg=1.0-(((asb[ixb]/2.0)+dest)/br[ixb]);
// 3C if everyone is wiped out
if(dmg<=0.0) {
foreach(sf[ixa][ixb], ixc) {
missive[ixa]["dest"][ixb]+=({d[series][game]["f"][ixc]["name"]});
if((d[series][game]["f"][ixc]["type"]=="Minefield")) {
mined[ixa]=1;
} // if minefield (exploded by secondary damage)
d[series][game]["p"][d[series][game]["f"][ixc]["owner"]]["ship_count"]--;
d[series][game]["f"]-=([ixc:""]);
}
} else {
foreach(sf[ixa][ixb], ixc) { // each remaining ship, sighting, sweeping and secondary damage
missive[ixa]["sight"][ixb]+=({d[series][game]["f"][ixc]["name"]});
if(d[series][game]["f"][ixc]["type"]=="Minesweeper") {
swept[ixa]=1;
} // if minesweeper
d[series][game]["f"][ixc]["br"]*=dmg;
}
} // 3C wiped out or not
} // 3C if there are any ships left
}
}
// 2.9C end ship combat