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