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