main.c revision 1.8
1#ifndef lint 2static char rcsid[] = "$NetBSD: main.c,v 1.8 1996/05/21 23:19:20 mrg Exp $"; 3#endif /* not lint */ 4 5/* main.c */ 6#include <sys/types.h> 7#include "header.h" 8#include <pwd.h> 9#include <string.h> 10 11static char copyright[]="\nLarn is copyrighted 1986 by Noah Morgan.\n"; 12int srcount=0; /* line counter for showstr() */ 13int dropflag=0; /* if 1 then don't lookforobject() next round */ 14int rmst=80; /* random monster creation counter */ 15int userid; /* the players login user id number */ 16char nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a move */ 17static char viewflag=0; 18 /* if viewflag then we have done a 99 stay here and don't showcell in the main loop */ 19char restorflag=0; /* 1 means restore has been done */ 20static char cmdhelp[] = "\ 21Cmd line format: larn [-slicnh] [-o<optsifle>] [-##] [++]\n\ 22 -s show the scoreboard\n\ 23 -l show the logfile (wizard id only)\n\ 24 -i show scoreboard with inventories of dead characters\n\ 25 -c create new scoreboard (wizard id only)\n\ 26 -n suppress welcome message on starting game\n\ 27 -## specify level of difficulty (example: -5)\n\ 28 -h print this help text\n\ 29 ++ restore game from checkpoint file\n\ 30 -o<optsfile> specify .larnopts filename to be used instead of \"~/.larnopts\"\n\ 31"; 32#ifdef VT100 33static char *termtypes[] = { "vt100", "vt101", "vt102", "vt103", "vt125", 34 "vt131", "vt140", "vt180", "vt220", "vt240", "vt241", "vt320", "vt340", 35 "vt341" }; 36#endif VT100 37/* 38 ************ 39 MAIN PROGRAM 40 ************ 41 */ 42main(argc,argv) 43 int argc; 44 char **argv; 45 { 46 register int i,j; 47 int hard; 48 char *ptr=0,*ttype; 49 struct passwd *pwe; 50 51 setuid(getuid()); /* give up "games" if we have it */ 52/* 53 * first task is to identify the player 54 */ 55#ifndef VT100 56 init_term(); /* setup the terminal (find out what type) for termcap */ 57#endif VT100 58 if (((ptr = getlogin()) == 0) || (*ptr==0)) /* try to get login name */ 59 if (pwe=getpwuid(getuid())) /* can we get it from /etc/passwd? */ 60 ptr = pwe->pw_name; 61 else 62 if ((ptr = getenv("USER")) == 0) 63 if ((ptr = getenv("LOGNAME")) == 0) 64 { 65 noone: write(2, "Can't find your logname. Who Are You?\n",39); 66 exit(); 67 } 68 if (ptr==0) goto noone; 69 if (strlen(ptr)==0) goto noone; 70/* 71 * second task is to prepare the pathnames the player will need 72 */ 73 strcpy(loginname,ptr); /* save loginname of the user for logging purposes */ 74 strcpy(logname,ptr); /* this will be overwritten with the players name */ 75 if ((ptr = getenv("HOME")) == 0) ptr = "."; 76 strcpy(savefilename, ptr); 77 strcat(savefilename, "/Larn.sav"); /* save file name in home directory */ 78 sprintf(optsfile, "%s/.larnopts",ptr); /* the .larnopts filename */ 79 80/* 81 * now malloc the memory for the dungeon 82 */ 83 cell = (struct cel *)malloc(sizeof(struct cel)*(MAXLEVEL+MAXVLEVEL)*MAXX*MAXY); 84 if (cell == 0) died(-285); /* malloc failure */ 85 lpbuf = malloc((5* BUFBIG)>>2); /* output buffer */ 86 inbuffer = malloc((5*MAXIBUF)>>2); /* output buffer */ 87 if ((lpbuf==0) || (inbuffer==0)) died(-285); /* malloc() failure */ 88 89 lcreat((char*)0); newgame(); /* set the initial clock */ hard= -1; 90 91#ifdef VT100 92/* 93 * check terminal type to avoid users who have not vt100 type terminals 94 */ 95 ttype = getenv("TERM"); 96 for (j=1, i=0; i<sizeof(termtypes)/sizeof(char *); i++) 97 if (strcmp(ttype,termtypes[i]) == 0) { j=0; break; } 98 if (j) 99 { 100 lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush(); 101 exit(); 102 } 103#endif VT100 104 105/* 106 * now make scoreboard if it is not there (don't clear) 107 */ 108 if (access(scorefile,0) == -1) /* not there */ 109 makeboard(); 110 111/* 112 * now process the command line arguments 113 */ 114 for (i=1; i<argc; i++) 115 { 116 if (argv[i][0] == '-') 117 switch(argv[i][1]) 118 { 119 case 's': showscores(); exit(); /* show scoreboard */ 120 121 case 'l': /* show log file */ 122 diedlog(); exit(); 123 124 case 'i': showallscores(); exit(); /* show all scoreboard */ 125 126 case 'c': /* anyone with password can create scoreboard */ 127 lprcat("Preparing to initialize the scoreboard.\n"); 128 if (getpassword() != 0) /*make new scoreboard*/ 129 { 130 makeboard(); lprc('\n'); showscores(); 131 } 132 exit(); 133 134 case 'n': /* no welcome msg */ nowelcome=1; argv[i][0]=0; break; 135 136 case '0': case '1': case '2': case '3': case '4': case '5': 137 case '6': case '7': case '8': case '9': /* for hardness */ 138 sscanf(&argv[i][1],"%d",&hard); 139 break; 140 141 case 'h': /* print out command line arguments */ 142 write(1,cmdhelp,sizeof(cmdhelp)); exit(); 143 144 case 'o': /* specify a .larnopts filename */ 145 strncpy(optsfile,argv[i]+2,127); break; 146 147 default: printf("Unknown option <%s>\n",argv[i]); exit(); 148 }; 149 150 if (argv[i][0] == '+') 151 { 152 clear(); restorflag = 1; 153 if (argv[i][1] == '+') 154 { 155 hitflag=1; restoregame(ckpfile); /* restore checkpointed game */ 156 } 157 i = argc; 158 } 159 } 160 161 readopts(); /* read the options file if there is one */ 162 163 164#ifdef UIDSCORE 165 userid = geteuid(); /* obtain the user's effective id number */ 166#else UIDSCORE 167 userid = getplid(logname); /* obtain the players id number */ 168#endif UIDSCORE 169 if (userid < 0) { write(2,"Can't obtain playerid\n",22); exit(); } 170 171#ifdef HIDEBYLINK 172/* 173 * this section of code causes the program to look like something else to ps 174 */ 175 if (strcmp(psname,argv[0])) /* if a different process name only */ 176 { 177 if ((i=access(psname,1)) < 0) 178 { /* link not there */ 179 if (link(argv[0],psname)>=0) 180 { 181 argv[0] = psname; execv(psname,argv); 182 } 183 } 184 else 185 unlink(psname); 186 } 187 188 for (i=1; i<argc; i++) 189 { 190 szero(argv[i]); /* zero the argument to avoid ps snooping */ 191 } 192#endif HIDEBYLINK 193 194 if (access(savefilename,0)==0) /* restore game if need to */ 195 { 196 clear(); restorflag = 1; 197 hitflag=1; restoregame(savefilename); /* restore last game */ 198 } 199 sigsetup(); /* trap all needed signals */ 200 sethard(hard); /* set up the desired difficulty */ 201 setupvt100(); /* setup the terminal special mode */ 202 if (c[HP]==0) /* create new game */ 203 { 204 makeplayer(); /* make the character that will play */ 205 newcavelevel(0);/* make the dungeon */ 206 predostuff = 1; /* tell signals that we are in the welcome screen */ 207 if (nowelcome==0) welcome(); /* welcome the player to the game */ 208 } 209 drawscreen(); /* show the initial dungeon */ 210 predostuff = 2; /* tell the trap functions that they must do a showplayer() 211 from here on */ 212 /* nice(1); /* games should be run niced */ 213 yrepcount = hit2flag = 0; 214 while (1) 215 { 216 if (dropflag==0) lookforobject(); /* see if there is an object here */ 217 else dropflag=0; /* don't show it just dropped an item */ 218 if (hitflag==0) { if (c[HASTEMONST]) movemonst(); movemonst(); } /* move the monsters */ 219 if (viewflag==0) showcell(playerx,playery); else viewflag=0; /* show stuff around player */ 220 if (hit3flag) flushall(); 221 hitflag=hit3flag=0; nomove=1; 222 bot_linex(); /* update bottom line */ 223 while (nomove) 224 { 225 if (hit3flag) flushall(); 226 nomove=0; parse(); 227 } /* get commands and make moves */ 228 regen(); /* regenerate hp and spells */ 229 if (c[TIMESTOP]==0) 230 if (--rmst <= 0) 231 { rmst = 120-(level<<2); fillmonst(makemonst(level)); } 232 } 233 } 234 235/* 236 showstr() 237 238 show character's inventory 239 */ 240showstr() 241 { 242 register int i,number; 243 for (number=3, i=0; i<26; i++) 244 if (iven[i]) number++; /* count items in inventory */ 245 t_setup(number); qshowstr(); t_endup(number); 246 } 247 248qshowstr() 249 { 250 register int i,j,k,sigsav; 251 srcount=0; sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ 252 if (c[GOLD]) { lprintf(".) %d gold pieces",(long)c[GOLD]); srcount++; } 253 for (k=26; k>=0; k--) 254 if (iven[k]) 255 { for (i=22; i<84; i++) 256 for (j=0; j<=k; j++) if (i==iven[j]) show3(j); k=0; } 257 258 lprintf("\nElapsed time is %d. You have %d mobuls left",(long)((gtime+99)/100+1),(long)((TIMELIMIT-gtime)/100)); 259 more(); nosignal=sigsav; 260 } 261 262/* 263 * subroutine to clear screen depending on # lines to display 264 */ 265t_setup(count) 266 register int count; 267 { 268 if (count<20) /* how do we clear the screen? */ 269 { 270 cl_up(79,count); cursor(1,1); 271 } 272 else 273 { 274 resetscroll(); clear(); 275 } 276 } 277 278/* 279 * subroutine to restore normal display screen depending on t_setup() 280 */ 281t_endup(count) 282 register int count; 283 { 284 if (count<18) /* how did we clear the screen? */ 285 draws(0,MAXX,0,(count>MAXY) ? MAXY : count); 286 else 287 { 288 drawscreen(); setscroll(); 289 } 290 } 291 292/* 293 function to show the things player is wearing only 294 */ 295showwear() 296 { 297 register int i,j,sigsav,count; 298 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ 299 srcount=0; 300 301 for (count=2,j=0; j<=26; j++) /* count number of items we will display */ 302 if (i=iven[j]) 303 switch(i) 304 { 305 case OLEATHER: case OPLATE: case OCHAIN: 306 case ORING: case OSTUDLEATHER: case OSPLINT: 307 case OPLATEARMOR: case OSSPLATE: case OSHIELD: 308 count++; 309 }; 310 311 t_setup(count); 312 313 for (i=22; i<84; i++) 314 for (j=0; j<=26; j++) 315 if (i==iven[j]) 316 switch(i) 317 { 318 case OLEATHER: case OPLATE: case OCHAIN: 319 case ORING: case OSTUDLEATHER: case OSPLINT: 320 case OPLATEARMOR: case OSSPLATE: case OSHIELD: 321 show3(j); 322 }; 323 more(); nosignal=sigsav; t_endup(count); 324 } 325 326/* 327 function to show the things player can wield only 328 */ 329showwield() 330 { 331 register int i,j,sigsav,count; 332 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ 333 srcount=0; 334 335 for (count=2,j=0; j<=26; j++) /* count how many items */ 336 if (i=iven[j]) 337 switch(i) 338 { 339 case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE: 340 case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT: 341 case OSPIRITSCARAB: case OCUBEofUNDEAD: 342 case OPOTION: case OSCROLL: break; 343 default: count++; 344 }; 345 346 t_setup(count); 347 348 for (i=22; i<84; i++) 349 for (j=0; j<=26; j++) 350 if (i==iven[j]) 351 switch(i) 352 { 353 case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE: 354 case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT: 355 case OSPIRITSCARAB: case OCUBEofUNDEAD: 356 case OPOTION: case OSCROLL: break; 357 default: show3(j); 358 }; 359 more(); nosignal=sigsav; t_endup(count); 360 } 361 362/* 363 * function to show the things player can read only 364 */ 365showread() 366 { 367 register int i,j,sigsav,count; 368 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ 369 srcount=0; 370 371 for (count=2,j=0; j<=26; j++) 372 switch(iven[j]) 373 { 374 case OBOOK: case OSCROLL: count++; 375 }; 376 t_setup(count); 377 378 for (i=22; i<84; i++) 379 for (j=0; j<=26; j++) 380 if (i==iven[j]) 381 switch(i) 382 { 383 case OBOOK: case OSCROLL: show3(j); 384 }; 385 more(); nosignal=sigsav; t_endup(count); 386 } 387 388/* 389 * function to show the things player can eat only 390 */ 391showeat() 392 { 393 register int i,j,sigsav,count; 394 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ 395 srcount=0; 396 397 for (count=2,j=0; j<=26; j++) 398 switch(iven[j]) 399 { 400 case OCOOKIE: count++; 401 }; 402 t_setup(count); 403 404 for (i=22; i<84; i++) 405 for (j=0; j<=26; j++) 406 if (i==iven[j]) 407 switch(i) 408 { 409 case OCOOKIE: show3(j); 410 }; 411 more(); nosignal=sigsav; t_endup(count); 412 } 413 414/* 415 function to show the things player can quaff only 416 */ 417showquaff() 418 { 419 register int i,j,sigsav,count; 420 sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ 421 srcount=0; 422 423 for (count=2,j=0; j<=26; j++) 424 switch(iven[j]) 425 { 426 case OPOTION: count++; 427 }; 428 t_setup(count); 429 430 for (i=22; i<84; i++) 431 for (j=0; j<=26; j++) 432 if (i==iven[j]) 433 switch(i) 434 { 435 case OPOTION: show3(j); 436 }; 437 more(); nosignal=sigsav; t_endup(count); 438 } 439 440show1(idx,str2) 441 register int idx; 442 register char *str2[]; 443 { 444 lprintf("\n%c) %s",idx+'a',objectname[iven[idx]]); 445 if (str2!=0 && str2[ivenarg[idx]][0]!=0) lprintf(" of%s",str2[ivenarg[idx]]); 446 } 447 448show3(index) 449 register int index; 450 { 451 switch(iven[index]) 452 { 453 case OPOTION: show1(index,potionname); break; 454 case OSCROLL: show1(index,scrollname); break; 455 456 case OLARNEYE: case OBOOK: case OSPIRITSCARAB: 457 case ODIAMOND: case ORUBY: case OCUBEofUNDEAD: 458 case OEMERALD: case OCHEST: case OCOOKIE: 459 case OSAPPHIRE: case ONOTHEFT: show1(index,(char **)0); break; 460 461 default: lprintf("\n%c) %s",index+'a',objectname[iven[index]]); 462 if (ivenarg[index]>0) lprintf(" + %d",(long)ivenarg[index]); 463 else if (ivenarg[index]<0) lprintf(" %d",(long)ivenarg[index]); 464 break; 465 } 466 if (c[WIELD]==index) lprcat(" (weapon in hand)"); 467 if ((c[WEAR]==index) || (c[SHIELD]==index)) lprcat(" (being worn)"); 468 if (++srcount>=22) { srcount=0; more(); clear(); } 469 } 470 471/* 472 subroutine to randomly create monsters if needed 473 */ 474randmonst() 475 { 476 if (c[TIMESTOP]) return; /* don't make monsters if time is stopped */ 477 if (--rmst <= 0) 478 { 479 rmst = 120 - (level<<2); fillmonst(makemonst(level)); 480 } 481 } 482 483 484/* 485 parse() 486 487 get and execute a command 488 */ 489parse() 490 { 491 register int i,j,k,flag; 492 while (1) 493 { 494 k = yylex(); 495 switch(k) /* get the token from the input and switch on it */ 496 { 497 case 'h': moveplayer(4); return; /* west */ 498 case 'H': run(4); return; /* west */ 499 case 'l': moveplayer(2); return; /* east */ 500 case 'L': run(2); return; /* east */ 501 case 'j': moveplayer(1); return; /* south */ 502 case 'J': run(1); return; /* south */ 503 case 'k': moveplayer(3); return; /* north */ 504 case 'K': run(3); return; /* north */ 505 case 'u': moveplayer(5); return; /* northeast */ 506 case 'U': run(5); return; /* northeast */ 507 case 'y': moveplayer(6); return; /* northwest */ 508 case 'Y': run(6); return; /* northwest */ 509 case 'n': moveplayer(7); return; /* southeast */ 510 case 'N': run(7); return; /* southeast */ 511 case 'b': moveplayer(8); return; /* southwest */ 512 case 'B': run(8); return; /* southwest */ 513 514 case '.': if (yrepcount) viewflag=1; return; /* stay here */ 515 516 case 'w': yrepcount=0; wield(); return; /* wield a weapon */ 517 518 case 'W': yrepcount=0; wear(); return; /* wear armor */ 519 520 case 'r': yrepcount=0; 521 if (c[BLINDCOUNT]) { cursors(); lprcat("\nYou can't read anything when you're blind!"); } else 522 if (c[TIMESTOP]==0) readscr(); return; /* to read a scroll */ 523 524 case 'q': yrepcount=0; if (c[TIMESTOP]==0) quaff(); return; /* quaff a potion */ 525 526 case 'd': yrepcount=0; if (c[TIMESTOP]==0) dropobj(); return; /* to drop an object */ 527 528 case 'c': yrepcount=0; cast(); return; /* cast a spell */ 529 530 case 'i': yrepcount=0; nomove=1; showstr(); return; /* status */ 531 532 case 'e': yrepcount=0; 533 if (c[TIMESTOP]==0) eatcookie(); return; /* to eat a fortune cookie */ 534 535 case 'D': yrepcount=0; seemagic(0); nomove=1; return; /* list spells and scrolls */ 536 537 case '?': yrepcount=0; help(); nomove=1; return; /* give the help screen*/ 538 539 case 'S': clear(); lprcat("Saving . . ."); lflush(); 540 savegame(savefilename); wizard=1; died(-257); /* save the game - doesn't return */ 541 542 case 'Z': yrepcount=0; if (c[LEVEL]>9) { oteleport(1); return; } 543 cursors(); lprcat("\nAs yet, you don't have enough experience to use teleportation"); 544 return; /* teleport yourself */ 545 546 case '^': /* identify traps */ flag=yrepcount=0; cursors(); 547 lprc('\n'); for (j=playery-1; j<playery+2; j++) 548 { 549 if (j < 0) j=0; if (j >= MAXY) break; 550 for (i=playerx-1; i<playerx+2; i++) 551 { 552 if (i < 0) i=0; if (i >= MAXX) break; 553 switch(item[i][j]) 554 { 555 case OTRAPDOOR: case ODARTRAP: 556 case OTRAPARROW: case OTELEPORTER: 557 lprcat("\nIts "); lprcat(objectname[item[i][j]]); flag++; 558 }; 559 } 560 } 561 if (flag==0) lprcat("\nNo traps are visible"); 562 return; 563 564#if WIZID 565 case '_': /* this is the fudge player password for wizard mode*/ 566 yrepcount=0; cursors(); nomove=1; 567 if (userid!=wisid) 568 { 569 lprcat("Sorry, you are not empowered to be a wizard.\n"); 570 scbr(); /* system("stty -echo cbreak"); */ 571 lflush(); return; 572 } 573 if (getpassword()==0) 574 { 575 scbr(); /* system("stty -echo cbreak"); */ return; 576 } 577 wizard=1; scbr(); /* system("stty -echo cbreak"); */ 578 for (i=0; i<6; i++) c[i]=70; iven[0]=iven[1]=0; 579 take(OPROTRING,50); take(OLANCE,25); c[WIELD]=1; 580 c[LANCEDEATH]=1; c[WEAR] = c[SHIELD] = -1; 581 raiseexperience(6000000L); c[AWARENESS] += 25000; 582 { 583 register int i,j; 584 for (i=0; i<MAXY; i++) 585 for (j=0; j<MAXX; j++) know[j][i]=1; 586 for (i=0; i<SPNUM; i++) spelknow[i]=1; 587 for (i=0; i<MAXSCROLL; i++) scrollname[i]=scrollhide[i]; 588 for (i=0; i<MAXPOTION; i++) potionname[i]=potionhide[i]; 589 } 590 for (i=0; i<MAXSCROLL; i++) 591 if (strlen(scrollname[i])>2) /* no null items */ 592 { item[i][0]=OSCROLL; iarg[i][0]=i; } 593 for (i=MAXX-1; i>MAXX-1-MAXPOTION; i--) 594 if (strlen(potionname[i-MAXX+MAXPOTION])>2) /* no null items */ 595 { item[i][0]=OPOTION; iarg[i][0]=i-MAXX+MAXPOTION; } 596 for (i=1; i<MAXY; i++) 597 { item[0][i]=i; iarg[0][i]=0; } 598 for (i=MAXY; i<MAXY+MAXX; i++) 599 { item[i-MAXY][MAXY-1]=i; iarg[i-MAXY][MAXY-1]=0; } 600 for (i=MAXX+MAXY; i<MAXX+MAXY+MAXY; i++) 601 { item[MAXX-1][i-MAXX-MAXY]=i; iarg[MAXX-1][i-MAXX-MAXY]=0; } 602 c[GOLD]+=25000; drawscreen(); return; 603#endif 604 605 case 'T': yrepcount=0; cursors(); if (c[SHIELD] != -1) { c[SHIELD] = -1; lprcat("\nYour shield is off"); bottomline(); } else 606 if (c[WEAR] != -1) { c[WEAR] = -1; lprcat("\nYour armor is off"); bottomline(); } 607 else lprcat("\nYou aren't wearing anything"); 608 return; 609 610 case 'g': cursors(); 611 lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long)packweight()); 612 case ' ': yrepcount=0; nomove=1; return; 613 614 case 'v': yrepcount=0; cursors(); 615 lprintf("\nCaverns of Larn, Version %d.%d, Diff=%d",(long)VERSION,(long)SUBVERSION,(long)c[HARDGAME]); 616 if (wizard) lprcat(" Wizard"); nomove=1; 617 if (cheat) lprcat(" Cheater"); 618 lprcat(copyright); 619 return; 620 621 case 'Q': yrepcount=0; quit(); nomove=1; return; /* quit */ 622 623 case 'L'-64: yrepcount=0; drawscreen(); nomove=1; return; /* look */ 624 625#if WIZID 626#ifdef EXTRA 627 case 'A': yrepcount=0; nomove=1; if (wizard) { diag(); return; } /* create diagnostic file */ 628 return; 629#endif 630#endif 631 case 'P': cursors(); 632 if (outstanding_taxes>0) 633 lprintf("\nYou presently owe %d gp in taxes.",(long)outstanding_taxes); 634 else 635 lprcat("\nYou do not owe any taxes."); 636 return; 637 }; 638 } 639 } 640 641parse2() 642 { 643 if (c[HASTEMONST]) movemonst(); movemonst(); /* move the monsters */ 644 randmonst(); regen(); 645 } 646 647run(dir) 648 int dir; 649 { 650 register int i; 651 i=1; while (i) 652 { 653 i=moveplayer(dir); 654 if (i>0) { if (c[HASTEMONST]) movemonst(); movemonst(); randmonst(); regen(); } 655 if (hitflag) i=0; 656 if (i!=0) showcell(playerx,playery); 657 } 658 } 659 660/* 661 function to wield a weapon 662 */ 663wield() 664 { 665 register int i; 666 while (1) 667 { 668 if ((i = whatitem("wield"))=='\33') return; 669 if (i != '.') 670 { 671 if (i=='*') showwield(); 672 else if (iven[i-'a']==0) { ydhi(i); return; } 673 else if (iven[i-'a']==OPOTION) { ycwi(i); return; } 674 else if (iven[i-'a']==OSCROLL) { ycwi(i); return; } 675 else if ((c[SHIELD]!= -1) && (iven[i-'a']==O2SWORD)) { lprcat("\nBut one arm is busy with your shield!"); return; } 676 else { c[WIELD]=i-'a'; if (iven[i-'a'] == OLANCE) c[LANCEDEATH]=1; else c[LANCEDEATH]=0; bottomline(); return; } 677 } 678 } 679 } 680 681/* 682 common routine to say you don't have an item 683 */ 684ydhi(x) 685 int x; 686 { cursors(); lprintf("\nYou don't have item %c!",x); } 687ycwi(x) 688 int x; 689 { cursors(); lprintf("\nYou can't wield item %c!",x); } 690 691/* 692 function to wear armor 693 */ 694wear() 695 { 696 register int i; 697 while (1) 698 { 699 if ((i = whatitem("wear"))=='\33') return; 700 if (i != '.') 701 { 702 if (i=='*') showwear(); else 703 switch(iven[i-'a']) 704 { 705 case 0: ydhi(i); return; 706 case OLEATHER: case OCHAIN: case OPLATE: case OSTUDLEATHER: 707 case ORING: case OSPLINT: case OPLATEARMOR: case OSSPLATE: 708 if (c[WEAR] != -1) { lprcat("\nYou're already wearing some armor"); return; } 709 c[WEAR]=i-'a'; bottomline(); return; 710 case OSHIELD: if (c[SHIELD] != -1) { lprcat("\nYou are already wearing a shield"); return; } 711 if (iven[c[WIELD]]==O2SWORD) { lprcat("\nYour hands are busy with the two handed sword!"); return; } 712 c[SHIELD] = i-'a'; bottomline(); return; 713 default: lprcat("\nYou can't wear that!"); 714 }; 715 } 716 } 717 } 718 719/* 720 function to drop an object 721 */ 722dropobj() 723 { 724 register int i; 725 register char *p; 726 long amt; 727 p = &item[playerx][playery]; 728 while (1) 729 { 730 if ((i = whatitem("drop"))=='\33') return; 731 if (i=='*') showstr(); else 732 { 733 if (i=='.') /* drop some gold */ 734 { 735 if (*p) { lprcat("\nThere's something here already!"); return; } 736 lprcat("\n\n"); 737 cl_dn(1,23); 738 lprcat("How much gold do you drop? "); 739 if ((amt=readnum((long)c[GOLD])) == 0) return; 740 if (amt>c[GOLD]) 741 { lprcat("\nYou don't have that much!"); return; } 742 if (amt<=32767) 743 { *p=OGOLDPILE; i=amt; } 744 else if (amt<=327670L) 745 { *p=ODGOLD; i=amt/10; amt = 10*i; } 746 else if (amt<=3276700L) 747 { *p=OMAXGOLD; i=amt/100; amt = 100*i; } 748 else if (amt<=32767000L) 749 { *p=OKGOLD; i=amt/1000; amt = 1000*i; } 750 else 751 { *p=OKGOLD; i=32767; amt = 32767000L; } 752 c[GOLD] -= amt; 753 lprintf("You drop %d gold pieces",(long)amt); 754 iarg[playerx][playery]=i; bottomgold(); 755 know[playerx][playery]=0; dropflag=1; return; 756 } 757 drop_object(i-'a'); 758 return; 759 } 760 } 761 } 762 763/* 764 * readscr() Subroutine to read a scroll one is carrying 765 */ 766readscr() 767 { 768 register int i; 769 while (1) 770 { 771 if ((i = whatitem("read"))=='\33') return; 772 if (i != '.') 773 { 774 if (i=='*') showread(); else 775 { 776 if (iven[i-'a']==OSCROLL) { read_scroll(ivenarg[i-'a']); iven[i-'a']=0; return; } 777 if (iven[i-'a']==OBOOK) { readbook(ivenarg[i-'a']); iven[i-'a']=0; return; } 778 if (iven[i-'a']==0) { ydhi(i); return; } 779 lprcat("\nThere's nothing on it to read"); return; 780 } 781 } 782 } 783 } 784 785/* 786 * subroutine to eat a cookie one is carrying 787 */ 788eatcookie() 789{ 790register int i; 791char *p; 792while (1) 793 { 794 if ((i = whatitem("eat"))=='\33') return; 795 if (i != '.') 796 if (i=='*') showeat(); else 797 { 798 if (iven[i-'a']==OCOOKIE) 799 { 800 lprcat("\nThe cookie was delicious."); 801 iven[i-'a']=0; 802 if (!c[BLINDCOUNT]) 803 { 804 if (p=fortune()) 805 { 806 lprcat(" Inside you find a scrap of paper that says:\n"); 807 lprcat(p); 808 } 809 } 810 return; 811 } 812 if (iven[i-'a']==0) { ydhi(i); return; } 813 lprcat("\nYou can't eat that!"); return; 814 } 815 } 816} 817 818/* 819 * subroutine to quaff a potion one is carrying 820 */ 821quaff() 822 { 823 register int i; 824 while (1) 825 { 826 if ((i = whatitem("quaff"))=='\33') return; 827 if (i != '.') 828 { 829 if (i=='*') showquaff(); else 830 { 831 if (iven[i-'a']==OPOTION) { quaffpotion(ivenarg[i-'a']); iven[i-'a']=0; return; } 832 if (iven[i-'a']==0) { ydhi(i); return; } 833 lprcat("\nYou wouldn't want to quaff that, would you? "); return; 834 } 835 } 836 } 837 } 838 839/* 840 function to ask what player wants to do 841 */ 842whatitem(str) 843 char *str; 844 { 845 int i; 846 cursors(); lprintf("\nWhat do you want to %s [* for all] ? ",str); 847 i=0; while (i>'z' || (i<'a' && i!='*' && i!='\33' && i!='.')) i=getchar(); 848 if (i=='\33') lprcat(" aborted"); 849 return(i); 850 } 851 852/* 853 subroutine to get a number from the player 854 and allow * to mean return amt, else return the number entered 855 */ 856unsigned long readnum(mx) 857 long mx; 858 { 859 register int i; 860 register unsigned long amt=0; 861 sncbr(); 862 if ((i=getchar()) == '*') amt = mx; /* allow him to say * for all gold */ 863 else 864 while (i != '\n') 865 { 866 if (i=='\033') { scbr(); lprcat(" aborted"); return(0); } 867 if ((i <= '9') && (i >= '0') && (amt<99999999)) 868 amt = amt*10+i-'0'; 869 i = getchar(); 870 } 871 scbr(); return(amt); 872 } 873 874#ifdef HIDEBYLINK 875/* 876 * routine to zero every byte in a string 877 */ 878szero(str) 879 register char *str; 880 { 881 while (*str) 882 *str++ = 0; 883 } 884#endif HIDEBYLINK 885