Improve slightly on Peje's L12 patch, changing documentation to match.

This commit is contained in:
Eric S. Raymond 2017-06-13 07:36:57 -04:00
parent 804e60ccff
commit 3bdab31a0d
3 changed files with 100 additions and 90 deletions

4
TODO
View file

@ -7,9 +7,7 @@ remain to be cleaned up:
rather promiscuously to pass around information that ought to be function rather promiscuously to pass around information that ought to be function
arguments in a modern language. arguments in a modern language.
* Remaining unstructured gotos in playermove() and do_command(). The goto L12 * Remaining unstructured gotos in do_command().
in playermove() is particularly horrible, jumping backwards into the
middle of a loop.
* The program is still pretty much typeless - full of magic numbers being * The program is still pretty much typeless - full of magic numbers being
sliced and diced in cryptic ways. Some attempt has been made to introduce sliced and diced in cryptic ways. Some attempt has been made to introduce

176
main.c
View file

@ -399,6 +399,10 @@ static bool dwarfmove(void)
game.dloc[PIRATE]=game.chloc; game.dloc[PIRATE]=game.chloc;
game.odloc[PIRATE]=game.chloc; game.odloc[PIRATE]=game.chloc;
game.dseen[PIRATE]=false; game.dseen[PIRATE]=false;
/* C doesn't have what the Structured rogramming
* Theorem says we need here - multi-level loop
* breakout. We simulate with a goto. Irreducible, alas.
*/
goto jumpout; goto jumpout;
} }
if (HERE(j)) if (HERE(j))
@ -606,96 +610,104 @@ static bool playermove(FILE *cmdin, token_t verb, int motion)
} }
LL=LL/1000; LL=LL/1000;
L12: do {
for (;;) { /*
game.newloc=LL/1000; * (ESR) This special-travel loop may have to be repeated if it includes
motion=MOD(game.newloc,100); * the plover passage. Same deal for any future cases wgerw we beed to
if (game.newloc <= 300) { * block travel and then redo it once the blocking condition has been
if (game.newloc <= 100) { * removed.
if (game.newloc == 0 || PCT(game.newloc)) */
break; for (;;) {
game.newloc=LL/1000;
motion=MOD(game.newloc,100);
if (game.newloc <= 300) {
if (game.newloc <= 100) {
if (game.newloc == 0 || PCT(game.newloc))
break;
/* else fall through */
} if (TOTING(motion) || (game.newloc > 200 && AT(motion)))
break;
/* else fall through */ /* else fall through */
} if (TOTING(motion) || (game.newloc > 200 && AT(motion))) }
break; else if (game.prop[motion] != game.newloc/100-3)
/* else fall through */ break;
}
else if (game.prop[motion] != game.newloc/100-3)
break;
do {
if (TRAVEL[KK] < 0)BUG(25);
++KK;
game.newloc=labs(TRAVEL[KK])/1000;
} while
(game.newloc == LL);
LL=game.newloc;
}
game.newloc=MOD(LL,1000);
if (game.newloc <= 300)
return true;
if (game.newloc <= 500) {
game.newloc=game.newloc-300;
switch (game.newloc)
{
case 1:
/* Travel 301. Plover-alcove passage. Can carry only
* emerald. Note: travel table must include "useless"
* entries going through passage, which can never be used for
* actual motion, but can be spotted by "go back". */
game.newloc=99+100-game.loc;
if (game.holdng == 0 || (game.holdng == 1 && TOTING(EMRALD)))
return true;
game.newloc=game.loc;
RSPEAK(117);
return true;
case 2:
/* Travel 302. Plover transport. Drop the emerald (only use
* special travel if toting it), so he's forced to use the
* plover-passage to get it out. Having dropped it, go back and
* pretend he wasn't carrying it after all. */
DROP(EMRALD,game.loc);
do { do {
if (TRAVEL[KK] < 0)BUG(25); if (TRAVEL[KK] < 0)BUG(25);
++KK; ++KK;
game.newloc=labs(TRAVEL[KK])/1000; game.newloc=labs(TRAVEL[KK])/1000;
} while } while
(game.newloc == LL); (game.newloc == LL);
goto L12; LL=game.newloc;
case 3:
/* Travel 303. Troll bridge. Must be done only as special
* motion so that dwarves won't wander across and encounter
* the bear. (They won't follow the player there because
* that region is forbidden to the pirate.) If
* game.prop(TROLL)=1, he's crossed since paying, so step out
* and block him. (standard travel entries check for
* game.prop(TROLL)=0.) Special stuff for bear. */
if (game.prop[TROLL] == 1) {
PSPEAK(TROLL,1);
game.prop[TROLL]=0;
MOVE(TROLL2,0);
MOVE(TROLL2+NOBJECTS,0);
MOVE(TROLL,PLAC[TROLL]);
MOVE(TROLL+NOBJECTS,FIXD[TROLL]);
JUGGLE(CHASM);
game.newloc=game.loc;
return true;
} else {
game.newloc=PLAC[TROLL]+FIXD[TROLL]-game.loc;
if (game.prop[TROLL] == 0)game.prop[TROLL]=1;
if (!TOTING(BEAR)) return true;
RSPEAK(162);
game.prop[CHASM]=1;
game.prop[TROLL]=2;
DROP(BEAR,game.newloc);
game.fixed[BEAR]= -1;
game.prop[BEAR]=3;
game.oldlc2=game.newloc;
croak(cmdin);
return false;
}
} }
BUG(20);
} game.newloc=MOD(LL,1000);
if (game.newloc <= 300)
return true;
if (game.newloc <= 500) {
game.newloc=game.newloc-300;
switch (game.newloc)
{
case 1:
/* Travel 301. Plover-alcove passage. Can carry only
* emerald. Note: travel table must include "useless"
* entries going through passage, which can never be used for
* actual motion, but can be spotted by "go back". */
game.newloc=99+100-game.loc;
if (game.holdng == 0 || (game.holdng == 1 && TOTING(EMRALD)))
return true;
game.newloc=game.loc;
RSPEAK(117);
return true;
case 2:
/* Travel 302. Plover transport. Drop the emerald (only use
* special travel if toting it), so he's forced to use the
* plover-passage to get it out. Having dropped it, go back and
* pretend he wasn't carrying it after all. */
DROP(EMRALD,game.loc);
do {
if (TRAVEL[KK] < 0)BUG(25);
++KK;
game.newloc=labs(TRAVEL[KK])/1000;
} while
(game.newloc == LL);
continue; /* back to top of do/while loop */
case 3:
/* Travel 303. Troll bridge. Must be done only as special
* motion so that dwarves won't wander across and encounter
* the bear. (They won't follow the player there because
* that region is forbidden to the pirate.) If
* game.prop(TROLL)=1, he's crossed since paying, so step out
* and block him. (standard travel entries check for
* game.prop(TROLL)=0.) Special stuff for bear. */
if (game.prop[TROLL] == 1) {
PSPEAK(TROLL,1);
game.prop[TROLL]=0;
MOVE(TROLL2,0);
MOVE(TROLL2+NOBJECTS,0);
MOVE(TROLL,PLAC[TROLL]);
MOVE(TROLL+NOBJECTS,FIXD[TROLL]);
JUGGLE(CHASM);
game.newloc=game.loc;
return true;
} else {
game.newloc=PLAC[TROLL]+FIXD[TROLL]-game.loc;
if (game.prop[TROLL] == 0)game.prop[TROLL]=1;
if (!TOTING(BEAR)) return true;
RSPEAK(162);
game.prop[CHASM]=1;
game.prop[TROLL]=2;
DROP(BEAR,game.newloc);
game.fixed[BEAR]= -1;
game.prop[BEAR]=3;
game.oldlc2=game.newloc;
croak(cmdin);
return false;
}
}
BUG(20);
}
} while
(false);
RSPEAK(game.newloc-500); RSPEAK(game.newloc-500);
game.newloc=game.loc; game.newloc=game.loc;
return true; return true;

