ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/monster.C
Revision: 1.36
Committed: Sun Jul 1 05:00:20 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.35: +10 -11 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# Content
1 /*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 *
8 * Crossfire TRT is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 */
23
24 #include <global.h>
25 #include <sproto.h>
26 #include <spells.h>
27 #include <skills.h>
28
29 #define MIN_MON_RADIUS 3 /* minimum monster detection radius */
30
31 /* checks npc->enemy and returns that enemy if still valid,
32 * NULL otherwise.
33 * this is map tile aware.
34 * If this returns an enemy, the range vector rv should also be
35 * set to sane values.
36 */
37 object *
38 check_enemy (object *npc, rv_vector * rv)
39 {
40
41 /* if this is pet, let him attack the same enemy as his owner
42 * TODO: when there is no ower enemy, try to find a target,
43 * which CAN attack the owner. */
44 if ((npc->attack_movement & HI4) == PETMOVE)
45 {
46 if (npc->owner == NULL)
47 npc->enemy = NULL;
48 else if (npc->enemy == NULL)
49 npc->enemy = npc->owner->enemy;
50 }
51
52 /* periodically, a monster mayu change its target. Also, if the object
53 * has been destroyed, etc, clear the enemy.
54 * TODO: this should be changed, because it invokes to attack forced or
55 * attacked monsters to leave the attacker alone, before it is destroyed
56 */
57 /* i had removed the random target leave, this invokes problems with friendly
58 * objects, getting attacked and defending herself - they don't try to attack
59 * again then but perhaps get attack on and on
60 * If we include a aggravated flag in , we can handle evil vs evil and good vs good
61 * too. */
62
63 if (npc->enemy)
64 {
65 /* I broke these if's apart to better be able to see what
66 * the grouping checks are. Code is the same.
67 */
68 if (QUERY_FLAG (npc->enemy, FLAG_REMOVED) ||
69 QUERY_FLAG (npc->enemy, FLAG_FREED) ||
70 !on_same_map (npc, npc->enemy) || npc == npc->enemy || QUERY_FLAG (npc, FLAG_NEUTRAL) || QUERY_FLAG (npc->enemy, FLAG_NEUTRAL))
71 npc->enemy = NULL;
72
73 else if (QUERY_FLAG (npc, FLAG_FRIENDLY) && ((QUERY_FLAG (npc->enemy, FLAG_FRIENDLY)
74 && !(should_arena_attack (npc, npc->owner, npc->enemy)))
75 || ((npc->enemy->type == PLAYER) && !(should_arena_attack (npc, npc->owner, npc->enemy)))
76 || npc->enemy == npc->owner))
77 npc->enemy = NULL;
78
79
80 else if (!QUERY_FLAG (npc, FLAG_FRIENDLY) && (!QUERY_FLAG (npc->enemy, FLAG_FRIENDLY) && npc->enemy->type != PLAYER))
81 npc->enemy = NULL;
82
83 /* I've noticed that pets could sometimes get an arrow as the
84 * target enemy - this code below makes sure the enemy is something
85 * that should be attacked. My guess is that the arrow hits
86 * the creature/owner, and so the creature then takes that
87 * as the enemy to attack.
88 */
89 else if (!QUERY_FLAG (npc->enemy, FLAG_MONSTER)
90 && !QUERY_FLAG (npc->enemy, FLAG_GENERATOR)
91 && npc->enemy->type != PLAYER
92 && npc->enemy->type != GOLEM)
93 npc->enemy = NULL;
94
95 }
96 return can_detect_enemy (npc, npc->enemy, rv) ? npc->enemy : NULL;
97 }
98
99 /* Returns the nearest living creature (monster or generator).
100 * Modified to deal with tiled maps properly.
101 * Also fixed logic so that monsters in the lower directions were more
102 * likely to be skipped - instead of just skipping the 'start' number
103 * of direction, revisit them after looking at all the other spaces.
104 *
105 * Note that being this may skip some number of spaces, it will
106 * not necessarily find the nearest living creature - it basically
107 * chooses one from within a 3 space radius, and since it skips
108 * the first few directions, it could very well choose something
109 * 3 spaces away even though something directly north is closer.
110 *
111 * this function is map tile aware.
112 */
113 object *
114 find_nearest_living_creature (object *npc)
115 {
116 int i, mflags;
117 sint16 nx, ny;
118 maptile *m;
119 int search_arr[SIZEOFFREE];
120
121 get_search_arr (search_arr);
122
123 for (i = 0; i < SIZEOFFREE; i++)
124 {
125 /* modified to implement smart searching using search_arr
126 * guidance array to determine direction of search order
127 */
128 nx = npc->x + freearr_x[search_arr[i]];
129 ny = npc->y + freearr_y[search_arr[i]];
130 m = npc->map;
131
132 mflags = get_map_flags (m, &m, nx, ny, &nx, &ny);
133
134 if (mflags & P_OUT_OF_MAP)
135 continue;
136
137 if (mflags & P_IS_ALIVE)
138 {
139 for (object *tmp = m->at (nx, ny).top; tmp; tmp = tmp->below)
140 if (tmp->flag [FLAG_MONSTER] || tmp->flag [FLAG_GENERATOR] || tmp->type == PLAYER)
141 if (can_see_monsterP (m, nx, ny, i))
142 return tmp;
143 }
144 }
145
146 return 0;
147 }
148
149 /* Tries to find an enemy for npc. We pass the range vector since
150 * our caller will find the information useful.
151 * Currently, only move_monster calls this function.
152 * Fix function so that we always make calls to get_rangevector
153 * if we have a valid target - function as not doing so in
154 * many cases.
155 */
156 object *
157 find_enemy (object *npc, rv_vector * rv)
158 {
159 object *attacker, *tmp = NULL;
160
161 attacker = npc->attacked_by; /* save this for later use. This can be a attacker. */
162 npc->attacked_by = 0; /* always clear the attacker entry */
163
164 /* if we berserk, we don't care about others - we attack all we can find */
165 if (QUERY_FLAG (npc, FLAG_BERSERK))
166 {
167 tmp = find_nearest_living_creature (npc);
168
169 if (tmp)
170 get_rangevector (npc, tmp, rv, 0);
171 return tmp;
172 }
173
174 /* Here is the main enemy selection.
175 * We want this: if there is an enemy, attack him until its not possible or
176 * one of both is dead.
177 * If we have no enemy and we are...
178 * a monster: try to find a player, a pet or a friendly monster
179 * a friendly: only target a monster which is targeting you first or targeting a player
180 * a neutral: fight a attacker (but there should be none), then do nothing
181 * a pet: attack player enemy or a monster
182 */
183
184 /* pet move */
185 if ((npc->attack_movement & HI4) == PETMOVE)
186 {
187 tmp = get_pet_enemy (npc, rv);
188
189 if (tmp)
190 get_rangevector (npc, tmp, rv, 0);
191
192 return tmp;
193 }
194
195 /* we check our old enemy. */
196 if (!(tmp = check_enemy (npc, rv)))
197 {
198 if (attacker) /* if we have an attacker, check him */
199 {
200 /* TODO: thats not finished */
201 /* we don't want a fight evil vs evil or good against non evil */
202
203 if (QUERY_FLAG (npc, FLAG_NEUTRAL) || QUERY_FLAG (attacker, FLAG_NEUTRAL) || /* neutral */
204 (QUERY_FLAG (npc, FLAG_FRIENDLY) && QUERY_FLAG (attacker, FLAG_FRIENDLY)) ||
205 (!QUERY_FLAG (npc, FLAG_FRIENDLY) && (!QUERY_FLAG (attacker, FLAG_FRIENDLY) && attacker->type != PLAYER)))
206 CLEAR_FLAG (npc, FLAG_SLEEP); /* skip it, but lets wakeup */
207 else if (on_same_map (npc, attacker)) /* thats the only thing we must know... */
208 {
209 CLEAR_FLAG (npc, FLAG_SLEEP); /* well, NOW we really should wake up! */
210 npc->enemy = attacker;
211 return attacker; /* yes, we face our attacker! */
212 }
213 }
214
215 /* we have no legal enemy or attacker, so we try to target a new one */
216 if (!QUERY_FLAG (npc, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (npc, FLAG_FRIENDLY) && !QUERY_FLAG (npc, FLAG_NEUTRAL))
217 {
218 npc->enemy = get_nearest_player (npc);
219 if (npc->enemy)
220 tmp = check_enemy (npc, rv);
221 }
222
223 }
224
225 return tmp;
226 }
227
228 /* Sees if this monster should wake up.
229 * Currently, this is only called from move_monster, and
230 * if enemy is set, then so should be rv.
231 * returns 1 if the monster should wake up, 0 otherwise.
232 */
233 int
234 check_wakeup (object *op, object *enemy, rv_vector * rv)
235 {
236 int radius = op->stats.Wis > MIN_MON_RADIUS ? op->stats.Wis : MIN_MON_RADIUS;
237
238 /* Trim work - if no enemy, no need to do anything below */
239 if (!enemy)
240 return 0;
241
242 /* blinded monsters can only find nearby objects to attack */
243 if (QUERY_FLAG (op, FLAG_BLIND))
244 radius = MIN_MON_RADIUS;
245
246 /* This covers the situation where the monster is in the dark
247 * and has an enemy. If the enemy has no carried light (or isnt
248 * glowing!) then the monster has trouble finding the enemy.
249 * Remember we already checked to see if the monster can see in
250 * the dark. */
251
252 else if (op->map && op->map->darkness > 0 && enemy && !enemy->invisible &&
253 !stand_in_light (enemy) && (!QUERY_FLAG (op, FLAG_SEE_IN_DARK) || !QUERY_FLAG (op, FLAG_SEE_INVISIBLE)))
254 {
255 int dark = radius / (op->map->darkness);
256
257 radius = (dark > MIN_MON_RADIUS) ? (dark + 1) : MIN_MON_RADIUS;
258 }
259 else if (!QUERY_FLAG (op, FLAG_SLEEP))
260 return 1;
261
262 /* enemy should already be on this map, so don't really need to check
263 * for that.
264 */
265 if (rv->distance < (unsigned int) (QUERY_FLAG (enemy, FLAG_STEALTH) ? (radius / 2) + 1 : radius))
266 {
267 CLEAR_FLAG (op, FLAG_SLEEP);
268 return 1;
269 }
270 return 0;
271 }
272
273 int
274 move_randomly (object *op)
275 {
276 int i;
277
278 /* Give up to 15 chances for a monster to move randomly */
279 for (i = 0; i < 15; i++)
280 {
281 if (move_object (op, rndm (8) + 1))
282 return 1;
283 }
284 return 0;
285 }
286
287 /*
288 * Move-monster returns 1 if the object has been freed, otherwise 0.
289 */
290 int
291 move_monster (object *op)
292 {
293 int dir, diff, pre_att_dir; /* elmex: pre_att_dir remembers the direction before attack movement */
294 object *owner, *enemy, *part, *oph = op;
295 rv_vector rv;
296
297 /* Monsters not on maps don't do anything. These monsters are things
298 * Like royal guards in city dwellers inventories.
299 */
300 if (!op->map)
301 return 0;
302
303 /* for target facing, we copy this value here for fast access */
304 if (oph->head) /* force update the head - one arch one pic */
305 oph = oph->head;
306
307 if (QUERY_FLAG (op, FLAG_NO_ATTACK)) /* we never ever attack */
308 enemy = op->enemy = NULL;
309 else if ((enemy = find_enemy (op, &rv)))
310 /* we have an enemy, just tell him we want him dead */
311 enemy->attacked_by = op; /* our ptr */
312
313 /* generate hp, if applicable */
314 if (op->stats.Con > 0 && op->stats.hp < op->stats.maxhp)
315 {
316
317 /* last heal is in funny units. Dividing by speed puts
318 * the regeneration rate on a basis of time instead of
319 * #moves the monster makes. The scaling by 8 is
320 * to capture 8th's of a hp fraction regens
321 *
322 * Cast to sint32 before comparing to maxhp since otherwise an (sint16)
323 * overflow might produce monsters with negative hp.
324 */
325
326 op->last_heal += (int) ((float) (8 * op->stats.Con) / FABS (op->speed));
327 op->stats.hp = MIN ((sint32) op->stats.hp + op->last_heal / 32, op->stats.maxhp); /* causes Con/4 hp/tick */
328 op->last_heal %= 32;
329
330 /* So if the monster has gained enough HP that they are no longer afraid */
331 if (QUERY_FLAG (op, FLAG_RUN_AWAY) && op->stats.hp >= (signed short) (((float) op->run_away / (float) 100) * (float) op->stats.maxhp))
332 CLEAR_FLAG (op, FLAG_RUN_AWAY);
333
334 if (op->stats.hp > op->stats.maxhp)
335 op->stats.hp = op->stats.maxhp;
336 }
337
338 /* generate sp, if applicable */
339 if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp)
340 {
341
342 /* last_sp is in funny units. Dividing by speed puts
343 * the regeneration rate on a basis of time instead of
344 * #moves the monster makes. The scaling by 8 is
345 * to capture 8th's of a sp fraction regens
346 *
347 * Cast to sint32 before comparing to maxhp since otherwise an (sint16)
348 * overflow might produce monsters with negative sp.
349 */
350
351 op->last_sp += (int) ((float) (8 * op->stats.Pow) / FABS (op->speed));
352 op->stats.sp = MIN (op->stats.sp + op->last_sp / 128, op->stats.maxsp); /* causes Pow/16 sp/tick */
353 op->last_sp %= 128;
354 }
355
356 /* this should probably get modified by many more values.
357 * (eg, creatures resistance to fear, level, etc. )
358 */
359 if (QUERY_FLAG (op, FLAG_SCARED) && !(rndm (20)))
360 {
361 CLEAR_FLAG (op, FLAG_SCARED); /* Time to regain some "guts"... */
362 }
363
364 if (INVOKE_OBJECT (MONSTER_MOVE, op, ARG_OBJECT (op->enemy)))
365 return QUERY_FLAG (op, FLAG_FREED);
366
367 if (QUERY_FLAG (op, FLAG_SLEEP) || QUERY_FLAG (op, FLAG_BLIND) ||
368 ((op->map->darkness > 0) && !QUERY_FLAG (op, FLAG_SEE_IN_DARK) && !QUERY_FLAG (op, FLAG_SEE_INVISIBLE)))
369 {
370 if (!check_wakeup (op, enemy, &rv))
371 return 0;
372 }
373
374 /* check if monster pops out of hidden spot */
375 if (op->hide)
376 do_hidden_move (op);
377
378 if (op->pick_up)
379 monster_check_pickup (op);
380
381 if (op->will_apply)
382 monster_apply_below (op); /* Check for items to apply below */
383
384 /* If we don't have an enemy, do special movement or the like */
385 if (!enemy)
386 {
387 if (QUERY_FLAG (op, FLAG_ONLY_ATTACK))
388 {
389 op->destroy ();
390 return 1;
391 }
392
393 /* Probably really a bug for a creature to have both
394 * stand still and a movement type set.
395 */
396 if (!QUERY_FLAG (op, FLAG_STAND_STILL))
397 {
398 if (op->attack_movement & HI4)
399 {
400 switch (op->attack_movement & HI4)
401 {
402 case (PETMOVE):
403 pet_move (op);
404 break;
405
406 case (CIRCLE1):
407 circ1_move (op);
408 break;
409
410 case (CIRCLE2):
411 circ2_move (op);
412 break;
413
414 case (PACEV):
415 pace_movev (op);
416 break;
417
418 case (PACEH):
419 pace_moveh (op);
420 break;
421
422 case (PACEV2):
423 pace2_movev (op);
424 break;
425
426 case (PACEH2):
427 pace2_moveh (op);
428 break;
429
430 case (RANDO):
431 rand_move (op);
432 break;
433
434 case (RANDO2):
435 move_randomly (op);
436 break;
437 }
438 return 0;
439 }
440 else if (QUERY_FLAG (op, FLAG_RANDOM_MOVE))
441 (void) move_randomly (op);
442
443 } /* stand still */
444 return 0;
445 } /* no enemy */
446
447 /* We have an enemy. Block immediately below is for pets */
448 if ((op->attack_movement & HI4) == PETMOVE
449 && (owner = op->owner) != NULL
450 && !on_same_map (op, owner)
451 && !owner->flag [FLAG_REMOVED])
452 return follow_owner (op, owner);
453
454 /* doppleganger code to change monster facing to that of the nearest
455 * player. Hmm. The code is here, but no monster in the current
456 * arch set uses it.
457 */
458 if ((op->race != NULL) && strcmp (op->race, "doppleganger") == 0)
459 {
460 op->face = enemy->face;
461 op->name = enemy->name;
462 }
463
464 /* Calculate range information for closest body part - this
465 * is used for the 'skill' code, which isn't that smart when
466 * it comes to figuring it out - otherwise, giants throw boulders
467 * into themselves.
468 */
469 get_rangevector (op, enemy, &rv, 0);
470
471 /* Move the check for scared up here - if the monster was scared,
472 * we were not doing any of the logic below, so might as well save
473 * a few cpu cycles.
474 */
475 if (!QUERY_FLAG (op, FLAG_SCARED))
476 {
477 rv_vector rv1;
478
479 /* now we test every part of an object .... this is a real ugly piece of code */
480 for (part = op; part; part = part->more)
481 {
482 get_rangevector (part, enemy, &rv1, 0x1);
483 dir = rv1.direction;
484
485 /* hm, not sure about this part - in original was a scared flag here too
486 * but that we test above... so can be old code here
487 */
488 if (QUERY_FLAG (op, FLAG_RUN_AWAY))
489 dir = absdir (dir + 4);
490
491 if (QUERY_FLAG (op, FLAG_CONFUSED))
492 dir = absdir (dir + rndm (3) + rndm (3) - 2);
493
494 if (QUERY_FLAG (op, FLAG_CAST_SPELL) && !(rndm (3)))
495 if (monster_cast_spell (op, part, enemy, dir, &rv1))
496 return 0;
497
498 if (QUERY_FLAG (op, FLAG_READY_SCROLL) && !(rndm (3)))
499 if (monster_use_scroll (op, part, enemy, dir, &rv1))
500 return 0;
501
502 if (QUERY_FLAG (op, FLAG_READY_RANGE) && !(rndm (3)))
503 if (monster_use_range (op, part, enemy, dir))
504 return 0;
505
506 if (QUERY_FLAG (op, FLAG_READY_SKILL) && !(rndm (3)))
507 if (monster_use_skill (op, rv.part, enemy, rv.direction))
508 return 0;
509
510 if (QUERY_FLAG (op, FLAG_READY_BOW) && !(rndm (2)))
511 if (monster_use_bow (op, part, enemy, dir))
512 return 0;
513 } /* for processing of all parts */
514 } /* If not scared */
515
516
517 part = rv.part;
518 dir = rv.direction;
519
520 if (QUERY_FLAG (op, FLAG_SCARED) || QUERY_FLAG (op, FLAG_RUN_AWAY))
521 dir = absdir (dir + 4);
522
523 if (QUERY_FLAG (op, FLAG_CONFUSED))
524 dir = absdir (dir + rndm (3) + rndm (3) - 2);
525
526 pre_att_dir = dir; /* remember the original direction */
527
528 if ((op->attack_movement & LO4) && !QUERY_FLAG (op, FLAG_SCARED))
529 {
530 switch (op->attack_movement & LO4)
531 {
532 case DISTATT:
533 dir = dist_att (dir, op, enemy, part, &rv);
534 break;
535
536 case RUNATT:
537 dir = run_att (dir, op, enemy, part, &rv);
538 break;
539
540 case HITRUN:
541 dir = hitrun_att (dir, op, enemy);
542 break;
543
544 case WAITATT:
545 dir = wait_att (dir, op, enemy, part, &rv);
546 break;
547
548 case RUSH: /* default - monster normally moves towards player */
549 case ALLRUN:
550 break;
551
552 case DISTHIT:
553 dir = disthit_att (dir, op, enemy, part, &rv);
554 break;
555
556 case WAIT2:
557 dir = wait_att2 (dir, op, enemy, part, &rv);
558 break;
559
560 default:
561 LOG (llevDebug, "Illegal low mon-move: %d\n", op->attack_movement & LO4);
562 }
563 }
564
565 if (!dir)
566 return 0;
567
568 if (!QUERY_FLAG (op, FLAG_STAND_STILL))
569 {
570 if (move_object (op, dir)) /* Can the monster move directly toward player? */
571 {
572 /* elmex: Turn our monster after it moved if it has DISTATT attack */
573 if ((op->attack_movement & LO4) == DISTATT)
574 op->direction = pre_att_dir;
575
576 return 0;
577 }
578
579 if (QUERY_FLAG (op, FLAG_SCARED) || !can_hit (part, enemy, &rv) || QUERY_FLAG (op, FLAG_RUN_AWAY))
580 {
581
582 /* Try move around corners if !close */
583 int maxdiff = (QUERY_FLAG (op, FLAG_ONLY_ATTACK) || RANDOM () & 1) ? 1 : 2;
584
585 for (diff = 1; diff <= maxdiff; diff++)
586 {
587 /* try different detours */
588 int m = 1 - (RANDOM () & 2); /* Try left or right first? */
589
590 if (move_object (op, absdir (dir + diff * m)) || move_object (op, absdir (dir - diff * m)))
591 return 0;
592 }
593 }
594 } /* if monster is not standing still */
595
596 /* elmex: Turn our monster after it moved if it has DISTATT attack */
597 if ((op->attack_movement & LO4) == DISTATT)
598 op->direction = pre_att_dir;
599
600 /*
601 * Eneq(@csd.uu.se): Patch to make RUN_AWAY or SCARED monsters move a random
602 * direction if they can't move away.
603 */
604 if (!QUERY_FLAG (op, FLAG_ONLY_ATTACK) && (QUERY_FLAG (op, FLAG_RUN_AWAY) || QUERY_FLAG (op, FLAG_SCARED)))
605 if (move_randomly (op))
606 return 0;
607
608 /*
609 * Try giving the monster a new enemy - the player that is closest
610 * to it. In this way, it won't just keep trying to get to a target
611 * that is inaccessible.
612 * This could be more clever - it should go through a list of several
613 * enemies, as it is now, you could perhaps get situations where there
614 * are two players flanking the monster at close distance, but which
615 * the monster can't get to, and a third one at a far distance that
616 * the monster could get to - as it is, the monster won't look at that
617 * third one.
618 */
619 if (!QUERY_FLAG (op, FLAG_FRIENDLY) && enemy == op->enemy)
620 {
621 object *nearest_player = get_nearest_player (op);
622
623 if (nearest_player && nearest_player != enemy && !can_hit (part, enemy, &rv))
624 {
625 op->enemy = NULL;
626 enemy = nearest_player;
627 }
628 }
629
630 if (!QUERY_FLAG (op, FLAG_SCARED) && can_hit (part, enemy, &rv))
631 {
632 /* The adjustement to wc that was here before looked totally bogus -
633 * since wc can in fact get negative, that would mean by adding
634 * the current wc, the creature gets better? Instead, just
635 * add a fixed amount - nasty creatures that are runny away should
636 * still be pretty nasty.
637 */
638 if (QUERY_FLAG (op, FLAG_RUN_AWAY))
639 {
640 part->stats.wc += 10;
641 (void) skill_attack (enemy, part, 0, NULL, NULL);
642 part->stats.wc -= 10;
643 }
644 else
645 (void) skill_attack (enemy, part, 0, NULL, NULL);
646 } /* if monster is in attack range */
647
648 if (QUERY_FLAG (part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */
649 return 1;
650
651 if (QUERY_FLAG (op, FLAG_ONLY_ATTACK))
652 {
653 op->remove ();
654 op->destroy ();
655 return 1;
656 }
657 return 0;
658 }
659
660 int
661 can_hit (object *ob1, object *ob2, rv_vector * rv)
662 {
663 object *more;
664 rv_vector rv1;
665
666 if (QUERY_FLAG (ob1, FLAG_CONFUSED) && !(rndm (3)))
667 return 0;
668
669 if (abs (rv->distance_x) < 2 && abs (rv->distance_y) < 2)
670 return 1;
671
672 /* check all the parts of ob2 - just because we can't get to
673 * its head doesn't mean we don't want to pound its feet
674 */
675 for (more = ob2->more; more != NULL; more = more->more)
676 {
677 get_rangevector (ob1, more, &rv1, 0);
678 if (abs (rv1.distance_x) < 2 && abs (rv1.distance_y) < 2)
679 return 1;
680 }
681 return 0;
682
683 }
684
685 /* Returns 1 is monster should cast spell sp at an enemy
686 * Returns 0 if the monster should not cast this spell.
687 *
688 * Note that this function does not check to see if the monster can
689 * in fact cast the spell (sp dependencies and what not.) That is because
690 * this function is also sued to see if the monster should use spell items
691 * (rod/horn/wand/scroll).
692 * Note that there are certainly other offensive spells that could be
693 * included, but I decided to leave out the spells that may kill more
694 * monsters than players (eg, disease).
695 *
696 * This could be a lot smarter - if there are few monsters around,
697 * then disease might not be as bad. Likewise, if the monster is damaged,
698 * the right type of healing spell could be useful.
699 */
700
701 static int
702 monster_should_cast_spell (object *monster, object *spell_ob)
703 {
704 if (spell_ob->subtype == SP_BOLT || spell_ob->subtype == SP_BULLET ||
705 spell_ob->subtype == SP_EXPLOSION || spell_ob->subtype == SP_CONE ||
706 spell_ob->subtype == SP_BOMB || spell_ob->subtype == SP_SMITE ||
707 spell_ob->subtype == SP_MAGIC_MISSILE || spell_ob->subtype == SP_SUMMON_GOLEM ||
708 spell_ob->subtype == SP_MAGIC_WALL || spell_ob->subtype == SP_SUMMON_MONSTER ||
709 spell_ob->subtype == SP_MOVING_BALL || spell_ob->subtype == SP_SWARM || spell_ob->subtype == SP_INVISIBLE)
710
711 return 1;
712
713 return 0;
714 }
715
716
717 #define MAX_KNOWN_SPELLS 20
718
719 /* Returns a randomly selected spell. This logic is still
720 * less than ideal. This code also only seems to deal with
721 * wizard spells, as the check is against sp, and not grace.
722 * can mosnters know cleric spells?
723 */
724 object *
725 monster_choose_random_spell (object *monster)
726 {
727 object *altern[MAX_KNOWN_SPELLS];
728 object *tmp;
729 int i = 0;
730
731 for (tmp = monster->inv; tmp != NULL; tmp = tmp->below)
732 if (tmp->type == SPELLBOOK || tmp->type == SPELL)
733 {
734 /* Check and see if it's actually a useful spell.
735 * If its a spellbook, the spell is actually the inventory item.
736 * if it is a spell, then it is just the object itself.
737 */
738 if (monster_should_cast_spell (monster, (tmp->type == SPELLBOOK) ? tmp->inv : tmp))
739 {
740 altern[i++] = tmp;
741 if (i == MAX_KNOWN_SPELLS)
742 break;
743 }
744 }
745 if (!i)
746 return NULL;
747 return altern[RANDOM () % i];
748 }
749
750 /* This checks to see if the monster should cast a spell/ability.
751 * it returns true if the monster casts a spell, 0 if he doesn't.
752 * head is the head of the monster.
753 * part is the part of the monster we are checking against.
754 * pl is the target.
755 * dir is the direction to case.
756 * rv is the vector which describes where the enemy is.
757 */
758
759 int
760 monster_cast_spell (object *head, object *part, object *pl, int dir, rv_vector * rv)
761 {
762 object *spell_item;
763 object *owner;
764 rv_vector rv1;
765
766 /* If you want monsters to cast spells over friends, this spell should
767 * be removed. It probably should be in most cases, since monsters still
768 * don't care about residual effects (ie, casting a cone which may have a
769 * clear path to the player, the side aspects of the code will still hit
770 * other monsters)
771 */
772 if (!(dir = path_to_player (part, pl, 0)))
773 return 0;
774
775 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
776 {
777 get_rangevector (head, owner, &rv1, 0x1);
778 if (dirdiff (dir, rv1.direction) < 2)
779 {
780 return 0; /* Might hit owner with spell */
781 }
782 }
783
784 if (QUERY_FLAG (head, FLAG_CONFUSED))
785 dir = absdir (dir + rndm (3) + rndm (3) - 2);
786
787 /* If the monster hasn't already chosen a spell, choose one
788 * I'm not sure if it really make sense to pre-select spells (events
789 * could be different by the time the monster goes again).
790 */
791 if (head->spellitem == NULL)
792 {
793 if ((spell_item = monster_choose_random_spell (head)) == NULL)
794 {
795 LOG (llevMonster, "Turned off spells in %s\n", &head->name);
796 CLEAR_FLAG (head, FLAG_CAST_SPELL); /* Will be turned on when picking up book */
797 return 0;
798 }
799 if (spell_item->type == SPELLBOOK)
800 {
801 if (!spell_item->inv)
802 {
803 LOG (llevError, "spellbook %s does not contain a spell?\n", &spell_item->name);
804 return 0;
805 }
806 spell_item = spell_item->inv;
807 }
808 }
809 else
810 spell_item = head->spellitem;
811
812 if (!spell_item)
813 return 0;
814
815 /* Best guess this is a defensive/healing spell */
816 if (spell_item->range <= 1 || spell_item->stats.dam < 0)
817 dir = 0;
818
819 /* Monster doesn't have enough spell-points */
820 if (head->stats.sp < SP_level_spellpoint_cost (head, spell_item, SPELL_MANA))
821 return 0;
822
823 if (head->stats.grace < SP_level_spellpoint_cost (head, spell_item, SPELL_GRACE))
824 return 0;
825
826 head->stats.sp -= SP_level_spellpoint_cost (head, spell_item, SPELL_MANA);
827 head->stats.grace -= SP_level_spellpoint_cost (head, spell_item, SPELL_GRACE);
828
829 /* set this to null, so next time monster will choose something different */
830 head->spellitem = NULL;
831
832 return cast_spell (part, part, dir, spell_item, NULL);
833 }
834
835
836 int
837 monster_use_scroll (object *head, object *part, object *pl, int dir, rv_vector * rv)
838 {
839 object *scroll;
840 object *owner;
841 rv_vector rv1;
842
843 /* If you want monsters to cast spells over friends, this spell should
844 * be removed. It probably should be in most cases, since monsters still
845 * don't care about residual effects (ie, casting a cone which may have a
846 * clear path to the player, the side aspects of the code will still hit
847 * other monsters)
848 */
849 if (!(dir = path_to_player (part, pl, 0)))
850 return 0;
851
852 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
853 {
854 get_rangevector (head, owner, &rv1, 0x1);
855 if (dirdiff (dir, rv1.direction) < 2)
856 {
857 return 0; /* Might hit owner with spell */
858 }
859 }
860
861 if (QUERY_FLAG (head, FLAG_CONFUSED))
862 dir = absdir (dir + rndm (3) + rndm (3) - 2);
863
864 for (scroll = head->inv; scroll; scroll = scroll->below)
865 if (scroll->type == SCROLL && monster_should_cast_spell (head, scroll->inv))
866 break;
867
868 /* Used up all his scrolls, so nothing do to */
869 if (!scroll)
870 {
871 CLEAR_FLAG (head, FLAG_READY_SCROLL);
872 return 0;
873 }
874
875 /* Spell should be cast on caster (ie, heal, strength) */
876 if (scroll->inv->range == 0)
877 dir = 0;
878
879 apply_scroll (part, scroll, dir);
880 return 1;
881 }
882
883 /* monster_use_skill()-implemented 95-04-28 to allow monster skill use.
884 * Note that monsters do not need the skills SK_MELEE_WEAPON and
885 * SK_MISSILE_WEAPON to make those respective attacks, if we
886 * required that we would drastically increase the memory
887 * requirements of CF!!
888 *
889 * The skills we are treating here are all but those. -b.t.
890 *
891 * At the moment this is only useful for throwing, perhaps for
892 * stealing. TODO: This should be more integrated in the game. -MT, 25.11.01
893 */
894 int
895 monster_use_skill (object *head, object *part, object *pl, int dir)
896 {
897 object *skill, *owner;
898
899 if (!(dir = path_to_player (part, pl, 0)))
900 return 0;
901
902 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
903 {
904 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
905
906 if (dirdiff (dir, dir2) < 1)
907 return 0; /* Might hit owner with skill -thrown rocks for example ? */
908 }
909
910 if (QUERY_FLAG (head, FLAG_CONFUSED))
911 dir = absdir (dir + rndm (3) + rndm (3) - 2);
912
913 /* skill selection - monster will use the next unused skill.
914 * well...the following scenario will allow the monster to
915 * toggle between 2 skills. One day it would be nice to make
916 * more skills available to monsters.
917 */
918 for (skill = head->inv; skill; skill = skill->below)
919 if (skill->type == SKILL && skill != head->chosen_skill)
920 {
921 head->chosen_skill = skill;
922 break;
923 }
924
925 if (!skill && !head->chosen_skill)
926 {
927 LOG (llevDebug, "Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", &head->name, head->count);
928 CLEAR_FLAG (head, FLAG_READY_SKILL);
929 return 0;
930 }
931
932 /* use skill */
933 return do_skill (head, part, head->chosen_skill, dir, NULL);
934 }
935
936 /* Monster will use a ranged spell attack. */
937 int
938 monster_use_range (object *head, object *part, object *pl, int dir)
939 {
940 object *wand, *owner;
941 int at_least_one = 0;
942
943 if (!(dir = path_to_player (part, pl, 0)))
944 return 0;
945
946 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
947 {
948 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
949
950 if (dirdiff (dir, dir2) < 2)
951 return 0; /* Might hit owner with spell */
952 }
953
954 if (QUERY_FLAG (head, FLAG_CONFUSED))
955 dir = absdir (dir + rndm (3) + rndm (3) - 2);
956
957 for (wand = head->inv; wand; wand = wand->below)
958 {
959 if (wand->type == WAND)
960 {
961 /* Found a wand, let's see if it has charges left */
962 at_least_one = 1;
963 if (wand->stats.food <= 0)
964 continue;
965
966 cast_spell (head, wand, dir, wand->inv, NULL);
967
968 if (!(--wand->stats.food))
969 {
970 if (wand->arch)
971 {
972 CLEAR_FLAG (wand, FLAG_ANIMATE);
973 wand->face = wand->arch->face;
974 wand->set_speed (0);
975 }
976 }
977 /* Success */
978 return 1;
979 }
980 else if (wand->type == ROD || wand->type == HORN)
981 {
982 /* Found rod/horn, let's use it if possible */
983 at_least_one = 1;
984 if (wand->stats.hp < MAX (wand->inv->stats.sp, wand->inv->stats.grace))
985 continue;
986
987 /* drain charge before casting spell - can be a case where the
988 * spell destroys the monster, and rod, so if done after, results
989 * in crash.
990 */
991 drain_rod_charge (wand);
992 cast_spell (head, wand, dir, wand->inv, NULL);
993
994 /* Success */
995 return 1;
996 }
997 }
998
999 if (at_least_one)
1000 return 0;
1001
1002 LOG (llevError, "Error: Monster %s (%d) HAS_READY_RANGE() without wand/horn/rod.\n", &head->name, head->count);
1003 CLEAR_FLAG (head, FLAG_READY_RANGE);
1004 return 0;
1005 }
1006
1007 int
1008 monster_use_bow (object *head, object *part, object *pl, int dir)
1009 {
1010 object *owner;
1011
1012 if (!(dir = path_to_player (part, pl, 0)))
1013 return 0;
1014
1015 if (QUERY_FLAG (head, FLAG_CONFUSED))
1016 dir = absdir (dir + rndm (3) + rndm (3) - 2);
1017
1018 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
1019 {
1020 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
1021
1022 if (dirdiff (dir, dir2) < 1)
1023 return 0; /* Might hit owner with arrow */
1024 }
1025
1026 /* in server/player.c */
1027 return fire_bow (head, part, NULL, dir, 0, part->x, part->y);
1028
1029 }
1030
1031 /* Checks if putting on 'item' will make 'who' do more
1032 * damage. This is a very simplistic check - also checking things
1033 * like speed and ac are also relevant.
1034 *
1035 * return true if item is a better object.
1036 */
1037 int
1038 check_good_weapon (object *who, object *item)
1039 {
1040 object *other_weap;
1041 int val = 0, i;
1042
1043 for (other_weap = who->inv; other_weap; other_weap = other_weap->below)
1044 if (other_weap->type == item->type && QUERY_FLAG (other_weap, FLAG_APPLIED))
1045 break;
1046
1047 if (!other_weap) /* No other weapons */
1048 return 1;
1049
1050 /* Rather than go through and apply the new one, and see if it is
1051 * better, just do some simple checks
1052 * Put some multipliers for things that hvae several effects,
1053 * eg, magic affects both damage and wc, so it has more weight
1054 */
1055
1056 val = item->stats.dam - other_weap->stats.dam;
1057 val += (item->magic - other_weap->magic) * 3;
1058 /* Monsters don't really get benefits from things like regen rates
1059 * from items. But the bonus for their stats are very important.
1060 */
1061 for (i = 0; i < NUM_STATS; i++)
1062 val += item->stats.stat (i) - other_weap->stats.stat (i) * 2;
1063
1064 if (val > 0)
1065 return 1;
1066 else
1067 return 0;
1068 }
1069
1070 int
1071 check_good_armour (object *who, object *item)
1072 {
1073 object *other_armour;
1074 int val = 0, i;
1075
1076 for (other_armour = who->inv; other_armour; other_armour = other_armour->below)
1077 if (other_armour->type == item->type && QUERY_FLAG (other_armour, FLAG_APPLIED))
1078 break;
1079
1080 if (other_armour == NULL) /* No other armour, use the new */
1081 return 1;
1082
1083 /* Like above function , see which is better */
1084 val = item->stats.ac - other_armour->stats.ac;
1085 val = (item->resist[ATNR_PHYSICAL] - other_armour->resist[ATNR_PHYSICAL]) / 5;
1086 val += (item->magic - other_armour->magic) * 3;
1087
1088 /* for the other protections, do weigh them very much in the equation -
1089 * it is the armor protection which is most important, because there is
1090 * no good way to know what the player may attack the monster with.
1091 * So if the new item has better protection than the old, give that higher
1092 * value. If the reverse, then decrease the value of this item some.
1093 */
1094 for (i = 1; i < NROFATTACKS; i++)
1095 {
1096 if (item->resist[i] > other_armour->resist[i])
1097 val++;
1098 else if (item->resist[i] < other_armour->resist[i])
1099 val--;
1100 }
1101
1102 /* Very few armours have stats, so not much need to worry about those. */
1103
1104 if (val > 0)
1105 return 1;
1106 else
1107 return 0;
1108 }
1109
1110 /*
1111 * monster_check_pickup(): checks for items that monster can pick up.
1112 *
1113 * Vick's (vick@bern.docs.uu.se) fix 921030 for the sweeper blob.
1114 * Each time the blob passes over some treasure, it will
1115 * grab it a.s.a.p.
1116 *
1117 * Eneq(@csd.uu.se): This can now be defined in the archetypes, added code
1118 * to handle this.
1119 *
1120 * This function was seen be continueing looping at one point (tmp->below
1121 * became a recursive loop. It may be better to call monster_check_apply
1122 * after we pick everything up, since that function may call others which
1123 * affect stacking on this space.
1124 */
1125 void
1126 monster_check_pickup (object *monster)
1127 {
1128 object *tmp, *next;
1129
1130 for (tmp = monster->below; tmp != NULL; tmp = next)
1131 {
1132 next = tmp->below;
1133 if (monster_can_pick (monster, tmp))
1134 {
1135 tmp->remove ();
1136 tmp = insert_ob_in_ob (tmp, monster);
1137 (void) monster_check_apply (monster, tmp);
1138 }
1139 /* We could try to re-establish the cycling, of the space, but probably
1140 * not a big deal to just bail out.
1141 */
1142 if (next && next->destroyed ())
1143 return;
1144 }
1145 }
1146
1147 /*
1148 * monster_can_pick(): If the monster is interested in picking up
1149 * the item, then return 0. Otherwise 0.
1150 * Instead of pick_up, flags for "greed", etc, should be used.
1151 * I've already utilized flags for bows, wands, rings, etc, etc. -Frank.
1152 */
1153 int
1154 monster_can_pick (object *monster, object *item)
1155 {
1156 int flag = 0;
1157 int i;
1158
1159 if (!can_pick (monster, item))
1160 return 0;
1161
1162 if (QUERY_FLAG (item, FLAG_UNPAID))
1163 return 0;
1164
1165 if (monster->pick_up & 64) /* All */
1166 flag = 1;
1167
1168 else
1169 switch (item->type)
1170 {
1171 case MONEY:
1172 case GEM:
1173 flag = monster->pick_up & 2;
1174 break;
1175
1176 case FOOD:
1177 flag = monster->pick_up & 4;
1178 break;
1179
1180 case WEAPON:
1181 flag = (monster->pick_up & 8) || QUERY_FLAG (monster, FLAG_USE_WEAPON);
1182 break;
1183
1184 case ARMOUR:
1185 case SHIELD:
1186 case HELMET:
1187 case BOOTS:
1188 case GLOVES:
1189 case GIRDLE:
1190 flag = (monster->pick_up & 16) || QUERY_FLAG (monster, FLAG_USE_ARMOUR);
1191 break;
1192
1193 case SKILL:
1194 flag = QUERY_FLAG (monster, FLAG_CAN_USE_SKILL);
1195 break;
1196
1197 case RING:
1198 flag = QUERY_FLAG (monster, FLAG_USE_RING);
1199 break;
1200
1201 case WAND:
1202 case HORN:
1203 case ROD:
1204 flag = QUERY_FLAG (monster, FLAG_USE_RANGE);
1205 break;
1206
1207 case SPELLBOOK:
1208 flag = monster->arch && QUERY_FLAG (monster->arch, FLAG_CAST_SPELL);
1209 break;
1210
1211 case SCROLL:
1212 flag = QUERY_FLAG (monster, FLAG_USE_SCROLL);
1213 break;
1214
1215 case BOW:
1216 case ARROW:
1217 flag = QUERY_FLAG (monster, FLAG_USE_BOW);
1218 break;
1219 }
1220
1221 /* Simplistic check - if the monster has a location to equip it, he will
1222 * pick it up. Note that this doesn't handle cases where an item may
1223 * use several locations.
1224 */
1225 for (i = 0; i < NUM_BODY_LOCATIONS; i++)
1226 {
1227 if (monster->slot[i].info && item->slot[i].info)
1228 {
1229 flag = 1;
1230 break;
1231 }
1232 }
1233
1234 if (((!(monster->pick_up & 32)) && flag) || ((monster->pick_up & 32) && (!flag)))
1235 return 1;
1236 return 0;
1237 }
1238
1239 /*
1240 * monster_apply_below():
1241 * Vick's (vick@bern.docs.uu.se) @921107 -> If a monster who's
1242 * eager to apply things, encounters something apply-able,
1243 * then make him apply it
1244 */
1245 void
1246 monster_apply_below (object *monster)
1247 {
1248 object *tmp, *next;
1249
1250 for (tmp = monster->below; tmp != NULL; tmp = next)
1251 {
1252 next = tmp->below;
1253 switch (tmp->type)
1254 {
1255 case CF_HANDLE:
1256 case TRIGGER:
1257 if (monster->will_apply & 1)
1258 manual_apply (monster, tmp, 0);
1259 break;
1260
1261 case TREASURE:
1262 if (monster->will_apply & 2)
1263 manual_apply (monster, tmp, 0);
1264 break;
1265
1266 }
1267 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1268 break;
1269 }
1270 }
1271
1272 /*
1273 * monster_check_apply() is meant to be called after an item is
1274 * inserted in a monster.
1275 * If an item becomes outdated (monster found a better item),
1276 * a pointer to that object is returned, so it can be dropped.
1277 * (so that other monsters can pick it up and use it)
1278 * Note that as things are now, monsters never drop something -
1279 * they can pick up all that they can use.
1280 */
1281 /* Sept 96, fixed this so skills will be readied -b.t.*/
1282 void
1283 monster_check_apply (object *mon, object *item)
1284 {
1285 int flag = 0;
1286
1287 if (item->type == SPELLBOOK && mon->arch && (QUERY_FLAG (mon->arch, FLAG_CAST_SPELL)))
1288 {
1289 SET_FLAG (mon, FLAG_CAST_SPELL);
1290 return;
1291 }
1292
1293 /* If for some reason, this item is already applied, no more work to do */
1294 if (QUERY_FLAG (item, FLAG_APPLIED))
1295 return;
1296
1297 /* Might be better not to do this - if the monster can fire a bow,
1298 * it is possible in his wanderings, he will find one to use. In
1299 * which case, it would be nice to have ammo for it.
1300 */
1301 if (QUERY_FLAG (mon, FLAG_USE_BOW) && item->type == ARROW)
1302 {
1303 /* Check for the right kind of bow */
1304 object *bow;
1305
1306 for (bow = mon->inv; bow; bow = bow->below)
1307 if (bow->type == BOW && bow->race == item->race)
1308 {
1309 SET_FLAG (mon, FLAG_READY_BOW);
1310 LOG (llevMonster, "Found correct bow for arrows.\n");
1311 return; /* nothing more to do for arrows */
1312 }
1313 }
1314
1315 if (item->type == TREASURE && mon->will_apply & WILL_APPLY_TREASURE)
1316 flag = 1;
1317 /* Eating food gets hp back */
1318 else if (item->type == FOOD && mon->will_apply & WILL_APPLY_FOOD)
1319 flag = 1;
1320 else if (item->type == SCROLL && QUERY_FLAG (mon, FLAG_USE_SCROLL))
1321 {
1322 if (!item->inv)
1323 LOG (llevDebug, "Monster %d having scroll %d with empty inventory!", mon->count, item->count);
1324 else if (monster_should_cast_spell (mon, item->inv))
1325 SET_FLAG (mon, FLAG_READY_SCROLL);
1326 /* Don't use it right now */
1327 return;
1328 }
1329 else if (item->type == WEAPON)
1330 flag = check_good_weapon (mon, item);
1331 else if (item->is_armor ())
1332 flag = check_good_armour (mon, item);
1333 /* Should do something more, like make sure this is a better item */
1334 else if (item->type == RING)
1335 flag = 1;
1336 else if (item->type == WAND || item->type == ROD || item->type == HORN)
1337 {
1338 /* We never really 'ready' the wand/rod/horn, because that would mean the
1339 * weapon would get undone.
1340 */
1341 if (!(can_apply_object (mon, item) & CAN_APPLY_NOT_MASK))
1342 {
1343 SET_FLAG (mon, FLAG_READY_RANGE);
1344 SET_FLAG (item, FLAG_APPLIED);
1345 }
1346 return;
1347 }
1348 else if (item->type == BOW)
1349 {
1350 /* We never really 'ready' the bow, because that would mean the
1351 * weapon would get undone.
1352 */
1353 if (!(can_apply_object (mon, item) & CAN_APPLY_NOT_MASK))
1354 SET_FLAG (mon, FLAG_READY_BOW);
1355 return;
1356 }
1357 else if (item->type == SKILL)
1358 {
1359 /*
1360 * skills are specials: monsters must have the 'FLAG_READY_SKILL' flag set,
1361 * else they can't use the skill...
1362 * Skills also don't need to get applied, so return now.
1363 */
1364 SET_FLAG (mon, FLAG_READY_SKILL);
1365 return;
1366 }
1367
1368 /* if we don't match one of the above types, return now.
1369 * can_apply_object will say that we can apply things like flesh,
1370 * bolts, and whatever else, because it only checks against the
1371 * body_info locations.
1372 */
1373 if (!flag)
1374 return;
1375
1376 /* Check to see if the monster can use this item. If not, no need
1377 * to do further processing. Note that can_apply_object already checks
1378 * for the CAN_USE flags.
1379 */
1380 if (can_apply_object (mon, item) & CAN_APPLY_NOT_MASK)
1381 return;
1382
1383 /* should only be applying this item, not unapplying it.
1384 * also, ignore status of curse so they can take off old armour.
1385 * monsters have some advantages after all.
1386 */
1387 manual_apply (mon, item, AP_APPLY | AP_IGNORE_CURSE);
1388 }
1389
1390 void
1391 npc_call_help (object *op)
1392 {
1393 int x, y, mflags;
1394 object *npc;
1395 sint16 sx, sy;
1396 maptile *m;
1397
1398 for (x = -3; x < 4; x++)
1399 for (y = -3; y < 4; y++)
1400 {
1401 m = op->map;
1402 sx = op->x + x;
1403 sy = op->y + y;
1404 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
1405 /* If nothing alive on this space, no need to search the space. */
1406 if ((mflags & P_OUT_OF_MAP) || !(mflags & P_IS_ALIVE))
1407 continue;
1408
1409 for (npc = GET_MAP_OB (m, sx, sy); npc != NULL; npc = npc->above)
1410 if (QUERY_FLAG (npc, FLAG_ALIVE) && QUERY_FLAG (npc, FLAG_UNAGGRESSIVE))
1411 npc->enemy = op->enemy;
1412 }
1413 }
1414
1415 int
1416 dist_att (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1417 {
1418 if (can_hit (part, enemy, rv))
1419 return dir;
1420 if (rv->distance < 10)
1421 return absdir (dir + 4);
1422 else if (rv->distance > 18)
1423 return dir;
1424
1425 return 0;
1426 }
1427
1428 int
1429 run_att (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1430 {
1431 if ((can_hit (part, enemy, rv) && ob->move_status < 20) || ob->move_status < 20)
1432 {
1433 ob->move_status++;
1434 return (dir);
1435 }
1436 else if (ob->move_status > 20)
1437 ob->move_status = 0;
1438
1439 return absdir (dir + 4);
1440 }
1441
1442 int
1443 hitrun_att (int dir, object *ob, object *enemy)
1444 {
1445 if (ob->move_status++ < 25)
1446 return dir;
1447 else if (ob->move_status < 50)
1448 return absdir (dir + 4);
1449 else
1450 ob->move_status = 0;
1451
1452 return absdir (dir + 4);
1453 }
1454
1455 int
1456 wait_att (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1457 {
1458
1459 int inrange = can_hit (part, enemy, rv);
1460
1461 if (ob->move_status || inrange)
1462 ob->move_status++;
1463
1464 if (ob->move_status == 0)
1465 return 0;
1466 else if (ob->move_status < 10)
1467 return dir;
1468 else if (ob->move_status < 15)
1469 return absdir (dir + 4);
1470
1471 ob->move_status = 0;
1472 return 0;
1473 }
1474
1475 int
1476 disthit_att (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1477 {
1478
1479 /* The logic below here looked plain wrong before. Basically, what should
1480 * happen is that if the creatures hp percentage falls below run_away,
1481 * the creature should run away (dir+4)
1482 * I think its wrong for a creature to have a zero maxhp value, but
1483 * at least one map has this set, and whatever the map contains, the
1484 * server should try to be resilant enough to avoid the problem
1485 */
1486 if (ob->stats.maxhp && (ob->stats.hp * 100) / ob->stats.maxhp < ob->run_away)
1487 return absdir (dir + 4);
1488
1489 return dist_att (dir, ob, enemy, part, rv);
1490 }
1491
1492 int
1493 wait_att2 (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1494 {
1495 if (rv->distance < 9)
1496 return absdir (dir + 4);
1497
1498 return 0;
1499 }
1500
1501 void
1502 circ1_move (object *ob)
1503 {
1504 static int circle[12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 };
1505
1506 if (++ob->move_status > 11)
1507 ob->move_status = 0;
1508
1509 if (!(move_object (ob, circle[ob->move_status])))
1510 move_object (ob, rndm (8) + 1);
1511 }
1512
1513 void
1514 circ2_move (object *ob)
1515 {
1516 static int circle[20] = { 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 1, 1, 1, 2, 2 };
1517
1518 if (++ob->move_status > 19)
1519 ob->move_status = 0;
1520
1521 if (!(move_object (ob, circle[ob->move_status])))
1522 move_object (ob, rndm (8) + 1);
1523 }
1524
1525 void
1526 pace_movev (object *ob)
1527 {
1528 if (ob->move_status++ > 6)
1529 ob->move_status = 0;
1530
1531 if (ob->move_status < 4)
1532 move_object (ob, 5);
1533 else
1534 move_object (ob, 1);
1535 }
1536
1537 void
1538 pace_moveh (object *ob)
1539 {
1540 if (ob->move_status++ > 6)
1541 ob->move_status = 0;
1542
1543 if (ob->move_status < 4)
1544 move_object (ob, 3);
1545 else
1546 move_object (ob, 7);
1547 }
1548
1549 void
1550 pace2_movev (object *ob)
1551 {
1552 if (ob->move_status++ > 16)
1553 ob->move_status = 0;
1554
1555 if (ob->move_status < 6)
1556 move_object (ob, 5);
1557 else if (ob->move_status < 8)
1558 return;
1559 else if (ob->move_status < 13)
1560 move_object (ob, 1);
1561 else
1562 return;
1563 }
1564
1565 void
1566 pace2_moveh (object *ob)
1567 {
1568 if (ob->move_status++ > 16)
1569 ob->move_status = 0;
1570
1571 if (ob->move_status < 6)
1572 move_object (ob, 3);
1573 else if (ob->move_status < 8)
1574 return;
1575 else if (ob->move_status < 13)
1576 move_object (ob, 7);
1577 else
1578 return;
1579 }
1580
1581 void
1582 rand_move (object *ob)
1583 {
1584 int i;
1585
1586 if (ob->move_status < 1 || ob->move_status > 8 || !(move_object (ob, ob->move_status || !(rndm (9)))))
1587 for (i = 0; i < 5; i++)
1588 if (move_object (ob, ob->move_status = rndm (8) + 1))
1589 return;
1590 }
1591
1592 void
1593 check_earthwalls (object *op, maptile *m, int x, int y)
1594 {
1595 object *tmp;
1596
1597 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
1598 {
1599 if (tmp->type == EARTHWALL)
1600 {
1601 hit_player (tmp, op->stats.dam, op, AT_PHYSICAL, 1);
1602 return;
1603 }
1604 }
1605 }
1606
1607 void
1608 check_doors (object *op, maptile *m, int x, int y)
1609 {
1610 object *tmp;
1611
1612 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
1613 {
1614 if (tmp->type == DOOR)
1615 {
1616 hit_player (tmp, 1000, op, AT_PHYSICAL, 1);
1617 return;
1618 }
1619 }
1620 }
1621
1622 /* find_mon_throw_ob() - modeled on find_throw_ob
1623 * This is probably overly simplistic as it is now - We want
1624 * monsters to throw things like chairs and other pieces of
1625 * furniture, even if they are not good throwable objects.
1626 * Probably better to have the monster throw a throwable object
1627 * first, then throw any non equipped weapon.
1628 */
1629 object *
1630 find_mon_throw_ob (object *op)
1631 {
1632 object *tmp = NULL;
1633
1634 if (op->head)
1635 tmp = op->head;
1636 else
1637 tmp = op;
1638
1639 /* New throw code: look through the inventory. Grap the first legal is_thrown
1640 * marked item and throw it to the enemy.
1641 */
1642 for (tmp = op->inv; tmp; tmp = tmp->below)
1643 {
1644 /* Can't throw invisible objects or items that are applied */
1645 if (tmp->invisible || QUERY_FLAG (tmp, FLAG_APPLIED))
1646 continue;
1647
1648 if (QUERY_FLAG (tmp, FLAG_IS_THROWN))
1649 break;
1650
1651 }
1652
1653 #ifdef DEBUG_THROW
1654 LOG (llevDebug, "%s chooses to throw: %s (%d)\n", op->name, !(tmp) ? "(nothing)" : query_name (tmp), tmp ? tmp->count : -1);
1655 #endif
1656
1657 return tmp;
1658 }
1659
1660 /* determine if we can 'detect' the enemy. Check for walls blocking the
1661 * los. Also, just because its hidden/invisible, we may be sensitive/smart
1662 * enough (based on Wis & Int) to figure out where the enemy is. -b.t.
1663 * modified by MSW to use the get_rangevector so that map tiling works
1664 * properly. I also so odd code in place that checked for x distance
1665 * OR y distance being within some range - that seemed wrong - both should
1666 * be within the valid range. MSW 2001-08-05
1667 * Returns 0 if enemy can not be detected, 1 if it is detected
1668 */
1669
1670 int
1671 can_detect_enemy (object *op, object *enemy, rv_vector * rv)
1672 {
1673 int radius = MIN_MON_RADIUS, hide_discovery;
1674
1675 /* null detection for any of these condtions always */
1676 if (!op || !enemy || !op->map || !enemy->map)
1677 return 0;
1678
1679 /* If the monster (op) has no way to get to the enemy, do nothing */
1680 if (!on_same_map (op, enemy))
1681 return 0;
1682
1683 get_rangevector (op, enemy, rv, 0);
1684
1685 /* Monsters always ignore the DM */
1686 if ((op->type != PLAYER) && QUERY_FLAG (enemy, FLAG_WIZ))
1687 return 0;
1688
1689 /* simple check. Should probably put some range checks in here. */
1690 if (can_see_enemy (op, enemy))
1691 return 1;
1692
1693 /* The rest of this is for monsters. Players are on their own for
1694 * finding enemies!
1695 */
1696 if (op->type == PLAYER)
1697 return 0;
1698
1699 /* Quality invisible? Bah, we wont see them w/o SEE_INVISIBLE
1700 * flag (which was already checked) in can_see_enmy (). Lets get out of here
1701 */
1702 if (enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden)))
1703 return 0;
1704
1705 /* use this for invis also */
1706 hide_discovery = op->stats.Int / 5;
1707
1708 /* Determine Detection radii */
1709 if (!enemy->hide) /* to detect non-hidden (eg dark/invis enemy) */
1710 radius = (op->stats.Wis / 5) + 1 > MIN_MON_RADIUS ? (op->stats.Wis / 5) + 1 : MIN_MON_RADIUS;
1711 else
1712 { /* a level/INT/Dex adjustment for hiding */
1713 object *sk_hide;
1714 int bonus = (op->level / 2) + (op->stats.Int / 5);
1715
1716 if (enemy->type == PLAYER)
1717 {
1718 if ((sk_hide = find_skill_by_number (enemy, SK_HIDING)))
1719 bonus -= sk_hide->level;
1720 else
1721 {
1722 LOG (llevError, "can_detect_enemy() got hidden player w/o hiding skill!\n");
1723 make_visible (enemy);
1724 radius = radius < MIN_MON_RADIUS ? MIN_MON_RADIUS : radius;
1725 }
1726 }
1727 else /* enemy is not a player */
1728 bonus -= enemy->level;
1729
1730 radius += bonus / 5;
1731 hide_discovery += bonus * 5;
1732 } /* else creature has modifiers for hiding */
1733
1734 /* Radii stealth adjustment. Only if you are stealthy
1735 * will you be able to sneak up closer to creatures */
1736 if (QUERY_FLAG (enemy, FLAG_STEALTH))
1737 radius = radius / 2, hide_discovery = hide_discovery / 3;
1738
1739 /* Radii adjustment for enemy standing in the dark */
1740 if (op->map->darkness > 0 && !stand_in_light (enemy))
1741 {
1742 /* on dark maps body heat can help indicate location with infravision
1743 * undead don't have body heat, so no benefit detecting them.
1744 */
1745 if (QUERY_FLAG (op, FLAG_SEE_IN_DARK) && !is_true_undead (enemy))
1746 radius += op->map->darkness / 2;
1747 else
1748 radius -= op->map->darkness / 2;
1749
1750 /* op next to a monster (and not in complete darkness)
1751 * the monster should have a chance to see you.
1752 */
1753 if (radius < MIN_MON_RADIUS && op->map->darkness < 5 && rv->distance <= 1)
1754 radius = MIN_MON_RADIUS;
1755 } /* if on dark map */
1756
1757 /* Lets not worry about monsters that have incredible detection
1758 * radii, we only need to worry here about things the player can
1759 * (potentially) see. This is 13, as that is the maximum size the player
1760 * may have for their map - in that way, creatures at the edge will
1761 * do something. Note that the distance field in the
1762 * vector is real distance, so in theory this should be 18 to
1763 * find that.
1764 */
1765 if (radius > 13)
1766 radius = 13;
1767
1768 /* Enemy in range! Now test for detection */
1769 if ((int) rv->distance <= radius)
1770 {
1771 /* ah, we are within range, detected? take cases */
1772 if (!enemy->invisible) /* enemy in dark squares... are seen! */
1773 return 1;
1774
1775 /* hidden or low-quality invisible */
1776 if (enemy->hide && (rv->distance <= 1) && (rndm (100) <= hide_discovery))
1777 {
1778 make_visible (enemy);
1779 /* inform players of new status */
1780 if (enemy->type == PLAYER && player_can_view (enemy, op))
1781 new_draw_info_format (NDI_UNIQUE, 0, enemy, "You are discovered by %s!", &op->name);
1782 return 1; /* detected enemy */
1783 }
1784 else if (enemy->invisible)
1785 {
1786 /* Change this around - instead of negating the invisible, just
1787 * return true so that the mosnter that managed to detect you can
1788 * do something to you. Decreasing the duration of invisible
1789 * doesn't make a lot of sense IMO, as a bunch of stupid creatures
1790 * can then basically negate the spell. The spell isn't negated -
1791 * they just know where you are!
1792 */
1793 if ((rndm (50)) <= hide_discovery)
1794 {
1795 if (enemy->type == PLAYER)
1796 {
1797 new_draw_info_format (NDI_UNIQUE, 0, enemy, "You see %s noticing your position.", query_name (op));
1798 }
1799 return 1;
1800 }
1801 }
1802 } /* within range */
1803
1804 /* Wasn't detected above, so still hidden */
1805 return 0;
1806 }
1807
1808 /* determine if op stands in a lighted square. This is not a very
1809 * intellegent algorithm. For one thing, we ignore los here, SO it
1810 * is possible for a bright light to illuminate a player on the
1811 * other side of a wall (!).
1812 */
1813 int
1814 stand_in_light (object *op)
1815 {
1816 sint16 nx, ny;
1817 maptile *m;
1818
1819 if (!op)
1820 return 0;
1821
1822 if (op->glow_radius > 0)
1823 return 1;
1824
1825 if (op->map)
1826 {
1827 int x, y, x1, y1;
1828
1829 /* Check the spaces with the max light radius to see if any of them
1830 * have lights, and if any of them light the player enough, then return 1.
1831 */
1832 for (x = op->x - MAX_LIGHT_RADII; x <= op->x + MAX_LIGHT_RADII; x++)
1833 {
1834 for (y = op->y - MAX_LIGHT_RADII; y <= op->y + MAX_LIGHT_RADII; y++)
1835 {
1836 m = op->map;
1837 nx = x;
1838 ny = y;
1839
1840 if (get_map_flags (m, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP)
1841 continue;
1842
1843 x1 = abs (x - op->x) * abs (x - op->x);
1844 y1 = abs (y - op->y) * abs (y - op->y);
1845 if (isqrt (x1 + y1) < GET_MAP_LIGHT (m, nx, ny))
1846 return 1;
1847 }
1848 }
1849 }
1850
1851 return 0;
1852 }
1853
1854 /* assuming no walls/barriers, lets check to see if its *possible*
1855 * to see an enemy. Note, "detection" is different from "seeing".
1856 * See can_detect_enemy() for more details. -b.t.
1857 * return 0 if can't be seen, 1 if can be
1858 */
1859 int
1860 can_see_enemy (object *op, object *enemy)
1861 {
1862 object *looker = op->head ? op->head : op;
1863
1864 /* safety */
1865 if (!looker || !enemy || !QUERY_FLAG (looker, FLAG_ALIVE))
1866 return 0;
1867
1868 /* we dont give a full treatment of xrays here (shorter range than normal,
1869 * see through walls). Should we change the code elsewhere to make you
1870 * blind even if you can xray?
1871 */
1872 if (QUERY_FLAG (looker, FLAG_BLIND) && !QUERY_FLAG (looker, FLAG_XRAYS))
1873 return 0;
1874
1875 /* checking for invisible things */
1876 if (enemy->invisible)
1877 {
1878 /* HIDDEN ENEMY. by definition, you can't see hidden stuff!
1879 * However,if you carry any source of light, then the hidden
1880 * creature is seeable (and stupid) */
1881
1882 if (has_carried_lights (enemy))
1883 {
1884 if (enemy->hide)
1885 {
1886 make_visible (enemy);
1887 new_draw_info (NDI_UNIQUE, 0, enemy, "Your light reveals your hiding spot!");
1888 }
1889 return 1;
1890 }
1891 else if (enemy->hide)
1892 return 0;
1893
1894 /* Invisible enemy. Break apart the check for invis undead/invis looker
1895 * into more simple checks - the QUERY_FLAG doesn't return 1/0 values,
1896 * and making it a conditional makes the code pretty ugly.
1897 */
1898 if (!QUERY_FLAG (looker, FLAG_SEE_INVISIBLE))
1899 {
1900 if (makes_invisible_to (enemy, looker))
1901 return 0;
1902 }
1903 }
1904 else if (looker->type == PLAYER) /* for players, a (possible) shortcut */
1905 if (player_can_view (looker, enemy))
1906 return 1;
1907
1908 /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen
1909 * unless they carry a light or stand in light. Darkness doesnt
1910 * inhibit the undead per se (but we should give their archs
1911 * CAN_SEE_IN_DARK, this is just a safety
1912 * we care about the enemy maps status, not the looker.
1913 * only relevant for tiled maps, but it is possible that the
1914 * enemy is on a bright map and the looker on a dark - in that
1915 * case, the looker can still see the enemy
1916 */
1917 if (enemy->map->darkness > 0 && !stand_in_light (enemy)
1918 && (!QUERY_FLAG (looker, FLAG_SEE_IN_DARK) || !is_true_undead (looker) || !QUERY_FLAG (looker, FLAG_XRAYS)))
1919 return 0;
1920
1921 return 1;
1922 }