]> git.pond.sub.org Git - empserver/blobdiff - src/lib/commands/load.c
Update copyright notice
[empserver] / src / lib / commands / load.c
index 17b31bd534f59cc6bb0187c021687ba1a97fc0f7..fb32f5b6dabd3b86414e24fa6d939d346beb2e5d 100644 (file)
@@ -1,11 +1,11 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
- *                           Ken Stevens, Steve McClure
+ *  Copyright (C) 1986-2014, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *                Ken Stevens, Steve McClure, Markus Armbruster
  *
- *  This program is free software; you can redistribute it and/or modify
+ *  Empire is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
+ *  the Free Software Foundation, either version 3 of the License, or
  *  (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  *  ---
  *
- *  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.
  *
  *  ---
  *
  *  load.c: load/unload goods from a sector onto a ship or land unit
- * 
+ *
  *  Known contributors to this file:
  *     David Sharnoff, 1987
  *     Ken Stevens, 1995 (rewritten)
  *     Steve McClure, 1998-2000
+ *     Markus Armbruster, 2004-2013
  */
 
-#ifdef Rel4
-#include <string.h>
-#endif /* Rel4 */
-#include "misc.h"
-#include "player.h"
-#include "xy.h"
-#include "file.h"
-#include "var.h"
-#include "sect.h"
-#include "ship.h"
-#include "plane.h"     
-#include "land.h"      
+#include <config.h>
+
+#include <ctype.h>
+#include "commands.h"
 #include "item.h"
-#include "nsc.h"
-#include "nat.h"
+#include "land.h"
 #include "optlist.h"
-#include "commands.h"
+#include "plague.h"
+#include "plane.h"
+#include "ship.h"
+#include "unit.h"
 
 /*
  * The values 1 and -1 are important below, don't change them.
  */
-#define        LOAD    1
-#define        UNLOAD  -1
-
-void gift(int givee, int giver, s_char *ptr, int type, s_char *mesg);
-static int load_plane_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unload, int *nshipsp);
-static int load_land_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unload, int *nshipsp);
-static int load_comm_ship(struct sctstr *sectp, struct shpstr *sp, struct ichrstr *ich, int load_unload, int *nshipsp);
-static int load_plane_land(struct sctstr *sectp, struct lndstr *lp, int noisy, int load_unload, int *nunitsp);
-static int load_land_land(struct sctstr *sectp, struct lndstr *lp, int noisy, int load_unload, int *nunitsp);
-static int load_comm_land(struct sctstr *sectp, struct lndstr *lp, struct ichrstr *ich, int load_unload, int *nunitsp);
+#define LOAD   1
+#define UNLOAD -1
+
+static int load_plane_ship(struct sctstr *sectp, struct shpstr *sp,
+                          int noisy, int load_unload, int *nshipsp);
+static int load_land_ship(struct sctstr *sectp, struct shpstr *sp,
+                         int noisy, int load_unload, int *nshipsp);
+static int load_comm_ship(struct sctstr *sectp, struct shpstr *sp,
+                         struct ichrstr *ich, int load_unload,
+                         int *nshipsp);
+static int load_plane_land(struct sctstr *sectp, struct lndstr *lp,
+                          int noisy, int load_unload, int *nunitsp);
+static int load_land_land(struct sctstr *sectp, struct lndstr *lp,
+                         int noisy, int load_unload, int *nunitsp);
+static int load_comm_land(struct sctstr *sectp, struct lndstr *lp,
+                         struct ichrstr *ich, int load_unload,
+                         int *nunitsp);
 
 int
 load(void)
 {
-       int     noisy;
-       int     load_unload;
-       int     type;
-       struct  nstr_item nbst;
-       struct  ichrstr *ich;
-       int     nships;
-       struct  sctstr sect;
-       struct  shpstr ship;
-       int     retval;
-       s_char  *p;
-       s_char  buf[1024];
-
-       if (!(p = getstarg(player->argp[1],
-               "What commodity (or 'plane' or 'land')? ", buf)) || !*p)
-               return RET_SYN;
-       
-       if (!strncmp(p, "plane", 5))
-               type = EF_PLANE;
-       else if (!strncmp(p, "land", 4))
-               type = EF_LAND;
-       else if (NULL != (ich = whatitem(p, (s_char *)0)))
-               type = EF_SECTOR;
-       else {
-               pr("Bad commodity.\n");
-               return RET_SYN;
-       }
+    int noisy;
+    int load_unload;
+    int type;
+    struct nstr_item nbst;
+    struct ichrstr *ich;
+    int nships;
+    struct sctstr sect;
+    struct shpstr ship;
+    int retval;
+    char *p;
+    char buf[1024];
+
+    p = getstarg(player->argp[1],
+                "What commodity (or 'plane' or 'land')? ", buf);
+    if (!p || !*p)
+       return RET_SYN;
 
-       if (!(p = getstarg(player->argp[2], "Ship(s): ", buf)) || !*p)
-               return RET_SYN;
+    if (!strncmp(p, "plane", 5))
+       type = EF_PLANE;
+    else if (!strncmp(p, "land", 4))
+       type = EF_LAND;
+    else if (NULL != (ich = item_by_name(p)))
+       type = EF_SECTOR;
+    else {
+       pr("Can't load '%s'\n", p);
+       return RET_SYN;
+    }
 
-       noisy = isdigit(*p);
+    p = getstarg(player->argp[2], "Ship(s): ", buf);
+    if (!p || !*p)
+       return RET_SYN;
 
-       if (!snxtitem(&nbst, EF_SHIP, p))
-               return RET_SYN;
+    noisy = isdigit(*p);
 
-       nbst.flags &= ~(EFF_OWNER);
+    if (!snxtitem(&nbst, EF_SHIP, p, NULL))
+       return RET_SYN;
 
-       load_unload = **player->argp == 'l' ? LOAD : UNLOAD;
+    load_unload = **player->argp == 'l' ? LOAD : UNLOAD;
 
-       nships = 0;
-       while (nxtitem(&nbst, (s_char *)&ship)) {
-               if (!ship.shp_own)
-                       continue;
-               if (!player->owner && (load_unload == UNLOAD)) {
-                       continue;
-               }
-               if (opt_MARKET) {
-                   if (ontradingblock(EF_SHIP, (int *)&ship)) {
-                       pr("You cannot load/unload an item on the trading block!\n");
-                       continue;
-                   }
-               }
+    nships = 0;
+    while (nxtitem(&nbst, &ship)) {
+       if (!ship.shp_own)
+           continue;
+       if (!player->owner) {
+           if (load_unload == UNLOAD || !noisy)
+               continue;
+           if (relations_with(ship.shp_own, player->cnum) < FRIENDLY)
+               continue;
+       }
 
-               if (ship.shp_own != player->cnum) {
-                       if (!noisy)
-                               continue;
-                       if (getrel(getnatp(player->cnum),ship.shp_own) < FRIENDLY)
-                               continue;
-               }
-               if (!getsect(ship.shp_x, ship.shp_y, &sect)) /* XXX */
-                       continue;
-               if ((sect.sct_own != player->cnum) &&
-                   (ship.shp_own != player->cnum))
-                       continue;
-               if (!player->owner &&
-                   sect.sct_type != SCT_HARBR &&
-                   (!opt_BIG_CITY || sect.sct_type != SCT_CAPIT))
-                       continue;
-               if (!sect.sct_own)
-                       continue;
-               if ((sect.sct_own != player->cnum) && (load_unload == LOAD)) {
-                       if (noisy)
-                       pr("You don't own %s \n",
-                               xyas(ship.shp_x, ship.shp_y, player->cnum));
-                       continue;
-               }
-               if (sect.sct_type != SCT_HARBR &&
-                   (!opt_BIG_CITY || sect.sct_type != SCT_CAPIT)) {
-                       if (noisy)
-                       pr("Sector %s is not a harbor%s.\n",
-                          xyas(ship.shp_x, ship.shp_y, player->cnum),
-                          opt_BIG_CITY?" or a city":"");
-                       continue;
-               }
-               if (sect.sct_own != player->cnum && load_unload == UNLOAD && getrel(getnatp(sect.sct_own), player->cnum) < FRIENDLY) {
-                       if (noisy)
-                       pr("You can't unload into an unfriendly %s\n",
-                          dchr[sect.sct_type].d_name);
-                       continue;
-               }
-               if (sect.sct_effic < 2) {
-                       if (noisy)
-                       pr("The %s at %s is not 2%% efficient yet.\n",
-                          dchr[sect.sct_type].d_name,
-                          xyas(ship.shp_x, ship.shp_y, player->cnum));
-                       continue;
-               }
-               switch (type) {
-               case EF_PLANE:
-                       if (0 != (retval=load_plane_ship(&sect, &ship, noisy, load_unload, &nships)))
-                               return retval;
-                       break;
-               case EF_LAND:
-                       if (0 != (retval=load_land_ship(&sect, &ship, noisy, load_unload, &nships)))
-                               return retval;
-                       break;
-               case EF_SECTOR:
-                       if (0 != (retval=load_comm_ship(&sect, &ship, ich, load_unload, &nships)))
-                               return retval;
-               }
-               /* load/unload plague */
-               if (getvar(V_PSTAGE, (s_char *)&sect, EF_SECTOR) == PLG_INFECT &&
-                   getvar(V_PSTAGE, (s_char *)&ship, EF_SHIP) == PLG_HEALTHY)
-                       putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&ship, EF_SHIP);
-               if (getvar(V_PSTAGE, (s_char *)&ship, EF_SHIP) == PLG_INFECT &&
-                   getvar(V_PSTAGE, (s_char *)&sect, EF_SECTOR) == PLG_HEALTHY)
-                       putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&sect, EF_SECTOR);
-               putsect(&sect);
-               putship(ship.shp_uid, &ship);
+       if (!getsect(ship.shp_x, ship.shp_y, &sect))    /* XXX */
+           continue;
+       if (!sect.sct_own)
+           continue;
+       if (!player->owner) {
+           if (ship.shp_own != player->cnum)
+               continue;
+           if (!sect_has_dock(&sect))
+               continue;
+           if (load_unload == LOAD) {
+               if (noisy)
+                   pr("You don't own %s \n",
+                      xyas(sect.sct_x, sect.sct_y, player->cnum));
+               continue;
+           }
        }
-       if (!nships)
-               pr("No ships affected\n");
-       else
-               pr("%d ship%s %sloaded\n", nships, splur(nships),
-                       load_unload == UNLOAD ? "un" : "");
-       return RET_OK;
+       if (!sect_has_dock(&sect)) {
+           if (noisy)
+               pr("Sector %s is not a harbor or canal.\n",
+                  xyas(sect.sct_x, sect.sct_y, player->cnum));
+           continue;
+       }
+       if (load_unload == UNLOAD
+           && !player->owner
+           && relations_with(sect.sct_own, player->cnum) < FRIENDLY) {
+           if (noisy)
+               pr("You can't unload into an unfriendly %s\n",
+                  dchr[sect.sct_type].d_name);
+           continue;
+       }
+       if (sect.sct_effic < 2) {
+           if (noisy)
+               pr("The %s at %s is not 2%% efficient yet.\n",
+                  dchr[sect.sct_type].d_name,
+                  xyas(sect.sct_x, sect.sct_y, player->cnum));
+           continue;
+       }
+
+       if (opt_MARKET) {
+           if (ontradingblock(EF_SHIP, &ship)) {
+               pr("You cannot load/unload an item on the trading block!\n");
+               continue;
+           }
+       }
+
+       switch (type) {
+       case EF_PLANE:
+           retval = load_plane_ship(&sect, &ship, noisy, load_unload,
+                                    &nships);
+           if (retval != 0)
+               return retval;
+           break;
+       case EF_LAND:
+           retval = load_land_ship(&sect, &ship, noisy, load_unload,
+                                   &nships);
+           if (retval != 0)
+               return retval;
+           break;
+       case EF_SECTOR:
+           retval = load_comm_ship(&sect, &ship, ich, load_unload,
+                                   &nships);
+           if (retval != 0)
+               return retval;
+       }
+       /* load/unload plague */
+       if (sect.sct_pstage == PLG_INFECT
+           && ship.shp_pstage == PLG_HEALTHY)
+           ship.shp_pstage = PLG_EXPOSED;
+       if (ship.shp_pstage == PLG_INFECT
+           && sect.sct_pstage == PLG_HEALTHY)
+           sect.sct_pstage = PLG_EXPOSED;
+       putsect(&sect);
+       putship(ship.shp_uid, &ship);
+    }
+    if (!nships)
+       pr("No ships affected\n");
+    else
+       pr("%d ship%s %sloaded\n", nships, splur(nships),
+          load_unload == UNLOAD ? "un" : "");
+    return RET_OK;
 }
 
 int
 lload(void)
 {
-       int     noisy;
-       int     load_unload;
-       int     type;
-       struct  nstr_item nbst;
-       struct  ichrstr *ich;
-       int     nunits;
-       struct  sctstr sect;
-       struct  lndstr land;
-       int     retval;
-       s_char  *p;
-       s_char  buf[1024];
-
-       if (!(p = getstarg(player->argp[1],
-                  "What commodity (or 'plane' or 'land')? ", buf)) || !*p)
-               return RET_SYN;
-       if (!strncmp(p, "plane", 5))
-               type = EF_PLANE;
-       else if (!strncmp(p, "land", 4))
-               type = EF_LAND;
-       else if (NULL != (ich = whatitem(p, (s_char *)0)))
-               type = EF_SECTOR;
-       else {
-               pr("Bad commodity.\n");
-               return RET_SYN;
-       }
-
-       if (!(p = getstarg(player->argp[2], "Unit(s): ", buf)) || !*p)
-               return RET_SYN;
-
-       noisy = isdigit(*p);
+    int noisy;
+    int load_unload;
+    int type;
+    struct nstr_item nbst;
+    struct ichrstr *ich;
+    int nunits;
+    struct sctstr sect;
+    struct lndstr land;
+    int retval;
+    char *p;
+    char buf[1024];
+
+    p = getstarg(player->argp[1],
+                "What commodity (or 'plane' or 'land')? ", buf);
+    if (!p || !*p)
+       return RET_SYN;
+    if (!strncmp(p, "plane", 5))
+       type = EF_PLANE;
+    else if (!strncmp(p, "land", 4))
+       type = EF_LAND;
+    else if (NULL != (ich = item_by_name(p)))
+       type = EF_SECTOR;
+    else {
+       pr("Can't load '%s'\n", p);
+       return RET_SYN;
+    }
 
-       if (!snxtitem(&nbst, EF_LAND, p))
-               return RET_SYN;
+    p = getstarg(player->argp[2], "Unit(s): ", buf);
+    if (!p || !*p)
+       return RET_SYN;
 
-       load_unload = *(*player->argp+1) == 'l' ? LOAD : UNLOAD;
+    noisy = isdigit(*p);
 
-       nbst.flags &= ~(EFF_OWNER);
+    if (!snxtitem(&nbst, EF_LAND, p, NULL))
+       return RET_SYN;
 
-       nunits = 0;
-       while (nxtitem(&nbst, (s_char *)&land)) {
-               if (land.lnd_own == 0)
-                       continue;
+    load_unload = player->argp[0][1] == 'l' ? LOAD : UNLOAD;
 
-               if (player->cnum != land.lnd_own &&
-                   getrel(getnatp(player->cnum), land.lnd_own) != ALLIED)
-                       continue;
+    nunits = 0;
+    while (nxtitem(&nbst, &land)) {
+       if (land.lnd_own == 0)
+           continue;
+       if (!player->owner) {
+           if (load_unload == UNLOAD || !noisy)
+               continue;
+           if (relations_with(land.lnd_own, player->cnum) != ALLIED)
+               continue;
+       }
 
-               if (!getsect(land.lnd_x, land.lnd_y, &sect)) /* XXX */
-                       continue;
+       if (!getsect(land.lnd_x, land.lnd_y, &sect))    /* XXX */
+           continue;
+       if (!player->owner) {
+           if (land.lnd_own != player->cnum)
+               continue;
+           if (load_unload == LOAD) {
+               if (noisy)
+                   pr("Sector %s is not yours.\n",
+                      xyas(sect.sct_x, sect.sct_y, player->cnum));
+               continue;
+           }
+           if (relations_with(sect.sct_own, player->cnum) != ALLIED) {
+               pr("Sector %s is not yours.\n",
+                  xyas(sect.sct_x, sect.sct_y, player->cnum));
+               continue;
+           }
+       }
 
-               if (sect.sct_own != player->cnum &&
-                   land.lnd_own != player->cnum)
-                       continue;
-               if (opt_MARKET) {
-                   if (ontradingblock(EF_LAND, (int *)&land)) {
-                       pr("You cannot load/unload an item on the trading block!\n");
-                       continue;
-                   }
-               }
+       if (opt_MARKET) {
+           if (ontradingblock(EF_LAND, &land)) {
+               pr("You cannot load/unload an item on the trading block!\n");
+               continue;
+           }
+       }
 
-               if (sect.sct_own != player->cnum &&
-                   getrel(getnatp(sect.sct_own), land.lnd_own) != ALLIED) {
-                       pr("Sector %s is not yours.\n",
-                               xyas(land.lnd_x, land.lnd_y, player->cnum));
-                       continue;
-               }
-               switch (type) {
-               case EF_LAND:
-                       if (0 != (retval=load_land_land(&sect, &land, noisy, load_unload, &nunits)))
-                               return retval;
-                       break;
-               case EF_PLANE:
-                       if (0 != (retval=load_plane_land(&sect, &land, noisy, load_unload, &nunits)))
-                               return retval;
-                       break;
-               case EF_SECTOR:
-                       if (0 != (retval=load_comm_land(&sect, &land, ich, load_unload, &nunits)))
-                               return retval;
-               }
-               /* load/unload plague */
-               if (getvar(V_PSTAGE, (s_char *)&sect, EF_SECTOR) == PLG_INFECT &&
-                   getvar(V_PSTAGE, (s_char *)&land, EF_LAND) == PLG_HEALTHY)
-                       putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&land, EF_LAND);
-               if (getvar(V_PSTAGE, (s_char *)&land, EF_LAND) == PLG_INFECT &&
-                   getvar(V_PSTAGE, (s_char *)&sect, EF_SECTOR) == PLG_HEALTHY)
-                       putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&sect, EF_SECTOR);
-               
-               putsect(&sect);
-               putland(land.lnd_uid, &land);
+       switch (type) {
+       case EF_LAND:
+           retval = load_land_land(&sect, &land, noisy, load_unload,
+                                   &nunits);
+           if (retval != 0)
+               return retval;
+           break;
+       case EF_PLANE:
+           retval = load_plane_land(&sect, &land, noisy, load_unload,
+                                    &nunits);
+           if (retval != 0)
+               return retval;
+           break;
+       case EF_SECTOR:
+           retval = load_comm_land(&sect, &land, ich, load_unload,
+                                   &nunits);
+           if (retval != 0)
+               return retval;
        }
-       if (nunits == 0)
-               pr("No units affected\n");
-       else
-               pr("%d unit%s %sloaded\n", nunits, splur(nunits),
-                       load_unload == UNLOAD ? "un" : "");
-       return RET_OK;
+       /* load/unload plague */
+       if (sect.sct_pstage == PLG_INFECT
+           && land.lnd_pstage == PLG_HEALTHY)
+           land.lnd_pstage = PLG_EXPOSED;
+       if (land.lnd_pstage == PLG_INFECT
+           && sect.sct_pstage == PLG_HEALTHY)
+           sect.sct_pstage = PLG_EXPOSED;
+
+       putsect(&sect);
+       putland(land.lnd_uid, &land);
+    }
+    if (nunits == 0)
+       pr("No units affected\n");
+    else
+       pr("%d unit%s %sloaded\n", nunits, splur(nunits),
+          load_unload == UNLOAD ? "un" : "");
+    return RET_OK;
 }
 
