Home | History | Annotate | Line # | Download | only in adventure
      1  1.23    rillig /*	$NetBSD: io.c,v 1.23 2021/05/02 12:50:43 rillig Exp $	*/
      2   1.2       cgd 
      3   1.1       jtc /*-
      4   1.1       jtc  * Copyright (c) 1991, 1993
      5   1.1       jtc  *	The Regents of the University of California.  All rights reserved.
      6   1.1       jtc  *
      7   1.1       jtc  * The game adventure was originally written in Fortran by Will Crowther
      8   1.1       jtc  * and Don Woods.  It was later translated to C and enhanced by Jim
      9   1.1       jtc  * Gillogly.  This code is derived from software contributed to Berkeley
     10   1.1       jtc  * by Jim Gillogly at The Rand Corporation.
     11   1.1       jtc  *
     12   1.1       jtc  * Redistribution and use in source and binary forms, with or without
     13   1.1       jtc  * modification, are permitted provided that the following conditions
     14   1.1       jtc  * are met:
     15   1.1       jtc  * 1. Redistributions of source code must retain the above copyright
     16   1.1       jtc  *    notice, this list of conditions and the following disclaimer.
     17   1.1       jtc  * 2. Redistributions in binary form must reproduce the above copyright
     18   1.1       jtc  *    notice, this list of conditions and the following disclaimer in the
     19   1.1       jtc  *    documentation and/or other materials provided with the distribution.
     20  1.13       agc  * 3. Neither the name of the University nor the names of its contributors
     21   1.1       jtc  *    may be used to endorse or promote products derived from this software
     22   1.1       jtc  *    without specific prior written permission.
     23   1.1       jtc  *
     24   1.1       jtc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25   1.1       jtc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26   1.1       jtc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27   1.1       jtc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28   1.1       jtc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29   1.1       jtc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30   1.1       jtc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31   1.1       jtc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32   1.1       jtc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33   1.1       jtc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34   1.1       jtc  * SUCH DAMAGE.
     35   1.1       jtc  */
     36   1.1       jtc 
     37   1.4  christos #include <sys/cdefs.h>
     38   1.1       jtc #ifndef lint
     39   1.2       cgd #if 0
     40   1.1       jtc static char sccsid[] = "@(#)io.c	8.1 (Berkeley) 5/31/93";
     41   1.2       cgd #else
     42  1.23    rillig __RCSID("$NetBSD: io.c,v 1.23 2021/05/02 12:50:43 rillig Exp $");
     43   1.2       cgd #endif
     44   1.1       jtc #endif /* not lint */
     45   1.1       jtc 
     46   1.1       jtc /*      Re-coding of advent in C: file i/o and user i/o                 */
     47   1.1       jtc 
     48   1.9   hubertf #include <err.h>
     49   1.1       jtc #include <stdio.h>
     50   1.3       cgd #include <string.h>
     51   1.4  christos #include <stdlib.h>
     52   1.4  christos #include "hdr.h"
     53   1.4  christos #include "extern.h"
     54   1.1       jtc 
     55  1.21  dholland static int next(void);
     56  1.21  dholland static void rdesc(int);
     57  1.22  dholland static void rdefault(void);
     58  1.21  dholland static void rhints(void);
     59  1.21  dholland static void rliq(void);
     60  1.21  dholland static void rlocs(void);
     61  1.21  dholland static int rnum(void);
     62  1.21  dholland static void rtrav(void);
     63  1.21  dholland static void rvoc(void);
     64   1.1       jtc 
     65  1.16       jmc /* get command from user        */
     66  1.16       jmc /* no prompt, usually           */
     67   1.4  christos void
     68  1.16       jmc getin(char **wrd1, char **wrd2)
     69   1.6     lukem {
     70   1.6     lukem 	char   *s;
     71   1.6     lukem 	static char wd1buf[MAXSTR], wd2buf[MAXSTR];
     72  1.20       mrg 	int     first, numch, c;
     73   1.6     lukem 
     74   1.6     lukem 	*wrd1 = wd1buf;				/* return ptr to internal str */
     75   1.6     lukem 	*wrd2 = wd2buf;
     76   1.6     lukem 	wd2buf[0] = 0;				/* in case it isn't set here */
     77   1.6     lukem 	for (s = wd1buf, first = 1, numch = 0;;) {
     78  1.20       mrg 		c = getchar();
     79  1.20       mrg 		if ((*s = (char)c) >= 'A' && *s <= 'Z')
     80   1.6     lukem 			*s = *s - ('A' - 'a');
     81   1.6     lukem 		/* convert to upper case */
     82  1.20       mrg 		switch (c) {			/* start reading from user */
     83   1.6     lukem 		case '\n':
     84   1.6     lukem 			*s = 0;
     85   1.1       jtc 			return;
     86   1.6     lukem 		case ' ':
     87   1.6     lukem 			if (s == wd1buf || s == wd2buf)	/* initial blank */
     88   1.1       jtc 				continue;
     89   1.6     lukem 			*s = 0;
     90   1.6     lukem 			if (first) {		/* finished 1st wd; start 2nd */
     91   1.6     lukem 				first = numch = 0;
     92   1.6     lukem 				s = wd2buf;
     93   1.1       jtc 				break;
     94   1.6     lukem 			} else {		/* finished 2nd word */
     95   1.6     lukem 				FLUSHLINE;
     96   1.6     lukem 				*s = 0;
     97   1.1       jtc 				return;
     98   1.1       jtc 			}
     99  1.11   hubertf 		case EOF:
    100  1.11   hubertf 			printf("user closed input stream, quitting...\n");
    101  1.11   hubertf 			exit(0);
    102   1.6     lukem 		default:
    103   1.6     lukem 			if (++numch >= MAXSTR) {	/* string too long */
    104   1.6     lukem 				printf("Give me a break!!\n");
    105   1.6     lukem 				wd1buf[0] = wd2buf[0] = 0;
    106   1.1       jtc 				FLUSHLINE;
    107   1.1       jtc 				return;
    108   1.1       jtc 			}
    109   1.1       jtc 			s++;
    110   1.1       jtc 		}
    111   1.1       jtc 	}
    112   1.1       jtc }
    113   1.1       jtc 
    114  1.16       jmc /* confirm with rspeak          */
    115   1.4  christos int
    116  1.16       jmc yes(int x, int y, int z)
    117   1.6     lukem {
    118   1.6     lukem 	int     result = TRUE;	/* pacify gcc */
    119  1.11   hubertf 	int    ch;
    120   1.6     lukem 	for (;;) {
    121   1.6     lukem 		rspeak(x);	/* tell him what we want */
    122   1.6     lukem 		if ((ch = getchar()) == 'y')
    123   1.6     lukem 			result = TRUE;
    124  1.11   hubertf 		else if (ch == 'n')
    125  1.11   hubertf 			result = FALSE;
    126  1.11   hubertf 		else if (ch == EOF) {
    127  1.11   hubertf 			printf("user closed input stream, quitting...\n");
    128  1.11   hubertf 			exit(0);
    129  1.11   hubertf 		}
    130   1.1       jtc 		FLUSHLINE;
    131   1.6     lukem 		if (ch == 'y' || ch == 'n')
    132   1.6     lukem 			break;
    133   1.1       jtc 		printf("Please answer the question.\n");
    134   1.1       jtc 	}
    135   1.6     lukem 	if (result == TRUE)
    136   1.6     lukem 		rspeak(y);
    137   1.6     lukem 	if (result == FALSE)
    138   1.6     lukem 		rspeak(z);
    139   1.6     lukem 	return (result);
    140   1.1       jtc }
    141   1.1       jtc 
    142  1.16       jmc /* confirm with mspeak          */
    143   1.4  christos int
    144  1.16       jmc yesm(int x, int y, int z)
    145   1.6     lukem {
    146   1.6     lukem 	int     result = TRUE;	/* pacify gcc */
    147  1.11   hubertf 	int    ch;
    148   1.6     lukem 	for (;;) {
    149   1.6     lukem 		mspeak(x);	/* tell him what we want */
    150   1.6     lukem 		if ((ch = getchar()) == 'y')
    151   1.6     lukem 			result = TRUE;
    152  1.11   hubertf 		else if (ch == 'n')
    153  1.11   hubertf 			result = FALSE;
    154  1.11   hubertf 		else if (ch == EOF) {
    155  1.11   hubertf 			printf("user closed input stream, quitting...\n");
    156  1.11   hubertf 			exit(0);
    157  1.11   hubertf 		}
    158   1.1       jtc 		FLUSHLINE;
    159   1.6     lukem 		if (ch == 'y' || ch == 'n')
    160   1.6     lukem 			break;
    161   1.1       jtc 		printf("Please answer the question.\n");
    162   1.1       jtc 	}
    163   1.6     lukem 	if (result == TRUE)
    164   1.6     lukem 		mspeak(y);
    165   1.6     lukem 	if (result == FALSE)
    166   1.6     lukem 		mspeak(z);
    167   1.6     lukem 	return (result);
    168   1.1       jtc }
    169   1.1       jtc /* FILE *inbuf,*outbuf; */
    170   1.1       jtc 
    171  1.21  dholland static char *inptr;		/* Pointer into virtual disk    */
    172   1.1       jtc 
    173  1.21  dholland static int outsw = 0;		/* putting stuff to data file?  */
    174   1.1       jtc 
    175  1.21  dholland static const char    iotape[] = "Ax3F'\003tt$8h\315qer*h\017nGKrX\207:!l";
    176  1.21  dholland static const char   *tape = iotape;	/* pointer to encryption tape   */
    177   1.1       jtc 
    178  1.16       jmc /* next virtual char, bump adr  */
    179  1.21  dholland static int
    180  1.16       jmc next(void)
    181  1.23    rillig {
    182   1.6     lukem 	int     ch;
    183   1.6     lukem 
    184  1.16       jmc 	ch = (*inptr ^ random()) & 0xFF;	/* Decrypt input data  */
    185   1.6     lukem 	if (outsw) {		/* putting data in tmp file     */
    186   1.6     lukem 		if (*tape == 0)
    187   1.6     lukem 			tape = iotape;	/* rewind encryption tape       */
    188   1.6     lukem 		*inptr = ch ^ *tape++;	/* re-encrypt and replace value */
    189   1.1       jtc 	}
    190   1.1       jtc 	inptr++;
    191   1.6     lukem 	return (ch);
    192   1.1       jtc }
    193   1.1       jtc 
    194  1.21  dholland static char breakch;		/* tell which char ended rnum   */
    195   1.1       jtc 
    196  1.16       jmc /* "read" data from virtual file */
    197   1.4  christos void
    198  1.16       jmc rdata(void)
    199  1.23    rillig {
    200   1.6     lukem 	int     sect;
    201   1.6     lukem 	char    ch;
    202   1.1       jtc 
    203   1.6     lukem 	inptr = data_file;	/* Pointer to virtual data file */
    204   1.6     lukem 	srandom(SEED);		/* which is lightly encrypted.  */
    205   1.1       jtc 
    206  1.22  dholland 	classes = 1;
    207   1.6     lukem 	for (;;) {		/* read data sections           */
    208   1.6     lukem 		sect = next() - '0';	/* 1st digit of section number  */
    209   1.1       jtc #ifdef VERBOSE
    210   1.6     lukem 		printf("Section %c", sect + '0');
    211   1.1       jtc #endif
    212   1.6     lukem 		if ((ch = next()) != LF) {	/* is there a second digit?     */
    213   1.1       jtc 			FLUSHLF;
    214   1.1       jtc #ifdef VERBOSE
    215   1.1       jtc 			putchar(ch);
    216   1.1       jtc #endif
    217   1.6     lukem 			sect = 10 * sect + ch - '0';
    218   1.1       jtc 		}
    219   1.1       jtc #ifdef VERBOSE
    220   1.1       jtc 		putchar('\n');
    221   1.1       jtc #endif
    222   1.6     lukem 		switch (sect) {
    223   1.6     lukem 		case 0:	/* finished reading database    */
    224   1.1       jtc 			return;
    225   1.6     lukem 		case 1:	/* long form descriptions       */
    226   1.1       jtc 			rdesc(1);
    227   1.1       jtc 			break;
    228   1.6     lukem 		case 2:	/* short form descriptions      */
    229   1.1       jtc 			rdesc(2);
    230   1.1       jtc 			break;
    231   1.6     lukem 		case 3:	/* travel table                 */
    232   1.6     lukem 			rtrav();
    233   1.6     lukem 			break;
    234   1.6     lukem 		case 4:	/* vocabulary                   */
    235   1.1       jtc 			rvoc();
    236   1.1       jtc 			break;
    237   1.6     lukem 		case 5:	/* object descriptions          */
    238   1.1       jtc 			rdesc(5);
    239   1.1       jtc 			break;
    240   1.6     lukem 		case 6:	/* arbitrary messages           */
    241   1.1       jtc 			rdesc(6);
    242   1.1       jtc 			break;
    243   1.6     lukem 		case 7:	/* object locations             */
    244   1.6     lukem 			rlocs();
    245   1.6     lukem 			break;
    246   1.6     lukem 		case 8:	/* action defaults              */
    247  1.22  dholland 			rdefault();
    248   1.6     lukem 			break;
    249   1.6     lukem 		case 9:	/* liquid assets                */
    250   1.6     lukem 			rliq();
    251   1.6     lukem 			break;
    252   1.6     lukem 		case 10:	/* class messages               */
    253   1.1       jtc 			rdesc(10);
    254   1.1       jtc 			break;
    255   1.6     lukem 		case 11:	/* hints                        */
    256   1.6     lukem 			rhints();
    257   1.6     lukem 			break;
    258   1.6     lukem 		case 12:	/* magic messages               */
    259   1.1       jtc 			rdesc(12);
    260   1.1       jtc 			break;
    261   1.6     lukem 		default:
    262   1.6     lukem 			printf("Invalid data section number: %d\n", sect);
    263   1.6     lukem 			for (;;)
    264   1.6     lukem 				putchar(next());
    265   1.1       jtc 		}
    266   1.6     lukem 		if (breakch != LF)	/* routines return after "-1"   */
    267   1.1       jtc 			FLUSHLF;
    268   1.1       jtc 	}
    269   1.1       jtc }
    270   1.1       jtc 
    271  1.21  dholland static char nbf[12];
    272   1.1       jtc 
    273  1.16       jmc /* read initial location num    */
    274  1.21  dholland static int
    275  1.16       jmc rnum(void)
    276  1.23    rillig {
    277   1.6     lukem 	char   *s;
    278   1.6     lukem 	tape = iotape;		/* restart encryption tape      */
    279   1.6     lukem 	for (s = nbf, *s = 0;; s++)
    280   1.6     lukem 		if ((*s = next()) == TAB || *s == '\n' || *s == LF)
    281   1.6     lukem 			break;
    282   1.6     lukem 	breakch = *s;		/* save char for rtrav()        */
    283   1.6     lukem 	*s = 0;			/* got the number as ascii      */
    284   1.6     lukem 	if (nbf[0] == '-')
    285   1.6     lukem 		return (-1);	/* end of data                  */
    286   1.6     lukem 	return (atoi(nbf));	/* convert it to integer        */
    287   1.6     lukem }
    288   1.6     lukem 
    289  1.21  dholland static char *seekhere;
    290   1.6     lukem 
    291  1.16       jmc /* read description-format msgs */
    292  1.21  dholland static void
    293  1.16       jmc rdesc(int sect)
    294   1.6     lukem {
    295   1.6     lukem 	int     locc;
    296   1.6     lukem 	char   *seekstart, *maystart;
    297   1.6     lukem 
    298   1.6     lukem 	seekhere = inptr;	/* Where are we in virtual file? */
    299   1.6     lukem 	outsw = 1;		/* these msgs go into tmp file  */
    300   1.6     lukem 	for (oldloc = -1, seekstart = seekhere;;) {
    301   1.6     lukem 		maystart = inptr;	/* maybe starting new entry     */
    302  1.16       jmc 		if ((locc = rnum()) != oldloc && oldloc >= 0 /* finished msg */
    303  1.16       jmc   		    /* unless sect 5 */
    304  1.16       jmc 		    && !(sect == 5 && (locc == 0 || locc >= 100))) {
    305   1.6     lukem 			switch (sect) {	/* now put it into right table  */
    306   1.6     lukem 			case 1:/* long descriptions            */
    307   1.6     lukem 				ltext[oldloc].seekadr = seekhere;
    308   1.6     lukem 				ltext[oldloc].txtlen = maystart - seekstart;
    309   1.1       jtc 				break;
    310   1.6     lukem 			case 2:/* short descriptions           */
    311   1.6     lukem 				stext[oldloc].seekadr = seekhere;
    312   1.6     lukem 				stext[oldloc].txtlen = maystart - seekstart;
    313   1.1       jtc 				break;
    314   1.6     lukem 			case 5:/* object descriptions          */
    315   1.6     lukem 				ptext[oldloc].seekadr = seekhere;
    316   1.6     lukem 				ptext[oldloc].txtlen = maystart - seekstart;
    317   1.1       jtc 				break;
    318   1.6     lukem 			case 6:/* random messages              */
    319  1.23    rillig 				if (oldloc >= RTXSIZE)
    320  1.10   hubertf 					errx(1,"Too many random msgs");
    321   1.6     lukem 				rtext[oldloc].seekadr = seekhere;
    322   1.6     lukem 				rtext[oldloc].txtlen = maystart - seekstart;
    323   1.1       jtc 				break;
    324   1.6     lukem 			case 10:	/* class messages               */
    325  1.22  dholland 				ctext[classes].seekadr = seekhere;
    326  1.22  dholland 				ctext[classes].txtlen = maystart - seekstart;
    327  1.22  dholland 				cval[classes++] = oldloc;
    328   1.1       jtc 				break;
    329   1.6     lukem 			case 12:	/* magic messages               */
    330  1.22  dholland 				if (oldloc >= MAGSIZE)
    331  1.10   hubertf 					errx(1,"Too many magic msgs");
    332   1.6     lukem 				mtext[oldloc].seekadr = seekhere;
    333   1.6     lukem 				mtext[oldloc].txtlen = maystart - seekstart;
    334   1.1       jtc 				break;
    335   1.6     lukem 			default:
    336  1.10   hubertf 				errx(1,"rdesc called with bad section");
    337   1.1       jtc 			}
    338   1.6     lukem 			seekhere += maystart - seekstart;
    339   1.1       jtc 		}
    340   1.6     lukem 		if (locc < 0) {
    341   1.6     lukem 			outsw = 0;	/* turn off output              */
    342   1.6     lukem 			seekhere += 3;	/* -1<delimiter>                */
    343   1.1       jtc 			return;
    344   1.1       jtc 		}
    345   1.6     lukem 		if (sect != 5 || (locc > 0 && locc < 100)) {
    346  1.16       jmc 			if (oldloc != locc)	/* starting a new message */
    347   1.6     lukem 				seekstart = maystart;
    348   1.6     lukem 			oldloc = locc;
    349   1.1       jtc 		}
    350   1.6     lukem 		FLUSHLF;	/* scan the line                */
    351   1.1       jtc 	}
    352   1.1       jtc }
    353   1.1       jtc 
    354  1.16       jmc /* read travel table            */
    355  1.21  dholland static void
    356  1.16       jmc rtrav(void)
    357  1.23    rillig {
    358   1.6     lukem 	int     locc;
    359   1.5     lukem 	struct travlist *t = NULL;
    360   1.6     lukem 	char   *s;
    361   1.6     lukem 	char    buf[12];
    362   1.6     lukem 	int     len, m, n, entries = 0;
    363   1.6     lukem 
    364   1.6     lukem 	for (oldloc = -1;;) {	/* get another line             */
    365  1.23    rillig 		/* end of entry */
    366  1.17  christos 		if ((locc = rnum()) != oldloc && oldloc >= 0 && t) {
    367   1.6     lukem 			t->next = 0;	/* terminate the old entry      */
    368   1.6     lukem 			/* printf("%d:%d entries\n",oldloc,entries);       */
    369   1.6     lukem 			/* twrite(oldloc);                                 */
    370   1.6     lukem 		}
    371   1.6     lukem 		if (locc == -1)
    372   1.6     lukem 			return;
    373   1.6     lukem 		if (locc != oldloc) {	/* getting a new entry         */
    374  1.19  christos 			t = travel[locc] = calloc(1, sizeof(*t));
    375  1.19  christos 			if (t == NULL)
    376  1.12       jsm 				err(1, NULL);
    377   1.6     lukem 			/* printf("New travel list for %d\n",locc);        */
    378   1.6     lukem 			entries = 0;
    379   1.6     lukem 			oldloc = locc;
    380   1.6     lukem 		}
    381   1.6     lukem 		for (s = buf;; s++)	/* get the newloc number /ASCII */
    382   1.6     lukem 			if ((*s = next()) == TAB || *s == LF)
    383   1.6     lukem 				break;
    384   1.6     lukem 		*s = 0;
    385   1.6     lukem 		len = length(buf) - 1;	/* quad long number handling    */
    386   1.6     lukem 		/* printf("Newloc: %s (%d chars)\n",buf,len);              */
    387   1.6     lukem 		if (len < 4) {	/* no "m" conditions            */
    388   1.6     lukem 			m = 0;
    389   1.6     lukem 			n = atoi(buf);	/* newloc mod 1000 = newloc     */
    390   1.6     lukem 		} else {	/* a long integer               */
    391   1.6     lukem 			n = atoi(buf + len - 3);
    392  1.16       jmc 			buf[len - 3] = 0;	/* terminate newloc/1000  */
    393   1.6     lukem 			m = atoi(buf);
    394   1.6     lukem 		}
    395   1.6     lukem 		while (breakch != LF) {	/* only do one line at a time   */
    396  1.19  christos 			if (t == NULL)
    397  1.19  christos 				abort();
    398  1.19  christos 			if (entries++) {
    399  1.19  christos 				t->next = calloc(1, sizeof(*t));
    400  1.17  christos 				if (t->next == NULL)
    401  1.12       jsm 					err(1, NULL);
    402  1.17  christos 				t = t->next;
    403   1.9   hubertf 			}
    404  1.16       jmc 			t->tverb = rnum();	/* get verb from the file */
    405   1.6     lukem 			t->tloc = n;	/* table entry mod 1000         */
    406  1.16       jmc 			t->conditions = m;	/* table entry / 1000   */
    407  1.16       jmc 			/* printf("entry %d for %d\n",entries,locc);    */
    408   1.1       jtc 		}
    409   1.1       jtc 	}
    410   1.1       jtc }
    411   1.1       jtc #ifdef DEBUG
    412   1.1       jtc 
    413  1.16       jmc /* travel options from this loc */
    414   1.4  christos void
    415  1.16       jmc twrite(int loq)
    416   1.6     lukem {
    417   1.6     lukem 	struct travlist *t;
    418   1.1       jtc 	printf("If");
    419   1.1       jtc 	speak(&ltext[loq]);
    420   1.1       jtc 	printf("then\n");
    421   1.6     lukem 	for (t = travel[loq]; t != 0; t = t->next) {
    422   1.6     lukem 		printf("verb %d takes you to ", t->tverb);
    423   1.6     lukem 		if (t->tloc <= 300)
    424   1.1       jtc 			speak(&ltext[t->tloc]);
    425   1.1       jtc 		else
    426   1.6     lukem 			if (t->tloc <= 500)
    427   1.6     lukem 				printf("special code %d\n", t->tloc - 300);
    428   1.6     lukem 			else
    429   1.6     lukem 				rspeak(t->tloc - 500);
    430   1.6     lukem 		printf("under conditions %d\n", t->conditions);
    431   1.1       jtc 	}
    432   1.1       jtc }
    433   1.6     lukem #endif				/* DEBUG */
    434   1.1       jtc 
    435  1.16       jmc /* read the vocabulary          */
    436  1.21  dholland static void
    437  1.16       jmc rvoc(void)
    438   1.6     lukem {
    439  1.16       jmc 	char   *s;
    440  1.16       jmc 	int     idx;
    441   1.6     lukem 	char    buf[6];
    442   1.6     lukem 	for (;;) {
    443  1.16       jmc 		idx = rnum();
    444  1.16       jmc 		if (idx < 0)
    445   1.6     lukem 			break;
    446  1.16       jmc 		for (s = buf, *s = 0;; s++)	/* get the word  */
    447   1.6     lukem 			if ((*s = next()) == TAB || *s == '\n' || *s == LF
    448   1.6     lukem 			    || *s == ' ')
    449   1.6     lukem 				break;
    450   1.6     lukem 		/* terminate word with newline, LF, tab, blank  */
    451   1.6     lukem 		if (*s != '\n' && *s != LF)
    452   1.6     lukem 			FLUSHLF;/* can be comments    */
    453   1.6     lukem 		*s = 0;
    454  1.16       jmc 		/* printf("\"%s\"=%d\n",buf,idx); */
    455  1.16       jmc 		vocab(buf, -2, idx);
    456   1.1       jtc 	}
    457   1.1       jtc /*	prht();	*/
    458   1.1       jtc }
    459   1.1       jtc 
    460  1.16       jmc /* initial object locations     */
    461  1.21  dholland static void
    462  1.16       jmc rlocs(void)
    463  1.23    rillig {
    464   1.6     lukem 	for (;;) {
    465   1.6     lukem 		if ((obj = rnum()) < 0)
    466   1.6     lukem 			break;
    467   1.6     lukem 		plac[obj] = rnum();	/* initial loc for this obj     */
    468   1.6     lukem 		if (breakch == TAB)	/* there's another entry        */
    469   1.6     lukem 			fixd[obj] = rnum();
    470   1.6     lukem 		else
    471   1.6     lukem 			fixd[obj] = 0;
    472   1.1       jtc 	}
    473   1.1       jtc }
    474   1.1       jtc 
    475  1.16       jmc /* default verb messages        */
    476  1.21  dholland static void
    477  1.22  dholland rdefault(void)
    478  1.23    rillig {
    479   1.6     lukem 	for (;;) {
    480   1.6     lukem 		if ((verb = rnum()) < 0)
    481   1.6     lukem 			break;
    482  1.22  dholland 		actspeak[verb] = rnum();
    483   1.1       jtc 	}
    484   1.1       jtc }
    485   1.1       jtc 
    486  1.16       jmc /* liquid assets &c: cond bits  */
    487  1.21  dholland static void
    488  1.16       jmc rliq(void)
    489  1.23    rillig {
    490   1.6     lukem 	int     bitnum;
    491   1.6     lukem 	for (;;) {		/* read new bit list            */
    492   1.6     lukem 		if ((bitnum = rnum()) < 0)
    493   1.6     lukem 			break;
    494   1.6     lukem 		for (;;) {	/* read locs for bits           */
    495  1.18  christos 			int n = rnum();
    496  1.18  christos 			if (n < 0)
    497  1.18  christos 				break;
    498  1.18  christos 			cond[n] |= setbit[bitnum];
    499   1.6     lukem 			if (breakch == LF)
    500   1.6     lukem 				break;
    501   1.1       jtc 		}
    502   1.1       jtc 	}
    503   1.1       jtc }
    504   1.1       jtc 
    505  1.21  dholland static void
    506  1.16       jmc rhints(void)
    507   1.6     lukem {
    508   1.6     lukem 	int     hintnum, i;
    509  1.22  dholland 	hintmax = 0;
    510   1.6     lukem 	for (;;) {
    511   1.6     lukem 		if ((hintnum = rnum()) < 0)
    512   1.6     lukem 			break;
    513   1.6     lukem 		for (i = 1; i < 5; i++)
    514   1.6     lukem 			hints[hintnum][i] = rnum();
    515  1.22  dholland 		if (hintnum > hintmax)
    516  1.22  dholland 			hintmax = hintnum;
    517   1.1       jtc 	}
    518   1.1       jtc }
    519   1.1       jtc 
    520   1.1       jtc 
    521   1.4  christos void
    522  1.16       jmc rspeak(int msg)
    523   1.6     lukem {
    524   1.6     lukem 	if (msg != 0)
    525   1.6     lukem 		speak(&rtext[msg]);
    526   1.1       jtc }
    527   1.1       jtc 
    528   1.1       jtc 
    529   1.4  christos void
    530  1.16       jmc mspeak(int msg)
    531   1.6     lukem {
    532   1.6     lukem 	if (msg != 0)
    533   1.6     lukem 		speak(&mtext[msg]);
    534   1.1       jtc }
    535   1.1       jtc 
    536   1.1       jtc 
    537  1.16       jmc /* read, decrypt, and print a message (not ptext)      */
    538  1.16       jmc /* msg is a pointer to seek address and length of mess */
    539   1.4  christos void
    540  1.16       jmc speak(const struct text *msg)
    541   1.1       jtc {
    542   1.6     lukem 	char   *s, nonfirst;
    543   1.1       jtc 
    544   1.1       jtc 	s = msg->seekadr;
    545   1.6     lukem 	nonfirst = 0;
    546  1.16       jmc 	while (s - msg->seekadr < msg->txtlen) { /* read a line at a time */
    547   1.6     lukem 		tape = iotape;	/* restart decryption tape      */
    548  1.16       jmc 		while ((*s++ ^ *tape++) != TAB); /* read past loc num       */
    549   1.1       jtc 		/* assume tape is longer than location number           */
    550   1.6     lukem 		/* plus the lookahead put together                    */
    551   1.1       jtc 		if ((*s ^ *tape) == '>' &&
    552   1.6     lukem 		    (*(s + 1) ^ *(tape + 1)) == '$' &&
    553   1.6     lukem 		    (*(s + 2) ^ *(tape + 2)) == '<')
    554   1.6     lukem 			break;
    555   1.6     lukem 		if (blklin && !nonfirst++)
    556   1.6     lukem 			putchar('\n');
    557   1.6     lukem 		do {
    558   1.6     lukem 			if (*tape == 0)
    559   1.6     lukem 				tape = iotape;	/* rewind decryp tape */
    560   1.1       jtc 			putchar(*s ^ *tape);
    561  1.16       jmc 		} while ((*s++ ^ *tape++) != LF); /* better end with LF   */
    562   1.1       jtc 	}
    563   1.1       jtc }
    564   1.1       jtc 
    565  1.16       jmc /* read, decrypt and print a ptext message  */
    566  1.16       jmc /* msg is the number of all the p msgs for this place  */
    567  1.16       jmc /* assumes object 1 doesn't have prop 1, obj 2 no prop 2 &c */
    568   1.4  christos void
    569  1.16       jmc pspeak(int m, int skip)
    570   1.1       jtc {
    571   1.6     lukem 	char   *s, nonfirst;
    572  1.16       jmc 	char   *numst;
    573   1.1       jtc 	struct text *msg;
    574   1.6     lukem 	char   *tbuf;
    575   1.1       jtc 
    576   1.1       jtc 	msg = &ptext[m];
    577   1.9   hubertf 	if ((tbuf = (char *) malloc(msg->txtlen + 1)) == NULL)
    578  1.12       jsm 		err(1, NULL);
    579   1.6     lukem 	memcpy(tbuf, msg->seekadr, msg->txtlen + 1);	/* Room to null */
    580   1.1       jtc 	s = tbuf;
    581   1.1       jtc 
    582   1.6     lukem 	nonfirst = 0;
    583   1.6     lukem 	while (s - tbuf < msg->txtlen) {	/* read line at a time */
    584   1.6     lukem 		tape = iotape;	/* restart decryption tape      */
    585  1.16       jmc 		for (numst = s; (*s ^= *tape++) != TAB; s++); /* get number  */
    586   1.6     lukem 
    587  1.16       jmc 				/* Temporarily trash the string (cringe) */
    588  1.16       jmc 		*s++ = 0;	/* decrypting number within the string   */
    589   1.6     lukem 
    590   1.6     lukem 		if (atoi(numst) != 100 * skip && skip >= 0) {
    591   1.6     lukem 			while ((*s++ ^ *tape++) != LF)	/* flush the line    */
    592   1.6     lukem 				if (*tape == 0)
    593   1.6     lukem 					tape = iotape;
    594   1.1       jtc 			continue;
    595   1.1       jtc 		}
    596   1.6     lukem 		if ((*s ^ *tape) == '>' && (*(s + 1) ^ *(tape + 1)) == '$' &&
    597   1.6     lukem 		    (*(s + 2) ^ *(tape + 2)) == '<')
    598   1.6     lukem 			break;
    599   1.6     lukem 		if (blklin && !nonfirst++)
    600   1.6     lukem 			putchar('\n');
    601   1.6     lukem 		do {
    602   1.6     lukem 			if (*tape == 0)
    603   1.6     lukem 				tape = iotape;
    604   1.6     lukem 			putchar(*s ^ *tape);
    605  1.16       jmc 		} while ((*s++ ^ *tape++) != LF); /* better end with LF   */
    606   1.6     lukem 		if (skip < 0)
    607   1.6     lukem 			break;
    608   1.1       jtc 	}
    609   1.1       jtc 	free(tbuf);
    610   1.1       jtc }
    611