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