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