-void
-gift(int givee, int giver, s_char *ptr, int type, s_char *mesg)
+static int
+move_amount(int sect_amt, int unit_amt, int unit_max,
+          int load_unload, int amount)
 {
-       s_char  *p, line[256];
-
-       if (giver == givee)
-               return;
-
+    int move_amt;
+
+    if (amount < 0)
+       move_amt = -amount - unit_amt;
+    else
+       move_amt = load_unload == LOAD ? amount : -amount;
+    move_amt = LIMIT_TO(move_amt, -unit_amt, unit_max - unit_amt);
+    move_amt = LIMIT_TO(move_amt, sect_amt - ITEM_MAX, sect_amt);
+    return move_amt;
+}
 
-       switch(type) {
-               case EF_SHIP:   p = prship((struct shpstr *)ptr);
-                               break;
-               case EF_PLANE:  p = prplane((struct plnstr *)ptr);
-                               break;
-               case EF_LAND:   p = prland((struct lndstr *)ptr);
-                               break;
-       }
+int
+load_comm_ok(struct sctstr *sectp, natid unit_own,
+            i_type item, int move_amt)
+{
+    if (!move_amt)
+       return 0;
+    if (move_amt < 0 && !player->god && unit_own != player->cnum)
+       return 0;
+    if (move_amt > 0 && !player->god && sectp->sct_own != player->cnum)
+       return 0;
+    if (sectp->sct_oldown != unit_own && item == I_CIVIL) {
+       pr("%s civilians refuse to %s at %s!\n",
+          (move_amt < 0 ? unit_own : sectp->sct_oldown) == player->cnum
+          ? "Your" : "Foreign",
+          move_amt < 0 ? "disembark" : "board",
+          xyas(sectp->sct_x, sectp->sct_y, player->cnum));
+       return 0;
+    }
+    return 1;
+}
 
