]> git.pond.sub.org Git - empserver/blobdiff - src/lib/subs/mission.c
Update copyright notice.
[empserver] / src / lib / subs / mission.c
index 9e9898032db005d04cd947a5352821455fc7abb8..4def9a1b07607daa5e35d9423ebea287bb7f404e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                           Ken Stevens, Steve McClure
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -19,9 +19,9 @@
  *
  *  ---
  *
- *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
- *  related information and legal notices. It is expected that any future
- *  projects/authors will amend these files as needed.
+ *  See files README, COPYING and CREDITS in the root of the source
+ *  tree for related information and legal notices.  It is expected
+ *  that future projects/authors will amend these files as needed.
  *
  *  ---
  *
  *     Steve McClure, 1996-2000
  */
 
-#include "options.h"
+#include <config.h>
+
+#include <stdlib.h>
+#include "damage.h"
+#include "empobj.h"
+#include "file.h"
+#include "item.h"
 #include "misc.h"
-#include "player.h"
-#include "var.h"
-#include "xy.h"
-#include "sect.h"
-#include "retreat.h"
-#include "ship.h"
-#include "land.h"
-#include "plane.h"
-#include "nat.h"
+#include "mission.h"
 #include "nsc.h"
-#include "file.h"
+#include "optlist.h"
 #include "path.h"
-#include "mission.h"
-#include "genitem.h"
-#include "nuke.h"
-#include "news.h"
-#include "item.h"
-#include <fcntl.h>
-#include "damage.h"
+#include "player.h"
 #include "prototypes.h"
-#include "optlist.h"
+#include "queue.h"
+#include "xy.h"
+
+struct genlist {
+    struct emp_qelem queue;    /* list of units */
+    void *cp;                  /* pointer to desc of thing */
+    struct empobj *thing;      /* thing's struct */
+};
 
 struct airport {
     struct emp_qelem queue;
@@ -64,7 +63,7 @@ struct airport {
 
 static void add_airport(struct emp_qelem *, coord, coord);
 static int air_damage(struct emp_qelem *, coord, coord, int, natid,
-                     s_char *, int);
+                     char *, int);
 static void build_mission_list(struct genlist *, coord, coord, int, natid);
 static void build_mission_list_type(struct genlist *, coord, coord, int,
                                    int, natid);
@@ -75,15 +74,15 @@ static int mission_pln_arm(struct emp_qelem *, coord, coord, int,
                           int, struct ichrstr *, int, int, int *);
 static void mission_pln_sel(struct emp_qelem *, int, int, int);
 static int perform_mission(coord, coord, natid, struct emp_qelem *, int,
-                          s_char *, int);
+                          char *, int);
 
 /*
  * Interdict commodities & transported planes
  */
 int
