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