1 /* $FreeBSD: src/games/larn/main.c,v 1.9 1999/11/30 03:48:59 billf Exp $ */ 2 /* $DragonFly: src/games/larn/main.c,v 1.5 2008/06/05 18:06:30 swildner Exp $ */ 3 /* main.c */ 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 /* try to get login name */ 85 if (((ptr = getlogin()) == 0) || (*ptr == 0)) { 86 /* can we get it from /etc/passwd? */ 87 if ((pwe = getpwuid(getuid())) != NULL) 88 ptr = pwe->pw_name; 89 else if ((ptr = getenv("USER")) == 0) 90 if ((ptr = getenv("LOGNAME")) == 0) { 91 noone: write(2, "Can't find your logname. Who Are You?\n", 39); 92 exit(1); 93 } 94 } 95 if (ptr == 0) 96 goto noone; 97 if (strlen(ptr) == 0) 98 goto noone; 99 100 /* 101 * second task is to prepare the pathnames the player will need 102 */ 103 strcpy(loginname, ptr); /* save loginname of the user for logging purposes */ 104 strcpy(logname, ptr); /* this will be overwritten with the players name */ 105 if ((ptr = getenv("HOME")) == 0) 106 ptr = "."; 107 strcpy(savefilename, ptr); 108 strcat(savefilename, "/Larn.sav"); /* save file name in home directory */ 109 sprintf(optsfile, "%s/.larnopts", ptr); /* the .larnopts filename */ 110 111 /* 112 * now malloc the memory for the dungeon 113 */ 114 cell = malloc(sizeof(struct cel) * (MAXLEVEL + MAXVLEVEL) * MAXX * MAXY); 115 if (cell == NULL) /* malloc failure */ 116 died(-285); 117 lpbuf = malloc((5 * BUFBIG) >> 2); /* output buffer */ 118 inbuffer = malloc((5 * MAXIBUF) >> 2); /* output buffer */ 119 if ((lpbuf == NULL) || (inbuffer == NULL)) /* malloc() failure */ 120 died(-285); 121 122 lcreat(NULL); 123 newgame(); /* set the initial clock */ 124 hard = -1; 125 126 #ifdef VT100 127 /* 128 * check terminal type to avoid users who have not vt100 type terminals 129 */ 130 ttype = getenv("TERM"); 131 for (j = 1, i = 0; i < sizeof(termtypes) / sizeof(char *); i++) 132 if (strcmp(ttype, termtypes[i]) == 0) { 133 j = 0; 134 break; 135 } 136 if (j) { 137 lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); 138 lflush(); 139 exit(1); 140 } 141 #endif /* VT100 */ 142 143 /* 144 * now make scoreboard if it is not there (don't clear) 145 */ 146 if (stat(scorefile, &sb) < 0 || sb.st_size == 0) /* not there */ 147 makeboard(); 148 149 /* 150 * now process the command line arguments 151 */ 152 for (i = 1; i < argc; i++) { 153 if (argv[i][0] == '-') 154 switch (argv[i][1]) { 155 case 's': 156 showscores(); 157 exit(0); /* show scoreboard */ 158 159 case 'l': /* show log file */ 160 diedlog(); 161 exit(0); 162 163 case 'i': 164 showallscores(); 165 exit(0); /* show all scoreboard */ 166 167 case 'c': /* anyone with password can create scoreboard */ 168 lprcat("Preparing to initialize the scoreboard.\n"); 169 if (getpassword() != 0) { /* make new scoreboard */ 170 makeboard(); 171 lprc('\n'); 172 showscores(); 173 } 174 exit(0); 175 176 case 'n': /* no welcome msg */ 177 nowelcome = 1; 178 argv[i][0] = 0; 179 break; 180 181 case '0': 182 case '1': 183 case '2': 184 case '3': 185 case '4': 186 case '5': 187 case '6': 188 case '7': 189 case '8': 190 case '9': /* for hardness */ 191 sscanf(&argv[i][1], "%d", &hard); 192 break; 193 194 case 'h': /* print out command line arguments */ 195 write(1, cmdhelp, sizeof(cmdhelp)); 196 exit(0); 197 198 case 'o': /* specify a .larnopts filename */ 199 strncpy(optsfile, argv[i] + 2, 127); 200 break; 201 202 default: 203 printf("Unknown option <%s>\n", argv[i]); 204 exit(1); 205 } 206 207 if (argv[i][0] == '+') { 208 clear(); 209 restorflag = 1; 210 if (argv[i][1] == '+') { 211 hitflag = 1; 212 restoregame(ckpfile); /* restore checkpointed game */ 213 } 214 i = argc; 215 } 216 } 217 218 readopts(); /* read the options file if there is one */ 219 220 221 #ifdef UIDSCORE 222 userid = geteuid(); /* obtain the user's effective id number */ 223 #else /* UIDSCORE */ 224 userid = getplid(logname); /* obtain the players id number */ 225 #endif /* UIDSCORE */ 226 if (userid < 0) { 227 write(2, "Can't obtain playerid\n", 22); 228 exit(1); 229 } 230 231 #ifdef HIDEBYLINK 232 /* 233 * this section of code causes the program to look like something else to ps 234 */ 235 if (strcmp(psname, argv[0])) { /* if a different process name only */ 236 if ((i = access(psname, 1)) < 0) { /* link not there */ 237 if (link(argv[0], psname) >= 0) { 238 argv[0] = psname; 239 execv(psname, argv); 240 } 241 } else 242 unlink(psname); 243 } 244 245 for (i = 1; i < argc; i++) { 246 szero(argv[i]); /* zero the argument to avoid ps snooping */ 247 } 248 #endif /* HIDEBYLINK */ 249 250 if (access(savefilename, 0) == 0) { /* restore game if need to */ 251 clear(); 252 restorflag = 1; 253 hitflag = 1; 254 restoregame(savefilename); /* restore last game */ 255 } 256 sigsetup(); /* trap all needed signals */ 257 sethard(hard); /* set up the desired difficulty */ 258 setupvt100(); /* setup the terminal special mode */ 259 if (c[HP] == 0) { /* create new game */ 260 makeplayer(); /* make the character that will play */ 261 newcavelevel(0);/* make the dungeon */ 262 predostuff = 1; /* tell signals that we are in the welcome screen */ 263 if (nowelcome == 0) 264 welcome(); /* welcome the player to the game */ 265 } 266 drawscreen(); /* show the initial dungeon */ 267 predostuff = 2; /* tell the trap functions that they must do 268 * a showplayer() from here on */ 269 #if 0 270 nice(1); /* games should be run niced */ 271 #endif 272 yrepcount = hit2flag = 0; 273 while (1) { 274 if (dropflag == 0) /* see if there is an object here */ 275 lookforobject(); 276 else /* don't show it just dropped an item */ 277 dropflag = 0; 278 if (hitflag == 0) { 279 if (c[HASTEMONST]) 280 movemonst(); 281 movemonst(); 282 } /* move the monsters */ 283 if (viewflag == 0) 284 showcell(playerx, playery); 285 else 286 viewflag = 0; /* show stuff around player */ 287 if (hit3flag) 288 flushall(); 289 hitflag = hit3flag = 0; 290 nomove = 1; 291 bot_linex(); /* update bottom line */ 292 while (nomove) { 293 if (hit3flag) 294 flushall(); 295 nomove = 0; 296 parse(); 297 } /* get commands and make moves */ 298 regen(); /* regenerate hp and spells */ 299 if (c[TIMESTOP] == 0) 300 if (--rmst <= 0) { 301 rmst = 120 - (level << 2); 302 fillmonst(makemonst(level)); 303 } 304 } 305 } 306 307 /* 308 showstr() 309 310 show character's inventory 311 */ 312 static void 313 showstr(void) 314 { 315 int i, number; 316 for (number = 3, i = 0; i < 26; i++) 317 if (iven[i]) /* count items in inventory */ 318 number++; 319 t_setup(number); 320 qshowstr(); 321 t_endup(number); 322 } 323 324 void 325 qshowstr(void) 326 { 327 int i, j, k, sigsav; 328 srcount = 0; 329 sigsav = nosignal; 330 nosignal = 1; /* don't allow ^c etc */ 331 if (c[GOLD]) { 332 lprintf(".) %d gold pieces", (long)c[GOLD]); 333 srcount++; 334 } 335 for (k = 26; k >= 0; k--) 336 if (iven[k]) { 337 for (i = 22; i < 84; i++) 338 for (j = 0; j <= k; j++) 339 if (i == iven[j]) 340 show3(j); 341 k = 0; 342 } 343 344 lprintf("\nElapsed time is %d. You have %d mobuls left", (long)((gtime + 99) / 100 + 1), (long)((TIMELIMIT - gtime) / 100)); 345 more(); 346 nosignal = sigsav; 347 } 348 349 /* 350 * subroutine to clear screen depending on # lines to display 351 */ 352 static void 353 t_setup(int count) 354 { 355 if (count < 20) { /* how do we clear the screen? */ 356 cl_up(79, count); 357 cursor(1, 1); 358 } else { 359 resetscroll(); 360 clear(); 361 } 362 } 363 364 /* 365 * subroutine to restore normal display screen depending on t_setup() 366 */ 367 static void 368 t_endup(int count) 369 { 370 if (count < 18) /* how did we clear the screen? */ 371 draws(0, MAXX, 0, (count > MAXY) ? MAXY : count); 372 else { 373 drawscreen(); 374 setscroll(); 375 } 376 } 377 378 /* 379 function to show the things player is wearing only 380 */ 381 static void 382 showwear(void) 383 { 384 int i, j, sigsav, count; 385 sigsav = nosignal; 386 nosignal = 1; /* don't allow ^c etc */ 387 srcount = 0; 388 389 for (count = 2, j = 0; j <= 26; j++) /* count number of items we will display */ 390 if ((i = iven[j]) != 0) 391 switch (i) { 392 case OLEATHER: 393 case OPLATE: 394 case OCHAIN: 395 case ORING: 396 case OSTUDLEATHER: 397 case OSPLINT: 398 case OPLATEARMOR: 399 case OSSPLATE: 400 case OSHIELD: 401 count++; 402 } 403 404 t_setup(count); 405 406 for (i = 22; i < 84; i++) 407 for (j = 0; j <= 26; j++) 408 if (i == iven[j]) 409 switch (i) { 410 case OLEATHER: 411 case OPLATE: 412 case OCHAIN: 413 case ORING: 414 case OSTUDLEATHER: 415 case OSPLINT: 416 case OPLATEARMOR: 417 case OSSPLATE: 418 case OSHIELD: 419 show3(j); 420 } 421 more(); 422 nosignal = sigsav; 423 t_endup(count); 424 } 425 426 /* 427 function to show the things player can wield only 428 */ 429 static void 430 showwield(void) 431 { 432 int i, j, sigsav, count; 433 sigsav = nosignal; 434 nosignal = 1; /* don't allow ^c etc */ 435 srcount = 0; 436 437 for (count = 2, j = 0; j <= 26; j++) /* count how many items */ 438 if ((i = iven[j]) != 0) 439 switch (i) { 440 case ODIAMOND: 441 case ORUBY: 442 case OEMERALD: 443 case OSAPPHIRE: 444 case OBOOK: 445 case OCHEST: 446 case OLARNEYE: 447 case ONOTHEFT: 448 case OSPIRITSCARAB: 449 case OCUBEofUNDEAD: 450 case OPOTION: 451 case OSCROLL: 452 break; 453 default: 454 count++; 455 } 456 457 t_setup(count); 458 459 for (i = 22; i < 84; i++) 460 for (j = 0; j <= 26; j++) 461 if (i == iven[j]) 462 switch (i) { 463 case ODIAMOND: 464 case ORUBY: 465 case OEMERALD: 466 case OSAPPHIRE: 467 case OBOOK: 468 case OCHEST: 469 case OLARNEYE: 470 case ONOTHEFT: 471 case OSPIRITSCARAB: 472 case OCUBEofUNDEAD: 473 case OPOTION: 474 case OSCROLL: 475 break; 476 default: 477 show3(j); 478 } 479 more(); 480 nosignal = sigsav; 481 t_endup(count); 482 } 483 484 /* 485 * function to show the things player can read only 486 */ 487 static void 488 showread(void) 489 { 490 int i, j, sigsav, count; 491 sigsav = nosignal; 492 nosignal = 1; /* don't allow ^c etc */ 493 srcount = 0; 494 495 for (count = 2, j = 0; j <= 26; j++) 496 switch (iven[j]) { 497 case OBOOK: 498 case OSCROLL: 499 count++; 500 } 501 t_setup(count); 502 503 for (i = 22; i < 84; i++) 504 for (j = 0; j <= 26; j++) 505 if (i == iven[j]) 506 switch (i) { 507 case OBOOK: 508 case OSCROLL: 509 show3(j); 510 } 511 more(); 512 nosignal = sigsav; 513 t_endup(count); 514 } 515 516 /* 517 * function to show the things player can eat only 518 */ 519 static void 520 showeat(void) 521 { 522 int i, j, sigsav, count; 523 sigsav = nosignal; 524 nosignal = 1; /* don't allow ^c etc */ 525 srcount = 0; 526 527 for (count = 2, j = 0; j <= 26; j++) 528 switch (iven[j]) { 529 case OCOOKIE: 530 count++; 531 } 532 t_setup(count); 533 534 for (i = 22; i < 84; i++) 535 for (j = 0; j <= 26; j++) 536 if (i == iven[j]) 537 switch (i) { 538 case OCOOKIE: 539 show3(j); 540 } 541 more(); 542 nosignal = sigsav; 543 t_endup(count); 544 } 545 546 /* 547 function to show the things player can quaff only 548 */ 549 static void 550 showquaff(void) 551 { 552 int i, j, sigsav, count; 553 sigsav = nosignal; 554 nosignal = 1; /* don't allow ^c etc */ 555 srcount = 0; 556 557 for (count = 2, j = 0; j <= 26; j++) 558 switch (iven[j]) { 559 case OPOTION: 560 count++; 561 } 562 t_setup(count); 563 564 for (i = 22; i < 84; i++) 565 for (j = 0; j <= 26; j++) 566 if (i == iven[j]) 567 switch (i) { 568 case OPOTION: 569 show3(j); 570 } 571 more(); 572 nosignal = sigsav; 573 t_endup(count); 574 } 575 576 static void 577 show1(int idx, const char *str2[]) 578 { 579 lprintf("\n%c) %s", idx + 'a', objectname[(int)iven[idx]]); 580 if (str2 != NULL && str2[ivenarg[idx]][0] != 0) 581 lprintf(" of%s", str2[ivenarg[idx]]); 582 } 583 584 void 585 show3(int idx) 586 { 587 switch (iven[idx]) { 588 case OPOTION: 589 show1(idx, potionname); 590 break; 591 case OSCROLL: 592 show1(idx, scrollname); 593 break; 594 595 case OLARNEYE: 596 case OBOOK: 597 case OSPIRITSCARAB: 598 case ODIAMOND: 599 case ORUBY: 600 case OCUBEofUNDEAD: 601 case OEMERALD: 602 case OCHEST: 603 case OCOOKIE: 604 case OSAPPHIRE: 605 case ONOTHEFT: 606 show1(idx, NULL); 607 break; 608 609 default: 610 lprintf("\n%c) %s", idx + 'a', objectname[(int)iven[idx]]); 611 if (ivenarg[idx] > 0) 612 lprintf(" + %d", (long)ivenarg[idx]); 613 else if (ivenarg[idx] < 0) 614 lprintf(" %d", (long)ivenarg[idx]); 615 break; 616 } 617 if (c[WIELD] == idx) 618 lprcat(" (weapon in hand)"); 619 if ((c[WEAR] == idx) || (c[SHIELD] == idx)) 620 lprcat(" (being worn)"); 621 if (++srcount >= 22) { 622 srcount = 0; 623 more(); 624 clear(); 625 } 626 } 627 628 /* 629 subroutine to randomly create monsters if needed 630 */ 631 static void 632 randmonst(void) 633 { 634 if (c[TIMESTOP]) /* don't make monsters if time is stopped */ 635 return; 636 if (--rmst <= 0) { 637 rmst = 120 - (level << 2); 638 fillmonst(makemonst(level)); 639 } 640 } 641 642 /* 643 parse() 644 645 get and execute a command 646 */ 647 static void 648 parse(void) 649 { 650 int i, j, k, flag; 651 while (1) { 652 k = yylex(); 653 switch (k) { /* get the token from the input and switch on it */ 654 case 'h': 655 moveplayer(4); 656 return; /* west */ 657 case 'H': 658 run(4); 659 return; /* west */ 660 case 'l': 661 moveplayer(2); 662 return; /* east */ 663 case 'L': 664 run(2); 665 return; /* east */ 666 case 'j': 667 moveplayer(1); 668 return; /* south */ 669 case 'J': 670 run(1); 671 return; /* south */ 672 case 'k': 673 moveplayer(3); 674 return; /* north */ 675 case 'K': 676 run(3); 677 return; /* north */ 678 case 'u': 679 moveplayer(5); 680 return; /* northeast */ 681 case 'U': 682 run(5); 683 return; /* northeast */ 684 case 'y': 685 moveplayer(6); 686 return; /* northwest */ 687 case 'Y': 688 run(6); 689 return; /* northwest */ 690 case 'n': 691 moveplayer(7); 692 return; /* southeast */ 693 case 'N': 694 run(7); 695 return; /* southeast */ 696 case 'b': 697 moveplayer(8); 698 return; /* southwest */ 699 case 'B': 700 run(8); 701 return; /* southwest */ 702 703 case '.': 704 if (yrepcount) 705 viewflag = 1; 706 return; /* stay here */ 707 708 case 'w': 709 yrepcount = 0; 710 wield(); 711 return; /* wield a weapon */ 712 713 case 'W': 714 yrepcount = 0; 715 wear(); 716 return; /* wear armor */ 717 718 case 'r': 719 yrepcount = 0; 720 if (c[BLINDCOUNT]) { 721 cursors(); 722 lprcat("\nYou can't read anything when you're blind!"); 723 } else if (c[TIMESTOP] == 0) 724 readscr(); 725 return; /* to read a scroll */ 726 727 case 'q': 728 yrepcount = 0; 729 if (c[TIMESTOP] == 0) 730 quaff(); 731 return; /* quaff a potion */ 732 733 case 'd': 734 yrepcount = 0; 735 if (c[TIMESTOP] == 0) 736 dropobj(); 737 return; /* to drop an object */ 738 739 case 'c': 740 yrepcount = 0; 741 cast(); 742 return; /* cast a spell */ 743 744 case 'i': 745 yrepcount = 0; 746 nomove = 1; 747 showstr(); 748 return; /* status */ 749 750 case 'e': 751 yrepcount = 0; 752 if (c[TIMESTOP] == 0) 753 eatcookie(); 754 return; /* to eat a fortune cookie */ 755 756 case 'D': 757 yrepcount = 0; 758 seemagic(0); 759 nomove = 1; 760 return; /* list spells and scrolls */ 761 762 case '?': 763 yrepcount = 0; 764 help(); 765 nomove = 1; 766 return; /* give the help screen */ 767 768 case 'S': 769 clear(); 770 lprcat("Saving . . ."); 771 lflush(); 772 savegame(savefilename); 773 wizard = 1; 774 died(-257); /* save the game - doesn't return */ 775 776 case 'Z': 777 yrepcount = 0; 778 if (c[LEVEL] > 9) { 779 oteleport(1); 780 return; 781 } 782 cursors(); 783 lprcat("\nAs yet, you don't have enough experience to use teleportation"); 784 return; /* teleport yourself */ 785 786 case '^': /* identify traps */ 787 flag = yrepcount = 0; 788 cursors(); 789 lprc('\n'); 790 for (j = playery - 1; j < playery + 2; j++) { 791 if (j < 0) 792 j = 0; 793 if (j >= MAXY) 794 break; 795 for (i = playerx - 1; i < playerx + 2; i++) { 796 if (i < 0) 797 i = 0; 798 if (i >= MAXX) 799 break; 800 switch (item[i][j]) { 801 case OTRAPDOOR: 802 case ODARTRAP: 803 case OTRAPARROW: 804 case OTELEPORTER: 805 lprcat("\nIts "); 806 lprcat(objectname[(int)item[i][j]]); 807 flag++; 808 } 809 } 810 } 811 if (flag == 0) 812 lprcat("\nNo traps are visible"); 813 return; 814 815 #if WIZID 816 case '_': /* this is the fudge player password for wizard mode */ 817 yrepcount = 0; 818 cursors(); 819 nomove = 1; 820 if (userid != wisid) { 821 lprcat("Sorry, you are not empowered to be a wizard.\n"); 822 scbr(); /* system("stty -echo cbreak"); */ 823 lflush(); 824 return; 825 } 826 if (getpassword() == 0) { 827 scbr(); /* system("stty -echo cbreak"); */ 828 return; 829 } 830 wizard = 1; 831 scbr(); /* system("stty -echo cbreak"); */ 832 for (i = 0; i < 6; i++) 833 c[i] = 70; 834 iven[0] = iven[1] = 0; 835 take(OPROTRING, 50); 836 take(OLANCE, 25); 837 c[WIELD] = 1; 838 c[LANCEDEATH] = 1; 839 c[WEAR] = c[SHIELD] = -1; 840 raiseexperience(6000000L); 841 c[AWARENESS] += 25000; 842 { 843 int i, j; 844 for (i = 0; i < MAXY; i++) 845 for (j = 0; j < MAXX; j++) 846 know[j][i] = 1; 847 for (i = 0; i < SPNUM; i++) 848 spelknow[i] = 1; 849 for (i = 0; i < MAXSCROLL; i++) 850 scrollname[i] = scrollhide[i]; 851 for (i = 0; i < MAXPOTION; i++) 852 potionname[i] = potionhide[i]; 853 } 854 for (i = 0; i < MAXSCROLL; i++) 855 if (strlen(scrollname[i]) > 2) { /* no null items */ 856 item[i][0] = OSCROLL; 857 iarg[i][0] = i; 858 } 859 for (i = MAXX - 1; i > MAXX - 1 - MAXPOTION; i--) 860 if (strlen(potionname[i - MAXX + MAXPOTION]) > 2) { /* no null items */ 861 item[i][0] = OPOTION; 862 iarg[i][0] = i - MAXX + MAXPOTION; 863 } 864 for (i = 1; i < MAXY; i++) { 865 item[0][i] = i; 866 iarg[0][i] = 0; 867 } 868 for (i = MAXY; i < MAXY + MAXX; i++) { 869 item[i - MAXY][MAXY - 1] = i; 870 iarg[i - MAXY][MAXY - 1] = 0; 871 } 872 for (i = MAXX + MAXY; i < MAXX + MAXY + MAXY; i++) { 873 item[MAXX - 1][i - MAXX - MAXY] = i; 874 iarg[MAXX - 1][i - MAXX - MAXY] = 0; 875 } 876 c[GOLD] += 25000; 877 drawscreen(); 878 return; 879 #endif 880 881 case 'T': 882 yrepcount = 0; 883 cursors(); 884 if (c[SHIELD] != -1) { 885 c[SHIELD] = -1; 886 lprcat("\nYour shield is off"); 887 bottomline(); 888 } else if (c[WEAR] != -1) { 889 c[WEAR] = -1; 890 lprcat("\nYour armor is off"); 891 bottomline(); 892 } else 893 lprcat("\nYou aren't wearing anything"); 894 return; 895 896 case 'g': 897 cursors(); 898 lprintf("\nThe stuff you are carrying presently weighs %d pounds", (long)packweight()); 899 case ' ': 900 yrepcount = 0; 901 nomove = 1; 902 return; 903 904 case 'v': 905 yrepcount = 0; 906 cursors(); 907 lprintf("\nCaverns of Larn, Version %d.%d, Diff=%d", (long)VERSION, (long)SUBVERSION, (long)c[HARDGAME]); 908 if (wizard) 909 lprcat(" Wizard"); 910 nomove = 1; 911 if (cheat) 912 lprcat(" Cheater"); 913 lprcat(copyright); 914 return; 915 916 case 'Q': 917 yrepcount = 0; 918 quit(); 919 nomove = 1; 920 return; /* quit */ 921 922 case 'L' - 64: 923 yrepcount = 0; 924 drawscreen(); 925 nomove = 1; 926 return; /* look */ 927 928 #if WIZID 929 #ifdef EXTRA 930 case 'A': 931 yrepcount = 0; 932 nomove = 1; 933 if (wizard) { 934 diag(); 935 return; 936 } /* create diagnostic file */ 937 return; 938 #endif 939 #endif 940 case 'P': 941 cursors(); 942 if (outstanding_taxes > 0) 943 lprintf("\nYou presently owe %d gp in taxes.", (long)outstanding_taxes); 944 else 945 lprcat("\nYou do not owe any taxes."); 946 return; 947 } 948 } 949 } 950 951 void 952 parse2(void) 953 { 954 if (c[HASTEMONST]) 955 movemonst(); 956 movemonst(); /* move the monsters */ 957 randmonst(); 958 regen(); 959 } 960 961 static void 962 run(int dir) 963 { 964 int i; 965 i = 1; 966 while (i) { 967 i = moveplayer(dir); 968 if (i > 0) { 969 if (c[HASTEMONST]) 970 movemonst(); 971 movemonst(); 972 randmonst(); 973 regen(); 974 } 975 if (hitflag) 976 i = 0; 977 if (i != 0) 978 showcell(playerx, playery); 979 } 980 } 981 982 /* 983 function to wield a weapon 984 */ 985 static void 986 wield(void) 987 { 988 int i; 989 while (1) { 990 if ((i = whatitem("wield")) == '\33') 991 return; 992 if (i != '.') { 993 if (i == '*') 994 showwield(); 995 else if (iven[i - 'a'] == 0) { 996 ydhi(i); 997 return; 998 } else if (iven[i - 'a'] == OPOTION) { 999 ycwi(i); 1000 return; 1001 } else if (iven[i - 'a'] == OSCROLL) { 1002 ycwi(i); 1003 return; 1004 } else if ((c[SHIELD] != -1) && (iven[i - 'a'] == O2SWORD)) { 1005 lprcat("\nBut one arm is busy with your shield!"); 1006 return; 1007 } else { 1008 c[WIELD] = i - 'a'; 1009 if (iven[i - 'a'] == OLANCE) 1010 c[LANCEDEATH] = 1; 1011 else 1012 c[LANCEDEATH] = 0; 1013 bottomline(); 1014 return; 1015 } 1016 } 1017 } 1018 } 1019 1020 /* 1021 common routine to say you don't have an item 1022 */ 1023 static void 1024 ydhi(int x) 1025 { 1026 cursors(); 1027 lprintf("\nYou don't have item %c!", x); 1028 } 1029 1030 static void 1031 ycwi(int x) 1032 { 1033 cursors(); 1034 lprintf("\nYou can't wield item %c!", x); 1035 } 1036 1037 /* 1038 function to wear armor 1039 */ 1040 static void 1041 wear(void) 1042 { 1043 int i; 1044 while (1) { 1045 if ((i = whatitem("wear")) == '\33') 1046 return; 1047 if (i != '.') { 1048 if (i == '*') 1049 showwear(); 1050 else 1051 switch (iven[i - 'a']) { 1052 case 0: 1053 ydhi(i); 1054 return; 1055 case OLEATHER: 1056 case OCHAIN: 1057 case OPLATE: 1058 case OSTUDLEATHER: 1059 case ORING: 1060 case OSPLINT: 1061 case OPLATEARMOR: 1062 case OSSPLATE: 1063 if (c[WEAR] != -1) { 1064 lprcat("\nYou're already wearing some armor"); 1065 return; 1066 } 1067 c[WEAR] = i - 'a'; 1068 bottomline(); 1069 return; 1070 case OSHIELD: 1071 if (c[SHIELD] != -1) { 1072 lprcat("\nYou are already wearing a shield"); 1073 return; 1074 } 1075 if (iven[c[WIELD]] == O2SWORD) { 1076 lprcat("\nYour hands are busy with the two handed sword!"); 1077 return; 1078 } 1079 c[SHIELD] = i - 'a'; 1080 bottomline(); 1081 return; 1082 default: 1083 lprcat("\nYou can't wear that!"); 1084 } 1085 } 1086 } 1087 } 1088 1089 /* 1090 function to drop an object 1091 */ 1092 static void 1093 dropobj(void) 1094 { 1095 int i; 1096 char *p; 1097 long amt; 1098 p = &item[playerx][playery]; 1099 while (1) { 1100 if ((i = whatitem("drop")) == '\33') 1101 return; 1102 if (i == '*') 1103 showstr(); 1104 else { 1105 if (i == '.') { /* drop some gold */ 1106 if (*p) { 1107 lprcat("\nThere's something here already!"); 1108 return; 1109 } 1110 lprcat("\n\n"); 1111 cl_dn(1, 23); 1112 lprcat("How much gold do you drop? "); 1113 if ((amt = readnum((long)c[GOLD])) == 0) 1114 return; 1115 if (amt > c[GOLD]) { 1116 lprcat("\nYou don't have that much!"); 1117 return; 1118 } 1119 if (amt <= 32767) { 1120 *p = OGOLDPILE; 1121 i = amt; 1122 } else if (amt <= 327670L) { 1123 *p = ODGOLD; 1124 i = amt / 10; 1125 amt = 10 * i; 1126 } else if (amt <= 3276700L) { 1127 *p = OMAXGOLD; 1128 i = amt / 100; 1129 amt = 100 * i; 1130 } else if (amt <= 32767000L) { 1131 *p = OKGOLD; 1132 i = amt / 1000; 1133 amt = 1000 * i; 1134 } else { 1135 *p = OKGOLD; 1136 i = 32767; 1137 amt = 32767000L; 1138 } 1139 c[GOLD] -= amt; 1140 lprintf("You drop %d gold pieces", (long)amt); 1141 iarg[playerx][playery] = i; 1142 bottomgold(); 1143 know[playerx][playery] = 0; 1144 dropflag = 1; 1145 return; 1146 } 1147 drop_object(i - 'a'); 1148 return; 1149 } 1150 } 1151 } 1152 1153 /* 1154 * readscr() Subroutine to read a scroll one is carrying 1155 */ 1156 static void 1157 readscr(void) 1158 { 1159 int i; 1160 while (1) { 1161 if ((i = whatitem("read")) == '\33') 1162 return; 1163 if (i != '.') { 1164 if (i == '*') 1165 showread(); 1166 else { 1167 if (iven[i - 'a'] == OSCROLL) { 1168 read_scroll(ivenarg[i - 'a']); 1169 iven[i - 'a'] = 0; 1170 return; 1171 } 1172 if (iven[i - 'a'] == OBOOK) { 1173 readbook(ivenarg[i - 'a']); 1174 iven[i - 'a'] = 0; 1175 return; 1176 } 1177 if (iven[i - 'a'] == 0) { 1178 ydhi(i); 1179 return; 1180 } 1181 lprcat("\nThere's nothing on it to read"); 1182 return; 1183 } 1184 } 1185 } 1186 } 1187 1188 /* 1189 * subroutine to eat a cookie one is carrying 1190 */ 1191 static void 1192 eatcookie(void) 1193 { 1194 int i; 1195 const char *p; 1196 1197 while (1) { 1198 if ((i = whatitem("eat")) == '\33') 1199 return; 1200 if (i != '.') { 1201 if (i == '*') 1202 showeat(); 1203 else { 1204 if (iven[i - 'a'] == OCOOKIE) { 1205 lprcat("\nThe cookie was delicious."); 1206 iven[i - 'a'] = 0; 1207 if (!c[BLINDCOUNT]) { 1208 if ((p = fortune()) != NULL) { 1209 lprcat(" Inside you find a scrap of paper that says:\n"); 1210 lprcat(p); 1211 } 1212 } 1213 return; 1214 } 1215 if (iven[i - 'a'] == 0) { 1216 ydhi(i); 1217 return; 1218 } 1219 lprcat("\nYou can't eat that!"); 1220 return; 1221 } 1222 } 1223 } 1224 } 1225 1226 /* 1227 * subroutine to quaff a potion one is carrying 1228 */ 1229 static void 1230 quaff(void) 1231 { 1232 int i; 1233 while (1) { 1234 if ((i = whatitem("quaff")) == '\33') 1235 return; 1236 if (i != '.') { 1237 if (i == '*') 1238 showquaff(); 1239 else { 1240 if (iven[i - 'a'] == OPOTION) { 1241 quaffpotion(ivenarg[i - 'a']); 1242 iven[i - 'a'] = 0; 1243 return; 1244 } 1245 if (iven[i - 'a'] == 0) { 1246 ydhi(i); 1247 return; 1248 } 1249 lprcat("\nYou wouldn't want to quaff that, would you? "); 1250 return; 1251 } 1252 } 1253 } 1254 } 1255 1256 /* 1257 function to ask what player wants to do 1258 */ 1259 static int 1260 whatitem(const char *str) 1261 { 1262 int i; 1263 cursors(); 1264 lprintf("\nWhat do you want to %s [* for all] ? ", str); 1265 i = 0; 1266 while (i > 'z' || (i < 'a' && i != '*' && i != '\33' && i != '.')) 1267 i = getchr(); 1268 if (i == '\33') 1269 lprcat(" aborted"); 1270 return (i); 1271 } 1272 1273 /* 1274 subroutine to get a number from the player 1275 and allow * to mean return amt, else return the number entered 1276 */ 1277 unsigned long 1278 readnum(long mx) 1279 { 1280 int i; 1281 unsigned long amt = 0; 1282 sncbr(); 1283 if ((i = getchr()) == '*') 1284 amt = mx; /* allow him to say * for all gold */ 1285 else 1286 while (i != '\n') { 1287 if (i == '\033') { 1288 scbr(); 1289 lprcat(" aborted"); 1290 return (0); 1291 } 1292 if ((i <= '9') && (i >= '0') && (amt < 99999999)) 1293 amt = amt * 10 + i - '0'; 1294 i = getchr(); 1295 } 1296 scbr(); 1297 return (amt); 1298 } 1299 1300 #ifdef HIDEBYLINK 1301 /* 1302 * routine to zero every byte in a string 1303 */ 1304 static void 1305 szero(char *str) 1306 { 1307 while (*str) 1308 *str++ = 0; 1309 } 1310 #endif /* HIDEBYLINK */ 1311