]> git.pond.sub.org Git - empserver/commitdiff
march: Check for sector abandonment before anyone marches
authorMarkus Armbruster <armbru@pond.sub.org>
Sun, 28 Dec 2014 20:55:44 +0000 (21:55 +0100)
committerMarkus Armbruster <armbru@pond.sub.org>
Sat, 28 Feb 2015 15:13:14 +0000 (16:13 +0100)
Unlike the move command, march checks sector abandonment before every
step.

If the player declines, the last land unit stays put and is removed
from the march.

Except when sectors or land units change while we're waiting for the
player's reply.  Then the last unit is not removed from the march.
This can scatter land units.  Screwed up when checking for abandoning
the sector was added in 4.2.2.

Change march to work like move, and to avoid scattering land units: if
the player declines to abandon the sector, the command simply fails.

Put the check into new lnd_abandon_askyn().

Extend would_abandon() and want_to_abandon() from a single land unit
to many.  Rename the latter to abandon_askyn() for consistency.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
include/land.h
include/prototypes.h
src/lib/commands/expl.c
src/lib/commands/load.c
src/lib/commands/move.c
src/lib/commands/navi.c
src/lib/subs/control.c
src/lib/subs/lndsub.c
tests/navi-march/02-march-1
tests/navi-march/final.xdump
tests/navi-march/journal.log

index 8a86537a0634c733a472bf8a1ef4794d4b00b5b1..c1bd797d23478369cd67229a5f61cf00ce0138e9 100644 (file)
@@ -196,6 +196,7 @@ extern void lnd_mar(struct emp_qelem *, double *, double *, int *, natid);
 extern void lnd_put(struct emp_qelem *);
 extern void lnd_put_one(struct ulist *);
 extern int lnd_hardtarget(struct lndstr *);
 extern void lnd_put(struct emp_qelem *);
 extern void lnd_put_one(struct ulist *);
 extern int lnd_hardtarget(struct lndstr *);
+extern int lnd_abandon_askyn(struct emp_qelem *);
 extern int lnd_mar_one_sector(struct emp_qelem *, int, natid, int);
 extern int lnd_support(natid, natid, coord, coord, int);
 extern int lnd_can_attack(struct lndstr *);
 extern int lnd_mar_one_sector(struct emp_qelem *, int, natid, int);
 extern int lnd_support(natid, natid, coord, coord, int);
 extern int lnd_can_attack(struct lndstr *);
index 0a08db85e9241c6e94df51c2741477192ae4678a..d569033e2ba4d206381dfa9110dcca2c57ad95a2 100644 (file)
@@ -404,8 +404,8 @@ extern int check_trade_ok(struct trdstr *);
 extern void set_coastal(struct sctstr *, int, int);
 /* control.c */
 extern int military_control(struct sctstr *);
 extern void set_coastal(struct sctstr *, int, int);
 /* control.c */
 extern int military_control(struct sctstr *);
-extern int want_to_abandon(struct sctstr *, i_type, int, struct lndstr *);
-extern int would_abandon(struct sctstr *, i_type, int, struct lndstr *);
+extern int abandon_askyn(struct sctstr *, i_type, int, struct ulist *);
+extern int would_abandon(struct sctstr *, i_type, int, struct ulist *);
 /* damage.c */
 extern void landdamage(struct lndstr *, int);
 extern void ship_damage(struct shpstr *, int);
 /* damage.c */
 extern void landdamage(struct lndstr *, int);
 extern void ship_damage(struct shpstr *, int);
index 89b61be33c326216e949e1008549a5bb7966d864..51f60bfa5a40ef3430052328e99e51e1677b6f5a 100644 (file)
@@ -118,7 +118,7 @@ explore(void)
        pr("Only exploring with %d.\n", amount);
     }
 
        pr("Only exploring with %d.\n", amount);
     }
 
-    if (!want_to_abandon(&sect, vtype, amount, NULL)) {
+    if (!abandon_askyn(&sect, vtype, amount, NULL)) {
        pr("Explore cancelled.\n");
        return RET_FAIL;
     }
        pr("Explore cancelled.\n");
        return RET_FAIL;
     }
index e60d9a1c4781a1509064525bbeb19fb6414556e1..2a995d478d9c128309d1a2fd4063f4c08f02ff8f 100644 (file)
@@ -30,7 +30,7 @@
  *     David Sharnoff, 1987
  *     Ken Stevens, 1995 (rewritten)
  *     Steve McClure, 1998-2000
  *     David Sharnoff, 1987
  *     Ken Stevens, 1995 (rewritten)
  *     Steve McClure, 1998-2000
- *     Markus Armbruster, 2004-2013
+ *     Markus Armbruster, 2004-2014
  */
 
 #include <config.h>
  */
 
 #include <config.h>
