Partial misc.c gotoectomy.

This commit is contained in:
Eric S. Raymond 2017-06-07 16:30:51 -04:00
parent ed80d6dd2f
commit 1d3a087c39

396
misc.c
View file

@ -28,7 +28,7 @@ L10: L=labs(LINES[K])-1;
LNPOSN=1; LNPOSN=1;
STATE=0; STATE=0;
for (I=K; I<=L; I++) { for (I=K; I<=L; I++) {
PUTTXT(LINES[I],STATE,2); PUTTXT(LINES[I],STATE,2);
} /* end loop */ } /* end loop */
LNPOSN=0; LNPOSN=0;
L30: LNPOSN=LNPOSN+1; L30: LNPOSN=LNPOSN+1;
@ -111,48 +111,43 @@ L40: if(BLANK)TYPE0();
return; return;
} }
void PSPEAK(vocab_t MSG,int SKIP) { void PSPEAK(vocab_t MSG,int SKIP)
long I, M; /* Find the skip+1st message from msg and print it. MSG should be
* the index of the inventory message for object. (INVEN+N+1 message
/* Find the skip+1st message from msg and print it. MSG should be the index of * is game.prop=N message). */
* the inventory message for object. (INVEN+N+1 message is game.prop=N message). */ {
long I, M;
M=PTEXT[MSG]; M=PTEXT[MSG];
if(SKIP < 0) goto L9; if(SKIP < 0)
goto L9;
for (I=0; I<=SKIP; I++) { for (I=0; I<=SKIP; I++) {
L1: M=labs(LINES[M]); L1: M=labs(LINES[M]);
if(LINES[M] >= 0) goto L1; if(LINES[M] >= 0)
/*etc*/ ; goto L1;
} /* end loop */ }
L9: SPEAK(M); L9: SPEAK(M);
return; return;
} }
void RSPEAK(vocab_t i)
void RSPEAK(vocab_t I) { /* Print the i-th "random" message (section 6 of database). */
{
/* Print the I-TH "random" message (section 6 of database). */ if (i != 0)
SPEAK(RTEXT[i]);
if(I != 0)SPEAK(RTEXT[I]);
return;
} }
void SETPRM(long first, long p1, long p2)
void SETPRM(long FIRST, long P1, long P2) {
;
/* Stores parameters into the PRMCOM parms array for use by speak. P1 and P2 /* Stores parameters into the PRMCOM parms array for use by speak. P1 and P2
* are stored into PARMS(FIRST) and PARMS(FIRST+1). */ * are stored into PARMS(first) and PARMS(first+1). */
{
if(first >= MAXPARMS)
if(FIRST >= 25)BUG(29); BUG(29);
PARMS[FIRST]=P1; else {
{long x = FIRST+1; PARMS[x]=P2;} PARMS[first] = p1;
return; PARMS[first+1] = p2;
}
} }
#undef GETIN #undef GETIN
#define WORD1 (*wORD1) #define WORD1 (*wORD1)
#define WORD1X (*wORD1X) #define WORD1X (*wORD1X)
@ -359,53 +354,50 @@ L2: LNLENG=LNLENG+DELTA;
} }
void TYPE0() { void TYPE0(void)
long TEMP;
/* Type a blank line. This procedure is provided as a convenience for callers /* Type a blank line. This procedure is provided as a convenience for callers
* who otherwise have no use for MAPCOM. */ * who otherwise have no use for MAPCOM. */
{
long temp;
TEMP=LNLENG; temp=LNLENG;
LNLENG=0; LNLENG=0;
TYPE(); TYPE();
LNLENG=TEMP; LNLENG=temp;
return; return;
} }
/* Suspend/resume I/O routines (SAVWDS, SAVARR, SAVWRD) */ /* Suspend/resume I/O routines (SAVWDS, SAVARR, SAVWRD) */
#undef SAVWDS #undef SAVWDS
void fSAVWDS(long *W1, long *W2, long *W3, long *W4, long *W5, long *W6, long *W7) { void fSAVWDS(long *W1, long *W2, long *W3, long *W4,
long *W5, long *W6, long *W7)
/* Write or read 7 variables. See SAVWRD. */ /* Write or read 7 variables. See SAVWRD. */
{
SAVWRD(0,(*W1)); SAVWRD(0,(*W1));
SAVWRD(0,(*W2)); SAVWRD(0,(*W2));
SAVWRD(0,(*W3)); SAVWRD(0,(*W3));
SAVWRD(0,(*W4)); SAVWRD(0,(*W4));
SAVWRD(0,(*W5)); SAVWRD(0,(*W5));
SAVWRD(0,(*W6)); SAVWRD(0,(*W6));
SAVWRD(0,(*W7)); SAVWRD(0,(*W7));
return; return;
} }
#define SAVWDS(W1,W2,W3,W4,W5,W6,W7) fSAVWDS(&W1,&W2,&W3,&W4,&W5,&W6,&W7) #define SAVWDS(W1,W2,W3,W4,W5,W6,W7) fSAVWDS(&W1,&W2,&W3,&W4,&W5,&W6,&W7)
#undef SAVARR #undef SAVARR
void fSAVARR(long ARR[], long N) { void fSAVARR(long arr[], long n)
long I; /* Write or read an array of n words. See SAVWRD. */
{
long i;
/* Write or read an array of N words. See SAVWRD. */ for (i=1; i<=n; i++) {
SAVWRD(0,arr[i]);
}
for (I=1; I<=N; I++) { return;
SAVWRD(0,ARR[I]);
} /* end loop */
return;
} }
#define SAVARR(ARR,N) fSAVARR(ARR,N) #define SAVARR(ARR,N) fSAVARR(ARR,N)
#undef SAVWRD #undef SAVWRD
#define WORD (*wORD) #define WORD (*wORD)
void fSAVWRD(long OP, long *wORD) { void fSAVWRD(long OP, long *wORD) {
@ -566,110 +558,107 @@ L8: game.link[TEMP]=game.link[OBJECT];
return; return;
} }
void DROP(long OBJECT, long WHERE) { void DROP(long object, long where)
/* Place an object at a given loc, prefixing it onto the game.atloc list. Decr /* Place an object at a given loc, prefixing it onto the game.atloc list. Decr
* game.holdng if the object was being toted. */ * game.holdng if the object was being toted. */
{
if(OBJECT > NOBJECTS) goto L1; if(object > NOBJECTS) goto L1;
if(game.place[OBJECT] == -1)game.holdng=game.holdng-1; if(game.place[object] == -1)
game.place[OBJECT]=WHERE; game.holdng=game.holdng-1;
goto L2; game.place[object]=where;
L1: {long x = OBJECT-NOBJECTS; game.fixed[x]=WHERE;} goto L2;
L2: if(WHERE <= 0)return; L1: game.fixed[object-NOBJECTS]=where;
game.link[OBJECT]=game.atloc[WHERE]; L2: if(where <= 0)
game.atloc[WHERE]=OBJECT;
return; return;
game.link[object]=game.atloc[where];
game.atloc[where]=object;
} }
long ATDWRF(long where)
long ATDWRF(long WHERE) {
long AT, I;
/* Return the index of first dwarf at the given location, zero if no dwarf is /* Return the index of first dwarf at the given location, zero if no dwarf is
* there (or if dwarves not active yet), -1 if all dwarves are dead. Ignore * there (or if dwarves not active yet), -1 if all dwarves are dead. Ignore
* the pirate (6th dwarf). */ * the pirate (6th dwarf). */
{
long at, i;
at=0;
AT=0; if(game.dflag < 2)
if(game.dflag < 2)return(AT); return(at);
AT= -1; at= -1;
for (I=1; I<=NDWARVES-1; I++) { for (i=1; i<=NDWARVES-1; i++) {
if(game.dloc[I] == WHERE) goto L2; if(game.dloc[i] == where)
if(game.dloc[I] != 0)AT=0; return i;
} /* end loop */ if(game.dloc[i] != 0)
return(AT); at=0;
} /* end loop */
L2: AT=I; return(at);
return(AT);
} }
/* Utility routines (SETBIT, TSTBIT, set_seed, get_next_lcg_value, /* Utility routines (SETBIT, TSTBIT, set_seed, get_next_lcg_value,
* randrange, RNDVOC, BUG) */ * randrange, RNDVOC, BUG) */
long SETBIT(long bit) { long SETBIT(long bit)
/* Returns 2**bit for use in constructing bit-masks. */ /* Returns 2**bit for use in constructing bit-masks. */
{
return(2 << bit); return(2 << bit);
} }
bool TSTBIT(long mask, int bit) { bool TSTBIT(long mask, int bit)
/* Returns true if the specified bit is set in the mask. */ /* Returns true if the specified bit is set in the mask. */
return((mask & (1 << bit)) != 0); {
return (mask & (1 << bit)) != 0;
} }
void set_seed(long seedval) void set_seed(long seedval)
/* Set the LCG seed */
{ {
lcgstate.x = (unsigned long) seedval % lcgstate.m; lcgstate.x = (unsigned long) seedval % lcgstate.m;
} }
unsigned long get_next_lcg_value(void) unsigned long get_next_lcg_value(void)
/* Return the LCG's current value, and then iterate it. */
{ {
/* Return the LCG's current value, and then iterate it. */ unsigned long old_x = lcgstate.x;
unsigned long old_x = lcgstate.x; lcgstate.x = (lcgstate.a * lcgstate.x + lcgstate.c) % lcgstate.m;
lcgstate.x = (lcgstate.a * lcgstate.x + lcgstate.c) % lcgstate.m; return old_x;
return(old_x);
} }
long randrange(long range) long randrange(long range)
/* Return a random integer from [0, range). */
{ {
/* Return a random integer from [0, range). */ return range * get_next_lcg_value() / lcgstate.m;
long result = range * get_next_lcg_value() / lcgstate.m;
return(result);
} }
long RNDVOC(long CHAR, long FORCE) { long RNDVOC(long second, long force)
/* Searches the vocabulary for a word whose second character is char, and /* Searches the vocabulary ATAB for a word whose second character is
* changes that word such that each of the other four characters is a * char, and changes that word such that each of the other four
* random letter. If force is non-zero, it is used as the new word. * characters is a random letter. If force is non-zero, it is used
* Returns the new word. */ * as the new word. Returns the new word. */
{
long rnd = force;
long RND; if (rnd == 0) {
for (int i = 1; i <= 5; i++) {
RND=FORCE; long j = 11 + randrange(26);
if (i == 2)
if (RND == 0) { j = second;
for (int I = 1; I <= 5; I++) { rnd = rnd * 64 + j;
long J = 11 + randrange(26);
if (I == 2)
J = CHAR;
RND = RND * 64 + J;
}
} }
}
long DIV = 64L * 64L * 64L; long div = 64L * 64L * 64L;
for (int I = 1; I <= TABSIZ; I++) { for (int i = 1; i <= TABSIZ; i++) {
if (MOD(ATAB[I]/DIV, 64L) == CHAR) if (MOD(ATAB[i]/div, 64L) == second)
{ {
ATAB[I] = RND; ATAB[i] = rnd;
break; break;
}
} }
}
return(RND); return rnd;
} }
void BUG(long NUM) { void BUG(long num)
/* The following conditions are currently considered fatal bugs. Numbers < 20 /* The following conditions are currently considered fatal bugs. Numbers < 20
* are detected while reading the database; the others occur at "run time". * are detected while reading the database; the others occur at "run time".
* 0 Message line > 70 characters * 0 Message line > 70 characters
@ -694,92 +683,90 @@ void BUG(long NUM) {
* 27 Hint number exceeds goto list * 27 Hint number exceeds goto list
* 28 Invalid month returned by date function * 28 Invalid month returned by date function
* 29 Too many parameters given to SETPRM */ * 29 Too many parameters given to SETPRM */
{
printf("Fatal error %ld. See source code for interpretation.\n", printf("Fatal error %ld. See source code for interpretation.\n", num);
NUM); exit(0);
exit(0);
} }
/* Machine dependent routines (MAPLIN, TYPE, MPINIT, SAVEIO) */ /* Machine dependent routines (MAPLIN, TYPE, MPINIT, SAVEIO) */
void MAPLIN(FILE *OPENED) { void MAPLIN(FILE *OPENED)
long I, VAL; {
long I, VAL;
/* Read a line of input, from the specified input source, /* Read a line of input, from the specified input source,
* translate the chars to integers in the range 0-126 and store * translate the chars to integers in the range 0-126 and store
* them in the common array "INLINE". Integer values are as follows: * them in the common array "INLINE". Integer values are as follows:
* 0 = space [ASCII CODE 40 octal, 32 decimal] * 0 = space [ASCII CODE 40 octal, 32 decimal]
* 1-2 = !" [ASCII 41-42 octal, 33-34 decimal] * 1-2 = !" [ASCII 41-42 octal, 33-34 decimal]
* 3-10 = '()*+,-. [ASCII 47-56 octal, 39-46 decimal] * 3-10 = '()*+,-. [ASCII 47-56 octal, 39-46 decimal]
* 11-36 = upper-case letters * 11-36 = upper-case letters
* 37-62 = lower-case letters * 37-62 = lower-case letters
* 63 = percent (%) [ASCII 45 octal, 37 decimal] * 63 = percent (%) [ASCII 45 octal, 37 decimal]
* 64-73 = digits, 0 through 9 * 64-73 = digits, 0 through 9
* Remaining characters can be translated any way that is convenient; * Remaining characters can be translated any way that is convenient;
* The "TYPE" routine below is used to map them back to characters when * The "TYPE" routine below is used to map them back to characters when
* necessary. The above mappings are required so that certain special * necessary. The above mappings are required so that certain special
* characters are known to fit in 6 bits and/or can be easily spotted. * characters are known to fit in 6 bits and/or can be easily spotted.
* Array elements beyond the end of the line should be filled with 0, * Array elements beyond the end of the line should be filled with 0,
* and LNLENG should be set to the index of the last character. * and LNLENG should be set to the index of the last character.
* *
* If the data file uses a character other than space (e.g., tab) to * If the data file uses a character other than space (e.g., tab) to
* separate numbers, that character should also translate to 0. * separate numbers, that character should also translate to 0.
* *
* This procedure may use the map1,map2 arrays to maintain static data for * This procedure may use the map1,map2 arrays to maintain static data for
* the mapping. MAP2(1) is set to 0 when the program starts * the mapping. MAP2(1) is set to 0 when the program starts
* and is not changed thereafter unless the routines on this page choose * and is not changed thereafter unless the routines on this page choose
* to do so. */ * to do so. */
if(MAP2[1] == 0)MPINIT(); if(MAP2[1] == 0)MPINIT();
if (!oldstyle && OPENED == stdin) if (!oldstyle && OPENED == stdin)
fputs("> ", stdout); fputs("> ", stdout);
do { do {
IGNORE(fgets(rawbuf,sizeof(rawbuf)-1,OPENED)); IGNORE(fgets(rawbuf,sizeof(rawbuf)-1,OPENED));
} while } while
(!feof(OPENED) && rawbuf[0] == '#'); (!feof(OPENED) && rawbuf[0] == '#');
if (feof(OPENED)) { if (feof(OPENED)) {
if (logfp && OPENED == stdin) if (logfp && OPENED == stdin)
fclose(logfp); fclose(logfp);
} else { } else {
if (logfp && OPENED == stdin) if (logfp && OPENED == stdin)
IGNORE(fputs(rawbuf, logfp)); IGNORE(fputs(rawbuf, logfp));
else if (!isatty(0)) else if (!isatty(0))
IGNORE(fputs(rawbuf, stdout)); IGNORE(fputs(rawbuf, stdout));
strcpy(INLINE+1, rawbuf); strcpy(INLINE+1, rawbuf);
LNLENG=0; LNLENG=0;
for (I=1; I<=(long)sizeof(INLINE) && INLINE[I]!=0; I++) { for (I=1; I<=(long)sizeof(INLINE) && INLINE[I]!=0; I++) {
VAL=INLINE[I]+1; VAL=INLINE[I]+1;
INLINE[I]=MAP1[VAL]; INLINE[I]=MAP1[VAL];
if(INLINE[I] != 0)LNLENG=I; if(INLINE[I] != 0)LNLENG=I;
} /* end loop */ } /* end loop */
LNPOSN=1; LNPOSN=1;
} }
} }
void TYPE(void) { void TYPE(void)
long I, VAL;
/* Type the first "LNLENG" characters stored in inline, mapping them /* Type the first "LNLENG" characters stored in inline, mapping them
* from integers to text per the rules described above. INLINE(I), * from integers to text per the rules described above. INLINE
* I=1,LNLENG may be changed by this routine. */ * may be changed by this routine. */
{
long i;
if(LNLENG != 0) goto L10; if(LNLENG == 0) {
printf("\n"); printf("\n");
return; return;
}
L10: if(MAP2[1] == 0)MPINIT(); if(MAP2[1] == 0)
for (I=1; I<=LNLENG; I++) { MPINIT();
VAL=INLINE[I]; for (i=1; i<=LNLENG; i++) {
{long x = VAL+1; INLINE[I]=MAP2[x];} INLINE[i]=MAP2[INLINE[i]+1];
} /* end loop */ }
{long x = LNLENG+1; INLINE[x]=0;} INLINE[LNLENG+1]=0;
printf("%s\n",INLINE+1); printf("%s\n", INLINE+1);
return; return;
} }
void MPINIT(void) { void MPINIT(void) {
@ -846,11 +833,12 @@ L30: if(IN)IGNORE(fread(ARR,sizeof(long),250,F));
} }
void DATIME(long* D, long* T) { void DATIME(long* D, long* T)
struct timeval tv; {
gettimeofday(&tv, NULL); struct timeval tv;
*D = (long) tv.tv_sec; gettimeofday(&tv, NULL);
*T = (long) tv.tv_usec; *D = (long) tv.tv_sec;
*T = (long) tv.tv_usec;
} }
long MOD(N,M)long N, M; {return(N%M);} long MOD(N,M)long N, M; {return(N%M);}