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