main.c revision 1.21
1/* $NetBSD: main.c,v 1.21 2008/02/03 03:45:55 dholland Exp $ */ 2 3/* main.c */ 4#include <sys/cdefs.h> 5#ifndef lint 6__RCSID("$NetBSD: main.c,v 1.21 2008/02/03 03:45:55 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 char copyright[] = "\nLarn is copyrighted 1986 by Noah Morgan.\n"; 19int srcount = 0; /* line counter for showstr() */ 20int dropflag = 0; /* if 1 then don't lookforobject() next round */ 21int rmst = 80; /* random monster creation counter */ 22int userid; /* the players login user id number */ 23gid_t gid, egid; /* used for security */ 24u_char nowelcome = 0, nomove = 0; /* if (nomove) then don't 25 * count next iteration as a 26 * move */ 27static 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 */ 32u_char restorflag = 0; /* 1 means restore has been done */ 33static char cmdhelp[] = "\ 34Cmd 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 46static 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 */ 55int 56main(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 egid = getegid(); 67 gid = getgid(); 68 setegid(gid); /* 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 its 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 */ 310void 311showstr() 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 322void 323qshowstr() 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(".) %ld 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 %ld. You have %ld 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 */ 349void 350t_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 */ 365void 366t_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 */ 380void 381showwear() 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 */ 429void 430showwield() 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 */ 487void 488showread() 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 */ 519void 520showeat() 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 */ 549void 550showquaff() 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 576void 577show1(idx, str2) 578 int idx; 579 const 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 586void 587show3(int indx) 588{ 589 switch (iven[indx]) { 590 case OPOTION: 591 show1(indx, potionname); 592 break; 593 case OSCROLL: 594 show1(indx, scrollname); 595 break; 596 597 case OLARNEYE: 598 case OBOOK: 599 case OSPIRITSCARAB: 600 case ODIAMOND: 601 case ORUBY: 602 case OCUBEofUNDEAD: 603 case OEMERALD: 604 case OCHEST: 605 case OCOOKIE: 606 case OSAPPHIRE: 607 case ONOTHEFT: 608 show1(indx, NULL); 609 break; 610 611 default: 612 lprintf("\n%c) %s", indx + 'a', objectname[iven[indx]]); 613 if (ivenarg[indx] > 0) 614 lprintf(" + %ld", (long) ivenarg[indx]); 615 else if (ivenarg[indx] < 0) 616 lprintf(" %ld", (long) ivenarg[indx]); 617 break; 618 } 619 if (c[WIELD] == indx) 620 lprcat(" (weapon in hand)"); 621 if ((c[WEAR] == indx) || (c[SHIELD] == indx)) 622 lprcat(" (being worn)"); 623 if (++srcount >= 22) { 624 srcount = 0; 625 more(); 626 clear(); 627 } 628} 629 630/* 631 subroutine to randomly create monsters if needed 632 */ 633void 634randmonst() 635{ 636 if (c[TIMESTOP]) 637 return; /* don't make monsters if time is stopped */ 638 if (--rmst <= 0) { 639 rmst = 120 - (level << 2); 640 fillmonst(makemonst(level)); 641 } 642} 643 644 645 646/* 647 parse() 648 649 get and execute a command 650 */ 651void 652parse() 653{ 654 int i, j, k, flag; 655 while (1) { 656 k = yylex(); 657 switch (k) { /* get the token from the input and switch on 658 * it */ 659 case 'h': 660 moveplayer(4); 661 return; /* west */ 662 case 'H': 663 run(4); 664 return; /* west */ 665 case 'l': 666 moveplayer(2); 667 return; /* east */ 668 case 'L': 669 run(2); 670 return; /* east */ 671 case 'j': 672 moveplayer(1); 673 return; /* south */ 674 case 'J': 675 run(1); 676 return; /* south */ 677 case 'k': 678 moveplayer(3); 679 return; /* north */ 680 case 'K': 681 run(3); 682 return; /* north */ 683 case 'u': 684 moveplayer(5); 685 return; /* northeast */ 686 case 'U': 687 run(5); 688 return; /* northeast */ 689 case 'y': 690 moveplayer(6); 691 return; /* northwest */ 692 case 'Y': 693 run(6); 694 return; /* northwest */ 695 case 'n': 696 moveplayer(7); 697 return; /* southeast */ 698 case 'N': 699 run(7); 700 return; /* southeast */ 701 case 'b': 702 moveplayer(8); 703 return; /* southwest */ 704 case 'B': 705 run(8); 706 return; /* southwest */ 707 708 case '.': 709 if (yrepcount) 710 viewflag = 1; 711 return; /* stay here */ 712 713 case 'w': 714 yrepcount = 0; 715 wield(); 716 return; /* wield a weapon */ 717 718 case 'W': 719 yrepcount = 0; 720 wear(); 721 return; /* wear armor */ 722 723 case 'r': 724 yrepcount = 0; 725 if (c[BLINDCOUNT]) { 726 cursors(); 727 lprcat("\nYou can't read anything when you're blind!"); 728 } else if (c[TIMESTOP] == 0) 729 readscr(); 730 return; /* to read a scroll */ 731 732 case 'q': 733 yrepcount = 0; 734 if (c[TIMESTOP] == 0) 735 quaff(); 736 return; /* quaff a potion */ 737 738 case 'd': 739 yrepcount = 0; 740 if (c[TIMESTOP] == 0) 741 dropobj(); 742 return; /* to drop an object */ 743 744 case 'c': 745 yrepcount = 0; 746 cast(); 747 return; /* cast a spell */ 748 749 case 'i': 750 yrepcount = 0; 751 nomove = 1; 752 showstr(); 753 return; /* status */ 754 755 case 'e': 756 yrepcount = 0; 757 if (c[TIMESTOP] == 0) 758 eatcookie(); 759 return; /* to eat a fortune cookie */ 760 761 case 'D': 762 yrepcount = 0; 763 seemagic(0); 764 nomove = 1; 765 return; /* list spells and scrolls */ 766 767 case '?': 768 yrepcount = 0; 769 help(); 770 nomove = 1; 771 return; /* give the help screen */ 772 773 case 'S': 774 clear(); 775 lprcat("Saving . . ."); 776 lflush(); 777 savegame(savefilename); 778 wizard = 1; 779 died(-257); /* save the game - doesn't return */ 780 781 case 'Z': 782 yrepcount = 0; 783 if (c[LEVEL] > 9) { 784 oteleport(1); 785 return; 786 } 787 cursors(); 788 lprcat("\nAs yet, you don't have enough experience to use teleportation"); 789 return; /* teleport yourself */ 790 791 case '^': /* identify traps */ 792 flag = yrepcount = 0; 793 cursors(); 794 lprc('\n'); 795 for (j = playery - 1; j < playery + 2; j++) { 796 if (j < 0) 797 j = 0; 798 if (j >= MAXY) 799 break; 800 for (i = playerx - 1; i < playerx + 2; i++) { 801 if (i < 0) 802 i = 0; 803 if (i >= MAXX) 804 break; 805 switch (item[i][j]) { 806 case OTRAPDOOR: 807 case ODARTRAP: 808 case OTRAPARROW: 809 case OTELEPORTER: 810 lprcat("\nIt's "); 811 lprcat(objectname[item[i][j]]); 812 flag++; 813 }; 814 } 815 } 816 if (flag == 0) 817 lprcat("\nNo traps are visible"); 818 return; 819 820#if WIZID 821 case '_': /* this is the fudge player password for 822 * wizard mode */ 823 yrepcount = 0; 824 cursors(); 825 nomove = 1; 826 if (userid != wisid) { 827 lprcat("Sorry, you are not empowered to be a wizard.\n"); 828 scbr(); /* system("stty -echo cbreak"); */ 829 lflush(); 830 return; 831 } 832 if (getpassword() == 0) { 833 scbr(); /* system("stty -echo cbreak"); */ 834 return; 835 } 836 wizard = 1; 837 scbr(); /* system("stty -echo cbreak"); */ 838 for (i = 0; i < 6; i++) 839 c[i] = 70; 840 iven[0] = iven[1] = 0; 841 take(OPROTRING, 50); 842 take(OLANCE, 25); 843 c[WIELD] = 1; 844 c[LANCEDEATH] = 1; 845 c[WEAR] = c[SHIELD] = -1; 846 raiseexperience(6000000L); 847 c[AWARENESS] += 25000; 848 { 849 int i, j; 850 for (i = 0; i < MAXY; i++) 851 for (j = 0; j < MAXX; j++) 852 know[j][i] = 1; 853 for (i = 0; i < SPNUM; i++) 854 spelknow[i] = 1; 855 for (i = 0; i < MAXSCROLL; i++) 856 scrollname[i] = scrollhide[i]; 857 for (i = 0; i < MAXPOTION; i++) 858 potionname[i] = potionhide[i]; 859 } 860 for (i = 0; i < MAXSCROLL; i++) 861 if (strlen(scrollname[i]) > 2) { /* no null items */ 862 item[i][0] = OSCROLL; 863 iarg[i][0] = i; 864 } 865 for (i = MAXX - 1; i > MAXX - 1 - MAXPOTION; i--) 866 if (strlen(potionname[i - MAXX + MAXPOTION]) > 2) { /* no null items */ 867 item[i][0] = OPOTION; 868 iarg[i][0] = i - MAXX + MAXPOTION; 869 } 870 for (i = 1; i < MAXY; i++) { 871 item[0][i] = i; 872 iarg[0][i] = 0; 873 } 874 for (i = MAXY; i < MAXY + MAXX; i++) { 875 item[i - MAXY][MAXY - 1] = i; 876 iarg[i - MAXY][MAXY - 1] = 0; 877 } 878 for (i = MAXX + MAXY; i < MAXX + MAXY + MAXY; i++) { 879 item[MAXX - 1][i - MAXX - MAXY] = i; 880 iarg[MAXX - 1][i - MAXX - MAXY] = 0; 881 } 882 c[GOLD] += 25000; 883 drawscreen(); 884 return; 885#endif 886 887 case 'T': 888 yrepcount = 0; 889 cursors(); 890 if (c[SHIELD] != -1) { 891 c[SHIELD] = -1; 892 lprcat("\nYour shield is off"); 893 bottomline(); 894 } else if (c[WEAR] != -1) { 895 c[WEAR] = -1; 896 lprcat("\nYour armor is off"); 897 bottomline(); 898 } else 899 lprcat("\nYou aren't wearing anything"); 900 return; 901 902 case 'g': 903 cursors(); 904 lprintf("\nThe stuff you are carrying presently weighs %ld pounds", (long) packweight()); 905 case ' ': 906 yrepcount = 0; 907 nomove = 1; 908 return; 909 910 case 'v': 911 yrepcount = 0; 912 cursors(); 913 lprintf("\nCaverns of Larn, Version %ld.%ld, Diff=%ld", 914 (long) VERSION, (long) SUBVERSION, 915 (long) c[HARDGAME]); 916 if (wizard) 917 lprcat(" Wizard"); 918 nomove = 1; 919 if (cheat) 920 lprcat(" Cheater"); 921 lprcat(copyright); 922 return; 923 924 case 'Q': 925 yrepcount = 0; 926 quit(); 927 nomove = 1; 928 return; /* quit */ 929 930 case 'L' - 64: 931 yrepcount = 0; 932 drawscreen(); 933 nomove = 1; 934 return; /* look */ 935 936#if WIZID 937#ifdef EXTRA 938 case 'A': 939 yrepcount = 0; 940 nomove = 1; 941 if (wizard) { 942 diag(); 943 return; 944 } /* create diagnostic file */ 945 return; 946#endif 947#endif 948 case 'P': 949 cursors(); 950 if (outstanding_taxes > 0) 951 lprintf("\nYou presently owe %ld gp in taxes.", 952 (long) outstanding_taxes); 953 else 954 lprcat("\nYou do not owe any taxes."); 955 return; 956 }; 957 } 958} 959 960void 961parse2() 962{ 963 if (c[HASTEMONST]) 964 movemonst(); 965 movemonst(); /* move the monsters */ 966 randmonst(); 967 regen(); 968} 969 970void 971run(dir) 972 int dir; 973{ 974 int i; 975 i = 1; 976 while (i) { 977 i = moveplayer(dir); 978 if (i > 0) { 979 if (c[HASTEMONST]) 980 movemonst(); 981 movemonst(); 982 randmonst(); 983 regen(); 984 } 985 if (hitflag) 986 i = 0; 987 if (i != 0) 988 showcell(playerx, playery); 989 } 990} 991 992/* 993 function to wield a weapon 994 */ 995void 996wield() 997{ 998 int i; 999 while (1) { 1000 if ((i = whatitem("wield")) == '\33') 1001 return; 1002 if (i != '.') { 1003 if (i == '*') 1004 showwield(); 1005 else if (iven[i - 'a'] == 0) { 1006 ydhi(i); 1007 return; 1008 } else if (iven[i - 'a'] == OPOTION) { 1009 ycwi(i); 1010 return; 1011 } else if (iven[i - 'a'] == OSCROLL) { 1012 ycwi(i); 1013 return; 1014 } else if ((c[SHIELD] != -1) && (iven[i - 'a'] == O2SWORD)) { 1015 lprcat("\nBut one arm is busy with your shield!"); 1016 return; 1017 } else { 1018 c[WIELD] = i - 'a'; 1019 if (iven[i - 'a'] == OLANCE) 1020 c[LANCEDEATH] = 1; 1021 else 1022 c[LANCEDEATH] = 0; 1023 bottomline(); 1024 return; 1025 } 1026 } 1027 } 1028} 1029 1030/* 1031 common routine to say you don't have an item 1032 */ 1033void 1034ydhi(x) 1035 int x; 1036{ 1037 cursors(); 1038 lprintf("\nYou don't have item %c!", x); 1039} 1040void 1041ycwi(x) 1042 int x; 1043{ 1044 cursors(); 1045 lprintf("\nYou can't wield item %c!", x); 1046} 1047 1048/* 1049 function to wear armor 1050 */ 1051void 1052wear() 1053{ 1054 int i; 1055 while (1) { 1056 if ((i = whatitem("wear")) == '\33') 1057 return; 1058 if (i != '.') { 1059 if (i == '*') 1060 showwear(); 1061 else 1062 switch (iven[i - 'a']) { 1063 case 0: 1064 ydhi(i); 1065 return; 1066 case OLEATHER: 1067 case OCHAIN: 1068 case OPLATE: 1069 case OSTUDLEATHER: 1070 case ORING: 1071 case OSPLINT: 1072 case OPLATEARMOR: 1073 case OSSPLATE: 1074 if (c[WEAR] != -1) { 1075 lprcat("\nYou're already wearing some armor"); 1076 return; 1077 } 1078 c[WEAR] = i - 'a'; 1079 bottomline(); 1080 return; 1081 case OSHIELD: 1082 if (c[SHIELD] != -1) { 1083 lprcat("\nYou are already wearing a shield"); 1084 return; 1085 } 1086 if (iven[c[WIELD]] == O2SWORD) { 1087 lprcat("\nYour hands are busy with the two handed sword!"); 1088 return; 1089 } 1090 c[SHIELD] = i - 'a'; 1091 bottomline(); 1092 return; 1093 default: 1094 lprcat("\nYou can't wear that!"); 1095 }; 1096 } 1097 } 1098} 1099 1100/* 1101 function to drop an object 1102 */ 1103void 1104dropobj() 1105{ 1106 int i; 1107 unsigned char *p; 1108 long amt; 1109 p = &item[playerx][playery]; 1110 while (1) { 1111 if ((i = whatitem("drop")) == '\33') 1112 return; 1113 if (i == '*') 1114 showstr(); 1115 else { 1116 if (i == '.') { /* drop some gold */ 1117 if (*p) { 1118 lprcat("\nThere's something here already!"); 1119 return; 1120 } 1121 lprcat("\n\n"); 1122 cl_dn(1, 23); 1123 lprcat("How much gold do you drop? "); 1124 if ((amt = readnum((long) c[GOLD])) == 0) 1125 return; 1126 if (amt > c[GOLD]) { 1127 lprcat("\nYou don't have that much!"); 1128 return; 1129 } 1130 if (amt <= 32767) { 1131 *p = OGOLDPILE; 1132 i = amt; 1133 } else if (amt <= 327670L) { 1134 *p = ODGOLD; 1135 i = amt / 10; 1136 amt = 10 * i; 1137 } else if (amt <= 3276700L) { 1138 *p = OMAXGOLD; 1139 i = amt / 100; 1140 amt = 100 * i; 1141 } else if (amt <= 32767000L) { 1142 *p = OKGOLD; 1143 i = amt / 1000; 1144 amt = 1000 * i; 1145 } else { 1146 *p = OKGOLD; 1147 i = 32767; 1148 amt = 32767000L; 1149 } 1150 c[GOLD] -= amt; 1151 lprintf("You drop %ld gold pieces", (long)amt); 1152 iarg[playerx][playery] = i; 1153 bottomgold(); 1154 know[playerx][playery] = 0; 1155 dropflag = 1; 1156 return; 1157 } 1158 drop_object(i - 'a'); 1159 return; 1160 } 1161 } 1162} 1163 1164/* 1165 * readscr() Subroutine to read a scroll one is carrying 1166 */ 1167void 1168readscr() 1169{ 1170 int i; 1171 while (1) { 1172 if ((i = whatitem("read")) == '\33') 1173 return; 1174 if (i != '.') { 1175 if (i == '*') 1176 showread(); 1177 else { 1178 if (iven[i - 'a'] == OSCROLL) { 1179 read_scroll(ivenarg[i - 'a']); 1180 iven[i - 'a'] = 0; 1181 return; 1182 } 1183 if (iven[i - 'a'] == OBOOK) { 1184 readbook(ivenarg[i - 'a']); 1185 iven[i - 'a'] = 0; 1186 return; 1187 } 1188 if (iven[i - 'a'] == 0) { 1189 ydhi(i); 1190 return; 1191 } 1192 lprcat("\nThere's nothing on it to read"); 1193 return; 1194 } 1195 } 1196 } 1197} 1198 1199/* 1200 * subroutine to eat a cookie one is carrying 1201 */ 1202void 1203eatcookie(void) 1204{ 1205 const char *p; 1206 int i; 1207 1208 while (1) { 1209 if ((i = whatitem("eat")) == '\33') 1210 return; 1211 if (i != '.') { 1212 if (i == '*') 1213 showeat(); 1214 else { 1215 if (iven[i - 'a'] == OCOOKIE) { 1216 lprcat("\nThe cookie was delicious."); 1217 iven[i - 'a'] = 0; 1218 if (!c[BLINDCOUNT]) { 1219 if ((p = fortune()) != NULL) { 1220 lprcat(" Inside you find a scrap of paper that says:\n"); 1221 lprcat(p); 1222 } 1223 } 1224 return; 1225 } 1226 if (iven[i - 'a'] == 0) { 1227 ydhi(i); 1228 return; 1229 } 1230 lprcat("\nYou can't eat that!"); 1231 return; 1232 } 1233 } 1234 } 1235} 1236 1237/* 1238 * subroutine to quaff a potion one is carrying 1239 */ 1240void 1241quaff() 1242{ 1243 int i; 1244 while (1) { 1245 if ((i = whatitem("quaff")) == '\33') 1246 return; 1247 if (i != '.') { 1248 if (i == '*') 1249 showquaff(); 1250 else { 1251 if (iven[i - 'a'] == OPOTION) { 1252 quaffpotion(ivenarg[i - 'a']); 1253 iven[i - 'a'] = 0; 1254 return; 1255 } 1256 if (iven[i - 'a'] == 0) { 1257 ydhi(i); 1258 return; 1259 } 1260 lprcat("\nYou wouldn't want to quaff that, would you? "); 1261 return; 1262 } 1263 } 1264 } 1265} 1266 1267/* 1268 function to ask what player wants to do 1269 */ 1270int 1271whatitem(const char *str) 1272{ 1273 int i; 1274 cursors(); 1275 lprintf("\nWhat do you want to %s [* for all] ? ", str); 1276 i = 0; 1277 while (i > 'z' || (i < 'a' && i != '*' && i != '\33' && i != '.')) 1278 i = lgetchar(); 1279 if (i == '\33') 1280 lprcat(" aborted"); 1281 return (i); 1282} 1283 1284/* 1285 subroutine to get a number from the player 1286 and allow * to mean return amt, else return the number entered 1287 */ 1288unsigned long 1289readnum(mx) 1290 long mx; 1291{ 1292 int i; 1293 unsigned long amt = 0; 1294 sncbr(); 1295 if ((i = lgetchar()) == '*') 1296 amt = mx; /* allow him to say * for all gold */ 1297 else 1298 while (i != '\n') { 1299 if (i == '\033') { 1300 scbr(); 1301 lprcat(" aborted"); 1302 return (0); 1303 } 1304 if ((i <= '9') && (i >= '0') && (amt < 99999999)) 1305 amt = amt * 10 + i - '0'; 1306 i = lgetchar(); 1307 } 1308 scbr(); 1309 return (amt); 1310} 1311 1312#ifdef HIDEBYLINK 1313/* 1314 * routine to zero every byte in a string 1315 */ 1316void 1317szero(str) 1318 char *str; 1319{ 1320 while (*str) 1321 *str++ = 0; 1322} 1323#endif /* HIDEBYLINK */ 1324