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