-       sprintf(line,"%s %s %s\n",cname(giver),p,mesg);
-       wu(0,givee,line);
+void
+gift(natid givee, natid giver, void *ptr, char *mesg)
+{
+    if (giver != givee)
+       wu(0, givee, "%s %s %s\n", cname(giver), unit_nameof(ptr), mesg);
+    unit_give_away(ptr, givee, 0);
 }
 
 static int
@@ -340,192 +381,175 @@ still_ok_land(struct sctstr *sectp, struct lndstr *landp)
 }
 
 static int
-load_plane_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unload, int *nshipsp)
+load_plane_ship(struct sctstr *sectp, struct shpstr *sp, int noisy,
+               int load_unload, int *nshipsp)
 {
-       struct  nstr_item ni;
-       struct  plnstr pln;
-       int     loaded = 0;
-       s_char  buf[1024];
-       s_char  *p;
-       s_char  prompt[512];
-       struct  mchrstr *mcp = mchr + sp->shp_type;
-
-       if (!(mcp->m_flags & (M_CHOPPER|M_XLIGHT|M_FLY|M_MSL))) {
-               if (noisy)
-                       pr("%s cannot carry planes\n", prship(sp));
-               return 0;
+    struct nstr_item ni;
+    struct plnstr pln;
+    int loaded = 0;
+    char buf[1024];
+    char *p;
+    char prompt[512];
+    struct mchrstr *mcp = mchr + sp->shp_type;
+
+    if (mcp->m_nplanes + mcp->m_nchoppers + mcp->m_nxlight == 0) {
+       if (noisy)
+           pr("%s cannot carry planes\n", prship(sp));
+       return 0;
+    }
+    if (load_unload == LOAD &&
+       shp_nplane(sp, NULL, NULL, NULL)
+               >= mcp->m_nchoppers + mcp->m_nxlight + mcp->m_nplanes) {
+       if (noisy)
+           pr("%s doesn't have room for any more planes\n", prship(sp));
+       return 0;
+    }
+    sprintf(prompt, "Plane(s) to %s %s? ",
+           load_unload == LOAD ? "load onto" : "unload from", prship(sp));
+    p = getstarg(player->argp[3], prompt, buf);
+    if (!p)
+       return RET_SYN;
+    if (!snxtitem(&ni, EF_PLANE, p, NULL))
+       return RET_SYN;
+
+    if (!still_ok_ship(sectp, sp))
+       return RET_SYN;
+
+    if (noisy && p && *p)
+       noisy = isdigit(*p);
+
+    while (nxtitem(&ni, &pln)) {
+       if (!player->owner)
+           continue;
+       if (!(plchr[(int)pln.pln_type].pl_flags & P_L)
+           && !(plchr[(int)pln.pln_type].pl_flags & P_E)
+           && !(plchr[(int)pln.pln_type].pl_flags & P_K)
+           && !(plchr[(int)pln.pln_type].pl_flags & P_M)
+           ) {
+           if (noisy)
+               pr("You can only load light planes, helos, xtra-light, or missiles onto ships.\n");
+           continue;
        }
-       count_planes(sp);
-       if (load_unload==LOAD &&
-           sp->shp_nchoppers >= mcp->m_nchoppers &&
-           sp->shp_nxlight >= mcp->m_nxlight &&
-           sp->shp_nplane >= mcp->m_nplanes) {
-               if (noisy)
-                       pr("%s doesn't have room for any more planes\n",
-                          prship(sp));
-               return 0;
+       if (load_unload == LOAD && pln.pln_ship > -1) {
+           if (noisy)
+               pr("%s is already on ship #%d!\n",
+                  prplane(&pln), pln.pln_ship);
+           continue;
+       }
+       if (load_unload == LOAD && pln.pln_land > -1) {
+           if (noisy)
+               pr("%s is already on land unit #%d!\n",
+                  prplane(&pln), pln.pln_land);
+           continue;
+       }
+       if (pln.pln_harden != 0) {
+           if (noisy)
+               pr("%s has been hardened and can't be loaded\n",
+                  prplane(&pln));
+           continue;
        }
-       sprintf(prompt, "Plane(s) to %s %s? ",
-               load_unload==LOAD?"load onto":"unload from",
-               prship(sp));
-       if (!snxtitem(&ni, EF_PLANE, p=getstarg(player->argp[3], prompt, buf)))
-               return RET_SYN;
-
-       if (!still_ok_ship(sectp, sp))
-           return RET_SYN;
-
-       if (p && *p)
-               noisy &= isdigit(*p);
-
-       while(nxtitem(&ni, (s_char *)&pln)) {                   
-               if (pln.pln_own != player->cnum)
-                       continue;
-               if (!(plchr[(int)pln.pln_type].pl_flags & P_L)
-                   &&  !(plchr[(int)pln.pln_type].pl_flags & P_E)
-                   &&  !(plchr[(int)pln.pln_type].pl_flags & P_K)
-                   &&  !(plchr[(int)pln.pln_type].pl_flags & P_M)
-                   ) {
-                       if (noisy)
-                               pr("You can only load light planes, helos, xtra-light, or missiles onto ships.\n");
-                       continue;
-               }
-               if (load_unload == LOAD && pln.pln_ship > -1) {
-                       if (noisy)
-                               pr("%s is already on ship #%d!\n",
-                                  prplane(&pln), pln.pln_ship);
-                       continue;
-               }
-               if (load_unload == LOAD && pln.pln_land > -1) {
-                       if (noisy)
-                               pr("%s is already on land unit #%d!\n",
-                                  prplane(&pln), pln.pln_land);
-                       continue;
-               }
 
-               /* Plane sanity done */
-               /* Find the right ship */
-               if (load_unload == UNLOAD) {
-                       if (pln.pln_ship != sp->shp_uid)
-                               continue;
-               } else if (sp->shp_x != pln.pln_x
-                          || sp->shp_y != pln.pln_y)
-                       continue;
-
-               /* ship to (plane or missle) sanity */
-               if (!can_be_on_ship(pln.pln_uid, sp->shp_uid)) {
-                       if (plchr[(int)pln.pln_type].pl_flags & P_L) {
-                               strcpy(buf, "planes");
-                       } else if (plchr[(int)pln.pln_type].pl_flags & P_K) {
-                               strcpy(buf, "choppers");
-                       } else if (plchr[(int)pln.pln_type].pl_flags & P_M) {
-                               strcpy(buf, "missiles");
-                       } else if (plchr[(int)pln.pln_type].pl_flags & P_E) {
-                               strcpy(buf, "extra light planes");
-                       } /* else impossible */
-                       if (noisy)
-                               pr("%s cannot carry %s.\n",
-                                  prship(sp),
-                                  buf);
-                       continue;
-               }
-               /* Fit plane on ship */
-               if (load_unload == LOAD){
-                       if (!put_plane_on_ship(&pln,sp)){
-                               if (noisy)
-                                       pr("Can't put plane %d on this ship!\n",pln.pln_uid);
-                               continue;
-                       }
-                       sprintf(buf, "loaded on your %s at %s",
-                               prship(sp),xyas(sp->shp_x,
-                                               sp->shp_y, sp->shp_own));
-                       gift(sp->shp_own, player->cnum, (s_char *)&pln,
-                            EF_PLANE, buf);
-                       makelost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y);
-                       pln.pln_own = sp->shp_own;
-                       makenotlost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y);
-                       pln.pln_mission = 0;
-                       putplane(pln.pln_uid,&pln);
-               } else {
-                       if (!take_plane_off_ship(&pln,sp)) {
-                               pr("Unable to take plane off ship!\n");
-                               logerror("load: plane %d could not be taken off ship %d\n",pln.pln_uid,sp->shp_uid);
-                               continue;
-                       }
-                       sprintf(buf, "unloaded in your %s at %s",
-                               dchr[sectp->sct_type].d_name,
-                               xyas(sectp->sct_x,sectp->sct_y,
-                                    sectp->sct_own));
-                       gift(sectp->sct_own, player->cnum, (s_char *)&pln,
-                            EF_PLANE, buf);
-                       makelost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y);
-                       pln.pln_own = sectp->sct_own;
-                       makenotlost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y);
-                       putplane(pln.pln_uid,&pln);
-               }
-               pr("%s %s %s at %s.\n",
-                  prplane(&pln),
-                  (load_unload==UNLOAD)?
-                  "unloaded from":"loaded onto",
-                  prship(sp),
-                  xyas(sp->shp_x, sp->shp_y, player->cnum));
-               loaded = 1;
+       if (load_unload == UNLOAD) {
+           if (pln.pln_ship != sp->shp_uid)
+               continue;
+       } else if (sp->shp_x != pln.pln_x || sp->shp_y != pln.pln_y)
+           continue;
+
+       if (!could_be_on_ship(&pln, sp)) {
+           if (noisy) {
+               if (plchr[(int)pln.pln_type].pl_flags & P_K)
+                   p = "choppers";
+               else if (plchr[(int)pln.pln_type].pl_flags & P_E)
+                   p = "extra light planes";
+               else if (plchr[(int)pln.pln_type].pl_flags & P_M)
+                   p = "missiles";
+               else
+                   p = "planes";
+               pr("%s cannot carry %s.\n", prship(sp), p);
+           }
+           continue;
        }
-       *nshipsp += loaded;
-       return 0;
+       /* Fit plane on ship */
+       if (load_unload == LOAD) {
+           if (!put_plane_on_ship(&pln, sp)) {
+               if (noisy)
+                   pr("Can't put plane %d on this ship!\n", pln.pln_uid);
+               continue;
+           }
+           sprintf(buf, "loaded on your %s at %s",
+                   prship(sp), xyas(sp->shp_x, sp->shp_y, sp->shp_own));
+           gift(sp->shp_own, player->cnum, &pln, buf);
+           putplane(pln.pln_uid, &pln);
+       } else {
+           pln.pln_ship = -1;
+           sprintf(buf, "unloaded in your %s at %s",
+                   dchr[sectp->sct_type].d_name,
+                   xyas(sectp->sct_x, sectp->sct_y, sectp->sct_own));
+           gift(sectp->sct_own, player->cnum, &pln, buf);
+           putplane(pln.pln_uid, &pln);
+       }
+       pr("%s %s %s at %s.\n",
+          prplane(&pln),
+          (load_unload == UNLOAD) ?
+          "unloaded from" : "loaded onto",
+          prship(sp), xyas(sp->shp_x, sp->shp_y, player->cnum));
+       loaded = 1;
+    }
+    *nshipsp += loaded;
+    return 0;
 }
 
 static int
