]> git.pond.sub.org Git - empserver/blobdiff - src/lib/subs/mission.c
Update copyright notice
[empserver] / src / lib / subs / mission.c
index 395b170fef105b3841bf83722a973c3b0c1bd8d5..517826ff35ee8a0b42bd2f5748219238442721ef 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2009, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2010, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                           Ken Stevens, Steve McClure
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -51,7 +51,6 @@
 
 struct genlist {
     struct emp_qelem queue;    /* list of units */
-    void *cp;                  /* pointer to desc of thing */
     struct empobj *thing;      /* thing's struct */
 };
 
@@ -74,15 +73,21 @@ static void mission_pln_arm(struct emp_qelem *, coord, coord, int,
                            int, struct ichrstr *);
 static void mission_pln_sel(struct emp_qelem *, int, int, int);
 static int perform_mission_land(int, struct lndstr *, coord, coord,
-                               natid, int, char *, int, int);
+                               natid, int, char *, int);
 static int perform_mission_ship(int, struct shpstr *, coord, coord,
-                               natid, int, char *, int, int);
+                               natid, int, char *, int);
 static int perform_mission_msl(int, struct emp_qelem *, coord, coord,
                               natid, int);
 static int perform_mission_bomb(int, struct emp_qelem *, coord, coord,
                                natid, int, char *, int, int);
-static int perform_mission(coord, coord, natid, struct emp_qelem *, int,
-                          char *, int);
+static int perform_mission(coord, coord, natid, struct emp_qelem *,
+                          int, char *, int);
+
+static int
+tally_dam(int dam, int newdam)
+{
+    return dam < 0 ? newdam : dam + newdam;
+}
 
 /*
  * Interdict commodities & transported planes
@@ -93,11 +98,10 @@ ground_interdict(coord x, coord y, natid victim, char *s)
     int cn;
     int dam = 0, newdam, rel;
     struct genlist mi[MAXNOC];
-    int z;
 
     memset(mi, 0, sizeof(mi));
-    for (z = 1; z < MAXNOC; z++)
-       emp_initque((struct emp_qelem *)&mi[z]);
+    for (cn = 1; cn < MAXNOC; cn++)
+       emp_initque((struct emp_qelem *)&mi[cn]);
 
     build_mission_list(mi, x, y, MI_INTERDICT, victim);
 
@@ -111,10 +115,11 @@ ground_interdict(coord x, coord y, natid victim, char *s)
 
        newdam = perform_mission(x, y, victim, &mi[cn].queue,
                                 MI_INTERDICT, s, SECT_HARDTARGET);
-       dam += newdam;
-       if (newdam)
+       if (newdam > 0) {
+           dam += newdam;
            mpr(victim, "%s interdiction mission does %d damage!\n",
                cname(cn), newdam);
+       }
     }
     if (dam) {
        collateral_damage(x, y, dam);
@@ -150,15 +155,13 @@ only_subs(struct emp_qelem *list)
 {
     struct emp_qelem *qp;
     struct genlist *glp;
-    struct mchrstr *mcp;
 
     for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
        glp = (struct genlist *)qp;
 
        if (glp->thing->ef_type != EF_SHIP)
            return 0;
-       mcp = glp->cp;
-       if (!(mcp->m_flags & M_SUB))
+       if (!(mchr[glp->thing->type].m_flags & M_SUB))
            return 0;
        /* It's a sub! */
     }
@@ -174,15 +177,13 @@ int
 unit_interdict(coord x, coord y, natid victim, char *s, int hardtarget,
               int mission)
 {
-    int cn;
-    int dam = 0, newdam;
+    int cn, newdam, osubs;
+    int dam = -1;
     struct genlist mi[MAXNOC];
-    int z;
-    int osubs;
 
     memset(mi, 0, sizeof(mi));
-    for (z = 1; z < MAXNOC; z++)
-       emp_initque((struct emp_qelem *)&mi[z]);
+    for (cn = 1; cn < MAXNOC; cn++)
+       emp_initque((struct emp_qelem *)&mi[cn]);
 
     build_mission_list(mi, x, y, mission, victim);
 
@@ -201,17 +202,13 @@ unit_interdict(coord x, coord y, natid victim, char *s, int hardtarget,
        osubs = only_subs(&mi[cn].queue);
        newdam = perform_mission(x, y, victim, &mi[cn].queue,
                                 mission, s, hardtarget);
-       dam += newdam;
-       if (newdam) {
-           /* If only subs responded, then we don't know who's
-              subs they are */
+       dam = tally_dam(dam, newdam);
+       if (newdam > 0)
            mpr(victim, "%s interdiction mission does %d damage!\n",
                osubs ? "Enemy" : cname(cn), newdam);
-       }
     }
-    if (dam) {
+    if (dam > 0)
        collateral_damage(x, y, dam);
-    }
     return dam;
 }
 
