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