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