]> git.pond.sub.org Git - empserver/blobdiff - src/lib/commands/assa.c
Update copyright notice
[empserver] / src / lib / commands / assa.c
index bc794ae7f5f787b7f39f019375acfb25e2ec70c2..31a36e65ad6f90a8e5d2389515c7d2ed525ff82c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2013, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2018, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                Ken Stevens, Steve McClure, Markus Armbruster
  *
  *  Empire is free software: you can redistribute it and/or modify
  *  Known contributors to this file:
  *     Ken Stevens, 1995
  *     Steve McClure, 1997
+ *     Markus Armbruster, 2009-2016
  */
 
 #include <config.h>
 
+#include "chance.h"
 #include "combat.h"
 #include "commands.h"
 #include "empobj.h"
 #include "unit.h"
 
+static int only_spies(struct combat[], struct emp_qelem *);
+static void sneak_ashore(struct combat[], struct emp_qelem *,
+                        struct combat *);
+
 int
 assa(void)
 {
@@ -53,11 +59,6 @@ assa(void)
     double dsupport = 1.0;     /* defense support */
     char *p;
     char buf[1024];
-    int n;
-    int ourtotal;
-    struct emp_qelem *qp, *next;
-    struct ulist *llp;
-    int rel;
 
     att_combat_init(off, EF_SHIP);
     att_combat_init(def, EF_SECTOR);
@@ -88,10 +89,8 @@ assa(void)
        return RET_OK;
     }
 
-    /* Show what we're assaulting, and check treaties */
-
-    if (att_show(def))
-       return RET_FAIL;
+    /* Show what we're assaulting */
+    att_show(def);
 
     /* Ask about offensive support */
 
@@ -120,6 +119,12 @@ assa(void)
        return RET_OK;
     }
 
+    /* If only spies assault, try to sneak them ashore */
+    if (only_spies(off, &olist)) {
+       sneak_ashore(off, &olist, def);
+       return RET_OK;
+    }
+
     ototal = att_get_offense(A_ASSAULT, off, &olist, def);
     if (att_abort(A_ASSAULT, off, def)) {
        pr("Assault aborted\n");
@@ -133,66 +138,6 @@ assa(void)
      * happening in the game.
      */
 
-    /* First, we check to see if the only thing we have are spies
-     * assaulting.  If so, we try to sneak them on land.  If they
-     * make it, the defenders don't see a thing.  If they fail, well,
-     * the spies die, and the defenders see them. */
-
-    ourtotal = 0;
-    for (n = 0; n <= off->last; n++) {
-       if (off[n].type == EF_BAD)
-           continue;
-       ourtotal += off[n].troops * att_combat_eff(off + n);
-    }
-    for (qp = olist.q_forw; qp != &olist; qp = next) {
-       next = qp->q_forw;
-       llp = (struct ulist *)qp;
-       if (lchr[(int)llp->unit.land.lnd_type].l_flags & L_SPY)
-           continue;
-       ourtotal++;
-    }
-
-    /* If no attacking forces (i.e. we got here with only spies)
-     * then try to sneak on-land. */
-
-    if (!ourtotal) {
-       pr("Trying to sneak on shore...\n");
-
-       for (qp = olist.q_forw; qp != &olist; qp = next) {
-           next = qp->q_forw;
-           llp = (struct ulist *)qp;
-           rel = relations_with(def->own, player->cnum);
-           if (chance(0.10) || rel == ALLIED || !def->own) {
-               pr("%s made it on shore safely.\n", prland(&llp->unit.land));
-               llp->unit.land.lnd_x = def->x;
-               llp->unit.land.lnd_y = def->y;
-               llp->unit.land.lnd_ship = -1;
-               putland(llp->unit.land.lnd_uid, &llp->unit.land);
-           } else {
-               pr("%s was spotted", prland(&llp->unit.land));
-               if (rel <= HOSTILE) {
-                   wu(0, def->own, "%s spy shot and killed in %s.\n",
-                      cname(player->cnum), xyas(def->x, def->y,
-                                                def->own));
-                   pr(" and was killed in the attempt.\n");
-                   llp->unit.land.lnd_effic = 0;
-                   putland(llp->unit.land.lnd_uid, &llp->unit.land);
-                   lnd_delete(llp);
-               } else {
-                   wu(0, def->own, "%s spy spotted in %s.\n",
-                      cname(player->cnum), xyas(def->x, def->y,
-                                                def->own));
-                   pr(" but made it ok.\n");
-                   llp->unit.land.lnd_x = def->x;
-                   llp->unit.land.lnd_y = def->y;
-                   llp->unit.land.lnd_ship = -1;
-                   putland(llp->unit.land.lnd_uid, &llp->unit.land);
-               }
-           }
-       }
-       return RET_OK;
-    }
-
     /* Get the real defense */
 
     att_get_defense(&olist, def, &dlist, a_spy, ototal);
@@ -216,3 +161,67 @@ assa(void)
 
     return RET_OK;
 }
+
+static int
+only_spies(struct combat off[], struct emp_qelem *olist)
+{
+    int n;
+    struct emp_qelem *qp;
+    struct ulist *llp;
+
+    for (n = 0; n <= off->last; n++) {
+       if (off[n].type == EF_BAD)
+           continue;
+       if (off[n].troops)
+           return 0;
+    }
+
+    for (qp = olist->q_forw; qp != olist; qp = qp->q_forw) {
+       llp = (struct ulist *)qp;
+       if (!(lchr[llp->unit.land.lnd_type].l_flags & L_SPY))
+           return 0;
+    }
+
+    return 1;
+}
+
+static void
+sneak_ashore(struct combat off[], struct emp_qelem *olist,
+            struct combat *def)
+{
+    struct emp_qelem *qp;
+    struct ulist *llp;
+    struct lndstr *lp;
+    enum relations rel;
+
+    pr("Trying to sneak on shore...\n");
+
+    att_move_land(A_ASSAULT, off, olist, def);
+
+    for (qp = olist->q_forw; qp != olist; qp = qp->q_forw) {
+       llp = (struct ulist *)qp;
+       lp = &llp->unit.land;
+       rel = relations_with(def->own, player->cnum);
+       if (rel == ALLIED || !def->own
+           || !chance(LND_SPY_DETECT_CHANCE(lp->lnd_effic / 2))) {
+                               /* eff/2 because this is hard */
+           pr("%s made it on shore safely.\n", prland(lp));
+       } else {
+           pr("%s was spotted", prland(lp));
+           if (rel <= HOSTILE) {
+               wu(0, def->own, "%s spy shot and killed in %s.\n",
+                  cname(player->cnum), xyas(def->x, def->y,
+                                            def->own));
+               pr(" and was killed in the attempt.\n");
+               lp->lnd_effic = 0;
+           } else {
+               wu(0, def->own, "%s spy spotted in %s.\n",
+                  cname(player->cnum), xyas(def->x, def->y,
+                                            def->own));
+               pr(" but made it OK.\n");
+           }
+       }
+    }
+
+    lnd_put(olist);
+}