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