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(<ext[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(<ext[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