1 /* $NetBSD: fight.c,v 1.12 2009/08/12 08:21:41 dholland Exp $ */
4 * fight.c Phantasia monster fighting routines
13 #include "phantdefs.h"
14 #include "phantstruct.h"
15 #include "phantglobs.h"
20 static void awardtreasure(void);
21 static void callmonster(int);
22 static void cancelmonster(void);
23 static void cursedtreasure(void);
24 static void hitmonster(double);
25 static void monsthits(void);
26 static int pickmonster(void);
27 static void playerhits(void);
28 static void scramblestats(void);
29 static void throwspell(void);
32 encounter(int particular
)
34 volatile bool firsthit
= Player
.p_blessing
; /* set if player gets
36 volatile int flockcnt
= 1; /* how many time flocked */
38 /* let others know what we are doing */
39 Player
.p_status
= S_MONSTER
;
40 writerecord(&Player
, Fileloc
);
46 Shield
= 0.0; /* no shield up yet */
49 /* monster is specified */
50 Whichmonster
= particular
;
52 /* pick random monster */
53 Whichmonster
= pickmonster();
55 setjmp(Fightenv
); /* this is to enable changing fight state */
58 clrtobot(); /* clear bottom area of screen */
61 callmonster(Whichmonster
); /* set up monster to fight */
63 Luckout
= FALSE
; /* haven't tried to luckout yet */
65 if (Curmonster
.m_type
== SM_MORGOTH
)
66 mvprintw(4, 0, "You've encountered %s, Bane of the Council and Valar.\n",
69 if (Curmonster
.m_type
== SM_UNICORN
) {
70 if (Player
.p_virgin
) {
71 printw("You just subdued %s, thanks to the virgin.\n", Enemyname
);
72 Player
.p_virgin
= FALSE
;
74 printw("You just saw %s running away!\n", Enemyname
);
75 Curmonster
.m_experience
= 0.0;
76 Curmonster
.m_treasuretype
= 0;
79 /* not a special monster */
81 /* print header, and arbitrate between player and
84 mvprintw(6, 0, "You are being attacked by %s, EXP: %.0f (Size: %.0f)\n",
85 Enemyname
, Curmonster
.m_experience
, Circle
);
88 mvprintw(1, 26, "%20.0f", Player
.p_energy
+ Shield
); /* overprint energy */
91 if (Curmonster
.m_type
== SM_DARKLORD
93 && Player
.p_charms
> 0)
94 /* overpower Dark Lord with blessing and charm */
96 mvprintw(7, 0, "You just overpowered %s!", Enemyname
);
98 Player
.p_blessing
= FALSE
;
102 /* allow paralyzed monster to wake up */
103 Curmonster
.m_speed
= MIN(Curmonster
.m_speed
+ 1.0, Curmonster
.m_maxspeed
);
105 if (drandom() * Curmonster
.m_speed
> drandom() * Player
.p_speed
106 /* monster is faster */
107 && Curmonster
.m_type
!= SM_DARKLORD
109 && Curmonster
.m_type
!= SM_SHRIEKER
112 /* monster gets a hit */
115 /* player gets a hit */
123 if (Lines
> LINES
- 2)
124 /* near bottom of screen - pause */
130 if (Player
.p_energy
<= 0.0)
136 break; /* fight ends if the player is saved
139 if (Curmonster
.m_energy
<= 0.0)
144 /* give player credit for killing monster */
145 Player
.p_experience
+= Curmonster
.m_experience
;
147 if (drandom() < Curmonster
.m_flock
/ 100.0)
152 longjmp(Fightenv
, 0);
156 && Curmonster
.m_treasuretype
> 0
157 && drandom() > 0.2 + pow(0.4, (double) (flockcnt
/ 3 + Circle
/ 3.0)))
158 /* monster has treasure; this takes # of flocks and
159 * size into account */
164 /* pause before returning */
165 getyx(stdscr
, Lines
, flockcnt
);
168 Player
.p_ring
.ring_inuse
= FALSE
; /* not using ring */
170 /* clean up the screen */
178 if (Player
.p_specialtype
== SC_VALAR
)
179 /* even chance of any monster */
180 return ((int) ROLL(0.0, 100.0));
184 return ((int) ROLL(0.0, 15.0));
188 /* even chance of all non-water monsters */
189 return ((int) ROLL(14.0, 86.0));
193 /* chance of all non-water monsters, weighted
195 return ((int) (ROLL(0.0, 50.0) + ROLL(14.0, 37.0)));
199 /* not all non-water monsters,
200 * weighted toward middle */
201 return ((int) (ROLL(0.0, 50.0) + ROLL(14.0, 26.0)));
205 /* even chance of some tamer
206 * non-water monsters */
207 return ((int) ROLL(14.0, 50.0));
210 /* even chance of some of the
211 * tamest non-water monsters */
212 return ((int) ROLL(14.0, 25.0));
218 double inflict
; /* damage inflicted */
221 mvaddstr(7, 0, "1:Melee 2:Skirmish 3:Evade 4:Spell 5:Nick ");
224 /* haven't tried to luckout yet */
225 if (Curmonster
.m_type
== SM_MORGOTH
)
226 /* cannot luckout against Morgoth */
229 addstr("6:Luckout ");
232 if (Player
.p_ring
.ring_type
!= R_NONE
)
233 /* player has a ring */
234 addstr("7:Use Ring ");
241 clrtobot(); /* clear any messages from before */
243 mvaddstr(4, 0, "\n\n"); /* clear status area */
246 case 'T': /* timeout; lose turn */
250 case '1': /* melee */
251 /* melee affects monster's energy and strength */
252 inflict
= ROLL(Player
.p_might
/ 2.0 + 5.0, 1.3 * Player
.p_might
)
253 + (Player
.p_ring
.ring_inuse
? Player
.p_might
: 0.0);
255 Curmonster
.m_melee
+= inflict
;
256 Curmonster
.m_strength
= Curmonster
.m_o_strength
257 - Curmonster
.m_melee
/ Curmonster
.m_o_energy
258 * Curmonster
.m_o_strength
/ 4.0;
262 case '2': /* skirmish */
263 /* skirmish affects monter's energy and speed */
264 inflict
= ROLL(Player
.p_might
/ 3.0 + 3.0, 1.1 * Player
.p_might
)
265 + (Player
.p_ring
.ring_inuse
? Player
.p_might
: 0.0);
267 Curmonster
.m_skirmish
+= inflict
;
268 Curmonster
.m_maxspeed
= Curmonster
.m_o_speed
269 - Curmonster
.m_skirmish
/ Curmonster
.m_o_energy
270 * Curmonster
.m_o_speed
/ 4.0;
274 case '3': /* evade */
275 /* use brains and speed to try to evade */
276 if ((Curmonster
.m_type
== SM_DARKLORD
277 || Curmonster
.m_type
== SM_SHRIEKER
278 /* can always run from D. L. and shrieker */
279 || drandom() * Player
.p_speed
* Player
.p_brains
280 > drandom() * Curmonster
.m_speed
* Curmonster
.m_brains
)
281 && (Curmonster
.m_type
!= SM_MIMIC
))
282 /* cannot run from mimic */
284 mvaddstr(Lines
++, 0, "You got away!");
286 altercoordinates(0.0, 0.0, A_NEAR
);
288 mvprintw(Lines
++, 0, "%s is still after you!", Enemyname
);
293 case '4': /* magic spell */
298 /* hit 1 plus sword; give some experience */
299 inflict
= 1.0 + Player
.p_sword
;
300 Player
.p_experience
+= floor(Curmonster
.m_experience
/ 10.0);
301 Curmonster
.m_experience
*= 0.92;
302 /* monster gets meaner */
303 Curmonster
.m_maxspeed
+= 2.0;
304 Curmonster
.m_speed
= (Curmonster
.m_speed
< 0.0) ? 0.0 : Curmonster
.m_speed
+ 2.0;
305 if (Curmonster
.m_type
== SM_DARKLORD
)
306 /* Dark Lord; doesn't like to be nicked */
309 "You hit %s %.0f times, and made him mad!", Enemyname
, inflict
);
310 Player
.p_quickness
/= 2.0;
311 altercoordinates(0.0, 0.0, A_FAR
);
318 case '6': /* luckout */
320 mvaddstr(Lines
++, 0, "You already tried that.");
323 if (Curmonster
.m_type
== SM_MORGOTH
)
326 if (drandom() < Player
.p_sin
/ 100.0) {
327 mvprintw(Lines
++, 0, "%s accepted!", Enemyname
);
330 mvaddstr(Lines
++, 0, "Nope, he's not interested.");
332 /* normal monster; use brains for success */
334 if ((drandom() + 0.333) * Player
.p_brains
335 < (drandom() + 0.333) * Curmonster
.m_brains
)
336 mvprintw(Lines
++, 0, "You blew it, %s.", Player
.p_name
);
338 mvaddstr(Lines
++, 0, "You made it!");
339 Curmonster
.m_energy
= 0.0;
345 case '7': /* use ring */
346 if (Player
.p_ring
.ring_type
!= R_NONE
) {
347 mvaddstr(Lines
++, 0, "Now using ring.");
348 Player
.p_ring
.ring_inuse
= TRUE
;
349 if (Player
.p_ring
.ring_type
!= R_DLREG
)
351 --Player
.p_ring
.ring_duration
;
361 double inflict
; /* damage inflicted */
364 switch (Curmonster
.m_type
)
365 /* may be a special monster */
368 /* hits just enough to kill player */
369 inflict
= (Player
.p_energy
+ Shield
) * 1.02;
373 /* call a big monster */
375 "Shrieeeek!! You scared it, and it called one of its friends.");
377 Whichmonster
= (int) ROLL(70.0, 30.0);
378 longjmp(Fightenv
, 0);
382 /* take experience away */
383 inflict
= ROLL(10.0, Curmonster
.m_strength
);
384 inflict
= MIN(Player
.p_experience
, inflict
);
386 "%s took away %.0f experience points.", Enemyname
, inflict
);
387 Player
.p_experience
-= inflict
;
391 if (Player
.p_holywater
> 0)
392 /* holy water kills when monster tries to hit */
394 mvprintw(Lines
++, 0, "Your holy water killed it!");
395 --Player
.p_holywater
;
396 Curmonster
.m_energy
= 0.0;
410 /* else special things */
411 switch (Curmonster
.m_type
) {
413 /* takes some of the player's strength */
414 inflict
= ROLL(1.0, (Circle
- 1.0) / 2.0);
415 inflict
= MIN(Player
.p_strength
, inflict
);
416 mvprintw(Lines
++, 0, "%s sapped %.0f of your strength!",
418 Player
.p_strength
-= inflict
;
419 Player
.p_might
-= inflict
;
423 if (Player
.p_palantir
)
424 /* take away palantir */
426 mvprintw(Lines
++, 0, "Wormtongue stole your palantir!");
427 Player
.p_palantir
= FALSE
;
430 /* gems turn to gold */
433 "%s transformed your gems into gold!", Enemyname
);
434 Player
.p_gold
+= Player
.p_gems
;
437 /* scramble some stats */
439 mvprintw(Lines
++, 0, "%s scrambled your stats!", Enemyname
);
445 /* transport player */
446 mvprintw(Lines
++, 0, "%s transported you!", Enemyname
);
447 altercoordinates(0.0, 0.0, A_FAR
);
452 /* suck up some mana */
453 inflict
= ROLL(0, 7.5 * Circle
);
454 inflict
= MIN(Player
.p_mana
, floor(inflict
));
456 "%s sucked up %.0f of your mana!", Enemyname
, inflict
);
457 Player
.p_mana
-= inflict
;
461 /* try to take ring if player has one */
462 if (Player
.p_ring
.ring_type
!= R_NONE
)
463 /* player has a ring */
465 mvaddstr(Lines
++, 0, "Will you relinguish your ring ? ");
466 ch
= getanswer("YN", FALSE
);
470 Player
.p_ring
.ring_type
= R_NONE
;
471 Player
.p_ring
.ring_inuse
= FALSE
;
476 /* otherwise, take some brains */
478 "%s neutralized 1/5 of your brain!", Enemyname
);
479 Player
.p_brains
*= 0.8;
483 /* take some gold and gems */
485 "%s took half your gold and gems and flew off.", Enemyname
);
486 Player
.p_gold
/= 2.0;
487 Player
.p_gems
/= 2.0;
492 /* steal a gold piece and run */
494 "%s stole one gold piece and ran away.", Enemyname
);
495 Player
.p_gold
= MAX(0.0, Player
.p_gold
- 1.0);
500 /* bite and (medium) poison */
502 "%s has bitten and poisoned you!", Enemyname
);
503 Player
.p_poison
-= 1.0;
507 /* bite and (small) poison */
508 mvprintw(Lines
++, 0, "%s bit and poisoned you!", Enemyname
);
509 Player
.p_poison
+= 0.25;
514 mvprintw(Lines
++, 0, "%s farted and scampered off.", Enemyname
);
515 Player
.p_energy
/= 2.0; /* damage from fumes */
520 if (Player
.p_ring
.ring_type
!= R_NONE
)
521 /* try to steal ring */
524 "%s tried to steal your ring, ", Enemyname
);
526 addstr("but was unsuccessful.");
528 addstr("and ran away with it!");
529 Player
.p_ring
.ring_type
= R_NONE
;
536 /* inflict damage through shield */
537 inflict
= ROLL(15.0, Circle
* 10.0);
538 inflict
= MIN(inflict
, Player
.p_energy
);
539 mvprintw(Lines
++, 0, "%s sapped %.0f of your energy.",
541 Player
.p_energy
-= inflict
;
545 /* take all metal treasures */
547 "%s took all your metal treasures!", Enemyname
);
556 /* (large) poison and take a quickness */
558 "%s poisoned you, and took one quik.", Enemyname
);
559 Player
.p_poison
+= 5.0;
560 Player
.p_quickness
-= 1.0;
564 /* fly away, and leave either a Jubjub bird or
567 "%s flew away, and left you to contend with one of its friends.",
569 Whichmonster
= 55 + ((drandom() > 0.5) ? 22 : 0);
570 longjmp(Fightenv
, 0);
574 /* partially regenerate monster */
576 "%s partially regenerated his energy.!", Enemyname
);
577 Curmonster
.m_energy
+=
578 floor((Curmonster
.m_o_energy
- Curmonster
.m_energy
) / 2.0);
579 Curmonster
.m_strength
= Curmonster
.m_o_strength
;
580 Curmonster
.m_melee
= Curmonster
.m_skirmish
= 0.0;
581 Curmonster
.m_maxspeed
= Curmonster
.m_o_speed
;
585 if (!Player
.p_blindness
)
588 mvprintw(Lines
++, 0, "%s blinded you!", Enemyname
);
589 Player
.p_blindness
= TRUE
;
590 Enemyname
= "A monster";
597 /* fall through to here if monster inflicts a normal hit */
598 inflict
= drandom() * Curmonster
.m_strength
+ 0.5;
600 mvprintw(Lines
++, 0, "%s hit you %.0f times!", Enemyname
, inflict
);
602 if ((Shield
-= inflict
) < 0) {
603 Player
.p_energy
+= Shield
;
611 Curmonster
.m_energy
= 0.0;
612 Curmonster
.m_experience
= 0.0;
613 Curmonster
.m_treasuretype
= 0;
614 Curmonster
.m_flock
= 0.0;
618 hitmonster(double inflict
)
620 mvprintw(Lines
++, 0, "You hit %s %.0f times!", Enemyname
, inflict
);
621 Curmonster
.m_energy
-= inflict
;
622 if (Curmonster
.m_energy
> 0.0) {
623 if (Curmonster
.m_type
== SM_DARKLORD
|| Curmonster
.m_type
== SM_SHRIEKER
)
624 /* special monster didn't die */
627 /* monster died. print message. */
629 if (Curmonster
.m_type
== SM_MORGOTH
)
630 mvaddstr(Lines
++, 0, "You have defeated Morgoth, but he may return. . .");
632 /* all other types of monsters */
634 mvprintw(Lines
++, 0, "You killed it. Good work, %s.", Player
.p_name
);
636 if (Curmonster
.m_type
== SM_MIMIC
637 && strcmp(Curmonster
.m_name
, "A Mimic") != 0
638 && !Player
.p_blindness
)
639 mvaddstr(Lines
++, 0, "The body slowly changes into the form of a mimic.");
647 double inflict
; /* damage inflicted */
648 double dtemp
; /* for dtemporary calculations */
652 mvaddstr(7, 0, "\n\n"); /* clear menu area */
654 if (Player
.p_magiclvl
>= ML_ALLORNOTHING
)
655 mvaddstr(7, 0, "1:All or Nothing ");
656 if (Player
.p_magiclvl
>= ML_MAGICBOLT
)
657 addstr("2:Magic Bolt ");
658 if (Player
.p_magiclvl
>= ML_FORCEFIELD
)
659 addstr("3:Force Field ");
660 if (Player
.p_magiclvl
>= ML_XFORM
)
661 addstr("4:Transform ");
662 if (Player
.p_magiclvl
>= ML_INCRMIGHT
)
663 addstr("5:Increase Might\n");
664 if (Player
.p_magiclvl
>= ML_INVISIBLE
)
665 mvaddstr(8, 0, "6:Invisibility ");
666 if (Player
.p_magiclvl
>= ML_XPORT
)
667 addstr("7:Transport ");
668 if (Player
.p_magiclvl
>= ML_PARALYZE
)
669 addstr("8:Paralyze ");
670 if (Player
.p_specialtype
>= SC_COUNCIL
)
672 mvaddstr(4, 0, "Spell ? ");
674 ch
= getanswer(" ", TRUE
);
676 mvaddstr(7, 0, "\n\n"); /* clear menu area */
678 if (Curmonster
.m_type
== SM_MORGOTH
&& ch
!= '3')
679 /* can only throw force field against Morgoth */
683 case '1': /* all or nothing */
684 if (drandom() < 0.25)
687 inflict
= Curmonster
.m_energy
* 1.01 + 1.0;
689 if (Curmonster
.m_type
== SM_DARKLORD
)
690 /* all or nothing doesn't quite work
694 /* failure -- monster gets stronger and
697 Curmonster
.m_o_strength
= Curmonster
.m_strength
*= 2.0;
698 Curmonster
.m_maxspeed
*= 2.0;
699 Curmonster
.m_o_speed
*= 2.0;
701 /* paralyzed monsters wake up a bit */
702 Curmonster
.m_speed
= MAX(1.0, Curmonster
.m_speed
* 2.0);
705 if (Player
.p_mana
>= MM_ALLORNOTHING
)
706 /* take a mana if player has one */
707 Player
.p_mana
-= MM_ALLORNOTHING
;
712 case '2': /* magic bolt */
713 if (Player
.p_magiclvl
< ML_MAGICBOLT
)
717 /* prompt for amount to expend */
719 mvaddstr(4, 0, "How much mana for bolt? ");
720 dtemp
= floor(infloat());
722 while (dtemp
< 0.0 || dtemp
> Player
.p_mana
);
724 Player
.p_mana
-= dtemp
;
726 if (Curmonster
.m_type
== SM_DARKLORD
)
727 /* magic bolts don't work against D.
731 inflict
= dtemp
* ROLL(15.0, sqrt(Player
.p_magiclvl
/ 3.0 + 1.0));
732 mvaddstr(5, 0, "Magic Bolt fired!\n");
737 case '3': /* force field */
738 if (Player
.p_magiclvl
< ML_FORCEFIELD
)
741 if (Player
.p_mana
< MM_FORCEFIELD
)
744 Player
.p_mana
-= MM_FORCEFIELD
;
745 Shield
= (Player
.p_maxenergy
+ Player
.p_shield
) * 4.2 + 45.0;
746 mvaddstr(5, 0, "Force Field up.\n");
750 case '4': /* transform */
751 if (Player
.p_magiclvl
< ML_XFORM
)
754 if (Player
.p_mana
< MM_XFORM
)
757 Player
.p_mana
-= MM_XFORM
;
758 Whichmonster
= (int) ROLL(0.0, 100.0);
759 longjmp(Fightenv
, 0);
764 case '5': /* increase might */
765 if (Player
.p_magiclvl
< ML_INCRMIGHT
)
768 if (Player
.p_mana
< MM_INCRMIGHT
)
771 Player
.p_mana
-= MM_INCRMIGHT
;
773 (1.2 * (Player
.p_strength
+ Player
.p_sword
)
774 + 5.0 - Player
.p_might
) / 2.0;
775 mvprintw(5, 0, "New strength: %.0f\n", Player
.p_might
);
779 case '6': /* invisible */
780 if (Player
.p_magiclvl
< ML_INVISIBLE
)
783 if (Player
.p_mana
< MM_INVISIBLE
)
786 Player
.p_mana
-= MM_INVISIBLE
;
788 (1.2 * (Player
.p_quickness
+ Player
.p_quksilver
)
789 + 5.0 - Player
.p_speed
) / 2.0;
790 mvprintw(5, 0, "New quickness: %.0f\n", Player
.p_speed
);
794 case '7': /* transport */
795 if (Player
.p_magiclvl
< ML_XPORT
)
798 if (Player
.p_mana
< MM_XPORT
)
801 Player
.p_mana
-= MM_XPORT
;
802 if (Player
.p_brains
+ Player
.p_magiclvl
803 < Curmonster
.m_experience
/ 200.0 * drandom()) {
804 mvaddstr(5, 0, "Transport backfired!\n");
805 altercoordinates(0.0, 0.0, A_FAR
);
808 mvprintw(5, 0, "%s is transported.\n", Enemyname
);
810 /* monster didn't drop
812 Curmonster
.m_treasuretype
= 0;
814 Curmonster
.m_energy
= 0.0;
819 case '8': /* paralyze */
820 if (Player
.p_magiclvl
< ML_PARALYZE
)
823 if (Player
.p_mana
< MM_PARALYZE
)
826 Player
.p_mana
-= MM_PARALYZE
;
827 if (Player
.p_magiclvl
>
828 Curmonster
.m_experience
/ 1000.0 * drandom()) {
829 mvprintw(5, 0, "%s is held.\n", Enemyname
);
830 Curmonster
.m_speed
= -2.0;
832 mvaddstr(5, 0, "Monster unaffected.\n");
836 case '9': /* specify */
837 if (Player
.p_specialtype
< SC_COUNCIL
)
840 if (Player
.p_mana
< MM_SPECIFY
)
843 Player
.p_mana
-= MM_SPECIFY
;
844 mvaddstr(5, 0, "Which monster do you want [0-99] ? ");
845 Whichmonster
= (int) infloat();
846 Whichmonster
= MAX(0, MIN(99, Whichmonster
));
847 longjmp(Fightenv
, 0);
855 callmonster(int which
)
857 struct monster Othermonster
; /* to find a name for mimics */
859 which
= MIN(which
, 99); /* make sure within range */
862 fseek(Monstfp
, (long) which
* (long) SZ_MONSTERSTRUCT
, SEEK_SET
);
863 fread((char *) &Curmonster
, SZ_MONSTERSTRUCT
, 1, Monstfp
);
865 /* handle some special monsters */
866 if (Curmonster
.m_type
== SM_MODNAR
) {
867 if (Player
.p_specialtype
< SC_COUNCIL
)
868 /* randomize some stats */
870 Curmonster
.m_strength
*= drandom() + 0.5;
871 Curmonster
.m_brains
*= drandom() + 0.5;
872 Curmonster
.m_speed
*= drandom() + 0.5;
873 Curmonster
.m_energy
*= drandom() + 0.5;
874 Curmonster
.m_experience
*= drandom() + 0.5;
875 Curmonster
.m_treasuretype
=
876 (int) ROLL(0.0, (double) Curmonster
.m_treasuretype
);
878 /* make Modnar into Morgoth */
880 strcpy(Curmonster
.m_name
, "Morgoth");
881 Curmonster
.m_strength
= drandom() * (Player
.p_maxenergy
+ Player
.p_shield
) / 1.4
882 + drandom() * (Player
.p_maxenergy
+ Player
.p_shield
) / 1.5;
883 Curmonster
.m_brains
= Player
.p_brains
;
884 Curmonster
.m_energy
= Player
.p_might
* 30.0;
885 Curmonster
.m_type
= SM_MORGOTH
;
886 Curmonster
.m_speed
= Player
.p_speed
* 1.1
887 + ((Player
.p_specialtype
== SC_EXVALAR
) ? Player
.p_speed
: 0.0);
888 Curmonster
.m_flock
= 0.0;
889 Curmonster
.m_treasuretype
= 0;
890 Curmonster
.m_experience
= 0.0;
893 if (Curmonster
.m_type
== SM_MIMIC
)
894 /* pick another name */
896 which
= (int) ROLL(0.0, 100.0);
897 fseek(Monstfp
, (long) which
* (long) SZ_MONSTERSTRUCT
, SEEK_SET
);
898 fread(&Othermonster
, SZ_MONSTERSTRUCT
, 1, Monstfp
);
899 strcpy(Curmonster
.m_name
, Othermonster
.m_name
);
901 truncstring(Curmonster
.m_name
);
903 if (Curmonster
.m_type
!= SM_MORGOTH
)
904 /* adjust stats based on which circle player is in */
906 Curmonster
.m_strength
*= (1.0 + Circle
/ 2.0);
907 Curmonster
.m_brains
*= Circle
;
908 Curmonster
.m_speed
+= Circle
* 1.e
-9;
909 Curmonster
.m_energy
*= Circle
;
910 Curmonster
.m_experience
*= Circle
;
912 if (Player
.p_blindness
)
913 /* cannot see monster if blind */
914 Enemyname
= "A monster";
916 Enemyname
= Curmonster
.m_name
;
918 if (Player
.p_speed
<= 0.0)
919 /* make Player.p_speed positive */
921 Curmonster
.m_speed
+= -Player
.p_speed
;
922 Player
.p_speed
= 1.0;
924 /* fill up the rest of the structure */
925 Curmonster
.m_o_strength
= Curmonster
.m_strength
;
926 Curmonster
.m_o_speed
= Curmonster
.m_maxspeed
= Curmonster
.m_speed
;
927 Curmonster
.m_o_energy
= Curmonster
.m_energy
;
928 Curmonster
.m_melee
= Curmonster
.m_skirmish
= 0.0;
934 int whichtreasure
; /* calculated treasure to grant */
935 int temp
; /* temporary */
937 double treasuretype
; /* monster's treasure type */
938 double gold
= 0.0; /* gold awarded */
939 double gems
= 0.0; /* gems awarded */
940 double dtemp
; /* for temporary calculations */
942 whichtreasure
= (int) ROLL(1.0, 3.0); /* pick a treasure */
943 treasuretype
= (double) Curmonster
.m_treasuretype
;
949 if (drandom() > 0.65)
952 if (Curmonster
.m_treasuretype
> 7)
955 gems
= ROLL(1.0, (treasuretype
- 7.0)
956 * (treasuretype
- 7.0) * (Circle
- 1.0) / 4.0);
957 printw("You have discovered %.0f gems!", gems
);
961 gold
= ROLL(treasuretype
* 10.0, treasuretype
962 * treasuretype
* 10.0 * (Circle
- 1.0));
963 printw("You have found %.0f gold pieces.", gold
);
966 addstr(" Do you want to pick them up ? ");
967 ch
= getanswer("NY", FALSE
);
971 if (drandom() < treasuretype
/ 35.0 + 0.04)
974 addstr("They were cursed!\n");
977 collecttaxes(gold
, gems
);
982 /* other treasures */
984 addstr("You have found some treasure. Do you want to inspect it ? ");
985 ch
= getanswer("NY", FALSE
);
991 if (drandom() < 0.08 && Curmonster
.m_treasuretype
!= 4) {
992 addstr("It was cursed!\n");
996 switch (Curmonster
.m_treasuretype
) {
997 case 1: /* treasure type 1 */
998 switch (whichtreasure
) {
1000 addstr("You've discovered a power booster!\n");
1001 Player
.p_mana
+= ROLL(Circle
* 4.0, Circle
* 30.0);
1005 addstr("You have encountered a druid.\n");
1006 Player
.p_experience
+=
1007 ROLL(0.0, 2000.0 + Circle
* 400.0);
1011 addstr("You have found a holy orb.\n");
1012 Player
.p_sin
= MAX(0.0, Player
.p_sin
- 0.25);
1016 /* end treasure type 1 */
1018 case 2: /* treasure type 2 */
1019 switch (whichtreasure
) {
1021 addstr("You have found an amulet.\n");
1026 addstr("You've found some holy water!\n");
1027 ++Player
.p_holywater
;
1031 addstr("You've met a hermit!\n");
1032 Player
.p_sin
*= 0.75;
1033 Player
.p_mana
+= 12.0 * Circle
;
1037 /* end treasure type 2 */
1039 case 3: /* treasure type 3 */
1040 switch (whichtreasure
) {
1042 dtemp
= ROLL(7.0, 30.0 + Circle
/ 10.0);
1043 printw("You've found a +%.0f shield!\n", dtemp
);
1044 if (dtemp
>= Player
.p_shield
)
1045 Player
.p_shield
= dtemp
;
1051 addstr("You have rescued a virgin. Will you be honorable ? ");
1052 ch
= getanswer("NY", FALSE
);
1055 Player
.p_virgin
= TRUE
;
1057 Player
.p_experience
+= 2000.0 * Circle
;
1063 addstr("You've discovered some athelas!\n");
1068 /* end treasure type 3 */
1070 case 4: /* treasure type 4 */
1071 addstr("You've found a scroll. Will you read it ? ");
1072 ch
= getanswer("NY", FALSE
);
1076 switch ((int) ROLL(1, 6)) {
1078 addstr("It throws up a shield for you next monster.\n");
1079 getyx(stdscr
, whichtreasure
, ch
);
1080 more(whichtreasure
);
1082 (Player
.p_maxenergy
+ Player
.p_energy
) * 5.5 + Circle
* 50.0;
1083 Whichmonster
= pickmonster();
1084 longjmp(Fightenv
, 0);
1088 addstr("It makes you invisible for you next monster.\n");
1089 getyx(stdscr
, whichtreasure
, ch
);
1090 more(whichtreasure
);
1091 Player
.p_speed
= 1e6
;
1092 Whichmonster
= pickmonster();
1093 longjmp(Fightenv
, 0);
1097 addstr("It increases your strength ten fold to fight your next monster.\n");
1098 getyx(stdscr
, whichtreasure
, ch
);
1099 more(whichtreasure
);
1100 Player
.p_might
*= 10.0;
1101 Whichmonster
= pickmonster();
1102 longjmp(Fightenv
, 0);
1106 addstr("It is a general knowledge scroll.\n");
1107 Player
.p_brains
+= ROLL(2.0, Circle
);
1108 Player
.p_magiclvl
+= ROLL(1.0, Circle
/ 2.0);
1112 addstr("It tells you how to pick your next monster.\n");
1113 addstr("Which monster do you want [0-99] ? ");
1114 Whichmonster
= (int) infloat();
1115 Whichmonster
= MIN(99, MAX(0, Whichmonster
));
1116 longjmp(Fightenv
, 0);
1119 addstr("It was cursed!\n");
1124 /* end treasure type 4 */
1126 case 5: /* treasure type 5 */
1127 switch (whichtreasure
) {
1129 dtemp
= ROLL(Circle
/ 4.0 + 5.0, Circle
/ 2.0 + 9.0);
1130 printw("You've discovered a +%.0f dagger.\n", dtemp
);
1131 if (dtemp
>= Player
.p_sword
)
1132 Player
.p_sword
= dtemp
;
1138 dtemp
= ROLL(7.5 + Circle
* 3.0, Circle
* 2.0 + 160.0);
1139 printw("You have found some +%.0f armour!\n", dtemp
);
1140 if (dtemp
>= Player
.p_shield
)
1141 Player
.p_shield
= dtemp
;
1147 addstr("You've found a tablet.\n");
1148 Player
.p_brains
+= 4.5 * Circle
;
1152 /* end treasure type 5 */
1154 case 6: /* treasure type 6 */
1155 switch (whichtreasure
) {
1157 addstr("You've found a priest.\n");
1158 Player
.p_energy
= Player
.p_maxenergy
+ Player
.p_shield
;
1159 Player
.p_sin
/= 2.0;
1160 Player
.p_mana
+= 24.0 * Circle
;
1161 Player
.p_brains
+= Circle
;
1165 addstr("You have come upon Robin Hood!\n");
1166 Player
.p_shield
+= Circle
* 2.0;
1167 Player
.p_strength
+= Circle
/ 2.5 + 1.0;
1171 dtemp
= ROLL(2.0 + Circle
/ 4.0, Circle
/ 1.2 + 10.0);
1172 printw("You have found a +%.0f axe!\n", dtemp
);
1173 if (dtemp
>= Player
.p_sword
)
1174 Player
.p_sword
= dtemp
;
1180 /* end treasure type 6 */
1182 case 7: /* treasure type 7 */
1183 switch (whichtreasure
) {
1185 addstr("You've discovered a charm!\n");
1190 addstr("You have encountered Merlyn!\n");
1191 Player
.p_brains
+= Circle
+ 5.0;
1192 Player
.p_magiclvl
+= Circle
/ 3.0 + 5.0;
1193 Player
.p_mana
+= Circle
* 10.0;
1197 dtemp
= ROLL(5.0 + Circle
/ 3.0, Circle
/ 1.5 + 20.0);
1198 printw("You have found a +%.0f war hammer!\n", dtemp
);
1199 if (dtemp
>= Player
.p_sword
)
1200 Player
.p_sword
= dtemp
;
1206 /* end treasure type 7 */
1208 case 8: /* treasure type 8 */
1209 switch (whichtreasure
) {
1211 addstr("You have found a healing potion.\n");
1212 Player
.p_poison
= MIN(-2.0, Player
.p_poison
- 2.0);
1216 addstr("You have discovered a transporter. Do you wish to go anywhere ? ");
1217 ch
= getanswer("NY", FALSE
);
1222 addstr("X Y Coordinates ? ");
1223 getstring(Databuf
, SZ_DATABUF
);
1224 sscanf(Databuf
, "%lf %lf", &x
, &y
);
1225 altercoordinates(x
, y
, A_FORCED
);
1230 dtemp
= ROLL(10.0 + Circle
/ 1.2, Circle
* 3.0 + 30.0);
1231 printw("You've found a +%.0f sword!\n", dtemp
);
1232 if (dtemp
>= Player
.p_sword
)
1233 Player
.p_sword
= dtemp
;
1239 /* end treasure type 8 */
1244 case 13: /* treasure types 10 - 13 */
1245 if (drandom() < 0.33) {
1246 if (Curmonster
.m_treasuretype
== 10) {
1247 addstr("You've found a pair of elven boots!\n");
1248 Player
.p_quickness
+= 2.0;
1251 if (Curmonster
.m_treasuretype
== 11
1252 && !Player
.p_palantir
) {
1253 addstr("You've acquired Saruman's palantir.\n");
1254 Player
.p_palantir
= TRUE
;
1257 if (Player
.p_ring
.ring_type
== R_NONE
1258 && Player
.p_specialtype
< SC_COUNCIL
1259 && (Curmonster
.m_treasuretype
== 12
1260 || Curmonster
.m_treasuretype
== 13))
1267 if (drandom() < 0.8)
1282 if (Curmonster
.m_treasuretype
== 12) {
1283 whichtreasure
= R_NAZREG
;
1286 whichtreasure
= R_DLREG
;
1300 whichtreasure
= R_BAD
;
1301 temp
= 15 + Statptr
->c_ringduration
+ (int) ROLL(0, 5);
1304 addstr("You've discovered a ring. Will you pick it up ? ");
1305 ch
= getanswer("NY", FALSE
);
1309 Player
.p_ring
.ring_type
= whichtreasure
;
1310 Player
.p_ring
.ring_duration
= temp
;
1315 /* end treasure types 10 - 13 */
1316 /* fall through to treasure type 9 if
1317 * no treasure from above */
1319 case 9: /* treasure type 9 */
1320 switch (whichtreasure
) {
1322 if (Player
.p_level
<= 1000.0
1323 && Player
.p_crowns
<= 3
1324 && Player
.p_level
>= 10.0) {
1325 addstr("You have found a golden crown!\n");
1329 /* fall through otherwise */
1332 addstr("You've been blessed!\n");
1333 Player
.p_blessing
= TRUE
;
1334 Player
.p_sin
/= 3.0;
1335 Player
.p_energy
= Player
.p_maxenergy
+ Player
.p_shield
;
1336 Player
.p_mana
+= 100.0 * Circle
;
1340 dtemp
= ROLL(1.0, Circle
/ 5.0 + 5.0);
1341 dtemp
= MIN(dtemp
, 99.0);
1342 printw("You have discovered some +%.0f quicksilver!\n", dtemp
);
1343 if (dtemp
>= Player
.p_quksilver
)
1344 Player
.p_quksilver
= dtemp
;
1350 /* end treasure type 9 */
1356 cursedtreasure(void)
1358 if (Player
.p_charms
> 0) {
1359 addstr("But your charm saved you!\n");
1362 if (Player
.p_amulets
> 0) {
1363 addstr("But your amulet saved you!\n");
1367 (Player
.p_maxenergy
+ Player
.p_shield
) / 10.0;
1368 Player
.p_poison
+= 0.25;
1375 double dbuf
[6]; /* to put statistic in */
1376 double dtemp1
, dtemp2
; /* for swapping values */
1377 int first
, second
; /* indices for swapping */
1378 double *dptr
; /* pointer for filling and emptying buf[] */
1382 *dptr
++ = Player
.p_strength
;
1383 *dptr
++ = Player
.p_mana
;
1384 *dptr
++ = Player
.p_brains
;
1385 *dptr
++ = Player
.p_magiclvl
;
1386 *dptr
++ = Player
.p_energy
;
1387 *dptr
= Player
.p_sin
;
1389 /* pick values to swap */
1390 first
= (int) ROLL(0, 5);
1391 second
= (int) ROLL(0, 5);
1395 dtemp1
= dptr
[first
];
1396 /* this expression is split to prevent a compiler loop on some
1398 dtemp2
= dptr
[second
];
1399 dptr
[first
] = dtemp2
;
1400 dptr
[second
] = dtemp1
;
1403 Player
.p_strength
= *dptr
++;
1404 Player
.p_mana
= *dptr
++;
1405 Player
.p_brains
= *dptr
++;
1406 Player
.p_magiclvl
= *dptr
++;
1407 Player
.p_energy
= *dptr
++;
1408 Player
.p_sin
= *dptr
;