@@ -692,7 +692,7 @@ load_comm_ship(struct sctstr *sectp, struct shpstr *sp,
                           load_unload, atoi(p));
     if (!load_comm_ok(sectp, sp->shp_own, item, move_amt))
        return RET_OK;
                           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))
+    if (!abandon_askyn(sectp, item, move_amt, NULL))
        return RET_FAIL;
     if (!still_ok_ship(sectp, sp))
        return RET_SYN;
        return RET_FAIL;
     if (!still_ok_ship(sectp, sp))
        return RET_SYN;
index c9f012fb0719062de84a13752d9214238577aa39..05e5d689a8a17a2e08f67a8f58416984eef393ad 100644 (file)
@@ -140,7 +140,7 @@ move(void)
        }
     }
 
        }
     }
 
-    if (!istest && !want_to_abandon(&sect, vtype, amount, NULL)) {
+    if (!istest && !abandon_askyn(&sect, vtype, amount, NULL)) {
        pr("Move cancelled.\n");
        return RET_FAIL;
     }
        pr("Move cancelled.\n");
        return RET_FAIL;
     }
index 0870b373fa95dd10342ee97602e5e142c222267d..c398e848793c1c683908076a57a1fc57cba04a4c 100644 (file)
@@ -74,6 +74,7 @@ do_unit_move(struct emp_qelem *ulist, int *together,
     int dir;
     int stopping = 0;
     int skip = 0;
     int dir;
     int stopping = 0;
     int skip = 0;
+    int moved = 0;
     char buf[1024];
     char prompt[128];
     char bmap_flag;
     char buf[1024];
     char prompt[128];
     char bmap_flag;
@@ -153,10 +154,14 @@ do_unit_move(struct emp_qelem *ulist, int *together,
            if (type == EF_SHIP)
                stopping |= shp_nav_one_sector(ulist, dir,
                                               player->cnum, *together);
            if (type == EF_SHIP)
                stopping |= shp_nav_one_sector(ulist, dir,
                                               player->cnum, *together);
-           else
+           else {
+               if (!moved && !lnd_abandon_askyn(ulist))
+                   return RET_FAIL;
                stopping |=
                    lnd_mar_one_sector(ulist, dir, player->cnum,
                                       *together);
                stopping |=
                    lnd_mar_one_sector(ulist, dir, player->cnum,
                                       *together);
+           }
+           moved = 1;
            cp++;
            continue;
        }
            cp++;
            continue;
        }
index cec33a7cab43521b81f8a94a96e407f7e73626d4..e25cb4cfe7140694fab07e8e9dc873f5aebf26e9 100644 (file)
@@ -28,6 +28,7 @@
  *
  *  Known contributors to this file:
  *     Dave Pare, 1986
  *
  *  Known contributors to this file:
  *     Dave Pare, 1986
+ *     Markus Armbruster, 2014
  */
 
 #include <config.h>
  */
 
 #include <config.h>
@@ -38,6 +39,7 @@
 #include "player.h"
 #include "prototypes.h"
 #include "sect.h"
 #include "player.h"
 #include "prototypes.h"
 #include "sect.h"
+#include "unit.h"
 
 /*
  * Does the player->owner have military control of this sector?
 
 /*
  * Does the player->owner have military control of this sector?
@@ -62,8 +64,16 @@ military_control(struct sctstr *sp)
     return 1;
 }
 
     return 1;
 }
 
+/*
+ * Ask user to confirm abandonment of sector SP, if any.
+ * If removing AMNT commodities of type VTYPE and the land units in
+ * LIST would abandon their sector, ask the user to confirm.
+ * All land units in LIST must be in this sector.  LIST may be null.
+ * Return zero when abandonment was declined, else non-zero.
+ */
 int
 int
-want_to_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp)
+abandon_askyn(struct sctstr *sp, i_type vtype, int amnt,
+             struct ulist *land_list)
 {
     char prompt[80];
 
 {
     char prompt[80];
 
@@ -71,7 +81,7 @@ want_to_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp)
      * First, would we be abandoning it?  If not, just return that
      * it's ok to move out.
      */
      * First, would we be abandoning it?  If not, just return that
      * it's ok to move out.
      */
-    if (!would_abandon(sp, vtype, amnt, lp))
+    if (!would_abandon(sp, vtype, amnt, land_list))
        return 1;
 
     sprintf(prompt, "Do you really want to abandon %s [yn]? ",
        return 1;
 
     sprintf(prompt, "Do you really want to abandon %s [yn]? ",
@@ -80,10 +90,17 @@ want_to_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp)
     return askyn(prompt);
 }
 
     return askyn(prompt);
 }
 
