]> git.pond.sub.org Git - empserver/blobdiff - src/lib/subs/attsub.c
Replace "roll0(N) + M" by "roll(N) + M-1"
[empserver] / src / lib / subs / attsub.c
index 9a6fb161b94255bbfa2c88e614518c602246cade..ef22fac45b158ebbf784344c0827b4094e0349fe 100644 (file)
@@ -1,11 +1,11 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2010, Dave Pare, Jeff Bailey, Thomas Ruschak,
- *                           Ken Stevens, Steve McClure
+ *  Copyright (C) 1986-2013, 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,
@@ -14,8 +14,7 @@
  *  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/>.
  *
  *  ---
  *
  *  Known contributors to this file:
  *     Ken Stevens, 1995
  *     Steve McClure, 1996-2000
- *     Markus Armbruster, 2006-2009
+ *     Markus Armbruster, 2006-2012
  */
 
 #include <config.h>
 
 #include <ctype.h>
 #include <math.h>
+#include "chance.h"
 #include "combat.h"
+#include "empobj.h"
 #include "file.h"
 #include "map.h"
 #include "misc.h"
 #include "mission.h"
+#include "news.h"
 #include "nsc.h"
 #include "optlist.h"
 #include "path.h"
 #include "plague.h"
 #include "player.h"
 #include "prototypes.h"
-#include "xy.h"
-#include "empobj.h"
 #include "unit.h"
+#include "xy.h"
 
 #define CASUALTY_LUMP  1       /* How big casualty chunks should be */
 
@@ -83,8 +84,8 @@ static void send_reacting_units_home(struct emp_qelem *list);
 static int take_def(int combat_mode, struct emp_qelem *list,
                    struct combat *off, struct combat *def);
 
