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