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