1 /* global.c Larn is copyrighted 1986 by Noah Morgan. 2 * 3 * raiselevel() subroutine to raise the player one level 4 * loselevel() subroutine to lower the player by one level 5 * raiseexperience(x) subroutine to increase experience points 6 * loseexperience(x) subroutine to lose experience points 7 * losehp(x) subroutine to remove hit points from the player 8 * losemhp(x) subroutine to remove max # hit points from the player 9 * raisehp(x) subroutine to gain hit points 10 * raisemhp(x) subroutine to gain maximum hit points 11 * losespells(x) subroutine to lose spells 12 * losemspells(x) subroutine to lose maximum spells 13 * raisespells(x) subroutine to gain spells 14 * raisemspells(x) subroutine to gain maximum spells 15 * recalc() function to recalculate the armor class of the player 16 * makemonst(lev) function to return monster number for a randomly selected monster 17 * positionplayer() function to be sure player is not in a wall 18 * quit() subroutine to ask if the player really wants to quit 19 */ 20 21 #include "header.h" 22 extern int score[],srcount,dropflag; 23 extern int random;/* the random number seed */ 24 extern short playerx,playery,lastnum; 25 extern char cheat,level,monstnamelist[]; 26 extern char lastmonst[],*what[],*who[]; 27 extern char winner[]; 28 extern char logname[],monstlevel[]; 29 extern char sciv[SCORESIZE+1][26][2],*potionname[],*scrollname[]; 30 /* 31 *********** 32 RAISE LEVEL 33 *********** 34 raiselevel() 35 36 subroutine to raise the player one level 37 uses the skill[] array to find level boundarys 38 uses c[EXPERIENCE] c[LEVEL] 39 */ 40 raiselevel() 41 { 42 if (c[LEVEL] < MAXPLEVEL) raiseexperience((long)(skill[c[LEVEL]]-c[EXPERIENCE])); 43 } 44 45 /* 46 *********** 47 LOOSE LEVEL 48 *********** 49 loselevel() 50 51 subroutine to lower the players character level by one 52 */ 53 loselevel() 54 { 55 if (c[LEVEL] > 1) loseexperience((long)(c[EXPERIENCE] - skill[c[LEVEL]-1] + 1)); 56 } 57 58 /* 59 **************** 60 RAISE EXPERIENCE 61 **************** 62 raiseexperience(x) 63 64 subroutine to increase experience points 65 */ 66 raiseexperience(x) 67 register long x; 68 { 69 register int i,tmp; 70 i=c[LEVEL]; c[EXPERIENCE]+=x; 71 while (c[EXPERIENCE] >= skill[c[LEVEL]] && (c[LEVEL] < MAXPLEVEL)) 72 { 73 tmp = (c[CONSTITUTION]-c[HARDGAME])>>1; 74 c[LEVEL]++; raisemhp((int)(rnd(3)+rnd((tmp>0)?tmp:1))); 75 raisemspells((int)rund(3)); 76 if (c[LEVEL] < 7-c[HARDGAME]) raisemhp((int)(c[CONSTITUTION]>>2)); 77 } 78 if (c[LEVEL] != i) 79 { 80 cursors(); 81 beep(); lprintf("\nWelcome to level %d",(long)c[LEVEL]); /* if we changed levels */ 82 } 83 bottomline(); 84 } 85 86 /* 87 **************** 88 LOOSE EXPERIENCE 89 **************** 90 loseexperience(x) 91 92 subroutine to lose experience points 93 */ 94 loseexperience(x) 95 register long x; 96 { 97 register int i,tmp; 98 i=c[LEVEL]; c[EXPERIENCE]-=x; 99 if (c[EXPERIENCE] < 0) c[EXPERIENCE]=0; 100 while (c[EXPERIENCE] < skill[c[LEVEL]-1]) 101 { 102 if (--c[LEVEL] <= 1) c[LEVEL]=1; /* down one level */ 103 tmp = (c[CONSTITUTION]-c[HARDGAME])>>1; /* lose hpoints */ 104 losemhp((int)rnd((tmp>0)?tmp:1)); /* lose hpoints */ 105 if (c[LEVEL] < 7-c[HARDGAME]) losemhp((int)(c[CONSTITUTION]>>2)); 106 losemspells((int)rund(3)); /* lose spells */ 107 } 108 if (i!=c[LEVEL]) 109 { 110 cursors(); 111 beep(); lprintf("\nYou went down to level %d!",(long)c[LEVEL]); 112 } 113 bottomline(); 114 } 115 116 /* 117 ******** 118 LOOSE HP 119 ******** 120 losehp(x) 121 losemhp(x) 122 123 subroutine to remove hit points from the player 124 warning -- will kill player if hp goes to zero 125 */ 126 losehp(x) 127 register int x; 128 { 129 if ((c[HP] -= x) <= 0) 130 { 131 beep(); lprcat("\n"); nap(3000); died(lastnum); 132 } 133 } 134 135 losemhp(x) 136 register int x; 137 { 138 c[HP] -= x; if (c[HP] < 1) c[HP]=1; 139 c[HPMAX] -= x; if (c[HPMAX] < 1) c[HPMAX]=1; 140 } 141 142 /* 143 ******** 144 RAISE HP 145 ******** 146 raisehp(x) 147 raisemhp(x) 148 149 subroutine to gain maximum hit points 150 */ 151 raisehp(x) 152 register int x; 153 { 154 if ((c[HP] += x) > c[HPMAX]) c[HP] = c[HPMAX]; 155 } 156 157 raisemhp(x) 158 register int x; 159 { 160 c[HPMAX] += x; c[HP] += x; 161 } 162 163 /* 164 ************ 165 RAISE SPELLS 166 ************ 167 raisespells(x) 168 raisemspells(x) 169 170 subroutine to gain maximum spells 171 */ 172 raisespells(x) 173 register int x; 174 { 175 if ((c[SPELLS] += x) > c[SPELLMAX]) c[SPELLS] = c[SPELLMAX]; 176 } 177 178 raisemspells(x) 179 register int x; 180 { 181 c[SPELLMAX]+=x; c[SPELLS]+=x; 182 } 183 184 /* 185 ************ 186 LOOSE SPELLS 187 ************ 188 losespells(x) 189 losemspells(x) 190 191 subroutine to lose maximum spells 192 */ 193 losespells(x) 194 register int x; 195 { 196 if ((c[SPELLS] -= x) < 0) c[SPELLS]=0; 197 } 198 199 losemspells(x) 200 register int x; 201 { 202 if ((c[SPELLMAX] -= x) < 0) c[SPELLMAX]=0; 203 if ((c[SPELLS] -= x) < 0) c[SPELLS]=0; 204 } 205 206 /* 207 makemonst(lev) 208 int lev; 209 210 function to return monster number for a randomly selected monster 211 for the given cave level 212 */ 213 makemonst(lev) 214 register int lev; 215 { 216 register int tmp,x; 217 if (lev < 1) lev = 1; if (lev > 12) lev = 12; 218 tmp=WATERLORD; 219 if (lev < 5) 220 while (tmp==WATERLORD) tmp=rnd((x=monstlevel[lev-1])?x:1); 221 else while (tmp==WATERLORD) 222 tmp=rnd((x=monstlevel[lev-1]-monstlevel[lev-4])?x:1)+monstlevel[lev-4]; 223 224 while (monster[tmp].genocided && tmp<MAXMONST) tmp++; /* genocided? */ 225 return(tmp); 226 } 227 228 /* 229 positionplayer() 230 231 function to be sure player is not in a wall 232 */ 233 positionplayer() 234 { 235 int try; 236 try = 2; 237 while ((item[playerx][playery] || mitem[playerx][playery]) && (try)) 238 if (++playerx >= MAXX-1) 239 { 240 playerx = 1; 241 if (++playery >= MAXY-1) 242 { playery = 1; --try; } 243 } 244 if (try==0) lprcat("Failure in positionplayer\n"); 245 } 246 247 /* 248 recalc() function to recalculate the armor class of the player 249 */ 250 recalc() 251 { 252 register int i,j,k; 253 c[AC] = c[MOREDEFENSES]; 254 if (c[WEAR] >= 0) 255 switch(iven[c[WEAR]]) 256 { 257 case OSHIELD: c[AC] += 2 + ivenarg[c[WEAR]]; break; 258 case OLEATHER: c[AC] += 2 + ivenarg[c[WEAR]]; break; 259 case OSTUDLEATHER: c[AC] += 3 + ivenarg[c[WEAR]]; break; 260 case ORING: c[AC] += 5 + ivenarg[c[WEAR]]; break; 261 case OCHAIN: c[AC] += 6 + ivenarg[c[WEAR]]; break; 262 case OSPLINT: c[AC] += 7 + ivenarg[c[WEAR]]; break; 263 case OPLATE: c[AC] += 9 + ivenarg[c[WEAR]]; break; 264 case OPLATEARMOR: c[AC] += 10 + ivenarg[c[WEAR]]; break; 265 case OSSPLATE: c[AC] += 12 + ivenarg[c[WEAR]]; break; 266 } 267 268 if (c[SHIELD] >= 0) if (iven[c[SHIELD]] == OSHIELD) c[AC] += 2 + ivenarg[c[SHIELD]]; 269 if (c[WIELD] < 0) c[WCLASS] = 0; else 270 { 271 i = ivenarg[c[WIELD]]; 272 switch(iven[c[WIELD]]) 273 { 274 case ODAGGER: c[WCLASS] = 3 + i; break; 275 case OBELT: c[WCLASS] = 7 + i; break; 276 case OSHIELD: c[WCLASS] = 8 + i; break; 277 case OSPEAR: c[WCLASS] = 10 + i; break; 278 case OFLAIL: c[WCLASS] = 14 + i; break; 279 case OBATTLEAXE: c[WCLASS] = 17 + i; break; 280 case OLANCE: c[WCLASS] = 19 + i; break; 281 case OLONGSWORD: c[WCLASS] = 22 + i; break; 282 case O2SWORD: c[WCLASS] = 26 + i; break; 283 case OSWORD: c[WCLASS] = 32 + i; break; 284 case OSWORDofSLASHING: c[WCLASS] = 30 + i; break; 285 case OHAMMER: c[WCLASS] = 35 + i; break; 286 default: c[WCLASS] = 0; 287 } 288 } 289 c[WCLASS] += c[MOREDAM]; 290 291 /* now for regeneration abilities based on rings */ 292 c[REGEN]=1; c[ENERGY]=0; 293 j=0; for (k=25; k>0; k--) if (iven[k]) {j=k; k=0; } 294 for (i=0; i<=j; i++) 295 { 296 switch(iven[i]) 297 { 298 case OPROTRING: c[AC] += ivenarg[i] + 1; break; 299 case ODAMRING: c[WCLASS] += ivenarg[i] + 1; break; 300 case OBELT: c[WCLASS] += ((ivenarg[i]<<1)) + 2; break; 301 302 case OREGENRING: c[REGEN] += ivenarg[i] + 1; break; 303 case ORINGOFEXTRA: c[REGEN] += 5 * (ivenarg[i]+1); break; 304 case OENERGYRING: c[ENERGY] += ivenarg[i] + 1; break; 305 } 306 } 307 } 308 309 310 /* 311 quit() 312 313 subroutine to ask if the player really wants to quit 314 */ 315 quit() 316 { 317 register int i; 318 cursors(); strcpy(lastmonst,""); 319 lprcat("\n\nDo you really want to quit?"); 320 while (1) 321 { 322 i=getchar(); 323 if (i == 'y') { died(300); return; } 324 if ((i == 'n') || (i == '\33')) { lprcat(" no"); lflush(); return; } 325 lprcat("\n"); setbold(); lprcat("Yes"); resetbold(); lprcat(" or "); 326 setbold(); lprcat("No"); resetbold(); lprcat(" please? Do you want to quit? "); 327 } 328 } 329 330 /* 331 function to ask --more-- then the user must enter a space 332 */ 333 more() 334 { 335 lprcat("\n --- press "); standout("space"); lprcat(" to continue --- "); 336 while (getchar() != ' '); 337 } 338 339 /* 340 function to put something in the players inventory 341 returns 0 if success, 1 if a failure 342 */ 343 take(itm,arg) 344 int itm,arg; 345 { 346 register int i,limit; 347 /* cursors(); */ 348 if ((limit = 15+(c[LEVEL]>>1)) > 26) limit=26; 349 for (i=0; i<limit; i++) 350 if (iven[i]==0) 351 { 352 iven[i] = itm; ivenarg[i] = arg; limit=0; 353 switch(itm) 354 { 355 case OPROTRING: case ODAMRING: case OBELT: limit=1; break; 356 case ODEXRING: c[DEXTERITY] += ivenarg[i]+1; limit=1; break; 357 case OSTRRING: c[STREXTRA] += ivenarg[i]+1; limit=1; break; 358 case OCLEVERRING: c[INTELLIGENCE] += ivenarg[i]+1; limit=1; break; 359 case OHAMMER: c[DEXTERITY] += 10; c[STREXTRA]+=10; 360 c[INTELLIGENCE]-=10; limit=1; break; 361 362 case OORBOFDRAGON: c[SLAYING]++; break; 363 case OSPIRITSCARAB: c[NEGATESPIRIT]++; break; 364 case OCUBEofUNDEAD: c[CUBEofUNDEAD]++; break; 365 case ONOTHEFT: c[NOTHEFT]++; break; 366 case OSWORDofSLASHING: c[DEXTERITY] +=5; limit=1; break; 367 }; 368 lprcat("\nYou pick up:"); srcount=0; show3(i); 369 if (limit) bottomline(); return(0); 370 } 371 lprcat("\nYou can't carry anything else"); return(1); 372 } 373 374 /* 375 subroutine to drop an object returns 1 if something there already else 0 376 */ 377 drop_object(k) 378 int k; 379 { 380 int itm; 381 if ((k<0) || (k>25)) return(0); 382 itm = iven[k]; cursors(); 383 if (itm==0) { lprintf("\nYou don't have item %c! ",k+'a'); return(1); } 384 if (item[playerx][playery]) 385 { beep(); lprcat("\nThere's something here already"); return(1); } 386 if (playery==MAXY-1 && playerx==33) return(1); /* not in entrance */ 387 item[playerx][playery] = itm; 388 iarg[playerx][playery] = ivenarg[k]; 389 srcount=0; lprcat("\n You drop:"); show3(k); /* show what item you dropped*/ 390 know[playerx][playery] = 0; iven[k]=0; 391 if (c[WIELD]==k) c[WIELD]= -1; if (c[WEAR]==k) c[WEAR] = -1; 392 if (c[SHIELD]==k) c[SHIELD]= -1; 393 adjustcvalues(itm,ivenarg[k]); 394 dropflag=1; /* say dropped an item so wont ask to pick it up right away */ 395 return(0); 396 } 397 398 /* 399 function to enchant armor player is currently wearing 400 */ 401 enchantarmor() 402 { 403 register int tmp; 404 if (c[WEAR]<0) { if (c[SHIELD] < 0) 405 { cursors(); beep(); lprcat("\nYou feel a sense of loss"); return; } 406 else { tmp=iven[c[SHIELD]]; if (tmp != OSCROLL) if (tmp != OPOTION) { ivenarg[c[SHIELD]]++; bottomline(); } } } 407 tmp = iven[c[WEAR]]; 408 if (tmp!=OSCROLL) if (tmp!=OPOTION) { ivenarg[c[WEAR]]++; bottomline(); } 409 } 410 411 /* 412 function to enchant a weapon presently being wielded 413 */ 414 enchweapon() 415 { 416 register int tmp; 417 if (c[WIELD]<0) 418 { cursors(); beep(); lprcat("\nYou feel a sense of loss"); return; } 419 tmp = iven[c[WIELD]]; 420 if (tmp!=OSCROLL) if (tmp!=OPOTION) 421 { ivenarg[c[WIELD]]++; 422 if (tmp==OCLEVERRING) c[INTELLIGENCE]++; else 423 if (tmp==OSTRRING) c[STREXTRA]++; else 424 if (tmp==ODEXRING) c[DEXTERITY]++; bottomline(); } 425 } 426 427 /* 428 routine to tell if player can carry one more thing 429 returns 1 if pockets are full, else 0 430 */ 431 pocketfull() 432 { 433 register int i,limit; 434 if ((limit = 15+(c[LEVEL]>>1)) > 26) limit=26; 435 for (i=0; i<limit; i++) if (iven[i]==0) return(0); 436 return(1); 437 } 438 439 /* 440 function to return 1 if a monster is next to the player else returns 0 441 */ 442 nearbymonst() 443 { 444 register int tmp,tmp2; 445 for (tmp=playerx-1; tmp<playerx+2; tmp++) 446 for (tmp2=playery-1; tmp2<playery+2; tmp2++) 447 if (mitem[tmp][tmp2]) return(1); /* if monster nearby */ 448 return(0); 449 } 450 451 /* 452 function to steal an item from the players pockets 453 returns 1 if steals something else returns 0 454 */ 455 stealsomething() 456 { 457 register int i,j; 458 j=100; 459 while (1) 460 { 461 i=rund(26); 462 if (iven[i]) if (c[WEAR]!=i) if (c[WIELD]!=i) if (c[SHIELD]!=i) 463 { 464 srcount=0; show3(i); 465 adjustcvalues(iven[i],ivenarg[i]); iven[i]=0; return(1); 466 } 467 if (--j <= 0) return(0); 468 } 469 } 470 471 /* 472 function to return 1 is player carrys nothing else return 0 473 */ 474 emptyhanded() 475 { 476 register int i; 477 for (i=0; i<26; i++) 478 if (iven[i]) if (i!=c[WIELD]) if (i!=c[WEAR]) if (i!=c[SHIELD]) return(0); 479 return(1); 480 } 481 482 /* 483 function to create a gem on a square near the player 484 */ 485 creategem() 486 { 487 register int i,j; 488 switch(rnd(4)) 489 { 490 case 1: i=ODIAMOND; j=50; break; 491 case 2: i=ORUBY; j=40; break; 492 case 3: i=OEMERALD; j=30; break; 493 default: i=OSAPPHIRE; j=20; break; 494 }; 495 createitem(i,rnd(j)+j/10); 496 } 497 498 /* 499 function to change character levels as needed when dropping an object 500 that affects these characteristics 501 */ 502 adjustcvalues(itm,arg) 503 int itm,arg; 504 { 505 register int flag; 506 flag=0; 507 switch(itm) 508 { 509 case ODEXRING: c[DEXTERITY] -= arg+1; flag=1; break; 510 case OSTRRING: c[STREXTRA] -= arg+1; flag=1; break; 511 case OCLEVERRING: c[INTELLIGENCE] -= arg+1; flag=1; break; 512 case OHAMMER: c[DEXTERITY] -= 10; c[STREXTRA] -= 10; 513 c[INTELLIGENCE] += 10; flag=1; break; 514 case OSWORDofSLASHING: c[DEXTERITY] -= 5; flag=1; break; 515 case OORBOFDRAGON: --c[SLAYING]; return; 516 case OSPIRITSCARAB: --c[NEGATESPIRIT]; return; 517 case OCUBEofUNDEAD: --c[CUBEofUNDEAD]; return; 518 case ONOTHEFT: --c[NOTHEFT]; return; 519 case OLANCE: c[LANCEDEATH]=0; return; 520 case OPOTION: case OSCROLL: return; 521 522 default: flag=1; 523 }; 524 if (flag) bottomline(); 525 } 526 527 /* 528 function to read a string from token input "string" 529 returns a pointer to the string 530 */ 531 gettokstr(str) 532 register char *str; 533 { 534 register int i,j; 535 i=50; 536 while ((getchar() != '"') && (--i > 0)); 537 i=36; 538 while (--i > 0) 539 { 540 if ((j=getchar()) != '"') *str++ = j; else i=0; 541 } 542 *str = 0; 543 i=50; 544 if (j != '"') while ((getchar() != '"') && (--i > 0)); /* if end due to too long, then find closing quote */ 545 } 546 547 /* 548 function to ask user for a password (no echo) 549 returns 1 if entered correctly, 0 if not 550 */ 551 static char gpwbuf[33]; 552 getpassword() 553 { 554 register int i,j; 555 register char *gpwp; 556 extern char *password; 557 scbr(); /* system("stty -echo cbreak"); */ 558 gpwp = gpwbuf; lprcat("\nEnter Password: "); lflush(); 559 i = strlen(password); 560 for (j=0; j<i; j++) read(0,gpwp++,1); gpwbuf[i]=0; 561 sncbr(); /* system("stty echo -cbreak"); */ 562 if (strcmp(gpwbuf,password) != 0) 563 { lprcat("\nSorry\n"); lflush(); return(0); } 564 else return(1); 565 } 566 567 /* 568 subroutine to get a yes or no response from the user 569 returns y or n 570 */ 571 getyn() 572 { 573 register int i; 574 i=0; while (i!='y' && i!='n' && i!='\33') i=getchar(); 575 return(i); 576 } 577 578 /* 579 function to calculate the pack weight of the player 580 returns the number of pounds the player is carrying 581 */ 582 packweight() 583 { 584 register int i,j,k; 585 k=c[GOLD]/1000; j=25; while ((iven[j]==0) && (j>0)) --j; 586 for (i=0; i<=j; i++) 587 switch(iven[i]) 588 { 589 case 0: break; 590 case OSSPLATE: case OPLATEARMOR: k += 40; break; 591 case OPLATE: k += 35; break; 592 case OHAMMER: k += 30; break; 593 case OSPLINT: k += 26; break; 594 case OSWORDofSLASHING: case OCHAIN: 595 case OBATTLEAXE: case O2SWORD: k += 23; break; 596 case OLONGSWORD: case OSWORD: 597 case ORING: case OFLAIL: k += 20; break; 598 case OLANCE: case OSTUDLEATHER: k += 15; break; 599 case OLEATHER: case OSPEAR: k += 8; break; 600 case OORBOFDRAGON: case OBELT: k += 4; break; 601 case OSHIELD: k += 7; break; 602 case OCHEST: k += 30 + ivenarg[i]; break; 603 default: k++; 604 }; 605 return(k); 606 } 607 608 #ifndef MACRORND 609 /* macros to generate random numbers 1<=rnd(N)<=N 0<=rund(N)<=N-1 */ 610 rnd(x) 611 int x; 612 { 613 return((((randx=randx*1103515245+12345)>>7)%(x))+1); 614 } 615 616 rund(x) 617 int x; 618 { 619 return((((randx=randx*1103515245+12345)>>7)%(x)) ); 620 } 621 #endif MACRORND 622