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