Annotation of early-roguelike/xrogue/actions.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: actions.c - functions for dealing with monster actions
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 <ctype.h>
20: #include <curses.h>
21: #include <limits.h>
22: #include "rogue.h"
23:
24: int mf_count = 0; /* move_free counter - see actions.c(m_act()) */
25: int mf_jmpcnt = 0; /* move_free counter for # of jumps */
26:
27: void m_breathe(struct thing *tp);
28: void m_select(struct thing *th, bool flee);
29: void m_sonic(struct thing *tp);
30: void m_spell(struct thing *tp);
31: void m_summon(struct thing *tp);
32: bool m_use_it(struct thing *tp, bool flee, struct room *rer, struct room *ree);
33: bool m_use_pack(struct thing *monster, coord *defend_pos, int dist,
34: coord *shoot_dir);
35:
36: /*
37: * Did we disrupt a spell?
38: */
39: void
40: dsrpt_monster(struct thing *tp, bool always, bool see_him)
41: {
42: switch (tp->t_action) {
43: case A_SUMMON:
44: case A_MISSILE:
45: case A_SLOW:
46: tp->t_action = A_NIL; /* Just make the old fellow start over again */
47: tp->t_no_move = movement(tp);
48: tp->t_using = NULL; /* Just to be on the safe side */
49: turn_on(*tp, WASDISRUPTED);
50: if (see_him)
51: msg("%s's spell has been disrupted.",prname(monster_name(tp),TRUE));
52: /*
53: * maybe choose something else to do next time since player
54: * is disrupting us
55: */
56: tp->t_summon *= 2;
57: tp->t_cast /= 2;
58: return;
59: }
60:
61: /* We may want to disrupt other actions, too */
62: if (always) {
63: tp->t_action = A_NIL; /* Just make the old fellow start over again */
64: tp->t_no_move = movement(tp);
65: tp->t_using = NULL;/* Just to be on the safe side */
66: }
67: }
68:
69: void
70: dsrpt_player(void)
71: {
72: int which, action;
73: struct linked_list *item;
74: struct object *obj;
75:
76: action = player.t_action;
77: which = player.t_selection;
78:
79: switch (action) {
80: case C_CAST: /* Did we disrupt a spell? */
81: case C_PRAY:
82: case C_CHANT:
83: {
84: msg("Your %s was disrupted!", action == C_CAST ? "spell" : "prayer");
85:
86: /* Charge him 1/4 anyway */
87: if (action == C_CAST)
88: spell_power += magic_spells[which].s_cost / 4;
89: else if (action == C_PRAY)
90: pray_time += cleric_spells[which].s_cost / 4;
91: else if (action == C_CHANT)
92: chant_time += druid_spells[which].s_cost / 4;
93: }
94: when C_COUNT: /* counting of gold? */
95: {
96: if (purse > 0) {
97: msg("Your gold goes flying everywhere!");
98: do {
99: item = spec_item(GOLD, 0, 0, 0);
100: obj = OBJPTR(item);
101: obj->o_count = min(purse, rnd(20)+1);
102: purse -= obj->o_count;
103: obj->o_pos = hero;
104: fall(item, FALSE);
105: } while (purse > 0 && rnd(25) != 1);
106: }
107: }
108: when C_EAT:
109: msg("Ack! You gag on your food for a moment. ");
110: del_pack(player.t_using);
111:
112: when A_PICKUP:
113: msg("You drop what you are picking up! ");
114:
115: when C_SEARCH: /* searching for traps and secret doors... */
116: msg("Ouch! You decide to stop searching. ");
117: count = 0; /* don't search again */
118:
119: when C_SETTRAP:
120: msg("Ouch! You can't set a trap right now. ");
121:
122: when A_NIL:
123: default:
124: return;
125: }
126: player.t_no_move = movement(&player); /* disoriented for a while */
127: player.t_action = A_NIL;
128: player.t_selection = 0;
129: }
130:
131: /*
132: * m_act:
133: * If the critter isn't doing anything, choose an action for it.
134: * Otherwise, let it perform its chosen action.
135: */
136:
137: void
138: m_act(struct thing *tp)
139: {
140: struct object *obj;
141: bool flee; /* Are we scared? */
142:
143: /* What are we planning to do? */
144: switch (tp->t_action) {
145: default:
146: /* An unknown action! */
147: msg("Unknown monster action (%d)", tp->t_action);
148:
149: /* Fall through */
150:
151: case A_NIL:
152: /* If the monster is fairly intelligent and about to die, it
153: * may turn tail and run. But if we are a FRIENDLY creature
154: * in the hero's service, don't run.
155: */
156: if (off(*tp, ISFLEE) &&
157: tp->t_stats.s_hpt < tp->maxstats.s_hpt &&
158: tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt/6) &&
159: (off(*tp, ISFRIENDLY) || tp->t_dest != &hero) &&
160: rnd(25) < tp->t_stats.s_intel) {
161: turn_on(*tp, ISFLEE);
162:
163: /* It is okay to turn tail */
164: tp->t_oldpos = tp->t_pos;
165: }
166:
167: /* Should the monster run away? */
168: flee = on(*tp, ISFLEE) ||
169: ((tp->t_dest == &hero) && on(player, ISINWALL) &&
170: off(*tp, CANINWALL));
171:
172: m_select(tp, flee); /* Select an action */
173: return;
174:
175: when A_ATTACK:
176: /*
177: * We're trying to attack the player or monster at t_newpos
178: * if the prey moved, do nothing
179: */
180: obj = tp->t_using ? OBJPTR(tp->t_using) : NULL;
181: if (ce(tp->t_newpos, hero)) {
182: attack(tp, obj, FALSE);
183: }
184: else if (mvwinch(mw, tp->t_newpos.y, tp->t_newpos.x) &&
185: step_ok(tp->t_newpos.y, tp->t_newpos.x, FIGHTOK, tp)) {
186: skirmish(tp, &tp->t_newpos, obj, FALSE);
187: }
188:
189: when A_SELL:
190: /* Is the quartermaster still next to us? */
191: if (ce(tp->t_newpos, hero)) sell(tp);
192:
193: /* The quartermaster moved away */
194: else if (off(player, ISBLIND) && cansee(unc(tp->t_pos)) &&
195: (off(*tp, ISINVIS) || on(player, CANSEE)) &&
196: (off(*tp, ISSHADOW) || on(player, CANSEE)) &&
197: (off(*tp, CANSURPRISE) || ISWEARING(R_ALERT)) &&
198: (rnd(12) < 4))
199: msg("%s grunts with frustration",prname(monster_name(tp),TRUE));
200:
201: when A_MOVE:
202: /* Let's try to move */
203: do_chase(tp);
204:
205: /* If t_no_move > 0, we found that we have to fight! */
206: if (tp->t_no_move > 0) return;
207:
208: when A_BREATHE:
209: /* Breathe on the critter */
210: m_breathe(tp);
211:
212: when A_SLOW:
213: /* make him move slower */
214: add_slow();
215: turn_off(*tp, CANSLOW);
216:
217: when A_MISSILE:
218: /* Start up a magic missile spell */
219: m_spell(tp);
220:
221: when A_SONIC:
222: /* Let out a sonic blast! */
223: m_sonic(tp);
224:
225: when A_THROW:
226: /* We're throwing something (like an arrow) */
227: missile(tp->t_newpos.y, tp->t_newpos.x, tp->t_using, tp);
228:
229: when A_SUMMON:
230: /* We're summoning help */
231: m_summon(tp);
232:
233: when A_USERELIC:
234: /* Use our relic */
235: m_use_relic(tp);
236:
237: when A_USEWAND:
238: /* use the wand we have */
239: m_use_wand(tp);
240: }
241:
242: /* Can we in fact move? (we might have solidified in solid rock) */
243: if (!step_ok(hero.y, hero.x, NOMONST, &player)) {
244:
245: if (move_free > 1) goto jump_over; /* avoid messages */
246: if (mf_count > 2) goto jump_over; /* limit messages */
247:
248: if (pstats.s_hpt < 1) {
249: pstats.s_hpt = -1;
250: msg("You have merged into the surroundings! --More--");
251: wait_for(' ');
252: death(D_PETRIFY);
253: }
254: else {
255: mf_count += 1; /* count number of times we are here */
256: pstats.s_hpt -= rnd(2)+1;
257: if (pstats.s_hpt < 1) {
258: pstats.s_hpt = -1;
259: msg("You have merged into the surroundings! --More--");
260: wait_for(' ');
261: death(D_PETRIFY);
262: }
263: }
264: switch (rnd(51)) {
265: case 0: msg("Arrrggghhhhh!! ");
266: when 5: msg("You can't move! ");
267: when 10: msg("You motion angrily! ");
268: when 15: msg("You feel so weird! ");
269: when 20: msg("If only you could phase. ");
270: when 25: msg("The rock maggots are closing in! ");
271: when 30: msg("You wrench and wrench and wrench... ");
272: when 35: msg("You wish you could teleport out of here! ");
273: when 40: msg("Your feel your life force ebbing away... ");
274: when 45: msg("You partially regain your senses. ");
275: when 50: msg("The rock maggots have found you!!! ");
276: otherwise: pstats.s_hpt -= rnd(4)+1;
277: }
278: if (pstats.s_hpt < 1) {
279: pstats.s_hpt = -1;
280: msg("You lose the urge to live... --More--");
281: wait_for(' ');
282: death(D_PETRIFY);
283: }
284: jump_over:
285: mf_jmpcnt++; /* count this jump */
286: if (mf_jmpcnt > 9) { /* take a few turns, then reset it */
287: mf_jmpcnt = 0;
288: mf_count = 0;
289: }
290: }
291:
292: /* No action now */
293: tp->t_action = A_NIL;
294: tp->t_using = NULL;
295: }
296:
297: /*
298: * m_breathe:
299: * Breathe in the chosen direction.
300: */
301:
302: void
303: m_breathe(struct thing *tp)
304: {
305: register int damage;
306: register char *breath = NULL;
307:
308: damage = tp->t_stats.s_hpt;
309: turn_off(*tp, CANSURPRISE);
310:
311: /* Will it breathe at random */
312: if (on(*tp, CANBRANDOM)) {
313: /* Turn off random breath */
314: turn_off(*tp, CANBRANDOM);
315:
316: /* Select type of breath */
317: switch (rnd(10)) {
318: case 0: breath = "acid";
319: turn_on(*tp, NOACID);
320: when 1: breath = "flame";
321: turn_on(*tp, NOFIRE);
322: when 2: breath = "lightning bolt";
323: turn_on(*tp, NOBOLT);
324: when 3: breath = "chlorine gas";
325: turn_on(*tp, NOGAS);
326: when 4: breath = "ice";
327: turn_on(*tp, NOCOLD);
328: when 5: breath = "nerve gas";
329: turn_on(*tp, NOPARALYZE);
330: when 6: breath = "sleeping gas";
331: turn_on(*tp, NOSLEEP);
332: when 7: breath = "slow gas";
333: turn_on(*tp, NOSLOW);
334: when 8: breath = "confusion gas";
335: turn_on(*tp, ISCLEAR);
336: when 9: breath = "fear gas";
337: turn_on(*tp, NOFEAR);
338: }
339: }
340:
341: /* Or can it breathe acid? */
342: else if (on(*tp, CANBACID)) {
343: turn_off(*tp, CANBACID);
344: breath = "acid";
345: }
346:
347: /* Or can it breathe fire */
348: else if (on(*tp, CANBFIRE)) {
349: turn_off(*tp, CANBFIRE);
350: breath = "flame";
351: }
352:
353: /* Or can it breathe electricity? */
354: else if (on(*tp, CANBBOLT)) {
355: turn_off(*tp, CANBBOLT);
356: breath = "lightning bolt";
357: }
358:
359: /* Or can it breathe gas? */
360: else if (on(*tp, CANBGAS)) {
361: turn_off(*tp, CANBGAS);
362: breath = "chlorine gas";
363: }
364:
365: /* Or can it breathe ice? */
366: else if (on(*tp, CANBICE)) {
367: turn_off(*tp, CANBICE);
368: breath = "ice";
369: }
370:
371: else if (on(*tp, CANBPGAS)) {
372: turn_off(*tp, CANBPGAS);
373: breath = "nerve gas";
374: }
375:
376: /* can it breathe sleeping gas */
377: else if (on(*tp, CANBSGAS)) {
378: turn_off(*tp, CANBSGAS);
379: breath = "sleeping gas";
380: }
381:
382: /* can it breathe slow gas */
383: else if (on(*tp, CANBSLGAS)) {
384: turn_off(*tp, CANBSLGAS);
385: breath = "slow gas";
386: }
387:
388: /* can it breathe confusion gas */
389: else if (on(*tp, CANBCGAS)) {
390: turn_off(*tp, CANBCGAS);
391: breath = "confusion gas";
392: }
393:
394: /* can it breathe fear gas */
395: else {
396: turn_off(*tp, CANBFGAS);
397: breath = "fear gas";
398: }
399:
400: /* Now breathe */
401: shoot_bolt(tp, tp->t_pos, tp->t_newpos, FALSE,
402: tp->t_index, breath, damage);
403:
404: running = FALSE;
405: if (fight_flush) flushinp();
406: }
407:
408: /*
409: * m_select:
410: * Select an action for the monster.
411: * flee: True if running away or player is inaccessible in wall
412: */
413:
414: void
415: m_select(struct thing *th, bool flee)
416: {
417: register struct room *rer, *ree; /* room of chaser, room of chasee */
418: int dist = INT_MIN;
419: int mindist = INT_MAX, maxdist = INT_MIN;
420: bool rundoor; /* TRUE means run to a door */
421: char sch;
422: coord *last_door=0, /* Door we just came from */
423: this; /* Temporary destination for chaser */
424:
425: rer = roomin(&th->t_pos); /* Find room of chaser */
426: ree = roomin(th->t_dest); /* Find room of chasee */
427:
428: /* First see if we want to use an ability or weapon */
429: if (m_use_it(th, flee, rer, ree)) return;
430:
431: /*
432: * We don't count monsters on doors as inside rooms here because when
433: * a monster is in a room and the player is not in that room, the
434: * monster looks for the best door out. If we counted doors as part
435: * of the room, the monster would already be on the best door out;
436: * so he would never move.
437: */
438: if ((sch = mvwinch(stdscr, th->t_pos.y, th->t_pos.x)) == DOOR ||
439: sch == SECRETDOOR || sch == PASSAGE) {
440: rer = NULL;
441: }
442: this = *th->t_dest;
443:
444: /*
445: * If we are in a room heading for the player and the player is not
446: * in the room with us, we run to the "best" door.
447: * If we are in a room fleeing from the player, then we run to the
448: * "best" door if he IS in the same room.
449: *
450: * Note: We don't bother with doors in mazes or if we can walk
451: * through walls.
452: */
453: if (rer != NULL && levtype != MAZELEV && off(*th, CANINWALL)) {
454: if (flee) rundoor = (rer == ree);
455: else rundoor = (rer != ree);
456: }
457: else rundoor = FALSE;
458:
459: if (rundoor) {
460: register struct linked_list *exitptr; /* For looping through exits */
461: coord *exit, /* A particular door */
462: *entrance; /* Place just inside doorway */
463: int exity, exitx; /* Door's coordinates */
464: char dch='\0'; /* Door character */
465:
466: if ((th->t_doorgoal.x != -1) && (th->t_doorgoal.y != -1))
467: dch = mvwinch(stdscr, th->t_doorgoal.y, th->t_doorgoal.x);
468:
469: /* Do we have a valid goal? */
470: if ((dch == PASSAGE || dch == DOOR) && /* A real door */
471: (!flee || !ce(th->t_doorgoal, *th->t_dest))) { /* Prey should not
472: * be at door if
473: * we are running
474: * away
475: */
476: /* Make sure the player is not in the doorway, either */
477: entrance = doorway(rer, &th->t_doorgoal);
478: if (!flee || entrance == NULL || !ce(*entrance, *th->t_dest)) {
479: this = th->t_doorgoal;
480: dist = 0; /* Indicate that we have our door */
481: }
482: }
483:
484: /* Go through all the doors */
485: else for (exitptr = rer->r_exit; exitptr; exitptr = next(exitptr)) {
486: exit = DOORPTR(exitptr);
487: exity = exit->y;
488: exitx = exit->x;
489:
490: /* Make sure it is a real door */
491: dch = mvwinch(stdscr, exity, exitx);
492: if (dch == PASSAGE || dch == DOOR) {
493: /* Don't count a door if we are fleeing from someone and
494: * he is standing on it. Also, don't count it if he is
495: * standing in the doorway.
496: */
497: if (flee) {
498: if (ce(*exit, *th->t_dest)) continue;
499:
500: entrance = doorway(rer, exit);
501: if (entrance != NULL && ce(*entrance, *th->t_dest))
502: continue;
503: }
504:
505: /* Were we just on this door? */
506: if (ce(*exit, th->t_oldpos)) last_door = exit;
507:
508: else {
509: dist = DISTANCE(th->t_dest->y, th->t_dest->x, exity, exitx);
510:
511: /* If fleeing, we want to maximize distance from door to
512: * what we flee, and minimize distance from door to us.
513: */
514: if (flee)
515: dist -= DISTANCE(th->t_pos.y, th->t_pos.x, exity, exitx);
516:
517: /* Maximize distance if fleeing, otherwise minimize it */
518: if ((flee && (dist > maxdist)) ||
519: (!flee && (dist < mindist))) {
520: th->t_doorgoal = *exit; /* Use this door */
521: this = *exit;
522: mindist = maxdist = dist;
523: }
524: }
525: }
526: }
527:
528: /* Could we not find a door? */
529: if (dist == INT_MIN) {
530: /* If we were on a door, go ahead and use it */
531: if (last_door) {
532: th->t_doorgoal = *last_door;
533: this = th->t_oldpos;
534: dist = 0; /* Indicate that we found a door */
535: }
536: else th->t_doorgoal.x = th->t_doorgoal.y = -1; /* No more door goal */
537: }
538:
539: /* Indicate that we do not want to flee from the door */
540: if (dist != INT_MIN) flee = FALSE;
541: }
542: else th->t_doorgoal.x = th->t_doorgoal.y = -1; /* Not going to any door */
543:
544: /* Now select someplace to go and start the action */
545: chase(th, &this, rer, ree, flee);
546: }
547:
548: /*
549: * m_sonic:
550: * The monster is sounding a sonic blast.
551: */
552:
553: void
554: m_sonic(struct thing *tp)
555: {
556: register int damage;
557: struct object blast =
558: {
559: MISSILE, {0, 0}, 0, "", "150" , NULL, 0, 0, 0, 0
560: };
561:
562: turn_off(*tp, CANSONIC);
563: turn_off(*tp, CANSURPRISE);
564: do_motion(&blast, tp->t_newpos.y, tp->t_newpos.x, tp);
565: damage = rnd(61)+40;
566: if (save(VS_BREATH, &player, -3))
567: damage /= 2;
568: msg ("%s's ultra-sonic blast hits you", prname(monster_name(tp), TRUE));
569: if ((pstats.s_hpt -= damage) <= 0) {
570: pstats.s_hpt = -1;
571: death(tp->t_index);
572: }
573: running = FALSE;
574: if (fight_flush) flushinp();
575: dsrpt_player();
576: }
577:
578: /*
579: * m_spell:
580: * The monster casts a spell. Currently this is limited to
581: * magic missile.
582: */
583: void
584: m_spell(struct thing *tp)
585: {
586: struct object missile =
587: {
588: MISSILE, {0, 0}, 0, "", "0d4 " , NULL, 0, WS_MISSILE, 100, 1
589: };
590:
591: sprintf(missile.o_hurldmg, "%dd4", tp->t_stats.s_lvl);
592: do_motion(&missile, tp->t_newpos.y, tp->t_newpos.x, tp);
593: hit_monster(unc(missile.o_pos), &missile, tp);
594: turn_off(*tp, CANMISSILE);
595: turn_off(*tp, CANSURPRISE);
596:
597: running = FALSE;
598: if (fight_flush) flushinp();
599: }
600:
601: /*
602: * m_summon:
603: * Summon aid.
604: */
605:
606: void
607: m_summon(struct thing *tp)
608: {
609: register char *helpname, *mname;
610: int fail, numsum;
611: register int which, i;
612:
613: /* Let's make sure our prey is still here */
614: if (!cansee(unc(tp->t_pos)) || fallpos(&hero, FALSE, 2) == NULL) return;
615:
616: /*
617: * Non-uniques can only summon once. Uniques get fewer
618: * creatures with each successive summoning. Also, the
619: * probability of summoning goes down
620: */
621: if (off(*tp, ISUNIQUE))
622: turn_off(*tp, CANSUMMON);
623:
624: turn_off(*tp, CANSURPRISE);
625: mname = monster_name(tp);
626: helpname = monsters[tp->t_index].m_typesum;
627: which = findmindex(helpname);
628:
629: if ((off(*tp, ISINVIS) || on(player, CANSEE)) &&
630: (off(*tp, ISSHADOW) || on(player, CANSEE)) &&
631: (off(*tp, CANSURPRISE) || ISWEARING(R_ALERT))) {
632: if (monsters[which].m_normal == FALSE) { /* genocided? */
633: msg("%s appears dismayed", prname(mname, TRUE));
634: monsters[tp->t_index].m_numsum = 0;
635: }
636: else {
637: msg("%s summons %ss for help", prname(mname, TRUE), helpname);
638: }
639: }
640: else {
641: if (monsters[which].m_normal == FALSE) /* genocided? */
642: monsters[tp->t_index].m_numsum = 0;
643: else {
644: msg("%ss seem to appear from nowhere!", helpname);
645: }
646: }
647: numsum = monsters[tp->t_index].m_numsum;
648: if (numsum && on(*tp, ISUNIQUE)) { /* UNIQUEs summon less each time */
649: monsters[tp->t_index].m_numsum--;
650: tp->t_summon *= 2; /* cut probability in half */
651: }
652:
653: /*
654: * try to make all the creatures around player but remember
655: * if unsuccessful
656: */
657: for (i=0, fail=0; i<numsum; i++) {
658: if (!creat_mons(&player, which, FALSE))
659: fail++; /* remember the failures */
660: }
661:
662: /*
663: * try once again to make the buggers
664: */
665: for (i=0; i<fail; i++)
666: creat_mons(tp, which, FALSE);
667:
668: /* Now let the poor fellow see all the trouble */
669: light(&hero);
670: turn_on(*tp, HASSUMMONED);
671: }
672:
673: /*
674: * m_use_it:
675: * See if the monster (tp) has anything useful it can do
676: * (ie. an ability or a weapon) other than just move.
677: */
678:
679: bool
680: m_use_it(struct thing *tp, bool flee, struct room *rer, struct room *ree)
681: {
682: int dist;
683: register coord *ee = tp->t_dest, *er = &tp->t_pos;
684: coord *shoot_dir = NULL;
685: coord straight_dir;
686: int straight_shot = FALSE;
687: struct thing *prey;
688: bool dest_player; /* Are we after the player? */
689:
690: /*
691: * If we are fleeing, there's a chance, depending on our
692: * intelligence, that we'll just run in terror.
693: */
694: if (flee && rnd(25) >= tp->t_stats.s_intel) return(FALSE);
695:
696: /*
697: * Make sure that we have a living destination, and record whether
698: * it is the player.
699: */
700: if (ee != NULL) {
701: if (ce(*ee, hero)) {
702: dest_player = TRUE;
703: prey = &player;
704: }
705: else {
706: struct linked_list *item;
707:
708: dest_player = FALSE;
709:
710: /* What is the monster we're chasing? */
711: item = find_mons(ee->y, ee->x);
712: if (item != NULL) prey = THINGPTR(item);
713: else return(FALSE);
714: }
715: }
716: else return(FALSE);
717:
718: /*
719: * If we are friendly to the hero, we don't do anything.
720: */
721: if (on(*tp, ISFRIENDLY) && dest_player) return(FALSE);
722:
723: /*
724: * Also, for now, if our prey is in a wall, we won't do
725: * anything. The prey must be in the same room as we are OR
726: * we must have a straight shot at him. Note that
727: * shoot_dir must get set before rer is checked so
728: * that we get a valid value.
729: */
730:
731: if (can_shoot(er, ee, &straight_dir) == 0)
732: shoot_dir = &straight_dir;
733: else
734: shoot_dir = NULL;
735:
736: if (on(*prey, ISINWALL) ||
737: ( (shoot_dir == NULL) && (rer == NULL || rer != ree)))
738: return(FALSE);
739:
740: /*
741: * If we can't see the prey then forget it
742: */
743: if (on(*prey, ISINVIS) && off(*tp, CANSEE))
744: return(FALSE);
745:
746: /* How far are we from our prey? */
747: dist = DISTANCE(er->y, er->x, ee->y, ee->x);
748:
749: /*
750: * Shall we summon aid so we don't have to get our hands dirty?
751: * For now, we will only summon aid against the player.
752: * We'll wait until he's within 2 dots of a missile length.
753: */
754: if (on(*tp, CANSUMMON) && dest_player &&
755: dist < (BOLT_LENGTH+2)*(BOLT_LENGTH+2) &&
756: rnd(tp->t_summon) < tp->t_stats.s_lvl &&
757: monsters[tp->t_index].m_numsum > 0 &&
758: fallpos(&hero, FALSE, 2) != NULL) {
759: tp->t_action = A_SUMMON; /* We're going to summon help */
760: tp->t_no_move = movement(tp); /* It takes time! */
761: return(TRUE);
762: }
763:
764: /*
765: * If the creature can cast a slow spell and if the prey is within
766: * 2 dots of a missile fire, then see whether we will cast it.
767: * if next to player, lessen chance because we don't like being
768: * disrupted
769: */
770: if (on(*tp, CANSLOW) && dest_player &&
771: dist < (BOLT_LENGTH+5)*(BOLT_LENGTH+5) &&
772: rnd(100) < (dist > 3 ? tp->t_cast : tp->t_cast/2)) {
773: tp->t_action = A_SLOW; /* We're going to slow him */
774: tp->t_no_move = 3 * movement(tp); /* Takes time! */
775: debug("casting slow spell!");
776: return(TRUE);
777: }
778:
779: /*
780: * If we have a special magic item, we might use it. We will restrict
781: * this options to uniques with relics and creatures with wands for now.
782: * Also check for the quartermaster. Don't want him shooting wands....
783: */
784: if ((on(*tp, ISUNIQUE) || on(*tp, CARRYSTICK)) &&
785: off(*tp, CANSELL) && dest_player &&
786: m_use_pack(tp, ee, dist, shoot_dir)) {
787: return(TRUE);
788: }
789:
790: /* From now on, we must have a direct shot at the prey */
791: if (!straight_shot) return(FALSE);
792:
793: /* We may use a sonic blast if we can, only on the player */
794: if (on(*tp, CANSONIC) &&
795: dest_player &&
796: (dist < BOLT_LENGTH*2) &&
797: (rnd(100) < tp->t_breathe)) {
798: tp->t_newpos = *shoot_dir; /* Save the direction */
799: tp->t_action = A_SONIC; /* We're going to sonic blast */
800: tp->t_no_move = 2 * movement(tp); /* Takes 2 movement periods */
801: }
802:
803: /* If we can breathe, we may do so */
804: else if (on(*tp, CANBREATHE) &&
805: (dist < BOLT_LENGTH*BOLT_LENGTH) &&
806: (rnd(100) < tp->t_breathe)) {
807: tp->t_newpos = *shoot_dir; /* Save the direction */
808: tp->t_action = A_BREATHE; /* We're going to breathe */
809: tp->t_no_move = movement(tp); /* It takes 1 movement period */
810: }
811:
812: /*
813: * We may shoot missiles if we can
814: * if next to player, lessen chance so we don't get disrupted as often
815: */
816: else if (on(*tp,CANMISSILE) &&
817: rnd(100) < (dist > 3 ? tp->t_cast : tp->t_cast/2)){
818: tp->t_newpos = *shoot_dir; /* Save the direction */
819: tp->t_action = A_MISSILE; /* We're going to shoot MM's */
820: tp->t_no_move = 3 * movement(tp); /* Takes time! */
821: }
822:
823: /*
824: * If we can shoot or throw something, we might do so.
825: * If next to player, then forget it
826: */
827: else if ((on(*tp,CANSHOOT) || on(*tp,CARRYWEAPON) ||
828: on(*tp,CARRYDAGGER) || on(*tp, CARRYAXE)) &&
829: dist > 3 &&
830: off(*tp, CANSELL) &&
831: (get_hurl(tp) != NULL)) {
832: tp->t_newpos = *shoot_dir; /* Save the direction */
833: tp->t_action = A_THROW; /* We're going to throw something */
834: tp->t_using = get_hurl(tp); /* Save our weapon */
835: tp->t_no_move = 2 * movement(tp); /* Takes 2 movement periods */
836: }
837:
838: /* We couldn't find anything to do */
839: else return(FALSE);
840:
841: return(TRUE);
842:
843: }
844:
845: void
846: reap(void)
847: {
848: _t_free_list(&rlist);
849: }
850:
851: /*
852: * runners:
853: * Make all the awake monsters try to do something.
854: * segments: Number of segments since last called
855: */
856:
857: int
858: runners(int segments)
859: {
860: register struct linked_list *item;
861: register struct thing *tp = NULL;
862: register int min_time = 20; /* Minimum time until a monster can act */
863:
864: /*
865: * loop thru the list of running (wandering) monsters and see what
866: * each one will do this time.
867: *
868: * Note: the special case that one of this buggers kills another.
869: * if this happens than we have to see if the monster killed
870: * himself or someone else. In case its himself we have to get next
871: * one immediately. If it wasn't we have to get next one at very
872: * end in case he killed the next one.
873: */
874: for (item = mlist; item != NULL; item = item->l_next)
875: {
876: tp = THINGPTR(item);
877: turn_on(*tp, NEEDSTOACT);
878: }
879:
880: for(;;)
881: {
882: for (item = mlist; item != NULL; item = item->l_next)
883: {
884: tp = THINGPTR(item);
885:
886: if (on(*tp, NEEDSTOACT))
887: break;
888: }
889:
890: if (item == NULL)
891: break;
892:
893: turn_off(*tp, NEEDSTOACT);
894:
895: /* If we are not awake, just skip us */
896:
897: if (off(*tp, ISRUN) && off(*tp, ISHELD))
898: continue;
899:
900: /* See if it's our turn */
901:
902: tp->t_no_move -= segments;
903:
904: if (tp->t_no_move > 0)
905: {
906: if (tp->t_no_move < min_time) min_time = tp->t_no_move;
907: continue;
908: }
909:
910: /* If we were frozen, we're moving now */
911:
912: if (tp->t_action == A_FREEZE)
913: tp->t_action = A_NIL;
914:
915: if (on(*tp, ISHELD))
916: {
917: /* Make sure the action and using are nil */
918:
919: tp->t_action = A_NIL;
920: tp->t_using = NULL;
921:
922: /* Can we break free? */
923:
924: if (rnd(tp->t_stats.s_lvl) > 11)
925: {
926: turn_off(*tp, ISHELD);
927:
928: runto(tp, &hero);
929:
930: if (cansee(tp->t_pos.y, tp->t_pos.x))
931: msg("%s breaks free from the hold spell",
932: prname(monster_name(tp), TRUE));
933: }
934: else /* Too bad -- try again later */
935: tp->t_no_move = movement(tp);
936: }
937:
938: /* Heal the creature if it's not in the middle of some action */
939:
940: if (tp->t_action == A_NIL)
941: doctor(tp);
942:
943: while (off(*tp, ISELSEWHERE) &&
944: off(*tp, ISDEAD) &&
945: tp->t_no_move <= 0 &&
946: off(*tp, ISHELD) &&
947: on(*tp, ISRUN) )
948: {
949: /* Let's act (or choose an action if t_action = A_NIL) */
950:
951: m_act(tp);
952: }
953:
954: if ( off(*tp,ISELSEWHERE) && off(*tp,ISDEAD) )
955: {
956: if (tp->t_no_move < min_time)
957: min_time = tp->t_no_move;
958:
959: if (tp->t_quiet < 0)
960: tp->t_quiet = 0;
961: }
962: }
963:
964: return(min_time);
965: }
966:
967: /*
968: * See if a monster has some magic it can use. Return TRUE if so.
969: * Only care about relics and wands for now.
970: */
971: bool
972: m_use_pack(struct thing *monster, coord *defend_pos, int dist, coord *shoot_dir)
973: {
974: register struct object *obj;
975: register struct linked_list *pitem, *relic, *stick;
976: register int units = -1;
977:
978: relic = stick = NULL;
979:
980: for (pitem=monster->t_pack; pitem; pitem=next(pitem)) {
981: obj = OBJPTR(pitem);
982: if (obj->o_flags & ISCURSED) continue;
983: if (obj->o_type == RELIC) {
984: switch (obj->o_which) {
985: case MING_STAFF:
986: if (shoot_dir != NULL) {
987: units = 2; /* Use 2 time units */
988: relic = pitem;
989: }
990:
991: when EMORI_CLOAK:
992: if (obj->o_charges != 0 &&
993: shoot_dir != NULL) {
994: units = 2; /* Use 2 time units */
995: relic = pitem;
996: }
997:
998: when ASMO_ROD:
999: /* The bolt must be able to reach the defendant */
1000: if (shoot_dir != NULL &&
1001: dist < BOLT_LENGTH * BOLT_LENGTH) {
1002: units = 2; /* Use 2 time units */
1003: relic = pitem;
1004: }
1005:
1006: when BRIAN_MANDOLIN:
1007: /* The defendant must be the player and within 4 spaces */
1008: if (ce(*defend_pos, hero) &&
1009: dist < 25 &&
1010: player.t_action != A_FREEZE) {
1011: units = 4;
1012: relic = pitem;
1013: }
1014:
1015: when GERYON_HORN:
1016: /* The defendant must be the player and within 5 spaces */
1017: if (ce(*defend_pos, hero) &&
1018: dist < 25 &&
1019: (off(player,ISFLEE)|| player.t_dest!=&monster->t_pos)) {
1020: units = 3;
1021: relic = pitem;
1022: }
1023: }
1024: }
1025: if (obj->o_type == STICK) {
1026: if (obj->o_charges < 1) continue;
1027: switch(obj->o_which) {
1028: case WS_ELECT:
1029: case WS_FIRE:
1030: case WS_COLD:
1031: /* The bolt must be able to reach the defendant */
1032: if (shoot_dir != NULL &&
1033: dist < BOLT_LENGTH * BOLT_LENGTH) {
1034: units = 3;
1035: stick = pitem;
1036: }
1037:
1038: when WS_MISSILE:
1039: case WS_SLOW_M:
1040: case WS_CONFMON:
1041: case WS_PARALYZE:
1042: case WS_MDEG:
1043: case WS_FEAR:
1044: if (shoot_dir != NULL) {
1045: units = 3;
1046: stick = pitem;
1047: }
1048:
1049: otherwise:
1050: break;
1051: }
1052: }
1053: }
1054:
1055: /* use relics in preference to all others */
1056: if (relic) debug("chance to use relic = %d%%", monster->t_artifact);
1057: if (stick) debug("chance to use stick = %d%%", monster->t_wand);
1058: if (relic && rnd(100) < monster->t_artifact) {
1059: monster->t_action = A_USERELIC;
1060: pitem = relic;
1061: }
1062: else if (stick && rnd(100) < monster->t_wand) {
1063: /*
1064: * see if the monster will use the wand
1065: */
1066: pitem = stick;
1067: monster->t_action = A_USEWAND;
1068: }
1069: else {
1070: return(FALSE);
1071: }
1072:
1073: monster->t_no_move = units * movement(monster);
1074: monster->t_using = pitem;
1075: monster->t_newpos = *shoot_dir;
1076: return(TRUE);
1077: }
1078:
CVSweb