-load_land_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unload, int *nshipsp)
+load_land_ship(struct sctstr *sectp, struct shpstr *sp, int noisy,
+              int load_unload, int *nshipsp)
 {
-    struct     nstr_item pni, ni;
-    struct     lndstr land;
-    struct     plnstr plane;
-    int        loaded = 0;
-    s_char     *p;
-    s_char     prompt[512];
-    s_char     buf[1024];
-    int     load_spy = 0;
-    
-    count_units(sp);
+    struct nstr_item ni;
+    struct lndstr land;
+    int loaded = 0;
+    char *p;
+    char prompt[512];
+    char buf[1024];
+    int load_spy = 0;
+
     if (load_unload == LOAD) {
-       if (opt_LANDSPIES) {
-           if ((mchr[(int)sp->shp_type].m_flags & M_SUB) &&
-               (mchr[(int)sp->shp_type].m_nland == 0)) {
-               if (sp->shp_nland >= 2) {
-                   pr("Non-land unit carrying subs can only carry up to two spy units.\n");
-                   return 0;
-               }
-               /* Eh, let 'em load a spy only */
-               load_spy = 1;
+       if ((mchr[(int)sp->shp_type].m_flags & M_SUB) &&
+           (mchr[(int)sp->shp_type].m_nland == 0)) {
+           if (shp_nland(sp) >= 2) {
+               pr("Non-land unit carrying subs can only carry up to two spy units.\n");
+               return 0;
            }
+           /* Eh, let 'em load a spy only */
+           load_spy = 1;
        }
-       if ((!load_spy) && 
-           (sp->shp_nland >= mchr[(int)sp->shp_type].m_nland)) {
+       if (!load_spy && shp_nland(sp) >= mchr[sp->shp_type].m_nland) {
            if (noisy) {
                if (mchr[(int)sp->shp_type].m_nland)
-                   pr("%s doesn't have room for any more land units!\n",prship(sp));
+                   pr("%s doesn't have room for any more land units!\n",
+                      prship(sp));
                else
-                   pr("%s cannot carry land units!\n",prship(sp));
+                   pr("%s cannot carry land units!\n", prship(sp));
            }
            return 0;
        }
     }
     sprintf(prompt, "Land unit(s) to %s %s? ",
-           load_unload==LOAD?"load onto":"unload from",
-           prship(sp));
-    if (!snxtitem(&ni, EF_LAND, p=getstarg(player->argp[3], prompt, buf)))
+           load_unload == LOAD ? "load onto" : "unload from", prship(sp));
+    p = getstarg(player->argp[3], prompt, buf);
+    if (!p)
+       return RET_SYN;
+    if (!snxtitem(&ni, EF_LAND, p, NULL))
        return RET_SYN;
-    
+
     if (!still_ok_ship(sectp, sp))
        return RET_SYN;
-    
-    if (p && *p)
-       noisy &= isdigit(*p);
-    
-    while(nxtitem(&ni, (s_char *)&land)) {
-       if (land.lnd_own != player->cnum)
+
+    if (noisy && p && *p)
+       noisy = isdigit(*p);
+
+    while (nxtitem(&ni, &land)) {
+       if (!player->owner)
            continue;
-       
+
        if (load_unload == LOAD) {
            if (land.lnd_ship > -1) {
                if (noisy)
@@ -539,8 +563,7 @@ load_land_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unlo
                       prland(&land), land.lnd_land);
                continue;
            }
-           lnd_count_units(&land);
-           if (land.lnd_nland > 0) {
+           if (lnd_first_on_land(&land) >= 0) {
                if (noisy)
                    pr("%s cannot be loaded since it is carrying units\n",
                       prland(&land));
@@ -557,7 +580,7 @@ load_land_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unlo
                continue;
            }
        }
-       
+
        /* Unit sanity done */
        /* Find the right ship */
        if (load_unload == UNLOAD) {
@@ -565,10 +588,9 @@ load_land_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unlo
                continue;
            if (land.lnd_land > -1)
                continue;
-       } else if (sp->shp_x != land.lnd_x
-                  || sp->shp_y != land.lnd_y)
+       } else if (sp->shp_x != land.lnd_x || sp->shp_y != land.lnd_y)
            continue;
-       
+
        if ((!(lchr[(int)land.lnd_type].l_flags & L_LIGHT)) &&
            (!((mchr[(int)sp->shp_type].m_flags & M_SUPPLY) &&
               (!(mchr[(int)sp->shp_type].m_flags & M_SUB))))) {
@@ -581,130 +603,60 @@ load_land_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unlo
        }
        /* Fit unit on ship */
        if (load_unload == LOAD) {
-           count_units(sp);
            /* We have to check again, since it may have changed */
-           if (opt_LANDSPIES) {
-               if ((mchr[(int)sp->shp_type].m_flags & M_SUB) &&
-                   (mchr[(int)sp->shp_type].m_nland == 0)) {
-                   if (sp->shp_nland >= 2) {
-                       pr("Non-land unit carrying subs can only carry up to two spy units.\n");
-                       return 0;
-                   }
-                               /* Eh, let 'em load a spy only */
-                   load_spy = 1;
+           if ((mchr[(int)sp->shp_type].m_flags & M_SUB) &&
+               (mchr[(int)sp->shp_type].m_nland == 0)) {
+               if (shp_nland(sp) >= 2) {
+                   pr("Non-land unit carrying subs can only carry up to two spy units.\n");
+                   return 0;
                }
+               /* Eh, let 'em load a spy only */
+               load_spy = 1;
            }
-           if ((!load_spy) && 
-               (sp->shp_nland >= mchr[(int)sp->shp_type].m_nland)) {
-               if (noisy) {
+           if (!load_spy && shp_nland(sp) >= mchr[sp->shp_type].m_nland) {
+               if (noisy) {
                    if (mchr[(int)sp->shp_type].m_nland)
-                       pr("%s doesn't have room for any more land units!\n",prship(sp));
+                       pr("%s doesn't have room for any more land units!\n",
+                          prship(sp));
                    else
-                       pr("%s cannot carry land units!\n",prship(sp));
+                       pr("%s cannot carry land units!\n", prship(sp));
                }
                return 0;
            }
-#if 0
-           if (sp->shp_nland >= mchr[(int)sp->shp_type].m_nland) {
-               if (noisy)
-                   if (mchr[(int)sp->shp_type].m_nland)
-                       pr("%s doesn't have room for any more land units!\n",prship(sp));
-                   else
-                       pr("%s cannot carry land units!\n",prship(sp));
-               break;
-           }
-#endif
            sprintf(buf, "loaded on your %s at %s",
-                   prship(sp),xyas(sp->shp_x,sp->shp_y,
-                                   sp->shp_own));
-           gift(sp->shp_own,player->cnum,(s_char *)&land,
-                EF_LAND, buf);
-           makelost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x,
-                    land.lnd_y);
-           land.lnd_own = sp->shp_own;
-           makenotlost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x,
-                       land.lnd_y);
+                   prship(sp), xyas(sp->shp_x, sp->shp_y, sp->shp_own));
+           gift(sp->shp_own, player->cnum, &land, buf);
            land.lnd_ship = sp->shp_uid;
            land.lnd_harden = 0;
-           land.lnd_mission = 0;
-           resupply_all(&land);
-           sp->shp_nland++;
-           putland(land.lnd_uid,&land);
-           if (!has_supply(&land))
-               pr("WARNING: %s is out of supply!\n",
-                  prland(&land));
-           putship(sp->shp_uid,sp);
-           snxtitem_xy(&pni,EF_PLANE,land.lnd_x,land.lnd_y);
-           while (nxtitem(&pni, (s_char *)&plane)){
-               if (plane.pln_flags & PLN_LAUNCHED)
-                   continue;
-               if (plane.pln_land != land.lnd_uid)
-                   continue;
-               sprintf(buf, "loaded on %s",
-                       prship(sp));
-               gift(sp->shp_own,player->cnum,(s_char *)&plane,
-                    EF_PLANE, buf);
-               makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x,
-                        plane.pln_y);
-               plane.pln_own = sp->shp_own;
-               makenotlost(EF_PLANE, plane.pln_own, plane.pln_uid, 
-                           plane.pln_x, plane.pln_y);
-               plane.pln_mission = 0;
-               putplane(plane.pln_uid,&plane);
-           }
+           putland(land.lnd_uid, &land);
+#if 0
+          /*
+           * FIXME if this supplies from the sector, the putsect in
+           * load() / lload() duplicates those supplies, causing a
+           * seqno mismatch
+           */
+           if (!lnd_supply_all(&land))
+               pr("WARNING: %s is out of supply!\n", prland(&land));
+#else
+           if (!lnd_in_supply(&land))
+               pr("WARNING: %s is out of supply!\n", prland(&land));
+#endif
        } else {
            sprintf(buf, "unloaded in your %s at %s",
                    dchr[sectp->sct_type].d_name,
-                   xyas(sectp->sct_x,sectp->sct_y,
-                        sectp->sct_own));
-           
+                   xyas(sectp->sct_x, sectp->sct_y, sectp->sct_own));
+
            /* Spies are unloaded quietly, others aren't */
-           if (!(lchr[(int)land.lnd_type].l_flags & L_SPY)) {
-               gift(sectp->sct_own,player->cnum,(s_char *)&land,
-                    EF_LAND, buf);
-               makelost(EF_LAND, land.lnd_own, land.lnd_uid,
-                        land.lnd_x, land.lnd_y);
-               land.lnd_own = sectp->sct_own;
-               makenotlost(EF_LAND, land.lnd_own, land.lnd_uid,
-                           land.lnd_x, land.lnd_y);
-           }
-           
-           land.lnd_ship = (-1);
-           sp->shp_nland--;
-           putland(land.lnd_uid,&land);
-           putship(sp->shp_uid,sp);
-           
-           /* Spies are unloaded quietly, others aren't, and
-              in the off chance they can carry a plane (missile?)
-              they are quietly unloaded too. */
-           if (!(lchr[(int)land.lnd_type].l_flags & L_SPY)) {
-               snxtitem_xy(&pni,EF_PLANE,land.lnd_x,land.lnd_y);
-               while (nxtitem(&pni, (s_char *)&plane)){
-                   if (plane.pln_flags & PLN_LAUNCHED)
-                       continue;
-                   if (plane.pln_land != land.lnd_uid)
-                       continue;
-                   sprintf(buf, "unloaded at %s",
-                           xyas(plane.pln_x,plane.pln_y,
-                                sectp->sct_own));
-                   gift(sectp->sct_own,player->cnum,(s_char *)&plane,
-                        EF_PLANE, buf);
-                   makelost(EF_PLANE, plane.pln_own, plane.pln_uid,
-                            plane.pln_x, plane.pln_y);
-                   plane.pln_own = sectp->sct_own;
-                   makenotlost(EF_PLANE, plane.pln_own, plane.pln_uid,
-                               plane.pln_x, plane.pln_y);
-                   plane.pln_mission = 0;
-                   putplane(plane.pln_uid,&plane);
-               }
-           }
+           if (!(lchr[(int)land.lnd_type].l_flags & L_SPY))
+               gift(sectp->sct_own, player->cnum, &land, buf);
+           land.lnd_ship = -1;
+           putland(land.lnd_uid, &land);
        }
        pr("%s %s %s at %s.\n",
           prland(&land),
-          (load_unload==UNLOAD)?
-          "unloaded from":"loaded onto",
-          prship(sp),
-          xyas(sp->shp_x, sp->shp_y, player->cnum));
+          (load_unload == UNLOAD) ?
+          "unloaded from" : "loaded onto",
+          prship(sp), xyas(sp->shp_x, sp->shp_y, player->cnum));
        loaded = 1;
     }
     *nshipsp += loaded;
@@ -712,518 +664,348 @@ load_land_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unlo
 }
 
 static int