-ground_interdict(coord x, coord y, natid victim, s_char *s)
+ground_interdict(coord x, coord y, natid victim, char *s)
 {
-    register int cn;
+    int cn;
     int dam = 0, newdam, rel;
     struct genlist mi[MAXNOC];
     int z;
@@ -143,16 +142,14 @@ only_subs(struct emp_qelem *list)
 {
     struct emp_qelem *qp;
     struct genlist *glp;
-    struct genitem *gp;
     struct mchrstr *mcp;
 
     for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
        glp = (struct genlist *)qp;
-       gp = (struct genitem *)glp->thing;
 
-       if (glp->type != EF_SHIP)
+       if (glp->thing->ef_type != EF_SHIP)
            return 0;
-       mcp = (struct mchrstr *)glp->cp;
+       mcp = glp->cp;
        if (!(mcp->m_flags & M_SUB))
            return 0;
        /* It's a sub! */
@@ -164,13 +161,12 @@ only_subs(struct emp_qelem *list)
 
 /*
  *  Interdict ships & land units
- *
  */
 int
-unit_interdict(coord x, coord y, natid victim, s_char *s, int hardtarget,
+unit_interdict(coord x, coord y, natid victim, char *s, int hardtarget,
               int mission)
 {
-    register int cn;
+    int cn;
     int dam = 0, newdam;
     struct genlist mi[MAXNOC];
     int z;
@@ -201,15 +197,8 @@ unit_interdict(coord x, coord y, natid victim, s_char *s, int hardtarget,
        if (newdam) {
            /* If only subs responded, then we don't know who's
               subs they are */
-           if (osubs) {
-               mpr(victim,
-                   "Enemy interdiction mission does %d damage!\n",
-                   newdam);
-           } else {
-               mpr(victim,
-                   "%s interdiction mission does %d damage!\n",
-                   cname(cn), newdam);
-           }
+           mpr(victim, "%s interdiction mission does %d damage!\n",
+               osubs ? "Enemy" : cname(cn), newdam);
        }
     }
     if (dam) {
@@ -263,7 +252,7 @@ def_support(coord x, coord y, natid victim, natid actee)
 static int
 dosupport(struct genlist *mi, coord x, coord y, natid victim, natid actee)
 {
-    register int cn;
+    int cn;
     int rel;
     int dam = 0;
 
@@ -299,29 +288,16 @@ build_mission_list_type(struct genlist *mi, coord x, coord y, int mission,
 {
     struct nstr_item ni;
     struct genlist *glp;
-    struct genitem *gp;
-    union {
-       struct shpstr u_sp;
-       struct lndstr u_lp;
-       struct plnstr u_pp;
-    } u_block;
-    s_char *block;
-    int dist, size;
+    struct empobj *gp;
+    union empobj_storage item;
+    int dist;
     int radius;
     int relat;
     struct sctstr sect;
 
-/*
-        size = max(sizeof(struct shpstr),sizeof(struct lndstr));
-        size = max(size,sizeof(struct plnstr));
-        block = (s_char *)malloc(size);
- */
-    size = sizeof(u_block);
-    block = (s_char *)&u_block;
-
     snxtitem_all(&ni, type);
-    while (nxtitem(&ni, block)) {
-       gp = (struct genitem *)block;
+    while (nxtitem(&ni, &item)) {
+       gp = (struct empobj *)&item;
 
        if (gp->own == 0)
            continue;
@@ -349,7 +325,7 @@ build_mission_list_type(struct genlist *mi, coord x, coord y, int mission,
 
        radius = gp->radius;
        if (mission != MI_RESERVE)      /* XXX */
-           oprange(gp, type, &radius);
+           oprange(gp, &radius);
 
        if (dist > radius)
            continue;
@@ -358,14 +334,14 @@ build_mission_list_type(struct genlist *mi, coord x, coord y, int mission,
        /* Now check from where the object actually is */
        dist = mapdist(x, y, gp->x, gp->y);
        radius = 999;
-       oprange(gp, type, &radius);
+       oprange(gp, &radius);
        if (dist > radius)
            continue;
        /* Ok, the object can get to where the x,y is */
 
        if (opt_SLOW_WAR) {
            if (mission != MI_AIR_DEFENSE) {
-               getsect(x, y, (s_char *)&sect);
+               getsect(x, y, &sect);
                if (getrel(getnatp(gp->own), sect.sct_own) > AT_WAR) {
 
                    /*
@@ -382,24 +358,11 @@ build_mission_list_type(struct genlist *mi, coord x, coord y, int mission,
            }
        }
 
-       glp = (struct genlist *)malloc(sizeof(struct genlist));
+       glp = malloc(sizeof(struct genlist));
        memset(glp, 0, sizeof(struct genlist));
-       glp->x = gp->x;
-       glp->y = gp->y;
-       glp->type = type;
-       switch (type) {
-       case EF_LAND:
-           glp->cp = (s_char *)&lchr[(int)gp->type];
-           break;
-       case EF_SHIP:
-           glp->cp = (s_char *)&mchr[(int)gp->type];
-           break;
-       case EF_PLANE:
-           glp->cp = (s_char *)&plchr[(int)gp->type];
-           break;
-       }
-       glp->thing = (s_char *)malloc(size);
-       memcpy(glp->thing, block, size);
+       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);
     }
 }
@@ -413,7 +376,7 @@ find_escorts(coord x, coord y, natid cn, struct emp_qelem *escorts)
     int dist;
 
     snxtitem_all(&ni, EF_PLANE);
-    while (nxtitem(&ni, (s_char *)&plane)) {
+    while (nxtitem(&ni, &plane)) {
        if (plane.pln_own != cn)
            continue;
 
@@ -421,11 +384,10 @@ find_escorts(coord x, coord y, natid cn, struct emp_qelem *escorts)
            continue;
 
        dist = mapdist(x, y, plane.pln_x, plane.pln_y);
-
-       if (dist > ((int)((float)plane.pln_range / 2.0)))
+       if (dist > plane.pln_range / 2)
            continue;
 
-       plp = (struct plist *)malloc(sizeof(struct plist));
+       plp = malloc(sizeof(struct plist));
        memset(plp, 0, sizeof(struct plist));
        plp->pcp = &plchr[(int)plane.pln_type];
        plp->plane = plane;
@@ -435,23 +397,22 @@ find_escorts(coord x, coord y, natid cn, struct emp_qelem *escorts)
 
 static int
 perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
-               int mission, s_char *s, int hardtarget)
+               int mission, char *s, int hardtarget)
 {
     struct emp_qelem *qp, missiles, bombers, escorts, airp, b, e;
     struct emp_qelem *newqp;
     struct genlist *glp;
     struct plist *plp;
-    struct genitem *gp;
+    struct empobj *gp;
     struct lndstr *lp;
     struct shpstr *sp;
     struct sctstr sect;
-    struct lchrstr *lcp;
     struct mchrstr *mcp;
     struct plchrstr *pcp;
     int dam = 0, dam2, mission_flags, tech;
     natid plane_owner = 0;
-    int gun, shell, md, air_dam = 0;
-    double range2, prb, range, mobcost, hitchance;
+    int gun, shell, md, range, air_dam = 0;
+    double prb, hitchance, vrange;
 
     getsect(x, y, &sect);
 
@@ -462,13 +423,12 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
 
     for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
        glp = (struct genlist *)qp;
-       gp = (struct genitem *)glp->thing;
+       gp = glp->thing;
 
        md = mapdist(x, y, gp->x, gp->y);
 
-       if (glp->type == EF_LAND) {
+       if (glp->thing->ef_type == EF_LAND) {
            lp = (struct lndstr *)glp->thing;
-           lcp = (struct lchrstr *)glp->cp;
 
            if (lp->lnd_effic < LAND_MINFIREEFF)
                continue;
@@ -480,16 +440,14 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
                (md > land_max_interdiction_range))
                continue;
 
-           if (md > (lp->lnd_frg / 2))
+           if ((lp->lnd_ship != -1) || (lp->lnd_land != -1))
                continue;
 
-           if (lnd_getmil(lp) < 1)
+           if (lp->lnd_item[I_MILIT] < 1)
                continue;
 
-           range = techfact((int)lp->lnd_tech, (double)lp->lnd_frg / 2.0);
-           range2 = (double)roundrange(range);
-
-           if (md > range2)
+           range = roundrange(effrange(lp->lnd_frg, lp->lnd_tech));
+           if (md > range)
                continue;
 
            shell = lp->lnd_item[I_SHELL];
@@ -503,9 +461,8 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
                dam2 = ldround(landunitgun(lp->lnd_effic, lp->lnd_dam, gun,
                                           lp->lnd_ammo, shell), 1);
                if (sect.sct_type == SCT_WATER) {
-                   double dam3 = (double)dam2;
-                   if (chance(((double)lp->lnd_acc) / 100.0))
-                       dam2 = ldround((dam3 / 2.0), 1);
+                   if (chance(lp->lnd_acc / 100.0))
+                       dam2 = ldround(dam2 / 2.0, 1);
                }
                dam += dam2;
                if (sect.sct_type == SCT_WATER)
@@ -519,9 +476,9 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
                mpr(victim, "%s %s fires at you at %s\n",
                    cname(lp->lnd_own), prland(lp), xyas(x, y, victim));
            }
-       } else if (glp->type == EF_SHIP) {
+       } else if (glp->thing->ef_type == EF_SHIP) {
            sp = (struct shpstr *)glp->thing;
-           mcp = (struct mchrstr *)glp->cp;
+           mcp = glp->cp;
 
            if (sp->shp_effic < 60)
                continue;
@@ -543,9 +500,9 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
                    continue;
                if (!(mcp->m_flags & M_DCH) && !(mcp->m_flags & M_SUBT))
                    continue;
-               range2 = techfact(sp->shp_tech, (double)mcp->m_vrnge);
-               range2 *= (double)sp->shp_effic / 200.0;
-               if (md > range2)
+               vrange = techfact(sp->shp_tech, mcp->m_vrnge);
+               vrange *= sp->shp_effic / 200.0;
+               if (md > vrange)
                    continue;
                /* can't look all the time */
                if (chance(0.5))
@@ -556,34 +513,27 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
    a sub. */
                if (*s != 's')
                    continue;
-               if (sp->shp_mobil < (s_char)0)
+               if (sp->shp_mobil < 0)
                    continue;
                gun = sp->shp_item[I_GUN];
                if (gun < 1)
                    continue;
                shell = sp->shp_item[I_SHELL];
-               if (shell < M_TORP_SHELLS)
+               if (shell < SHP_TORP_SHELLS)
                    shell += supply_commod(sp->shp_own,
                                           sp->shp_x, sp->shp_y, I_SHELL,
-                                          M_TORP_SHELLS - shell);
-               if (shell < M_TORP_SHELLS)
+                                          SHP_TORP_SHELLS - shell);
+               if (shell < SHP_TORP_SHELLS)
                    continue;
 
-               range = sp->shp_effic * techfact(sp->shp_tech,
-                                                ((double)sp->shp_frnge)) /
-                   100.0;
-
-               range2 = (double)roundrange(range);
+               range = roundrange(torprange(sp));
                if (md > range)
                    continue;
 
-               if (!line_of_sight((s_char **)0, x, y, gp->x, gp->y))
+               if (!line_of_sight(NULL, x, y, gp->x, gp->y))
                    continue;
-               sp->shp_item[I_SHELL] = shell - M_TORP_SHELLS;
-               mobcost = sp->shp_effic * 0.01 * sp->shp_speed;
-               mobcost = (480.0 / (mobcost +
-                                   techfact(sp->shp_tech, mobcost)));
-               sp->shp_mobil -= mobcost;
+               sp->shp_item[I_SHELL] = shell - SHP_TORP_SHELLS;
+               sp->shp_mobil -= shp_mobcost(sp) / 2.0;
                putship(sp->shp_uid, sp);
                hitchance = DTORP_HITCHANCE(md, sp->shp_visib);
 
@@ -591,7 +541,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
                   "%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 %.1f\n", range);
+                  "\tEffective torpedo range is %d.0\n", range);
                wu(0, sp->shp_own,
                   "\tWhooosh... Hitchance = %d%%\n",
                   (int)(hitchance * 100));
@@ -607,7 +557,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
                dam2 = TORP_DAMAGE();
 
                dam += dam2;
-               nreport(victim, N_TORP_SHIP, sp->shp_own, 1);
+               nreport(victim, N_TORP_SHIP, 0, 1);
                wu(0, sp->shp_own,
                   "\tTorpedo hit %s %s for %d damage\n",
                   cname(victim), s, dam2);
@@ -616,30 +566,29 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
                    "Incoming torpedo sighted @ %s hits and does %d damage!\n",
                    xyas(x, y, victim), dam2);
            } else {
-               range = techfact(sp->shp_tech, (double)mcp->m_frnge / 2.0);
-               range2 = (double)roundrange(range);
-               if (md > range2)
+               range = roundrange(effrange(sp->shp_frnge, sp->shp_tech));
+               if (md > range)
                    continue;
                gun = sp->shp_item[I_GUN];
-               gun = min(gun, sp->shp_glim);
+               gun = MIN(gun, sp->shp_glim);
                shell = sp->shp_item[I_SHELL];
                if (shell < gun)
                    shell += supply_commod(sp->shp_own,
                                           sp->shp_x, sp->shp_y, I_SHELL,
                                           gun - shell);
-               gun = min(gun, shell);
-               gun = min(gun, sp->shp_item[I_MILIT] / 2.0);
+               gun = MIN(gun, shell);
+               gun = MIN(gun, sp->shp_item[I_MILIT] / 2.0);
                if (gun == 0)
                    continue;
-               gun = max(gun, 1);
+               gun = MAX(gun, 1);
                dam2 = seagun(sp->shp_effic, gun);
-               if (range2 == 0.0)
+               if (range == 0.0)
                    prb = 1.0;
                else
-                   prb = ((double)md) / range2;
+                   prb = (double)md / range;
                prb *= prb;
                if (chance(prb))
-                   dam2 = (int)((float)dam2 / 2.0);
+                   dam2 /= 2;
                dam += dam2;
                if (sect.sct_type == SCT_WATER)
                    nreport(sp->shp_own, N_SHP_SHELL, victim, 1);
@@ -655,15 +604,15 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
                sp->shp_item[I_SHELL] = shell - gun;
                putship(sp->shp_uid, sp);
            }
-       } else if (glp->type == EF_PLANE) {
-           pcp = (struct plchrstr *)glp->cp;
+       } else if (glp->thing->ef_type == EF_PLANE) {
+           pcp = glp->cp;
            if (pcp->pl_flags & P_M)
                /* units have their own missile interdiction */
                if (hardtarget != SECT_HARDTARGET || pcp->pl_flags & P_MAR)
                    continue;
 
            /* save planes for later */
-           plp = (struct plist *)malloc(sizeof(struct plist));
+           plp = malloc(sizeof(struct plist));
 
            memset(plp, 0, sizeof(struct plist));
            plp->pcp = pcp;
@@ -696,7 +645,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
            qp = qp->q_forw;
 
            free(glp->thing);
-           free((s_char *)glp);
+           free(glp);
        }
        return dam;
     }
@@ -723,7 +672,8 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
 
     for (qp = airp.q_forw; qp != (&airp); qp = qp->q_forw) {
        struct airport *air;
-       s_char pp[512];
+       char buf[512];
+       char *pp;
 
        air = (struct airport *)qp;
        md = mapdist(x, y, air->x, air->y);
@@ -745,14 +695,15 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
        mission_flags = mission_pln_arm(&b, air->x, air->y, 2 * md, 'p', 0,
                                        0, mission_flags, &tech);
 
-       if (QEMPTY(&b)) {
+       if (QEMPTY(&b))
            continue;
-       }
 
        mission_flags = mission_pln_arm(&e, air->x, air->y, 2 * md, 'p', 0,
                                        P_F | P_ESC, mission_flags, &tech);
 
-       BestAirPath(pp, air->x, air->y, x, y);
+       pp = BestAirPath(buf, air->x, air->y, x, y);
+       if (CANT_HAPPEN(!pp))
+           continue;
        wu(0, plane_owner, "Flying %s mission from %s\n",
           mission_name(mission), xyas(air->x, air->y, plane_owner));
        if (air->own && (air->own != plane_owner)) {
@@ -786,14 +737,14 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
        qp = qp->q_forw;
 
        free(glp->thing);
-       free((s_char *)glp);
+       free(glp);
     }
 
     qp = escorts.q_forw;
     while (qp != (&escorts)) {
        newqp = qp->q_forw;
        emp_remque(qp);
-       free((s_char *)qp);
+       free(qp);
        qp = newqp;
     }
 
@@ -801,7 +752,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
     while (qp != (&bombers)) {
        newqp = qp->q_forw;
        emp_remque(qp);
-       free((s_char *)qp);
+       free(qp);
        qp = newqp;
     }
 
@@ -841,47 +792,8 @@ cando(int mission, int type)
     return 0;
 }
 
-s_char *
-nameofitem(struct genitem *gp, int type)
-{
-    switch (type) {
-    case EF_SHIP:
-       return prship((struct shpstr *)gp);
-    case EF_PLANE:
-       return prplane((struct plnstr *)gp);
-    case EF_LAND:
-       return prland((struct lndstr *)gp);
-    }
-    return NULL;
-}
-
-s_char *
-mission_short_name(int mission)
-{
-    switch (mission) {
-    case MI_INTERDICT:
-       return "interdict";
-    case MI_SUPPORT:
-       return "support  ";
-    case MI_OSUPPORT:
-       return "offensive";
-    case MI_DSUPPORT:
-       return "defensive";
-    case MI_RESERVE:
-       return "reserve  ";
-    case MI_ESCORT:
-       return "escort   ";
-    case MI_SINTERDICT:
-       return "interdict";
-    case MI_AIR_DEFENSE:
-       return "air def  ";
-    default:
-       return "         ";
-    }
-}
-
-s_char *
-mission_name(short int mission)
+char *
+mission_name(short mission)
 {
     switch (mission) {
     case MI_INTERDICT:
@@ -907,16 +819,12 @@ mission_name(short int mission)
 void
 show_mission(int type, struct nstr_item *np)
 {
-    int size, first = 1, radius;
-    s_char *block;
-    struct genitem *gp;
-
-    size = max(sizeof(struct lndstr), sizeof(struct plnstr));
-    size = max(size, sizeof(struct shpstr));
-    block = (s_char *)malloc(size);
+    int first = 1, radius;
+    union empobj_storage item;
+    struct empobj *gp;
 
-    while (nxtitem(np, block)) {
-       gp = (struct genitem *)block;
+    while (nxtitem(np, &item)) {
+       gp = (struct empobj *)&item;
        if (!player->owner || gp->own == 0)
            continue;
 
@@ -924,14 +832,14 @@ show_mission(int type, struct nstr_item *np)
            pr("Thing                         x,y   op-sect rad mission\n");
            first = 0;
        }
-       pr("%-25s", nameofitem(gp, type));
-       pr(" %7s", xyas(gp->x, gp->y, player->cnum));
+       pr("%-25s", obj_nameof(gp));
+       prxy(" %3d,%-3d", gp->x, gp->y, player->cnum);
        if (gp->mission == MI_INTERDICT || gp->mission == MI_SUPPORT ||
            gp->mission == MI_OSUPPORT ||
            gp->mission == MI_DSUPPORT || gp->mission == MI_AIR_DEFENSE) {
            radius = 999;
-           oprange(gp, type, &radius);
-           pr(" %7s", xyas(gp->opx, gp->opy, player->cnum));
+           oprange(gp, &radius);
+           prxy(" %3d,%-3d", gp->opx, gp->opy, player->cnum);
            if (radius < gp->radius)
                pr("  %4d", radius);
            else
@@ -944,17 +852,15 @@ show_mission(int type, struct nstr_item *np)
            if ((sect.sct_type == SCT_HEADQ) && (sect.sct_effic >= 60))
                plus++;
 
-           if (((struct lndstr *)block)->lnd_rad_max == 0)
+           if (item.land.lnd_rad_max == 0)
                plus = 0;
            else
-               plus += ((struct lndstr *)block)->lnd_rad_max;
-           pr(" %7s", xyas(gp->x, gp->y, player->cnum));
+               plus += item.land.lnd_rad_max;
+           prxy(" %3d,%-3d", gp->x, gp->y, player->cnum);
            pr("  %4d", plus);
        } else if (gp->mission == MI_ESCORT) {
            pr("        ");
-           pr("  %4d", (int)
-              ((float)((struct plnstr *)block)->pln_range / 2.0)
-               );
+           pr("  %4d", item.plane.pln_range / 2);
        } else
            pr("              ");
        if (gp->mission)
@@ -965,35 +871,32 @@ show_mission(int type, struct nstr_item *np)
 }
 
 int
-oprange(struct genitem *gp, int type, int *radius)
+oprange(struct empobj *gp, int *radius)
 {
     int range;
-    struct shpstr ship;
-    struct lndstr land;
-    struct plnstr plane;
 
-    switch (type) {
+    switch (gp->ef_type) {
     case EF_SHIP:
-       getship(gp->uid, &ship);
-       range = ldround(techfact(gp->tech,
-                                (double)ship.shp_frnge / 2.0), 1);
+       range = ldround(effrange(((struct shpstr *)gp)->shp_frnge,
+                                ((struct shpstr *)gp)->shp_tech), 1);
        break;
     case EF_LAND:
-       getland(gp->uid, &land);
-       range = ldround(techfact((int)land.lnd_tech,
-                                (double)land.lnd_frg / 2.0), 1);
+       range = ldround(effrange(((struct lndstr *)gp)->lnd_frg,
+                                ((struct lndstr *)gp)->lnd_tech), 1);
        break;
     case EF_PLANE:
-       getplane(gp->uid, &plane);
        /* missiles go one way, so we can use all the range */
-       if (plchr[(int)plane.pln_type].pl_flags & P_M)
-           range = plane.pln_range;
+       if (plchr[(int)gp->type].pl_flags & P_M)
+           range = ((struct plnstr *)gp)->pln_range;
        else
-           range = ldround((double)plane.pln_range / 2.0, 1);;
+           range = ((struct plnstr *)gp)->pln_range / 2;
        break;
+    default:
+       CANT_HAPPEN("bad TYPE");
+       range = -1;
     }
 
-    if ((*radius) > range)
+    if (*radius > range)
        *radius = range;
 
     return range;
@@ -1014,8 +917,8 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
     struct sctstr sect;
     struct plchrstr *pcp;
     struct plist *plp;
-    register int y, bad, bad1;
-    unsigned int x;
+    int y, bad, bad1;
+    unsigned x;
 
     for (qp = list->q_forw; qp != list; qp = next) {
        next = qp->q_forw;
@@ -1025,20 +928,20 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
 
        if (pp->pln_effic < 40) {
            emp_remque(qp);
-           free((s_char *)qp);
+           free(qp);
            continue;
        }
 
        if (pp->pln_mobil < 1) {
            emp_remque(qp);
-           free((s_char *)qp);
+           free(qp);
            continue;
        }
 
        if (opt_MARKET) {
-           if (ontradingblock(EF_PLANE, (int *)pp)) {
+           if (ontradingblock(EF_PLANE, pp)) {
                emp_remque(qp);
-               free((s_char *)qp);
+               free(qp);
                continue;
            }
        }
@@ -1067,7 +970,7 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
            }
            if (bad) {
                emp_remque(qp);
-               free((s_char *)qp);
+               free(qp);
                continue;
            }
            if (bad1 == 2) {
@@ -1081,7 +984,7 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
            }
            if (bad1) {
                emp_remque(qp);
-               free((s_char *)qp);
+               free(qp);
                continue;
            }
        }
@@ -1096,7 +999,7 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
            }
            if (bad) {
                emp_remque(qp);
-               free((s_char *)qp);
+               free(qp);
                continue;
            }
        }
@@ -1106,7 +1009,7 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
                pp->pln_effic = 0;
                putplane(pp->pln_uid, pp);
                emp_remque(qp);
-               free((s_char *)qp);
+               free(qp);
                continue;
            }
            if (!can_be_on_ship(pp->pln_uid, ship.shp_uid)) {
@@ -1115,12 +1018,12 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
            if (ship.shp_effic < SHIP_MINEFF) {
                goto shipsunk;
            }
-           /* Can't fly off of ships < 50%, or non-owned or non-allied ships */
-           if ((ship.shp_effic < 50) ||
+           /* Can't fly off of inefficient or non-owned, non-allied ships */
+           if ((ship.shp_effic < SHP_AIROPS_EFF) ||
                ((ship.shp_own != pp->pln_own) &&
                 (getrel(getnatp(ship.shp_own), pp->pln_own) != ALLIED))) {
                emp_remque(qp);
-               free((s_char *)qp);
+               free(qp);
                continue;
            }
        }
@@ -1130,7 +1033,7 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
                pp->pln_effic = 0;
                putplane(pp->pln_uid, pp);
                emp_remque(qp);
-               free((s_char *)qp);
+               free(qp);
                continue;
            }
            if (!(pcp->pl_flags & P_E))
@@ -1138,19 +1041,19 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
            if (land.lnd_effic < LAND_MINEFF)
                goto landdead;
 
-           /* Can't fly off of units < 50%, or non-owned or non-allied units */
-           if ((land.lnd_effic < 50) ||
+           /* Can't fly off of inefficient or non-owned, non-allied units */
+           if ((land.lnd_effic < LND_AIROPS_EFF) ||
                ((land.lnd_own != pp->pln_own) &&
                 (getrel(getnatp(land.lnd_own), pp->pln_own) != ALLIED))) {
                emp_remque(qp);
-               free((s_char *)qp);
+               free(qp);
                continue;
            }
 
            /* Can't fly off units in ships or other units */
            if ((land.lnd_ship >= 0) || (land.lnd_land >= 0)) {
                emp_remque(qp);
-               free((s_char *)qp);
+               free(qp);
                continue;
            }
        }
@@ -1159,7 +1062,7 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
            /* If we can't get the sector, we can't check it, and can't fly */
            if (!getsect(pp->pln_x, pp->pln_y, &sect)) {
                emp_remque(qp);
-               free((s_char *)qp);
+               free(qp);
                continue;
            }
            /* First, check allied status */
@@ -1167,14 +1070,14 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
            if ((sect.sct_own != pp->pln_own) &&
                (getrel(getnatp(sect.sct_own), pp->pln_own) != ALLIED)) {
                emp_remque(qp);
-               free((s_char *)qp);
+               free(qp);
                continue;
            }
            /* non-vtol plane */
            if ((pcp->pl_flags & P_V) == 0) {
                if ((sect.sct_type != SCT_AIRPT) || (sect.sct_effic < 40)) {
                    emp_remque(qp);
-                   free((s_char *)qp);
+                   free(qp);
                    continue;
                }
            }
@@ -1182,7 +1085,7 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
        if (pcp->pl_flags & P_A) {
            if (roll(100) > pln_identchance(pp, hardtarget, EF_SHIP)) {
                emp_remque(qp);
-               free((s_char *)qp);
+               free(qp);
                continue;
            }
        }
@@ -1193,7 +1096,6 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
 
 /*
  * Arm only the planes at x,y
- *
  */
 static int
 mission_pln_arm(struct emp_qelem *list, coord x, coord y, int dist,
@@ -1217,7 +1119,7 @@ mission_pln_arm(struct emp_qelem *list, coord x, coord y, int dist,
 
        if (mission_pln_equip(plp, ip, flags, mission) < 0) {
            emp_remque(qp);
-           free((s_char *)qp);
+           free(qp);
            continue;
        }
        if (flags & (P_S | P_I)) {
@@ -1256,15 +1158,15 @@ mission_pln_arm(struct emp_qelem *list, coord x, coord y, int dist,
 
 int
 mission_pln_equip(struct plist *plp, struct ichrstr *ip, int flags,
-                 s_char mission)
+                 char mission)
 {
-    register struct plchrstr *pcp;
+    struct plchrstr *pcp;
     struct plnstr *pp;
     int needed;
     struct lndstr land;
     struct shpstr ship;
     struct sctstr sect;
-    int itype;
+    i_type itype;
     int rval;
     short *item;
 
@@ -1286,7 +1188,7 @@ mission_pln_equip(struct plist *plp, struct ichrstr *ip, int flags,
     item[I_PETROL] -= pcp->pl_fuel;
     rval = 0;
     if (!(flags & P_F)) {
-       itype = 0;
+       itype = I_NONE;
        needed = 0;
        switch (mission) {
        case 's':
@@ -1299,13 +1201,13 @@ mission_pln_equip(struct plist *plp, struct ichrstr *ip, int flags,
        case 't':
            if ((pcp->pl_flags & P_C) == 0 || ip == 0)
                break;
-           itype = ip->i_vtype;
+           itype = ip->i_uid;
            needed = (pp->pln_load * 2) / ip->i_lbs;
            break;
        case 'd':
            if ((pcp->pl_flags & P_C) == 0 || ip == 0)
                break;
-           itype = ip->i_vtype;
+           itype = ip->i_uid;
            needed = (pp->pln_load * 2) / ip->i_lbs;
            break;
        case 'a':
@@ -1327,16 +1229,17 @@ mission_pln_equip(struct plist *plp, struct ichrstr *ip, int flags,
        default:
            break;
        }
-       if (rval < 0 || (itype && needed <= 0)) {
+       if (rval < 0 || (itype != I_NONE && needed <= 0)) {
            return -1;
        }
-       if (item[itype] < needed && (itype == I_SHELL))
-           item[itype] += supply_commod(plp->plane.pln_own,
-                                        plp->plane.pln_x, plp->plane.pln_y,
-                                        I_SHELL, needed);
-       if (item[itype] < needed) {
-           return -1;
-       } else {
+       if (itype != I_NONE) {
+           if (itype == I_SHELL && item[itype] < needed)
+               item[itype] += supply_commod(plp->plane.pln_own,
+                                            plp->plane.pln_x,
+                                            plp->plane.pln_y,
+                                            I_SHELL, needed);
+           if (item[itype] < needed)
+               return -1;
            item[itype] -= needed;
        }
        if (itype == I_SHELL && (mission == 's' || mission == 'p'))
@@ -1378,7 +1281,7 @@ add_airport(struct emp_qelem *airp, coord x, coord y)
     struct airport *a;
     struct sctstr sect;
 
-    a = (struct airport *)malloc(sizeof(struct airport));
+    a = malloc(sizeof(struct airport));
 
     a->x = x;
     a->y = y;
@@ -1414,7 +1317,7 @@ divide(struct emp_qelem *l1, struct emp_qelem *l2, coord x, coord y)
 
 static int
 air_damage(struct emp_qelem *bombers, coord x, coord y, int mission,
-          natid victim, s_char *s, int hardtarget)
+          natid victim, char *s, int hardtarget)
 {
     struct emp_qelem *qp;
     struct plist *plp;
@@ -1484,8 +1387,7 @@ air_damage(struct emp_qelem *bombers, coord x, coord y, int mission,
                    "RUMBLE... your sub in %s hears a depth-charge explode nearby\n",
                    xyas(x, y, victim));
            } else if (*s == 's') {
-               mpr(victim,
-                   "SPLASH!  Bombs miss your %s in %s\n",
+               mpr(victim, "SPLASH!  Bombs miss your %s in %s\n",
                    s, xyas(x, y, victim));
            } else {
                mpr(victim, "SPLAT!  Bombs miss your %s in %s\n",
@@ -1497,11 +1399,8 @@ air_damage(struct emp_qelem *bombers, coord x, coord y, int mission,
        }
 
        /* use up missiles */
-       if (plp->pcp->pl_flags & P_M) {
-           makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x,
-                    pp->pln_y);
-           pp->pln_own = 0;
-       }
+       if (plp->pcp->pl_flags & P_M)
+           pp->pln_effic = 0;
     }
 
     return dam;
@@ -1521,9 +1420,10 @@ air_defense(coord x, coord y, natid victim, struct emp_qelem *bomb_list,
     struct emp_qelem *qp, interceptors, airp, i, empty, *next;
     struct plist *plp;
     struct genlist *glp;
-    struct genitem *gp;
+    struct empobj *gp;
     struct genlist mi[MAXNOC];
-    s_char path[512];
+    char buf[512];
+    char *path;
     int count;
     int tcount;
 
@@ -1554,16 +1454,14 @@ air_defense(coord x, coord y, natid victim, struct emp_qelem *bomb_list,
        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 = (struct genitem *)glp->thing;
-           plp = (struct plist *)qp;
+           gp = glp->thing;
 
            dist = mapdist(x, y, gp->x, gp->y);
 
-           plp = (struct plist *)malloc(sizeof(struct plist));
+           plp = malloc(sizeof(struct plist));
            memset(plp, 0, sizeof(struct plist));
-           plp->pcp = (struct plchrstr *)glp->cp;
+           plp->pcp = glp->cp;
            memcpy(&plp->plane, glp->thing, sizeof(struct plnstr));
 
            /* missiles go one way, so we can use all the range */
@@ -1590,7 +1488,7 @@ air_defense(coord x, coord y, natid victim, struct emp_qelem *bomb_list,
        for (qp = interceptors.q_forw; qp != (&interceptors);
             qp = qp->q_forw)
            tcount++;
-       tcount -= (count * 2);
+       tcount -= count * 2;
        /* Just in case there are more incoming than we have */
        if (tcount < 0)
            tcount = 0;
@@ -1601,7 +1499,7 @@ air_defense(coord x, coord y, natid victim, struct emp_qelem *bomb_list,
                /* Free it up and continue */
                emp_remque(qp);
                glp = (struct genlist *)qp;
-               free((s_char *)glp);
+               free(glp);
            }
        }
 
@@ -1659,7 +1557,9 @@ air_defense(coord x, coord y, natid victim, struct emp_qelem *bomb_list,
                continue;
            }
 
-           BestAirPath(path, air->x, air->y, x, y);
+           path = BestAirPath(buf, air->x, air->y, x, y);
+           if (CANT_HAPPEN(!path))
+               continue;
            wu(0, cn, "Flying %s mission from %s\n",
               mission_name(MI_AIR_DEFENSE), xyas(air->x, air->y, cn));
            if (air->own && (air->own != cn)) {
@@ -1684,7 +1584,7 @@ air_defense(coord x, coord y, natid victim, struct emp_qelem *bomb_list,
                mpr(victim, "%s air defense planes intercept!\n",
                    cname(cn));
                ac_combat_headers(victim, cn);
-               ac_airtoair(esc_list, &i, air->own);
+               ac_airtoair(esc_list, &i);
                combat = 1;
            }
            /* Now intercept the bombers */
@@ -1694,7 +1594,7 @@ air_defense(coord x, coord y, natid victim, struct emp_qelem *bomb_list,
                        cname(cn));
                    ac_combat_headers(victim, cn);
                }
-               ac_airtoair(bomb_list, &i, air->own);
+               ac_airtoair(bomb_list, &i);
                PR(cn, "\n");
                PR(victim, "\n");
            }
@@ -1711,7 +1611,7 @@ air_defense(coord x, coord y, natid victim, struct emp_qelem *bomb_list,
            next = qp->q_forw;
            glp = (struct genlist *)qp;
            free(glp->thing);
-           free((s_char *)glp);
+           free(glp);
        }
     }