From 69c99a0f298c59feae8cdc705b34749da56ae5b9 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sun, 28 Dec 2014 22:24:17 +0100 Subject: [PATCH] march: Require all land units to start in the same sector The capability to march land units spread over several sectors is obscure and rarely useful. Accidental use is probably more frequent than intentional use. Issues: * Interactive prompts show only the leader's position, and give no clue that some land units are actually elsewhere. * Path finding is supported only when all marching land units are in the same sector. * In each step, the bmap is updated for the leader's radar. The bmap is not updated around other marching land units. Already odd when all units are in the leader's sector, and odder still when some are elsewhere. * Interdiction becomes rather complex. For each movement, every sector entered is interdicted independently. This means the same ship, land unit or plane can interdict multiple times. Interdiction order depends on the order the code examines land units. which the player can control. This is all pretty much undocumented. * Complicates the code and its maintenance. Multiplies the number of test cases needed to cover march. I feel we're better off without this feature. Signed-off-by: Markus Armbruster --- include/land.h | 4 +- info/march.t | 7 +-- src/lib/commands/marc.c | 4 +- src/lib/commands/navi.c | 8 ++-- src/lib/subs/lndsub.c | 91 ++++++++++++------------------------ tests/navi-march-test | 1 - tests/navi-march/02-march-1 | 3 ++ tests/navi-march/final.xdump | 2 +- tests/navi-march/journal.log | 15 ++++-- 9 files changed, 54 insertions(+), 81 deletions(-) diff --git a/include/land.h b/include/land.h index c1bd797d..e4266477 100644 --- a/include/land.h +++ b/include/land.h @@ -192,12 +192,12 @@ extern void lnd_submil(struct lndstr *, int); extern void lnd_takemob(struct emp_qelem *, double); extern int lnd_spyval(struct lndstr *); extern void intelligence_report(int, struct lndstr *, int, char *); -extern void lnd_mar(struct emp_qelem *, double *, double *, int *, natid); +extern void lnd_mar(struct emp_qelem *, double *, double *, 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_mar_one_sector(struct emp_qelem *, int, natid); extern int lnd_support(natid, natid, coord, coord, int); extern int lnd_can_attack(struct lndstr *); extern int lnd_fortify(struct lndstr *lp, int hard_amt); diff --git a/info/march.t b/info/march.t index ecb5bc58..bfc1afd1 100644 --- a/info/march.t +++ b/info/march.t @@ -3,7 +3,8 @@ .LV Basic .SY "march " The march command is the \*Qmove\*U command applied to land units. -You can control one unit or an entire army with it. +You can control one unit or an entire army with it, but they must all +start in the same sector. .s1 Land units may only move into sectors you own, sectors of countries you are allied with or deity-owned sectors with 1 exception. Spies. Spies @@ -115,10 +116,6 @@ For example, war band #18 stopped at -5,-3 .FI .s1 -Note that if you are marching multiple units, you may only specify a -destination sector on the command line if all the units start in the -same sector. -.s1 See \*Qinfo Mobility\*U for the mobility cost to march land units. .s1 Moving a unit through a sector that has been mined diff --git a/src/lib/commands/marc.c b/src/lib/commands/marc.c index 65b5a157..951aedaf 100644 --- a/src/lib/commands/marc.c +++ b/src/lib/commands/marc.c @@ -44,12 +44,12 @@ march(void) struct nstr_item ni_land; struct emp_qelem land_list; double minmob, maxmob; - int together; + int together = 1; if (!snxtitem(&ni_land, EF_LAND, player->argp[1], NULL)) return RET_SYN; lnd_sel(&ni_land, &land_list); - lnd_mar(&land_list, &minmob, &maxmob, &together, player->cnum); + lnd_mar(&land_list, &minmob, &maxmob, player->cnum); if (QEMPTY(&land_list)) { pr("No lands\n"); return RET_FAIL; diff --git a/src/lib/commands/navi.c b/src/lib/commands/navi.c index c398e848..54ab8c05 100644 --- a/src/lib/commands/navi.c +++ b/src/lib/commands/navi.c @@ -101,7 +101,7 @@ do_unit_move(struct emp_qelem *ulist, int *together, if (type == EF_SHIP) shp_nav(ulist, minmob, maxmob, together, player->cnum); else - lnd_mar(ulist, minmob, maxmob, together, player->cnum); + lnd_mar(ulist, minmob, maxmob, player->cnum); if (QEMPTY(ulist)) { pr("No %s left\n", type == EF_SHIP ? "ships" : "lands"); return RET_OK; @@ -128,7 +128,7 @@ do_unit_move(struct emp_qelem *ulist, int *together, if (type == EF_SHIP) shp_nav(ulist, minmob, maxmob, together, player->cnum); else - lnd_mar(ulist, minmob, maxmob, together, player->cnum); + lnd_mar(ulist, minmob, maxmob, player->cnum); if (QEMPTY(ulist)) { pr("No %s left\n", type == EF_SHIP ? "ships" : "lands"); return RET_OK; @@ -157,9 +157,7 @@ do_unit_move(struct emp_qelem *ulist, int *together, 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); } moved = 1; cp++; diff --git a/src/lib/subs/lndsub.c b/src/lib/subs/lndsub.c index c80da183..ab6ac4aa 100644 --- a/src/lib/subs/lndsub.c +++ b/src/lib/subs/lndsub.c @@ -454,21 +454,17 @@ lnd_insque(struct lndstr *lp, struct emp_qelem *list) /* This function assumes that the list was created by lnd_sel */ void lnd_mar(struct emp_qelem *list, double *minmobp, double *maxmobp, - int *togetherp, natid actor) + natid actor) { struct emp_qelem *qp; struct emp_qelem *next; struct ulist *llp; - struct lndstr *lp; + struct lndstr *lp, *ldr = NULL; struct sctstr sect; - coord allx; - coord ally; - int first = 1; char mess[128]; *minmobp = 9876.0; *maxmobp = -9876.0; - *togetherp = 1; for (qp = list->q_back; qp != list; qp = next) { next = qp->q_back; llp = (struct ulist *)qp; @@ -519,13 +515,12 @@ lnd_mar(struct emp_qelem *list, double *minmobp, double *maxmobp, lnd_stays(actor, mess, llp); continue; } - if (first) { - allx = lp->lnd_x; - ally = lp->lnd_y; - first = 0; + if (!ldr) + ldr = lp; + else if (lp->lnd_x != ldr->lnd_x || lp->lnd_y != ldr->lnd_y) { + lnd_stays(actor, "is not with the leader", llp); + continue; } - if (lp->lnd_x != allx || lp->lnd_y != ally) - *togetherp = 0; if (lp->lnd_mobil + 1 < (int)llp->mobil) { llp->mobil = lp->lnd_mobil; } @@ -978,14 +973,12 @@ int lnd_abandon_askyn(struct emp_qelem *list) } int -lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor, - int together) +lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor) { struct sctstr sect, osect; struct emp_qelem *qp; struct emp_qelem *next; struct ulist *llp; - struct emp_qelem cur, done; coord dx; coord dy; coord newx; @@ -998,6 +991,9 @@ lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor, int rel; int oldown; + if (CANT_HAPPEN(QEMPTY(list))) + return 1; + if (dir <= DIR_STOP || dir >= DIR_VIEW) { lnd_mar_put(list, actor); return 1; @@ -1005,19 +1001,21 @@ lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor, dx = diroff[dir][0]; dy = diroff[dir][1]; + llp = (struct ulist *)list->q_back; + getsect(llp->unit.land.lnd_x, llp->unit.land.lnd_y, &osect); + oldown = osect.sct_own; + newx = xnorm(llp->unit.land.lnd_x + dx); + newy = ynorm(llp->unit.land.lnd_y + dy); + getsect(newx, newy, §); + rel = relations_with(sect.sct_own, actor); + move = 0; for (qp = list->q_back; qp != list; qp = next) { next = qp->q_back; llp = (struct ulist *)qp; - getsect(llp->unit.land.lnd_x, llp->unit.land.lnd_y, &osect); - oldown = osect.sct_own; - newx = xnorm(llp->unit.land.lnd_x + dx); - newy = ynorm(llp->unit.land.lnd_y + dy); - getsect(newx, newy, §); stuck = lnd_check_mar(&llp->unit.land, §); if (stuck == LND_STUCK_NOT - && (relations_with(sect.sct_own, actor) == ALLIED - || !sect.sct_own + && (!sect.sct_own || rel == ALLIED || (lchr[llp->unit.land.lnd_type].l_flags & L_SPY))) { move = 1; } @@ -1026,19 +1024,13 @@ lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor, for (qp = list->q_back; qp != list; qp = next) { next = qp->q_back; llp = (struct ulist *)qp; - getsect(llp->unit.land.lnd_x, llp->unit.land.lnd_y, &osect); - oldown = osect.sct_own; - newx = xnorm(llp->unit.land.lnd_x + dx); - newy = ynorm(llp->unit.land.lnd_y + dy); - getsect(newx, newy, §); - rel = relations_with(sect.sct_own, actor); stuck = lnd_check_mar(&llp->unit.land, §); if (stuck != LND_STUCK_NOT || (sect.sct_own && rel != ALLIED && !(lchr[llp->unit.land.lnd_type].l_flags & L_SPY))) { if (stuck == LND_STUCK_NO_RAIL && (!sect.sct_own || rel == ALLIED)) { - if (together && !move) { + if (!move) { mpr(actor, "no rail system in %s\n", xyas(newx, newy, actor)); return 1; @@ -1049,7 +1041,7 @@ lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor, continue; } } else { - if (together && !move) { + if (!move) { mpr(actor, "can't go to %s\n", xyas(newx, newy, actor)); return 1; } else { @@ -1104,38 +1096,15 @@ lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor, if (QEMPTY(list)) return stopping; - /* interdict land units sector by sector */ - emp_initque(&cur); - emp_initque(&done); - while (!QEMPTY(list)) { - llp = (struct ulist *)list->q_back; - newx = llp->unit.land.lnd_x; - newy = llp->unit.land.lnd_y; - /* move units in NEWX,NEWY to cur */ - visible = 0; - for (qp = list->q_back; qp != list; qp = next) { - next = qp->q_back; - llp = (struct ulist *)qp; - if (llp->unit.land.lnd_x == newx && llp->unit.land.lnd_y == newy) { - emp_remque(qp); - emp_insque(qp, &cur); - if (!(lchr[(int)llp->unit.land.lnd_type].l_flags & L_SPY)) - visible = 1; - } - } - /* interdict them */ - if (visible) - stopping |= lnd_interdict(&cur, newx, newy, actor); - /* move survivors to done */ - for (qp = cur.q_back; qp != &cur; qp = next) { - next = qp->q_back; - emp_remque(qp); - emp_insque(qp, &done); - } + visible = 0; + for (qp = list->q_back; qp != list; qp = next) { + next = qp->q_back; + llp = (struct ulist *)qp; + if (!(lchr[(int)llp->unit.land.lnd_type].l_flags & L_SPY)) + visible = 1; } - /* assign surviving land units back to list */ - emp_insque(list, &done); - emp_remque(&done); + if (visible) + stopping |= lnd_interdict(list, newx, newy, actor); return stopping; } diff --git a/tests/navi-march-test b/tests/navi-march-test index f4ca34b6..776b739e 100755 --- a/tests/navi-march-test +++ b/tests/navi-march-test @@ -17,7 +17,6 @@ MARKET 1 EOF customize big-city # TODO cover scattered navigate -# TODO cover scattered march # TODO cover RAILWAYS 0 begin_test "$srcdir"/tests/navi-march/setup-POGO diff --git a/tests/navi-march/02-march-1 b/tests/navi-march/02-march-1 index 1d6ac57c..6aee63b1 100644 --- a/tests/navi-march/02-march-1 +++ b/tests/navi-march/02-march-1 @@ -16,6 +16,9 @@ march 22/21/23 jh march 24 nh | kidnapped in -5,3 march 25 gh +| not with leader +march 21/10 nh +__cmd added 1 1 0 || get stuck on the way | die, by hitting mine in 8,6 | #31 hits a mine, #30 doesn't diff --git a/tests/navi-march/final.xdump b/tests/navi-march/final.xdump index 04c3fddf..0388a371 100644 --- a/tests/navi-march/final.xdump +++ b/tests/navi-march/final.xdump @@ -214,7 +214,7 @@ uid owner xloc yloc type effic mobil off tech opx opy mission radius army ship h 14 1 1 1 0 100 127 0 30 1 1 none 3 "" 1 0 42 () "" 0 2 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0 15 1 1 1 0 100 127 0 30 1 1 none 3 "" -1 0 42 () "" 0 2 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 1 0 20 1 3 3 0 100 105 0 30 1 3 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0 -21 1 1 3 0 100 127 0 30 1 3 reserve 3 "" -1 127 42 (bombed) "hhhhn" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0 +21 1 2 4 0 100 105 0 30 1 3 none 3 "" -1 0 42 () "" 0 5 0 0 0 0 0 0 0 0 0 0 0 0 healthy 0 -1 0 22 1 3 3 7 100 60 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 23 1 3 3 7 50 -5 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 24 1 2 2 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 diff --git a/tests/navi-march/journal.log b/tests/navi-march/journal.log index e1570b35..42af4f6f 100644 --- a/tests/navi-march/journal.log +++ b/tests/navi-march/journal.log @@ -786,6 +786,15 @@ Play#1 output Play#1 1 No lands Play#1 output Play#1 1 command failed Play#1 output Play#1 6 0 583 + Play#1 input march 21/10 nh + Play#1 command march + Play#1 output Play#1 1 cav cavalry #10 is not with the leader & stays in 2,2 + Play#1 output Play#1 1 Leader is cav cavalry #21 + Play#1 output Play#1 1 cav cavalry #21 stopped at 2,4 + Play#1 output Play#1 6 0 582 + Play#1 input __cmd added 1 1 0 + Play#1 command __cmd + Play#1 output Play#1 6 0 583 Play#1 input march 31/30 jX Play#1 command march Play#1 output Play#1 1 Leader is cav cavalry #31 @@ -1480,7 +1489,7 @@ Play#0 output Play#0 1 1 14 cav cavalry 1,1 100% 2 0 127 0 30 42% 0 0 1S Play#0 output Play#0 1 1 15 cav cavalry 1,1 100% 2 0 127 0 30 42% 0 0 1L Play#0 output Play#0 1 1 20 cav cavalry 3,3 100% 5 0 105 0 30 42% 0 0 - Play#0 output Play#0 1 1 21 cav cavalry 1,3 100% 5 127 127 0 30 42% 0 0 + Play#0 output Play#0 1 1 21 cav cavalry 2,4 100% 5 0 105 0 30 42% 0 0 Play#0 output Play#0 1 1 22 tra train 3,3 100% 5 0 60 0 40 42% 0 0 Play#0 output Play#0 1 1 23 tra train 3,3 50% 5 0 -5 0 40 42% 0 0 Play#0 output Play#0 1 1 24 tra train 2,2 100% 5 0 127 0 40 42% 0 0 @@ -1554,8 +1563,7 @@ Play#0 output Play#0 1 1 4 eng engineer 1,1 hhhhn b Play#0 output Play#0 1 2 11 cav cavalry 1,1 hhhhn b Play#0 output Play#0 1 1 12 cav cavalry 1,1 hhhhn b - Play#0 output Play#0 1 1 21 cav cavalry 1,3 hhhhn b - Play#0 output Play#0 1 5 units + Play#0 output Play#0 1 4 units Play#0 output Play#0 6 0 636 Play#0 input miss l * ?mission#0 q Play#0 command mission @@ -1563,7 +1571,6 @@ Play#0 output Play#0 1 eng engineer #4 1,1 1,1 1 is on a reserve mission Play#0 output Play#0 1 cav cavalry #11 1,1 1,1 3 is on a reserve mission Play#0 output Play#0 1 cav cavalry #12 1,1 1,1 3 is on a reserve mission - Play#0 output Play#0 1 cav cavalry #21 1,3 1,3 3 is on a reserve mission Play#0 output Play#0 6 0 634 Play#0 input ctld Play#0 output Play#0 1 Bye-bye