March code reads the land units into a land unit list, and writes them
back when it changes them, e.g. when a land unit stops. If a land
unit changes in the land unit file while it is in such a land unit
list, the copy in the land unit list becomes stale, and must not be
used.
To that end, do_unit_move() calls lnd_mar() after prompting for path
or destination. lnd_mar() re-reads all the land units.
Unfortunately, it still writes back stale copies in certain
circumstances. Known ways to trigger such writes:
* Deity loads land unit onto a ship or land unit
* Land unit's crew killed just right, e.g. by collateral damage from
interdiction, followed by additional updates, such as shell fire
damage
* Sector no longer owned or allied, e.g. allied sector captured by an
enemy (own sector would kill or retreat the land unit)
Writing a stale copy wipes out the updates that made the copy stale,
and triggers a seqno mismatch oops. For instance, damage that follows
killing of all crew by collateral damage from interdiction is wiped
out. If no damage follows, we still get a generation oops.
struct emp_qelem *qp;
struct emp_qelem *next;
struct ulist *llp;
struct emp_qelem *qp;
struct emp_qelem *next;
struct ulist *llp;
coord allx;
coord ally;
int first = 1;
coord allx;
coord ally;
int first = 1;
for (qp = list->q_back; qp != list; qp = next) {
next = qp->q_back;
llp = (struct ulist *)qp;
for (qp = list->q_back; qp != list; qp = next) {
next = qp->q_back;
llp = (struct ulist *)qp;
- getland(llp->unit.land.lnd_uid, &land);
- if (land.lnd_own != actor) {
+ lp = &llp->unit.land;
+ getland(lp->lnd_uid, lp);
+ if (lp->lnd_own != actor) {
mpr(actor, "%s was disbanded at %s\n",
mpr(actor, "%s was disbanded at %s\n",
- prland(&land), xyas(land.lnd_x, land.lnd_y, actor));
+ prland(lp), xyas(lp->lnd_x, lp->lnd_y, actor));
emp_remque((struct emp_qelem *)llp);
free(llp);
continue;
}
emp_remque((struct emp_qelem *)llp);
free(llp);
continue;
}
- if (land.lnd_ship >= 0) {
+ if (lp->lnd_ship >= 0) {
lnd_stays(actor, "is on a ship", llp);
continue;
}
lnd_stays(actor, "is on a ship", llp);
continue;
}
- if (land.lnd_land >= 0) {
+ if (lp->lnd_land >= 0) {
lnd_stays(actor, "is on a unit", llp);
continue;
}
lnd_stays(actor, "is on a unit", llp);
continue;
}
- if (!getsect(land.lnd_x, land.lnd_y, §)) {
+ if (!getsect(lp->lnd_x, lp->lnd_y, §)) {
lnd_stays(actor, "was sucked into the sky by a strange looking spaceland", llp); /* heh -KHS */
continue;
}
lnd_stays(actor, "was sucked into the sky by a strange looking spaceland", llp); /* heh -KHS */
continue;
}
- if (!(lchr[(int)llp->unit.land.lnd_type].l_flags & L_SPY) &&
- !(lchr[(int)llp->unit.land.lnd_type].l_flags & L_TRAIN) &&
- llp->unit.land.lnd_item[I_MILIT] == 0) {
+ if (!(lchr[lp->lnd_type].l_flags & L_SPY) &&
+ !(lchr[lp->lnd_type].l_flags & L_TRAIN) &&
+ lp->lnd_item[I_MILIT] == 0) {
lnd_stays(actor, "has no mil on it to guide it", llp);
continue;
}
if (relations_with(sect.sct_own, actor) != ALLIED &&
lnd_stays(actor, "has no mil on it to guide it", llp);
continue;
}
if (relations_with(sect.sct_own, actor) != ALLIED &&
- !(lchr[(int)llp->unit.land.lnd_type].l_flags & L_SPY) &&
+ !(lchr[lp->lnd_type].l_flags & L_SPY) &&
sect.sct_own) {
sprintf(mess, "has been kidnapped by %s", cname(sect.sct_own));
lnd_stays(actor, mess, llp);
continue;
}
if (first) {
sect.sct_own) {
sprintf(mess, "has been kidnapped by %s", cname(sect.sct_own));
lnd_stays(actor, mess, llp);
continue;
}
if (first) {
- allx = land.lnd_x;
- ally = land.lnd_y;
+ allx = lp->lnd_x;
+ ally = lp->lnd_y;
- if (land.lnd_x != allx || land.lnd_y != ally)
+ if (lp->lnd_x != allx || lp->lnd_y != ally)
- if (land.lnd_mobil + 1 < (int)llp->mobil) {
- llp->mobil = land.lnd_mobil;
+ if (lp->lnd_mobil + 1 < (int)llp->mobil) {
+ llp->mobil = lp->lnd_mobil;
}
if (llp->mobil < *minmobp)
*minmobp = llp->mobil;
if (llp->mobil > *maxmobp)
*maxmobp = llp->mobil;
}
if (llp->mobil < *minmobp)
*minmobp = llp->mobil;
if (llp->mobil > *maxmobp)
*maxmobp = llp->mobil;