+ dam = perform_mission_msl(dam, &missiles, x, y, victim, hardtarget);
+ dam = perform_mission_bomb(dam, &bombers, x, y, victim, mission, s,
+ hardtarget, targeting_ships);
+
+ qp = list->q_forw;
+ while (qp != list) {
+ glp = (struct genlist *)qp;
+ qp = qp->q_forw;
+
+ free(glp->thing);
+ free(glp);
+ }
+
+ return dam;
+}
+
+static int
+perform_mission_land(int dam, struct lndstr *lp, coord x, coord y,
+ natid victim, int mission, char *s, int md,
+ int targeting_ships)
+{
+ int range, dam2;
+
+ if (mission == MI_SINTERDICT)
+ return dam;
+
+ if ((mission == MI_INTERDICT) &&
+ (md > land_max_interdiction_range))
+ return dam;
+
+ range = roundrange(lnd_fire_range(lp));
+ if (md > range)
+ return dam;
+
+ dam2 = lnd_fire(lp);
+ putland(lp->lnd_uid, lp);
+ if (dam2 < 0)
+ return dam;
+
+ if (targeting_ships) {
+ if (chance(lnd_acc(lp) / 100.0))
+ dam2 = ldround(dam2 / 2.0, 1);
+ }
+ if (targeting_ships)
+ nreport(lp->lnd_own, N_SHP_SHELL, victim, 1);
+ else
+ nreport(lp->lnd_own, N_SCT_SHELL, victim, 1);
+ wu(0, lp->lnd_own,
+ "%s fires at %s %s at %s\n",
+ prland(lp), cname(victim), s, xyas(x, y, lp->lnd_own));
+
+ mpr(victim, "%s %s fires at you at %s\n",
+ cname(lp->lnd_own), prland(lp), xyas(x, y, victim));
+
+ return dam + dam2;
+}
+
+static int
+perform_mission_ship(int dam, struct shpstr *sp, coord x, coord y,
+ natid victim, int mission, char *s, int md,
+ int targeting_ships)
+{
+ struct mchrstr *mcp = &mchr[sp->shp_type];
+ double vrange, hitchance;
+ int range, dam2;
+
+ if (((mission == MI_INTERDICT) ||
+ (mission == MI_SINTERDICT)) &&
+ (md > ship_max_interdiction_range))
+ return dam;
+ if (mission == MI_SINTERDICT) {
+ if (!(mcp->m_flags & M_SONAR))
+ return dam;
+ if (!(mcp->m_flags & M_DCH) && !(mcp->m_flags & M_SUBT))
+ return dam;
+ vrange = techfact(sp->shp_tech, mcp->m_vrnge);
+ vrange *= sp->shp_effic / 200.0;
+ if (md > vrange)
+ return dam;
+ /* can't look all the time */
+ if (chance(0.5))
+ return dam;
+ }
+ if (mcp->m_flags & M_SUB) {
+ if (!targeting_ships)
+ return dam; /* subs interdict only ships */
+ range = roundrange(torprange(sp));
+ if (md > range)
+ return dam;
+ if (!line_of_sight(NULL, x, y, sp->shp_x, sp->shp_y))
+ return dam;
+ dam2 = shp_torp(sp, 1);
+ putship(sp->shp_uid, sp);
+ if (dam2 < 0)
+ return dam;
+ hitchance = shp_torp_hitchance(sp, md);
+
+ wu(0, sp->shp_own,
+ "%s locking on %s %s in %s\n",
+ prship(sp), cname(victim), s, xyas(x, y, sp->shp_own));
+ wu(0, sp->shp_own,
+ "\tEffective torpedo range is %d.0\n", range);
+ wu(0, sp->shp_own,
+ "\tWhooosh... Hitchance = %d%%\n",
+ (int)(hitchance * 100));
+
+ if (!chance(hitchance)) {
+ wu(0, sp->shp_own, "\tMissed\n");
+ mpr(victim,
+ "Incoming torpedo sighted @ %s missed (whew)!\n",
+ xyas(x, y, victim));
+ return dam;
+ }
+ wu(0, sp->shp_own, "\tBOOM!...\n");
+ nreport(victim, N_TORP_SHIP, 0, 1);
+ wu(0, sp->shp_own,
+ "\tTorpedo hit %s %s for %d damage\n",
+ cname(victim), s, dam2);
+
+ mpr(victim,
+ "Incoming torpedo sighted @ %s hits and does %d damage!\n",
+ xyas(x, y, victim), dam2);
+ } else {
+ range = roundrange(shp_fire_range(sp));
+ if (md > range)
+ return dam;
+ if (mission == MI_SINTERDICT)
+ dam2 = shp_dchrg(sp);
+ else
+ dam2 = shp_fire(sp);
+ putship(sp->shp_uid, sp);
+ if (dam2 < 0)
+ return dam;
+ if (targeting_ships)
+ nreport(sp->shp_own, N_SHP_SHELL, victim, 1);
+ else
+ nreport(sp->shp_own, N_SCT_SHELL, victim, 1);
+ wu(0, sp->shp_own,
+ "%s fires at %s %s at %s\n",
+ prship(sp), cname(victim), s, xyas(x, y, sp->shp_own));
+
+ mpr(victim, "%s %s fires at you at %s\n",
+ cname(sp->shp_own), prship(sp), xyas(x, y, victim));
+ }
+
+ return dam + dam2;
+}
+
+static int
+perform_mission_msl(int dam, struct emp_qelem *missiles, coord x, coord y,
+ natid victim, int hardtarget)
+{
+ int air_dam;
+ struct emp_qelem *qp, *newqp;
+ struct plist *plp;
+ int sublaunch, dam2;
+