Crossfire Server, Trunk  R21078
monster.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
20 #include "global.h"
21 
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "skills.h"
27 #include "spells.h"
28 #include "sproto.h"
29 
30 static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv);
31 static int monster_cast_spell(object *head, object *part, object *pl, int dir);
32 static int monster_use_scroll(object *head, object *part, object *pl, int dir);
33 static int monster_use_skill(object *head, object *part, object *pl, int dir);
34 static int monster_use_range(object *head, object *part, object *pl, int dir);
35 static int monster_use_bow(object *head, object *part, object *pl, int dir);
36 static void monster_check_pickup(object *monster);
37 static int monster_can_pick(object *monster, object *item);
38 static void monster_apply_below(object *monster);
39 static int monster_dist_att(int dir, object *enemy, object *part, rv_vector *rv);
40 static int monster_run_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv);
41 static int monster_hitrun_att(int dir, object *ob, object *enemy);
42 static int monster_wait_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv);
43 static int monster_disthit_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv);
44 static int monster_wait_att2(int dir, rv_vector *rv);
45 static void monster_circ1_move(object *ob);
46 static void monster_circ2_move(object *ob);
47 static void monster_pace_movev(object *ob);
48 static void monster_pace_moveh(object *ob);
49 static void monster_pace2_movev(object *ob);
50 static void monster_pace2_moveh(object *ob);
51 static void monster_rand_move(object *ob);
52 static int monster_talk_to_npc(object *npc, talk_info *info);
53 
55 #define MIN_MON_RADIUS 3
56 
71 object *monster_check_enemy(object *npc, rv_vector *rv) {
72  object *owner;
73 
74  /* if this is pet, let him attack the same enemy as his owner
75  * TODO: when there is no ower enemy, try to find a target,
76  * which CAN attack the owner. */
77  owner = object_get_owner(npc);
78  if ((npc->attack_movement&HI4) == PETMOVE) {
79  if (owner == NULL)
80  object_set_enemy(npc, NULL);
81  else if (npc->enemy == NULL)
82  object_set_enemy(npc, owner->enemy);
83  }
84 
85  /* periodically, a monster may change its target. Also, if the object
86  * has been destroyed, etc, clear the enemy.
87  * TODO: this should be changed, because it invokes to attack forced or
88  * attacked monsters to leave the attacker alone, before it is destroyed
89  */
90  /* i had removed the random target leave, this invokes problems with friendly
91  * objects, getting attacked and defending herself - they don't try to attack
92  * again then but perhaps get attack on and on
93  * If we include a aggravated flag in , we can handle evil vs evil and good vs good
94  * too. */
95 
96  if (npc->enemy) {
97  /* I broke these if's apart to better be able to see what
98  * the grouping checks are. Code is the same.
99  */
100  if (QUERY_FLAG(npc->enemy, FLAG_REMOVED)
101  || QUERY_FLAG(npc->enemy, FLAG_FREED)
102  || !on_same_map(npc, npc->enemy)
103  || npc == npc->enemy
104  || QUERY_FLAG(npc, FLAG_NEUTRAL)
105  || QUERY_FLAG(npc->enemy, FLAG_NEUTRAL))
106  object_set_enemy(npc, NULL);
107 
108  else if (QUERY_FLAG(npc, FLAG_FRIENDLY) && (
109  (QUERY_FLAG(npc->enemy, FLAG_FRIENDLY) && !pets_should_arena_attack(npc, owner, npc->enemy))
110  || (npc->enemy->type == PLAYER && !pets_should_arena_attack(npc, owner, npc->enemy))
111  || npc->enemy == owner))
112  object_set_enemy(npc, NULL);
113  else if (!QUERY_FLAG(npc, FLAG_FRIENDLY)
114  && (!QUERY_FLAG(npc->enemy, FLAG_FRIENDLY) && npc->enemy->type != PLAYER))
115  object_set_enemy(npc, NULL);
116 
117  /* I've noticed that pets could sometimes get an arrow as the
118  * target enemy - this code below makes sure the enemy is something
119  * that should be attacked. My guess is that the arrow hits
120  * the creature/owner, and so the creature then takes that
121  * as the enemy to attack.
122  */
123  else if (!QUERY_FLAG(npc->enemy, FLAG_MONSTER)
124  && !QUERY_FLAG(npc->enemy, FLAG_GENERATOR)
125  && npc->enemy->type != PLAYER
126  && npc->enemy->type != GOLEM)
127  object_set_enemy(npc, NULL);
128  }
129  return monster_can_detect_enemy(npc, npc->enemy, rv) ? npc->enemy : NULL;
130 }
131 
153  int i, mflags;
154  int16_t nx, ny;
155  mapstruct *m;
156  int search_arr[SIZEOFFREE];
157 
158  get_search_arr(search_arr);
159  for (i = 0; i < SIZEOFFREE; i++) {
160  /* modified to implement smart searching using search_arr
161  * guidance array to determine direction of search order
162  */
163  nx = npc->x+freearr_x[search_arr[i]];
164  ny = npc->y+freearr_y[search_arr[i]];
165  m = npc->map;
166 
167  mflags = get_map_flags(m, &m, nx, ny, &nx, &ny);
168  if (mflags&P_OUT_OF_MAP)
169  continue;
170 
171  if (mflags&P_IS_ALIVE) {
172  object *creature;
173 
174  creature = NULL;
175  FOR_MAP_PREPARE(m, nx, ny, tmp)
176  if (QUERY_FLAG(tmp, FLAG_MONSTER)
177  || QUERY_FLAG(tmp, FLAG_GENERATOR)
178  || tmp->type == PLAYER) {
179  creature = tmp;
180  break;
181  }
182  FOR_MAP_FINISH();
183  if (!creature) {
184  LOG(llevDebug, "monster_find_nearest_living_creature: map %s (%d,%d) has is_alive set but did not find a monster?\n", m->path, nx, ny);
185  } else {
186  if (can_see_monsterP(m, nx, ny, i))
187  return creature;
188  }
189  } /* is something living on this space */
190  }
191  return NULL; /* nothing found */
192 }
193 
209 static object *monster_find_enemy(object *npc, rv_vector *rv) {
210  object *attacker, *tmp = NULL;
211 
212  attacker = npc->attacked_by; /* save this for later use. This can be a attacker. */
213  npc->attacked_by = NULL; /* always clear the attacker entry */
214 
215  /* if we berserk, we don't care about others - we attack all we can find */
216  if (QUERY_FLAG(npc, FLAG_BERSERK)) {
218  if (tmp == NULL)
219  return NULL;
220  if (!get_rangevector(npc, tmp, rv, 0))
221  return NULL;
222  return tmp;
223  }
224 
225  /* Here is the main enemy selection.
226  * We want this: if there is an enemy, attack him until its not possible or
227  * one of both is dead.
228  * If we have no enemy and we are...
229  * a monster: try to find a player, a pet or a friendly monster
230  * a friendly: only target a monster which is targeting you first or targeting a player
231  * a neutral: fight a attacker (but there should be none), then do nothing
232  * a pet: attack player enemy or a monster
233  */
234 
235  /* pet move */
236  if ((npc->attack_movement&HI4) == PETMOVE) {
237  tmp = pets_get_enemy(npc, rv);
238  if (tmp == NULL)
239  return NULL;
240  if (!get_rangevector(npc, tmp, rv, 0))
241  return NULL;
242  return tmp;
243  }
244 
245  /* we check our old enemy. */
246  tmp = monster_check_enemy(npc, rv);
247  if (tmp == NULL) {
248  if (attacker) { /* if we have an attacker, check him */
249  /* we want be sure this is the right one! */
250  if (attacker->count == npc->attacked_by_count) {
251  /* TODO: thats not finished */
252  /* we don't want a fight evil vs evil or good against non evil */
253  if (QUERY_FLAG(npc, FLAG_NEUTRAL)
254  || QUERY_FLAG(attacker, FLAG_NEUTRAL) /* neutral */
255  || (QUERY_FLAG(npc, FLAG_FRIENDLY) && QUERY_FLAG(attacker, FLAG_FRIENDLY))
256  || (!QUERY_FLAG(npc, FLAG_FRIENDLY) && (!QUERY_FLAG(attacker, FLAG_FRIENDLY) && attacker->type != PLAYER)))
257  CLEAR_FLAG(npc, FLAG_SLEEP); /* skip it, but lets wakeup */
258  else if (on_same_map(npc, attacker)) { /* thats the only thing we must know... */
259  CLEAR_FLAG(npc, FLAG_SLEEP); /* well, NOW we really should wake up! */
260  object_set_enemy(npc, attacker);
261  if (!get_rangevector(npc, attacker, rv, 0))
262  return NULL;
263  return attacker; /* yes, we face our attacker! */
264  }
265  }
266  }
267 
268  /* we have no legal enemy or attacker, so we try to target a new one */
269  if (!QUERY_FLAG(npc, FLAG_UNAGGRESSIVE)
270  && !QUERY_FLAG(npc, FLAG_FRIENDLY)
271  && !QUERY_FLAG(npc, FLAG_NEUTRAL)) {
273  if (npc->enemy)
274  tmp = monster_check_enemy(npc, rv);
275  }
276  }
277 
278  return tmp;
279 }
280 
296 static int monster_check_wakeup(object *op, object *enemy, rv_vector *rv) {
297  int radius = MAX(op->stats.Wis, MIN_MON_RADIUS);
298 
299  /* Trim work - if no enemy, no need to do anything below */
300  if (!enemy)
301  return 0;
302 
303  /* blinded monsters can only find nearby objects to attack */
304  if (QUERY_FLAG(op, FLAG_BLIND))
305  radius = MIN_MON_RADIUS;
306 
307  /* This covers the situation where the monster is in the dark
308  * and has an enemy. If the enemy has no carried light (or isnt
309  * glowing!) then the monster has trouble finding the enemy.
310  * Remember we already checked to see if the monster can see in
311  * the dark. */
312  else if (op->map
313  && op->map->darkness > 0
314  && enemy
315  && !enemy->invisible
316  && !monster_stand_in_light(enemy)
318  int dark = radius/(op->map->darkness);
319 
320  radius = (dark > MIN_MON_RADIUS) ? (dark+1) : MIN_MON_RADIUS;
321  } else if (!QUERY_FLAG(op, FLAG_SLEEP))
322  return 1;
323 
324  /* enemy should already be on this map, so don't really need to check
325  * for that.
326  */
327  if (rv->distance < (unsigned)(QUERY_FLAG(enemy, FLAG_STEALTH) ? radius/2+1 : radius)) {
328  CLEAR_FLAG(op, FLAG_SLEEP);
329  return 1;
330  }
331  return 0;
332 }
333 
342 static int monster_move_randomly(object *op) {
343  int i;
344  sstring talked;
345  char value[2];
346 
347  /* timeout before moving */
348  if (QUERY_FLAG(op, FLAG_UNAGGRESSIVE)) {
349  talked = object_get_value(op, "talked_to");
350  if (talked && strlen(talked) > 0) {
351  i = atoi(talked);
352  i--;
353 
354  if (i != 0) {
355  value[1] = '\0';
356  value[0] = '0' + i;
357  object_set_value(op, "talked_to", value, 1);
358  return 1;
359  }
360 
361  /* finished timeout talked to */
362  object_set_value(op, "talked_to", "", 1);
363  }
364  }
365 
366  /* Give up to 15 chances for a monster to move randomly */
367  for (i = 0; i < 15; i++) {
368  if (move_object(op, RANDOM()%8+1))
369  return 1;
370  }
371  return 0;
372 }
373 
375 #define MAX_EXPLORE 5000
376 
393 int monster_compute_path(object *source, object *target, int default_dir) {
394  unsigned short *distance;
395  int explore_x[MAX_EXPLORE], explore_y[MAX_EXPLORE], dirs[8];
396  int current = 0, dir, max = 1, x, y, i;
397 
398  if (target->map != source->map)
399  return default_dir;
400 
401  // These shouldn't change during the calculation, so store them once to avoid dereferencing.
402  mapstruct * cur_map = source->map; // Not constant to silence some warnings.
403  const uint16_t map_height = cur_map->height;
404  /*printf("monster_compute_path (%d, %d) => (%d, %d)\n", source->x, source->y, target->x, target->y);*/
405 
406  // Leave width like this because it is used just this once.
407  const int size = cur_map->width * map_height;
408 
419  if (!source->more) // Skip multitile monsters, since this does not work right for them
420  {
421  dir = -1; // Set a sentinel. -1 = no escape, 0 = many ways out, [1, 8] = one way out in dir
422  for (i = 1; i <= 8; ++i)
423  {
424  x = source->x + freearr_x[i];
425  y = source->y + freearr_y[i];
426  if (OUT_OF_REAL_MAP(cur_map, x, y))
427  continue;
428  if (ob_blocked(source, cur_map, x, y))
429  continue;
430  // We have a way out. Make note of it
431  if (dir < 0)
432  dir = i;
433  // We have many ways out -- do the pathing part of the function
434  else
435  {
436  dir = 0;
437  break;
438  }
439  }
440  // If dir > 0, we have our direction to go, as it is our only choice.
441  if (dir > 0)
442  return dir;
443  // If dir < 0, then we have no way to go. Return default_dir.
444  if (dir < 0)
445  return default_dir;
446  }
447 
448  /* We are setting all the values manually anyway,
449  * so there's no reason to use calloc().
450  * malloc() is more efficient here for that reason.
451  */
452  distance = malloc(size * sizeof(*distance));
453  if (distance == NULL) {
455  }
456  /*
457  * 999 seems to be an arbitrary intializer.
458  * 65535 can be set more efficiently.
459  *
460  for (dir = 0; dir < size; ++dir) {
461  distance[dir] = 999;
462  }
463  *
464  * To set to 65535 efficiently, though, I need to memset each byte to 255.
465  * each element is two bytes,
466  */
467  memset(distance, 255, sizeof(*distance) * size);
468 
469  distance[map_height * target->x + target->y] = 0;
470  explore_x[0] = target->x;
471  explore_y[0] = target->y;
472 
473  /* The first time through, current = 0 and max = 1.
474  * This will evaluate to true, so we might as well use a do-while loop.
475  */
476  do {
477  /* Fisher–Yates shuffle the directions, "inside-out" algorithm
478  * from http://en.wikipedia.org/wiki/Fisher-Yates_shuffle */
479  dirs[0] = 1;
480  for (i = 1; i < 8; ++i) {
481  x = RANDOM() % (i+1);
482  dirs[i] = dirs[x];
483  dirs[x] = i+1;
484  }
485 
486  for (i = 0; i < 8; ++i) {
487  unsigned short new_distance;
488 
489  /*
490  * dirs[i] is the direction we wish to check.
491  */
492  dir = absdir(default_dir+4+dirs[i]);
493  x = explore_x[current]+freearr_x[dir];
494  y = explore_y[current]+freearr_y[dir];
495 
496  if (x == source->x && y == source->y) {
497  free(distance);
498  return absdir(dir+4);
499  }
500 
501  if (OUT_OF_REAL_MAP(cur_map, x, y))
502  continue;
503 
504  // Move these up, so we can reduce calls to ob_blocked with their info.
505  assert(map_height * x + y >= 0);
506  assert(map_height * x + y < size);
507 
508  new_distance =
509  distance[map_height * explore_x[current] + explore_y[current]]
510  /* Mod 2 is equivalent to checking only the 1's bit (1 or 0), but & 1 is faster.
511  * Also, dir & 1 == 0 is true if we have a diagonal dir.
512  */
513  + ((dir & 1) == 0 ? 3 : 2);
514 
515  // If already known blocked or arrivable in less distance, we skip
516  if (distance[map_height * x + y] <= new_distance)
517  continue;
518  // If we have a non-default value here, we will have lready done ob_blocked on it.
519  // So, only call ob_blocked if we are staring at 65535.
520  // If we are not looking at an untested space, then we will skip this block and avoid ob_blocked
521  if (distance[map_height * x + y] == 65535 && ob_blocked(source, cur_map, x, y))
522  {
523  // Mark as something we can't otherwise get -- the goal is to cache what spaces are blocked.
524  // At least, this call to monster_compute_path will remember this spot is blocked.
525  // This should cut our calls to ob_blocked some.
526  distance[map_height * x + y] = 1;
527  // The value of 1 also allows for walls to be considered already checked, but since we do not add to the
528  // explore array, this makes them hit the condition above if they are checked again without going through walls.
529  continue;
530  }
531 
532  /*LOG(llevDebug, "check %d, %d dist = %d, nd = %d\n", x, y, distance[source->map->height*x+y], new_distance);*/
533 
534  /* This condition is now always true, since we bail before we get here if this is false.
535  if (distance[map_height * x + y] > new_distance) {
536  */
537  assert(max < MAX_EXPLORE);
538  explore_x[max] = x;
539  explore_y[max] = y;
540 
541  distance[map_height * x + y] = new_distance;
542  /* printf("explore[%d] => (%d, %d) %u\n", max, x, y, new_distance);*/
543  ++max;
544  if (max == MAX_EXPLORE) {
545  free(distance);
546  return default_dir;
547  }
548  //}
549  }
550  ++current;
551  } while (current < max);
552 
553  /*LOG(llevDebug, "no path\n");*/
554  free(distance);
555  return default_dir;
556 }
557 
564 void monster_do_living(object *op) {
565  assert(op);
566  assert(QUERY_FLAG(op, FLAG_MONSTER));
567 
568  /* generate hp, if applicable */
569  if (op->stats.Con > 0 && op->stats.hp < op->stats.maxhp) {
570  /* last heal is in funny units. Dividing by speed puts
571  * the regeneration rate on a basis of time instead of
572  * #moves the monster makes. The scaling by 8 is
573  * to capture 8th's of a hp fraction regens
574  *
575  * Cast to int32_t before comparing to maxhp since otherwise an (int16_t)
576  * overflow might produce monsters with negative hp.
577  */
578 
579  op->last_heal += (int)((float)(8*op->stats.Con)/FABS(op->speed));
580  op->stats.hp = MIN((int32_t)op->stats.hp+op->last_heal/32, op->stats.maxhp); /* causes Con/4 hp/tick */
581  op->last_heal %= 32;
582 
583  /* So if the monster has gained enough HP that they are no longer afraid */
584  if (QUERY_FLAG(op, FLAG_RUN_AWAY)
585  && op->stats.hp >= (int16_t)((int32_t)op->run_away * op->stats.maxhp / 100))
587  /*
588  * This should already be covered by the MIN() check above.
589 
590  if (op->stats.hp > op->stats.maxhp)
591  op->stats.hp = op->stats.maxhp;
592  */
593  }
594 
595  /* generate sp, if applicable */
596  if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp) {
597  /* last_sp is in funny units. Dividing by speed puts
598  * the regeneration rate on a basis of time instead of
599  * #moves the monster makes. The scaling by 8 is
600  * to capture 8th's of a sp fraction regens
601  *
602  * Cast to int32_t before comparing to maxhp since otherwise an (int16_t)
603  * overflow might produce monsters with negative sp.
604  */
605 
606  op->last_sp += (int)((float)(8*op->stats.Pow)/FABS(op->speed));
607  op->stats.sp = MIN(op->stats.sp+op->last_sp/128, op->stats.maxsp); /* causes Pow/16 sp/tick */
608  op->last_sp %= 128;
609  }
610 
611  /* this should probably get modified by many more values.
612  * (eg, creatures resistance to fear, level, etc. )
613  */
614  if (QUERY_FLAG(op, FLAG_SCARED) && !(RANDOM()%20)) {
615  CLEAR_FLAG(op, FLAG_SCARED); /* Time to regain some "guts"... */
616  }
617 }
618 
627 static int monster_move_no_enemy(object *op) {
628  assert(QUERY_FLAG(op, FLAG_MONSTER));
629 
630  if (QUERY_FLAG(op, FLAG_ONLY_ATTACK)) {
631  object_remove(op);
633  return 1;
634  }
635 
636  /* Probably really a bug for a creature to have both
637  * stand still and a movement type set.
638  */
639  if (!QUERY_FLAG(op, FLAG_STAND_STILL)) {
640  if (op->attack_movement&HI4) {
641  switch (op->attack_movement&HI4) {
642  case PETMOVE:
643  pets_move(op);
644  break;
645 
646  case CIRCLE1:
647  monster_circ1_move(op);
648  break;
649 
650  case CIRCLE2:
651  monster_circ2_move(op);
652  break;
653 
654  case PACEV:
655  monster_pace_movev(op);
656  break;
657 
658  case PACEH:
659  monster_pace_moveh(op);
660  break;
661 
662  case PACEV2:
664  break;
665 
666  case PACEH2:
668  break;
669 
670  case RANDO:
671  monster_rand_move(op);
672  break;
673 
674  case RANDO2:
676  break;
677  }
678  return 0;
679  }
680 
681  if (QUERY_FLAG(op, FLAG_RANDOM_MOVE))
683  } /* stand still */
684 
685  return 0;
686 }
687 
699 int monster_move(object *op) {
700  int dir, diff;
701  object *owner, *enemy, *part;
702  rv_vector rv;
703 
704  /* Monsters not on maps don't do anything. These monsters are things
705  * Like royal guards in city dwellers inventories.
706  */
707  if (!op->map)
708  return 0;
709 
710  if (QUERY_FLAG(op, FLAG_NO_ATTACK)) { /* we never ever attack */
711  object_set_enemy(op, NULL);
712  enemy = NULL;
713  } else {
714  enemy = monster_find_enemy(op, &rv);
715  if (enemy != NULL) {
716  /* we have an enemy, just tell him we want him dead */
717  enemy->attacked_by = op; /* our ptr */
718  enemy->attacked_by_count = op->count; /* our tag */
719  }
720  }
721 
722  monster_do_living(op);
723 
724  if (QUERY_FLAG(op, FLAG_SLEEP)
725  || QUERY_FLAG(op, FLAG_BLIND)
726  || (op->map->darkness > 0 && !QUERY_FLAG(op, FLAG_SEE_IN_DARK) && !QUERY_FLAG(op, FLAG_SEE_INVISIBLE))) {
727  if (!monster_check_wakeup(op, enemy, &rv))
728  return 0;
729  }
730 
731  /* check if monster pops out of hidden spot */
732  if (op->hide)
733  do_hidden_move(op);
734 
735  if (op->pick_up)
737 
738  if (op->will_apply)
739  monster_apply_below(op); /* Check for items to apply below */
740 
741  /* If we don't have an enemy, do special movement or the like */
742  if (!enemy) {
743  return monster_move_no_enemy(op);
744  } /* no enemy */
745 
746  /* We have an enemy. Block immediately below is for pets */
747  if ((op->attack_movement&HI4) == PETMOVE) {
748  owner = object_get_owner(op);
749  if (owner != NULL && !on_same_map(op, owner)) {
750  pets_follow_owner(op, owner);
751  /* If the pet was unable to follow the owner, free it */
752  if (QUERY_FLAG(op, FLAG_REMOVED) && FABS(op->speed) > MIN_ACTIVE_SPEED) {
755  return 1;
756  }
757  return 0;
758  }
759  }
760 
761  /* doppleganger code to change monster facing to that of the nearest
762  * player. Hmm. The code is here, but no monster in the current
763  * arch set uses it.
764  */
765  if (op->race != NULL && strcmp(op->race, "doppleganger") == 0) {
766  op->face = enemy->face;
767  if (op->name)
768  free_string(op->name);
769  add_refcount(op->name = enemy->name);
770  }
771 
772  /* Calculate range information for closest body part - this
773  * is used for the 'skill' code, which isn't that smart when
774  * it comes to figuring it out - otherwise, giants throw boulders
775  * into themselves.
776  */
777  if (!get_rangevector(op, enemy, &rv, 0))
778  return 0;
779  if (op->direction != rv.direction) {
780  op->direction = rv.direction;
781  op->facing = op->direction;
782  if (op->animation_id)
783  animate_object(op, op->direction);
784  }
785 
786  // We are looking at movement -- if monster was paralyzed, they aren't anymore
787  if (QUERY_FLAG(op, FLAG_PARALYZED)) {
789  }
790 
791  /* Move the check for scared up here - if the monster was scared,
792  * we were not doing any of the logic below, so might as well save
793  * a few cpu cycles.
794  */
795  if (!QUERY_FLAG(op, FLAG_SCARED)) {
796  dir = rv.direction;
797 
798  /* Was two if statements assigning to the same variable
799  * We can get the same effect by reversing the order and making an else-if
800  */
801  if (QUERY_FLAG(op, FLAG_CONFUSED))
802  dir = get_randomized_dir(dir);
803  else if (QUERY_FLAG(op, FLAG_RUN_AWAY))
804  dir = absdir(dir+4);
805 
806  if (QUERY_FLAG(op, FLAG_CAST_SPELL) && !(RANDOM()%3)) {
807  if (monster_cast_spell(op, rv.part, enemy, dir))
808  return 0;
809  }
810 
811  if (QUERY_FLAG(op, FLAG_READY_SCROLL) && !(RANDOM()%3)) {
812  if (monster_use_scroll(op, rv.part, enemy, dir))
813  return 0;
814  }
815 
816  if (QUERY_FLAG(op, FLAG_READY_RANGE) && !(RANDOM()%3)) {
817  if (monster_use_range(op, rv.part, enemy, dir))
818  return 0;
819  }
820  if (QUERY_FLAG(op, FLAG_READY_SKILL) && !(RANDOM()%3)) {
821  if (monster_use_skill(op, rv.part, enemy, rv.direction))
822  return 0;
823  }
824  if (QUERY_FLAG(op, FLAG_READY_BOW) && !(RANDOM()%2)) {
825  if (monster_use_bow(op, rv.part, enemy, dir))
826  return 0;
827  }
828  } /* If not scared */
829 
830 
831  /* code below is for when we didn't use a range attack or a skill, so
832  * either move or hit with hth attack. */
833 
834  part = rv.part;
835  dir = rv.direction;
836 
837  /* This first clause used to happen after the other two, but would trample dir.
838  * Moved to before them as another check to slightly reduce calls to monster_compute_path
839  */
840  if (QUERY_FLAG(op, FLAG_CONFUSED))
841  dir = get_randomized_dir(dir);
842  else if (QUERY_FLAG(op, FLAG_SCARED) || QUERY_FLAG(op, FLAG_RUN_AWAY))
843  dir = absdir(dir+4);
844  // Don't compute a path if we aren't going to move anyway.
845  else if (QUERY_FLAG(op, FLAG_STAND_STILL))
846  dir = rv.direction;
847  else if (!monster_can_hit(part, enemy, &rv)) {
848  // if door or earthwall is in direction of player and monster will apply doors or earthwalls, then hit the door.
849  // Don't do a path because the path could move them away from the door.
851  get_map_flags(op->map, 0, op->x+freearr_x[rv.direction], op->y+freearr_y[rv.direction], 0, 0)&~P_OUT_OF_MAP) {
852  // Note we don't call monster_check_earthwalls because it returns no type
853  FOR_MAP_PREPARE(op->map, op->x+freearr_x[rv.direction], op->y+freearr_y[rv.direction], tmp)
854  // Ensure the tile in rv.direction is an earthwall
855  if (tmp->type == EARTHWALL && op->will_apply&WILL_APPLY_EARTHWALL) {
856  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
857  return 0;
858  }
859  // Ensure the tile in rv.direction is a door
860  if (tmp->type == DOOR && op->will_apply&WILL_APPLY_DOOR) {
861  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
862  return 0;
863  }
864  FOR_MAP_FINISH();
865  }
866  // We do fallthrough because it returns from the function if we punch the door.
867  dir = monster_compute_path(op, enemy, rv.direction);
868  }
869 
870  if ((op->attack_movement&LO4) && !QUERY_FLAG(op, FLAG_SCARED)) {
871  switch (op->attack_movement&LO4) {
872  case DISTATT:
873  dir = monster_dist_att(dir, enemy, part, &rv);
874  break;
875 
876  case RUNATT:
877  dir = monster_run_att(dir, op, enemy, part, &rv);
878  break;
879 
880  case HITRUN:
881  dir = monster_hitrun_att(dir, op, enemy);
882  break;
883 
884  case WAITATT:
885  dir = monster_wait_att(dir, op, enemy, part, &rv);
886  break;
887 
888  case RUSH: /* default - monster normally moves towards player */
889  case ALLRUN:
890  break;
891 
892  case DISTHIT:
893  dir = monster_disthit_att(dir, op, enemy, part, &rv);
894  break;
895 
896  case WAIT2:
897  dir = monster_wait_att2(dir, &rv);
898  break;
899 
900  default:
901  LOG(llevDebug, "Illegal low mon-move: %d\n", op->attack_movement&LO4);
902  }
903  }
904 
905  if (!dir)
906  return 0;
907 
908  if (!QUERY_FLAG(op, FLAG_STAND_STILL)) {
909  if (move_object(op, dir)) /* Can the monster move directly toward player? */
910  return 0;
911 
912  if (QUERY_FLAG(op, FLAG_SCARED)
913  || !monster_can_hit(part, enemy, &rv)
914  || QUERY_FLAG(op, FLAG_RUN_AWAY)) {
915  /* Try move around corners if !close */
916  int maxdiff = (QUERY_FLAG(op, FLAG_ONLY_ATTACK) || RANDOM()&1) ? 1 : 2;
917  for (diff = 1; diff <= maxdiff; diff++) {
918  /* try different detours */
919  int m = 1-(RANDOM()&2); /* Try left or right first? */
920  if (move_object(op, absdir(dir+diff*m))
921  || move_object(op, absdir(dir-diff*m)))
922  return 0;
923  }
924  }
925  } /* if monster is not standing still */
926 
927  /*
928  * Eneq(@csd.uu.se): Patch to make RUN_AWAY or SCARED monsters move a random
929  * direction if they can't move away.
930  */
931  if (!QUERY_FLAG(op, FLAG_ONLY_ATTACK)
933  if (monster_move_randomly(op))
934  return 0;
935 
936  /*
937  * Try giving the monster a new enemy - the player that is closest
938  * to it. In this way, it won't just keep trying to get to a target
939  * that is inaccessible.
940  * This could be more clever - it should go through a list of several
941  * enemies, as it is now, you could perhaps get situations where there
942  * are two players flanking the monster at close distance, but which
943  * the monster can't get to, and a third one at a far distance that
944  * the monster could get to - as it is, the monster won't look at that
945  * third one.
946  */
947  if (!QUERY_FLAG(op, FLAG_FRIENDLY) && enemy == op->enemy) {
948  object *nearest_player = get_nearest_player(op);
949 
950  if (nearest_player && nearest_player != enemy && !monster_can_hit(part, enemy, &rv)) {
951  object_set_enemy(op, NULL);
952  enemy = nearest_player;
953  }
954  }
955 
956  if (!QUERY_FLAG(op, FLAG_SCARED) && monster_can_hit(part, enemy, &rv)) {
957  /* The adjustement to wc that was here before looked totally bogus -
958  * since wc can in fact get negative, that would mean by adding
959  * the current wc, the creature gets better? Instead, just
960  * add a fixed amount - nasty creatures that are runny away should
961  * still be pretty nasty.
962  */
963  if (QUERY_FLAG(op, FLAG_RUN_AWAY)) {
964  part->stats.wc += 10;
965  skill_attack(enemy, part, 0, NULL, NULL);
966  part->stats.wc -= 10;
967  } else
968  skill_attack(enemy, part, 0, NULL, NULL);
969  } /* if monster is in attack range */
970 
971  if (QUERY_FLAG(part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */
972  return 1;
973 
974  if (QUERY_FLAG(op, FLAG_ONLY_ATTACK)) {
975  object_remove(op);
977  return 1;
978  }
979  return 0;
980 }
981 
996 static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv) {
997  object *more;
998  rv_vector rv1;
999 
1000  if (QUERY_FLAG(ob1, FLAG_CONFUSED) && !(RANDOM()%3))
1001  return 0;
1002 
1003  if (abs(rv->distance_x) < 2 && abs(rv->distance_y) < 2)
1004  return 1;
1005 
1006  /* check all the parts of ob2 - just because we can't get to
1007  * its head doesn't mean we don't want to pound its feet
1008  */
1009  for (more = ob2->more; more != NULL; more = more->more) {
1010  if (get_rangevector(ob1, more, &rv1, 0)
1011  && abs(rv1.distance_x) < 2 && abs(rv1.distance_y) < 2)
1012  return 1;
1013  }
1014  return 0;
1015 }
1016 
1039 static int monster_should_cast_spell(object *spell_ob) {
1040  /* The caller is responsible for making sure that *spell_ob is defined. */
1041  assert(spell_ob != NULL);
1042 
1043  if (spell_ob->subtype == SP_BOLT
1044  || spell_ob->subtype == SP_BULLET
1045  || spell_ob->subtype == SP_EXPLOSION
1046  || spell_ob->subtype == SP_CONE
1047  || spell_ob->subtype == SP_BOMB
1048  || spell_ob->subtype == SP_SMITE
1049  || spell_ob->subtype == SP_MAGIC_MISSILE
1050  || spell_ob->subtype == SP_SUMMON_GOLEM
1051  || spell_ob->subtype == SP_MAGIC_WALL
1052  || spell_ob->subtype == SP_SUMMON_MONSTER
1053  || spell_ob->subtype == SP_MOVING_BALL
1054  || spell_ob->subtype == SP_SWARM
1055  || spell_ob->subtype == SP_INVISIBLE)
1056  return 1;
1057 
1058  return 0;
1059 }
1060 
1062 #define MAX_KNOWN_SPELLS 20
1063 
1079 static object *monster_choose_random_spell(object *monster) {
1080  object *altern[MAX_KNOWN_SPELLS];
1081  int i = 0;
1082 
1083  FOR_INV_PREPARE(monster, tmp)
1084  if (tmp->type == SPELLBOOK || tmp->type == SPELL) {
1085  /* Check and see if it's actually a useful spell.
1086  * If its a spellbook, the spell is actually the inventory item.
1087  * if it is a spell, then it is just the object itself.
1088  */
1089  if (monster_should_cast_spell(tmp->type == SPELLBOOK ? tmp->inv : tmp)) {
1090  altern[i++] = tmp;
1091  if (i == MAX_KNOWN_SPELLS)
1092  break;
1093  }
1094  }
1095  FOR_INV_FINISH();
1096  if (!i)
1097  return NULL;
1098  return altern[RANDOM()%i];
1099 }
1100 
1117 static int monster_cast_spell(object *head, object *part, object *pl, int dir) {
1118  object *spell_item;
1119  object *owner;
1120  rv_vector rv1;
1121 
1122  /* If you want monsters to cast spells over friends, this spell should
1123  * be removed. It probably should be in most cases, since monsters still
1124  * don't care about residual effects (ie, casting a cone which may have a
1125  * clear path to the player, the side aspects of the code will still hit
1126  * other monsters)
1127  */
1128  dir = path_to_player(part, pl, 0);
1129  if (dir == 0)
1130  return 0;
1131 
1132  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1133  owner = object_get_owner(head);
1134  if (owner != NULL) {
1135  if (get_rangevector(head, owner, &rv1, 0x1)
1136  && dirdiff(dir, rv1.direction) < 2) {
1137  return 0; /* Might hit owner with spell */
1138  }
1139  }
1140  }
1141 
1142  if (QUERY_FLAG(head, FLAG_CONFUSED))
1143  dir = get_randomized_dir(dir);
1144 
1145  /* If the monster hasn't already chosen a spell, choose one
1146  * I'm not sure if it really make sense to pre-select spells (events
1147  * could be different by the time the monster goes again).
1148  */
1149  if (head->spellitem == NULL) {
1150  spell_item = monster_choose_random_spell(head);
1151  if (spell_item == NULL) {
1152  LOG(llevMonster, "Turned off spells in %s\n", head->name);
1153  CLEAR_FLAG(head, FLAG_CAST_SPELL); /* Will be turned on when picking up book */
1154  return 0;
1155  }
1156  if (spell_item->type == SPELLBOOK) {
1157  if (!spell_item->inv) {
1158  LOG(llevError, "spellbook %s does not contain a spell?\n", spell_item->name);
1159  return 0;
1160  }
1161  spell_item = spell_item->inv;
1162  }
1163  } else
1164  spell_item = head->spellitem;
1165 
1166  if (!spell_item)
1167  return 0;
1168 
1169  /* Best guess this is a defensive/healing spell */
1170  if (spell_item->range <= 1 || spell_item->stats.dam < 0)
1171  dir = 0;
1172 
1173  /* Monster doesn't have enough spell-points */
1174  if (head->stats.sp < SP_level_spellpoint_cost(head, spell_item, SPELL_MANA))
1175  return 0;
1176 
1177  if (head->stats.grace < SP_level_spellpoint_cost(head, spell_item, SPELL_GRACE))
1178  return 0;
1179 
1180  head->stats.sp -= SP_level_spellpoint_cost(head, spell_item, SPELL_MANA);
1181  head->stats.grace -= SP_level_spellpoint_cost(head, spell_item, SPELL_GRACE);
1182 
1183  /* set this to null, so next time monster will choose something different */
1184  head->spellitem = NULL;
1185 
1186  return cast_spell(part, part, dir, spell_item, NULL);
1187 }
1188 
1203 static int monster_use_scroll(object *head, object *part, object *pl, int dir) {
1204  object *scroll;
1205  object *owner;
1206  rv_vector rv1;
1207 
1208  /* If you want monsters to cast spells over friends, this spell should
1209  * be removed. It probably should be in most cases, since monsters still
1210  * don't care about residual effects (ie, casting a cone which may have a
1211  * clear path to the player, the side aspects of the code will still hit
1212  * other monsters)
1213  */
1214  dir = path_to_player(part, pl, 0);
1215  if (dir == 0)
1216  return 0;
1217 
1218  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1219  owner = object_get_owner(head);
1220  if (owner != NULL) {
1221  if (get_rangevector(head, owner, &rv1, 0x1)
1222  && dirdiff(dir, rv1.direction) < 2) {
1223  return 0; /* Might hit owner with spell */
1224  }
1225  }
1226  }
1227 
1228  if (QUERY_FLAG(head, FLAG_CONFUSED))
1229  dir = get_randomized_dir(dir);
1230 
1231  scroll = NULL;
1232  FOR_INV_PREPARE(head, tmp)
1233  if (tmp->type == SCROLL && monster_should_cast_spell(tmp->inv)) {
1234  scroll = tmp;
1235  break;
1236  }
1237  FOR_INV_FINISH();
1238 
1239  /* Used up all his scrolls, so nothing do to */
1240  if (!scroll) {
1242  return 0;
1243  }
1244 
1245  /* Spell should be cast on caster (ie, heal, strength) */
1246  if (scroll->inv->range == 0)
1247  dir = 0;
1248 
1249  /* Face the direction that we want to cast. */
1250  head->direction = dir;
1251  head->facing = head->direction;
1252  if (head->animation_id)
1253  animate_object(head, head->direction);
1254 
1255  ob_apply(scroll, part, 0);
1256  return 1;
1257 }
1258 
1287 static int monster_use_skill(object *head, object *part, object *pl, int dir) {
1288  object *owner;
1289  int found;
1290 
1291  dir = path_to_player(part, pl, 0);
1292  if (dir == 0)
1293  return 0;
1294 
1295  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1296  owner = object_get_owner(head);
1297  if (owner != NULL) {
1298  rv_vector rv;
1299 
1300  if (get_rangevector(head, owner, &rv, 0) && dirdiff(dir, rv.direction) < 1)
1301  return 0; /* Might hit owner with skill -thrown rocks for example ?*/
1302  }
1303  }
1304  if (QUERY_FLAG(head, FLAG_CONFUSED))
1305  dir = get_randomized_dir(dir);
1306 
1307  /* skill selection - monster will use the next unused skill.
1308  * well...the following scenario will allow the monster to
1309  * toggle between 2 skills. One day it would be nice to make
1310  * more skills available to monsters.
1311  */
1312  found = 0;
1313  FOR_INV_PREPARE(head, skill)
1314  if (skill->type == SKILL && skill != head->chosen_skill) {
1315  head->chosen_skill = skill;
1316  found = 1;
1317  break;
1318  }
1319  FOR_INV_FINISH();
1320 
1321  if (!found && !head->chosen_skill) {
1322  LOG(llevDebug, "Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", head->name, head->count);
1324  return 0;
1325  }
1326  /* use skill */
1327  return do_skill(head, part, head->chosen_skill, dir, NULL);
1328 }
1329 
1344 static int monster_use_range(object *head, object *part, object *pl, int dir) {
1345  object *owner;
1346  int at_least_one = 0;
1347 
1348  dir = path_to_player(part, pl, 0);
1349  if (dir == 0)
1350  return 0;
1351 
1352  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1353  owner = object_get_owner(head);
1354  if (owner != NULL) {
1355  rv_vector rv;
1356 
1357  if (get_rangevector(head, owner, &rv, 0) && dirdiff(dir, rv.direction) < 2)
1358  return 0; /* Might hit owner with spell */
1359  }
1360  }
1361  if (QUERY_FLAG(head, FLAG_CONFUSED))
1362  dir = get_randomized_dir(dir);
1363 
1364  FOR_INV_PREPARE(head, wand) {
1365  if (wand->type == WAND) {
1366  /* Found a wand, let's see if it has charges left */
1367  at_least_one = 1;
1368  if (wand->stats.food <= 0)
1369  continue;
1370 
1371  cast_spell(head, wand, dir, wand->inv, NULL);
1372  drain_wand_charge(wand);
1373 
1374  /* Success */
1375  return 1;
1376  }
1377 
1378  if (wand->type == ROD) {
1379  /* Found rod/horn, let's use it if possible */
1380  at_least_one = 1;
1381  if (wand->stats.hp < MAX(wand->inv->stats.sp, wand->inv->stats.grace))
1382  continue;
1383 
1384  /* drain charge before casting spell - can be a case where the
1385  * spell destroys the monster, and rod, so if done after, results
1386  * in crash.
1387  */
1388  drain_rod_charge(wand);
1389  cast_spell(head, wand, dir, wand->inv, NULL);
1390 
1391  /* Success */
1392  return 1;
1393  }
1394  } FOR_INV_FINISH();
1395 
1396  if (at_least_one)
1397  return 0;
1398 
1399  LOG(llevError, "Error: Monster %s (%d) HAS_READY_RANG() without wand/horn/rod.\n", head->name, head->count);
1401  return 0;
1402 }
1403 
1420 static int monster_use_bow(object *head, object *part, object *pl, int dir) {
1421  object *owner;
1422  rv_vector rv;
1423  int16_t x, y;
1424  mapstruct *map;
1425 
1426  if (!get_rangevector(part, pl, &rv, 1))
1427  return 0;
1428  if (rv.distance > 100)
1429  /* Too far */
1430  return 0;
1431  if (rv.distance_x != 0 && rv.distance_y != 0 && abs(rv.distance_x) != abs(rv.distance_y))
1432  /* Player must be on same horizontal, vertical or diagonal line. */
1433  return 0;
1434  dir = rv.direction;
1435 
1436  if (QUERY_FLAG(head, FLAG_FRIENDLY))
1437  owner = object_get_owner(head);
1438  else
1439  owner = NULL;
1440 
1441  /* The monster can possibly fire, let's see if the path is ok for an arrow. */
1442  x = part->x;
1443  y = part->y;
1444  map = part->map;
1445  while (x != pl->x || y != pl->y || map != pl->map) {
1446  x += freearr_x[dir];
1447  y += freearr_y[dir];
1448  map = get_map_from_coord(map, &x, &y);
1449  if (!map) {
1450  LOG(llevError, "monster_use_bow: no map but still path exists??\n");
1451  return 0;
1452  }
1453  if ((GET_MAP_MOVE_BLOCK(map, x, y)&MOVE_FLY_LOW) == MOVE_FLY_LOW)
1454  return 0;
1455  if (owner && owner->x == x && owner->y == y && owner->map == map)
1456  /* Don't hit owner! */
1457  return 0;
1458  }
1459 
1460  /* Finally, path is clear, can fire. */
1461 
1462  if (QUERY_FLAG(head, FLAG_CONFUSED))
1463  dir = get_randomized_dir(dir);
1464 
1465  /* in server/player.c */
1466  return fire_bow(head, NULL, dir, 0, part->x, part->y);
1467 }
1468 
1477 static int monster_get_weapon_quality(const object *item) {
1478  int val;
1479  int i;
1480 
1481  val = item->stats.dam;
1482  val += item->magic*3;
1483  /* Monsters don't really get benefits from things like regen rates
1484  * from items. But the bonus for their stats are very important.
1485  */
1486  for (i = 0; i < NUM_STATS; i++)
1487  val += get_attr_value(&item->stats, i)*2;
1488  return val;
1489 }
1490 
1503 static int monster_check_good_weapon(object *who, object *item) {
1504  object *other_weap;
1505  int val;
1506 
1507  other_weap = object_find_by_type_applied(who, item->type);
1508  if (other_weap == NULL) /* No other weapons */
1509  return 1;
1510 
1511  /* Rather than go through and apply the new one, and see if it is
1512  * better, just do some simple checks
1513  * Put some multipliers for things that hvae several effects,
1514  * eg, magic affects both damage and wc, so it has more weight
1515  */
1516 
1518  return val > 0;
1519 }
1520 
1529 static int monster_get_armour_quality(const object *item) {
1530  int val;
1531 
1532  val = item->stats.ac;
1533  val += item->resist[ATNR_PHYSICAL]/5;
1534  val += item->magic*3;
1535  return val;
1536 }
1537 
1550 static int monster_check_good_armour(object *who, object *item) {
1551  object *other_armour;
1552  int val, i;
1553 
1554  other_armour = object_find_by_type_applied(who, item->type);
1555  if (other_armour == NULL) /* No other armour, use the new */
1556  return 1;
1557 
1558  val = monster_get_armour_quality(item)-monster_get_armour_quality(other_armour);
1559 
1560  /* for the other protections, do weigh them very much in the equation -
1561  * it is the armor protection which is most important, because there is
1562  * no good way to know what the player may attack the monster with.
1563  * So if the new item has better protection than the old, give that higher
1564  * value. If the reverse, then decrease the value of this item some.
1565  */
1566  for (i = 1; i < NROFATTACKS; i++) {
1567  if (item->resist[i] > other_armour->resist[i])
1568  val++;
1569  else if (item->resist[i] < other_armour->resist[i])
1570  val--;
1571  }
1572 
1573  /* Very few armours have stats, so not much need to worry about those. */
1574 
1575  return val > 0;
1576 }
1577 
1585 static void monster_check_apply(object *mon, object *item) {
1586  int flag = 0;
1587 
1588  if (item->type == SPELLBOOK
1589  && mon->arch != NULL
1590  && (QUERY_FLAG(&mon->arch->clone, FLAG_CAST_SPELL))) {
1591  SET_FLAG(mon, FLAG_CAST_SPELL);
1592  return;
1593  }
1594 
1595  /* If for some reason, this item is already applied, no more work to do */
1596  if (QUERY_FLAG(item, FLAG_APPLIED))
1597  return;
1598 
1599  /* Might be better not to do this - if the monster can fire a bow,
1600  * it is possible in his wanderings, he will find one to use. In
1601  * which case, it would be nice to have ammo for it.
1602  */
1603  if (QUERY_FLAG(mon, FLAG_USE_BOW) && item->type == ARROW) {
1604  /* Check for the right kind of bow */
1605  object *bow;
1606 
1607  bow = object_find_by_type_and_race(mon, BOW, item->race);
1608  if (bow != NULL) {
1609  SET_FLAG(mon, FLAG_READY_BOW);
1610  LOG(llevMonster, "Found correct bow for arrows.\n");
1611  return; /* nothing more to do for arrows */
1612  }
1613  }
1614 
1615  if (item->type == TREASURE && mon->will_apply&WILL_APPLY_TREASURE)
1616  flag = 1;
1617  /* Eating food gets hp back */
1618  else if (item->type == FOOD && mon->will_apply&WILL_APPLY_FOOD)
1619  flag = 1;
1620  else if (item->type == SCROLL && QUERY_FLAG(mon, FLAG_USE_SCROLL)) {
1621  if (!item->inv)
1622  LOG(llevDebug, "Monster %d having scroll %d with empty inventory!\n", mon->count, item->count);
1623  else if (monster_should_cast_spell(item->inv))
1625  /* Don't use it right now */
1626  return;
1627  } else if (item->type == WEAPON)
1628  flag = monster_check_good_weapon(mon, item);
1629  else if (IS_ARMOR(item) || IS_SHIELD(item))
1630  flag = monster_check_good_armour(mon, item);
1631  /* Should do something more, like make sure this is a better item */
1632  else if (item->type == RING)
1633  flag = 1;
1634  else if (item->type == WAND || item->type == ROD) {
1635  /* We never really 'ready' the wand/rod/horn, because that would mean the
1636  * weapon would get undone.
1637  */
1638  if (!(apply_can_apply_object(mon, item)&CAN_APPLY_NOT_MASK)) {
1639  SET_FLAG(mon, FLAG_READY_RANGE);
1640  SET_FLAG(item, FLAG_APPLIED);
1641  }
1642  return;
1643  } else if (item->type == BOW) {
1644  /* We never really 'ready' the bow, because that would mean the
1645  * weapon would get undone.
1646  */
1647  if (!(apply_can_apply_object(mon, item)&CAN_APPLY_NOT_MASK))
1648  SET_FLAG(mon, FLAG_READY_BOW);
1649  return;
1650  } else if (item->type == SKILL) {
1651  /*
1652  * skills are specials: monsters must have the 'FLAG_READY_SKILL' flag set,
1653  * else they can't use the skill...
1654  * Skills also don't need to get applied, so return now.
1655  */
1656  SET_FLAG(mon, FLAG_READY_SKILL);
1657  return;
1658  }
1659 
1660  /* if we don't match one of the above types, return now.
1661  * apply_can_apply_object() will say that we can apply things like flesh,
1662  * bolts, and whatever else, because it only checks against the
1663  * body_info locations.
1664  */
1665  if (!flag)
1666  return;
1667 
1668  /* Check to see if the monster can use this item. If not, no need
1669  * to do further processing. Note that apply_can_apply_object() already checks
1670  * for the CAN_USE flags.
1671  */
1673  return;
1674 
1675  /* should only be applying this item, not unapplying it.
1676  * also, ignore status of curse so they can take off old armour.
1677  * monsters have some advantages after all.
1678  */
1680  return;
1681 }
1682 
1702 static void monster_check_pickup(object *monster) {
1703  object *part;
1704 
1705  for (part = monster; part != NULL; part = part->more)
1706  FOR_BELOW_PREPARE(part, tmp) {
1707  if (monster_can_pick(monster, tmp)) {
1708  uint32_t nrof;
1709 
1710  if (tmp->weight > 0) {
1711  int32_t weight_limit;
1712 
1713  weight_limit = get_weight_limit(monster->stats.Str);
1714  if (weight_limit >= monster->weight-monster->carrying)
1715  nrof = (weight_limit-monster->weight-monster->carrying)/tmp->weight;
1716  else
1717  nrof = 0;
1718  } else
1719  nrof = MAX(1, tmp->nrof);
1720  if (nrof >= 1) {
1721  object *tmp2;
1722 
1723  tmp2 = object_split(tmp, MIN(nrof, MAX(1, tmp->nrof)), NULL, 0);
1724  tmp2 = object_insert_in_ob(tmp2, monster);
1725  (void)monster_check_apply(monster, tmp2);
1726  }
1727  }
1728  } FOR_BELOW_FINISH();
1729 }
1730 
1740 static int monster_can_pick(object *monster, object *item) {
1741  int flag = 0;
1742  int i;
1743 
1744  if (!object_can_pick(monster, item))
1745  return 0;
1746 
1747  if (QUERY_FLAG(item, FLAG_UNPAID))
1748  return 0;
1749 
1750  if (monster->pick_up&64) /* All */
1751  flag = 1;
1752 
1753  else {
1754  if (IS_WEAPON(item))
1755  flag = (monster->pick_up&8) || QUERY_FLAG(monster, FLAG_USE_WEAPON);
1756  else if (IS_ARMOR(item))
1757  flag = (monster->pick_up&16) || QUERY_FLAG(monster, FLAG_USE_ARMOUR);
1758  else if (IS_SHIELD(item))
1759  flag = (monster->pick_up&16) || QUERY_FLAG(monster, FLAG_USE_SHIELD);
1760  else switch (item->type) {
1761  case MONEY:
1762  case GEM:
1763  flag = monster->pick_up&2;
1764  break;
1765 
1766  case FOOD:
1767  flag = monster->pick_up&4;
1768  break;
1769 
1770  case SKILL:
1771  flag = QUERY_FLAG(monster, FLAG_CAN_USE_SKILL);
1772  break;
1773 
1774  case RING:
1775  flag = QUERY_FLAG(monster, FLAG_USE_RING);
1776  break;
1777 
1778  case WAND:
1779  case ROD:
1780  flag = QUERY_FLAG(monster, FLAG_USE_RANGE);
1781  break;
1782 
1783  case SPELLBOOK:
1784  flag = (monster->arch != NULL && QUERY_FLAG(&monster->arch->clone, FLAG_CAST_SPELL));
1785  break;
1786 
1787  case SCROLL:
1788  flag = QUERY_FLAG(monster, FLAG_USE_SCROLL);
1789  break;
1790 
1791  case BOW:
1792  case ARROW:
1793  flag = QUERY_FLAG(monster, FLAG_USE_BOW);
1794  break;
1795  }
1796  if (!flag && QUERY_FLAG(item, FLAG_IS_THROWN) && object_find_by_type_subtype(monster, SKILL, SK_THROWING) != NULL)
1797  flag = (monster->pick_up&8) || QUERY_FLAG(monster, FLAG_USE_WEAPON);
1798  /* Simplistic check - if the monster has a location to equip it, he will
1799  * pick it up. Note that this doesn't handle cases where an item may
1800  * use several locations.
1801  */
1802  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
1803  if (monster->body_info[i] && item->body_info[i]) {
1804  flag = 1;
1805  break;
1806  }
1807  }
1808  }
1809 
1810  if (((!(monster->pick_up&32)) && flag) || ((monster->pick_up&32) && (!flag)))
1811  return 1;
1812  return 0;
1813 }
1814 
1821 static void monster_apply_below(object *monster) {
1822  FOR_BELOW_PREPARE(monster, tmp) {
1823  switch (tmp->type) {
1824  case CF_HANDLE:
1825  case TRIGGER:
1826  if (monster->will_apply&WILL_APPLY_HANDLE)
1827  apply_manual(monster, tmp, 0);
1828  break;
1829 
1830  case TREASURE:
1831  if (monster->will_apply&WILL_APPLY_TREASURE)
1832  apply_manual(monster, tmp, 0);
1833  break;
1834  }
1835  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
1836  break;
1837  } FOR_BELOW_FINISH();
1838 }
1839 
1844 void monster_check_apply_all(object *monster) {
1845  FOR_INV_PREPARE(monster, inv)
1846  monster_check_apply(monster, inv);
1847  FOR_INV_FINISH();
1848 }
1849 
1854 void monster_npc_call_help(object *op) {
1855  const int help_radius = 3;
1856  for (int x = -help_radius; x <= help_radius; x++)
1857  for (int y = -help_radius; y <= help_radius; y++) {
1858  mapstruct *m = op->map;
1859  int16_t sx = op->x+x;
1860  int16_t sy = op->y+y;
1861  int mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
1862  /* If nothing alive on this space, no need to search the space. */
1863  if ((mflags&P_OUT_OF_MAP) || !(mflags&P_IS_ALIVE))
1864  continue;
1865 
1866  FOR_MAP_PREPARE(m, sx, sy, npc)
1868  object_set_enemy(npc, op->enemy);
1869  FOR_MAP_FINISH();
1870  }
1871 }
1872 
1881 static int monster_dist_att(int dir, object *enemy, object *part, rv_vector *rv) {
1882  if (monster_can_hit(part, enemy, rv))
1883  return dir;
1884  if (rv->distance < 10)
1885  return absdir(dir+4);
1886  else if (rv->distance > 18)
1887  return dir;
1888  return 0;
1889 }
1890 
1900 static int monster_run_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
1901  if ((monster_can_hit(part, enemy, rv) && ob->move_status < 20) || ob->move_status < 20) {
1902  ob->move_status++;
1903  return (dir);
1904  } else if (ob->move_status > 20)
1905  ob->move_status = 0;
1906  return absdir(dir+4);
1907 }
1908 
1916 static int monster_hitrun_att(int dir, object *ob, object *enemy) {
1917  if (ob->move_status++ < 25)
1918  return dir;
1919  else if (ob->move_status < 50)
1920  return absdir(dir+4);
1921  ob->move_status = 0;
1922  return absdir(dir+4);
1923 }
1924 
1934 static int monster_wait_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
1935  int inrange = monster_can_hit(part, enemy, rv);
1936 
1937  if (ob->move_status || inrange)
1938  ob->move_status++;
1939 
1940  if (ob->move_status == 0)
1941  return 0;
1942  else if (ob->move_status < 10)
1943  return dir;
1944  else if (ob->move_status < 15)
1945  return absdir(dir+4);
1946  ob->move_status = 0;
1947  return 0;
1948 }
1949 
1959 static int monster_disthit_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
1960  /* The logic below here looked plain wrong before. Basically, what should
1961  * happen is that if the creatures hp percentage falls below run_away,
1962  * the creature should run away (dir+4)
1963  * I think its wrong for a creature to have a zero maxhp value, but
1964  * at least one map has this set, and whatever the map contains, the
1965  * server should try to be resilant enough to avoid the problem
1966  */
1967  if (ob->stats.maxhp && (ob->stats.hp*100)/ob->stats.maxhp < ob->run_away)
1968  return absdir(dir+4);
1969  return monster_dist_att(dir, enemy, part, rv);
1970 }
1971 
1978 static int monster_wait_att2(int dir, rv_vector *rv) {
1979  if (rv->distance < 9)
1980  return absdir(dir+4);
1981  return 0;
1982 }
1983 
1988 static void monster_circ1_move(object *ob) {
1989  static const int circle [12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 };
1990 
1991  if (++ob->move_status > 11)
1992  ob->move_status = 0;
1993  if (!(move_object(ob, circle[ob->move_status])))
1994  (void)move_object(ob, RANDOM()%8+1);
1995 }
1996 
2001 static void monster_circ2_move(object *ob) {
2002  static const int circle[20] = { 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 1, 1, 1, 2, 2 };
2003 
2004  if (++ob->move_status > 19)
2005  ob->move_status = 0;
2006  if (!(move_object(ob, circle[ob->move_status])))
2007  (void)move_object(ob, RANDOM()%8+1);
2008 }
2009 
2014 static void monster_pace_movev(object *ob) {
2015  if (ob->move_status++ > 6)
2016  ob->move_status = 0;
2017  if (ob->move_status < 4)
2018  (void)move_object(ob, 5);
2019  else
2020  (void)move_object(ob, 1);
2021 }
2022 
2027 static void monster_pace_moveh(object *ob) {
2028  if (ob->move_status++ > 6)
2029  ob->move_status = 0;
2030  if (ob->move_status < 4)
2031  (void)move_object(ob, 3);
2032  else
2033  (void)move_object(ob, 7);
2034 }
2035 
2040 static void monster_pace2_movev(object *ob) {
2041  if (ob->move_status++ > 16)
2042  ob->move_status = 0;
2043  if (ob->move_status < 6)
2044  (void)move_object(ob, 5);
2045  else if (ob->move_status < 8)
2046  return;
2047  else if (ob->move_status < 13)
2048  (void)move_object(ob, 1);
2049 }
2050 
2055 static void monster_pace2_moveh(object *ob) {
2056  if (ob->move_status++ > 16)
2057  ob->move_status = 0;
2058  if (ob->move_status < 6)
2059  (void)move_object(ob, 3);
2060  else if (ob->move_status < 8)
2061  return;
2062  else if (ob->move_status < 13)
2063  (void)move_object(ob, 7);
2064 }
2065 
2070 static void monster_rand_move(object *ob) {
2071  int i;
2072 
2073  if (ob->move_status < 1
2074  || ob->move_status > 8
2075  || !(move_object(ob, ob->move_status || !(RANDOM()%9))))
2076  for (i = 0; i < 5; i++) {
2077  ob->move_status = RANDOM()%8+1;
2078  if (move_object(ob, ob->move_status))
2079  return;
2080  }
2081 }
2082 
2090 void monster_check_earthwalls(object *op, mapstruct *m, int x, int y) {
2091  FOR_MAP_PREPARE(m, x, y, tmp)
2092  if (tmp->type == EARTHWALL) {
2093  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
2094  return;
2095  }
2096  FOR_MAP_FINISH();
2097 }
2098 
2106 void monster_check_doors(object *op, mapstruct *m, int x, int y) {
2107  FOR_MAP_PREPARE(m, x, y, tmp)
2108  if (tmp->type == DOOR) {
2109  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
2110  return;
2111  }
2112  FOR_MAP_FINISH();
2113 }
2114 
2120 void monster_do_say(const mapstruct *map, const char *message) {
2122  message);
2123 }
2124 
2131 static StringBuffer *monster_format_say(const object* npc, const char *message) {
2132  char name[MAX_BUF];
2133  StringBuffer *buf;
2134 
2135  query_name(npc, name, sizeof(name));
2136  buf = stringbuffer_new();
2137  stringbuffer_append_printf(buf, "%s says: %s", name, message);
2138  return buf;
2139 }
2140 
2146 static const char *get_reply_text_own(reply_type rt) {
2147  switch (rt) {
2148  case rt_say:
2149  return "say";
2150  case rt_reply:
2151  return "reply";
2152  case rt_question:
2153  return "ask";
2154  }
2155  assert(0);
2156  return NULL;
2157 }
2158 
2164 static const char *get_reply_text_other(reply_type rt) {
2165  switch (rt) {
2166  case rt_say:
2167  return "says";
2168  case rt_reply:
2169  return "replies";
2170  case rt_question:
2171  return "asks";
2172  }
2173  assert(0);
2174  return NULL;
2175 }
2176 
2202 void monster_communicate(object *op, const char *txt) {
2203  int i, mflags;
2204  int16_t x, y;
2205  mapstruct *mp, *orig_map = op->map;
2206  char own[MAX_BUF], others[MAX_BUF];
2207  talk_info info;
2208 
2209  info.text = txt;
2210  info.message = NULL;
2211  info.replies_count = 0;
2212  info.who = op;
2213  info.npc_msg_count = 0;
2214 
2215  /* Note that this loop looks pretty inefficient to me - we look and try to talk
2216  * to every object within 2 spaces. It would seem that if we trim this down to
2217  * only try to talk to objects with npc->msg set, things would be a lot more efficient,
2218  * but I'm not sure if there are any objects out there that don't have a message and instead
2219  * rely sorely on events - MSW 2009-04-14
2220  */
2221  for (i = 0; i <= SIZEOFFREE2; i++) {
2222  mp = op->map;
2223  x = op->x+freearr_x[i];
2224  y = op->y+freearr_y[i];
2225 
2226  mflags = get_map_flags(mp, &mp, x, y, &x, &y);
2227  if (mflags&P_OUT_OF_MAP)
2228  continue;
2229 
2230  FOR_MAP_PREPARE(mp, x, y, npc) {
2231  monster_talk_to_npc(npc, &info);
2232  if (orig_map != op->map) {
2233  LOG(llevDebug, "Warning: Forced to swap out very recent map - MAX_OBJECTS should probably be increased\n");
2234  return;
2235  }
2236  } FOR_MAP_FINISH();
2237  }
2238 
2239  /* First, what the player says. */
2240  if (info.message != NULL) {
2241  snprintf(own, sizeof(own), "You %s: %s", get_reply_text_own(info.message_type), info.message);
2242  snprintf(others, sizeof(others), "%s %s: %s", op->name, get_reply_text_other(info.message_type), info.message);
2243  free_string(info.message);
2244  } else {
2245  snprintf(own, sizeof(own), "You say: %s", txt);
2246  snprintf(others, sizeof(others), "%s says: %s", op->name, txt);
2247  }
2250 
2251  /* Then NPCs can actually talk. */
2252  for (i = 0; i < info.npc_msg_count; i++) {
2253  monster_do_say(orig_map, info.npc_msgs[i]);
2254  free_string(info.npc_msgs[i]);
2255  }
2256 
2257  /* Finally, the replies the player can use. */
2258  if (info.replies_count > 0) {
2260  for (i = 0; i < info.replies_count; i++) {
2262  free_string(info.replies_words[i]);
2263  free_string(info.replies[i]);
2264  }
2265  }
2266 }
2267 
2276 static int monster_do_talk_npc(object *npc, talk_info *info) {
2277  struct_dialog_reply *reply;
2278  struct_dialog_message *message;
2279 
2280  if (!get_dialog_message(npc, info->text, &message, &reply))
2281  return 0;
2282 
2283  if (reply) {
2284  info->message = add_string(reply->message);
2285  info->message_type = reply->type;
2286  }
2287 
2288  if (npc->type == MAGIC_EAR) {
2290  use_trigger(npc);
2291  } else {
2292  char value[2];
2293 
2294  if (info->npc_msg_count < MAX_NPC) {
2296  info->npc_msg_count++;
2297  }
2298 
2299  /* mark that the npc was talked to, so it won't move randomly later on */
2300  value[0] = '3' + rand() % 6;
2301  value[1] = '\0';
2302  object_set_value(npc, "talked_to", value, 1);
2303 
2304  reply = message->replies;
2305  while (reply && info->replies_count < MAX_REPLIES) {
2306  info->replies[info->replies_count] = add_string(reply->message);
2307  info->replies_words[info->replies_count] = add_string(reply->reply);
2308  info->replies_count++;
2309  reply = reply->next;
2310  }
2311  }
2312 
2313  return 1;
2314 }
2315 
2321 void monster_npc_say(object *npc, const char *cp) {
2322  char *message;
2323  StringBuffer *buf = monster_format_say(npc, cp);
2324 
2325  message = stringbuffer_finish(buf);
2326  monster_do_say(npc->map, message);
2327  free(message);
2328 }
2329 
2338 static int monster_talk_to_npc(object *npc, talk_info *info) {
2339  /* Move this commone area up here - shouldn't cost much extra cpu
2340  * time, and makes the function more readable */
2341  /* Lauwenmark: Handle for plugin say event */
2342  if (plugin_event_say(npc, info) != 0)
2343  return 0;
2344  /* Lauwenmark - Here we let the objects inside inventories hear and answer, too. */
2345  /* This allows the existence of "intelligent" weapons you can discuss with */
2346  FOR_INV_PREPARE(npc, cobj)
2347  if (plugin_event_say(cobj, info) != 0)
2348  return 0;
2349  FOR_INV_FINISH();
2350  if (info->who == npc)
2351  return 0;
2352  return monster_do_talk_npc(npc, info);
2353 }
2354 
2367 object *monster_find_throw_ob(object *op) {
2368  /* New throw code: look through the inventory. Grap the first legal is_thrown
2369  * marked item and throw it to the enemy.
2370  */
2371 
2372  FOR_INV_PREPARE(op, tmp) {
2373  /* Can't throw invisible objects or items that are applied */
2374  if (!tmp->invisible && !QUERY_FLAG(tmp, FLAG_APPLIED) && QUERY_FLAG(tmp, FLAG_IS_THROWN)) {
2375 #ifdef DEBUG_THROW
2376  char what[MAX_BUF];
2377 
2378  query_name(tmp, what, MAX_BUF);
2379  LOG(llevDebug, "%s chooses to throw: %s (%d)\n", op->name, what, tmp->count);
2380 #endif
2381  return tmp;
2382  }
2383  } FOR_INV_FINISH();
2384 
2385 #ifdef DEBUG_THROW
2386  LOG(llevDebug, "%s chooses to throw nothing\n", op->name);
2387 #endif
2388  return NULL;
2389 }
2390 
2406 int monster_can_detect_enemy(object *op, object *enemy, rv_vector *rv) {
2407  int radius = MIN_MON_RADIUS, hide_discovery;
2408 
2409  /* null detection for any of these condtions always */
2410  if (!op || !enemy || !op->map || !enemy->map)
2411  return 0;
2412 
2413  /* If the monster (op) has no way to get to the enemy, do nothing */
2414  if (!get_rangevector(op, enemy, rv, 0))
2415  return 0;
2416 
2417  /* Monsters always ignore the DM */
2418  if (op->type != PLAYER && QUERY_FLAG(enemy, FLAG_WIZ))
2419  return 0;
2420 
2421  /* simple check. Should probably put some range checks in here. */
2422  if (monster_can_see_enemy(op, enemy))
2423  return 1;
2424 
2425  /* The rest of this is for monsters. Players are on their own for
2426  * finding enemies!
2427  */
2428  if (op->type == PLAYER)
2429  return 0;
2430 
2431  /* Quality invisible? Bah, we wont see them w/o SEE_INVISIBLE
2432  * flag (which was already checked) in can_see_enmy (). Lets get out of here
2433  */
2434  if (enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden)))
2435  return 0;
2436 
2437  /* use this for invis also */
2438  hide_discovery = op->stats.Int/5;
2439 
2440  /* Determine Detection radii */
2441  if (!enemy->hide) /* to detect non-hidden (eg dark/invis enemy) */
2442  radius = MAX(op->stats.Wis/5+1, MIN_MON_RADIUS);
2443  else { /* a level/INT/Dex adjustment for hiding */
2444  object *sk_hide;
2445  int bonus = (op->level/2)+(op->stats.Int/5);
2446 
2447  if (enemy->type == PLAYER) {
2448  sk_hide = find_skill_by_number(enemy, SK_HIDING);
2449  if (sk_hide != NULL)
2450  bonus -= sk_hide->level;
2451  else {
2452  LOG(llevError, "monster_can_detect_enemy() got hidden player w/o hiding skill!\n");
2453  make_visible(enemy);
2454  radius = MAX(radius, MIN_MON_RADIUS);
2455  }
2456  } else /* enemy is not a player */
2457  bonus -= enemy->level;
2458 
2459  radius += bonus/5;
2460  hide_discovery += bonus*5;
2461  } /* else creature has modifiers for hiding */
2462 
2463  /* Radii stealth adjustment. Only if you are stealthy
2464  * will you be able to sneak up closer to creatures */
2465  if (QUERY_FLAG(enemy, FLAG_STEALTH))
2466  radius = radius/2, hide_discovery = hide_discovery/3;
2467 
2468  /* Radii adjustment for enemy standing in the dark */
2469  if (op->map->darkness > 0 && !monster_stand_in_light(enemy)) {
2470  /* on dark maps body heat can help indicate location with infravision
2471  * undead don't have body heat, so no benefit detecting them.
2472  */
2473  if (QUERY_FLAG(op, FLAG_SEE_IN_DARK) && !is_true_undead(enemy))
2474  radius += op->map->darkness/2;
2475  else
2476  radius -= op->map->darkness/2;
2477 
2478  /* op next to a monster (and not in complete darkness)
2479  * the monster should have a chance to see you.
2480  */
2481  if (radius < MIN_MON_RADIUS && op->map->darkness < 5 && rv->distance <= 1)
2482  radius = MIN_MON_RADIUS;
2483  } /* if on dark map */
2484 
2485  /* Lets not worry about monsters that have incredible detection
2486  * radii, we only need to worry here about things the player can
2487  * (potentially) see. This is 13, as that is the maximum size the player
2488  * may have for their map - in that way, creatures at the edge will
2489  * do something. Note that the distance field in the
2490  * vector is real distance, so in theory this should be 18 to
2491  * find that.
2492  */
2493  if (radius > 13)
2494  radius = 13;
2495 
2496  /* Enemy in range! Now test for detection */
2497  if ((int)rv->distance <= radius) {
2498  /* ah, we are within range, detected? take cases */
2499  if (!enemy->invisible) /* enemy in dark squares... are seen! */
2500  return 1;
2501 
2502  /* hidden or low-quality invisible */
2503  if (enemy->hide && rv->distance <= 1 && RANDOM()%100 <= (unsigned int)hide_discovery) {
2504  make_visible(enemy);
2505  /* inform players of new status */
2506  if (enemy->type == PLAYER && player_can_view(enemy, op))
2508  "You are discovered by %s!",
2509  op->name);
2510  return 1; /* detected enemy */
2511  } else if (enemy->invisible) {
2512  /* Change this around - instead of negating the invisible, just
2513  * return true so that the mosnter that managed to detect you can
2514  * do something to you. Decreasing the duration of invisible
2515  * doesn't make a lot of sense IMO, as a bunch of stupid creatures
2516  * can then basically negate the spell. The spell isn't negated -
2517  * they just know where you are!
2518  */
2519  if (RANDOM()%50 <= (unsigned int)hide_discovery) {
2520  if (enemy->type == PLAYER) {
2521  char name[MAX_BUF];
2522 
2523  query_name(op, name, MAX_BUF);
2525  "You see %s noticing your position.",
2526  name);
2527  }
2528  return 1;
2529  }
2530  }
2531  } /* within range */
2532 
2533  /* Wasn't detected above, so still hidden */
2534  return 0;
2535 }
2536 
2546 int monster_stand_in_light(object *op) {
2547  int16_t nx, ny;
2548  mapstruct *m;
2549 
2550  if (!op)
2551  return 0;
2552  if (op->glow_radius > 0)
2553  return 1;
2554 
2555  if (op->map) {
2556  int x, y, x1, y1;
2557 
2558  /* Check the spaces with the max light radius to see if any of them
2559  * have lights, and if any of them light the player enough, then return 1.
2560  */
2561  for (x = op->x-MAX_LIGHT_RADII; x <= op->x+MAX_LIGHT_RADII; x++) {
2562  for (y = op->y-MAX_LIGHT_RADII; y <= op->y+MAX_LIGHT_RADII; y++) {
2563  m = op->map;
2564  nx = x;
2565  ny = y;
2566 
2567  if (get_map_flags(m, &m, nx, ny, &nx, &ny)&P_OUT_OF_MAP)
2568  continue;
2569 
2570  x1 = abs(x-op->x)*abs(x-op->x);
2571  y1 = abs(y-op->y)*abs(y-op->y);
2572  if (isqrt(x1+y1) < GET_MAP_LIGHT(m, nx, ny))
2573  return 1;
2574  }
2575  }
2576  }
2577  return 0;
2578 }
2579 
2589 int monster_can_see_enemy(object *op, object *enemy) {
2590  object *looker = HEAD(op);
2591 
2592  /* safety */
2593  if (!looker || !enemy || !QUERY_FLAG(looker, FLAG_ALIVE))
2594  return 0;
2595 
2596  /* we dont give a full treatment of xrays here (shorter range than normal,
2597  * see through walls). Should we change the code elsewhere to make you
2598  * blind even if you can xray?
2599  */
2600  if (QUERY_FLAG(looker, FLAG_BLIND) && !QUERY_FLAG(looker, FLAG_XRAYS))
2601  return 0;
2602 
2603  /* checking for invisible things */
2604  if (enemy->invisible) {
2605  /* HIDDEN ENEMY. by definition, you can't see hidden stuff!
2606  * However, if you carry any source of light, then the hidden
2607  * creature is seeable (and stupid) */
2608  if (has_carried_lights(enemy)) {
2609  if (enemy->hide) {
2610  make_visible(enemy);
2612  "Your light reveals your hiding spot!");
2613  }
2614  return 1;
2615  } else if (enemy->hide)
2616  return 0;
2617 
2618  /* Invisible enemy. Break apart the check for invis undead/invis looker
2619  * into more simple checks - the QUERY_FLAG doesn't return 1/0 values,
2620  * and making it a conditional makes the code pretty ugly.
2621  */
2622  if (!QUERY_FLAG(looker, FLAG_SEE_INVISIBLE)) {
2623  if (makes_invisible_to(enemy, looker))
2624  return 0;
2625  }
2626  } else if (looker->type == PLAYER) /* for players, a (possible) shortcut */
2627  if (player_can_view(looker, enemy))
2628  return 1;
2629 
2630  /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen
2631  * unless they carry a light or stand in light. Darkness doesnt
2632  * inhibit the undead per se (but we should give their archs
2633  * CAN_SEE_IN_DARK, this is just a safety
2634  * we care about the enemy maps status, not the looker.
2635  * only relevant for tiled maps, but it is possible that the
2636  * enemy is on a bright map and the looker on a dark - in that
2637  * case, the looker can still see the enemy
2638  */
2639  if (enemy->map->darkness > 0
2640  && !monster_stand_in_light(enemy)
2641  && (!QUERY_FLAG(looker, FLAG_SEE_IN_DARK) || !is_true_undead(looker) || !QUERY_FLAG(looker, FLAG_XRAYS)))
2642  return 0;
2643 
2644  return 1;
2645 }
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:315
char path[HUGE_BUF]
Definition: map.h:365
int get_dialog_message(object *op, const char *text, struct_dialog_message **message, struct_dialog_reply **reply)
Definition: dialog.c:209
int8_t Int
Definition: living.h:36
#define NUM_BODY_LOCATIONS
Definition: object.h:13
Definition: player.h:92
#define FLAG_SEE_IN_DARK
Definition: define.h:338
int apply_manual(object *op, object *tmp, int aflag)
Definition: apply.c:510
static int monster_use_scroll(object *head, object *part, object *pl, int dir)
Definition: monster.c:1203
#define FLAG_IS_FLOOR
Definition: define.h:303
int npc_msg_count
Definition: dialog.h:59
#define FLAG_UNPAID
Definition: define.h:236
int8_t ac
Definition: living.h:38
static int monster_check_good_armour(object *who, object *item)
Definition: monster.c:1550
#define SP_BOLT
Definition: spells.h:78
Definition: object.h:185
#define RANDO
Definition: define.h:552
Definition: map.h:380
void monster_npc_say(object *npc, const char *cp)
Definition: monster.c:2321
#define FLAG_SLEEP
Definition: define.h:308
const char * race
Definition: object.h:318
uint16_t attack_movement
Definition: object.h:391
#define MAX_LIGHT_RADII
Definition: define.h:466
#define FLAG_USE_SCROLL
Definition: define.h:292
static int monster_hitrun_att(int dir, object *ob, object *enemy)
Definition: monster.c:1916
static int monster_should_cast_spell(object *spell_ob)
Definition: monster.c:1039
tag_t attacked_by_count
Definition: object.h:383
#define SET_FLAG(xyz, p)
Definition: define.h:223
sstring add_refcount(sstring str)
Definition: shstr.c:210
#define SP_CONE
Definition: spells.h:81
int makes_invisible_to(object *pl, object *mon)
Definition: spell_effect.c:740
object * object_find_by_type_applied(const object *who, int type)
Definition: object.c:3994
#define FABS(x)
Definition: define.h:22
Definition: object.h:221
#define WILL_APPLY_EARTHWALL
Definition: object.h:54
object * part
Definition: map.h:385
void pets_follow_owner(object *ob, object *owner)
Definition: pets.c:293
uint16_t animation_id
Definition: object.h:416
#define NDI_WHITE
Definition: newclient.h:222
void monster_do_living(object *op)
Definition: monster.c:564
#define FLAG_USE_ARMOUR
Definition: define.h:296
#define FLAG_STAND_STILL
Definition: define.h:309
int message_type
Definition: dialog.h:55
void drain_wand_charge(object *wand)
Definition: spell_util.c:829
#define WILL_APPLY_DOOR
Definition: object.h:55
Definition: object.h:112
#define MSG_TYPE_DIALOG_MAGIC_EAR
Definition: newclient.h:467
Definition: object.h:117
#define FLAG_FRIENDLY
Definition: define.h:246
static int monster_get_weapon_quality(const object *item)
Definition: monster.c:1477
sstring stringbuffer_finish_shared(StringBuffer *sb)
Definition: stringbuffer.c:85
#define PACEV2
Definition: define.h:561
sstring message
Definition: dialog.h:54
void fatal(enum fatal_error err)
Definition: utils.c:597
object * mon
Definition: comet_perf.c:74
int8_t range
Definition: object.h:405
#define SP_MOVING_BALL
Definition: spells.h:109
struct obj * who
Definition: dialog.h:52
void pets_move(object *ob)
Definition: pets.c:329
#define SPELL_GRACE
Definition: spells.h:59
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
void get_search_arr(int *search_arr)
Definition: object.c:3518
int32_t last_heal
Definition: object.h:357
#define FLAG_READY_RANGE
Definition: define.h:299
void free_string(sstring str)
Definition: shstr.c:280
static const char * get_reply_text_other(reply_type rt)
Definition: monster.c:2164
int monster_compute_path(object *source, object *target, int default_dir)
Definition: monster.c:393
mapstruct * get_map_from_coord(mapstruct *m, int16_t *x, int16_t *y)
Definition: map.c:2380
const char * object_get_value(const object *op, const char *const key)
Definition: object.c:4266
Definition: object.h:137
sstring replies[MAX_REPLIES]
Definition: dialog.h:58
static object * monster_find_enemy(object *npc, rv_vector *rv)
Definition: monster.c:209
object clone
Definition: object.h:470
int16_t invisible
Definition: object.h:360
short freearr_x[SIZEOFFREE]
Definition: object.c:65
#define MSG_TYPE_DIALOG
Definition: newclient.h:375
int16_t SP_level_spellpoint_cost(object *caster, object *spell, int flags)
Definition: spell_util.c:277
Definition: object.h:119
int isqrt(int n)
Definition: utils.c:586
#define MIN_MON_RADIUS
Definition: monster.c:55
#define IS_WEAPON(op)
Definition: define.h:162
#define FLAG_CONFUSED
Definition: define.h:312
int32_t last_sp
Definition: object.h:358
#define FLAG_STEALTH
Definition: define.h:313
#define FLAG_RANDOM_MOVE
Definition: define.h:310
#define MAX_EXPLORE
Definition: monster.c:375
uint8_t subtype
Definition: object.h:339
sstring replies_words[MAX_REPLIES]
Definition: dialog.h:57
Definition: object.h:109
#define FLAG_USE_WEAPON
Definition: define.h:297
uint8_t hide
Definition: object.h:387
static int monster_cast_spell(object *head, object *part, object *pl, int dir)
Definition: monster.c:1117
char * message
Definition: dialog.h:20
#define OUT_OF_REAL_MAP(M, X, Y)
Definition: map.h:217
int apply_can_apply_object(const object *who, const object *op)
Definition: apply.c:942
#define FLAG_NO_ATTACK
Definition: define.h:363
int8_t get_attr_value(const living *stats, int attr)
Definition: living.c:313
void remove_friendly_object(object *op)
Definition: friend.c:56
#define MSG_TYPE_DIALOG_NPC
Definition: newclient.h:465
#define MAX(x, y)
Definition: compat.h:20
method_ret ob_apply(object *op, object *applier, int aflags)
Definition: ob_methods.c:42
#define CIRCLE1
Definition: define.h:534
int16_t sp
Definition: living.h:42
uint32_t get_weight_limit(int stat)
Definition: living.c:2281
int player_can_view(object *pl, object *op)
Definition: player.c:4130
int path_to_player(object *mon, object *pl, unsigned mindiff)
Definition: player.c:629
#define PETMOVE
Definition: define.h:519
#define AP_APPLY
Definition: define.h:612
uint32_t hidden
Definition: player.h:132
struct obj * enemy
Definition: object.h:381
#define FLAG_USE_RING
Definition: define.h:298
static int monster_talk_to_npc(object *npc, talk_info *info)
Definition: monster.c:2338
int distance_y
Definition: map.h:383
int absdir(int d)
Definition: object.c:3654
#define HITRUN
Definition: define.h:511
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.c:310
Definition: object.h:220
int plugin_event_say(object *npc, talk_info *talk)
Definition: plugins.c:379
static int monster_wait_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv)
Definition: monster.c:1934
int16_t maxsp
Definition: living.h:43
#define MIN(x, y)
Definition: compat.h:17
int8_t Con
Definition: living.h:36
#define FLAG_REMOVED
Definition: define.h:232
int16_t hp
Definition: living.h:40
short freearr_y[SIZEOFFREE]
Definition: object.c:71
static void monster_pace2_moveh(object *ob)
Definition: monster.c:2055
static int monster_dist_att(int dir, object *enemy, object *part, rv_vector *rv)
Definition: monster.c:1881
#define NDI_NAVY
Definition: newclient.h:223
uint16_t height
Definition: map.h:347
#define FLAG_SEE_INVISIBLE
Definition: define.h:253
static void monster_circ1_move(object *ob)
Definition: monster.c:1988
#define FLAG_READY_SKILL
Definition: define.h:334
struct obj * chosen_skill
Definition: object.h:386
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.c:4395
void object_free_drop_inventory(object *ob)
Definition: object.c:1389
int16_t y
Definition: object.h:326
#define RUNATT
Definition: define.h:510
int16_t maxhp
Definition: living.h:41
int dirdiff(int dir1, int dir2)
Definition: object.c:3672
reply_type
Definition: dialog.h:9
#define HI4
Definition: define.h:569
Definition: object.h:118
#define SP_BULLET
Definition: spells.h:79
int replies_count
Definition: dialog.h:56
#define FLAG_ALIVE
Definition: define.h:230
void do_hidden_move(object *op)
Definition: player.c:4021
#define AP_IGNORE_CURSE
Definition: define.h:619
int monster_can_see_enemy(object *op, object *enemy)
Definition: monster.c:2589
static void monster_rand_move(object *ob)
Definition: monster.c:2070
int get_randomized_dir(int dir)
Definition: utils.c:439
static int monster_get_armour_quality(const object *item)
Definition: monster.c:1529
#define MAX_REPLIES
Definition: dialog.h:44
int object_can_pick(const object *who, const object *item)
Definition: object.c:3810
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2707
signed short int16_t
Definition: win32.h:160
#define FLAG_READY_SCROLL
Definition: define.h:325
int32_t weight
Definition: object.h:365
#define FLAG_CAN_USE_SKILL
Definition: define.h:322
#define MOVE_FLY_LOW
Definition: define.h:408
uint32_t tmp_invis
Definition: player.h:125
void drain_rod_charge(object *rod)
Definition: spell_util.c:819
#define SP_BOMB
Definition: spells.h:82
int8_t Wis
Definition: living.h:36
const char * text
Definition: dialog.h:53
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
#define FLAG_USE_SHIELD
Definition: define.h:237
static StringBuffer * monster_format_say(const object *npc, const char *message)
Definition: monster.c:2131
#define FLAG_USE_RANGE
Definition: define.h:293
struct mapdef * map
Definition: object.h:297
#define snprintf
Definition: win32.h:46
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
Definition: map.c:487
void monster_do_say(const mapstruct *map, const char *message)
Definition: monster.c:2120
static int monster_check_good_weapon(object *who, object *item)
Definition: monster.c:1503
object * get_nearest_player(object *mon)
Definition: player.c:520
int pets_should_arena_attack(object *pet, object *owner, object *target)
Definition: pets.c:1152
#define WILL_APPLY_TREASURE
Definition: object.h:53
#define FOR_INV_FINISH()
Definition: define.h:714
int16_t dam
Definition: living.h:46
Definition: object.h:145
int32_t carrying
Definition: object.h:367
#define PACEH
Definition: define.h:542
void monster_check_apply_all(object *monster)
Definition: monster.c:1844
object * monster_find_nearest_living_creature(object *npc)
Definition: monster.c:152
const char * name
Definition: object.h:311
static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv)
Definition: monster.c:996
static int monster_wait_att2(int dir, rv_vector *rv)
Definition: monster.c:1978
static void monster_pace2_movev(object *ob)
Definition: monster.c:2040
int distance_x
Definition: map.h:382
#define MSG_TYPE_COMMUNICATION_SAY
Definition: newclient.h:618
void ext_info_map_except(int color, const mapstruct *map, const object *op, uint8_t type, uint8_t subtype, const char *str1)
Definition: info.c:185
#define SP_SMITE
Definition: spells.h:84
int is_true_undead(object *op)
Definition: player.c:3957
#define MSG_TYPE_COMMUNICATION
Definition: newclient.h:386
object * monster_find_throw_ob(object *op)
Definition: monster.c:2367
void monster_communicate(object *op, const char *txt)
Definition: monster.c:2202
#define GET_MAP_LIGHT(M, X, Y)
Definition: map.h:165
#define FLAG_PARALYZED
Definition: define.h:380
int8_t direction
Definition: object.h:334
#define AP_NOPRINT
Definition: define.h:623
void monster_check_earthwalls(object *op, mapstruct *m, int x, int y)
Definition: monster.c:2090
static object * monster_choose_random_spell(object *monster)
Definition: monster.c:1079
#define SIZEOFFREE
Definition: define.h:154
#define P_OUT_OF_MAP
Definition: map.h:251
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:192
int do_skill(object *op, object *part, object *skill, int dir, const char *string)
Definition: skill_util.c:428
static int monster_disthit_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv)
Definition: monster.c:1959
struct pl * contr
Definition: object.h:276
#define FLAG_SCARED
Definition: define.h:271
uint8_t darkness
Definition: map.h:346
#define SP_INVISIBLE
Definition: spells.h:93
#define MSG_TYPE_SKILL_FAILURE
Definition: newclient.h:585
static int monster_move_randomly(object *op)
Definition: monster.c:342
#define FLAG_ONLY_ATTACK
Definition: define.h:311
#define FLAG_XRAYS
Definition: define.h:301
void use_trigger(object *op)
Definition: button.c:259
#define ATNR_PHYSICAL
Definition: attack.h:49
static void monster_pace_moveh(object *ob)
Definition: monster.c:2027
object * object_find_by_type_and_race(const object *who, int type, const char *race)
Definition: object.c:4044
#define AT_PHYSICAL
Definition: attack.h:76
float speed
Definition: object.h:328
Definition: object.h:214
int on_same_map(const object *op1, const object *op2)
Definition: map.c:2650
#define CAN_APPLY_NOT_MASK
Definition: define.h:669
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
#define HEAD(op)
Definition: object.h:592
#define FLAG_WIZ
Definition: define.h:231
#define MAX_BUF
Definition: define.h:35
#define SP_SWARM
Definition: spells.h:110
#define IS_SHIELD(op)
Definition: define.h:169
Definition: object.h:126
int fire_bow(object *op, object *arrow, int dir, int wc_mod, int16_t sx, int16_t sy)
Definition: player.c:2166
#define FLAG_CAST_SPELL
Definition: define.h:291
int16_t x
Definition: object.h:326
#define FLAG_BERSERK
Definition: define.h:359
void skill_attack(object *tmp, object *pl, int dir, const char *string, object *skill)
Definition: skill_util.c:1239
#define WAITATT
Definition: define.h:512
static int monster_use_range(object *head, object *part, object *pl, int dir)
Definition: monster.c:1344
#define FLAG_RUN_AWAY
Definition: define.h:280
Definition: dialog.h:10
int8_t wc
Definition: living.h:37
unsigned short uint16_t
Definition: win32.h:163
#define ALLRUN
Definition: define.h:514
#define FLAG_IS_THROWN
Definition: define.h:249
#define FOR_MAP_FINISH()
Definition: define.h:767
int8_t Str
Definition: living.h:36
void animate_object(object *op, int dir)
Definition: anim.c:212
int16_t resist[NROFATTACKS]
Definition: object.h:341
int has_carried_lights(const object *op)
Definition: los.c:315
const char * sstring
Definition: global.h:40
void monster_check_doors(object *op, mapstruct *m, int x, int y)
Definition: monster.c:2106
unsigned int uint32_t
Definition: win32.h:162
Definition: object.h:107
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Definition: object.c:4215
#define RUSH
Definition: define.h:513
int8_t body_info[NUM_BODY_LOCATIONS]
Definition: object.h:372
#define WAIT2
Definition: define.h:516
#define FLAG_GENERATOR
Definition: define.h:248
struct obj * spellitem
Definition: object.h:394
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
Definition: object.c:2478
#define FLAG_BLIND
Definition: define.h:337
#define WILL_APPLY_HANDLE
Definition: object.h:52
#define FLAG_NEUTRAL
Definition: define.h:362
static const char * get_reply_text_own(reply_type rt)
Definition: monster.c:2146
#define RANDOM()
Definition: define.h:681
#define MAX_NPC
Definition: dialog.h:46
int16_t grace
Definition: living.h:44
Definition: object.h:143
static int monster_use_bow(object *head, object *part, object *pl, int dir)
Definition: monster.c:1420
static void monster_check_apply(object *mon, object *item)
Definition: monster.c:1585
tag_t count
Definition: object.h:299
living stats
Definition: object.h:368
struct archt * arch
Definition: object.h:412
#define RANDO2
Definition: define.h:557
uint8_t will_apply
Definition: object.h:392
static int monster_move_no_enemy(object *op)
Definition: monster.c:627
uint16_t width
Definition: map.h:347
unsigned int distance
Definition: map.h:381
uint8_t type
Definition: object.h:338
void object_set_enemy(object *op, object *enemy)
Definition: object.c:710
int direction
Definition: map.h:384
static int monster_use_skill(object *head, object *part, object *pl, int dir)
Definition: monster.c:1287
#define SP_MAGIC_MISSILE
Definition: spells.h:85
void monster_npc_call_help(object *op)
Definition: monster.c:1854
#define FLAG_APPLIED
Definition: define.h:235
#define NROFATTACKS
Definition: attack.h:17
int move_object(object *op, int dir)
Definition: move.c:39
signed int int32_t
Definition: win32.h:159
#define SIZEOFFREE2
Definition: define.h:153
#define SP_SUMMON_MONSTER
Definition: spells.h:101
struct struct_dialog_reply * replies
Definition: dialog.h:31
static int monster_run_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv)
Definition: monster.c:1900
object * monster_check_enemy(object *npc, rv_vector *rv)
Definition: monster.c:71
sstring add_string(const char *str)
Definition: shstr.c:124
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.c:104
#define MIN_ACTIVE_SPEED
Definition: define.h:676
#define DISTATT
Definition: define.h:507
int8_t glow_radius
Definition: object.h:364
int monster_move(object *op)
Definition: monster.c:699
#define FLAG_MONSTER
Definition: define.h:245
#define MSG_TYPE_SKILL
Definition: newclient.h:383
static void monster_check_pickup(object *monster)
Definition: monster.c:1702
int8_t Pow
Definition: living.h:36
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
Definition: map.c:300
struct obj * inv
Definition: object.h:290
#define NDI_UNIQUE
Definition: newclient.h:245
#define FLAG_READY_BOW
Definition: define.h:300
sstring npc_msgs[MAX_NPC]
Definition: dialog.h:60
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
int monster_stand_in_light(object *op)
Definition: monster.c:2546
static void monster_pace_movev(object *ob)
Definition: monster.c:2014
void make_visible(object *op)
Definition: player.c:3937
#define SP_MAGIC_WALL
Definition: spells.h:89
uint8_t pick_up
Definition: object.h:361
#define PACEH2
Definition: define.h:545
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:760
uint8_t run_away
Definition: object.h:384
#define IS_ARMOR(op)
Definition: define.h:165
static void monster_apply_below(object *monster)
Definition: monster.c:1821
int can_see_monsterP(mapstruct *m, int x, int y, int dir)
Definition: object.c:3762
#define PACEV
Definition: define.h:558
#define WILL_APPLY_FOOD
Definition: object.h:56
struct struct_dialog_reply * next
Definition: dialog.h:22
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:623
#define SPELL_MANA
Definition: spells.h:58
#define FOR_BELOW_PREPARE(op_, it_)
Definition: define.h:741
static int monster_can_pick(object *monster, object *item)
Definition: monster.c:1740
#define CIRCLE2
Definition: define.h:541
object * find_skill_by_number(object *who, int skillno)
Definition: main.c:351
reply_type type
Definition: dialog.h:21
Definition: map.h:325
#define P_IS_ALIVE
Definition: map.h:237
object * pets_get_enemy(object *pet, rv_vector *rv)
Definition: pets.c:57
const New_Face * face
Definition: object.h:332
Definition: object.h:167
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Definition: attack.c:1871
int get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
Definition: map.c:2539
void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1)
Definition: main.c:325
int32_t move_status
Definition: object.h:390
int16_t level
Definition: object.h:351
int8_t facing
Definition: object.h:335
#define SP_SUMMON_GOLEM
Definition: spells.h:86
#define SP_EXPLOSION
Definition: spells.h:80
static int monster_do_talk_npc(object *npc, talk_info *info)
Definition: monster.c:2276
struct obj * more
Definition: object.h:295
static void monster_circ2_move(object *ob)
Definition: monster.c:2001
object * object_get_owner(object *op)
Definition: object.c:590
int8_t magic
Definition: object.h:348
#define FLAG_USE_BOW
Definition: define.h:294
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
#define FOR_BELOW_FINISH()
Definition: define.h:748
int monster_can_detect_enemy(object *op, object *enemy, rv_vector *rv)
Definition: monster.c:2406
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:707
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Definition: spell_util.c:1471
void object_remove(object *op)
Definition: object.c:1669
#define DISTHIT
Definition: define.h:515
#define MAX_KNOWN_SPELLS
Definition: monster.c:1062
struct obj * attacked_by
Definition: object.h:382
#define FLAG_FREED
Definition: define.h:233
static int monster_check_wakeup(object *op, object *enemy, rv_vector *rv)
Definition: monster.c:296
#define LO4
Definition: define.h:568