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