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