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