march: Fix check for sector abandonment

sct_prewrite() makes an owned sector revert to the deity when there
are no civilians, military or own land units.

would_abandon() tries to predict that, but gets it wrong: it ignores
land units that evade spy detection or are loaded on ships, and it
fails to ignore land units loaded on land units marching out.

Broken in commit 7c1b166, v4.3.33.  Fix by counting manually rather
than with unitsatxy().

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
This commit is contained in:
Markus Armbruster 2016-05-14 22:00:36 +02:00
parent bd9fbca995
commit 7224442533
3 changed files with 38 additions and 9 deletions

View file

@ -28,7 +28,7 @@
* *
* Known contributors to this file: * Known contributors to this file:
* Dave Pare, 1986 * Dave Pare, 1986
* Markus Armbruster, 2014 * Markus Armbruster, 2014-2016
*/ */
#include <config.h> #include <config.h>
@ -68,7 +68,8 @@ military_control(struct sctstr *sp)
* Ask user to confirm abandonment of sector @sp, if any. * Ask user to confirm abandonment of sector @sp, if any.
* If removing @amnt commodities of type @vtype and the land units in * If removing @amnt commodities of type @vtype and the land units in
* @list would abandon the sector, ask the user to confirm. * @list would abandon the sector, ask the user to confirm.
* All land units in @list must be in this sector. @list may be null. * All land units in @land_list must be in this sector, owned by the
* player, and not loaded onto anything. @land_list may be null.
* Return zero when abandonment was declined, else non-zero. * Return zero when abandonment was declined, else non-zero.
*/ */
int int
@ -93,14 +94,22 @@ abandon_askyn(struct sctstr *sp, i_type vtype, int amnt,
/* /*
* Would removing this stuff from @sp abandon it? * Would removing this stuff from @sp abandon it?
* Consider removal of @amnt commodities of type @vtype and the land * Consider removal of @amnt commodities of type @vtype and the land
* units in @list. * units in @land_list.
* All land units in @list must be in this sector. @list may be null. * All land units in @land_list must be in this sector, owned by the
* player, and not loaded onto anything. @land_list may be null.
*/ */
int int
would_abandon(struct sctstr *sp, i_type vtype, int amnt, would_abandon(struct sctstr *sp, i_type vtype, int amnt,
struct ulist *land_list) struct ulist *land_list)
{ {
int mil, civs, nland; int mil, civs, nland;
struct nstr_item ni;
struct lndstr land;
/*
* sct_prewrite() abandons when there are no civilians, military
* and own units left.
*/
if (vtype != I_CIVIL && vtype != I_MILIT) if (vtype != I_CIVIL && vtype != I_MILIT)
return 0; return 0;
@ -115,7 +124,23 @@ would_abandon(struct sctstr *sp, i_type vtype, int amnt,
if (!sp->sct_own || civs > 0 || mil > 0) if (!sp->sct_own || civs > 0 || mil > 0)
return 0; return 0;
nland = unitsatxy(sp->sct_x, sp->sct_y, 0, 0, 1);
/*
* Okay, no civilians and no military would be left. Any own land
* units left? Land units on ships stay, so count them. Land
* units not on anything stay unless in @land_list, so count them,
* then subtract length of @land_list. Land units on land units
* stay if their carrier stays, and therefore won't change the
* outcome; don't count them.
*/
nland = 0;
snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y);
while (nxtitem(&ni, &land)) {
if (land.lnd_own == player->cnum && land.lnd_land < 0)
++nland;
}
if (land_list) if (land_list)
nland -= emp_quelen(&land_list->queue); nland -= emp_quelen(&land_list->queue);
return nland <= 0; return nland <= 0;

View file

@ -29,7 +29,7 @@
* Known contributors to this file: * Known contributors to this file:
* Ken Stevens, 1995 * Ken Stevens, 1995
* Steve McClure, 1998-2000 * Steve McClure, 1998-2000
* Markus Armbruster, 2004-2015 * Markus Armbruster, 2004-2016
*/ */
#include <config.h> #include <config.h>
@ -954,7 +954,8 @@ lnd_mobcost(struct lndstr *lp, struct sctstr *sp)
/* /*
* Ask user to confirm sector abandonment, if any. * Ask user to confirm sector abandonment, if any.
* All land units in @list must be in the same sector. * All land units in @list must be in the same sector, owned by the
* player, and not loaded onto anything.
* If removing the land units in @list would abandon their sector, ask * If removing the land units in @list would abandon their sector, ask
* the user to confirm. * the user to confirm.
* Return zero when abandonment was declined, else non-zero. * Return zero when abandonment was declined, else non-zero.

View file

@ -29,7 +29,7 @@
* Known contributors to this file: * Known contributors to this file:
* Dave Pare, 1989 * Dave Pare, 1989
* Steve McClure, 1996 * Steve McClure, 1996
* Markus Armbruster, 2004-2014 * Markus Armbruster, 2004-2016
*/ */
#include <config.h> #include <config.h>
@ -83,9 +83,12 @@ sct_prewrite(int id, void *old, void *new)
sp->sct_oldown = own; sp->sct_oldown = own;
} }
/*
* Without civilians, military and land units, revert to deity.
* Note: would_abandon() must match this condition.
*/
if (own && !civs && !mil && !has_units(sp->sct_x, sp->sct_y, own) if (own && !civs && !mil && !has_units(sp->sct_x, sp->sct_y, own)
&& !(sp->sct_flags & MOVE_IN_PROGRESS)) { && !(sp->sct_flags & MOVE_IN_PROGRESS)) {
/* more cruft! */
own = sp->sct_own = 0; own = sp->sct_own = 0;
sp->sct_mobil = 0; sp->sct_mobil = 0;
if (sp->sct_type == SCT_CAPIT || sp->sct_type == SCT_MOUNT) if (sp->sct_type == SCT_CAPIT || sp->sct_type == SCT_MOUNT)