comparison xrogue/monsters.c @ 133:e6179860cb76

Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 21 Apr 2015 08:55:20 -0400
parents
children f54901b9c39b
comparison
equal deleted inserted replaced
124:d10fc4a065ac 133:e6179860cb76
1 /*
2 monsters.c - File with various monster functions in it
3
4 XRogue: Expeditions into the Dungeons of Doom
5 Copyright (C) 1991 Robert Pietkivitch
6 All rights reserved.
7
8 Based on "Advanced Rogue"
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
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 <curses.h>
20 #include <ctype.h>
21 #include <string.h>
22 #include "rogue.h"
23
24 /*
25 * Check_residue takes care of any effect of the monster
26 */
27
28 check_residue(tp)
29 register struct thing *tp;
30 {
31 /*
32 * Take care of special abilities
33 */
34 if (on(*tp, DIDHOLD) && (--hold_count == 0)) {
35 turn_off(player, ISHELD);
36 turn_off(*tp, DIDHOLD);
37 }
38
39 /* If frightened of this monster, stop */
40 if (on(player, ISFLEE) &&
41 player.t_dest == &tp->t_pos) turn_off(player, ISFLEE);
42
43 /* If monster was suffocating player, stop it */
44 if (on(*tp, DIDSUFFOCATE)) {
45 extinguish(suffocate);
46 turn_off(*tp, DIDSUFFOCATE);
47 }
48
49 /* If something with fire, may darken */
50 if (on(*tp, HASFIRE)) {
51 register struct room *rp=roomin(&tp->t_pos);
52 register struct linked_list *fire_item;
53
54 if (rp) {
55 for (fire_item = rp->r_fires; fire_item != NULL;
56 fire_item = next(fire_item)) {
57 if (THINGPTR(fire_item) == tp) {
58 detach(rp->r_fires, fire_item);
59 destroy_item(fire_item);
60 if (rp->r_fires == NULL) {
61 rp->r_flags &= ~HASFIRE;
62 if (cansee(tp->t_pos.y, tp->t_pos.x)) light(&hero);
63 }
64 break;
65 }
66 }
67 }
68 }
69 }
70
71 /*
72 * Creat_mons creates the specified monster -- any if 0
73 */
74
75 bool
76 creat_mons(person, monster, report)
77 struct thing *person; /* Where to create next to */
78 short monster;
79 bool report;
80 {
81 struct linked_list *nitem;
82 register struct thing *tp;
83 struct room *rp;
84 coord *mp;
85
86 if (levtype == POSTLEV)
87 return(FALSE);
88 if ((mp = fallpos(&(person->t_pos), FALSE, 2)) != NULL) {
89 nitem = new_item(sizeof (struct thing));
90 new_monster(nitem,
91 monster == 0 ? randmonster(FALSE, FALSE)
92 : monster,
93 mp,
94 TRUE);
95 tp = THINGPTR(nitem);
96 runto(tp, &hero);
97 carry_obj(tp, monsters[tp->t_index].m_carry/2); /* only half chance */
98
99 /* since it just got here, it is disoriented */
100 tp->t_no_move = 2 * movement(tp);
101
102 if (on(*tp, HASFIRE)) {
103 rp = roomin(&tp->t_pos);
104 if (rp) {
105 register struct linked_list *fire_item;
106
107 /* Put the new fellow in the room list */
108 fire_item = creat_item();
109 ldata(fire_item) = (char *) tp;
110 attach(rp->r_fires, fire_item);
111
112 rp->r_flags |= HASFIRE;
113 }
114 }
115
116 /*
117 * If we can see this monster, set oldch to ' ' to make light()
118 * think the creature used to be invisible (ie. not seen here)
119 */
120 if (cansee(tp->t_pos.y, tp->t_pos.x)) tp->t_oldch = ' ';
121 return(TRUE);
122 }
123 if (report) msg("You hear a faint cry of anguish in the distance.. ");
124 return(FALSE);
125 }
126
127 /*
128 * Genmonsters:
129 * Generate at least 'least' monsters for this single room level.
130 * 'Treas' indicates whether this is a "treasure" level.
131 */
132
133 void
134 genmonsters(least, treas)
135 register int least;
136 bool treas;
137 {
138 reg int i;
139 reg struct room *rp = &rooms[0];
140 reg struct linked_list *item;
141 reg struct thing *mp;
142 coord tp;
143
144 for (i = 0; i < (max(50, level) + least); i++) {
145 if (!treas && rnd(100) < 65) /* put in some little buggers */
146 continue;
147
148 /*
149 * Put the monster in
150 */
151 item = new_item(sizeof *mp);
152 mp = THINGPTR(item);
153 do {
154 rnd_pos(rp, &tp);
155 } until(mvwinch(stdscr, tp.y, tp.x) == FLOOR);
156
157 new_monster(item, randmonster(FALSE, FALSE), &tp, FALSE);
158 /*
159 * See if we want to give it a treasure to carry around.
160 */
161 carry_obj(mp, monsters[mp->t_index].m_carry);
162
163 /* Calculate a movement rate */
164 mp->t_no_move = movement(mp);
165
166 /* Is it going to give us some light? */
167 if (on(*mp, HASFIRE)) {
168 register struct linked_list *fire_item;
169
170 fire_item = creat_item();
171 ldata(fire_item) = (char *) mp;
172 attach(rp->r_fires, fire_item);
173 rp->r_flags |= HASFIRE;
174 }
175 }
176 }
177
178 /*
179 * id_monst returns the index of the monster given its letter
180 */
181
182 short
183 id_monst(monster)
184 register char monster;
185 {
186 register short result;
187
188 if (levtype == OUTSIDE) {
189 result = NLEVMONS*vlevel + (NUMMONST-NUMDINOS-1);
190 if (result > NUMMONST) result = NUMMONST;
191 }
192 else {
193 result = NLEVMONS*vlevel;
194 if (result > NUMMONST-NUMDINOS) result = NUMMONST-NUMDINOS;
195 }
196
197 if (levtype == OUTSIDE) {
198 for(; result>(NUMMONST-NUMDINOS-1); result--)
199 if (monsters[result].m_appear == monster) return(result);
200 for (result=(NLEVMONS*vlevel)+1; result <= NUMMONST-NUMDINOS; result++)
201 if (monsters[result].m_appear == monster) return(result);
202 }
203 else {
204 for(; result>0; result--)
205 if (monsters[result].m_appear == monster) return(result);
206 for (result=(NLEVMONS*vlevel)+1; result <= NUMMONST; result++)
207 if (monsters[result].m_appear == monster) return(result);
208 }
209 return(0);
210 }
211
212
213 /*
214 * new_monster:
215 * Pick a new monster and add it to the list
216 */
217
218 new_monster(item, type, cp, max_monster)
219 struct linked_list *item;
220 short type;
221 coord *cp;
222 bool max_monster;
223 {
224 register struct thing *tp;
225 register struct monster *mp;
226 register char *ip, *hitp;
227 register int i, min_intel, max_intel;
228 register int num_dice, num_sides=8, num_extra=0;
229
230 attach(mlist, item);
231 tp = THINGPTR(item);
232 tp->t_pack = NULL;
233 tp->t_index = type;
234 tp->t_wasshot = FALSE;
235 tp->t_type = monsters[type].m_appear;
236 tp->t_ctype = C_MONSTER;
237 tp->t_action = A_NIL;
238 tp->t_doorgoal.x = tp->t_doorgoal.y = -1;
239 tp->t_quiet = 0;
240 tp->t_dest = NULL;
241 tp->t_name = NULL;
242 tp->t_pos = tp->t_oldpos = *cp;
243 tp->t_oldch = mvwinch(cw, cp->y, cp->x);
244 mvwaddch(mw, cp->y, cp->x, tp->t_type);
245 mp = &monsters[tp->t_index];
246
247 /* Figure out monster's hit points */
248 hitp = mp->m_stats.ms_hpt;
249 num_dice = atoi(hitp);
250 if ((hitp = strchr(hitp, 'd')) != NULL) {
251 num_sides = atoi(++hitp);
252 if ((hitp = strchr(hitp, '+')) != NULL)
253 num_extra = atoi(++hitp);
254 }
255
256 tp->t_stats.s_lvladj = 0;
257 tp->t_stats.s_lvl = mp->m_stats.ms_lvl;
258 tp->t_stats.s_arm = mp->m_stats.ms_arm;
259 strcpy(tp->t_stats.s_dmg,mp->m_stats.ms_dmg);
260 tp->t_stats.s_str = mp->m_stats.ms_str;
261 tp->t_stats.s_dext = mp->m_stats.ms_dex;
262 tp->t_movement = mp->m_stats.ms_move;
263 if (vlevel > HARDER) { /* the deeper, the meaner we get */
264 tp->t_stats.s_lvl += (vlevel - HARDER);
265 num_dice += (vlevel - HARDER)/2;
266 tp->t_stats.s_arm -= (vlevel - HARDER) / 4;
267 }
268 if (max_monster)
269 tp->t_stats.s_hpt = num_dice * num_sides + num_extra;
270 else
271 tp->t_stats.s_hpt = roll(num_dice, num_sides) + num_extra;
272 tp->t_stats.s_exp = mp->m_stats.ms_exp + mp->m_add_exp*tp->t_stats.s_hpt;
273
274 /*
275 * just initailize others values to something reasonable for now
276 * maybe someday will *really* put these in monster table
277 */
278 tp->t_stats.s_wisdom = 8 + rnd(7);
279 tp->t_stats.s_const = 8 + rnd(7);
280 tp->t_stats.s_charisma = 8 + rnd(7);
281
282 /* Set the initial flags */
283 for (i=0; i<16; i++) tp->t_flags[i] = 0;
284 for (i=0; i<MAXFLAGS; i++)
285 turn_on(*tp, mp->m_flags[i]);
286
287 /*
288 * these are the base chances that a creatures will do something
289 * assuming it can. These are(or can be) modified at runtime
290 * based on what the creature experiences
291 */
292 tp->t_breathe = 70; /* base chance of breathing */
293 tp->t_artifact = 90; /* base chance of using artifact */
294 tp->t_summon = 50; /* base chance of summoning */
295 tp->t_cast = 70; /* base chance of casting a spell */
296 tp->t_wand = on(*tp, ISUNIQUE) ? 35 : 50; /* base chance of using wands */
297
298 /* suprising monsters don't always surprise you */
299 if (!max_monster && on(*tp, CANSURPRISE) &&
300 off(*tp, ISUNIQUE) && rnd(100) < 25)
301 turn_off(*tp, CANSURPRISE);
302
303 /* If this monster is unique, gen it */
304 if (on(*tp, ISUNIQUE)) mp->m_normal = FALSE;
305
306 /*
307 * If it is the quartermaster, then compute his level and exp pts
308 * based on the level. This will make it fair when thieves try to
309 * steal and give them reasonable experience if they succeed.
310 * Then fill his pack with his wares.
311 */
312 if (on(*tp, CANSELL)) {
313 tp->t_stats.s_exp = vlevel * 100;
314 tp->t_stats.s_lvl = vlevel/2 + 1;
315 make_sell_pack(tp);
316 }
317
318 /* Normally scared monsters have a chance to not be scared */
319 if (on(*tp, ISFLEE) && (rnd(4) == 0)) turn_off(*tp, ISFLEE);
320
321 /* Figure intelligence */
322 min_intel = atoi(mp->m_intel);
323 if ((ip = (char *) strchr(mp->m_intel, '-')) == NULL)
324 tp->t_stats.s_intel = min_intel;
325 else {
326 max_intel = atoi(++ip);
327 if (max_monster)
328 tp->t_stats.s_intel = max_intel;
329 else
330 tp->t_stats.s_intel = min_intel + rnd(max_intel - min_intel);
331 }
332 if (vlevel > HARDER)
333 tp->t_stats.s_intel += ((vlevel - HARDER)/2);
334 tp->maxstats = tp->t_stats;
335
336 /* If the monster can shoot, it may have a weapon */
337 if (on(*tp, CANSHOOT) && ((rnd(100) < (20 + vlevel)) || max_monster)) {
338 struct linked_list *item1;
339 register struct object *cur, *cur1;
340
341 item = new_item(sizeof *cur);
342 item1 = new_item(sizeof *cur1);
343 cur = OBJPTR(item);
344 cur1 = OBJPTR(item1);
345 cur->o_hplus = (rnd(4) < 3) ? 0
346 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
347 cur->o_dplus = (rnd(4) < 3) ? 0
348 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
349 cur1->o_hplus = (rnd(4) < 3) ? 0
350 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
351 cur1->o_dplus = (rnd(4) < 3) ? 0
352 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
353 strcpy(cur->o_damage,"0d0");
354 strcpy(cur->o_hurldmg,"0d0");
355 strcpy(cur1->o_damage,"0d0");
356 strcpy(cur1->o_hurldmg,"0d0");
357 cur->o_ac = cur1->o_ac = 11;
358 cur->o_count = cur1->o_count = 1;
359 cur->o_group = cur1->o_group = 0;
360 cur->contents = cur1->contents = NULL;
361 if ((cur->o_hplus <= 0) && (cur->o_dplus <= 0)) cur->o_flags = ISCURSED;
362 if ((cur1->o_hplus <= 0) && (cur1->o_dplus <= 0))
363 cur1->o_flags = ISCURSED;
364 cur->o_flags = cur1->o_flags = 0;
365 cur->o_type = cur1->o_type = WEAPON;
366 cur->o_mark[0] = cur1->o_mark[0] = '\0';
367
368 /* The monster may use a crossbow, sling, or an arrow */
369 i = rnd(100);
370 if (i < 35) {
371 cur->o_which = CROSSBOW;
372 cur1->o_which = BOLT;
373 init_weapon(cur, CROSSBOW);
374 init_weapon(cur1, BOLT);
375 }
376 else if (i < 70) {
377 cur->o_which = BOW;
378 cur1->o_which = ARROW;
379 init_weapon(cur, BOW);
380 init_weapon(cur1, ARROW);
381 }
382 else {
383 cur->o_which = SLING;
384 cur1->o_which = ROCK;
385 init_weapon(cur, SLING);
386 init_weapon(cur1, ROCK);
387 }
388
389 attach(tp->t_pack, item);
390 attach(tp->t_pack, item1);
391 }
392
393
394 /* Calculate the initial movement rate */
395 updpack(TRUE, tp);
396 tp->t_no_move = movement(tp);
397
398 if (ISWEARING(R_AGGR))
399 runto(tp, &hero);
400
401 if (on(*tp, ISDISGUISE))
402 {
403 char mch = 0;
404
405 if (tp->t_pack != NULL)
406 mch = (OBJPTR(tp->t_pack))->o_type;
407 else
408 switch (rnd(10)) {
409 case 0: mch = GOLD;
410 when 1: mch = POTION;
411 when 2: mch = SCROLL;
412 when 3: mch = FOOD;
413 when 4: mch = WEAPON;
414 when 5: mch = ARMOR;
415 when 6: mch = RING;
416 when 7: mch = STICK;
417 when 8: mch = monsters[randmonster(FALSE, FALSE)].m_appear;
418 when 9: mch = MM;
419 }
420 tp->t_disguise = mch;
421 }
422 }
423
424 /*
425 * randmonster:
426 * Pick a monster to show up. The lower the level,
427 * the meaner the monster.
428 */
429
430 short
431 randmonster(wander, no_unique)
432 register bool wander, no_unique;
433 {
434 register int d, cur_level, range, i;
435
436 /*
437 * Do we want a merchant? Merchant is always in place 'NUMMONST'
438 */
439 if (wander && monsters[NUMMONST].m_wander && rnd(100) < pstats.s_charisma/3)
440 return NUMMONST;
441
442 cur_level = vlevel;
443 range = (4*NLEVMONS)+1; /* range is 0 thru 12 */
444 i = 0;
445 do
446 {
447 if (i++ > NUMMONST-1) { /* in case all have be genocided */
448 i = 0;
449 if (--cur_level <= 0)
450 fatal("rogue: Could not find a monster to make! ");
451 }
452 if (levtype == OUTSIDE) { /* create DINOSUARS */
453 d = (cur_level - rnd(range/2)) + (NUMMONST-NUMDINOS-1);
454 if (d < NUMMONST-NUMDINOS)
455 d = (NUMMONST-NUMDINOS) + rnd(range/2);
456 if (d > NUMMONST-1)
457 d = (NUMMONST-NUMDINOS) + rnd(NUMDINOS);
458 }
459 else { /* Create NORMALs and UNIQs here */
460 d = (NLEVMONS*(cur_level-1) + rnd(range) - (range-NLEVMONS-1));
461 if (d < 1) d = rnd(6)+1;
462
463 if (d > NUMMONST-NUMDINOS-1) { /* Entire range NORMs + UNIQs */
464 if (no_unique) /* Choose from last 12 NORMAL monsters */
465 d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) - rnd(NUMUNIQUE/5);
466 else /* Choose from entire UNIQ monsters + range */
467 d = (NUMMONST-NUMDINOS-1) - rnd(NUMUNIQUE+range);
468 }
469 /* Half-way into the UNIQs now */
470 else if (d > (NUMMONST-NUMDINOS-(NUMUNIQUE/2)-1)) {
471 if (no_unique) /* Choose from last 15 NORMAL monsters */
472 d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) - rnd(NUMUNIQUE/4);
473 else /* Choose from entire UNIQ monsters + range */
474 d = (NUMMONST-NUMDINOS-1) - rnd(NUMUNIQUE+range);
475 }
476 /* End NORMALs and begin relic bearing UNIQs */
477 else if (d > (NUMMONST-NUMDINOS-NUMUNIQUE-1)) {
478 if (no_unique) /* Choose from last 20 NORMAL monsters */
479 d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) - rnd(NUMUNIQUE/3);
480 else /* Choose from first 20 UNIQ monsters */
481 d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) + rnd(NUMUNIQUE/3);
482 }
483 }
484 }
485 while (wander ? !monsters[d].m_wander || !monsters[d].m_normal
486 : !monsters[d].m_normal);
487 return d;
488 }
489
490 /* Sell displays a menu of goods from which the player may choose
491 * to purchase something.
492 */
493
494 sell(tp)
495 register struct thing *tp;
496 {
497 register struct linked_list *item, *seller;
498 register struct linked_list *sellpack;
499 register struct object *obj;
500 register long worth, min_worth;
501 char buffer[LINELEN];
502
503 /*
504 * Get a linked_list pointer to the seller. We need this in case
505 * he disappears so we can set him ISDEAD.
506 */
507 seller = find_mons(tp->t_pos.y, tp->t_pos.x);
508
509 sellpack = tp->t_pack;
510 if (sellpack == NULL) {
511 msg("%s looks puzzled and departs.", prname(monster_name(tp), TRUE));
512
513 /* Get rid of the monster */
514 killed(seller, FALSE, FALSE, FALSE);
515 return;
516 }
517
518 /* See how much the minimum pack item is worth */
519 min_worth = 100000;
520 for (item = sellpack; item != NULL; item = next(item)) {
521 obj = OBJPTR(item);
522 obj->o_flags |= ISPOST; /* Force a long description of the item */
523 worth = get_worth(obj);
524 if (worth < min_worth) min_worth = worth;
525 }
526
527 /* See if player can afford an item */
528 if (min_worth > purse) {
529 msg("%s eyes your small purse and departs.",
530 prname(monster_name(tp), TRUE));
531
532 /* Get rid of the monster */
533 killed(seller, FALSE, FALSE, FALSE);
534 return;
535 }
536
537 /* Announce our intentions */
538 msg("%s opens his pack. --More--", prname(monster_name(tp), TRUE));
539 wait_for(' ');
540
541 /* Try to sell something */
542 sprintf(buffer, "You got %ld gold pieces. Buy", purse);
543 item = get_item(sellpack, buffer, ALL, TRUE, TRUE);
544
545 /* Get rid of the monster */
546 if (item != NULL) detach(tp->t_pack, item); /* Take it out of the pack */
547 killed(seller, FALSE, FALSE, FALSE);
548
549 if (item == NULL) return;
550
551 /* Can he afford the selected item? */
552 obj = OBJPTR(item);
553
554 worth = get_worth(obj);
555 if (worth > purse) {
556 msg("You cannot afford it.");
557 o_discard(item);
558 return;
559 }
560
561 /* Charge him through the nose */
562 purse -= worth;
563
564 /* If a stick or ring, let player know the type */
565 switch (obj->o_type) {
566 case RING: r_know[obj->o_which] = TRUE;
567 when POTION: p_know[obj->o_which] = TRUE;
568 when SCROLL: s_know[obj->o_which] = TRUE;
569 when STICK: ws_know[obj->o_which] = TRUE;
570 when MM: m_know[obj->o_which] = TRUE;
571
572 }
573
574 /* identify it */
575 whatis (item);
576
577 /* Remove the POST flag that we used for get_item() */
578 obj->o_flags &= ~ISPOST;
579
580 if (add_pack(item, FALSE) == FALSE) {
581 obj->o_pos = hero;
582 fall(item, TRUE);
583 }
584 }
585
586 /*
587 * what to do when the hero steps next to a monster
588 */
589
590 struct linked_list *
591 wake_monster(y, x)
592 int y, x;
593 {
594 register struct thing *tp;
595 register struct linked_list *it;
596 register struct room *trp;
597 register char *mname;
598 bool nasty; /* Will the monster "attack"? */
599
600 if ((it = find_mons(y, x)) == NULL) {
601 msg("Wake: can't find monster in show (%d, %d)", y, x);
602 return (NULL);
603 }
604 tp = THINGPTR(it);
605 if (on(*tp, ISSTONE)) /* if stoned, don't do anything */
606 return it;
607
608 /*
609 * For now, if we are a friendly monster, we won't do any of
610 * our special effects.
611 */
612 if (on(*tp, ISFRIENDLY)) return it;
613
614 trp = roomin(&tp->t_pos); /* Current room for monster */
615
616 /*
617 * Let greedy ones in a room guard gold
618 * (except in a maze where lots of creatures would all go for the
619 * same piece of gold)
620 */
621 if (on(*tp, ISGREED) && off(*tp, ISRUN) && levtype != MAZELEV &&
622 trp != NULL && lvl_obj != NULL) {
623 register struct linked_list *item;
624 register struct object *cur;
625
626 for (item = lvl_obj; item != NULL; item = next(item)) {
627 cur = OBJPTR(item);
628 if ((cur->o_type == GOLD) && (roomin(&cur->o_pos) == trp)) {
629 /* Run to the gold */
630 runto(tp, &cur->o_pos);
631
632 /* Make it worth protecting */
633 cur->o_count += GOLDCALC + GOLDCALC;
634 break;
635 }
636 }
637 }
638
639 /*
640 * Every time he sees mean monster, it might start chasing him
641 */
642 if (on(*tp, ISMEAN) &&
643 off(*tp, ISHELD) &&
644 off(*tp, ISRUN) &&
645 rnd(100) > 35 &&
646 (!is_stealth(&player) || (on(*tp, ISUNIQUE) && rnd(100) > 35)) &&
647 (off(player, ISINVIS) || on(*tp, CANSEE)) ||
648 (trp != NULL && (trp->r_flags & ISTREAS))) {
649 runto(tp, &hero);
650 }
651
652 /*
653 * Get the name; we don't want to do it until here because we need to
654 * know whether the monster is still sleeping or not.
655 */
656 mname = monster_name(tp);
657
658 /* See if the monster will bother the player */
659 nasty = (on(*tp, ISRUN) && cansee(tp->t_pos.y, tp->t_pos.x));
660
661 /*
662 * if the creature is awake and can see the player and the
663 * player has the dreaded "eye of vecna" then see if the
664 * creature is turned to stone
665 */
666 if (cur_relic[EYE_VECNA] && nasty && off(*tp, NOSTONE) &&
667 (off(player, ISINVIS) || on(*tp, CANSEE))) {
668 turn_on(*tp, NOSTONE); /* only have to save once */
669 if (!save(VS_PETRIFICATION, tp, -2)) {
670 turn_on(*tp, ISSTONE);
671 turn_off(*tp, ISRUN);
672 turn_off(*tp, ISINVIS);
673 turn_off(*tp, CANSURPRISE);
674 turn_off(*tp, ISDISGUISE);
675 msg("%s is turned to stone!", prname(mname, TRUE));
676 return it;
677 }
678 }
679
680 /*
681 * Handle monsters that can gaze and do things while running
682 * Player must be able to see the monster and the monster must
683 * not be asleep
684 */
685 if (nasty && !invisible(tp)) {
686 /*
687 * Confusion
688 */
689 if (on(*tp, CANHUH) &&
690 (off(*tp, ISINVIS) || on(player, CANSEE)) &&
691 (off(*tp, CANSURPRISE) || ISWEARING(R_ALERT))) {
692 if (!save(VS_MAGIC, &player, 0)) {
693 if (off(player, ISCLEAR)) {
694 if (find_slot(unconfuse))
695 lengthen(unconfuse, HUHDURATION);
696 else {
697 fuse(unconfuse, (VOID *)NULL, HUHDURATION, AFTER);
698 msg("%s's gaze has confused you.",prname(mname, TRUE));
699 turn_on(player, ISHUH);
700 }
701 }
702 else msg("You feel dizzy for a moment, but it quickly passes.");
703 }
704 else if (rnd(100) < 67)
705 turn_off(*tp, CANHUH); /* Once you save, maybe that's it */
706 }
707
708 /* Sleep */
709 if(on(*tp, CANSNORE) &&
710 player.t_action != A_FREEZE &&
711 !save(VS_PARALYZATION, &player, 0)) {
712 if (ISWEARING(R_ALERT))
713 msg("You feel drowsy for a moment.. ");
714 else {
715 msg("%s's gaze puts you to sleep! ", prname(mname, TRUE));
716 player.t_no_move += movement(&player) * SLEEPTIME;
717 player.t_action = A_FREEZE;
718 if (rnd(100) < 50) turn_off(*tp, CANSNORE);
719 }
720 }
721
722 /* Fear */
723 if (on(*tp, CANFRIGHTEN) && !on(player, ISFLEE)) {
724 turn_off(*tp, CANFRIGHTEN);
725 if (!ISWEARING(R_HEROISM) &&
726 !save(VS_WAND, &player, -(tp->t_stats.s_lvl/10))) {
727 turn_on(player, ISFLEE);
728 player.t_dest = &tp->t_pos;
729 msg("The sight of %s terrifies you!", prname(mname, FALSE));
730 }
731 }
732
733 /* blinding creatures */
734 if(on(*tp, CANBLIND) && !find_slot(sight)) {
735 turn_off(*tp, CANBLIND);
736 if (!save(VS_WAND, &player, 0)) {
737 msg("The gaze of %s blinds you! ", prname(mname, FALSE));
738 turn_on(player, ISBLIND);
739 fuse(sight, (VOID *)NULL, rnd(30)+20, AFTER);
740 light(&hero);
741 }
742 }
743
744 /* the sight of the ghost can age you! */
745 if (on(*tp, CANAGE)) {
746 turn_off (*tp, CANAGE);
747 if (!save(VS_MAGIC, &player, 0)) {
748 msg ("The sight of %s ages you!", prname(mname, FALSE));
749 pstats.s_const--;
750 /* max_stats.s_const--; */
751 if (pstats.s_const < 1) {
752 pstats.s_hpt = -1;
753 death (D_CONSTITUTION);
754 }
755 }
756 }
757
758 /* Turning to stone */
759 if (on(*tp, LOOKSTONE)) {
760 turn_off(*tp, LOOKSTONE);
761
762 if (on(player, CANINWALL))
763 msg("The gaze of %s has no effect.", prname(mname, FALSE));
764 else {
765 if (!save(VS_PETRIFICATION, &player, 0) && rnd(100) < 5) {
766 pstats.s_hpt = -1;
767 msg("The gaze of %s petrifies you!", prname(mname, FALSE));
768 msg("You are turned to stone!!! --More--");
769 wait_for(' ');
770 death(D_PETRIFY);
771 }
772 else {
773 msg("The gaze of %s stiffens your limbs.",
774 prname(mname, FALSE));
775 player.t_no_move += movement(&player) * STONETIME;
776 player.t_action = A_FREEZE;
777 }
778 }
779 }
780 }
781
782 return it;
783 }
784 /*
785 * wanderer:
786 * A wandering monster has awakened and is headed for the player
787 */
788
789 wanderer()
790 {
791 register int i;
792 register struct room *hr = roomin(&hero);
793 register struct linked_list *item;
794 register struct thing *tp;
795 register long *attr; /* Points to monsters' attributes */
796 int carry; /* Chance of wanderer carrying anything */
797 short rmonst; /* Our random wanderer */
798 bool canteleport = FALSE, /* Can the monster teleport? */
799 seehim; /* Is monster within sight? */
800 coord cp;
801
802 rmonst = randmonster(TRUE, FALSE); /* Choose a random wanderer */
803 attr = &monsters[rmonst].m_flags[0]; /* Start of attributes */
804 for (i=0; i<MAXFLAGS; i++)
805 if (*attr++ == CANTELEPORT) {
806 canteleport = TRUE;
807 break;
808 }
809
810 /* Find a place for it -- avoid the player's room if can't teleport */
811 do {
812 do {
813 i = rnd_room();
814 } until (canteleport || hr != &rooms[i] || levtype == MAZELEV ||
815 levtype == OUTSIDE);
816
817 /* Make sure the monster does not teleport on top of the player */
818 do {
819 rnd_pos(&rooms[i], &cp);
820 } while (hr == &rooms[i] && ce(cp, hero));
821 } until (step_ok(cp.y, cp.x, NOMONST, (struct thing *)NULL));
822
823 /* Create a new wandering monster */
824 item = new_item(sizeof *tp);
825 new_monster(item, rmonst, &cp, FALSE);
826 tp = THINGPTR(item);
827 runto(tp, &hero);
828 tp->t_pos = cp; /* Assign the position to the monster */
829 seehim = cansee(tp->t_pos.y, tp->t_pos.x);
830 if (on(*tp, HASFIRE)) {
831 register struct room *rp;
832
833 rp = roomin(&tp->t_pos);
834 if (rp) {
835 register struct linked_list *fire_item;
836
837 fire_item = creat_item();
838 ldata(fire_item) = (char *) tp;
839 attach(rp->r_fires, fire_item);
840
841 rp->r_flags |= HASFIRE;
842 if (seehim && next(rp->r_fires) == NULL)
843 light(&hero);
844 }
845 }
846
847 /* See if we give the monster anything */
848 carry = monsters[tp->t_index].m_carry;
849 if (off(*tp, ISUNIQUE)) carry /= 2; /* Non-unique has only a half chance */
850 carry_obj(tp, carry);
851
852 /* Calculate its movement rate */
853 tp->t_no_move = movement(tp);
854
855 /* Alert the player if a monster just teleported in */
856 if (hr == &rooms[i] && canteleport && seehim && !invisible(tp)) {
857 msg("A %s just teleported in", monster_name(tp));
858 light(&hero);
859 running = FALSE;
860 }
861
862 if (wizard)
863 msg("Started a wandering %s", monster_name(tp));
864 }
865