1/*	$NetBSD: tok.c,v 1.10 2008/02/04 01:07:01 dholland Exp $	*/
2
3/* tok.c		Larn is copyrighted 1986 by Noah Morgan. */
4#include <sys/cdefs.h>
5#ifndef lint
6__RCSID("$NetBSD: tok.c,v 1.10 2008/02/04 01:07:01 dholland Exp $");
7#endif				/* not lint */
8
9#include <sys/types.h>
10#include <string.h>
11#include <sys/ioctl.h>
12#include <stdlib.h>
13#include <unistd.h>
14#include <sys/wait.h>
15#include <ctype.h>
16#include "header.h"
17#include "extern.h"
18
19/* Keystrokes (roughly) between checkpoints */
20#define CHECKPOINT_INTERVAL	400
21
22static char     lastok = 0;
23int             yrepcount = 0;
24#ifndef FLUSHNO
25#define FLUSHNO 5
26#endif	/* FLUSHNO */
27static int      flushno = FLUSHNO;	/* input queue flushing threshold */
28#define MAXUM 52		/* maximum number of user re-named monsters */
29#define MAXMNAME 40		/* max length of a monster re-name */
30static char     usermonster[MAXUM][MAXMNAME];	/* the user named monster
31						 * name goes here */
32static u_char     usermpoint = 0;	/* the user monster pointer */
33
34/*
35	lexical analyzer for larn
36 */
37int
38yylex(void)
39{
40	char            cc;
41	int             ic;
42	if (hit2flag) {
43		hit2flag = 0;
44		yrepcount = 0;
45		return (' ');
46	}
47	if (yrepcount > 0) {
48		--yrepcount;
49		return (lastok);
50	} else
51		yrepcount = 0;
52	if (yrepcount == 0) {
53		bottomdo();
54		showplayer();
55	}			/* show where the player is	 */
56	lflush();
57	while (1) {
58		c[BYTESIN]++;
59		/* check for periodic checkpointing */
60		if (ckpflag)
61			if ((c[BYTESIN] % CHECKPOINT_INTERVAL) == 0) {
62#ifndef DOCHECKPOINTS
63				savegame(ckpfile);
64#else
65				wait(0);	/* wait for other forks to
66						 * finish */
67				if (fork() == 0) {
68					savegame(ckpfile);
69					exit();
70				}
71#endif
72			}
73		do {		/* if keyboard input buffer is too big, flush
74				 * some of it */
75			ioctl(0, FIONREAD, &ic);
76			if (ic > flushno)
77				read(0, &cc, 1);
78		}
79		while (ic > flushno);
80
81		if (read(0, &cc, 1) != 1)
82			return (lastok = -1);
83
84		if (cc == 'Y' - 64) {	/* control Y -- shell escape */
85			resetscroll();
86			clear();/* scrolling region, home, clear, no
87				 * attributes */
88			if ((ic = fork()) == 0) {	/* child */
89				execl("/bin/csh", "/bin/csh", NULL);
90				exit(1);
91			}
92			wait(0);
93			if (ic < 0) {	/* error */
94				write(2, "Can't fork off a shell!\n", 25);
95				sleep(2);
96			}
97			setscroll();
98			return (lastok = 'L' - 64);	/* redisplay screen */
99		}
100		if ((cc <= '9') && (cc >= '0')) {
101			yrepcount = yrepcount * 10 + cc - '0';
102		} else {
103			if (yrepcount > 0)
104				--yrepcount;
105			return (lastok = cc);
106		}
107	}
108}
109
110/*
111 *	flushall()		Function to flush all type-ahead in the input buffer
112 */
113void
114flushall(void)
115{
116	char            cc;
117	int             ic;
118	for (;;) {		/* if keyboard input buffer is too big, flush
119				 * some of it */
120		ioctl(0, FIONREAD, &ic);
121		if (ic <= 0)
122			return;
123		while (ic > 0) {
124			read(0, &cc, 1);
125			--ic;
126		}		/* gobble up the byte */
127	}
128}
129
130/*
131	function to set the desired hardness
132	enter with hard= -1 for default hardness, else any desired hardness
133 */
134void
135sethard(int hard)
136{
137	int    j, k, i;
138	struct monst *mp;
139
140	j = c[HARDGAME];
141	hashewon();
142	if (restorflag == 0) {	/* don't set c[HARDGAME] if restoring game */
143		if (hard >= 0)
144			c[HARDGAME] = hard;
145	} else
146		c[HARDGAME] = j;/* set c[HARDGAME] to proper value if
147				 * restoring game */
148
149	if ((k = c[HARDGAME]) != 0)
150		for (j = 0; j <= MAXMONST + 8; j++) {
151			mp = &monster[j];
152			i = ((6 + k) * mp->hitpoints + 1) / 6;
153			mp->hitpoints = (i < 0) ? 32767 : i;
154			i = ((6 + k) * mp->damage + 1) / 5;
155			mp->damage = (i > 127) ? 127 : i;
156			i = (10 * mp->gold) / (10 + k);
157			mp->gold = (i > 32767) ? 32767 : i;
158			i = mp->armorclass - k;
159			mp->armorclass = (i < -127) ? -127 : i;
160			i = (7 * mp->experience) / (7 + k) + 1;
161			mp->experience = (i <= 0) ? 1 : i;
162		}
163}
164
165/*
166	function to read and process the larn options file
167 */
168void
169readopts(void)
170{
171	const char  *i;
172	int    j, k;
173	int             flag;
174
175	flag = 1;		/* set to 0 if a name is specified */
176
177	if (lopen(optsfile) < 0) {
178		strcpy(logname, loginname);
179		return;		/* user name if no character name */
180	}
181	i = " ";
182	while (*i) {
183		if ((i = lgetw()) == NULL)
184			break;	/* check for EOF */
185		while ((*i == ' ') || (*i == '\t'))
186			i++;	/* eat leading whitespace */
187
188		if (strcmp(i, "bold-objects") == 0)
189			boldon = 1;
190		else if (strcmp(i, "enable-checkpointing") == 0)
191			ckpflag = 1;
192		else if (strcmp(i, "inverse-objects") == 0)
193			boldon = 0;
194		else if (strcmp(i, "female") == 0)
195			sex = 0;	/* male or female */
196		else if (strcmp(i, "monster:") == 0) {	/* name favorite monster */
197			if ((i = lgetw()) == 0)
198				break;
199			strlcpy(usermonster[usermpoint], i, MAXMNAME);
200			if (usermpoint >= MAXUM)
201				continue;	/* defined all of em */
202			if (isalpha(j = usermonster[usermpoint][0])) {
203				for (k = 1; k < MAXMONST + 8; k++)	/* find monster */
204					if (monstnamelist[k] == j) {
205						monster[k].name = &usermonster[usermpoint++][0];
206						break;
207					}
208			}
209		} else if (strcmp(i, "male") == 0)
210			sex = 1;
211		else if (strcmp(i, "name:") == 0) {	/* defining players name */
212			if ((i = lgetw()) == 0)
213				break;
214			strlcpy(logname, i, LOGNAMESIZE);
215			flag = 0;
216		} else if (strcmp(i, "no-introduction") == 0)
217			nowelcome = 1;
218		else if (strcmp(i, "no-beep") == 0)
219			nobeep = 1;
220		else if (strcmp(i, "process-name:") == 0) {
221			if ((i = lgetw()) == 0)
222				break;
223			strlcpy(psname, i, PSNAMESIZE);
224		} else if (strcmp(i, "play-day-play") == 0) {
225			/* bypass time restrictions: ignored */
226		} else if (strcmp(i, "savefile:") == 0) {	/* defining savefilename */
227			if ((i = lgetw()) == 0)
228				break;
229			strcpy(savefilename, i);
230			flag = 0;
231		}
232	}
233	if (flag)
234		strcpy(logname, loginname);
235}
236