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