Crossfire Server  1.75.0
monster.cpp
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 "shop.h"
30 #include "minheap.h"
31 
32 static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv);
33 static int monster_cast_spell(object *head, object *part, object *pl, int dir);
34 static int monster_use_scroll(object *head, object *part, object *pl, int dir);
35 static int monster_use_skill(object *head, object *part, object *pl, int dir);
36 static int monster_use_range(object *head, object *part, object *pl, int dir);
37 static int monster_use_bow(object *head, object *part, object *pl, int dir);
38 static void monster_check_pickup(object *monster);
39 static int monster_can_pick(object *monster, object *item);
40 static void monster_apply_below(object *monster);
41 static int monster_dist_att(int dir, object *enemy, object *part, rv_vector *rv);
42 static int monster_run_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv);
43 static int monster_hitrun_att(int dir, object *ob);
44 static int monster_wait_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv);
45 static int monster_disthit_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv);
46 static int monster_wait_att2(int dir, rv_vector *rv);
47 static void monster_circ1_move(object *ob);
48 static void monster_circ2_move(object *ob);
49 static void monster_pace_movev(object *ob);
50 static void monster_pace_moveh(object *ob);
51 static void monster_pace2_movev(object *ob);
52 static void monster_pace2_moveh(object *ob);
53 static void monster_rand_move(object *ob);
54 static void shopkeeper_move(object *ob);
55 static int monster_talk_to_npc(object *npc, talk_info *info);
56 
58 #define MIN_MON_RADIUS 3
59 
61 const char *key_shopkeeper = "shopkeeper";
62 const char *key_shopkeeper_debug = "shopkeeper_debug";
63 const char *key_shopkeeper_pilesize = "shopkeeper_pilesize";
80 object *monster_check_enemy(object *npc, rv_vector *rv) {
81  object *owner;
82 
83  /* if this is pet, let him attack the same enemy as his owner
84  * TODO: when there is no ower enemy, try to find a target,
85  * which CAN attack the owner. */
86  owner = object_get_owner(npc);
87  if ((npc->attack_movement&HI4) == PETMOVE) {
88  if (owner == NULL)
89  object_set_enemy(npc, NULL);
90  else if (npc->enemy == NULL)
91  object_set_enemy(npc, owner->enemy);
92  }
93 
94  /* periodically, a monster may change its target. Also, if the object
95  * has been destroyed, etc, clear the enemy.
96  * TODO: this should be changed, because it invokes to attack forced or
97  * attacked monsters to leave the attacker alone, before it is destroyed
98  */
99  /* i had removed the random target leave, this invokes problems with friendly
100  * objects, getting attacked and defending herself - they don't try to attack
101  * again then but perhaps get attack on and on
102  * If we include a aggravated flag in , we can handle evil vs evil and good vs good
103  * too. */
104 
105  if (npc->enemy && !object_value_set(npc, "is_guard")) {
106  /* I broke these if's apart to better be able to see what
107  * the grouping checks are. Code is the same.
108  */
109  if (QUERY_FLAG(npc->enemy, FLAG_REMOVED)
110  || QUERY_FLAG(npc->enemy, FLAG_FREED)
111  || !on_same_map(npc, npc->enemy)
112  || npc == npc->enemy
113  || QUERY_FLAG(npc, FLAG_NEUTRAL)
114  || QUERY_FLAG(npc->enemy, FLAG_NEUTRAL))
115  object_set_enemy(npc, NULL);
116 
117  else if (QUERY_FLAG(npc, FLAG_FRIENDLY) && (
118  (QUERY_FLAG(npc->enemy, FLAG_FRIENDLY) && !pets_should_arena_attack(npc, owner, npc->enemy))
119  || (npc->enemy->type == PLAYER && !pets_should_arena_attack(npc, owner, npc->enemy))
120  || npc->enemy == owner))
121  object_set_enemy(npc, NULL);
122  else if (!QUERY_FLAG(npc, FLAG_FRIENDLY)
123  && (!QUERY_FLAG(npc->enemy, FLAG_FRIENDLY) && npc->enemy->type != PLAYER))
124  object_set_enemy(npc, NULL);
125 
126  /* I've noticed that pets could sometimes get an arrow as the
127  * target enemy - this code below makes sure the enemy is something
128  * that should be attacked. My guess is that the arrow hits
129  * the creature/owner, and so the creature then takes that
130  * as the enemy to attack.
131  */
132  else if (!QUERY_FLAG(npc->enemy, FLAG_MONSTER)
133  && !QUERY_FLAG(npc->enemy, FLAG_GENERATOR)
134  && npc->enemy->type != PLAYER
135  && npc->enemy->type != GOLEM)
136  object_set_enemy(npc, NULL);
137  }
138  return monster_can_detect_enemy(npc, npc->enemy, rv) ? npc->enemy : NULL;
139 }
140 
150 static int is_enemy(object *who, object *owner) {
151  if (who == owner) {
152  return 0;
153  }
154  if (!QUERY_FLAG(who, FLAG_MONSTER) && !QUERY_FLAG(who, FLAG_GENERATOR) && who->type != PLAYER) {
155  return 0;
156  }
157  if (QUERY_FLAG(who, FLAG_MONSTER) && owner && object_get_owner(who) == owner) {
158  return 0;
159  }
160  if (who->type == PLAYER && owner && owner->type == PLAYER) {
161  if (owner->contr->peaceful && who->contr->peaceful) {
162  return 0;
163  }
164  }
165  return 1;
166 }
167 
183 object *monster_find_nearest_enemy(object *npc, object *owner) {
184  int i, mflags;
185  int16_t nx, ny;
186  mapstruct *m;
187  int search_arr[SIZEOFFREE];
188 
189  get_search_arr(search_arr);
190  for (i = 0; i < SIZEOFFREE; i++) {
191  /* modified to implement smart searching using search_arr
192  * guidance array to determine direction of search order
193  */
194  nx = npc->x+freearr_x[search_arr[i]];
195  ny = npc->y+freearr_y[search_arr[i]];
196  m = npc->map;
197 
198  if (nx == npc->x && ny == npc->y) {
199  continue; // Don't try to attack ourself
200  }
201 
202  mflags = get_map_flags(m, &m, nx, ny, &nx, &ny);
203  if (mflags&P_OUT_OF_MAP)
204  continue;
205 
206  if (mflags&P_IS_ALIVE) {
207  object *creature = NULL;
208  FOR_MAP_PREPARE(m, nx, ny, tmp)
209  if (is_enemy(tmp, owner)) {
210  creature = tmp;
211  break;
212  }
213  FOR_MAP_FINISH();
214  // it is possible to not find an enemy even if the square is alive,
215  // e.g. the npc's owner is there
216  if (creature) {
217  if (can_see_monsterP(m, npc->x, npc->y, i))
218  return creature;
219  }
220  } /* is something living on this space */
221  }
222  return NULL; /* nothing found */
223 }
224 
240 static object *monster_find_enemy(object *npc, rv_vector *rv) {
241  object *attacker, *tmp = NULL;
242 
243  attacker = npc->attacked_by; /* save this for later use. This can be a attacker. */
244  npc->attacked_by = NULL; /* always clear the attacker entry */
245 
246  /* if we berserk, we don't care about others - we attack all we can find */
247  if (QUERY_FLAG(npc, FLAG_BERSERK)) {
248  tmp = monster_find_nearest_enemy(npc, NULL);
249  if (tmp == NULL)
250  return NULL;
251  if (!get_rangevector(npc, tmp, rv, 0))
252  return NULL;
253  return tmp;
254  }
255 
256  /* Here is the main enemy selection.
257  * We want this: if there is an enemy, attack him until its not possible or
258  * one of both is dead.
259  * If we have no enemy and we are...
260  * a monster: try to find a player, a pet or a friendly monster
261  * a friendly: only target a monster which is targeting you first or targeting a player
262  * a neutral: fight a attacker (but there should be none), then do nothing
263  * a pet: attack player enemy or a monster
264  */
265 
266  /* pet move */
267  if ((npc->attack_movement&HI4) == PETMOVE) {
268  tmp = pets_get_enemy(npc, rv);
269  if (tmp == NULL)
270  return NULL;
271  if (!get_rangevector(npc, tmp, rv, 0))
272  return NULL;
273  return tmp;
274  }
275 
276  /* we check our old enemy. */
277  tmp = monster_check_enemy(npc, rv);
278  if (tmp == NULL) {
279  if (attacker) { /* if we have an attacker, check him */
280  /* we want be sure this is the right one! */
281  if (attacker->count == npc->attacked_by_count) {
282  /* TODO: thats not finished */
283  /* we don't want a fight evil vs evil or good against non evil */
284  if (QUERY_FLAG(npc, FLAG_NEUTRAL)
285  || QUERY_FLAG(attacker, FLAG_NEUTRAL) /* neutral */
286  || (QUERY_FLAG(npc, FLAG_FRIENDLY) && QUERY_FLAG(attacker, FLAG_FRIENDLY))
287  || (!QUERY_FLAG(npc, FLAG_FRIENDLY) && (!QUERY_FLAG(attacker, FLAG_FRIENDLY) && attacker->type != PLAYER)))
288  CLEAR_FLAG(npc, FLAG_SLEEP); /* skip it, but lets wakeup */
289  else if (on_same_map(npc, attacker)) { /* thats the only thing we must know... */
290  CLEAR_FLAG(npc, FLAG_SLEEP); /* well, NOW we really should wake up! */
291  object_set_enemy(npc, attacker);
292  if (!get_rangevector(npc, attacker, rv, 0))
293  return NULL;
294  return attacker; /* yes, we face our attacker! */
295  }
296  }
297  }
298 
299  if (object_value_set(npc, "is_guard")) {
301  if (npc->enemy) {
302  char buf[MAX_BUF];
303  snprintf(buf, sizeof(buf), "Halt, %s, you are under arrest!", npc->enemy->name);
304  monster_npc_say(npc, buf);
305  tmp = monster_check_enemy(npc, rv);
306  }
307  } else {
308  /* we have no legal enemy or attacker, so we try to target a new one */
309  if (!QUERY_FLAG(npc, FLAG_UNAGGRESSIVE)
310  && !QUERY_FLAG(npc, FLAG_FRIENDLY)
311  && !QUERY_FLAG(npc, FLAG_NEUTRAL)) {
313  if (npc->enemy)
314  tmp = monster_check_enemy(npc, rv);
315  }
316  }
317  }
318 
319  return tmp;
320 }
321 
337 static int monster_check_wakeup(object *op, object *enemy, rv_vector *rv) {
338  int radius = MAX(op->stats.Wis, MIN_MON_RADIUS);
339 
340  /* Trim work - if no enemy, no need to do anything below */
341  if (!enemy)
342  return 0;
343 
344  /* blinded monsters can only find nearby objects to attack */
345  if (QUERY_FLAG(op, FLAG_BLIND))
346  radius = MIN_MON_RADIUS;
347 
348  /* This covers the situation where the monster is in the dark
349  * and has an enemy. If the enemy has no carried light (or isnt
350  * glowing!) then the monster has trouble finding the enemy.
351  * Remember we already checked to see if the monster can see in
352  * the dark. */
353  else if (op->map
354  && op->map->darkness > 0
355  && enemy
356  && !enemy->invisible
357  && !monster_stand_in_light(enemy)
359  int dark = radius/(op->map->darkness);
360 
361  radius = (dark > MIN_MON_RADIUS) ? (dark+1) : MIN_MON_RADIUS;
362  } else if (!QUERY_FLAG(op, FLAG_SLEEP))
363  return 1;
364 
365  /* enemy should already be on this map, so don't really need to check
366  * for that.
367  */
368  if (rv->distance < (unsigned)(QUERY_FLAG(enemy, FLAG_STEALTH) ? radius/2+1 : radius)) {
369  CLEAR_FLAG(op, FLAG_SLEEP);
370  return 1;
371  }
372  return 0;
373 }
374 
383 static int monster_move_randomly(object *op) {
384  int i;
385  sstring talked;
386  char value[2];
387 
388  /* timeout before moving */
389  if (QUERY_FLAG(op, FLAG_UNAGGRESSIVE)) {
390  talked = object_get_value(op, "talked_to");
391  if (talked && strlen(talked) > 0) {
392  i = atoi(talked);
393  i--;
394 
395  if (i != 0) {
396  value[1] = '\0';
397  value[0] = '0' + i;
398  object_set_value(op, "talked_to", value, 1);
399  return 1;
400  }
401 
402  /* finished timeout talked to */
403  object_set_value(op, "talked_to", "", 1);
404  }
405  }
406 
407  /* Give up to 15 chances for a monster to move randomly */
408  for (i = 0; i < 15; i++) {
409  if (move_object(op, RANDOM()%8+1))
410  return 1;
411  }
412  return 0;
413 }
414 
416 #define MAX_EXPLORE 5000
417 
421 struct path_data {
422  int16_t x;
423  int16_t y;
424  uint16_t distance;
425  uint16_t heuristic_dist;
426  // This way we only have to calculate penalties once per tile per pathing calculation.
428 };
429 
439 int path_measure_func(const void *ob) {
440  const path_data *dat = (path_data *)ob;
441  return dat->distance + dat->heuristic_dist;
442 }
443 
449 static inline uint16_t estimate_distance(int16_t ax, int16_t ay, int16_t bx, int16_t by) {
450  uint16_t dx = FABS(ax - bx), dy = FABS(ay - by);
451  uint16_t diag = MIN(dx, dy);
452  return (MAX(dx, dy) - diag) * 2 + diag * 3;
453 }
454 
471 int monster_compute_path(object *source, object *target, int default_dir) {
472  path_data *distance, *current, *explore;
473  path_data *heaparr[MAX_EXPLORE];
474  int dirs[8];
475  int dir, x, y, i;
476  MinHeap heap;
477 
478  if (target->map != source->map)
479  return default_dir;
480 
481  // These shouldn't change during the calculation, so store them once to avoid dereferencing.
482  mapstruct * cur_map = source->map; // Not constant to silence some warnings.
483  const uint16_t map_height = cur_map->height;
484  /*printf("monster_compute_path (%d, %d) => (%d, %d)\n", source->x, source->y, target->x, target->y);*/
485 
486  // Leave width like this because it is used just this once.
487  const int size = cur_map->width * map_height;
488 
489  // Determine the amount by which terrain is over or under valued by the monster.
490  /* terrain value is as follows:
491  * 0 - ignore terrain penalties
492  * 1 - undervalue terrain penalties by half
493  * 2 - correctly value terrain penalties
494  * 3 - overvalue terrain penalties by 50%
495  */
496  int terrain_value;
497  if (source->attack_movement & RUSH)
498  terrain_value = 0;
499  else if (source->stats.Int < 8) {
500  terrain_value = 0;
501  }
502  else if (source->stats.Int < 13) {
503  // If low Wis, then over-value terrain penalties.
504  // Otherwise, under-value terrain penalties.
505  if (source->stats.Wis < 13) {
506  terrain_value = 3;
507  }
508  else {
509  terrain_value = 1;
510  }
511  }
512  else {
513  terrain_value = 2;
514  }
515 
526  if (!source->more) // Skip multitile monsters, since this does not work right for them
527  {
528  dir = -1; // Set a sentinel. -1 = no escape, 0 = many ways out, [1, 8] = one way out in dir
529  for (i = 1; i <= 8; ++i)
530  {
531  x = source->x + freearr_x[i];
532  y = source->y + freearr_y[i];
533  if (OUT_OF_REAL_MAP(cur_map, x, y))
534  continue;
535  if (ob_blocked(source, cur_map, x, y))
536  continue;
537  // We have a way out. Make note of it
538  if (dir < 0)
539  dir = i;
540  // We have many ways out -- do the pathing part of the function
541  else
542  {
543  dir = 0;
544  break;
545  }
546  }
547  // If dir > 0, we have our direction to go, as it is our only choice.
548  if (dir > 0)
549  return dir;
550  // If dir < 0, then we have no way to go. Return default_dir.
551  if (dir < 0)
552  return default_dir;
553  }
554 
555  /* We are setting all the values manually anyway,
556  * so there's no reason to use calloc().
557  * malloc() is more efficient here for that reason.
558  */
559  distance = static_cast<path_data *>(malloc(size * sizeof(*distance)));
560  if (distance == NULL) {
562  }
563  /*
564  * To set to 65535 efficiently, though, I need to memset each byte to 255.
565  * each element is multiple bytes, and this will fill the non-distance values, too.
566  */
567  memset(distance, 255, sizeof(*distance) * size);
568 
569  // Set current to the starting point.
570  current = &distance[map_height * target->x + target->y];
571 
572  current->distance = 0;
573  current->x = target->x;
574  current->y = target->y;
575  current->heuristic_dist = 0;
576  current->movement_penalty = 0;
577 
578  // Initialize the minheap
579  minheap_init_static(&heap, (void **)heaparr, MAX_EXPLORE, path_measure_func);
580 
581  /* The first time through, current = 0 and max = 1.
582  * This will evaluate to true, so we might as well use a do-while loop.
583  */
584  do {
585  /* Fisher–Yates shuffle the directions, "inside-out" algorithm
586  * from http://en.wikipedia.org/wiki/Fisher-Yates_shuffle */
587  dirs[0] = 1;
588  for (i = 1; i < 8; ++i) {
589  x = RANDOM() % (i+1);
590  dirs[i] = dirs[x];
591  dirs[x] = i+1;
592  }
593 
594  for (i = 0; i < 8; ++i) {
595  uint16_t new_distance;
596 
597  /*
598  * dirs[i] is the direction we wish to check.
599  */
600  dir = absdir(default_dir+4+dirs[i]);
601  x = current->x+freearr_x[dir];
602  y = current->y+freearr_y[dir];
603 
604  if (x == source->x && y == source->y) {
605  // Randomly decide to bob/weave on some steps if not RUSH movement.
606  // When not in RUSH mode, 1/4 chance of bob/weaving
607  if (source->attack_movement != RUSH && (RANDOM() & 3) == 0) {
608  // We take the perspective of the source when determining our dodge/weave direction,
609  // incorporating the required dir+4 reversal immediately.
610  int newdir = absdir(dir+4+1-(RANDOM()&2)); // Bob/weave up to one space.
611  int newx = source->x+freearr_x[newdir],
612  newy = source->y+freearr_y[newdir];
613  // If we travel out of the map with this dodge, then we didn't try to path there.
614  // In such a case, we need to skip bob/weave and just go at the target.
615  if (!OUT_OF_REAL_MAP(source->map, newx, newy)) {
616  const path_data *newloc = &distance[map_height * newx + newy];
617  // If we checked the tile during pathing and it is not a wall and the movement penalty of the tile
618  // is not greater than the shortest-path's movement penalty, then go to that space.
619  if (newloc->distance != 65535 && newloc->distance != 1 &&
620  newloc->movement_penalty <= current->movement_penalty)
621  dir = newdir; // Commit to the bob/weave
622  else
623  dir = absdir(dir + 4);
624  }
625  else
626  dir = absdir(dir + 4);
627  }
628  // Otherwise, just follow the path we were given.
629  else
630  dir = absdir(dir + 4);
631  free(distance);
632  return dir;
633  }
634 
635  if (OUT_OF_REAL_MAP(cur_map, x, y))
636  continue;
637 
638  // Move these up, so we can reduce calls to ob_blocked with their info.
639  assert(map_height * x + y >= 0);
640  assert(map_height * x + y < size);
641 
642  // Set a pointer to the tile we are exploring.
643  explore = &distance[map_height * x + y];
644 
645  // Penalty-less spaces are handled by the inline if in the new_distance assignment.
646  // We can have move_penalty be zero because it assumes the penalty-less cost is already accounted for.
647  int16_t move_penalty = 0;
648  // Skip the penalty search if terrain value is zero. We will ignore any move penalty anyway.
649  if (terrain_value > 0) {
650  // Only calculate movement penalty if this tile does not have it yet.
651  if (explore->movement_penalty == -1) {
652  // Sum the move_slow_penalties on the map space.
653  object *tmp = GET_MAP_OB(cur_map, x, y);
655  if ((!source->move_type && tmp->move_slow&MOVE_WALK)
656  || ((source->move_type&tmp->move_slow) && (source->move_type&~tmp->move_slow&~tmp->move_block) == 0)) {
657  move_penalty += (int16_t)tmp->move_slow_penalty;
658  }
660  // And, make sure to store this for when we bump into this tile again
661  explore->movement_penalty = move_penalty;
662  }
663  else {
664  move_penalty = explore->movement_penalty;
665  }
666  }
667 
668  /* Mod 2 is equivalent to checking only the 1's bit (1 or 0), but & 1 is faster.
669  * Also, dir & 1 == 0 is true if we have a diagonal dir.
670  */
671  const int base_move_cost = ((dir & 1) == 0 ? 3 : 2);
672 
673  new_distance =
674  current->distance
675  // If terrain value is zero, we will ignore movement_penalties.
676  // If move_penalty is 0, then there were no penalties for moving onto this space.
677  + (move_penalty != 0 && terrain_value != 0 ? base_move_cost + base_move_cost * move_penalty * terrain_value / 2 : base_move_cost);
678 
679  // If already known blocked or arrivable in less distance, we skip
680  if (explore->distance <= new_distance)
681  continue;
682  // If we have a non-default value here, we will have lready done ob_blocked on it.
683  // So, only call ob_blocked if we are staring at 65535.
684  // If we are not looking at an untested space, then we will skip this block and avoid ob_blocked
685  if (explore->distance == 65535 && ob_blocked(source, cur_map, x, y))
686  {
687  // Mark as something we can't otherwise get -- the goal is to cache what spaces are blocked.
688  // At least, this call to monster_compute_path will remember this spot is blocked.
689  // This should cut our calls to ob_blocked some.
690  explore->distance = 1;
691  // The value of 1 also allows for walls to be considered already checked, but since we do not add to the
692  // explore array, this makes them hit the condition above if they are checked again without going through walls.
693  continue;
694  }
695 
696  /*LOG(llevDebug, "check %d, %d dist = %d, nd = %d\n", x, y, distance[source->map->height*x+y], new_distance);*/
697 
698  // Only set x and y when we insert into the minheap.
699  explore->x = x;
700  explore->y = y;
701  explore->distance = new_distance;
702  explore->heuristic_dist = estimate_distance(x, y, source->x, source->y); // Add a heuristic to make this A*.
703  /* printf("explore[%d] => (%d, %d) %u\n", max, x, y, new_distance);*/
704 
705  // TODO: If the space has already been evaluated, we'd really want to do an in-place update, not an insert.
706 
707  // If the heap is full when we try to insert, then we have exhausted exploration space.
708  if (minheap_insert(&heap, explore) != 0) {
709  free(distance);
710  return default_dir;
711  }
712  }
713  current = static_cast<path_data *>(minheap_remove(&heap));
714  } while (current != NULL);
715 
716  /*LOG(llevDebug, "no path\n");*/
717  free(distance);
718  return default_dir;
719 }
720 
727 void monster_do_living(object *op) {
728  assert(op);
729  assert(QUERY_FLAG(op, FLAG_MONSTER));
730 
731  /* generate hp, if applicable */
732  if (op->stats.Con > 0 && op->stats.hp < op->stats.maxhp) {
733  /* last heal is in funny units. Dividing by speed puts
734  * the regeneration rate on a basis of time instead of
735  * #moves the monster makes. The scaling by 8 is
736  * to capture 8th's of a hp fraction regens
737  *
738  * Cast to int32_t before comparing to maxhp since otherwise an (int16_t)
739  * overflow might produce monsters with negative hp.
740  */
741 
742  op->last_heal += (int)((float)(8*op->stats.Con)/FABS(op->speed));
743  op->stats.hp = MIN((int32_t)op->stats.hp+op->last_heal/32, op->stats.maxhp); /* causes Con/4 hp/tick */
744  op->last_heal %= 32;
745 
746  /* So if the monster has gained enough HP that they are no longer afraid */
747  if (QUERY_FLAG(op, FLAG_RUN_AWAY)
748  && op->stats.hp >= (int16_t)((int32_t)op->run_away * op->stats.maxhp / 100))
750  /*
751  * This should already be covered by the MIN() check above.
752 
753  if (op->stats.hp > op->stats.maxhp)
754  op->stats.hp = op->stats.maxhp;
755  */
756  }
757 
758  /* generate sp, if applicable */
759  if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp) {
760  /* last_sp is in funny units. Dividing by speed puts
761  * the regeneration rate on a basis of time instead of
762  * #moves the monster makes. The scaling by 8 is
763  * to capture 8th's of a sp fraction regens
764  *
765  * Cast to int32_t before comparing to maxhp since otherwise an (int16_t)
766  * overflow might produce monsters with negative sp.
767  */
768 
769  op->last_sp += (int)((float)(8*op->stats.Pow)/FABS(op->speed));
770  op->stats.sp = MIN(op->stats.sp+op->last_sp/128, op->stats.maxsp); /* causes Pow/16 sp/tick */
771  op->last_sp %= 128;
772  }
773 
774  /* this should probably get modified by many more values.
775  * (eg, creatures resistance to fear, level, etc. )
776  */
777  if (QUERY_FLAG(op, FLAG_SCARED) && !(RANDOM()%20)) {
778  CLEAR_FLAG(op, FLAG_SCARED); /* Time to regain some "guts"... */
779  }
780 }
781 
790 static int monster_move_no_enemy(object *op) {
791  assert(QUERY_FLAG(op, FLAG_MONSTER));
792 
793  if (QUERY_FLAG(op, FLAG_ONLY_ATTACK)) {
794  object_remove(op);
796  return 1;
797  }
798 
799  /* Probably really a bug for a creature to have both
800  * stand still and a movement type set.
801  */
802  if (!QUERY_FLAG(op, FLAG_STAND_STILL)) {
803  if (object_value_set(op, key_shopkeeper)) {
804  shopkeeper_move(op);
805  return 0;
806  }
807 
808  if (op->attack_movement&HI4) {
809  switch (op->attack_movement&HI4) {
810  case PETMOVE:
811  pets_move(op);
812  break;
813 
814  case CIRCLE1:
815  monster_circ1_move(op);
816  break;
817 
818  case CIRCLE2:
819  monster_circ2_move(op);
820  break;
821 
822  case PACEV:
823  monster_pace_movev(op);
824  break;
825 
826  case PACEH:
827  monster_pace_moveh(op);
828  break;
829 
830  case PACEV2:
832  break;
833 
834  case PACEH2:
836  break;
837 
838  case RANDO:
839  monster_rand_move(op);
840  break;
841 
842  case RANDO2:
844  break;
845  }
846  return 0;
847  }
848 
849  if (QUERY_FLAG(op, FLAG_RANDOM_MOVE))
851  } /* stand still */
852 
853  return 0;
854 }
855 
867 int monster_move(object *op) {
868  int dir, diff;
869  object *owner, *enemy, *part;
870  rv_vector rv;
871 
872  /* Monsters not on maps don't do anything. These monsters are things
873  * Like royal guards in city dwellers inventories.
874  */
875  if (!op->map)
876  return 0;
877 
878  if (QUERY_FLAG(op, FLAG_NO_ATTACK)) { /* we never ever attack */
879  object_set_enemy(op, NULL);
880  enemy = NULL;
881  } else {
882  enemy = monster_find_enemy(op, &rv);
883  if (enemy != NULL) {
884  /* we have an enemy, just tell him we want him dead */
885  enemy->attacked_by = op; /* our ptr */
886  enemy->attacked_by_count = op->count; /* our tag */
887  }
888  }
889 
890  monster_do_living(op);
891 
892  if (QUERY_FLAG(op, FLAG_SLEEP)
893  || QUERY_FLAG(op, FLAG_BLIND)
894  || (op->map->darkness > 0 && !QUERY_FLAG(op, FLAG_SEE_IN_DARK) && !QUERY_FLAG(op, FLAG_SEE_INVISIBLE))) {
895  if (!monster_check_wakeup(op, enemy, &rv))
896  return 0;
897  }
898 
899  /* check if monster pops out of hidden spot */
900  if (op->hide)
901  do_hidden_move(op);
902 
903  if (op->pick_up)
905 
906  if (op->will_apply)
907  monster_apply_below(op); /* Check for items to apply below */
908 
909  // Can happen due to monster_apply_below().
910  if (QUERY_FLAG(op, FLAG_REMOVED)) {
911  return 1;
912  }
913 
914  /* If we don't have an enemy, do special movement or the like */
915  if (!enemy) {
916  return monster_move_no_enemy(op);
917  } /* no enemy */
918 
919  /* We have an enemy. Block immediately below is for pets */
920  if ((op->attack_movement&HI4) == PETMOVE) {
921  owner = object_get_owner(op);
922  if (owner != NULL && !on_same_map(op, owner)) {
923  pets_follow_owner(op, owner);
924  /* If the pet was unable to follow the owner, free it */
925  if (QUERY_FLAG(op, FLAG_REMOVED) && FABS(op->speed) > MIN_ACTIVE_SPEED) {
928  return 1;
929  }
930  return 0;
931  }
932  }
933 
934  /* Calculate range information for closest body part - this
935  * is used for the 'skill' code, which isn't that smart when
936  * it comes to figuring it out - otherwise, giants throw boulders
937  * into themselves.
938  */
939  if (!get_rangevector(op, enemy, &rv, 0))
940  return 0;
941  if (op->direction != rv.direction) {
942  op->direction = rv.direction;
943  op->facing = op->direction;
944  if (op->animation)
945  animate_object(op, op->direction);
946  }
947 
948  // We are looking at movement -- if monster was paralyzed, they aren't anymore
949  if (QUERY_FLAG(op, FLAG_PARALYZED)) {
951  }
952 
953  /* Move the check for scared up here - if the monster was scared,
954  * we were not doing any of the logic below, so might as well save
955  * a few cpu cycles.
956  */
957  if (!QUERY_FLAG(op, FLAG_SCARED)) {
958  dir = rv.direction;
959 
960  /* Was two if statements assigning to the same variable
961  * We can get the same effect by reversing the order and making an else-if
962  */
963  if (QUERY_FLAG(op, FLAG_CONFUSED))
964  dir = get_randomized_dir(dir);
965  else if (QUERY_FLAG(op, FLAG_RUN_AWAY))
966  dir = absdir(dir+4);
967 
968  if (QUERY_FLAG(op, FLAG_CAST_SPELL) && !(RANDOM()%3)) {
969  if (monster_cast_spell(op, rv.part, enemy, dir))
970  return 0;
971  }
972 
973  if (QUERY_FLAG(op, FLAG_READY_SCROLL) && !(RANDOM()%3)) {
974  if (monster_use_scroll(op, rv.part, enemy, dir))
975  return 0;
976  }
977 
978  if (QUERY_FLAG(op, FLAG_READY_RANGE) && !(RANDOM()%3)) {
979  if (monster_use_range(op, rv.part, enemy, dir))
980  return 0;
981  }
982  if (QUERY_FLAG(op, FLAG_READY_SKILL) && !(RANDOM()%3)) {
983  if (monster_use_skill(op, rv.part, enemy, rv.direction))
984  return 0;
985  }
986  if (QUERY_FLAG(op, FLAG_READY_BOW) && !(RANDOM()%2)) {
987  if (monster_use_bow(op, rv.part, enemy, dir))
988  return 0;
989  }
990  } /* If not scared */
991 
992 
993  /* code below is for when we didn't use a range attack or a skill, so
994  * either move or hit with hth attack. */
995 
996  part = rv.part;
997  dir = rv.direction;
998 
999  /* This first clause used to happen after the other two, but would trample dir.
1000  * Moved to before them as another check to slightly reduce calls to monster_compute_path
1001  */
1002  if (QUERY_FLAG(op, FLAG_CONFUSED))
1003  dir = get_randomized_dir(dir);
1004  else if (QUERY_FLAG(op, FLAG_SCARED) || QUERY_FLAG(op, FLAG_RUN_AWAY))
1005  dir = absdir(dir+4);
1006  else if (!monster_can_hit(part, enemy, &rv)) {
1007  dir = monster_compute_path(op, enemy, -1);
1008  if (dir == -1) {
1009  // Can't reach enemy, so remove it, attempt to move in its last direction so not stay still
1010  LOG(llevMonster, "monster %s (%d, %d on %s) can't reach enemy %s (%d, %d on %s)\n",
1011  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)");
1012  object_set_enemy(op, NULL);
1013  dir = rv.direction;
1014  }
1015  }
1016 
1017  if ((op->attack_movement&LO4) && !QUERY_FLAG(op, FLAG_SCARED)) {
1018  switch (op->attack_movement&LO4) {
1019  case DISTATT:
1020  dir = monster_dist_att(dir, enemy, part, &rv);
1021  break;
1022 
1023  case RUNATT:
1024  dir = monster_run_att(dir, op, enemy, part, &rv);
1025  break;
1026 
1027  case HITRUN:
1028  dir = monster_hitrun_att(dir, op);
1029  break;
1030 
1031  case WAITATT:
1032  dir = monster_wait_att(dir, op, enemy, part, &rv);
1033  break;
1034 
1035  case RUSH: /* default - monster normally moves towards player */
1036  case ALLRUN:
1037  break;
1038 
1039  case DISTHIT:
1040  dir = monster_disthit_att(dir, op, enemy, part, &rv);
1041  break;
1042 
1043  case WAIT2:
1044  dir = monster_wait_att2(dir, &rv);
1045  break;
1046 
1047  default:
1048  LOG(llevDebug, "Illegal low mon-move: %d\n", op->attack_movement&LO4);
1049  }
1050  }
1051 
1052  if (!dir)
1053  return 0;
1054 
1055  if (!QUERY_FLAG(op, FLAG_STAND_STILL)) {
1056  if (move_object(op, dir)) /* Can the monster move directly toward player? */
1057  return 0;
1058 
1059  if (QUERY_FLAG(op, FLAG_SCARED)
1060  || !monster_can_hit(part, enemy, &rv)
1061  || QUERY_FLAG(op, FLAG_RUN_AWAY)) {
1062  /* Try move around corners if !close */
1063  int maxdiff = (QUERY_FLAG(op, FLAG_ONLY_ATTACK) || RANDOM()&1) ? 1 : 2;
1064  for (diff = 1; diff <= maxdiff; diff++) {
1065  /* try different detours */
1066  int m = 1-(RANDOM()&2); /* Try left or right first? */
1067  if (move_object(op, absdir(dir+diff*m))
1068  || move_object(op, absdir(dir-diff*m)))
1069  return 0;
1070  }
1071  }
1072  } /* if monster is not standing still */
1073 
1074  /*
1075  * Eneq(@csd.uu.se): Patch to make RUN_AWAY or SCARED monsters move a random
1076  * direction if they can't move away.
1077  */
1078  if (!QUERY_FLAG(op, FLAG_ONLY_ATTACK)
1079  && (QUERY_FLAG(op, FLAG_RUN_AWAY) || QUERY_FLAG(op, FLAG_SCARED)))
1080  if (monster_move_randomly(op))
1081  return 0;
1082 
1083  /*
1084  * Try giving the monster a new enemy - the player that is closest
1085  * to it. In this way, it won't just keep trying to get to a target
1086  * that is inaccessible.
1087  * This could be more clever - it should go through a list of several
1088  * enemies, as it is now, you could perhaps get situations where there
1089  * are two players flanking the monster at close distance, but which
1090  * the monster can't get to, and a third one at a far distance that
1091  * the monster could get to - as it is, the monster won't look at that
1092  * third one.
1093  */
1094  if (!QUERY_FLAG(op, FLAG_FRIENDLY) && enemy == op->enemy) {
1095  object *nearest_player = get_nearest_player(op);
1096 
1097  if (nearest_player && nearest_player != enemy && !monster_can_hit(part, enemy, &rv)) {
1098  object_set_enemy(op, NULL);
1099  enemy = nearest_player;
1100  }
1101  }
1102 
1103  if (!QUERY_FLAG(op, FLAG_SCARED) && monster_can_hit(part, enemy, &rv)) {
1104  /* The adjustement to wc that was here before looked totally bogus -
1105  * since wc can in fact get negative, that would mean by adding
1106  * the current wc, the creature gets better? Instead, just
1107  * add a fixed amount - nasty creatures that are runny away should
1108  * still be pretty nasty.
1109  */
1110  if (QUERY_FLAG(op, FLAG_RUN_AWAY)) {
1111  part->stats.wc += 10;
1112  skill_attack(enemy, part, 0, NULL, NULL);
1113  part->stats.wc -= 10;
1114  } else
1115  skill_attack(enemy, part, 0, NULL, NULL);
1116  } /* if monster is in attack range */
1117 
1118  if (QUERY_FLAG(part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */
1119  return 1;
1120 
1121  if (QUERY_FLAG(op, FLAG_ONLY_ATTACK)) {
1122  object_remove(op);
1124  return 1;
1125  }
1126  return 0;
1127 }
1128 
1143 static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv) {
1144  object *more;
1145  rv_vector rv1;
1146 
1147  if (QUERY_FLAG(ob1, FLAG_CONFUSED) && !(RANDOM()%3))
1148  return 0;
1149 
1150  if (abs(rv->distance_x) < 2 && abs(rv->distance_y) < 2)
1151  return 1;
1152 
1153  /* check all the parts of ob2 - just because we can't get to
1154  * its head doesn't mean we don't want to pound its feet
1155  */
1156  for (more = ob2->more; more != NULL; more = more->more) {
1157  if (get_rangevector(ob1, more, &rv1, 0)
1158  && abs(rv1.distance_x) < 2 && abs(rv1.distance_y) < 2)
1159  return 1;
1160  }
1161  return 0;
1162 }
1163 
1186 static int monster_should_cast_spell(object *spell_ob) {
1187  /* The caller is responsible for making sure that *spell_ob is defined. */
1188  assert(spell_ob != NULL);
1189 
1190  switch (spell_ob->subtype) {
1191  case SP_BOLT:
1192  case SP_BULLET:
1193  case SP_EXPLOSION:
1194  case SP_CONE:
1195  case SP_BOMB:
1196  case SP_SMITE:
1197  case SP_MAGIC_MISSILE:
1198  case SP_SUMMON_GOLEM:
1199  case SP_MAGIC_WALL:
1200  case SP_SUMMON_MONSTER:
1201  case SP_MOVING_BALL:
1202  case SP_SWARM:
1203  case SP_INVISIBLE:
1204  case SP_AURA:
1205  return 1;
1206  }
1207 
1208  return 0;
1209 }
1210 
1212 #define MAX_KNOWN_SPELLS 20
1213 
1229 static object *monster_choose_random_spell(object *monster) {
1230  object *altern[MAX_KNOWN_SPELLS];
1231  int i = 0;
1232 
1233  FOR_INV_PREPARE(monster, tmp)
1234  if (tmp->type == SPELLBOOK || tmp->type == SPELL) {
1235  /* Check and see if it's actually a useful spell.
1236  * If its a spellbook, the spell is actually the inventory item.
1237  * if it is a spell, then it is just the object itself.
1238  */
1239  if (monster_should_cast_spell(tmp->type == SPELLBOOK ? tmp->inv : tmp)) {
1240  altern[i++] = tmp;
1241  if (i == MAX_KNOWN_SPELLS)
1242  break;
1243  }
1244  }
1245  FOR_INV_FINISH();
1246  if (!i)
1247  return NULL;
1248  return altern[RANDOM()%i];
1249 }
1250 
1267 static int monster_cast_spell(object *head, object *part, object *pl, int dir) {
1268  object *spell_item;
1269  object *owner;
1270  rv_vector rv1;
1271 
1272  /* If you want monsters to cast spells over friends, this spell should
1273  * be removed. It probably should be in most cases, since monsters still
1274  * don't care about residual effects (ie, casting a cone which may have a
1275  * clear path to the player, the side aspects of the code will still hit
1276  * other monsters)
1277  */
1278  dir = path_to_player(part, pl, 0);
1279  if (dir == 0)
1280  return 0;
1281 
1282  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1283  owner = object_get_owner(head);
1284  if (owner != NULL) {
1285  if (get_rangevector(head, owner, &rv1, 0x1)
1286  && dirdiff(dir, rv1.direction) < 2) {
1287  return 0; /* Might hit owner with spell */
1288  }
1289  }
1290  }
1291 
1292  if (QUERY_FLAG(head, FLAG_CONFUSED))
1293  dir = get_randomized_dir(dir);
1294 
1295  /* If the monster hasn't already chosen a spell, choose one
1296  * I'm not sure if it really make sense to pre-select spells (events
1297  * could be different by the time the monster goes again).
1298  */
1299  if (head->spellitem == NULL) {
1300  spell_item = monster_choose_random_spell(head);
1301  if (spell_item == NULL) {
1302  LOG(llevMonster, "Turned off spells in %s\n", head->name);
1303  CLEAR_FLAG(head, FLAG_CAST_SPELL); /* Will be turned on when picking up book */
1304  return 0;
1305  }
1306  if (spell_item->type == SPELLBOOK) {
1307  if (!spell_item->inv) {
1308  LOG(llevError, "spellbook %s does not contain a spell?\n", spell_item->name);
1309  return 0;
1310  }
1311  spell_item = spell_item->inv;
1312  }
1313  } else
1314  spell_item = head->spellitem;
1315 
1316  if (!spell_item)
1317  return 0;
1318 
1319  /* Best guess this is a defensive/healing spell */
1320  if (spell_item->range <= 1 || spell_item->stats.dam < 0)
1321  dir = 0;
1322 
1323  /* Monster doesn't have enough spell-points */
1324  /* As of 2023, monsters do not possess grace points, and so will use sp for prayers too. */
1325  if (head->stats.sp < SP_level_spellpoint_cost(head, spell_item, SPELL_MANA))
1326  return 0;
1327 
1328  if (head->stats.sp < SP_level_spellpoint_cost(head, spell_item, SPELL_GRACE))
1329  return 0;
1330 
1331  head->stats.sp -= SP_level_spellpoint_cost(head, spell_item, SPELL_MANA);
1332  head->stats.sp -= SP_level_spellpoint_cost(head, spell_item, SPELL_GRACE);
1333 
1334  /* set this to null, so next time monster will choose something different */
1335  head->spellitem = NULL;
1336 
1337  return cast_spell(part, part, dir, spell_item, NULL);
1338 }
1339 
1354 static int monster_use_scroll(object *head, object *part, object *pl, int dir) {
1355  object *scroll;
1356  object *owner;
1357  rv_vector rv1;
1358 
1359  /* If you want monsters to cast spells over friends, this spell should
1360  * be removed. It probably should be in most cases, since monsters still
1361  * don't care about residual effects (ie, casting a cone which may have a
1362  * clear path to the player, the side aspects of the code will still hit
1363  * other monsters)
1364  */
1365  dir = path_to_player(part, pl, 0);
1366  if (dir == 0)
1367  return 0;
1368 
1369  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1370  owner = object_get_owner(head);
1371  if (owner != NULL) {
1372  if (get_rangevector(head, owner, &rv1, 0x1)
1373  && dirdiff(dir, rv1.direction) < 2) {
1374  return 0; /* Might hit owner with spell */
1375  }
1376  }
1377  }
1378 
1379  if (QUERY_FLAG(head, FLAG_CONFUSED))
1380  dir = get_randomized_dir(dir);
1381 
1382  scroll = NULL;
1383  FOR_INV_PREPARE(head, tmp)
1384  if (tmp->type == SCROLL && monster_should_cast_spell(tmp->inv)) {
1385  scroll = tmp;
1386  break;
1387  }
1388  FOR_INV_FINISH();
1389 
1390  /* Used up all his scrolls, so nothing do to */
1391  if (!scroll) {
1393  return 0;
1394  }
1395 
1396  /* Spell should be cast on caster (ie, heal, strength) */
1397  if (scroll->inv->range == 0)
1398  dir = 0;
1399 
1400  /* Face the direction that we want to cast. */
1401  head->direction = dir;
1402  head->facing = head->direction;
1403  if (head->animation)
1404  animate_object(head, head->direction);
1405 
1406  apply_manual(part, scroll, 0);
1407  return 1;
1408 }
1409 
1438 static int monster_use_skill(object *head, object *part, object *pl, int dir) {
1439  object *owner;
1440  int found;
1441 
1442  dir = path_to_player(part, pl, 0);
1443  if (dir == 0)
1444  return 0;
1445 
1446  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1447  owner = object_get_owner(head);
1448  if (owner != NULL) {
1449  rv_vector rv;
1450 
1451  if (get_rangevector(head, owner, &rv, 0) && dirdiff(dir, rv.direction) < 1)
1452  return 0; /* Might hit owner with skill -thrown rocks for example ?*/
1453  }
1454  }
1455  if (QUERY_FLAG(head, FLAG_CONFUSED))
1456  dir = get_randomized_dir(dir);
1457 
1458  /* skill selection - monster will use the next unused skill.
1459  * well...the following scenario will allow the monster to
1460  * toggle between 2 skills. One day it would be nice to make
1461  * more skills available to monsters.
1462  */
1463  found = 0;
1464  FOR_INV_PREPARE(head, skill)
1465  if (skill->type == SKILL && skill != head->chosen_skill) {
1466  head->chosen_skill = skill;
1467  found = 1;
1468  break;
1469  }
1470  FOR_INV_FINISH();
1471 
1472  if (!found && !head->chosen_skill) {
1473  LOG(llevDebug, "Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", head->name, head->count);
1475  return 0;
1476  }
1477  /* use skill */
1478  return do_skill(head, part, head->chosen_skill, dir, NULL);
1479 }
1480 
1495 static int monster_use_range(object *head, object *part, object *pl, int dir) {
1496  object *owner;
1497  int at_least_one = 0;
1498 
1499  dir = path_to_player(part, pl, 0);
1500  if (dir == 0)
1501  return 0;
1502 
1503  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1504  owner = object_get_owner(head);
1505  if (owner != NULL) {
1506  rv_vector rv;
1507 
1508  if (get_rangevector(head, owner, &rv, 0) && dirdiff(dir, rv.direction) < 2)
1509  return 0; /* Might hit owner with spell */
1510  }
1511  }
1512  if (QUERY_FLAG(head, FLAG_CONFUSED))
1513  dir = get_randomized_dir(dir);
1514 
1515  FOR_INV_PREPARE(head, wand) {
1516  if (wand->type == WAND) {
1517  /* Found a wand, let's see if it has charges left */
1518  at_least_one = 1;
1519  if (wand->stats.food <= 0)
1520  continue;
1521 
1522  cast_spell(head, wand, dir, wand->inv, NULL);
1523  drain_wand_charge(wand);
1524 
1525  /* Success */
1526  return 1;
1527  }
1528 
1529  if (wand->type == ROD && wand->inv) {
1530  /* Found rod/horn, let's use it if possible */
1531  at_least_one = 1;
1532  if (wand->stats.hp < MAX(wand->inv->stats.sp, wand->inv->stats.grace))
1533  continue;
1534 
1535  /* drain charge before casting spell - can be a case where the
1536  * spell destroys the monster, and rod, so if done after, results
1537  * in crash.
1538  */
1539  drain_rod_charge(wand);
1540  cast_spell(head, wand, dir, wand->inv, NULL);
1541 
1542  /* Success */
1543  return 1;
1544  }
1545  } FOR_INV_FINISH();
1546 
1547  if (at_least_one)
1548  return 0;
1549 
1550  LOG(llevError, "Error: Monster %s (%d) HAS_READY_RANG() without wand/horn/rod.\n", head->name, head->count);
1552  return 0;
1553 }
1554 
1571 static int monster_use_bow(object *head, object *part, object *pl, int dir) {
1572  object *owner;
1573  rv_vector rv;
1574  int16_t x, y;
1575  mapstruct *map;
1576 
1577  if (!get_rangevector(part, pl, &rv, 1))
1578  return 0;
1579  if (rv.distance > 100)
1580  /* Too far */
1581  return 0;
1582  if (rv.distance_x != 0 && rv.distance_y != 0 && abs(rv.distance_x) != abs(rv.distance_y))
1583  /* Player must be on same horizontal, vertical or diagonal line. */
1584  return 0;
1585  dir = rv.direction;
1586 
1587  if (QUERY_FLAG(head, FLAG_FRIENDLY))
1588  owner = object_get_owner(head);
1589  else
1590  owner = NULL;
1591 
1592  /* The monster can possibly fire, let's see if the path is ok for an arrow. */
1593  x = part->x;
1594  y = part->y;
1595  map = part->map;
1596  while (x != pl->x || y != pl->y || map != pl->map) {
1597  x += freearr_x[dir];
1598  y += freearr_y[dir];
1599  map = get_map_from_coord(map, &x, &y);
1600  if (!map) {
1601  LOG(llevError, "monster_use_bow: no map but still path exists??\n");
1602  return 0;
1603  }
1604  if ((GET_MAP_MOVE_BLOCK(map, x, y)&MOVE_FLY_LOW) == MOVE_FLY_LOW)
1605  return 0;
1606  if (owner && owner->x == x && owner->y == y && owner->map == map)
1607  /* Don't hit owner! */
1608  return 0;
1609  }
1610 
1611  /* Finally, path is clear, can fire. */
1612 
1613  if (QUERY_FLAG(head, FLAG_CONFUSED))
1614  dir = get_randomized_dir(dir);
1615 
1616  /* in server/player.c */
1617  return fire_bow(head, NULL, dir, 0, part->x, part->y);
1618 }
1619 
1628 static int monster_get_weapon_quality(const object *item) {
1629  int val;
1630  int i;
1631 
1632  val = item->stats.dam;
1633  val += item->magic*3;
1634  /* Monsters don't really get benefits from things like regen rates
1635  * from items. But the bonus for their stats are very important.
1636  */
1637  for (i = 0; i < NUM_STATS; i++)
1638  val += get_attr_value(&item->stats, i)*2;
1639  return val;
1640 }
1641 
1654 static int monster_check_good_weapon(object *who, object *item) {
1655  object *other_weap;
1656  int val;
1657 
1658  other_weap = object_find_by_type_applied(who, item->type);
1659  if (other_weap == NULL) /* No other weapons */
1660  return 1;
1661 
1662  /* Rather than go through and apply the new one, and see if it is
1663  * better, just do some simple checks
1664  * Put some multipliers for things that hvae several effects,
1665  * eg, magic affects both damage and wc, so it has more weight
1666  */
1667 
1669  return val > 0;
1670 }
1671 
1680 static int monster_get_armour_quality(const object *item) {
1681  int val;
1682 
1683  val = item->stats.ac;
1684  val += item->resist[ATNR_PHYSICAL]/5;
1685  val += item->magic*3;
1686  return val;
1687 }
1688 
1701 static int monster_check_good_armour(object *who, object *item) {
1702  object *other_armour;
1703  int val, i;
1704 
1705  other_armour = object_find_by_type_applied(who, item->type);
1706  if (other_armour == NULL) /* No other armour, use the new */
1707  return 1;
1708 
1709  val = monster_get_armour_quality(item)-monster_get_armour_quality(other_armour);
1710 
1711  /* for the other protections, do weigh them very much in the equation -
1712  * it is the armor protection which is most important, because there is
1713  * no good way to know what the player may attack the monster with.
1714  * So if the new item has better protection than the old, give that higher
1715  * value. If the reverse, then decrease the value of this item some.
1716  */
1717  for (i = 1; i < NROFATTACKS; i++) {
1718  if (item->resist[i] > other_armour->resist[i])
1719  val++;
1720  else if (item->resist[i] < other_armour->resist[i])
1721  val--;
1722  }
1723 
1724  /* Very few armours have stats, so not much need to worry about those. */
1725 
1726  return val > 0;
1727 }
1728 
1736 static void monster_check_apply(object *mon, object *item) {
1737  int flag = 0;
1738 
1739  if (item->type == SPELLBOOK
1740  && mon->arch != NULL
1741  && (QUERY_FLAG(&mon->arch->clone, FLAG_CAST_SPELL))) {
1742  SET_FLAG(mon, FLAG_CAST_SPELL);
1743  return;
1744  }
1745 
1746  /* If for some reason, this item is already applied, no more work to do */
1747  if (QUERY_FLAG(item, FLAG_APPLIED))
1748  return;
1749 
1750  /* Might be better not to do this - if the monster can fire a bow,
1751  * it is possible in his wanderings, he will find one to use. In
1752  * which case, it would be nice to have ammo for it.
1753  */
1754  if (QUERY_FLAG(mon, FLAG_USE_BOW) && item->type == ARROW) {
1755  /* Check for the right kind of bow */
1756  object *bow;
1757 
1758  bow = object_find_by_type_and_race(mon, BOW, item->race);
1759  if (bow != NULL) {
1760  SET_FLAG(mon, FLAG_READY_BOW);
1761  LOG(llevMonster, "Found correct bow for arrows.\n");
1762  return; /* nothing more to do for arrows */
1763  }
1764  }
1765 
1766  if (item->type == TREASURE && mon->will_apply&WILL_APPLY_TREASURE)
1767  flag = 1;
1768  /* Eating food gets hp back */
1769  else if (item->type == FOOD && mon->will_apply&WILL_APPLY_FOOD)
1770  flag = 1;
1771  else if (item->type == SCROLL && QUERY_FLAG(mon, FLAG_USE_SCROLL)) {
1772  if (!item->inv)
1773  LOG(llevDebug, "Monster %d having scroll %d with empty inventory!\n", mon->count, item->count);
1774  else if (monster_should_cast_spell(item->inv))
1776  /* Don't use it right now */
1777  return;
1778  } else if (item->type == WEAPON)
1779  flag = monster_check_good_weapon(mon, item);
1780  else if (IS_ARMOR(item) || IS_SHIELD(item))
1781  flag = monster_check_good_armour(mon, item);
1782  /* Should do something more, like make sure this is a better item */
1783  else if (item->type == RING)
1784  flag = 1;
1785  else if (item->type == WAND || item->type == ROD) {
1786  /* We never really 'ready' the wand/rod/horn, because that would mean the
1787  * weapon would get undone.
1788  */
1789  if (!(apply_can_apply_object(mon, item)&CAN_APPLY_NOT_MASK)) {
1790  SET_FLAG(mon, FLAG_READY_RANGE);
1791  SET_FLAG(item, FLAG_APPLIED);
1792  }
1793  return;
1794  } else if (item->type == BOW) {
1795  /* We never really 'ready' the bow, because that would mean the
1796  * weapon would get undone.
1797  */
1798  if (!(apply_can_apply_object(mon, item)&CAN_APPLY_NOT_MASK))
1799  SET_FLAG(mon, FLAG_READY_BOW);
1800  return;
1801  } else if (item->type == SKILL) {
1802  /*
1803  * skills are specials: monsters must have the 'FLAG_READY_SKILL' flag set,
1804  * else they can't use the skill...
1805  * Skills also don't need to get applied, so return now.
1806  */
1807  SET_FLAG(mon, FLAG_READY_SKILL);
1808  return;
1809  }
1810 
1811  /* if we don't match one of the above types, return now.
1812  * apply_can_apply_object() will say that we can apply things like flesh,
1813  * bolts, and whatever else, because it only checks against the
1814  * body_info locations.
1815  */
1816  if (!flag)
1817  return;
1818 
1819  /* Check to see if the monster can use this item. If not, no need
1820  * to do further processing. Note that apply_can_apply_object() already checks
1821  * for the CAN_USE flags.
1822  */
1824  return;
1825 
1826  /* should only be applying this item, not unapplying it.
1827  * also, ignore status of curse so they can take off old armour.
1828  * monsters have some advantages after all.
1829  */
1831  return;
1832 }
1833 
1853 static void monster_check_pickup(object *monster) {
1854  object *part;
1855 
1856  for (part = monster; part != NULL; part = part->more)
1857  FOR_BELOW_PREPARE(part, tmp) {
1858  /* Don't try to pick items that are in the process of being thrown.
1859  * It is fairly likely that an ally threw it past monster to hit player.
1860  * IDEA: Maybe have a dex save to catch player-thrown projectiles?
1861  *
1862  * Neila Hawkins 2020-09-07
1863  */
1864  if (tmp->type != THROWN_OBJ && monster_can_pick(monster, tmp)) {
1865  uint32_t nrof;
1866 
1867  if (tmp->weight > 0) {
1868  int32_t weight_limit;
1869 
1870  weight_limit = get_weight_limit(monster->stats.Str);
1871  if (weight_limit >= monster->weight-monster->carrying)
1872  nrof = (weight_limit-monster->weight-monster->carrying)/tmp->weight;
1873  else
1874  nrof = 0;
1875  } else
1876  nrof = MAX(1, tmp->nrof);
1877  if (nrof >= 1) {
1878  object *tmp2;
1879 
1880  tmp2 = object_split(tmp, MIN(nrof, MAX(1, tmp->nrof)), NULL, 0);
1881  tmp2 = object_insert_in_ob(tmp2, monster);
1882  (void)monster_check_apply(monster, tmp2);
1883  }
1884  }
1885  } FOR_BELOW_FINISH();
1886 }
1887 
1897 static int monster_can_pick(object *monster, object *item) {
1898  int flag = 0;
1899  int i;
1900 
1901  if (!object_can_pick(monster, item))
1902  return 0;
1903 
1904  if (QUERY_FLAG(item, FLAG_UNPAID))
1905  return 0;
1906 
1907  if (monster->pick_up&64) /* All */
1908  flag = 1;
1909 
1910  else {
1911  if (IS_WEAPON(item))
1912  flag = (monster->pick_up&8) || QUERY_FLAG(monster, FLAG_USE_WEAPON);
1913  else if (IS_ARMOR(item))
1914  flag = (monster->pick_up&16) || QUERY_FLAG(monster, FLAG_USE_ARMOUR);
1915  else if (IS_SHIELD(item))
1916  flag = (monster->pick_up&16) || QUERY_FLAG(monster, FLAG_USE_SHIELD);
1917  else switch (item->type) {
1918  case MONEY:
1919  case GEM:
1920  flag = monster->pick_up&2;
1921  break;
1922 
1923  case FOOD:
1924  flag = monster->pick_up&4;
1925  break;
1926 
1927  case SKILL:
1928  flag = QUERY_FLAG(monster, FLAG_CAN_USE_SKILL);
1929  break;
1930 
1931  case RING:
1932  flag = QUERY_FLAG(monster, FLAG_USE_RING);
1933  break;
1934 
1935  case WAND:
1936  case ROD:
1937  flag = QUERY_FLAG(monster, FLAG_USE_RANGE);
1938  break;
1939 
1940  case SPELLBOOK:
1941  flag = (monster->arch != NULL && QUERY_FLAG(&monster->arch->clone, FLAG_CAST_SPELL));
1942  break;
1943 
1944  case SCROLL:
1945  flag = QUERY_FLAG(monster, FLAG_USE_SCROLL);
1946  break;
1947 
1948  case BOW:
1949  case ARROW:
1950  flag = QUERY_FLAG(monster, FLAG_USE_BOW);
1951  break;
1952  }
1953  if (!flag && QUERY_FLAG(item, FLAG_IS_THROWN) && object_find_by_type_subtype(monster, SKILL, SK_THROWING) != NULL)
1954  flag = (monster->pick_up&8) || QUERY_FLAG(monster, FLAG_USE_WEAPON);
1955  /* Simplistic check - if the monster has a location to equip it, he will
1956  * pick it up. Note that this doesn't handle cases where an item may
1957  * use several locations.
1958  */
1959  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
1960  if (monster->body_info[i] && item->body_info[i]) {
1961  flag = 1;
1962  break;
1963  }
1964  }
1965  }
1966 
1967  if (((!(monster->pick_up&32)) && flag) || ((monster->pick_up&32) && (!flag)))
1968  return 1;
1969  return 0;
1970 }
1971 
1978 static void monster_apply_below(object *monster) {
1979  FOR_BELOW_PREPARE(monster, tmp) {
1980  switch (tmp->type) {
1981  case CF_HANDLE:
1982  case TRIGGER:
1983  if (monster->will_apply&WILL_APPLY_HANDLE)
1984  apply_manual(monster, tmp, 0);
1985  break;
1986 
1987  case TREASURE:
1988  if (monster->will_apply&WILL_APPLY_TREASURE)
1989  apply_manual(monster, tmp, 0);
1990  break;
1991  }
1992  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
1993  break;
1994  } FOR_BELOW_FINISH();
1995 }
1996 
2001 void monster_check_apply_all(object *monster) {
2002  if (!monster->head) {
2003  fix_object(monster); // Needed to correctly fill various body fields.
2004  }
2005  FOR_INV_PREPARE(monster, inv)
2006  monster_check_apply(monster, inv);
2007  FOR_INV_FINISH();
2008 }
2009 
2014 void monster_npc_call_help(object *op) {
2015  const char *value;
2016  int help_radius = 3;
2017 
2018  value = object_get_value(op, "help_radius");
2019  if ( value ) {
2020  int override_help_radius;
2021 
2022  override_help_radius = strtol(value, NULL, 10);
2023  if (override_help_radius >= 0 && override_help_radius < 30)
2024  help_radius = override_help_radius;
2025  else
2026  LOG(llevDebug, "monster_npc_call_help: invalid help_radius %d\n", override_help_radius);
2027  }
2028 
2029  for (int x = -help_radius; x <= help_radius; x++)
2030  for (int y = -help_radius; y <= help_radius; y++) {
2031  mapstruct *m = op->map;
2032  int16_t sx = op->x+x;
2033  int16_t sy = op->y+y;
2034  int mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
2035  /* If nothing alive on this space, no need to search the space. */
2036  if ((mflags&P_OUT_OF_MAP) || !(mflags&P_IS_ALIVE))
2037  continue;
2038 
2039  FOR_MAP_PREPARE(m, sx, sy, npc)
2040  if (QUERY_FLAG(npc, FLAG_ALIVE) && QUERY_FLAG(npc, FLAG_UNAGGRESSIVE)) {
2041  object_set_enemy(npc, op->enemy);
2043  }
2044  FOR_MAP_FINISH();
2045  }
2046 }
2047 
2056 static int monster_dist_att(int dir, object *enemy, object *part, rv_vector *rv) {
2057  if (monster_can_hit(part, enemy, rv))
2058  return dir;
2059  if (rv->distance < 10)
2060  return absdir(dir+4);
2061  else if (rv->distance > 18)
2062  return dir;
2063  return 0;
2064 }
2065 
2075 static int monster_run_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
2076  if ((monster_can_hit(part, enemy, rv) && ob->move_status < 20) || ob->move_status < 20) {
2077  ob->move_status++;
2078  return (dir);
2079  } else if (ob->move_status > 20)
2080  ob->move_status = 0;
2081  return absdir(dir+4);
2082 }
2083 
2090 static int monster_hitrun_att(int dir, object *ob) {
2091  if (ob->move_status++ < 25)
2092  return dir;
2093  else if (ob->move_status < 50)
2094  return absdir(dir+4);
2095  ob->move_status = 0;
2096  return absdir(dir+4);
2097 }
2098 
2108 static int monster_wait_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
2109  int inrange = monster_can_hit(part, enemy, rv);
2110 
2111  if (ob->move_status || inrange)
2112  ob->move_status++;
2113 
2114  if (ob->move_status == 0)
2115  return 0;
2116  else if (ob->move_status < 10)
2117  return dir;
2118  else if (ob->move_status < 15)
2119  return absdir(dir+4);
2120  ob->move_status = 0;
2121  return 0;
2122 }
2123 
2133 static int monster_disthit_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
2134  /* The logic below here looked plain wrong before. Basically, what should
2135  * happen is that if the creatures hp percentage falls below run_away,
2136  * the creature should run away (dir+4)
2137  * I think its wrong for a creature to have a zero maxhp value, but
2138  * at least one map has this set, and whatever the map contains, the
2139  * server should try to be resilant enough to avoid the problem
2140  */
2141  if (ob->stats.maxhp && (ob->stats.hp*100)/ob->stats.maxhp < ob->run_away)
2142  return absdir(dir+4);
2143  return monster_dist_att(dir, enemy, part, rv);
2144 }
2145 
2152 static int monster_wait_att2(int dir, rv_vector *rv) {
2153  if (rv->distance < 9)
2154  return absdir(dir+4);
2155  return 0;
2156 }
2157 
2162 static void monster_circ1_move(object *ob) {
2163  static const int circle [12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 };
2164 
2165  if (++ob->move_status > 11)
2166  ob->move_status = 0;
2167  if (!(move_object(ob, circle[ob->move_status])))
2168  (void)move_object(ob, RANDOM()%8+1);
2169 }
2170 
2175 static void monster_circ2_move(object *ob) {
2176  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 };
2177 
2178  if (++ob->move_status > 19)
2179  ob->move_status = 0;
2180  if (!(move_object(ob, circle[ob->move_status])))
2181  (void)move_object(ob, RANDOM()%8+1);
2182 }
2183 
2188 static void monster_pace_movev(object *ob) {
2189  if (ob->move_status++ > 6)
2190  ob->move_status = 0;
2191  if (ob->move_status < 4)
2192  (void)move_object(ob, 5);
2193  else
2194  (void)move_object(ob, 1);
2195 }
2196 
2201 static void monster_pace_moveh(object *ob) {
2202  if (ob->move_status++ > 6)
2203  ob->move_status = 0;
2204  if (ob->move_status < 4)
2205  (void)move_object(ob, 3);
2206  else
2207  (void)move_object(ob, 7);
2208 }
2209 
2214 static void monster_pace2_movev(object *ob) {
2215  if (ob->move_status++ > 16)
2216  ob->move_status = 0;
2217  if (ob->move_status < 6)
2218  (void)move_object(ob, 5);
2219  else if (ob->move_status < 8)
2220  return;
2221  else if (ob->move_status < 13)
2222  (void)move_object(ob, 1);
2223 }
2224 
2229 static void monster_pace2_moveh(object *ob) {
2230  if (ob->move_status++ > 16)
2231  ob->move_status = 0;
2232  if (ob->move_status < 6)
2233  (void)move_object(ob, 3);
2234  else if (ob->move_status < 8)
2235  return;
2236  else if (ob->move_status < 13)
2237  (void)move_object(ob, 7);
2238 }
2239 
2244 static void monster_rand_move(object *ob) {
2245  int i;
2246 
2247  // change direction when stuck, or 1/8 of the time
2248  if (ob->move_status < 1
2249  || ob->move_status > 8
2250  || !move_object(ob, ob->move_status) || (RANDOM()%9 == 0))
2251  // change direction
2252  for (i = 0; i < 5; i++) {
2253  ob->move_status = RANDOM()%8+1;
2254  if (move_object(ob, ob->move_status))
2255  return;
2256  }
2257 }
2258 
2264 static void shopkeeper_move(object *ob) {
2265  const bool debug = object_value_set(ob, key_shopkeeper_debug);
2266  char buf[MAX_BUF], buf2[MAX_BUF];
2267  const bool on_shop_tile = coords_in_shop(ob->map, ob->x, ob->y);
2268  // count number of visible, pickable items above floor
2269  int nbelow = 0;
2270  int cum_client_type = 0; // for calculating average client_type
2271  FOR_BELOW_PREPARE(ob, tmp) {
2272  if (!LOOK_OBJ(tmp) || QUERY_FLAG(tmp, FLAG_NO_PICK))
2273  continue;
2274  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
2275  break;
2276  if (QUERY_FLAG(tmp, FLAG_UNPAID) && !QUERY_FLAG(tmp, FLAG_UNIQUE) && !object_value_set(tmp, "price")) {
2277  // Belongs to shop, but we're no longer interested. Liquidate
2278  uint64_t price = price_base(tmp);
2279  if (ob->map->shopmin && price < ob->map->shopmin) {
2280  if (debug) {
2281  query_short_name(tmp, buf, sizeof(buf));
2282  snprintf(buf2, sizeof(buf2), "Liquidating %s (price %lu < shopmin %lu)", buf, price, ob->map->shopmin);
2283  monster_npc_say(ob, buf2);
2284  }
2285  object_remove(tmp);
2286  object_free(tmp, 0);
2287  continue;
2288  }
2289  }
2290  cum_client_type += tmp->client_type;
2291  nbelow++;
2292  } FOR_BELOW_FINISH();
2293 
2294  // Update running average
2295  float newavg = 0;
2296  if (on_shop_tile) {
2297  const char *curr = object_get_value(ob, key_shopkeeper_pilesize);
2298  float last = 1; // initial average pile size guess, if not set
2299  if (curr != NULL) {
2300  sscanf(curr, "%f", &last);
2301  }
2302  const float alpha = 1.0/50; // 1/(number of tiles to average over)
2303  newavg = alpha*nbelow + (1-alpha)*last;
2304  snprintf(buf, sizeof(buf), "%f", newavg);
2306  }
2307 
2308  if (debug) {
2309  snprintf(buf2, sizeof(buf2), "%d items below, shop avg %.1f", nbelow, newavg);
2310  monster_npc_say(ob, buf2);
2311  }
2312 
2313  // Keep shop tiles average or below and clear walkways
2314  const int want_pile = on_shop_tile ? MAX(1, newavg) : 0;
2315  if (nbelow > want_pile) {
2316  // pick up until the pile is smaller
2317  int npicked = 0;
2318  FOR_BELOW_PREPARE(ob, tmp) {
2319  if (!LOOK_OBJ(tmp) || QUERY_FLAG(tmp, FLAG_NO_PICK))
2320  continue;
2321  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
2322  break;
2323  if (pick_up(ob, tmp)) {
2324  npicked++;
2325  if (nbelow - npicked <= want_pile)
2326  break;
2327  }
2328  } FOR_BELOW_FINISH();
2329 
2330  if (debug) {
2331  snprintf(buf2, sizeof(buf2), "picked up %d items", npicked);
2332  monster_npc_say(ob, buf2);
2333  }
2334  } else if (on_shop_tile) {
2335  // Drop stuff on shop tiles
2336  int ndropped = 0;
2337  FOR_INV_PREPARE(ob, tmp) {
2338  // Skip our own spells, skills, etc.
2339  if (!LOOK_OBJ(tmp))
2340  continue;
2341 
2342  // Try to drop similar items based on client_type
2343  int dtype = 0;
2344  if (nbelow > 0)
2345  dtype = abs(tmp->client_type - cum_client_type/nbelow);
2346  dtype = MAX(1, dtype); // no divide by zero
2347  if (chance(50, dtype)) {
2348  drop(ob, tmp);
2349  ndropped++;
2350  if (nbelow + ndropped >= want_pile)
2351  break;
2352  }
2353  } FOR_INV_FINISH();
2354 
2355  if (debug) {
2356  snprintf(buf2, sizeof(buf2), "dropped %d items", ndropped);
2357  monster_npc_say(ob, buf2);
2358  }
2359  }
2360 
2361  monster_rand_move(ob);
2362 }
2363 
2371 void monster_check_earthwalls(object *op, mapstruct *m, int x, int y) {
2372  FOR_MAP_PREPARE(m, x, y, tmp)
2373  if (tmp->type == EARTHWALL) {
2374  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
2375  return;
2376  }
2377  FOR_MAP_FINISH();
2378 }
2379 
2387 void monster_check_doors(object *op, mapstruct *m, int x, int y) {
2388  FOR_MAP_PREPARE(m, x, y, tmp)
2389  if (tmp->type == DOOR) {
2390  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
2391  return;
2392  }
2393  FOR_MAP_FINISH();
2394 }
2395 
2401 void monster_do_say(const mapstruct *map, const char *message) {
2403  message);
2404 }
2405 
2412 static StringBuffer *monster_format_say(const object* npc, const char *message) {
2413  char name[MAX_BUF];
2414  StringBuffer *buf;
2415 
2416  query_name(npc, name, sizeof(name));
2417  buf = stringbuffer_new();
2418  stringbuffer_append_printf(buf, "%s says: %s", name, message);
2419  return buf;
2420 }
2421 
2428  switch (rt) {
2429  case rt_say:
2430  return "say";
2431  case rt_reply:
2432  return "reply";
2433  case rt_question:
2434  return "ask";
2435  }
2436  assert(0);
2437  return NULL;
2438 }
2439 
2445 static const char *get_reply_text_other(reply_type rt) {
2446  switch (rt) {
2447  case rt_say:
2448  return "says";
2449  case rt_reply:
2450  return "replies";
2451  case rt_question:
2452  return "asks";
2453  }
2454  assert(0);
2455  return NULL;
2456 }
2457 
2483 void monster_communicate(object *op, const char *txt) {
2484  int i, mflags;
2485  int16_t x, y;
2486  mapstruct *mp, *orig_map = op->map;
2487  char own[MAX_BUF], others[MAX_BUF];
2488  talk_info info;
2489 
2490  info.text = txt;
2491  info.message = NULL;
2492  info.replies_count = 0;
2493  info.who = op;
2494  info.npc_msg_count = 0;
2495 
2496  /* Note that this loop looks pretty inefficient to me - we look and try to talk
2497  * to every object within 2 spaces. It would seem that if we trim this down to
2498  * only try to talk to objects with npc->msg set, things would be a lot more efficient,
2499  * but I'm not sure if there are any objects out there that don't have a message and instead
2500  * rely sorely on events - MSW 2009-04-14
2501  */
2502  for (i = 0; i <= SIZEOFFREE2; i++) {
2503  mp = op->map;
2504  x = op->x+freearr_x[i];
2505  y = op->y+freearr_y[i];
2506 
2507  mflags = get_map_flags(mp, &mp, x, y, &x, &y);
2508  if (mflags&P_OUT_OF_MAP)
2509  continue;
2510 
2511  FOR_MAP_PREPARE(mp, x, y, npc) {
2512  monster_talk_to_npc(npc, &info);
2513  if (orig_map != op->map) {
2514  LOG(llevDebug, "Warning: Forced to swap out very recent map\n");
2515  return;
2516  }
2517  } FOR_MAP_FINISH();
2518  }
2519 
2520  /* First, what the player says. */
2521  if (info.message != NULL) {
2522  snprintf(own, sizeof(own), "You %s: %s", get_reply_text_own(info.message_type), info.message);
2523  snprintf(others, sizeof(others), "%s %s: %s", op->name, get_reply_text_other(info.message_type), info.message);
2524  free_string(info.message);
2525  } else {
2526  snprintf(own, sizeof(own), "You say: %s", txt);
2527  snprintf(others, sizeof(others), "%s says: %s", op->name, txt);
2528  }
2531 
2532  /* Then NPCs can actually talk. */
2533  for (i = 0; i < info.npc_msg_count; i++) {
2534  monster_do_say(orig_map, info.npc_msgs[i]);
2535  free_string(info.npc_msgs[i]);
2536  }
2537 
2538  /* Finally, the replies the player can use. */
2539  if (info.replies_count > 0) {
2541  for (i = 0; i < info.replies_count; i++) {
2543  free_string(info.replies_words[i]);
2544  free_string(info.replies[i]);
2545  }
2546  }
2547 }
2548 
2557 static int monster_do_talk_npc(object *npc, talk_info *info) {
2558  struct_dialog_reply *reply;
2559  struct_dialog_message *message;
2560 
2561  if (!get_dialog_message(npc, info->text, &message, &reply))
2562  return 0;
2563 
2564  if (reply) {
2565  info->message = add_string(reply->message);
2566  info->message_type = reply->type;
2567  }
2568 
2569  if (message->identifies) {
2570  identify(npc);
2571  }
2572 
2573  if (npc->type == MAGIC_EAR) {
2575  use_trigger(npc);
2576  } else {
2577  char value[2];
2578 
2579  if (info->npc_msg_count < MAX_NPC) {
2581  info->npc_msg_count++;
2582  }
2583 
2584  /* mark that the npc was talked to, so it won't move randomly later on */
2585  value[0] = '3' + rand() % 6;
2586  value[1] = '\0';
2587  object_set_value(npc, "talked_to", value, 1);
2588 
2589  reply = message->replies;
2590  while (reply && info->replies_count < MAX_REPLIES) {
2591  info->replies[info->replies_count] = add_string(reply->message);
2592  info->replies_words[info->replies_count] = add_string(reply->reply);
2593  info->replies_count++;
2594  reply = reply->next;
2595  }
2596  }
2597 
2598  return 1;
2599 }
2600 
2606 void monster_npc_say(object *npc, const char *cp) {
2607  char *message;
2608  StringBuffer *buf = monster_format_say(npc, cp);
2609 
2610  message = stringbuffer_finish(buf);
2611  monster_do_say(npc->map, message);
2612  free(message);
2613 }
2614 
2623 static int monster_talk_to_npc(object *npc, talk_info *info) {
2624  dialog_preparse(npc);
2625  if (events_execute_object_say(npc, info) != 0)
2626  return 0;
2627 
2628  /* Here we let the objects inside inventories hear and answer, too. */
2629  /* This allows the existence of "intelligent" weapons you can discuss with */
2630  FOR_INV_PREPARE(npc, cobj)
2631  if (events_execute_object_say(cobj, info) != 0)
2632  return 0;
2633  FOR_INV_FINISH();
2634  if (info->who == npc)
2635  return 0;
2636  return monster_do_talk_npc(npc, info);
2637 }
2638 
2651 object *monster_find_throw_ob(object *op) {
2652  /* New throw code: look through the inventory. Grap the first legal is_thrown
2653  * marked item and throw it to the enemy.
2654  */
2655 
2656  FOR_INV_PREPARE(op, tmp) {
2657  /* Can't throw invisible objects or items that are applied */
2658  if (!tmp->invisible && !QUERY_FLAG(tmp, FLAG_APPLIED) && QUERY_FLAG(tmp, FLAG_IS_THROWN)) {
2659 #ifdef DEBUG_THROW
2660  char what[MAX_BUF];
2661 
2662  query_name(tmp, what, MAX_BUF);
2663  LOG(llevDebug, "%s chooses to throw: %s (%d)\n", op->name, what, tmp->count);
2664 #endif
2665  return tmp;
2666  }
2667  } FOR_INV_FINISH();
2668 
2669 #ifdef DEBUG_THROW
2670  LOG(llevDebug, "%s chooses to throw nothing\n", op->name);
2671 #endif
2672  return NULL;
2673 }
2674 
2690 int monster_can_detect_enemy(object *op, object *enemy, rv_vector *rv) {
2691  int radius = MIN_MON_RADIUS, hide_discovery;
2692 
2693  /* null detection for any of these condtions always */
2694  if (!op || !enemy || !op->map || !enemy->map)
2695  return 0;
2696 
2697  /* If the monster (op) has no way to get to the enemy, do nothing */
2698  if (!get_rangevector(op, enemy, rv, 0))
2699  return 0;
2700 
2701  /* Monsters always ignore the DM */
2702  if (op->type != PLAYER && QUERY_FLAG(enemy, FLAG_WIZ))
2703  return 0;
2704 
2705  /* simple check. Should probably put some range checks in here. */
2706  if (monster_can_see_enemy(op, enemy))
2707  return 1;
2708 
2709  /* The rest of this is for monsters. Players are on their own for
2710  * finding enemies!
2711  */
2712  if (op->type == PLAYER)
2713  return 0;
2714 
2715  /* Quality invisible? Bah, we wont see them w/o SEE_INVISIBLE
2716  * flag (which was already checked) in can_see_enmy (). Lets get out of here
2717  */
2718  if (enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden)))
2719  return 0;
2720 
2721  /* use this for invis also */
2722  hide_discovery = op->stats.Int/5;
2723 
2724  /* Determine Detection radii */
2725  if (!enemy->hide) /* to detect non-hidden (eg dark/invis enemy) */
2726  radius = MAX(op->stats.Wis/5+1, MIN_MON_RADIUS);
2727  else { /* a level/INT/Dex adjustment for hiding */
2728  object *sk_hide;
2729  int bonus = (op->level/2)+(op->stats.Int/5);
2730 
2731  if (enemy->type == PLAYER) {
2732  sk_hide = find_skill_by_number(enemy, SK_HIDING);
2733  if (sk_hide != NULL)
2734  bonus -= sk_hide->level;
2735  else {
2736  LOG(llevError, "monster_can_detect_enemy() got hidden player w/o hiding skill!\n");
2737  make_visible(enemy);
2738  radius = MAX(radius, MIN_MON_RADIUS);
2739  }
2740  } else /* enemy is not a player */
2741  bonus -= enemy->level;
2742 
2743  radius += bonus/5;
2744  hide_discovery += bonus*5;
2745  } /* else creature has modifiers for hiding */
2746 
2747  /* Radii stealth adjustment. Only if you are stealthy
2748  * will you be able to sneak up closer to creatures */
2749  if (QUERY_FLAG(enemy, FLAG_STEALTH))
2750  radius = radius/2, hide_discovery = hide_discovery/3;
2751 
2752  /* Radii adjustment for enemy standing in the dark */
2753  if (op->map->darkness > 0 && !monster_stand_in_light(enemy)) {
2754  /* on dark maps body heat can help indicate location with infravision
2755  * undead don't have body heat, so no benefit detecting them.
2756  */
2757  if (QUERY_FLAG(op, FLAG_SEE_IN_DARK) && !is_true_undead(enemy))
2758  radius += op->map->darkness/2;
2759  else
2760  radius -= op->map->darkness/2;
2761 
2762  /* op next to a monster (and not in complete darkness)
2763  * the monster should have a chance to see you.
2764  */
2765  if (radius < MIN_MON_RADIUS && op->map->darkness < 5 && rv->distance <= 1)
2766  radius = MIN_MON_RADIUS;
2767  } /* if on dark map */
2768 
2769  /* Lets not worry about monsters that have incredible detection
2770  * radii, we only need to worry here about things the player can
2771  * (potentially) see. This is 13, as that is the maximum size the player
2772  * may have for their map - in that way, creatures at the edge will
2773  * do something. Note that the distance field in the
2774  * vector is real distance, so in theory this should be 18 to
2775  * find that.
2776  */
2777  if (radius > 13)
2778  radius = 13;
2779 
2780  /* Enemy in range! Now test for detection */
2781  if ((int)rv->distance <= radius) {
2782  /* ah, we are within range, detected? take cases */
2783  if (!enemy->invisible) /* enemy in dark squares... are seen! */
2784  return 1;
2785 
2786  /* hidden or low-quality invisible */
2787  if (enemy->hide && rv->distance <= 1 && RANDOM()%100 <= (unsigned int)hide_discovery) {
2788  make_visible(enemy);
2789  /* inform players of new status */
2790  if (enemy->type == PLAYER && player_can_view(enemy, op))
2792  "You are discovered by %s!",
2793  op->name);
2794  return 1; /* detected enemy */
2795  } else if (enemy->invisible) {
2796  /* Change this around - instead of negating the invisible, just
2797  * return true so that the mosnter that managed to detect you can
2798  * do something to you. Decreasing the duration of invisible
2799  * doesn't make a lot of sense IMO, as a bunch of stupid creatures
2800  * can then basically negate the spell. The spell isn't negated -
2801  * they just know where you are!
2802  */
2803  if (RANDOM()%50 <= (unsigned int)hide_discovery) {
2804  if (enemy->type == PLAYER) {
2805  char name[MAX_BUF];
2806 
2807  query_name(op, name, MAX_BUF);
2809  "You see %s noticing your position.",
2810  name);
2811  }
2812  return 1;
2813  }
2814  }
2815  } /* within range */
2816 
2817  /* Wasn't detected above, so still hidden */
2818  return 0;
2819 }
2820 
2830 static int monster_stand_in_light_internal(object *op) {
2831  if (!op)
2832  return 0;
2833  if (op->glow_radius > 0)
2834  return 1;
2835 
2836  if (op->map) {
2837  return map_light_on(op->map, op->x, op->y);
2838  }
2839  return 0;
2840 }
2841 
2845 int monster_stand_in_light(object *op) {
2846  if (!op)
2847  return 0;
2848 
2849  if (op->light_cached_time == pticks)
2850  return op->light_cached;
2851 
2852  int val = monster_stand_in_light_internal(op);
2853  op->light_cached = val;
2854  op->light_cached_time = pticks;
2855  return val;
2856 }
2857 
2867 int monster_can_see_enemy(object *op, object *enemy) {
2868  object *looker = HEAD(op);
2869 
2870  /* safety */
2871  if (!looker || !enemy || !QUERY_FLAG(looker, FLAG_ALIVE))
2872  return 0;
2873 
2874  /* we dont give a full treatment of xrays here (shorter range than normal,
2875  * see through walls). Should we change the code elsewhere to make you
2876  * blind even if you can xray?
2877  */
2878  if (QUERY_FLAG(looker, FLAG_BLIND) && !QUERY_FLAG(looker, FLAG_XRAYS))
2879  return 0;
2880 
2881  /* checking for invisible things */
2882  if (enemy->invisible) {
2883  /* HIDDEN ENEMY. by definition, you can't see hidden stuff!
2884  * However, if you carry any source of light, then the hidden
2885  * creature is seeable (and stupid) */
2886  if (has_carried_lights(enemy)) {
2887  if (enemy->hide) {
2888  make_visible(enemy);
2890  "Your light reveals your hiding spot!");
2891  }
2892  return 1;
2893  } else if (enemy->hide)
2894  return 0;
2895 
2896  /* Invisible enemy. Break apart the check for invis undead/invis looker
2897  * into more simple checks - the QUERY_FLAG doesn't return 1/0 values,
2898  * and making it a conditional makes the code pretty ugly.
2899  */
2900  if (!QUERY_FLAG(looker, FLAG_SEE_INVISIBLE)) {
2901  if (makes_invisible_to(enemy, looker))
2902  return 0;
2903  }
2904  } else if (looker->type == PLAYER) /* for players, a (possible) shortcut */
2905  if (player_can_view(looker, enemy))
2906  return 1;
2907 
2908  /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen
2909  * unless they carry a light or stand in light. Darkness doesnt
2910  * inhibit the undead per se (but we should give their archs
2911  * CAN_SEE_IN_DARK, this is just a safety
2912  * we care about the enemy maps status, not the looker.
2913  * only relevant for tiled maps, but it is possible that the
2914  * enemy is on a bright map and the looker on a dark - in that
2915  * case, the looker can still see the enemy
2916  */
2917  if (enemy->map->darkness > 0
2918  && !monster_stand_in_light(enemy)
2919  && (!QUERY_FLAG(looker, FLAG_SEE_IN_DARK) || !is_true_undead(looker) || !QUERY_FLAG(looker, FLAG_XRAYS)))
2920  return 0;
2921 
2922  return 1;
2923 }
Error, serious thing.
Definition: logger.h:11
int on_same_map(const object *op1, const object *op2)
Checks whether 2 objects are on the same map or not.
Definition: map.cpp:2628
static int monster_hitrun_att(int dir, object *ob)
Return the next direction the monster should move for a specific movement type.
Definition: monster.cpp:2090
#define NDI_DELAYED
If set, then message is sent only after the player&#39;s tick completes.
Definition: newclient.h:280
#define NUM_BODY_LOCATIONS
Number of body locations.
Definition: object.h:15
#define FLAG_SEE_IN_DARK
if set ob not effected by darkness
Definition: define.h:325
int apply_manual(object *op, object *tmp, int aflag)
Main apply handler.
Definition: apply.cpp:259
uint16_t attack_movement
What kind of attack movement.
Definition: object.h:401
int npc_msg_count
How many NPCs reacted to the text being said.
Definition: dialog.h:58
#define FLAG_UNPAID
Object hasn&#39;t been paid for yet.
Definition: define.h:223
#define MOVE_WALK
Object walks.
Definition: define.h:398
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
#define SP_BOLT
Definition: spells.h:78
static void monster_circ1_move(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2162
Spell-related defines: spellpath, subtypes, ...
See Ring.
Definition: object.h:190
#define RANDO
The monster will go in a random direction until it is stopped by an obstacle, then it chooses another...
Definition: define.h:535
This is used by get_rangevector to determine where the other creature is.
Definition: map.h:375
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
#define FLAG_SLEEP
NPC is sleeping.
Definition: define.h:295
uint32_t hidden
If True, player (DM) is hidden from view.
Definition: player.h:149
#define FOR_OB_AND_ABOVE_PREPARE(op_)
Constructs a loop iterating over an object and all objects above it in the same pile.
Definition: define.h:762
object * object_get_owner(object *op)
Returns the object which this object marks as being the owner.
Definition: object.cpp:789
#define FLAG_USE_SCROLL
(Monster) can read scroll
Definition: define.h:279
object * get_nearest_criminal(object *mon)
Definition: player.cpp:591
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
object_split(ob,nr) splits up ob into two parts.
Definition: object.cpp:2622
void animate_object(object *op, int dir)
Updates the face-variable of an object.
Definition: anim.cpp:44
static int monster_wait_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv)
Return the next direction the monster should move for a specific movement type.
Definition: monster.cpp:2108
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
#define SP_CONE
Definition: spells.h:81
static int monster_should_cast_spell(object *spell_ob)
Checks if a monster should cast a spell.
Definition: monster.cpp:1186
int makes_invisible_to(object *pl, object *mon)
This checks to see if &#39;pl&#39; is invisible to &#39;mon&#39;.
int8_t direction
Means the object is moving that way.
Definition: object.h:344
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
See Scroll.
Definition: object.h:226
object * part
Part we found.
Definition: map.h:380
void pets_follow_owner(object *ob, object *owner)
A pet is trying to follow its owner.
Definition: pets.cpp:297
#define NDI_WHITE
Definition: newclient.h:247
void use_trigger(object *op)
Toggles the state of specified button.
Definition: button.cpp:254
#define FLAG_USE_ARMOUR
(Monster) can wear armour/shield/helmet
Definition: define.h:283
#define FLAG_STAND_STILL
NPC will not (ever) move.
Definition: define.h:296
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
void drain_wand_charge(object *wand)
Drains a charge from a wand.
Definition: spell_util.cpp:786
See Food.
Definition: object.h:117
#define MSG_TYPE_DIALOG_MAGIC_EAR
Magic ear.
Definition: newclient.h:508
float move_slow_penalty
How much this slows down the object.
Definition: object.h:442
See Projectile.
Definition: object.h:122
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:233
static void monster_rand_move(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2244
#define FLAG_IS_FLOOR
Can&#39;t see what&#39;s underneath this object.
Definition: define.h:290
uint32_t peaceful
If set, won&#39;t attack friendly creatures.
Definition: player.h:148
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.cpp:1132
#define PACEV2
The monster will pace as above but the length of the pace area is longer and the monster stops before...
Definition: define.h:544
sstring message
If not NULL, what the player will be displayed as said.
Definition: dialog.h:53
#define SP_MOVING_BALL
Definition: spells.h:109
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.cpp:1818
#define SP_AURA
Definition: spells.h:120
void pets_move(object *ob)
Handles a pet&#39;s movement.
Definition: pets.cpp:330
#define LOOK_OBJ(ob)
This returns TRUE if the object is something that should be displayed in the look window...
Definition: object.h:521
bool coords_in_shop(mapstruct *map, int x, int y)
Check if the given map coordinates are in a shop.
Definition: map.cpp:2756
#define SPELL_GRACE
Definition: spells.h:59
Number of statistics.
Definition: living.h:18
int monster_can_detect_enemy(object *op, object *enemy, rv_vector *rv)
Determine if we can &#39;detect&#39; the enemy.
Definition: monster.cpp:2690
#define FLAG_READY_RANGE
(Monster) has a range attack readied...
Definition: define.h:286
See Spellbook.
Definition: object.h:208
See Money.
Definition: object.h:142
int path_measure_func(const void *ob)
Function to retrieve the measurement the minheap will organize by.
Definition: monster.cpp:439
object * more
Pointer to the rest of a large body of objects.
Definition: object.h:303
sstring replies[MAX_REPLIES]
Description for replies_words.
Definition: dialog.h:57
sstring add_string(const char *str)
Share a string.
Definition: shstr.cpp:137
#define FLAG_BLIND
If set, object cannot see (visually)
Definition: define.h:324
#define MSG_TYPE_DIALOG
NPCs, magic mouths, and altars.
Definition: newclient.h:416
uint8_t will_apply
See crossfire.doc and What monsters apply.
Definition: object.h:402
static int monster_wait_att2(int dir, rv_vector *rv)
Return the next direction the monster should move for a specific movement type.
Definition: monster.cpp:2152
int16_t SP_level_spellpoint_cost(object *caster, object *spell, int flags)
Scales the spellpoint cost of a spell by it&#39;s increased effectiveness.
Definition: spell_util.cpp:236
See Weapon.
Definition: object.h:124
void remove_friendly_object(object *op)
Removes the specified object from the linked list of friendly objects.
Definition: friend.cpp:52
static int monster_use_range(object *head, object *part, object *pl, int dir)
Monster will use a ranged attack (ROD, WAND, ...).
Definition: monster.cpp:1495
#define IS_WEAPON(op)
Definition: define.h:163
static int monster_do_talk_npc(object *npc, talk_info *info)
Checks the messages of a NPC for a matching text.
Definition: monster.cpp:2557
#define FLAG_CONFUSED
Will also be unable to cast spells.
Definition: define.h:299
#define FLAG_STEALTH
Will wake monsters with less range.
Definition: define.h:300
#define FLAG_RANDOM_MOVE
NPC will move randomly.
Definition: define.h:297
void monster_communicate(object *op, const char *txt)
This function looks for an object or creature that is listening to said text.
Definition: monster.cpp:2483
sstring replies_words[MAX_REPLIES]
Available reply words.
Definition: dialog.h:56
See Rod.
Definition: object.h:114
int map_light_on(mapstruct *m, int x, int y)
Return the light level at position (X, Y) on map M.
Definition: map.cpp:2729
const char * get_reply_text_own(reply_type rt)
Return the verb for the player&#39;s dialog type.
Definition: monster.cpp:2427
int16_t y
Position in the map for this object.
Definition: object.h:335
object * object_find_by_type_applied(const object *who, int type)
Find applied object in inventory.
Definition: object.cpp:4068
int8_t magic
Any magical bonuses to this item.
Definition: object.h:358
#define FLAG_USE_WEAPON
(Monster) can wield weapons
Definition: define.h:284
char * message
What the player will actually say for this reply.
Definition: dialog.h:18
uint32_t get_weight_limit(int stat)
Definition: living.cpp:2373
MoveType move_block
What movement types this blocks.
Definition: object.h:437
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
#define OUT_OF_REAL_MAP(M, X, Y)
Checks if a square is out of the map.
Definition: map.h:220
uint16_t height
Width and height of map.
Definition: map.h:342
uint16_t width
Definition: map.h:342
static object * monster_find_enemy(object *npc, rv_vector *rv)
Tries to find an enmy for npc.
Definition: monster.cpp:240
int apply_can_apply_object(const object *who, const object *op)
Checks to see if &#39;who&#39; can apply object &#39;op&#39;.
Definition: apply.cpp:678
object * attacked_by
This object start to attack us! only player & monster.
Definition: object.h:392
int monster_stand_in_light(object *op)
Cache monster_stand_in_light_internal().
Definition: monster.cpp:2845
#define FLAG_NO_ATTACK
monster don&#39;t attack
Definition: define.h:350
void monster_do_say(const mapstruct *map, const char *message)
Output a NPC message on a map.
Definition: monster.cpp:2401
object * chosen_skill
The skill chosen to use.
Definition: object.h:396
int monster_compute_path(object *source, object *target, int default_dir)
Computes a path from source to target.
Definition: monster.cpp:471
#define MSG_TYPE_DIALOG_NPC
A message from the npc.
Definition: newclient.h:506
#define MAX(x, y)
Definition: compat.h:24
#define CIRCLE1
If the upper four bits of move_type / attack_movement are set to this number, the monster will move i...
Definition: define.h:517
static void monster_pace2_movev(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2214
int16_t x
Definition: object.h:335
int player_can_view(object *pl, object *op)
Check the player los field for viewability of the object op.
Definition: player.cpp:4168
int path_to_player(object *mon, object *pl, unsigned mindiff)
Returns the direction to the player, if valid.
Definition: player.cpp:659
static int monster_move_no_enemy(object *op)
Makes a monster without any enemy move.
Definition: monster.cpp:790
Global type definitions and header inclusions.
#define PETMOVE
If the upper four bits of attack_movement are set to this number, the monster follows a player until ...
Definition: define.h:502
#define AP_APPLY
Item is to be applied.
Definition: define.h:595
struct player * contr
Pointer to the player which control this object.
Definition: object.h:284
int8_t Con
Use
Definition: living.h:36
int16_t movement_penalty
Definition: monster.cpp:427
static void monster_apply_below(object *monster)
If a monster who&#39;s eager to apply things encounters something apply-able, then make him apply it...
Definition: monster.cpp:1978
#define FLAG_USE_RING
(Monster) can use rings, boots, gauntlets, etc
Definition: define.h:285
static int monster_get_armour_quality(const object *item)
Returns the "quality" value of an armour of a monster.
Definition: monster.cpp:1680
int distance_y
Y delta.
Definition: map.h:378
static int monster_talk_to_npc(object *npc, talk_info *info)
Give an object the chance to handle something being said.
Definition: monster.cpp:2623
#define HITRUN
Run to then hit player then run away cyclicly.
Definition: define.h:494
int light_cached
Definition: object.h:454
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: main.cpp:308
See Wand & Staff.
Definition: object.h:225
sstring stringbuffer_finish_shared(StringBuffer *sb)
Deallocate the string buffer instance and return the string as a shared string.
void monster_check_doors(object *op, mapstruct *m, int x, int y)
Living creature attempts to open a door.
Definition: monster.cpp:2387
#define MIN(x, y)
Definition: compat.h:21
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:219
int32_t weight
Attributes of the object.
Definition: object.h:375
bool chance(int a, int b)
Return true with a probability of a/b.
Definition: treasure.cpp:890
int monster_can_see_enemy(object *op, object *enemy)
Assuming no walls/barriers, lets check to see if its possible to see an enemy.
Definition: monster.cpp:2867
One reply a NPC can expect.
Definition: dialog.h:16
See Magic Ear.
Definition: object.h:136
#define NDI_NAVY
Definition: newclient.h:248
#define NROFATTACKS
Definition: attack.h:15
uint8_t run_away
Monster runs away if it&#39;s hp goes below this percentage.
Definition: object.h:394
#define FLAG_SEE_INVISIBLE
Will see invisible player.
Definition: define.h:240
Throwing.
Definition: skills.h:44
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.cpp:294
#define FLAG_READY_SKILL
(Monster or Player) has a skill readied
Definition: define.h:321
int16_t level
Level of creature or object.
Definition: object.h:361
#define RUNATT
Run but attack if player catches up to object.
Definition: define.h:493
int16_t sp
Spell points.
Definition: living.h:42
void object_free(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.cpp:1577
reply_type
Various kind of messages a player or NPC can say.
Definition: dialog.h:7
#define HI4
Definition: define.h:552
static int monster_stand_in_light_internal(object *op)
Determine if op stands in a lighted square.
Definition: monster.cpp:2830
See Shooting Weapon.
Definition: object.h:123
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Find object in inventory.
Definition: object.cpp:4286
uint8_t hide
The object is hidden, not invisible.
Definition: object.h:397
#define SP_BULLET
Definition: spells.h:79
int replies_count
How many items in replies_words and replies.
Definition: dialog.h:55
Asking a question.
Definition: dialog.h:10
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:217
void do_hidden_move(object *op)
For hidden creatures - a chance of becoming &#39;unhidden&#39; every time they move - as we subtract off &#39;inv...
Definition: player.cpp:4059
#define AP_IGNORE_CURSE
Apply/unapply regardless of cursed/damned status.
Definition: define.h:603
int16_t resist[NROFATTACKS]
Resistance adjustments for attacks.
Definition: object.h:351
object * identify(object *op)
Identifies an item.
Definition: item.cpp:1446
#define MAX_REPLIES
How many NPC replies maximum to tell the player.
Definition: dialog.h:43
#define FOR_OB_AND_ABOVE_FINISH()
Finishes FOR_OB_AND_ABOVE_PREPARE().
Definition: define.h:766
void monster_npc_say(object *npc, const char *cp)
Simple function to have some NPC say something.
Definition: monster.cpp:2606
See Treasure.
Definition: object.h:115
#define FLAG_READY_SCROLL
monster has scroll in inv and can use it
Definition: define.h:312
int8_t range
Range of the spell.
Definition: object.h:417
float speed
Frequency of object &#39;moves&#39; relative to server tick rate.
Definition: object.h:337
int32_t carrying
How much weight this object contains.
Definition: object.h:377
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
#define FLAG_CAN_USE_SKILL
The monster can use skills.
Definition: define.h:309
#define MOVE_FLY_LOW
Low flying object.
Definition: define.h:399
Structure used to build up dialog information when a player says something.
Definition: dialog.h:50
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:360
void drain_rod_charge(object *rod)
Drain charges from a rod.
Definition: spell_util.cpp:776
#define SP_BOMB
Definition: spells.h:82
#define SET_FLAG(xyz, p)
Definition: define.h:384
const char * text
What the player actually said.
Definition: dialog.h:52
int32_t last_sp
As last_heal, but for spell points.
Definition: object.h:368
#define FLAG_UNAGGRESSIVE
Monster doesn&#39;t attack players.
Definition: define.h:259
#define QUERY_FLAG(xyz, p)
Definition: define.h:386
#define FLAG_USE_SHIELD
Can this creature use a shield?
Definition: define.h:224
bool identifies
Identify the speaker when this message is matched.
Definition: dialog.h:31
#define FLAG_USE_RANGE
(Monster) can apply and use range items
Definition: define.h:280
int8_t Wis
Use
Definition: living.h:36
static void monster_check_apply(object *mon, object *item)
Called after an item is inserted in a monster.
Definition: monster.cpp:1736
int get_dialog_message(object *op, const char *text, struct_dialog_message **message, struct_dialog_reply **reply)
Tries to find a message matching the said text.
Definition: dialog.cpp:233
object * get_nearest_player(object *mon)
Finds the nearest visible player or player-friendly for some object.
Definition: player.cpp:548
uint8_t pick_up
See crossfire.doc.
Definition: object.h:371
static void monster_circ2_move(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2175
int pets_should_arena_attack(object *pet, object *owner, object *target)
Determines if checks so pets don&#39;t attack players or other pets should be overruled by the arena petm...
Definition: pets.cpp:1099
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.cpp:594
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.cpp:1545
#define WILL_APPLY_TREASURE
Open chests.
Definition: object.h:55
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.cpp:299
int monster_move(object *op)
Main monster processing routine.
Definition: monster.cpp:867
tag_t attacked_by_count
The tag of attacker, so we can be sure.
Definition: object.h:393
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:700
Reply to something.
Definition: dialog.h:9
object * head
Points to the main object of a large body.
Definition: object.h:304
int has_carried_lights(const object *op)
Checks if op has a light source.
Definition: los.cpp:346
sstring race
Human, goblin, dragon, etc.
Definition: object.h:326
This is a game-map.
Definition: map.h:320
const Animations * animation
Animation of this item, NULL if not animated.
Definition: object.h:428
Definition: object.h:150
#define PACEH
The monster will pace back and forth until attacked.
Definition: define.h:525
#define MAX_KNOWN_SPELLS
Maximum number of spells to consider when choosing a spell for a monster.
Definition: monster.cpp:1212
void get_search_arr(int *search_arr)
New function to make monster searching more efficient, and effective! This basically returns a random...
Definition: object.cpp:3627
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
Returns true if the given object can&#39;t fit in the given spot.
Definition: map.cpp:489
char * reply
Reply expected from the player.
Definition: dialog.h:17
int distance_x
X delta.
Definition: map.h:377
#define MSG_TYPE_COMMUNICATION_SAY
Player says something.
Definition: newclient.h:659
void ext_info_map_except(int color, const mapstruct *map, const object *op, uint8_t type, uint8_t subtype, const char *str1)
Writes to everyone on the map except *op.
Definition: info.cpp:220
#define SP_SMITE
Definition: spells.h:84
int is_true_undead(object *op)
Is the object a true undead?
Definition: player.cpp:4001
static void monster_pace2_moveh(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2229
#define MSG_TYPE_COMMUNICATION
Communication between players.
Definition: newclient.h:427
sstring object_get_value(const object *op, const char *const key)
Get an extra value by key.
Definition: object.cpp:4331
#define FLAG_PARALYZED
Monster or player is paralyzed.
Definition: define.h:367
int8_t glow_radius
indicates the glow radius of the object
Definition: object.h:374
static void monster_pace_movev(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2188
uint64_t shopmin
Minimum price a shop will trade for.
Definition: map.h:354
#define AP_NOPRINT
Don&#39;t print messages - caller will do that may be some that still print.
Definition: define.h:607
#define SIZEOFFREE
Definition: define.h:155
#define P_OUT_OF_MAP
This space is outside the map.
Definition: map.h:254
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Gets the blocking state of a square.
Definition: map.h:195
int do_skill(object *op, object *part, object *skill, int dir, const char *string)
Main skills use function-similar in scope to cast_spell().
Definition: skill_util.cpp:443
object * monster_find_throw_ob(object *op)
Find an item for the monster to throw.
Definition: monster.cpp:2651
#define FLAG_SCARED
Monster is scared (mb player in future)
Definition: define.h:258
#define SP_INVISIBLE
Definition: spells.h:93
#define MSG_TYPE_SKILL_FAILURE
Failure in using skill.
Definition: newclient.h:626
#define FLAG_ONLY_ATTACK
NPC will evaporate if there is no enemy.
Definition: define.h:298
#define FLAG_XRAYS
X-ray vision.
Definition: define.h:288
static void monster_check_pickup(object *monster)
Checks for items that monster can pick up.
Definition: monster.cpp:1853
int16_t dam
How much damage this object does when hitting.
Definition: living.h:46
#define AT_PHYSICAL
Basic attack (1)
Definition: attack.h:78
uint32_t pticks
Number of ticks since time reset.
Definition: time.cpp:47
See Spell.
Definition: object.h:219
#define CAN_APPLY_NOT_MASK
Definition: define.h:655
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:609
int get_randomized_dir(int dir)
Returns a random direction (1..8) similar to a given direction.
Definition: utils.cpp:412
See Handle Trigger.
Definition: object.h:134
void fatal(enum fatal_error err)
fatal() is meant to be called whenever a fatal signal is intercepted.
Definition: utils.cpp:590
int16_t x
Definition: monster.cpp:422
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:218
living stats
Str, Con, Dex, etc.
Definition: object.h:378
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
#define SP_SWARM
Definition: spells.h:110
#define IS_SHIELD(op)
Definition: define.h:170
See Door.
Definition: object.h:131
In order to adequately path for A* search, we will need a minheap to efficiently handle pathing from ...
Definition: minheap.h:16
Many many details.
Definition: logger.h:14
int fire_bow(object *op, object *arrow, int dir, int wc_mod, int16_t sx, int16_t sy)
Creature (monster or player) fires a bow.
Definition: player.cpp:2107
int16_t invisible
How much longer the object will be invis.
Definition: object.h:370
#define FLAG_CAST_SPELL
(Monster) can learn and cast spells
Definition: define.h:278
void minheap_init_static(MinHeap *heap, void **arr, int amt, int(*measure_func)(const void *))
Initialize the minheap using statically allocated components.
Definition: minheap.cpp:162
object * monster_check_enemy(object *npc, rv_vector *rv)
Checks npc->enemy and returns that enemy if still valid, NULL otherwise.
Definition: monster.cpp:80
#define FLAG_BERSERK
monster will attack closest living object
Definition: define.h:346
void drop(object *op, object *tmp)
Drop an item, either on the floor or in a container.
Definition: c_object.cpp:1120
uint64_t price_base(const object *obj)
Price an item based on its value or archetype value, type, identification/BUC status, and other heuristics.
Definition: item.cpp:1507
void skill_attack(object *tmp, object *pl, int dir, const char *string, object *skill)
Core routine for use when we attack using a skills system.
uint16_t distance
Definition: monster.cpp:424
#define WAITATT
Wait for player to approach then hit, move if hit.
Definition: define.h:495
mapstruct * get_map_from_coord(mapstruct *m, int16_t *x, int16_t *y)
This is basically the same as out_of_map above(), but instead we return NULL if no map is valid (coor...
Definition: map.cpp:2351
static StringBuffer * monster_format_say(const object *npc, const char *message)
Format an NPC message.
Definition: monster.cpp:2412
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
#define FLAG_RUN_AWAY
Object runs away from nearest player \ but can still attack at a distance.
Definition: define.h:267
Skill-related defines, including subtypes.
Basic sentence.
Definition: dialog.h:8
static int monster_get_weapon_quality(const object *item)
Returns the "quality" value of a weapon of a monster.
Definition: monster.cpp:1628
#define ALLRUN
Always run, never attack good for sim.
Definition: define.h:497
int object_can_pick(const object *who, const object *item)
Finds out if an object can be picked up.
Definition: object.cpp:3852
#define FLAG_IS_THROWN
Object is designed to be thrown.
Definition: define.h:236
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.cpp:305
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:753
MoveType move_slow
Movement types this slows down.
Definition: object.h:441
int8_t facing
Object is oriented/facing that way.
Definition: object.h:345
static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv)
Checks if monster can hit in hand-to-hand combat.
Definition: monster.cpp:1143
int16_t y
Definition: monster.cpp:423
static int monster_can_pick(object *monster, object *item)
Check if the monster can and is interested in picking up an item.
Definition: monster.cpp:1897
static int monster_use_skill(object *head, object *part, object *pl, int dir)
A monster attempts using a skill.
Definition: monster.cpp:1438
See Player.
Definition: object.h:112
static int is_enemy(object *who, object *owner)
Determine if an object can be considered an enemy.
Definition: monster.cpp:150
static int monster_use_bow(object *head, object *part, object *pl, int dir)
Tries to make a (part of a) monster fire a bow.
Definition: monster.cpp:1571
#define RUSH
Rush toward player blindly, similiar to dumb monster.
Definition: define.h:496
const char * key_shopkeeper
Definition: monster.cpp:61
int8_t body_info[NUM_BODY_LOCATIONS]
Body info as loaded from the file.
Definition: object.h:382
uint16_t heuristic_dist
Definition: monster.cpp:425
#define WAIT2
Monster does not try to move towards player if far.
Definition: define.h:499
#define FLAG_GENERATOR
Will generate type ob->stats.food.
Definition: define.h:235
int dirdiff(int dir1, int dir2)
Computes a direction difference.
Definition: object.cpp:3717
#define WILL_APPLY_HANDLE
Apply handles and triggers.
Definition: object.h:54
static event_registration m
Definition: citylife.cpp:424
#define FLAG_NEUTRAL
monster is from type neutral
Definition: define.h:349
#define RANDOM()
Definition: define.h:667
static int monster_disthit_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv)
Return the next direction the monster should move for a specific movement type.
Definition: monster.cpp:2133
#define MAX_NPC
How many NPCs maximum will reply to the player.
Definition: dialog.h:45
static int monster_check_wakeup(object *op, object *enemy, rv_vector *rv)
Sees if this monster should wake up.
Definition: monster.cpp:337
Also see SKILL_TOOL (74) below.
Definition: object.h:148
MoveType move_type
Type of movement this object uses.
Definition: object.h:436
sstring name
The name of the object, obviously...
Definition: object.h:319
int8_t get_attr_value(const living *stats, int attr)
Gets the value of a stat.
Definition: living.cpp:313
object * spellitem
Spell ability monster is choosing to use.
Definition: object.h:406
Only for debugging purposes.
Definition: logger.h:13
const char * key_shopkeeper_pilesize
Definition: monster.cpp:63
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
This rolls up wall, blocks_magic, blocks_view, etc, all into one function that just returns a P_...
Definition: map.cpp:300
Hiding.
Definition: skills.h:21
uint8_t darkness
Indicates level of darkness of map.
Definition: map.h:341
#define RANDO2
Constantly move in a different random direction.
Definition: define.h:540
One message a NPC can react to.
Definition: dialog.h:26
#define MIN_MON_RADIUS
Minimum monster detection radius.
Definition: monster.cpp:58
unsigned int distance
Distance, in squares.
Definition: map.h:376
static int monster_check_good_weapon(object *who, object *item)
Checks if using weapon &#39;item&#39; would be better for &#39;who&#39;.
Definition: monster.cpp:1654
const char * key_shopkeeper_debug
Definition: monster.cpp:62
void object_set_enemy(object *op, object *enemy)
Sets the enemy of an object.
Definition: object.cpp:900
void dialog_preparse(object *op)
Definition: dialog.cpp:110
static object * monster_choose_random_spell(object *monster)
Selects a spell to cast for a monster.
Definition: monster.cpp:1229
#define CLEAR_FLAG(xyz, p)
Definition: define.h:385
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
int direction
General direction to the targer.
Definition: map.h:379
See Handle.
Definition: object.h:213
int8_t ac
Armor Class, lower AC increases probability of not getting hit.
Definition: living.h:38
#define SP_MAGIC_MISSILE
Definition: spells.h:85
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:222
int move_object(object *op, int dir)
Try to move op in the direction "dir".
Definition: move.cpp:39
int8_t Pow
Use
Definition: living.h:36
Structure to store data so we can use a minheap.
Definition: monster.cpp:421
int can_see_monsterP(mapstruct *m, int x, int y, int dir)
Recursive routine to see if we can find a path to a certain point.
Definition: object.cpp:3807
#define SIZEOFFREE2
Definition: define.h:154
reply_type message_type
A reply_type value for message.
Definition: dialog.h:54
static void shopkeeper_move(object *ob)
Special move for shopkeepers.
Definition: monster.cpp:2264
int get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
From map.c This is used by get_player to determine where the other creature is.
Definition: map.cpp:2522
int object_set_value(object *op, const char *key, const char *value, int add_key)
Updates the key in op to value.
Definition: object.cpp:4484
void monster_check_earthwalls(object *op, mapstruct *m, int x, int y)
Living creature attempts to hit an earthwall.
Definition: monster.cpp:2371
#define SP_SUMMON_MONSTER
Definition: spells.h:101
object * inv
Pointer to the first object in the inventory.
Definition: object.h:298
struct struct_dialog_reply * replies
Replies this message has.
Definition: dialog.h:29
static int monster_cast_spell(object *head, object *part, object *pl, int dir)
Tries to make a (part of a) monster cast a spell.
Definition: monster.cpp:1267
void monster_npc_call_help(object *op)
A monster calls for help against its enemy.
Definition: monster.cpp:2014
uint32_t light_cached_time
Computing whether or not an item is in the light is very expensive, so cache it.
Definition: object.h:453
char * message
What the NPC will say.
Definition: dialog.h:28
static int monster_move_randomly(object *op)
Handles random object movement.
Definition: monster.cpp:383
struct object * who
Player saying something.
Definition: dialog.h:51
void monster_do_living(object *op)
For a monster, regenerate hp and sp, potentially clear scared status.
Definition: monster.cpp:727
#define MIN_ACTIVE_SPEED
Cut off point of when an object is put on the active list or not.
Definition: define.h:662
#define GET_MAP_OB(M, X, Y)
Gets the bottom object on a map.
Definition: map.h:173
#define DISTATT
Move toward a player if far, but maintain some space, attack from a distance - good for missile users...
Definition: define.h:490
int minheap_insert(MinHeap *heap, void *ob)
Inserts an element into the min-heap.
Definition: minheap.cpp:184
int16_t maxsp
Max spell points.
Definition: living.h:43
#define FLAG_MONSTER
Will attack players.
Definition: define.h:232
#define MSG_TYPE_SKILL
Messages related to skill use.
Definition: newclient.h:424
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:270
int32_t last_heal
Last healed.
Definition: object.h:367
uint32_t tmp_invis
Will invis go away when we attack?
Definition: player.h:142
#define FLAG_READY_BOW
not implemented yet
Definition: define.h:287
bool pick_up(object *op, object *alt)
Try to pick up an item.
Definition: c_object.cpp:470
sstring npc_msgs[MAX_NPC]
What the NPCs will say.
Definition: dialog.h:59
object * object_find_by_type_and_race(const object *who, int type, const char *race)
Find object in inventory by type and race.
Definition: object.cpp:4118
void make_visible(object *op)
Makes an object visible again.
Definition: player.cpp:3982
static void monster_pace_moveh(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2201
#define SP_MAGIC_WALL
Definition: spells.h:89
int absdir(int d)
Computes an absolute direction.
Definition: object.cpp:3699
#define PACEH2
The monster will pace as above but the length of the pace area is longer and the monster stops before...
Definition: define.h:528
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:746
StringBuffer * buf
Definition: readable.cpp:1563
#define IS_ARMOR(op)
Definition: define.h:166
static int monster_run_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv)
Return the next direction the monster should move for a specific movement type.
Definition: monster.cpp:2075
static uint16_t estimate_distance(int16_t ax, int16_t ay, int16_t bx, int16_t by)
Heuristic function to make the pathing follow an A* search.
Definition: monster.cpp:449
#define PACEV
The monster will pace back and forth until attacked.
Definition: define.h:541
#define WILL_APPLY_FOOD
Eat food (not drinks).
Definition: object.h:58
struct struct_dialog_reply * next
Next reply, NULL for last.
Definition: dialog.h:20
A buffer that will be expanded as content is added to it.
#define SPELL_MANA
Definition: spells.h:58
int16_t maxhp
Max hit points.
Definition: living.h:41
uint8_t subtype
Subtype of object.
Definition: object.h:349
#define FOR_BELOW_PREPARE(op_, it_)
Constructs a loop iterating over all objects below an object.
Definition: define.h:727
object * monster_find_nearest_enemy(object *npc, object *owner)
Returns the nearest enemy (monster or generator) which is visible to npc.
Definition: monster.cpp:183
#define CIRCLE2
Same as CIRCLE1 but a larger circle is used.
Definition: define.h:524
object * find_skill_by_number(object *who, int skillno)
This returns the first skill pointer of the given subtype (the one that accumulates exp...
Definition: main.cpp:375
const char * sstring
Definition: sstring.h:2
reply_type type
Type of message.
Definition: dialog.h:19
#define P_IS_ALIVE
Something alive is on this space.
Definition: map.h:240
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.cpp:2842
object * pets_get_enemy(object *pet, rv_vector *rv)
Given that &#39;pet&#39; is a friendly object, this function returns a monster the pet should attack...
Definition: pets.cpp:54
int8_t wc
Weapon Class, lower WC increases probability of hitting.
Definition: living.h:37
int8_t Int
Use
Definition: living.h:36
See Jewel.
Definition: object.h:172
tag_t count
Unique object number for this object.
Definition: object.h:307
#define FLAG_UNIQUE
Item is really unique (UNIQUE_ITEMS)
Definition: define.h:275
#define FLAG_NO_PICK
Object can&#39;t be picked up.
Definition: define.h:226
static int monster_check_good_armour(object *who, object *item)
Checks if using armor &#39;item&#39; would be better for &#39;who&#39;.
Definition: monster.cpp:1701
static int monster_use_scroll(object *head, object *part, object *pl, int dir)
Tries to make a (part of a) monster apply a spell.
Definition: monster.cpp:1354
void * minheap_remove(MinHeap *heap)
Pops the top of the minheap off.
Definition: minheap.cpp:209
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Object is attacked by something.
Definition: attack.cpp:1907
int32_t move_status
What stage in attack mode.
Definition: object.h:400
void void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1)
Writes to everyone on the specified map.
Definition: main.cpp:334
void query_short_name(const object *op, char *buf, size_t size)
query_short_name(object) is similar to query_name(), but doesn&#39;t contain any information about object...
Definition: item.cpp:518
#define SP_SUMMON_GOLEM
Definition: spells.h:86
#define SP_EXPLOSION
Definition: spells.h:80
void monster_check_apply_all(object *monster)
Calls monster_check_apply() for all inventory objects.
Definition: monster.cpp:2001
static int monster_dist_att(int dir, object *enemy, object *part, rv_vector *rv)
Return the direction the monster should move or look to attack an enemy.
Definition: monster.cpp:2056
static const char * get_reply_text_other(reply_type rt)
Return the verb for the player&#39;s dialog type seen from others (third person).
Definition: monster.cpp:2445
object clone
An object from which to do object_copy()
Definition: object.h:487
#define FLAG_USE_BOW
(Monster) can apply and fire bows
Definition: define.h:281
bool object_value_set(const object *op, const char *const key)
Determine if an extra value is set.
Definition: object.cpp:4361
#define FOR_BELOW_FINISH()
Finishes FOR_BELOW_PREPARE().
Definition: define.h:734
int8_t Str
Use
Definition: living.h:36
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:693
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Main dispatch when someone casts a spell.
#define DISTHIT
Attack from a distance if hit as recommended by Frank.
Definition: define.h:498
#define ATNR_PHYSICAL
Definition: attack.h:47
char * name
Name of map as given by its creator.
Definition: map.h:323
int16_t hp
Hit Points.
Definition: living.h:40
int events_execute_object_say(object *npc, talk_info *talk)
Execute an EVENT_SAY on the specified object.
Definition: events.cpp:313
#define FLAG_FREED
Object is in the list of free objects.
Definition: define.h:220
#define MAX_EXPLORE
Maximum map size to consider when finding a path in monster_compute_path().
Definition: monster.cpp:416
object * enemy
Monster/player to follow even if not closest.
Definition: object.h:391
#define LO4
bitmasks for upper and lower 4 bits from 8 bit fields
Definition: define.h:551