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