+/*
+ * Would removing this stuff from SP abandon it?
+ * Consider removal of AMNT commodities of type VTYPE and the land
+ * units in LIST.
+ * All land units in LIST must be in this sector.  LIST may be null.
+ */
 int
 int
-would_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp)
+would_abandon(struct sctstr *sp, i_type vtype, int amnt,
+             struct ulist *land_list)
 {
 {
-    int mil, civs;
+    int mil, civs, nland;
 
     if (vtype != I_CIVIL && vtype != I_MILIT)
        return 0;
 
     if (vtype != I_CIVIL && vtype != I_MILIT)
        return 0;
@@ -96,6 +113,10 @@ would_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp)
     if (vtype == I_CIVIL)
        civs -= amnt;
 
     if (vtype == I_CIVIL)
        civs -= amnt;
 
-    return sp->sct_own != 0 && civs <= 0 && mil <= 0
-       && !has_units(sp->sct_x, sp->sct_y, sp->sct_own, lp);
+    if (!sp->sct_own || civs > 0 || mil > 0)
+       return 0;
+    nland = unitsatxy(sp->sct_x, sp->sct_y, 0, 0, 1);
+    if (land_list)
+       nland -= emp_quelen(&land_list->queue);
+    return nland <= 0;
 }
 }
index 276050d7a53b01d31d2ab9d502574a6cc316eca9..c80da183b1010a6fd6c6c62e2cbb23f68bb6b7d5 100644 (file)
@@ -949,13 +949,40 @@ lnd_mobcost(struct lndstr *lp, struct sctstr *sp)
     return lnd_pathcost(lp, sector_mcost(sp, lnd_mobtype(lp)));
 }
 
     return lnd_pathcost(lp, sector_mcost(sp, lnd_mobtype(lp)));
 }
 
+/*
+ * Ask user to confirm sector abandonment, if any.
+ * All land units in LIST must be in the same sector.
+ * If removing the land units in LIST would abandon their sector, ask
+ * the user to confirm.
+ * Return zero when abandonment was declined, else non-zero.
+ */
+int lnd_abandon_askyn(struct emp_qelem *list)
+{
+    struct ulist *llp;
+    struct sctstr sect;
+    struct emp_qelem *qp;
+
+    if (QEMPTY(list))
+       return 1;
+    llp = (struct ulist *)list->q_back;
+    getsect(llp->unit.land.lnd_x, llp->unit.land.lnd_y, &sect);
+    if (!abandon_askyn(&sect, I_CIVIL, 0, llp))
+       return 0;
+    if (!check_sect_ok(&sect))
+       return 0;
+    for (qp = list->q_back; qp != list; qp = qp->q_back) {
+       if (!check_land_ok(&((struct ulist *)qp)->unit.land))
+           return 0;
+    }
+    return 1;
+}
+
 int
 lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor,
                   int together)
 {
     struct sctstr sect, osect;
     struct emp_qelem *qp;
 int
 lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor,
                   int together)
 {
     struct sctstr sect, osect;
     struct emp_qelem *qp;
-    struct emp_qelem *qp2;
     struct emp_qelem *next;
     struct ulist *llp;
     struct emp_qelem cur, done;
     struct emp_qelem *next;
     struct ulist *llp;
     struct emp_qelem cur, done;
@@ -967,7 +994,6 @@ lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor,
     enum lnd_stuck stuck;
     int stopping = 0;
     int visible;
     enum lnd_stuck stuck;
     int stopping = 0;
     int visible;
-    int stop;
     char dp[80];
     int rel;
     int oldown;
     char dp[80];
     int rel;
     int oldown;
@@ -1033,27 +1059,6 @@ lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor,
                }
            }
        }
                }
            }
        }
