comparison urogue/monsters.c @ 256:c495a4f288c6

Import UltraRogue from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 31 Jan 2017 19:56:04 -0500
parents
children 0250220d8cdd
comparison
equal deleted inserted replaced
253:d9badb9c0179 256:c495a4f288c6
1 /*
2 monsters.c - File with various monster functions in it
3
4 UltraRogue: The Ultimate Adventure in the Dungeons of Doom
5 Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
6 All rights reserved.
7
8 Based on "Advanced Rogue"
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
10 All rights reserved.
11
12 Based on "Rogue: Exploring the Dungeons of Doom"
13 Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
14 All rights reserved.
15
16 See the file LICENSE.TXT for full copyright and licensing information.
17 */
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include "rogue.h"
23
24 /*
25 summon_monster()
26 Summon a monster.
27 */
28
29 struct linked_list *
30 summon_monster(int type, int familiar, int print_message)
31 {
32 struct linked_list *mp;
33 struct thing *tp;
34 int monster;
35
36 if (familiar && !is_wearing(R_WIZARD) && off(player, CANSUMMON))
37 {
38 msg("Only spellcasters can summon familiars!");
39 return(NULL);
40 }
41
42 if (type == 0) /* Random monster modified by level */
43 {
44 int ndice = min(pstats.s_lvl, (nummonst - NUMSUMMON) / 8);
45
46 monster = min(nummonst, roll(ndice, pstats.s_charisma));
47
48 /*
49 * if a familiar exists, and it is higher in level, make it
50 * again
51 */
52
53 if (fam_ptr != NULL)
54 {
55 struct thing *fp = THINGPTR(fam_ptr);
56
57 monster = max(fp->t_index, monster);
58 }
59 }
60 else
61 monster = type;
62
63 turn_on(player, SUMMONING);
64
65 mp = creat_mons(&player, monster, NOMESSAGE);
66
67 if (!mp)
68 {
69 msg("Summon failed.");
70 turn_off(player, SUMMONING);
71 return(NULL);
72 }
73
74 if (print_message == MESSAGE)
75 {
76 msg("A %s appears out of nowhere!", monsters[monster].m_name);
77
78 if (familiar)
79 msg("I am here to serve %s.", whoami);
80 else
81 {
82 msg("My goodness, are you Yendor?");
83 ++mons_summoned;
84 debug("%d monsters now summoned.", mons_summoned);
85 }
86 }
87
88 tp = THINGPTR(mp);
89 turn_on(*tp, ISCHARMED); /* Summoned monsters are always charmed */
90
91 if (familiar)
92 {
93 int i;
94 static const unsigned long fam_on[]= {ISREGEN,CANSHOOT,CANWIELD,HASARMOR,ISFAMILIAR,0};
95 static const unsigned long fam_off[]={ISMEAN, ISHUH, ISINVIS,
96 CANSURPRISE, NOMOVE,
97 ISSLOW, ISSHADOW, ISGREED, ISFAST,
98 CANFLY, ISFLEE, 0};
99
100 for (i = 0; fam_on[i]; i++)
101 turn_on(*tp, fam_on[i]);
102
103 for (i = 0; fam_off[i]; i++)
104 turn_off(*tp, fam_off[i]);
105
106 if (fam_ptr != NULL) /* Get rid of old familiar */
107 {
108 struct thing *fp = THINGPTR(fam_ptr);
109 struct linked_list *fpack = fp->t_pack;
110 struct linked_list *item;
111
112 if (fpack != NULL) /* Transfer pack */
113 {
114 if (tp->t_pack == NULL)
115 tp->t_pack = fpack;
116 else
117 {
118 for(item=tp->t_pack; item->l_next != NULL; item=next(item))
119 ; /* find last item in list */
120
121 item->l_next = fpack;
122 fpack->l_prev = item;
123 }
124 }
125
126 fpack = NULL;
127 killed(NULL, fam_ptr, NOMESSAGE, NOPOINTS);
128 }
129
130 fam_ptr = mp;
131 fam_type = monster;
132
133 /* improve their abilities a bit */
134
135 tp->t_stats.s_hpt += roll(2, pstats.s_lvl);
136 tp->t_stats.s_lvl += roll(2, (pstats.s_lvl / 4) + 1);
137 tp->t_stats.s_arm -= roll(2, (pstats.s_lvl / 4) + 1);
138 tp->t_stats.s_str += roll(2, (pstats.s_lvl / 4) + 1);
139 tp->t_stats.s_intel += roll(2, (pstats.s_lvl / 4) + 1);
140 tp->t_stats.s_wisdom += roll(2, (pstats.s_lvl / 4) + 1);
141 tp->t_stats.s_dext += roll(2, (pstats.s_lvl / 4) + 1);
142 tp->t_stats.s_const += roll(2, (pstats.s_lvl / 4) + 1);
143 tp->t_stats.s_charisma += roll(2, (pstats.s_lvl / 4) + 1);
144
145 /* some monsters do no damage by default */
146
147 if (strcmp(tp->t_stats.s_dmg, "0d0") == 0)
148 tp->t_stats.s_dmg = "1d8";
149
150 tp->maxstats = tp->t_stats; /* structure assignment */
151 }
152
153 turn_off(player, SUMMONING);
154
155 return(mp);
156 }
157
158 /*
159 randmonster()
160 wander - wandering monster allowed
161 grab - a throne room monster allowed
162 */
163
164 int
165 randmonster(int wander, int grab)
166 {
167 int mons_number, cur_level, range, i;
168
169 /* Do we want a merchant? */
170
171 if (wander == WANDER && monsters[nummonst].m_wander && rnd(5000) < 3)
172 return(nummonst);
173
174 cur_level = level;
175 range = 4 * NLEVMONS;
176 i = 0;
177
178 do
179 {
180 if (i++ > range * 10) /* just in case all have be genocided */
181 {
182 i = 0;
183
184 if (--cur_level <= 0)
185 fatal("Rogue could not find a monster to make");
186 }
187
188 mons_number = NLEVMONS * (cur_level - 1) +
189 (rnd(range) - (range - 1 - NLEVMONS));
190
191 if (mons_number < 1)
192 mons_number = rnd(NLEVMONS) + 1;
193 else if (mons_number > nummonst - NUMSUMMON - 1)
194 {
195 if (grab == GRAB)
196 mons_number = rnd(range + NUMSUMMON) +
197 (nummonst - 1) -
198 (range + NUMSUMMON - 1);
199 else if (mons_number > nummonst - 1)
200 mons_number = rnd(range) +
201 (nummonst - NUMSUMMON - 1) -
202 (range - 1);
203 }
204 }
205 while (wander == WANDER ? !monsters[mons_number].m_wander ||
206 !monsters[mons_number].m_normal :
207 !monsters[mons_number].m_normal);
208
209 return((short)mons_number);
210 }
211
212 /*
213 new_monster()
214 Pick a new monster and add it to the list
215 */
216
217 void
218 new_monster(struct linked_list *item, int type, coord *cp, int max_monster)
219 {
220 struct thing *tp;
221 struct monster *mp;
222 char *ip, *hitp;
223 int i, min_intel, max_intel;
224 int num_dice, num_sides = 8, num_extra = 0;
225 int eff_charisma = pstats.s_charisma;
226 int eff_intel = pstats.s_intel;
227
228 attach(mlist, item);
229 tp = THINGPTR(item);
230 tp->t_index = type;
231 tp->t_wasshot = FALSE;
232 tp->t_type = monsters[type].m_appear;
233 tp->t_ctype = C_MONSTER;
234 tp->t_no_move = 0;
235 tp->t_doorgoal = -1;
236 tp->t_pos = *cp;
237 tp->t_oldpos = *cp;
238 tp->t_oldch = CCHAR( mvwinch(cw, cp->y, cp->x) );
239 mvwaddch(mw, cp->y, cp->x, tp->t_type);
240 mp = &monsters[tp->t_index];
241
242 /* Figure out monster's hit points */
243
244 hitp = mp->m_stats.s_hpt;
245 num_dice = atoi(hitp);
246
247 if ((hitp = strchr(hitp, 'd')) != NULL)
248 {
249 num_sides = atoi(++hitp);
250
251 if ((hitp = strchr(hitp, '+')) != NULL)
252 num_extra = atoi(++hitp);
253 }
254
255 if (max_monster == MAXSTATS)
256 tp->t_stats.s_hpt = num_dice * num_sides + num_extra;
257 else
258 tp->t_stats.s_hpt = roll(num_dice, num_sides) + num_extra;
259
260 tp->t_stats.s_lvl = mp->m_stats.s_lvl;
261 tp->t_stats.s_arm = mp->m_stats.s_arm;
262 tp->t_stats.s_dmg = mp->m_stats.s_dmg;
263 tp->t_stats.s_exp = mp->m_stats.s_exp + mp->m_add_exp * tp->t_stats.s_hpt;
264 tp->t_stats.s_str = mp->m_stats.s_str;
265
266 if (max_level > 30)
267 {
268 tp->t_stats.s_hpt += roll(4, (max_level - 60) * 2);
269 tp->t_stats.s_lvl += roll(4, (max_level - 60) / 8);
270 tp->t_stats.s_arm -= roll(2, (max_level - 60) / 8);
271 tp->t_stats.s_str += roll(2, (max_level - 60) / 12);
272 tp->t_stats.s_exp += roll(4, (max_level - 60) * 2) * mp->m_add_exp;
273 }
274
275 /*
276 * just initailize others values to something reasonable for now
277 * maybe someday will *really* put these in monster table
278 */
279
280 tp->t_stats.s_wisdom = 8 + rnd(4);
281 tp->t_stats.s_dext = 8 + rnd(4);
282 tp->t_stats.s_const = 8 + rnd(4);
283 tp->t_stats.s_charisma = 8 + rnd(4);
284
285 if (max_level > 45)
286 tp->t_stats.s_dext += roll(2, (max_level - 50) / 8);
287
288 /* Set the initial flags */
289
290 for (i = 0; i < 16; i++)
291 tp->t_flags[i] = 0;
292
293 for (i = 0; i < 16; i++)
294 turn_on(*tp, mp->m_flags[i]);
295
296 /* suprising monsters don't always surprise you */
297
298 if (!max_monster && on(*tp, CANSURPRISE) && rnd(100) < 20)
299 turn_off(*tp, CANSURPRISE);
300
301 /* If this monster is unique, genocide it */
302
303 if (on(*tp, ISUNIQUE))
304 mp->m_normal = FALSE;
305
306 /* gods automatically get special abilities */
307
308 if (on(*tp, ISGOD))
309 {
310 turn_on(*tp, CANFRIGHTEN);
311 turn_on(*tp, CANCAST);
312 turn_on(*tp, CANFLY);
313 turn_on(*tp, CANBARGAIN);
314 turn_on(*tp, ISLARGE);
315 turn_on(*tp, CANTELEPORT);
316 turn_on(*tp, CANSPEAK);
317 turn_on(*tp, CANDARKEN);
318 turn_on(*tp, CANSEE);
319 turn_on(*tp, CANLIGHT);
320 turn_on(*tp, BMAGICHIT);
321 }
322
323 tp->t_turn = TRUE;
324 tp->t_pack = NULL;
325
326 /* Figure intelligence */
327
328 min_intel = atoi(mp->m_intel);
329
330 if ((ip = (char *) strchr(mp->m_intel, '-')) == NULL)
331 tp->t_stats.s_intel = min_intel;
332 else
333 {
334 max_intel = atoi(++ip);
335
336 if (max_monster)
337 tp->t_stats.s_intel = max_intel;
338 else
339 tp->t_stats.s_intel = min_intel + rnd(max_intel - min_intel);
340 }
341
342 tp->t_stats.s_power = (rnd(tp->t_stats.s_lvl / 5) + 1) * tp->t_stats.s_intel;
343
344 tp->maxstats = tp->t_stats; /* structure assignment */
345
346 /* If the monster can shoot, it may have a weapon */
347
348 if (on(*tp, CANSHOOT) && (max_monster || rnd(9) < 6))
349 {
350 struct linked_list *thrower_item, *missile_item;
351 struct object *thrower, *a_missile;
352
353 thrower_item = new_item(sizeof *thrower);
354 thrower = OBJPTR(thrower_item);
355 carried_weapon(tp, thrower);
356
357 missile_item = new_item(sizeof *a_missile);
358 a_missile = OBJPTR(missile_item);
359 carried_weapon(tp, a_missile);
360
361 /* The monster may use a crossbow, sling, footbow, or an arrow */
362 /* Take racial preferences into account */
363
364 if ((strcmp(mp->m_name, "elf") == 0) ||
365 (strcmp(mp->m_name, "noldor elf") == 0))
366 {
367 thrower->o_which = BOW;
368
369 if (rnd(5) == 0)
370 a_missile->o_which = SILVERARROW;
371 else
372 a_missile->o_which = ARROW;
373 }
374 else if ((strcmp(mp->m_name, "dwarf") == 0) ||
375 (strcmp(mp->m_name, "kazad dwarf") == 0))
376 {
377 thrower->o_which = CROSSBOW;
378 a_missile->o_which = BOLT;
379 }
380 else if (on(*tp, ISSMALL))
381 {
382 switch (rnd(3))
383 {
384 case 0:
385 thrower->o_which = SLING;
386 a_missile->o_which = BULLET;
387 break;
388 default:
389 thrower->o_which = SLING;
390 a_missile->o_which = ROCK;
391 }
392 }
393 else if (on(*tp, ISLARGE))
394 {
395 switch (rnd(4))
396 {
397 case 0:
398 thrower->o_which = CROSSBOW;
399 a_missile->o_which = BOLT;
400 break;
401
402 case 1:
403 thrower->o_which = FOOTBOW;
404 a_missile->o_which = FBBOLT;
405 break;
406
407 default:
408 thrower->o_which = BOW;
409
410 if (rnd(5) == 0)
411 a_missile->o_which = FLAMEARROW;
412 else
413 a_missile->o_which = ARROW;
414
415 break;
416 }
417 }
418 else
419 {
420 switch (rnd(6))
421 {
422 case 1:
423 thrower->o_which = SLING;
424 a_missile->o_which = ROCK;
425 break;
426
427 case 2:
428 thrower->o_which = CROSSBOW;
429 a_missile->o_which = BOLT;
430 break;
431
432 case 3:
433 thrower->o_which = FOOTBOW;
434 a_missile->o_which = FBBOLT;
435 break;
436
437 case 4:
438 thrower->o_which = BOW;
439 a_missile->o_which = ARROW;
440 break;
441
442 default:
443 thrower->o_which = SLING;
444 a_missile->o_which = BULLET;
445 break;
446 }
447 }
448
449 init_weapon(thrower, thrower->o_which);
450 init_weapon(a_missile, a_missile->o_which);
451
452 attach(tp->t_pack, thrower_item);
453 attach(tp->t_pack, missile_item);
454 }
455
456 /* monsters that wield weapons */
457
458 if (on(*tp, CANWIELD))
459 {
460 if (max_monster || rnd(3))
461 {
462 struct linked_list *wield_item;
463 struct object *wielded;
464
465 wield_item = new_item(sizeof *wielded);
466 wielded = OBJPTR(wield_item);
467 carried_weapon(tp, wielded);
468
469 i = rnd(CLAYMORE - CLUB) + rnd(2 * tp->t_stats.s_lvl);
470 i = min(i, CLAYMORE);
471 wielded->o_which = i;
472 init_weapon(wielded, wielded->o_which);
473
474 /* Is it too heavy? */
475
476 if (itemweight(wielded) > 8 * tp->t_stats.s_str)
477 discard(wield_item);
478 else
479 attach(tp->t_pack, wield_item);
480 }
481 }
482
483 if (is_wearing(R_AGGR))
484 chase_it(cp, &player);
485 else
486 {
487 turn_off(*tp, ISRUN);
488
489 if (on(*tp, ISFLEE) && (rnd(4) == 0))
490 turn_off(*tp, ISFLEE);
491
492 if (rnd(luck) == 0)
493 switch (player.t_ctype)
494 {
495 case C_MAGICIAN:
496 case C_ILLUSION:
497 eff_intel = 2 * pstats.s_intel;
498 break;
499 case C_DRUID:
500 eff_intel = 2 * pstats.s_intel;
501 case C_RANGER:
502 eff_charisma = 2 * pstats.s_charisma;
503 break;
504 case C_ASSASIN:
505 case C_THIEF:
506 case C_NINJA:
507 eff_charisma = pstats.s_charisma / 2;
508 break;
509 }
510
511 /* LOWFRIENDLY monsters might be friendly */
512
513 i = roll(1,100);
514
515 if (i == 0 || (on(*tp, LOWFRIENDLY) && i < eff_charisma) ||
516 (on(*tp, MEDFRIENDLY) && i < 3 * eff_charisma) ||
517 (on(*tp, HIGHFRIENDLY) && i < 5 * eff_charisma))
518 {
519 turn_on(*tp, ISFRIENDLY);
520 turn_off(*tp, ISMEAN);
521 }
522
523 i = roll(1,100);
524
525 if (i == 0 || (on(*tp, LOWCAST) && i < eff_intel) ||
526 (on(*tp, MEDCAST) && i < 3 * eff_intel) ||
527 (on(*tp, HIGHCAST) && i < 5 * eff_intel))
528 {
529 turn_on(*tp, CANCAST);
530 }
531
532 if (on(*tp, ISDISGUISE))
533 {
534 char mch = 0;
535
536 if (tp->t_pack != NULL)
537 mch = (OBJPTR(tp->t_pack))->o_type;
538 else
539 switch (rnd(level > arts[0].ar_level ? 10 : 9))
540 {
541 case 0: mch = GOLD; break;
542 case 1: mch = POTION; break;
543 case 2: mch = SCROLL; break;
544 case 3: mch = FOOD; break;
545 case 4: mch = WEAPON; break;
546 case 5: mch = ARMOR; break;
547 case 6: mch = RING; break;
548 case 7: mch = STICK; break;
549 case 8: mch = monsters[randmonster(NOWANDER, NOGRAB)].m_appear;
550 break;
551 case 9: mch = ARTIFACT; break;
552 }
553
554 tp->t_disguise = mch;
555 }
556 }
557 }
558
559 /*
560 wanderer()
561 A wandering monster has awakened and is headed for the player
562 */
563
564 void
565 wanderer(void)
566 {
567 int i, cnt = 0;
568 struct room *hr = roomin(hero);
569 struct linked_list *item;
570 struct thing *tp;
571 coord cp;
572 char *loc;
573 int which;
574
575 /* Find a place for it -- avoid the player's room */
576
577 do
578 {
579 do
580 {
581 cnt++;
582 i = rnd_room();
583 }
584 while (!(hr != &rooms[i] || levtype == MAZELEV
585 || levtype == THRONE || cnt > 5000));
586
587 rnd_pos(&rooms[i], &cp);
588 }
589 while(!step_ok(cp.y, cp.x, NOMONST, NULL));
590
591 /* Create a new wandering monster */
592
593 item = new_item(sizeof *tp);
594 which = randmonster(TRUE, FALSE);
595 new_monster(item, which, &cp, FALSE);
596
597 tp = THINGPTR(item);
598 tp->t_pos = cp; /* Assign the position to the monster */
599
600 chase_it(&tp->t_pos, &player);
601
602 i = rnd(7);
603
604 if (on(*tp, ISSWARM) && i < 5)
605 cnt = roll(2, 4);
606 else if (on(*tp, ISFLOCK) && i < 5)
607 cnt = roll(1, 4);
608 else
609 cnt = 0;
610
611 for (i = 1; i <= cnt; i++)
612 {
613 struct linked_list *ip = creat_mons(tp, which, NOMESSAGE);
614
615 if (ip != NULL)
616 {
617 struct thing *mp = THINGPTR(ip);
618
619 if (on(*tp, ISFRIENDLY))
620 turn_on(*mp, ISFRIENDLY);
621 else
622 turn_off(*mp, ISFRIENDLY);
623 }
624 }
625
626 if (cnt > 0)
627 {
628 if (on(*tp, LOWCAST) || on(*tp, MEDCAST) || on(*tp, HIGHCAST))
629 turn_on(*tp, CANCAST);
630
631 tp->t_stats.s_hpt += roll(2, 8);
632 tp->t_stats.s_lvl += roll(2, 3);
633 tp->t_stats.s_arm -= roll(1, 6);
634 tp->t_stats.s_str += roll(2, 3);
635 tp->t_stats.s_intel += roll(2, 3);
636 tp->t_stats.s_exp += roll(2, 8) * monsters[which].m_add_exp;
637 }
638
639 i = DISTANCE(cp, hero);
640
641 if (i < 20)
642 loc = "very close to you";
643 else if (i < 400)
644 loc = "nearby";
645 else
646 loc = "in the distance";
647
648 if (wizard)
649 msg("Started a wandering %s.", monsters[tp->t_index].m_name);
650 else if (on(*tp, ISUNDEAD) && (player.t_ctype == C_CLERIC ||
651 player.t_ctype == C_PALADIN || is_wearing(R_PIETY)))
652 msg("You sense a new ungodly monster %s.", loc);
653 else if (on(player, CANHEAR) || (player.t_ctype == C_THIEF &&
654 rnd(20) == 0))
655 msg("You hear a new %s moving %s.",
656 monsters[tp->t_index].m_name, loc);
657 else if (on(player, CANSCENT) || (player.t_ctype == C_THIEF &&
658 rnd(20) == 0))
659 msg("You smell a new %s %s.", monsters[tp->t_index].m_name,
660 loc);
661 }
662
663 /*
664 wake_monster
665
666 what to do when the hero steps next to a monster
667 */
668
669 struct linked_list *
670 wake_monster(int y, int x)
671 {
672 struct thing *tp;
673 struct linked_list *it;
674 struct room *trp;
675 char *mname;
676
677 if ((it = find_mons(y, x)) == NULL)
678 {
679 debug("Can't find monster in show.");
680 return(NULL);
681 }
682
683 tp = THINGPTR(it);
684
685 if ((good_monster(*tp)) || on(player, SUMMONING))
686 {
687 chase_it(&tp->t_pos, &player);
688 turn_off(*tp, ISINVIS);
689 turn_off(*tp, CANSURPRISE);
690 return(it);
691 }
692
693 trp = roomin(tp->t_pos); /* Current room for monster */
694 mname = monsters[tp->t_index].m_name;
695
696 /* Let greedy ones guard gold */
697
698 if (on(*tp, ISGREED) && off(*tp, ISRUN))
699 if ((trp != NULL) && (lvl_obj != NULL))
700 {
701 struct linked_list *item;
702 struct object *cur;
703
704 for (item = lvl_obj; item != NULL; item = next(item))
705 {
706 cur = OBJPTR(item);
707
708 if ((cur->o_type == GOLD) &&
709 (roomin(cur->o_pos) == trp))
710 {
711 /* Run to the gold */
712 tp->t_horde = cur;
713 turn_on(*tp, ISRUN);
714 turn_off(*tp, ISDISGUISE);
715 tp->t_ischasing = FALSE;
716 /* Make it worth protecting */
717 cur->o_count += roll(2, 3) * GOLDCALC;
718 break;
719 }
720 }
721 }
722
723 /*
724 * Every time he sees mean monster, it might start chasing him unique
725 * monsters always do
726 */
727
728 if ( (on(*tp, ISUNIQUE)) ||
729 ( (rnd(100) > 33) &&
730 on(*tp, ISMEAN) &&
731 off(*tp, ISHELD) &&
732 off(*tp, ISRUN) &&
733 !is_stealth(&player) &&
734 (off(player, ISINVIS) || on(*tp, CANSEE))
735 )
736 )
737 {
738 chase_it(&tp->t_pos, &player);
739 }
740
741 /* Handle gaze attacks */
742
743 if (on(*tp, ISRUN) && cansee(tp->t_pos.y, tp->t_pos.x) &&
744 off(player, ISINVIS))
745 {
746 if (on(*tp, CANHUH)) /* Confusion */
747 {
748 if (on(player, CANREFLECT))
749 {
750 msg("You reflect the bewildering stare of the %s.", mname);
751
752 if (save_throw(VS_MAGIC, tp))
753 {
754 msg("The %s is confused!", mname);
755 turn_on(*tp, ISHUH);
756 }
757 else
758 msg("The %s staggers for a moment.", mname);
759 }
760 else if (save(VS_MAGIC))
761 {
762 msg("You feel dizzy for a moment, but it quickly passes.");
763
764 if (rnd(100) < 67)
765 turn_off(*tp, CANHUH);
766 }
767 else if (off(player, ISCLEAR))
768 {
769 if (off(player, ISHUH))
770 {
771 light_fuse(FUSE_UNCONFUSE, 0, rnd(20) + HUHDURATION, AFTER);
772 msg("The %s's gaze has confused you.", mname);
773 turn_on(player, ISHUH);
774 }
775 else
776 lengthen_fuse(FUSE_UNCONFUSE, rnd(20) + HUHDURATION);
777 }
778 }
779
780 if (on(*tp, CANSNORE)) /* Sleep */
781 {
782 if (on(player, CANREFLECT))
783 {
784 msg("You reflect the lethargic glance of the %s", mname);
785
786 if (save_throw(VS_PARALYZATION, tp))
787 {
788 msg("The %s falls asleep!", mname);
789 tp->t_no_move += SLEEPTIME;
790 }
791 }
792 else if (no_command == 0 && !save(VS_PARALYZATION))
793 {
794 if (is_wearing(R_ALERT))
795 msg("You feel slightly drowsy for a moment.");
796 else
797 {
798 msg("The %s's gaze puts you to sleep.", mname);
799 no_command = SLEEPTIME;
800
801 if (rnd(100) < 50)
802 turn_off(*tp, CANSNORE);
803 }
804 }
805 }
806
807 if (on(*tp, CANFRIGHTEN)) /* Fear */
808 {
809 turn_off(*tp, CANFRIGHTEN);
810
811 if (on(player, CANREFLECT))
812 {
813 msg("The %s sees its reflection. ", mname);
814
815 if (save_throw(VS_MAGIC,tp))
816 {
817 msg("The %s is terrified by its reflection!", mname);
818 turn_on(*tp, ISFLEE);
819 }
820 }
821 else
822 {
823 if (!save(VS_WAND) && !(on(player, ISFLEE) &&
824 (player.t_chasee==tp)))
825 {
826 if ((player.t_ctype != C_PALADIN) &&
827 off(player, SUPERHERO))
828 {
829 turn_on(player, ISFLEE);
830 player.t_ischasing = FALSE;
831 player.t_chasee = tp;
832 msg("The sight of the %s terrifies you.", mname);
833 }
834 else
835 msg("My, the %s looks ugly.", mname);
836 }
837 }
838 }
839
840 if (on(*tp, LOOKSLOW)) /* Slow */
841 {
842 turn_off(*tp, LOOKSLOW);
843
844 if (on(player, CANREFLECT))
845 {
846 msg("You reflect the mournful glare of the %s.", mname);
847
848 if (save_throw(VS_MAGIC,tp))
849 {
850 msg("The %s is slowing down!", mname);
851 turn_on(*tp, ISSLOW);
852 }
853 }
854 else if (is_wearing(R_FREEDOM) || save(VS_MAGIC))
855 msg("You feel run-down for a moment.");
856 else
857 {
858 if (on(player, ISHASTE)) /* Already sped up */
859 {
860 extinguish_fuse(FUSE_NOHASTE);
861 nohaste(NULL);
862 }
863 else
864 {
865 msg("You feel yourself moving %sslower.",
866 on(player, ISSLOW) ? "even " : "");
867
868 if (on(player, ISSLOW))
869 lengthen_fuse(FUSE_NOSLOW, rnd(4) + 4);
870 else
871 {
872 turn_on(player, ISSLOW);
873 player.t_turn = TRUE;
874 light_fuse(FUSE_NOSLOW, 0, rnd(4) + 4, AFTER);
875 }
876 }
877 }
878 }
879
880 if (on(*tp, CANBLIND)) /* Blinding */
881 {
882 turn_off(*tp, CANBLIND);
883
884 if (on(player, CANREFLECT))
885 {
886 msg("You reflect the blinding stare of the %s.", mname);
887
888 if (save_throw(VS_WAND, tp))
889 {
890 msg("The %s is blinded!", mname);
891 turn_on(*tp, ISHUH);
892 }
893 }
894 else if (off(player, ISBLIND))
895 if (save(VS_WAND) || is_wearing(R_TRUESEE) || is_wearing(R_SEEINVIS))
896 msg("Your eyes film over for a moment.");
897 else
898 {
899 msg("The gaze of the %s blinds you.", mname);
900 turn_on(player, ISBLIND);
901 light_fuse(FUSE_SIGHT, 0, rnd(30) + 20, AFTER);
902 look(FALSE);
903 }
904 }
905
906 if (on(*tp, LOOKSTONE)) /* Stoning */
907 {
908 turn_off(*tp, LOOKSTONE);
909
910 if (on(player, CANREFLECT))
911 {
912 msg("You reflect the flinty look of the %s.", mname);
913
914 if (save_throw(VS_PETRIFICATION,tp))
915 {
916 msg("The %s suddenly stiffens", mname);
917 tp->t_no_move += STONETIME;
918 }
919 else
920 {
921 msg("The %s is turned to stone!", mname);
922 killed(&player, it, NOMESSAGE, POINTS);
923 }
924 }
925 else
926 {
927 if (on(player, CANINWALL))
928 msg("The %s cannot focus on you.", mname);
929 else
930 {
931 msg("The gaze of the %s stiffens your limbs.", mname);
932
933 if (save(VS_PETRIFICATION))
934 no_command = STONETIME;
935 else if (rnd(100))
936 no_command = STONETIME * 3;
937 else
938 {
939 msg("The gaze of the %s petrifies you.", mname);
940 msg("You are turned to stone!!! --More--");
941 wait_for(' ');
942 death(D_PETRIFY);
943 return(it);
944 }
945 }
946 }
947 }
948 }
949
950 /*
951 * True Sight sees all Never see ISINWALL or CANSURPRISE See ISSHADOW
952 * 80% See ISINVIS with See Invisibilty
953 */
954
955 if (off(player, CANTRUESEE) &&
956 on(*tp, ISINWALL) || on(*tp, CANSURPRISE) ||
957 (on(*tp, ISSHADOW) && rnd(100) < 80) ||
958 (on(*tp, ISINVIS) && off(player, CANSEE)))
959 {
960 /*
961 TODO: incomplete - need to finish logic
962 int ch = mvwinch(stdscr, y, x);
963 */
964 }
965
966
967 /* hero might be able to hear or smell monster if he can't see it */
968
969 if ((rnd(player.t_ctype == C_THIEF ? 40 : 200) == 0 ||
970 on(player, CANHEAR)) && !cansee(tp->t_pos.y, tp->t_pos.x))
971 msg("You hear a %s nearby.", mname);
972 else if ((rnd(player.t_ctype == C_THIEF ? 40 : 200) == 0 ||
973 on(player, CANSCENT)) && !cansee(tp->t_pos.y, tp->t_pos.x))
974 msg("You smell a %s nearby.", mname);
975
976 return(it);
977 }
978
979 /*
980 genocide()
981 wipe out hated monsters flags: ISBLESSED, ISCURSED
982 */
983
984 void
985 genocide(int flags)
986 {
987 struct linked_list *ip;
988 struct thing *mp;
989 struct linked_list *nip;
990 int which_monst;
991 int blessed = flags & ISBLESSED;
992 int cursed = flags & ISCURSED;
993
994 while ((which_monst = get_monster_number("genocide")) == 0)
995 ;
996
997 if (cursed) /* oops... */
998 {
999 new_level(THRONE, which_monst);
1000 msg("What's this I hear about you trying to wipe me out?");
1001 fighting = running = after = FALSE;
1002 return;
1003 }
1004
1005 /* Remove this monster from the present level */
1006
1007 for (ip = mlist; ip; ip = nip)
1008 {
1009 mp = THINGPTR(ip);
1010 nip = next(ip);
1011
1012 if (mp->t_index == which_monst)
1013 {
1014 check_residue(mp); /* Check for special features before removing */
1015 remove_monster(&mp->t_pos, ip);
1016 }
1017 }
1018
1019 /* Remove from available monsters */
1020
1021 monsters[which_monst].m_normal = FALSE;
1022 monsters[which_monst].m_wander = FALSE;
1023 mpos = 0;
1024 msg("You have wiped out the %s.", monsters[which_monst].m_name);
1025
1026 if (blessed)
1027 genocide(ISNORMAL);
1028 }
1029
1030
1031 /*
1032 id_monst()
1033 lists the monsters with the displayed by the character unless
1034 there is only one in which case it is returned as the string
1035 */
1036
1037 void
1038 id_monst(int monster)
1039 {
1040 int i;
1041
1042 for (i = 1; i <= nummonst + 2; i++)
1043 if (monsters[i].m_appear == monster)
1044 add_line("A %s ", monsters[i].m_name);
1045
1046 end_line();
1047 }
1048
1049
1050 /*
1051 check_residue()
1052 takes care of any effect of the monster
1053 */
1054
1055 void
1056 check_residue(struct thing *tp)
1057 {
1058 /* Take care of special abilities */
1059
1060 if (on(*tp, DIDHOLD) && (--hold_count == 0))
1061 turn_off(player, ISHELD);
1062
1063 /* If it has lowered player, give him back a level, maybe */
1064
1065 if (on(*tp, DIDDRAIN) && rnd(3) == 0)
1066 raise_level();
1067
1068 /* If frightened of this monster, stop */
1069
1070 if (on(player, ISFLEE) && (player.t_chasee==tp))
1071 turn_off(player, ISFLEE);
1072
1073 /* If monster was suffocating player, stop it */
1074 if (on(*tp, DIDSUFFOCATE))
1075 extinguish_fuse(FUSE_SUFFOCATE);
1076
1077 /* If something with fire, may darken */
1078 if (on(*tp, HASFIRE))
1079 {
1080 struct room *rp = roomin(tp->t_pos);
1081
1082 if (rp && (--(rp->r_fires) <= 0))
1083 {
1084 rp->r_flags &= ~HASFIRE;
1085 light(&tp->t_pos);
1086 }
1087 }
1088 }
1089
1090 /*
1091 sell()
1092 displays a menu of goods from which the player may choose to
1093 purchase something.
1094 */
1095
1096 #define SELL_ITEMS 10 /* How many things 'q' might carry */
1097
1098 void
1099 sell(struct thing *tp)
1100 {
1101 struct linked_list *item;
1102 int i, j, min_worth, nitems, chance, which_item, w;
1103 char goods;
1104 struct object *obj;
1105 char buffer[2 * LINELEN];
1106 char dbuf[2 * LINELEN];
1107
1108 struct
1109 {
1110 int which;
1111 int plus1, plus2;
1112 int count;
1113 int worth;
1114 int flags;
1115 char *name;
1116 }
1117 selection[SELL_ITEMS];
1118
1119 int effective_purse = ((player.t_ctype == C_PALADIN) ?
1120 (9 * purse / 10) : purse);
1121
1122 min_worth = -1; /* hope item is never worth less than this */
1123 item = find_mons(tp->t_pos.y, tp->t_pos.x); /* Get pointer to monster */
1124
1125 /* Select the items */
1126
1127 nitems = rnd(6) + 5;
1128
1129 switch (rnd(6))
1130 {
1131 /* Armor */
1132 case 0:
1133 case 1:
1134 goods = ARMOR;
1135 for (i = 0; i < nitems; i++)
1136 {
1137 chance = rnd(100);
1138
1139 for (j = 0; j < maxarmors; j++)
1140 if (chance < armors[j].a_prob)
1141 break;
1142
1143 if (j == maxarmors)
1144 {
1145 debug("Picked a bad armor %d", chance);
1146 j = 0;
1147 }
1148
1149 selection[i].which = j;
1150 selection[i].count = 1;
1151
1152 if (rnd(100) < 40)
1153 selection[i].plus1 = rnd(5) + 1;
1154 else
1155 selection[i].plus1 = 0;
1156
1157 selection[i].name = armors[j].a_name;
1158
1159 switch (luck)
1160 {
1161 case 0: break;
1162 case 1:
1163 if (rnd(3) == 0)
1164 {
1165 selection[i].flags |= ISCURSED;
1166 selection[i].plus1 = -1 - rnd(5);
1167 }
1168 break;
1169
1170 default:
1171 if (rnd(luck))
1172 {
1173 selection[i].flags |= ISCURSED;
1174 selection[i].plus1 = -1 - rnd(5);
1175 }
1176 break;
1177 }
1178
1179 /* Calculate price */
1180
1181 w = armors[j].a_worth;
1182 w *= (1 + luck + (10 * selection[i].plus1));
1183 w = (w / 2) + (roll(6, w) / 6);
1184 selection[i].worth = max(w, 25);
1185
1186 if (min_worth > selection[i].worth || i == 1)
1187 min_worth = selection[i].worth;
1188 }
1189 break;
1190
1191 /* Weapon */
1192 case 2:
1193 case 3:
1194 goods = WEAPON;
1195 for (i = 0; i < nitems; i++)
1196 {
1197 selection[i].which = rnd(maxweapons);
1198 selection[i].count = 1;
1199
1200 if (rnd(100) < 35)
1201 {
1202 selection[i].plus1 = rnd(3);
1203 selection[i].plus2 = rnd(3);
1204 }
1205 else
1206 {
1207 selection[i].plus1 = 0;
1208 selection[i].plus2 = 0;
1209 }
1210
1211 if (weaps[selection[i].which].w_flags & ISMANY)
1212 selection[i].count = rnd(15) + 8;
1213
1214 selection[i].name = weaps[selection[i].which].w_name;
1215
1216 switch (luck)
1217 {
1218 case 0: break;
1219 case 1:
1220 if (rnd(3) == 0)
1221 {
1222 selection[i].flags |= ISCURSED;
1223 selection[i].plus1 = -rnd(3);
1224 selection[i].plus2 = -rnd(3);
1225 }
1226 break;
1227
1228 default:
1229 if (rnd(luck))
1230 {
1231 selection[i].flags |= ISCURSED;
1232 selection[i].plus1 = -rnd(3);
1233 selection[i].plus2 = -rnd(3);
1234 }
1235 break;
1236 }
1237
1238 w = weaps[selection[i].which].w_worth * selection[i].count;
1239 w *= (1 + luck + (10 * selection[i].plus1 +
1240 10 * selection[i].plus2));
1241 w = (w / 2) + (roll(6, w) / 6);
1242 selection[i].worth = max(w, 25);
1243
1244 if (min_worth > selection[i].worth || i == 1)
1245 min_worth = selection[i].worth;
1246 }
1247 break;
1248
1249 /* Staff or wand */
1250 case 4:
1251 goods = STICK;
1252
1253 for (i = 0; i < nitems; i++)
1254 {
1255 selection[i].which = pick_one(ws_magic, maxsticks);
1256 selection[i].plus1 = rnd(11) + 5;
1257 selection[i].count = 1;
1258 selection[i].name = ws_magic[selection[i].which].mi_name;
1259
1260 switch (luck)
1261 {
1262 case 0: break;
1263 case 1:
1264 if (rnd(3) == 0)
1265 {
1266 selection[i].flags |= ISCURSED;
1267 selection[i].plus1 = 1;
1268 }
1269 break;
1270
1271 default:
1272 if (rnd(luck))
1273 {
1274 selection[i].flags |= ISCURSED;
1275 selection[i].plus1 = 1;
1276 }
1277 }
1278
1279 w = ws_magic[selection[i].which].mi_worth;
1280 w += (luck + 1) * 20 * selection[i].plus1;
1281 w = (w / 2) + (roll(6, w) / 6);
1282 selection[i].worth = max(w, 25);
1283
1284 if (min_worth > selection[i].worth || i == 1)
1285 min_worth = selection[i].worth;
1286 }
1287 break;
1288
1289 /* Ring */
1290
1291 case 5:
1292 goods = RING;
1293 for (i = 0; i < nitems; i++)
1294 {
1295 selection[i].which = pick_one(r_magic, maxrings);
1296 selection[i].plus1 = rnd(2) + 1;
1297 selection[i].count = 1;
1298
1299 if (rnd(100) < r_magic[selection[i].which].mi_bless + 10)
1300 selection[i].plus1 += rnd(2) + 1;
1301
1302 selection[i].name = r_magic[selection[i].which].mi_name;
1303
1304 switch (luck)
1305 {
1306 case 0: break;
1307 case 1:
1308 if (rnd(3) == 0)
1309 {
1310 selection[i].flags |= ISCURSED;
1311 selection[i].plus1 = -1 - rnd(2);
1312 }
1313 break;
1314
1315 default:
1316 if (rnd(luck))
1317 {
1318 selection[i].flags |= ISCURSED;
1319 selection[i].plus1 = -1 - rnd(2);
1320 }
1321 }
1322
1323 w = r_magic[selection[i].which].mi_worth;
1324
1325 switch(selection[i].which)
1326 {
1327 case R_DIGEST:
1328 if (selection[i].plus1 > 2)
1329 selection[i].plus1 = 2;
1330 else if (selection[i].plus1 < 1)
1331 selection[i].plus1 = 1;
1332 /* fall thru here to other cases */
1333 case R_ADDSTR:
1334 case R_ADDDAM:
1335 case R_PROTECT:
1336 case R_ADDHIT:
1337 case R_ADDINTEL:
1338 case R_ADDWISDOM:
1339 if (selection[i].plus1 > 0)
1340 w += selection[i].plus1 * 50;
1341 }
1342
1343 w *= (1 + luck);
1344 w = (w / 2) + (roll(6, w) / 6);
1345 selection[i].worth = max(w, 25);
1346
1347 if (min_worth > selection[i].worth * selection[i].count)
1348 min_worth = selection[i].worth;
1349 }
1350 }
1351
1352 /* See if player can afford an item */
1353
1354 if (min_worth > effective_purse)
1355 {
1356 msg("The %s eyes your small purse and departs.",
1357 monsters[nummonst].m_name);
1358
1359 /* Get rid of the monster */
1360
1361 killed(NULL, item, NOMESSAGE, NOPOINTS);
1362
1363 return;
1364 }
1365
1366 /* Display the goods */
1367
1368 msg("The %s shows you his wares.", monsters[nummonst].m_name);
1369 wstandout(cw);
1370 mvwaddstr(cw, 0, mpos, morestr);
1371 wstandend(cw);
1372 wrefresh(cw);
1373 wait_for(' ');
1374 msg("");
1375 clearok(cw, TRUE);
1376 touchwin(cw);
1377
1378 wclear(hw);
1379 touchwin(hw);
1380
1381 for (i = 0; i < nitems; i++)
1382 {
1383 if (selection[i].worth > effective_purse)
1384 continue;
1385
1386 wmove(hw, i + 2, 0);
1387 sprintf(dbuf, "[%c] ", ('a' + i));
1388
1389 switch(goods)
1390 {
1391 case ARMOR:
1392 strcat(dbuf, "Some ");
1393 break;
1394 case WEAPON:
1395 if (selection[i].count == 1)
1396 strcat(dbuf, "A ");
1397 else
1398 {
1399 sprintf(buffer, "%2d ", selection[i].count);
1400 strcat(dbuf, buffer);
1401 }
1402 break;
1403
1404 case STICK:
1405 strcat(dbuf, "A ");
1406 strcat(dbuf, ws_type[selection[i].which]);
1407 strcat(dbuf, " of ");
1408 break;
1409
1410 case RING:
1411 strcat(dbuf, "A ring of ");
1412 break;
1413 }
1414
1415 strcat(dbuf, selection[i].name);
1416
1417 if (selection[i].count > 1)
1418 strcat(dbuf, "s");
1419
1420 sprintf(buffer, "%-50s Price: %d", dbuf, selection[i].worth);
1421 waddstr(hw, buffer);
1422 }
1423
1424 sprintf(buffer, "Purse: %d", purse);
1425 mvwaddstr(hw, nitems + 3, 0, buffer);
1426 mvwaddstr(hw, 0, 0, "How about one of the following goods? ");
1427 wrefresh(hw);
1428
1429 /* Get rid of the monster */
1430
1431 killed(NULL, item, NOMESSAGE, NOPOINTS);
1432
1433 which_item = (short) ((readchar() & 0177) - 'a');
1434
1435 while (which_item < 0 || which_item >= nitems ||
1436 selection[which_item].worth > effective_purse)
1437 {
1438 if (which_item == (short) ESCAPE - (short) 'a')
1439 return;
1440
1441 mvwaddstr(hw, 0, 0, "Please enter one of the listed items: ");
1442 wrefresh(hw);
1443 which_item = (short) ((readchar() & 0177) - 'a');
1444 }
1445
1446 if (purse > selection[which_item].worth)
1447 purse -= selection[which_item].worth;
1448 else
1449 purse = 0L;
1450
1451 item = spec_item(goods, selection[which_item].which,
1452 selection[which_item].plus1, selection[which_item].plus2);
1453
1454 obj = OBJPTR(item);
1455
1456 if (selection[which_item].count > 1)
1457 {
1458 obj->o_count = selection[which_item].count;
1459 obj->o_group = ++group;
1460 }
1461
1462 /* If a stick or ring, let player know the type */
1463
1464 switch (goods)
1465 {
1466 case STICK: know_items[TYP_STICK][selection[which_item].which] = TRUE;
1467 break;
1468 case RING: know_items[TYP_RING][selection[which_item].which] = TRUE;
1469 break;
1470 }
1471
1472 if (add_pack(item, MESSAGE) == FALSE)
1473 {
1474 obj->o_pos = hero;
1475 fall(&player, item, TRUE, FALSE);
1476 }
1477 }
1478
1479 void
1480 carried_weapon(struct thing *owner, struct object *weapon)
1481 {
1482 weapon->o_hplus = (rnd(4) < 3) ? 0 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
1483 weapon->o_dplus = (rnd(4) < 3) ? 0 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
1484 weapon->o_hplus += rnd(owner->t_stats.s_lvl / 3 + 1);
1485 weapon->o_hplus += rnd(owner->t_stats.s_lvl / 3 + 1);
1486 weapon->o_damage = weapon->o_hurldmg = "0d0";
1487 weapon->o_ac = 11;
1488 weapon->o_count = 1;
1489 weapon->o_group = 0;
1490
1491 if ((weapon->o_hplus <= 0) && (weapon->o_dplus <= 0))
1492 weapon->o_flags = ISCURSED;
1493
1494 weapon->o_flags = 0;
1495 weapon->o_type = WEAPON;
1496 weapon->o_mark[0] = '\0';
1497 }