-load_comm_ship(struct sctstr *sectp, struct shpstr *sp, struct ichrstr *ich, int load_unload, int *nshipsp)
+load_comm_ship(struct sctstr *sectp, struct shpstr *sp,
+              struct ichrstr *ich, int load_unload, int *nshipsp)
 {
-       register int item = ich->i_vtype;
-       register int max_amt;
-       register int move_amt;
-       register int ship_amt;
-       register int sect_amt;
-       int     amount;
-       int     upto=0, abs_max;
-       s_char  prompt[512];
-       s_char  *p;
-       s_char  buf[1024];
-
-       sprintf(prompt, "Number of %s to %s %s at %s? ",
-               ich->i_name,
-               (load_unload==UNLOAD)?
-               "unload from":"load onto",
-               prship(sp),
-               xyas(sp->shp_x, sp->shp_y, player->cnum));
-       if (!(p = getstarg(player->argp[3], prompt, buf)) ||
-           !*p)
-               return RET_SYN;
-
-       if (!still_ok_ship(sectp, sp))
-           return RET_SYN;
-
-       amount = atoi(p);
-       if (amount < 0) {
-               /* We want to load up to this amount */
-               upto = -(amount);
-               load_unload = LOAD;
-       } else if (!amount)
-               return 0;
-       ship_amt = getvar(item, (s_char *)sp, EF_SHIP);
-       sect_amt = getvar(item, (s_char *)sectp, EF_SECTOR);
-       if (sectp->sct_oldown != player->cnum &&
-           item == V_CIVIL) {
-               pr("%s civilians refuse to %s at %s!\n",
-                  load_unload == UNLOAD ? "Your" : "Foreign",
-                  load_unload == UNLOAD ?
-                  "disembark" : "board",
-                  xyas(sectp->sct_x, sectp->sct_y, player->cnum));
-               return 0;
-       }
-       if (load_unload == UNLOAD) {
-               abs_max = max_amt = min(9999 - sect_amt, ship_amt);
-       } else {
-               struct mchrstr *vbase;
-               vbase = &mchr[(int)sp->shp_type];
-               abs_max = max_amt = vl_find(item, vbase->m_vtype,
-                                           vbase->m_vamt, (int) vbase->m_nv);
-               max_amt = min(sect_amt, max_amt - ship_amt);
-       }
-       if (max_amt <= 0 && !upto)
-               return 0;
-       if (upto) {
-               move_amt = upto - ship_amt;
-               if (move_amt > sect_amt)
-                       move_amt = sect_amt;
-               if (ship_amt+move_amt > abs_max)
-                       move_amt = abs_max - ship_amt;
-       } else
-               move_amt = load_unload * min(amount, max_amt);
-       if (!move_amt)
-               return 0;
+    i_type item = ich->i_uid;
+    struct mchrstr *mcp = &mchr[(int)sp->shp_type];
+    int ship_amt, sect_amt, move_amt;
+    char prompt[512];
+    char *p;
+    char buf[1024];
+
+    sprintf(prompt, "Number of %s to %s %s at %s? ",
+           ich->i_name,
+           (load_unload == UNLOAD) ?
+           "unload from" : "load onto",
+           prship(sp), xyas(sp->shp_x, sp->shp_y, player->cnum));
+    p = getstarg(player->argp[3], prompt, buf);
+    if (!p || !*p)
+       return RET_SYN;
 
-       if (!want_to_abandon(sectp, item, move_amt, 0))
-           return RET_FAIL;
-       if (!still_ok_ship(sectp, sp))
-           return RET_SYN;
-       putvar(item, sect_amt - move_amt, (s_char *)sectp, EF_SECTOR);
-       putvar(item, ship_amt + move_amt, (s_char *)sp, EF_SHIP);
-       if (load_unload == LOAD) {
-               pr("%d %s loaded onto %s at %s\n",
-                  move_amt,
-                  ich->i_name,
-                  prship(sp),
-                  xyas(sp->shp_x, sp->shp_y, player->cnum));
-               if (sp->shp_own != player->cnum) {
-                       sprintf(buf,"%s loaded %d %s onto %s at %s\n",
-                               cname(player->cnum),
-                               move_amt,
-                               ich->i_name,
-                               prship(sp),
-                               xyas(sp->shp_x, sp->shp_y,
-                                    sp->shp_own));
-                       wu(0, sp->shp_own, buf);
-               }
-       } else {
-               pr("%d %s unloaded from %s at %s\n",
-                  -move_amt,
-                  ich->i_name,
-                  prship(sp),
-                  xyas(sp->shp_x, sp->shp_y, player->cnum));
-               if (sectp->sct_own != player->cnum) {
-                       sprintf(buf,"%s unloaded %d %s from %s at %s\n",
-                               cname(player->cnum),
-                               -move_amt,
-                               ich->i_name,
-                               prship(sp),
-                               xyas(sp->shp_x, sp->shp_y,
-                                    sectp->sct_own));
-                       wu(0, sectp->sct_own, buf);
-               }
+    if (!still_ok_ship(sectp, sp))
+       return RET_SYN;
+
+    ship_amt = sp->shp_item[item];
+    sect_amt = sectp->sct_item[item];
+    move_amt = move_amount(sect_amt, ship_amt, mcp->m_item[item],
+                          load_unload, atoi(p));
+    if (!load_comm_ok(sectp, sp->shp_own, item, move_amt))
+       return RET_OK;
+    if (!want_to_abandon(sectp, item, move_amt, NULL))
+       return RET_FAIL;
+    if (!still_ok_ship(sectp, sp))
+       return RET_SYN;
+    sectp->sct_item[item] = sect_amt - move_amt;
+    sp->shp_item[item] = ship_amt + move_amt;
+
+    if (move_amt >= 0) {
+       pr("%d %s loaded onto %s at %s\n",
+          move_amt, ich->i_name,
+          prship(sp), xyas(sp->shp_x, sp->shp_y, player->cnum));
+       if (sp->shp_own != player->cnum) {
+           wu(0, sp->shp_own, "%s loaded %d %s onto %s at %s\n",
+              cname(player->cnum), move_amt, ich->i_name,
+              prship(sp), xyas(sp->shp_x, sp->shp_y, sp->shp_own));
        }
-       ++(*nshipsp);
-       return 0;
+    } else {
+       pr("%d %s unloaded from %s at %s\n",
+          -move_amt, ich->i_name,
+          prship(sp), xyas(sp->shp_x, sp->shp_y, player->cnum));
+       if (sectp->sct_own != player->cnum) {
+           wu(0, sectp->sct_own, "%s unloaded %d %s from %s at %s\n",
+              cname(player->cnum), -move_amt, ich->i_name,
+              prship(sp), xyas(sp->shp_x, sp->shp_y, sectp->sct_own));
+       }
+    }
+    ++*nshipsp;
+    return 0;
 }
 
 static int
-load_plane_land(struct sctstr *sectp, struct lndstr *lp, int noisy, int load_unload, int *nunitsp)
+load_plane_land(struct sctstr *sectp, struct lndstr *lp, int noisy,
+               int load_unload, int *nunitsp)
 {
-       struct  nstr_item ni;
-       struct  plnstr pln;
-       int     loaded = 0;
-       s_char  *p;
-       s_char  prompt[512];
-       s_char  buf[1024];
-
-       if (!(lchr[(int)lp->lnd_type].l_flags & L_XLIGHT)) {
-               if (noisy)
-                       pr("%s cannot carry extra-light planes.\n",
-                          prland(lp));
-               return 0;
-       }
-       count_land_planes(lp);
-       if (load_unload==LOAD &&
-           lp->lnd_nxlight >= lp->lnd_maxlight) {
-               if (noisy)
-                       pr("%s doesn't have room for any more extra-light planes\n",
-                          prland(lp));
-               return 0;
-       }
-       sprintf(prompt, "Plane(s) to %s %s? ",
-               load_unload==LOAD?"load onto":"unload from",
-               prland(lp));
-       if (!snxtitem(&ni, EF_PLANE, p=getstarg(player->argp[3], prompt, buf)))
-               return RET_SYN;
+    struct nstr_item ni;
+    struct plnstr pln;
+    int loaded = 0;
+    char *p;
+    char prompt[512];
+    char buf[1024];
+    struct lchrstr *lcp = lchr + lp->lnd_type;
+
+    if (!lcp->l_nxlight) {
+       if (noisy)
+           pr("%s cannot carry extra-light planes.\n", prland(lp));
+       return 0;
+    }
+    if (load_unload == LOAD && lnd_nxlight(lp) >= lcp->l_nxlight) {
+       if (noisy)
+           pr("%s doesn't have room for any more extra-light planes\n",
+              prland(lp));
+       return 0;
+    }
+    sprintf(prompt, "Plane(s) to %s %s? ",
+           load_unload == LOAD ? "load onto" : "unload from", prland(lp));
+    p = getstarg(player->argp[3], prompt, buf);
+    if (!p)
+       return RET_SYN;
+    if (!snxtitem(&ni, EF_PLANE, p, NULL))
+       return RET_SYN;
 
-       if (!still_ok_land(sectp, lp))
-           return RET_SYN;
+    if (!still_ok_land(sectp, lp))
+       return RET_SYN;
 
-       if (p && *p)
-               noisy &= isdigit(*p);
+    if (noisy && p && *p)
+       noisy = isdigit(*p);
 
-       if (sectp->sct_own != player->cnum && load_unload == LOAD) {
-               pr("Sector %s is not yours.\n",
-                  xyas(lp->lnd_x, lp->lnd_y, player->cnum));
-               return 0;
+    while (nxtitem(&ni, &pln)) {
+       if (!player->owner)
+           continue;
+
+       if (!(plchr[(int)pln.pln_type].pl_flags & P_E)) {
+           if (noisy)
+               pr("You can only load xlight planes onto units.\n");
+           continue;
        }
 
-       while(nxtitem(&ni, (s_char *)&pln)) {                   
-               if (pln.pln_own != player->cnum)
-                       continue;
-               
-               if (!(plchr[(int)pln.pln_type].pl_flags & P_E)) {
-                       if (noisy)
-                               pr("You can only load xlight planes onto units.\n");
-                       continue;
-               }
+       if (load_unload == LOAD && pln.pln_ship > -1) {
+           if (noisy)
+               pr("%s is already on ship #%d!\n",
+                  prplane(&pln), pln.pln_ship);
+           continue;
+       }
+       if (load_unload == LOAD && pln.pln_land > -1) {
+           if (noisy)
+               pr("%s is already on unit #%d!\n",
+                  prplane(&pln), pln.pln_land);
+           continue;
+       }
+       if (pln.pln_harden != 0) {
+           if (noisy)
+               pr("%s has been hardened and can't be loaded\n",
+                  prplane(&pln));
+           continue;
+       }
 
-               if (load_unload == LOAD && pln.pln_ship > -1) {
-                       if (noisy)
-                               pr("%s is already on ship #%d!\n",
-                                  prplane(&pln), pln.pln_ship);
-                       continue;
-               }
-               if (load_unload == LOAD && pln.pln_land > -1) {
-                       if (noisy)
-                               pr("%s is already on unit #%d!\n",
-                                  prplane(&pln), pln.pln_land);
-                       continue;
-               }
-               /* Plane sanity done */
-               /* Find the right unit */
-               if (load_unload == UNLOAD) {
-                       if (pln.pln_land != lp->lnd_uid)
-                               continue;
-               } else if (lp->lnd_x != pln.pln_x
-                          || lp->lnd_y != pln.pln_y)
-                       continue;
-
-               /* Fit plane on unit */
-               if (load_unload == LOAD){
-                       if (!put_plane_on_land(&pln,lp)){
-                               if (noisy)
-                                       pr("Can't put plane %d on this unit!\n",pln.pln_uid);
-                               continue;
-                       }
-                       sprintf(buf, "loaded on %s at %s",
-                               prland(lp), xyas(lp->lnd_x,
-                                                  lp->lnd_y, lp->lnd_own));
-                       gift(lp->lnd_own,player->cnum,(s_char *)&pln,
-                            EF_PLANE, buf);
-                       makelost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y);
-                       pln.pln_own = lp->lnd_own;
-                       makenotlost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y);
-                       putplane(pln.pln_uid,&pln);
-               }else{
-                       if (!take_plane_off_land(&pln,lp)){
-                               pr("Unable to take plane off unit!\n");
-                               logerror("load: plane %d could not be taken off unit %d\n",pln.pln_uid,lp->lnd_uid);
-                               continue;
-                       }
-                       sprintf(buf, "unloaded at your sector at %s",
-                               xyas(sectp->sct_x,sectp->sct_y,
-                                    sectp->sct_own));
-                       gift(sectp->sct_own,player->cnum,(s_char *)&pln,
-                            EF_PLANE, buf);
-                       makelost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y);
-                       pln.pln_own = sectp->sct_own;
-                       makenotlost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y);
-                       putplane(pln.pln_uid,&pln);
-               }
-               pr("%s %s %s at %s.\n",
-                  prplane(&pln),
-                  (load_unload==UNLOAD)?
-                  "unloaded from":"loaded onto",
-                  prland(lp),
-                  xyas(lp->lnd_x, lp->lnd_y, player->cnum));
-               loaded = 1;
+       /* Plane sanity done */
+       /* Find the right unit */
+       if (load_unload == UNLOAD) {
+           if (pln.pln_land != lp->lnd_uid)
+               continue;
+       } else if (lp->lnd_x != pln.pln_x || lp->lnd_y != pln.pln_y)
+           continue;
+
+       /* Fit plane on unit */
+       if (load_unload == LOAD) {
+           if (!put_plane_on_land(&pln, lp)) {
+               if (noisy)
+                   pr("Can't put plane %d on this unit!\n", pln.pln_uid);
+               continue;
+           }
+           sprintf(buf, "loaded on %s at %s",
+                   prland(lp), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own));
+           gift(lp->lnd_own, player->cnum, &pln, buf);
+           putplane(pln.pln_uid, &pln);
+       } else {
+           pln.pln_land = -1;
+           sprintf(buf, "unloaded at your sector at %s",
+                   xyas(sectp->sct_x, sectp->sct_y, sectp->sct_own));
+           gift(sectp->sct_own, player->cnum, &pln, buf);
+           putplane(pln.pln_uid, &pln);
        }