@@ -223,11 +220,11 @@ off_support(coord x, coord y, natid victim, natid actee)
 {
     int dam = 0;
     struct genlist mi[MAXNOC];
-    int z;
+    int cn;
 
     memset(mi, 0, sizeof(mi));
-    for (z = 1; z < MAXNOC; z++)
-       emp_initque((struct emp_qelem *)&mi[z]);
+    for (cn = 1; cn < MAXNOC; cn++)
+       emp_initque((struct emp_qelem *)&mi[cn]);
 
     build_mission_list(mi, x, y, MI_SUPPORT, victim);
     build_mission_list(mi, x, y, MI_OSUPPORT, victim);
@@ -244,11 +241,11 @@ def_support(coord x, coord y, natid victim, natid actee)
 {
     int dam = 0;
     struct genlist mi[MAXNOC];
-    int z;
+    int cn;
 
     memset(mi, 0, sizeof(mi));
-    for (z = 1; z < MAXNOC; z++)
-       emp_initque((struct emp_qelem *)&mi[z]);
+    for (cn = 1; cn < MAXNOC; cn++)
+       emp_initque((struct emp_qelem *)&mi[cn]);
 
     build_mission_list(mi, x, y, MI_SUPPORT, victim);
     build_mission_list(mi, x, y, MI_DSUPPORT, victim);
@@ -261,7 +258,7 @@ static int
 dosupport(struct genlist *mi, coord x, coord y, natid victim, natid actee)
 {
     int cn;
-    int rel;
+    int rel, newdam;
     int dam = 0;
 
     for (cn = 1; cn < MAXNOC; cn++) {
@@ -275,8 +272,10 @@ dosupport(struct genlist *mi, coord x, coord y, natid victim, natid actee)
        if (QEMPTY(&mi[cn].queue))
            continue;
 
-       dam += perform_mission(x, y, victim, &mi[cn].queue, MI_SUPPORT,
-                              "", SECT_HARDTARGET);
+       newdam = perform_mission(x, y, victim, &mi[cn].queue, MI_SUPPORT,
+                                "", SECT_HARDTARGET);
+       if (newdam > 0)
+           dam += newdam;
     }
     return dam;
 }
@@ -351,7 +350,6 @@ build_mission_list_type(struct genlist *mi, coord x, coord y, int mission,
 
        glp = malloc(sizeof(struct genlist));
        memset(glp, 0, sizeof(struct genlist));
-       glp->cp = get_empobj_chr(gp);
        glp->thing = malloc(sizeof(item));
        memcpy(glp->thing, &item, sizeof(item));
        emp_insque(&glp->queue, &mi[gp->own].queue);
@@ -388,34 +386,27 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
     struct emp_qelem *qp, missiles, bombers;
     struct genlist *glp;
     struct plist *plp;
-    struct empobj *gp;
-    struct sctstr sect;
     struct plchrstr *pcp;
-    int dam = 0;
-    int md;
+    int dam = -1;
     int targeting_ships = *s == 's'; /* "subs" or "ships" FIXME gross! */
 
-    getsect(x, y, &sect);
-
     emp_initque(&missiles);
     emp_initque(&bombers);
 
-    for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
+    for (qp = list->q_forw; qp != list; ) {
        glp = (struct genlist *)qp;
-       gp = glp->thing;
-
-       md = mapdist(x, y, gp->x, gp->y);
+       qp = qp->q_forw;
 
        if (glp->thing->ef_type == EF_LAND) {
            dam = perform_mission_land(dam, (struct lndstr *)glp->thing,
                                       x, y, victim, mission, s,
-                                      md, targeting_ships);
+                                      targeting_ships);
        } else if (glp->thing->ef_type == EF_SHIP) {
            dam = perform_mission_ship(dam, (struct shpstr *)glp->thing,
                                       x, y, victim, mission, s,
-                                      md, targeting_ships);
+                                      targeting_ships);
        } else if (glp->thing->ef_type == EF_PLANE) {
-           pcp = glp->cp;
+           pcp = &plchr[glp->thing->type];
            if (pcp->pl_flags & P_M)
                /* units have their own missile interdiction */
                if (hardtarget != SECT_HARDTARGET || pcp->pl_flags & P_MAR)
@@ -435,36 +426,29 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
            CANT_REACH();
            break;
        }
+       free(glp->thing);
+       free(glp);
     }
 
     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,
+                    natid victim, int mission, char *s,
                     int targeting_ships)
 {
-    int range, dam2;
+    int md, range, dam2;
 
     if (mission == MI_SINTERDICT)
        return dam;
 
-    if ((mission == MI_INTERDICT) &&
-       (md > land_max_interdiction_range))
+    md = mapdist(x, y, lp->lnd_x, lp->lnd_y);
+
+    if (mission == MI_INTERDICT && md > land_max_interdiction_range)
        return dam;
 
     range = roundrange(lnd_fire_range(lp));
@@ -491,22 +475,24 @@ perform_mission_land(int dam, struct lndstr *lp, coord x, coord y,
     mpr(victim, "%s %s fires at you at %s\n",
        cname(lp->lnd_own), prland(lp), xyas(x, y, victim));
 
-    return dam + dam2;
+    return tally_dam(dam, dam2);
 }
 
 static int
 perform_mission_ship(int dam, struct shpstr *sp, coord x, coord y,
-                    natid victim, int mission, char *s, int md,
+                    natid victim, int mission, char *s,
                     int targeting_ships)
 {
     struct mchrstr *mcp = &mchr[sp->shp_type];
     double vrange, hitchance;
-    int range, dam2;
+    int md, range, dam2;
 
-    if (((mission == MI_INTERDICT) ||
-        (mission == MI_SINTERDICT)) &&
-       (md > ship_max_interdiction_range))
+    md = mapdist(x, y, sp->shp_x, sp->shp_y);
+
+    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;
@@ -548,7 +534,7 @@ perform_mission_ship(int dam, struct shpstr *sp, coord x, coord y,
            mpr(victim,
                "Incoming torpedo sighted @ %s missed (whew)!\n",
                xyas(x, y, victim));
-           return dam;
+           return tally_dam(dam, 0);
        }
        wu(0, sp->shp_own, "\tBOOM!...\n");
        nreport(victim, N_TORP_SHIP, 0, 1);
@@ -582,24 +568,23 @@ perform_mission_ship(int dam, struct shpstr *sp, coord x, coord y,
            cname(sp->shp_own), prship(sp), xyas(x, y, victim));
     }
 
-    return dam + dam2;
+    return tally_dam(dam, dam2);
 }
 
 static int
 perform_mission_msl(int dam, struct emp_qelem *missiles, coord x, coord y,
                    natid victim, int hardtarget)
 {
-    int air_dam;
+    int performed, air_dam, sublaunch, dam2;
     struct emp_qelem *qp, *newqp;
     struct plist *plp;
-    int sublaunch, dam2;
 
     /*
      * Missiles, except for interdiction of ships or land units,
      * because that happens elsewhere, in shp_missile_interdiction()
      * and lnd_missile_interdiction().
      */
-    air_dam = 0;
+    performed = air_dam = 0;
     for (qp = missiles->q_back; qp != missiles; qp = newqp) {
        newqp = qp->q_back;
        plp = (struct plist *)qp;
@@ -611,6 +596,7 @@ perform_mission_msl(int dam, struct emp_qelem *missiles, coord x, coord y,
            if (msl_launch(&plp->plane, EF_SECTOR, "sector", x, y, victim,
                           &sublaunch) < 0)
                goto use_up_msl;
+           performed = 1;
            if (!msl_hit(&plp->plane, SECT_HARDTARGET, EF_SECTOR,
                         N_SCT_MISS, N_SCT_SMISS, sublaunch, victim))
                CANT_REACH();
@@ -623,7 +609,8 @@ perform_mission_msl(int dam, struct emp_qelem *missiles, coord x, coord y,
        emp_remque(qp);
        free(qp);
     }
-    return dam + air_dam;
+
+    return performed ? tally_dam(dam, air_dam) : dam;
 }
 
 static int
@@ -633,7 +620,7 @@ perform_mission_bomb(int dam, struct emp_qelem *bombers, coord x, coord y,
 {
     struct emp_qelem *qp, *newqp, escorts, airp, b, e;
     struct plist *plp;
-    int plane_owner, air_dam, md;
+    int plane_owner, performed, air_dam, md;
 
     emp_initque(&escorts);
     emp_initque(&airp);
@@ -665,7 +652,7 @@ perform_mission_bomb(int dam, struct emp_qelem *bombers, coord x, coord y,
            add_airport(&airp, plp->plane.pln_x, plp->plane.pln_y);
     }
 
-    air_dam = 0;
+    performed = air_dam = 0;
     for (qp = airp.q_forw; qp != (&airp); qp = qp->q_forw) {
        struct airport *air;
        char buf[512];
@@ -693,6 +680,7 @@ perform_mission_bomb(int dam, struct emp_qelem *bombers, coord x, coord y,
        pp = BestAirPath(buf, air->x, air->y, x, y);
        if (CANT_HAPPEN(!pp))
            continue;
+       performed = 1;
        wu(0, plane_owner, "Flying %s mission from %s to %s\n",
           mission_name(mission),
           xyas(air->x, air->y, plane_owner),
@@ -737,7 +725,7 @@ perform_mission_bomb(int dam, struct emp_qelem *bombers, coord x, coord y,
        qp = newqp;
     }
 
-    return dam + air_dam;
+    return performed ? tally_dam(dam, air_dam) : dam;
 }
 
 int