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