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