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\ 28 "; 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 */ 34 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 59 60 /* 61 ************ 62 MAIN PROGRAM 63 ************ 64 */ 65 int 66 main(int argc, char **argv) 67 { 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; 77 78 /* 79 * first task is to identify the player 80 */ 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) 90 { 91 noone: write(2, "Can't find your logname. Who Are You?\n",39); 92 exit(1); 93 } 94 } 95 if (ptr==0) goto noone; 96 if (strlen(ptr)==0) goto noone; 97 /* 98 * second task is to prepare the pathnames the player will need 99 */ 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 */ 106 107 /* 108 * now malloc the memory for the dungeon 109 */ 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 */ 115 116 lcreat(NULL); newgame(); /* set the initial clock */ hard= -1; 117 118 #ifdef VT100 119 /* 120 * check terminal type to avoid users who have not vt100 type terminals 121 */ 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) 126 { 127 lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush(); 128 exit(1); 129 } 130 #endif /* VT100 */ 131 132 /* 133 * now make scoreboard if it is not there (don't clear) 134 */ 135 if (stat(scorefile,&sb) < 0 || sb.st_size == 0) /* not there */ 136 makeboard(); 137 138 /* 139 * now process the command line arguments 140 */ 141 for (i=1; i<argc; i++) 142 { 143 if (argv[i][0] == '-') 144 switch(argv[i][1]) 145 { 146 case 's': showscores(); exit(0); /* show scoreboard */ 147 148 case 'l': /* show log file */ 149 diedlog(); exit(0); 150 151 case 'i': showallscores(); exit(0); /* show all scoreboard */ 152 153 case 'c': /* anyone with password can create scoreboard */ 154 lprcat("Preparing to initialize the scoreboard.\n"); 155 if (getpassword() != 0) /*make new scoreboard*/ 156 { 157 makeboard(); lprc('\n'); showscores(); 158 } 159 exit(0); 160 161 case 'n': /* no welcome msg */ nowelcome=1; argv[i][0]=0; break; 162 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; 167 168 case 'h': /* print out command line arguments */ 169 write(1,cmdhelp,sizeof(cmdhelp)); exit(0); 170 171 case 'o': /* specify a .larnopts filename */ 172 strncpy(optsfile,argv[i]+2,127); break; 173 174 default: printf("Unknown option <%s>\n",argv[i]); exit(1); 175 }; 176 177 if (argv[i][0] == '+') 178 { 179 clear(); restorflag = 1; 180 if (argv[i][1] == '+') 181 { 182 hitflag=1; restoregame(ckpfile); /* restore checkpointed game */ 183 } 184 i = argc; 185 } 186 } 187 188 readopts(); /* read the options file if there is one */ 189 190 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); } 197 198 #ifdef HIDEBYLINK 199 /* 200 * this section of code causes the program to look like something else to ps 201 */ 202 if (strcmp(psname,argv[0])) /* if a different process name only */ 203 { 204 if ((i=access(psname,1)) < 0) 205 { /* link not there */ 206 if (link(argv[0],psname)>=0) 207 { 208 argv[0] = psname; execv(psname,argv); 209 } 210 } 211 else 212 unlink(psname); 213 } 214 215 for (i=1; i<argc; i++) 216 { 217 szero(argv[i]); /* zero the argument to avoid ps snooping */ 218 } 219 #endif /* HIDEBYLINK */ 220 221 if (access(savefilename,0)==0) /* restore game if need to */ 222 { 223 clear(); restorflag = 1; 224 hitflag=1; restoregame(savefilename); /* restore last game */ 225 } 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 */ 230 { 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 */ 235 } 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) 242 { 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) 251 { 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)); } 259 } 260 } 261 262 /* 263 showstr() 264 265 show character's inventory 266 */ 267 static void 268 showstr(void) 269 { 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); 274 } 275 276 void 277 qshowstr(void) 278 { 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; } 286 287 lprintf("\nElapsed time is %d. You have %d mobuls left",(long)((gtime+99)/100+1),(long)((TIMELIMIT-gtime)/100)); 288 more(); nosignal=sigsav; 289 } 290 291 /* 292 * subroutine to clear screen depending on # lines to display 293 */ 294 static void 295 t_setup(int count) 296 { 297 if (count<20) /* how do we clear the screen? */ 298 { 299 cl_up(79,count); cursor(1,1); 300 } 301 else 302 { 303 resetscroll(); clear(); 304 } 305 } 306 307 /* 308 * subroutine to restore normal display screen depending on t_setup() 309 */ 310 static void 311 t_endup(int count) 312 { 313 if (count<18) /* how did we clear the screen? */ 314 draws(0,MAXX,0,(count>MAXY) ? MAXY : count); 315 else 316 { 317 drawscreen(); setscroll(); 318 } 319 } 320 321 /* 322 function to show the things player is wearing only 323 */ 324 static void 325 showwear(void) 326 { 327 int i,j,sigsav,count; 328 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ 329 srcount=0; 330 331 for (count=2,j=0; j<=26; j++) /* count number of items we will display */ 332 if ((i=iven[j])) 333 switch(i) 334 { 335 case OLEATHER: case OPLATE: case OCHAIN: 336 case ORING: case OSTUDLEATHER: case OSPLINT: 337 case OPLATEARMOR: case OSSPLATE: case OSHIELD: 338 count++; 339 }; 340 341 t_setup(count); 342 343 for (i=22; i<84; i++) 344 for (j=0; j<=26; j++) 345 if (i==iven[j]) 346 switch(i) 347 { 348 case OLEATHER: case OPLATE: case OCHAIN: 349 case ORING: case OSTUDLEATHER: case OSPLINT: 350 case OPLATEARMOR: case OSSPLATE: case OSHIELD: 351 show3(j); 352 }; 353 more(); nosignal=sigsav; t_endup(count); 354 } 355 356 /* 357 function to show the things player can wield only 358 */ 359 static void 360 showwield(void) 361 { 362 int i,j,sigsav,count; 363 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ 364 srcount=0; 365 366 for (count=2,j=0; j<=26; j++) /* count how many items */ 367 if ((i=iven[j])) 368 switch(i) 369 { 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++; 375 }; 376 377 t_setup(count); 378 379 for (i=22; i<84; i++) 380 for (j=0; j<=26; j++) 381 if (i==iven[j]) 382 switch(i) 383 { 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); 389 }; 390 more(); nosignal=sigsav; t_endup(count); 391 } 392 393 /* 394 * function to show the things player can read only 395 */ 396 static void 397 showread(void) 398 { 399 int i,j,sigsav,count; 400 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ 401 srcount=0; 402 403 for (count=2,j=0; j<=26; j++) 404 switch(iven[j]) 405 { 406 case OBOOK: case OSCROLL: count++; 407 }; 408 t_setup(count); 409 410 for (i=22; i<84; i++) 411 for (j=0; j<=26; j++) 412 if (i==iven[j]) 413 switch(i) 414 { 415 case OBOOK: case OSCROLL: show3(j); 416 }; 417 more(); nosignal=sigsav; t_endup(count); 418 } 419 420 /* 421 * function to show the things player can eat only 422 */ 423 static void 424 showeat(void) 425 { 426 int i,j,sigsav,count; 427 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ 428 srcount=0; 429 430 for (count=2,j=0; j<=26; j++) 431 switch(iven[j]) 432 { 433 case OCOOKIE: count++; 434 }; 435 t_setup(count); 436 437 for (i=22; i<84; i++) 438 for (j=0; j<=26; j++) 439 if (i==iven[j]) 440 switch(i) 441 { 442 case OCOOKIE: show3(j); 443 }; 444 more(); nosignal=sigsav; t_endup(count); 445 } 446 447 /* 448 function to show the things player can quaff only 449 */ 450 static void 451 showquaff(void) 452 { 453 int i,j,sigsav,count; 454 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ 455 srcount=0; 456 457 for (count=2,j=0; j<=26; j++) 458 switch(iven[j]) 459 { 460 case OPOTION: count++; 461 }; 462 t_setup(count); 463 464 for (i=22; i<84; i++) 465 for (j=0; j<=26; j++) 466 if (i==iven[j]) 467 switch(i) 468 { 469 case OPOTION: show3(j); 470 }; 471 more(); nosignal=sigsav; t_endup(count); 472 } 473 474 static void 475 show1(int idx, const char *str2[]) 476 { 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]]); 480 } 481 482 void 483 show3(int idx) 484 { 485 switch(iven[idx]) 486 { 487 case OPOTION: show1(idx,potionname); break; 488 case OSCROLL: show1(idx,scrollname); break; 489 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; 494 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; 499 } 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(); } 503 } 504 505 /* 506 subroutine to randomly create monsters if needed 507 */ 508 static void 509 randmonst(void) 510 { 511 if (c[TIMESTOP]) return; /* don't make monsters if time is stopped */ 512 if (--rmst <= 0) 513 { 514 rmst = 120 - (level<<2); fillmonst(makemonst(level)); 515 } 516 } 517 518 519 /* 520 parse() 521 522 get and execute a command 523 */ 524 static void 525 parse(void) 526 { 527 int i,j,k,flag; 528 while (1) 529 { 530 k = yylex(); 531 switch(k) /* get the token from the input and switch on it */ 532 { 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 */ 549 550 case '.': if (yrepcount) viewflag=1; return; /* stay here */ 551 552 case 'w': yrepcount=0; wield(); return; /* wield a weapon */ 553 554 case 'W': yrepcount=0; wear(); return; /* wear armor */ 555 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 */ 559 560 case 'q': yrepcount=0; if (c[TIMESTOP]==0) quaff(); return; /* quaff a potion */ 561 562 case 'd': yrepcount=0; if (c[TIMESTOP]==0) dropobj(); return; /* to drop an object */ 563 564 case 'c': yrepcount=0; cast(); return; /* cast a spell */ 565 566 case 'i': yrepcount=0; nomove=1; showstr(); return; /* status */ 567 568 case 'e': yrepcount=0; 569 if (c[TIMESTOP]==0) eatcookie(); return; /* to eat a fortune cookie */ 570 571 case 'D': yrepcount=0; seemagic(0); nomove=1; return; /* list spells and scrolls */ 572 573 case '?': yrepcount=0; help(); nomove=1; return; /* give the help screen*/ 574 575 case 'S': clear(); lprcat("Saving . . ."); lflush(); 576 savegame(savefilename); wizard=1; died(-257); /* save the game - doesn't return */ 577 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 */ 581 582 case '^': /* identify traps */ flag=yrepcount=0; cursors(); 583 lprc('\n'); for (j=playery-1; j<playery+2; j++) 584 { 585 if (j < 0) j=0; if (j >= MAXY) break; 586 for (i=playerx-1; i<playerx+2; i++) 587 { 588 if (i < 0) i=0; if (i >= MAXX) break; 589 switch(item[i][j]) 590 { 591 case OTRAPDOOR: case ODARTRAP: 592 case OTRAPARROW: case OTELEPORTER: 593 lprcat("\nIts "); lprcat(objectname[(int)item[i][j]]); flag++; 594 }; 595 } 596 } 597 if (flag==0) lprcat("\nNo traps are visible"); 598 return; 599 600 #if WIZID 601 case '_': /* this is the fudge player password for wizard mode*/ 602 yrepcount=0; cursors(); nomove=1; 603 if (userid!=wisid) 604 { 605 lprcat("Sorry, you are not empowered to be a wizard.\n"); 606 scbr(); /* system("stty -echo cbreak"); */ 607 lflush(); return; 608 } 609 if (getpassword()==0) 610 { 611 scbr(); /* system("stty -echo cbreak"); */ return; 612 } 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; 618 { 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]; 625 } 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 640 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; 645 646 case 'g': cursors(); 647 lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long)packweight()); 648 case ' ': yrepcount=0; nomove=1; return; 649 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; 656 657 case 'Q': yrepcount=0; quit(); nomove=1; return; /* quit */ 658 659 case 'L'-64: yrepcount=0; drawscreen(); nomove=1; return; /* look */ 660 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; 673 }; 674 } 675 } 676 677 void 678 parse2(void) 679 { 680 if (c[HASTEMONST]) movemonst(); movemonst(); /* move the monsters */ 681 randmonst(); regen(); 682 } 683 684 static void 685 run(int dir) 686 { 687 int i; 688 i=1; while (i) 689 { 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); 694 } 695 } 696 697 /* 698 function to wield a weapon 699 */ 700 static void 701 wield(void) 702 { 703 int i; 704 while (1) 705 { 706 if ((i = whatitem("wield"))=='\33') return; 707 if (i != '.') 708 { 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; } 715 } 716 } 717 } 718 719 /* 720 common routine to say you don't have an item 721 */ 722 static void 723 ydhi(int x) 724 { cursors(); lprintf("\nYou don't have item %c!",x); } 725 726 static void 727 ycwi(int x) 728 { cursors(); lprintf("\nYou can't wield item %c!",x); } 729 730 /* 731 function to wear armor 732 */ 733 static void 734 wear(void) 735 { 736 int i; 737 while (1) 738 { 739 if ((i = whatitem("wear"))=='\33') return; 740 if (i != '.') 741 { 742 if (i=='*') showwear(); else 743 switch(iven[i-'a']) 744 { 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!"); 754 }; 755 } 756 } 757 } 758 759 /* 760 function to drop an object 761 */ 762 static void 763 dropobj(void) 764 { 765 int i; 766 char *p; 767 long amt; 768 p = &item[playerx][playery]; 769 while (1) 770 { 771 if ((i = whatitem("drop"))=='\33') return; 772 if (i=='*') showstr(); else 773 { 774 if (i=='.') /* drop some gold */ 775 { 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; 797 } 798 drop_object(i-'a'); 799 return; 800 } 801 } 802 } 803 804 /* 805 * readscr() Subroutine to read a scroll one is carrying 806 */ 807 static void 808 readscr(void) 809 { 810 int i; 811 while (1) 812 { 813 if ((i = whatitem("read"))=='\33') return; 814 if (i != '.') 815 { 816 if (i=='*') showread(); else 817 { 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; 822 } 823 } 824 } 825 } 826 827 /* 828 * subroutine to eat a cookie one is carrying 829 */ 830 static void 831 eatcookie(void) 832 { 833 int i; 834 const char *p; 835 while (1) 836 { 837 if ((i = whatitem("eat"))=='\33') return; 838 if (i != '.') { 839 if (i=='*') showeat(); else 840 { 841 if (iven[i-'a']==OCOOKIE) 842 { 843 lprcat("\nThe cookie was delicious."); 844 iven[i-'a']=0; 845 if (!c[BLINDCOUNT]) 846 { 847 if ((p=fortune())) 848 { 849 lprcat(" Inside you find a scrap of paper that says:\n"); 850 lprcat(p); 851 } 852 } 853 return; 854 } 855 if (iven[i-'a']==0) { ydhi(i); return; } 856 lprcat("\nYou can't eat that!"); return; 857 } 858 } 859 } 860 } 861 862 /* 863 * subroutine to quaff a potion one is carrying 864 */ 865 static void 866 quaff(void) 867 { 868 int i; 869 while (1) 870 { 871 if ((i = whatitem("quaff"))=='\33') return; 872 if (i != '.') 873 { 874 if (i=='*') showquaff(); else 875 { 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; 879 } 880 } 881 } 882 } 883 884 /* 885 function to ask what player wants to do 886 */ 887 static int 888 whatitem(const char *str) 889 { 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); 895 } 896 897 /* 898 subroutine to get a number from the player 899 and allow * to mean return amt, else return the number entered 900 */ 901 unsigned long 902 readnum(long mx) 903 { 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') 910 { 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(); 915 } 916 scbr(); return(amt); 917 } 918 919 #ifdef HIDEBYLINK 920 /* 921 * routine to zero every byte in a string 922 */ 923 static void 924 szero(char *str) 925 { 926 while (*str) 927 *str++ = 0; 928 } 929 #endif /* HIDEBYLINK */ 930