1 /* 2 * fight.c Phantasia monster fighting routines 3 * 4 * $FreeBSD: src/games/phantasia/fight.c,v 1.7 1999/11/16 02:57:33 billf Exp $ 5 * $DragonFly: src/games/phantasia/fight.c,v 1.3 2005/05/31 00:06:26 swildner Exp $ 6 */ 7 8 #include <string.h> 9 #include "include.h" 10 11 /* functions which we need to know about */ 12 /* io.c */ 13 extern int getanswer(const char *, bool); 14 extern void getstring(char *, int); 15 extern double infloat(void); 16 extern int inputoption(void); 17 extern void more(int); 18 /* misc.c */ 19 extern void altercoordinates(double, double, int); 20 extern void collecttaxes(double, double); 21 extern void death(const char *); 22 extern void displaystats(void); 23 extern void readmessage(void); 24 extern void truncstring(char *); 25 extern void writerecord(struct player *, long); 26 /* phantglobs.c */ 27 extern double drandom(void); 28 29 void encounter(int); 30 int pickmonster(void); 31 void playerhits(void); 32 void monsthits(void); 33 void cancelmonster(void); 34 void hitmonster(double); 35 void throwspell(void); 36 void callmonster(int); 37 void awardtreasure(void); 38 void cursedtreasure(void); 39 void scramblestats(void); 40 41 /************************************************************************ 42 / 43 / FUNCTION NAME: encounter() 44 / 45 / FUNCTION: monster battle routine 46 / 47 / AUTHOR: E. A. Estes, 2/20/86 48 / 49 / ARGUMENTS: 50 / int particular - particular monster to fight if >= 0 51 / 52 / RETURN VALUE: none 53 / 54 / MODULES CALLED: monsthits(), playerhits(), readmessage(), callmonster(), 55 / writerecord(), pickmonster(), displaystats(), pow(), cancelmonster(), 56 / awardtreasure(), more(), death(), wmove(), setjmp(), drandom(), printw(), 57 / longjmp(), wrefresh(), mvprintw(), wclrtobot() 58 / 59 / GLOBAL INPUTS: Curmonster, Whichmonster, LINES, Lines, Circle, Shield, 60 / Player, *stdscr, Fileloc, Fightenv[], *Enemyname 61 / 62 / GLOBAL OUTPUTS: Curmonster, Whichmonster, Lines, Shield, Player, Luckout 63 / 64 / DESCRIPTION: 65 / Choose a monster and check against some special types. 66 / Arbitrate between monster and player. Watch for either 67 / dying. 68 / 69 *************************************************************************/ 70 71 void 72 encounter(int particular) 73 { 74 volatile bool firsthit = Player.p_blessing; /* set if player gets the first hit */ 75 int flockcnt = 1; /* how many time flocked */ 76 77 /* let others know what we are doing */ 78 Player.p_status = S_MONSTER; 79 writerecord(&Player, Fileloc); 80 81 #ifdef SYS5 82 flushinp(); 83 #endif 84 85 Shield = 0.0; /* no shield up yet */ 86 87 if (particular >= 0) 88 /* monster is specified */ 89 Whichmonster = particular; 90 else 91 /* pick random monster */ 92 Whichmonster = pickmonster(); 93 94 setjmp(Fightenv); /* this is to enable changing fight state */ 95 96 move(6, 0); 97 clrtobot(); /* clear bottom area of screen */ 98 99 Lines = 9; 100 callmonster(Whichmonster); /* set up monster to fight */ 101 102 Luckout = FALSE; /* haven't tried to luckout yet */ 103 104 if (Curmonster.m_type == SM_MORGOTH) 105 mvprintw(4, 0, "You've encountered %s, Bane of the Council and Valar.\n", 106 Enemyname); 107 108 if (Curmonster.m_type == SM_UNICORN) 109 { 110 if (Player.p_virgin) 111 { 112 printw("You just subdued %s, thanks to the virgin.\n", Enemyname); 113 Player.p_virgin = FALSE; 114 } 115 else 116 { 117 printw("You just saw %s running away!\n", Enemyname); 118 Curmonster.m_experience = 0.0; 119 Curmonster.m_treasuretype = 0; 120 } 121 } 122 else 123 /* not a special monster */ 124 for (;;) 125 /* print header, and arbitrate between player and monster */ 126 { 127 mvprintw(6, 0, "You are being attacked by %s, EXP: %.0f (Size: %.0f)\n", 128 Enemyname, Curmonster.m_experience, Circle); 129 130 displaystats(); 131 mvprintw(1, 26, "%20.0f", Player.p_energy + Shield); /* overprint energy */ 132 readmessage(); 133 134 if (Curmonster.m_type == SM_DARKLORD 135 && Player.p_blessing 136 && Player.p_charms > 0) 137 /* overpower Dark Lord with blessing and charm */ 138 { 139 mvprintw(7, 0, "You just overpowered %s!", Enemyname); 140 Lines = 8; 141 Player.p_blessing = FALSE; 142 --Player.p_charms; 143 break; 144 } 145 146 /* allow paralyzed monster to wake up */ 147 Curmonster.m_speed = MIN(Curmonster.m_speed + 1.0, Curmonster.m_maxspeed); 148 149 if (drandom() * Curmonster.m_speed > drandom() * Player.p_speed 150 /* monster is faster */ 151 && Curmonster.m_type != SM_DARKLORD 152 /* not D. L. */ 153 && Curmonster.m_type != SM_SHRIEKER 154 /* not mimic */ 155 && !firsthit) 156 /* monster gets a hit */ 157 monsthits(); 158 else 159 /* player gets a hit */ 160 { 161 firsthit = FALSE; 162 playerhits(); 163 } 164 165 refresh(); 166 167 if (Lines > LINES - 2) 168 /* near bottom of screen - pause */ 169 { 170 more(Lines); 171 move(Lines = 8, 0); 172 clrtobot(); 173 } 174 175 if (Player.p_energy <= 0.0) 176 /* player died */ 177 { 178 more(Lines); 179 death(Enemyname); 180 cancelmonster(); 181 break; /* fight ends if the player is saved from death */ 182 } 183 184 if (Curmonster.m_energy <= 0.0) 185 /* monster died */ 186 break; 187 } 188 189 /* give player credit for killing monster */ 190 Player.p_experience += Curmonster.m_experience; 191 192 if (drandom() < Curmonster.m_flock / 100.0) 193 /* monster flocks */ 194 { 195 more(Lines); 196 ++flockcnt; 197 longjmp(Fightenv, 0); 198 /*NOTREACHED*/ 199 } 200 else if (Circle > 1.0 201 && Curmonster.m_treasuretype > 0 202 && drandom() > 0.2 + pow(0.4, (double) (flockcnt / 3 + Circle / 3.0))) 203 /* monster has treasure; this takes # of flocks and size into account */ 204 { 205 more(Lines); 206 awardtreasure(); 207 } 208 209 /* pause before returning */ 210 getyx(stdscr, Lines, flockcnt); 211 more(Lines + 1); 212 213 Player.p_ring.ring_inuse = FALSE; /* not using ring */ 214 215 /* clean up the screen */ 216 move(4, 0); 217 clrtobot(); 218 } 219 /**/ 220 /************************************************************************ 221 / 222 / FUNCTION NAME: pickmonster() 223 / 224 / FUNCTION: choose a monster based upon where we are 225 / 226 / AUTHOR: E. A. Estes, 2/20/86 227 / 228 / ARGUMENTS: none 229 / 230 / RETURN VALUE: monster number to call 231 / 232 / MODULES CALLED: floor(), drandom() 233 / 234 / GLOBAL INPUTS: Marsh, Circle, Player 235 / 236 / GLOBAL OUTPUTS: none 237 / 238 / DESCRIPTION: 239 / Certain monsters can be found in certain areas of the grid. 240 / We take care of rolling them here. 241 / Unfortunately, this routine assumes that the monster data 242 / base is arranged in a particular order. If the data base 243 / is altered (to add monsters, or make them tougher), this 244 / routine may also need to be changed. 245 / 246 *************************************************************************/ 247 248 int 249 pickmonster(void) 250 { 251 if (Player.p_specialtype == SC_VALAR) 252 /* even chance of any monster */ 253 return((int) ROLL(0.0, 100.0)); 254 255 if (Marsh) 256 /* water monsters */ 257 return((int) ROLL(0.0, 15.0)); 258 259 else if (Circle > 24) 260 /* even chance of all non-water monsters */ 261 return((int) ROLL(14.0, 86.0)); 262 263 else if (Circle > 15) 264 /* chance of all non-water monsters, weighted toward middle */ 265 return((int) (ROLL(0.0, 50.0) + ROLL(14.0, 37.0))); 266 267 else if (Circle > 8) 268 /* not all non-water monsters, weighted toward middle */ 269 return((int) (ROLL(0.0, 50.0) + ROLL(14.0, 26.0))); 270 271 else if (Circle > 3) 272 /* even chance of some tamer non-water monsters */ 273 return((int) ROLL(14.0, 50.0)); 274 275 else 276 /* even chance of some of the tamest non-water monsters */ 277 return((int) ROLL(14.0, 25.0)); 278 } 279 /**/ 280 /************************************************************************ 281 / 282 / FUNCTION NAME: playerhits() 283 / 284 / FUNCTION: prompt player for action in monster battle, and process 285 / 286 / AUTHOR: E. A. Estes, 12/4/85 287 / 288 / ARGUMENTS: none 289 / 290 / RETURN VALUE: none 291 / 292 / MODULES CALLED: hitmonster(), throwspell(), inputoption(), cancelmonster(), 293 / floor(), wmove(), drandom(), altercoordinates(), waddstr(), mvprintw(), 294 / wclrtoeol(), wclrtobot() 295 / 296 / GLOBAL INPUTS: Curmonster, Lines, Player, *stdscr, Luckout, *Enemyname 297 / 298 / GLOBAL OUTPUTS: Curmonster, Lines, Player, Luckout 299 / 300 / DESCRIPTION: 301 / Process all monster battle options. 302 / 303 *************************************************************************/ 304 305 void 306 playerhits(void) 307 { 308 double inflict; /* damage inflicted */ 309 int ch; /* input */ 310 311 mvaddstr(7, 0, "1:Melee 2:Skirmish 3:Evade 4:Spell 5:Nick "); 312 313 if (!Luckout) { 314 /* haven't tried to luckout yet */ 315 if (Curmonster.m_type == SM_MORGOTH) 316 /* cannot luckout against Morgoth */ 317 addstr("6:Ally "); 318 else 319 addstr("6:Luckout "); 320 } 321 322 if (Player.p_ring.ring_type != R_NONE) 323 /* player has a ring */ 324 addstr("7:Use Ring "); 325 else 326 clrtoeol(); 327 328 ch = inputoption(); 329 330 move(8, 0); 331 clrtobot(); /* clear any messages from before */ 332 Lines = 9; 333 mvaddstr(4, 0, "\n\n"); /* clear status area */ 334 335 switch (ch) 336 { 337 case 'T': /* timeout; lose turn */ 338 break; 339 340 case ' ': 341 case '1': /* melee */ 342 /* melee affects monster's energy and strength */ 343 inflict = ROLL(Player.p_might / 2.0 + 5.0, 1.3 * Player.p_might) 344 + (Player.p_ring.ring_inuse ? Player.p_might : 0.0); 345 346 Curmonster.m_melee += inflict; 347 Curmonster.m_strength = Curmonster.m_o_strength 348 - Curmonster.m_melee / Curmonster.m_o_energy 349 * Curmonster.m_o_strength / 4.0; 350 hitmonster(inflict); 351 break; 352 353 case '2': /* skirmish */ 354 /* skirmish affects monter's energy and speed */ 355 inflict = ROLL(Player.p_might / 3.0 + 3.0, 1.1 * Player.p_might) 356 + (Player.p_ring.ring_inuse ? Player.p_might : 0.0); 357 358 Curmonster.m_skirmish += inflict; 359 Curmonster.m_maxspeed = Curmonster.m_o_speed 360 - Curmonster.m_skirmish / Curmonster.m_o_energy 361 * Curmonster.m_o_speed / 4.0; 362 hitmonster(inflict); 363 break; 364 365 case '3': /* evade */ 366 /* use brains and speed to try to evade */ 367 if ((Curmonster.m_type == SM_DARKLORD 368 || Curmonster.m_type == SM_SHRIEKER 369 /* can always run from D. L. and shrieker */ 370 || drandom() * Player.p_speed * Player.p_brains 371 > drandom() * Curmonster.m_speed * Curmonster.m_brains) 372 && (Curmonster.m_type != SM_MIMIC)) 373 /* cannot run from mimic */ 374 { 375 mvaddstr(Lines++, 0, "You got away!"); 376 cancelmonster(); 377 altercoordinates(0.0, 0.0, A_NEAR); 378 } 379 else 380 mvprintw(Lines++, 0, "%s is still after you!", Enemyname); 381 382 break; 383 384 case 'M': 385 case '4': /* magic spell */ 386 throwspell(); 387 break; 388 389 case '5': /* nick */ 390 /* hit 1 plus sword; give some experience */ 391 inflict = 1.0 + Player.p_sword; 392 Player.p_experience += floor(Curmonster.m_experience / 10.0); 393 Curmonster.m_experience *= 0.92; 394 /* monster gets meaner */ 395 Curmonster.m_maxspeed += 2.0; 396 Curmonster.m_speed = (Curmonster.m_speed < 0.0) ? 0.0 : Curmonster.m_speed + 2.0; 397 if (Curmonster.m_type == SM_DARKLORD) 398 /* Dark Lord; doesn't like to be nicked */ 399 { 400 mvprintw(Lines++, 0, 401 "You hit %s %.0f times, and made him mad!", Enemyname, inflict); 402 Player.p_quickness /= 2.0; 403 altercoordinates(0.0, 0.0, A_FAR); 404 cancelmonster(); 405 } 406 else 407 hitmonster(inflict); 408 break; 409 410 case 'B': 411 case '6': /* luckout */ 412 if (Luckout) 413 mvaddstr(Lines++, 0, "You already tried that."); 414 else 415 { 416 Luckout = TRUE; 417 if (Curmonster.m_type == SM_MORGOTH) 418 /* Morgoth; ally */ 419 { 420 if (drandom() < Player.p_sin / 100.0) 421 { 422 mvprintw(Lines++, 0, "%s accepted!", Enemyname); 423 cancelmonster(); 424 } 425 else 426 mvaddstr(Lines++, 0, "Nope, he's not interested."); 427 } 428 else 429 /* normal monster; use brains for success */ 430 { 431 if ((drandom() + 0.333) * Player.p_brains 432 < (drandom() + 0.333) * Curmonster.m_brains) 433 mvprintw(Lines++, 0, "You blew it, %s.", Player.p_name); 434 else 435 { 436 mvaddstr(Lines++, 0, "You made it!"); 437 Curmonster.m_energy = 0.0; 438 } 439 } 440 } 441 break; 442 443 case '7': /* use ring */ 444 if (Player.p_ring.ring_type != R_NONE) 445 { 446 mvaddstr(Lines++, 0, "Now using ring."); 447 Player.p_ring.ring_inuse = TRUE; 448 if (Player.p_ring.ring_type != R_DLREG) 449 /* age ring */ 450 --Player.p_ring.ring_duration; 451 } 452 break; 453 } 454 455 } 456 /**/ 457 /************************************************************************ 458 / 459 / FUNCTION NAME: monsthits() 460 / 461 / FUNCTION: process a monster hitting the player 462 / 463 / AUTHOR: E. A. Estes, 12/4/85 464 / 465 / ARGUMENTS: none 466 / 467 / RETURN VALUE: none 468 / 469 / MODULES CALLED: cancelmonster(), scramblestats(), more(), floor(), wmove(), 470 / drandom(), altercoordinates(), longjmp(), waddstr(), mvprintw(), 471 / getanswer() 472 / 473 / GLOBAL INPUTS: Curmonster, Lines, Circle, Shield, Player, *stdscr, 474 / Fightenv[], *Enemyname 475 / 476 / GLOBAL OUTPUTS: Curmonster, Whichmonster, Lines, Shield, Player, 477 / *Enemyname 478 / 479 / DESCRIPTION: 480 / Handle all special monsters here. If the monster is not a special 481 / one, simply roll a hit against the player. 482 / 483 *************************************************************************/ 484 485 void 486 monsthits(void) 487 { 488 double inflict; /* damage inflicted */ 489 int ch; /* input */ 490 491 switch (Curmonster.m_type) 492 /* may be a special monster */ 493 { 494 case SM_DARKLORD: 495 /* hits just enough to kill player */ 496 inflict = (Player.p_energy + Shield) * 1.02; 497 goto SPECIALHIT; 498 499 case SM_SHRIEKER: 500 /* call a big monster */ 501 mvaddstr(Lines++, 0, 502 "Shrieeeek!! You scared it, and it called one of its friends."); 503 more(Lines); 504 Whichmonster = (int) ROLL(70.0, 30.0); 505 longjmp(Fightenv, 0); 506 /*NOTREACHED*/ 507 508 case SM_BALROG: 509 /* take experience away */ 510 inflict = ROLL(10.0, Curmonster.m_strength); 511 inflict = MIN(Player.p_experience, inflict); 512 mvprintw(Lines++, 0, 513 "%s took away %.0f experience points.", Enemyname, inflict); 514 Player.p_experience -= inflict; 515 return; 516 517 case SM_FAERIES: 518 if (Player.p_holywater > 0) 519 /* holy water kills when monster tries to hit */ 520 { 521 mvprintw(Lines++, 0, "Your holy water killed it!"); 522 --Player.p_holywater; 523 Curmonster.m_energy = 0.0; 524 return; 525 } 526 break; 527 528 case SM_NONE: 529 /* normal hit */ 530 break; 531 532 default: 533 if (drandom() > 0.2) 534 /* normal hit */ 535 break; 536 537 /* else special things */ 538 switch (Curmonster.m_type) 539 { 540 case SM_LEANAN: 541 /* takes some of the player's strength */ 542 inflict = ROLL(1.0, (Circle - 1.0) / 2.0); 543 inflict = MIN(Player.p_strength, inflict); 544 mvprintw(Lines++, 0, "%s sapped %0.f of your strength!", 545 Enemyname, inflict); 546 Player.p_strength -= inflict; 547 Player.p_might -= inflict; 548 break; 549 550 case SM_SARUMAN: 551 if (Player.p_palantir) 552 /* take away palantir */ 553 { 554 mvprintw(Lines++, 0, "Wormtongue stole your palantir!"); 555 Player.p_palantir = FALSE; 556 } 557 else if (drandom() > 0.5) 558 /* gems turn to gold */ 559 { 560 mvprintw(Lines++, 0, 561 "%s transformed your gems into gold!", Enemyname); 562 Player.p_gold += Player.p_gems; 563 Player.p_gems = 0.0; 564 } 565 else 566 /* scramble some stats */ 567 { 568 mvprintw(Lines++, 0, "%s scrambled your stats!", Enemyname); 569 scramblestats(); 570 } 571 break; 572 573 case SM_THAUMATURG: 574 /* transport player */ 575 mvprintw(Lines++, 0, "%s transported you!", Enemyname); 576 altercoordinates(0.0, 0.0, A_FAR); 577 cancelmonster(); 578 break; 579 580 case SM_VORTEX: 581 /* suck up some mana */ 582 inflict = ROLL(0, 7.5 * Circle); 583 inflict = MIN(Player.p_mana, floor(inflict)); 584 mvprintw(Lines++, 0, 585 "%s sucked up %.0f of your mana!", Enemyname, inflict); 586 Player.p_mana -= inflict; 587 break; 588 589 case SM_NAZGUL: 590 /* try to take ring if player has one */ 591 if (Player.p_ring.ring_type != R_NONE) 592 /* player has a ring */ 593 { 594 mvaddstr(Lines++, 0, "Will you relinguish your ring ? "); 595 ch = getanswer("YN", FALSE); 596 if (ch == 'Y') 597 /* take ring away */ 598 { 599 Player.p_ring.ring_type = R_NONE; 600 Player.p_ring.ring_inuse = FALSE; 601 cancelmonster(); 602 break; 603 } 604 } 605 606 /* otherwise, take some brains */ 607 mvprintw(Lines++, 0, 608 "%s neutralized 1/5 of your brain!", Enemyname); 609 Player.p_brains *= 0.8; 610 break; 611 612 case SM_TIAMAT: 613 /* take some gold and gems */ 614 mvprintw(Lines++, 0, 615 "%s took half your gold and gems and flew off.", Enemyname); 616 Player.p_gold /= 2.0; 617 Player.p_gems /= 2.0; 618 cancelmonster(); 619 break; 620 621 case SM_KOBOLD: 622 /* steal a gold piece and run */ 623 mvprintw(Lines++, 0, 624 "%s stole one gold piece and ran away.", Enemyname); 625 Player.p_gold = MAX(0.0, Player.p_gold - 1.0); 626 cancelmonster(); 627 break; 628 629 case SM_SHELOB: 630 /* bite and (medium) poison */ 631 mvprintw(Lines++, 0, 632 "%s has bitten and poisoned you!", Enemyname); 633 Player.p_poison -= 1.0; 634 break; 635 636 case SM_LAMPREY: 637 /* bite and (small) poison */ 638 mvprintw(Lines++, 0, "%s bit and poisoned you!", Enemyname); 639 Player.p_poison += 0.25; 640 break; 641 642 case SM_BONNACON: 643 /* fart and run */ 644 mvprintw(Lines++, 0, "%s farted and scampered off.", Enemyname); 645 Player.p_energy /= 2.0; /* damage from fumes */ 646 cancelmonster(); 647 break; 648 649 case SM_SMEAGOL: 650 if (Player.p_ring.ring_type != R_NONE) 651 /* try to steal ring */ 652 { 653 mvprintw(Lines++, 0, 654 "%s tried to steal your ring, ", Enemyname); 655 if (drandom() > 0.1) 656 addstr("but was unsuccessful."); 657 else 658 { 659 addstr("and ran away with it!"); 660 Player.p_ring.ring_type = R_NONE; 661 cancelmonster(); 662 } 663 } 664 break; 665 666 case SM_SUCCUBUS: 667 /* inflict damage through shield */ 668 inflict = ROLL(15.0, Circle * 10.0); 669 inflict = MIN(inflict, Player.p_energy); 670 mvprintw(Lines++, 0, "%s sapped %.0f of your energy.", 671 Enemyname, inflict); 672 Player.p_energy -= inflict; 673 break; 674 675 case SM_CERBERUS: 676 /* take all metal treasures */ 677 mvprintw(Lines++, 0, 678 "%s took all your metal treasures!", Enemyname); 679 Player.p_crowns = 0; 680 Player.p_sword = 681 Player.p_shield = 682 Player.p_gold = 0.0; 683 cancelmonster(); 684 break; 685 686 case SM_UNGOLIANT: 687 /* (large) poison and take a quickness */ 688 mvprintw(Lines++, 0, 689 "%s poisoned you, and took one quik.", Enemyname); 690 Player.p_poison += 5.0; 691 Player.p_quickness -= 1.0; 692 break; 693 694 case SM_JABBERWOCK: 695 /* fly away, and leave either a Jubjub bird or Bonnacon */ 696 mvprintw(Lines++, 0, 697 "%s flew away, and left you to contend with one of its friends.", 698 Enemyname); 699 Whichmonster = 55 + (drandom() > 0.5) ? 22 : 0; 700 longjmp(Fightenv, 0); 701 /*NOTREACHED*/ 702 703 case SM_TROLL: 704 /* partially regenerate monster */ 705 mvprintw(Lines++, 0, 706 "%s partially regenerated his energy.!", Enemyname); 707 Curmonster.m_energy += 708 floor((Curmonster.m_o_energy - Curmonster.m_energy) / 2.0); 709 Curmonster.m_strength = Curmonster.m_o_strength; 710 Curmonster.m_melee = Curmonster.m_skirmish = 0.0; 711 Curmonster.m_maxspeed = Curmonster.m_o_speed; 712 break; 713 714 case SM_WRAITH: 715 if (!Player.p_blindness) 716 /* make blind */ 717 { 718 mvprintw(Lines++, 0, "%s blinded you!", Enemyname); 719 Player.p_blindness = TRUE; 720 Enemyname = "A monster"; 721 } 722 break; 723 } 724 return; 725 } 726 727 /* fall through to here if monster inflicts a normal hit */ 728 inflict = drandom() * Curmonster.m_strength + 0.5; 729 SPECIALHIT: 730 mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, inflict); 731 732 if ((Shield -= inflict) < 0) 733 { 734 Player.p_energy += Shield; 735 Shield = 0.0; 736 } 737 } 738 /**/ 739 /************************************************************************ 740 / 741 / FUNCTION NAME: cancelmonster() 742 / 743 / FUNCTION: mark current monster as no longer active 744 / 745 / AUTHOR: E. A. Estes, 12/4/85 746 / 747 / ARGUMENTS: none 748 / 749 / RETURN VALUE: none 750 / 751 / MODULES CALLED: none 752 / 753 / GLOBAL INPUTS: none 754 / 755 / GLOBAL OUTPUTS: Curmonster 756 / 757 / DESCRIPTION: 758 / Clear current monster's energy, experience, treasure type, and 759 / flock. This is the same as having the monster run away. 760 / 761 *************************************************************************/ 762 763 void 764 cancelmonster(void) 765 { 766 Curmonster.m_energy = 0.0; 767 Curmonster.m_experience = 0.0; 768 Curmonster.m_treasuretype = 0; 769 Curmonster.m_flock = 0.0; 770 } 771 /**/ 772 /************************************************************************ 773 / 774 / FUNCTION NAME: hitmonster() 775 / 776 / FUNCTION: inflict damage upon current monster 777 / 778 / AUTHOR: E. A. Estes, 12/4/85 779 / 780 / ARGUMENTS: 781 / double inflict - damage to inflict upon monster 782 / 783 / RETURN VALUE: none 784 / 785 / MODULES CALLED: monsthits(), wmove(), strcmp(), waddstr(), mvprintw() 786 / 787 / GLOBAL INPUTS: Curmonster, Lines, Player, *stdscr, *Enemyname 788 / 789 / GLOBAL OUTPUTS: Curmonster, Lines 790 / 791 / DESCRIPTION: 792 / Hit monster specified number of times. Handle when monster dies, 793 / and a few special monsters. 794 / 795 *************************************************************************/ 796 797 void 798 hitmonster(double inflict) 799 { 800 mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, inflict); 801 Curmonster.m_energy -= inflict; 802 if (Curmonster.m_energy > 0.0) 803 { 804 if (Curmonster.m_type == SM_DARKLORD || Curmonster.m_type == SM_SHRIEKER) 805 /* special monster didn't die */ 806 monsthits(); 807 } 808 else 809 /* monster died. print message. */ 810 { 811 if (Curmonster.m_type == SM_MORGOTH) 812 mvaddstr(Lines++, 0, "You have defeated Morgoth, but he may return. . ."); 813 else 814 /* all other types of monsters */ 815 { 816 mvprintw(Lines++, 0, "You killed it. Good work, %s.", Player.p_name); 817 818 if (Curmonster.m_type == SM_MIMIC 819 && strcmp(Curmonster.m_name, "A Mimic") != 0 820 && !Player.p_blindness) 821 mvaddstr(Lines++, 0, "The body slowly changes into the form of a mimic."); 822 } 823 } 824 } 825 /**/ 826 /************************************************************************ 827 / 828 / FUNCTION NAME: throwspell() 829 / 830 / FUNCTION: throw a magic spell 831 / 832 / AUTHOR: E. A. Estes, 12/4/85 833 / 834 / ARGUMENTS: none 835 / 836 / RETURN VALUE: none 837 / 838 / MODULES CALLED: hitmonster(), cancelmonster(), sqrt(), floor(), wmove(), 839 / drandom(), altercoordinates(), longjmp(), infloat(), waddstr(), mvprintw(), 840 / getanswer() 841 / 842 / GLOBAL INPUTS: Curmonster, Whichmonster, Nomana[], Player, *stdscr, 843 / Fightenv[], Illspell[], *Enemyname 844 / 845 / GLOBAL OUTPUTS: Curmonster, Whichmonster, Shield, Player 846 / 847 / DESCRIPTION: 848 / Prompt player and process magic spells. 849 / 850 *************************************************************************/ 851 852 void 853 throwspell(void) 854 { 855 double inflict = 0; /* damage inflicted */ 856 double dtemp; /* for dtemporary calculations */ 857 int ch; /* input */ 858 859 mvaddstr(7, 0, "\n\n"); /* clear menu area */ 860 861 if (Player.p_magiclvl >= ML_ALLORNOTHING) 862 mvaddstr(7, 0, "1:All or Nothing "); 863 if (Player.p_magiclvl >= ML_MAGICBOLT) 864 addstr("2:Magic Bolt "); 865 if (Player.p_magiclvl >= ML_FORCEFIELD) 866 addstr("3:Force Field "); 867 if (Player.p_magiclvl >= ML_XFORM) 868 addstr("4:Transform "); 869 if (Player.p_magiclvl >= ML_INCRMIGHT) 870 addstr("5:Increase Might\n"); 871 if (Player.p_magiclvl >= ML_INVISIBLE) 872 mvaddstr(8, 0, "6:Invisibility "); 873 if (Player.p_magiclvl >= ML_XPORT) 874 addstr("7:Transport "); 875 if (Player.p_magiclvl >= ML_PARALYZE) 876 addstr("8:Paralyze "); 877 if (Player.p_specialtype >= SC_COUNCIL) 878 addstr("9:Specify"); 879 mvaddstr(4, 0, "Spell ? "); 880 881 ch = getanswer(" ", TRUE); 882 883 mvaddstr(7, 0, "\n\n"); /* clear menu area */ 884 885 if (Curmonster.m_type == SM_MORGOTH && ch != '3') 886 /* can only throw force field against Morgoth */ 887 ILLSPELL(); 888 else 889 switch (ch) 890 { 891 case '1': /* all or nothing */ 892 if (drandom() < 0.25) 893 /* success */ 894 { 895 inflict = Curmonster.m_energy * 1.01 + 1.0; 896 897 if (Curmonster.m_type == SM_DARKLORD) 898 /* all or nothing doesn't quite work against D. L. */ 899 inflict *= 0.9; 900 } 901 else 902 /* failure -- monster gets stronger and quicker */ 903 { 904 Curmonster.m_o_strength = Curmonster.m_strength *= 2.0; 905 Curmonster.m_maxspeed *= 2.0; 906 Curmonster.m_o_speed *= 2.0; 907 908 /* paralyzed monsters wake up a bit */ 909 Curmonster.m_speed = MAX(1.0, Curmonster.m_speed * 2.0); 910 } 911 912 if (Player.p_mana >= MM_ALLORNOTHING) 913 /* take a mana if player has one */ 914 Player.p_mana -= MM_ALLORNOTHING; 915 916 hitmonster(inflict); 917 break; 918 919 case '2': /* magic bolt */ 920 if (Player.p_magiclvl < ML_MAGICBOLT) 921 ILLSPELL(); 922 else 923 { 924 do 925 /* prompt for amount to expend */ 926 { 927 mvaddstr(4, 0, "How much mana for bolt? "); 928 dtemp = floor(infloat()); 929 } 930 while (dtemp < 0.0 || dtemp > Player.p_mana); 931 932 Player.p_mana -= dtemp; 933 934 if (Curmonster.m_type == SM_DARKLORD) 935 /* magic bolts don't work against D. L. */ 936 inflict = 0.0; 937 else 938 inflict = dtemp * ROLL(15.0, sqrt(Player.p_magiclvl / 3.0 + 1.0)); 939 mvaddstr(5, 0, "Magic Bolt fired!\n"); 940 hitmonster(inflict); 941 } 942 break; 943 944 case '3': /* force field */ 945 if (Player.p_magiclvl < ML_FORCEFIELD) 946 ILLSPELL(); 947 else if (Player.p_mana < MM_FORCEFIELD) 948 NOMANA(); 949 else 950 { 951 Player.p_mana -= MM_FORCEFIELD; 952 Shield = (Player.p_maxenergy + Player.p_shield) * 4.2 + 45.0; 953 mvaddstr(5, 0, "Force Field up.\n"); 954 } 955 break; 956 957 case '4': /* transform */ 958 if (Player.p_magiclvl < ML_XFORM) 959 ILLSPELL(); 960 else if (Player.p_mana < MM_XFORM) 961 NOMANA(); 962 else 963 { 964 Player.p_mana -= MM_XFORM; 965 Whichmonster = (int) ROLL(0.0, 100.0); 966 longjmp(Fightenv, 0); 967 /*NOTREACHED*/ 968 } 969 break; 970 971 case '5': /* increase might */ 972 if (Player.p_magiclvl < ML_INCRMIGHT) 973 ILLSPELL(); 974 else if (Player.p_mana < MM_INCRMIGHT) 975 NOMANA(); 976 else 977 { 978 Player.p_mana -= MM_INCRMIGHT; 979 Player.p_might += 980 (1.2 * (Player.p_strength + Player.p_sword) 981 + 5.0 - Player.p_might) / 2.0; 982 mvprintw(5, 0, "New strength: %.0f\n", Player.p_might); 983 } 984 break; 985 986 case '6': /* invisible */ 987 if (Player.p_magiclvl < ML_INVISIBLE) 988 ILLSPELL(); 989 else if (Player.p_mana < MM_INVISIBLE) 990 NOMANA(); 991 else 992 { 993 Player.p_mana -= MM_INVISIBLE; 994 Player.p_speed += 995 (1.2 * (Player.p_quickness + Player.p_quksilver) 996 + 5.0 - Player.p_speed) / 2.0; 997 mvprintw(5, 0, "New quickness: %.0f\n", Player.p_speed); 998 } 999 break; 1000 1001 case '7': /* transport */ 1002 if (Player.p_magiclvl < ML_XPORT) 1003 ILLSPELL(); 1004 else if (Player.p_mana < MM_XPORT) 1005 NOMANA(); 1006 else 1007 { 1008 Player.p_mana -= MM_XPORT; 1009 if (Player.p_brains + Player.p_magiclvl 1010 < Curmonster.m_experience / 200.0 * drandom()) 1011 { 1012 mvaddstr(5, 0, "Transport backfired!\n"); 1013 altercoordinates(0.0, 0.0, A_FAR); 1014 cancelmonster(); 1015 } 1016 else 1017 { 1018 mvprintw(5, 0, "%s is transported.\n", Enemyname); 1019 if (drandom() < 0.3) 1020 /* monster didn't drop its treasure */ 1021 Curmonster.m_treasuretype = 0; 1022 1023 Curmonster.m_energy = 0.0; 1024 } 1025 } 1026 break; 1027 1028 case '8': /* paralyze */ 1029 if (Player.p_magiclvl < ML_PARALYZE) 1030 ILLSPELL(); 1031 else if (Player.p_mana < MM_PARALYZE) 1032 NOMANA(); 1033 else 1034 { 1035 Player.p_mana -= MM_PARALYZE; 1036 if (Player.p_magiclvl > 1037 Curmonster.m_experience / 1000.0 * drandom()) 1038 { 1039 mvprintw(5, 0, "%s is held.\n", Enemyname); 1040 Curmonster.m_speed = -2.0; 1041 } 1042 else 1043 mvaddstr(5, 0, "Monster unaffected.\n"); 1044 } 1045 break; 1046 1047 case '9': /* specify */ 1048 if (Player.p_specialtype < SC_COUNCIL) 1049 ILLSPELL(); 1050 else if (Player.p_mana < MM_SPECIFY) 1051 NOMANA(); 1052 else 1053 { 1054 Player.p_mana -= MM_SPECIFY; 1055 mvaddstr(5, 0, "Which monster do you want [0-99] ? "); 1056 Whichmonster = (int) infloat(); 1057 Whichmonster = MAX(0, MIN(99, Whichmonster)); 1058 longjmp(Fightenv, 0); 1059 /*NOTREACHED*/ 1060 } 1061 break; 1062 } 1063 } 1064 /**/ 1065 /************************************************************************ 1066 / 1067 / FUNCTION NAME: callmonster() 1068 / 1069 / FUNCTION: read monster from file, and fill structure 1070 / 1071 / AUTHOR: E. A. Estes, 2/25/86 1072 / 1073 / ARGUMENTS: 1074 / int which - which monster to call 1075 / 1076 / RETURN VALUE: none 1077 / 1078 / MODULES CALLED: truncstring(), fread(), fseek(), floor(), drandom(), 1079 / strcpy() 1080 / 1081 / GLOBAL INPUTS: Curmonster, Circle, Player, *Monstfp 1082 / 1083 / GLOBAL OUTPUTS: Curmonster, Player, *Enemyname 1084 / 1085 / DESCRIPTION: 1086 / Read specified monster from monster database and fill up 1087 / current monster structure. 1088 / Adjust statistics based upon current size. 1089 / Handle some special monsters. 1090 / 1091 *************************************************************************/ 1092 1093 void 1094 callmonster(int which) 1095 { 1096 struct monster Othermonster; /* to find a name for mimics */ 1097 1098 which = MIN(which, 99); /* make sure within range */ 1099 1100 /* fill structure */ 1101 fseek(Monstfp, (long) which * (long) SZ_MONSTERSTRUCT, 0); 1102 fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp); 1103 1104 /* handle some special monsters */ 1105 if (Curmonster.m_type == SM_MODNAR) 1106 { 1107 if (Player.p_specialtype < SC_COUNCIL) 1108 /* randomize some stats */ 1109 { 1110 Curmonster.m_strength *= drandom() + 0.5; 1111 Curmonster.m_brains *= drandom() + 0.5; 1112 Curmonster.m_speed *= drandom() + 0.5; 1113 Curmonster.m_energy *= drandom() + 0.5; 1114 Curmonster.m_experience *= drandom() + 0.5; 1115 Curmonster.m_treasuretype = 1116 (int) ROLL(0.0, (double) Curmonster.m_treasuretype); 1117 } 1118 else 1119 /* make Modnar into Morgoth */ 1120 { 1121 strcpy(Curmonster.m_name, "Morgoth"); 1122 Curmonster.m_strength = drandom() * (Player.p_maxenergy + Player.p_shield) / 1.4 1123 + drandom() * (Player.p_maxenergy + Player.p_shield) / 1.5; 1124 Curmonster.m_brains = Player.p_brains; 1125 Curmonster.m_energy = Player.p_might * 30.0; 1126 Curmonster.m_type = SM_MORGOTH; 1127 Curmonster.m_speed = Player.p_speed * 1.1 1128 + (Player.p_specialtype == SC_EXVALAR) ? Player.p_speed : 0.0; 1129 Curmonster.m_flock = 0.0; 1130 Curmonster.m_treasuretype = 0; 1131 Curmonster.m_experience = 0.0; 1132 } 1133 } 1134 else if (Curmonster.m_type == SM_MIMIC) 1135 /* pick another name */ 1136 { 1137 which = (int) ROLL(0.0, 100.0); 1138 fseek(Monstfp, (long) which * (long) SZ_MONSTERSTRUCT, 0); 1139 fread(&Othermonster, SZ_MONSTERSTRUCT, 1, Monstfp); 1140 strcpy(Curmonster.m_name, Othermonster.m_name); 1141 } 1142 1143 truncstring(Curmonster.m_name); 1144 1145 if (Curmonster.m_type != SM_MORGOTH) 1146 /* adjust stats based on which circle player is in */ 1147 { 1148 Curmonster.m_strength *= (1.0 + Circle / 2.0); 1149 Curmonster.m_brains *= Circle; 1150 Curmonster.m_speed += Circle * 1.e-9; 1151 Curmonster.m_energy *= Circle; 1152 Curmonster.m_experience *= Circle; 1153 } 1154 1155 if (Player.p_blindness) 1156 /* cannot see monster if blind */ 1157 Enemyname = "A monster"; 1158 else 1159 Enemyname = Curmonster.m_name; 1160 1161 if (Player.p_speed <= 0.0) 1162 /* make Player.p_speed positive */ 1163 { 1164 Curmonster.m_speed += -Player.p_speed; 1165 Player.p_speed = 1.0; 1166 } 1167 1168 /* fill up the rest of the structure */ 1169 Curmonster.m_o_strength = Curmonster.m_strength; 1170 Curmonster.m_o_speed = Curmonster.m_maxspeed = Curmonster.m_speed; 1171 Curmonster.m_o_energy = Curmonster.m_energy; 1172 Curmonster.m_melee = Curmonster.m_skirmish = 0.0; 1173 } 1174 /**/ 1175 /************************************************************************ 1176 / 1177 / FUNCTION NAME: awardtreasure() 1178 / 1179 / FUNCTION: select a treasure 1180 / 1181 / AUTHOR: E. A. Estes, 12/4/85 1182 / 1183 / ARGUMENTS: none 1184 / 1185 / RETURN VALUE: none 1186 / 1187 / MODULES CALLED: pickmonster(), collecttaxes(), more(), cursedtreasure(), 1188 / floor(), wmove(), drandom(), sscanf(), printw(), altercoordinates(), 1189 / longjmp(), infloat(), waddstr(), getanswer(), getstring(), wclrtobot() 1190 / 1191 / GLOBAL INPUTS: Somebetter[], Curmonster, Whichmonster, Circle, Player, 1192 / *stdscr, Databuf[], *Statptr, Fightenv[] 1193 / 1194 / GLOBAL OUTPUTS: Whichmonster, Shield, Player 1195 / 1196 / DESCRIPTION: 1197 / Roll up a treasure based upon monster type and size, and 1198 / certain player statistics. 1199 / Handle cursed treasure. 1200 / 1201 *************************************************************************/ 1202 1203 void 1204 awardtreasure(void) 1205 { 1206 int whichtreasure; /* calculated treasure to grant */ 1207 int temp; /* temporary */ 1208 int ch; /* input */ 1209 double treasuretype; /* monster's treasure type */ 1210 double gold = 0.0; /* gold awarded */ 1211 double gems = 0.0; /* gems awarded */ 1212 double dtemp; /* for temporary calculations */ 1213 1214 whichtreasure = (int) ROLL(1.0, 3.0); /* pick a treasure */ 1215 treasuretype = (double) Curmonster.m_treasuretype; 1216 1217 move(4, 0); 1218 clrtobot(); 1219 move(6, 0); 1220 1221 if (drandom() > 0.65) 1222 /* gold and gems */ 1223 { 1224 if (Curmonster.m_treasuretype > 7) 1225 /* gems */ 1226 { 1227 gems = ROLL(1.0, (treasuretype - 7.0) 1228 * (treasuretype - 7.0) * (Circle - 1.0) / 4.0); 1229 printw("You have discovered %.0f gems!", gems); 1230 } 1231 else 1232 /* gold */ 1233 { 1234 gold = ROLL(treasuretype * 10.0, treasuretype 1235 * treasuretype * 10.0 * (Circle - 1.0)); 1236 printw("You have found %.0f gold pieces.", gold); 1237 } 1238 1239 addstr(" Do you want to pick them up ? "); 1240 ch = getanswer("NY", FALSE); 1241 addstr("\n\n"); 1242 1243 if (ch == 'Y') { 1244 if (drandom() < treasuretype / 35.0 + 0.04) 1245 /* cursed */ 1246 { 1247 addstr("They were cursed!\n"); 1248 cursedtreasure(); 1249 } 1250 else 1251 collecttaxes(gold, gems); 1252 } 1253 1254 return; 1255 } 1256 else 1257 /* other treasures */ 1258 { 1259 addstr("You have found some treasure. Do you want to inspect it ? "); 1260 ch = getanswer("NY", FALSE); 1261 addstr("\n\n"); 1262 1263 if (ch != 'Y') 1264 return; 1265 else 1266 if (drandom() < 0.08 && Curmonster.m_treasuretype != 4) 1267 { 1268 addstr("It was cursed!\n"); 1269 cursedtreasure(); 1270 return; 1271 } 1272 else 1273 switch (Curmonster.m_treasuretype) 1274 { 1275 case 1: /* treasure type 1 */ 1276 switch (whichtreasure) 1277 { 1278 case 1: 1279 addstr("You've discovered a power booster!\n"); 1280 Player.p_mana += ROLL(Circle * 4.0, Circle * 30.0); 1281 break; 1282 1283 case 2: 1284 addstr("You have encountered a druid.\n"); 1285 Player.p_experience += 1286 ROLL(0.0, 2000.0 + Circle * 400.0); 1287 break; 1288 1289 case 3: 1290 addstr("You have found a holy orb.\n"); 1291 Player.p_sin = MAX(0.0, Player.p_sin - 0.25); 1292 break; 1293 } 1294 break; 1295 /* end treasure type 1 */ 1296 1297 case 2: /* treasure type 2 */ 1298 switch (whichtreasure) 1299 { 1300 case 1: 1301 addstr("You have found an amulet.\n"); 1302 ++Player.p_amulets; 1303 break; 1304 1305 case 2: 1306 addstr("You've found some holy water!\n"); 1307 ++Player.p_holywater; 1308 break; 1309 1310 case 3: 1311 addstr("You've met a hermit!\n"); 1312 Player.p_sin *= 0.75; 1313 Player.p_mana += 12.0 * Circle; 1314 break; 1315 } 1316 break; 1317 /* end treasure type 2 */ 1318 1319 case 3: /* treasure type 3 */ 1320 switch (whichtreasure) 1321 { 1322 case 1: 1323 dtemp = ROLL(7.0, 30.0 + Circle / 10.0); 1324 printw("You've found a +%.0f shield!\n", dtemp); 1325 if (dtemp >= Player.p_shield) 1326 Player.p_shield = dtemp; 1327 else 1328 SOMEBETTER(); 1329 break; 1330 1331 case 2: 1332 addstr("You have rescued a virgin. Will you be honorable ? "); 1333 ch = getanswer("NY", FALSE); 1334 addstr("\n\n"); 1335 if (ch == 'Y') 1336 Player.p_virgin = TRUE; 1337 else 1338 { 1339 Player.p_experience += 2000.0 * Circle; 1340 ++Player.p_sin; 1341 } 1342 break; 1343 1344 case 3: 1345 addstr("You've discovered some athelas!\n"); 1346 --Player.p_poison; 1347 break; 1348 } 1349 break; 1350 /* end treasure type 3 */ 1351 1352 case 4: /* treasure type 4 */ 1353 addstr("You've found a scroll. Will you read it ? "); 1354 ch = getanswer("NY", FALSE); 1355 addstr("\n\n"); 1356 1357 if (ch == 'Y') 1358 switch ((int) ROLL(1, 6)) 1359 { 1360 case 1: 1361 addstr("It throws up a shield for you next monster.\n"); 1362 getyx(stdscr, whichtreasure, ch); 1363 more(whichtreasure); 1364 Shield = 1365 (Player.p_maxenergy + Player.p_energy) * 5.5 + Circle * 50.0; 1366 Whichmonster = pickmonster(); 1367 longjmp(Fightenv, 0); 1368 /*NOTREACHED*/ 1369 1370 case 2: 1371 addstr("It makes you invisible for you next monster.\n"); 1372 getyx(stdscr, whichtreasure, ch); 1373 more(whichtreasure); 1374 Player.p_speed = 1e6; 1375 Whichmonster = pickmonster(); 1376 longjmp(Fightenv, 0); 1377 /*NOTREACHED*/ 1378 1379 case 3: 1380 addstr("It increases your strength ten fold to fight your next monster.\n"); 1381 getyx(stdscr, whichtreasure, ch); 1382 more(whichtreasure); 1383 Player.p_might *= 10.0; 1384 Whichmonster = pickmonster(); 1385 longjmp(Fightenv, 0); 1386 /*NOTREACHED*/ 1387 1388 case 4: 1389 addstr("It is a general knowledge scroll.\n"); 1390 Player.p_brains += ROLL(2.0, Circle); 1391 Player.p_magiclvl += ROLL(1.0, Circle / 2.0); 1392 break; 1393 1394 case 5: 1395 addstr("It tells you how to pick your next monster.\n"); 1396 addstr("Which monster do you want [0-99] ? "); 1397 Whichmonster = (int) infloat(); 1398 Whichmonster = MIN(99, MAX(0, Whichmonster)); 1399 longjmp(Fightenv, 0); 1400 1401 case 6: 1402 addstr("It was cursed!\n"); 1403 cursedtreasure(); 1404 break; 1405 } 1406 break; 1407 /* end treasure type 4 */ 1408 1409 case 5: /* treasure type 5 */ 1410 switch (whichtreasure) 1411 { 1412 case 1: 1413 dtemp = ROLL(Circle / 4.0 + 5.0, Circle / 2.0 + 9.0); 1414 printw("You've discovered a +%.0f dagger.\n", dtemp); 1415 if (dtemp >= Player.p_sword) 1416 Player.p_sword = dtemp; 1417 else 1418 SOMEBETTER(); 1419 break; 1420 1421 case 2: 1422 dtemp = ROLL(7.5 + Circle * 3.0, Circle * 2.0 + 160.0); 1423 printw("You have found some +%.0f armour!\n", dtemp); 1424 if (dtemp >= Player.p_shield) 1425 Player.p_shield = dtemp; 1426 else 1427 SOMEBETTER(); 1428 break; 1429 1430 case 3: 1431 addstr("You've found a tablet.\n"); 1432 Player.p_brains += 4.5 * Circle; 1433 break; 1434 } 1435 break; 1436 /* end treasure type 5 */ 1437 1438 case 6: /* treasure type 6 */ 1439 switch (whichtreasure) 1440 { 1441 case 1: 1442 addstr("You've found a priest.\n"); 1443 Player.p_energy = Player.p_maxenergy + Player.p_shield; 1444 Player.p_sin /= 2.0; 1445 Player.p_mana += 24.0 * Circle; 1446 Player.p_brains += Circle; 1447 break; 1448 1449 case 2: 1450 addstr("You have come upon Robin Hood!\n"); 1451 Player.p_shield += Circle * 2.0; 1452 Player.p_strength += Circle / 2.5 + 1.0; 1453 break; 1454 1455 case 3: 1456 dtemp = ROLL(2.0 + Circle / 4.0, Circle / 1.2 + 10.0); 1457 printw("You have found a +%.0f axe!\n", dtemp); 1458 if (dtemp >= Player.p_sword) 1459 Player.p_sword = dtemp; 1460 else 1461 SOMEBETTER(); 1462 break; 1463 } 1464 break; 1465 /* end treasure type 6 */ 1466 1467 case 7: /* treasure type 7 */ 1468 switch (whichtreasure) 1469 { 1470 case 1: 1471 addstr("You've discovered a charm!\n"); 1472 ++Player.p_charms; 1473 break; 1474 1475 case 2: 1476 addstr("You have encountered Merlyn!\n"); 1477 Player.p_brains += Circle + 5.0; 1478 Player.p_magiclvl += Circle / 3.0 + 5.0; 1479 Player.p_mana += Circle * 10.0; 1480 break; 1481 1482 case 3: 1483 dtemp = ROLL(5.0 + Circle / 3.0, Circle / 1.5 + 20.0); 1484 printw("You have found a +%.0f war hammer!\n", dtemp); 1485 if (dtemp >= Player.p_sword) 1486 Player.p_sword = dtemp; 1487 else 1488 SOMEBETTER(); 1489 break; 1490 } 1491 break; 1492 /* end treasure type 7 */ 1493 1494 case 8: /* treasure type 8 */ 1495 switch (whichtreasure) 1496 { 1497 case 1: 1498 addstr("You have found a healing potion.\n"); 1499 Player.p_poison = MIN(-2.0, Player.p_poison - 2.0); 1500 break; 1501 1502 case 2: 1503 addstr("You have discovered a transporter. Do you wish to go anywhere ? "); 1504 ch = getanswer("NY", FALSE); 1505 addstr("\n\n"); 1506 if (ch == 'Y') 1507 { 1508 double x, y; 1509 1510 addstr("X Y Coordinates ? "); 1511 getstring(Databuf, SZ_DATABUF); 1512 sscanf(Databuf, "%lf %lf", &x, &y); 1513 altercoordinates(x, y, A_FORCED); 1514 } 1515 break; 1516 1517 case 3: 1518 dtemp = ROLL(10.0 + Circle / 1.2, Circle * 3.0 + 30.0); 1519 printw("You've found a +%.0f sword!\n", dtemp); 1520 if (dtemp >= Player.p_sword) 1521 Player.p_sword = dtemp; 1522 else 1523 SOMEBETTER(); 1524 break; 1525 } 1526 break; 1527 /* end treasure type 8 */ 1528 1529 case 10: 1530 case 11: 1531 case 12: 1532 case 13: /* treasure types 10 - 13 */ 1533 if (drandom() < 0.33) 1534 { 1535 if (Curmonster.m_treasuretype == 10) 1536 { 1537 addstr("You've found a pair of elven boots!\n"); 1538 Player.p_quickness += 2.0; 1539 break; 1540 } 1541 else if (Curmonster.m_treasuretype == 11 1542 && !Player.p_palantir) 1543 { 1544 addstr("You've acquired Saruman's palantir.\n"); 1545 Player.p_palantir = TRUE; 1546 break; 1547 } 1548 else if (Player.p_ring.ring_type == R_NONE 1549 && Player.p_specialtype < SC_COUNCIL 1550 && (Curmonster.m_treasuretype == 12 1551 || Curmonster.m_treasuretype == 13)) 1552 /* roll up a ring */ 1553 { 1554 if (drandom() < 0.8) 1555 /* regular rings */ 1556 { 1557 if (Curmonster.m_treasuretype == 12) 1558 { 1559 whichtreasure = R_NAZREG; 1560 temp = 35; 1561 } 1562 else 1563 { 1564 whichtreasure = R_DLREG; 1565 temp = 0; 1566 } 1567 } 1568 else 1569 /* bad rings */ 1570 { 1571 whichtreasure = R_BAD; 1572 temp = 15 + Statptr->c_ringduration + (int) ROLL(0,5); 1573 } 1574 1575 addstr("You've discovered a ring. Will you pick it up ? "); 1576 ch = getanswer("NY", FALSE); 1577 addstr("\n\n"); 1578 1579 if (ch == 'Y') 1580 { 1581 Player.p_ring.ring_type = whichtreasure; 1582 Player.p_ring.ring_duration = temp; 1583 } 1584 1585 break; 1586 } 1587 } 1588 /* end treasure types 10 - 13 */ 1589 /* fall through to treasure type 9 if no treasure from above */ 1590 1591 case 9: /* treasure type 9 */ 1592 switch (whichtreasure) 1593 { 1594 case 1: 1595 if (Player.p_level <= 1000.0 1596 && Player.p_crowns <= 3 1597 && Player.p_level >= 10.0) 1598 { 1599 addstr("You have found a golden crown!\n"); 1600 ++Player.p_crowns; 1601 break; 1602 } 1603 /* fall through otherwise */ 1604 1605 case 2: 1606 addstr("You've been blessed!\n"); 1607 Player.p_blessing = TRUE; 1608 Player.p_sin /= 3.0; 1609 Player.p_energy = Player.p_maxenergy + Player.p_shield; 1610 Player.p_mana += 100.0 * Circle; 1611 break; 1612 1613 case 3: 1614 dtemp = ROLL(1.0, Circle / 5.0 + 5.0); 1615 dtemp = MIN(dtemp, 99.0); 1616 printw("You have discovered some +%.0f quicksilver!\n",dtemp); 1617 if (dtemp >= Player.p_quksilver) 1618 Player.p_quksilver = dtemp; 1619 else 1620 SOMEBETTER(); 1621 break; 1622 } 1623 break; 1624 /* end treasure type 9 */ 1625 } 1626 } 1627 } 1628 /**/ 1629 /************************************************************************ 1630 / 1631 / FUNCTION NAME: cursedtreasure() 1632 / 1633 / FUNCTION: take care of cursed treasure 1634 / 1635 / AUTHOR: E. A. Estes, 12/4/85 1636 / 1637 / ARGUMENTS: none 1638 / 1639 / RETURN VALUE: none 1640 / 1641 / MODULES CALLED: waddstr() 1642 / 1643 / GLOBAL INPUTS: Player, *stdscr 1644 / 1645 / GLOBAL OUTPUTS: Player 1646 / 1647 / DESCRIPTION: 1648 / Handle cursed treasure. Look for amulets and charms to save 1649 / the player from the curse. 1650 / 1651 *************************************************************************/ 1652 1653 void 1654 cursedtreasure(void) 1655 { 1656 if (Player.p_charms > 0) 1657 { 1658 addstr("But your charm saved you!\n"); 1659 --Player.p_charms; 1660 } 1661 else if (Player.p_amulets > 0) 1662 { 1663 addstr("But your amulet saved you!\n"); 1664 --Player.p_amulets; 1665 } 1666 else 1667 { 1668 Player.p_energy = (Player.p_maxenergy + Player.p_shield) / 10.0; 1669 Player.p_poison += 0.25; 1670 } 1671 } 1672 /**/ 1673 /************************************************************************ 1674 / 1675 / FUNCTION NAME: scramblestats() 1676 / 1677 / FUNCTION: scramble some selected statistics 1678 / 1679 / AUTHOR: E. A. Estes, 12/4/85 1680 / 1681 / ARGUMENTS: none 1682 / 1683 / RETURN VALUE: none 1684 / 1685 / MODULES CALLED: floor(), drandom() 1686 / 1687 / GLOBAL INPUTS: Player 1688 / 1689 / GLOBAL OUTPUTS: Player 1690 / 1691 / DESCRIPTION: 1692 / Swap a few player statistics randomly. 1693 / 1694 *************************************************************************/ 1695 1696 void 1697 scramblestats(void) 1698 { 1699 double dbuf[6]; /* to put statistic in */ 1700 double dtemp1, dtemp2; /* for swapping values */ 1701 int first, second; /* indices for swapping */ 1702 double *dptr; /* pointer for filling and emptying buf[] */ 1703 1704 /* fill buffer */ 1705 dptr = &dbuf[0]; 1706 *dptr++ = Player.p_strength; 1707 *dptr++ = Player.p_mana; 1708 *dptr++ = Player.p_brains; 1709 *dptr++ = Player.p_magiclvl; 1710 *dptr++ = Player.p_energy; 1711 *dptr = Player.p_sin; 1712 1713 /* pick values to swap */ 1714 first = (int) ROLL(0, 5); 1715 second = (int) ROLL(0, 5); 1716 1717 /* swap values */ 1718 dptr = &dbuf[0]; 1719 dtemp1 = dptr[first]; 1720 /* this expression is split to prevent a compiler loop on some compilers */ 1721 dtemp2 = dptr[second]; 1722 dptr[first] = dtemp2; 1723 dptr[second] = dtemp1; 1724 1725 /* empty buffer */ 1726 Player.p_strength = *dptr++; 1727 Player.p_mana = *dptr++; 1728 Player.p_brains = *dptr++; 1729 Player.p_magiclvl = *dptr++; 1730 Player.p_energy = *dptr++; 1731 Player.p_sin = *dptr; 1732 } 1733