View file

@ -81,7 +81,7 @@ against a comprehesive test suite that we built first and verified with
coverage tools. This is what you are running when you do "make check". coverage tools. This is what you are running when you do "make check".
This move entailed some structural changes. The most important was This move entailed some structural changes. The most important was
the refactoring of 354 gotos into if/loop/break structures. We the refactoring of 355 gotos into if/loop/break structures. We
also abolished almost all shared globals; the main one left is a also abolished almost all shared globals; the main one left is a
struct holding the game's saveable/restorable state. struct holding the game's saveable/restorable state.
@ -108,10 +108,10 @@ ways:
and the choice to refrain will make forward translation into future and the choice to refrain will make forward translation into future
languages easier. languages easier.
* There are 20 gotos left that resist restructuring; all but one of * There are 19 gotos left that resist restructuring; all of these are
these are in the principal command interpreter function implementing in the principal command interpreter function implementing its state
its state machine. A 21st, a two-level loop breakout, is not reducible machine. A 21st, a two-level loop breakout, is not reducible even
even in principle. in principle.
* Linked lists (for objects at a location) are implemented using an array * Linked lists (for objects at a location) are implemented using an array
of link indices. This is a surviving FORTRANism that is quite unlike of link indices. This is a surviving FORTRANism that is quite unlike