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