main.c revision 1.9 1 1.3 mycroft #ifndef lint
2 1.9 mrg static char rcsid[] = "$NetBSD: main.c,v 1.9 1996/05/22 00:36:09 mrg Exp $";
3 1.3 mycroft #endif /* not lint */
4 1.3 mycroft
5 1.1 cgd /* main.c */
6 1.1 cgd #include <sys/types.h>
7 1.1 cgd #include "header.h"
8 1.1 cgd #include <pwd.h>
9 1.7 cgd #include <string.h>
10 1.7 cgd
11 1.1 cgd static char copyright[]="\nLarn is copyrighted 1986 by Noah Morgan.\n";
12 1.1 cgd int srcount=0; /* line counter for showstr() */
13 1.1 cgd int dropflag=0; /* if 1 then don't lookforobject() next round */
14 1.1 cgd int rmst=80; /* random monster creation counter */
15 1.1 cgd int userid; /* the players login user id number */
16 1.9 mrg uid_t uid, euid; /* used for security */
17 1.1 cgd char nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a move */
18 1.1 cgd static char viewflag=0;
19 1.1 cgd /* if viewflag then we have done a 99 stay here and don't showcell in the main loop */
20 1.1 cgd char restorflag=0; /* 1 means restore has been done */
21 1.1 cgd static char cmdhelp[] = "\
22 1.1 cgd Cmd line format: larn [-slicnh] [-o<optsifle>] [-##] [++]\n\
23 1.1 cgd -s show the scoreboard\n\
24 1.1 cgd -l show the logfile (wizard id only)\n\
25 1.1 cgd -i show scoreboard with inventories of dead characters\n\
26 1.1 cgd -c create new scoreboard (wizard id only)\n\
27 1.1 cgd -n suppress welcome message on starting game\n\
28 1.1 cgd -## specify level of difficulty (example: -5)\n\
29 1.1 cgd -h print this help text\n\
30 1.1 cgd ++ restore game from checkpoint file\n\
31 1.1 cgd -o<optsfile> specify .larnopts filename to be used instead of \"~/.larnopts\"\n\
32 1.1 cgd ";
33 1.1 cgd #ifdef VT100
34 1.1 cgd static char *termtypes[] = { "vt100", "vt101", "vt102", "vt103", "vt125",
35 1.1 cgd "vt131", "vt140", "vt180", "vt220", "vt240", "vt241", "vt320", "vt340",
36 1.1 cgd "vt341" };
37 1.1 cgd #endif VT100
38 1.1 cgd /*
39 1.1 cgd ************
40 1.1 cgd MAIN PROGRAM
41 1.1 cgd ************
42 1.1 cgd */
43 1.1 cgd main(argc,argv)
44 1.1 cgd int argc;
45 1.1 cgd char **argv;
46 1.1 cgd {
47 1.1 cgd register int i,j;
48 1.1 cgd int hard;
49 1.1 cgd char *ptr=0,*ttype;
50 1.1 cgd struct passwd *pwe;
51 1.1 cgd
52 1.9 mrg euid = geteuid();
53 1.9 mrg uid = getuid();
54 1.9 mrg seteuid(uid); /* give up "games" if we have it */
55 1.1 cgd /*
56 1.1 cgd * first task is to identify the player
57 1.1 cgd */
58 1.1 cgd #ifndef VT100
59 1.1 cgd init_term(); /* setup the terminal (find out what type) for termcap */
60 1.1 cgd #endif VT100
61 1.1 cgd if (((ptr = getlogin()) == 0) || (*ptr==0)) /* try to get login name */
62 1.1 cgd if (pwe=getpwuid(getuid())) /* can we get it from /etc/passwd? */
63 1.1 cgd ptr = pwe->pw_name;
64 1.1 cgd else
65 1.1 cgd if ((ptr = getenv("USER")) == 0)
66 1.1 cgd if ((ptr = getenv("LOGNAME")) == 0)
67 1.1 cgd {
68 1.1 cgd noone: write(2, "Can't find your logname. Who Are You?\n",39);
69 1.1 cgd exit();
70 1.1 cgd }
71 1.1 cgd if (ptr==0) goto noone;
72 1.1 cgd if (strlen(ptr)==0) goto noone;
73 1.1 cgd /*
74 1.1 cgd * second task is to prepare the pathnames the player will need
75 1.1 cgd */
76 1.1 cgd strcpy(loginname,ptr); /* save loginname of the user for logging purposes */
77 1.1 cgd strcpy(logname,ptr); /* this will be overwritten with the players name */
78 1.1 cgd if ((ptr = getenv("HOME")) == 0) ptr = ".";
79 1.1 cgd strcpy(savefilename, ptr);
80 1.1 cgd strcat(savefilename, "/Larn.sav"); /* save file name in home directory */
81 1.1 cgd sprintf(optsfile, "%s/.larnopts",ptr); /* the .larnopts filename */
82 1.1 cgd
83 1.1 cgd /*
84 1.1 cgd * now malloc the memory for the dungeon
85 1.1 cgd */
86 1.1 cgd cell = (struct cel *)malloc(sizeof(struct cel)*(MAXLEVEL+MAXVLEVEL)*MAXX*MAXY);
87 1.1 cgd if (cell == 0) died(-285); /* malloc failure */
88 1.1 cgd lpbuf = malloc((5* BUFBIG)>>2); /* output buffer */
89 1.1 cgd inbuffer = malloc((5*MAXIBUF)>>2); /* output buffer */
90 1.1 cgd if ((lpbuf==0) || (inbuffer==0)) died(-285); /* malloc() failure */
91 1.1 cgd
92 1.1 cgd lcreat((char*)0); newgame(); /* set the initial clock */ hard= -1;
93 1.1 cgd
94 1.1 cgd #ifdef VT100
95 1.1 cgd /*
96 1.1 cgd * check terminal type to avoid users who have not vt100 type terminals
97 1.1 cgd */
98 1.1 cgd ttype = getenv("TERM");
99 1.1 cgd for (j=1, i=0; i<sizeof(termtypes)/sizeof(char *); i++)
100 1.1 cgd if (strcmp(ttype,termtypes[i]) == 0) { j=0; break; }
101 1.1 cgd if (j)
102 1.1 cgd {
103 1.1 cgd lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush();
104 1.1 cgd exit();
105 1.1 cgd }
106 1.1 cgd #endif VT100
107 1.1 cgd
108 1.1 cgd /*
109 1.1 cgd * now make scoreboard if it is not there (don't clear)
110 1.1 cgd */
111 1.1 cgd if (access(scorefile,0) == -1) /* not there */
112 1.1 cgd makeboard();
113 1.1 cgd
114 1.1 cgd /*
115 1.1 cgd * now process the command line arguments
116 1.1 cgd */
117 1.1 cgd for (i=1; i<argc; i++)
118 1.1 cgd {
119 1.1 cgd if (argv[i][0] == '-')
120 1.1 cgd switch(argv[i][1])
121 1.1 cgd {
122 1.1 cgd case 's': showscores(); exit(); /* show scoreboard */
123 1.1 cgd
124 1.1 cgd case 'l': /* show log file */
125 1.1 cgd diedlog(); exit();
126 1.1 cgd
127 1.1 cgd case 'i': showallscores(); exit(); /* show all scoreboard */
128 1.1 cgd
129 1.1 cgd case 'c': /* anyone with password can create scoreboard */
130 1.1 cgd lprcat("Preparing to initialize the scoreboard.\n");
131 1.1 cgd if (getpassword() != 0) /*make new scoreboard*/
132 1.1 cgd {
133 1.1 cgd makeboard(); lprc('\n'); showscores();
134 1.1 cgd }
135 1.1 cgd exit();
136 1.1 cgd
137 1.1 cgd case 'n': /* no welcome msg */ nowelcome=1; argv[i][0]=0; break;
138 1.1 cgd
139 1.1 cgd case '0': case '1': case '2': case '3': case '4': case '5':
140 1.1 cgd case '6': case '7': case '8': case '9': /* for hardness */
141 1.1 cgd sscanf(&argv[i][1],"%d",&hard);
142 1.1 cgd break;
143 1.1 cgd
144 1.1 cgd case 'h': /* print out command line arguments */
145 1.1 cgd write(1,cmdhelp,sizeof(cmdhelp)); exit();
146 1.1 cgd
147 1.1 cgd case 'o': /* specify a .larnopts filename */
148 1.1 cgd strncpy(optsfile,argv[i]+2,127); break;
149 1.1 cgd
150 1.1 cgd default: printf("Unknown option <%s>\n",argv[i]); exit();
151 1.1 cgd };
152 1.1 cgd
153 1.1 cgd if (argv[i][0] == '+')
154 1.1 cgd {
155 1.1 cgd clear(); restorflag = 1;
156 1.1 cgd if (argv[i][1] == '+')
157 1.1 cgd {
158 1.1 cgd hitflag=1; restoregame(ckpfile); /* restore checkpointed game */
159 1.1 cgd }
160 1.1 cgd i = argc;
161 1.1 cgd }
162 1.1 cgd }
163 1.1 cgd
164 1.1 cgd readopts(); /* read the options file if there is one */
165 1.1 cgd
166 1.1 cgd
167 1.1 cgd #ifdef UIDSCORE
168 1.1 cgd userid = geteuid(); /* obtain the user's effective id number */
169 1.1 cgd #else UIDSCORE
170 1.1 cgd userid = getplid(logname); /* obtain the players id number */
171 1.1 cgd #endif UIDSCORE
172 1.1 cgd if (userid < 0) { write(2,"Can't obtain playerid\n",22); exit(); }
173 1.1 cgd
174 1.1 cgd #ifdef HIDEBYLINK
175 1.1 cgd /*
176 1.1 cgd * this section of code causes the program to look like something else to ps
177 1.1 cgd */
178 1.1 cgd if (strcmp(psname,argv[0])) /* if a different process name only */
179 1.1 cgd {
180 1.1 cgd if ((i=access(psname,1)) < 0)
181 1.1 cgd { /* link not there */
182 1.1 cgd if (link(argv[0],psname)>=0)
183 1.1 cgd {
184 1.1 cgd argv[0] = psname; execv(psname,argv);
185 1.1 cgd }
186 1.1 cgd }
187 1.1 cgd else
188 1.1 cgd unlink(psname);
189 1.1 cgd }
190 1.1 cgd
191 1.1 cgd for (i=1; i<argc; i++)
192 1.1 cgd {
193 1.1 cgd szero(argv[i]); /* zero the argument to avoid ps snooping */
194 1.1 cgd }
195 1.1 cgd #endif HIDEBYLINK
196 1.1 cgd
197 1.1 cgd if (access(savefilename,0)==0) /* restore game if need to */
198 1.1 cgd {
199 1.1 cgd clear(); restorflag = 1;
200 1.1 cgd hitflag=1; restoregame(savefilename); /* restore last game */
201 1.1 cgd }
202 1.1 cgd sigsetup(); /* trap all needed signals */
203 1.1 cgd sethard(hard); /* set up the desired difficulty */
204 1.1 cgd setupvt100(); /* setup the terminal special mode */
205 1.1 cgd if (c[HP]==0) /* create new game */
206 1.1 cgd {
207 1.1 cgd makeplayer(); /* make the character that will play */
208 1.1 cgd newcavelevel(0);/* make the dungeon */
209 1.1 cgd predostuff = 1; /* tell signals that we are in the welcome screen */
210 1.1 cgd if (nowelcome==0) welcome(); /* welcome the player to the game */
211 1.1 cgd }
212 1.1 cgd drawscreen(); /* show the initial dungeon */
213 1.1 cgd predostuff = 2; /* tell the trap functions that they must do a showplayer()
214 1.1 cgd from here on */
215 1.1 cgd /* nice(1); /* games should be run niced */
216 1.1 cgd yrepcount = hit2flag = 0;
217 1.1 cgd while (1)
218 1.1 cgd {
219 1.1 cgd if (dropflag==0) lookforobject(); /* see if there is an object here */
220 1.1 cgd else dropflag=0; /* don't show it just dropped an item */
221 1.1 cgd if (hitflag==0) { if (c[HASTEMONST]) movemonst(); movemonst(); } /* move the monsters */
222 1.1 cgd if (viewflag==0) showcell(playerx,playery); else viewflag=0; /* show stuff around player */
223 1.1 cgd if (hit3flag) flushall();
224 1.1 cgd hitflag=hit3flag=0; nomove=1;
225 1.1 cgd bot_linex(); /* update bottom line */
226 1.1 cgd while (nomove)
227 1.1 cgd {
228 1.1 cgd if (hit3flag) flushall();
229 1.1 cgd nomove=0; parse();
230 1.1 cgd } /* get commands and make moves */
231 1.1 cgd regen(); /* regenerate hp and spells */
232 1.1 cgd if (c[TIMESTOP]==0)
233 1.1 cgd if (--rmst <= 0)
234 1.1 cgd { rmst = 120-(level<<2); fillmonst(makemonst(level)); }
235 1.1 cgd }
236 1.1 cgd }
237 1.1 cgd
238 1.1 cgd /*
240 1.1 cgd showstr()
241 1.1 cgd
242 1.1 cgd show character's inventory
243 1.1 cgd */
244 1.1 cgd showstr()
245 1.1 cgd {
246 1.1 cgd register int i,number;
247 1.1 cgd for (number=3, i=0; i<26; i++)
248 1.1 cgd if (iven[i]) number++; /* count items in inventory */
249 1.1 cgd t_setup(number); qshowstr(); t_endup(number);
250 1.1 cgd }
251 1.1 cgd
252 1.1 cgd qshowstr()
253 1.1 cgd {
254 1.1 cgd register int i,j,k,sigsav;
255 1.1 cgd srcount=0; sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
256 1.1 cgd if (c[GOLD]) { lprintf(".) %d gold pieces",(long)c[GOLD]); srcount++; }
257 1.1 cgd for (k=26; k>=0; k--)
258 1.1 cgd if (iven[k])
259 1.1 cgd { for (i=22; i<84; i++)
260 1.1 cgd for (j=0; j<=k; j++) if (i==iven[j]) show3(j); k=0; }
261 1.1 cgd
262 1.1 cgd lprintf("\nElapsed time is %d. You have %d mobuls left",(long)((gtime+99)/100+1),(long)((TIMELIMIT-gtime)/100));
263 1.1 cgd more(); nosignal=sigsav;
264 1.1 cgd }
265 1.1 cgd
266 1.1 cgd /*
267 1.1 cgd * subroutine to clear screen depending on # lines to display
268 1.1 cgd */
269 1.1 cgd t_setup(count)
270 1.1 cgd register int count;
271 1.1 cgd {
272 1.1 cgd if (count<20) /* how do we clear the screen? */
273 1.1 cgd {
274 1.1 cgd cl_up(79,count); cursor(1,1);
275 1.1 cgd }
276 1.1 cgd else
277 1.1 cgd {
278 1.1 cgd resetscroll(); clear();
279 1.1 cgd }
280 1.1 cgd }
281 1.1 cgd
282 1.1 cgd /*
283 1.1 cgd * subroutine to restore normal display screen depending on t_setup()
284 1.1 cgd */
285 1.1 cgd t_endup(count)
286 1.1 cgd register int count;
287 1.1 cgd {
288 1.1 cgd if (count<18) /* how did we clear the screen? */
289 1.1 cgd draws(0,MAXX,0,(count>MAXY) ? MAXY : count);
290 1.1 cgd else
291 1.1 cgd {
292 1.1 cgd drawscreen(); setscroll();
293 1.1 cgd }
294 1.1 cgd }
295 1.1 cgd
296 1.1 cgd /*
297 1.1 cgd function to show the things player is wearing only
298 1.1 cgd */
299 1.1 cgd showwear()
300 1.1 cgd {
301 1.1 cgd register int i,j,sigsav,count;
302 1.1 cgd sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
303 1.1 cgd srcount=0;
304 1.1 cgd
305 1.1 cgd for (count=2,j=0; j<=26; j++) /* count number of items we will display */
306 1.1 cgd if (i=iven[j])
307 1.1 cgd switch(i)
308 1.1 cgd {
309 1.1 cgd case OLEATHER: case OPLATE: case OCHAIN:
310 1.1 cgd case ORING: case OSTUDLEATHER: case OSPLINT:
311 1.1 cgd case OPLATEARMOR: case OSSPLATE: case OSHIELD:
312 1.1 cgd count++;
313 1.1 cgd };
314 1.1 cgd
315 1.1 cgd t_setup(count);
316 1.1 cgd
317 1.1 cgd for (i=22; i<84; i++)
318 1.1 cgd for (j=0; j<=26; j++)
319 1.1 cgd if (i==iven[j])
320 1.1 cgd switch(i)
321 1.1 cgd {
322 1.1 cgd case OLEATHER: case OPLATE: case OCHAIN:
323 1.1 cgd case ORING: case OSTUDLEATHER: case OSPLINT:
324 1.1 cgd case OPLATEARMOR: case OSSPLATE: case OSHIELD:
325 1.1 cgd show3(j);
326 1.1 cgd };
327 1.1 cgd more(); nosignal=sigsav; t_endup(count);
328 1.1 cgd }
329 1.1 cgd
330 1.1 cgd /*
331 1.1 cgd function to show the things player can wield only
332 1.1 cgd */
333 1.1 cgd showwield()
334 1.1 cgd {
335 1.1 cgd register int i,j,sigsav,count;
336 1.1 cgd sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
337 1.1 cgd srcount=0;
338 1.1 cgd
339 1.1 cgd for (count=2,j=0; j<=26; j++) /* count how many items */
340 1.1 cgd if (i=iven[j])
341 1.1 cgd switch(i)
342 1.1 cgd {
343 1.1 cgd case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE:
344 1.1 cgd case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT:
345 1.1 cgd case OSPIRITSCARAB: case OCUBEofUNDEAD:
346 1.1 cgd case OPOTION: case OSCROLL: break;
347 1.1 cgd default: count++;
348 1.1 cgd };
349 1.1 cgd
350 1.1 cgd t_setup(count);
351 1.1 cgd
352 1.1 cgd for (i=22; i<84; i++)
353 1.1 cgd for (j=0; j<=26; j++)
354 1.1 cgd if (i==iven[j])
355 1.1 cgd switch(i)
356 1.1 cgd {
357 1.1 cgd case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE:
358 1.1 cgd case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT:
359 1.1 cgd case OSPIRITSCARAB: case OCUBEofUNDEAD:
360 1.1 cgd case OPOTION: case OSCROLL: break;
361 1.1 cgd default: show3(j);
362 1.1 cgd };
363 1.1 cgd more(); nosignal=sigsav; t_endup(count);
364 1.1 cgd }
365 1.1 cgd
366 1.1 cgd /*
367 1.1 cgd * function to show the things player can read only
368 1.1 cgd */
369 1.1 cgd showread()
370 1.1 cgd {
371 1.1 cgd register int i,j,sigsav,count;
372 1.1 cgd sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
373 1.1 cgd srcount=0;
374 1.1 cgd
375 1.1 cgd for (count=2,j=0; j<=26; j++)
376 1.1 cgd switch(iven[j])
377 1.1 cgd {
378 1.1 cgd case OBOOK: case OSCROLL: count++;
379 1.1 cgd };
380 1.1 cgd t_setup(count);
381 1.1 cgd
382 1.1 cgd for (i=22; i<84; i++)
383 1.1 cgd for (j=0; j<=26; j++)
384 1.1 cgd if (i==iven[j])
385 1.1 cgd switch(i)
386 1.1 cgd {
387 1.1 cgd case OBOOK: case OSCROLL: show3(j);
388 1.1 cgd };
389 1.1 cgd more(); nosignal=sigsav; t_endup(count);
390 1.1 cgd }
391 1.1 cgd
392 1.1 cgd /*
393 1.1 cgd * function to show the things player can eat only
394 1.1 cgd */
395 1.1 cgd showeat()
396 1.1 cgd {
397 1.1 cgd register int i,j,sigsav,count;
398 1.1 cgd sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
399 1.1 cgd srcount=0;
400 1.1 cgd
401 1.1 cgd for (count=2,j=0; j<=26; j++)
402 1.1 cgd switch(iven[j])
403 1.1 cgd {
404 1.1 cgd case OCOOKIE: count++;
405 1.1 cgd };
406 1.1 cgd t_setup(count);
407 1.1 cgd
408 1.1 cgd for (i=22; i<84; i++)
409 1.1 cgd for (j=0; j<=26; j++)
410 1.1 cgd if (i==iven[j])
411 1.1 cgd switch(i)
412 1.1 cgd {
413 1.1 cgd case OCOOKIE: show3(j);
414 1.1 cgd };
415 1.1 cgd more(); nosignal=sigsav; t_endup(count);
416 1.1 cgd }
417 1.1 cgd
418 1.1 cgd /*
419 1.1 cgd function to show the things player can quaff only
420 1.1 cgd */
421 1.1 cgd showquaff()
422 1.1 cgd {
423 1.1 cgd register int i,j,sigsav,count;
424 1.1 cgd sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
425 1.1 cgd srcount=0;
426 1.1 cgd
427 1.1 cgd for (count=2,j=0; j<=26; j++)
428 1.1 cgd switch(iven[j])
429 1.1 cgd {
430 1.1 cgd case OPOTION: count++;
431 1.1 cgd };
432 1.1 cgd t_setup(count);
433 1.1 cgd
434 1.1 cgd for (i=22; i<84; i++)
435 1.1 cgd for (j=0; j<=26; j++)
436 1.1 cgd if (i==iven[j])
437 1.1 cgd switch(i)
438 1.1 cgd {
439 1.1 cgd case OPOTION: show3(j);
440 1.1 cgd };
441 1.1 cgd more(); nosignal=sigsav; t_endup(count);
442 1.1 cgd }
443 1.1 cgd
444 1.1 cgd show1(idx,str2)
445 1.1 cgd register int idx;
446 1.1 cgd register char *str2[];
447 1.4 mycroft {
448 1.4 mycroft lprintf("\n%c) %s",idx+'a',objectname[iven[idx]]);
449 1.1 cgd if (str2!=0 && str2[ivenarg[idx]][0]!=0) lprintf(" of%s",str2[ivenarg[idx]]);
450 1.1 cgd }
451 1.1 cgd
452 1.1 cgd show3(index)
453 1.1 cgd register int index;
454 1.1 cgd {
455 1.1 cgd switch(iven[index])
456 1.1 cgd {
457 1.1 cgd case OPOTION: show1(index,potionname); break;
458 1.1 cgd case OSCROLL: show1(index,scrollname); break;
459 1.1 cgd
460 1.1 cgd case OLARNEYE: case OBOOK: case OSPIRITSCARAB:
461 1.1 cgd case ODIAMOND: case ORUBY: case OCUBEofUNDEAD:
462 1.1 cgd case OEMERALD: case OCHEST: case OCOOKIE:
463 1.1 cgd case OSAPPHIRE: case ONOTHEFT: show1(index,(char **)0); break;
464 1.1 cgd
465 1.1 cgd default: lprintf("\n%c) %s",index+'a',objectname[iven[index]]);
466 1.1 cgd if (ivenarg[index]>0) lprintf(" + %d",(long)ivenarg[index]);
467 1.1 cgd else if (ivenarg[index]<0) lprintf(" %d",(long)ivenarg[index]);
468 1.1 cgd break;
469 1.1 cgd }
470 1.1 cgd if (c[WIELD]==index) lprcat(" (weapon in hand)");
471 1.1 cgd if ((c[WEAR]==index) || (c[SHIELD]==index)) lprcat(" (being worn)");
472 1.1 cgd if (++srcount>=22) { srcount=0; more(); clear(); }
473 1.1 cgd }
474 1.1 cgd
475 1.1 cgd /*
476 1.1 cgd subroutine to randomly create monsters if needed
477 1.1 cgd */
478 1.1 cgd randmonst()
479 1.1 cgd {
480 1.1 cgd if (c[TIMESTOP]) return; /* don't make monsters if time is stopped */
481 1.1 cgd if (--rmst <= 0)
482 1.1 cgd {
483 1.1 cgd rmst = 120 - (level<<2); fillmonst(makemonst(level));
484 1.1 cgd }
485 1.1 cgd }
486 1.1 cgd
487 1.1 cgd
488 1.1 cgd /*
490 1.1 cgd parse()
491 1.1 cgd
492 1.1 cgd get and execute a command
493 1.1 cgd */
494 1.1 cgd parse()
495 1.1 cgd {
496 1.1 cgd register int i,j,k,flag;
497 1.1 cgd while (1)
498 1.1 cgd {
499 1.1 cgd k = yylex();
500 1.1 cgd switch(k) /* get the token from the input and switch on it */
501 1.1 cgd {
502 1.1 cgd case 'h': moveplayer(4); return; /* west */
503 1.1 cgd case 'H': run(4); return; /* west */
504 1.1 cgd case 'l': moveplayer(2); return; /* east */
505 1.1 cgd case 'L': run(2); return; /* east */
506 1.1 cgd case 'j': moveplayer(1); return; /* south */
507 1.1 cgd case 'J': run(1); return; /* south */
508 1.1 cgd case 'k': moveplayer(3); return; /* north */
509 1.1 cgd case 'K': run(3); return; /* north */
510 1.1 cgd case 'u': moveplayer(5); return; /* northeast */
511 1.1 cgd case 'U': run(5); return; /* northeast */
512 1.1 cgd case 'y': moveplayer(6); return; /* northwest */
513 1.1 cgd case 'Y': run(6); return; /* northwest */
514 1.1 cgd case 'n': moveplayer(7); return; /* southeast */
515 1.1 cgd case 'N': run(7); return; /* southeast */
516 1.1 cgd case 'b': moveplayer(8); return; /* southwest */
517 1.1 cgd case 'B': run(8); return; /* southwest */
518 1.1 cgd
519 1.1 cgd case '.': if (yrepcount) viewflag=1; return; /* stay here */
520 1.1 cgd
521 1.1 cgd case 'w': yrepcount=0; wield(); return; /* wield a weapon */
522 1.1 cgd
523 1.1 cgd case 'W': yrepcount=0; wear(); return; /* wear armor */
524 1.1 cgd
525 1.1 cgd case 'r': yrepcount=0;
526 1.1 cgd if (c[BLINDCOUNT]) { cursors(); lprcat("\nYou can't read anything when you're blind!"); } else
527 1.1 cgd if (c[TIMESTOP]==0) readscr(); return; /* to read a scroll */
528 1.1 cgd
529 1.1 cgd case 'q': yrepcount=0; if (c[TIMESTOP]==0) quaff(); return; /* quaff a potion */
530 1.1 cgd
531 1.1 cgd case 'd': yrepcount=0; if (c[TIMESTOP]==0) dropobj(); return; /* to drop an object */
532 1.1 cgd
533 1.1 cgd case 'c': yrepcount=0; cast(); return; /* cast a spell */
534 1.1 cgd
535 1.1 cgd case 'i': yrepcount=0; nomove=1; showstr(); return; /* status */
536 1.1 cgd
537 1.1 cgd case 'e': yrepcount=0;
538 1.1 cgd if (c[TIMESTOP]==0) eatcookie(); return; /* to eat a fortune cookie */
539 1.1 cgd
540 1.1 cgd case 'D': yrepcount=0; seemagic(0); nomove=1; return; /* list spells and scrolls */
541 1.1 cgd
542 1.1 cgd case '?': yrepcount=0; help(); nomove=1; return; /* give the help screen*/
543 1.1 cgd
544 1.1 cgd case 'S': clear(); lprcat("Saving . . ."); lflush();
545 1.1 cgd savegame(savefilename); wizard=1; died(-257); /* save the game - doesn't return */
546 1.1 cgd
547 1.1 cgd case 'Z': yrepcount=0; if (c[LEVEL]>9) { oteleport(1); return; }
548 1.1 cgd cursors(); lprcat("\nAs yet, you don't have enough experience to use teleportation");
549 1.1 cgd return; /* teleport yourself */
550 1.1 cgd
551 1.1 cgd case '^': /* identify traps */ flag=yrepcount=0; cursors();
552 1.1 cgd lprc('\n'); for (j=playery-1; j<playery+2; j++)
553 1.1 cgd {
554 1.1 cgd if (j < 0) j=0; if (j >= MAXY) break;
555 1.1 cgd for (i=playerx-1; i<playerx+2; i++)
556 1.1 cgd {
557 1.1 cgd if (i < 0) i=0; if (i >= MAXX) break;
558 1.1 cgd switch(item[i][j])
559 1.1 cgd {
560 1.1 cgd case OTRAPDOOR: case ODARTRAP:
561 1.1 cgd case OTRAPARROW: case OTELEPORTER:
562 1.1 cgd lprcat("\nIts "); lprcat(objectname[item[i][j]]); flag++;
563 1.1 cgd };
564 1.1 cgd }
565 1.1 cgd }
566 1.1 cgd if (flag==0) lprcat("\nNo traps are visible");
567 1.1 cgd return;
568 1.1 cgd
569 1.1 cgd #if WIZID
570 1.1 cgd case '_': /* this is the fudge player password for wizard mode*/
571 1.1 cgd yrepcount=0; cursors(); nomove=1;
572 1.1 cgd if (userid!=wisid)
573 1.1 cgd {
574 1.1 cgd lprcat("Sorry, you are not empowered to be a wizard.\n");
575 1.1 cgd scbr(); /* system("stty -echo cbreak"); */
576 1.1 cgd lflush(); return;
577 1.1 cgd }
578 1.1 cgd if (getpassword()==0)
579 1.1 cgd {
580 1.1 cgd scbr(); /* system("stty -echo cbreak"); */ return;
581 1.1 cgd }
582 1.1 cgd wizard=1; scbr(); /* system("stty -echo cbreak"); */
583 1.1 cgd for (i=0; i<6; i++) c[i]=70; iven[0]=iven[1]=0;
584 1.1 cgd take(OPROTRING,50); take(OLANCE,25); c[WIELD]=1;
585 1.1 cgd c[LANCEDEATH]=1; c[WEAR] = c[SHIELD] = -1;
586 1.1 cgd raiseexperience(6000000L); c[AWARENESS] += 25000;
587 1.1 cgd {
588 1.1 cgd register int i,j;
589 1.1 cgd for (i=0; i<MAXY; i++)
590 1.2 mycroft for (j=0; j<MAXX; j++) know[j][i]=1;
591 1.2 mycroft for (i=0; i<SPNUM; i++) spelknow[i]=1;
592 1.1 cgd for (i=0; i<MAXSCROLL; i++) scrollname[i]=scrollhide[i];
593 1.1 cgd for (i=0; i<MAXPOTION; i++) potionname[i]=potionhide[i];
594 1.1 cgd }
595 1.1 cgd for (i=0; i<MAXSCROLL; i++)
596 1.1 cgd if (strlen(scrollname[i])>2) /* no null items */
597 1.1 cgd { item[i][0]=OSCROLL; iarg[i][0]=i; }
598 1.1 cgd for (i=MAXX-1; i>MAXX-1-MAXPOTION; i--)
599 1.1 cgd if (strlen(potionname[i-MAXX+MAXPOTION])>2) /* no null items */
600 1.1 cgd { item[i][0]=OPOTION; iarg[i][0]=i-MAXX+MAXPOTION; }
601 1.1 cgd for (i=1; i<MAXY; i++)
602 1.1 cgd { item[0][i]=i; iarg[0][i]=0; }
603 1.1 cgd for (i=MAXY; i<MAXY+MAXX; i++)
604 1.1 cgd { item[i-MAXY][MAXY-1]=i; iarg[i-MAXY][MAXY-1]=0; }
605 1.1 cgd for (i=MAXX+MAXY; i<MAXX+MAXY+MAXY; i++)
606 1.1 cgd { item[MAXX-1][i-MAXX-MAXY]=i; iarg[MAXX-1][i-MAXX-MAXY]=0; }
607 1.1 cgd c[GOLD]+=25000; drawscreen(); return;
608 1.1 cgd #endif
609 1.1 cgd
610 1.1 cgd case 'T': yrepcount=0; cursors(); if (c[SHIELD] != -1) { c[SHIELD] = -1; lprcat("\nYour shield is off"); bottomline(); } else
611 1.1 cgd if (c[WEAR] != -1) { c[WEAR] = -1; lprcat("\nYour armor is off"); bottomline(); }
612 1.1 cgd else lprcat("\nYou aren't wearing anything");
613 1.1 cgd return;
614 1.1 cgd
615 1.1 cgd case 'g': cursors();
616 1.1 cgd lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long)packweight());
617 1.1 cgd case ' ': yrepcount=0; nomove=1; return;
618 1.1 cgd
619 1.1 cgd case 'v': yrepcount=0; cursors();
620 1.1 cgd lprintf("\nCaverns of Larn, Version %d.%d, Diff=%d",(long)VERSION,(long)SUBVERSION,(long)c[HARDGAME]);
621 1.1 cgd if (wizard) lprcat(" Wizard"); nomove=1;
622 1.1 cgd if (cheat) lprcat(" Cheater");
623 1.1 cgd lprcat(copyright);
624 1.1 cgd return;
625 1.1 cgd
626 1.1 cgd case 'Q': yrepcount=0; quit(); nomove=1; return; /* quit */
627 1.1 cgd
628 1.1 cgd case 'L'-64: yrepcount=0; drawscreen(); nomove=1; return; /* look */
629 1.1 cgd
630 1.1 cgd #if WIZID
631 1.1 cgd #ifdef EXTRA
632 1.1 cgd case 'A': yrepcount=0; nomove=1; if (wizard) { diag(); return; } /* create diagnostic file */
633 1.1 cgd return;
634 1.1 cgd #endif
635 1.1 cgd #endif
636 1.1 cgd case 'P': cursors();
637 1.1 cgd if (outstanding_taxes>0)
638 1.1 cgd lprintf("\nYou presently owe %d gp in taxes.",(long)outstanding_taxes);
639 1.1 cgd else
640 1.1 cgd lprcat("\nYou do not owe any taxes.");
641 1.1 cgd return;
642 1.1 cgd };
643 1.1 cgd }
644 1.1 cgd }
645 1.1 cgd
646 1.1 cgd parse2()
647 1.1 cgd {
648 1.1 cgd if (c[HASTEMONST]) movemonst(); movemonst(); /* move the monsters */
649 1.1 cgd randmonst(); regen();
650 1.1 cgd }
651 1.1 cgd
652 1.1 cgd run(dir)
653 1.1 cgd int dir;
654 1.1 cgd {
655 1.1 cgd register int i;
656 1.1 cgd i=1; while (i)
657 1.1 cgd {
658 1.1 cgd i=moveplayer(dir);
659 1.1 cgd if (i>0) { if (c[HASTEMONST]) movemonst(); movemonst(); randmonst(); regen(); }
660 1.1 cgd if (hitflag) i=0;
661 1.1 cgd if (i!=0) showcell(playerx,playery);
662 1.1 cgd }
663 1.1 cgd }
664 1.1 cgd
665 1.1 cgd /*
666 1.1 cgd function to wield a weapon
667 1.1 cgd */
668 1.1 cgd wield()
669 1.1 cgd {
670 1.1 cgd register int i;
671 1.1 cgd while (1)
672 1.1 cgd {
673 1.1 cgd if ((i = whatitem("wield"))=='\33') return;
674 1.1 cgd if (i != '.')
675 1.1 cgd {
676 1.1 cgd if (i=='*') showwield();
677 1.1 cgd else if (iven[i-'a']==0) { ydhi(i); return; }
678 1.1 cgd else if (iven[i-'a']==OPOTION) { ycwi(i); return; }
679 1.1 cgd else if (iven[i-'a']==OSCROLL) { ycwi(i); return; }
680 1.1 cgd else if ((c[SHIELD]!= -1) && (iven[i-'a']==O2SWORD)) { lprcat("\nBut one arm is busy with your shield!"); return; }
681 1.1 cgd else { c[WIELD]=i-'a'; if (iven[i-'a'] == OLANCE) c[LANCEDEATH]=1; else c[LANCEDEATH]=0; bottomline(); return; }
682 1.1 cgd }
683 1.1 cgd }
684 1.1 cgd }
685 1.1 cgd
686 1.1 cgd /*
687 1.1 cgd common routine to say you don't have an item
688 1.1 cgd */
689 1.1 cgd ydhi(x)
690 1.1 cgd int x;
691 1.1 cgd { cursors(); lprintf("\nYou don't have item %c!",x); }
692 1.1 cgd ycwi(x)
693 1.1 cgd int x;
694 1.1 cgd { cursors(); lprintf("\nYou can't wield item %c!",x); }
695 1.1 cgd
696 1.1 cgd /*
697 1.1 cgd function to wear armor
698 1.1 cgd */
699 1.1 cgd wear()
700 1.1 cgd {
701 1.1 cgd register int i;
702 1.1 cgd while (1)
703 1.1 cgd {
704 1.1 cgd if ((i = whatitem("wear"))=='\33') return;
705 1.1 cgd if (i != '.')
706 1.1 cgd {
707 1.1 cgd if (i=='*') showwear(); else
708 1.1 cgd switch(iven[i-'a'])
709 1.1 cgd {
710 1.1 cgd case 0: ydhi(i); return;
711 1.1 cgd case OLEATHER: case OCHAIN: case OPLATE: case OSTUDLEATHER:
712 1.1 cgd case ORING: case OSPLINT: case OPLATEARMOR: case OSSPLATE:
713 1.1 cgd if (c[WEAR] != -1) { lprcat("\nYou're already wearing some armor"); return; }
714 1.1 cgd c[WEAR]=i-'a'; bottomline(); return;
715 1.1 cgd case OSHIELD: if (c[SHIELD] != -1) { lprcat("\nYou are already wearing a shield"); return; }
716 1.1 cgd if (iven[c[WIELD]]==O2SWORD) { lprcat("\nYour hands are busy with the two handed sword!"); return; }
717 1.1 cgd c[SHIELD] = i-'a'; bottomline(); return;
718 1.1 cgd default: lprcat("\nYou can't wear that!");
719 1.1 cgd };
720 1.1 cgd }
721 1.1 cgd }
722 1.1 cgd }
723 1.1 cgd
724 1.1 cgd /*
725 1.1 cgd function to drop an object
726 1.1 cgd */
727 1.1 cgd dropobj()
728 1.1 cgd {
729 1.1 cgd register int i;
730 1.1 cgd register char *p;
731 1.1 cgd long amt;
732 1.1 cgd p = &item[playerx][playery];
733 1.1 cgd while (1)
734 1.1 cgd {
735 1.1 cgd if ((i = whatitem("drop"))=='\33') return;
736 1.1 cgd if (i=='*') showstr(); else
737 1.1 cgd {
738 1.1 cgd if (i=='.') /* drop some gold */
739 1.1 cgd {
740 1.1 cgd if (*p) { lprcat("\nThere's something here already!"); return; }
741 1.1 cgd lprcat("\n\n");
742 1.1 cgd cl_dn(1,23);
743 1.1 cgd lprcat("How much gold do you drop? ");
744 1.1 cgd if ((amt=readnum((long)c[GOLD])) == 0) return;
745 1.1 cgd if (amt>c[GOLD])
746 1.1 cgd { lprcat("\nYou don't have that much!"); return; }
747 1.1 cgd if (amt<=32767)
748 1.1 cgd { *p=OGOLDPILE; i=amt; }
749 1.1 cgd else if (amt<=327670L)
750 1.1 cgd { *p=ODGOLD; i=amt/10; amt = 10*i; }
751 1.1 cgd else if (amt<=3276700L)
752 1.1 cgd { *p=OMAXGOLD; i=amt/100; amt = 100*i; }
753 1.1 cgd else if (amt<=32767000L)
754 1.1 cgd { *p=OKGOLD; i=amt/1000; amt = 1000*i; }
755 1.1 cgd else
756 1.1 cgd { *p=OKGOLD; i=32767; amt = 32767000L; }
757 1.1 cgd c[GOLD] -= amt;
758 1.1 cgd lprintf("You drop %d gold pieces",(long)amt);
759 1.1 cgd iarg[playerx][playery]=i; bottomgold();
760 1.1 cgd know[playerx][playery]=0; dropflag=1; return;
761 1.1 cgd }
762 1.1 cgd drop_object(i-'a');
763 1.1 cgd return;
764 1.1 cgd }
765 1.1 cgd }
766 1.1 cgd }
767 1.1 cgd
768 1.1 cgd /*
769 1.1 cgd * readscr() Subroutine to read a scroll one is carrying
770 1.1 cgd */
771 1.1 cgd readscr()
772 1.1 cgd {
773 1.1 cgd register int i;
774 1.1 cgd while (1)
775 1.1 cgd {
776 1.1 cgd if ((i = whatitem("read"))=='\33') return;
777 1.1 cgd if (i != '.')
778 1.1 cgd {
779 1.1 cgd if (i=='*') showread(); else
780 1.1 cgd {
781 1.1 cgd if (iven[i-'a']==OSCROLL) { read_scroll(ivenarg[i-'a']); iven[i-'a']=0; return; }
782 1.1 cgd if (iven[i-'a']==OBOOK) { readbook(ivenarg[i-'a']); iven[i-'a']=0; return; }
783 1.1 cgd if (iven[i-'a']==0) { ydhi(i); return; }
784 1.1 cgd lprcat("\nThere's nothing on it to read"); return;
785 1.1 cgd }
786 1.1 cgd }
787 1.1 cgd }
788 1.1 cgd }
789 1.1 cgd
790 1.1 cgd /*
791 1.1 cgd * subroutine to eat a cookie one is carrying
792 1.1 cgd */
793 1.1 cgd eatcookie()
794 1.1 cgd {
795 1.1 cgd register int i;
796 1.1 cgd char *p;
797 1.1 cgd while (1)
798 1.1 cgd {
799 1.1 cgd if ((i = whatitem("eat"))=='\33') return;
800 1.1 cgd if (i != '.')
801 1.1 cgd if (i=='*') showeat(); else
802 1.1 cgd {
803 1.1 cgd if (iven[i-'a']==OCOOKIE)
804 1.1 cgd {
805 1.1 cgd lprcat("\nThe cookie was delicious.");
806 1.1 cgd iven[i-'a']=0;
807 1.6 cgd if (!c[BLINDCOUNT])
808 1.1 cgd {
809 1.1 cgd if (p=fortune())
810 1.1 cgd {
811 1.1 cgd lprcat(" Inside you find a scrap of paper that says:\n");
812 1.1 cgd lprcat(p);
813 1.1 cgd }
814 1.1 cgd }
815 1.1 cgd return;
816 1.1 cgd }
817 1.1 cgd if (iven[i-'a']==0) { ydhi(i); return; }
818 1.1 cgd lprcat("\nYou can't eat that!"); return;
819 1.1 cgd }
820 1.1 cgd }
821 1.1 cgd }
822 1.1 cgd
823 1.1 cgd /*
824 1.1 cgd * subroutine to quaff a potion one is carrying
825 1.1 cgd */
826 1.1 cgd quaff()
827 1.1 cgd {
828 1.1 cgd register int i;
829 1.1 cgd while (1)
830 1.1 cgd {
831 1.1 cgd if ((i = whatitem("quaff"))=='\33') return;
832 1.1 cgd if (i != '.')
833 1.1 cgd {
834 1.1 cgd if (i=='*') showquaff(); else
835 1.1 cgd {
836 1.1 cgd if (iven[i-'a']==OPOTION) { quaffpotion(ivenarg[i-'a']); iven[i-'a']=0; return; }
837 1.1 cgd if (iven[i-'a']==0) { ydhi(i); return; }
838 1.1 cgd lprcat("\nYou wouldn't want to quaff that, would you? "); return;
839 1.1 cgd }
840 1.1 cgd }
841 1.1 cgd }
842 1.1 cgd }
843 1.1 cgd
844 1.1 cgd /*
845 1.1 cgd function to ask what player wants to do
846 1.1 cgd */
847 1.1 cgd whatitem(str)
848 1.1 cgd char *str;
849 1.1 cgd {
850 1.1 cgd int i;
851 1.1 cgd cursors(); lprintf("\nWhat do you want to %s [* for all] ? ",str);
852 1.1 cgd i=0; while (i>'z' || (i<'a' && i!='*' && i!='\33' && i!='.')) i=getchar();
853 1.1 cgd if (i=='\33') lprcat(" aborted");
854 1.1 cgd return(i);
855 1.1 cgd }
856 1.1 cgd
857 1.1 cgd /*
858 1.1 cgd subroutine to get a number from the player
859 1.1 cgd and allow * to mean return amt, else return the number entered
860 1.1 cgd */
861 1.1 cgd unsigned long readnum(mx)
862 1.1 cgd long mx;
863 1.1 cgd {
864 1.1 cgd register int i;
865 1.1 cgd register unsigned long amt=0;
866 1.1 cgd sncbr();
867 1.1 cgd if ((i=getchar()) == '*') amt = mx; /* allow him to say * for all gold */
868 1.1 cgd else
869 1.1 cgd while (i != '\n')
870 1.1 cgd {
871 1.1 cgd if (i=='\033') { scbr(); lprcat(" aborted"); return(0); }
872 1.1 cgd if ((i <= '9') && (i >= '0') && (amt<99999999))
873 1.1 cgd amt = amt*10+i-'0';
874 1.1 cgd i = getchar();
875 1.1 cgd }
876 1.1 cgd scbr(); return(amt);
877 1.1 cgd }
878 1.1 cgd
879 1.1 cgd #ifdef HIDEBYLINK
880 1.1 cgd /*
881 1.1 cgd * routine to zero every byte in a string
882 1.1 cgd */
883 1.1 cgd szero(str)
884 1.1 cgd register char *str;
885 1.1 cgd {
886 1.1 cgd while (*str)
887 1.1 cgd *str++ = 0;
888 }
889 #endif HIDEBYLINK
890