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