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