-       /* Note we check would_abandon first because we don't want
-          to always have to do these checks */
-       if (would_abandon(&osect, I_CIVIL, 0, &llp->unit.land)) {
-           stop = 0;
-           if (!want_to_abandon(&osect, I_CIVIL, 0, &llp->unit.land)) {
-               stop = 1;
-           }
-           /* now check stuff */
-           if (!check_sect_ok(&sect))
-               return 1;
-           if (!check_sect_ok(&osect))
-               return 1;
-           for (qp2 = list->q_back; qp2 != list; qp2 = qp2->q_back) {
-               if (!check_land_ok(&((struct ulist *)qp2)->unit.land))
-                   return 1;
-           }
-           if (stop) {
-               lnd_stays(actor, "stops", llp);
-               continue;
-           }
-       }
        if (llp->mobil <= 0.0) {
            lnd_stays(actor, "is out of mobility", llp);
            continue;
        if (llp->mobil <= 0.0) {
            lnd_stays(actor, "is out of mobility", llp);
            continue;
index a4ca71a320af286194c4611696387e6455e77bfa..1d6ac57c954ab07cef368ba2645172f29ea0fc9f 100644 (file)
@@ -66,8 +66,6 @@ y
 h
 march 78/79 yj
 n
 h
 march 78/79 yj
 n
-h
-| TODO empty sector at march prompt
 | run out of mob, change leader
 march 84/83/80/81/82
 jjun
 | run out of mob, change leader
 march 84/83/80/81/82
 jjun
index c7570a35ebd61eb78009b549a70e8d8385831127..04c3fddf9ea5eb2950b864314238faf2fc5ac4a5 100644 (file)
@@ -248,7 +248,7 @@ uid owner xloc yloc type effic mobil off tech opx opy mission radius army ship h
 75 1 0 4 7 100 127 0 40 0 0 none 0 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
 76 1 2 6 0 100 104 0 30 1 7 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
 77 1 2 6 0 100 104 0 30 1 7 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
 75 1 0 4 7 100 127 0 40 0 0 none 0 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
 76 1 2 6 0 100 104 0 30 1 7 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
 77 1 2 6 0 100 104 0 30 1 7 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
-78 1 4 6 0 100 104 0 30 3 7 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
+78 1 3 7 0 100 127 0 30 3 7 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
 79 1 3 7 0 100 127 0 30 3 7 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
 80 1 9 5 0 100 60 0 30 3 5 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
 81 1 9 5 0 100 60 0 30 3 5 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
 79 1 3 7 0 100 127 0 30 3 7 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
 80 1 9 5 0 100 60 0 30 3 5 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
 81 1 9 5 0 100 60 0 30 3 5 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0
index 4d66635964b85cb6e9854df23d30b47e1488c80a..e1570b35e1feecf334e2fad820013e4ca3e71773 100644 (file)
     Play#1 output Play#1 1 Leader is cav  cavalry #78
     Play#1 output Play#1 4 Do you really want to abandon 3,7 [yn]?
     Play#1 input n
     Play#1 output Play#1 1 Leader is cav  cavalry #78
     Play#1 output Play#1 4 Do you really want to abandon 3,7 [yn]?
     Play#1 input n
-    Play#1 output Play#1 1 cav  cavalry #79 stops & stays in 3,7
-    Play#1 output Play#1 1  + m
-    Play#1 output Play#1 1 m m m
-    Play#1 output Play#1 1  m m
-    Play#1 output Play#1 4 <104.7:104.7: 4,6>
-    Play#1 input h
-    Play#1 output Play#1 1 cav  cavalry #78 stopped at 4,6
+    Play#1 output Play#1 1 command failed
     Play#1 output Play#1 6 0 567
     Play#1 input march 84/83/80/81/82
     Play#1 command march
     Play#1 output Play#1 6 0 567
     Play#1 input march 84/83/80/81/82
     Play#1 command march
     Play#0 output Play#0 1   1   75 tra  train         0,4       100%   5   0 127   0  40  42%  0  0
     Play#0 output Play#0 1   1   76 cav  cavalry       2,6       100%   5   0 104   0  30  42%  0  0
     Play#0 output Play#0 1   1   77 cav  cavalry       2,6       100%   5   0 104   0  30  42%  0  0
     Play#0 output Play#0 1   1   75 tra  train         0,4       100%   5   0 127   0  40  42%  0  0
     Play#0 output Play#0 1   1   76 cav  cavalry       2,6       100%   5   0 104   0  30  42%  0  0
     Play#0 output Play#0 1   1   77 cav  cavalry       2,6       100%   5   0 104   0  30  42%  0  0
-    Play#0 output Play#0 1   1   78 cav  cavalry       4,6       100%   5   0 104   0  30  42%  0  0
+    Play#0 output Play#0 1   1   78 cav  cavalry       3,7       100%   5   0 127   0  30  42%  0  0
     Play#0 output Play#0 1   1   79 cav  cavalry       3,7       100%   5   0 127   0  30  42%  0  0
     Play#0 output Play#0 1   1   80 cav  cavalry       9,5       100%   5   0  60   0  30  42%  0  0
     Play#0 output Play#0 1   1   81 cav  cavalry       9,5       100%   5   0  60   0  30  42%  0  0
     Play#0 output Play#0 1   1   79 cav  cavalry       3,7       100%   5   0 127   0  30  42%  0  0
     Play#0 output Play#0 1   1   80 cav  cavalry       9,5       100%   5   0  60   0  30  42%  0  0
     Play#0 output Play#0 1   1   81 cav  cavalry       9,5       100%   5   0  60   0  30  42%  0  0