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