Crossfire Server, Trunk  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  /* doppleganger code to change monster facing to that of the nearest
935  * player. Hmm. The code is here, but no monster in the current
936  * arch set uses it.
937  */
938  if (op->race != NULL && strcmp(op->race, "doppleganger") == 0) {
939  op->face = enemy->face;
940  if (op->name)
941  free_string(op->name);
942  add_refcount(op->name = enemy->name);
943  }
944 
945  /* Calculate range information for closest body part - this
946  * is used for the 'skill' code, which isn't that smart when
947  * it comes to figuring it out - otherwise, giants throw boulders
948  * into themselves.
949  */
950  if (!get_rangevector(op, enemy, &rv, 0))
951  return 0;
952  if (op->direction != rv.direction) {
953  op->direction = rv.direction;
954  op->facing = op->direction;
955  if (op->animation)
956  animate_object(op, op->direction);
957  }
958 
959  // We are looking at movement -- if monster was paralyzed, they aren't anymore
960  if (QUERY_FLAG(op, FLAG_PARALYZED)) {
962  }
963 
964  /* Move the check for scared up here - if the monster was scared,
965  * we were not doing any of the logic below, so might as well save
966  * a few cpu cycles.
967  */
968  if (!QUERY_FLAG(op, FLAG_SCARED)) {
969  dir = rv.direction;
970 
971  /* Was two if statements assigning to the same variable
972  * We can get the same effect by reversing the order and making an else-if
973  */
974  if (QUERY_FLAG(op, FLAG_CONFUSED))
975  dir = get_randomized_dir(dir);
976  else if (QUERY_FLAG(op, FLAG_RUN_AWAY))
977  dir = absdir(dir+4);
978 
979  if (QUERY_FLAG(op, FLAG_CAST_SPELL) && !(RANDOM()%3)) {
980  if (monster_cast_spell(op, rv.part, enemy, dir))
981  return 0;
982  }
983 
984  if (QUERY_FLAG(op, FLAG_READY_SCROLL) && !(RANDOM()%3)) {
985  if (monster_use_scroll(op, rv.part, enemy, dir))
986  return 0;
987  }
988 
989  if (QUERY_FLAG(op, FLAG_READY_RANGE) && !(RANDOM()%3)) {
990  if (monster_use_range(op, rv.part, enemy, dir))
991  return 0;
992  }
993  if (QUERY_FLAG(op, FLAG_READY_SKILL) && !(RANDOM()%3)) {
994  if (monster_use_skill(op, rv.part, enemy, rv.direction))
995  return 0;
996  }
997  if (QUERY_FLAG(op, FLAG_READY_BOW) && !(RANDOM()%2)) {
998  if (monster_use_bow(op, rv.part, enemy, dir))
999  return 0;
1000  }
1001  } /* If not scared */
1002 
1003 
1004  /* code below is for when we didn't use a range attack or a skill, so
1005  * either move or hit with hth attack. */
1006 
1007  part = rv.part;
1008  dir = rv.direction;
1009 
1010  /* This first clause used to happen after the other two, but would trample dir.
1011  * Moved to before them as another check to slightly reduce calls to monster_compute_path
1012  */
1013  if (QUERY_FLAG(op, FLAG_CONFUSED))
1014  dir = get_randomized_dir(dir);
1015  else if (QUERY_FLAG(op, FLAG_SCARED) || QUERY_FLAG(op, FLAG_RUN_AWAY))
1016  dir = absdir(dir+4);
1017  else if (!monster_can_hit(part, enemy, &rv)) {
1018  dir = monster_compute_path(op, enemy, -1);
1019  if (dir == -1) {
1020  // Can't reach enemy, so remove it, attempt to move in its last direction so not stay still
1021  LOG(llevMonster, "monster %s (%d, %d on %s) can't reach enemy %s (%d, %d on %s)\n",
1022  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)");
1023  object_set_enemy(op, NULL);
1024  dir = rv.direction;
1025  }
1026  }
1027 
1028  if ((op->attack_movement&LO4) && !QUERY_FLAG(op, FLAG_SCARED)) {
1029  switch (op->attack_movement&LO4) {
1030  case DISTATT:
1031  dir = monster_dist_att(dir, enemy, part, &rv);
1032  break;
1033 
1034  case RUNATT:
1035  dir = monster_run_att(dir, op, enemy, part, &rv);
1036  break;
1037 
1038  case HITRUN:
1039  dir = monster_hitrun_att(dir, op);
1040  break;
1041 
1042  case WAITATT:
1043  dir = monster_wait_att(dir, op, enemy, part, &rv);
1044  break;
1045 
1046  case RUSH: /* default - monster normally moves towards player */
1047  case ALLRUN:
1048  break;
1049 
1050  case DISTHIT:
1051  dir = monster_disthit_att(dir, op, enemy, part, &rv);
1052  break;
1053 
1054  case WAIT2:
1055  dir = monster_wait_att2(dir, &rv);
1056  break;
1057 
1058  default:
1059  LOG(llevDebug, "Illegal low mon-move: %d\n", op->attack_movement&LO4);
1060  }
1061  }
1062 
1063  if (!dir)
1064  return 0;
1065 
1066  if (!QUERY_FLAG(op, FLAG_STAND_STILL)) {
1067  if (move_object(op, dir)) /* Can the monster move directly toward player? */
1068  return 0;
1069 
1070  if (QUERY_FLAG(op, FLAG_SCARED)
1071  || !monster_can_hit(part, enemy, &rv)
1072  || QUERY_FLAG(op, FLAG_RUN_AWAY)) {
1073  /* Try move around corners if !close */
1074  int maxdiff = (QUERY_FLAG(op, FLAG_ONLY_ATTACK) || RANDOM()&1) ? 1 : 2;
1075  for (diff = 1; diff <= maxdiff; diff++) {
1076  /* try different detours */
1077  int m = 1-(RANDOM()&2); /* Try left or right first? */
1078  if (move_object(op, absdir(dir+diff*m))
1079  || move_object(op, absdir(dir-diff*m)))
1080  return 0;
1081  }
1082  }
1083  } /* if monster is not standing still */
1084 
1085  /*
1086  * Eneq(@csd.uu.se): Patch to make RUN_AWAY or SCARED monsters move a random
1087  * direction if they can't move away.
1088  */
1089  if (!QUERY_FLAG(op, FLAG_ONLY_ATTACK)
1090  && (QUERY_FLAG(op, FLAG_RUN_AWAY) || QUERY_FLAG(op, FLAG_SCARED)))
1091  if (monster_move_randomly(op))
1092  return 0;
1093 
1094  /*
1095  * Try giving the monster a new enemy - the player that is closest
1096  * to it. In this way, it won't just keep trying to get to a target
1097  * that is inaccessible.
1098  * This could be more clever - it should go through a list of several
1099  * enemies, as it is now, you could perhaps get situations where there
1100  * are two players flanking the monster at close distance, but which
1101  * the monster can't get to, and a third one at a far distance that
1102  * the monster could get to - as it is, the monster won't look at that
1103  * third one.
1104  */
1105  if (!QUERY_FLAG(op, FLAG_FRIENDLY) && enemy == op->enemy) {
1106  object *nearest_player = get_nearest_player(op);
1107 
1108  if (nearest_player && nearest_player != enemy && !monster_can_hit(part, enemy, &rv)) {
1109  object_set_enemy(op, NULL);
1110  enemy = nearest_player;
1111  }
1112  }
1113 
1114  if (!QUERY_FLAG(op, FLAG_SCARED) && monster_can_hit(part, enemy, &rv)) {
1115  /* The adjustement to wc that was here before looked totally bogus -
1116  * since wc can in fact get negative, that would mean by adding
1117  * the current wc, the creature gets better? Instead, just
1118  * add a fixed amount - nasty creatures that are runny away should
1119  * still be pretty nasty.
1120  */
1121  if (QUERY_FLAG(op, FLAG_RUN_AWAY)) {
1122  part->stats.wc += 10;
1123  skill_attack(enemy, part, 0, NULL, NULL);
1124  part->stats.wc -= 10;
1125  } else
1126  skill_attack(enemy, part, 0, NULL, NULL);
1127  } /* if monster is in attack range */
1128 
1129  if (QUERY_FLAG(part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */
1130  return 1;
1131 
1132  if (QUERY_FLAG(op, FLAG_ONLY_ATTACK)) {
1133  object_remove(op);
1135  return 1;
1136  }
1137  return 0;
1138 }
1139 
1154 static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv) {
1155  object *more;
1156  rv_vector rv1;
1157 
1158  if (QUERY_FLAG(ob1, FLAG_CONFUSED) && !(RANDOM()%3))
1159  return 0;
1160 
1161  if (abs(rv->distance_x) < 2 && abs(rv->distance_y) < 2)
1162  return 1;
1163 
1164  /* check all the parts of ob2 - just because we can't get to
1165  * its head doesn't mean we don't want to pound its feet
1166  */
1167  for (more = ob2->more; more != NULL; more = more->more) {
1168  if (get_rangevector(ob1, more, &rv1, 0)
1169  && abs(rv1.distance_x) < 2 && abs(rv1.distance_y) < 2)
1170  return 1;
1171  }
1172  return 0;
1173 }
1174 
1197 static int monster_should_cast_spell(object *spell_ob) {
1198  /* The caller is responsible for making sure that *spell_ob is defined. */
1199  assert(spell_ob != NULL);
1200 
1201  switch (spell_ob->subtype) {
1202  case SP_BOLT:
1203  case SP_BULLET:
1204  case SP_EXPLOSION:
1205  case SP_CONE:
1206  case SP_BOMB:
1207  case SP_SMITE:
1208  case SP_MAGIC_MISSILE:
1209  case SP_SUMMON_GOLEM:
1210  case SP_MAGIC_WALL:
1211  case SP_SUMMON_MONSTER:
1212  case SP_MOVING_BALL:
1213  case SP_SWARM:
1214  case SP_INVISIBLE:
1215  case SP_AURA:
1216  return 1;
1217  }
1218 
1219  return 0;
1220 }
1221 
1223 #define MAX_KNOWN_SPELLS 20
1224 
1240 static object *monster_choose_random_spell(object *monster) {
1241  object *altern[MAX_KNOWN_SPELLS];
1242  int i = 0;
1243 
1244  FOR_INV_PREPARE(monster, tmp)
1245  if (tmp->type == SPELLBOOK || tmp->type == SPELL) {
1246  /* Check and see if it's actually a useful spell.
1247  * If its a spellbook, the spell is actually the inventory item.
1248  * if it is a spell, then it is just the object itself.
1249  */
1250  if (monster_should_cast_spell(tmp->type == SPELLBOOK ? tmp->inv : tmp)) {
1251  altern[i++] = tmp;
1252  if (i == MAX_KNOWN_SPELLS)
1253  break;
1254  }
1255  }
1256  FOR_INV_FINISH();
1257  if (!i)
1258  return NULL;
1259  return altern[RANDOM()%i];
1260 }
1261 
1278 static int monster_cast_spell(object *head, object *part, object *pl, int dir) {
1279  object *spell_item;
1280  object *owner;
1281  rv_vector rv1;
1282 
1283  /* If you want monsters to cast spells over friends, this spell should
1284  * be removed. It probably should be in most cases, since monsters still
1285  * don't care about residual effects (ie, casting a cone which may have a
1286  * clear path to the player, the side aspects of the code will still hit
1287  * other monsters)
1288  */
1289  dir = path_to_player(part, pl, 0);
1290  if (dir == 0)
1291  return 0;
1292 
1293  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1294  owner = object_get_owner(head);
1295  if (owner != NULL) {
1296  if (get_rangevector(head, owner, &rv1, 0x1)
1297  && dirdiff(dir, rv1.direction) < 2) {
1298  return 0; /* Might hit owner with spell */
1299  }
1300  }
1301  }
1302 
1303  if (QUERY_FLAG(head, FLAG_CONFUSED))
1304  dir = get_randomized_dir(dir);
1305 
1306  /* If the monster hasn't already chosen a spell, choose one
1307  * I'm not sure if it really make sense to pre-select spells (events
1308  * could be different by the time the monster goes again).
1309  */
1310  if (head->spellitem == NULL) {
1311  spell_item = monster_choose_random_spell(head);
1312  if (spell_item == NULL) {
1313  LOG(llevMonster, "Turned off spells in %s\n", head->name);
1314  CLEAR_FLAG(head, FLAG_CAST_SPELL); /* Will be turned on when picking up book */
1315  return 0;
1316  }
1317  if (spell_item->type == SPELLBOOK) {
1318  if (!spell_item->inv) {
1319  LOG(llevError, "spellbook %s does not contain a spell?\n", spell_item->name);
1320  return 0;
1321  }
1322  spell_item = spell_item->inv;
1323  }
1324  } else
1325  spell_item = head->spellitem;
1326 
1327  if (!spell_item)
1328  return 0;
1329 
1330  /* Best guess this is a defensive/healing spell */
1331  if (spell_item->range <= 1 || spell_item->stats.dam < 0)
1332  dir = 0;
1333 
1334  /* Monster doesn't have enough spell-points */
1335  /* As of 2023, monsters do not possess grace points, and so will use sp for prayers too. */
1336  if (head->stats.sp < SP_level_spellpoint_cost(head, spell_item, SPELL_MANA))
1337  return 0;
1338 
1339  if (head->stats.sp < SP_level_spellpoint_cost(head, spell_item, SPELL_GRACE))
1340  return 0;
1341 
1342  head->stats.sp -= SP_level_spellpoint_cost(head, spell_item, SPELL_MANA);
1343  head->stats.sp -= SP_level_spellpoint_cost(head, spell_item, SPELL_GRACE);
1344 
1345  /* set this to null, so next time monster will choose something different */
1346  head->spellitem = NULL;
1347 
1348  return cast_spell(part, part, dir, spell_item, NULL);
1349 }
1350 
1365 static int monster_use_scroll(object *head, object *part, object *pl, int dir) {
1366  object *scroll;
1367  object *owner;
1368  rv_vector rv1;
1369 
1370  /* If you want monsters to cast spells over friends, this spell should
1371  * be removed. It probably should be in most cases, since monsters still
1372  * don't care about residual effects (ie, casting a cone which may have a
1373  * clear path to the player, the side aspects of the code will still hit
1374  * other monsters)
1375  */
1376  dir = path_to_player(part, pl, 0);
1377  if (dir == 0)
1378  return 0;
1379 
1380  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1381  owner = object_get_owner(head);
1382  if (owner != NULL) {
1383  if (get_rangevector(head, owner, &rv1, 0x1)
1384  && dirdiff(dir, rv1.direction) < 2) {
1385  return 0; /* Might hit owner with spell */
1386  }
1387  }
1388  }
1389 
1390  if (QUERY_FLAG(head, FLAG_CONFUSED))
1391  dir = get_randomized_dir(dir);
1392 
1393  scroll = NULL;
1394  FOR_INV_PREPARE(head, tmp)
1395  if (tmp->type == SCROLL && monster_should_cast_spell(tmp->inv)) {
1396  scroll = tmp;
1397  break;
1398  }
1399  FOR_INV_FINISH();
1400 
1401  /* Used up all his scrolls, so nothing do to */
1402  if (!scroll) {
1404  return 0;
1405  }
1406 
1407  /* Spell should be cast on caster (ie, heal, strength) */
1408  if (scroll->inv->range == 0)
1409  dir = 0;
1410 
1411  /* Face the direction that we want to cast. */
1412  head->direction = dir;
1413  head->facing = head->direction;
1414  if (head->animation)
1415  animate_object(head, head->direction);
1416 
1417  apply_manual(part, scroll, 0);
1418  return 1;
1419 }
1420 
1449 static int monster_use_skill(object *head, object *part, object *pl, int dir) {
1450  object *owner;
1451  int found;
1452 
1453  dir = path_to_player(part, pl, 0);
1454  if (dir == 0)
1455  return 0;
1456 
1457  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1458  owner = object_get_owner(head);
1459  if (owner != NULL) {
1460  rv_vector rv;
1461 
1462  if (get_rangevector(head, owner, &rv, 0) && dirdiff(dir, rv.direction) < 1)
1463  return 0; /* Might hit owner with skill -thrown rocks for example ?*/
1464  }
1465  }
1466  if (QUERY_FLAG(head, FLAG_CONFUSED))
1467  dir = get_randomized_dir(dir);
1468 
1469  /* skill selection - monster will use the next unused skill.
1470  * well...the following scenario will allow the monster to
1471  * toggle between 2 skills. One day it would be nice to make
1472  * more skills available to monsters.
1473  */
1474  found = 0;
1475  FOR_INV_PREPARE(head, skill)
1476  if (skill->type == SKILL && skill != head->chosen_skill) {
1477  head->chosen_skill = skill;
1478  found = 1;
1479  break;
1480  }
1481  FOR_INV_FINISH();
1482 
1483  if (!found && !head->chosen_skill) {
1484  LOG(llevDebug, "Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", head->name, head->count);
1486  return 0;
1487  }
1488  /* use skill */
1489  return do_skill(head, part, head->chosen_skill, dir, NULL);
1490 }
1491 
1506 static int monster_use_range(object *head, object *part, object *pl, int dir) {
1507  object *owner;
1508  int at_least_one = 0;
1509 
1510  dir = path_to_player(part, pl, 0);
1511  if (dir == 0)
1512  return 0;
1513 
1514  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1515  owner = object_get_owner(head);
1516  if (owner != NULL) {
1517  rv_vector rv;
1518 
1519  if (get_rangevector(head, owner, &rv, 0) && dirdiff(dir, rv.direction) < 2)
1520  return 0; /* Might hit owner with spell */
1521  }
1522  }
1523  if (QUERY_FLAG(head, FLAG_CONFUSED))
1524  dir = get_randomized_dir(dir);
1525 
1526  FOR_INV_PREPARE(head, wand) {
1527  if (wand->type == WAND) {
1528  /* Found a wand, let's see if it has charges left */
1529  at_least_one = 1;
1530  if (wand->stats.food <= 0)
1531  continue;
1532 
1533  cast_spell(head, wand, dir, wand->inv, NULL);
1534  drain_wand_charge(wand);
1535 
1536  /* Success */
1537  return 1;
1538  }
1539 
1540  if (wand->type == ROD && wand->inv) {
1541  /* Found rod/horn, let's use it if possible */
1542  at_least_one = 1;
1543  if (wand->stats.hp < MAX(wand->inv->stats.sp, wand->inv->stats.grace))
1544  continue;
1545 
1546  /* drain charge before casting spell - can be a case where the
1547  * spell destroys the monster, and rod, so if done after, results
1548  * in crash.
1549  */
1550  drain_rod_charge(wand);
1551  cast_spell(head, wand, dir, wand->inv, NULL);
1552 
1553  /* Success */
1554  return 1;
1555  }
1556  } FOR_INV_FINISH();
1557 
1558  if (at_least_one)
1559  return 0;
1560 
1561  LOG(llevError, "Error: Monster %s (%d) HAS_READY_RANG() without wand/horn/rod.\n", head->name, head->count);
1563  return 0;
1564 }
1565 
1582 static int monster_use_bow(object *head, object *part, object *pl, int dir) {
1583  object *owner;
1584  rv_vector rv;
1585  int16_t x, y;
1586  mapstruct *map;
1587 
1588  if (!get_rangevector(part, pl, &rv, 1))
1589  return 0;
1590  if (rv.distance > 100)
1591  /* Too far */
1592  return 0;
1593  if (rv.distance_x != 0 && rv.distance_y != 0 && abs(rv.distance_x) != abs(rv.distance_y))
1594  /* Player must be on same horizontal, vertical or diagonal line. */
1595  return 0;
1596  dir = rv.direction;
1597 
1598  if (QUERY_FLAG(head, FLAG_FRIENDLY))
1599  owner = object_get_owner(head);
1600  else
1601  owner = NULL;
1602 
1603  /* The monster can possibly fire, let's see if the path is ok for an arrow. */
1604  x = part->x;
1605  y = part->y;
1606  map = part->map;
1607  while (x != pl->x || y != pl->y || map != pl->map) {
1608  x += freearr_x[dir];
1609  y += freearr_y[dir];
1610  map = get_map_from_coord(map, &x, &y);
1611  if (!map) {
1612  LOG(llevError, "monster_use_bow: no map but still path exists??\n");
1613  return 0;
1614  }
1615  if ((GET_MAP_MOVE_BLOCK(map, x, y)&MOVE_FLY_LOW) == MOVE_FLY_LOW)
1616  return 0;
1617  if (owner && owner->x == x && owner->y == y && owner->map == map)
1618  /* Don't hit owner! */
1619  return 0;
1620  }
1621 
1622  /* Finally, path is clear, can fire. */
1623 
1624  if (QUERY_FLAG(head, FLAG_CONFUSED))
1625  dir = get_randomized_dir(dir);
1626 
1627  /* in server/player.c */
1628  return fire_bow(head, NULL, dir, 0, part->x, part->y);
1629 }
1630 
1639 static int monster_get_weapon_quality(const object *item) {
1640  int val;
1641  int i;
1642 
1643  val = item->stats.dam;
1644  val += item->magic*3;
1645  /* Monsters don't really get benefits from things like regen rates
1646  * from items. But the bonus for their stats are very important.
1647  */
1648  for (i = 0; i < NUM_STATS; i++)
1649  val += get_attr_value(&item->stats, i)*2;
1650  return val;
1651 }
1652 
1665 static int monster_check_good_weapon(object *who, object *item) {
1666  object *other_weap;
1667  int val;
1668 
1669  other_weap = object_find_by_type_applied(who, item->type);
1670  if (other_weap == NULL) /* No other weapons */
1671  return 1;
1672 
1673  /* Rather than go through and apply the new one, and see if it is
1674  * better, just do some simple checks
1675  * Put some multipliers for things that hvae several effects,
1676  * eg, magic affects both damage and wc, so it has more weight
1677  */
1678 
1680  return val > 0;
1681 }
1682 
1691 static int monster_get_armour_quality(const object *item) {
1692  int val;
1693 
1694  val = item->stats.ac;
1695  val += item->resist[ATNR_PHYSICAL]/5;
1696  val += item->magic*3;
1697  return val;
1698 }
1699 
1712 static int monster_check_good_armour(object *who, object *item) {
1713  object *other_armour;
1714  int val, i;
1715 
1716  other_armour = object_find_by_type_applied(who, item->type);
1717  if (other_armour == NULL) /* No other armour, use the new */
1718  return 1;
1719 
1720  val = monster_get_armour_quality(item)-monster_get_armour_quality(other_armour);
1721 
1722  /* for the other protections, do weigh them very much in the equation -
1723  * it is the armor protection which is most important, because there is
1724  * no good way to know what the player may attack the monster with.
1725  * So if the new item has better protection than the old, give that higher
1726  * value. If the reverse, then decrease the value of this item some.
1727  */
1728  for (i = 1; i < NROFATTACKS; i++) {
1729  if (item->resist[i] > other_armour->resist[i])
1730  val++;
1731  else if (item->resist[i] < other_armour->resist[i])
1732  val--;
1733  }
1734 
1735  /* Very few armours have stats, so not much need to worry about those. */
1736 
1737  return val > 0;
1738 }
1739 
1747 static void monster_check_apply(object *mon, object *item) {
1748  int flag = 0;
1749 
1750  if (item->type == SPELLBOOK
1751  && mon->arch != NULL
1752  && (QUERY_FLAG(&mon->arch->clone, FLAG_CAST_SPELL))) {
1753  SET_FLAG(mon, FLAG_CAST_SPELL);
1754  return;
1755  }
1756 
1757  /* If for some reason, this item is already applied, no more work to do */
1758  if (QUERY_FLAG(item, FLAG_APPLIED))
1759  return;
1760 
1761  /* Might be better not to do this - if the monster can fire a bow,
1762  * it is possible in his wanderings, he will find one to use. In
1763  * which case, it would be nice to have ammo for it.
1764  */
1765  if (QUERY_FLAG(mon, FLAG_USE_BOW) && item->type == ARROW) {
1766  /* Check for the right kind of bow */
1767  object *bow;
1768 
1769  bow = object_find_by_type_and_race(mon, BOW, item->race);
1770  if (bow != NULL) {
1771  SET_FLAG(mon, FLAG_READY_BOW);
1772  LOG(llevMonster, "Found correct bow for arrows.\n");
1773  return; /* nothing more to do for arrows */
1774  }
1775  }
1776 
1777  if (item->type == TREASURE && mon->will_apply&WILL_APPLY_TREASURE)
1778  flag = 1;
1779  /* Eating food gets hp back */
1780  else if (item->type == FOOD && mon->will_apply&WILL_APPLY_FOOD)
1781  flag = 1;
1782  else if (item->type == SCROLL && QUERY_FLAG(mon, FLAG_USE_SCROLL)) {
1783  if (!item->inv)
1784  LOG(llevDebug, "Monster %d having scroll %d with empty inventory!\n", mon->count, item->count);
1785  else if (monster_should_cast_spell(item->inv))
1787  /* Don't use it right now */
1788  return;
1789  } else if (item->type == WEAPON)
1790  flag = monster_check_good_weapon(mon, item);
1791  else if (IS_ARMOR(item) || IS_SHIELD(item))
1792  flag = monster_check_good_armour(mon, item);
1793  /* Should do something more, like make sure this is a better item */
1794  else if (item->type == RING)
1795  flag = 1;
1796  else if (item->type == WAND || item->type == ROD) {
1797  /* We never really 'ready' the wand/rod/horn, because that would mean the
1798  * weapon would get undone.
1799  */
1800  if (!(apply_can_apply_object(mon, item)&CAN_APPLY_NOT_MASK)) {
1801  SET_FLAG(mon, FLAG_READY_RANGE);
1802  SET_FLAG(item, FLAG_APPLIED);
1803  }
1804  return;
1805  } else if (item->type == BOW) {
1806  /* We never really 'ready' the bow, because that would mean the
1807  * weapon would get undone.
1808  */
1809  if (!(apply_can_apply_object(mon, item)&CAN_APPLY_NOT_MASK))
1810  SET_FLAG(mon, FLAG_READY_BOW);
1811  return;
1812  } else if (item->type == SKILL) {
1813  /*
1814  * skills are specials: monsters must have the 'FLAG_READY_SKILL' flag set,
1815  * else they can't use the skill...
1816  * Skills also don't need to get applied, so return now.
1817  */
1818  SET_FLAG(mon, FLAG_READY_SKILL);
1819  return;
1820  }
1821 
1822  /* if we don't match one of the above types, return now.
1823  * apply_can_apply_object() will say that we can apply things like flesh,
1824  * bolts, and whatever else, because it only checks against the
1825  * body_info locations.
1826  */
1827  if (!flag)
1828  return;
1829 
1830  /* Check to see if the monster can use this item. If not, no need
1831  * to do further processing. Note that apply_can_apply_object() already checks
1832  * for the CAN_USE flags.
1833  */
1835  return;
1836 
1837  /* should only be applying this item, not unapplying it.
1838  * also, ignore status of curse so they can take off old armour.
1839  * monsters have some advantages after all.
1840  */
1842  return;
1843 }
1844 
1864 static void monster_check_pickup(object *monster) {
1865  object *part;
1866 
1867  for (part = monster; part != NULL; part = part->more)
1868  FOR_BELOW_PREPARE(part, tmp) {
1869  /* Don't try to pick items that are in the process of being thrown.
1870  * It is fairly likely that an ally threw it past monster to hit player.
1871  * IDEA: Maybe have a dex save to catch player-thrown projectiles?
1872  *
1873  * Neila Hawkins 2020-09-07
1874  */
1875  if (tmp->type != THROWN_OBJ && monster_can_pick(monster, tmp)) {
1876  uint32_t nrof;
1877 
1878  if (tmp->weight > 0) {
1879  int32_t weight_limit;
1880 
1881  weight_limit = get_weight_limit(monster->stats.Str);
1882  if (weight_limit >= monster->weight-monster->carrying)
1883  nrof = (weight_limit-monster->weight-monster->carrying)/tmp->weight;
1884  else
1885  nrof = 0;
1886  } else
1887  nrof = MAX(1, tmp->nrof);
1888  if (nrof >= 1) {
1889  object *tmp2;
1890 
1891  tmp2 = object_split(tmp, MIN(nrof, MAX(1, tmp->nrof)), NULL, 0);
1892  tmp2 = object_insert_in_ob(tmp2, monster);
1893  (void)monster_check_apply(monster, tmp2);
1894  }
1895  }
1896  } FOR_BELOW_FINISH();
1897 }
1898 
1908 static int monster_can_pick(object *monster, object *item) {
1909  int flag = 0;
1910  int i;
1911 
1912  if (!object_can_pick(monster, item))
1913  return 0;
1914 
1915  if (QUERY_FLAG(item, FLAG_UNPAID))
1916  return 0;
1917 
1918  if (monster->pick_up&64) /* All */
1919  flag = 1;
1920 
1921  else {
1922  if (IS_WEAPON(item))
1923  flag = (monster->pick_up&8) || QUERY_FLAG(monster, FLAG_USE_WEAPON);
1924  else if (IS_ARMOR(item))
1925  flag = (monster->pick_up&16) || QUERY_FLAG(monster, FLAG_USE_ARMOUR);
1926  else if (IS_SHIELD(item))
1927  flag = (monster->pick_up&16) || QUERY_FLAG(monster, FLAG_USE_SHIELD);
1928  else switch (item->type) {
1929  case MONEY:
1930  case GEM:
1931  flag = monster->pick_up&2;
1932  break;
1933 
1934  case FOOD:
1935  flag = monster->pick_up&4;
1936  break;
1937 
1938  case SKILL:
1940  break;
1941 
1942  case RING:
1943  flag = QUERY_FLAG(monster, FLAG_USE_RING);
1944  break;
1945 
1946  case WAND:
1947  case ROD:
1949  break;
1950 
1951  case SPELLBOOK:
1952  flag = (monster->arch != NULL && QUERY_FLAG(&monster->arch->clone, FLAG_CAST_SPELL));
1953  break;
1954 
1955  case SCROLL:
1957  break;
1958 
1959  case BOW:
1960  case ARROW:
1961  flag = QUERY_FLAG(monster, FLAG_USE_BOW);
1962  break;
1963  }
1965  flag = (monster->pick_up&8) || QUERY_FLAG(monster, FLAG_USE_WEAPON);
1966  /* Simplistic check - if the monster has a location to equip it, he will
1967  * pick it up. Note that this doesn't handle cases where an item may
1968  * use several locations.
1969  */
1970  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
1971  if (monster->body_info[i] && item->body_info[i]) {
1972  flag = 1;
1973  break;
1974  }
1975  }
1976  }
1977 
1978  if (((!(monster->pick_up&32)) && flag) || ((monster->pick_up&32) && (!flag)))
1979  return 1;
1980  return 0;
1981 }
1982 
1989 static void monster_apply_below(object *monster) {
1990  FOR_BELOW_PREPARE(monster, tmp) {
1991  switch (tmp->type) {
1992  case CF_HANDLE:
1993  case TRIGGER:
1994  if (monster->will_apply&WILL_APPLY_HANDLE)
1995  apply_manual(monster, tmp, 0);
1996  break;
1997 
1998  case TREASURE:
1999  if (monster->will_apply&WILL_APPLY_TREASURE)
2000  apply_manual(monster, tmp, 0);
2001  break;
2002  }
2003  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
2004  break;
2005  } FOR_BELOW_FINISH();
2006 }
2007 
2013  if (!monster->head) {
2014  fix_object(monster); // Needed to correctly fill various body fields.
2015  }
2016  FOR_INV_PREPARE(monster, inv)
2018  FOR_INV_FINISH();
2019 }
2020 
2025 void monster_npc_call_help(object *op) {
2026  const char *value;
2027  int help_radius = 3;
2028 
2029  value = object_get_value(op, "help_radius");
2030  if ( value ) {
2031  int override_help_radius;
2032 
2033  override_help_radius = strtol(value, NULL, 10);
2034  if (override_help_radius >= 0 && override_help_radius < 30)
2035  help_radius = override_help_radius;
2036  else
2037  LOG(llevDebug, "monster_npc_call_help: invalid help_radius %d\n", override_help_radius);
2038  }
2039 
2040  for (int x = -help_radius; x <= help_radius; x++)
2041  for (int y = -help_radius; y <= help_radius; y++) {
2042  mapstruct *m = op->map;
2043  int16_t sx = op->x+x;
2044  int16_t sy = op->y+y;
2045  int mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
2046  /* If nothing alive on this space, no need to search the space. */
2047  if ((mflags&P_OUT_OF_MAP) || !(mflags&P_IS_ALIVE))
2048  continue;
2049 
2050  FOR_MAP_PREPARE(m, sx, sy, npc)
2051  if (QUERY_FLAG(npc, FLAG_ALIVE) && QUERY_FLAG(npc, FLAG_UNAGGRESSIVE)) {
2052  object_set_enemy(npc, op->enemy);
2054  }
2055  FOR_MAP_FINISH();
2056  }
2057 }
2058 
2067 static int monster_dist_att(int dir, object *enemy, object *part, rv_vector *rv) {
2068  if (monster_can_hit(part, enemy, rv))
2069  return dir;
2070  if (rv->distance < 10)
2071  return absdir(dir+4);
2072  else if (rv->distance > 18)
2073  return dir;
2074  return 0;
2075 }
2076 
2086 static int monster_run_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
2087  if ((monster_can_hit(part, enemy, rv) && ob->move_status < 20) || ob->move_status < 20) {
2088  ob->move_status++;
2089  return (dir);
2090  } else if (ob->move_status > 20)
2091  ob->move_status = 0;
2092  return absdir(dir+4);
2093 }
2094 
2101 static int monster_hitrun_att(int dir, object *ob) {
2102  if (ob->move_status++ < 25)
2103  return dir;
2104  else if (ob->move_status < 50)
2105  return absdir(dir+4);
2106  ob->move_status = 0;
2107  return absdir(dir+4);
2108 }
2109 
2119 static int monster_wait_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
2120  int inrange = monster_can_hit(part, enemy, rv);
2121 
2122  if (ob->move_status || inrange)
2123  ob->move_status++;
2124 
2125  if (ob->move_status == 0)
2126  return 0;
2127  else if (ob->move_status < 10)
2128  return dir;
2129  else if (ob->move_status < 15)
2130  return absdir(dir+4);
2131  ob->move_status = 0;
2132  return 0;
2133 }
2134 
2144 static int monster_disthit_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
2145  /* The logic below here looked plain wrong before. Basically, what should
2146  * happen is that if the creatures hp percentage falls below run_away,
2147  * the creature should run away (dir+4)
2148  * I think its wrong for a creature to have a zero maxhp value, but
2149  * at least one map has this set, and whatever the map contains, the
2150  * server should try to be resilant enough to avoid the problem
2151  */
2152  if (ob->stats.maxhp && (ob->stats.hp*100)/ob->stats.maxhp < ob->run_away)
2153  return absdir(dir+4);
2154  return monster_dist_att(dir, enemy, part, rv);
2155 }
2156 
2163 static int monster_wait_att2(int dir, rv_vector *rv) {
2164  if (rv->distance < 9)
2165  return absdir(dir+4);
2166  return 0;
2167 }
2168 
2173 static void monster_circ1_move(object *ob) {
2174  static const int circle [12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 };
2175 
2176  if (++ob->move_status > 11)
2177  ob->move_status = 0;
2178  if (!(move_object(ob, circle[ob->move_status])))
2179  (void)move_object(ob, RANDOM()%8+1);
2180 }
2181 
2186 static void monster_circ2_move(object *ob) {
2187  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 };
2188 
2189  if (++ob->move_status > 19)
2190  ob->move_status = 0;
2191  if (!(move_object(ob, circle[ob->move_status])))
2192  (void)move_object(ob, RANDOM()%8+1);
2193 }
2194 
2199 static void monster_pace_movev(object *ob) {
2200  if (ob->move_status++ > 6)
2201  ob->move_status = 0;
2202  if (ob->move_status < 4)
2203  (void)move_object(ob, 5);
2204  else
2205  (void)move_object(ob, 1);
2206 }
2207 
2212 static void monster_pace_moveh(object *ob) {
2213  if (ob->move_status++ > 6)
2214  ob->move_status = 0;
2215  if (ob->move_status < 4)
2216  (void)move_object(ob, 3);
2217  else
2218  (void)move_object(ob, 7);
2219 }
2220 
2225 static void monster_pace2_movev(object *ob) {
2226  if (ob->move_status++ > 16)
2227  ob->move_status = 0;
2228  if (ob->move_status < 6)
2229  (void)move_object(ob, 5);
2230  else if (ob->move_status < 8)
2231  return;
2232  else if (ob->move_status < 13)
2233  (void)move_object(ob, 1);
2234 }
2235 
2240 static void monster_pace2_moveh(object *ob) {
2241  if (ob->move_status++ > 16)
2242  ob->move_status = 0;
2243  if (ob->move_status < 6)
2244  (void)move_object(ob, 3);
2245  else if (ob->move_status < 8)
2246  return;
2247  else if (ob->move_status < 13)
2248  (void)move_object(ob, 7);
2249 }
2250 
2255 static void monster_rand_move(object *ob) {
2256  int i;
2257 
2258  // change direction when stuck, or 1/8 of the time
2259  if (ob->move_status < 1
2260  || ob->move_status > 8
2261  || !move_object(ob, ob->move_status) || (RANDOM()%9 == 0))
2262  // change direction
2263  for (i = 0; i < 5; i++) {
2264  ob->move_status = RANDOM()%8+1;
2265  if (move_object(ob, ob->move_status))
2266  return;
2267  }
2268 }
2269 
2275 static void shopkeeper_move(object *ob) {
2276  const bool debug = object_value_set(ob, key_shopkeeper_debug);
2277  char buf[MAX_BUF], buf2[MAX_BUF];
2278  const bool on_shop_tile = coords_in_shop(ob->map, ob->x, ob->y);
2279  // count number of visible, pickable items above floor
2280  int nbelow = 0;
2281  int cum_client_type = 0; // for calculating average client_type
2282  FOR_BELOW_PREPARE(ob, tmp) {
2283  if (!LOOK_OBJ(tmp) || QUERY_FLAG(tmp, FLAG_NO_PICK))
2284  continue;
2285  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
2286  break;
2287  if (QUERY_FLAG(tmp, FLAG_UNPAID) && !QUERY_FLAG(tmp, FLAG_UNIQUE) && !object_value_set(tmp, "price")) {
2288  // Belongs to shop, but we're no longer interested. Liquidate
2289  uint64_t price = price_base(tmp);
2290  if (ob->map->shopmin && price < ob->map->shopmin) {
2291  if (debug) {
2292  query_short_name(tmp, buf, sizeof(buf));
2293  snprintf(buf2, sizeof(buf2), "Liquidating %s (price %lu < shopmin %lu)", buf, price, ob->map->shopmin);
2294  monster_npc_say(ob, buf2);
2295  }
2296  object_remove(tmp);
2297  object_free(tmp, 0);
2298  continue;
2299  }
2300  }
2301  cum_client_type += tmp->client_type;
2302  nbelow++;
2303  } FOR_BELOW_FINISH();
2304 
2305  // Update running average
2306  float newavg = 0;
2307  if (on_shop_tile) {
2308  const char *curr = object_get_value(ob, key_shopkeeper_pilesize);
2309  float last = 1; // initial average pile size guess, if not set
2310  if (curr != NULL) {
2311  sscanf(curr, "%f", &last);
2312  }
2313  const float alpha = 1.0/50; // 1/(number of tiles to average over)
2314  newavg = alpha*nbelow + (1-alpha)*last;
2315  snprintf(buf, sizeof(buf), "%f", newavg);
2317  }
2318 
2319  if (debug) {
2320  snprintf(buf2, sizeof(buf2), "%d items below, shop avg %.1f", nbelow, newavg);
2321  monster_npc_say(ob, buf2);
2322  }
2323 
2324  // Keep shop tiles average or below and clear walkways
2325  const int want_pile = on_shop_tile ? MAX(1, newavg) : 0;
2326  if (nbelow > want_pile) {
2327  // pick up until the pile is smaller
2328  int npicked = 0;
2329  FOR_BELOW_PREPARE(ob, tmp) {
2330  if (!LOOK_OBJ(tmp) || QUERY_FLAG(tmp, FLAG_NO_PICK))
2331  continue;
2332  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
2333  break;
2334  if (pick_up(ob, tmp)) {
2335  npicked++;
2336  if (nbelow - npicked <= want_pile)
2337  break;
2338  }
2339  } FOR_BELOW_FINISH();
2340 
2341  if (debug) {
2342  snprintf(buf2, sizeof(buf2), "picked up %d items", npicked);
2343  monster_npc_say(ob, buf2);
2344  }
2345  } else if (on_shop_tile) {
2346  // Drop stuff on shop tiles
2347  int ndropped = 0;
2348  FOR_INV_PREPARE(ob, tmp) {
2349  // Skip our own spells, skills, etc.
2350  if (!LOOK_OBJ(tmp))
2351  continue;
2352 
2353  // Try to drop similar items based on client_type
2354  int dtype = 0;
2355  if (nbelow > 0)
2356  dtype = abs(tmp->client_type - cum_client_type/nbelow);
2357  dtype = MAX(1, dtype); // no divide by zero
2358  if (chance(50, dtype)) {
2359  drop(ob, tmp);
2360  ndropped++;
2361  if (nbelow + ndropped >= want_pile)
2362  break;
2363  }
2364  } FOR_INV_FINISH();
2365 
2366  if (debug) {
2367  snprintf(buf2, sizeof(buf2), "dropped %d items", ndropped);
2368  monster_npc_say(ob, buf2);
2369  }
2370  }
2371 
2372  monster_rand_move(ob);
2373 }
2374 
2382 void monster_check_earthwalls(object *op, mapstruct *m, int x, int y) {
2383  FOR_MAP_PREPARE(m, x, y, tmp)
2384  if (tmp->type == EARTHWALL) {
2385  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
2386  return;
2387  }
2388  FOR_MAP_FINISH();
2389 }
2390 
2398 void monster_check_doors(object *op, mapstruct *m, int x, int y) {
2399  FOR_MAP_PREPARE(m, x, y, tmp)
2400  if (tmp->type == DOOR) {
2401  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
2402  return;
2403  }
2404  FOR_MAP_FINISH();
2405 }
2406 
2412 void monster_do_say(const mapstruct *map, const char *message) {
2414  message);
2415 }
2416 
2423 static StringBuffer *monster_format_say(const object* npc, const char *message) {
2424  char name[MAX_BUF];
2425  StringBuffer *buf;
2426 
2427  query_name(npc, name, sizeof(name));
2428  buf = stringbuffer_new();
2429  stringbuffer_append_printf(buf, "%s says: %s", name, message);
2430  return buf;
2431 }
2432 
2439  switch (rt) {
2440  case rt_say:
2441  return "say";
2442  case rt_reply:
2443  return "reply";
2444  case rt_question:
2445  return "ask";
2446  }
2447  assert(0);
2448  return NULL;
2449 }
2450 
2456 static const char *get_reply_text_other(reply_type rt) {
2457  switch (rt) {
2458  case rt_say:
2459  return "says";
2460  case rt_reply:
2461  return "replies";
2462  case rt_question:
2463  return "asks";
2464  }
2465  assert(0);
2466  return NULL;
2467 }
2468 
2494 void monster_communicate(object *op, const char *txt) {
2495  int i, mflags;
2496  int16_t x, y;
2497  mapstruct *mp, *orig_map = op->map;
2498  char own[MAX_BUF], others[MAX_BUF];
2499  talk_info info;
2500 
2501  info.text = txt;
2502  info.message = NULL;
2503  info.replies_count = 0;
2504  info.who = op;
2505  info.npc_msg_count = 0;
2506 
2507  /* Note that this loop looks pretty inefficient to me - we look and try to talk
2508  * to every object within 2 spaces. It would seem that if we trim this down to
2509  * only try to talk to objects with npc->msg set, things would be a lot more efficient,
2510  * but I'm not sure if there are any objects out there that don't have a message and instead
2511  * rely sorely on events - MSW 2009-04-14
2512  */
2513  for (i = 0; i <= SIZEOFFREE2; i++) {
2514  mp = op->map;
2515  x = op->x+freearr_x[i];
2516  y = op->y+freearr_y[i];
2517 
2518  mflags = get_map_flags(mp, &mp, x, y, &x, &y);
2519  if (mflags&P_OUT_OF_MAP)
2520  continue;
2521 
2522  FOR_MAP_PREPARE(mp, x, y, npc) {
2523  monster_talk_to_npc(npc, &info);
2524  if (orig_map != op->map) {
2525  LOG(llevDebug, "Warning: Forced to swap out very recent map\n");
2526  return;
2527  }
2528  } FOR_MAP_FINISH();
2529  }
2530 
2531  /* First, what the player says. */
2532  if (info.message != NULL) {
2533  snprintf(own, sizeof(own), "You %s: %s", get_reply_text_own(info.message_type), info.message);
2534  snprintf(others, sizeof(others), "%s %s: %s", op->name, get_reply_text_other(info.message_type), info.message);
2535  free_string(info.message);
2536  } else {
2537  snprintf(own, sizeof(own), "You say: %s", txt);
2538  snprintf(others, sizeof(others), "%s says: %s", op->name, txt);
2539  }
2542 
2543  /* Then NPCs can actually talk. */
2544  for (i = 0; i < info.npc_msg_count; i++) {
2545  monster_do_say(orig_map, info.npc_msgs[i]);
2546  free_string(info.npc_msgs[i]);
2547  }
2548 
2549  /* Finally, the replies the player can use. */
2550  if (info.replies_count > 0) {
2552  for (i = 0; i < info.replies_count; i++) {
2554  free_string(info.replies_words[i]);
2555  free_string(info.replies[i]);
2556  }
2557  }
2558 }
2559 
2568 static int monster_do_talk_npc(object *npc, talk_info *info) {
2569  struct_dialog_reply *reply;
2571 
2572  if (!get_dialog_message(npc, info->text, &message, &reply))
2573  return 0;
2574 
2575  if (reply) {
2576  info->message = add_string(reply->message);
2577  info->message_type = reply->type;
2578  }
2579 
2580  if (message->identifies) {
2581  identify(npc);
2582  }
2583 
2584  if (npc->type == MAGIC_EAR) {
2586  use_trigger(npc);
2587  } else {
2588  char value[2];
2589 
2590  if (info->npc_msg_count < MAX_NPC) {
2592  info->npc_msg_count++;
2593  }
2594 
2595  /* mark that the npc was talked to, so it won't move randomly later on */
2596  value[0] = '3' + rand() % 6;
2597  value[1] = '\0';
2598  object_set_value(npc, "talked_to", value, 1);
2599 
2600  reply = message->replies;
2601  while (reply && info->replies_count < MAX_REPLIES) {
2602  info->replies[info->replies_count] = add_string(reply->message);
2603  info->replies_words[info->replies_count] = add_string(reply->reply);
2604  info->replies_count++;
2605  reply = reply->next;
2606  }
2607  }
2608 
2609  return 1;
2610 }
2611 
2617 void monster_npc_say(object *npc, const char *cp) {
2618  char *message;
2619  StringBuffer *buf = monster_format_say(npc, cp);
2620 
2622  monster_do_say(npc->map, message);
2623  free(message);
2624 }
2625 
2634 static int monster_talk_to_npc(object *npc, talk_info *info) {
2635  dialog_preparse(npc);
2636  if (events_execute_object_say(npc, info) != 0)
2637  return 0;
2638 
2639  /* Here we let the objects inside inventories hear and answer, too. */
2640  /* This allows the existence of "intelligent" weapons you can discuss with */
2641  FOR_INV_PREPARE(npc, cobj)
2642  if (events_execute_object_say(cobj, info) != 0)
2643  return 0;
2644  FOR_INV_FINISH();
2645  if (info->who == npc)
2646  return 0;
2647  return monster_do_talk_npc(npc, info);
2648 }
2649 
2662 object *monster_find_throw_ob(object *op) {
2663  /* New throw code: look through the inventory. Grap the first legal is_thrown
2664  * marked item and throw it to the enemy.
2665  */
2666 
2667  FOR_INV_PREPARE(op, tmp) {
2668  /* Can't throw invisible objects or items that are applied */
2669  if (!tmp->invisible && !QUERY_FLAG(tmp, FLAG_APPLIED) && QUERY_FLAG(tmp, FLAG_IS_THROWN)) {
2670 #ifdef DEBUG_THROW
2671  char what[MAX_BUF];
2672 
2673  query_name(tmp, what, MAX_BUF);
2674  LOG(llevDebug, "%s chooses to throw: %s (%d)\n", op->name, what, tmp->count);
2675 #endif
2676  return tmp;
2677  }
2678  } FOR_INV_FINISH();
2679 
2680 #ifdef DEBUG_THROW
2681  LOG(llevDebug, "%s chooses to throw nothing\n", op->name);
2682 #endif
2683  return NULL;
2684 }
2685 
2701 int monster_can_detect_enemy(object *op, object *enemy, rv_vector *rv) {
2702  int radius = MIN_MON_RADIUS, hide_discovery;
2703 
2704  /* null detection for any of these condtions always */
2705  if (!op || !enemy || !op->map || !enemy->map)
2706  return 0;
2707 
2708  /* If the monster (op) has no way to get to the enemy, do nothing */
2709  if (!get_rangevector(op, enemy, rv, 0))
2710  return 0;
2711 
2712  /* Monsters always ignore the DM */
2713  if (op->type != PLAYER && QUERY_FLAG(enemy, FLAG_WIZ))
2714  return 0;
2715 
2716  /* simple check. Should probably put some range checks in here. */
2717  if (monster_can_see_enemy(op, enemy))
2718  return 1;
2719 
2720  /* The rest of this is for monsters. Players are on their own for
2721  * finding enemies!
2722  */
2723  if (op->type == PLAYER)
2724  return 0;
2725 
2726  /* Quality invisible? Bah, we wont see them w/o SEE_INVISIBLE
2727  * flag (which was already checked) in can_see_enmy (). Lets get out of here
2728  */
2729  if (enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden)))
2730  return 0;
2731 
2732  /* use this for invis also */
2733  hide_discovery = op->stats.Int/5;
2734 
2735  /* Determine Detection radii */
2736  if (!enemy->hide) /* to detect non-hidden (eg dark/invis enemy) */
2737  radius = MAX(op->stats.Wis/5+1, MIN_MON_RADIUS);
2738  else { /* a level/INT/Dex adjustment for hiding */
2739  object *sk_hide;
2740  int bonus = (op->level/2)+(op->stats.Int/5);
2741 
2742  if (enemy->type == PLAYER) {
2743  sk_hide = find_skill_by_number(enemy, SK_HIDING);
2744  if (sk_hide != NULL)
2745  bonus -= sk_hide->level;
2746  else {
2747  LOG(llevError, "monster_can_detect_enemy() got hidden player w/o hiding skill!\n");
2748  make_visible(enemy);
2749  radius = MAX(radius, MIN_MON_RADIUS);
2750  }
2751  } else /* enemy is not a player */
2752  bonus -= enemy->level;
2753 
2754  radius += bonus/5;
2755  hide_discovery += bonus*5;
2756  } /* else creature has modifiers for hiding */
2757 
2758  /* Radii stealth adjustment. Only if you are stealthy
2759  * will you be able to sneak up closer to creatures */
2760  if (QUERY_FLAG(enemy, FLAG_STEALTH))
2761  radius = radius/2, hide_discovery = hide_discovery/3;
2762 
2763  /* Radii adjustment for enemy standing in the dark */
2764  if (op->map->darkness > 0 && !monster_stand_in_light(enemy)) {
2765  /* on dark maps body heat can help indicate location with infravision
2766  * undead don't have body heat, so no benefit detecting them.
2767  */
2768  if (QUERY_FLAG(op, FLAG_SEE_IN_DARK) && !is_true_undead(enemy))
2769  radius += op->map->darkness/2;
2770  else
2771  radius -= op->map->darkness/2;
2772 
2773  /* op next to a monster (and not in complete darkness)
2774  * the monster should have a chance to see you.
2775  */
2776  if (radius < MIN_MON_RADIUS && op->map->darkness < 5 && rv->distance <= 1)
2777  radius = MIN_MON_RADIUS;
2778  } /* if on dark map */
2779 
2780  /* Lets not worry about monsters that have incredible detection
2781  * radii, we only need to worry here about things the player can
2782  * (potentially) see. This is 13, as that is the maximum size the player
2783  * may have for their map - in that way, creatures at the edge will
2784  * do something. Note that the distance field in the
2785  * vector is real distance, so in theory this should be 18 to
2786  * find that.
2787  */
2788  if (radius > 13)
2789  radius = 13;
2790 
2791  /* Enemy in range! Now test for detection */
2792  if ((int)rv->distance <= radius) {
2793  /* ah, we are within range, detected? take cases */
2794  if (!enemy->invisible) /* enemy in dark squares... are seen! */
2795  return 1;
2796 
2797  /* hidden or low-quality invisible */
2798  if (enemy->hide && rv->distance <= 1 && RANDOM()%100 <= (unsigned int)hide_discovery) {
2799  make_visible(enemy);
2800  /* inform players of new status */
2801  if (enemy->type == PLAYER && player_can_view(enemy, op))
2803  "You are discovered by %s!",
2804  op->name);
2805  return 1; /* detected enemy */
2806  } else if (enemy->invisible) {
2807  /* Change this around - instead of negating the invisible, just
2808  * return true so that the mosnter that managed to detect you can
2809  * do something to you. Decreasing the duration of invisible
2810  * doesn't make a lot of sense IMO, as a bunch of stupid creatures
2811  * can then basically negate the spell. The spell isn't negated -
2812  * they just know where you are!
2813  */
2814  if (RANDOM()%50 <= (unsigned int)hide_discovery) {
2815  if (enemy->type == PLAYER) {
2816  char name[MAX_BUF];
2817 
2818  query_name(op, name, MAX_BUF);
2820  "You see %s noticing your position.",
2821  name);
2822  }
2823  return 1;
2824  }
2825  }
2826  } /* within range */
2827 
2828  /* Wasn't detected above, so still hidden */
2829  return 0;
2830 }
2831 
2841 static int monster_stand_in_light_internal(object *op) {
2842  if (!op)
2843  return 0;
2844  if (op->glow_radius > 0)
2845  return 1;
2846 
2847  if (op->map) {
2848  return map_light_on(op->map, op->x, op->y);
2849  }
2850  return 0;
2851 }
2852 
2856 int monster_stand_in_light(object *op) {
2857  if (!op)
2858  return 0;
2859 
2860  if (op->light_cached_time == pticks)
2861  return op->light_cached;
2862 
2863  int val = monster_stand_in_light_internal(op);
2864  op->light_cached = val;
2865  op->light_cached_time = pticks;
2866  return val;
2867 }
2868 
2878 int monster_can_see_enemy(object *op, object *enemy) {
2879  object *looker = HEAD(op);
2880 
2881  /* safety */
2882  if (!looker || !enemy || !QUERY_FLAG(looker, FLAG_ALIVE))
2883  return 0;
2884 
2885  /* we dont give a full treatment of xrays here (shorter range than normal,
2886  * see through walls). Should we change the code elsewhere to make you
2887  * blind even if you can xray?
2888  */
2889  if (QUERY_FLAG(looker, FLAG_BLIND) && !QUERY_FLAG(looker, FLAG_XRAYS))
2890  return 0;
2891 
2892  /* checking for invisible things */
2893  if (enemy->invisible) {
2894  /* HIDDEN ENEMY. by definition, you can't see hidden stuff!
2895  * However, if you carry any source of light, then the hidden
2896  * creature is seeable (and stupid) */
2897  if (has_carried_lights(enemy)) {
2898  if (enemy->hide) {
2899  make_visible(enemy);
2901  "Your light reveals your hiding spot!");
2902  }
2903  return 1;
2904  } else if (enemy->hide)
2905  return 0;
2906 
2907  /* Invisible enemy. Break apart the check for invis undead/invis looker
2908  * into more simple checks - the QUERY_FLAG doesn't return 1/0 values,
2909  * and making it a conditional makes the code pretty ugly.
2910  */
2911  if (!QUERY_FLAG(looker, FLAG_SEE_INVISIBLE)) {
2912  if (makes_invisible_to(enemy, looker))
2913  return 0;
2914  }
2915  } else if (looker->type == PLAYER) /* for players, a (possible) shortcut */
2916  if (player_can_view(looker, enemy))
2917  return 1;
2918 
2919  /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen
2920  * unless they carry a light or stand in light. Darkness doesnt
2921  * inhibit the undead per se (but we should give their archs
2922  * CAN_SEE_IN_DARK, this is just a safety
2923  * we care about the enemy maps status, not the looker.
2924  * only relevant for tiled maps, but it is possible that the
2925  * enemy is on a bright map and the looker on a dark - in that
2926  * case, the looker can still see the enemy
2927  */
2928  if (enemy->map->darkness > 0
2929  && !monster_stand_in_light(enemy)
2930  && (!QUERY_FLAG(looker, FLAG_SEE_IN_DARK) || !is_true_undead(looker) || !QUERY_FLAG(looker, FLAG_XRAYS)))
2931  return 0;
2932 
2933  return 1;
2934 }
object_value_set
bool object_value_set(const object *op, const char *const key)
Determine if an extra value is set.
Definition: object.cpp:4361
FLAG_USE_BOW
#define FLAG_USE_BOW
(Monster) can apply and fire bows
Definition: define.h:293
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Gets the bottom object on a map.
Definition: map.h:170
do_skill
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:431
TRIGGER
@ TRIGGER
Definition: object.h:134
PLAYER
@ PLAYER
Definition: object.h:112
object::light_cached
int light_cached
Definition: object.h:454
object_get_owner
object * object_get_owner(object *op)
Returns the object which this object marks as being the owner.
Definition: object.cpp:789
path_to_player
int path_to_player(object *mon, object *pl, unsigned mindiff)
Returns the direction to the player, if valid.
Definition: player.cpp:659
monster_pace2_movev
static void monster_pace2_movev(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2225
SP_MAGIC_MISSILE
#define SP_MAGIC_MISSILE
Definition: spells.h:85
monster_check_wakeup
static int monster_check_wakeup(object *op, object *enemy, rv_vector *rv)
Sees if this monster should wake up.
Definition: monster.cpp:337
global.h
FLAG_NEUTRAL
#define FLAG_NEUTRAL
monster is from type neutral
Definition: define.h:354
estimate_distance
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
object_find_by_type_subtype
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Find object in inventory.
Definition: object.cpp:4286
SP_BOLT
#define SP_BOLT
Definition: spells.h:78
CF_HANDLE
@ CF_HANDLE
Definition: object.h:213
object::move_status
int32_t move_status
What stage in attack mode.
Definition: object.h:400
talk_info::replies
sstring replies[MAX_REPLIES]
Description for replies_words.
Definition: dialog.h:57
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:724
remove_friendly_object
void remove_friendly_object(object *op)
Removes the specified object from the linked list of friendly objects.
Definition: friend.cpp:52
living::maxhp
int16_t maxhp
Max hit points.
Definition: living.h:41
object_find_by_type_applied
object * object_find_by_type_applied(const object *who, int type)
Find applied object in inventory.
Definition: object.cpp:4068
struct_dialog_reply::next
struct struct_dialog_reply * next
Next reply, NULL for last.
Definition: dialog.h:20
NUM_BODY_LOCATIONS
#define NUM_BODY_LOCATIONS
Number of body locations.
Definition: object.h:15
FLAG_STAND_STILL
#define FLAG_STAND_STILL
NPC will not (ever) move.
Definition: define.h:308
FLAG_CONFUSED
#define FLAG_CONFUSED
Will also be unable to cast spells.
Definition: define.h:311
AP_APPLY
#define AP_APPLY
Item is to be applied.
Definition: define.h:568
BOW
@ BOW
Definition: object.h:123
WAITATT
#define WAITATT
Wait for player to approach then hit, move if hit.
Definition: define.h:489
llevError
@ llevError
Error, serious thing.
Definition: logger.h:11
FABS
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
find_skill_by_number
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
SP_BOMB
#define SP_BOMB
Definition: spells.h:82
WAND
@ WAND
Definition: object.h:225
FLAG_USE_RING
#define FLAG_USE_RING
(Monster) can use rings, boots, gauntlets, etc
Definition: define.h:297
LOG
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
ALLRUN
#define ALLRUN
Always run, never attack good for sim.
Definition: define.h:491
talk_info::replies_words
sstring replies_words[MAX_REPLIES]
Available reply words.
Definition: dialog.h:56
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
talk_info::npc_msg_count
int npc_msg_count
How many NPCs reacted to the text being said.
Definition: dialog.h:58
CAN_APPLY_NOT_MASK
#define CAN_APPLY_NOT_MASK
Definition: define.h:626
monster_check_apply_all
void monster_check_apply_all(object *monster)
Calls monster_check_apply() for all inventory objects.
Definition: monster.cpp:2012
FLAG_GENERATOR
#define FLAG_GENERATOR
Will generate type ob->stats.food.
Definition: define.h:248
object::inv
object * inv
Pointer to the first object in the inventory.
Definition: object.h:298
RUNATT
#define RUNATT
Run but attack if player catches up to object.
Definition: define.h:487
MSG_TYPE_SKILL
#define MSG_TYPE_SKILL
Messages related to skill use.
Definition: newclient.h:411
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
mapstruct::shopmin
uint64_t shopmin
Minimum price a shop will trade for.
Definition: map.h:349
monster_stand_in_light_internal
static int monster_stand_in_light_internal(object *op)
Determine if op stands in a lighted square.
Definition: monster.cpp:2841
PACEV2
#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:520
monster_disthit_att
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:2144
pets_should_arena_attack
int pets_should_arena_attack(object *pet, object *owner, object *target)
Determines if checks so pets don't attack players or other pets should be overruled by the arena petm...
Definition: pets.cpp:1099
path_data
Structure to store data so we can use a minheap.
Definition: monster.cpp:421
make_visible
void make_visible(object *op)
Makes an object visible again.
Definition: player.cpp:3974
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
Definition: stringbuffer.cpp:138
WILL_APPLY_HANDLE
#define WILL_APPLY_HANDLE
Apply handles and triggers.
Definition: object.h:54
pick_up
bool pick_up(object *op, object *alt)
Try to pick up an item.
Definition: c_object.cpp:520
FLAG_SEE_IN_DARK
#define FLAG_SEE_IN_DARK
if set ob not effected by darkness
Definition: define.h:337
map_light_on
int map_light_on(mapstruct *m, int x, int y)
Return the light level at position (X, Y) on map M.
Definition: map.cpp:2730
AT_PHYSICAL
#define AT_PHYSICAL
Definition: attack.h:76
object::arch
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
cast_spell
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Main dispatch when someone casts a spell.
Definition: spell_util.cpp:1424
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.cpp:57
object::attack_movement
uint16_t attack_movement
What kind of attack movement.
Definition: object.h:401
absdir
int absdir(int d)
Computes an absolute direction.
Definition: object.cpp:3699
FOR_BELOW_PREPARE
#define FOR_BELOW_PREPARE(op_, it_)
Constructs a loop iterating over all objects below an object.
Definition: define.h:698
object::range
int8_t range
Range of the spell.
Definition: object.h:417
object::speed
float speed
Frequency of object 'moves' relative to server tick rate.
Definition: object.h:337
object_set_enemy
void object_set_enemy(object *op, object *enemy)
Sets the enemy of an object.
Definition: object.cpp:900
GEM
@ GEM
Definition: object.h:172
FLAG_UNIQUE
#define FLAG_UNIQUE
Item is really unique (UNIQUE_ITEMS)
Definition: define.h:287
object::invisible
int16_t invisible
How much longer the object will be invis.
Definition: object.h:370
monster_check_good_weapon
static int monster_check_good_weapon(object *who, object *item)
Checks if using weapon 'item' would be better for 'who'.
Definition: monster.cpp:1665
HITRUN
#define HITRUN
Run to then hit player then run away cyclicly.
Definition: define.h:488
object::x
int16_t x
Definition: object.h:335
player::peaceful
uint32_t peaceful
If set, won't attack friendly creatures.
Definition: player.h:146
monster_check_enemy
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
object::pick_up
uint8_t pick_up
See crossfire.doc.
Definition: object.h:371
object::map
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
WEAPON
@ WEAPON
Definition: object.h:124
monster_run_att
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:2086
MinHeap
In order to adequately path for A* search, we will need a minheap to efficiently handle pathing from ...
Definition: minheap.h:16
monster_check_doors
void monster_check_doors(object *op, mapstruct *m, int x, int y)
Living creature attempts to open a door.
Definition: monster.cpp:2398
SP_CONE
#define SP_CONE
Definition: spells.h:81
mapstruct::height
uint16_t height
Width and height of map.
Definition: map.h:337
FLAG_SEE_INVISIBLE
#define FLAG_SEE_INVISIBLE
Will see invisible player.
Definition: define.h:253
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
monster_check_pickup
static void monster_check_pickup(object *monster)
Checks for items that monster can pick up.
Definition: monster.cpp:1864
MIN
#define MIN(x, y)
Definition: compat.h:21
TREASURE
@ TREASURE
Definition: object.h:115
SKILL
@ SKILL
Also see SKILL_TOOL (74) below.
Definition: object.h:148
object::direction
int8_t direction
Means the object is moving that way.
Definition: object.h:344
monster_check_good_armour
static int monster_check_good_armour(object *who, object *item)
Checks if using armor 'item' would be better for 'who'.
Definition: monster.cpp:1712
object::count
tag_t count
Unique object number for this object.
Definition: object.h:307
FLAG_SCARED
#define FLAG_SCARED
Monster is scared (mb player in future)
Definition: define.h:271
fix_object
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.cpp:1132
FLAG_ONLY_ATTACK
#define FLAG_ONLY_ATTACK
NPC will evaporate if there is no enemy.
Definition: define.h:310
FLAG_READY_SCROLL
#define FLAG_READY_SCROLL
monster has scroll in inv and can use it
Definition: define.h:324
NDI_NAVY
#define NDI_NAVY
Definition: newclient.h:248
RANDO
#define RANDO
The monster will go in a random direction until it is stopped by an obstacle, then it chooses another...
Definition: define.h:514
monster_can_hit
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:1154
llevMonster
@ llevMonster
Many many details.
Definition: logger.h:14
get_nearest_criminal
object * get_nearest_criminal(object *mon)
Definition: player.cpp:591
monster
the faster the spell may be cast there are several other common only the caster may be affected by the spell The most common spell range is that of touch This denotes that the caster much touch the recipient of the spell in order to release the spell monster
Definition: spell-info.txt:45
ATNR_PHYSICAL
#define ATNR_PHYSICAL
Definition: attack.h:49
player::hidden
uint32_t hidden
If True, player (DM) is hidden from view.
Definition: player.h:147
object::enemy
object * enemy
Monster/player to follow even if not closest.
Definition: object.h:391
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
skills.h
rv_vector::part
object * part
Part we found.
Definition: map.h:375
object::hide
uint8_t hide
The object is hidden, not invisible.
Definition: object.h:397
apply_manual
int apply_manual(object *op, object *tmp, int aflag)
Main apply handler.
Definition: apply.cpp:597
FOR_OB_AND_ABOVE_FINISH
#define FOR_OB_AND_ABOVE_FINISH()
Finishes FOR_OB_AND_ABOVE_PREPARE().
Definition: define.h:737
mapstruct::path
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:355
P_IS_ALIVE
#define P_IS_ALIVE
Something alive is on this space.
Definition: map.h:237
FLAG_APPLIED
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:235
object::level
int16_t level
Level of creature or object.
Definition: object.h:361
FLAG_STEALTH
#define FLAG_STEALTH
Will wake monsters with less range.
Definition: define.h:312
pticks
uint32_t pticks
Number of ticks since time reset.
Definition: time.cpp:47
buf
StringBuffer * buf
Definition: readable.cpp:1565
monster_find_enemy
static object * monster_find_enemy(object *npc, rv_vector *rv)
Tries to find an enmy for npc.
Definition: monster.cpp:240
object_insert_in_ob
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::will_apply
uint8_t will_apply
See crossfire.doc and What monsters apply.
Definition: object.h:402
PACEH
#define PACEH
The monster will pace back and forth until attacked.
Definition: define.h:508
MAX
#define MAX(x, y)
Definition: compat.h:24
get_nearest_player
object * get_nearest_player(object *mon)
Finds the nearest visible player or player-friendly for some object.
Definition: player.cpp:548
object::resist
int16_t resist[NROFATTACKS]
Resistance adjustments for attacks.
Definition: object.h:351
FLAG_NO_PICK
#define FLAG_NO_PICK
Object can't be picked up.
Definition: define.h:239
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
mapstruct::width
uint16_t width
Definition: map.h:337
monster_rand_move
static void monster_rand_move(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2255
talk_info::message
sstring message
If not NULL, what the player will be displayed as said.
Definition: dialog.h:53
FLAG_IS_FLOOR
#define FLAG_IS_FLOOR
Can't see what's underneath this object.
Definition: define.h:302
FOR_BELOW_FINISH
#define FOR_BELOW_FINISH()
Finishes FOR_BELOW_PREPARE().
Definition: define.h:705
draw_ext_info
vs only yadda is in because all tags get reset on the next draw_ext_info In the second since it is all in one draw_ext_info
Definition: media-tags.txt:61
talk_info::replies_count
int replies_count
How many items in replies_words and replies.
Definition: dialog.h:55
FLAG_ALIVE
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:230
monster_find_nearest_enemy
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
rv_vector::distance_y
int distance_y
Y delta.
Definition: map.h:373
FOR_OB_AND_ABOVE_PREPARE
#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:733
SP_SUMMON_MONSTER
#define SP_SUMMON_MONSTER
Definition: spells.h:101
LOOK_OBJ
#define LOOK_OBJ(ob)
This returns TRUE if the object is something that should be displayed in the look window.
Definition: object.h:521
monster_wait_att2
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:2163
object::y
int16_t y
Position in the map for this object.
Definition: object.h:335
object_find_by_type_and_race
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
m
static event_registration m
Definition: citylife.cpp:424
rv_vector::distance_x
int distance_x
X delta.
Definition: map.h:372
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.cpp:76
FLAG_NO_ATTACK
#define FLAG_NO_ATTACK
monster don't attack
Definition: define.h:355
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects,...
Definition: object.cpp:1545
object::contr
struct player * contr
Pointer to the player which control this object.
Definition: object.h:284
object::chosen_skill
object * chosen_skill
The skill chosen to use.
Definition: object.h:396
SP_BULLET
#define SP_BULLET
Definition: spells.h:79
key_shopkeeper_pilesize
const char * key_shopkeeper_pilesize
Definition: monster.cpp:63
object::last_heal
int32_t last_heal
Last healed.
Definition: object.h:367
pets_get_enemy
object * pets_get_enemy(object *pet, rv_vector *rv)
Given that 'pet' is a friendly object, this function returns a monster the pet should attack,...
Definition: pets.cpp:54
object::subtype
uint8_t subtype
Subtype of object.
Definition: object.h:349
add_refcount
sstring add_refcount(sstring str)
This will increase the refcount of the string str.
Definition: shstr.cpp:210
minheap.h
freearr_y
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.cpp:305
monster_wait_att
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:2119
drop
void drop(object *op, object *tmp)
Drop an item, either on the floor or in a container.
Definition: c_object.cpp:1170
struct_dialog_reply::message
char * message
What the player will actually say for this reply.
Definition: dialog.h:18
monster_get_armour_quality
static int monster_get_armour_quality(const object *item)
Returns the "quality" value of an armour of a monster.
Definition: monster.cpp:1691
query_name
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.cpp:594
FLAG_USE_RANGE
#define FLAG_USE_RANGE
(Monster) can apply and use range items
Definition: define.h:292
FLAG_RUN_AWAY
#define FLAG_RUN_AWAY
Object runs away from nearest player \ but can still attack at a distance.
Definition: define.h:280
can_see_monsterP
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
monster_get_weapon_quality
static int monster_get_weapon_quality(const object *item)
Returns the "quality" value of a weapon of a monster.
Definition: monster.cpp:1639
MOVE_WALK
#define MOVE_WALK
Object walks.
Definition: define.h:392
stringbuffer_finish_shared
sstring stringbuffer_finish_shared(StringBuffer *sb)
Deallocate the string buffer instance and return the string as a shared string.
Definition: stringbuffer.cpp:85
archetype::clone
object clone
An object from which to do object_copy()
Definition: object.h:487
object::run_away
uint8_t run_away
Monster runs away if it's hp goes below this percentage.
Definition: object.h:394
monster_can_see_enemy
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:2878
price_base
uint64_t price_base(const object *obj)
Price an item based on its value or archetype value, type, identification/BUC status,...
Definition: item.cpp:1510
add_string
sstring add_string(const char *str)
This will add 'str' to the hash table.
Definition: shstr.cpp:124
monster_apply_below
static void monster_apply_below(object *monster)
If a monster who's eager to apply things encounters something apply-able, then make him apply it.
Definition: monster.cpp:1989
HEAD
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:607
ROD
@ ROD
Definition: object.h:114
dialog_preparse
void dialog_preparse(object *op)
Definition: dialog.cpp:110
object::move_type
MoveType move_type
Type of movement this object uses.
Definition: object.h:436
NDI_DELAYED
#define NDI_DELAYED
If set, then message is sent only after the player's tick completes.
Definition: newclient.h:273
query_short_name
void query_short_name(const object *op, char *buf, size_t size)
query_short_name(object) is similar to query_name(), but doesn't contain any information about object...
Definition: item.cpp:518
ext_info_map
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
FLAG_FREED
#define FLAG_FREED
Object is in the list of free objects.
Definition: define.h:233
path_measure_func
int path_measure_func(const void *ob)
Function to retrieve the measurement the minheap will organize by.
Definition: monster.cpp:439
FLAG_BLIND
#define FLAG_BLIND
If set, object cannot see (visually)
Definition: define.h:336
SPELL_GRACE
#define SPELL_GRACE
Definition: spells.h:59
object::face
const Face * face
Face with colors.
Definition: object.h:341
path_data::movement_penalty
int16_t movement_penalty
Definition: monster.cpp:427
AP_IGNORE_CURSE
#define AP_IGNORE_CURSE
Apply/unapply regardless of cursed/damned status.
Definition: define.h:576
monster_circ2_move
static void monster_circ2_move(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2186
path_data::x
int16_t x
Definition: monster.cpp:422
has_carried_lights
int has_carried_lights(const object *op)
Checks if op has a light source.
Definition: los.cpp:346
MIN_MON_RADIUS
#define MIN_MON_RADIUS
Minimum monster detection radius.
Definition: monster.cpp:58
struct_dialog_reply
One reply a NPC can expect.
Definition: dialog.h:16
monster_pace2_moveh
static void monster_pace2_moveh(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2240
MAX_NPC
#define MAX_NPC
How many NPCs maximum will reply to the player.
Definition: dialog.h:45
CIRCLE2
#define CIRCLE2
Same as CIRCLE1 but a larger circle is used.
Definition: define.h:507
player::tmp_invis
uint32_t tmp_invis
Will invis go away when we attack?
Definition: player.h:140
object::type
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
message
TIPS on SURVIVING Crossfire is populated with a wealth of different monsters These monsters can have varying immunities and attack types In some of them can be quite a bit smarter than others It will be important for new players to learn the abilities of different monsters and learn just how much it will take to kill them This section discusses how monsters can interact with players Most monsters in the game are out to mindlessly kill and destroy the players These monsters will help boost a player s after he kills them When fighting a large amount of monsters in a single attempt to find a narrower hallway so that you are not being attacked from all sides Charging into a room full of Beholders for instance would not be open the door and fight them one at a time For there are several maps designed for them Find these areas and clear them out All throughout these a player can find signs and books which they can read by stepping onto them and hitting A to apply the book sign These messages will help the player to learn the system One more always keep an eye on your food If your food drops to your character will soon so BE CAREFUL ! NPCs Non Player Character are special monsters which have intelligence Players may be able to interact with these monsters to help solve puzzles and find items of interest To speak with a monster you suspect to be a simply move to an adjacent square to them and push the double ie Enter your message
Definition: survival-guide.txt:34
monster_pace_moveh
static void monster_pace_moveh(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2212
SP_SMITE
#define SP_SMITE
Definition: spells.h:84
living::dam
int16_t dam
How much damage this object does when hitting.
Definition: living.h:46
object::magic
int8_t magic
Any magical bonuses to this item.
Definition: object.h:358
key_shopkeeper_debug
const char * key_shopkeeper_debug
Definition: monster.cpp:62
FLAG_PARALYZED
#define FLAG_PARALYZED
Monster or player is paralyzed.
Definition: define.h:371
FLAG_USE_SHIELD
#define FLAG_USE_SHIELD
Can this creature use a shield?
Definition: define.h:237
object_free
void object_free(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects,...
Definition: object.cpp:1577
rt_say
@ rt_say
Basic sentence.
Definition: dialog.h:8
GET_MAP_MOVE_BLOCK
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Gets the blocking state of a square.
Definition: map.h:192
FOR_INV_FINISH
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:671
is_enemy
static int is_enemy(object *who, object *owner)
Determine if an object can be considered an enemy.
Definition: monster.cpp:150
GOLEM
@ GOLEM
Definition: object.h:150
apply_can_apply_object
int apply_can_apply_object(const object *who, const object *op)
Checks to see if 'who' can apply object 'op'.
Definition: apply.cpp:1016
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Monster doesn't attack players.
Definition: define.h:272
monster_choose_random_spell
static object * monster_choose_random_spell(object *monster)
Selects a spell to cast for a monster.
Definition: monster.cpp:1240
FLAG_USE_WEAPON
#define FLAG_USE_WEAPON
(Monster) can wield weapons
Definition: define.h:296
sproto.h
ARROW
@ ARROW
Definition: object.h:122
IS_SHIELD
#define IS_SHIELD(op)
Definition: define.h:170
living::sp
int16_t sp
Spell points.
Definition: living.h:42
get_map_from_coord
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:2352
FLAG_CAN_USE_SKILL
#define FLAG_CAN_USE_SKILL
The monster can use skills.
Definition: define.h:321
rt_reply
@ rt_reply
Reply to something.
Definition: dialog.h:9
PACEV
#define PACEV
The monster will pace back and forth until attacked.
Definition: define.h:518
monster_can_pick
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:1908
living::Int
int8_t Int
Definition: living.h:36
SP_level_spellpoint_cost
int16_t SP_level_spellpoint_cost(object *caster, object *spell, int flags)
Scales the spellpoint cost of a spell by it's increased effectiveness.
Definition: spell_util.cpp:236
monster_format_say
static StringBuffer * monster_format_say(const object *npc, const char *message)
Format an NPC message.
Definition: monster.cpp:2423
monster_compute_path
int monster_compute_path(object *source, object *target, int default_dir)
Computes a path from source to target.
Definition: monster.cpp:471
object::race
sstring race
Human, goblin, dragon, etc.
Definition: object.h:326
object::facing
int8_t facing
Object is oriented/facing that way.
Definition: object.h:345
object::animation
const Animations * animation
Animation of this item, NULL if not animated.
Definition: object.h:428
monster_find_throw_ob
object * monster_find_throw_ob(object *op)
Find an item for the monster to throw.
Definition: monster.cpp:2662
RING
@ RING
Definition: object.h:190
ob_blocked
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
Returns true if the given object can't fit in the given spot.
Definition: map.cpp:489
LO4
#define LO4
bitmasks for upper and lower 4 bits from 8 bit fields
Definition: define.h:524
FLAG_MONSTER
#define FLAG_MONSTER
Will attack players.
Definition: define.h:245
FLAG_RANDOM_MOVE
#define FLAG_RANDOM_MOVE
NPC will move randomly.
Definition: define.h:309
fatal
void fatal(enum fatal_error err)
fatal() is meant to be called whenever a fatal signal is intercepted.
Definition: utils.cpp:590
monster_hitrun_att
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:2101
monster_npc_call_help
void monster_npc_call_help(object *op)
A monster calls for help against its enemy.
Definition: monster.cpp:2025
SIZEOFFREE
#define SIZEOFFREE
Definition: define.h:155
P_OUT_OF_MAP
#define P_OUT_OF_MAP
This space is outside the map.
Definition: map.h:249
MAX_BUF
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
monster_use_range
static int monster_use_range(object *head, object *part, object *pl, int dir)
Monster will use a ranged attack (ROD, WAND, ...).
Definition: monster.cpp:1506
MSG_TYPE_DIALOG
#define MSG_TYPE_DIALOG
NPCs, magic mouths, and altars.
Definition: newclient.h:404
minheap_remove
void * minheap_remove(MinHeap *heap)
Pops the top of the minheap off.
Definition: minheap.cpp:209
IS_WEAPON
#define IS_WEAPON(op)
Definition: define.h:163
get_weight_limit
uint32_t get_weight_limit(int stat)
Definition: living.cpp:2373
use_trigger
void use_trigger(object *op)
Toggles the state of specified button.
Definition: button.cpp:254
talk_info::text
const char * text
What the player actually said.
Definition: dialog.h:52
free_string
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.cpp:280
object::move_slow
MoveType move_slow
Movement types this slows down.
Definition: object.h:441
living::wc
int8_t wc
Weapon Class, lower WC increases probability of hitting.
Definition: living.h:37
pets_move
void pets_move(object *ob)
Handles a pet's movement.
Definition: pets.cpp:330
object::move_slow_penalty
float move_slow_penalty
How much this slows down the object.
Definition: object.h:442
RANDOM
#define RANDOM()
Definition: define.h:638
HI4
#define HI4
Definition: define.h:525
move_object
int move_object(object *op, int dir)
Try to move op in the direction "dir".
Definition: move.cpp:39
SK_HIDING
@ SK_HIDING
Hiding.
Definition: skills.h:21
StringBuffer
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.cpp:25
MOVE_FLY_LOW
#define MOVE_FLY_LOW
Low flying object.
Definition: define.h:393
SP_MAGIC_WALL
#define SP_MAGIC_WALL
Definition: spells.h:89
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:717
SP_INVISIBLE
#define SP_INVISIBLE
Definition: spells.h:93
OUT_OF_REAL_MAP
#define OUT_OF_REAL_MAP(M, X, Y)
Checks if a square is out of the map.
Definition: map.h:217
MAGIC_EAR
@ MAGIC_EAR
Definition: object.h:136
get_search_arr
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
living::Wis
int8_t Wis
Definition: living.h:36
MAX_KNOWN_SPELLS
#define MAX_KNOWN_SPELLS
Maximum number of spells to consider when choosing a spell for a monster.
Definition: monster.cpp:1223
FLAG_READY_SKILL
#define FLAG_READY_SKILL
(Monster or Player) has a skill readied
Definition: define.h:333
FLAG_READY_BOW
#define FLAG_READY_BOW
not implemented yet
Definition: define.h:299
FLAG_REMOVED
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:232
path_data::y
int16_t y
Definition: monster.cpp:423
reply_type
reply_type
Various kind of messages a player or NPC can say.
Definition: dialog.h:7
FLAG_WIZ
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:231
ext_info_map_except
void ext_info_map_except(int color, const mapstruct *map, const object *op, uint8_t type, uint8_t subtype, const char *str1)
Writes to everyone on the map except *op.
Definition: info.cpp:219
struct_dialog_reply::reply
char * reply
Reply expected from the player.
Definition: dialog.h:17
talk_info::message_type
reply_type message_type
A reply_type value for message.
Definition: dialog.h:54
NDI_UNIQUE
#define NDI_UNIQUE
Print immediately, don't buffer.
Definition: newclient.h:266
monster_circ1_move
static void monster_circ1_move(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2173
object::glow_radius
int8_t glow_radius
indicates the glow radius of the object
Definition: object.h:374
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:246
spells.h
struct_dialog_message
One message a NPC can react to.
Definition: dialog.h:26
object::name
sstring name
The name of the object, obviously...
Definition: object.h:319
MSG_TYPE_SKILL_FAILURE
#define MSG_TYPE_SKILL_FAILURE
Failure in using skill.
Definition: newclient.h:594
monster_move_no_enemy
static int monster_move_no_enemy(object *op)
Makes a monster without any enemy move.
Definition: monster.cpp:790
get_dialog_message
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::spellitem
object * spellitem
Spell ability monster is choosing to use.
Definition: object.h:406
path_data::distance
uint16_t distance
Definition: monster.cpp:424
SIZEOFFREE2
#define SIZEOFFREE2
Definition: define.h:154
MAX_REPLIES
#define MAX_REPLIES
How many NPC replies maximum to tell the player.
Definition: dialog.h:43
object_can_pick
int object_can_pick(const object *who, const object *item)
Finds out if an object can be picked up.
Definition: object.cpp:3852
IS_ARMOR
#define IS_ARMOR(op)
Definition: define.h:166
monster_can_detect_enemy
int monster_can_detect_enemy(object *op, object *enemy, rv_vector *rv)
Determine if we can 'detect' the enemy.
Definition: monster.cpp:2701
get_map_flags
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
monster_do_say
void monster_do_say(const mapstruct *map, const char *message)
Output a NPC message on a map.
Definition: monster.cpp:2412
FLAG_USE_ARMOUR
#define FLAG_USE_ARMOUR
(Monster) can wear armour/shield/helmet
Definition: define.h:295
FLAG_CAST_SPELL
#define FLAG_CAST_SPELL
(Monster) can learn and cast spells
Definition: define.h:290
EARTHWALL
@ EARTHWALL
Definition: object.h:149
living::maxsp
int16_t maxsp
Max spell points.
Definition: living.h:43
SP_MOVING_BALL
#define SP_MOVING_BALL
Definition: spells.h:109
mapstruct
This is a game-map.
Definition: map.h:315
object::last_sp
int32_t last_sp
As last_heal, but for spell points.
Definition: object.h:368
sstring
const typedef char * sstring
Definition: sstring.h:2
shopkeeper_move
static void shopkeeper_move(object *ob)
Special move for shopkeepers.
Definition: monster.cpp:2275
rt_question
@ rt_question
Asking a question.
Definition: dialog.h:10
animate_object
void animate_object(object *op, int dir)
Updates the face-variable of an object.
Definition: anim.cpp:44
shop.h
object_split
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
monster_move_randomly
static int monster_move_randomly(object *op)
Handles random object movement.
Definition: monster.cpp:383
monster_move
int monster_move(object *op)
Main monster processing routine.
Definition: monster.cpp:867
monster_use_skill
static int monster_use_skill(object *head, object *part, object *pl, int dir)
A monster attempts using a skill.
Definition: monster.cpp:1449
mapstruct::name
char * name
Name of map as given by its creator.
Definition: map.h:318
object::light_cached_time
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
object::attacked_by_count
tag_t attacked_by_count
The tag of attacker, so we can be sure.
Definition: object.h:393
monster_use_bow
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:1582
pets_follow_owner
void pets_follow_owner(object *ob, object *owner)
A pet is trying to follow its owner.
Definition: pets.cpp:297
rv_vector
This is used by get_rangevector to determine where the other creature is.
Definition: map.h:370
hit_player
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Object is attacked by something.
Definition: attack.cpp:1907
get_randomized_dir
int get_randomized_dir(int dir)
Returns a random direction (1..8) similar to a given direction.
Definition: utils.cpp:412
object_get_value
sstring object_get_value(const object *op, const char *const key)
Get an extra value by key.
Definition: object.cpp:4331
do_hidden_move
void do_hidden_move(object *op)
For hidden creatures - a chance of becoming 'unhidden' every time they move - as we subtract off 'inv...
Definition: player.cpp:4051
NDI_WHITE
#define NDI_WHITE
Definition: newclient.h:247
on_same_map
int on_same_map(const object *op1, const object *op2)
Checks whether 2 objects are on the same map or not.
Definition: map.cpp:2629
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
AP_NOPRINT
#define AP_NOPRINT
Don't print messages - caller will do that may be some that still print.
Definition: define.h:579
talk_info
Structure used to build up dialog information when a player says something.
Definition: dialog.h:50
living::ac
int8_t ac
Armor Class, lower AC increases probability of not getting hit.
Definition: living.h:38
object::attacked_by
object * attacked_by
This object start to attack us! only player & monster.
Definition: object.h:392
MSG_TYPE_DIALOG_MAGIC_EAR
#define MSG_TYPE_DIALOG_MAGIC_EAR
Magic ear.
Definition: newclient.h:493
minheap_init_static
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
MSG_TYPE_DIALOG_NPC
#define MSG_TYPE_DIALOG_NPC
A message from the npc.
Definition: newclient.h:491
fire_bow
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
get_rangevector
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:2523
monster_pace_movev
static void monster_pace_movev(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2199
talk_info::npc_msgs
sstring npc_msgs[MAX_NPC]
What the NPCs will say.
Definition: dialog.h:59
MIN_ACTIVE_SPEED
#define MIN_ACTIVE_SPEED
Cut off point of when an object is put on the active list or not.
Definition: define.h:633
object::body_info
int8_t body_info[NUM_BODY_LOCATIONS]
Body info as loaded from the file.
Definition: object.h:382
FLAG_BERSERK
#define FLAG_BERSERK
monster will attack closest living object
Definition: define.h:352
FOOD
@ FOOD
Definition: object.h:117
monster_stand_in_light
int monster_stand_in_light(object *op)
Cache monster_stand_in_light_internal().
Definition: monster.cpp:2856
skill
skill
Definition: arch-handbook.txt:585
object_remove
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
monster_do_living
void monster_do_living(object *op)
For a monster, regenerate hp and sp, potentially clear scared status.
Definition: monster.cpp:727
DOOR
@ DOOR
Definition: object.h:131
player_can_view
int player_can_view(object *pl, object *op)
Check the player los field for viewability of the object op.
Definition: player.cpp:4160
FLAG_UNPAID
#define FLAG_UNPAID
Object hasn't been paid for yet.
Definition: define.h:236
SP_SUMMON_GOLEM
#define SP_SUMMON_GOLEM
Definition: spells.h:86
WAIT2
#define WAIT2
Monster does not try to move towards player if far.
Definition: define.h:493
path_data::heuristic_dist
uint16_t heuristic_dist
Definition: monster.cpp:425
monster_npc_say
void monster_npc_say(object *npc, const char *cp)
Simple function to have some NPC say something.
Definition: monster.cpp:2617
FLAG_READY_RANGE
#define FLAG_READY_RANGE
(Monster) has a range attack readied...
Definition: define.h:298
key_shopkeeper
const char * key_shopkeeper
Definition: monster.cpp:61
SCROLL
@ SCROLL
Definition: object.h:226
monster_talk_to_npc
static int monster_talk_to_npc(object *npc, talk_info *info)
Give an object the chance to handle something being said.
Definition: monster.cpp:2634
DISTHIT
#define DISTHIT
Attack from a distance if hit as recommended by Frank.
Definition: define.h:492
FLAG_XRAYS
#define FLAG_XRAYS
X-ray vision.
Definition: define.h:300
RUSH
#define RUSH
Rush toward player blindly, similiar to dumb monster.
Definition: define.h:490
PETMOVE
#define PETMOVE
If the upper four bits of attack_movement are set to this number, the monster follows a player until ...
Definition: define.h:495
chance
bool chance(int a, int b)
Return true with a probability of a/b.
Definition: treasure.cpp:890
monster_use_scroll
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:1365
object::stats
living stats
Str, Con, Dex, etc.
Definition: object.h:378
object_set_value
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
object::more
object * more
Pointer to the rest of a large body of objects.
Definition: object.h:303
MSG_TYPE_COMMUNICATION
#define MSG_TYPE_COMMUNICATION
Communication between players.
Definition: newclient.h:414
get_attr_value
int8_t get_attr_value(const living *stats, int attr)
Gets the value of a stat.
Definition: living.cpp:313
drain_rod_charge
void drain_rod_charge(object *rod)
Drain charges from a rod.
Definition: spell_util.cpp:776
DISTATT
#define DISTATT
Move toward a player if far, but maintain some space, attack from a distance - good for missile users...
Definition: define.h:485
WILL_APPLY_TREASURE
#define WILL_APPLY_TREASURE
Open chests.
Definition: object.h:55
minheap_insert
int minheap_insert(MinHeap *heap, void *ob)
Inserts an element into the min-heap.
Definition: minheap.cpp:184
freearr_x
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.cpp:299
bonus
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various what they and how they effect the player s actions Also in this section are the stat modifiers that specific classes professions bring Player and sps the current and maximum the Current and Maximum The Current Sp can go somewhat negative When Sp is negative not all spells can be and a more negative Sp makes spell casting less likey to succeed can affect Damage and how the characters as well as how often the character can attack this affects the prices when buying and selling items if this drops the player will start losing hit points wd Cleric or Dwarf sm Elf wd Fireborn ft Human ra Mage C Monk se Ninja hi Priest C Quetzalcoatl mw Swashbuckler si Thief st Viking ba Warrior or Wizard C Wraith C Class Prof Str Dex Con Wis Cha Int Pow Net Skills Enclosed are codes used for the skills above The ones in and fighting should all be pretty self explanatory For the other a brief description is for a more detailed look at the skills doc file Skill remove use magic items phys no fire cold Fireborns are supposed to be fire spirits They re closely in tune with magic and are powerful and learn magic easily Being fire they are immune to fire and and vulnerable to cold They are vulnerable to ghosthit and drain because being mostly non anything which strikes directly at the spirit hits them harder race attacktype restrictions immunities prot vuln Quetzalcoatl physical no armour fire cold Quetzalcoatl s are now born knowing the spell of burning but because of their negative wisdom bonus
Definition: stats.txt:176
MAX_EXPLORE
#define MAX_EXPLORE
Maximum map size to consider when finding a path in monster_compute_path().
Definition: monster.cpp:416
monster_cast_spell
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:1278
SPELL
@ SPELL
Definition: object.h:219
events_execute_object_say
int events_execute_object_say(object *npc, talk_info *talk)
Execute an EVENT_SAY on the specified object.
Definition: events.cpp:313
mapstruct::darkness
uint8_t darkness
Indicates level of darkness of map.
Definition: map.h:336
living::Pow
int8_t Pow
Definition: living.h:36
SP_SWARM
#define SP_SWARM
Definition: spells.h:110
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
FLAG_USE_SCROLL
#define FLAG_USE_SCROLL
(Monster) can read scroll
Definition: define.h:291
CIRCLE1
#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:503
rv_vector::direction
int direction
General direction to the targer.
Definition: map.h:374
dirdiff
int dirdiff(int dir1, int dir2)
Computes a direction difference.
Definition: object.cpp:3717
makes_invisible_to
int makes_invisible_to(object *pl, object *mon)
This checks to see if 'pl' is invisible to 'mon'.
Definition: spell_effect.cpp:756
PACEH2
#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:510
SP_EXPLOSION
#define SP_EXPLOSION
Definition: spells.h:80
FLAG_IS_THROWN
#define FLAG_IS_THROWN
Object is designed to be thrown.
Definition: define.h:249
THROWN_OBJ
@ THROWN_OBJ
Definition: object.h:151
FLAG_SLEEP
#define FLAG_SLEEP
NPC is sleeping.
Definition: define.h:307
SK_THROWING
@ SK_THROWING
Throwing.
Definition: skills.h:44
rv_vector::distance
unsigned int distance
Distance, in squares.
Definition: map.h:371
SPELLBOOK
@ SPELLBOOK
Definition: object.h:208
NUM_STATS
@ NUM_STATS
Number of statistics.
Definition: living.h:18
object::move_block
MoveType move_block
What movement types this blocks.
Definition: object.h:437
monster_check_earthwalls
void monster_check_earthwalls(object *op, mapstruct *m, int x, int y)
Living creature attempts to hit an earthwall.
Definition: monster.cpp:2382
get_reply_text_own
const char * get_reply_text_own(reply_type rt)
Return the verb for the player's dialog type.
Definition: monster.cpp:2438
monster_dist_att
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:2067
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:664
living::hp
int16_t hp
Hit Points.
Definition: living.h:40
MSG_TYPE_COMMUNICATION_SAY
#define MSG_TYPE_COMMUNICATION_SAY
Player says something.
Definition: newclient.h:627
drain_wand_charge
void drain_wand_charge(object *wand)
Drains a charge from a wand.
Definition: spell_util.cpp:786
monster_should_cast_spell
static int monster_should_cast_spell(object *spell_ob)
Checks if a monster should cast a spell.
Definition: monster.cpp:1197
struct_dialog_reply::type
reply_type type
Type of message.
Definition: dialog.h:19
monster_communicate
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:2494
WILL_APPLY_FOOD
#define WILL_APPLY_FOOD
Eat food (not drinks).
Definition: object.h:58
llevDebug
@ llevDebug
Only for debugging purposes.
Definition: logger.h:13
MONEY
@ MONEY
Definition: object.h:142
RANDO2
#define RANDO2
Constantly move in a different random direction.
Definition: define.h:517
monster_do_talk_npc
static int monster_do_talk_npc(object *npc, talk_info *info)
Checks the messages of a NPC for a matching text.
Definition: monster.cpp:2568
monster_check_apply
static void monster_check_apply(object *mon, object *item)
Called after an item is inserted in a monster.
Definition: monster.cpp:1747
is_true_undead
int is_true_undead(object *op)
Is the object a true undead?
Definition: player.cpp:3993
talk_info::who
struct object * who
Player saying something.
Definition: dialog.h:51
living::Con
int8_t Con
Definition: living.h:36
coords_in_shop
bool coords_in_shop(mapstruct *map, int x, int y)
Check if the given map coordinates are in a shop.
Definition: map.cpp:2757
skill_attack
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.
Definition: skill_util.cpp:1270
SPELL_MANA
#define SPELL_MANA
Definition: spells.h:58
identify
object * identify(object *op)
Identifies an item.
Definition: item.cpp:1449
SP_AURA
#define SP_AURA
Definition: spells.h:120
get_reply_text_other
static const char * get_reply_text_other(reply_type rt)
Return the verb for the player's dialog type seen from others (third person).
Definition: monster.cpp:2456