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