Crossfire Server, Trunk
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 #include "minheap.h"
30 
31 static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv);
32 static int monster_cast_spell(object *head, object *part, object *pl, int dir);
33 static int monster_use_scroll(object *head, object *part, object *pl, int dir);
34 static int monster_use_skill(object *head, object *part, object *pl, int dir);
35 static int monster_use_range(object *head, object *part, object *pl, int dir);
36 static int monster_use_bow(object *head, object *part, object *pl, int dir);
37 static void monster_check_pickup(object *monster);
38 static int monster_can_pick(object *monster, object *item);
39 static void monster_apply_below(object *monster);
40 static int monster_dist_att(int dir, object *enemy, object *part, rv_vector *rv);
41 static int monster_run_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv);
42 static int monster_hitrun_att(int dir, object *ob);
43 static int monster_wait_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv);
44 static int monster_disthit_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv);
45 static int monster_wait_att2(int dir, rv_vector *rv);
46 static void monster_circ1_move(object *ob);
47 static void monster_circ2_move(object *ob);
48 static void monster_pace_movev(object *ob);
49 static void monster_pace_moveh(object *ob);
50 static void monster_pace2_movev(object *ob);
51 static void monster_pace2_moveh(object *ob);
52 static void monster_rand_move(object *ob);
53 static int monster_talk_to_npc(object *npc, talk_info *info);
54 
56 #define MIN_MON_RADIUS 3
57 
72 object *monster_check_enemy(object *npc, rv_vector *rv) {
73  object *owner;
74 
75  /* if this is pet, let him attack the same enemy as his owner
76  * TODO: when there is no ower enemy, try to find a target,
77  * which CAN attack the owner. */
78  owner = object_get_owner(npc);
79  if ((npc->attack_movement&HI4) == PETMOVE) {
80  if (owner == NULL)
81  object_set_enemy(npc, NULL);
82  else if (npc->enemy == NULL)
83  object_set_enemy(npc, owner->enemy);
84  }
85 
86  /* periodically, a monster may change its target. Also, if the object
87  * has been destroyed, etc, clear the enemy.
88  * TODO: this should be changed, because it invokes to attack forced or
89  * attacked monsters to leave the attacker alone, before it is destroyed
90  */
91  /* i had removed the random target leave, this invokes problems with friendly
92  * objects, getting attacked and defending herself - they don't try to attack
93  * again then but perhaps get attack on and on
94  * If we include a aggravated flag in , we can handle evil vs evil and good vs good
95  * too. */
96 
97  if (npc->enemy && !object_value_set(npc, "is_guard")) {
98  /* I broke these if's apart to better be able to see what
99  * the grouping checks are. Code is the same.
100  */
101  if (QUERY_FLAG(npc->enemy, FLAG_REMOVED)
102  || QUERY_FLAG(npc->enemy, FLAG_FREED)
103  || !on_same_map(npc, npc->enemy)
104  || npc == npc->enemy
106  || QUERY_FLAG(npc->enemy, FLAG_NEUTRAL))
107  object_set_enemy(npc, NULL);
108 
109  else if (QUERY_FLAG(npc, FLAG_FRIENDLY) && (
110  (QUERY_FLAG(npc->enemy, FLAG_FRIENDLY) && !pets_should_arena_attack(npc, owner, npc->enemy))
111  || (npc->enemy->type == PLAYER && !pets_should_arena_attack(npc, owner, npc->enemy))
112  || npc->enemy == owner))
113  object_set_enemy(npc, NULL);
114  else if (!QUERY_FLAG(npc, FLAG_FRIENDLY)
115  && (!QUERY_FLAG(npc->enemy, FLAG_FRIENDLY) && npc->enemy->type != PLAYER))
116  object_set_enemy(npc, NULL);
117 
118  /* I've noticed that pets could sometimes get an arrow as the
119  * target enemy - this code below makes sure the enemy is something
120  * that should be attacked. My guess is that the arrow hits
121  * the creature/owner, and so the creature then takes that
122  * as the enemy to attack.
123  */
124  else if (!QUERY_FLAG(npc->enemy, FLAG_MONSTER)
125  && !QUERY_FLAG(npc->enemy, FLAG_GENERATOR)
126  && npc->enemy->type != PLAYER
127  && npc->enemy->type != GOLEM)
128  object_set_enemy(npc, NULL);
129  }
130  return monster_can_detect_enemy(npc, npc->enemy, rv) ? npc->enemy : NULL;
131 }
132 
142 static int is_enemy(object *who, object *owner) {
143  if (who == owner) {
144  return 0;
145  }
146  if (!QUERY_FLAG(who, FLAG_MONSTER) && !QUERY_FLAG(who, FLAG_GENERATOR) && who->type != PLAYER) {
147  return 0;
148  }
149  if (QUERY_FLAG(who, FLAG_MONSTER) && owner && object_get_owner(who) == owner) {
150  return 0;
151  }
152  if (who->type == PLAYER && owner && owner->type == PLAYER) {
153  if (owner->contr->peaceful && who->contr->peaceful) {
154  return 0;
155  }
156  }
157  return 1;
158 }
159 
175 object *monster_find_nearest_enemy(object *npc, object *owner) {
176  int i, mflags;
177  int16_t nx, ny;
178  mapstruct *m;
179  int search_arr[SIZEOFFREE];
180 
181  get_search_arr(search_arr);
182  for (i = 0; i < SIZEOFFREE; i++) {
183  /* modified to implement smart searching using search_arr
184  * guidance array to determine direction of search order
185  */
186  nx = npc->x+freearr_x[search_arr[i]];
187  ny = npc->y+freearr_y[search_arr[i]];
188  m = npc->map;
189 
190  if (nx == npc->x && ny == npc->y) {
191  continue; // Don't try to attack ourself
192  }
193 
194  mflags = get_map_flags(m, &m, nx, ny, &nx, &ny);
195  if (mflags&P_OUT_OF_MAP)
196  continue;
197 
198  if (mflags&P_IS_ALIVE) {
199  object *creature;
200 
201  creature = NULL;
202  FOR_MAP_PREPARE(m, nx, ny, tmp)
203  if (is_enemy(tmp, owner)) {
204  creature = tmp;
205  break;
206  }
207  FOR_MAP_FINISH();
208  if (!creature) {
209  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);
210  } else {
211  if (can_see_monsterP(m, npc->x, npc->y, i))
212  return creature;
213  }
214  } /* is something living on this space */
215  }
216  return NULL; /* nothing found */
217 }
218 
234 static object *monster_find_enemy(object *npc, rv_vector *rv) {
235  object *attacker, *tmp = NULL;
236 
237  attacker = npc->attacked_by; /* save this for later use. This can be a attacker. */
238  npc->attacked_by = NULL; /* always clear the attacker entry */
239 
240  /* if we berserk, we don't care about others - we attack all we can find */
241  if (QUERY_FLAG(npc, FLAG_BERSERK)) {
243  if (tmp == NULL)
244  return NULL;
245  if (!get_rangevector(npc, tmp, rv, 0))
246  return NULL;
247  return tmp;
248  }
249 
250  /* Here is the main enemy selection.
251  * We want this: if there is an enemy, attack him until its not possible or
252  * one of both is dead.
253  * If we have no enemy and we are...
254  * a monster: try to find a player, a pet or a friendly monster
255  * a friendly: only target a monster which is targeting you first or targeting a player
256  * a neutral: fight a attacker (but there should be none), then do nothing
257  * a pet: attack player enemy or a monster
258  */
259 
260  /* pet move */
261  if ((npc->attack_movement&HI4) == PETMOVE) {
262  tmp = pets_get_enemy(npc, rv);
263  if (tmp == NULL)
264  return NULL;
265  if (!get_rangevector(npc, tmp, rv, 0))
266  return NULL;
267  return tmp;
268  }
269 
270  /* we check our old enemy. */
271  tmp = monster_check_enemy(npc, rv);
272  if (tmp == NULL) {
273  if (attacker) { /* if we have an attacker, check him */
274  /* we want be sure this is the right one! */
275  if (attacker->count == npc->attacked_by_count) {
276  /* TODO: thats not finished */
277  /* we don't want a fight evil vs evil or good against non evil */
279  || QUERY_FLAG(attacker, FLAG_NEUTRAL) /* neutral */
281  || (!QUERY_FLAG(npc, FLAG_FRIENDLY) && (!QUERY_FLAG(attacker, FLAG_FRIENDLY) && attacker->type != PLAYER)))
282  CLEAR_FLAG(npc, FLAG_SLEEP); /* skip it, but lets wakeup */
283  else if (on_same_map(npc, attacker)) { /* thats the only thing we must know... */
284  CLEAR_FLAG(npc, FLAG_SLEEP); /* well, NOW we really should wake up! */
285  object_set_enemy(npc, attacker);
286  if (!get_rangevector(npc, attacker, rv, 0))
287  return NULL;
288  return attacker; /* yes, we face our attacker! */
289  }
290  }
291  }
292 
293  if (object_value_set(npc, "is_guard")) {
295  if (npc->enemy) {
296  char buf[MAX_BUF];
297  snprintf(buf, sizeof(buf), "Halt, %s, you are under arrest!", npc->enemy->name);
299  tmp = monster_check_enemy(npc, rv);
300  }
301  } else {
302  /* we have no legal enemy or attacker, so we try to target a new one */
305  && !QUERY_FLAG(npc, FLAG_NEUTRAL)) {
307  if (npc->enemy)
308  tmp = monster_check_enemy(npc, rv);
309  }
310  }
311  }
312 
313  return tmp;
314 }
315 
331 static int monster_check_wakeup(object *op, object *enemy, rv_vector *rv) {
332  int radius = MAX(op->stats.Wis, MIN_MON_RADIUS);
333 
334  /* Trim work - if no enemy, no need to do anything below */
335  if (!enemy)
336  return 0;
337 
338  /* blinded monsters can only find nearby objects to attack */
339  if (QUERY_FLAG(op, FLAG_BLIND))
340  radius = MIN_MON_RADIUS;
341 
342  /* This covers the situation where the monster is in the dark
343  * and has an enemy. If the enemy has no carried light (or isnt
344  * glowing!) then the monster has trouble finding the enemy.
345  * Remember we already checked to see if the monster can see in
346  * the dark. */
347  else if (op->map
348  && op->map->darkness > 0
349  && enemy
350  && !enemy->invisible
351  && !monster_stand_in_light(enemy)
353  int dark = radius/(op->map->darkness);
354 
355  radius = (dark > MIN_MON_RADIUS) ? (dark+1) : MIN_MON_RADIUS;
356  } else if (!QUERY_FLAG(op, FLAG_SLEEP))
357  return 1;
358 
359  /* enemy should already be on this map, so don't really need to check
360  * for that.
361  */
362  if (rv->distance < (unsigned)(QUERY_FLAG(enemy, FLAG_STEALTH) ? radius/2+1 : radius)) {
364  return 1;
365  }
366  return 0;
367 }
368 
377 static int monster_move_randomly(object *op) {
378  int i;
379  sstring talked;
380  char value[2];
381 
382  /* timeout before moving */
384  talked = object_get_value(op, "talked_to");
385  if (talked && strlen(talked) > 0) {
386  i = atoi(talked);
387  i--;
388 
389  if (i != 0) {
390  value[1] = '\0';
391  value[0] = '0' + i;
392  object_set_value(op, "talked_to", value, 1);
393  return 1;
394  }
395 
396  /* finished timeout talked to */
397  object_set_value(op, "talked_to", "", 1);
398  }
399  }
400 
401  /* Give up to 15 chances for a monster to move randomly */
402  for (i = 0; i < 15; i++) {
403  if (move_object(op, RANDOM()%8+1))
404  return 1;
405  }
406  return 0;
407 }
408 
410 #define MAX_EXPLORE 5000
411 
415 typedef struct {
416  int16_t x;
417  int16_t y;
418  uint16_t distance;
419  uint16_t heuristic_dist;
420  // This way we only have to calculate penalties once per tile per pathing calculation.
422 } path_data;
423 
433 int path_measure_func(const void *ob) {
434  const path_data *dat = (path_data *)ob;
435  return dat->distance + dat->heuristic_dist;
436 }
437 
443 static inline uint16_t estimate_distance(int16_t ax, int16_t ay, int16_t bx, int16_t by) {
444  uint16_t dx = FABS(ax - bx), dy = FABS(ay - by);
445  uint16_t diag = MIN(dx, dy);
446  return (MAX(dx, dy) - diag) * 2 + diag * 3;
447 }
448 
465 int monster_compute_path(object *source, object *target, int default_dir) {
466  path_data *distance, *current, *explore;
467  path_data *heaparr[MAX_EXPLORE];
468  int dirs[8];
469  int dir, x, y, i;
470  MinHeap heap;
471 
472  if (target->map != source->map)
473  return default_dir;
474 
475  // These shouldn't change during the calculation, so store them once to avoid dereferencing.
476  mapstruct * cur_map = source->map; // Not constant to silence some warnings.
477  const uint16_t map_height = cur_map->height;
478  /*printf("monster_compute_path (%d, %d) => (%d, %d)\n", source->x, source->y, target->x, target->y);*/
479 
480  // Leave width like this because it is used just this once.
481  const int size = cur_map->width * map_height;
482 
483  // Determine the amount by which terrain is over or under valued by the monster.
484  /* terrain value is as follows:
485  * 0 - ignore terrain penalties
486  * 1 - undervalue terrain penalties by half
487  * 2 - correctly value terrain penalties
488  * 3 - overvalue terrain penalties by 50%
489  */
490  int terrain_value;
491  if (source->attack_movement & RUSH)
492  terrain_value = 0;
493  else if (source->stats.Int < 8) {
494  terrain_value = 0;
495  }
496  else if (source->stats.Int < 13) {
497  // If low Wis, then over-value terrain penalties.
498  // Otherwise, under-value terrain penalties.
499  if (source->stats.Wis < 13) {
500  terrain_value = 3;
501  }
502  else {
503  terrain_value = 1;
504  }
505  }
506  else {
507  terrain_value = 2;
508  }
509 
520  if (!source->more) // Skip multitile monsters, since this does not work right for them
521  {
522  dir = -1; // Set a sentinel. -1 = no escape, 0 = many ways out, [1, 8] = one way out in dir
523  for (i = 1; i <= 8; ++i)
524  {
525  x = source->x + freearr_x[i];
526  y = source->y + freearr_y[i];
527  if (OUT_OF_REAL_MAP(cur_map, x, y))
528  continue;
529  if (ob_blocked(source, cur_map, x, y))
530  continue;
531  // We have a way out. Make note of it
532  if (dir < 0)
533  dir = i;
534  // We have many ways out -- do the pathing part of the function
535  else
536  {
537  dir = 0;
538  break;
539  }
540  }
541  // If dir > 0, we have our direction to go, as it is our only choice.
542  if (dir > 0)
543  return dir;
544  // If dir < 0, then we have no way to go. Return default_dir.
545  if (dir < 0)
546  return default_dir;
547  }
548 
549  /* We are setting all the values manually anyway,
550  * so there's no reason to use calloc().
551  * malloc() is more efficient here for that reason.
552  */
553  distance = malloc(size * sizeof(*distance));
554  if (distance == NULL) {
556  }
557  /*
558  * To set to 65535 efficiently, though, I need to memset each byte to 255.
559  * each element is multiple bytes, and this will fill the non-distance values, too.
560  */
561  memset(distance, 255, sizeof(*distance) * size);
562 
563  // Set current to the starting point.
564  current = &distance[map_height * target->x + target->y];
565 
566  current->distance = 0;
567  current->x = target->x;
568  current->y = target->y;
569  current->heuristic_dist = 0;
570  current->movement_penalty = 0;
571 
572  // Initialize the minheap
573  minheap_init_static(&heap, (void **)heaparr, MAX_EXPLORE, path_measure_func);
574 
575  /* The first time through, current = 0 and max = 1.
576  * This will evaluate to true, so we might as well use a do-while loop.
577  */
578  do {
579  /* Fisher–Yates shuffle the directions, "inside-out" algorithm
580  * from http://en.wikipedia.org/wiki/Fisher-Yates_shuffle */
581  dirs[0] = 1;
582  for (i = 1; i < 8; ++i) {
583  x = RANDOM() % (i+1);
584  dirs[i] = dirs[x];
585  dirs[x] = i+1;
586  }
587 
588  for (i = 0; i < 8; ++i) {
589  uint16_t new_distance;
590 
591  /*
592  * dirs[i] is the direction we wish to check.
593  */
594  dir = absdir(default_dir+4+dirs[i]);
595  x = current->x+freearr_x[dir];
596  y = current->y+freearr_y[dir];
597 
598  if (x == source->x && y == source->y) {
599  // Randomly decide to bob/weave on some steps if not RUSH movement.
600  // When not in RUSH mode, 1/4 chance of bob/weaving
601  if (source->attack_movement != RUSH && (RANDOM() & 3) == 0) {
602  // We take the perspective of the source when determining our dodge/weave direction,
603  // incorporating the required dir+4 reversal immediately.
604  int newdir = absdir(dir+4+1-(RANDOM()&2)); // Bob/weave up to one space.
605  int newx = source->x+freearr_x[newdir],
606  newy = source->y+freearr_y[newdir];
607  const path_data *newloc = &distance[map_height * newx + newy];
608  // If we checked the tile during pathing and it is not a wall and the movement penalty of the tile
609  // is not greater than the shortest-path's movement penalty, then go to that space.
610  if (newloc->distance != 65535 && newloc->distance != 1 &&
611  newloc->movement_penalty <= current->movement_penalty)
612  dir = newdir; // Commit to the bob/weave
613  else
614  dir = absdir(dir + 4);
615  }
616  // Otherwise, just follow the path we were given.
617  else
618  dir = absdir(dir + 4);
619  free(distance);
620  return dir;
621  }
622 
623  if (OUT_OF_REAL_MAP(cur_map, x, y))
624  continue;
625 
626  // Move these up, so we can reduce calls to ob_blocked with their info.
627  assert(map_height * x + y >= 0);
628  assert(map_height * x + y < size);
629 
630  // Set a pointer to the tile we are exploring.
631  explore = &distance[map_height * x + y];
632 
633  // Penalty-less spaces are handled by the inline if in the new_distance assignment.
634  // We can have move_penalty be zero because it assumes the penalty-less cost is already accounted for.
635  int16_t move_penalty = 0;
636  // Skip the penalty search if terrain value is zero. We will ignore any move penalty anyway.
637  if (terrain_value > 0) {
638  // Only calculate movement penalty if this tile does not have it yet.
639  if (explore->movement_penalty == -1) {
640  // Sum the move_slow_penalties on the map space.
641  object *tmp = GET_MAP_OB(cur_map, x, y);
643  if ((!source->move_type && tmp->move_slow&MOVE_WALK)
644  || ((source->move_type&tmp->move_slow) && (source->move_type&~tmp->move_slow&~tmp->move_block) == 0)) {
645  move_penalty += (int16_t)tmp->move_slow_penalty;
646  }
648  // And, make sure to store this for when we bump into this tile again
649  explore->movement_penalty = move_penalty;
650  }
651  else {
652  move_penalty = explore->movement_penalty;
653  }
654  }
655 
656  /* Mod 2 is equivalent to checking only the 1's bit (1 or 0), but & 1 is faster.
657  * Also, dir & 1 == 0 is true if we have a diagonal dir.
658  */
659  const int base_move_cost = ((dir & 1) == 0 ? 3 : 2);
660 
661  new_distance =
662  current->distance
663  // If terrain value is zero, we will ignore movement_penalties.
664  // If move_penalty is 0, then there were no penalties for moving onto this space.
665  + (move_penalty != 0 && terrain_value != 0 ? base_move_cost + base_move_cost * move_penalty * terrain_value / 2 : base_move_cost);
666 
667  // If already known blocked or arrivable in less distance, we skip
668  if (explore->distance <= new_distance)
669  continue;
670  // If we have a non-default value here, we will have lready done ob_blocked on it.
671  // So, only call ob_blocked if we are staring at 65535.
672  // If we are not looking at an untested space, then we will skip this block and avoid ob_blocked
673  if (explore->distance == 65535 && ob_blocked(source, cur_map, x, y))
674  {
675  // Mark as something we can't otherwise get -- the goal is to cache what spaces are blocked.
676  // At least, this call to monster_compute_path will remember this spot is blocked.
677  // This should cut our calls to ob_blocked some.
678  explore->distance = 1;
679  // The value of 1 also allows for walls to be considered already checked, but since we do not add to the
680  // explore array, this makes them hit the condition above if they are checked again without going through walls.
681  continue;
682  }
683 
684  /*LOG(llevDebug, "check %d, %d dist = %d, nd = %d\n", x, y, distance[source->map->height*x+y], new_distance);*/
685 
686  // Only set x and y when we insert into the minheap.
687  explore->x = x;
688  explore->y = y;
689  explore->distance = new_distance;
690  explore->heuristic_dist = estimate_distance(x, y, source->x, source->y); // Add a heuristic to make this A*.
691  /* printf("explore[%d] => (%d, %d) %u\n", max, x, y, new_distance);*/
692 
693  // TODO: If the space has already been evaluated, we'd really want to do an in-place update, not an insert.
694 
695  // If the heap is full when we try to insert, then we have exhausted exploration space.
696  if (minheap_insert(&heap, explore) != 0) {
697  free(distance);
698  return default_dir;
699  }
700  }
701  current = minheap_remove(&heap);
702  } while (current != NULL);
703 
704  /*LOG(llevDebug, "no path\n");*/
705  free(distance);
706  return default_dir;
707 }
708 
715 void monster_do_living(object *op) {
716  assert(op);
717  assert(QUERY_FLAG(op, FLAG_MONSTER));
718 
719  /* generate hp, if applicable */
720  if (op->stats.Con > 0 && op->stats.hp < op->stats.maxhp) {
721  /* last heal is in funny units. Dividing by speed puts
722  * the regeneration rate on a basis of time instead of
723  * #moves the monster makes. The scaling by 8 is
724  * to capture 8th's of a hp fraction regens
725  *
726  * Cast to int32_t before comparing to maxhp since otherwise an (int16_t)
727  * overflow might produce monsters with negative hp.
728  */
729 
730  op->last_heal += (int)((float)(8*op->stats.Con)/FABS(op->speed));
731  op->stats.hp = MIN((int32_t)op->stats.hp+op->last_heal/32, op->stats.maxhp); /* causes Con/4 hp/tick */
732  op->last_heal %= 32;
733 
734  /* So if the monster has gained enough HP that they are no longer afraid */
736  && op->stats.hp >= (int16_t)((int32_t)op->run_away * op->stats.maxhp / 100))
738  /*
739  * This should already be covered by the MIN() check above.
740 
741  if (op->stats.hp > op->stats.maxhp)
742  op->stats.hp = op->stats.maxhp;
743  */
744  }
745 
746  /* generate sp, if applicable */
747  if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp) {
748  /* last_sp is in funny units. Dividing by speed puts
749  * the regeneration rate on a basis of time instead of
750  * #moves the monster makes. The scaling by 8 is
751  * to capture 8th's of a sp fraction regens
752  *
753  * Cast to int32_t before comparing to maxhp since otherwise an (int16_t)
754  * overflow might produce monsters with negative sp.
755  */
756 
757  op->last_sp += (int)((float)(8*op->stats.Pow)/FABS(op->speed));
758  op->stats.sp = MIN(op->stats.sp+op->last_sp/128, op->stats.maxsp); /* causes Pow/16 sp/tick */
759  op->last_sp %= 128;
760  }
761 
762  /* this should probably get modified by many more values.
763  * (eg, creatures resistance to fear, level, etc. )
764  */
765  if (QUERY_FLAG(op, FLAG_SCARED) && !(RANDOM()%20)) {
766  CLEAR_FLAG(op, FLAG_SCARED); /* Time to regain some "guts"... */
767  }
768 }
769 
778 static int monster_move_no_enemy(object *op) {
779  assert(QUERY_FLAG(op, FLAG_MONSTER));
780 
782  object_remove(op);
784  return 1;
785  }
786 
787  /* Probably really a bug for a creature to have both
788  * stand still and a movement type set.
789  */
790  if (!QUERY_FLAG(op, FLAG_STAND_STILL)) {
791  if (op->attack_movement&HI4) {
792  switch (op->attack_movement&HI4) {
793  case PETMOVE:
794  pets_move(op);
795  break;
796 
797  case CIRCLE1:
799  break;
800 
801  case CIRCLE2:
803  break;
804 
805  case PACEV:
807  break;
808 
809  case PACEH:
811  break;
812 
813  case PACEV2:
815  break;
816 
817  case PACEH2:
819  break;
820 
821  case RANDO:
823  break;
824 
825  case RANDO2:
827  break;
828  }
829  return 0;
830  }
831 
834  } /* stand still */
835 
836  return 0;
837 }
838 
850 int monster_move(object *op) {
851  int dir, diff;
852  object *owner, *enemy, *part;
853  rv_vector rv;
854 
855  /* Monsters not on maps don't do anything. These monsters are things
856  * Like royal guards in city dwellers inventories.
857  */
858  if (!op->map)
859  return 0;
860 
861  if (QUERY_FLAG(op, FLAG_NO_ATTACK)) { /* we never ever attack */
862  object_set_enemy(op, NULL);
863  enemy = NULL;
864  } else {
865  enemy = monster_find_enemy(op, &rv);
866  if (enemy != NULL) {
867  /* we have an enemy, just tell him we want him dead */
868  enemy->attacked_by = op; /* our ptr */
869  enemy->attacked_by_count = op->count; /* our tag */
870  }
871  }
872 
874 
875  if (QUERY_FLAG(op, FLAG_SLEEP)
877  || (op->map->darkness > 0 && !QUERY_FLAG(op, FLAG_SEE_IN_DARK) && !QUERY_FLAG(op, FLAG_SEE_INVISIBLE))) {
878  if (!monster_check_wakeup(op, enemy, &rv))
879  return 0;
880  }
881 
882  /* check if monster pops out of hidden spot */
883  if (op->hide)
885 
886  if (op->pick_up)
888 
889  if (op->will_apply)
890  monster_apply_below(op); /* Check for items to apply below */
891 
892  // Can happen due to monster_apply_below().
893  if (QUERY_FLAG(op, FLAG_REMOVED)) {
894  return 1;
895  }
896 
897  /* If we don't have an enemy, do special movement or the like */
898  if (!enemy) {
899  return monster_move_no_enemy(op);
900  } /* no enemy */
901 
902  /* We have an enemy. Block immediately below is for pets */
903  if ((op->attack_movement&HI4) == PETMOVE) {
904  owner = object_get_owner(op);
905  if (owner != NULL && !on_same_map(op, owner)) {
906  pets_follow_owner(op, owner);
907  /* If the pet was unable to follow the owner, free it */
908  if (QUERY_FLAG(op, FLAG_REMOVED) && FABS(op->speed) > MIN_ACTIVE_SPEED) {
911  return 1;
912  }
913  return 0;
914  }
915  }
916 
917  /* doppleganger code to change monster facing to that of the nearest
918  * player. Hmm. The code is here, but no monster in the current
919  * arch set uses it.
920  */
921  if (op->race != NULL && strcmp(op->race, "doppleganger") == 0) {
922  op->face = enemy->face;
923  if (op->name)
924  free_string(op->name);
925  add_refcount(op->name = enemy->name);
926  }
927 
928  /* Calculate range information for closest body part - this
929  * is used for the 'skill' code, which isn't that smart when
930  * it comes to figuring it out - otherwise, giants throw boulders
931  * into themselves.
932  */
933  if (!get_rangevector(op, enemy, &rv, 0))
934  return 0;
935  if (op->direction != rv.direction) {
936  op->direction = rv.direction;
937  op->facing = op->direction;
938  if (op->animation)
939  animate_object(op, op->direction);
940  }
941 
942  // We are looking at movement -- if monster was paralyzed, they aren't anymore
943  if (QUERY_FLAG(op, FLAG_PARALYZED)) {
945  }
946 
947  /* Move the check for scared up here - if the monster was scared,
948  * we were not doing any of the logic below, so might as well save
949  * a few cpu cycles.
950  */
951  if (!QUERY_FLAG(op, FLAG_SCARED)) {
952  dir = rv.direction;
953 
954  /* Was two if statements assigning to the same variable
955  * We can get the same effect by reversing the order and making an else-if
956  */
958  dir = get_randomized_dir(dir);
959  else if (QUERY_FLAG(op, FLAG_RUN_AWAY))
960  dir = absdir(dir+4);
961 
962  if (QUERY_FLAG(op, FLAG_CAST_SPELL) && !(RANDOM()%3)) {
963  if (monster_cast_spell(op, rv.part, enemy, dir))
964  return 0;
965  }
966 
967  if (QUERY_FLAG(op, FLAG_READY_SCROLL) && !(RANDOM()%3)) {
968  if (monster_use_scroll(op, rv.part, enemy, dir))
969  return 0;
970  }
971 
972  if (QUERY_FLAG(op, FLAG_READY_RANGE) && !(RANDOM()%3)) {
973  if (monster_use_range(op, rv.part, enemy, dir))
974  return 0;
975  }
976  if (QUERY_FLAG(op, FLAG_READY_SKILL) && !(RANDOM()%3)) {
977  if (monster_use_skill(op, rv.part, enemy, rv.direction))
978  return 0;
979  }
980  if (QUERY_FLAG(op, FLAG_READY_BOW) && !(RANDOM()%2)) {
981  if (monster_use_bow(op, rv.part, enemy, dir))
982  return 0;
983  }
984  } /* If not scared */
985 
986 
987  /* code below is for when we didn't use a range attack or a skill, so
988  * either move or hit with hth attack. */
989 
990  part = rv.part;
991  dir = rv.direction;
992 
993  /* This first clause used to happen after the other two, but would trample dir.
994  * Moved to before them as another check to slightly reduce calls to monster_compute_path
995  */
997  dir = get_randomized_dir(dir);
999  dir = absdir(dir+4);
1000  else if (!monster_can_hit(part, enemy, &rv)) {
1001  dir = monster_compute_path(op, enemy, -1);
1002  if (dir == -1) {
1003  // Can't reach enemy, so remove it, attempt to move in its last direction so not stay still
1004  LOG(llevMonster, "monster %s (%d, %d on %s) can't reach enemy %s (%d, %d on %s)\n",
1005  op->name, op->x, op->y, op->map ? op->map->name : "(unknown map)", enemy->name, enemy->x, enemy->y, enemy->map ? enemy->map->path : "(unknown map)");
1006  object_set_enemy(op, NULL);
1007  dir = rv.direction;
1008  }
1009  }
1010 
1011  if ((op->attack_movement&LO4) && !QUERY_FLAG(op, FLAG_SCARED)) {
1012  switch (op->attack_movement&LO4) {
1013  case DISTATT:
1014  dir = monster_dist_att(dir, enemy, part, &rv);
1015  break;
1016 
1017  case RUNATT:
1018  dir = monster_run_att(dir, op, enemy, part, &rv);
1019  break;
1020 
1021  case HITRUN:
1022  dir = monster_hitrun_att(dir, op);
1023  break;
1024 
1025  case WAITATT:
1026  dir = monster_wait_att(dir, op, enemy, part, &rv);
1027  break;
1028 
1029  case RUSH: /* default - monster normally moves towards player */
1030  case ALLRUN:
1031  break;
1032 
1033  case DISTHIT:
1034  dir = monster_disthit_att(dir, op, enemy, part, &rv);
1035  break;
1036 
1037  case WAIT2:
1038  dir = monster_wait_att2(dir, &rv);
1039  break;
1040 
1041  default:
1042  LOG(llevDebug, "Illegal low mon-move: %d\n", op->attack_movement&LO4);
1043  }
1044  }
1045 
1046  if (!dir)
1047  return 0;
1048 
1049  if (!QUERY_FLAG(op, FLAG_STAND_STILL)) {
1050  if (move_object(op, dir)) /* Can the monster move directly toward player? */
1051  return 0;
1052 
1053  if (QUERY_FLAG(op, FLAG_SCARED)
1054  || !monster_can_hit(part, enemy, &rv)
1055  || QUERY_FLAG(op, FLAG_RUN_AWAY)) {
1056  /* Try move around corners if !close */
1057  int maxdiff = (QUERY_FLAG(op, FLAG_ONLY_ATTACK) || RANDOM()&1) ? 1 : 2;
1058  for (diff = 1; diff <= maxdiff; diff++) {
1059  /* try different detours */
1060  int m = 1-(RANDOM()&2); /* Try left or right first? */
1061  if (move_object(op, absdir(dir+diff*m))
1062  || move_object(op, absdir(dir-diff*m)))
1063  return 0;
1064  }
1065  }
1066  } /* if monster is not standing still */
1067 
1068  /*
1069  * Eneq(@csd.uu.se): Patch to make RUN_AWAY or SCARED monsters move a random
1070  * direction if they can't move away.
1071  */
1075  return 0;
1076 
1077  /*
1078  * Try giving the monster a new enemy - the player that is closest
1079  * to it. In this way, it won't just keep trying to get to a target
1080  * that is inaccessible.
1081  * This could be more clever - it should go through a list of several
1082  * enemies, as it is now, you could perhaps get situations where there
1083  * are two players flanking the monster at close distance, but which
1084  * the monster can't get to, and a third one at a far distance that
1085  * the monster could get to - as it is, the monster won't look at that
1086  * third one.
1087  */
1088  if (!QUERY_FLAG(op, FLAG_FRIENDLY) && enemy == op->enemy) {
1089  object *nearest_player = get_nearest_player(op);
1090 
1091  if (nearest_player && nearest_player != enemy && !monster_can_hit(part, enemy, &rv)) {
1092  object_set_enemy(op, NULL);
1093  enemy = nearest_player;
1094  }
1095  }
1096 
1097  if (!QUERY_FLAG(op, FLAG_SCARED) && monster_can_hit(part, enemy, &rv)) {
1098  /* The adjustement to wc that was here before looked totally bogus -
1099  * since wc can in fact get negative, that would mean by adding
1100  * the current wc, the creature gets better? Instead, just
1101  * add a fixed amount - nasty creatures that are runny away should
1102  * still be pretty nasty.
1103  */
1104  if (QUERY_FLAG(op, FLAG_RUN_AWAY)) {
1105  part->stats.wc += 10;
1106  skill_attack(enemy, part, 0, NULL, NULL);
1107  part->stats.wc -= 10;
1108  } else
1109  skill_attack(enemy, part, 0, NULL, NULL);
1110  } /* if monster is in attack range */
1111 
1112  if (QUERY_FLAG(part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */
1113  return 1;
1114 
1115  if (QUERY_FLAG(op, FLAG_ONLY_ATTACK)) {
1116  object_remove(op);
1118  return 1;
1119  }
1120  return 0;
1121 }
1122 
1137 static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv) {
1138  object *more;
1139  rv_vector rv1;
1140 
1141  if (QUERY_FLAG(ob1, FLAG_CONFUSED) && !(RANDOM()%3))
1142  return 0;
1143 
1144  if (abs(rv->distance_x) < 2 && abs(rv->distance_y) < 2)
1145  return 1;
1146 
1147  /* check all the parts of ob2 - just because we can't get to
1148  * its head doesn't mean we don't want to pound its feet
1149  */
1150  for (more = ob2->more; more != NULL; more = more->more) {
1151  if (get_rangevector(ob1, more, &rv1, 0)
1152  && abs(rv1.distance_x) < 2 && abs(rv1.distance_y) < 2)
1153  return 1;
1154  }
1155  return 0;
1156 }
1157 
1180 static int monster_should_cast_spell(object *spell_ob) {
1181  /* The caller is responsible for making sure that *spell_ob is defined. */
1182  assert(spell_ob != NULL);
1183 
1184  if (spell_ob->subtype == SP_BOLT
1185  || spell_ob->subtype == SP_BULLET
1186  || spell_ob->subtype == SP_EXPLOSION
1187  || spell_ob->subtype == SP_CONE
1188  || spell_ob->subtype == SP_BOMB
1189  || spell_ob->subtype == SP_SMITE
1190  || spell_ob->subtype == SP_MAGIC_MISSILE
1191  || spell_ob->subtype == SP_SUMMON_GOLEM
1192  || spell_ob->subtype == SP_MAGIC_WALL
1193  || spell_ob->subtype == SP_SUMMON_MONSTER
1194  || spell_ob->subtype == SP_MOVING_BALL
1195  || spell_ob->subtype == SP_SWARM
1196  || spell_ob->subtype == SP_INVISIBLE)
1197  return 1;
1198 
1199  return 0;
1200 }
1201 
1203 #define MAX_KNOWN_SPELLS 20
1204 
1220 static object *monster_choose_random_spell(object *monster) {
1221  object *altern[MAX_KNOWN_SPELLS];
1222  int i = 0;
1223 
1224  FOR_INV_PREPARE(monster, tmp)
1225  if (tmp->type == SPELLBOOK || tmp->type == SPELL) {
1226  /* Check and see if it's actually a useful spell.
1227  * If its a spellbook, the spell is actually the inventory item.
1228  * if it is a spell, then it is just the object itself.
1229  */
1230  if (monster_should_cast_spell(tmp->type == SPELLBOOK ? tmp->inv : tmp)) {
1231  altern[i++] = tmp;
1232  if (i == MAX_KNOWN_SPELLS)
1233  break;
1234  }
1235  }
1236  FOR_INV_FINISH();
1237  if (!i)
1238  return NULL;
1239  return altern[RANDOM()%i];
1240 }
1241 
1258 static int monster_cast_spell(object *head, object *part, object *pl, int dir) {
1259  object *spell_item;
1260  object *owner;
1261  rv_vector rv1;
1262 
1263  /* If you want monsters to cast spells over friends, this spell should
1264  * be removed. It probably should be in most cases, since monsters still
1265  * don't care about residual effects (ie, casting a cone which may have a
1266  * clear path to the player, the side aspects of the code will still hit
1267  * other monsters)
1268  */
1269  dir = path_to_player(part, pl, 0);
1270  if (dir == 0)
1271  return 0;
1272 
1273  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1274  owner = object_get_owner(head);
1275  if (owner != NULL) {
1276  if (get_rangevector(head, owner, &rv1, 0x1)
1277  && dirdiff(dir, rv1.direction) < 2) {
1278  return 0; /* Might hit owner with spell */
1279  }
1280  }
1281  }
1282 
1283  if (QUERY_FLAG(head, FLAG_CONFUSED))
1284  dir = get_randomized_dir(dir);
1285 
1286  /* If the monster hasn't already chosen a spell, choose one
1287  * I'm not sure if it really make sense to pre-select spells (events
1288  * could be different by the time the monster goes again).
1289  */
1290  if (head->spellitem == NULL) {
1291  spell_item = monster_choose_random_spell(head);
1292  if (spell_item == NULL) {
1293  LOG(llevMonster, "Turned off spells in %s\n", head->name);
1294  CLEAR_FLAG(head, FLAG_CAST_SPELL); /* Will be turned on when picking up book */
1295  return 0;
1296  }
1297  if (spell_item->type == SPELLBOOK) {
1298  if (!spell_item->inv) {
1299  LOG(llevError, "spellbook %s does not contain a spell?\n", spell_item->name);
1300  return 0;
1301  }
1302  spell_item = spell_item->inv;
1303  }
1304  } else
1305  spell_item = head->spellitem;
1306 
1307  if (!spell_item)
1308  return 0;
1309 
1310  /* Best guess this is a defensive/healing spell */
1311  if (spell_item->range <= 1 || spell_item->stats.dam < 0)
1312  dir = 0;
1313 
1314  /* Monster doesn't have enough spell-points */
1315  if (head->stats.sp < SP_level_spellpoint_cost(head, spell_item, SPELL_MANA))
1316  return 0;
1317 
1318  if (head->stats.grace < SP_level_spellpoint_cost(head, spell_item, SPELL_GRACE))
1319  return 0;
1320 
1321  head->stats.sp -= SP_level_spellpoint_cost(head, spell_item, SPELL_MANA);
1322  head->stats.grace -= SP_level_spellpoint_cost(head, spell_item, SPELL_GRACE);
1323 
1324  /* set this to null, so next time monster will choose something different */
1325  head->spellitem = NULL;
1326 
1327  return cast_spell(part, part, dir, spell_item, NULL);
1328 }
1329 
1344 static int monster_use_scroll(object *head, object *part, object *pl, int dir) {
1345  object *scroll;
1346  object *owner;
1347  rv_vector rv1;
1348 
1349  /* If you want monsters to cast spells over friends, this spell should
1350  * be removed. It probably should be in most cases, since monsters still
1351  * don't care about residual effects (ie, casting a cone which may have a
1352  * clear path to the player, the side aspects of the code will still hit
1353  * other monsters)
1354  */
1355  dir = path_to_player(part, pl, 0);
1356  if (dir == 0)
1357  return 0;
1358 
1359  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1360  owner = object_get_owner(head);
1361  if (owner != NULL) {
1362  if (get_rangevector(head, owner, &rv1, 0x1)
1363  && dirdiff(dir, rv1.direction) < 2) {
1364  return 0; /* Might hit owner with spell */
1365  }
1366  }
1367  }
1368 
1369  if (QUERY_FLAG(head, FLAG_CONFUSED))
1370  dir = get_randomized_dir(dir);
1371 
1372  scroll = NULL;
1373  FOR_INV_PREPARE(head, tmp)
1374  if (tmp->type == SCROLL && monster_should_cast_spell(tmp->inv)) {
1375  scroll = tmp;
1376  break;
1377  }
1378  FOR_INV_FINISH();
1379 
1380  /* Used up all his scrolls, so nothing do to */
1381  if (!scroll) {
1383  return 0;
1384  }
1385 
1386  /* Spell should be cast on caster (ie, heal, strength) */
1387  if (scroll->inv->range == 0)
1388  dir = 0;
1389 
1390  /* Face the direction that we want to cast. */
1391  head->direction = dir;
1392  head->facing = head->direction;
1393  if (head->animation)
1394  animate_object(head, head->direction);
1395 
1396  apply_manual(part, scroll, 0);
1397  return 1;
1398 }
1399 
1428 static int monster_use_skill(object *head, object *part, object *pl, int dir) {
1429  object *owner;
1430  int found;
1431 
1432  dir = path_to_player(part, pl, 0);
1433  if (dir == 0)
1434  return 0;
1435 
1436  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1437  owner = object_get_owner(head);
1438  if (owner != NULL) {
1439  rv_vector rv;
1440 
1441  if (get_rangevector(head, owner, &rv, 0) && dirdiff(dir, rv.direction) < 1)
1442  return 0; /* Might hit owner with skill -thrown rocks for example ?*/
1443  }
1444  }
1445  if (QUERY_FLAG(head, FLAG_CONFUSED))
1446  dir = get_randomized_dir(dir);
1447 
1448  /* skill selection - monster will use the next unused skill.
1449  * well...the following scenario will allow the monster to
1450  * toggle between 2 skills. One day it would be nice to make
1451  * more skills available to monsters.
1452  */
1453  found = 0;
1454  FOR_INV_PREPARE(head, skill)
1455  if (skill->type == SKILL && skill != head->chosen_skill) {
1456  head->chosen_skill = skill;
1457  found = 1;
1458  break;
1459  }
1460  FOR_INV_FINISH();
1461 
1462  if (!found && !head->chosen_skill) {
1463  LOG(llevDebug, "Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", head->name, head->count);
1465  return 0;
1466  }
1467  /* use skill */
1468  return do_skill(head, part, head->chosen_skill, dir, NULL);
1469 }
1470 
1485 static int monster_use_range(object *head, object *part, object *pl, int dir) {
1486  object *owner;
1487  int at_least_one = 0;
1488 
1489  dir = path_to_player(part, pl, 0);
1490  if (dir == 0)
1491  return 0;
1492 
1493  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1494  owner = object_get_owner(head);
1495  if (owner != NULL) {
1496  rv_vector rv;
1497 
1498  if (get_rangevector(head, owner, &rv, 0) && dirdiff(dir, rv.direction) < 2)
1499  return 0; /* Might hit owner with spell */
1500  }
1501  }
1502  if (QUERY_FLAG(head, FLAG_CONFUSED))
1503  dir = get_randomized_dir(dir);
1504 
1505  FOR_INV_PREPARE(head, wand) {
1506  if (wand->type == WAND) {
1507  /* Found a wand, let's see if it has charges left */
1508  at_least_one = 1;
1509  if (wand->stats.food <= 0)
1510  continue;
1511 
1512  cast_spell(head, wand, dir, wand->inv, NULL);
1513  drain_wand_charge(wand);
1514 
1515  /* Success */
1516  return 1;
1517  }
1518 
1519  if (wand->type == ROD && wand->inv) {
1520  /* Found rod/horn, let's use it if possible */
1521  at_least_one = 1;
1522  if (wand->stats.hp < MAX(wand->inv->stats.sp, wand->inv->stats.grace))
1523  continue;
1524 
1525  /* drain charge before casting spell - can be a case where the
1526  * spell destroys the monster, and rod, so if done after, results
1527  * in crash.
1528  */
1529  drain_rod_charge(wand);
1530  cast_spell(head, wand, dir, wand->inv, NULL);
1531 
1532  /* Success */
1533  return 1;
1534  }
1535  } FOR_INV_FINISH();
1536 
1537  if (at_least_one)
1538  return 0;
1539 
1540  LOG(llevError, "Error: Monster %s (%d) HAS_READY_RANG() without wand/horn/rod.\n", head->name, head->count);
1542  return 0;
1543 }
1544 
1561 static int monster_use_bow(object *head, object *part, object *pl, int dir) {
1562  object *owner;
1563  rv_vector rv;
1564  int16_t x, y;
1565  mapstruct *map;
1566 
1567  if (!get_rangevector(part, pl, &rv, 1))
1568  return 0;
1569  if (rv.distance > 100)
1570  /* Too far */
1571  return 0;
1572  if (rv.distance_x != 0 && rv.distance_y != 0 && abs(rv.distance_x) != abs(rv.distance_y))
1573  /* Player must be on same horizontal, vertical or diagonal line. */
1574  return 0;
1575  dir = rv.direction;
1576 
1577  if (QUERY_FLAG(head, FLAG_FRIENDLY))
1578  owner = object_get_owner(head);
1579  else
1580  owner = NULL;
1581 
1582  /* The monster can possibly fire, let's see if the path is ok for an arrow. */
1583  x = part->x;
1584  y = part->y;
1585  map = part->map;
1586  while (x != pl->x || y != pl->y || map != pl->map) {
1587  x += freearr_x[dir];
1588  y += freearr_y[dir];
1589  map = get_map_from_coord(map, &x, &y);
1590  if (!map) {
1591  LOG(llevError, "monster_use_bow: no map but still path exists??\n");
1592  return 0;
1593  }
1595  return 0;
1596  if (owner && owner->x == x && owner->y == y && owner->map == map)
1597  /* Don't hit owner! */
1598  return 0;
1599  }
1600 
1601  /* Finally, path is clear, can fire. */
1602 
1603  if (QUERY_FLAG(head, FLAG_CONFUSED))
1604  dir = get_randomized_dir(dir);
1605 
1606  /* in server/player.c */
1607  return fire_bow(head, NULL, dir, 0, part->x, part->y);
1608 }
1609 
1618 static int monster_get_weapon_quality(const object *item) {
1619  int val;
1620  int i;
1621 
1622  val = item->stats.dam;
1623  val += item->magic*3;
1624  /* Monsters don't really get benefits from things like regen rates
1625  * from items. But the bonus for their stats are very important.
1626  */
1627  for (i = 0; i < NUM_STATS; i++)
1628  val += get_attr_value(&item->stats, i)*2;
1629  return val;
1630 }
1631 
1644 static int monster_check_good_weapon(object *who, object *item) {
1645  object *other_weap;
1646  int val;
1647 
1648  other_weap = object_find_by_type_applied(who, item->type);
1649  if (other_weap == NULL) /* No other weapons */
1650  return 1;
1651 
1652  /* Rather than go through and apply the new one, and see if it is
1653  * better, just do some simple checks
1654  * Put some multipliers for things that hvae several effects,
1655  * eg, magic affects both damage and wc, so it has more weight
1656  */
1657 
1659  return val > 0;
1660 }
1661 
1670 static int monster_get_armour_quality(const object *item) {
1671  int val;
1672 
1673  val = item->stats.ac;
1674  val += item->resist[ATNR_PHYSICAL]/5;
1675  val += item->magic*3;
1676  return val;
1677 }
1678 
1691 static int monster_check_good_armour(object *who, object *item) {
1692  object *other_armour;
1693  int val, i;
1694 
1695  other_armour = object_find_by_type_applied(who, item->type);
1696  if (other_armour == NULL) /* No other armour, use the new */
1697  return 1;
1698 
1700 
1701  /* for the other protections, do weigh them very much in the equation -
1702  * it is the armor protection which is most important, because there is
1703  * no good way to know what the player may attack the monster with.
1704  * So if the new item has better protection than the old, give that higher
1705  * value. If the reverse, then decrease the value of this item some.
1706  */
1707  for (i = 1; i < NROFATTACKS; i++) {
1708  if (item->resist[i] > other_armour->resist[i])
1709  val++;
1710  else if (item->resist[i] < other_armour->resist[i])
1711  val--;
1712  }
1713 
1714  /* Very few armours have stats, so not much need to worry about those. */
1715 
1716  return val > 0;
1717 }
1718 
1726 static void monster_check_apply(object *mon, object *item) {
1727  int flag = 0;
1728 
1729  if (item->type == SPELLBOOK
1730  && mon->arch != NULL
1731  && (QUERY_FLAG(&mon->arch->clone, FLAG_CAST_SPELL))) {
1733  return;
1734  }
1735 
1736  /* If for some reason, this item is already applied, no more work to do */
1738  return;
1739 
1740  /* Might be better not to do this - if the monster can fire a bow,
1741  * it is possible in his wanderings, he will find one to use. In
1742  * which case, it would be nice to have ammo for it.
1743  */
1744  if (QUERY_FLAG(mon, FLAG_USE_BOW) && item->type == ARROW) {
1745  /* Check for the right kind of bow */
1746  object *bow;
1747 
1748  bow = object_find_by_type_and_race(mon, BOW, item->race);
1749  if (bow != NULL) {
1751  LOG(llevMonster, "Found correct bow for arrows.\n");
1752  return; /* nothing more to do for arrows */
1753  }
1754  }
1755 
1756  if (item->type == TREASURE && mon->will_apply&WILL_APPLY_TREASURE)
1757  flag = 1;
1758  /* Eating food gets hp back */
1759  else if (item->type == FOOD && mon->will_apply&WILL_APPLY_FOOD)
1760  flag = 1;
1761  else if (item->type == SCROLL && QUERY_FLAG(mon, FLAG_USE_SCROLL)) {
1762  if (!item->inv)
1763  LOG(llevDebug, "Monster %d having scroll %d with empty inventory!\n", mon->count, item->count);
1764  else if (monster_should_cast_spell(item->inv))
1766  /* Don't use it right now */
1767  return;
1768  } else if (item->type == WEAPON)
1770  else if (IS_ARMOR(item) || IS_SHIELD(item))
1772  /* Should do something more, like make sure this is a better item */
1773  else if (item->type == RING)
1774  flag = 1;
1775  else if (item->type == WAND || item->type == ROD) {
1776  /* We never really 'ready' the wand/rod/horn, because that would mean the
1777  * weapon would get undone.
1778  */
1782  }
1783  return;
1784  } else if (item->type == BOW) {
1785  /* We never really 'ready' the bow, because that would mean the
1786  * weapon would get undone.
1787  */
1790  return;
1791  } else if (item->type == SKILL) {
1792  /*
1793  * skills are specials: monsters must have the 'FLAG_READY_SKILL' flag set,
1794  * else they can't use the skill...
1795  * Skills also don't need to get applied, so return now.
1796  */
1798  return;
1799  }
1800 
1801  /* if we don't match one of the above types, return now.
1802  * apply_can_apply_object() will say that we can apply things like flesh,
1803  * bolts, and whatever else, because it only checks against the
1804  * body_info locations.
1805  */
1806  if (!flag)
1807  return;
1808 
1809  /* Check to see if the monster can use this item. If not, no need
1810  * to do further processing. Note that apply_can_apply_object() already checks
1811  * for the CAN_USE flags.
1812  */
1814  return;
1815 
1816  /* should only be applying this item, not unapplying it.
1817  * also, ignore status of curse so they can take off old armour.
1818  * monsters have some advantages after all.
1819  */
1821  return;
1822 }
1823 
1843 static void monster_check_pickup(object *monster) {
1844  object *part;
1845 
1846  for (part = monster; part != NULL; part = part->more)
1847  FOR_BELOW_PREPARE(part, tmp) {
1848  /* Don't try to pick items that are in the process of being thrown.
1849  * It is fairly likely that an ally threw it past monster to hit player.
1850  * IDEA: Maybe have a dex save to catch player-thrown projectiles?
1851  *
1852  * Daniel Hawkins 2020-09-07
1853  */
1854  if (tmp->type != THROWN_OBJ && monster_can_pick(monster, tmp)) {
1855  uint32_t nrof;
1856 
1857  if (tmp->weight > 0) {
1858  int32_t weight_limit;
1859 
1860  weight_limit = get_weight_limit(monster->stats.Str);
1861  if (weight_limit >= monster->weight-monster->carrying)
1862  nrof = (weight_limit-monster->weight-monster->carrying)/tmp->weight;
1863  else
1864  nrof = 0;
1865  } else
1866  nrof = MAX(1, tmp->nrof);
1867  if (nrof >= 1) {
1868  object *tmp2;
1869 
1870  tmp2 = object_split(tmp, MIN(nrof, MAX(1, tmp->nrof)), NULL, 0);
1871  tmp2 = object_insert_in_ob(tmp2, monster);
1872  (void)monster_check_apply(monster, tmp2);
1873  }
1874  }
1875  } FOR_BELOW_FINISH();
1876 }
1877 
1887 static int monster_can_pick(object *monster, object *item) {
1888  int flag = 0;
1889  int i;
1890 
1891  if (!object_can_pick(monster, item))
1892  return 0;
1893 
1894  if (QUERY_FLAG(item, FLAG_UNPAID))
1895  return 0;
1896 
1897  if (monster->pick_up&64) /* All */
1898  flag = 1;
1899 
1900  else {
1901  if (IS_WEAPON(item))
1902  flag = (monster->pick_up&8) || QUERY_FLAG(monster, FLAG_USE_WEAPON);
1903  else if (IS_ARMOR(item))
1904  flag = (monster->pick_up&16) || QUERY_FLAG(monster, FLAG_USE_ARMOUR);
1905  else if (IS_SHIELD(item))
1906  flag = (monster->pick_up&16) || QUERY_FLAG(monster, FLAG_USE_SHIELD);
1907  else switch (item->type) {
1908  case MONEY:
1909  case GEM:
1910  flag = monster->pick_up&2;
1911  break;
1912 
1913  case FOOD:
1914  flag = monster->pick_up&4;
1915  break;
1916 
1917  case SKILL:
1918  flag = QUERY_FLAG(monster, FLAG_CAN_USE_SKILL);
1919  break;
1920 
1921  case RING:
1922  flag = QUERY_FLAG(monster, FLAG_USE_RING);
1923  break;
1924 
1925  case WAND:
1926  case ROD:
1927  flag = QUERY_FLAG(monster, FLAG_USE_RANGE);
1928  break;
1929 
1930  case SPELLBOOK:
1931  flag = (monster->arch != NULL && QUERY_FLAG(&monster->arch->clone, FLAG_CAST_SPELL));
1932  break;
1933 
1934  case SCROLL:
1935  flag = QUERY_FLAG(monster, FLAG_USE_SCROLL);
1936  break;
1937 
1938  case BOW:
1939  case ARROW:
1940  flag = QUERY_FLAG(monster, FLAG_USE_BOW);
1941  break;
1942  }
1943  if (!flag && QUERY_FLAG(item, FLAG_IS_THROWN) && object_find_by_type_subtype(monster, SKILL, SK_THROWING) != NULL)
1944  flag = (monster->pick_up&8) || QUERY_FLAG(monster, FLAG_USE_WEAPON);
1945  /* Simplistic check - if the monster has a location to equip it, he will
1946  * pick it up. Note that this doesn't handle cases where an item may
1947  * use several locations.
1948  */
1949  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
1950  if (monster->body_info[i] && item->body_info[i]) {
1951  flag = 1;
1952  break;
1953  }
1954  }
1955  }
1956 
1957  if (((!(monster->pick_up&32)) && flag) || ((monster->pick_up&32) && (!flag)))
1958  return 1;
1959  return 0;
1960 }
1961 
1968 static void monster_apply_below(object *monster) {
1969  FOR_BELOW_PREPARE(monster, tmp) {
1970  switch (tmp->type) {
1971  case CF_HANDLE:
1972  case TRIGGER:
1973  if (monster->will_apply&WILL_APPLY_HANDLE)
1974  apply_manual(monster, tmp, 0);
1975  break;
1976 
1977  case TREASURE:
1978  if (monster->will_apply&WILL_APPLY_TREASURE)
1979  apply_manual(monster, tmp, 0);
1980  break;
1981  }
1983  break;
1984  } FOR_BELOW_FINISH();
1985 }
1986 
1991 void monster_check_apply_all(object *monster) {
1992  if (!monster->head) {
1993  fix_object(monster); // Needed to correctly fill various body fields.
1994  }
1995  FOR_INV_PREPARE(monster, inv)
1996  monster_check_apply(monster, inv);
1997  FOR_INV_FINISH();
1998 }
1999 
2004 void monster_npc_call_help(object *op) {
2005  const char *value;
2006  int help_radius = 3;
2007 
2008  value = object_get_value(op, "help_radius");
2009  if ( value ) {
2010  int override_help_radius;
2011 
2012  override_help_radius = strtol(value, NULL, 10);
2013  if (override_help_radius >= 0 && override_help_radius < 30)
2014  help_radius = override_help_radius;
2015  else
2016  LOG(llevDebug, "monster_npc_call_help: invalid help_radius %d\n", override_help_radius);
2017  }
2018 
2019  for (int x = -help_radius; x <= help_radius; x++)
2020  for (int y = -help_radius; y <= help_radius; y++) {
2021  mapstruct *m = op->map;
2022  int16_t sx = op->x+x;
2023  int16_t sy = op->y+y;
2024  int mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
2025  /* If nothing alive on this space, no need to search the space. */
2026  if ((mflags&P_OUT_OF_MAP) || !(mflags&P_IS_ALIVE))
2027  continue;
2028 
2029  FOR_MAP_PREPARE(m, sx, sy, npc)
2031  object_set_enemy(npc, op->enemy);
2033  }
2034  FOR_MAP_FINISH();
2035  }
2036 }
2037 
2046 static int monster_dist_att(int dir, object *enemy, object *part, rv_vector *rv) {
2047  if (monster_can_hit(part, enemy, rv))
2048  return dir;
2049  if (rv->distance < 10)
2050  return absdir(dir+4);
2051  else if (rv->distance > 18)
2052  return dir;
2053  return 0;
2054 }
2055 
2065 static int monster_run_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
2066  if ((monster_can_hit(part, enemy, rv) && ob->move_status < 20) || ob->move_status < 20) {
2067  ob->move_status++;
2068  return (dir);
2069  } else if (ob->move_status > 20)
2070  ob->move_status = 0;
2071  return absdir(dir+4);
2072 }
2073 
2080 static int monster_hitrun_att(int dir, object *ob) {
2081  if (ob->move_status++ < 25)
2082  return dir;
2083  else if (ob->move_status < 50)
2084  return absdir(dir+4);
2085  ob->move_status = 0;
2086  return absdir(dir+4);
2087 }
2088 
2098 static int monster_wait_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
2099  int inrange = monster_can_hit(part, enemy, rv);
2100 
2101  if (ob->move_status || inrange)
2102  ob->move_status++;
2103 
2104  if (ob->move_status == 0)
2105  return 0;
2106  else if (ob->move_status < 10)
2107  return dir;
2108  else if (ob->move_status < 15)
2109  return absdir(dir+4);
2110  ob->move_status = 0;
2111  return 0;
2112 }
2113 
2123 static int monster_disthit_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
2124  /* The logic below here looked plain wrong before. Basically, what should
2125  * happen is that if the creatures hp percentage falls below run_away,
2126  * the creature should run away (dir+4)
2127  * I think its wrong for a creature to have a zero maxhp value, but
2128  * at least one map has this set, and whatever the map contains, the
2129  * server should try to be resilant enough to avoid the problem
2130  */
2131  if (ob->stats.maxhp && (ob->stats.hp*100)/ob->stats.maxhp < ob->run_away)
2132  return absdir(dir+4);
2133  return monster_dist_att(dir, enemy, part, rv);
2134 }
2135 
2142 static int monster_wait_att2(int dir, rv_vector *rv) {
2143  if (rv->distance < 9)
2144  return absdir(dir+4);
2145  return 0;
2146 }
2147 
2152 static void monster_circ1_move(object *ob) {
2153  static const int circle [12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 };
2154 
2155  if (++ob->move_status > 11)
2156  ob->move_status = 0;
2157  if (!(move_object(ob, circle[ob->move_status])))
2158  (void)move_object(ob, RANDOM()%8+1);
2159 }
2160 
2165 static void monster_circ2_move(object *ob) {
2166  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 };
2167 
2168  if (++ob->move_status > 19)
2169  ob->move_status = 0;
2170  if (!(move_object(ob, circle[ob->move_status])))
2171  (void)move_object(ob, RANDOM()%8+1);
2172 }
2173 
2178 static void monster_pace_movev(object *ob) {
2179  if (ob->move_status++ > 6)
2180  ob->move_status = 0;
2181  if (ob->move_status < 4)
2182  (void)move_object(ob, 5);
2183  else
2184  (void)move_object(ob, 1);
2185 }
2186 
2191 static void monster_pace_moveh(object *ob) {
2192  if (ob->move_status++ > 6)
2193  ob->move_status = 0;
2194  if (ob->move_status < 4)
2195  (void)move_object(ob, 3);
2196  else
2197  (void)move_object(ob, 7);
2198 }
2199 
2204 static void monster_pace2_movev(object *ob) {
2205  if (ob->move_status++ > 16)
2206  ob->move_status = 0;
2207  if (ob->move_status < 6)
2208  (void)move_object(ob, 5);
2209  else if (ob->move_status < 8)
2210  return;
2211  else if (ob->move_status < 13)
2212  (void)move_object(ob, 1);
2213 }
2214 
2219 static void monster_pace2_moveh(object *ob) {
2220  if (ob->move_status++ > 16)
2221  ob->move_status = 0;
2222  if (ob->move_status < 6)
2223  (void)move_object(ob, 3);
2224  else if (ob->move_status < 8)
2225  return;
2226  else if (ob->move_status < 13)
2227  (void)move_object(ob, 7);
2228 }
2229 
2234 static void monster_rand_move(object *ob) {
2235  int i;
2236 
2237  if (ob->move_status < 1
2238  || ob->move_status > 8
2239  || !(move_object(ob, ob->move_status || !(RANDOM()%9))))
2240  for (i = 0; i < 5; i++) {
2241  ob->move_status = RANDOM()%8+1;
2242  if (move_object(ob, ob->move_status))
2243  return;
2244  }
2245 }
2246 
2254 void monster_check_earthwalls(object *op, mapstruct *m, int x, int y) {
2255  FOR_MAP_PREPARE(m, x, y, tmp)
2256  if (tmp->type == EARTHWALL) {
2257  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
2258  return;
2259  }
2260  FOR_MAP_FINISH();
2261 }
2262 
2270 void monster_check_doors(object *op, mapstruct *m, int x, int y) {
2271  FOR_MAP_PREPARE(m, x, y, tmp)
2272  if (tmp->type == DOOR) {
2273  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
2274  return;
2275  }
2276  FOR_MAP_FINISH();
2277 }
2278 
2284 void monster_do_say(const mapstruct *map, const char *message) {
2286  message);
2287 }
2288 
2295 static StringBuffer *monster_format_say(const object* npc, const char *message) {
2296  char name[MAX_BUF];
2297  StringBuffer *buf;
2298 
2299  query_name(npc, name, sizeof(name));
2300  buf = stringbuffer_new();
2301  stringbuffer_append_printf(buf, "%s says: %s", name, message);
2302  return buf;
2303 }
2304 
2311  switch (rt) {
2312  case rt_say:
2313  return "say";
2314  case rt_reply:
2315  return "reply";
2316  case rt_question:
2317  return "ask";
2318  }
2319  assert(0);
2320  return NULL;
2321 }
2322 
2328 static const char *get_reply_text_other(reply_type rt) {
2329  switch (rt) {
2330  case rt_say:
2331  return "says";
2332  case rt_reply:
2333  return "replies";
2334  case rt_question:
2335  return "asks";
2336  }
2337  assert(0);
2338  return NULL;
2339 }
2340 
2366 void monster_communicate(object *op, const char *txt) {
2367  int i, mflags;
2368  int16_t x, y;
2369  mapstruct *mp, *orig_map = op->map;
2370  char own[MAX_BUF], others[MAX_BUF];
2371  talk_info info;
2372 
2373  info.text = txt;
2374  info.message = NULL;
2375  info.replies_count = 0;
2376  info.who = op;
2377  info.npc_msg_count = 0;
2378 
2379  /* Note that this loop looks pretty inefficient to me - we look and try to talk
2380  * to every object within 2 spaces. It would seem that if we trim this down to
2381  * only try to talk to objects with npc->msg set, things would be a lot more efficient,
2382  * but I'm not sure if there are any objects out there that don't have a message and instead
2383  * rely sorely on events - MSW 2009-04-14
2384  */
2385  for (i = 0; i <= SIZEOFFREE2; i++) {
2386  mp = op->map;
2387  x = op->x+freearr_x[i];
2388  y = op->y+freearr_y[i];
2389 
2390  mflags = get_map_flags(mp, &mp, x, y, &x, &y);
2391  if (mflags&P_OUT_OF_MAP)
2392  continue;
2393 
2394  FOR_MAP_PREPARE(mp, x, y, npc) {
2395  monster_talk_to_npc(npc, &info);
2396  if (orig_map != op->map) {
2397  LOG(llevDebug, "Warning: Forced to swap out very recent map\n");
2398  return;
2399  }
2400  } FOR_MAP_FINISH();
2401  }
2402 
2403  /* First, what the player says. */
2404  if (info.message != NULL) {
2405  snprintf(own, sizeof(own), "You %s: %s", get_reply_text_own(info.message_type), info.message);
2406  snprintf(others, sizeof(others), "%s %s: %s", op->name, get_reply_text_other(info.message_type), info.message);
2407  free_string(info.message);
2408  } else {
2409  snprintf(own, sizeof(own), "You say: %s", txt);
2410  snprintf(others, sizeof(others), "%s says: %s", op->name, txt);
2411  }
2414 
2415  /* Then NPCs can actually talk. */
2416  for (i = 0; i < info.npc_msg_count; i++) {
2417  monster_do_say(orig_map, info.npc_msgs[i]);
2418  free_string(info.npc_msgs[i]);
2419  }
2420 
2421  /* Finally, the replies the player can use. */
2422  if (info.replies_count > 0) {
2424  for (i = 0; i < info.replies_count; i++) {
2426  free_string(info.replies_words[i]);
2427  free_string(info.replies[i]);
2428  }
2429  }
2430 }
2431 
2440 static int monster_do_talk_npc(object *npc, talk_info *info) {
2443 
2444  if (!get_dialog_message(npc, info->text, &message, &reply))
2445  return 0;
2446 
2447  if (reply) {
2448  info->message = add_string(reply->message);
2449  info->message_type = reply->type;
2450  }
2451 
2452  if (npc->type == MAGIC_EAR) {
2454  use_trigger(npc);
2455  } else {
2456  char value[2];
2457 
2458  if (info->npc_msg_count < MAX_NPC) {
2460  info->npc_msg_count++;
2461  }
2462 
2463  /* mark that the npc was talked to, so it won't move randomly later on */
2464  value[0] = '3' + rand() % 6;
2465  value[1] = '\0';
2466  object_set_value(npc, "talked_to", value, 1);
2467 
2468  reply = message->replies;
2469  while (reply && info->replies_count < MAX_REPLIES) {
2470  info->replies[info->replies_count] = add_string(reply->message);
2471  info->replies_words[info->replies_count] = add_string(reply->reply);
2472  info->replies_count++;
2473  reply = reply->next;
2474  }
2475  }
2476 
2477  return 1;
2478 }
2479 
2485 void monster_npc_say(object *npc, const char *cp) {
2486  char *message;
2488 
2490  monster_do_say(npc->map, message);
2491  free(message);
2492 }
2493 
2502 static int monster_talk_to_npc(object *npc, talk_info *info) {
2503 
2504  if (events_execute_object_say(npc, info) != 0)
2505  return 0;
2506 
2507  /* Here we let the objects inside inventories hear and answer, too. */
2508  /* This allows the existence of "intelligent" weapons you can discuss with */
2509  FOR_INV_PREPARE(npc, cobj)
2510  if (events_execute_object_say(cobj, info) != 0)
2511  return 0;
2512  FOR_INV_FINISH();
2513  if (info->who == npc)
2514  return 0;
2515  return monster_do_talk_npc(npc, info);
2516 }
2517 
2530 object *monster_find_throw_ob(object *op) {
2531  /* New throw code: look through the inventory. Grap the first legal is_thrown
2532  * marked item and throw it to the enemy.
2533  */
2534 
2535  FOR_INV_PREPARE(op, tmp) {
2536  /* Can't throw invisible objects or items that are applied */
2537  if (!tmp->invisible && !QUERY_FLAG(tmp, FLAG_APPLIED) && QUERY_FLAG(tmp, FLAG_IS_THROWN)) {
2538 #ifdef DEBUG_THROW
2539  char what[MAX_BUF];
2540 
2541  query_name(tmp, what, MAX_BUF);
2542  LOG(llevDebug, "%s chooses to throw: %s (%d)\n", op->name, what, tmp->count);
2543 #endif
2544  return tmp;
2545  }
2546  } FOR_INV_FINISH();
2547 
2548 #ifdef DEBUG_THROW
2549  LOG(llevDebug, "%s chooses to throw nothing\n", op->name);
2550 #endif
2551  return NULL;
2552 }
2553 
2569 int monster_can_detect_enemy(object *op, object *enemy, rv_vector *rv) {
2570  int radius = MIN_MON_RADIUS, hide_discovery;
2571 
2572  /* null detection for any of these condtions always */
2573  if (!op || !enemy || !op->map || !enemy->map)
2574  return 0;
2575 
2576  /* If the monster (op) has no way to get to the enemy, do nothing */
2577  if (!get_rangevector(op, enemy, rv, 0))
2578  return 0;
2579 
2580  /* Monsters always ignore the DM */
2581  if (op->type != PLAYER && QUERY_FLAG(enemy, FLAG_WIZ))
2582  return 0;
2583 
2584  /* simple check. Should probably put some range checks in here. */
2585  if (monster_can_see_enemy(op, enemy))
2586  return 1;
2587 
2588  /* The rest of this is for monsters. Players are on their own for
2589  * finding enemies!
2590  */
2591  if (op->type == PLAYER)
2592  return 0;
2593 
2594  /* Quality invisible? Bah, we wont see them w/o SEE_INVISIBLE
2595  * flag (which was already checked) in can_see_enmy (). Lets get out of here
2596  */
2597  if (enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden)))
2598  return 0;
2599 
2600  /* use this for invis also */
2601  hide_discovery = op->stats.Int/5;
2602 
2603  /* Determine Detection radii */
2604  if (!enemy->hide) /* to detect non-hidden (eg dark/invis enemy) */
2605  radius = MAX(op->stats.Wis/5+1, MIN_MON_RADIUS);
2606  else { /* a level/INT/Dex adjustment for hiding */
2607  object *sk_hide;
2608  int bonus = (op->level/2)+(op->stats.Int/5);
2609 
2610  if (enemy->type == PLAYER) {
2611  sk_hide = find_skill_by_number(enemy, SK_HIDING);
2612  if (sk_hide != NULL)
2613  bonus -= sk_hide->level;
2614  else {
2615  LOG(llevError, "monster_can_detect_enemy() got hidden player w/o hiding skill!\n");
2616  make_visible(enemy);
2617  radius = MAX(radius, MIN_MON_RADIUS);
2618  }
2619  } else /* enemy is not a player */
2620  bonus -= enemy->level;
2621 
2622  radius += bonus/5;
2623  hide_discovery += bonus*5;
2624  } /* else creature has modifiers for hiding */
2625 
2626  /* Radii stealth adjustment. Only if you are stealthy
2627  * will you be able to sneak up closer to creatures */
2628  if (QUERY_FLAG(enemy, FLAG_STEALTH))
2629  radius = radius/2, hide_discovery = hide_discovery/3;
2630 
2631  /* Radii adjustment for enemy standing in the dark */
2632  if (op->map->darkness > 0 && !monster_stand_in_light(enemy)) {
2633  /* on dark maps body heat can help indicate location with infravision
2634  * undead don't have body heat, so no benefit detecting them.
2635  */
2636  if (QUERY_FLAG(op, FLAG_SEE_IN_DARK) && !is_true_undead(enemy))
2637  radius += op->map->darkness/2;
2638  else
2639  radius -= op->map->darkness/2;
2640 
2641  /* op next to a monster (and not in complete darkness)
2642  * the monster should have a chance to see you.
2643  */
2644  if (radius < MIN_MON_RADIUS && op->map->darkness < 5 && rv->distance <= 1)
2645  radius = MIN_MON_RADIUS;
2646  } /* if on dark map */
2647 
2648  /* Lets not worry about monsters that have incredible detection
2649  * radii, we only need to worry here about things the player can
2650  * (potentially) see. This is 13, as that is the maximum size the player
2651  * may have for their map - in that way, creatures at the edge will
2652  * do something. Note that the distance field in the
2653  * vector is real distance, so in theory this should be 18 to
2654  * find that.
2655  */
2656  if (radius > 13)
2657  radius = 13;
2658 
2659  /* Enemy in range! Now test for detection */
2660  if ((int)rv->distance <= radius) {
2661  /* ah, we are within range, detected? take cases */
2662  if (!enemy->invisible) /* enemy in dark squares... are seen! */
2663  return 1;
2664 
2665  /* hidden or low-quality invisible */
2666  if (enemy->hide && rv->distance <= 1 && RANDOM()%100 <= (unsigned int)hide_discovery) {
2667  make_visible(enemy);
2668  /* inform players of new status */
2669  if (enemy->type == PLAYER && player_can_view(enemy, op))
2671  "You are discovered by %s!",
2672  op->name);
2673  return 1; /* detected enemy */
2674  } else if (enemy->invisible) {
2675  /* Change this around - instead of negating the invisible, just
2676  * return true so that the mosnter that managed to detect you can
2677  * do something to you. Decreasing the duration of invisible
2678  * doesn't make a lot of sense IMO, as a bunch of stupid creatures
2679  * can then basically negate the spell. The spell isn't negated -
2680  * they just know where you are!
2681  */
2682  if (RANDOM()%50 <= (unsigned int)hide_discovery) {
2683  if (enemy->type == PLAYER) {
2684  char name[MAX_BUF];
2685 
2688  "You see %s noticing your position.",
2689  name);
2690  }
2691  return 1;
2692  }
2693  }
2694  } /* within range */
2695 
2696  /* Wasn't detected above, so still hidden */
2697  return 0;
2698 }
2699 
2710  int16_t nx, ny;
2711  mapstruct *m;
2712 
2713  if (!op)
2714  return 0;
2715  if (op->glow_radius > 0)
2716  return 1;
2717 
2718  if (op->map) {
2719  int x, y, x1, y1;
2720 
2721  /* Check the spaces with the max light radius to see if any of them
2722  * have lights, and if any of them light the player enough, then return 1.
2723  */
2724  for (x = op->x-MAX_LIGHT_RADII; x <= op->x+MAX_LIGHT_RADII; x++) {
2725  for (y = op->y-MAX_LIGHT_RADII; y <= op->y+MAX_LIGHT_RADII; y++) {
2726  m = op->map;
2727  nx = x;
2728  ny = y;
2729 
2730  if (get_map_flags(m, &m, nx, ny, &nx, &ny)&P_OUT_OF_MAP)
2731  continue;
2732 
2733  x1 = abs(x-op->x)*abs(x-op->x);
2734  y1 = abs(y-op->y)*abs(y-op->y);
2735  if (isqrt(x1+y1) < GET_MAP_LIGHT(m, nx, ny))
2736  return 1;
2737  }
2738  }
2739  }
2740  return 0;
2741 }
2742 
2752 int monster_can_see_enemy(object *op, object *enemy) {
2753  object *looker = HEAD(op);
2754 
2755  /* safety */
2756  if (!looker || !enemy || !QUERY_FLAG(looker, FLAG_ALIVE))
2757  return 0;
2758 
2759  /* we dont give a full treatment of xrays here (shorter range than normal,
2760  * see through walls). Should we change the code elsewhere to make you
2761  * blind even if you can xray?
2762  */
2763  if (QUERY_FLAG(looker, FLAG_BLIND) && !QUERY_FLAG(looker, FLAG_XRAYS))
2764  return 0;
2765 
2766  /* checking for invisible things */
2767  if (enemy->invisible) {
2768  /* HIDDEN ENEMY. by definition, you can't see hidden stuff!
2769  * However, if you carry any source of light, then the hidden
2770  * creature is seeable (and stupid) */
2771  if (has_carried_lights(enemy)) {
2772  if (enemy->hide) {
2773  make_visible(enemy);
2775  "Your light reveals your hiding spot!");
2776  }
2777  return 1;
2778  } else if (enemy->hide)
2779  return 0;
2780 
2781  /* Invisible enemy. Break apart the check for invis undead/invis looker
2782  * into more simple checks - the QUERY_FLAG doesn't return 1/0 values,
2783  * and making it a conditional makes the code pretty ugly.
2784  */
2785  if (!QUERY_FLAG(looker, FLAG_SEE_INVISIBLE)) {
2786  if (makes_invisible_to(enemy, looker))
2787  return 0;
2788  }
2789  } else if (looker->type == PLAYER) /* for players, a (possible) shortcut */
2790  if (player_can_view(looker, enemy))
2791  return 1;
2792 
2793  /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen
2794  * unless they carry a light or stand in light. Darkness doesnt
2795  * inhibit the undead per se (but we should give their archs
2796  * CAN_SEE_IN_DARK, this is just a safety
2797  * we care about the enemy maps status, not the looker.
2798  * only relevant for tiled maps, but it is possible that the
2799  * enemy is on a bright map and the looker on a dark - in that
2800  * case, the looker can still see the enemy
2801  */
2802  if (enemy->map->darkness > 0
2803  && !monster_stand_in_light(enemy)
2804  && (!QUERY_FLAG(looker, FLAG_SEE_IN_DARK) || !is_true_undead(looker) || !QUERY_FLAG(looker, FLAG_XRAYS)))
2805  return 0;
2806 
2807  return 1;
2808 }
mapdef::height
uint16_t height
Definition: map.h:340
FLAG_USE_BOW
#define FLAG_USE_BOW
Definition: define.h:293
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Definition: map.h:173
do_skill
int do_skill(object *op, object *part, object *skill, int dir, const char *string)
Definition: skill_util.c:422
get_weight_limit
uint32_t get_weight_limit(int stat)
Definition: living.c:2362
MAX_KNOWN_SPELLS
#define MAX_KNOWN_SPELLS
Definition: monster.c:1203
MAX_EXPLORE
#define MAX_EXPLORE
Definition: monster.c:410
TRIGGER
@ TRIGGER
Definition: object.h:129
PLAYER
@ PLAYER
Definition: object.h:107
obj::attack_movement
uint16_t attack_movement
Definition: object.h:396
path_to_player
int path_to_player(object *mon, object *pl, unsigned mindiff)
Definition: player.c:643
SP_MAGIC_MISSILE
#define SP_MAGIC_MISSILE
Definition: spells.h:85
monster_check_wakeup
static int monster_check_wakeup(object *op, object *enemy, rv_vector *rv)
Definition: monster.c:331
global.h
FLAG_NEUTRAL
#define FLAG_NEUTRAL
Definition: define.h:354
monster_npc_call_help
void monster_npc_call_help(object *op)
Definition: monster.c:2004
add_refcount
sstring add_refcount(sstring str)
Definition: shstr.c:210
SP_BOLT
#define SP_BOLT
Definition: spells.h:78
CF_HANDLE
@ CF_HANDLE
Definition: object.h:208
liv::dam
int16_t dam
Definition: living.h:46
add_string
sstring add_string(const char *str)
Definition: shstr.c:124
talk_info::replies
sstring replies[MAX_REPLIES]
Definition: dialog.h:58
object_remove
void object_remove(object *op)
Definition: object.c:1819
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
remove_friendly_object
void remove_friendly_object(object *op)
Definition: friend.cpp:56
object_set_enemy
void object_set_enemy(object *op, object *enemy)
Definition: object.c:919
NUM_BODY_LOCATIONS
#define NUM_BODY_LOCATIONS
Definition: object.h:13
obj::face
const Face * face
Definition: object.h:336
FLAG_STAND_STILL
#define FLAG_STAND_STILL
Definition: define.h:308
FLAG_CONFUSED
#define FLAG_CONFUSED
Definition: define.h:311
AP_APPLY
#define AP_APPLY
Definition: define.h:574
BOW
@ BOW
Definition: object.h:118
WAITATT
#define WAITATT
Definition: define.h:495
llevError
@ llevError
Definition: logger.h:11
FABS
#define FABS(x)
Definition: define.h:22
monster_check_good_weapon
static int monster_check_good_weapon(object *who, object *item)
Definition: monster.c:1644
find_skill_by_number
object * find_skill_by_number(object *who, int skillno)
Definition: main.c:376
SP_BOMB
#define SP_BOMB
Definition: spells.h:82
WAND
@ WAND
Definition: object.h:220
FLAG_USE_RING
#define FLAG_USE_RING
Definition: define.h:297
ALLRUN
#define ALLRUN
Definition: define.h:497
talk_info::replies_words
sstring replies_words[MAX_REPLIES]
Definition: dialog.h:57
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
talk_info::npc_msg_count
int npc_msg_count
Definition: dialog.h:59
CAN_APPLY_NOT_MASK
#define CAN_APPLY_NOT_MASK
Definition: define.h:632
monster_use_scroll
static int monster_use_scroll(object *head, object *part, object *pl, int dir)
Definition: monster.c:1344
FLAG_GENERATOR
#define FLAG_GENERATOR
Definition: define.h:248
diamondslots.x
x
Definition: diamondslots.py:15
obj::count
tag_t count
Definition: object.h:302
RUNATT
#define RUNATT
Definition: define.h:493
obj::map
struct mapdef * map
Definition: object.h:300
MSG_TYPE_SKILL
#define MSG_TYPE_SKILL
Definition: newclient.h:407
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
monster_apply_below
static void monster_apply_below(object *monster)
Definition: monster.c:1968
PACEV2
#define PACEV2
Definition: define.h:526
pl::peaceful
uint32_t peaceful
Definition: player.h:146
pets_should_arena_attack
int pets_should_arena_attack(object *pet, object *owner, object *target)
Definition: pets.c:1086
liv::wc
int8_t wc
Definition: living.h:37
path_data
Definition: monster.c:415
make_visible
void make_visible(object *op)
Definition: player.c:3920
monster_check_enemy
object * monster_check_enemy(object *npc, rv_vector *rv)
Definition: monster.c:72
WILL_APPLY_HANDLE
#define WILL_APPLY_HANDLE
Definition: object.h:52
liv::Str
int8_t Str
Definition: living.h:36
FLAG_SEE_IN_DARK
#define FLAG_SEE_IN_DARK
Definition: define.h:337
monster_check_apply
static void monster_check_apply(object *mon, object *item)
Definition: monster.c:1726
AT_PHYSICAL
#define AT_PHYSICAL
Definition: attack.h:76
cast_spell
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Definition: spell_util.c:1420
obj::attacked_by_count
tag_t attacked_by_count
Definition: object.h:388
FOR_BELOW_PREPARE
#define FOR_BELOW_PREPARE(op_, it_)
Definition: define.h:704
GEM
@ GEM
Definition: object.h:167
pl
Definition: player.h:105
monster_run_att
static int monster_run_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv)
Definition: monster.c:2065
HITRUN
#define HITRUN
Definition: define.h:494
monster_choose_random_spell
static object * monster_choose_random_spell(object *monster)
Definition: monster.c:1220
monster_get_armour_quality
static int monster_get_armour_quality(const object *item)
Definition: monster.c:1670
WEAPON
@ WEAPON
Definition: object.h:119
obj::invisible
int16_t invisible
Definition: object.h:365
MinHeap
Definition: minheap.h:16
guildjoin.ob
ob
Definition: guildjoin.py:42
say.reply
string reply
Definition: say.py:77
SP_CONE
#define SP_CONE
Definition: spells.h:81
commongive.inv
inv
Definition: commongive.py:28
FLAG_SEE_INVISIBLE
#define FLAG_SEE_INVISIBLE
Definition: define.h:253
MIN
#define MIN(x, y)
Definition: compat.h:21
TREASURE
@ TREASURE
Definition: object.h:110
talk_info::who
struct obj * who
Definition: dialog.h:52
SKILL
@ SKILL
Definition: object.h:143
object_find_by_type_applied
object * object_find_by_type_applied(const object *who, int type)
Definition: object.c:4054
FLAG_SCARED
#define FLAG_SCARED
Definition: define.h:271
ob_blocked
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
Definition: map.c:488
monster_use_range
static int monster_use_range(object *head, object *part, object *pl, int dir)
Definition: monster.c:1485
Ice.tmp
int tmp
Definition: Ice.py:207
FLAG_ONLY_ATTACK
#define FLAG_ONLY_ATTACK
Definition: define.h:310
FLAG_READY_SCROLL
#define FLAG_READY_SCROLL
Definition: define.h:324
NDI_NAVY
#define NDI_NAVY
Definition: newclient.h:244
RANDO
#define RANDO
Definition: define.h:520
llevMonster
@ llevMonster
Definition: logger.h:14
get_nearest_criminal
object * get_nearest_criminal(object *mon)
Definition: player.c:575
monster_use_bow
static int monster_use_bow(object *head, object *part, object *pl, int dir)
Definition: monster.c:1561
ATNR_PHYSICAL
#define ATNR_PHYSICAL
Definition: attack.h:49
is_enemy
static int is_enemy(object *who, object *owner)
Definition: monster.c:142
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
get_rangevector
int get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
Definition: map.c:2545
ext_info_map
void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1)
Definition: main.c:335
obj::body_info
int8_t body_info[NUM_BODY_LOCATIONS]
Definition: object.h:377
skills.h
rv_vector::part
object * part
Definition: map.h:378
monster_move_randomly
static int monster_move_randomly(object *op)
Definition: monster.c:377
apply_manual
int apply_manual(object *op, object *tmp, int aflag)
Definition: apply.c:597
FOR_OB_AND_ABOVE_FINISH
#define FOR_OB_AND_ABOVE_FINISH()
Definition: define.h:743
P_IS_ALIVE
#define P_IS_ALIVE
Definition: map.h:238
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
talk_info::message_type
int message_type
Definition: dialog.h:55
FLAG_STEALTH
#define FLAG_STEALTH
Definition: define.h:312
FLAG_BLIND
#define FLAG_BLIND
Definition: define.h:336
monster_check_apply_all
void monster_check_apply_all(object *monster)
Definition: monster.c:1991
monster_get_weapon_quality
static int monster_get_weapon_quality(const object *item)
Definition: monster.c:1618
monster_should_cast_spell
static int monster_should_cast_spell(object *spell_ob)
Definition: monster.c:1180
monster_npc_say
void monster_npc_say(object *npc, const char *cp)
Definition: monster.c:2485
isqrt
int isqrt(int n)
Definition: utils.c:569
PACEH
#define PACEH
Definition: define.h:514
MAX
#define MAX(x, y)
Definition: compat.h:24
get_nearest_player
object * get_nearest_player(object *mon)
Definition: player.c:531
freearr_x
short freearr_x[SIZEOFFREE]
Definition: object.c:299
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.c:305
talk_info::message
sstring message
Definition: dialog.h:54
FOR_BELOW_FINISH
#define FOR_BELOW_FINISH()
Definition: define.h:711
talk_info::replies_count
int replies_count
Definition: dialog.h:56
FLAG_ALIVE
#define FLAG_ALIVE
Definition: define.h:230
animate_object
void animate_object(object *op, int dir)
Definition: anim.c:43
rv_vector::distance_y
int distance_y
Definition: map.h:376
FOR_OB_AND_ABOVE_PREPARE
#define FOR_OB_AND_ABOVE_PREPARE(op_)
Definition: define.h:739
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.c:4317
obj::chosen_skill
struct obj * chosen_skill
Definition: object.h:391
SP_SUMMON_MONSTER
#define SP_SUMMON_MONSTER
Definition: spells.h:101
free_string
void free_string(sstring str)
Definition: shstr.c:280
m
static event_registration m
Definition: citylife.cpp:427
obj::attacked_by
struct obj * attacked_by
Definition: object.h:387
rv_vector::distance_x
int distance_x
Definition: map.h:375
monster_check_earthwalls
void monster_check_earthwalls(object *op, mapstruct *m, int x, int y)
Definition: monster.c:2254
autojail.who
who
Definition: autojail.py:3
has_carried_lights
int has_carried_lights(const object *op)
Definition: los.c:315
FLAG_NO_ATTACK
#define FLAG_NO_ATTACK
Definition: define.h:355
object_find_by_type_subtype
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Definition: object.c:4272
monster_stand_in_light
int monster_stand_in_light(object *op)
Definition: monster.c:2709
SP_BULLET
#define SP_BULLET
Definition: spells.h:79
disinfect.map
map
Definition: disinfect.py:4
pets_get_enemy
object * pets_get_enemy(object *pet, rv_vector *rv)
Definition: pets.c:54
obj::name
sstring name
Definition: object.h:314
minheap.h
minheap_remove
void * minheap_remove(MinHeap *heap)
Definition: minheap.c:209
pl::tmp_invis
uint32_t tmp_invis
Definition: player.h:140
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:585
stringbuffer_finish_shared
sstring stringbuffer_finish_shared(StringBuffer *sb)
Definition: stringbuffer.c:85
FLAG_USE_RANGE
#define FLAG_USE_RANGE
Definition: define.h:292
mon
object * mon
Definition: comet_perf.c:75
FLAG_RUN_AWAY
#define FLAG_RUN_AWAY
Definition: define.h:280
monster_do_say
void monster_do_say(const mapstruct *map, const char *message)
Definition: monster.c:2284
MOVE_WALK
#define MOVE_WALK
Definition: define.h:392
minheap_insert
int minheap_insert(MinHeap *heap, void *ob)
Definition: minheap.c:184
get_reply_text_own
const char * get_reply_text_own(reply_type rt)
Definition: monster.c:2310
get_randomized_dir
int get_randomized_dir(int dir)
Definition: utils.c:422
monster_talk_to_npc
static int monster_talk_to_npc(object *npc, talk_info *info)
Definition: monster.c:2502
monster_format_say
static StringBuffer * monster_format_say(const object *npc, const char *message)
Definition: monster.c:2295
monster_do_talk_npc
static int monster_do_talk_npc(object *npc, talk_info *info)
Definition: monster.c:2440
HEAD
#define HEAD(op)
Definition: object.h:593
minheap_init_static
void minheap_init_static(MinHeap *heap, void **arr, int amt, int(*measure_func)(const void *))
Definition: minheap.c:162
fatal
void fatal(enum fatal_error err)
Definition: utils.c:580
monster_hitrun_att
static int monster_hitrun_att(int dir, object *ob)
Definition: monster.c:2080
ROD
@ ROD
Definition: object.h:109
object_can_pick
int object_can_pick(const object *who, const object *item)
Definition: object.c:3838
monster_move
int monster_move(object *op)
Definition: monster.c:850
obj::hide
uint8_t hide
Definition: object.h:392
NDI_DELAYED
#define NDI_DELAYED
Definition: newclient.h:269
monster_pace2_movev
static void monster_pace2_movev(object *ob)
Definition: monster.c:2204
FLAG_FREED
#define FLAG_FREED
Definition: define.h:233
SPELL_GRACE
#define SPELL_GRACE
Definition: spells.h:59
monster_circ2_move
static void monster_circ2_move(object *ob)
Definition: monster.c:2165
path_data::movement_penalty
int16_t movement_penalty
Definition: monster.c:421
monster_check_doors
void monster_check_doors(object *op, mapstruct *m, int x, int y)
Definition: monster.c:2270
AP_IGNORE_CURSE
#define AP_IGNORE_CURSE
Definition: define.h:582
absdir
int absdir(int d)
Definition: object.c:3685
monster_compute_path
int monster_compute_path(object *source, object *target, int default_dir)
Definition: monster.c:465
path_data::x
int16_t x
Definition: monster.c:416
struct_dialog_reply
Definition: dialog.h:18
obj::carrying
int32_t carrying
Definition: object.h:372
MAX_NPC
#define MAX_NPC
Definition: dialog.h:46
CIRCLE2
#define CIRCLE2
Definition: define.h:513
obj::x
int16_t x
Definition: object.h:330
SP_SMITE
#define SP_SMITE
Definition: spells.h:84
fix_object
void fix_object(object *op)
Definition: living.c:1126
FLAG_PARALYZED
#define FLAG_PARALYZED
Definition: define.h:371
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
FLAG_USE_SHIELD
#define FLAG_USE_SHIELD
Definition: define.h:237
mapdef::darkness
uint8_t darkness
Definition: map.h:339
rt_say
@ rt_say
Definition: dialog.h:10
GET_MAP_MOVE_BLOCK
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:193
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
GOLEM
@ GOLEM
Definition: object.h:145
apply_can_apply_object
int apply_can_apply_object(const object *who, const object *op)
Definition: apply.c:1016
object_set_value
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.c:4470
sstring
const typedef char * sstring
Definition: global.h:40
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
FLAG_USE_WEAPON
#define FLAG_USE_WEAPON
Definition: define.h:296
sproto.h
ARROW
@ ARROW
Definition: object.h:117
IS_SHIELD
#define IS_SHIELD(op)
Definition: define.h:170
GET_MAP_LIGHT
#define GET_MAP_LIGHT(M, X, Y)
Definition: map.h:166
FLAG_CAN_USE_SKILL
#define FLAG_CAN_USE_SKILL
Definition: define.h:321
monster_can_see_enemy
int monster_can_see_enemy(object *op, object *enemy)
Definition: monster.c:2752
rt_reply
@ rt_reply
Definition: dialog.h:11
PACEV
#define PACEV
Definition: define.h:524
monster_communicate
void monster_communicate(object *op, const char *txt)
Definition: monster.c:2366
obj::enemy
struct obj * enemy
Definition: object.h:386
mapdef
Definition: map.h:317
SP_level_spellpoint_cost
int16_t SP_level_spellpoint_cost(object *caster, object *spell, int flags)
Definition: spell_util.c:235
monster_can_hit
static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv)
Definition: monster.c:1137
RING
@ RING
Definition: object.h:185
liv::Int
int8_t Int
Definition: living.h:36
obj::animation
const Animations * animation
Definition: object.h:421
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
LO4
#define LO4
Definition: define.h:530
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
FLAG_RANDOM_MOVE
#define FLAG_RANDOM_MOVE
Definition: define.h:309
SIZEOFFREE
#define SIZEOFFREE
Definition: define.h:155
P_OUT_OF_MAP
#define P_OUT_OF_MAP
Definition: map.h:250
MAX_BUF
#define MAX_BUF
Definition: define.h:35
obj::spellitem
struct obj * spellitem
Definition: object.h:399
monster_do_living
void monster_do_living(object *op)
Definition: monster.c:715
MSG_TYPE_DIALOG
#define MSG_TYPE_DIALOG
Definition: newclient.h:400
IS_WEAPON
#define IS_WEAPON(op)
Definition: define.h:163
talk_info::text
const char * text
Definition: dialog.h:53
pets_move
void pets_move(object *ob)
Definition: pets.c:317
RANDOM
#define RANDOM()
Definition: define.h:644
HI4
#define HI4
Definition: define.h:531
move_object
int move_object(object *op, int dir)
Definition: move.c:39
SK_HIDING
@ SK_HIDING
Definition: skills.h:21
StringBuffer
Definition: stringbuffer.c:25
MOVE_FLY_LOW
#define MOVE_FLY_LOW
Definition: define.h:393
SP_MAGIC_WALL
#define SP_MAGIC_WALL
Definition: spells.h:89
monster_check_good_armour
static int monster_check_good_armour(object *who, object *item)
Definition: monster.c:1691
guildbuy.ob2
ob2
Definition: guildbuy.py:23
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
obj::y
int16_t y
Definition: object.h:330
SP_INVISIBLE
#define SP_INVISIBLE
Definition: spells.h:93
OUT_OF_REAL_MAP
#define OUT_OF_REAL_MAP(M, X, Y)
Definition: map.h:218
dirdiff
int dirdiff(int dir1, int dir2)
Definition: object.c:3703
monster_find_nearest_enemy
object * monster_find_nearest_enemy(object *npc, object *owner)
Definition: monster.c:175
monster_use_skill
static int monster_use_skill(object *head, object *part, object *pl, int dir)
Definition: monster.c:1428
MAGIC_EAR
@ MAGIC_EAR
Definition: object.h:131
obj::arch
struct archt * arch
Definition: object.h:417
monster_dist_att
static int monster_dist_att(int dir, object *enemy, object *part, rv_vector *rv)
Definition: monster.c:2046
diamondslots.message
string message
Definition: diamondslots.py:57
FLAG_READY_SKILL
#define FLAG_READY_SKILL
Definition: define.h:333
FLAG_READY_BOW
#define FLAG_READY_BOW
Definition: define.h:299
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
path_data::y
int16_t y
Definition: monster.c:417
reply_type
reply_type
Definition: dialog.h:9
get_reply_text_other
static const char * get_reply_text_other(reply_type rt)
Definition: monster.c:2328
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
ext_info_map_except
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:219
obj::type
uint8_t type
Definition: object.h:343
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
monster_pace_movev
static void monster_pace_movev(object *ob)
Definition: monster.c:2178
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Definition: define.h:246
spells.h
guildbuy.ob1
ob1
Definition: guildbuy.py:22
struct_dialog_message
Definition: dialog.h:28
obj::stats
living stats
Definition: object.h:373
MSG_TYPE_SKILL_FAILURE
#define MSG_TYPE_SKILL_FAILURE
Definition: newclient.h:590
obj::direction
int8_t direction
Definition: object.h:339
path_data::distance
uint16_t distance
Definition: monster.c:418
archt::clone
object clone
Definition: object.h:473
SIZEOFFREE2
#define SIZEOFFREE2
Definition: define.h:154
obj::contr
struct pl * contr
Definition: object.h:279
obj::facing
int8_t facing
Definition: object.h:340
MAX_REPLIES
#define MAX_REPLIES
Definition: dialog.h:44
use_trigger
void use_trigger(object *op)
Definition: button.c:254
obj::weight
int32_t weight
Definition: object.h:370
IS_ARMOR
#define IS_ARMOR(op)
Definition: define.h:166
FLAG_USE_ARMOUR
#define FLAG_USE_ARMOUR
Definition: define.h:295
item
Definition: item.py:1
FLAG_CAST_SPELL
#define FLAG_CAST_SPELL
Definition: define.h:290
EARTHWALL
@ EARTHWALL
Definition: object.h:144
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
path_measure_func
int path_measure_func(const void *ob)
Definition: monster.c:433
SP_MOVING_BALL
#define SP_MOVING_BALL
Definition: spells.h:109
liv::Wis
int8_t Wis
Definition: living.h:36
liv::grace
int16_t grace
Definition: living.h:44
rt_question
@ rt_question
Definition: dialog.h:12
give.op
op
Definition: give.py:33
autojail.value
value
Definition: autojail.py:6
object_value_set
bool object_value_set(const object *op, const char *const key)
Definition: object.c:4347
monster_can_pick
static int monster_can_pick(object *monster, object *item)
Definition: monster.c:1887
pets_follow_owner
void pets_follow_owner(object *ob, object *owner)
Definition: pets.c:284
rv_vector
Definition: map.h:373
get_dialog_message
int get_dialog_message(object *op, const char *text, struct_dialog_message **message, struct_dialog_reply **reply)
Definition: dialog.c:209
hit_player
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Definition: attack.c:1860
do_hidden_move
void do_hidden_move(object *op)
Definition: player.c:4005
diamondslots.y
y
Definition: diamondslots.py:16
NDI_WHITE
#define NDI_WHITE
Definition: newclient.h:243
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
buf
StringBuffer * buf
Definition: readable.c:1610
AP_NOPRINT
#define AP_NOPRINT
Definition: define.h:585
talk_info
Definition: dialog.h:51
pl::hidden
uint32_t hidden
Definition: player.h:147
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.c:138
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2833
guild_entry.x1
int x1
Definition: guild_entry.py:33
MSG_TYPE_DIALOG_MAGIC_EAR
#define MSG_TYPE_DIALOG_MAGIC_EAR
Definition: newclient.h:489
obj::head
struct obj * head
Definition: object.h:299
obj::subtype
uint8_t subtype
Definition: object.h:344
obj::more
struct obj * more
Definition: object.h:298
MSG_TYPE_DIALOG_NPC
#define MSG_TYPE_DIALOG_NPC
Definition: newclient.h:487
obj::move_type
MoveType move_type
Definition: object.h:429
fire_bow
int fire_bow(object *op, object *arrow, int dir, int wc_mod, int16_t sx, int16_t sy)
Definition: player.c:2080
monster_find_enemy
static object * monster_find_enemy(object *npc, rv_vector *rv)
Definition: monster.c:234
talk_info::npc_msgs
sstring npc_msgs[MAX_NPC]
Definition: dialog.h:60
npc_dialog.npc
npc
Definition: npc_dialog.py:95
make_face_from_files.int
int
Definition: make_face_from_files.py:26
MIN_ACTIVE_SPEED
#define MIN_ACTIVE_SPEED
Definition: define.h:639
estimate_distance
static uint16_t estimate_distance(int16_t ax, int16_t ay, int16_t bx, int16_t by)
Definition: monster.c:443
obj::pick_up
uint8_t pick_up
Definition: object.h:366
monster_rand_move
static void monster_rand_move(object *ob)
Definition: monster.c:2234
draw_ext_info
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.c:309
FLAG_BERSERK
#define FLAG_BERSERK
Definition: define.h:352
get_attr_value
int8_t get_attr_value(const living *stats, int attr)
Definition: living.c:314
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.c:1546
FOOD
@ FOOD
Definition: object.h:112
monster_wait_att
static int monster_wait_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv)
Definition: monster.c:2098
DOOR
@ DOOR
Definition: object.h:126
player_can_view
int player_can_view(object *pl, object *op)
Definition: player.c:4114
object_find_by_type_and_race
object * object_find_by_type_and_race(const object *who, int type, const char *race)
Definition: object.c:4104
FLAG_UNPAID
#define FLAG_UNPAID
Definition: define.h:236
monster_circ1_move
static void monster_circ1_move(object *ob)
Definition: monster.c:2152
SP_SUMMON_GOLEM
#define SP_SUMMON_GOLEM
Definition: spells.h:86
monster_can_detect_enemy
int monster_can_detect_enemy(object *op, object *enemy, rv_vector *rv)
Definition: monster.c:2569
WAIT2
#define WAIT2
Definition: define.h:499
path_data::heuristic_dist
uint16_t heuristic_dist
Definition: monster.c:419
FLAG_READY_RANGE
#define FLAG_READY_RANGE
Definition: define.h:298
SCROLL
@ SCROLL
Definition: object.h:221
DISTHIT
#define DISTHIT
Definition: define.h:498
FLAG_XRAYS
#define FLAG_XRAYS
Definition: define.h:300
RUSH
#define RUSH
Definition: define.h:496
monster_check_pickup
static void monster_check_pickup(object *monster)
Definition: monster.c:1843
PETMOVE
#define PETMOVE
Definition: define.h:501
monster_move_no_enemy
static int monster_move_no_enemy(object *op)
Definition: monster.c:778
obj::will_apply
uint8_t will_apply
Definition: object.h:397
MSG_TYPE_COMMUNICATION
#define MSG_TYPE_COMMUNICATION
Definition: newclient.h:410
drain_rod_charge
void drain_rod_charge(object *rod)
Definition: spell_util.c:775
DISTATT
#define DISTATT
Definition: define.h:491
WILL_APPLY_TREASURE
#define WILL_APPLY_TREASURE
Definition: object.h:53
monster_pace_moveh
static void monster_pace_moveh(object *ob)
Definition: monster.c:2191
mapdef::path
char path[HUGE_BUF]
Definition: map.h:358
get_map_flags
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
Definition: map.c:301
get_search_arr
void get_search_arr(int *search_arr)
Definition: object.c:3613
SPELL
@ SPELL
Definition: object.h:214
events_execute_object_say
int events_execute_object_say(object *npc, talk_info *talk)
Definition: events.cpp:278
replace.current
current
Definition: replace.py:64
monster_find_throw_ob
object * monster_find_throw_ob(object *op)
Definition: monster.c:2530
liv::sp
int16_t sp
Definition: living.h:42
monster_pace2_moveh
static void monster_pace2_moveh(object *ob)
Definition: monster.c:2219
SP_SWARM
#define SP_SWARM
Definition: spells.h:110
monster_wait_att2
static int monster_wait_att2(int dir, rv_vector *rv)
Definition: monster.c:2142
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
FLAG_USE_SCROLL
#define FLAG_USE_SCROLL
Definition: define.h:291
mapdef::width
uint16_t width
Definition: map.h:340
CIRCLE1
#define CIRCLE1
Definition: define.h:509
rv_vector::direction
int direction
Definition: map.h:377
makes_invisible_to
int makes_invisible_to(object *pl, object *mon)
Definition: spell_effect.c:765
monster_cast_spell
static int monster_cast_spell(object *head, object *part, object *pl, int dir)
Definition: monster.c:1258
on_same_map
int on_same_map(const object *op1, const object *op2)
Definition: map.c:2657
PACEH2
#define PACEH2
Definition: define.h:516
SP_EXPLOSION
#define SP_EXPLOSION
Definition: spells.h:80
obj::resist
int16_t resist[NROFATTACKS]
Definition: object.h:346
FLAG_IS_THROWN
#define FLAG_IS_THROWN
Definition: define.h:249
THROWN_OBJ
@ THROWN_OBJ
Definition: object.h:146
get_map_from_coord
mapstruct * get_map_from_coord(mapstruct *m, int16_t *x, int16_t *y)
Definition: map.c:2385
FLAG_SLEEP
#define FLAG_SLEEP
Definition: define.h:307
SK_THROWING
@ SK_THROWING
Definition: skills.h:44
object_split
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
Definition: object.c:2613
guild_entry.y1
int y1
Definition: guild_entry.py:34
rv_vector::distance
unsigned int distance
Definition: map.h:374
SPELLBOOK
@ SPELLBOOK
Definition: object.h:203
NUM_STATS
@ NUM_STATS
Definition: living.h:18
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
MSG_TYPE_COMMUNICATION_SAY
#define MSG_TYPE_COMMUNICATION_SAY
Definition: newclient.h:623
drain_wand_charge
void drain_wand_charge(object *wand)
Definition: spell_util.c:785
monster_disthit_att
static int monster_disthit_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv)
Definition: monster.c:2123
can_see_monsterP
int can_see_monsterP(mapstruct *m, int x, int y, int dir)
Definition: object.c:3793
MAX_LIGHT_RADII
#define MAX_LIGHT_RADII
Definition: define.h:450
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:319
obj::level
int16_t level
Definition: object.h:356
WILL_APPLY_FOOD
#define WILL_APPLY_FOOD
Definition: object.h:56
llevDebug
@ llevDebug
Definition: logger.h:13
MONEY
@ MONEY
Definition: object.h:137
obj::range
int8_t range
Definition: object.h:410
RANDO2
#define RANDO2
Definition: define.h:523
FLAG_IS_FLOOR
#define FLAG_IS_FLOOR
Definition: define.h:302
is_true_undead
int is_true_undead(object *op)
Definition: player.c:3940
obj::inv
struct obj * inv
Definition: object.h:293
give.name
name
Definition: give.py:27
MIN_MON_RADIUS
#define MIN_MON_RADIUS
Definition: monster.c:56
skill_attack
void skill_attack(object *tmp, object *pl, int dir, const char *string, object *skill)
Definition: skill_util.c:1272
SPELL_MANA
#define SPELL_MANA
Definition: spells.h:58
object_get_owner
object * object_get_owner(object *op)
Definition: object.c:808