diff --git a/include/land.h b/include/land.h index 8a86537a..c1bd797d 100644 --- a/include/land.h +++ b/include/land.h @@ -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 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 *); diff --git a/include/prototypes.h b/include/prototypes.h index 0a08db85..d569033e 100644 --- a/include/prototypes.h +++ b/include/prototypes.h @@ -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 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); diff --git a/src/lib/commands/expl.c b/src/lib/commands/expl.c index 89b61be3..51f60bfa 100644 --- a/src/lib/commands/expl.c +++ b/src/lib/commands/expl.c @@ -118,7 +118,7 @@ explore(void) pr("Only exploring with %d.\n", amount); } - if (!want_to_abandon(§, vtype, amount, NULL)) { + if (!abandon_askyn(§, vtype, amount, NULL)) { pr("Explore cancelled.\n"); return RET_FAIL; } diff --git a/src/lib/commands/load.c b/src/lib/commands/load.c index e60d9a1c..2a995d47 100644 --- a/src/lib/commands/load.c +++ b/src/lib/commands/load.c @@ -30,7 +30,7 @@ * David Sharnoff, 1987 * Ken Stevens, 1995 (rewritten) * Steve McClure, 1998-2000 - * Markus Armbruster, 2004-2013 + * Markus Armbruster, 2004-2014 */ #include @@ -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; - 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; diff --git a/src/lib/commands/move.c b/src/lib/commands/move.c index c9f012fb..05e5d689 100644 --- a/src/lib/commands/move.c +++ b/src/lib/commands/move.c @@ -140,7 +140,7 @@ move(void) } } - if (!istest && !want_to_abandon(§, vtype, amount, NULL)) { + if (!istest && !abandon_askyn(§, vtype, amount, NULL)) { pr("Move cancelled.\n"); return RET_FAIL; } diff --git a/src/lib/commands/navi.c b/src/lib/commands/navi.c index 0870b373..c398e848 100644 --- a/src/lib/commands/navi.c +++ b/src/lib/commands/navi.c @@ -74,6 +74,7 @@ do_unit_move(struct emp_qelem *ulist, int *together, int dir; int stopping = 0; int skip = 0; + int moved = 0; 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); - else + else { + if (!moved && !lnd_abandon_askyn(ulist)) + return RET_FAIL; stopping |= lnd_mar_one_sector(ulist, dir, player->cnum, *together); + } + moved = 1; cp++; continue; } diff --git a/src/lib/subs/control.c b/src/lib/subs/control.c index cec33a7c..e25cb4cf 100644 --- a/src/lib/subs/control.c +++ b/src/lib/subs/control.c @@ -28,6 +28,7 @@ * * Known contributors to this file: * Dave Pare, 1986 + * Markus Armbruster, 2014 */ #include @@ -38,6 +39,7 @@ #include "player.h" #include "prototypes.h" #include "sect.h" +#include "unit.h" /* * Does the player->owner have military control of this sector? @@ -62,8 +64,16 @@ military_control(struct sctstr *sp) 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 -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]; @@ -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. */ - 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]? ", @@ -80,10 +90,17 @@ want_to_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp) 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 -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; @@ -96,6 +113,10 @@ would_abandon(struct sctstr *sp, i_type vtype, int amnt, struct lndstr *lp) 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; } diff --git a/src/lib/subs/lndsub.c b/src/lib/subs/lndsub.c index 276050d7..c80da183 100644 --- a/src/lib/subs/lndsub.c +++ b/src/lib/subs/lndsub.c @@ -949,13 +949,40 @@ lnd_mobcost(struct lndstr *lp, struct sctstr *sp) 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, §); + if (!abandon_askyn(§, I_CIVIL, 0, llp)) + return 0; + if (!check_sect_ok(§)) + 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; - struct emp_qelem *qp2; 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; - int stop; 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(§)) - 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; diff --git a/tests/navi-march/02-march-1 b/tests/navi-march/02-march-1 index a4ca71a3..1d6ac57c 100644 --- a/tests/navi-march/02-march-1 +++ b/tests/navi-march/02-march-1 @@ -66,8 +66,6 @@ y 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 diff --git a/tests/navi-march/final.xdump b/tests/navi-march/final.xdump index c7570a35..04c3fddf 100644 --- a/tests/navi-march/final.xdump +++ b/tests/navi-march/final.xdump @@ -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 -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 diff --git a/tests/navi-march/journal.log b/tests/navi-march/journal.log index 4d666359..e1570b35 100644 --- a/tests/navi-march/journal.log +++ b/tests/navi-march/journal.log @@ -971,13 +971,7 @@ 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 @@ -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 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