* Fix some cases where NULL was used but 0 was meant (and vice versa).
[dragonfly.git] / games / larn / main.c
blob58c0a25813a4e767fb19be71ad2b75f92547a23c
1 /* main.c */
2 /* $FreeBSD: src/games/larn/main.c,v 1.9 1999/11/30 03:48:59 billf Exp $ */
3 /* $DragonFly: src/games/larn/main.c,v 1.5 2008/06/05 18:06:30 swildner Exp $ */
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include "header.h"
7 #include <pwd.h>
8 static const char copyright[]="\nLarn is copyrighted 1986 by Noah Morgan.\n";
9 int srcount=0; /* line counter for showstr() */
10 int dropflag=0; /* if 1 then don't lookforobject() next round */
11 int rmst=80; /* random monster creation counter */
12 int userid; /* the players login user id number */
13 char nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a move */
14 static char viewflag=0;
15 /* if viewflag then we have done a 99 stay here and don't showcell in the main loop */
16 char restorflag=0; /* 1 means restore has been done */
17 static char cmdhelp[] = "\
18 Cmd line format: larn [-slicnh] [-o<optsifle>] [-##] [++]\n\
19 -s show the scoreboard\n\
20 -l show the logfile (wizard id only)\n\
21 -i show scoreboard with inventories of dead characters\n\
22 -c create new scoreboard (wizard id only)\n\
23 -n suppress welcome message on starting game\n\
24 -## specify level of difficulty (example: -5)\n\
25 -h print this help text\n\
26 ++ restore game from checkpoint file\n\
27 -o<optsfile> specify .larnopts filename to be used instead of \"~/.larnopts\"\n\
29 #ifdef VT100
30 static const char *termtypes[] = { "vt100", "vt101", "vt102", "vt103", "vt125",
31 "vt131", "vt140", "vt180", "vt220", "vt240", "vt241", "vt320", "vt340",
32 "vt341" };
33 #endif /* VT100 */
35 static void showstr(void);
36 static void t_setup(int);
37 static void t_endup(int);
38 static void showwear(void);
39 static void showwield(void);
40 static void showread(void);
41 static void showeat(void);
42 static void showquaff(void);
43 static void show1(int, const char **);
44 static void randmonst(void);
45 static void parse(void);
46 static void run(int);
47 static void wield(void);
48 static void ydhi(int);
49 static void ycwi(int);
50 static void wear(void);
51 static void dropobj(void);
52 static void readscr(void);
53 static void eatcookie(void);
54 static void quaff(void);
55 static int whatitem(const char *);
56 #ifdef HIDEBYLINK
57 static void szero(char *);
58 #endif
61 ************
62 MAIN PROGRAM
63 ************
65 int
66 main(int argc, char **argv)
68 int i;
69 int hard;
70 const char *ptr;
71 #ifdef VT100
72 char *ttype;
73 int j;
74 #endif
75 struct passwd *pwe;
76 struct stat sb;
79 * first task is to identify the player
81 #ifndef VT100
82 init_term(); /* setup the terminal (find out what type) for termcap */
83 #endif /* VT100 */
84 if (((ptr = getlogin()) == 0) || (*ptr==0)) { /* try to get login name */
85 if ((pwe=getpwuid(getuid()))) /* can we get it from /etc/passwd? */
86 ptr = pwe->pw_name;
87 else
88 if ((ptr = getenv("USER")) == 0)
89 if ((ptr = getenv("LOGNAME")) == 0)
91 noone: write(2, "Can't find your logname. Who Are You?\n",39);
92 exit(1);
95 if (ptr==0) goto noone;
96 if (strlen(ptr)==0) goto noone;
98 * second task is to prepare the pathnames the player will need
100 strcpy(loginname,ptr); /* save loginname of the user for logging purposes */
101 strcpy(logname,ptr); /* this will be overwritten with the players name */
102 if ((ptr = getenv("HOME")) == 0) ptr = ".";
103 strcpy(savefilename, ptr);
104 strcat(savefilename, "/Larn.sav"); /* save file name in home directory */
105 sprintf(optsfile, "%s/.larnopts",ptr); /* the .larnopts filename */
108 * now malloc the memory for the dungeon
110 cell = (struct cel *)malloc(sizeof(struct cel)*(MAXLEVEL+MAXVLEVEL)*MAXX*MAXY);
111 if (cell == 0) died(-285); /* malloc failure */
112 lpbuf = malloc((5* BUFBIG)>>2); /* output buffer */
113 inbuffer = malloc((5*MAXIBUF)>>2); /* output buffer */
114 if ((lpbuf==0) || (inbuffer==0)) died(-285); /* malloc() failure */
116 lcreat((char*)0); newgame(); /* set the initial clock */ hard= -1;
118 #ifdef VT100
120 * check terminal type to avoid users who have not vt100 type terminals
122 ttype = getenv("TERM");
123 for (j=1, i=0; i<sizeof(termtypes)/sizeof(char *); i++)
124 if (strcmp(ttype,termtypes[i]) == 0) { j=0; break; }
125 if (j)
127 lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush();
128 exit(1);
130 #endif /* VT100 */
133 * now make scoreboard if it is not there (don't clear)
135 if (stat(scorefile,&sb) < 0 || sb.st_size == 0) /* not there */
136 makeboard();
139 * now process the command line arguments
141 for (i=1; i<argc; i++)
143 if (argv[i][0] == '-')
144 switch(argv[i][1])
146 case 's': showscores(); exit(0); /* show scoreboard */
148 case 'l': /* show log file */
149 diedlog(); exit(0);
151 case 'i': showallscores(); exit(0); /* show all scoreboard */
153 case 'c': /* anyone with password can create scoreboard */
154 lprcat("Preparing to initialize the scoreboard.\n");
155 if (getpassword() != 0) /*make new scoreboard*/
157 makeboard(); lprc('\n'); showscores();
159 exit(0);
161 case 'n': /* no welcome msg */ nowelcome=1; argv[i][0]=0; break;
163 case '0': case '1': case '2': case '3': case '4': case '5':
164 case '6': case '7': case '8': case '9': /* for hardness */
165 sscanf(&argv[i][1],"%d",&hard);
166 break;
168 case 'h': /* print out command line arguments */
169 write(1,cmdhelp,sizeof(cmdhelp)); exit(0);
171 case 'o': /* specify a .larnopts filename */
172 strncpy(optsfile,argv[i]+2,127); break;
174 default: printf("Unknown option <%s>\n",argv[i]); exit(1);
177 if (argv[i][0] == '+')
179 clear(); restorflag = 1;
180 if (argv[i][1] == '+')
182 hitflag=1; restoregame(ckpfile); /* restore checkpointed game */
184 i = argc;
188 readopts(); /* read the options file if there is one */
191 #ifdef UIDSCORE
192 userid = geteuid(); /* obtain the user's effective id number */
193 #else /* UIDSCORE */
194 userid = getplid(logname); /* obtain the players id number */
195 #endif /* UIDSCORE */
196 if (userid < 0) { write(2,"Can't obtain playerid\n",22); exit(1); }
198 #ifdef HIDEBYLINK
200 * this section of code causes the program to look like something else to ps
202 if (strcmp(psname,argv[0])) /* if a different process name only */
204 if ((i=access(psname,1)) < 0)
205 { /* link not there */
206 if (link(argv[0],psname)>=0)
208 argv[0] = psname; execv(psname,argv);
211 else
212 unlink(psname);
215 for (i=1; i<argc; i++)
217 szero(argv[i]); /* zero the argument to avoid ps snooping */
219 #endif /* HIDEBYLINK */
221 if (access(savefilename,0)==0) /* restore game if need to */
223 clear(); restorflag = 1;
224 hitflag=1; restoregame(savefilename); /* restore last game */
226 sigsetup(); /* trap all needed signals */
227 sethard(hard); /* set up the desired difficulty */
228 setupvt100(); /* setup the terminal special mode */
229 if (c[HP]==0) /* create new game */
231 makeplayer(); /* make the character that will play */
232 newcavelevel(0);/* make the dungeon */
233 predostuff = 1; /* tell signals that we are in the welcome screen */
234 if (nowelcome==0) welcome(); /* welcome the player to the game */
236 drawscreen(); /* show the initial dungeon */
237 predostuff = 2; /* tell the trap functions that they must do a showplayer()
238 from here on */
239 /* nice(1); */ /* games should be run niced */
240 yrepcount = hit2flag = 0;
241 while (1)
243 if (dropflag==0) lookforobject(); /* see if there is an object here */
244 else dropflag=0; /* don't show it just dropped an item */
245 if (hitflag==0) { if (c[HASTEMONST]) movemonst(); movemonst(); } /* move the monsters */
246 if (viewflag==0) showcell(playerx,playery); else viewflag=0; /* show stuff around player */
247 if (hit3flag) flushall();
248 hitflag=hit3flag=0; nomove=1;
249 bot_linex(); /* update bottom line */
250 while (nomove)
252 if (hit3flag) flushall();
253 nomove=0; parse();
254 } /* get commands and make moves */
255 regen(); /* regenerate hp and spells */
256 if (c[TIMESTOP]==0)
257 if (--rmst <= 0)
258 { rmst = 120-(level<<2); fillmonst(makemonst(level)); }
263 showstr()
265 show character's inventory
267 static void
268 showstr(void)
270 int i,number;
271 for (number=3, i=0; i<26; i++)
272 if (iven[i]) number++; /* count items in inventory */
273 t_setup(number); qshowstr(); t_endup(number);
276 void
277 qshowstr(void)
279 int i,j,k,sigsav;
280 srcount=0; sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
281 if (c[GOLD]) { lprintf(".) %d gold pieces",(long)c[GOLD]); srcount++; }
282 for (k=26; k>=0; k--)
283 if (iven[k])
284 { for (i=22; i<84; i++)
285 for (j=0; j<=k; j++) if (i==iven[j]) show3(j); k=0; }
287 lprintf("\nElapsed time is %d. You have %d mobuls left",(long)((gtime+99)/100+1),(long)((TIMELIMIT-gtime)/100));
288 more(); nosignal=sigsav;
292 * subroutine to clear screen depending on # lines to display
294 static void
295 t_setup(int count)
297 if (count<20) /* how do we clear the screen? */
299 cl_up(79,count); cursor(1,1);
301 else
303 resetscroll(); clear();
308 * subroutine to restore normal display screen depending on t_setup()
310 static void
311 t_endup(int count)
313 if (count<18) /* how did we clear the screen? */
314 draws(0,MAXX,0,(count>MAXY) ? MAXY : count);
315 else
317 drawscreen(); setscroll();
322 function to show the things player is wearing only
324 static void
325 showwear(void)
327 int i,j,sigsav,count;
328 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
329 srcount=0;
331 for (count=2,j=0; j<=26; j++) /* count number of items we will display */
332 if ((i=iven[j]))
333 switch(i)
335 case OLEATHER: case OPLATE: case OCHAIN:
336 case ORING: case OSTUDLEATHER: case OSPLINT:
337 case OPLATEARMOR: case OSSPLATE: case OSHIELD:
338 count++;
341 t_setup(count);
343 for (i=22; i<84; i++)
344 for (j=0; j<=26; j++)
345 if (i==iven[j])
346 switch(i)
348 case OLEATHER: case OPLATE: case OCHAIN:
349 case ORING: case OSTUDLEATHER: case OSPLINT:
350 case OPLATEARMOR: case OSSPLATE: case OSHIELD:
351 show3(j);
353 more(); nosignal=sigsav; t_endup(count);
357 function to show the things player can wield only
359 static void
360 showwield(void)
362 int i,j,sigsav,count;
363 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
364 srcount=0;
366 for (count=2,j=0; j<=26; j++) /* count how many items */
367 if ((i=iven[j]))
368 switch(i)
370 case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE:
371 case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT:
372 case OSPIRITSCARAB: case OCUBEofUNDEAD:
373 case OPOTION: case OSCROLL: break;
374 default: count++;
377 t_setup(count);
379 for (i=22; i<84; i++)
380 for (j=0; j<=26; j++)
381 if (i==iven[j])
382 switch(i)
384 case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE:
385 case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT:
386 case OSPIRITSCARAB: case OCUBEofUNDEAD:
387 case OPOTION: case OSCROLL: break;
388 default: show3(j);
390 more(); nosignal=sigsav; t_endup(count);
394 * function to show the things player can read only
396 static void
397 showread(void)
399 int i,j,sigsav,count;
400 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
401 srcount=0;
403 for (count=2,j=0; j<=26; j++)
404 switch(iven[j])
406 case OBOOK: case OSCROLL: count++;
408 t_setup(count);
410 for (i=22; i<84; i++)
411 for (j=0; j<=26; j++)
412 if (i==iven[j])
413 switch(i)
415 case OBOOK: case OSCROLL: show3(j);
417 more(); nosignal=sigsav; t_endup(count);
421 * function to show the things player can eat only
423 static void
424 showeat(void)
426 int i,j,sigsav,count;
427 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
428 srcount=0;
430 for (count=2,j=0; j<=26; j++)
431 switch(iven[j])
433 case OCOOKIE: count++;
435 t_setup(count);
437 for (i=22; i<84; i++)
438 for (j=0; j<=26; j++)
439 if (i==iven[j])
440 switch(i)
442 case OCOOKIE: show3(j);
444 more(); nosignal=sigsav; t_endup(count);
448 function to show the things player can quaff only
450 static void
451 showquaff(void)
453 int i,j,sigsav,count;
454 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
455 srcount=0;
457 for (count=2,j=0; j<=26; j++)
458 switch(iven[j])
460 case OPOTION: count++;
462 t_setup(count);
464 for (i=22; i<84; i++)
465 for (j=0; j<=26; j++)
466 if (i==iven[j])
467 switch(i)
469 case OPOTION: show3(j);
471 more(); nosignal=sigsav; t_endup(count);
474 static void
475 show1(int idx, const char *str2[])
477 lprintf("\n%c) %s",idx+'a',objectname[(int)iven[idx]]);
478 if(str2 != NULL && str2[ivenarg[idx]][0] != 0)
479 lprintf(" of%s", str2[ivenarg[idx]]);
482 void
483 show3(int idx)
485 switch(iven[idx])
487 case OPOTION: show1(idx,potionname); break;
488 case OSCROLL: show1(idx,scrollname); break;
490 case OLARNEYE: case OBOOK: case OSPIRITSCARAB:
491 case ODIAMOND: case ORUBY: case OCUBEofUNDEAD:
492 case OEMERALD: case OCHEST: case OCOOKIE:
493 case OSAPPHIRE: case ONOTHEFT: show1(idx,NULL); break;
495 default: lprintf("\n%c) %s",idx+'a',objectname[(int)iven[idx]]);
496 if (ivenarg[idx]>0) lprintf(" + %d",(long)ivenarg[idx]);
497 else if (ivenarg[idx]<0) lprintf(" %d",(long)ivenarg[idx]);
498 break;
500 if (c[WIELD]==idx) lprcat(" (weapon in hand)");
501 if ((c[WEAR]==idx) || (c[SHIELD]==idx)) lprcat(" (being worn)");
502 if (++srcount>=22) { srcount=0; more(); clear(); }
506 subroutine to randomly create monsters if needed
508 static void
509 randmonst(void)
511 if (c[TIMESTOP]) return; /* don't make monsters if time is stopped */
512 if (--rmst <= 0)
514 rmst = 120 - (level<<2); fillmonst(makemonst(level));
520 parse()
522 get and execute a command
524 static void
525 parse(void)
527 int i,j,k,flag;
528 while (1)
530 k = yylex();
531 switch(k) /* get the token from the input and switch on it */
533 case 'h': moveplayer(4); return; /* west */
534 case 'H': run(4); return; /* west */
535 case 'l': moveplayer(2); return; /* east */
536 case 'L': run(2); return; /* east */
537 case 'j': moveplayer(1); return; /* south */
538 case 'J': run(1); return; /* south */
539 case 'k': moveplayer(3); return; /* north */
540 case 'K': run(3); return; /* north */
541 case 'u': moveplayer(5); return; /* northeast */
542 case 'U': run(5); return; /* northeast */
543 case 'y': moveplayer(6); return; /* northwest */
544 case 'Y': run(6); return; /* northwest */
545 case 'n': moveplayer(7); return; /* southeast */
546 case 'N': run(7); return; /* southeast */
547 case 'b': moveplayer(8); return; /* southwest */
548 case 'B': run(8); return; /* southwest */
550 case '.': if (yrepcount) viewflag=1; return; /* stay here */
552 case 'w': yrepcount=0; wield(); return; /* wield a weapon */
554 case 'W': yrepcount=0; wear(); return; /* wear armor */
556 case 'r': yrepcount=0;
557 if (c[BLINDCOUNT]) { cursors(); lprcat("\nYou can't read anything when you're blind!"); } else
558 if (c[TIMESTOP]==0) readscr(); return; /* to read a scroll */
560 case 'q': yrepcount=0; if (c[TIMESTOP]==0) quaff(); return; /* quaff a potion */
562 case 'd': yrepcount=0; if (c[TIMESTOP]==0) dropobj(); return; /* to drop an object */
564 case 'c': yrepcount=0; cast(); return; /* cast a spell */
566 case 'i': yrepcount=0; nomove=1; showstr(); return; /* status */
568 case 'e': yrepcount=0;
569 if (c[TIMESTOP]==0) eatcookie(); return; /* to eat a fortune cookie */
571 case 'D': yrepcount=0; seemagic(0); nomove=1; return; /* list spells and scrolls */
573 case '?': yrepcount=0; help(); nomove=1; return; /* give the help screen*/
575 case 'S': clear(); lprcat("Saving . . ."); lflush();
576 savegame(savefilename); wizard=1; died(-257); /* save the game - doesn't return */
578 case 'Z': yrepcount=0; if (c[LEVEL]>9) { oteleport(1); return; }
579 cursors(); lprcat("\nAs yet, you don't have enough experience to use teleportation");
580 return; /* teleport yourself */
582 case '^': /* identify traps */ flag=yrepcount=0; cursors();
583 lprc('\n'); for (j=playery-1; j<playery+2; j++)
585 if (j < 0) j=0; if (j >= MAXY) break;
586 for (i=playerx-1; i<playerx+2; i++)
588 if (i < 0) i=0; if (i >= MAXX) break;
589 switch(item[i][j])
591 case OTRAPDOOR: case ODARTRAP:
592 case OTRAPARROW: case OTELEPORTER:
593 lprcat("\nIts "); lprcat(objectname[(int)item[i][j]]); flag++;
597 if (flag==0) lprcat("\nNo traps are visible");
598 return;
600 #if WIZID
601 case '_': /* this is the fudge player password for wizard mode*/
602 yrepcount=0; cursors(); nomove=1;
603 if (userid!=wisid)
605 lprcat("Sorry, you are not empowered to be a wizard.\n");
606 scbr(); /* system("stty -echo cbreak"); */
607 lflush(); return;
609 if (getpassword()==0)
611 scbr(); /* system("stty -echo cbreak"); */ return;
613 wizard=1; scbr(); /* system("stty -echo cbreak"); */
614 for (i=0; i<6; i++) c[i]=70; iven[0]=iven[1]=0;
615 take(OPROTRING,50); take(OLANCE,25); c[WIELD]=1;
616 c[LANCEDEATH]=1; c[WEAR] = c[SHIELD] = -1;
617 raiseexperience(6000000L); c[AWARENESS] += 25000;
619 int i,j;
620 for (i=0; i<MAXY; i++)
621 for (j=0; j<MAXX; j++) know[j][i]=1;
622 for (i=0; i<SPNUM; i++) spelknow[i]=1;
623 for (i=0; i<MAXSCROLL; i++) scrollname[i] = scrollhide[i];
624 for (i=0; i<MAXPOTION; i++) potionname[i] = potionhide[i];
626 for (i=0; i<MAXSCROLL; i++)
627 if (strlen(scrollname[i])>2) /* no null items */
628 { item[i][0]=OSCROLL; iarg[i][0]=i; }
629 for (i=MAXX-1; i>MAXX-1-MAXPOTION; i--)
630 if (strlen(potionname[i-MAXX+MAXPOTION])>2) /* no null items */
631 { item[i][0]=OPOTION; iarg[i][0]=i-MAXX+MAXPOTION; }
632 for (i=1; i<MAXY; i++)
633 { item[0][i]=i; iarg[0][i]=0; }
634 for (i=MAXY; i<MAXY+MAXX; i++)
635 { item[i-MAXY][MAXY-1]=i; iarg[i-MAXY][MAXY-1]=0; }
636 for (i=MAXX+MAXY; i<MAXX+MAXY+MAXY; i++)
637 { item[MAXX-1][i-MAXX-MAXY]=i; iarg[MAXX-1][i-MAXX-MAXY]=0; }
638 c[GOLD]+=25000; drawscreen(); return;
639 #endif
641 case 'T': yrepcount=0; cursors(); if (c[SHIELD] != -1) { c[SHIELD] = -1; lprcat("\nYour shield is off"); bottomline(); } else
642 if (c[WEAR] != -1) { c[WEAR] = -1; lprcat("\nYour armor is off"); bottomline(); }
643 else lprcat("\nYou aren't wearing anything");
644 return;
646 case 'g': cursors();
647 lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long)packweight());
648 case ' ': yrepcount=0; nomove=1; return;
650 case 'v': yrepcount=0; cursors();
651 lprintf("\nCaverns of Larn, Version %d.%d, Diff=%d",(long)VERSION,(long)SUBVERSION,(long)c[HARDGAME]);
652 if (wizard) lprcat(" Wizard"); nomove=1;
653 if (cheat) lprcat(" Cheater");
654 lprcat(copyright);
655 return;
657 case 'Q': yrepcount=0; quit(); nomove=1; return; /* quit */
659 case 'L'-64: yrepcount=0; drawscreen(); nomove=1; return; /* look */
661 #if WIZID
662 #ifdef EXTRA
663 case 'A': yrepcount=0; nomove=1; if (wizard) { diag(); return; } /* create diagnostic file */
664 return;
665 #endif
666 #endif
667 case 'P': cursors();
668 if (outstanding_taxes>0)
669 lprintf("\nYou presently owe %d gp in taxes.",(long)outstanding_taxes);
670 else
671 lprcat("\nYou do not owe any taxes.");
672 return;
677 void
678 parse2(void)
680 if (c[HASTEMONST]) movemonst(); movemonst(); /* move the monsters */
681 randmonst(); regen();
684 static void
685 run(int dir)
687 int i;
688 i=1; while (i)
690 i=moveplayer(dir);
691 if (i>0) { if (c[HASTEMONST]) movemonst(); movemonst(); randmonst(); regen(); }
692 if (hitflag) i=0;
693 if (i!=0) showcell(playerx,playery);
698 function to wield a weapon
700 static void
701 wield(void)
703 int i;
704 while (1)
706 if ((i = whatitem("wield"))=='\33') return;
707 if (i != '.')
709 if (i=='*') showwield();
710 else if (iven[i-'a']==0) { ydhi(i); return; }
711 else if (iven[i-'a']==OPOTION) { ycwi(i); return; }
712 else if (iven[i-'a']==OSCROLL) { ycwi(i); return; }
713 else if ((c[SHIELD]!= -1) && (iven[i-'a']==O2SWORD)) { lprcat("\nBut one arm is busy with your shield!"); return; }
714 else { c[WIELD]=i-'a'; if (iven[i-'a'] == OLANCE) c[LANCEDEATH]=1; else c[LANCEDEATH]=0; bottomline(); return; }
720 common routine to say you don't have an item
722 static void
723 ydhi(int x)
724 { cursors(); lprintf("\nYou don't have item %c!",x); }
726 static void
727 ycwi(int x)
728 { cursors(); lprintf("\nYou can't wield item %c!",x); }
731 function to wear armor
733 static void
734 wear(void)
736 int i;
737 while (1)
739 if ((i = whatitem("wear"))=='\33') return;
740 if (i != '.')
742 if (i=='*') showwear(); else
743 switch(iven[i-'a'])
745 case 0: ydhi(i); return;
746 case OLEATHER: case OCHAIN: case OPLATE: case OSTUDLEATHER:
747 case ORING: case OSPLINT: case OPLATEARMOR: case OSSPLATE:
748 if (c[WEAR] != -1) { lprcat("\nYou're already wearing some armor"); return; }
749 c[WEAR]=i-'a'; bottomline(); return;
750 case OSHIELD: if (c[SHIELD] != -1) { lprcat("\nYou are already wearing a shield"); return; }
751 if (iven[c[WIELD]]==O2SWORD) { lprcat("\nYour hands are busy with the two handed sword!"); return; }
752 c[SHIELD] = i-'a'; bottomline(); return;
753 default: lprcat("\nYou can't wear that!");
760 function to drop an object
762 static void
763 dropobj(void)
765 int i;
766 char *p;
767 long amt;
768 p = &item[playerx][playery];
769 while (1)
771 if ((i = whatitem("drop"))=='\33') return;
772 if (i=='*') showstr(); else
774 if (i=='.') /* drop some gold */
776 if (*p) { lprcat("\nThere's something here already!"); return; }
777 lprcat("\n\n");
778 cl_dn(1,23);
779 lprcat("How much gold do you drop? ");
780 if ((amt=readnum((long)c[GOLD])) == 0) return;
781 if (amt>c[GOLD])
782 { lprcat("\nYou don't have that much!"); return; }
783 if (amt<=32767)
784 { *p=OGOLDPILE; i=amt; }
785 else if (amt<=327670L)
786 { *p=ODGOLD; i=amt/10; amt = 10*i; }
787 else if (amt<=3276700L)
788 { *p=OMAXGOLD; i=amt/100; amt = 100*i; }
789 else if (amt<=32767000L)
790 { *p=OKGOLD; i=amt/1000; amt = 1000*i; }
791 else
792 { *p=OKGOLD; i=32767; amt = 32767000L; }
793 c[GOLD] -= amt;
794 lprintf("You drop %d gold pieces",(long)amt);
795 iarg[playerx][playery]=i; bottomgold();
796 know[playerx][playery]=0; dropflag=1; return;
798 drop_object(i-'a');
799 return;
805 * readscr() Subroutine to read a scroll one is carrying
807 static void
808 readscr(void)
810 int i;
811 while (1)
813 if ((i = whatitem("read"))=='\33') return;
814 if (i != '.')
816 if (i=='*') showread(); else
818 if (iven[i-'a']==OSCROLL) { read_scroll(ivenarg[i-'a']); iven[i-'a']=0; return; }
819 if (iven[i-'a']==OBOOK) { readbook(ivenarg[i-'a']); iven[i-'a']=0; return; }
820 if (iven[i-'a']==0) { ydhi(i); return; }
821 lprcat("\nThere's nothing on it to read"); return;
828 * subroutine to eat a cookie one is carrying
830 static void
831 eatcookie(void)
833 int i;
834 const char *p;
835 while (1)
837 if ((i = whatitem("eat"))=='\33') return;
838 if (i != '.') {
839 if (i=='*') showeat(); else
841 if (iven[i-'a']==OCOOKIE)
843 lprcat("\nThe cookie was delicious.");
844 iven[i-'a']=0;
845 if (!c[BLINDCOUNT])
847 if ((p=fortune()))
849 lprcat(" Inside you find a scrap of paper that says:\n");
850 lprcat(p);
853 return;
855 if (iven[i-'a']==0) { ydhi(i); return; }
856 lprcat("\nYou can't eat that!"); return;
863 * subroutine to quaff a potion one is carrying
865 static void
866 quaff(void)
868 int i;
869 while (1)
871 if ((i = whatitem("quaff"))=='\33') return;
872 if (i != '.')
874 if (i=='*') showquaff(); else
876 if (iven[i-'a']==OPOTION) { quaffpotion(ivenarg[i-'a']); iven[i-'a']=0; return; }
877 if (iven[i-'a']==0) { ydhi(i); return; }
878 lprcat("\nYou wouldn't want to quaff that, would you? "); return;
885 function to ask what player wants to do
887 static int
888 whatitem(const char *str)
890 int i;
891 cursors(); lprintf("\nWhat do you want to %s [* for all] ? ",str);
892 i=0; while (i>'z' || (i<'a' && i!='*' && i!='\33' && i!='.')) i=getchr();
893 if (i=='\33') lprcat(" aborted");
894 return(i);
898 subroutine to get a number from the player
899 and allow * to mean return amt, else return the number entered
901 unsigned long
902 readnum(long mx)
904 int i;
905 unsigned long amt=0;
906 sncbr();
907 if ((i=getchr()) == '*') amt = mx; /* allow him to say * for all gold */
908 else
909 while (i != '\n')
911 if (i=='\033') { scbr(); lprcat(" aborted"); return(0); }
912 if ((i <= '9') && (i >= '0') && (amt<99999999))
913 amt = amt*10+i-'0';
914 i = getchr();
916 scbr(); return(amt);
919 #ifdef HIDEBYLINK
921 * routine to zero every byte in a string
923 static void
924 szero(char *str)
926 while (*str)
927 *str++ = 0;
929 #endif /* HIDEBYLINK */