-       *nunitsp += loaded;
-       return 0;
+       pr("%s %s %s at %s.\n",
+          prplane(&pln),
+          (load_unload == UNLOAD) ?
+          "unloaded from" : "loaded onto",
+          prland(lp), xyas(lp->lnd_x, lp->lnd_y, player->cnum));
+       loaded = 1;
+    }
+    *nunitsp += loaded;
+    return 0;
 }
 
 static int
-load_comm_land(struct sctstr *sectp, struct lndstr *lp, struct ichrstr *ich, int load_unload, int *nunitsp)
+load_comm_land(struct sctstr *sectp, struct lndstr *lp,
+              struct ichrstr *ich, int load_unload, int *nunitsp)
 {
-       register int item = ich->i_vtype;
-       register int max_amt;
-       register int move_amt;
-       register int land_amt;
-       register int sect_amt;
-       int     amount;
-       int     upto=0, abs_max;
-       s_char  prompt[512];
-       s_char  *p;
-       s_char  buf[1024];
-
-       sprintf(prompt, "Number of %s to %s %s at %s? ",
-               ich->i_name,
-               (load_unload==UNLOAD)?
-               "unload from":"load onto",
-               prland(lp),
-               xyas(lp->lnd_x, lp->lnd_y, player->cnum));
-       if (!(p = getstarg(player->argp[3], prompt, buf)) ||
-           !*p)
-               return RET_SYN;
-
-       if (!still_ok_land(sectp, lp))
-           return RET_SYN;
-
-       amount = atoi(p);
-       if (amount < 0) {
-               /* We want to load up to this amount */
-               upto = -(amount);
-               load_unload = LOAD;
-       } else if (!amount)
-               return 0;
+    i_type item = ich->i_uid;
+    struct lchrstr *lcp = &lchr[(int)lp->lnd_type];
+    int land_amt, sect_amt, move_amt;
+    char prompt[512];
+    char *p;
+    char buf[1024];
+
+    sprintf(prompt, "Number of %s to %s %s at %s? ",
+           ich->i_name,
+           (load_unload == UNLOAD) ?
+           "unload from" : "load onto",
+           prland(lp), xyas(lp->lnd_x, lp->lnd_y, player->cnum));
+    p = getstarg(player->argp[3], prompt, buf);
+    if (!p || !*p)
+       return RET_SYN;
 
-       if (sectp->sct_own != player->cnum && load_unload == LOAD) {
-               pr("Sector %s is not yours.\n",
-                  xyas(lp->lnd_x, lp->lnd_y, player->cnum));
-               return 0;
-       }
+    if (!still_ok_land(sectp, lp))
+       return RET_SYN;
 
-       land_amt = getvar(item, (s_char *)lp, EF_LAND);
-       sect_amt = getvar(item, (s_char *)sectp, EF_SECTOR);
-       if (sectp->sct_oldown != player->cnum && item == V_CIVIL) {
-               pr("%s civilians refuse to %s at %s!\n",
-                  load_unload == UNLOAD ? "Your" : "Foreign",
-                  load_unload == UNLOAD ?
-                  "disembark" : "board",
-                  xyas(sectp->sct_x, sectp->sct_y, player->cnum));
-               return 0;
+    land_amt = lp->lnd_item[item];
+    sect_amt = sectp->sct_item[item];
+    move_amt = move_amount(sect_amt, land_amt, lcp->l_item[item],
+                          load_unload, atoi(p));
+    if (!load_comm_ok(sectp, lp->lnd_own, item, move_amt))
+       return RET_OK;
+    sectp->sct_item[item] = sect_amt - move_amt;
+    lp->lnd_item[item] = land_amt + move_amt;
+
+    /* Did we put mils onto this unit? If so, reset the fortification */
+    if (item == I_MILIT && move_amt > 0)
+       lp->lnd_harden = 0;
+
+    if (move_amt >= 0) {
+       pr("%d %s loaded onto %s at %s\n",
+          move_amt, ich->i_name,
+          prland(lp), xyas(lp->lnd_x, lp->lnd_y, player->cnum));
+       if (lp->lnd_own != player->cnum) {
+           wu(0, lp->lnd_own, "%s loaded %d %s onto %s at %s\n",
+              cname(player->cnum), move_amt, ich->i_name,
+              prland(lp), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own));
        }
-       if (load_unload == UNLOAD) {
-               abs_max = max_amt = min(9999 - sect_amt, land_amt);
-       } else {
-               struct lchrstr *vbase;
-               vbase = &lchr[(int)lp->lnd_type];
-               abs_max = max_amt = vl_find(item, vbase->l_vtype,
-                                           vbase->l_vamt, (int) vbase->l_nv);
-               max_amt = min(sect_amt, max_amt - land_amt);
+    } else {
+       pr("%d %s unloaded from %s at %s\n",
+          -move_amt, ich->i_name,
+          prland(lp), xyas(lp->lnd_x, lp->lnd_y, player->cnum));
+       if (sectp->sct_own != player->cnum) {
+           wu(0, sectp->sct_own, "%s unloaded %d %s from %s at %s\n",
+              cname(player->cnum), -move_amt, ich->i_name,
+              prland(lp), xyas(lp->lnd_x, lp->lnd_y, sectp->sct_own));
        }
-       if ((max_amt <= 0) && (upto == 0))
-               return 0;
-       if (upto){
-               move_amt = upto - land_amt;
-               if (land_amt+move_amt > abs_max)
-                       move_amt = abs_max - land_amt;
-               if (move_amt > sect_amt)
-                       move_amt = sect_amt;
-       }else
-               move_amt = load_unload * min(amount, max_amt);
-       if (move_amt == 0)
-               return 0;
-       putvar(item, sect_amt - move_amt, (s_char *)sectp, EF_SECTOR);
-       putvar(item, land_amt + move_amt, (s_char *)lp, EF_LAND);
-
-       /* Did we put mils onto this unit? If so, reset the fortification */
-       if (item == V_MILIT && move_amt > 0)
-           lp->lnd_harden = 0;
-       if (load_unload == LOAD) {
-               pr("%d %s loaded onto %s at %s\n",
-                  move_amt,
-                  ich->i_name,
-                  prland(lp),
-                  xyas(lp->lnd_x, lp->lnd_y, player->cnum));
-               if (lp->lnd_own != player->cnum) {
-                       sprintf(buf,"%s loaded %d %s onto %s at %s\n",
-                               cname(player->cnum),
-                               move_amt,
-                               ich->i_name,
-                               prland(lp),
-                               xyas(lp->lnd_x, lp->lnd_y,
-                                    lp->lnd_own));
-                       wu(0, lp->lnd_own, buf);
-               }
-       } else {
-               pr("%d %s unloaded from %s at %s\n",
-                  -move_amt,
-                  ich->i_name,
-                  prland(lp),
-                  xyas(lp->lnd_x, lp->lnd_y, player->cnum));
-               if (sectp->sct_own != player->cnum) {
-                       sprintf(buf,"%s unloaded %d %s from %s at %s\n",
-                               cname(player->cnum),
-                               -move_amt,
-                               ich->i_name,
-                               prland(lp),
-                               xyas(lp->lnd_x, lp->lnd_y,
-                                    sectp->sct_own));
-                       wu(0, sectp->sct_own, buf);
-               }
-       }
-
-       ++(*nunitsp);
-       return 0;
+    }
+    ++*nunitsp;
+    return 0;
 }
 
 static int
-load_land_land(struct sctstr *sectp, struct lndstr *lp, int noisy, int load_unload, int *nunitsp)
+load_land_land(struct sctstr *sectp, struct lndstr *lp, int noisy,
+              int load_unload, int *nunitsp)
 {
-       struct  nstr_item pni, ni;
-       struct  lndstr land;
-       struct  plnstr plane;
-       int     loaded = 0;
-       s_char  *p;
-       s_char  prompt[512];
-       s_char  buf[1024];
-
-       lnd_count_units(lp);
-
-       if (load_unload==LOAD &&
-           lp->lnd_nland >= lp->lnd_maxland) {
-               if (noisy) {
-                       if (lp->lnd_nland)
-                               pr("%s doesn't have room for any more land units!\n",prland(lp));
-                       else
-                               pr("%s cannot carry land units!\n",prland(lp));
-               }
-               return 0;
+    struct nstr_item ni;
+    struct lndstr land;
+    int loaded = 0;
+    char *p;
+    char prompt[512];
+    char buf[1024];
+
+    if (load_unload == LOAD
+       && lnd_nland(lp) >= lchr[lp->lnd_type].l_nland) {
+       if (noisy) {
+           if (lchr[lp->lnd_type].l_nland)
+               pr("%s doesn't have room for any more land units!\n",
+                  prland(lp));
+           else
+               pr("%s cannot carry land units!\n", prland(lp));
        }
-       sprintf(prompt, "Land unit(s) to %s %s? ",
-               load_unload==LOAD?"load onto":"unload from",
-               prland(lp));
-       if (!snxtitem(&ni, EF_LAND, p=getstarg(player->argp[3], prompt, buf)))
-               return RET_SYN;
-
-       if (!still_ok_land(sectp, lp))
-           return RET_SYN;
-
-       if (p && *p)
-               noisy &= isdigit(*p);
-
-       while(nxtitem(&ni, (s_char *)&land)) {
-                       
-               if (land.lnd_own != player->cnum)
-                       continue;
-               
-               if (load_unload == LOAD) {
-                 if (land.lnd_ship > -1) {
-                   if (noisy)
-                     pr("%s is already on ship #%d!\n",
-                        prland(&land), land.lnd_ship);
-                   continue;
-                 }
-                 if (land.lnd_land > -1) {
-                   if (noisy)
-                     pr("%s is already on land #%d!\n",
-                        prland(&land), land.lnd_land);
-                   continue;
-                 }
-                 lnd_count_units(&land);
-                 if (land.lnd_nland > 0) {
-                   if (noisy)
-                     pr("%s cannot be loaded since it is carrying units\n",
-                        prland(&land));
-                   continue;
-                 }
-                 if (land.lnd_uid == lp->lnd_uid) {
-                   if (noisy)
-                     pr("%s can't be loaded onto itself!\n", prland(&land));
-                   continue;
-                 }
-                 if (lchr[(int)land.lnd_type].l_flags & L_HEAVY) {
-                   if (noisy)
-                     pr("%s is too heavy to load.\n", prland(&land));
-                   continue;
-                 }
-               }
+       return 0;
+    }
+    sprintf(prompt, "Land unit(s) to %s %s? ",
+           load_unload == LOAD ? "load onto" : "unload from", prland(lp));
+    p = getstarg(player->argp[3], prompt, buf);
+    if (!p)
+       return RET_SYN;
+    if (!snxtitem(&ni, EF_LAND, p, NULL))
+       return RET_SYN;
+
+    if (!still_ok_land(sectp, lp))
+       return RET_SYN;
+
+    if (noisy && p && *p)
+       noisy = isdigit(*p);
+
+    while (nxtitem(&ni, &land)) {
+       if (!player->owner)
+           continue;
+
+       if (load_unload == LOAD) {
+           if (land.lnd_ship > -1) {
+               if (noisy)
+                   pr("%s is already on ship #%d!\n",
+                      prland(&land), land.lnd_ship);
+               continue;
+           }
+           if (land.lnd_land > -1) {
+               if (noisy)
+                   pr("%s is already on land #%d!\n",
+                      prland(&land), land.lnd_land);
+               continue;
+           }
+           if (lnd_first_on_land(&land) >= 0) {
+               if (noisy)
+                   pr("%s cannot be loaded since it is carrying units\n",
+                      prland(&land));
+               continue;
+           }
+           if (land.lnd_uid == lp->lnd_uid) {
+               if (noisy)
+                   pr("%s can't be loaded onto itself!\n", prland(&land));
+               continue;
+           }
+           if (lchr[(int)land.lnd_type].l_flags & (L_HEAVY | L_TRAIN)) {
+               if (noisy)
+                   pr("%s is too heavy to load.\n", prland(&land));
+               continue;
+           }
+       }
+
+       /* Unit sanity done */
+       /* Find the right ship */
+       if (load_unload == UNLOAD) {
+           if (land.lnd_land != lp->lnd_uid)
+               continue;
+           if (land.lnd_ship > -1)
+               continue;
+       } else if (lp->lnd_x != land.lnd_x || lp->lnd_y != land.lnd_y)
+           continue;
 
-               /* Unit sanity done */
-               /* Find the right ship */
-               if (load_unload == UNLOAD) {
-                       if (land.lnd_land != lp->lnd_uid)
-                               continue;
-                       if (land.lnd_ship > -1)
-                               continue;
-               } else if (lp->lnd_x != land.lnd_x
-                          || lp->lnd_y != land.lnd_y)
-                       continue;
-
-               /* Fit unit on ship */
-               if (load_unload == LOAD) {
-                       lnd_count_units(lp);
-                       if (lp->lnd_nland >= lp->lnd_maxland) {
-                               if (noisy) {
-                                       if (lp->lnd_nland)
-                                               pr("%s doesn't have room for any more land units!\n",prland(lp));
-                                       else
-                                               pr("%s cannot carry land units!\n",prland(lp));
-                               }
-                               break;
-                       }
-                       sprintf(buf, "loaded on your %s at %s",
-                               prland(lp),xyas(lp->lnd_x,lp->lnd_y,
-                                                  lp->lnd_own));
-                       gift(lp->lnd_own,player->cnum,(s_char *)&land,
-                            EF_LAND, buf);
-                       makelost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y);
-                       land.lnd_own = lp->lnd_own;
-                       makenotlost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y);
-                       land.lnd_land = lp->lnd_uid;
-                       land.lnd_harden = 0;
-                       land.lnd_mission = 0;
-                       resupply_all(&land);
-                       lp->lnd_nland++;
-                       putland(land.lnd_uid,&land);
-                       if (!has_supply(&land))
-                               pr("WARNING: %s is out of supply!\n",
-                                  prland(&land));
-                       putland(lp->lnd_uid,lp);
-                       snxtitem_xy(&pni,EF_PLANE,land.lnd_x,land.lnd_y);
-                       while (nxtitem(&pni, (s_char *)&plane)){
-                               if (plane.pln_flags & PLN_LAUNCHED)
-                                       continue;
-                               if (plane.pln_land != land.lnd_uid)
-                                       continue;
-                               sprintf(buf, "loaded on %s",
-                                       prland(lp));
-                               gift(lp->lnd_own,player->cnum,(s_char *)&plane,
-                                    EF_PLANE, buf);
-                               makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y);
-                               plane.pln_own = lp->lnd_own;
-                               makenotlost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y);
-                               plane.pln_mission = 0;
-                               putplane(plane.pln_uid,&plane);
-                       }
-               } else {
-                       sprintf(buf, "unloaded in your %s at %s",
-                               dchr[sectp->sct_type].d_name,
-                               xyas(sectp->sct_x,sectp->sct_y,
-                                    sectp->sct_own));
-                       gift(sectp->sct_own,player->cnum,(s_char *)&land,
-                            EF_LAND, buf);
-                       makelost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y);
-                       land.lnd_own = sectp->sct_own;
-                       makenotlost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y);
-                       land.lnd_land = (-1);
-                       lp->lnd_nland--;
-                       putland(land.lnd_uid,&land);
-                       putland(lp->lnd_uid,lp);
-                       snxtitem_xy(&pni,EF_PLANE,land.lnd_x,land.lnd_y);
-                       while (nxtitem(&pni, (s_char *)&plane)){
-                               if (plane.pln_flags & PLN_LAUNCHED)
-                                       continue;
-                               if (plane.pln_land != land.lnd_uid)
-                                       continue;
-                               sprintf(buf, "unloaded at %s",
-                                       xyas(plane.pln_x,plane.pln_y,
-                                            sectp->sct_own));
-                               gift(sectp->sct_own,player->cnum,(s_char *)&plane,
-                                    EF_PLANE, buf);
-                               makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y);
-                               plane.pln_own = sectp->sct_own;
-                               makenotlost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y);
-                               plane.pln_mission = 0;
-                               putplane(plane.pln_uid,&plane);
-                       }
+       /* Fit unit on ship */
+       if (load_unload == LOAD) {
+           if (lnd_nland(lp) >= lchr[lp->lnd_type].l_nland) {
+               if (noisy) {
+                   if (lchr[lp->lnd_type].l_nland)
+                       pr("%s doesn't have room for any more land units!\n",
+                          prland(lp));
+                   else
+                       pr("%s cannot carry land units!\n", prland(lp));
                }
-               pr("%s %s %s at %s.\n",
-                  prland(&land),
-                  (load_unload==UNLOAD)?
-                  "unloaded from":"loaded onto",
-                  prland(lp),
-                  xyas(lp->lnd_x, lp->lnd_y, player->cnum));
-               loaded = 1;
+               break;
+           }
+           sprintf(buf, "loaded on your %s at %s",
+                   prland(lp), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own));
+           gift(lp->lnd_own, player->cnum, &land, buf);
+           land.lnd_land = lp->lnd_uid;
+           land.lnd_harden = 0;
+           putland(land.lnd_uid, &land);
+#if 0
+          /* FIXME same issue as in load_land_ship() */
+           if (!lnd_supply_all(&land))
+               pr("WARNING: %s is out of supply!\n", prland(&land));
+#else
+           if (!lnd_in_supply(&land))
+               pr("WARNING: %s is out of supply!\n", prland(&land));
+#endif
+       } else {
+           sprintf(buf, "unloaded in your %s at %s",
+                   dchr[sectp->sct_type].d_name,
+                   xyas(sectp->sct_x, sectp->sct_y, sectp->sct_own));
+           gift(sectp->sct_own, player->cnum, &land, buf);
+           land.lnd_land = -1;
+           putland(land.lnd_uid, &land);
        }
-       *nunitsp += loaded;
-       return 0;
+       pr("%s %s %s at %s.\n",
+          prland(&land),
+          (load_unload == UNLOAD) ?
+          "unloaded from" : "loaded onto",
+          prland(lp), xyas(lp->lnd_x, lp->lnd_y, player->cnum));
+       loaded = 1;
+    }
+    *nunitsp += loaded;
+    return 0;
 }
-