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