-static int get_land(int combat_mode, struct combat *def,
-                   struct ulist *llp, int victim_land);
+static int get_oland(int, struct ulist *);
+static int get_dland(struct combat *, struct ulist *);
 
 char *att_mode[] = {
     /* must match combat types in combat.h */
@@ -285,16 +286,15 @@ att_get_combat(struct combat *com, int isdef)
                   mil);
            com->troops = mil;
        } else {                /* attacker */
-           if (owner != player->cnum
-               && getrel(getnatp(owner), player->cnum) != ALLIED) {
+           if (owner != com->own && owner != player->cnum) {
                /* must be EF_SECTOR */
-               if (com->mil)
+               if (com->troops)
                    pr("WARNING: Your %d mil in %s were destroyed because %s just took the sector!\n",
                       com->mil, xyas(com->x, com->y, player->cnum),
                       cname(owner));
                else
-                   pr("You no longer own %s\n",
-                      xyas(com->x, com->y, player->cnum));
+                   pr("%s just took %s!\n",
+                      cname(owner), xyas(com->x, com->y, player->cnum));
                return att_combat_init(com, EF_BAD);
            }
            if (com->troops && com->troops + 1 > mil) {
@@ -435,9 +435,6 @@ int
 att_abort(int combat_mode, struct combat *off, struct combat *def)
 {
     struct sctstr sect;
-    int rel;
-    char y_or_n[512];
-    struct natstr *natp;
 
     if (player->aborted)
        return 1;
@@ -513,23 +510,7 @@ att_abort(int combat_mode, struct combat *off, struct combat *def)
        setcont(player->cnum, def->own, FOUND_SPY);
        setcont(def->own, player->cnum, FOUND_SPY);
     }
-    if (opt_SLOW_WAR && def->own != player->cnum) {
-       natp = getnatp(player->cnum);
-       rel = getrel(natp, def->own);
-
-       if (rel == ALLIED) {
-           sprintf(y_or_n, "Sector is owned by %s, your ally, %s [yn]? ",
-                   cname(def->own), att_mode[combat_mode]);
-           if (!confirm(y_or_n))
-               return abort_attack();
 
-       }
-       if ((rel != AT_WAR) && (def->own) &&
-           (sect.sct_oldown != player->cnum)) {
-           pr("You're not at war with them!\n");
-           return abort_attack();
-       }
-    }
     return 0;
 }
 
@@ -1042,7 +1023,7 @@ ask_olist(int combat_mode, struct combat *off, struct combat *def,
             * of high-mobility sectors (mountains): for those we
             * still require attack mobility.
             */
-           pathcost = att_mobcost(off->own, def, lnd_mobtype(&land));
+           pathcost = att_mobcost(land.lnd_own, def, lnd_mobtype(&land));
            mobcost = lnd_pathcost(&land, pathcost);
            if (pathcost < 1.0) {
                if (land.lnd_mobil <= 0) {
@@ -1278,8 +1259,7 @@ get_ototal(int combat_mode, struct combat *off, struct emp_qelem *olist,
     for (qp = olist->q_forw; qp != olist; qp = next) {
        next = qp->q_forw;
        llp = (struct ulist *)qp;
-       if (check &&
-           !get_land(combat_mode, NULL, llp, 0))
+       if (check && !get_oland(combat_mode, llp))
            continue;
        if (combat_mode == A_ATTACK) {
            w = -1;
@@ -1291,7 +1271,9 @@ get_ototal(int combat_mode, struct combat *off, struct emp_qelem *olist,
                    w = n;
            }
            if (w < 0) {
-               lnd_delete(llp, "is in a sector not owned by you");
+               lnd_print(player->cnum, llp,
+                         "can't attack from this sector now");
+               lnd_delete(llp);
                continue;
            }
            ototal += attack_val(combat_mode, &llp->unit.land) *
@@ -1328,7 +1310,7 @@ get_dtotal(struct combat *def, struct emp_qelem *list, double dsupport,
     for (qp = list->q_forw; qp != list; qp = next) {
        next = qp->q_forw;
        llp = (struct ulist *)qp;
-       if (check && !get_land(A_DEFEND, def, llp, 1))
+       if (check && !get_dland(def, llp))
            continue;
        d_unit = defense_val(&llp->unit.land);
        if (!llp->supplied)
@@ -1342,63 +1324,66 @@ get_dtotal(struct combat *def, struct emp_qelem *list, double dsupport,
 }
 
 /*
- * This is the land unit integrity check.  Note that we don't print
- * warnings about victim land units because the attacker may not have seen them
+ * This is the land unit integrity check.
  */
 
 static int
-get_land(int combat_mode, struct combat *def, struct ulist *llp,
-        int victim_land)
+get_oland(int combat_mode, struct ulist *llp)
 {
     struct lndstr *lp = &llp->unit.land;
     char buf[512];
 
     getland(llp->unit.land.lnd_uid, lp);
 
-    if (lp->lnd_effic < LAND_MINEFF) {
+    if (lp->lnd_own != player->cnum) {
        sprintf(buf, "was destroyed and is no longer a part of the %s",
                att_mode[combat_mode]);
-       lnd_delete(llp, buf);
+       lnd_print(player->cnum, llp, buf);
+       lnd_delete(llp);
        return 0;
     }
-    if (victim_land) {
-       if (lp->lnd_x != def->x || lp->lnd_y != def->y) {
-           lnd_delete(llp,
-                      "left to go fight another battle and is no longer a part of the defense");
-           return 0;
-       }
-    } else {
-       if (lp->lnd_own != player->cnum) {
-           sprintf(buf,
-                   "was destroyed and is no longer a part of the %s",
-                   att_mode[combat_mode]);
-           lnd_delete(llp, buf);
-           return 0;
-       }
-       if (lp->lnd_x != llp->x || lp->lnd_y != llp->y) {
-           sprintf(buf,
-                   "left to fight another battle and is no longer a part of the %s",
-                   att_mode[combat_mode]);
-           lnd_delete(llp, buf);
-           return 0;
-       }
-       if (lp->lnd_effic < llp->eff) {
-           sprintf(buf, "damaged from %d%% to %d%%",
-                   llp->eff, lp->lnd_effic);
-           lnd_print(llp, buf);
-       }
+    if (lp->lnd_x != llp->x || lp->lnd_y != llp->y) {
+       sprintf(buf,
+               "left to fight another battle and is no longer a part of the %s",
+               att_mode[combat_mode]);
+       lnd_print(player->cnum, llp, buf);
+       lnd_delete(llp);
+       return 0;
+    }
+    if (lp->lnd_effic < llp->eff) {
+       sprintf(buf, "damaged from %d%% to %d%%",
+               llp->eff, lp->lnd_effic);
+       lnd_print(player->cnum, llp, buf);
     }
-    llp->eff = llp->unit.land.lnd_effic;
 
+    llp->eff = llp->unit.land.lnd_effic;
     return 1;
 }
 
-/*
- * Put the land unit on the disk.  If there was some mobility cost, then
- * subtract it from the units mobility.  Note that this works the same way
- * as sectors & ships in that no mobility is actually taken until the attacker
- * has committed to attacking.
- */
+static int
+get_dland(struct combat *def, struct ulist *llp)
+{
+    struct lndstr *lp = &llp->unit.land;
+    char buf[512];
+
+    getland(llp->unit.land.lnd_uid, lp);
+
+    if (lp->lnd_effic < LAND_MINEFF) {
+       sprintf(buf, "was destroyed and is no longer a part of the defense");
+       lnd_print(llp->unit.land.lnd_own, llp, buf);
+       lnd_delete(llp);
+       return 0;
+    }
+    if (lp->lnd_x != def->x || lp->lnd_y != def->y) {
+       lnd_print(llp->unit.land.lnd_own, llp,
+                 "left to go fight another battle and is no longer a part of the defense");
+       lnd_delete(llp);
+       return 0;
+    }
+
+    llp->eff = llp->unit.land.lnd_effic;
+    return 1;
+}
 
 static void
 kill_land(struct emp_qelem *list)
@@ -1411,7 +1396,9 @@ kill_land(struct emp_qelem *list)
        llp = (struct ulist *)qp;
        if (llp->unit.land.lnd_ship >= 0) {
            llp->unit.land.lnd_effic = 0;
-           lnd_delete(llp, "cannot return to the ship, and dies!");
+           lnd_print(player->cnum, llp,
+                     "cannot return to the ship, and dies!");
+           lnd_delete(llp);
        }
     }
 }
@@ -1432,8 +1419,15 @@ att_infect_units(struct emp_qelem *list, int plague)
     }
 }
 
+/*
+ * Put the land unit on the disk.  If there was some mobility cost, then
+ * subtract it from the units mobility.  Note that this works the same way
+ * as sectors & ships in that no mobility is actually taken until the attacker
+ * has committed to attacking.
+ */
+
 static void
-put_land(struct emp_qelem *list)
+put_oland(struct emp_qelem *list)
 {
     struct emp_qelem *qp, *next;
     struct ulist *llp;
@@ -1450,7 +1444,7 @@ put_land(struct emp_qelem *list)
            emp_remque((struct emp_qelem *)llp);
            free(llp);
        } else
-           get_land(A_ATTACK, NULL, llp, 0);
+           get_oland(A_ATTACK, llp);
     }
 }
 
@@ -1465,7 +1459,6 @@ att_reacting_units(struct combat *def, struct emp_qelem *list, int a_spy,
 {
     struct nstr_item ni;
     struct lndstr land;
-    struct sctstr sect, dsect;
     struct ulist *llp;
     int dtotal;
     double new_land = 0;
@@ -1473,7 +1466,6 @@ att_reacting_units(struct combat *def, struct emp_qelem *list, int a_spy,
     double pathcost;
     int origx, origy;
     double eff = att_combat_eff(def);
-    char buf[1024];
 
     if (list)
        dtotal = get_dtotal(def, list, 1.0, 1);
@@ -1505,12 +1497,10 @@ att_reacting_units(struct combat *def, struct emp_qelem *list, int a_spy,
        if (!in_oparea((struct empobj *)&land, def->x, def->y))
            continue;
 
-       getsect(land.lnd_x, land.lnd_y, &sect);
-       getsect(def->x, def->y, &dsect);
-       if (!BestLandPath(buf, &sect, &dsect, &pathcost,
-                         lnd_mobtype(&land)))
+       pathcost = path_find(land.lnd_x, land.lnd_y, def->x, def->y,
+                           def->own, lnd_mobtype(&land));
+       if (pathcost < 0)
            continue;
-
        mobcost = lnd_pathcost(&land, pathcost);
        if (land.lnd_mobil < mobcost)
            continue;
@@ -1847,12 +1837,12 @@ att_fight(int combat_mode, struct combat *off, struct emp_qelem *olist,
      * since a single dead guy normally wouldn't cause a commander to
      * rethink his strategies, but 50 dead guys might.
      */
-    odds += (random() % 11 - 5) / 100.0;
+    odds += (roll(11) - 6) / 100.0;
     if (odds < 0.0)
        odds = 0.1;
     if (odds > 1.0)
        odds = 1.0;
-    recalctime = 8 + (random() % 43);
+    recalctime = 7 + roll(43);
     while (!success && ototal) {
        if (chance(odds)) {
            pr("!");
@@ -1868,9 +1858,9 @@ att_fight(int combat_mode, struct combat *off, struct emp_qelem *olist,
        if (((a_cas + d_cas) % 70) == 69)
            pr("\n");
        if (recalctime-- <= 0) {
-           recalctime = 8 + (random() % 43);
+           recalctime = 7 + roll(43);
            odds = att_calcodds(ototal, dtotal);
-           odds += (random() % 11 - 5) / 100.0;
+           odds += (roll(11) - 6) / 100.0;
            if (odds < 0.0)
                odds = 0.1;
            if (odds > 1.0)
@@ -2003,7 +1993,7 @@ att_fight(int combat_mode, struct combat *off, struct emp_qelem *olist,
     unit_put(dlist, 0);
 
     /* putland the attacking land */
-    put_land(olist);
+    put_oland(olist);
 
     /* put the victim sector/ship/land */
     if (!success || !take_def(combat_mode, olist, off, def))
@@ -2151,7 +2141,8 @@ send_reacting_units_home(struct emp_qelem *list)
                    xyas(llp->x, llp->y, llp->unit.land.lnd_own));
            llp->unit.land.lnd_x = llp->x;
            llp->unit.land.lnd_y = llp->y;
-           lnd_delete(llp, buf);
+           lnd_print(llp->unit.land.lnd_own, llp, buf);
+           lnd_delete(llp);
        }
     }
 }
@@ -2224,12 +2215,14 @@ take_def(int combat_mode, struct emp_qelem *list, struct combat *off,
            if (def->type == EF_SHIP) {
                llp->unit.land.lnd_ship = def->shp_uid;
                sprintf(buf, "boards %s", prcom(0, def));
+               lnd_print(player->cnum, llp, buf);
                delete_me = llp;
            } else {
                llp->unit.land.lnd_ship = -1;
                sprintf(buf, "moves in to occupy %s",
                        xyas(def->x, def->y, player->cnum));
-               lnd_delete(llp, buf);
+               lnd_print(player->cnum, llp, buf);
+               lnd_delete(llp);
            }
        }
     }
@@ -2251,7 +2244,7 @@ take_def(int combat_mode, struct emp_qelem *list, struct combat *off,
        putland(land.lnd_uid, &land);
     }
     if (delete_me)
-       lnd_delete(delete_me, buf);
+       lnd_delete(delete_me);
     att_get_combat(def, 0);
     return 1;
 }
@@ -2292,7 +2285,7 @@ ask_move_in(struct combat *off, struct emp_qelem *olist,
            *answerp = 'N';
        if (*answerp == 'Y')
            continue;
-       if (!get_land(A_ATTACK, def, llp, 0))
+       if (!get_oland(A_ATTACK, llp))
            continue;
        if (*answerp != 'N') {
            sprintf(prompt, "Move in with %s (%c %d%%) [ynYNq?] ",
@@ -2302,7 +2295,7 @@ ask_move_in(struct combat *off, struct emp_qelem *olist,
            *answerp = att_prompt(prompt, llp->unit.land.lnd_army);
            if (player->aborted || att_get_combat(def, 0) < 0)
                *answerp = 'N';
-           if (!get_land(A_ATTACK, def, llp, 0))
+           if (!get_oland(A_ATTACK, llp))
                continue;
        }
        if (*answerp == 'y' || *answerp == 'Y')
@@ -2310,7 +2303,8 @@ ask_move_in(struct combat *off, struct emp_qelem *olist,
        sprintf(buf, "stays in %s",
                xyas(llp->unit.land.lnd_x, llp->unit.land.lnd_y,
                     player->cnum));
-       lnd_delete(llp, buf);
+       lnd_print(player->cnum, llp, buf);
+       lnd_delete(llp);
     }
     if (QEMPTY(olist))
        return;
@@ -2318,12 +2312,13 @@ ask_move_in(struct combat *off, struct emp_qelem *olist,
        for (qp = olist->q_forw; qp != olist; qp = next) {
            next = qp->q_forw;
            llp = (struct ulist *)qp;
-           if (!get_land(A_ATTACK, def, llp, 0))
+           if (!get_oland(A_ATTACK, llp))
                continue;
            sprintf(buf, "stays in %s",
                    xyas(llp->unit.land.lnd_x, llp->unit.land.lnd_y,
                         player->cnum));
-           lnd_delete(llp, buf);
+           lnd_print(player->cnum, llp, buf);
+           lnd_delete(llp);
        }
        return;
     }
@@ -2347,7 +2342,7 @@ move_in_land(int combat_mode, struct combat *off, struct emp_qelem *olist,
     for (qp = olist->q_forw; qp != olist; qp = next) {
        next = qp->q_forw;
        llp = (struct ulist *)qp;
-       if (!get_land(combat_mode, def, llp, 0))
+       if (!get_oland(combat_mode, llp))
            continue;
        take_move_in_mob(combat_mode, llp, off, def);
        llp->unit.land.lnd_x = def->x;
@@ -2361,7 +2356,7 @@ move_in_land(int combat_mode, struct combat *off, struct emp_qelem *olist,
        return;
     if (def->type == EF_SECTOR) {
        if (opt_INTERDICT_ATT) {
-           lnd_sweep(olist, 0, 0, def->own);
+           lnd_sweep(olist, 0, 0, player->cnum);
            lnd_check_mines(olist);
        }
        sprintf(buf, "now occupies %s", prcom(0, def));
@@ -2373,7 +2368,7 @@ move_in_land(int combat_mode, struct combat *off, struct emp_qelem *olist,
     for (qp = olist->q_forw; qp != olist; qp = next) {
        next = qp->q_forw;
        llp = (struct ulist *)qp;
-       lnd_print(llp, buf);
+       lnd_print(player->cnum, llp, buf);
     }
     if (QEMPTY(olist))
        return;
@@ -2517,7 +2512,7 @@ take_move_in_mob(int combat_mode, struct ulist *llp, struct combat *off,
     switch (combat_mode) {
     case A_ATTACK:
        mobcost = lnd_pathcost(&llp->unit.land,
-                              att_mobcost(off->own, def,
+                              att_mobcost(llp->unit.land.lnd_own, def,
                                           lnd_mobtype(&llp->unit.land)));
        break;
     case A_ASSAULT: