]> git.pond.sub.org Git - empserver/blobdiff - src/lib/commands/mfir.c
Update copyright notice.
[empserver] / src / lib / commands / mfir.c
index f9e935a834de131f2c2cb02e61dc6a15902ed354..d205618886298e97fa48ef6a69190e1d7ca7fa76 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2004, 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.
  *
  *  ---
  *
  * 
  *  Known contributors to this file:
  *     Steve McClure, 2000
- *     
  */
 
-#include "misc.h"
-#include "player.h"
-#include "xy.h"
-#include "treaty.h"
-#include "nat.h"
-#include "ship.h"
-#include "land.h"
-#include "sect.h"
-#include "retreat.h"
-#include "news.h"
-#include "nsc.h"
-#include "file.h"
-#include "queue.h"
-#include <ctype.h>
-#include "options.h"
-#include "optlist.h"
-#include "damage.h"
+#include <config.h>
+
 #include "commands.h"
+#include "damage.h"
+#include "empobj.h"
+#include "optlist.h"
+#include "retreat.h"
 
 enum targ_type {
     targ_land, targ_ship, targ_sub, targ_unit, targ_bogus
@@ -64,12 +52,6 @@ struct flist {
     int victim;                        /* who I was shooting at */
 };
 
-union item_u {
-    struct shpstr ship;
-    struct sctstr sect;
-    struct lndstr land;
-};
-
 static void add_to_fired_queue(struct emp_qelem *, struct emp_qelem *);
 static int defend(struct emp_qelem *al,
                  struct emp_qelem *dl,
@@ -87,10 +69,11 @@ static void use_ammo(struct emp_qelem *);
 int
 multifire(void)
 {
-    s_char vbuf[20];
-    s_char *ptr;
-    double range2, range;
-    int trange;
+    static int ef_with_guns[] = { EF_SECTOR, EF_SHIP, EF_LAND, EF_BAD };
+    char vbuf[20];
+    char *ptr;
+    double range;
+    int trange, range2;
     coord fx;
     coord fy;
     coord x;
@@ -116,40 +99,35 @@ multifire(void)
     struct natstr *natp;
     struct nstr_item nbst;
     int type;
-    s_char *p;
+    char *p;
     int nfiring = 0;
     int ndefending = 0;
-    union item_u item;
+    union empobj_storage item;
     struct emp_qelem fired, defended;
     double odds;
-    s_char buf[1024];
-#if defined(_WIN32)
-    time_t now;
-#endif
+    char buf[1024];
 
     emp_initque(&fired);
     emp_initque(&defended);
-    type = (-1);
-    while ((type != EF_SECTOR) && (type != EF_SHIP) && (type != EF_LAND)) {
-       if (!(p = getstarg(player->argp[1],
-                          "Firing from ship(s), sect(s), or land unit(s)? ",
-                          buf)))
-           return RET_SYN;
-       player->argp[1] = 0;
-       type = ef_byname(p);
-       if (type == EF_SECTOR) {
-           if (opt_NO_FORT_FIRE) {
-               pr("Fort firing is disabled.\n");
-               return RET_FAIL;
-           }
-           orig_attacker = attacker = targ_land;
-           shots = 1;
-       } else if (type == EF_SHIP) {
-           orig_attacker = attacker = targ_ship;
-       } else if (type == EF_LAND) {
-           orig_attacker = attacker = targ_unit;
-       } else
-           pr("Please type 'sh', 'l', or 'se'!\n");
+    if (!(p = getstarg(player->argp[1],
+                      "Firing from ship(s), sect(s), or land unit(s)? ",
+                      buf)))
+       return RET_SYN;
+    type = ef_byname_from(p, ef_with_guns);
+    if (type == EF_SECTOR) {
+       if (opt_NO_FORT_FIRE) {
+           pr("Fort firing is disabled.\n");
+           return RET_FAIL;
+       }
+       orig_attacker = attacker = targ_land;
+       shots = 1;
+    } else if (type == EF_SHIP) {
+       orig_attacker = attacker = targ_ship;
+    } else if (type == EF_LAND) {
+       orig_attacker = attacker = targ_unit;
+    } else {
+       pr("Ships, land units or sectors only!\n");
+       return RET_SYN;
     }
     if ((ptr = getstarg(player->argp[2], "Firing from? ", buf)) == 0
        || *ptr == '\0')
@@ -162,7 +140,7 @@ multifire(void)
        pr("Fire aborted.\n");
        return RET_OK;
     }
-    while (nxtitem(&nbst, (s_char *)&item)) {
+    while (nxtitem(&nbst, &item)) {
        attacker = orig_attacker;
        if (attacker == targ_unit) {
            if (!getland(item.land.lnd_uid, &fland))
@@ -176,7 +154,7 @@ multifire(void)
                pr("Unit %d cannot fire!\n", fland.lnd_uid);
                continue;
            }
-           if (lnd_getmil(&fland) < 1) {
+           if (fland.lnd_item[I_MILIT] < 1) {
                pr("Unit %d cannot fire because it has no military!\n",
                   fland.lnd_uid);
                continue;
@@ -192,7 +170,8 @@ multifire(void)
                continue;
            }
            if (fland.lnd_effic < LAND_MINFIREEFF) {
-               pr("Unit %d cannot fire because it is less than %d%% efficient\n", fland.lnd_uid, LAND_MINFIREEFF);
+               pr("Unit %d cannot fire because it is less than %d%% efficient\n",
+                  fland.lnd_uid, LAND_MINFIREEFF);
                continue;
            }
            resupply_commod(&fland, I_SHELL);   /* Get more shells */
@@ -211,7 +190,7 @@ multifire(void)
                continue;
            }
            gun = item.ship.shp_item[I_GUN];
-           gun = min(gun, item.ship.shp_glim);
+           gun = MIN(gun, item.ship.shp_glim);
            if (item.ship.shp_frnge == 0) {
                pr("Ships %d cannot fire guns!\n", item.ship.shp_uid);
                continue;
@@ -236,7 +215,7 @@ multifire(void)
                continue;
            if (item.sect.sct_type != SCT_FORTR)
                continue;
-           if (item.sect.sct_effic < ((u_char)FORTEFF)) {
+           if (item.sect.sct_effic < FORTEFF) {
                pr("Fort not efficient enough to fire!\n");
                continue;
            }
@@ -330,49 +309,47 @@ multifire(void)
                continue;
            }
            gun = fship.shp_item[I_GUN];
-           gun = min(gun, fship.shp_glim);
+           gun = MIN(gun, fship.shp_glim);
            if (fship.shp_frnge == 0 || gun == 0) {
                pr("Insufficient arms.\n");
                continue;
            }
            shell = fship.shp_item[I_SHELL];
            if (shell < 2)
-               shell += supply_commod(fship.shp_own, fship.shp_x,
-                                      fship.shp_y, I_SHELL, 2 - shell);
+               shell += supply_commod(fship.shp_own,
+                                      fship.shp_x, fship.shp_y,
+                                      I_SHELL, 2 - shell);
            if (shell <= 0) {
                pr("Klick!     ...\n");
                continue;
            }
            if (fship.shp_effic < 60) {
-               pr("Ship #%d is crippled (%d%%)\n", fshipno,
-                  fship.shp_effic);
+               pr("Ship #%d is crippled (%d%%)\n",
+                  fshipno, fship.shp_effic);
                continue;
            }
-           range = techfact(fship.shp_tech,
-                            (double)fship.shp_frnge / 2.0);
-           range2 = (double)roundrange(range);
-           pr("range is %.2f (%.2f)\n", range2, range);
+           range = effrange(fship.shp_frnge, fship.shp_tech);
+           range2 = roundrange(range);
+           pr("range is %d.00 (%.2f)\n", range2, range);
            if (target == targ_sub) {
                if ((mchr[(int)fship.shp_type].m_flags & M_DCH) == 0) {
-                   pr("A %s can't drop depth charges!\n",
-                      mchr[(int)fship.shp_type].m_name);
-                   continue;
-               }
-               if (shell < 2) {
+                   /* Don't tell it's a sub */
+                   range2 = -1;
+               } else if (shell < 2) {
                    pr("Not enough shells for depth charge!\n");
                    continue;
                }
            }
-           gun = min(gun, shell * 2);
-           gun = min(gun, mil / 2);
-           gun = max(gun, 1);
+           gun = MIN(gun, shell * 2);
+           gun = MIN(gun, mil / 2);
+           gun = MAX(gun, 1);
            shots = gun;
            guneff = seagun(fship.shp_effic, shots);
            dam = (int)guneff;
-           shell -= ldround(((double)shots) / 2.0, 1);
+           shell -= ldround(shots / 2.0, 1);
            fship.shp_item[I_SHELL] = shell;
            if (opt_NOMOBCOST == 0)
-               fship.shp_mobil = max(fship.shp_mobil - 15, -100);
+               fship.shp_mobil = MAX(fship.shp_mobil - 15, -100);
            putship(fship.shp_uid, &fship);
        } else if (attacker == targ_unit) {
            if (fland.lnd_own != player->cnum) {
@@ -402,14 +379,12 @@ multifire(void)
 
            shell = fland.lnd_item[I_SHELL];
 
-           range = techfact((int)fland.lnd_tech,
-                            (double)fland.lnd_frg / 2.0);
-           range2 = (double)roundrange(range);
-           pr("range is %.2f (%.2f)\n", range2, range);
+           range = effrange(fland.lnd_frg, fland.lnd_tech);
+           range2 = roundrange(range);
+           pr("range is %d.00 (%.2f)\n", range2, range);
            if (target == targ_sub) {
-               pr("A %s can't drop depth charges!\n",
-                  lchr[(int)fland.lnd_type].l_name);
-               continue;
+               /* Don't tell it's a sub */
+               range2 = -1;
            }
 
            gun = fland.lnd_item[I_GUN];
@@ -421,8 +396,8 @@ multifire(void)
            dam = (int)landunitgun(fland.lnd_effic, fland.lnd_dam, gun,
                                   fland.lnd_ammo, shell);
            if (target == targ_ship) {
-               if (chance(((double)fland.lnd_acc) / 100.0))
-                   dam = ldround(((double)dam / 2.0), 1);
+               if (chance(fland.lnd_acc / 100.0))
+                   dam = ldround(dam / 2.0, 1);
            }
            use_supply(&fland);
            resupply_commod(&fland, I_SHELL);   /* Get more shells */
@@ -432,8 +407,8 @@ multifire(void)
            fy = fsect.sct_y;
            if (fsect.sct_own != player->cnum ||
                fsect.sct_type != SCT_FORTR) {
-               pr("No fortress at %s\n", xyas(fsect.sct_x,
-                                              fsect.sct_y, player->cnum));
+               pr("No fortress at %s\n",
+                  xyas(fsect.sct_x, fsect.sct_y, player->cnum));
                continue;
            }
            if (target == targ_land) {
@@ -450,8 +425,9 @@ multifire(void)
            }
            shell = fsect.sct_item[I_SHELL];
            if (shell <= 0)
-               shell += supply_commod(fsect.sct_own, fsect.sct_x,
-                                      fsect.sct_y, I_SHELL, 1);
+               shell += supply_commod(fsect.sct_own,
+                                      fsect.sct_x, fsect.sct_y,
+                                      I_SHELL, 1);
            if (shell <= 0) {
                pr("Klick!     ...\n");
                continue;
@@ -460,17 +436,15 @@ multifire(void)
                pr("Not enough military for firing crew.\n");
                continue;
            }
-           if (target == targ_sub) {
-               pr("Target ship not sighted!\n");
-               continue;
-           }
            if (gun > 7)
                gun = 7;
-           range = tfactfire(player->cnum, 7.0);
-           if (fsect.sct_effic > 59)
-               range++;
-           range2 = (double)roundrange(range);
-           pr("range is %.2f (%.2f)\n", range2, range);
+           range = fortrange(&fsect);
+           range2 = roundrange(range);
+           pr("range is %d.00 (%.2f)\n", range2, range);
+           if (target == targ_sub) {
+               /* Don't tell it's a sub */
+               range2 = -1;
+           }
            guneff = landgun((int)fsect.sct_effic, gun);
            dam = (int)guneff;
            shell--;
@@ -558,21 +532,12 @@ multifire(void)
        default:
            pr_beep();
            pr("Kaboom!!!\n");
-           prb = (double)(range2 ? (trange / range2) : 1.0);
+           prb = range2 ? (double)trange / range2 : 1.0;
            prb *= prb;
-#if !defined(_WIN32)
-           srandom(random());
-#else
-           (void)time(&now);
-           (void)srand(now);
-#endif
            if (chance(prb)) {
                pr("Wind deflects shell%s.\n", splur(shots));
-/*                     dam = (int)((double)dam / 2.0);*/
-               dam =
-                   (int)((double)dam *
-                         (double)((double)(90 - (random() % 11)) /
-                                  100.0));
+/*                     dam = (int)(dam / 2.0);*/
+               dam *= (90 - (random() % 11)) / 100.0;
                if (dam < 0)
                    dam = 0;
            }
@@ -636,7 +601,7 @@ multifire(void)
            break;
        }
        if ((totaldefdam == 0) && (target == targ_ship))
-           if (vship.shp_rflags & RET_INJURED)
+           if (vship.shp_rflags & RET_HELPLESS)
                retreat_ship(&vship, 'h');
        switch (attacker) {
        case targ_land:
@@ -687,7 +652,7 @@ defend(struct emp_qelem *al, struct emp_qelem *dl, enum targ_type target,
        (dam = quiet_bigdef(attacker, dl, vict, aown, fx, fy, &nfiring))) {
        if (nfiring > *nd)
            *nd = nfiring;
-       fp = (struct flist *)malloc(sizeof(struct flist));
+       fp = malloc(sizeof(struct flist));
        memset(fp, 0, sizeof(struct flist));
        fp->defdam = dam;
        fp->victim = vict;
@@ -705,7 +670,7 @@ defend(struct emp_qelem *al, struct emp_qelem *dl, enum targ_type target,
        emp_insque(&fp->queue, al);
     }
 
-    return (dam);
+    return dam;
 }
 
 static void
@@ -730,7 +695,7 @@ do_defdam(struct emp_qelem *list, double odds)
            pr("\nDefenders fire back!\n");
            first = 0;
        }
-       dam = (odds * (double)fp->defdam);
+       dam = odds * fp->defdam;
 
        if (fp->type == targ_ship) {
            vict = fp->victim;
@@ -755,7 +720,7 @@ do_defdam(struct emp_qelem *list, double odds)
                   xyas(fp->x, fp->y, vict), dam);
        }
        emp_remque(&fp->queue);
-       free((s_char *)fp);
+       free(fp);
     }
 }
 
@@ -763,13 +728,12 @@ static int
 quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
             coord ax, coord ay, int *nfiring)
 {
-    int nshot;
-    double range, erange, hitchance;
+    int nshot, range;
+    double erange, hitchance;
     struct shpstr ship;
     struct lndstr land;
     struct nstr_item ni;
     int dam, dam2, rel, rel2;
-    double tech;
     struct sctstr firing;
     struct nstr_sect ns;
     struct flist *fp;
@@ -805,7 +769,8 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
 
        if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
            if (shell < SHP_TORP_SHELLS)
-               shell += supply_commod(ship.shp_own, ship.shp_x, ship.shp_y,
+               shell += supply_commod(ship.shp_own,
+                                      ship.shp_x, ship.shp_y,
                                       I_SHELL, SHP_TORP_SHELLS - shell);
            if (shell < SHP_TORP_SHELLS)
                continue;
@@ -815,18 +780,15 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
   if (ship.shp_mobil <= 0)
   continue;
 */
-           erange = ship.shp_effic *
-               techfact(ship.shp_tech, ((double)ship.shp_frnge))
-               / 100.0;
-           erange = (double)roundrange(erange);
+           erange = torprange(&ship);
            range = mapdist(ship.shp_x, ship.shp_y, ax, ay);
-           if (range > erange)
+           if (range > roundrange(erange))
                continue;
-           if (!line_of_sight((s_char **)0, ship.shp_x, ship.shp_y, ax, ay))
+           if (!line_of_sight(NULL, ship.shp_x, ship.shp_y, ax, ay))
                continue;
 
            (*nfiring)++;
-           fp = (struct flist *)malloc(sizeof(struct flist));
+           fp = malloc(sizeof(struct flist));
            memset(fp, 0, sizeof(struct flist));
            fp->type = targ_ship;
            fp->uid = ship.shp_uid;
@@ -840,24 +802,22 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
 
            dam += TORP_DAMAGE();
        } else {
-           range = techfact(ship.shp_tech,
-                            ship.shp_frnge * ship.shp_effic / 200.0);
-           range = (double)roundrange(range);
-           if (range < ni.curdist)
+           erange = effrange(ship.shp_frnge, ship.shp_tech);
+           if (roundrange(erange) < ni.curdist)
                continue;
            /* must have gun, shell, and milit to fire */
            if (shell < 1)
-               shell += supply_commod(ship.shp_own, ship.shp_x, ship.shp_y,
-                                      I_SHELL, 1);
+               shell += supply_commod(ship.shp_own,
+                                      ship.shp_x, ship.shp_y, I_SHELL, 1);
            /* only need 1 shell, so don't check that */
            if (shell < 1)
                continue;
-           nshot = min(gun, ship.shp_item[I_MILIT]);
-           nshot = min(nshot, ship.shp_glim);
+           nshot = MIN(gun, ship.shp_item[I_MILIT]);
+           nshot = MIN(nshot, ship.shp_glim);
            if (nshot == 0)
                continue;
            (*nfiring)++;
-           fp = (struct flist *)malloc(sizeof(struct flist));
+           fp = malloc(sizeof(struct flist));
            memset(fp, 0, sizeof(struct flist));
            fp->type = targ_ship;
            fp->uid = ship.shp_uid;
@@ -878,7 +838,7 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
        if (land.lnd_land >= 0)
            continue;
        /* Gotta have military */
-       if (lnd_getmil(&land) < 1)
+       if (land.lnd_item[I_MILIT] < 1)
            continue;
        /* Don't shoot yourself */
        if (land.lnd_own == aown)
@@ -890,10 +850,8 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
        if ((land.lnd_own != own) && ((rel != ALLIED) || (rel2 != AT_WAR)))
            continue;
 
-
-       range = techfact((int)land.lnd_tech, (double)land.lnd_frg / 2.0);
-       range = (double)roundrange(range);
-       if (range < ni.curdist)
+       erange = effrange(land.lnd_frg, land.lnd_tech);
+       if (roundrange(erange) < ni.curdist)
            continue;
 
        resupply_all(&land);
@@ -910,7 +868,7 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
                                land.lnd_ammo, shell);
 
        (*nfiring)++;
-       fp = (struct flist *)malloc(sizeof(struct flist));
+       fp = malloc(sizeof(struct flist));
        memset(fp, 0, sizeof(struct flist));
        fp->type = targ_unit;
        fp->uid = land.lnd_uid;
@@ -931,9 +889,6 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
     if (!opt_NO_FORT_FIRE) {
        snxtsct_dist(&ns, ax, ay, 8);
        while (nxtsct(&ns, &firing)) {
-
-           if (firing.sct_type != SCT_FORTR)
-               continue;
            if (firing.sct_own == 0)
                continue;
            rel = getrel(getnatp(firing.sct_own), own);
@@ -945,12 +900,8 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
            /* Don't shoot yourself */
            if (firing.sct_own == aown)
                continue;
-           tech = tfactfire(firing.sct_own, 1.0);
-           range = tech * 7.0;
-           if (firing.sct_effic > 59)  /* fort bonus */
-               range++;
-           range = (double)roundrange(range);
-           if (range < ns.curdist)
+           erange = fortrange(&firing);
+           if (roundrange(erange) < ns.curdist)
                continue;
 
            gun = firing.sct_item[I_GUN];
@@ -963,7 +914,7 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
            if (gun == 0 || firing.sct_item[I_MILIT] < 5 || shell == 0)
                continue;
            (*nfiring)++;
-           fp = (struct flist *)malloc(sizeof(struct flist));
+           fp = malloc(sizeof(struct flist));
            memset(fp, 0, sizeof(struct flist));
            fp->x = firing.sct_x;
            fp->y = firing.sct_y;
@@ -976,7 +927,7 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
        }
     }
 
-    return ((*nfiring) == 0 ? 0 : (dam / (*nfiring)));
+    return *nfiring == 0 ? 0 : dam / *nfiring;
 }
 
 static void
@@ -989,8 +940,6 @@ use_ammo(struct emp_qelem *list)
     struct sctstr sect;
     int shell;
     short *item;
-    double mobcost;
-    struct mchrstr *mcp;
 
     /* use 1 shell from everyone */
     for (qp = list->q_forw; qp != list; qp = next) {
@@ -1006,13 +955,8 @@ use_ammo(struct emp_qelem *list)
                    shell = 0;
                item[I_SHELL] = shell;
                putship(ship.shp_uid, &ship);
-               mcp = &mchr[(int)ship.shp_type];
-               mobcost = ship.shp_effic * 0.01 * ship.shp_speed;
-               mobcost = (480.0 / (mobcost +
-                                   techfact(ship.shp_tech, mobcost)));
                /* mob cost = 1/2 a sect's mob */
-               mobcost /= 2.0;
-               ship.shp_mobil -= mobcost;
+               ship.shp_mobil -= shp_mobcost(&ship) / 2.0;
            }
        } else if (fp->type == targ_land) {
            getsect(fp->x, fp->y, &sect);
@@ -1034,7 +978,7 @@ use_ammo(struct emp_qelem *list)
            putland(land.lnd_uid, &land);
 
        emp_remque(&fp->queue);
-       free((s_char *)fp);
+       free(fp);
     }
 
 }