Crossfire Server, Trunk  R20513
monster.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
20 #include "global.h"
21 
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "skills.h"
27 #include "spells.h"
28 #include "sproto.h"
29 
30 static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv);
31 static int monster_cast_spell(object *head, object *part, object *pl, int dir);
32 static int monster_use_scroll(object *head, object *part, object *pl, int dir);
33 static int monster_use_skill(object *head, object *part, object *pl, int dir);
34 static int monster_use_range(object *head, object *part, object *pl, int dir);
35 static int monster_use_bow(object *head, object *part, object *pl, int dir);
36 static void monster_check_pickup(object *monster);
37 static int monster_can_pick(object *monster, object *item);
38 static void monster_apply_below(object *monster);
39 static int monster_dist_att(int dir, object *enemy, object *part, rv_vector *rv);
40 static int monster_run_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv);
41 static int monster_hitrun_att(int dir, object *ob, object *enemy);
42 static int monster_wait_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv);
43 static int monster_disthit_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv);
44 static int monster_wait_att2(int dir, rv_vector *rv);
45 static void monster_circ1_move(object *ob);
46 static void monster_circ2_move(object *ob);
47 static void monster_pace_movev(object *ob);
48 static void monster_pace_moveh(object *ob);
49 static void monster_pace2_movev(object *ob);
50 static void monster_pace2_moveh(object *ob);
51 static void monster_rand_move(object *ob);
52 static int monster_talk_to_npc(object *npc, talk_info *info);
53 
55 #define MIN_MON_RADIUS 3
56 
71 object *monster_check_enemy(object *npc, rv_vector *rv) {
72  object *owner;
73 
74  /* if this is pet, let him attack the same enemy as his owner
75  * TODO: when there is no ower enemy, try to find a target,
76  * which CAN attack the owner. */
77  owner = object_get_owner(npc);
78  if ((npc->attack_movement&HI4) == PETMOVE) {
79  if (owner == NULL)
80  object_set_enemy(npc, NULL);
81  else if (npc->enemy == NULL)
82  object_set_enemy(npc, owner->enemy);
83  }
84 
85  /* periodically, a monster may change its target. Also, if the object
86  * has been destroyed, etc, clear the enemy.
87  * TODO: this should be changed, because it invokes to attack forced or
88  * attacked monsters to leave the attacker alone, before it is destroyed
89  */
90  /* i had removed the random target leave, this invokes problems with friendly
91  * objects, getting attacked and defending herself - they don't try to attack
92  * again then but perhaps get attack on and on
93  * If we include a aggravated flag in , we can handle evil vs evil and good vs good
94  * too. */
95 
96  if (npc->enemy) {
97  /* I broke these if's apart to better be able to see what
98  * the grouping checks are. Code is the same.
99  */
100  if (QUERY_FLAG(npc->enemy, FLAG_REMOVED)
101  || QUERY_FLAG(npc->enemy, FLAG_FREED)
102  || !on_same_map(npc, npc->enemy)
103  || npc == npc->enemy
104  || QUERY_FLAG(npc, FLAG_NEUTRAL)
105  || QUERY_FLAG(npc->enemy, FLAG_NEUTRAL))
106  object_set_enemy(npc, NULL);
107 
108  else if (QUERY_FLAG(npc, FLAG_FRIENDLY) && (
109  (QUERY_FLAG(npc->enemy, FLAG_FRIENDLY) && !pets_should_arena_attack(npc, owner, npc->enemy))
110  || (npc->enemy->type == PLAYER && !pets_should_arena_attack(npc, owner, npc->enemy))
111  || npc->enemy == owner))
112  object_set_enemy(npc, NULL);
113  else if (!QUERY_FLAG(npc, FLAG_FRIENDLY)
114  && (!QUERY_FLAG(npc->enemy, FLAG_FRIENDLY) && npc->enemy->type != PLAYER))
115  object_set_enemy(npc, NULL);
116 
117  /* I've noticed that pets could sometimes get an arrow as the
118  * target enemy - this code below makes sure the enemy is something
119  * that should be attacked. My guess is that the arrow hits
120  * the creature/owner, and so the creature then takes that
121  * as the enemy to attack.
122  */
123  else if (!QUERY_FLAG(npc->enemy, FLAG_MONSTER)
124  && !QUERY_FLAG(npc->enemy, FLAG_GENERATOR)
125  && npc->enemy->type != PLAYER
126  && npc->enemy->type != GOLEM)
127  object_set_enemy(npc, NULL);
128  }
129  return monster_can_detect_enemy(npc, npc->enemy, rv) ? npc->enemy : NULL;
130 }
131 
153  int i, mflags;
154  int16_t nx, ny;
155  mapstruct *m;
156  int search_arr[SIZEOFFREE];
157 
158  get_search_arr(search_arr);
159  for (i = 0; i < SIZEOFFREE; i++) {
160  /* modified to implement smart searching using search_arr
161  * guidance array to determine direction of search order
162  */
163  nx = npc->x+freearr_x[search_arr[i]];
164  ny = npc->y+freearr_y[search_arr[i]];
165  m = npc->map;
166 
167  mflags = get_map_flags(m, &m, nx, ny, &nx, &ny);
168  if (mflags&P_OUT_OF_MAP)
169  continue;
170 
171  if (mflags&P_IS_ALIVE) {
172  object *creature;
173 
174  creature = NULL;
175  FOR_MAP_PREPARE(m, nx, ny, tmp)
176  if (QUERY_FLAG(tmp, FLAG_MONSTER)
177  || QUERY_FLAG(tmp, FLAG_GENERATOR)
178  || tmp->type == PLAYER) {
179  creature = tmp;
180  break;
181  }
182  FOR_MAP_FINISH();
183  if (!creature) {
184  LOG(llevDebug, "monster_find_nearest_living_creature: map %s (%d,%d) has is_alive set but did not find a monster?\n", m->path, nx, ny);
185  } else {
186  if (can_see_monsterP(m, nx, ny, i))
187  return creature;
188  }
189  } /* is something living on this space */
190  }
191  return NULL; /* nothing found */
192 }
193 
209 static object *monster_find_enemy(object *npc, rv_vector *rv) {
210  object *attacker, *tmp = NULL;
211 
212  attacker = npc->attacked_by; /* save this for later use. This can be a attacker. */
213  npc->attacked_by = NULL; /* always clear the attacker entry */
214 
215  /* if we berserk, we don't care about others - we attack all we can find */
216  if (QUERY_FLAG(npc, FLAG_BERSERK)) {
218  if (tmp == NULL)
219  return NULL;
220  if (!get_rangevector(npc, tmp, rv, 0))
221  return NULL;
222  return tmp;
223  }
224 
225  /* Here is the main enemy selection.
226  * We want this: if there is an enemy, attack him until its not possible or
227  * one of both is dead.
228  * If we have no enemy and we are...
229  * a monster: try to find a player, a pet or a friendly monster
230  * a friendly: only target a monster which is targeting you first or targeting a player
231  * a neutral: fight a attacker (but there should be none), then do nothing
232  * a pet: attack player enemy or a monster
233  */
234 
235  /* pet move */
236  if ((npc->attack_movement&HI4) == PETMOVE) {
237  tmp = pets_get_enemy(npc, rv);
238  if (tmp == NULL)
239  return NULL;
240  if (!get_rangevector(npc, tmp, rv, 0))
241  return NULL;
242  return tmp;
243  }
244 
245  /* we check our old enemy. */
246  tmp = monster_check_enemy(npc, rv);
247  if (tmp == NULL) {
248  if (attacker) { /* if we have an attacker, check him */
249  /* we want be sure this is the right one! */
250  if (attacker->count == npc->attacked_by_count) {
251  /* TODO: thats not finished */
252  /* we don't want a fight evil vs evil or good against non evil */
253  if (QUERY_FLAG(npc, FLAG_NEUTRAL)
254  || QUERY_FLAG(attacker, FLAG_NEUTRAL) /* neutral */
255  || (QUERY_FLAG(npc, FLAG_FRIENDLY) && QUERY_FLAG(attacker, FLAG_FRIENDLY))
256  || (!QUERY_FLAG(npc, FLAG_FRIENDLY) && (!QUERY_FLAG(attacker, FLAG_FRIENDLY) && attacker->type != PLAYER)))
257  CLEAR_FLAG(npc, FLAG_SLEEP); /* skip it, but lets wakeup */
258  else if (on_same_map(npc, attacker)) { /* thats the only thing we must know... */
259  CLEAR_FLAG(npc, FLAG_SLEEP); /* well, NOW we really should wake up! */
260  object_set_enemy(npc, attacker);
261  if (!get_rangevector(npc, attacker, rv, 0))
262  return NULL;
263  return attacker; /* yes, we face our attacker! */
264  }
265  }
266  }
267 
268  /* we have no legal enemy or attacker, so we try to target a new one */
269  if (!QUERY_FLAG(npc, FLAG_UNAGGRESSIVE)
270  && !QUERY_FLAG(npc, FLAG_FRIENDLY)
271  && !QUERY_FLAG(npc, FLAG_NEUTRAL)) {
273  if (npc->enemy)
274  tmp = monster_check_enemy(npc, rv);
275  }
276  }
277 
278  return tmp;
279 }
280 
296 static int monster_check_wakeup(object *op, object *enemy, rv_vector *rv) {
297  int radius = MAX(op->stats.Wis, MIN_MON_RADIUS);
298 
299  /* Trim work - if no enemy, no need to do anything below */
300  if (!enemy)
301  return 0;
302 
303  /* blinded monsters can only find nearby objects to attack */
304  if (QUERY_FLAG(op, FLAG_BLIND))
305  radius = MIN_MON_RADIUS;
306 
307  /* This covers the situation where the monster is in the dark
308  * and has an enemy. If the enemy has no carried light (or isnt
309  * glowing!) then the monster has trouble finding the enemy.
310  * Remember we already checked to see if the monster can see in
311  * the dark. */
312  else if (op->map
313  && op->map->darkness > 0
314  && enemy
315  && !enemy->invisible
316  && !monster_stand_in_light(enemy)
318  int dark = radius/(op->map->darkness);
319 
320  radius = (dark > MIN_MON_RADIUS) ? (dark+1) : MIN_MON_RADIUS;
321  } else if (!QUERY_FLAG(op, FLAG_SLEEP))
322  return 1;
323 
324  /* enemy should already be on this map, so don't really need to check
325  * for that.
326  */
327  if (rv->distance < (unsigned)(QUERY_FLAG(enemy, FLAG_STEALTH) ? radius/2+1 : radius)) {
328  CLEAR_FLAG(op, FLAG_SLEEP);
329  return 1;
330  }
331  return 0;
332 }
333 
342 static int monster_move_randomly(object *op) {
343  int i;
344  sstring talked;
345  char value[2];
346 
347  /* timeout before moving */
348  if (QUERY_FLAG(op, FLAG_UNAGGRESSIVE)) {
349  talked = object_get_value(op, "talked_to");
350  if (talked && strlen(talked) > 0) {
351  i = atoi(talked);
352  i--;
353 
354  if (i != 0) {
355  value[1] = '\0';
356  value[0] = '0' + i;
357  object_set_value(op, "talked_to", value, 1);
358  return 1;
359  }
360 
361  /* finished timeout talked to */
362  object_set_value(op, "talked_to", "", 1);
363  }
364  }
365 
366  /* Give up to 15 chances for a monster to move randomly */
367  for (i = 0; i < 15; i++) {
368  if (move_object(op, RANDOM()%8+1))
369  return 1;
370  }
371  return 0;
372 }
373 
375 #define MAX_EXPLORE 5000
376 
391 int monster_compute_path(object *source, object *target, int default_dir) {
392  unsigned short *distance;
393  int explore_x[MAX_EXPLORE], explore_y[MAX_EXPLORE], dirs[8];
394  int current = 0, dir, max = 1, x, y, i;
395 
396  if (target->map != source->map)
397  return default_dir;
398 
399  /*printf("monster_compute_path (%d, %d) => (%d, %d)\n", source->x, source->y, target->x, target->y);*/
400 
401  const int size = source->map->width*source->map->height;
402  /* We are setting all the values manually anyway,
403  * so there's no reason to use calloc().
404  * malloc() is more efficient here for that reason.
405  */
406  distance = malloc(size * sizeof(*distance));
407  if (distance == NULL) {
409  }
410  /*
411  * 999 seems to be an arbitrary intializer.
412  * 65535 can be set more efficiently.
413  *
414  for (dir = 0; dir < size; ++dir) {
415  distance[dir] = 999;
416  }
417  *
418  * To set to 65535 efficiently, though, I need to memset each byte to 255.
419  * each element is two bytes,
420  */
421  memset(distance, 255, sizeof(*distance) * size);
422 
423  distance[source->map->height * target->x + target->y] = 0;
424  explore_x[0] = target->x;
425  explore_y[0] = target->y;
426 
427  /* The first time through, current = 0 and max = 1.
428  * This will evaluate to true, so we might as well use a do-while loop.
429  */
430  do {
431  /* Fisher–Yates shuffle the directions, "inside-out" algorithm
432  * from http://en.wikipedia.org/wiki/Fisher-Yates_shuffle */
433  dirs[0] = 1;
434  for (i = 1; i < 8; ++i) {
435  x = RANDOM() % (i+1);
436  dirs[i] = dirs[x];
437  dirs[x] = i+1;
438  }
439 
440  for (i = 0; i < 8; ++i) {
441  unsigned short new_distance;
442 
443  /*
444  * dirs[i] is the direction we wish to check.
445  */
446  dir = absdir(default_dir+4+dirs[i]);
447  x = explore_x[current]+freearr_x[dir];
448  y = explore_y[current]+freearr_y[dir];
449 
450  if (x == source->x && y == source->y) {
451  free(distance);
452  return absdir(dir+4);
453  }
454 
455  if (OUT_OF_REAL_MAP(source->map, x, y))
456  continue;
457  if (ob_blocked(source, source->map, x, y))
458  continue;
459 
460  assert(source->map->height*x+y >= 0);
461  assert(source->map->height*x+y < size);
462 
463  new_distance =
464  distance[source->map->height*explore_x[current]+explore_y[current]]
465  /* Mod 2 is equivalent to checking only the 1's bit (1 or 0), but & 1 is faster.
466  * Also, dir & 1 == 0 is true if we have a diagonal dir.
467  */
468  + ((dir & 1) == 0 ? 3 : 2);
469 
470  /*LOG(llevDebug, "check %d, %d dist = %d, nd = %d\n", x, y, distance[source->map->height*x+y], new_distance);*/
471 
472  if (distance[source->map->height*x+y] > new_distance) {
473  assert(max < MAX_EXPLORE);
474  explore_x[max] = x;
475  explore_y[max] = y;
476 
477  distance[source->map->height*x+y] = new_distance;
478  /* printf("explore[%d] => (%d, %d) %u\n", max, x, y, new_distance);*/
479  ++max;
480  if (max == MAX_EXPLORE) {
481  free(distance);
482  return default_dir;
483  }
484  }
485  }
486  ++current;
487  } while (current < max);
488 
489  /*LOG(llevDebug, "no path\n");*/
490  free(distance);
491  return default_dir;
492 }
493 
500 void monster_do_living(object *op) {
501  assert(op);
502  assert(QUERY_FLAG(op, FLAG_MONSTER));
503 
504  /* generate hp, if applicable */
505  if (op->stats.Con > 0 && op->stats.hp < op->stats.maxhp) {
506  /* last heal is in funny units. Dividing by speed puts
507  * the regeneration rate on a basis of time instead of
508  * #moves the monster makes. The scaling by 8 is
509  * to capture 8th's of a hp fraction regens
510  *
511  * Cast to int32_t before comparing to maxhp since otherwise an (int16_t)
512  * overflow might produce monsters with negative hp.
513  */
514 
515  op->last_heal += (int)((float)(8*op->stats.Con)/FABS(op->speed));
516  op->stats.hp = MIN((int32_t)op->stats.hp+op->last_heal/32, op->stats.maxhp); /* causes Con/4 hp/tick */
517  op->last_heal %= 32;
518 
519  /* So if the monster has gained enough HP that they are no longer afraid */
520  if (QUERY_FLAG(op, FLAG_RUN_AWAY)
521  && op->stats.hp >= (int16_t)((int32_t)op->run_away * op->stats.maxhp / 100))
523  /*
524  * This should already be covered by the MIN() check above.
525 
526  if (op->stats.hp > op->stats.maxhp)
527  op->stats.hp = op->stats.maxhp;
528  */
529  }
530 
531  /* generate sp, if applicable */
532  if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp) {
533  /* last_sp is in funny units. Dividing by speed puts
534  * the regeneration rate on a basis of time instead of
535  * #moves the monster makes. The scaling by 8 is
536  * to capture 8th's of a sp fraction regens
537  *
538  * Cast to int32_t before comparing to maxhp since otherwise an (int16_t)
539  * overflow might produce monsters with negative sp.
540  */
541 
542  op->last_sp += (int)((float)(8*op->stats.Pow)/FABS(op->speed));
543  op->stats.sp = MIN(op->stats.sp+op->last_sp/128, op->stats.maxsp); /* causes Pow/16 sp/tick */
544  op->last_sp %= 128;
545  }
546 
547  /* this should probably get modified by many more values.
548  * (eg, creatures resistance to fear, level, etc. )
549  */
550  if (QUERY_FLAG(op, FLAG_SCARED) && !(RANDOM()%20)) {
551  CLEAR_FLAG(op, FLAG_SCARED); /* Time to regain some "guts"... */
552  }
553 }
554 
563 static int monster_move_no_enemy(object *op) {
564  assert(QUERY_FLAG(op, FLAG_MONSTER));
565 
566  if (QUERY_FLAG(op, FLAG_ONLY_ATTACK)) {
567  object_remove(op);
569  return 1;
570  }
571 
572  /* Probably really a bug for a creature to have both
573  * stand still and a movement type set.
574  */
575  if (!QUERY_FLAG(op, FLAG_STAND_STILL)) {
576  if (op->attack_movement&HI4) {
577  switch (op->attack_movement&HI4) {
578  case PETMOVE:
579  pets_move(op);
580  break;
581 
582  case CIRCLE1:
583  monster_circ1_move(op);
584  break;
585 
586  case CIRCLE2:
587  monster_circ2_move(op);
588  break;
589 
590  case PACEV:
591  monster_pace_movev(op);
592  break;
593 
594  case PACEH:
595  monster_pace_moveh(op);
596  break;
597 
598  case PACEV2:
600  break;
601 
602  case PACEH2:
604  break;
605 
606  case RANDO:
607  monster_rand_move(op);
608  break;
609 
610  case RANDO2:
612  break;
613  }
614  return 0;
615  }
616 
617  if (QUERY_FLAG(op, FLAG_RANDOM_MOVE))
619  } /* stand still */
620 
621  return 0;
622 }
623 
635 int monster_move(object *op) {
636  int dir, diff;
637  object *owner, *enemy, *part;
638  rv_vector rv;
639 
640  /* Monsters not on maps don't do anything. These monsters are things
641  * Like royal guards in city dwellers inventories.
642  */
643  if (!op->map)
644  return 0;
645 
646  if (QUERY_FLAG(op, FLAG_NO_ATTACK)) { /* we never ever attack */
647  object_set_enemy(op, NULL);
648  enemy = NULL;
649  } else {
650  enemy = monster_find_enemy(op, &rv);
651  if (enemy != NULL) {
652  /* we have an enemy, just tell him we want him dead */
653  enemy->attacked_by = op; /* our ptr */
654  enemy->attacked_by_count = op->count; /* our tag */
655  }
656  }
657 
658  monster_do_living(op);
659 
660  if (QUERY_FLAG(op, FLAG_SLEEP)
661  || QUERY_FLAG(op, FLAG_BLIND)
662  || (op->map->darkness > 0 && !QUERY_FLAG(op, FLAG_SEE_IN_DARK) && !QUERY_FLAG(op, FLAG_SEE_INVISIBLE))) {
663  if (!monster_check_wakeup(op, enemy, &rv))
664  return 0;
665  }
666 
667  /* check if monster pops out of hidden spot */
668  if (op->hide)
669  do_hidden_move(op);
670 
671  if (op->pick_up)
673 
674  if (op->will_apply)
675  monster_apply_below(op); /* Check for items to apply below */
676 
677  /* If we don't have an enemy, do special movement or the like */
678  if (!enemy) {
679  return monster_move_no_enemy(op);
680  } /* no enemy */
681 
682  /* We have an enemy. Block immediately below is for pets */
683  if ((op->attack_movement&HI4) == PETMOVE) {
684  owner = object_get_owner(op);
685  if (owner != NULL && !on_same_map(op, owner)) {
686  pets_follow_owner(op, owner);
687  /* If the pet was unable to follow the owner, free it */
688  if (QUERY_FLAG(op, FLAG_REMOVED) && FABS(op->speed) > MIN_ACTIVE_SPEED) {
691  return 1;
692  }
693  return 0;
694  }
695  }
696 
697  /* doppleganger code to change monster facing to that of the nearest
698  * player. Hmm. The code is here, but no monster in the current
699  * arch set uses it.
700  */
701  if (op->race != NULL && strcmp(op->race, "doppleganger") == 0) {
702  op->face = enemy->face;
703  if (op->name)
704  free_string(op->name);
705  add_refcount(op->name = enemy->name);
706  }
707 
708  /* Calculate range information for closest body part - this
709  * is used for the 'skill' code, which isn't that smart when
710  * it comes to figuring it out - otherwise, giants throw boulders
711  * into themselves.
712  */
713  if (!get_rangevector(op, enemy, &rv, 0))
714  return 0;
715  if (op->direction != rv.direction) {
716  op->direction = rv.direction;
717  op->facing = op->direction;
718  if (op->animation_id)
719  animate_object(op, op->direction);
720  }
721 
722  // We are looking at movement -- if monster was paralyzed, they aren't anymore
723  if (QUERY_FLAG(op, FLAG_PARALYZED)) {
725  }
726 
727  /* Move the check for scared up here - if the monster was scared,
728  * we were not doing any of the logic below, so might as well save
729  * a few cpu cycles.
730  */
731  if (!QUERY_FLAG(op, FLAG_SCARED)) {
732  dir = rv.direction;
733 
734  /* Was two if statements assigning to the same variable
735  * We can get the same effect by reversing the order and making an else-if
736  */
737  if (QUERY_FLAG(op, FLAG_CONFUSED))
738  dir = get_randomized_dir(dir);
739  else if (QUERY_FLAG(op, FLAG_RUN_AWAY))
740  dir = absdir(dir+4);
741 
742  if (QUERY_FLAG(op, FLAG_CAST_SPELL) && !(RANDOM()%3)) {
743  if (monster_cast_spell(op, rv.part, enemy, dir))
744  return 0;
745  }
746 
747  if (QUERY_FLAG(op, FLAG_READY_SCROLL) && !(RANDOM()%3)) {
748  if (monster_use_scroll(op, rv.part, enemy, dir))
749  return 0;
750  }
751 
752  if (QUERY_FLAG(op, FLAG_READY_RANGE) && !(RANDOM()%3)) {
753  if (monster_use_range(op, rv.part, enemy, dir))
754  return 0;
755  }
756  if (QUERY_FLAG(op, FLAG_READY_SKILL) && !(RANDOM()%3)) {
757  if (monster_use_skill(op, rv.part, enemy, rv.direction))
758  return 0;
759  }
760  if (QUERY_FLAG(op, FLAG_READY_BOW) && !(RANDOM()%2)) {
761  if (monster_use_bow(op, rv.part, enemy, dir))
762  return 0;
763  }
764  } /* If not scared */
765 
766 
767  /* code below is for when we didn't use a range attack or a skill, so
768  * either move or hit with hth attack. */
769 
770  part = rv.part;
771  dir = rv.direction;
772 
773  /* This first clause used to happen after the other two, but would trample dir.
774  * Moved to before them as another check to slightly reduce calls to monster_compute_path
775  */
776  if (QUERY_FLAG(op, FLAG_CONFUSED))
777  dir = get_randomized_dir(dir);
778  else if (QUERY_FLAG(op, FLAG_SCARED) || QUERY_FLAG(op, FLAG_RUN_AWAY))
779  dir = absdir(dir+4);
780  else if (!monster_can_hit(part, enemy, &rv))
781  dir = monster_compute_path(op, enemy, rv.direction);
782 
783  if ((op->attack_movement&LO4) && !QUERY_FLAG(op, FLAG_SCARED)) {
784  switch (op->attack_movement&LO4) {
785  case DISTATT:
786  dir = monster_dist_att(dir, enemy, part, &rv);
787  break;
788 
789  case RUNATT:
790  dir = monster_run_att(dir, op, enemy, part, &rv);
791  break;
792 
793  case HITRUN:
794  dir = monster_hitrun_att(dir, op, enemy);
795  break;
796 
797  case WAITATT:
798  dir = monster_wait_att(dir, op, enemy, part, &rv);
799  break;
800 
801  case RUSH: /* default - monster normally moves towards player */
802  case ALLRUN:
803  break;
804 
805  case DISTHIT:
806  dir = monster_disthit_att(dir, op, enemy, part, &rv);
807  break;
808 
809  case WAIT2:
810  dir = monster_wait_att2(dir, &rv);
811  break;
812 
813  default:
814  LOG(llevDebug, "Illegal low mon-move: %d\n", op->attack_movement&LO4);
815  }
816  }
817 
818  if (!dir)
819  return 0;
820 
821  if (!QUERY_FLAG(op, FLAG_STAND_STILL)) {
822  if (move_object(op, dir)) /* Can the monster move directly toward player? */
823  return 0;
824 
825  if (QUERY_FLAG(op, FLAG_SCARED)
826  || !monster_can_hit(part, enemy, &rv)
827  || QUERY_FLAG(op, FLAG_RUN_AWAY)) {
828  /* Try move around corners if !close */
829  int maxdiff = (QUERY_FLAG(op, FLAG_ONLY_ATTACK) || RANDOM()&1) ? 1 : 2;
830  for (diff = 1; diff <= maxdiff; diff++) {
831  /* try different detours */
832  int m = 1-(RANDOM()&2); /* Try left or right first? */
833  if (move_object(op, absdir(dir+diff*m))
834  || move_object(op, absdir(dir-diff*m)))
835  return 0;
836  }
837  }
838  } /* if monster is not standing still */
839 
840  /*
841  * Eneq(@csd.uu.se): Patch to make RUN_AWAY or SCARED monsters move a random
842  * direction if they can't move away.
843  */
844  if (!QUERY_FLAG(op, FLAG_ONLY_ATTACK)
846  if (monster_move_randomly(op))
847  return 0;
848 
849  /*
850  * Try giving the monster a new enemy - the player that is closest
851  * to it. In this way, it won't just keep trying to get to a target
852  * that is inaccessible.
853  * This could be more clever - it should go through a list of several
854  * enemies, as it is now, you could perhaps get situations where there
855  * are two players flanking the monster at close distance, but which
856  * the monster can't get to, and a third one at a far distance that
857  * the monster could get to - as it is, the monster won't look at that
858  * third one.
859  */
860  if (!QUERY_FLAG(op, FLAG_FRIENDLY) && enemy == op->enemy) {
861  object *nearest_player = get_nearest_player(op);
862 
863  if (nearest_player && nearest_player != enemy && !monster_can_hit(part, enemy, &rv)) {
864  object_set_enemy(op, NULL);
865  enemy = nearest_player;
866  }
867  }
868 
869  if (!QUERY_FLAG(op, FLAG_SCARED) && monster_can_hit(part, enemy, &rv)) {
870  /* The adjustement to wc that was here before looked totally bogus -
871  * since wc can in fact get negative, that would mean by adding
872  * the current wc, the creature gets better? Instead, just
873  * add a fixed amount - nasty creatures that are runny away should
874  * still be pretty nasty.
875  */
876  if (QUERY_FLAG(op, FLAG_RUN_AWAY)) {
877  part->stats.wc += 10;
878  skill_attack(enemy, part, 0, NULL, NULL);
879  part->stats.wc -= 10;
880  } else
881  skill_attack(enemy, part, 0, NULL, NULL);
882  } /* if monster is in attack range */
883 
884  if (QUERY_FLAG(part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */
885  return 1;
886 
887  if (QUERY_FLAG(op, FLAG_ONLY_ATTACK)) {
888  object_remove(op);
890  return 1;
891  }
892  return 0;
893 }
894 
909 static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv) {
910  object *more;
911  rv_vector rv1;
912 
913  if (QUERY_FLAG(ob1, FLAG_CONFUSED) && !(RANDOM()%3))
914  return 0;
915 
916  if (abs(rv->distance_x) < 2 && abs(rv->distance_y) < 2)
917  return 1;
918 
919  /* check all the parts of ob2 - just because we can't get to
920  * its head doesn't mean we don't want to pound its feet
921  */
922  for (more = ob2->more; more != NULL; more = more->more) {
923  if (get_rangevector(ob1, more, &rv1, 0)
924  && abs(rv1.distance_x) < 2 && abs(rv1.distance_y) < 2)
925  return 1;
926  }
927  return 0;
928 }
929 
952 static int monster_should_cast_spell(object *spell_ob) {
953  /* The caller is responsible for making sure that *spell_ob is defined. */
954  assert(spell_ob != NULL);
955 
956  if (spell_ob->subtype == SP_BOLT
957  || spell_ob->subtype == SP_BULLET
958  || spell_ob->subtype == SP_EXPLOSION
959  || spell_ob->subtype == SP_CONE
960  || spell_ob->subtype == SP_BOMB
961  || spell_ob->subtype == SP_SMITE
962  || spell_ob->subtype == SP_MAGIC_MISSILE
963  || spell_ob->subtype == SP_SUMMON_GOLEM
964  || spell_ob->subtype == SP_MAGIC_WALL
965  || spell_ob->subtype == SP_SUMMON_MONSTER
966  || spell_ob->subtype == SP_MOVING_BALL
967  || spell_ob->subtype == SP_SWARM
968  || spell_ob->subtype == SP_INVISIBLE)
969  return 1;
970 
971  return 0;
972 }
973 
975 #define MAX_KNOWN_SPELLS 20
976 
992 static object *monster_choose_random_spell(object *monster) {
993  object *altern[MAX_KNOWN_SPELLS];
994  int i = 0;
995 
996  FOR_INV_PREPARE(monster, tmp)
997  if (tmp->type == SPELLBOOK || tmp->type == SPELL) {
998  /* Check and see if it's actually a useful spell.
999  * If its a spellbook, the spell is actually the inventory item.
1000  * if it is a spell, then it is just the object itself.
1001  */
1002  if (monster_should_cast_spell(tmp->type == SPELLBOOK ? tmp->inv : tmp)) {
1003  altern[i++] = tmp;
1004  if (i == MAX_KNOWN_SPELLS)
1005  break;
1006  }
1007  }
1008  FOR_INV_FINISH();
1009  if (!i)
1010  return NULL;
1011  return altern[RANDOM()%i];
1012 }
1013 
1030 static int monster_cast_spell(object *head, object *part, object *pl, int dir) {
1031  object *spell_item;
1032  object *owner;
1033  rv_vector rv1;
1034 
1035  /* If you want monsters to cast spells over friends, this spell should
1036  * be removed. It probably should be in most cases, since monsters still
1037  * don't care about residual effects (ie, casting a cone which may have a
1038  * clear path to the player, the side aspects of the code will still hit
1039  * other monsters)
1040  */
1041  dir = path_to_player(part, pl, 0);
1042  if (dir == 0)
1043  return 0;
1044 
1045  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1046  owner = object_get_owner(head);
1047  if (owner != NULL) {
1048  if (get_rangevector(head, owner, &rv1, 0x1)
1049  && dirdiff(dir, rv1.direction) < 2) {
1050  return 0; /* Might hit owner with spell */
1051  }
1052  }
1053  }
1054 
1055  if (QUERY_FLAG(head, FLAG_CONFUSED))
1056  dir = get_randomized_dir(dir);
1057 
1058  /* If the monster hasn't already chosen a spell, choose one
1059  * I'm not sure if it really make sense to pre-select spells (events
1060  * could be different by the time the monster goes again).
1061  */
1062  if (head->spellitem == NULL) {
1063  spell_item = monster_choose_random_spell(head);
1064  if (spell_item == NULL) {
1065  LOG(llevMonster, "Turned off spells in %s\n", head->name);
1066  CLEAR_FLAG(head, FLAG_CAST_SPELL); /* Will be turned on when picking up book */
1067  return 0;
1068  }
1069  if (spell_item->type == SPELLBOOK) {
1070  if (!spell_item->inv) {
1071  LOG(llevError, "spellbook %s does not contain a spell?\n", spell_item->name);
1072  return 0;
1073  }
1074  spell_item = spell_item->inv;
1075  }
1076  } else
1077  spell_item = head->spellitem;
1078 
1079  if (!spell_item)
1080  return 0;
1081 
1082  /* Best guess this is a defensive/healing spell */
1083  if (spell_item->range <= 1 || spell_item->stats.dam < 0)
1084  dir = 0;
1085 
1086  /* Monster doesn't have enough spell-points */
1087  if (head->stats.sp < SP_level_spellpoint_cost(head, spell_item, SPELL_MANA))
1088  return 0;
1089 
1090  if (head->stats.grace < SP_level_spellpoint_cost(head, spell_item, SPELL_GRACE))
1091  return 0;
1092 
1093  head->stats.sp -= SP_level_spellpoint_cost(head, spell_item, SPELL_MANA);
1094  head->stats.grace -= SP_level_spellpoint_cost(head, spell_item, SPELL_GRACE);
1095 
1096  /* set this to null, so next time monster will choose something different */
1097  head->spellitem = NULL;
1098 
1099  return cast_spell(part, part, dir, spell_item, NULL);
1100 }
1101 
1116 static int monster_use_scroll(object *head, object *part, object *pl, int dir) {
1117  object *scroll;
1118  object *owner;
1119  rv_vector rv1;
1120 
1121  /* If you want monsters to cast spells over friends, this spell should
1122  * be removed. It probably should be in most cases, since monsters still
1123  * don't care about residual effects (ie, casting a cone which may have a
1124  * clear path to the player, the side aspects of the code will still hit
1125  * other monsters)
1126  */
1127  dir = path_to_player(part, pl, 0);
1128  if (dir == 0)
1129  return 0;
1130 
1131  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1132  owner = object_get_owner(head);
1133  if (owner != NULL) {
1134  if (get_rangevector(head, owner, &rv1, 0x1)
1135  && dirdiff(dir, rv1.direction) < 2) {
1136  return 0; /* Might hit owner with spell */
1137  }
1138  }
1139  }
1140 
1141  if (QUERY_FLAG(head, FLAG_CONFUSED))
1142  dir = get_randomized_dir(dir);
1143 
1144  scroll = NULL;
1145  FOR_INV_PREPARE(head, tmp)
1146  if (tmp->type == SCROLL && monster_should_cast_spell(tmp->inv)) {
1147  scroll = tmp;
1148  break;
1149  }
1150  FOR_INV_FINISH();
1151 
1152  /* Used up all his scrolls, so nothing do to */
1153  if (!scroll) {
1155  return 0;
1156  }
1157 
1158  /* Spell should be cast on caster (ie, heal, strength) */
1159  if (scroll->inv->range == 0)
1160  dir = 0;
1161 
1162  /* Face the direction that we want to cast. */
1163  head->direction = dir;
1164  head->facing = head->direction;
1165  if (head->animation_id)
1166  animate_object(head, head->direction);
1167 
1168  ob_apply(scroll, part, 0);
1169  return 1;
1170 }
1171 
1200 static int monster_use_skill(object *head, object *part, object *pl, int dir) {
1201  object *owner;
1202  int found;
1203 
1204  dir = path_to_player(part, pl, 0);
1205  if (dir == 0)
1206  return 0;
1207 
1208  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1209  owner = object_get_owner(head);
1210  if (owner != NULL) {
1211  rv_vector rv;
1212 
1213  if (get_rangevector(head, owner, &rv, 0) && dirdiff(dir, rv.direction) < 1)
1214  return 0; /* Might hit owner with skill -thrown rocks for example ?*/
1215  }
1216  }
1217  if (QUERY_FLAG(head, FLAG_CONFUSED))
1218  dir = get_randomized_dir(dir);
1219 
1220  /* skill selection - monster will use the next unused skill.
1221  * well...the following scenario will allow the monster to
1222  * toggle between 2 skills. One day it would be nice to make
1223  * more skills available to monsters.
1224  */
1225  found = 0;
1226  FOR_INV_PREPARE(head, skill)
1227  if (skill->type == SKILL && skill != head->chosen_skill) {
1228  head->chosen_skill = skill;
1229  found = 1;
1230  break;
1231  }
1232  FOR_INV_FINISH();
1233 
1234  if (!found && !head->chosen_skill) {
1235  LOG(llevDebug, "Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", head->name, head->count);
1237  return 0;
1238  }
1239  /* use skill */
1240  return do_skill(head, part, head->chosen_skill, dir, NULL);
1241 }
1242 
1257 static int monster_use_range(object *head, object *part, object *pl, int dir) {
1258  object *owner;
1259  int at_least_one = 0;
1260 
1261  dir = path_to_player(part, pl, 0);
1262  if (dir == 0)
1263  return 0;
1264 
1265  if (QUERY_FLAG(head, FLAG_FRIENDLY)) {
1266  owner = object_get_owner(head);
1267  if (owner != NULL) {
1268  rv_vector rv;
1269 
1270  if (get_rangevector(head, owner, &rv, 0) && dirdiff(dir, rv.direction) < 2)
1271  return 0; /* Might hit owner with spell */
1272  }
1273  }
1274  if (QUERY_FLAG(head, FLAG_CONFUSED))
1275  dir = get_randomized_dir(dir);
1276 
1277  FOR_INV_PREPARE(head, wand) {
1278  if (wand->type == WAND) {
1279  /* Found a wand, let's see if it has charges left */
1280  at_least_one = 1;
1281  if (wand->stats.food <= 0)
1282  continue;
1283 
1284  cast_spell(head, wand, dir, wand->inv, NULL);
1285  drain_wand_charge(wand);
1286 
1287  /* Success */
1288  return 1;
1289  }
1290 
1291  if (wand->type == ROD) {
1292  /* Found rod/horn, let's use it if possible */
1293  at_least_one = 1;
1294  if (wand->stats.hp < MAX(wand->inv->stats.sp, wand->inv->stats.grace))
1295  continue;
1296 
1297  /* drain charge before casting spell - can be a case where the
1298  * spell destroys the monster, and rod, so if done after, results
1299  * in crash.
1300  */
1301  drain_rod_charge(wand);
1302  cast_spell(head, wand, dir, wand->inv, NULL);
1303 
1304  /* Success */
1305  return 1;
1306  }
1307  } FOR_INV_FINISH();
1308 
1309  if (at_least_one)
1310  return 0;
1311 
1312  LOG(llevError, "Error: Monster %s (%d) HAS_READY_RANG() without wand/horn/rod.\n", head->name, head->count);
1314  return 0;
1315 }
1316 
1333 static int monster_use_bow(object *head, object *part, object *pl, int dir) {
1334  object *owner;
1335  rv_vector rv;
1336  int16_t x, y;
1337  mapstruct *map;
1338 
1339  if (!get_rangevector(part, pl, &rv, 1))
1340  return 0;
1341  if (rv.distance > 100)
1342  /* Too far */
1343  return 0;
1344  if (rv.distance_x != 0 && rv.distance_y != 0 && abs(rv.distance_x) != abs(rv.distance_y))
1345  /* Player must be on same horizontal, vertical or diagonal line. */
1346  return 0;
1347  dir = rv.direction;
1348 
1349  if (QUERY_FLAG(head, FLAG_FRIENDLY))
1350  owner = object_get_owner(head);
1351  else
1352  owner = NULL;
1353 
1354  /* The monster can possibly fire, let's see if the path is ok for an arrow. */
1355  x = part->x;
1356  y = part->y;
1357  map = part->map;
1358  while (x != pl->x || y != pl->y || map != pl->map) {
1359  x += freearr_x[dir];
1360  y += freearr_y[dir];
1361  map = get_map_from_coord(map, &x, &y);
1362  if (!map) {
1363  LOG(llevError, "monster_use_bow: no map but still path exists??\n");
1364  return 0;
1365  }
1366  if ((GET_MAP_MOVE_BLOCK(map, x, y)&MOVE_FLY_LOW) == MOVE_FLY_LOW)
1367  return 0;
1368  if (owner && owner->x == x && owner->y == y && owner->map == map)
1369  /* Don't hit owner! */
1370  return 0;
1371  }
1372 
1373  /* Finally, path is clear, can fire. */
1374 
1375  if (QUERY_FLAG(head, FLAG_CONFUSED))
1376  dir = get_randomized_dir(dir);
1377 
1378  /* in server/player.c */
1379  return fire_bow(head, NULL, dir, 0, part->x, part->y);
1380 }
1381 
1390 static int monster_get_weapon_quality(const object *item) {
1391  int val;
1392  int i;
1393 
1394  val = item->stats.dam;
1395  val += item->magic*3;
1396  /* Monsters don't really get benefits from things like regen rates
1397  * from items. But the bonus for their stats are very important.
1398  */
1399  for (i = 0; i < NUM_STATS; i++)
1400  val += get_attr_value(&item->stats, i)*2;
1401  return val;
1402 }
1403 
1416 static int monster_check_good_weapon(object *who, object *item) {
1417  object *other_weap;
1418  int val;
1419 
1420  other_weap = object_find_by_type_applied(who, item->type);
1421  if (other_weap == NULL) /* No other weapons */
1422  return 1;
1423 
1424  /* Rather than go through and apply the new one, and see if it is
1425  * better, just do some simple checks
1426  * Put some multipliers for things that hvae several effects,
1427  * eg, magic affects both damage and wc, so it has more weight
1428  */
1429 
1431  return val > 0;
1432 }
1433 
1442 static int monster_get_armour_quality(const object *item) {
1443  int val;
1444 
1445  val = item->stats.ac;
1446  val += item->resist[ATNR_PHYSICAL]/5;
1447  val += item->magic*3;
1448  return val;
1449 }
1450 
1463 static int monster_check_good_armour(object *who, object *item) {
1464  object *other_armour;
1465  int val, i;
1466 
1467  other_armour = object_find_by_type_applied(who, item->type);
1468  if (other_armour == NULL) /* No other armour, use the new */
1469  return 1;
1470 
1471  val = monster_get_armour_quality(item)-monster_get_armour_quality(other_armour);
1472 
1473  /* for the other protections, do weigh them very much in the equation -
1474  * it is the armor protection which is most important, because there is
1475  * no good way to know what the player may attack the monster with.
1476  * So if the new item has better protection than the old, give that higher
1477  * value. If the reverse, then decrease the value of this item some.
1478  */
1479  for (i = 1; i < NROFATTACKS; i++) {
1480  if (item->resist[i] > other_armour->resist[i])
1481  val++;
1482  else if (item->resist[i] < other_armour->resist[i])
1483  val--;
1484  }
1485 
1486  /* Very few armours have stats, so not much need to worry about those. */
1487 
1488  return val > 0;
1489 }
1490 
1498 static void monster_check_apply(object *mon, object *item) {
1499  int flag = 0;
1500 
1501  if (item->type == SPELLBOOK
1502  && mon->arch != NULL
1503  && (QUERY_FLAG(&mon->arch->clone, FLAG_CAST_SPELL))) {
1504  SET_FLAG(mon, FLAG_CAST_SPELL);
1505  return;
1506  }
1507 
1508  /* If for some reason, this item is already applied, no more work to do */
1509  if (QUERY_FLAG(item, FLAG_APPLIED))
1510  return;
1511 
1512  /* Might be better not to do this - if the monster can fire a bow,
1513  * it is possible in his wanderings, he will find one to use. In
1514  * which case, it would be nice to have ammo for it.
1515  */
1516  if (QUERY_FLAG(mon, FLAG_USE_BOW) && item->type == ARROW) {
1517  /* Check for the right kind of bow */
1518  object *bow;
1519 
1520  bow = object_find_by_type_and_race(mon, BOW, item->race);
1521  if (bow != NULL) {
1522  SET_FLAG(mon, FLAG_READY_BOW);
1523  LOG(llevMonster, "Found correct bow for arrows.\n");
1524  return; /* nothing more to do for arrows */
1525  }
1526  }
1527 
1528  if (item->type == TREASURE && mon->will_apply&WILL_APPLY_TREASURE)
1529  flag = 1;
1530  /* Eating food gets hp back */
1531  else if (item->type == FOOD && mon->will_apply&WILL_APPLY_FOOD)
1532  flag = 1;
1533  else if (item->type == SCROLL && QUERY_FLAG(mon, FLAG_USE_SCROLL)) {
1534  if (!item->inv)
1535  LOG(llevDebug, "Monster %d having scroll %d with empty inventory!\n", mon->count, item->count);
1536  else if (monster_should_cast_spell(item->inv))
1538  /* Don't use it right now */
1539  return;
1540  } else if (item->type == WEAPON)
1541  flag = monster_check_good_weapon(mon, item);
1542  else if (IS_ARMOR(item) || IS_SHIELD(item))
1543  flag = monster_check_good_armour(mon, item);
1544  /* Should do something more, like make sure this is a better item */
1545  else if (item->type == RING)
1546  flag = 1;
1547  else if (item->type == WAND || item->type == ROD) {
1548  /* We never really 'ready' the wand/rod/horn, because that would mean the
1549  * weapon would get undone.
1550  */
1551  if (!(apply_can_apply_object(mon, item)&CAN_APPLY_NOT_MASK)) {
1552  SET_FLAG(mon, FLAG_READY_RANGE);
1553  SET_FLAG(item, FLAG_APPLIED);
1554  }
1555  return;
1556  } else if (item->type == BOW) {
1557  /* We never really 'ready' the bow, because that would mean the
1558  * weapon would get undone.
1559  */
1560  if (!(apply_can_apply_object(mon, item)&CAN_APPLY_NOT_MASK))
1561  SET_FLAG(mon, FLAG_READY_BOW);
1562  return;
1563  } else if (item->type == SKILL) {
1564  /*
1565  * skills are specials: monsters must have the 'FLAG_READY_SKILL' flag set,
1566  * else they can't use the skill...
1567  * Skills also don't need to get applied, so return now.
1568  */
1569  SET_FLAG(mon, FLAG_READY_SKILL);
1570  return;
1571  }
1572 
1573  /* if we don't match one of the above types, return now.
1574  * apply_can_apply_object() will say that we can apply things like flesh,
1575  * bolts, and whatever else, because it only checks against the
1576  * body_info locations.
1577  */
1578  if (!flag)
1579  return;
1580 
1581  /* Check to see if the monster can use this item. If not, no need
1582  * to do further processing. Note that apply_can_apply_object() already checks
1583  * for the CAN_USE flags.
1584  */
1586  return;
1587 
1588  /* should only be applying this item, not unapplying it.
1589  * also, ignore status of curse so they can take off old armour.
1590  * monsters have some advantages after all.
1591  */
1593  return;
1594 }
1595 
1615 static void monster_check_pickup(object *monster) {
1616  object *part;
1617 
1618  for (part = monster; part != NULL; part = part->more)
1619  FOR_BELOW_PREPARE(part, tmp) {
1620  if (monster_can_pick(monster, tmp)) {
1621  uint32_t nrof;
1622 
1623  if (tmp->weight > 0) {
1624  int32_t weight_limit;
1625 
1626  weight_limit = get_weight_limit(monster->stats.Str);
1627  if (weight_limit >= monster->weight-monster->carrying)
1628  nrof = (weight_limit-monster->weight-monster->carrying)/tmp->weight;
1629  else
1630  nrof = 0;
1631  } else
1632  nrof = MAX(1, tmp->nrof);
1633  if (nrof >= 1) {
1634  object *tmp2;
1635 
1636  tmp2 = object_split(tmp, MIN(nrof, MAX(1, tmp->nrof)), NULL, 0);
1637  tmp2 = object_insert_in_ob(tmp2, monster);
1638  (void)monster_check_apply(monster, tmp2);
1639  }
1640  }
1641  } FOR_BELOW_FINISH();
1642 }
1643 
1653 static int monster_can_pick(object *monster, object *item) {
1654  int flag = 0;
1655  int i;
1656 
1657  if (!object_can_pick(monster, item))
1658  return 0;
1659 
1660  if (QUERY_FLAG(item, FLAG_UNPAID))
1661  return 0;
1662 
1663  if (monster->pick_up&64) /* All */
1664  flag = 1;
1665 
1666  else {
1667  if (IS_WEAPON(item))
1668  flag = (monster->pick_up&8) || QUERY_FLAG(monster, FLAG_USE_WEAPON);
1669  else if (IS_ARMOR(item))
1670  flag = (monster->pick_up&16) || QUERY_FLAG(monster, FLAG_USE_ARMOUR);
1671  else if (IS_SHIELD(item))
1672  flag = (monster->pick_up&16) || QUERY_FLAG(monster, FLAG_USE_SHIELD);
1673  else switch (item->type) {
1674  case MONEY:
1675  case GEM:
1676  flag = monster->pick_up&2;
1677  break;
1678 
1679  case FOOD:
1680  flag = monster->pick_up&4;
1681  break;
1682 
1683  case SKILL:
1684  flag = QUERY_FLAG(monster, FLAG_CAN_USE_SKILL);
1685  break;
1686 
1687  case RING:
1688  flag = QUERY_FLAG(monster, FLAG_USE_RING);
1689  break;
1690 
1691  case WAND:
1692  case ROD:
1693  flag = QUERY_FLAG(monster, FLAG_USE_RANGE);
1694  break;
1695 
1696  case SPELLBOOK:
1697  flag = (monster->arch != NULL && QUERY_FLAG(&monster->arch->clone, FLAG_CAST_SPELL));
1698  break;
1699 
1700  case SCROLL:
1701  flag = QUERY_FLAG(monster, FLAG_USE_SCROLL);
1702  break;
1703 
1704  case BOW:
1705  case ARROW:
1706  flag = QUERY_FLAG(monster, FLAG_USE_BOW);
1707  break;
1708  }
1709  if (!flag && QUERY_FLAG(item, FLAG_IS_THROWN) && object_find_by_type_subtype(monster, SKILL, SK_THROWING) != NULL)
1710  flag = (monster->pick_up&8) || QUERY_FLAG(monster, FLAG_USE_WEAPON);
1711  /* Simplistic check - if the monster has a location to equip it, he will
1712  * pick it up. Note that this doesn't handle cases where an item may
1713  * use several locations.
1714  */
1715  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
1716  if (monster->body_info[i] && item->body_info[i]) {
1717  flag = 1;
1718  break;
1719  }
1720  }
1721  }
1722 
1723  if (((!(monster->pick_up&32)) && flag) || ((monster->pick_up&32) && (!flag)))
1724  return 1;
1725  return 0;
1726 }
1727 
1734 static void monster_apply_below(object *monster) {
1735  FOR_BELOW_PREPARE(monster, tmp) {
1736  switch (tmp->type) {
1737  case CF_HANDLE:
1738  case TRIGGER:
1739  if (monster->will_apply&WILL_APPLY_HANDLE)
1740  apply_manual(monster, tmp, 0);
1741  break;
1742 
1743  case TREASURE:
1744  if (monster->will_apply&WILL_APPLY_TREASURE)
1745  apply_manual(monster, tmp, 0);
1746  break;
1747  }
1748  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
1749  break;
1750  } FOR_BELOW_FINISH();
1751 }
1752 
1757 void monster_check_apply_all(object *monster) {
1758  FOR_INV_PREPARE(monster, inv)
1759  monster_check_apply(monster, inv);
1760  FOR_INV_FINISH();
1761 }
1762 
1767 void monster_npc_call_help(object *op) {
1768  int x, y, mflags;
1769  int16_t sx, sy;
1770  mapstruct *m;
1771 
1772  for (x = -3; x < 4; x++)
1773  for (y = -3; y < 4; y++) {
1774  m = op->map;
1775  sx = op->x+x;
1776  sy = op->y+y;
1777  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
1778  /* If nothing alive on this space, no need to search the space. */
1779  if ((mflags&P_OUT_OF_MAP) || !(mflags&P_IS_ALIVE))
1780  continue;
1781 
1782  FOR_MAP_PREPARE(m, sx, sy, npc)
1784  object_set_enemy(npc, op->enemy);
1785  FOR_MAP_FINISH();
1786  }
1787 }
1788 
1797 static int monster_dist_att(int dir, object *enemy, object *part, rv_vector *rv) {
1798  if (monster_can_hit(part, enemy, rv))
1799  return dir;
1800  if (rv->distance < 10)
1801  return absdir(dir+4);
1802  else if (rv->distance > 18)
1803  return dir;
1804  return 0;
1805 }
1806 
1816 static int monster_run_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
1817  if ((monster_can_hit(part, enemy, rv) && ob->move_status < 20) || ob->move_status < 20) {
1818  ob->move_status++;
1819  return (dir);
1820  } else if (ob->move_status > 20)
1821  ob->move_status = 0;
1822  return absdir(dir+4);
1823 }
1824 
1832 static int monster_hitrun_att(int dir, object *ob, object *enemy) {
1833  if (ob->move_status++ < 25)
1834  return dir;
1835  else if (ob->move_status < 50)
1836  return absdir(dir+4);
1837  ob->move_status = 0;
1838  return absdir(dir+4);
1839 }
1840 
1850 static int monster_wait_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
1851  int inrange = monster_can_hit(part, enemy, rv);
1852 
1853  if (ob->move_status || inrange)
1854  ob->move_status++;
1855 
1856  if (ob->move_status == 0)
1857  return 0;
1858  else if (ob->move_status < 10)
1859  return dir;
1860  else if (ob->move_status < 15)
1861  return absdir(dir+4);
1862  ob->move_status = 0;
1863  return 0;
1864 }
1865 
1875 static int monster_disthit_att(int dir, object *ob, object *enemy, object *part, rv_vector *rv) {
1876  /* The logic below here looked plain wrong before. Basically, what should
1877  * happen is that if the creatures hp percentage falls below run_away,
1878  * the creature should run away (dir+4)
1879  * I think its wrong for a creature to have a zero maxhp value, but
1880  * at least one map has this set, and whatever the map contains, the
1881  * server should try to be resilant enough to avoid the problem
1882  */
1883  if (ob->stats.maxhp && (ob->stats.hp*100)/ob->stats.maxhp < ob->run_away)
1884  return absdir(dir+4);
1885  return monster_dist_att(dir, enemy, part, rv);
1886 }
1887 
1894 static int monster_wait_att2(int dir, rv_vector *rv) {
1895  if (rv->distance < 9)
1896  return absdir(dir+4);
1897  return 0;
1898 }
1899 
1904 static void monster_circ1_move(object *ob) {
1905  static const int circle [12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 };
1906 
1907  if (++ob->move_status > 11)
1908  ob->move_status = 0;
1909  if (!(move_object(ob, circle[ob->move_status])))
1910  (void)move_object(ob, RANDOM()%8+1);
1911 }
1912 
1917 static void monster_circ2_move(object *ob) {
1918  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 };
1919 
1920  if (++ob->move_status > 19)
1921  ob->move_status = 0;
1922  if (!(move_object(ob, circle[ob->move_status])))
1923  (void)move_object(ob, RANDOM()%8+1);
1924 }
1925 
1930 static void monster_pace_movev(object *ob) {
1931  if (ob->move_status++ > 6)
1932  ob->move_status = 0;
1933  if (ob->move_status < 4)
1934  (void)move_object(ob, 5);
1935  else
1936  (void)move_object(ob, 1);
1937 }
1938 
1943 static void monster_pace_moveh(object *ob) {
1944  if (ob->move_status++ > 6)
1945  ob->move_status = 0;
1946  if (ob->move_status < 4)
1947  (void)move_object(ob, 3);
1948  else
1949  (void)move_object(ob, 7);
1950 }
1951 
1956 static void monster_pace2_movev(object *ob) {
1957  if (ob->move_status++ > 16)
1958  ob->move_status = 0;
1959  if (ob->move_status < 6)
1960  (void)move_object(ob, 5);
1961  else if (ob->move_status < 8)
1962  return;
1963  else if (ob->move_status < 13)
1964  (void)move_object(ob, 1);
1965 }
1966 
1971 static void monster_pace2_moveh(object *ob) {
1972  if (ob->move_status++ > 16)
1973  ob->move_status = 0;
1974  if (ob->move_status < 6)
1975  (void)move_object(ob, 3);
1976  else if (ob->move_status < 8)
1977  return;
1978  else if (ob->move_status < 13)
1979  (void)move_object(ob, 7);
1980 }
1981 
1986 static void monster_rand_move(object *ob) {
1987  int i;
1988 
1989  if (ob->move_status < 1
1990  || ob->move_status > 8
1991  || !(move_object(ob, ob->move_status || !(RANDOM()%9))))
1992  for (i = 0; i < 5; i++) {
1993  ob->move_status = RANDOM()%8+1;
1994  if (move_object(ob, ob->move_status))
1995  return;
1996  }
1997 }
1998 
2006 void monster_check_earthwalls(object *op, mapstruct *m, int x, int y) {
2007  FOR_MAP_PREPARE(m, x, y, tmp)
2008  if (tmp->type == EARTHWALL) {
2009  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
2010  return;
2011  }
2012  FOR_MAP_FINISH();
2013 }
2014 
2022 void monster_check_doors(object *op, mapstruct *m, int x, int y) {
2023  FOR_MAP_PREPARE(m, x, y, tmp)
2024  if (tmp->type == DOOR) {
2025  hit_player(tmp, op->stats.dam, op, AT_PHYSICAL, 1);
2026  return;
2027  }
2028  FOR_MAP_FINISH();
2029 }
2030 
2036 void monster_do_say(const mapstruct *map, const char *message) {
2038  message);
2039 }
2040 
2047 static StringBuffer *monster_format_say(const object* npc, const char *message) {
2048  char name[MAX_BUF];
2049  StringBuffer *buf;
2050 
2051  query_name(npc, name, sizeof(name));
2052  buf = stringbuffer_new();
2053  stringbuffer_append_printf(buf, "%s says: %s", name, message);
2054  return buf;
2055 }
2056 
2062 static const char *get_reply_text_own(reply_type rt) {
2063  switch (rt) {
2064  case rt_say:
2065  return "say";
2066  case rt_reply:
2067  return "reply";
2068  case rt_question:
2069  return "ask";
2070  }
2071  assert(0);
2072  return NULL;
2073 }
2074 
2080 static const char *get_reply_text_other(reply_type rt) {
2081  switch (rt) {
2082  case rt_say:
2083  return "says";
2084  case rt_reply:
2085  return "replies";
2086  case rt_question:
2087  return "asks";
2088  }
2089  assert(0);
2090  return NULL;
2091 }
2092 
2118 void monster_communicate(object *op, const char *txt) {
2119  int i, mflags;
2120  int16_t x, y;
2121  mapstruct *mp, *orig_map = op->map;
2122  char own[MAX_BUF], others[MAX_BUF];
2123  talk_info info;
2124 
2125  info.text = txt;
2126  info.message = NULL;
2127  info.replies_count = 0;
2128  info.who = op;
2129  info.npc_msg_count = 0;
2130 
2131  /* Note that this loop looks pretty inefficient to me - we look and try to talk
2132  * to every object within 2 spaces. It would seem that if we trim this down to
2133  * only try to talk to objects with npc->msg set, things would be a lot more efficient,
2134  * but I'm not sure if there are any objects out there that don't have a message and instead
2135  * rely sorely on events - MSW 2009-04-14
2136  */
2137  for (i = 0; i <= SIZEOFFREE2; i++) {
2138  mp = op->map;
2139  x = op->x+freearr_x[i];
2140  y = op->y+freearr_y[i];
2141 
2142  mflags = get_map_flags(mp, &mp, x, y, &x, &y);
2143  if (mflags&P_OUT_OF_MAP)
2144  continue;
2145 
2146  FOR_MAP_PREPARE(mp, x, y, npc) {
2147  monster_talk_to_npc(npc, &info);
2148  if (orig_map != op->map) {
2149  LOG(llevDebug, "Warning: Forced to swap out very recent map - MAX_OBJECTS should probably be increased\n");
2150  return;
2151  }
2152  } FOR_MAP_FINISH();
2153  }
2154 
2155  /* First, what the player says. */
2156  if (info.message != NULL) {
2157  snprintf(own, sizeof(own), "You %s: %s", get_reply_text_own(info.message_type), info.message);
2158  snprintf(others, sizeof(others), "%s %s: %s", op->name, get_reply_text_other(info.message_type), info.message);
2159  free_string(info.message);
2160  } else {
2161  snprintf(own, sizeof(own), "You say: %s", txt);
2162  snprintf(others, sizeof(others), "%s says: %s", op->name, txt);
2163  }
2166 
2167  /* Then NPCs can actually talk. */
2168  for (i = 0; i < info.npc_msg_count; i++) {
2169  monster_do_say(orig_map, info.npc_msgs[i]);
2170  free_string(info.npc_msgs[i]);
2171  }
2172 
2173  /* Finally, the replies the player can use. */
2174  if (info.replies_count > 0) {
2176  for (i = 0; i < info.replies_count; i++) {
2178  free_string(info.replies_words[i]);
2179  free_string(info.replies[i]);
2180  }
2181  }
2182 }
2183 
2192 static int monster_do_talk_npc(object *npc, talk_info *info) {
2193  struct_dialog_reply *reply;
2194  struct_dialog_message *message;
2195 
2196  if (!get_dialog_message(npc, info->text, &message, &reply))
2197  return 0;
2198 
2199  if (reply) {
2200  info->message = add_string(reply->message);
2201  info->message_type = reply->type;
2202  }
2203 
2204  if (npc->type == MAGIC_EAR) {
2206  use_trigger(npc);
2207  } else {
2208  char value[2];
2209 
2210  if (info->npc_msg_count < MAX_NPC) {
2212  info->npc_msg_count++;
2213  }
2214 
2215  /* mark that the npc was talked to, so it won't move randomly later on */
2216  value[0] = '3' + rand() % 6;
2217  value[1] = '\0';
2218  object_set_value(npc, "talked_to", value, 1);
2219 
2220  reply = message->replies;
2221  while (reply && info->replies_count < MAX_REPLIES) {
2222  info->replies[info->replies_count] = add_string(reply->message);
2223  info->replies_words[info->replies_count] = add_string(reply->reply);
2224  info->replies_count++;
2225  reply = reply->next;
2226  }
2227  }
2228 
2229  return 1;
2230 }
2231 
2237 void monster_npc_say(object *npc, const char *cp) {
2238  char *message;
2239  StringBuffer *buf = monster_format_say(npc, cp);
2240 
2241  message = stringbuffer_finish(buf);
2242  monster_do_say(npc->map, message);
2243  free(message);
2244 }
2245 
2254 static int monster_talk_to_npc(object *npc, talk_info *info) {
2255  /* Move this commone area up here - shouldn't cost much extra cpu
2256  * time, and makes the function more readable */
2257  /* Lauwenmark: Handle for plugin say event */
2258  if (plugin_event_say(npc, info) != 0)
2259  return 0;
2260  /* Lauwenmark - Here we let the objects inside inventories hear and answer, too. */
2261  /* This allows the existence of "intelligent" weapons you can discuss with */
2262  FOR_INV_PREPARE(npc, cobj)
2263  if (plugin_event_say(cobj, info) != 0)
2264  return 0;
2265  FOR_INV_FINISH();
2266  if (info->who == npc)
2267  return 0;
2268  return monster_do_talk_npc(npc, info);
2269 }
2270 
2283 object *monster_find_throw_ob(object *op) {
2284  /* New throw code: look through the inventory. Grap the first legal is_thrown
2285  * marked item and throw it to the enemy.
2286  */
2287 
2288  FOR_INV_PREPARE(op, tmp) {
2289  /* Can't throw invisible objects or items that are applied */
2290  if (!tmp->invisible && !QUERY_FLAG(tmp, FLAG_APPLIED) && QUERY_FLAG(tmp, FLAG_IS_THROWN)) {
2291 #ifdef DEBUG_THROW
2292  char what[MAX_BUF];
2293 
2294  query_name(tmp, what, MAX_BUF);
2295  LOG(llevDebug, "%s chooses to throw: %s (%d)\n", op->name, what, tmp->count);
2296 #endif
2297  return tmp;
2298  }
2299  } FOR_INV_FINISH();
2300 
2301 #ifdef DEBUG_THROW
2302  LOG(llevDebug, "%s chooses to throw nothing\n", op->name);
2303 #endif
2304  return NULL;
2305 }
2306 
2322 int monster_can_detect_enemy(object *op, object *enemy, rv_vector *rv) {
2323  int radius = MIN_MON_RADIUS, hide_discovery;
2324 
2325  /* null detection for any of these condtions always */
2326  if (!op || !enemy || !op->map || !enemy->map)
2327  return 0;
2328 
2329  /* If the monster (op) has no way to get to the enemy, do nothing */
2330  if (!get_rangevector(op, enemy, rv, 0))
2331  return 0;
2332 
2333  /* Monsters always ignore the DM */
2334  if (op->type != PLAYER && QUERY_FLAG(enemy, FLAG_WIZ))
2335  return 0;
2336 
2337  /* simple check. Should probably put some range checks in here. */
2338  if (monster_can_see_enemy(op, enemy))
2339  return 1;
2340 
2341  /* The rest of this is for monsters. Players are on their own for
2342  * finding enemies!
2343  */
2344  if (op->type == PLAYER)
2345  return 0;
2346 
2347  /* Quality invisible? Bah, we wont see them w/o SEE_INVISIBLE
2348  * flag (which was already checked) in can_see_enmy (). Lets get out of here
2349  */
2350  if (enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden)))
2351  return 0;
2352 
2353  /* use this for invis also */
2354  hide_discovery = op->stats.Int/5;
2355 
2356  /* Determine Detection radii */
2357  if (!enemy->hide) /* to detect non-hidden (eg dark/invis enemy) */
2358  radius = MAX(op->stats.Wis/5+1, MIN_MON_RADIUS);
2359  else { /* a level/INT/Dex adjustment for hiding */
2360  object *sk_hide;
2361  int bonus = (op->level/2)+(op->stats.Int/5);
2362 
2363  if (enemy->type == PLAYER) {
2364  sk_hide = find_skill_by_number(enemy, SK_HIDING);
2365  if (sk_hide != NULL)
2366  bonus -= sk_hide->level;
2367  else {
2368  LOG(llevError, "monster_can_detect_enemy() got hidden player w/o hiding skill!\n");
2369  make_visible(enemy);
2370  radius = MAX(radius, MIN_MON_RADIUS);
2371  }
2372  } else /* enemy is not a player */
2373  bonus -= enemy->level;
2374 
2375  radius += bonus/5;
2376  hide_discovery += bonus*5;
2377  } /* else creature has modifiers for hiding */
2378 
2379  /* Radii stealth adjustment. Only if you are stealthy
2380  * will you be able to sneak up closer to creatures */
2381  if (QUERY_FLAG(enemy, FLAG_STEALTH))
2382  radius = radius/2, hide_discovery = hide_discovery/3;
2383 
2384  /* Radii adjustment for enemy standing in the dark */
2385  if (op->map->darkness > 0 && !monster_stand_in_light(enemy)) {
2386  /* on dark maps body heat can help indicate location with infravision
2387  * undead don't have body heat, so no benefit detecting them.
2388  */
2389  if (QUERY_FLAG(op, FLAG_SEE_IN_DARK) && !is_true_undead(enemy))
2390  radius += op->map->darkness/2;
2391  else
2392  radius -= op->map->darkness/2;
2393 
2394  /* op next to a monster (and not in complete darkness)
2395  * the monster should have a chance to see you.
2396  */
2397  if (radius < MIN_MON_RADIUS && op->map->darkness < 5 && rv->distance <= 1)
2398  radius = MIN_MON_RADIUS;
2399  } /* if on dark map */
2400 
2401  /* Lets not worry about monsters that have incredible detection
2402  * radii, we only need to worry here about things the player can
2403  * (potentially) see. This is 13, as that is the maximum size the player
2404  * may have for their map - in that way, creatures at the edge will
2405  * do something. Note that the distance field in the
2406  * vector is real distance, so in theory this should be 18 to
2407  * find that.
2408  */
2409  if (radius > 13)
2410  radius = 13;
2411 
2412  /* Enemy in range! Now test for detection */
2413  if ((int)rv->distance <= radius) {
2414  /* ah, we are within range, detected? take cases */
2415  if (!enemy->invisible) /* enemy in dark squares... are seen! */
2416  return 1;
2417 
2418  /* hidden or low-quality invisible */
2419  if (enemy->hide && rv->distance <= 1 && RANDOM()%100 <= (unsigned int)hide_discovery) {
2420  make_visible(enemy);
2421  /* inform players of new status */
2422  if (enemy->type == PLAYER && player_can_view(enemy, op))
2424  "You are discovered by %s!",
2425  op->name);
2426  return 1; /* detected enemy */
2427  } else if (enemy->invisible) {
2428  /* Change this around - instead of negating the invisible, just
2429  * return true so that the mosnter that managed to detect you can
2430  * do something to you. Decreasing the duration of invisible
2431  * doesn't make a lot of sense IMO, as a bunch of stupid creatures
2432  * can then basically negate the spell. The spell isn't negated -
2433  * they just know where you are!
2434  */
2435  if (RANDOM()%50 <= (unsigned int)hide_discovery) {
2436  if (enemy->type == PLAYER) {
2437  char name[MAX_BUF];
2438 
2439  query_name(op, name, MAX_BUF);
2441  "You see %s noticing your position.",
2442  name);
2443  }
2444  return 1;
2445  }
2446  }
2447  } /* within range */
2448 
2449  /* Wasn't detected above, so still hidden */
2450  return 0;
2451 }
2452 
2462 int monster_stand_in_light(object *op) {
2463  int16_t nx, ny;
2464  mapstruct *m;
2465 
2466  if (!op)
2467  return 0;
2468  if (op->glow_radius > 0)
2469  return 1;
2470 
2471  if (op->map) {
2472  int x, y, x1, y1;
2473 
2474  /* Check the spaces with the max light radius to see if any of them
2475  * have lights, and if any of them light the player enough, then return 1.
2476  */
2477  for (x = op->x-MAX_LIGHT_RADII; x <= op->x+MAX_LIGHT_RADII; x++) {
2478  for (y = op->y-MAX_LIGHT_RADII; y <= op->y+MAX_LIGHT_RADII; y++) {
2479  m = op->map;
2480  nx = x;
2481  ny = y;
2482 
2483  if (get_map_flags(m, &m, nx, ny, &nx, &ny)&P_OUT_OF_MAP)
2484  continue;
2485 
2486  x1 = abs(x-op->x)*abs(x-op->x);
2487  y1 = abs(y-op->y)*abs(y-op->y);
2488  if (isqrt(x1+y1) < GET_MAP_LIGHT(m, nx, ny))
2489  return 1;
2490  }
2491  }
2492  }
2493  return 0;
2494 }
2495 
2505 int monster_can_see_enemy(object *op, object *enemy) {
2506  object *looker = HEAD(op);
2507 
2508  /* safety */
2509  if (!looker || !enemy || !QUERY_FLAG(looker, FLAG_ALIVE))
2510  return 0;
2511 
2512  /* we dont give a full treatment of xrays here (shorter range than normal,
2513  * see through walls). Should we change the code elsewhere to make you
2514  * blind even if you can xray?
2515  */
2516  if (QUERY_FLAG(looker, FLAG_BLIND) && !QUERY_FLAG(looker, FLAG_XRAYS))
2517  return 0;
2518 
2519  /* checking for invisible things */
2520  if (enemy->invisible) {
2521  /* HIDDEN ENEMY. by definition, you can't see hidden stuff!
2522  * However, if you carry any source of light, then the hidden
2523  * creature is seeable (and stupid) */
2524  if (has_carried_lights(enemy)) {
2525  if (enemy->hide) {
2526  make_visible(enemy);
2528  "Your light reveals your hiding spot!");
2529  }
2530  return 1;
2531  } else if (enemy->hide)
2532  return 0;
2533 
2534  /* Invisible enemy. Break apart the check for invis undead/invis looker
2535  * into more simple checks - the QUERY_FLAG doesn't return 1/0 values,
2536  * and making it a conditional makes the code pretty ugly.
2537  */
2538  if (!QUERY_FLAG(looker, FLAG_SEE_INVISIBLE)) {
2539  if (makes_invisible_to(enemy, looker))
2540  return 0;
2541  }
2542  } else if (looker->type == PLAYER) /* for players, a (possible) shortcut */
2543  if (player_can_view(looker, enemy))
2544  return 1;
2545 
2546  /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen
2547  * unless they carry a light or stand in light. Darkness doesnt
2548  * inhibit the undead per se (but we should give their archs
2549  * CAN_SEE_IN_DARK, this is just a safety
2550  * we care about the enemy maps status, not the looker.
2551  * only relevant for tiled maps, but it is possible that the
2552  * enemy is on a bright map and the looker on a dark - in that
2553  * case, the looker can still see the enemy
2554  */
2555  if (enemy->map->darkness > 0
2556  && !monster_stand_in_light(enemy)
2557  && (!QUERY_FLAG(looker, FLAG_SEE_IN_DARK) || !is_true_undead(looker) || !QUERY_FLAG(looker, FLAG_XRAYS)))
2558  return 0;
2559 
2560  return 1;
2561 }
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Sends message to player(s).
Definition: main.c:315
Error, serious thing.
Definition: logger.h:11
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:365
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.c:209
int8_t Int
Definition: living.h:35
#define NUM_BODY_LOCATIONS
Number of body locations.
Definition: object.h:13
One player.
Definition: player.h:92
#define FLAG_SEE_IN_DARK
if set ob not effected by darkness
Definition: define.h:338
int apply_manual(object *op, object *tmp, int aflag)
Main apply handler.
Definition: apply.c:510
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.c:1116
#define FLAG_IS_FLOOR
Can&#39;t see what&#39;s underneath this object.
Definition: define.h:303
int npc_msg_count
How many NPCs reacted to the text being said.
Definition: dialog.h:59
#define FLAG_UNPAID
Object hasn&#39;t been paid for yet.
Definition: define.h:236
int8_t ac
Armour Class, how hard to hit, the lower the better.
Definition: living.h:37
static int monster_check_good_armour(object *who, object *item)
Checks if using armor &#39;item&#39; would be better for &#39;who&#39;.
Definition: monster.c:1463
#define SP_BOLT
Definition: spells.h:78
Spell-related defines: spellpath, subtypes, ...
See Ring.
Definition: object.h:185
#define RANDO
The monster will go in a random direction until it is stopped by an obstacle, then it chooses another...
Definition: define.h:550
This is used by get_rangevector to determine where the other creature is.
Definition: map.h:380
void monster_npc_say(object *npc, const char *cp)
Simple function to have some NPC say something.
Definition: monster.c:2237
#define FLAG_SLEEP
NPC is sleeping.
Definition: define.h:308
const char * race
Human, goblin, dragon, etc.
Definition: object.h:318
uint16_t attack_movement
What kind of attack movement.
Definition: object.h:391
#define MAX_LIGHT_RADII
Max radii for &#39;light&#39; object, really large values allow objects that can slow down the game...
Definition: define.h:466
#define FLAG_USE_SCROLL
(Monster) can read scroll
Definition: define.h:292
static int monster_hitrun_att(int dir, object *ob, object *enemy)
Return the next direction the monster should move for a specific movement type.
Definition: monster.c:1832
static int monster_should_cast_spell(object *spell_ob)
Checks if a monster should cast a spell.
Definition: monster.c:952
tag_t attacked_by_count
The tag of attacker, so we can be sure.
Definition: object.h:383
#define SET_FLAG(xyz, p)
Definition: define.h:223
sstring add_refcount(sstring str)
This will increase the refcount of the string str.
Definition: shstr.c:210
#define SP_CONE
Definition: spells.h:81
int makes_invisible_to(object *pl, object *mon)
This checks to see if &#39;pl&#39; is invisible to &#39;mon&#39;.
Definition: spell_effect.c:740
object * object_find_by_type_applied(const object *who, int type)
Find applied object in inventory.
Definition: object.c:3974
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
See Scroll.
Definition: object.h:221
object * part
Part we found.
Definition: map.h:385
void pets_follow_owner(object *ob, object *owner)
A pet is trying to follow its owner.
Definition: pets.c:293
uint16_t animation_id
An index into the animation array.
Definition: object.h:416
#define NDI_WHITE
Definition: newclient.h:222
void monster_do_living(object *op)
For a monster, regenerate hp and sp, potentially clear scared status.
Definition: monster.c:500
#define FLAG_USE_ARMOUR
(Monster) can wear armour/shield/helmet
Definition: define.h:296
#define FLAG_STAND_STILL
NPC will not (ever) move.
Definition: define.h:309
int message_type
A reply_type value for message.
Definition: dialog.h:55
void drain_wand_charge(object *wand)
Drains a charge from a wand.
Definition: spell_util.c:829
See Food.
Definition: object.h:112
#define MSG_TYPE_DIALOG_MAGIC_EAR
Magic ear.
Definition: newclient.h:467
See Projectile.
Definition: object.h:117
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:246
static int monster_get_weapon_quality(const object *item)
Returns the "quality" value of a weapon of a monster.
Definition: monster.c:1390
sstring stringbuffer_finish_shared(StringBuffer *sb)
Deallocate the string buffer instance and return the string as a shared string.
Definition: stringbuffer.c:85
#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:559
sstring message
If not NULL, what the player will be displayed as said.
Definition: dialog.h:54
void fatal(enum fatal_error err)
fatal() is meant to be called whenever a fatal signal is intercepted.
Definition: utils.c:596
object * mon
Definition: comet_perf.c:74
int8_t range
Range of the spell.
Definition: object.h:405
#define SP_MOVING_BALL
Definition: spells.h:109
struct obj * who
Player saying something.
Definition: dialog.h:52
void pets_move(object *ob)
Handles a pet&#39;s movement.
Definition: pets.c:329
#define SPELL_GRACE
Definition: spells.h:59
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.c:57
void get_search_arr(int *search_arr)
New function to make monster searching more efficient, and effective! This basically returns a random...
Definition: object.c:3501
int32_t last_heal
Last healed.
Definition: object.h:357
#define FLAG_READY_RANGE
(Monster) has a range attack readied...
Definition: define.h:299
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.c:280
static const char * get_reply_text_other(reply_type rt)
Return the verb for the player&#39;s dialog type seen from others (third person).
Definition: monster.c:2080
int monster_compute_path(object *source, object *target, int default_dir)
Computes a path from source to target.
Definition: monster.c:391
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.c:2366
See Spellbook.
Definition: object.h:203
const char * object_get_value(const object *op, const char *const key)
Get an extra value by key.
Definition: object.c:4246
See Money.
Definition: object.h:137
sstring replies[MAX_REPLIES]
Description for replies_words.
Definition: dialog.h:58
static object * monster_find_enemy(object *npc, rv_vector *rv)
Tries to find an enmy for npc.
Definition: monster.c:209
object clone
An object from which to do object_copy()
Definition: object.h:470
int16_t invisible
How much longer the object will be invis.
Definition: object.h:360
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.c:65
#define MSG_TYPE_DIALOG
NPCs, magic mouths, and altars.
Definition: newclient.h:375
int16_t SP_level_spellpoint_cost(object *caster, object *spell, int flags)
Scales the spellpoint cost of a spell by it&#39;s increased effectiveness.
Definition: spell_util.c:277
See Weapon.
Definition: object.h:119
int isqrt(int n)
Compute the square root.
Definition: utils.c:585
#define MIN_MON_RADIUS
Minimum monster detection radius.
Definition: monster.c:55
#define IS_WEAPON(op)
Definition: define.h:162
#define FLAG_CONFUSED
Will also be unable to cast spells.
Definition: define.h:312
int32_t last_sp
As last_heal, but for spell points.
Definition: object.h:358
#define FLAG_STEALTH
Will wake monsters with less range.
Definition: define.h:313
#define FLAG_RANDOM_MOVE
NPC will move randomly.
Definition: define.h:310
#define MAX_EXPLORE
Maximum map size to consider when finding a path in monster_compute_path().
Definition: monster.c:375
uint8_t subtype
Subtype of object.
Definition: object.h:339
sstring replies_words[MAX_REPLIES]
Available reply words.
Definition: dialog.h:57
See Rod.
Definition: object.h:109
#define FLAG_USE_WEAPON
(Monster) can wield weapons
Definition: define.h:297
uint8_t hide
The object is hidden, not invisible.
Definition: object.h:387
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.c:1030
char * message
What the player will actually say for this reply.
Definition: dialog.h:20
#define OUT_OF_REAL_MAP(M, X, Y)
Checks if a square is out of the map.
Definition: map.h:217
int apply_can_apply_object(const object *who, const object *op)
Checks to see if &#39;who&#39; can apply object &#39;op&#39;.
Definition: apply.c:942
#define FLAG_NO_ATTACK
monster don&#39;t attack
Definition: define.h:363
int8_t get_attr_value(const living *stats, int attr)
Gets the value of a stat.
Definition: living.c:313
void remove_friendly_object(object *op)
Removes the specified object from the linked list of friendly objects.
Definition: friend.c:56
#define MSG_TYPE_DIALOG_NPC
A message from the npc.
Definition: newclient.h:465
#define MAX(x, y)
Definition: compat.h:20
method_ret ob_apply(object *op, object *applier, int aflags)
Applies an object.
Definition: ob_methods.c:42
#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:532
int16_t sp
Spell points.
Definition: living.h:41
uint32_t get_weight_limit(int stat)
Definition: living.c:2255
int player_can_view(object *pl, object *op)
Check the player los field for viewability of the object op.
Definition: player.c:4134
int path_to_player(object *mon, object *pl, unsigned mindiff)
Returns the direction to the player, if valid.
Definition: player.c:629
Global type definitions and header inclusions.
#define PETMOVE
If the upper four bits of attack_movement are set to this number, the monster follows a player until ...
Definition: define.h:517
#define AP_APPLY
Item is to be applied.
Definition: define.h:610
uint32_t hidden
If True, player (DM) is hidden from view.
Definition: player.h:132
struct obj * enemy
Monster/player to follow even if not closest.
Definition: object.h:381
#define FLAG_USE_RING
(Monster) can use rings, boots, gauntlets, etc
Definition: define.h:298
static int monster_talk_to_npc(object *npc, talk_info *info)
Give an object the chance to handle something being said.
Definition: monster.c:2254
int distance_y
Y delta.
Definition: map.h:383
int absdir(int d)
Computes an absolute direction.
Definition: object.c:3637
#define HITRUN
Run to then hit player then run away cyclicly.
Definition: define.h:509
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: main.c:310
See Wand & Staff.
Definition: object.h:220
int plugin_event_say(object *npc, talk_info *talk)
Definition: plugins.c:375
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.c:1850
int16_t maxsp
Max spell points.
Definition: living.h:42
#define MIN(x, y)
Definition: compat.h:17
int8_t Con
Definition: living.h:35
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:232
int16_t hp
Hit Points.
Definition: living.h:39
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.c:71
static void monster_pace2_moveh(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.c:1971
One reply a NPC can expect.
Definition: dialog.h:18
See Magic Ear.
Definition: object.h:131
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.c:1797
#define NDI_NAVY
Definition: newclient.h:223
uint16_t height
Width and height of map.
Definition: map.h:347
#define FLAG_SEE_INVISIBLE
Will see invisible player.
Definition: define.h:253
Throwing.
Definition: skills.h:44
static void monster_circ1_move(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.c:1904
#define FLAG_READY_SKILL
(Monster or Player) has a skill readied
Definition: define.h:334
struct obj * chosen_skill
The skill chosen to use.
Definition: object.h:386
int object_set_value(object *op, const char *key, const char *value, int add_key)
Updates the key in op to value.
Definition: object.c:4375
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1368
int16_t y
Position in the map for this object.
Definition: object.h:326
#define RUNATT
Run but attack if player catches up to object.
Definition: define.h:508
int16_t maxhp
Max hit points.
Definition: living.h:40
int dirdiff(int dir1, int dir2)
Computes a direction difference.
Definition: object.c:3655
reply_type
Various kind of messages a player or NPC can say.
Definition: dialog.h:9
#define HI4
Definition: define.h:567
See Shooting Weapon.
Definition: object.h:118
#define SP_BULLET
Definition: spells.h:79
int replies_count
How many items in replies_words and replies.
Definition: dialog.h:56
Asking a question.
Definition: dialog.h:12
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:230
void do_hidden_move(object *op)
For hidden creatures - a chance of becoming &#39;unhidden&#39; every time they move - as we subtract off &#39;inv...
Definition: player.c:4025
#define AP_IGNORE_CURSE
Apply/unapply regardless of cursed/damned status.
Definition: define.h:617
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.c:2505
static void monster_rand_move(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.c:1986
int get_randomized_dir(int dir)
Returns a random direction (1..8) similar to a given direction.
Definition: utils.c:438
static int monster_get_armour_quality(const object *item)
Returns the "quality" value of an armour of a monster.
Definition: monster.c:1442
#define MAX_REPLIES
How many NPC replies maximum to tell the player.
Definition: dialog.h:44
int object_can_pick(const object *who, const object *item)
Finds out if an object can be picked up.
Definition: object.c:3793
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.c:2690
signed short int16_t
Definition: win32.h:160
See Treasure.
Definition: object.h:110
#define FLAG_READY_SCROLL
monster has scroll in inv and can use it
Definition: define.h:325
int32_t weight
Attributes of the object.
Definition: object.h:365
#define FLAG_CAN_USE_SKILL
The monster can use skills.
Definition: define.h:322
#define MOVE_FLY_LOW
Low flying object.
Definition: define.h:408
Structure used to build up dialog information when a player says something.
Definition: dialog.h:51
uint32_t tmp_invis
Will invis go away when we attack?
Definition: player.h:125
void drain_rod_charge(object *rod)
Drain charges from a rod.
Definition: spell_util.c:819
#define SP_BOMB
Definition: spells.h:82
int8_t Wis
Definition: living.h:35
const char * text
What the player actually said.
Definition: dialog.h:53
#define FLAG_UNAGGRESSIVE
Monster doesn&#39;t attack players.
Definition: define.h:272
#define FLAG_USE_SHIELD
Can this creature use a shield?
Definition: define.h:237
static StringBuffer * monster_format_say(const object *npc, const char *message)
Format an NPC message.
Definition: monster.c:2047
#define FLAG_USE_RANGE
(Monster) can apply and use range items
Definition: define.h:293
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
#define snprintf
Definition: win32.h:46
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
Returns true if the given object can&#39;t fit in the given spot.
Definition: map.c:489
void monster_do_say(const mapstruct *map, const char *message)
Output a NPC message on a map.
Definition: monster.c:2036
static int monster_check_good_weapon(object *who, object *item)
Checks if using weapon &#39;item&#39; would be better for &#39;who&#39;.
Definition: monster.c:1416
object * get_nearest_player(object *mon)
Finds the nearest visible player for some object.
Definition: player.c:520
int pets_should_arena_attack(object *pet, object *owner, object *target)
Determines if checks so pets don&#39;t attack players or other pets should be overruled by the arena petm...
Definition: pets.c:1152
#define WILL_APPLY_TREASURE
Open chests.
Definition: object.h:53
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:712
Reply to something.
Definition: dialog.h:11
int16_t dam
How much damage this object does when hitting.
Definition: living.h:45
Definition: object.h:145
int32_t carrying
How much weight this object contains.
Definition: object.h:367
#define PACEH
The monster will pace back and forth until attacked.
Definition: define.h:540
void monster_check_apply_all(object *monster)
Calls monster_check_apply() for all inventory objects.
Definition: monster.c:1757
object * monster_find_nearest_living_creature(object *npc)
Returns the nearest living creature (monster or generator).
Definition: monster.c:152
const char * name
The name of the object, obviously...
Definition: object.h:311
static int monster_can_hit(object *ob1, object *ob2, rv_vector *rv)
Checks if monster can hit in hand-to-hand combat.
Definition: monster.c:909
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.c:1894
static void monster_pace2_movev(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.c:1956
char * reply
Reply expected from the player.
Definition: dialog.h:19
int distance_x
X delta.
Definition: map.h:382
#define MSG_TYPE_COMMUNICATION_SAY
Player says something.
Definition: newclient.h:618
void ext_info_map_except(int color, const mapstruct *map, const object *op, uint8_t type, uint8_t subtype, const char *str1)
Writes to everyone on the map except *op.
Definition: info.c:185
#define SP_SMITE
Definition: spells.h:84
int is_true_undead(object *op)
Is the object a true undead?
Definition: player.c:3961
#define MSG_TYPE_COMMUNICATION
Communication between players.
Definition: newclient.h:386
object * monster_find_throw_ob(object *op)
Find an item for the monster to throw.
Definition: monster.c:2283
void monster_communicate(object *op, const char *txt)
This function looks for an object or creature that is listening to said text.
Definition: monster.c:2118
#define GET_MAP_LIGHT(M, X, Y)
Gets map light.
Definition: map.h:165
#define FLAG_PARALYZED
Monster or player is paralyzed.
Definition: define.h:380
int8_t direction
Means the object is moving that way.
Definition: object.h:334
#define AP_NOPRINT
Don&#39;t print messages - caller will do that may be some that still print.
Definition: define.h:621
void monster_check_earthwalls(object *op, mapstruct *m, int x, int y)
Living creature attempts to hit an earthwall.
Definition: monster.c:2006
static object * monster_choose_random_spell(object *monster)
Selects a spell to cast for a monster.
Definition: monster.c:992
#define SIZEOFFREE
Definition: define.h:154
#define P_OUT_OF_MAP
This space is outside the map.
Definition: map.h:251
Number of statistics.
Definition: living.h:18
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Gets the blocking state of a square.
Definition: map.h:192
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.c:429
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.c:1875
struct pl * contr
Pointer to the player which control this object.
Definition: object.h:276
#define FLAG_SCARED
Monster is scared (mb player in future)
Definition: define.h:271
uint8_t darkness
Indicates level of darkness of map.
Definition: map.h:346
#define SP_INVISIBLE
Definition: spells.h:93
#define MSG_TYPE_SKILL_FAILURE
Failure in using skill.
Definition: newclient.h:585
static int monster_move_randomly(object *op)
Handles random object movement.
Definition: monster.c:342
#define FLAG_ONLY_ATTACK
NPC will evaporate if there is no enemy.
Definition: define.h:311
#define FLAG_XRAYS
X-ray vision.
Definition: define.h:301
void use_trigger(object *op)
Toggles the state of specified button.
Definition: button.c:259
#define ATNR_PHYSICAL
Definition: attack.h:49
static void monster_pace_moveh(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.c:1943
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.c:4024
#define AT_PHYSICAL
Definition: attack.h:76
float speed
The overall speed of this object.
Definition: object.h:328
See Spell.
Definition: object.h:214
int on_same_map(const object *op1, const object *op2)
Checks whether 2 objects are on the same map or not.
Definition: map.c:2627
#define CAN_APPLY_NOT_MASK
Definition: define.h:667
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:594
See Handle Trigger.
Definition: object.h:129
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:231
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
#define SP_SWARM
Definition: spells.h:110
#define IS_SHIELD(op)
Definition: define.h:169
See Door.
Definition: object.h:126
Many many details.
Definition: logger.h:14
int fire_bow(object *op, object *arrow, int dir, int wc_mod, int16_t sx, int16_t sy)
Creature (monster or player) fires a bow.
Definition: player.c:2173
#define FLAG_CAST_SPELL
(Monster) can learn and cast spells
Definition: define.h:291
int16_t x
Definition: object.h:326
#define FLAG_BERSERK
monster will attack closest living object
Definition: define.h:359
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.c:1240
#define WAITATT
Wait for player to approach then hit, move if hit.
Definition: define.h:510
static int monster_use_range(object *head, object *part, object *pl, int dir)
Monster will use a ranged attack (ROD, WAND, ...).
Definition: monster.c:1257
#define FLAG_RUN_AWAY
Object runs away from nearest player \ but can still attack at a distance.
Definition: define.h:280
Skill-related defines, including subtypes.
Basic sentence.
Definition: dialog.h:10
int8_t wc
Weapon Class, how skilled, the lower the better.
Definition: living.h:36
#define ALLRUN
Always run, never attack good for sim.
Definition: define.h:512
#define FLAG_IS_THROWN
Object is designed to be thrown.
Definition: define.h:249
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:765
int8_t Str
Definition: living.h:35
void animate_object(object *op, int dir)
Updates the face-variable of an object.
Definition: anim.c:186
int16_t resist[NROFATTACKS]
Resistance adjustments for attacks.
Definition: object.h:341
int has_carried_lights(const object *op)
Checks if op has a light source.
Definition: los.c:311
const char * sstring
Strings that should be manipulated through add_string() and free_string().
Definition: global.h:40
void monster_check_doors(object *op, mapstruct *m, int x, int y)
Living creature attempts to open a door.
Definition: monster.c:2022
unsigned int uint32_t
Definition: win32.h:162
See Player.
Definition: object.h:107
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Find object in inventory.
Definition: object.c:4195
#define RUSH
Rush toward player blindly, similiar to dumb monster.
Definition: define.h:511
int8_t body_info[NUM_BODY_LOCATIONS]
Body info as loaded from the file.
Definition: object.h:372
#define WAIT2
Monster does not try to move towards player if far.
Definition: define.h:514
#define FLAG_GENERATOR
Will generate type ob->stats.food.
Definition: define.h:248
struct obj * spellitem
Spell ability monster is choosing to use.
Definition: object.h:394
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.c:2463
#define FLAG_BLIND
If set, object cannot see (visually)
Definition: define.h:337
#define WILL_APPLY_HANDLE
Apply handles and triggers.
Definition: object.h:52
#define FLAG_NEUTRAL
monster is from type neutral
Definition: define.h:362
static const char * get_reply_text_own(reply_type rt)
Return the verb for the player&#39;s dialog type.
Definition: monster.c:2062
#define RANDOM()
Definition: define.h:679
#define MAX_NPC
How many NPCs maximum will reply to the player.
Definition: dialog.h:46
int16_t grace
Grace.
Definition: living.h:43
Also see SKILL_TOOL (74) below.
Definition: object.h:143
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.c:1333
static void monster_check_apply(object *mon, object *item)
Called after an item is inserted in a monster.
Definition: monster.c:1498
tag_t count
Unique object number for this object.
Definition: object.h:299
living stats
Str, Con, Dex, etc.
Definition: object.h:368
struct archt * arch
Pointer to archetype.
Definition: object.h:412
Only for debugging purposes.
Definition: logger.h:13
Hiding.
Definition: skills.h:21
#define RANDO2
Constantly move in a different random direction.
Definition: define.h:555
uint8_t will_apply
See crossfire.doc and What monsters apply.
Definition: object.h:392
static int monster_move_no_enemy(object *op)
Makes a monster without any enemy move.
Definition: monster.c:563
One message a NPC can react to.
Definition: dialog.h:28
uint16_t width
Definition: map.h:347
unsigned int distance
Distance, in squares.
Definition: map.h:381
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
void object_set_enemy(object *op, object *enemy)
Sets the enemy of an object.
Definition: object.c:679
int direction
General direction to the targer.
Definition: map.h:384
See Handle.
Definition: object.h:208
static int monster_use_skill(object *head, object *part, object *pl, int dir)
A monster attempts using a skill.
Definition: monster.c:1200
#define SP_MAGIC_MISSILE
Definition: spells.h:85
void monster_npc_call_help(object *op)
A monster calls for help against its enemy.
Definition: monster.c:1767
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:235
#define NROFATTACKS
Definition: attack.h:17
int move_object(object *op, int dir)
Try to move op in the direction "dir".
Definition: move.c:39
signed int int32_t
Definition: win32.h:159
#define SIZEOFFREE2
Definition: define.h:153
#define SP_SUMMON_MONSTER
Definition: spells.h:101
struct struct_dialog_reply * replies
Replies this message has.
Definition: dialog.h:31
char * message
What the NPC will say.
Definition: dialog.h:30
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.c:1816
object * monster_check_enemy(object *npc, rv_vector *rv)
Checks npc->enemy and returns that enemy if still valid, NULL otherwise.
Definition: monster.c:71
sstring add_string(const char *str)
This will add &#39;str&#39; to the hash table.
Definition: shstr.c:124
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
Definition: stringbuffer.c:104
#define MIN_ACTIVE_SPEED
Cut off point of when an object is put on the active list or not.
Definition: define.h:674
#define DISTATT
Move toward a player if far, but maintain some space, attack from a distance - good for missile users...
Definition: define.h:505
int8_t glow_radius
indicates the glow radius of the object
Definition: object.h:364
int monster_move(object *op)
Main monster processing routine.
Definition: monster.c:635
#define FLAG_MONSTER
Will attack players.
Definition: define.h:245
#define MSG_TYPE_SKILL
Messages related to skill use.
Definition: newclient.h:383
static void monster_check_pickup(object *monster)
Checks for items that monster can pick up.
Definition: monster.c:1615
int8_t Pow
Definition: living.h:35
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.c:302
struct obj * inv
Pointer to the first object in the inventory.
Definition: object.h:290
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:245
#define FLAG_READY_BOW
not implemented yet
Definition: define.h:300
sstring npc_msgs[MAX_NPC]
What the NPCs will say.
Definition: dialog.h:60
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
int monster_stand_in_light(object *op)
Determine if op stands in a lighted square.
Definition: monster.c:2462
static void monster_pace_movev(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.c:1930
void make_visible(object *op)
Makes an object visible again.
Definition: player.c:3941
#define SP_MAGIC_WALL
Definition: spells.h:89
uint8_t pick_up
See crossfire.doc.
Definition: object.h:361
#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:543
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:758
uint8_t run_away
Monster runs away if it&#39;s hp goes below this percentage.
Definition: object.h:384
#define IS_ARMOR(op)
Definition: define.h:165
static void monster_apply_below(object *monster)
If a monster who&#39;s eager to apply things encounters something apply-able, then make him apply it...
Definition: monster.c:1734
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.c:3745
#define PACEV
The monster will pace back and forth until attacked.
Definition: define.h:556
#define WILL_APPLY_FOOD
Eat food (not drinks).
Definition: object.h:56
struct struct_dialog_reply * next
Next reply, NULL for last.
Definition: dialog.h:22
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.c:25
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.c:625
#define SPELL_MANA
Definition: spells.h:58
#define FOR_BELOW_PREPARE(op_, it_)
Constructs a loop iterating over all objects below an object.
Definition: define.h:739
static int monster_can_pick(object *monster, object *item)
Check if the monster can and is interested in picking up an item.
Definition: monster.c:1653
#define CIRCLE2
Same as CIRCLE1 but a larger circle is used.
Definition: define.h:539
object * find_skill_by_number(object *who, int skillno)
This returns the skill pointer of the given name (the one that accumulates exp, has the level...
Definition: main.c:351
reply_type type
Type of message.
Definition: dialog.h:21
This is a game-map.
Definition: map.h:325
#define P_IS_ALIVE
Something alive is on this space.
Definition: map.h:237
object * pets_get_enemy(object *pet, rv_vector *rv)
Given that &#39;pet&#39; is a friendly object, this function returns a monster the pet should attack...
Definition: pets.c:57
const New_Face * face
Face with colors.
Definition: object.h:332
See Jewel.
Definition: object.h:167
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Object is attacked by something.
Definition: attack.c:1861
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.c:2516
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.c:325
int32_t move_status
What stage in attack mode.
Definition: object.h:390
int16_t level
Level of creature or object.
Definition: object.h:351
int8_t facing
Object is oriented/facing that way.
Definition: object.h:335
#define SP_SUMMON_GOLEM
Definition: spells.h:86
#define SP_EXPLOSION
Definition: spells.h:80
static int monster_do_talk_npc(object *npc, talk_info *info)
Checks the messages of a NPC for a matching text.
Definition: monster.c:2192
struct obj * more
Pointer to the rest of a large body of objects.
Definition: object.h:295
static void monster_circ2_move(object *ob)
Move the monster in a specified movement pattern.
Definition: monster.c:1917
object * object_get_owner(object *op)
Returns the object which this object marks as being the owner.
Definition: object.c:559
int8_t magic
Any magical bonuses to this item.
Definition: object.h:348
#define FLAG_USE_BOW
(Monster) can apply and fire bows
Definition: define.h:294
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.c:76
#define FOR_BELOW_FINISH()
Finishes FOR_BELOW_PREPARE().
Definition: define.h:746
int monster_can_detect_enemy(object *op, object *enemy, rv_vector *rv)
Determine if we can &#39;detect&#39; the enemy.
Definition: monster.c:2322
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:705
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Main dispatch when someone casts a spell.
Definition: spell_util.c:1471
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.c:1654
#define DISTHIT
Attack from a distance if hit as recommended by Frank.
Definition: define.h:513
#define MAX_KNOWN_SPELLS
Maximum number of spells to consider when choosing a spell for a monster.
Definition: monster.c:975
struct obj * attacked_by
This object start to attack us! only player & monster.
Definition: object.h:382
#define FLAG_FREED
Object is in the list of free objects.
Definition: define.h:233
static int monster_check_wakeup(object *op, object *enemy, rv_vector *rv)
Sees if this monster should wake up.
Definition: monster.c:296
#define LO4
bitmasks for upper and lower 4 bits from 8 bit fields
Definition: define.h:566