march: Check for sector abandonment before anyone marches

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>
This commit is contained in:
Markus Armbruster 2014-12-28 21:55:44 +01:00
parent 3b9f2a149b
commit 7c1b1661f5
11 changed files with 71 additions and 47 deletions

View 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(struct emp_qelem *);
extern void lnd_put_one(struct ulist *); extern void lnd_put_one(struct ulist *);
extern int lnd_hardtarget(struct lndstr *); 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_mar_one_sector(struct emp_qelem *, int, natid, int);
extern int lnd_support(natid, natid, coord, coord, int); extern int lnd_support(natid, natid, coord, coord, int);
extern int lnd_can_attack(struct lndstr *); extern int lnd_can_attack(struct lndstr *);

View file

@ -404,8 +404,8 @@ extern int check_trade_ok(struct trdstr *);
extern void set_coastal(struct sctstr *, int, int); extern void set_coastal(struct sctstr *, int, int);
/* control.c */ /* control.c */
extern int military_control(struct sctstr *); extern int military_control(struct sctstr *);
extern int want_to_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 lndstr *); extern int would_abandon(struct sctstr *, i_type, int, struct ulist *);
/* damage.c */ /* damage.c */
extern void landdamage(struct lndstr *, int); extern void landdamage(struct lndstr *, int);
extern void ship_damage(struct shpstr *, int); extern void ship_damage(struct shpstr *, int);

View 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"); pr("Explore cancelled.\n");
return RET_FAIL; return RET_FAIL;
} }

View file

@ -30,7 +30,7 @@
* David Sharnoff, 1987 * David Sharnoff, 1987
* Ken Stevens, 1995 (rewritten) * Ken Stevens, 1995 (rewritten)
* Steve McClure, 1998-2000 * 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)); load_unload, atoi(p));
if (!load_comm_ok(sectp, sp->shp_own, item, move_amt)) if (!load_comm_ok(sectp, sp->shp_own, item, move_amt))
return RET_OK; return RET_OK;
if (!want_to_abandon(sectp, item, move_amt, NULL)) if (!abandon_askyn(sectp, item, move_amt, NULL))
return RET_FAIL; return RET_FAIL;
if (!still_ok_ship(sectp, sp)) if (!still_ok_ship(sectp, sp))
return RET_SYN; return RET_SYN;

View 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"); pr("Move cancelled.\n");
return RET_FAIL; return RET_FAIL;
} }

View file

@ -74,6 +74,7 @@ do_unit_move(struct emp_qelem *ulist, int *together,
int dir; int dir;
int stopping = 0; int stopping = 0;
int skip = 0; int skip = 0;
int moved = 0;
char buf[1024]; char buf[1024];
char prompt[128]; char prompt[128];
char bmap_flag; char bmap_flag;
@ -153,10 +154,14 @@ do_unit_move(struct emp_qelem *ulist, int *together,
if (type == EF_SHIP) if (type == EF_SHIP)
stopping |= shp_nav_one_sector(ulist, dir, stopping |= shp_nav_one_sector(ulist, dir,
player->cnum, *together); player->cnum, *together);
else else {
if (!moved && !lnd_abandon_askyn(ulist))
return RET_FAIL;
stopping |= stopping |=
lnd_mar_one_sector(ulist, dir, player->cnum, lnd_mar_one_sector(ulist, dir, player->cnum,
*together); *together);
}
moved = 1;
cp++; cp++;
continue; continue;
} }

View file

@ -28,6 +28,7 @@
* *
* Known contributors to this file: * Known contributors to this file:
* Dave Pare, 1986 * Dave Pare, 1986
* Markus Armbruster, 2014
*/ */
#include <config.h> #include <config.h>
@ -38,6 +39,7 @@
#include "player.h" #include "player.h"
#include "prototypes.h" #include "prototypes.h"
#include "sect.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 * First, would we be abandoning it? If not, just return that
* it's ok to move out. * it's ok to move out.
*/ */
if (!would_abandon(sp, vtype, amnt, lp)) if (!would_abandon(sp, vtype, amnt, land_list))
return 1; return 1;
sprintf(prompt, "Do you really want to abandon %s [yn]? ", 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) if (vtype != I_CIVIL && vtype != I_MILIT)
return 0; return 0;
@ -96,6 +113,10 @@ would_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp)
if (vtype == I_CIVIL) if (vtype == I_CIVIL)
civs -= amnt; civs -= amnt;
return sp->sct_own != 0 && civs <= 0 && mil <= 0 if (!sp->sct_own || civs > 0 || mil > 0)
&& !has_units(sp->sct_x, sp->sct_y, sp->sct_own, lp); 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;
} }

View 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 int
lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor, lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor,
int together) int together)
{ {
struct sctstr sect, osect; struct sctstr sect, osect;
struct emp_qelem *qp; struct emp_qelem *qp;
struct emp_qelem *qp2;
struct emp_qelem *next; struct emp_qelem *next;
struct ulist *llp; struct ulist *llp;
struct emp_qelem cur, done; 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; enum lnd_stuck stuck;
int stopping = 0; int stopping = 0;
int visible; int visible;
int stop;
char dp[80]; char dp[80];
int rel; int rel;
int oldown; 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) { if (llp->mobil <= 0.0) {
lnd_stays(actor, "is out of mobility", llp); lnd_stays(actor, "is out of mobility", llp);
continue; continue;

View file

@ -66,8 +66,6 @@ y
h h
march 78/79 yj march 78/79 yj
n n
h
| TODO empty sector at march prompt
| run out of mob, change leader | run out of mob, change leader
march 84/83/80/81/82 march 84/83/80/81/82
jjun jjun

View 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 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 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 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 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 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 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

View file

@ -971,13 +971,7 @@
Play#1 output Play#1 1 Leader is cav cavalry #78 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 output Play#1 4 Do you really want to abandon 3,7 [yn]?
Play#1 input n Play#1 input n
Play#1 output Play#1 1 cav cavalry #79 stops & stays in 3,7 Play#1 output Play#1 1 command failed
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 6 0 567 Play#1 output Play#1 6 0 567
Play#1 input march 84/83/80/81/82 Play#1 input march 84/83/80/81/82
Play#1 command march Play#1 command march
@ -1519,7 +1513,7 @@
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 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 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 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 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 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 81 cav cavalry 9,5 100% 5 0 60 0 30 42% 0 0