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