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