Integrate air defense missions into interception
The ancients designed interception dead simple: when you overfly a sector, you get intercepted by the sector owner. Fine print interception rules govern which planes intercept. Then complexity got piled on top of it. Chainsaw 2 added an extra interception by surface ship owners, in the target sector only. Chainsaw 3 added an extra interception by land unit owners, in the target sector only (Empire 4 later merged this extra land unit interception with the extra surface ship interception). Chainsaw 3 added an entirely separate kind of interception: air defense missions. When you enter a sector in some air defense op area, you get intercepted. Fine print air defense rules govern which planes intercept. These rules differ significantly from the interception fine print. Additional complexity comes from these facts: * Air defense mission interception happens in addition to non-mission interception. You can boost your total interception by setting up air defense. Which means you must set it up, or forgo an advantage. * Air defense planes are not available for non-mission interception duty. You need to decide on a split. * In contrast to non-mission interception, interceptors flying air defense get intercepted. Moreover, the air defense code breaks one of the plane code's design assumptions, namely that just one plane sortie is active at a time. The air defense sortie runs while the sortie it intercepts is in progress. This leads to two interceptions being active at the same time: the one intercepting the original sortie, and the one intercepting the air defense sortie. The same plane can fly in both interceptions, and damage received in the interception of the air defense sortie is wiped out, triggering a seqno mismatch oops. The previous commit already simplified non-mission interception: you get intercepted by anyone who owns the sector, or a surface ship or a land unit there, whether it's the target sector or not. Now simplify mission interception, by merging air defense back into ordinary interception: when you overfly a sector, you get intercepted by anyone who owns the sector, or a surface ship or land unit there, or has an air defense mission covering the sector. That's all. No multiple interceptions, no separate air defense rules. Remove air_defense(). Simplify ac_encounter() and sam_intercept() accordingly; both lose their last parameter. Change sam_intercept() and ac_intercept() to intercept in mission op areas. New parameter only_mission to suppress non-mission interception. Pass zero when the intercepting country owns the sector or a surface ship or land unit in the sector. ac_encounter() can't efficiently predict whether a country intercepts, so it needs to call ac_intercept() unconditionally. This kills the optimization to collect interceptors only when needed; simplify accordingly, replacing getilist() by getilists().
This commit is contained in:
parent
d1490b9ba5
commit
6564ff2240
10 changed files with 71 additions and 306 deletions
|
@ -630,7 +630,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
|
|||
xyas(x, y, air->own));
|
||||
}
|
||||
|
||||
ac_encounter(&b, &e, air->x, air->y, pp, 0, 0);
|
||||
ac_encounter(&b, &e, air->x, air->y, pp, 0);
|
||||
|
||||
if (!QEMPTY(&b))
|
||||
air_dam +=
|
||||
|
@ -1111,216 +1111,3 @@ air_damage(struct emp_qelem *bombers, coord x, coord y, int mission,
|
|||
|
||||
return dam;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if anyone hostile to the victim
|
||||
* is running an air defense mission on this
|
||||
* sector. If so, do air combat
|
||||
*/
|
||||
int
|
||||
air_defense(coord x, coord y, natid victim, struct emp_qelem *bomb_list,
|
||||
struct emp_qelem *esc_list)
|
||||
{
|
||||
int dam = 0, cn;
|
||||
int combat = 0, rel, dist, z;
|
||||
struct emp_qelem *qp, interceptors, airp, i, empty, *next;
|
||||
struct plist *plp;
|
||||
struct genlist *glp;
|
||||
struct empobj *gp;
|
||||
struct genlist mi[MAXNOC];
|
||||
char buf[512];
|
||||
char *path;
|
||||
int count;
|
||||
int tcount;
|
||||
|
||||
count = 0;
|
||||
for (qp = bomb_list->q_forw; qp != bomb_list; qp = qp->q_forw)
|
||||
count++;
|
||||
for (qp = esc_list->q_forw; qp != esc_list; qp = qp->q_forw)
|
||||
count++;
|
||||
|
||||
memset(mi, 0, sizeof(mi));
|
||||
for (z = 1; z < MAXNOC; z++)
|
||||
emp_initque((struct emp_qelem *)&mi[z]);
|
||||
|
||||
build_mission_list_type(mi, x, y, MI_AIR_DEFENSE, EF_PLANE, victim);
|
||||
|
||||
for (cn = 1; cn < MAXNOC; cn++) {
|
||||
/* Check our relations */
|
||||
rel = getrel(getnatp(cn), victim);
|
||||
|
||||
if (rel > HOSTILE)
|
||||
continue;
|
||||
|
||||
if (QEMPTY(&mi[cn].queue))
|
||||
continue;
|
||||
|
||||
/* Ok, make a list of all the interceptors. Note that this *copies* the
|
||||
* list from the mission creation. This list must be deleted later. */
|
||||
emp_initque(&interceptors);
|
||||
for (qp = mi[cn].queue.q_forw; qp != (&mi[cn].queue); qp = next) {
|
||||
next = qp->q_forw;
|
||||
glp = (struct genlist *)qp;
|
||||
gp = glp->thing;
|
||||
if (CANT_HAPPEN(gp->ef_type != EF_PLANE))
|
||||
break;
|
||||
|
||||
dist = mapdist(x, y, gp->x, gp->y);
|
||||
|
||||
plp = malloc(sizeof(struct plist));
|
||||
memset(plp, 0, sizeof(struct plist));
|
||||
plp->pcp = glp->cp;
|
||||
memcpy(&plp->plane, glp->thing, sizeof(struct plnstr));
|
||||
|
||||
/* missiles go one way, so we can use all the range */
|
||||
if (!(plp->pcp->pl_flags & P_M))
|
||||
dist *= 2;
|
||||
/* If it's out of range, free it and continue on */
|
||||
if (dist > plp->plane.pln_range) {
|
||||
free(plp);
|
||||
continue;
|
||||
}
|
||||
emp_insque(&plp->queue, &interceptors);
|
||||
}
|
||||
|
||||
/* Remove those who cannot go */
|
||||
mission_pln_sel(&interceptors, P_F, 0, SECT_HARDTARGET);
|
||||
|
||||
if (QEMPTY(&interceptors))
|
||||
continue;
|
||||
|
||||
/* Now, delete all the extras, but delete the first ones, not the last ones, so
|
||||
* that the higher numbered planes go into battle (they should be the better ones
|
||||
* at fighting, if all went well.) */
|
||||
tcount = 0;
|
||||
for (qp = interceptors.q_forw; qp != (&interceptors);
|
||||
qp = qp->q_forw)
|
||||
tcount++;
|
||||
tcount -= count * 2;
|
||||
/* Just in case there are more incoming than we have */
|
||||
if (tcount < 0)
|
||||
tcount = 0;
|
||||
for (qp = interceptors.q_forw; qp != (&interceptors); qp = next) {
|
||||
next = qp->q_forw;
|
||||
if (tcount) {
|
||||
tcount--;
|
||||
/* Free it up and continue */
|
||||
emp_remque(qp);
|
||||
glp = (struct genlist *)qp;
|
||||
free(glp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now, make a list of all the airports these planes are coming from */
|
||||
emp_initque(&airp);
|
||||
for (qp = interceptors.q_forw; qp != (&interceptors);
|
||||
qp = qp->q_forw) {
|
||||
plp = (struct plist *)qp;
|
||||
if (!find_airport(&airp, plp->plane.pln_x, plp->plane.pln_y))
|
||||
add_airport(&airp, plp->plane.pln_x, plp->plane.pln_y);
|
||||
}
|
||||
|
||||
/* Now, fly them out one airport at a time */
|
||||
for (qp = airp.q_forw; qp != (&airp); qp = qp->q_forw) {
|
||||
struct airport *air;
|
||||
|
||||
air = (struct airport *)qp;
|
||||
dist = mapdist(x, y, air->x, air->y);
|
||||
|
||||
emp_initque(&i);
|
||||
|
||||
/* Split off the interceptors at this base into i */
|
||||
divide(&interceptors, &i, air->x, air->y);
|
||||
|
||||
sam_intercept(bomb_list, &i, cn, victim, x, y, 0);
|
||||
sam_intercept(esc_list, &i, cn, victim, x, y, 1);
|
||||
|
||||
/* Did we run out of interceptors? */
|
||||
if (QEMPTY(&i))
|
||||
continue;
|
||||
/* Did we run out of bombers? */
|
||||
if (QEMPTY(bomb_list)) {
|
||||
/* Yes, so we have to put the rest of the interceptors back, and
|
||||
then continue, or we leak memory */
|
||||
pln_put(&i);
|
||||
continue;
|
||||
}
|
||||
mission_pln_arm(&i, air->x, air->y, 2 * dist, 0, 0, P_F);
|
||||
|
||||
/* Did we run out of interceptors? */
|
||||
if (QEMPTY(&i))
|
||||
continue;
|
||||
/* Did we run out of bombers? */
|
||||
if (QEMPTY(bomb_list)) {
|
||||
/* Yes, so we have to put the rest of the interceptors back, and
|
||||
then continue, or we leak memory */
|
||||
pln_put(&i);
|
||||
continue;
|
||||
}
|
||||
|
||||
path = BestAirPath(buf, air->x, air->y, x, y);
|
||||
if (CANT_HAPPEN(!path)) {
|
||||
pln_put(&i);
|
||||
continue;
|
||||
}
|
||||
wu(0, cn, "Flying %s mission from %s to %s\n",
|
||||
mission_name(MI_AIR_DEFENSE),
|
||||
xyas(air->x, air->y, cn),
|
||||
xyas(x, y, cn));
|
||||
if (air->own && (air->own != cn)) {
|
||||
wu(0, air->own, "%s is flying %s mission from %s to %s\n",
|
||||
cname(cn), mission_name(MI_AIR_DEFENSE),
|
||||
xyas(air->x, air->y, air->own),
|
||||
xyas(x, y, air->own));
|
||||
}
|
||||
|
||||
/* Now, fly the planes to the sector */
|
||||
emp_initque(&empty);
|
||||
ac_encounter(&i, &empty, air->x, air->y, path, 0, 1);
|
||||
|
||||
/* If none made it, continue */
|
||||
if (QEMPTY(&i))
|
||||
continue;
|
||||
|
||||
/* Some made it, so now they get to try to fight. */
|
||||
/* Intercept the escorts first */
|
||||
combat = 0;
|
||||
if (!QEMPTY(esc_list)) {
|
||||
mpr(victim, "%s air defense planes intercept!\n",
|
||||
cname(cn));
|
||||
ac_combat_headers(victim, cn);
|
||||
ac_airtoair(esc_list, &i);
|
||||
combat = 1;
|
||||
}
|
||||
/* Now intercept the bombers */
|
||||
if (!QEMPTY(bomb_list)) {
|
||||
if (!combat) {
|
||||
mpr(victim, "%s air defense planes intercept!\n",
|
||||
cname(cn));
|
||||
ac_combat_headers(victim, cn);
|
||||
}
|
||||
ac_airtoair(bomb_list, &i);
|
||||
PR(cn, "\n");
|
||||
PR(victim, "\n");
|
||||
}
|
||||
|
||||
pln_put(&i);
|
||||
}
|
||||
if (CANT_HAPPEN(!QEMPTY(&interceptors)))
|
||||
pln_put(&interceptors);
|
||||
}
|
||||
|
||||
/* We have to free all of these, if they are still there, otherwise they get
|
||||
lost and we leak memory all over the place. */
|
||||
for (cn = 1; cn < MAXNOC; cn++) {
|
||||
/* free up all this memory if it's still there */
|
||||
for (qp = mi[cn].queue.q_forw; qp != (&mi[cn].queue); qp = next) {
|
||||
next = qp->q_forw;
|
||||
glp = (struct genlist *)qp;
|
||||
free(glp->thing);
|
||||
free(glp);
|
||||
}
|
||||
}
|
||||
|
||||
return dam;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue