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