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  /* Calculate range information for closest body part - this
935  * is used for the 'skill' code, which isn't that smart when
936  * it comes to figuring it out - otherwise, giants throw boulders
937  * into themselves.
938  */
939  if (!get_rangevector(op, enemy, &rv, 0))
940  return 0;
941  if (op->direction != rv.direction) {
942  op->direction = rv.direction;
943  op->facing = op->direction;
944  if (op->animation)
945  animate_object(op, op->direction);
946  }
947 
948  // We are looking at movement -- if monster was paralyzed, they aren't anymore
949  if (QUERY_FLAG(op, FLAG_PARALYZED)) {
951  }
952 
953  /* Move the check for scared up here - if the monster was scared,
954  * we were not doing any of the logic below, so might as well save
955  * a few cpu cycles.
956  */
957  if (!QUERY_FLAG(op, FLAG_SCARED)) {
958  dir = rv.direction;
959 
960  /* Was two if statements assigning to the same variable
961  * We can get the same effect by reversing the order and making an else-if
962  */
963  if (QUERY_FLAG(op, FLAG_CONFUSED))
964  dir = get_randomized_dir(dir);
965  else if (QUERY_FLAG(op, FLAG_RUN_AWAY))
966  dir = absdir(dir+4);
967 
968  if (QUERY_FLAG(op, FLAG_CAST_SPELL) && !(RANDOM()%3)) {
969  if (monster_cast_spell(op, rv.part, enemy, dir))
970  return 0;
971  }
972 
973  if (QUERY_FLAG(op, FLAG_READY_SCROLL) && !(RANDOM()%3)) {
974  if (monster_use_scroll(op, rv.part, enemy, dir))
975  return 0;
976  }
977 
978  if (QUERY_FLAG(op, FLAG_READY_RANGE) && !(RANDOM()%3)) {
979  if (monster_use_range(op, rv.part, enemy, dir))
980  return 0;
981  }
982  if (QUERY_FLAG(op, FLAG_READY_SKILL) && !(RANDOM()%3)) {
983  if (monster_use_skill(op, rv.part, enemy, rv.direction))
984  return 0;
985  }
986  if (QUERY_FLAG(op, FLAG_READY_BOW) && !(RANDOM()%2)) {
987  if (monster_use_bow(op, rv.part, enemy, dir))
988  return 0;
989  }
990  } /* If not scared */
991 
992 
993  /* code below is for when we didn't use a range attack or a skill, so
994  * either move or hit with hth attack. */
995 
996  part = rv.part;
997  dir = rv.direction;
998 
999  /* This first clause used to happen after the other two, but would trample dir.
1000  * Moved to before them as another check to slightly reduce calls to monster_compute_path
1001  */
1002  if (QUERY_FLAG(op, FLAG_CONFUSED))
1003  dir = get_randomized_dir(dir);
1004  else if (QUERY_FLAG(op, FLAG_SCARED) || QUERY_FLAG(op, FLAG_RUN_AWAY))
1005  dir = absdir(dir+4);
1006  else if (!monster_can_hit(part, enemy, &rv)) {
1007  dir = monster_compute_path(op, enemy, -1);
1008  if (dir == -1) {
1009  // Can't reach enemy, so remove it, attempt to move in its last direction so not stay still
1010  LOG(llevMonster, "monster %s (%d, %d on %s) can't reach enemy %s (%d, %d on %s)\n",
1011  op->name, op->x, op->y, op->map ? op->map->name : "(unknown map)", enemy->name, enemy->x, enemy->y, enemy->map ? enemy->map->path : "(unknown map)");
1012  object_set_enemy(op, NULL);
1013  dir = rv.direction;
1014  }
1015  }
1016 
1017  if ((op->attack_movement&LO4) && !QUERY_FLAG(op, FLAG_SCARED)) {
1018  switch (op->attack_movement&LO4) {
1019  case DISTATT:
1020  dir = monster_dist_att(dir, enemy, part, &rv);
1021  break;
1022 
1023  case RUNATT:
1024  dir = monster_run_att(dir, op, enemy, part, &rv);
1025  break;
1026 
1027  case HITRUN:
1028  dir = monster_hitrun_att(dir, op);
1029  break;
1030 
1031  case WAITATT:
1032  dir = monster_wait_att(dir, op, enemy, part, &rv);
1033  break;
1034 
1035  case RUSH: /* default - monster normally moves towards player */
1036  case ALLRUN:
1037  break;
1038 
1039  case DISTHIT:
1040  dir = monster_disthit_att(dir, op, enemy, part, &rv);
1041  break;
1042 
1043  case WAIT2:
1044  dir = monster_wait_att2(dir, &rv);
1045  break;
1046 
1047  default:
1048  LOG(llevDebug, "Illegal low mon-move: %d\n", op->attack_movement&LO4);
1049  }
1050  }
1051 
1052  if (!dir)
1053  return 0;
1054 
1055  if (!QUERY_FLAG(op, FLAG_STAND_STILL)) {
1056  if (move_object(op, dir)) /* Can the monster move directly toward player? */
1057  return 0;
1058 
1059  if (QUERY_FLAG(op, FLAG_SCARED)
1060  || !monster_can_hit(part, enemy, &rv)
1061  || QUERY_FLAG(op, FLAG_RUN_AWAY)) {
1062  /* Try move around corners if !close */
1063  int maxdiff = (QUERY_FLAG(op, FLAG_ONLY_ATTACK) || RANDOM()&1) ? 1 : 2;
1064  for (diff = 1; diff <= maxdiff; diff++) {
1065  /* try different detours */
1066  int m = 1-(RANDOM()&2); /* Try left or right first? */
1067  if (move_object(op, absdir(dir+diff*m))
1068  || move_object(op, absdir(dir-diff*m)))
1069  return 0;
1070  }
1071  }
1072  } /* if monster is not standing still */
1073 
1074  /*
1075  * Eneq(@csd.uu.se): Patch to make RUN_AWAY or SCARED monsters move a random
1076  * direction if they can't move away.
1077  */
1078  if (!QUERY_FLAG(op, FLAG_ONLY_ATTACK)
1079  && (QUERY_FLAG(op, FLAG_RUN_AWAY) || QUERY_FLAG(op, FLAG_SCARED)))
1080  if (monster_move_randomly(op))
1081  return 0;
1082 
1083  /*
1084  * Try giving the monster a new enemy - the player that is closest
1085  * to it. In this way, it won't just keep trying to get to a target
1086  * that is inaccessible.
1087  * This could be more clever - it should go through a list of several
1088  * enemies, as it is now, you could perhaps get situations where there
1089  * are two players flanking the monster at close distance, but which
1090  * the monster can't get to, and a third one at a far distance that
1091  * the monster could get to - as it is, the monster won't look at that
1092  * third one.
1093  */
1094  if (!QUERY_FLAG(op, FLAG_FRIENDLY) && enemy == op->enemy) {
1095  object *nearest_player = get_nearest_player(op);
1096 
1097  if (nearest_player && nearest_player != enemy && !monster_can_hit(part, enemy, &rv)) {
1098  object_set_enemy(op, NULL);
1099  enemy = nearest_player;
1100  }
1101  }
1102 
1103  if (!QUERY_FLAG(op, FLAG_SCARED) && monster_can_hit(part, enemy, &rv)) {
1104  /* The adjustement to wc that was here before looked totally bogus -
1105  * since wc can in fact get negative, that would mean by adding
1106  * the current wc, the creature gets better? Instead, just
1107  * add a fixed amount - nasty creatures that are runny away should
1108  * still be pretty nasty.
1109  */
1110  if (QUERY_FLAG(op, FLAG_RUN_AWAY)) {
1111  part->stats.wc += 10;
1112  skill_attack(enemy, part, 0, NULL, NULL);
1113  part->stats.wc -= 10;
1114  } else
1115  skill_attack(enemy, part, 0, NULL, NULL);
1116  } /* if monster is in attack range */
1117 
1118  if (QUERY_FLAG(part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */
1119  return 1;
1120 
1121  if (QUERY_FLAG(op, FLAG_ONLY_ATTACK)) {
1122  object_remove(op);
1124  return 1;
1125  }
1126  return 0;
1127 }
1128 
1143 static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv) {
1144  object *more;
1145  rv_vector rv1;
1146 
1147  if (QUERY_FLAG(ob1, FLAG_CONFUSED) && !(RANDOM()%3))
1148  return 0;
1149 
1150  if (abs(rv->distance_x) < 2 && abs(rv->distance_y) < 2)
1151  return 1;
1152 
1153  /* check all the parts of ob2 - just because we can't get to
1154  * its head doesn't mean we don't want to pound its feet
1155  */
1156  for (more = ob2->more; more != NULL; more = more->more) {
1157  if (get_rangevector(ob1, more, &rv1, 0)
1158  && abs(rv1.distance_x) < 2 && abs(rv1.distance_y) < 2)
1159  return 1;
1160  }
1161  return 0;
1162 }
1163 
1186 static int monster_should_cast_spell(object *spell_ob) {
1187  /* The caller is responsible for making sure that *spell_ob is defined. */
1188  assert(spell_ob != NULL);
1189 
1190  switch (spell_ob->subtype) {
1191  case SP_BOLT:
1192  case SP_BULLET:
1193  case SP_EXPLOSION:
1194  case SP_CONE:
1195  case SP_BOMB:
1196  case SP_SMITE:
1197  case SP_MAGIC_MISSILE:
1198  case SP_SUMMON_GOLEM:
1199  case SP_MAGIC_WALL:
1200  case SP_SUMMON_MONSTER:
1201  case SP_MOVING_BALL:
1202  case SP_SWARM:
1203  case SP_INVISIBLE:
1204  case SP_AURA:
1205  return 1;
1206  }
1207 
1208  return 0;
1209 }
1210 
1212 #define MAX_KNOWN_SPELLS 20
1213 
1229 static object *monster_choose_random_spell(object *monster) {
1230  object *altern[MAX_KNOWN_SPELLS];
1231  int i = 0;
1232 
1233  FOR_INV_PREPARE(monster, tmp)
1234  if (tmp->type == SPELLBOOK || tmp->type == SPELL) {
1235  /* Check and see if it's actually a useful spell.
1236  * If its a spellbook, the spell is actually the inventory item.
1237  * if it is a spell, then it is just the object itself.
1238  */
1239  if (monster_should_cast_spell(tmp->type == SPELLBOOK ? tmp->inv : tmp)) {
1240  altern[i++] = tmp;
1241  if (i == MAX_KNOWN_SPELLS)
1242  break;
1243  }
1244  }
1245  FOR_INV_FINISH();
1246  if (!i)
1247  return NULL;
1248  return altern[RANDOM()%i];
1249 }
1250 
1267 static int monster_cast_spell(object *head, object *part, object *pl, int dir) {
1268  object *spell_item;
1269  object *owner;
1270  rv_vector rv1;
1271 
1272  /* If you want monsters to cast spells over friends, this spell should
1273  * be removed. It probably should be in most cases, since monsters still
1274  * don't care about residual effects (ie, casting a cone which may have a
1275  * clear path to the player, the side aspects of the code will still hit
1276  * other monsters)
1277  */
1278  dir = path_to_player(part, pl, 0);
1279  if (dir == 0)
1280  return 0;
1281 
1282  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1283  owner = object_get_owner(head);
1284  if (owner != NULL) {
1285  if (get_rangevector(head, owner, &rv1, 0x1)
1286  && dirdiff(dir, rv1.direction) < 2) {
1287  return 0; /* Might hit owner with spell */
1288  }
1289  }
1290  }
1291 
1292  if (QUERY_FLAG(head, FLAG_CONFUSED))
1293  dir = get_randomized_dir(dir);
1294 
1295  /* If the monster hasn't already chosen a spell, choose one
1296  * I'm not sure if it really make sense to pre-select spells (events
1297  * could be different by the time the monster goes again).
1298  */
1299  if (head->spellitem == NULL) {
1300  spell_item = monster_choose_random_spell(head);
1301  if (spell_item == NULL) {
1302  LOG(llevMonster, "Turned off spells in %s\n", head->name);
1303  CLEAR_FLAG(head, FLAG_CAST_SPELL); /* Will be turned on when picking up book */
1304  return 0;
1305  }
1306  if (spell_item->type == SPELLBOOK) {
1307  if (!spell_item->inv) {
1308  LOG(llevError, "spellbook %s does not contain a spell?\n", spell_item->name);
1309  return 0;
1310  }
1311  spell_item = spell_item->inv;
1312  }
1313  } else
1314  spell_item = head->spellitem;
1315 
1316  if (!spell_item)
1317  return 0;
1318 
1319  /* Best guess this is a defensive/healing spell */
1320  if (spell_item->range <= 1 || spell_item->stats.dam < 0)
1321  dir = 0;
1322 
1323  /* Monster doesn't have enough spell-points */
1324  /* As of 2023, monsters do not possess grace points, and so will use sp for prayers too. */
1325  if (head->stats.sp < SP_level_spellpoint_cost(head, spell_item, SPELL_MANA))
1326  return 0;
1327 
1328  if (head->stats.sp < SP_level_spellpoint_cost(head, spell_item, SPELL_GRACE))
1329  return 0;
1330 
1331  head->stats.sp -= SP_level_spellpoint_cost(head, spell_item, SPELL_MANA);
1332  head->stats.sp -= SP_level_spellpoint_cost(head, spell_item, SPELL_GRACE);
1333 
1334  /* set this to null, so next time monster will choose something different */
1335  head->spellitem = NULL;
1336 
1337  return cast_spell(part, part, dir, spell_item, NULL);
1338 }
1339 
1354 static int monster_use_scroll(object *head, object *part, object *pl, int dir) {
1355  object *scroll;
1356  object *owner;
1357  rv_vector rv1;
1358 
1359  /* If you want monsters to cast spells over friends, this spell should
1360  * be removed. It probably should be in most cases, since monsters still
1361  * don't care about residual effects (ie, casting a cone which may have a
1362  * clear path to the player, the side aspects of the code will still hit
1363  * other monsters)
1364  */
1365  dir = path_to_player(part, pl, 0);
1366  if (dir == 0)
1367  return 0;
1368 
1369  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1370  owner = object_get_owner(head);
1371  if (owner != NULL) {
1372  if (get_rangevector(head, owner, &rv1, 0x1)
1373  && dirdiff(dir, rv1.direction) < 2) {
1374  return 0; /* Might hit owner with spell */
1375  }
1376  }
1377  }
1378 
1379  if (QUERY_FLAG(head, FLAG_CONFUSED))
1380  dir = get_randomized_dir(dir);
1381 
1382  scroll = NULL;
1383  FOR_INV_PREPARE(head, tmp)
1384  if (tmp->type == SCROLL && monster_should_cast_spell(tmp->inv)) {
1385  scroll = tmp;
1386  break;
1387  }
1388  FOR_INV_FINISH();
1389 
1390  /* Used up all his scrolls, so nothing do to */
1391  if (!scroll) {
1393  return 0;
1394  }
1395 
1396  /* Spell should be cast on caster (ie, heal, strength) */
1397  if (scroll->inv->range == 0)
1398  dir = 0;
1399 
1400  /* Face the direction that we want to cast. */
1401  head->direction = dir;
1402  head->facing = head->direction;
1403  if (head->animation)
1404  animate_object(head, head->direction);
1405 
1406  apply_manual(part, scroll, 0);
1407  return 1;
1408 }
1409 
1438 static int monster_use_skill(object *head, object *part, object *pl, int dir) {
1439  object *owner;
1440  int found;
1441 
1442  dir = path_to_player(part, pl, 0);
1443  if (dir == 0)
1444  return 0;
1445 
1446  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1447  owner = object_get_owner(head);
1448  if (owner != NULL) {
1449  rv_vector rv;
1450 
1451  if (get_rangevector(head, owner, &rv, 0) && dirdiff(dir, rv.direction) < 1)
1452  return 0; /* Might hit owner with skill -thrown rocks for example ?*/
1453  }
1454  }
1455  if (QUERY_FLAG(head, FLAG_CONFUSED))
1456  dir = get_randomized_dir(dir);
1457 
1458  /* skill selection - monster will use the next unused skill.
1459  * well...the following scenario will allow the monster to
1460  * toggle between 2 skills. One day it would be nice to make
1461  * more skills available to monsters.
1462  */
1463  found = 0;
1464  FOR_INV_PREPARE(head, skill)
1465  if (skill->type == SKILL && skill != head->chosen_skill) {
1466  head->chosen_skill = skill;
1467  found = 1;
1468  break;
1469  }
1470  FOR_INV_FINISH();
1471 
1472  if (!found && !head->chosen_skill) {
1473  LOG(llevDebug, "Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", head->name, head->count);
1475  return 0;
1476  }
1477  /* use skill */
1478  return do_skill(head, part, head->chosen_skill, dir, NULL);
1479 }
1480 
1495 static int monster_use_range(object *head, object *part, object *pl, int dir) {
1496  object *owner;
1497  int at_least_one = 0;
1498 
1499  dir = path_to_player(part, pl, 0);
1500  if (dir == 0)
1501  return 0;
1502 
1503  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1504  owner = object_get_owner(head);
1505  if (owner != NULL) {
1506  rv_vector rv;
1507 
1508  if (get_rangevector(head, owner, &rv, 0) && dirdiff(dir, rv.direction) < 2)
1509  return 0; /* Might hit owner with spell */
1510  }
1511  }
1512  if (QUERY_FLAG(head, FLAG_CONFUSED))
1513  dir = get_randomized_dir(dir);
1514 
1515  FOR_INV_PREPARE(head, wand) {
1516  if (wand->type == WAND) {
1517  /* Found a wand, let's see if it has charges left */
1518  at_least_one = 1;
1519  if (wand->stats.food <= 0)
1520  continue;
1521 
1522  cast_spell(head, wand, dir, wand->inv, NULL);
1523  drain_wand_charge(wand);
1524 
1525  /* Success */
1526  return 1;
1527  }
1528 
1529  if (wand->type == ROD && wand->inv) {
1530  /* Found rod/horn, let's use it if possible */
1531  at_least_one = 1;
1532  if (wand->stats.hp < MAX(wand->inv->stats.sp, wand->inv->stats.grace))
1533  continue;
1534 
1535  /* drain charge before casting spell - can be a case where the
1536  * spell destroys the monster, and rod, so if done after, results
1537  * in crash.
1538  */
1539  drain_rod_charge(wand);
1540  cast_spell(head, wand, dir, wand->inv, NULL);
1541 
1542  /* Success */
1543  return 1;
1544  }
1545  } FOR_INV_FINISH();
1546 
1547  if (at_least_one)
1548  return 0;
1549 
1550  LOG(llevError, "Error: Monster %s (%d) HAS_READY_RANG() without wand/horn/rod.\n", head->name, head->count);
1552  return 0;
1553 }
1554 
1571 static int monster_use_bow(object *head, object *part, object *pl, int dir) {
1572  object *owner;
1573  rv_vector rv;
1574  int16_t x, y;
1575  mapstruct *map;
1576 
1577  if (!get_rangevector(part, pl, &rv, 1))
1578  return 0;
1579  if (rv.distance > 100)
1580  /* Too far */
1581  return 0;
1582  if (rv.distance_x != 0 && rv.distance_y != 0 && abs(rv.distance_x) != abs(rv.distance_y))
1583  /* Player must be on same horizontal, vertical or diagonal line. */
1584  return 0;
1585  dir = rv.direction;
1586 
1587  if (QUERY_FLAG(head, FLAG_FRIENDLY))
1588  owner = object_get_owner(head);
1589  else
1590  owner = NULL;
1591 
1592  /* The monster can possibly fire, let's see if the path is ok for an arrow. */
1593  x = part->x;
1594  y = part->y;
1595  map = part->map;
1596  while (x != pl->x || y != pl->y || map != pl->map) {
1597  x += freearr_x[dir];
1598  y += freearr_y[dir];
1599  map = get_map_from_coord(map, &x, &y);
1600  if (!map) {
1601  LOG(llevError, "monster_use_bow: no map but still path exists??\n");
1602  return 0;
1603  }
1604  if ((GET_MAP_MOVE_BLOCK(map, x, y)&MOVE_FLY_LOW) == MOVE_FLY_LOW)
1605  return 0;
1606  if (owner && owner->x == x && owner->y == y && owner->map == map)
1607  /* Don't hit owner! */
1608  return 0;
1609  }
1610 
1611  /* Finally, path is clear, can fire. */
1612 
1613  if (QUERY_FLAG(head, FLAG_CONFUSED))
1614  dir = get_randomized_dir(dir);
1615 
1616  /* in server/player.c */
1617  return fire_bow(head, NULL, dir, 0, part->x, part->y);
1618 }
1619 
1628 static int monster_get_weapon_quality(const object *item) {
1629  int val;
1630  int i;
1631 
1632  val = item->stats.dam;
1633  val += item->magic*3;
1634  /* Monsters don't really get benefits from things like regen rates
1635  * from items. But the bonus for their stats are very important.
1636  */
1637  for (i = 0; i < NUM_STATS; i++)
1638  val += get_attr_value(&item->stats, i)*2;
1639  return val;
1640 }
1641 
1654 static int monster_check_good_weapon(object *who, object *item) {
1655  object *other_weap;
1656  int val;
1657 
1658  other_weap = object_find_by_type_applied(who, item->type);
1659  if (other_weap == NULL) /* No other weapons */
1660  return 1;
1661 
1662  /* Rather than go through and apply the new one, and see if it is
1663  * better, just do some simple checks
1664  * Put some multipliers for things that hvae several effects,
1665  * eg, magic affects both damage and wc, so it has more weight
1666  */
1667 
1669  return val > 0;
1670 }
1671 
1680 static int monster_get_armour_quality(const object *item) {
1681  int val;
1682 
1683  val = item->stats.ac;
1684  val += item->resist[ATNR_PHYSICAL]/5;
1685  val += item->magic*3;
1686  return val;
1687 }
1688 
1701 static int monster_check_good_armour(object *who, object *item) {
1702  object *other_armour;
1703  int val, i;
1704 
1705  other_armour = object_find_by_type_applied(who, item->type);
1706  if (other_armour == NULL) /* No other armour, use the new */
1707  return 1;
1708 
1709  val = monster_get_armour_quality(item)-monster_get_armour_quality(other_armour);
1710 
1711  /* for the other protections, do weigh them very much in the equation -
1712  * it is the armor protection which is most important, because there is
1713  * no good way to know what the player may attack the monster with.
1714  * So if the new item has better protection than the old, give that higher
1715  * value. If the reverse, then decrease the value of this item some.
1716  */
1717  for (i = 1; i < NROFATTACKS; i++) {
1718  if (item->resist[i] > other_armour->resist[i])
1719  val++;
1720  else if (item->resist[i] < other_armour->resist[i])
1721  val--;
1722  }
1723 
1724  /* Very few armours have stats, so not much need to worry about those. */
1725 
1726  return val > 0;
1727 }
1728 
1736 static void monster_check_apply(object *mon, object *item) {
1737  int flag = 0;
1738 
1739  if (item->type == SPELLBOOK
1740  && mon->arch != NULL
1741  && (QUERY_FLAG(&mon->arch->clone, FLAG_CAST_SPELL))) {
1742  SET_FLAG(mon, FLAG_CAST_SPELL);
1743  return;
1744  }
1745 
1746  /* If for some reason, this item is already applied, no more work to do */
1747  if (QUERY_FLAG(item, FLAG_APPLIED))
1748  return;
1749 
1750  /* Might be better not to do this - if the monster can fire a bow,
1751  * it is possible in his wanderings, he will find one to use. In
1752  * which case, it would be nice to have ammo for it.
1753  */
1754  if (QUERY_FLAG(mon, FLAG_USE_BOW) && item->type == ARROW) {
1755  /* Check for the right kind of bow */
1756  object *bow;
1757 
1758  bow = object_find_by_type_and_race(mon, BOW, item->race);
1759  if (bow != NULL) {
1760  SET_FLAG(mon, FLAG_READY_BOW);
1761  LOG(llevMonster, "Found correct bow for arrows.\n");
1762  return; /* nothing more to do for arrows */
1763  }
1764  }
1765 
1766  if (item->type == TREASURE && mon->will_apply&WILL_APPLY_TREASURE)
1767  flag = 1;
1768  /* Eating food gets hp back */
1769  else if (item->type == FOOD && mon->will_apply&WILL_APPLY_FOOD)
1770  flag = 1;
1771  else if (item->type == SCROLL && QUERY_FLAG(mon, FLAG_USE_SCROLL)) {
1772  if (!item->inv)
1773  LOG(llevDebug, "Monster %d having scroll %d with empty inventory!\n", mon->count, item->count);
1774  else if (monster_should_cast_spell(item->inv))
1776  /* Don't use it right now */
1777  return;
1778  } else if (item->type == WEAPON)
1779  flag = monster_check_good_weapon(mon, item);
1780  else if (IS_ARMOR(item) || IS_SHIELD(item))
1781  flag = monster_check_good_armour(mon, item);
1782  /* Should do something more, like make sure this is a better item */
1783  else if (item->type == RING)
1784  flag = 1;
1785  else if (item->type == WAND || item->type == ROD) {
1786  /* We never really 'ready' the wand/rod/horn, because that would mean the
1787  * weapon would get undone.
1788  */
1789  if (!(apply_can_apply_object(mon, item)&CAN_APPLY_NOT_MASK)) {
1790  SET_FLAG(mon, FLAG_READY_RANGE);
1791  SET_FLAG(item, FLAG_APPLIED);
1792  }
1793  return;
1794  } else if (item->type == BOW) {
1795  /* We never really 'ready' the bow, because that would mean the
1796  * weapon would get undone.
1797  */
1798  if (!(apply_can_apply_object(mon, item)&CAN_APPLY_NOT_MASK))
1799  SET_FLAG(mon, FLAG_READY_BOW);
1800  return;
1801  } else if (item->type == SKILL) {
1802  /*
1803  * skills are specials: monsters must have the 'FLAG_READY_SKILL' flag set,
1804  * else they can't use the skill...
1805  * Skills also don't need to get applied, so return now.
1806  */
1807  SET_FLAG(mon, FLAG_READY_SKILL);
1808  return;
1809  }
1810 
1811  /* if we don't match one of the above types, return now.
1812  * apply_can_apply_object() will say that we can apply things like flesh,
1813  * bolts, and whatever else, because it only checks against the
1814  * body_info locations.
1815  */
1816  if (!flag)
1817  return;
1818 
1819  /* Check to see if the monster can use this item. If not, no need
1820  * to do further processing. Note that apply_can_apply_object() already checks
1821  * for the CAN_USE flags.
1822  */
1824  return;
1825 
1826  /* should only be applying this item, not unapplying it.
1827  * also, ignore status of curse so they can take off old armour.
1828  * monsters have some advantages after all.
1829  */
1831  return;
1832 }
1833 
1853 static void monster_check_pickup(object *monster) {
1854  object *part;
1855 
1856  for (part = monster; part != NULL; part = part->more)
1857  FOR_BELOW_PREPARE(part, tmp) {
1858  /* Don't try to pick items that are in the process of being thrown.
1859  * It is fairly likely that an ally threw it past monster to hit player.
1860  * IDEA: Maybe have a dex save to catch player-thrown projectiles?
1861  *
1862  * Neila Hawkins 2020-09-07
1863  */
1864  if (tmp->type != THROWN_OBJ && monster_can_pick(monster, tmp)) {
1865  uint32_t nrof;
1866 
1867  if (tmp->weight > 0) {
1868  int32_t weight_limit;
1869 
1870  weight_limit = get_weight_limit(monster->stats.Str);
1871  if (weight_limit >= monster->weight-monster->carrying)
1872  nrof = (weight_limit-monster->weight-monster->carrying)/tmp->weight;
1873  else
1874  nrof = 0;
1875  } else
1876  nrof = MAX(1, tmp->nrof);
1877  if (nrof >= 1) {
1878  object *tmp2;
1879 
1880  tmp2 = object_split(tmp, MIN(nrof, MAX(1, tmp->nrof)), NULL, 0);
1881  tmp2 = object_insert_in_ob(tmp2, monster);
1882  (void)monster_check_apply(monster, tmp2);
1883  }
1884  }
1885  } FOR_BELOW_FINISH();
1886 }
1887 
1897 static int monster_can_pick(object *monster, object *item) {
1898  int flag = 0;
1899  int i;
1900 
1901  if (!object_can_pick(monster, item))
1902  return 0;
1903 
1904  if (QUERY_FLAG(item, FLAG_UNPAID))
1905  return 0;
1906 
1907  if (monster->pick_up&64) /* All */
1908  flag = 1;
1909 
1910  else {
1911  if (IS_WEAPON(item))
1912  flag = (monster->pick_up&8) || QUERY_FLAG(monster, FLAG_USE_WEAPON);
1913  else if (IS_ARMOR(item))
1914  flag = (monster->pick_up&16) || QUERY_FLAG(monster, FLAG_USE_ARMOUR);
1915  else if (IS_SHIELD(item))
1916  flag = (monster->pick_up&16) || QUERY_FLAG(monster, FLAG_USE_SHIELD);
1917  else switch (item->type) {
1918  case MONEY:
1919  case GEM:
1920  flag = monster->pick_up&2;
1921  break;
1922 
1923  case FOOD:
1924  flag = monster->pick_up&4;
1925  break;
1926 
1927  case SKILL:
1929  break;
1930 
1931  case RING:
1932  flag = QUERY_FLAG(monster, FLAG_USE_RING);
1933  break;
1934 
1935  case WAND:
1936  case ROD:
1938  break;
1939 
1940  case SPELLBOOK:
1941  flag = (monster->arch != NULL && QUERY_FLAG(&monster->arch->clone, FLAG_CAST_SPELL));
1942  break;
1943 
1944  case SCROLL:
1946  break;
1947 
1948  case BOW:
1949  case ARROW:
1950  flag = QUERY_FLAG(monster, FLAG_USE_BOW);
1951  break;
1952  }
1954  flag = (monster->pick_up&8) || QUERY_FLAG(monster, FLAG_USE_WEAPON);
1955  /* Simplistic check - if the monster has a location to equip it, he will
1956  * pick it up. Note that this doesn't handle cases where an item may
1957  * use several locations.
1958  */
1959  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
1960  if (monster->body_info[i] && item->body_info[i]) {
1961  flag = 1;
1962  break;
1963  }
1964  }
1965  }
1966 
1967  if (((!(monster->pick_up&32)) && flag) || ((monster->pick_up&32) && (!flag)))
1968  return 1;
1969  return 0;
1970 }
1971 
1978 static void monster_apply_below(object *monster) {
1979  FOR_BELOW_PREPARE(monster, tmp) {
1980  switch (tmp->type) {
1981  case CF_HANDLE:
1982  case TRIGGER:
1983  if (monster->will_apply&WILL_APPLY_HANDLE)
1984  apply_manual(monster, tmp, 0);
1985  break;
1986 
1987  case TREASURE:
1988  if (monster->will_apply&WILL_APPLY_TREASURE)
1989  apply_manual(monster, tmp, 0);
1990  break;
1991  }
1992  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
1993  break;
1994  } FOR_BELOW_FINISH();
1995 }
1996 
2002  if (!monster->head) {
2003  fix_object(monster); // Needed to correctly fill various body fields.
2004  }
2005  FOR_INV_PREPARE(monster, inv)
2007  FOR_INV_FINISH();
2008 }
2009 
2014 void monster_npc_call_help(object *op) {
2015  const char *value;
2016  int help_radius = 3;
2017 
2018  value = object_get_value(op, "help_radius");
2019  if ( value ) {
2020  int override_help_radius;
2021 
2022  override_help_radius = strtol(value, NULL, 10);
2023  if (override_help_radius >= 0 && override_help_radius < 30)
2024  help_radius = override_help_radius;
2025  else
2026  LOG(llevDebug, "monster_npc_call_help: invalid help_radius %d\n", override_help_radius);
2027  }
2028 
2029  for (int x = -help_radius; x <= help_radius; x++)
2030  for (int y = -help_radius; y <= help_radius; y++) {
2031  mapstruct *m = op->map;
2032  int16_t sx = op->x+x;
2033  int16_t sy = op->y+y;
2034  int mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
2035  /* If nothing alive on this space, no need to search the space. */
2036  if ((mflags&P_OUT_OF_MAP) || !(mflags&P_IS_ALIVE))
2037  continue;
2038 
2039  FOR_MAP_PREPARE(m, sx, sy, npc)
2040  if (QUERY_FLAG(npc, FLAG_ALIVE) && QUERY_FLAG(npc, FLAG_UNAGGRESSIVE)) {
2041  object_set_enemy(npc, op->enemy);
2043  }
2044  FOR_MAP_FINISH();
2045  }
2046 }
2047 
2056 static int monster_dist_att(int dir, object *enemy, object *part, rv_vector *rv) {
2057  if (monster_can_hit(part, enemy, rv))
2058  return dir;
2059  if (rv->distance < 10)
2060  return absdir(dir+4);
2061  else if (rv->distance > 18)
2062  return dir;
2063  return 0;
2064 }
2065 
2075 static int monster_run_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
2076  if ((monster_can_hit(part, enemy, rv) && ob->move_status < 20) || ob->move_status < 20) {
2077  ob->move_status++;
2078  return (dir);
2079  } else if (ob->move_status > 20)
2080  ob->move_status = 0;
2081  return absdir(dir+4);
2082 }
2083 
2090 static int monster_hitrun_att(int dir, object *ob) {
2091  if (ob->move_status++ < 25)
2092  return dir;
2093  else if (ob->move_status < 50)
2094  return absdir(dir+4);
2095  ob->move_status = 0;
2096  return absdir(dir+4);
2097 }
2098 
2108 static int monster_wait_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
2109  int inrange = monster_can_hit(part, enemy, rv);
2110 
2111  if (ob->move_status || inrange)
2112  ob->move_status++;
2113 
2114  if (ob->move_status == 0)
2115  return 0;
2116  else if (ob->move_status < 10)
2117  return dir;
2118  else if (ob->move_status < 15)
2119  return absdir(dir+4);
2120  ob->move_status = 0;
2121  return 0;
2122 }
2123 
2133 static int monster_disthit_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
2134  /* The logic below here looked plain wrong before. Basically, what should
2135  * happen is that if the creatures hp percentage falls below run_away,
2136  * the creature should run away (dir+4)
2137  * I think its wrong for a creature to have a zero maxhp value, but
2138  * at least one map has this set, and whatever the map contains, the
2139  * server should try to be resilant enough to avoid the problem
2140  */
2141  if (ob->stats.maxhp && (ob->stats.hp*100)/ob->stats.maxhp < ob->run_away)
2142  return absdir(dir+4);
2143  return monster_dist_att(dir, enemy, part, rv);
2144 }
2145 
2152 static int monster_wait_att2(int dir, rv_vector *rv) {
2153  if (rv->distance < 9)
2154  return absdir(dir+4);
2155  return 0;
2156 }
2157 
2162 static void monster_circ1_move(object *ob) {
2163  static const int circle [12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 };
2164 
2165  if (++ob->move_status > 11)
2166  ob->move_status = 0;
2167  if (!(move_object(ob, circle[ob->move_status])))
2168  (void)move_object(ob, RANDOM()%8+1);
2169 }
2170 
2175 static void monster_circ2_move(object *ob) {
2176  static const int circle[20] = { 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 1, 1, 1, 2, 2 };
2177 
2178  if (++ob->move_status > 19)
2179  ob->move_status = 0;
2180  if (!(move_object(ob, circle[ob->move_status])))
2181  (void)move_object(ob, RANDOM()%8+1);
2182 }
2183 
2188 static void monster_pace_movev(object *ob) {
2189  if (ob->move_status++ > 6)
2190  ob->move_status = 0;
2191  if (ob->move_status < 4)
2192  (void)move_object(ob, 5);
2193  else
2194  (void)move_object(ob, 1);
2195 }
2196 
2201 static void monster_pace_moveh(object *ob) {
2202  if (ob->move_status++ > 6)
2203  ob->move_status = 0;
2204  if (ob->move_status < 4)
2205  (void)move_object(ob, 3);
2206  else
2207  (void)move_object(ob, 7);
2208 }
2209 
2214 static void monster_pace2_movev(object *ob) {
2215  if (ob->move_status++ > 16)
2216  ob->move_status = 0;
2217  if (ob->move_status < 6)
2218  (void)move_object(ob, 5);
2219  else if (ob->move_status < 8)
2220  return;
2221  else if (ob->move_status < 13)
2222  (void)move_object(ob, 1);
2223 }
2224 
2229 static void monster_pace2_moveh(object *ob) {
2230  if (ob->move_status++ > 16)
2231  ob->move_status = 0;
2232  if (ob->move_status < 6)
2233  (void)move_object(ob, 3);
2234  else if (ob->move_status < 8)
2235  return;
2236  else if (ob->move_status < 13)
2237  (void)move_object(ob, 7);
2238 }
2239 
2244 static void monster_rand_move(object *ob) {
2245  int i;
2246 
2247  // change direction when stuck, or 1/8 of the time
2248  if (ob->move_status < 1
2249  || ob->move_status > 8
2250  || !move_object(ob, ob->move_status) || (RANDOM()%9 == 0))
2251  // change direction
2252  for (i = 0; i < 5; i++) {
2253  ob->move_status = RANDOM()%8+1;
2254  if (move_object(ob, ob->move_status))
2255  return;
2256  }
2257 }
2258 
2264 static void shopkeeper_move(object *ob) {
2265  const bool debug = object_value_set(ob, key_shopkeeper_debug);
2266  char buf[MAX_BUF], buf2[MAX_BUF];
2267  const bool on_shop_tile = coords_in_shop(ob->map, ob->x, ob->y);
2268  // count number of visible, pickable items above floor
2269  int nbelow = 0;
2270  int cum_client_type = 0; // for calculating average client_type
2271  FOR_BELOW_PREPARE(ob, tmp) {
2272  if (!LOOK_OBJ(tmp) || QUERY_FLAG(tmp, FLAG_NO_PICK))
2273  continue;
2274  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
2275  break;
2276  if (QUERY_FLAG(tmp, FLAG_UNPAID) && !QUERY_FLAG(tmp, FLAG_UNIQUE) && !object_value_set(tmp, "price")) {
2277  // Belongs to shop, but we're no longer interested. Liquidate
2278  uint64_t price = price_base(tmp);
2279  if (ob->map->shopmin && price < ob->map->shopmin) {
2280  if (debug) {
2281  query_short_name(tmp, buf, sizeof(buf));
2282  snprintf(buf2, sizeof(buf2), "Liquidating %s (price %lu < shopmin %lu)", buf, price, ob->map->shopmin);
2283  monster_npc_say(ob, buf2);
2284  }
2285  object_remove(tmp);
2286  object_free(tmp, 0);
2287  continue;
2288  }
2289  }
2290  cum_client_type += tmp->client_type;
2291  nbelow++;
2292  } FOR_BELOW_FINISH();
2293 
2294  // Update running average
2295  float newavg = 0;
2296  if (on_shop_tile) {
2297  const char *curr = object_get_value(ob, key_shopkeeper_pilesize);
2298  float last = 1; // initial average pile size guess, if not set
2299  if (curr != NULL) {
2300  sscanf(curr, "%f", &last);
2301  }
2302  const float alpha = 1.0/50; // 1/(number of tiles to average over)
2303  newavg = alpha*nbelow + (1-alpha)*last;
2304  snprintf(buf, sizeof(buf), "%f", newavg);
2306  }
2307 
2308  if (debug) {
2309  snprintf(buf2, sizeof(buf2), "%d items below, shop avg %.1f", nbelow, newavg);
2310  monster_npc_say(ob, buf2);
2311  }
2312 
2313  // Keep shop tiles average or below and clear walkways
2314  const int want_pile = on_shop_tile ? MAX(1, newavg) : 0;
2315  if (nbelow > want_pile) {
2316  // pick up until the pile is smaller
2317  int npicked = 0;
2318  FOR_BELOW_PREPARE(ob, tmp) {
2319  if (!LOOK_OBJ(tmp) || QUERY_FLAG(tmp, FLAG_NO_PICK))
2320  continue;
2321  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
2322  break;
2323  if (pick_up(ob, tmp)) {
2324  npicked++;
2325  if (nbelow - npicked <= want_pile)
2326  break;
2327  }
2328  } FOR_BELOW_FINISH();
2329 
2330  if (debug) {
2331  snprintf(buf2, sizeof(buf2), "picked up %d items", npicked);
2332  monster_npc_say(ob, buf2);
2333  }
2334  } else if (on_shop_tile) {
2335  // Drop stuff on shop tiles
2336  int ndropped = 0;
2337  FOR_INV_PREPARE(ob, tmp) {
2338  // Skip our own spells, skills, etc.
2339  if (!LOOK_OBJ(tmp))
2340  continue;
2341 
2342  // Try to drop similar items based on client_type
2343  int dtype = 0;
2344  if (nbelow > 0)
2345  dtype = abs(tmp->client_type - cum_client_type/nbelow);
2346  dtype = MAX(1, dtype); // no divide by zero
2347  if (chance(50, dtype)) {
2348  drop(ob, tmp);
2349  ndropped++;
2350  if (nbelow + ndropped >= want_pile)
2351  break;
2352  }
2353  } FOR_INV_FINISH();
2354 
2355  if (debug) {
2356  snprintf(buf2, sizeof(buf2), "dropped %d items", ndropped);
2357  monster_npc_say(ob, buf2);
2358  }
2359  }
2360 
2361  monster_rand_move(ob);
2362 }
2363 
2371 void monster_check_earthwalls(object *op, mapstruct *m, int x, int y) {
2372  FOR_MAP_PREPARE(m, x, y, tmp)
2373  if (tmp->type == EARTHWALL) {
2374  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
2375  return;
2376  }
2377  FOR_MAP_FINISH();
2378 }
2379 
2387 void monster_check_doors(object *op, mapstruct *m, int x, int y) {
2388  FOR_MAP_PREPARE(m, x, y, tmp)
2389  if (tmp->type == DOOR) {
2390  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
2391  return;
2392  }
2393  FOR_MAP_FINISH();
2394 }
2395 
2401 void monster_do_say(const mapstruct *map, const char *message) {
2403  message);
2404 }
2405 
2412 static StringBuffer *monster_format_say(const object* npc, const char *message) {
2413  char name[MAX_BUF];
2414  StringBuffer *buf;
2415 
2416  query_name(npc, name, sizeof(name));
2417  buf = stringbuffer_new();
2418  stringbuffer_append_printf(buf, "%s says: %s", name, message);
2419  return buf;
2420 }
2421 
2428  switch (rt) {
2429  case rt_say:
2430  return "say";
2431  case rt_reply:
2432  return "reply";
2433  case rt_question:
2434  return "ask";
2435  }
2436  assert(0);
2437  return NULL;
2438 }
2439 
2445 static const char *get_reply_text_other(reply_type rt) {
2446  switch (rt) {
2447  case rt_say:
2448  return "says";
2449  case rt_reply:
2450  return "replies";
2451  case rt_question:
2452  return "asks";
2453  }
2454  assert(0);
2455  return NULL;
2456 }
2457 
2483 void monster_communicate(object *op, const char *txt) {
2484  int i, mflags;
2485  int16_t x, y;
2486  mapstruct *mp, *orig_map = op->map;
2487  char own[MAX_BUF], others[MAX_BUF];
2488  talk_info info;
2489 
2490  info.text = txt;
2491  info.message = NULL;
2492  info.replies_count = 0;
2493  info.who = op;
2494  info.npc_msg_count = 0;
2495 
2496  /* Note that this loop looks pretty inefficient to me - we look and try to talk
2497  * to every object within 2 spaces. It would seem that if we trim this down to
2498  * only try to talk to objects with npc->msg set, things would be a lot more efficient,
2499  * but I'm not sure if there are any objects out there that don't have a message and instead
2500  * rely sorely on events - MSW 2009-04-14
2501  */
2502  for (i = 0; i <= SIZEOFFREE2; i++) {
2503  mp = op->map;
2504  x = op->x+freearr_x[i];
2505  y = op->y+freearr_y[i];
2506 
2507  mflags = get_map_flags(mp, &mp, x, y, &x, &y);
2508  if (mflags&P_OUT_OF_MAP)
2509  continue;
2510 
2511  FOR_MAP_PREPARE(mp, x, y, npc) {
2512  monster_talk_to_npc(npc, &info);
2513  if (orig_map != op->map) {
2514  LOG(llevDebug, "Warning: Forced to swap out very recent map\n");
2515  return;
2516  }
2517  } FOR_MAP_FINISH();
2518  }
2519 
2520  /* First, what the player says. */
2521  if (info.message != NULL) {
2522  snprintf(own, sizeof(own), "You %s: %s", get_reply_text_own(info.message_type), info.message);
2523  snprintf(others, sizeof(others), "%s %s: %s", op->name, get_reply_text_other(info.message_type), info.message);
2524  free_string(info.message);
2525  } else {
2526  snprintf(own, sizeof(own), "You say: %s", txt);
2527  snprintf(others, sizeof(others), "%s says: %s", op->name, txt);
2528  }
2531 
2532  /* Then NPCs can actually talk. */
2533  for (i = 0; i < info.npc_msg_count; i++) {
2534  monster_do_say(orig_map, info.npc_msgs[i]);
2535  free_string(info.npc_msgs[i]);
2536  }
2537 
2538  /* Finally, the replies the player can use. */
2539  if (info.replies_count > 0) {
2541  for (i = 0; i < info.replies_count; i++) {
2543  free_string(info.replies_words[i]);
2544  free_string(info.replies[i]);
2545  }
2546  }
2547 }
2548 
2557 static int monster_do_talk_npc(object *npc, talk_info *info) {
2558  struct_dialog_reply *reply;
2560 
2561  if (!get_dialog_message(npc, info->text, &message, &reply))
2562  return 0;
2563 
2564  if (reply) {
2565  info->message = add_string(reply->message);
2566  info->message_type = reply->type;
2567  }
2568 
2569  if (message->identifies) {
2570  identify(npc);
2571  }
2572 
2573  if (npc->type == MAGIC_EAR) {
2575  use_trigger(npc);
2576  } else {
2577  char value[2];
2578 
2579  if (info->npc_msg_count < MAX_NPC) {
2581  info->npc_msg_count++;
2582  }
2583 
2584  /* mark that the npc was talked to, so it won't move randomly later on */
2585  value[0] = '3' + rand() % 6;
2586  value[1] = '\0';
2587  object_set_value(npc, "talked_to", value, 1);
2588 
2589  reply = message->replies;
2590  while (reply && info->replies_count < MAX_REPLIES) {
2591  info->replies[info->replies_count] = add_string(reply->message);
2592  info->replies_words[info->replies_count] = add_string(reply->reply);
2593  info->replies_count++;
2594  reply = reply->next;
2595  }
2596  }
2597 
2598  return 1;
2599 }
2600 
2606 void monster_npc_say(object *npc, const char *cp) {
2607  char *message;
2608  StringBuffer *buf = monster_format_say(npc, cp);
2609 
2611  monster_do_say(npc->map, message);
2612  free(message);
2613 }
2614 
2623 static int monster_talk_to_npc(object *npc, talk_info *info) {
2624  dialog_preparse(npc);
2625  if (events_execute_object_say(npc, info) != 0)
2626  return 0;
2627 
2628  /* Here we let the objects inside inventories hear and answer, too. */
2629  /* This allows the existence of "intelligent" weapons you can discuss with */
2630  FOR_INV_PREPARE(npc, cobj)
2631  if (events_execute_object_say(cobj, info) != 0)
2632  return 0;
2633  FOR_INV_FINISH();
2634  if (info->who == npc)
2635  return 0;
2636  return monster_do_talk_npc(npc, info);
2637 }
2638 
2651 object *monster_find_throw_ob(object *op) {
2652  /* New throw code: look through the inventory. Grap the first legal is_thrown
2653  * marked item and throw it to the enemy.
2654  */
2655 
2656  FOR_INV_PREPARE(op, tmp) {
2657  /* Can't throw invisible objects or items that are applied */
2658  if (!tmp->invisible && !QUERY_FLAG(tmp, FLAG_APPLIED) && QUERY_FLAG(tmp, FLAG_IS_THROWN)) {
2659 #ifdef DEBUG_THROW
2660  char what[MAX_BUF];
2661 
2662  query_name(tmp, what, MAX_BUF);
2663  LOG(llevDebug, "%s chooses to throw: %s (%d)\n", op->name, what, tmp->count);
2664 #endif
2665  return tmp;
2666  }
2667  } FOR_INV_FINISH();
2668 
2669 #ifdef DEBUG_THROW
2670  LOG(llevDebug, "%s chooses to throw nothing\n", op->name);
2671 #endif
2672  return NULL;
2673 }
2674 
2690 int monster_can_detect_enemy(object *op, object *enemy, rv_vector *rv) {
2691  int radius = MIN_MON_RADIUS, hide_discovery;
2692 
2693  /* null detection for any of these condtions always */
2694  if (!op || !enemy || !op->map || !enemy->map)
2695  return 0;
2696 
2697  /* If the monster (op) has no way to get to the enemy, do nothing */
2698  if (!get_rangevector(op, enemy, rv, 0))
2699  return 0;
2700 
2701  /* Monsters always ignore the DM */
2702  if (op->type != PLAYER && QUERY_FLAG(enemy, FLAG_WIZ))
2703  return 0;
2704 
2705  /* simple check. Should probably put some range checks in here. */
2706  if (monster_can_see_enemy(op, enemy))
2707  return 1;
2708 
2709  /* The rest of this is for monsters. Players are on their own for
2710  * finding enemies!
2711  */
2712  if (op->type == PLAYER)
2713  return 0;
2714 
2715  /* Quality invisible? Bah, we wont see them w/o SEE_INVISIBLE
2716  * flag (which was already checked) in can_see_enmy (). Lets get out of here
2717  */
2718  if (enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden)))
2719  return 0;
2720 
2721  /* use this for invis also */
2722  hide_discovery = op->stats.Int/5;
2723 
2724  /* Determine Detection radii */
2725  if (!enemy->hide) /* to detect non-hidden (eg dark/invis enemy) */
2726  radius = MAX(op->stats.Wis/5+1, MIN_MON_RADIUS);
2727  else { /* a level/INT/Dex adjustment for hiding */
2728  object *sk_hide;
2729  int bonus = (op->level/2)+(op->stats.Int/5);
2730 
2731  if (enemy->type == PLAYER) {
2732  sk_hide = find_skill_by_number(enemy, SK_HIDING);
2733  if (sk_hide != NULL)
2734  bonus -= sk_hide->level;
2735  else {
2736  LOG(llevError, "monster_can_detect_enemy() got hidden player w/o hiding skill!\n");
2737  make_visible(enemy);
2738  radius = MAX(radius, MIN_MON_RADIUS);
2739  }
2740  } else /* enemy is not a player */
2741  bonus -= enemy->level;
2742 
2743  radius += bonus/5;
2744  hide_discovery += bonus*5;
2745  } /* else creature has modifiers for hiding */
2746 
2747  /* Radii stealth adjustment. Only if you are stealthy
2748  * will you be able to sneak up closer to creatures */
2749  if (QUERY_FLAG(enemy, FLAG_STEALTH))
2750  radius = radius/2, hide_discovery = hide_discovery/3;
2751 
2752  /* Radii adjustment for enemy standing in the dark */
2753  if (op->map->darkness > 0 && !monster_stand_in_light(enemy)) {
2754  /* on dark maps body heat can help indicate location with infravision
2755  * undead don't have body heat, so no benefit detecting them.
2756  */
2757  if (QUERY_FLAG(op, FLAG_SEE_IN_DARK) && !is_true_undead(enemy))
2758  radius += op->map->darkness/2;
2759  else
2760  radius -= op->map->darkness/2;
2761 
2762  /* op next to a monster (and not in complete darkness)
2763  * the monster should have a chance to see you.
2764  */
2765  if (radius < MIN_MON_RADIUS && op->map->darkness < 5 && rv->distance <= 1)
2766  radius = MIN_MON_RADIUS;
2767  } /* if on dark map */
2768 
2769  /* Lets not worry about monsters that have incredible detection
2770  * radii, we only need to worry here about things the player can
2771  * (potentially) see. This is 13, as that is the maximum size the player
2772  * may have for their map - in that way, creatures at the edge will
2773  * do something. Note that the distance field in the
2774  * vector is real distance, so in theory this should be 18 to
2775  * find that.
2776  */
2777  if (radius > 13)
2778  radius = 13;
2779 
2780  /* Enemy in range! Now test for detection */
2781  if ((int)rv->distance <= radius) {
2782  /* ah, we are within range, detected? take cases */
2783  if (!enemy->invisible) /* enemy in dark squares... are seen! */
2784  return 1;
2785 
2786  /* hidden or low-quality invisible */
2787  if (enemy->hide && rv->distance <= 1 && RANDOM()%100 <= (unsigned int)hide_discovery) {
2788  make_visible(enemy);
2789  /* inform players of new status */
2790  if (enemy->type == PLAYER && player_can_view(enemy, op))
2792  "You are discovered by %s!",
2793  op->name);
2794  return 1; /* detected enemy */
2795  } else if (enemy->invisible) {
2796  /* Change this around - instead of negating the invisible, just
2797  * return true so that the mosnter that managed to detect you can
2798  * do something to you. Decreasing the duration of invisible
2799  * doesn't make a lot of sense IMO, as a bunch of stupid creatures
2800  * can then basically negate the spell. The spell isn't negated -
2801  * they just know where you are!
2802  */
2803  if (RANDOM()%50 <= (unsigned int)hide_discovery) {
2804  if (enemy->type == PLAYER) {
2805  char name[MAX_BUF];
2806 
2807  query_name(op, name, MAX_BUF);
2809  "You see %s noticing your position.",
2810  name);
2811  }
2812  return 1;
2813  }
2814  }
2815  } /* within range */
2816 
2817  /* Wasn't detected above, so still hidden */
2818  return 0;
2819 }
2820 
2830 static int monster_stand_in_light_internal(object *op) {
2831  if (!op)
2832  return 0;
2833  if (op->glow_radius > 0)
2834  return 1;
2835 
2836  if (op->map) {
2837  return map_light_on(op->map, op->x, op->y);
2838  }
2839  return 0;
2840 }
2841 
2845 int monster_stand_in_light(object *op) {
2846  if (!op)
2847  return 0;
2848 
2849  if (op->light_cached_time == pticks)
2850  return op->light_cached;
2851 
2852  int val = monster_stand_in_light_internal(op);
2853  op->light_cached = val;
2854  op->light_cached_time = pticks;
2855  return val;
2856 }
2857 
2867 int monster_can_see_enemy(object *op, object *enemy) {
2868  object *looker = HEAD(op);
2869 
2870  /* safety */
2871  if (!looker || !enemy || !QUERY_FLAG(looker, FLAG_ALIVE))
2872  return 0;
2873 
2874  /* we dont give a full treatment of xrays here (shorter range than normal,
2875  * see through walls). Should we change the code elsewhere to make you
2876  * blind even if you can xray?
2877  */
2878  if (QUERY_FLAG(looker, FLAG_BLIND) && !QUERY_FLAG(looker, FLAG_XRAYS))
2879  return 0;
2880 
2881  /* checking for invisible things */
2882  if (enemy->invisible) {
2883  /* HIDDEN ENEMY. by definition, you can't see hidden stuff!
2884  * However, if you carry any source of light, then the hidden
2885  * creature is seeable (and stupid) */
2886  if (has_carried_lights(enemy)) {
2887  if (enemy->hide) {
2888  make_visible(enemy);
2890  "Your light reveals your hiding spot!");
2891  }
2892  return 1;
2893  } else if (enemy->hide)
2894  return 0;
2895 
2896  /* Invisible enemy. Break apart the check for invis undead/invis looker
2897  * into more simple checks - the QUERY_FLAG doesn't return 1/0 values,
2898  * and making it a conditional makes the code pretty ugly.
2899  */
2900  if (!QUERY_FLAG(looker, FLAG_SEE_INVISIBLE)) {
2901  if (makes_invisible_to(enemy, looker))
2902  return 0;
2903  }
2904  } else if (looker->type == PLAYER) /* for players, a (possible) shortcut */
2905  if (player_can_view(looker, enemy))
2906  return 1;
2907 
2908  /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen
2909  * unless they carry a light or stand in light. Darkness doesnt
2910  * inhibit the undead per se (but we should give their archs
2911  * CAN_SEE_IN_DARK, this is just a safety
2912  * we care about the enemy maps status, not the looker.
2913  * only relevant for tiled maps, but it is possible that the
2914  * enemy is on a bright map and the looker on a dark - in that
2915  * case, the looker can still see the enemy
2916  */
2917  if (enemy->map->darkness > 0
2918  && !monster_stand_in_light(enemy)
2919  && (!QUERY_FLAG(looker, FLAG_SEE_IN_DARK) || !is_true_undead(looker) || !QUERY_FLAG(looker, FLAG_XRAYS)))
2920  return 0;
2921 
2922  return 1;
2923 }
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
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Gets the bottom object on a map.
Definition: map.h:173
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:443
FLAG_USE_BOW
#define FLAG_USE_BOW
(Monster) can apply and fire bows
Definition: define.h:280
FLAG_RUN_AWAY
#define FLAG_RUN_AWAY
Object runs away from nearest player \ but can still attack at a distance.
Definition: define.h:267
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:2214
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
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
MOVE_WALK
#define MOVE_WALK
Object walks.
Definition: define.h:383
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:714
FLAG_USE_RANGE
#define FLAG_USE_RANGE
(Monster) can apply and use range items
Definition: define.h:279
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
BOW
@ BOW
Definition: object.h:123
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
LOG
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
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:369
talk_info::npc_msg_count
int npc_msg_count
How many NPCs reacted to the text being said.
Definition: dialog.h:58
FLAG_USE_SCROLL
#define FLAG_USE_SCROLL
(Monster) can read scroll
Definition: define.h:278
monster_check_apply_all
void monster_check_apply_all(object *monster)
Calls monster_check_apply() for all inventory objects.
Definition: monster.cpp:2001
object::inv
object * inv
Pointer to the first object in the inventory.
Definition: object.h:298
HI4
#define HI4
Definition: define.h:515
WAIT2
#define WAIT2
Monster does not try to move towards player if far.
Definition: define.h:483
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:371
mapstruct::shopmin
uint64_t shopmin
Minimum price a shop will trade for.
Definition: map.h:352
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:2830
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:2133
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
FLAG_PARALYZED
#define FLAG_PARALYZED
Monster or player is paralyzed.
Definition: define.h:358
make_visible
void make_visible(object *op)
Makes an object visible again.
Definition: player.cpp:3982
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
pick_up
bool pick_up(object *op, object *alt)
Try to pick up an item.
Definition: c_object.cpp:470
AP_APPLY
#define AP_APPLY
Item is to be applied.
Definition: define.h:558
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:2729
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:233
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
IS_WEAPON
#define IS_WEAPON(op)
Definition: define.h:163
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
RANDO2
#define RANDO2
Constantly move in a different random direction.
Definition: define.h:507
FOR_BELOW_PREPARE
#define FOR_BELOW_PREPARE(op_, it_)
Constructs a loop iterating over all objects below an object.
Definition: define.h:688
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
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:1654
object::x
int16_t x
Definition: object.h:335
player::peaceful
uint32_t peaceful
If set, won't attack friendly creatures.
Definition: player.h:148
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
FLAG_USE_ARMOUR
#define FLAG_USE_ARMOUR
(Monster) can wear armour/shield/helmet
Definition: define.h:282
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:2075
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:2387
FLAG_BLIND
#define FLAG_BLIND
If set, object cannot see (visually)
Definition: define.h:323
SP_CONE
#define SP_CONE
Definition: spells.h:81
mapstruct::height
uint16_t height
Width and height of map.
Definition: map.h:340
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
WILL_APPLY_FOOD
#define WILL_APPLY_FOOD
Eat food (not drinks).
Definition: object.h:58
monster_check_pickup
static void monster_check_pickup(object *monster)
Checks for items that monster can pick up.
Definition: monster.cpp:1853
FLAG_WIZ
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:218
MIN
#define MIN(x, y)
Definition: compat.h:21
TREASURE
@ TREASURE
Definition: object.h:115
FLAG_SCARED
#define FLAG_SCARED
Monster is scared (mb player in future)
Definition: define.h:258
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:1701
FLAG_READY_RANGE
#define FLAG_READY_RANGE
(Monster) has a range attack readied...
Definition: define.h:285
object::count
tag_t count
Unique object number for this object.
Definition: object.h:307
FLAG_XRAYS
#define FLAG_XRAYS
X-ray vision.
Definition: define.h:287
AP_IGNORE_CURSE
#define AP_IGNORE_CURSE
Apply/unapply regardless of cursed/damned status.
Definition: define.h:566
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:510
FLAG_BERSERK
#define FLAG_BERSERK
monster will attack closest living object
Definition: define.h:339
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
PACEV
#define PACEV
The monster will pace back and forth until attacked.
Definition: define.h:508
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:493
LO4
#define LO4
bitmasks for upper and lower 4 bits from 8 bit fields
Definition: define.h:514
NDI_NAVY
#define NDI_NAVY
Definition: newclient.h:248
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:1143
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:47
player::hidden
uint32_t hidden
If True, player (DM) is hidden from view.
Definition: player.h:149
object::enemy
object * enemy
Monster/player to follow even if not closest.
Definition: object.h:391
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:15
FLAG_STEALTH
#define FLAG_STEALTH
Will wake monsters with less range.
Definition: define.h:299
skills.h
rv_vector::part
object * part
Part we found.
Definition: map.h:378
FLAG_READY_BOW
#define FLAG_READY_BOW
not implemented yet
Definition: define.h:286
object::hide
uint8_t hide
The object is hidden, not invisible.
Definition: object.h:397
FLAG_CAST_SPELL
#define FLAG_CAST_SPELL
(Monster) can learn and cast spells
Definition: define.h:277
apply_manual
int apply_manual(object *op, object *tmp, int aflag)
Main apply handler.
Definition: apply.cpp:259
FOR_OB_AND_ABOVE_FINISH
#define FOR_OB_AND_ABOVE_FINISH()
Finishes FOR_OB_AND_ABOVE_PREPARE().
Definition: define.h:727
mapstruct::path
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:358
object::level
int16_t level
Level of creature or object.
Definition: object.h:361
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
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
FLAG_NO_ATTACK
#define FLAG_NO_ATTACK
monster don't attack
Definition: define.h:342
object::resist
int16_t resist[NROFATTACKS]
Resistance adjustments for attacks.
Definition: object.h:351
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
mapstruct::width
uint16_t width
Definition: map.h:340
FLAG_REMOVED
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:219
monster_rand_move
static void monster_rand_move(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2244
talk_info::message
sstring message
If not NULL, what the player will be displayed as said.
Definition: dialog.h:53
FOR_BELOW_FINISH
#define FOR_BELOW_FINISH()
Finishes FOR_BELOW_PREPARE().
Definition: define.h:695
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
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:376
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:723
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:2152
FLAG_ALIVE
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:217
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:375
FLAG_SEE_INVISIBLE
#define FLAG_SEE_INVISIBLE
Will see invisible player.
Definition: define.h:240
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.cpp:76
FLAG_FREED
#define FLAG_FREED
Object is in the list of free objects.
Definition: define.h:220
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
DISTHIT
#define DISTHIT
Attack from a distance if hit as recommended by Frank.
Definition: define.h:482
FLAG_READY_SKILL
#define FLAG_READY_SKILL
(Monster or Player) has a skill readied
Definition: define.h:320
FLAG_NEUTRAL
#define FLAG_NEUTRAL
monster is from type neutral
Definition: define.h:341
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
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:2108
drop
void drop(object *op, object *tmp)
Drop an item, either on the floor or in a container.
Definition: c_object.cpp:1120
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:1680
FLAG_UNPAID
#define FLAG_UNPAID
Object hasn't been paid for yet.
Definition: define.h:223
query_name
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.cpp:594
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:1628
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
RUSH
#define RUSH
Rush toward player blindly, similiar to dumb monster.
Definition: define.h:480
DISTATT
#define DISTATT
Move toward a player if far, but maintain some space, attack from a distance - good for missile users...
Definition: define.h:475
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:2867
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:1507
add_string
sstring add_string(const char *str)
Share a string.
Definition: shstr.cpp:137
FLAG_MONSTER
#define FLAG_MONSTER
Will attack players.
Definition: define.h:232
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:1978
HEAD
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:607
FLAG_CAN_USE_SKILL
#define FLAG_CAN_USE_SKILL
The monster can use skills.
Definition: define.h:308
ROD
@ ROD
Definition: object.h:114
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Monster doesn't attack players.
Definition: define.h:259
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
path_measure_func
int path_measure_func(const void *ob)
Function to retrieve the measurement the minheap will organize by.
Definition: monster.cpp:439
SPELL_GRACE
#define SPELL_GRACE
Definition: spells.h:59
path_data::movement_penalty
int16_t movement_penalty
Definition: monster.cpp:427
monster_circ2_move
static void monster_circ2_move(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2175
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:2229
MAX_NPC
#define MAX_NPC
How many NPCs maximum will reply to the player.
Definition: dialog.h:45
player::tmp_invis
uint32_t tmp_invis
Will invis go away when we attack?
Definition: player.h:142
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:2201
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
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:195
CAN_APPLY_NOT_MASK
#define CAN_APPLY_NOT_MASK
Definition: define.h:616
FOR_INV_FINISH
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:661
FLAG_NO_PICK
#define FLAG_NO_PICK
Object can't be picked up.
Definition: define.h:226
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:678
monster_choose_random_spell
static object * monster_choose_random_spell(object *monster)
Selects a spell to cast for a monster.
Definition: monster.cpp:1229
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:504
P_OUT_OF_MAP
#define P_OUT_OF_MAP
This space is outside the map.
Definition: map.h:252
sproto.h
ARROW
@ ARROW
Definition: object.h:122
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:2351
rt_reply
@ rt_reply
Reply to something.
Definition: dialog.h:9
FLAG_IS_FLOOR
#define FLAG_IS_FLOOR
Can't see what's underneath this object.
Definition: define.h:289
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:1897
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:2412
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:2651
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
FLAG_RANDOM_MOVE
#define FLAG_RANDOM_MOVE
NPC will move randomly.
Definition: define.h:296
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:2090
monster_npc_call_help
void monster_npc_call_help(object *op)
A monster calls for help against its enemy.
Definition: monster.cpp:2014
SIZEOFFREE
#define SIZEOFFREE
Definition: define.h:155
FLAG_USE_WEAPON
#define FLAG_USE_WEAPON
(Monster) can wield weapons
Definition: define.h:283
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:1495
CIRCLE2
#define CIRCLE2
Same as CIRCLE1 but a larger circle is used.
Definition: define.h:497
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
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
PACEH
#define PACEH
The monster will pace back and forth until attacked.
Definition: define.h:498
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:294
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:628
FLAG_SEE_IN_DARK
#define FLAG_SEE_IN_DARK
if set ob not effected by darkness
Definition: define.h:324
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
SP_MAGIC_WALL
#define SP_MAGIC_WALL
Definition: spells.h:89
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
FLAG_ONLY_ATTACK
#define FLAG_ONLY_ATTACK
NPC will evaporate if there is no enemy.
Definition: define.h:297
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:707
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:220
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
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:500
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:1212
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
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:220
P_IS_ALIVE
#define P_IS_ALIVE
Something alive is on this space.
Definition: map.h:240
struct_dialog_reply::reply
char * reply
Reply expected from the player.
Definition: dialog.h:17
FLAG_SLEEP
#define FLAG_SLEEP
NPC is sleeping.
Definition: define.h:294
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:2162
object::glow_radius
int8_t glow_radius
indicates the glow radius of the object
Definition: object.h:374
spells.h
FLAG_GENERATOR
#define FLAG_GENERATOR
Will generate type ob->stats.food.
Definition: define.h:235
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
HITRUN
#define HITRUN
Run to then hit player then run away cyclicly.
Definition: define.h:478
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
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:2690
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
IS_SHIELD
#define IS_SHIELD(op)
Definition: define.h:170
monster_do_say
void monster_do_say(const mapstruct *map, const char *message)
Output a NPC message on a map.
Definition: monster.cpp:2401
WILL_APPLY_TREASURE
#define WILL_APPLY_TREASURE
Open chests.
Definition: object.h:55
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:318
object::last_sp
int32_t last_sp
As last_heal, but for spell points.
Definition: object.h:368
AP_NOPRINT
#define AP_NOPRINT
Don't print messages - caller will do that may be some that still print.
Definition: define.h:569
FLAG_IS_THROWN
#define FLAG_IS_THROWN
Object is designed to be thrown.
Definition: define.h:236
ALLRUN
#define ALLRUN
Always run, never attack good for sim.
Definition: define.h:481
sstring
const typedef char * sstring
Definition: sstring.h:2
shopkeeper_move
static void shopkeeper_move(object *ob)
Special move for shopkeepers.
Definition: monster.cpp:2264
FLAG_STAND_STILL
#define FLAG_STAND_STILL
NPC will not (ever) move.
Definition: define.h:295
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:1438
mapstruct::name
char * name
Name of map as given by its creator.
Definition: map.h:321
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
FLAG_APPLIED
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:222
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:1571
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:373
RUNATT
#define RUNATT
Run but attack if player catches up to object.
Definition: define.h:477
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:4059
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:2628
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:370
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
WILL_APPLY_HANDLE
#define WILL_APPLY_HANDLE
Apply handles and triggers.
Definition: object.h:54
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:2522
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:485
FLAG_READY_SCROLL
#define FLAG_READY_SCROLL
monster has scroll in inv and can use it
Definition: define.h:311
monster_pace_movev
static void monster_pace_movev(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.cpp:2188
FLAG_CONFUSED
#define FLAG_CONFUSED
Will also be unable to cast spells.
Definition: define.h:298
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:623
object::body_info
int8_t body_info[NUM_BODY_LOCATIONS]
Body info as loaded from the file.
Definition: object.h:382
AT_PHYSICAL
#define AT_PHYSICAL
Basic attack (1)
Definition: attack.h:78
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:2845
IS_ARMOR
#define IS_ARMOR(op)
Definition: define.h:166
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:4168
SP_SUMMON_GOLEM
#define SP_SUMMON_GOLEM
Definition: spells.h:86
MOVE_FLY_LOW
#define MOVE_FLY_LOW
Low flying object.
Definition: define.h:384
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:2606
key_shopkeeper
const char * key_shopkeeper
Definition: monster.cpp:61
FLAG_USE_SHIELD
#define FLAG_USE_SHIELD
Can this creature use a shield?
Definition: define.h:224
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:2623
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:1354
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
FLAG_USE_RING
#define FLAG_USE_RING
(Monster) can use rings, boots, gauntlets, etc
Definition: define.h:284
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
minheap_insert
int minheap_insert(MinHeap *heap, void *ob)
Inserts an element into the min-heap.
Definition: minheap.cpp:184
WAITATT
#define WAITATT
Wait for player to approach then hit, move if hit.
Definition: define.h:479
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:1267
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:339
living::Pow
int8_t Pow
Definition: living.h:36
SP_SWARM
#define SP_SWARM
Definition: spells.h:110
FLAG_UNIQUE
#define FLAG_UNIQUE
Item is really unique (UNIQUE_ITEMS)
Definition: define.h:274
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
rv_vector::direction
int direction
General direction to the targer.
Definition: map.h:377
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
SP_EXPLOSION
#define SP_EXPLOSION
Definition: spells.h:80
THROWN_OBJ
@ THROWN_OBJ
Definition: object.h:151
SK_THROWING
@ SK_THROWING
Throwing.
Definition: skills.h:44
rv_vector::distance
unsigned int distance
Distance, in squares.
Definition: map.h:374
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:2371
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:2427
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:2056
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:654
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:1186
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:2483
llevDebug
@ llevDebug
Only for debugging purposes.
Definition: logger.h:13
MONEY
@ MONEY
Definition: object.h:142
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:2557
monster_check_apply
static void monster_check_apply(object *mon, object *item)
Called after an item is inserted in a monster.
Definition: monster.cpp:1736
is_true_undead
int is_true_undead(object *op)
Is the object a true undead?
Definition: player.cpp:4001
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:2756
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:1294
SPELL_MANA
#define SPELL_MANA
Definition: spells.h:58
identify
object * identify(object *op)
Identifies an item.
Definition: item.cpp:1446
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:2445