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