Crossfire Server, Trunk  R21670
object.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 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 
19 /* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects.
20  object_sub/add_weight will transcend the environment updating the carrying
21  variable. */
22 
23 #include "global.h"
24 
25 #include <assert.h>
26 #include <stddef.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #ifndef WIN32 /* ---win32 exclude headers */
32 #include <sys/types.h>
33 #include <sys/uio.h>
34 #endif /* win32 */
35 
36 #include "loader.h"
37 #include "object.h"
38 #include "skills.h"
39 #include "sproto.h"
40 #include "stringbuffer.h"
41 
42 static int compare_ob_value_lists_one(const object *, const object *);
43 static int compare_ob_value_lists(const object *, const object *);
44 static void expand_objects(void);
45 static void permute(int *, int, int);
46 static int object_set_value_s(object *, const char *, const char *, int);
47 static void object_increase_nrof(object *op, uint32_t i);
48 
49 #ifdef MEMORY_DEBUG
50 int nroffreeobjects = 0;
51 int nrofallocobjects = 0;
52 #undef OBJ_EXPAND
53 #define OBJ_EXPAND 1
54 #else
55 static object objarray[STARTMAX];
58 #endif
59 
60 object *objects;
61 static object *free_objects;
62 object *active_objects;
66  0, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2, -1,
67  0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -3, -3, -3, -3, -2, -1
68 };
69 
72  0, -1, -1, 0, 1, 1, 1, 0, -1, -2, -2, -2, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2,
73  -3, -3, -3, -3, -2, -1, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3
74 };
75 
78  0, 9, 10, 13, 14, 17, 18, 21, 22, 25, 26, 27, 30, 31, 32, 33, 36, 37, 39, 39, 42, 43, 44, 45,
79  48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49
80 };
81 
84  0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 7, 8, 8, 8,
85  1, 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8
86 };
87 
93 void init_objects(void) {
94  /* Initialize all objects: */
95  objects = NULL;
96  active_objects = NULL;
97 
98 #ifdef MEMORY_DEBUG
99  free_objects = NULL;
100 #else
101  free_objects = objarray;
102  objarray[0].prev = NULL,
103  objarray[0].next = &objarray[1],
104  SET_FLAG(&objarray[0], FLAG_REMOVED);
105  SET_FLAG(&objarray[0], FLAG_FREED);
106  for (int i = 1; i < STARTMAX-1; i++) {
107  objarray[i].next = &objarray[i+1];
108  objarray[i].prev = &objarray[i-1];
109  SET_FLAG(&objarray[i], FLAG_REMOVED);
110  SET_FLAG(&objarray[i], FLAG_FREED);
111  }
112  objarray[STARTMAX-1].next = NULL;
113  objarray[STARTMAX-1].prev = &objarray[STARTMAX-2];
114  SET_FLAG(&objarray[STARTMAX-1], FLAG_REMOVED);
115  SET_FLAG(&objarray[STARTMAX-1], FLAG_FREED);
116 #endif
117 }
118 
129 static int compare_ob_value_lists_one(const object *wants, const object *has) {
130  key_value *wants_field;
131 
132  /* n-squared behaviour (see object_get_key_value()), but I'm hoping both
133  * objects with lists are rare, and lists stay short. If not, use a
134  * different structure or at least keep the lists sorted...
135  */
136 
137  /* For each field in wants, */
138  for (wants_field = wants->key_values; wants_field != NULL; wants_field = wants_field->next) {
139  key_value *has_field;
140 
141  /* Look for a field in has with the same key. */
142  has_field = object_get_key_value(has, wants_field->key);
143 
144  if (has_field == NULL) {
145  /* No field with that name. */
146  return FALSE;
147  }
148 
149  /* Found the matching field. */
150  if (has_field->value != wants_field->value) {
151  /* Values don't match, so this half of the comparison is false. */
152  return FALSE;
153  }
154 
155  /* If we get here, we found a match. Now for the next field in wants. */
156  }
157 
158  /* If we get here, every field in wants has a matching field in has. */
159  return TRUE;
160 }
161 
170 static int compare_ob_value_lists(const object *ob1, const object *ob2) {
171  /* However, there may be fields in has which aren't partnered in wants,
172  * so we need to run the comparison *twice*. :(
173  */
174  return compare_ob_value_lists_one(ob1, ob2) && compare_ob_value_lists_one(ob2, ob1);
175 }
176 
199 int object_can_merge(object *ob1, object *ob2) {
200  /* A couple quicksanity checks */
201  if (ob1 == ob2 || ob1->type != ob2->type)
202  return 0;
203 
204  if (ob1->speed != ob2->speed)
205  return 0;
206  /* Note sure why the following is the case - either the object has to
207  * be animated or have a very low speed. Is this an attempted monster
208  * check?
209  */
210  /*TODO is this check really needed?*/
211  if (!QUERY_FLAG(ob1, FLAG_ANIMATE) && FABS((ob1)->speed) > MIN_ACTIVE_SPEED)
212  return 0;
213 
214  /* Do not merge objects if nrof would overflow. We use 1UL<<31 since that
215  * value could not be stored in a int32_t (which unfortunately sometimes is
216  * used to store nrof).
217  */
218  if (ob1->nrof+ob2->nrof >= 1UL<<31)
219  return 0;
220 
221  /* This is really a spellbook check - really, we should
222  * check all objects in the inventory.
223  */
224  /*TODO is this check really needed?*/
225  if (ob1->inv || ob2->inv) {
226  /* if one object has inventory but the other doesn't, not equiv */
227  if ((ob1->inv && !ob2->inv) || (ob2->inv && !ob1->inv))
228  return 0;
229 
230  /* Now check to see if the two inventory objects could merge */
231  if (!object_can_merge(ob1->inv, ob2->inv))
232  return 0;
233 
234  /* inventory ok - still need to check rest of this object to see
235  * if it is valid.
236  */
237  }
238 
239  /* If the objects have been identified, set the BEEN_APPLIED flag.
240  * This is to the comparison of the flags below will be OK. We
241  * just can't ignore the been applied or identified flags, as they
242  * are not equal - just if it has been identified, the been_applied
243  * flags lose any meaning.
244  */
245 
246  /*TODO is this hack on BEEN_APPLIED really needed? */
247  if (QUERY_FLAG(ob1, FLAG_IDENTIFIED))
249 
250  if (QUERY_FLAG(ob2, FLAG_IDENTIFIED))
252 
253 
254  /* Note: FLAG_INV_LOCKED is ignored for merging purposes */
255  if ((ob1->arch != ob2->arch)
256  || (ob1->flags[0] != ob2->flags[0])
257  || (ob1->flags[1] != ob2->flags[1])
258  || (ob1->flags[2] != ob2->flags[2])
259  || ((ob1->flags[3]&~0x84) != (ob2->flags[3]&~0x84)) /* ignore CLIENT_SENT and FLAG_OBJ_ORIGINAL */
260  || (ob1->name != ob2->name)
261  || (ob1->title != ob2->title)
262  || (ob1->msg != ob2->msg)
263  || (ob1->weight != ob2->weight)
264  || (ob1->item_power != ob2->item_power)
265  || (memcmp(&ob1->resist, &ob2->resist, sizeof(ob1->resist)) != 0)
266  || (memcmp(&ob1->stats, &ob2->stats, sizeof(ob1->stats)) != 0)
267  || (ob1->attacktype != ob2->attacktype)
268  || (ob1->magic != ob2->magic)
269  || (ob1->slaying != ob2->slaying)
270  || (ob1->skill != ob2->skill)
271  || (ob1->value != ob2->value)
272  || (ob1->animation != ob2->animation)
273  || (ob1->client_type != ob2->client_type)
274  || (ob1->materialname != ob2->materialname)
275  || (ob1->lore != ob2->lore)
276  || (ob1->subtype != ob2->subtype)
277  || (ob1->move_type != ob2->move_type)
278  || (ob1->move_block != ob2->move_block)
279  || (ob1->move_allow != ob2->move_allow)
280  || (ob1->move_on != ob2->move_on)
281  || (ob1->move_off != ob2->move_off)
282  || (ob1->move_slow != ob2->move_slow)
283  || (ob1->move_slow_penalty != ob2->move_slow_penalty)
284  || (ob1->map_layer != ob2->map_layer))
285  return 0;
286 
287  /* Don't merge objects that are applied. With the new 'body' code,
288  * it is possible for most any character to have more than one of
289  * some items equipped, and we don't want those to merge.
290  */
291  if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED))
292  return 0;
293 
294  if (ob1->key_values != NULL || ob2->key_values != NULL) {
295  /* At least one of these has key_values. */
296  if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) {
297  /* One has fields, but the other one doesn't. */
298  return 0;
299  } else {
300  if (!compare_ob_value_lists(ob1, ob2)) {
301  return 0;
302  }
303  }
304  }
305 
306  /*TODO should this really be limited to scrolls?*/
307  switch (ob1->type) {
308  case SCROLL:
309  if (ob1->level != ob2->level)
310  return 0;
311  break;
312  }
313 
314  /* Don't merge items with differing custom names. */
315  if (ob1->custom_name != ob2->custom_name)
316  return 0;
317 
318  /* Everything passes, must be OK. */
319  return 1;
320 }
321 
337 /* TODO should check call this this are made a place where we really need reevaluaton of whole tree */
338 signed long object_sum_weight(object *op) {
339  signed long sum;
340 
341  sum = 0;
342  FOR_INV_PREPARE(op, inv) {
343  if (inv->inv)
344  object_sum_weight(inv);
345  sum += inv->carrying+inv->weight*NROF(inv);
346  } FOR_INV_FINISH();
347  if (op->type == CONTAINER && op->stats.Str)
348  sum = (sum*(100-op->stats.Str))/100;
349  op->carrying = sum;
350  return sum;
351 }
352 
360 object *object_get_env_recursive(object *op) {
361  while (op->env != NULL)
362  op = op->env;
363  return op;
364 }
365 
377 object *object_get_player_container(object *op) {
378  for (; op != NULL && op->type != PLAYER; op = op->env)
379  /*TODO this is patching the structure on the flight as side effect. Shoudln't be needed in clean code */
380  if (op->env == op)
381  op->env = NULL;
382  return op;
383 }
384 
394 static const object *object_get_owner_const(const object *op) {
395  if (op->owner == NULL)
396  return NULL;
397 
398  if (!QUERY_FLAG(op->owner, FLAG_FREED)
399  && !QUERY_FLAG(op->owner, FLAG_REMOVED)
400  && op->owner->count == op->ownercount)
401  return op->owner;
402 
403  LOG(llevError, "Warning, no owner found\n");
404  return NULL;
405 }
406 
415 void object_dump(const object *op, StringBuffer *sb) {
416  if (op == NULL) {
417  stringbuffer_append_string(sb, "[NULL pointer]");
418  return;
419  }
420 
421  /* object *tmp;*/
422 
423  if (op->arch != NULL) {
424  const object *owner;
425 
426  stringbuffer_append_string(sb, "arch ");
427  stringbuffer_append_string(sb, op->arch->name ? op->arch->name : "(null)");
428  stringbuffer_append_string(sb, "\n");
429 
430  if (op->artifact != NULL) {
431  stringbuffer_append_string(sb, "artifact ");
433  stringbuffer_append_string(sb, "\n");
434  }
435 
436  get_ob_diff(sb, op, &empty_archetype->clone);
437  if (op->more) {
438  stringbuffer_append_printf(sb, "more %u\n", op->more->count);
439  }
440  if (op->head) {
441  stringbuffer_append_printf(sb, "head %u\n", op->head->count);
442  }
443  if (op->env) {
444  stringbuffer_append_printf(sb, "env %u\n", op->env->count);
445  }
446  if (op->inv) {
447  stringbuffer_append_printf(sb, "inv %u\n", op->inv->count);
448  }
449  owner = object_get_owner_const(op);
450  if (owner != NULL) {
451  stringbuffer_append_printf(sb, "owner %u\n", owner->count);
452  }
453  stringbuffer_append_string(sb, "end\n");
454  } else {
455  stringbuffer_append_string(sb, "Object ");
456  stringbuffer_append_string(sb, op->name == NULL ? "(null)" : op->name);
457  stringbuffer_append_string(sb, "\nend\n");
458  }
459 }
460 
468 void object_dump_all(void) {
469  object *op;
470 
471  for (op = objects; op != NULL; op = op->next) {
472  StringBuffer *sb;
473  char *diff;
474 
475  sb = stringbuffer_new();
476  object_dump(op, sb);
477  diff = stringbuffer_finish(sb);
478  LOG(llevDebug, "Object %u\n:%s\n", op->count, diff);
479  free(diff);
480  }
481 }
482 
492  object *op;
493 
494  for (op = objects; op != NULL; op = op->next)
495  if (op->count == i)
496  break;
497  return op;
498 }
499 
511 object *object_find_by_name_global(const char *str) {
512  const char *name = add_string(str);
513  object *op;
514 
515  for (op = objects; op != NULL; op = op->next)
516  if (op->name == name)
517  break;
518  free_string(name);
519  return op;
520 }
521 
532 #ifdef MEMORY_DEBUG
533  object *op, *next;
534 
535  for (op = free_objects; op != NULL; ) {
536  next = op->next;
537  free(op);
539  nroffreeobjects--;
540  op = next;
541  }
542  free_objects = NULL;
543 
544  for (op = objects; op != NULL; ) {
545  next = op->next;
546  if (!QUERY_FLAG(op, FLAG_FREED)) {
547  LOG(llevDebug, "non freed object: %s\n", op->name);
548  }
549  op = next;
550  }
551 #endif
552 
553  LOG(llevDebug, "%d allocated objects, %d free objects, STARMAX=%d\n", nrofallocobjects, nroffreeobjects, STARTMAX);
554 }
555 
568 object *object_get_owner(object *op) {
569  if (op->owner == NULL)
570  return NULL;
571 
572  if (!QUERY_FLAG(op->owner, FLAG_FREED)
573  && !QUERY_FLAG(op->owner, FLAG_REMOVED)
574  && op->owner->count == op->ownercount)
575  return op->owner;
576 
577  object_clear_owner(op);
578  return NULL;
579 }
580 
587 void object_clear_owner(object *op) {
588  if (!op)
589  return;
590 
591  op->owner = NULL;
592  op->ownercount = 0;
593 }
594 
604 void object_set_owner(object *op, object *owner) {
605  /* Assign temp to something, so it can't accidentally be NULL */
606  object *tmp = owner;
607  if (op == NULL)
608  return;
609  if (owner == NULL) {
610  object_clear_owner(op);
611  return;
612  }
613 
614  /* next line added to allow objects which own objects */
615  /* Add a check for ownercounts in here, as I got into an endless loop
616  * with the fireball owning a poison cloud which then owned the
617  * fireball. I believe that was caused by one of the objects getting
618  * freed and then another object replacing it. Since the ownercounts
619  * didn't match, this check is valid and I believe that cause is valid.
620  */
621  /*
622  * if owner is NULL, function will have already returned,
623  * so loop should still function as before.
624  */
625  while (tmp) {
626  tmp = object_get_owner(owner);
627  if (tmp)
628  owner = tmp;
629  }
630 
631  /* must not cause owner cycles */
632  assert(op != owner);
633 
634  if (op->owner != NULL)
635  object_clear_owner(op);
636 
637  op->owner = owner;
638  op->ownercount = owner->count;
639 }
640 
657 void object_copy_owner(object *op, object *clone) {
658  object *owner = object_get_owner(clone);
659  if (owner == NULL) {
660  /* players don't have owners - they own themselves. Update
661  * as appropriate.
662  */
663  /*TODO owner=self is dangerous and should be avoided*/
664  if (clone->type != PLAYER)
665  return;
666  owner = clone;
667  }
668  object_set_owner(op, owner);
669 }
670 
679 void object_set_enemy(object *op, object *enemy) {
680  if (op->enemy == enemy) {
681  return;
682  }
683 
684 #if 0
685  if (op->type != PLAYER) {
686  LOG(llevDebug, "object_set_enemy: %s(%lu)->enemy=%s(%lu)\n", op->name, op->count, enemy == NULL ? "NONE" : enemy->name, enemy == NULL ? 0 : enemy->count);
687  }
688 #endif
689  op->enemy = enemy;
690 }
691 
698 void object_reset(object *op) {
699  op->name = NULL;
700  op->name_pl = NULL;
701  op->title = NULL;
702  op->race = NULL;
703  op->slaying = NULL;
704  op->skill = NULL;
705  op->msg = NULL;
706  op->materialname = NULL;
707  op->lore = NULL;
708  object_clear(op);
709 }
710 
718 void object_free_key_values(object *op) {
719  key_value *i;
720  key_value *next = NULL;
721 
722  if (op->key_values == NULL)
723  return;
724 
725  for (i = op->key_values; i != NULL; i = next) {
726  /* Store next *first*. */
727  next = i->next;
728 
729  if (i->key)
731  if (i->value)
733  i->next = NULL;
734  free(i);
735  }
736 
737  op->key_values = NULL;
738 }
739 
747 void object_clear(object *op) {
748  /*TODO this comment must be investigated*/
749  /* redo this to be simpler/more efficient. Was also seeing
750  * crashes in the old code. Move this to the top - am
751  * seeing periodic crashes in this code, and would like to have
752  * as much info available as possible (eg, object name).
753  */
756 
757  /* the memset will clear all these values for us, but we need
758  * to reduce the refcount on them.
759  */
760  if (op->name != NULL)
762  if (op->name_pl != NULL)
764  if (op->title != NULL)
766  if (op->race != NULL)
768  if (op->slaying != NULL)
770  if (op->skill != NULL)
772  if (op->msg != NULL)
773  FREE_AND_CLEAR_STR(op->msg);
774  if (op->lore != NULL)
776  if (op->materialname != NULL)
778 
779  /* Remove object from friendly list if needed. */
780  if (QUERY_FLAG(op, FLAG_FRIENDLY))
782 
783  memset((void *)((char *)op+offsetof(object, name)), 0, sizeof(object)-offsetof(object, name));
784  /* Below here, we clear things that are not done by the memset,
785  * or set default values that are not zero.
786  */
787  /* This is more or less true */
788  SET_FLAG(op, FLAG_REMOVED);
789 
790 
791  op->contr = NULL;
792  op->below = NULL;
793  op->above = NULL;
794  op->inv = NULL;
795  op->container = NULL;
796  op->env = NULL;
797  op->more = NULL;
798  op->head = NULL;
799  op->map = NULL;
800  op->active_next = NULL;
801  op->active_prev = NULL;
802  /* What is not cleared is next, prev, and count */
803 
804  op->expmul = 1.0;
805  op->face = blank_face;
806  op->attacked_by_count = -1;
808  op->casting_time = -1;
809 }
810 
824 void object_copy(const object *src_ob, object *dest_ob) {
825  int is_freed = QUERY_FLAG(dest_ob, FLAG_FREED), is_removed = QUERY_FLAG(dest_ob, FLAG_REMOVED);
826 
827  /* Decrement the refcounts, but don't bother zeroing the fields;
828  they'll be overwritten by memcpy. */
829  if (dest_ob->artifact != NULL)
830  free_string(dest_ob->artifact);
831  if (dest_ob->name != NULL)
832  free_string(dest_ob->name);
833  if (dest_ob->name_pl != NULL)
834  free_string(dest_ob->name_pl);
835  if (dest_ob->anim_suffix != NULL)
836  free_string(dest_ob->anim_suffix);
837  if (dest_ob->title != NULL)
838  free_string(dest_ob->title);
839  if (dest_ob->race != NULL)
840  free_string(dest_ob->race);
841  if (dest_ob->slaying != NULL)
842  free_string(dest_ob->slaying);
843  if (dest_ob->skill != NULL)
844  free_string(dest_ob->skill);
845  if (dest_ob->msg != NULL)
846  free_string(dest_ob->msg);
847  if (dest_ob->lore != NULL)
848  free_string(dest_ob->lore);
849  if (dest_ob->materialname != NULL)
850  free_string(dest_ob->materialname);
851  if (dest_ob->custom_name != NULL)
852  free_string(dest_ob->custom_name);
853  if (dest_ob->spell_tags != NULL)
854  FREE_AND_CLEAR(dest_ob->spell_tags);
855 
856  /* Basically, same code as from object_clear() */
857 
858  object_free_key_values(dest_ob);
859  free_dialog_information(dest_ob);
860 
861  /* Copy all attributes below name (name included). */
862  (void)memcpy((void *)((char *)dest_ob+offsetof(object, name)),
863  (void *)((char *)src_ob+offsetof(object, name)),
864  sizeof(object)-offsetof(object, name));
865 
866  if (is_freed)
867  SET_FLAG(dest_ob, FLAG_FREED);
868  if (is_removed)
869  SET_FLAG(dest_ob, FLAG_REMOVED);
870  if (dest_ob->artifact != NULL)
871  add_refcount(dest_ob->artifact);
872  if (dest_ob->name != NULL)
873  add_refcount(dest_ob->name);
874  if (dest_ob->name_pl != NULL)
875  add_refcount(dest_ob->name_pl);
876  if (dest_ob->anim_suffix != NULL)
877  add_refcount(dest_ob->anim_suffix);
878  if (dest_ob->title != NULL)
879  add_refcount(dest_ob->title);
880  if (dest_ob->race != NULL)
881  add_refcount(dest_ob->race);
882  if (dest_ob->slaying != NULL)
883  add_refcount(dest_ob->slaying);
884  if (dest_ob->skill != NULL)
885  add_refcount(dest_ob->skill);
886  if (dest_ob->lore != NULL)
887  add_refcount(dest_ob->lore);
888  if (dest_ob->msg != NULL)
889  add_refcount(dest_ob->msg);
890  if (dest_ob->custom_name != NULL)
891  add_refcount(dest_ob->custom_name);
892  if (dest_ob->materialname != NULL)
893  add_refcount(dest_ob->materialname);
894 
895  if (dest_ob->spell_tags != NULL) {
896  dest_ob->spell_tags = malloc(sizeof(tag_t)*SPELL_TAG_SIZE);
897  memcpy(dest_ob->spell_tags, src_ob->spell_tags, sizeof(tag_t)*SPELL_TAG_SIZE);
898  }
899 
900  /* If archetype is a temporary one, we need to update reference count, because
901  * that archetype will be freed by object_free_drop_inventory() when the last object is removed.
902  */
903  if (dest_ob->arch->reference_count > 0)
904  dest_ob->arch->reference_count++;
905 
906  if (src_ob->speed < 0)
907  dest_ob->speed_left = src_ob->speed_left-RANDOM()%200/100.0;
908 
909  /* Copy over key_values, if any. */
910  if (src_ob->key_values != NULL) {
911  key_value *tail = NULL;
912  key_value *i;
913 
914  dest_ob->key_values = NULL;
915 
916  for (i = src_ob->key_values; i != NULL; i = i->next) {
917  key_value *new_link = malloc(sizeof(key_value));
918 
919  new_link->next = NULL;
920  new_link->key = add_refcount(i->key);
921  if (i->value)
922  new_link->value = add_refcount(i->value);
923  else
924  new_link->value = NULL;
925 
926  /* Try and be clever here, too. */
927  if (dest_ob->key_values == NULL) {
928  dest_ob->key_values = new_link;
929  tail = new_link;
930  } else {
931  tail->next = new_link;
932  tail = new_link;
933  }
934  }
935  }
936 
937  /* This way, dialog information will be parsed again when/if needed. */
938  CLEAR_FLAG(dest_ob, FLAG_DIALOG_PARSED);
939 
940  object_update_speed(dest_ob);
941 }
942 
952 void object_copy_with_inv(const object *src_ob, object *dest_ob) {
953  object_copy(src_ob, dest_ob);
954  FOR_INV_PREPARE(src_ob, walk) {
955  object *tmp;
956 
957  tmp = object_new();
958  object_copy_with_inv(walk, tmp);
959  object_insert_in_ob(tmp, dest_ob);
960  } FOR_INV_FINISH();
961 }
962 
970 static void expand_objects(void) {
971  int i;
972  object *new;
973 
974  new = (object *)CALLOC(OBJ_EXPAND, sizeof(object));
975 
976  if (new == NULL)
978  free_objects = new;
979  new[0].prev = NULL;
980  new[0].next = &new[1],
981  SET_FLAG(&new[0], FLAG_REMOVED);
982  SET_FLAG(&new[0], FLAG_FREED);
983 
984  for (i = 1; i < OBJ_EXPAND-1; i++) {
985  new[i].next = &new[i+1],
986  new[i].prev = &new[i-1],
987  SET_FLAG(&new[i], FLAG_REMOVED);
988  SET_FLAG(&new[i], FLAG_FREED);
989  }
990  new[OBJ_EXPAND-1].prev = &new[OBJ_EXPAND-2],
991  new[OBJ_EXPAND-1].next = NULL,
992  SET_FLAG(&new[OBJ_EXPAND-1], FLAG_REMOVED);
993  SET_FLAG(&new[OBJ_EXPAND-1], FLAG_FREED);
994 
997 }
998 
1011 object *object_new(void) {
1012  object *op;
1013 #ifdef MEMORY_DEBUG
1014  /* FIXME: However this doesn't work since object_free() sometimes add
1015  * objects back to the free_objects linked list, and some functions mess
1016  * with the object after return of object_free(). This is bad and should be
1017  * fixed. But it would need fairly extensive changes and a lot of debugging.
1018  */
1019  op = calloc(1, sizeof(object));
1020  if (op == NULL)
1022 #else
1023  if (free_objects == NULL) {
1024  expand_objects();
1025  }
1026  op = free_objects;
1027  if (!QUERY_FLAG(op, FLAG_FREED)) {
1028  LOG(llevError, "Fatal: Getting busy object.\n");
1029 #ifdef MANY_CORES
1030  abort();
1031 #endif
1032  }
1033  free_objects = op->next;
1034  if (free_objects != NULL)
1035  free_objects->prev = NULL;
1036  nroffreeobjects--;
1037 #endif
1038  op->count = ++ob_count;
1039  op->name = NULL;
1040  op->name_pl = NULL;
1041  op->title = NULL;
1042  op->race = NULL;
1043  op->slaying = NULL;
1044  op->skill = NULL;
1045  op->lore = NULL;
1046  op->msg = NULL;
1047  op->materialname = NULL;
1048  op->next = objects;
1049  op->prev = NULL;
1050  op->active_next = NULL;
1051  op->active_prev = NULL;
1052  op->spell_tags = NULL;
1053  if (objects != NULL)
1054  objects->prev = op;
1055  objects = op;
1056  object_clear(op);
1057  SET_FLAG(op, FLAG_REMOVED);
1058  return op;
1059 }
1060 
1069 void object_update_turn_face(object *op) {
1070  if (op->animation == 0 || !QUERY_FLAG(op, FLAG_IS_TURNABLE))
1071  return;
1072  animate_object(op, op->direction);
1073 }
1074 
1086 void object_update_speed(object *op) {
1087  /* FIXME what the hell is this crappy hack?*/
1088  extern int arch_init;
1089 
1090  /* No reason putting the archetypes objects on the speed list,
1091  * since they never really need to be updated.
1092  */
1093 
1094  if (QUERY_FLAG(op, FLAG_FREED) && op->speed) {
1095  LOG(llevError, "Object %s is freed but has speed.\n", op->name);
1096 #ifdef MANY_CORES
1097  abort();
1098 #else
1099  op->speed = 0;
1100 #endif
1101  }
1102  if (arch_init) {
1103  return;
1104  }
1105  if (FABS(op->speed) > MIN_ACTIVE_SPEED) {
1106  /* If already on active list, don't do anything */
1107  /* TODO this check can probably be simplified a lot */
1108  if (op->active_next || op->active_prev || op == active_objects)
1109  return;
1110 
1111  /* process_events() expects us to insert the object at the beginning
1112  * of the list. */
1114  if (op->active_next != NULL)
1115  op->active_next->active_prev = op;
1116  active_objects = op;
1117  } else {
1118  /* If not on the active list, nothing needs to be done */
1119  if (!op->active_next && !op->active_prev && op != active_objects)
1120  return;
1121 
1122  if (op->active_prev == NULL) {
1123  active_objects = op->active_next;
1124  if (op->active_next != NULL)
1125  op->active_next->active_prev = NULL;
1126  } else {
1127  op->active_prev->active_next = op->active_next;
1128  if (op->active_next)
1129  op->active_next->active_prev = op->active_prev;
1130  }
1131  op->active_next = NULL;
1132  op->active_prev = NULL;
1133  }
1134 }
1135 
1149  /* If not on the active list, nothing needs to be done */
1150  if (!op->active_next && !op->active_prev && op != active_objects)
1151  return;
1152 
1153  if (op->active_prev == NULL) {
1154  active_objects = op->active_next;
1155  if (op->active_next != NULL)
1156  op->active_next->active_prev = NULL;
1157  } else {
1158  op->active_prev->active_next = op->active_next;
1159  if (op->active_next)
1160  op->active_next->active_prev = op->active_prev;
1161  }
1162  op->active_next = NULL;
1163  op->active_prev = NULL;
1164 }
1165 
1190 void object_update(object *op, int action) {
1191  int update_now = 0, flags;
1192  MoveType move_on, move_off, move_block, move_slow;
1193  object *pl;
1194 
1195  if (op == NULL) {
1196  /* this should never happen */
1197  LOG(llevDebug, "object_update() called for NULL object.\n");
1198  return;
1199  }
1200 
1201  if (op->env != NULL) {
1202  /* Animation is currently handled by client, so nothing
1203  * to do in this case.
1204  */
1205  return;
1206  }
1207 
1208  /* If the map is saving, don't do anything as everything is
1209  * going to get freed anyways.
1210  */
1211  if (!op->map || op->map->in_memory == MAP_SAVING)
1212  return;
1213 
1214  /* make sure the object is within map boundaries */
1215  if (op->x < 0 || op->x >= MAP_WIDTH(op->map)
1216  || op->y < 0 || op->y >= MAP_HEIGHT(op->map)) {
1217  LOG(llevError, "object_update() called for object out of map!\n");
1218 #ifdef MANY_CORES
1219  abort();
1220 #endif
1221  return;
1222  }
1223 
1224  flags = GET_MAP_FLAGS(op->map, op->x, op->y);
1225  SET_MAP_FLAGS(op->map, op->x, op->y, flags|P_NEED_UPDATE);
1226  move_slow = GET_MAP_MOVE_SLOW(op->map, op->x, op->y);
1227  move_on = GET_MAP_MOVE_ON(op->map, op->x, op->y);
1228  move_block = GET_MAP_MOVE_BLOCK(op->map, op->x, op->y);
1229  move_off = GET_MAP_MOVE_OFF(op->map, op->x, op->y);
1230 
1231  if (action == UP_OBJ_INSERT) {
1233  update_now = 1;
1234 
1235  if (QUERY_FLAG(op, FLAG_NO_MAGIC) && !(flags&P_NO_MAGIC))
1236  update_now = 1;
1237 
1238  if (QUERY_FLAG(op, FLAG_DAMNED) && !(flags&P_NO_CLERIC))
1239  update_now = 1;
1240 
1241  if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags&P_IS_ALIVE))
1242  update_now = 1;
1243 
1244  if ((move_on|op->move_on) != move_on)
1245  update_now = 1;
1246  if ((move_off|op->move_off) != move_off)
1247  update_now = 1;
1248  /* This isn't perfect, but I don't expect a lot of objects to
1249  * to have move_allow right now.
1250  */
1251  if (((move_block|op->move_block)&~op->move_allow) != move_block)
1252  update_now = 1;
1253  if ((move_slow|op->move_slow) != move_slow)
1254  update_now = 1;
1255 
1256  if (op->type == PLAYER)
1257  update_now = 1;
1258  /* if the object is being removed, we can't make intelligent
1259  * decisions, because object_remove() can't really pass the object
1260  * that is being removed.
1261  */
1262  } else if (action == UP_OBJ_REMOVE) {
1263  update_now = 1;
1264  } else if (action == UP_OBJ_FACE || action == UP_OBJ_CHANGE) {
1265  /* In addition to sending info to client, need to update space
1266  * information.
1267  */
1268  if (action == UP_OBJ_CHANGE)
1269  update_now = 1;
1270 
1271  /* There is a player on this space - we may need to send an
1272  * update to the client.
1273  * If this object is supposed to be animated by the client,
1274  * nothing to do here - let the client animate it.
1275  * We can't use FLAG_ANIMATE, as that is basically set for
1276  * all objects with multiple faces, regardless if they are animated.
1277  * (levers have it set for example).
1278  */
1279  if (flags&P_PLAYER
1282  pl = GET_MAP_PLAYER(op->map, op->x, op->y);
1283 
1284  /* If update_look is set, we're going to send this entire space
1285  * to the client, so no reason to send face information now.
1286  */
1287  if (!pl->contr->socket.update_look) {
1288  esrv_update_item(UPD_FACE, pl, op);
1289  }
1290  }
1291  } else {
1292  LOG(llevError, "object_update called with invalid action: %d\n", action);
1293  }
1294 
1295  if (update_now) {
1296  SET_MAP_FLAGS(op->map, op->x, op->y, flags|P_NO_ERROR|P_NEED_UPDATE);
1297  update_position(op->map, op->x, op->y);
1298  }
1299 
1300  if (op->more != NULL)
1301  object_update(op->more, action);
1302 }
1303 
1316 void object_free_drop_inventory(object *ob) {
1317  object_free(ob, 0);
1318 }
1319 
1336 void object_free(object *ob, int flags) {
1337  if (!QUERY_FLAG(ob, FLAG_REMOVED)) {
1338  StringBuffer *sb;
1339  char *diff;
1340 
1341  LOG(llevDebug, "Free object called with non removed object\n");
1342  sb = stringbuffer_new();
1343  object_dump(ob, sb);
1344  diff = stringbuffer_finish(sb);
1345  LOG(llevError, "%s", diff);
1346  free(diff);
1347 #ifdef MANY_CORES
1348  abort();
1349 #endif
1350  }
1351  if (QUERY_FLAG(ob, FLAG_FRIENDLY)) {
1352  LOG(llevMonster, "Warning: tried to free friendly object.\n");
1354  }
1355  if (QUERY_FLAG(ob, FLAG_FREED)) {
1356  StringBuffer *sb;
1357  char *diff;
1358 
1359  sb = stringbuffer_new();
1360  object_dump(ob, sb);
1361  diff = stringbuffer_finish(sb);
1362  LOG(llevError, "Trying to free freed object.\n%s\n", diff);
1363  free(diff);
1364  return;
1365  }
1366 
1367  if ((flags & FREE_OBJ_NO_DESTROY_CALLBACK) == 0) {
1368  /* Handle for plugin destroy event */
1369  execute_event(ob, EVENT_DESTROY, NULL, NULL, NULL, SCRIPT_FIX_NOTHING);
1370  }
1371 
1372  if (ob->inv) {
1373  /* Only if the space blocks everything do we not process -
1374  * if some form of movemnt is allowed, let objects
1375  * drop on that space.
1376  */
1377  if ((flags & FREE_OBJ_FREE_INVENTORY) != 0
1378  || ob->map == NULL
1379  || ob->map->in_memory != MAP_IN_MEMORY
1380  || (GET_MAP_MOVE_BLOCK(ob->map, ob->x, ob->y) == MOVE_ALL)) {
1381  FOR_INV_PREPARE(ob, op) {
1382  object_remove(op);
1383  object_free(op, flags);
1384  } FOR_INV_FINISH();
1385  } else { /* Put objects in inventory onto this space */
1386  FOR_INV_PREPARE(ob, op) {
1387  object_remove(op);
1388  /* No drop means no drop, including its inventory */
1389  if (QUERY_FLAG(op, FLAG_NO_DROP))
1390  object_free(op, FREE_OBJ_FREE_INVENTORY);
1391  else if (QUERY_FLAG(op, FLAG_STARTEQUIP)
1392  || QUERY_FLAG(op, FLAG_NO_DROP)
1393  || op->type == RUNE
1394  || op->type == TRAP
1397  else {
1398  object *part;
1399 
1400  /* If it's a multi-tile object, scatter dropped items randomly */
1401  if (ob->more) {
1402  int partcount = 0;
1403  /* Get the number of non-head parts */
1404  for (part = ob; part; part = part->more) {
1405  partcount++;
1406  }
1407  /* Select a random part */
1408  partcount = RANDOM()%partcount;
1409  for (part = ob; partcount > 0; partcount--) {
1410  part = part->more;
1411  }
1412  } else {
1413  part = ob;
1414  }
1415 
1416  if (QUERY_FLAG(op, FLAG_ALIVE)) {
1417  object_insert_to_free_spot_or_free(op, part->map, part->x, part->y, 0, SIZEOFFREE, NULL);
1418  } else {
1419  int f = 0;
1420  if (flags & FREE_OBJ_DROP_ABOVE_FLOOR)
1422  object_insert_in_map_at(op, part->map, NULL, f, part->x, part->y); /* Insert in same map as the envir */
1423  }
1424  }
1425  } FOR_INV_FINISH();
1426  }
1427  }
1428 
1429  if (ob->more != NULL) {
1430  object_free(ob->more, flags);
1431  ob->more = NULL;
1432  }
1433 
1434  /* Remove object from the active list */
1435  ob->speed = 0;
1436  object_update_speed(ob);
1437 
1438  SET_FLAG(ob, FLAG_FREED);
1439  ob->count = 0;
1440 
1441  /* Remove this object from the list of used objects */
1442  if (ob->prev == NULL) {
1443  objects = ob->next;
1444  if (objects != NULL)
1445  objects->prev = NULL;
1446  } else {
1447  ob->prev->next = ob->next;
1448  if (ob->next != NULL)
1449  ob->next->prev = ob->prev;
1450  }
1451 
1452  if (ob->artifact != NULL) FREE_AND_CLEAR_STR(ob->artifact);
1453  if (ob->name != NULL) FREE_AND_CLEAR_STR(ob->name);
1454  if (ob->name_pl != NULL) FREE_AND_CLEAR_STR(ob->name_pl);
1455  if (ob->title != NULL) FREE_AND_CLEAR_STR(ob->title);
1456  if (ob->race != NULL) FREE_AND_CLEAR_STR(ob->race);
1457  if (ob->slaying != NULL) FREE_AND_CLEAR_STR(ob->slaying);
1458  if (ob->skill != NULL) FREE_AND_CLEAR_STR(ob->skill);
1459  if (ob->lore != NULL) FREE_AND_CLEAR_STR(ob->lore);
1460  if (ob->msg != NULL) FREE_AND_CLEAR_STR(ob->msg);
1461  if (ob->materialname != NULL) FREE_AND_CLEAR_STR(ob->materialname);
1462  if (ob->spell_tags) FREE_AND_CLEAR(ob->spell_tags);
1463 
1464  /* Why aren't events freed? */
1466 
1468 
1469  /* Test whether archetype is a temporary one, and if so look whether it should be trashed. */
1470  if (ob->arch && ob->arch->reference_count > 0) {
1471  if (--ob->arch->reference_count == 0) {
1472  free_arch(ob->arch);
1473  }
1474  }
1475 
1476 #ifdef MEMORY_DEBUG
1477  free(ob);
1478 #else
1479  /* Now link it with the free_objects list: */
1480  ob->prev = NULL;
1481  ob->next = free_objects;
1482  if (free_objects != NULL)
1483  free_objects->prev = ob;
1484  free_objects = ob;
1485  nroffreeobjects++;
1486 #endif
1487 }
1488 
1496  int i = 0;
1497  object *tmp = free_objects;
1498 
1499  while (tmp != NULL)
1500  tmp = tmp->next,
1501  i++;
1502  return i;
1503 }
1504 
1512  int i = 0;
1513  object *tmp = objects;
1514 
1515  while (tmp != NULL)
1516  tmp = tmp->next,
1517  i++;
1518  return i;
1519 }
1520 
1528  int i = 0;
1529  object *tmp = active_objects;
1530 
1531  while (tmp != NULL)
1532  tmp = tmp->active_next,
1533  i++;
1534  return i;
1535 }
1536 
1551 void object_sub_weight(object *op, signed long weight) {
1552  while (op != NULL) {
1553  if (op->type == CONTAINER) {
1554  weight = (signed long)(weight*(100-op->stats.Str)/100);
1555  }
1556  op->carrying -= weight;
1557  op = op->env;
1558  }
1559 }
1560 
1577 void object_remove(object *op) {
1578  object *last = NULL;
1579  object *otmp;
1580  tag_t tag;
1581  int check_walk_off;
1582  mapstruct *m;
1583  int16_t x, y;
1584 
1585  if (QUERY_FLAG(op, FLAG_REMOVED)) {
1586  StringBuffer *sb;
1587  char *diff;
1588 
1589  sb = stringbuffer_new();
1590  object_dump(op, sb);
1591  diff = stringbuffer_finish(sb);
1592  LOG(llevError, "Trying to remove removed object.\n%s\n", diff);
1593  free(diff);
1594  abort();
1595  }
1596  if (op->more != NULL)
1597  object_remove(op->more);
1598 
1599  SET_FLAG(op, FLAG_REMOVED);
1600 
1601  /*
1602  * In this case, the object to be removed is in someones
1603  * inventory.
1604  */
1605  /* TODO try to call a generic inventory weight adjusting function like object_sub_weight */
1606  if (op->env != NULL) {
1607  player *pl = NULL;
1608 
1609  if (op->nrof)
1610  object_sub_weight(op->env, op->weight*op->nrof);
1611  else
1612  object_sub_weight(op->env, op->weight+op->carrying);
1613 
1614  /* Update in two cases: item is in a player, or in a container the player is looking into. */
1615  if (op->env->contr != NULL && op->head == NULL) {
1616  pl = op->env->contr;
1617  } else if (op->env->type == CONTAINER && QUERY_FLAG(op->env, FLAG_APPLIED)) {
1618 
1619  if (op->env->env && op->env->env->contr)
1620  /* Container is in player's inventory. */
1621  pl = op->env->env->contr;
1622  else if (op->env->map) {
1623  /* Container on map, look above for player. */
1624  object *above = op->env->above;
1625 
1626  while (above && !above->contr)
1627  above = above->above;
1628  if (above)
1629  pl = above->contr;
1630  }
1631  }
1632 
1633  /* NO_FIX_PLAYER is set when a great many changes are being
1634  * made to players inventory. If set, avoiding the call
1635  * to save cpu time.
1636  */
1637  otmp = object_get_player_container(op->env);
1638  if (otmp != NULL
1639  && otmp->contr
1640  && !QUERY_FLAG(otmp, FLAG_NO_FIX_PLAYER))
1641  fix_object(otmp);
1642 
1643  if (op->above != NULL)
1644  op->above->below = op->below;
1645  else
1646  op->env->inv = op->below;
1647 
1648  if (op->below != NULL)
1649  op->below->above = op->above;
1650 
1651  /* we set up values so that it could be inserted into
1652  * the map, but we don't actually do that - it is up
1653  * to the caller to decide what we want to do.
1654  */
1655  op->x = op->env->x;
1656  op->y = op->env->y;
1657  op->ox = op->x;
1658  op->oy = op->y;
1659  op->map = op->env->map;
1660  op->above = NULL;
1661  op->below = NULL;
1662  /* send the delitem before resetting env, so container's contents be may
1663  * refreshed */
1664  if (LOOK_OBJ(op) && pl != NULL)
1665  esrv_del_item(pl, op);
1666  op->env = NULL;
1667  return;
1668  }
1669 
1670  /* If we get here, we are removing it from a map */
1671  if (op->map == NULL)
1672  return;
1673 
1674  if (op->contr != NULL && !op->contr->hidden)
1675  op->map->players--;
1676 
1677  x = op->x;
1678  y = op->y;
1679  m = get_map_from_coord(op->map, &x, &y);
1680 
1681  if (!m) {
1682  LOG(llevError, "object_remove called when object was on map but appears to not be within valid coordinates? %s (%d,%d)\n", op->map->path, op->x, op->y);
1683  abort();
1684  }
1685  if (op->map != m) {
1686  LOG(llevError, "object_remove: Object not really on map it claimed to be on? %s != %s, %d,%d != %d,%d\n", op->map->path, m->path, op->x, op->y, x, y);
1687  }
1688 
1689  /* link the object above us */
1690  if (op->above)
1691  op->above->below = op->below;
1692  else
1693  SET_MAP_TOP(m, x, y, op->below); /* we were top, set new top */
1694 
1695  /* Relink the object below us, if there is one */
1696  if (op->below) {
1697  op->below->above = op->above;
1698  } else {
1699  /* Nothing below, which means we need to relink map object for this space
1700  * use translated coordinates in case some oddness with map tiling is
1701  * evident
1702  */
1703  /*TODO is this check really needed?*/
1704  if (GET_MAP_OB(m, x, y) != op) {
1705  StringBuffer *sb;
1706  char *diff;
1707 
1708  sb = stringbuffer_new();
1709  object_dump(op, sb);
1710  diff = stringbuffer_finish(sb);
1711  LOG(llevError, "object_remove: GET_MAP_OB on %s does not return object to be removed even though it appears to be on the bottom?\n%s\n", m->path, diff);
1712  free(diff);
1713 
1714  sb = stringbuffer_new();
1715  object_dump(GET_MAP_OB(m, x, y), sb);
1716  diff = stringbuffer_finish(sb);
1717  LOG(llevError, "%s\n", diff);
1718  free(diff);
1719  }
1720  SET_MAP_OB(m, x, y, op->above); /* goes on above it. */
1721  }
1722  op->above = NULL;
1723  op->below = NULL;
1724 
1725  if (op->map->in_memory == MAP_SAVING)
1726  return;
1727 
1728  tag = op->count;
1729  check_walk_off = !QUERY_FLAG(op, FLAG_NO_APPLY);
1730  FOR_MAP_PREPARE(m, x, y, tmp) {
1731  /* No point updating the players look faces if he is the object
1732  * being removed.
1733  */
1734 
1735  if (tmp->type == PLAYER && tmp != op) {
1736  /* If a container that the player is currently using somehow gets
1737  * removed (most likely destroyed), update the player view
1738  * appropriately.
1739  */
1740  if (tmp->container == op) {
1741  CLEAR_FLAG(op, FLAG_APPLIED);
1742  tmp->container = NULL;
1743  }
1744  tmp->contr->socket.update_look = 1;
1745  }
1746  /* See if player moving off should effect something */
1747  if (check_walk_off
1748  && ((op->move_type&tmp->move_off) && (op->move_type&~tmp->move_off&~tmp->move_block) == 0)) {
1749  ob_move_on(tmp, op, NULL);
1750  if (object_was_destroyed(op, tag)) {
1751  LOG(llevError, "BUG: object_remove(): name %s, archname %s destroyed leaving object\n", tmp->name, tmp->arch->name);
1752  }
1753  }
1754 
1755  /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */
1756  if (tmp->above == tmp)
1757  tmp->above = NULL;
1758  last = tmp;
1759  } FOR_MAP_FINISH();
1760  /* last == NULL or there are no objects on this space */
1761  if (last == NULL) {
1762  /* set P_NEED_UPDATE, otherwise update_position will complain. In theory,
1763  * we could preserve the flags (GET_MAP_FLAGS), but update_position figures
1764  * those out anyways, and if there are any flags set right now, they won't
1765  * be correct anyways.
1766  */
1767  SET_MAP_FLAGS(op->map, op->x, op->y, P_NEED_UPDATE);
1768  update_position(op->map, op->x, op->y);
1769  } else
1771 
1772  if (QUERY_FLAG(op, FLAG_BLOCKSVIEW) || (op->glow_radius != 0))
1773  update_all_los(op->map, op->x, op->y);
1774 }
1775 
1789 object *object_merge(object *op, object *top) {
1790  if (!op->nrof)
1791  return NULL;
1792 
1793  if (top == NULL)
1794  for (top = op; top != NULL && top->above != NULL; top = top->above)
1795  ;
1797  if (top == op)
1798  continue;
1799  if (object_can_merge(op, top)) {
1800  object_increase_nrof(top, op->nrof);
1801  /*
1802  * Previous behavior set weight to zero here.
1803  * This, however, caused the object_sub_weight
1804  * call in object_remove to subtract zero weight
1805  * when removing the object. Thus, until inventory
1806  * weight is next recalculated, the object merged
1807  * into another pile added weight in object_increase_nrof
1808  * but did not remove the weight from the original
1809  * instance of itself in object_remove, essentially
1810  * counting for double weight for several minutes.
1811  *
1812  * SilverNexus 2014-05-27
1813  */
1814  object_remove(op);
1816  return top;
1817  }
1819  return NULL;
1820 }
1821 
1838 object *object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y) {
1839  object *tmp;
1840 
1841  op = HEAD(op);
1842  for (tmp = op; tmp; tmp = tmp->more) {
1843  tmp->x = x+tmp->arch->clone.x;
1844  tmp->y = y+tmp->arch->clone.y;
1845  tmp->map = m;
1846  }
1847  return object_insert_in_map(op, m, originator, flag);
1848 }
1849 
1867 void object_merge_spell(object *op, int16_t x, int16_t y) {
1868  int i;
1869 
1870  /* We try to do some merging of spell objects - if something has same owner,
1871  * is same type of spell, and going in the same direction, it is somewhat
1872  * mergable.
1873  *
1874  * If the spell object has an other_arch, don't merge - when the spell
1875  * does something, like explodes, it will use this other_arch, and
1876  * if we merge, there is no easy way to make the correct values be
1877  * set on this new object (values should be doubled, tripled, etc.)
1878  *
1879  * We also care about speed - only process objects that will not be
1880  * active this tick. Without this, the results are incorrect - think
1881  * of a case where tmp would normally get processed this tick, but
1882  * get merges with op, which does not get processed.
1883  */
1884  FOR_MAP_PREPARE(op->map, x, y, tmp) {
1885  if (op->type == tmp->type
1886  && op->subtype == tmp->subtype
1887  && op->direction == tmp->direction
1888  && op->owner == tmp->owner && op->ownercount == tmp->ownercount
1889  && op->range == tmp->range
1890  && op->stats.wc == tmp->stats.wc
1891  && op->level == tmp->level
1892  && op->attacktype == tmp->attacktype
1893  && op->speed == tmp->speed
1894  && !tmp->other_arch
1895  && (tmp->speed_left+tmp->speed) < 0.0
1896  && op != tmp) {
1897  /* Quick test - if one or the other objects already have hash tables
1898  * set up, and that hash bucket contains a value that doesn't
1899  * match what we want to set it up, we won't be able to merge.
1900  * Note that these two if statements are the same, except
1901  * for which object they are checking against. They could
1902  * be merged, but the line wrapping would be large enough
1903  * that IMO it would become difficult to read the different clauses
1904  * so its cleaner just to do 2 statements - MSW
1905  */
1906  if (op->spell_tags
1907  && !OB_SPELL_TAG_MATCH(op, (tag_t)tmp->stats.maxhp)
1908  && OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) != 0)
1909  continue;
1910 
1911  if (tmp->spell_tags
1912  && !OB_SPELL_TAG_MATCH(tmp, (tag_t)op->stats.maxhp)
1913  && OB_SPELL_TAG_HASH(tmp, op->stats.maxhp) != 0)
1914  continue;
1915 
1916  /* If we merge, the data from tmp->spell_tags gets copied into op.
1917  * so we need to make sure that slot isn't filled up.
1918  */
1919  if (tmp->spell_tags
1920  && !OB_SPELL_TAG_MATCH(tmp, (tag_t)tmp->stats.maxhp)
1921  && OB_SPELL_TAG_HASH(tmp, tmp->stats.maxhp) != 0)
1922  continue;
1923 
1924  /* If both objects have spell_tags, we need to see if there are conflicting
1925  * values - if there are, we won't be able to merge then.
1926  */
1927  if (tmp->spell_tags && op->spell_tags) {
1928  int need_copy = 0;
1929 
1930  for (i = 0; i < SPELL_TAG_SIZE; i++) {
1931  /* If the two tag values in the hash are set, but are
1932  * not set to the same value, then these objects
1933  * can not be merged.
1934  */
1935  if (op->spell_tags[i] && tmp->spell_tags[i]
1936  && op->spell_tags[i] != tmp->spell_tags[i]) {
1938  break;
1939  }
1940  /* If one tag is set and the other is not, that is
1941  * fine, but we have to note that we need to copy
1942  * the data in that case.
1943  */
1944  if ((!op->spell_tags[i] && tmp->spell_tags[i])
1945  || (op->spell_tags[i] && !tmp->spell_tags[i])) {
1946  need_copy = 1;
1947  }
1948  }
1949  /* If we did not get through entire array, it means
1950  * we got a conflicting hash, and so we won't be
1951  * able to merge these - just continue processing
1952  * object on this space.
1953  */
1954  if (i <= SPELL_TAG_SIZE)
1955  continue;
1956 
1957  /* Ok - everything checked out - we should be able to
1958  * merge tmp in op. So lets copy the tag data if
1959  * needed. Note that this is a selective copy, as
1960  * we don't want to clear values that may be set in op.
1961  */
1962  if (need_copy) {
1963  for (i = 0; i < SPELL_TAG_SIZE; i++)
1964  if (!op->spell_tags[i]
1965  && tmp->spell_tags[i]
1966  && tmp->spell_tags[i] != (tag_t)op->stats.maxhp)
1967  op->spell_tags[i] = tmp->spell_tags[i];
1968  }
1969  FREE_AND_CLEAR(tmp->spell_tags);
1970  }
1971 
1972  /* if tmp has a spell_tags table, copy it to op and free tmps */
1973  if (tmp->spell_tags && !op->spell_tags) {
1974  op->spell_tags = tmp->spell_tags;
1975  tmp->spell_tags = NULL;
1976 
1977  /* We don't need to keep a copy of our maxhp value
1978  * in the copied over value
1979  */
1980  if (OB_SPELL_TAG_MATCH(op, (tag_t)op->stats.maxhp))
1981  OB_SPELL_TAG_HASH(op, op->stats.maxhp) = 0;
1982  }
1983 
1984  /* For spells to work correctly, we need to record what spell
1985  * tags we've merged in with this effect. This is used
1986  * in ok_to_put_more() to see if a spell effect is already on
1987  * the space.
1988  */
1989  if (op->stats.maxhp != tmp->stats.maxhp) {
1990 #ifdef OBJECT_DEBUG
1991  /* This if statement should never happen - the logic above should
1992  * have prevented it. It is a problem, because by now its possible
1993  * we've destroyed the spell_tags in tmp, so we can't really
1994  * just bail out.
1995  */
1996 
1997  if (op->spell_tags
1998  && OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) != 0
1999  && !OB_SPELL_TAG_MATCH(op, tmp->stats.maxhp)) {
2000  LOG(llevError, "object_insert_in_map: Got non matching spell tags: %d != %d\n", OB_SPELL_TAG_HASH(op, tmp->stats.maxhp), tmp->stats.maxhp);
2001  }
2002 #endif
2003  if (!op->spell_tags)
2004  op->spell_tags = calloc(SPELL_TAG_SIZE, sizeof(tag_t));
2005 
2006  OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) = tmp->stats.maxhp;
2007  }
2008 
2010  op->speed_left = MAX(op->speed_left, tmp->speed_left);
2011 
2012  if (tmp->duration != op->duration) {
2013  /* We need to use tmp_dam here because otherwise the
2014  * calculations can overflow the size of stats.dam.
2015  */
2016  int tmp_dam = tmp->stats.dam*(tmp->duration+1)+
2017  op->stats.dam*(op->duration+1);
2018 
2019  op->duration = MAX(op->duration, tmp->duration);
2020  tmp_dam /= op->duration+1;
2021  op->stats.dam = tmp_dam+1;
2022  } else {
2023  /* in this case, duration is the same, so simply adding
2024  * up damage works.
2025  */
2026  op->stats.dam += tmp->stats.dam;
2027  }
2028 
2029  object_remove(tmp);
2031  }
2032  } FOR_MAP_FINISH();
2033 }
2034 
2035 static object *find_insert_pos(object *op, const int flag) {
2036  object *floor = NULL;
2037  /*
2038  * If there are multiple objects on this space, we do some trickier handling.
2039  * We've already dealt with merging if appropriate.
2040  * Generally, we want to put the new object on top. But if
2041  * flag contains INS_ABOVE_FLOOR_ONLY, once we find the last
2042  * floor, we want to insert above that and no further.
2043  * Also, if there are spell objects on this space, we stop processing
2044  * once we get to them. This reduces the need to traverse over all of
2045  * them when adding another one - this saves quite a bit of cpu time
2046  * when lots of spells are cast in one area. Currently, it is presumed
2047  * that flying non pickable objects are spell objects.
2048  */
2049  if (flag&INS_ON_TOP) {
2050  return GET_MAP_TOP(op->map, op->x, op->y);
2051  }
2052  object *last = NULL;
2053  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp) {
2054  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR)
2055  || QUERY_FLAG(tmp, FLAG_OVERLAY_FLOOR))
2056  floor = tmp;
2057 
2058  if (QUERY_FLAG(tmp, FLAG_NO_PICK)
2059  && (tmp->move_type&(MOVE_FLY_LOW|MOVE_FLY_HIGH))
2060  && !QUERY_FLAG(tmp, FLAG_IS_FLOOR)) {
2061  /* We insert above tmp, so we want this object below this */
2062  break;
2063  }
2064  last = tmp;
2065  } FOR_MAP_FINISH();
2066  if (flag&INS_ABOVE_FLOOR_ONLY)
2067  return floor;
2068  return last;
2069 }
2070 
2099 object *object_insert_in_map(object *op, mapstruct *m, object *originator, int flag) {
2100  object *tmp, *top, *floor = NULL;
2101  int16_t x, y;
2102 
2103  if (QUERY_FLAG(op, FLAG_FREED)) {
2104  LOG(llevError, "Trying to insert freed object!\n");
2105  return NULL;
2106  }
2107  if (m == NULL) {
2108  StringBuffer *sb;
2109  char *diff;
2110 
2111  sb = stringbuffer_new();
2112  object_dump(op, sb);
2113  diff = stringbuffer_finish(sb);
2114  LOG(llevError, "Trying to insert in null-map!\n%s\n", diff);
2115  free(diff);
2116  return op;
2117  }
2118  if (out_of_map(m, op->x, op->y)) {
2119  StringBuffer *sb;
2120  char *diff;
2121 
2122  sb = stringbuffer_new();
2123  object_dump(op, sb);
2124  diff = stringbuffer_finish(sb);
2125  LOG(llevError, "Trying to insert object outside the map.\n%s\n", diff);
2126  free(diff);
2127 #ifdef MANY_CORES
2128  /* Better to catch this here, as otherwise the next use of this object
2129  * is likely to cause a crash. Better to find out where it is getting
2130  * improperly inserted.
2131  */
2132  abort();
2133 #endif
2134  return op;
2135  }
2136  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
2137  StringBuffer *sb;
2138  char *diff;
2139 
2140  sb = stringbuffer_new();
2141  object_dump(op, sb);
2142  diff = stringbuffer_finish(sb);
2143  LOG(llevError, "Trying to insert (map) inserted object.\n%s\n", diff);
2144  free(diff);
2145  return op;
2146  }
2147  if (op->more != NULL) {
2148  /* The part may be on a different map. */
2149 
2150  object *more = op->more;
2151 
2152  /* We really need the caller to normalize coordinates - if
2153  * we set the map, that doesn't work if the location is within
2154  * a map and this is straddling an edge. So only if coordinate
2155  * is clear wrong do we normalize it.
2156  */
2157  if (OUT_OF_REAL_MAP(more->map, more->x, more->y)) {
2158  /* Debugging information so you can see the last coordinates this object had */
2159  more->ox = more->x;
2160  more->oy = more->y;
2161  more->map = get_map_from_coord(more->map, &more->x, &more->y);
2162  } else if (!more->map) {
2163  /* For backwards compatibility - when not dealing with tiled maps,
2164  * more->map should always point to the parent.
2165  */
2166  more->map = m;
2167  }
2168 
2169  if (object_insert_in_map(more, more->map, originator, flag) == NULL) {
2170  if (!op->head)
2171  LOG(llevError, "BUG: object_insert_in_map(): inserting op->more killed op\n");
2172  return NULL;
2173  }
2174  }
2175  CLEAR_FLAG(op, FLAG_REMOVED);
2176 
2177  /* Debugging information so you can see the last coordinates this object had */
2178  op->ox = op->x;
2179  op->oy = op->y;
2180  x = op->x;
2181  y = op->y;
2182  op->map = get_map_from_coord(m, &x, &y);
2183 
2184  /* this has to be done after we translate the coordinates. */
2185  if (op->nrof
2186  && !(flag&INS_NO_MERGE)
2187  && op->type != SPELL_EFFECT) {
2188  FOR_MAP_PREPARE(op->map, x, y, tmp) {
2189  if (object_can_merge(op, tmp)) {
2190  op->nrof += tmp->nrof;
2191  object_remove(tmp);
2193  }
2194  } FOR_MAP_FINISH();
2195  } else if (op->type == SPELL_EFFECT
2196  && !op->range
2197  && !op->other_arch
2198  && (op->speed_left+op->speed) < 0.0) {
2199  object_merge_spell(op, x, y);
2200  }
2201 
2202  /* Ideally, the caller figures this out. However, it complicates a lot
2203  * of areas of callers (eg, anything that uses object_find_free_spot() would now
2204  * need extra work
2205  */
2206  if (op->map != m) {
2207  /* coordinates should not change unless map also changes */
2208  op->x = x;
2209  op->y = y;
2210  }
2211 
2212  if (op->type != LAMP)
2213  /* lamps use the FLAG_APPLIED to keep the light/unlit status, so don't reset it.
2214  Other objects just get unapplied, since the container "drops" them. */
2215  CLEAR_FLAG(op, FLAG_APPLIED);
2217  if (!QUERY_FLAG(op, FLAG_ALIVE))
2219 
2220  /* In many places, a player is passed as the originator, which
2221  * is fine. However, if the player is on a transport, they are not
2222  * actually on the map, so we can't use them for the linked pointers,
2223  * nor should the walk on function below use them either.
2224  */
2225  if (originator && originator->contr && originator->contr->transport)
2226  originator = originator->contr->transport;
2227 
2228  if (flag&INS_BELOW_ORIGINATOR) {
2229  if (originator->map != op->map
2230  || originator->x != op->x
2231  || originator->y != op->y) {
2232  LOG(llevError, "object_insert_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n");
2233  abort();
2234  }
2235  op->above = originator;
2236  op->below = originator->below;
2237  if (op->below)
2238  op->below->above = op;
2239  else
2240  SET_MAP_OB(op->map, op->x, op->y, op);
2241  /* since *below *originator, no need to update top */
2242  originator->below = op;
2243  } else {
2244  /* Top is the object that our object (op) is going to get inserted above. */
2245  top = find_insert_pos(op, flag);
2246 
2247  /* First object on this space */
2248  if (!top) {
2249  op->above = GET_MAP_OB(op->map, op->x, op->y);
2250  if (op->above)
2251  op->above->below = op;
2252  op->below = NULL;
2253  SET_MAP_OB(op->map, op->x, op->y, op);
2254  } else { /* get inserted into the stack above top */
2255  op->above = top->above;
2256  if (op->above)
2257  op->above->below = op;
2258  op->below = top;
2259  top->above = op;
2260  }
2261  if (op->above == NULL)
2262  SET_MAP_TOP(op->map, op->x, op->y, op);
2263  } /* else not INS_BELOW_ORIGINATOR */
2264 
2265  if (!(flag&INS_MAP_LOAD)) {
2266  if (op->type == PLAYER)
2267  op->contr->do_los = 1;
2268 
2269  /* If we have a floor, we know the player, if any, will be above
2270  * it, so save a few ticks and start from there.
2271  */
2272  tmp = floor ? floor : GET_MAP_OB(op->map, op->x, op->y);
2274  if (tmp->type == PLAYER)
2275  tmp->contr->socket.update_look = 1;
2277 
2278  /* If this object glows, it may affect lighting conditions that are
2279  * visible to others on this map. But update_all_los is really
2280  * an inefficient way to do this, as it means los for all players
2281  * on the map will get recalculated. The players could very well
2282  * be far away from this change and not affected in any way -
2283  * this should get redone to only look for players within range,
2284  * or just updating the P_NEED_UPDATE for spaces within this area
2285  * of effect may be sufficient.
2286  */
2287  if (MAP_DARKNESS(op->map) && (op->glow_radius != 0))
2288  update_all_los(op->map, op->x, op->y);
2289 
2290  if (op->contr && !op->contr->hidden)
2291  op->map->players++;
2292  }
2293 
2294  /* updates flags (blocked, alive, no magic, etc) for this map space */
2296 
2297  /* Don't know if moving this to the end will break anything. However,
2298  * we want to have update_look set above before calling this.
2299  *
2300  * object_check_move_on() must be after this because code called from
2301  * object_check_move_on() depends on correct map flags (so functions like
2302  * blocked() and wall() work properly), and these flags are updated by
2303  * object_update().
2304  */
2305 
2306  /* if this is not the head or flag has been passed, don't check walk on status */
2307 
2308  if (!(flag&INS_NO_WALK_ON) && !op->head) {
2309  if (object_check_move_on(op, originator))
2310  return NULL;
2311 
2312  /* If we are a multi part object, lets work our way through the check
2313  * walk on's.
2314  */
2315  for (tmp = op->more; tmp != NULL; tmp = tmp->more)
2316  if (object_check_move_on(tmp, originator))
2317  return NULL;
2318  }
2319  return op;
2320 }
2321 
2331 void object_replace_insert_in_map(const char *arch_string, object *op) {
2332  object *tmp1;
2333  archetype *at;
2334 
2335  /* first search for itself and remove any old instances */
2336  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp) {
2337  if (!strcmp(tmp->arch->name, arch_string)) { /* same archetype */
2338  object_remove(tmp);
2340  }
2341  } FOR_MAP_FINISH();
2342 
2343  at = find_archetype(arch_string);
2344  if (at == NULL) {
2345  return;
2346  }
2347  tmp1 = arch_to_object(at);
2348  object_insert_in_map_at(tmp1, op->map, op, INS_BELOW_ORIGINATOR, op->x, op->y);
2349 }
2350 
2371 object *object_split(object *orig_ob, uint32_t nr, char *err, size_t size) {
2372  object *newob;
2373 
2374  if (MAX(1, orig_ob->nrof) < nr) {
2375  /* If err is set, the caller knows that nr can be wrong (player trying to drop items), thus don't log that. */
2376  if (err)
2377  snprintf(err, size, "There are only %u %ss.", NROF(orig_ob), orig_ob->name);
2378  else
2379  LOG(llevDebug, "There are only %u %ss.\n", NROF(orig_ob), orig_ob->name);
2380  return NULL;
2381  }
2382  newob = object_create_clone(orig_ob);
2383  if (orig_ob->nrof == 0) {
2384  if (!QUERY_FLAG(orig_ob, FLAG_REMOVED)) {
2385  object_remove(orig_ob);
2386  }
2388  } else {
2389  newob->nrof = nr;
2390  object_decrease_nrof(orig_ob, nr);
2391  }
2392 
2393  return newob;
2394 }
2395 
2410 object *object_decrease_nrof(object *op, uint32_t i) {
2411  object *tmp;
2412 
2413  if (i == 0) /* objects with op->nrof require this check */
2414  return op;
2415 
2416  if (i > op->nrof)
2417  i = op->nrof;
2418 
2419  if (QUERY_FLAG(op, FLAG_REMOVED)) {
2420  op->nrof -= i;
2421  } else if (op->env != NULL) {
2422  if (i < op->nrof) {
2423  player *pl;
2424  /* is this object in the players inventory, or sub container
2425  * therein?
2426  */
2427  tmp = object_get_player_container(op->env);
2428  /* nope. Is this a container the player has opened?
2429  * If so, set tmp to that player.
2430  * IMO, searching through all the players will mostly
2431  * likely be quicker than following op->env to the map,
2432  * and then searching the map for a player.
2433  */
2434  if (!tmp) {
2435  for (pl = first_player; pl; pl = pl->next)
2436  if (pl->ob->container == op->env)
2437  break;
2438  if (pl)
2439  tmp = pl->ob;
2440  else
2441  tmp = NULL;
2442  }
2443 
2444  /* Because of weight reduction by container and integer arithmetic,
2445  * there is no guarantee the rounded weight of combined items will be
2446  * the same as the sum of rounded weights.
2447  * Therefore just remove the current weight, and add the new.
2448  * Same adjustment done in object_increase_nrof().
2449  */
2450  object_sub_weight(op->env, op->weight * op->nrof);
2451  op->nrof -= i;
2452  object_add_weight(op->env, op->weight * op->nrof);
2453  if (tmp) {
2454  esrv_update_item(UPD_NROF, tmp, op);
2455  esrv_update_item(UPD_WEIGHT, tmp, op->env);
2456  fix_object(tmp);
2457  }
2458  } else {
2459  object_remove(op);
2460  op->nrof = 0;
2461  }
2462  } else {
2463  /* On a map. */
2464  if (i < op->nrof) {
2465  op->nrof -= i;
2466 
2467  FOR_MAP_PREPARE(op->map, op->x, op->y, pl)
2468  if (pl->contr) {
2469  pl->contr->socket.update_look = 1;
2470  break;
2471  }
2472  FOR_MAP_FINISH();
2473  } else {
2474  object_remove(op);
2475  op->nrof = 0;
2476  }
2477  }
2478 
2479  if (op->nrof) {
2480  return op;
2481  } else {
2483  return NULL;
2484  }
2485 }
2486 
2497 static void object_increase_nrof(object *op, uint32_t i) {
2498  object *tmp;
2499 
2500  if (i == 0) /* objects with op->nrof require this check */
2501  return;
2502 
2503  if (QUERY_FLAG(op, FLAG_REMOVED)) {
2504  op->nrof += i;
2505  } else if (op->env != NULL) {
2506  player *pl;
2507  /* is this object in the players inventory, or sub container
2508  * therein?
2509  */
2510  tmp = object_get_player_container(op->env);
2511  /* nope. Is this a container the player has opened?
2512  * If so, set tmp to that player.
2513  * IMO, searching through all the players will mostly
2514  * likely be quicker than following op->env to the map,
2515  * and then searching the map for a player.
2516  */
2517  if (!tmp) {
2518  for (pl = first_player; pl; pl = pl->next)
2519  if (pl->ob->container == op->env)
2520  break;
2521  if (pl)
2522  tmp = pl->ob;
2523  else
2524  tmp = NULL;
2525  }
2526 
2527  /* Because of weight reduction by container and integer arithmetic,
2528  * there is no guarantee the rounded weight of combined items will be
2529  * the same as the sum of rounded weights.
2530  * Therefore just remove the current weight, and add the new.
2531  * Same adjustment done in object_decrease_nrof().
2532  */
2533  object_sub_weight(op->env, op->weight * op->nrof);
2534  op->nrof += i;
2535  object_add_weight(op->env, op->weight * op->nrof);
2536  if (tmp) {
2537  esrv_update_item(UPD_NROF, tmp, op);
2538  // Why don't we need to update weight of op->env here?
2539  }
2540  } else {
2541  /* On a map. */
2542  op->nrof += i;
2543 
2544  FOR_MAP_PREPARE(op->map, op->x, op->y, pl)
2545  if (pl->contr) {
2546  pl->contr->socket.update_look = 1;
2547  break;
2548  }
2549  FOR_MAP_FINISH();
2550  }
2551 }
2552 
2567 void object_add_weight(object *op, signed long weight) {
2568  while (op != NULL) {
2569  if (op->type == CONTAINER) {
2570  weight = (signed long)(weight*(100-op->stats.Str)/100);
2571  }
2572  op->carrying += weight;
2573  op = op->env;
2574  }
2575 }
2576 
2591 object *object_insert_in_ob(object *op, object *where) {
2592  object *otmp;
2593 
2594  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
2595  StringBuffer *sb;
2596  char *diff;
2597 
2598  sb = stringbuffer_new();
2599  object_dump(op, sb);
2600  diff = stringbuffer_finish(sb);
2601  LOG(llevError, "Trying to insert (ob) inserted object.\n%s\n", diff);
2602  free(diff);
2603  return op;
2604  }
2605 
2606  if (where == NULL) {
2607  StringBuffer *sb;
2608  char *diff;
2609 
2610  sb = stringbuffer_new();
2611  object_dump(op, sb);
2612  diff = stringbuffer_finish(sb);
2613  LOG(llevError, "Trying to put object in NULL.\n%s\n", diff);
2614  free(diff);
2615  return op;
2616  }
2617  if (where->head) {
2618  LOG(llevDebug, "Warning: Tried to insert object wrong part of multipart object.\n");
2619  }
2620  where = HEAD(where);
2621  if (op->more) {
2622  LOG(llevError, "Tried to insert multipart object %s (%u)\n", op->name, op->count);
2623  return op;
2624  }
2626  CLEAR_FLAG(op, FLAG_REMOVED);
2627  if (op->nrof) {
2628  FOR_INV_PREPARE(where, tmp)
2629  if (object_can_merge(tmp, op)) {
2630  /* return the original object and remove inserted object
2631  * (client needs the original object) */
2632  object_increase_nrof(tmp, op->nrof);
2633  SET_FLAG(op, FLAG_REMOVED);
2634  object_free(op, FREE_OBJ_FREE_INVENTORY | FREE_OBJ_NO_DESTROY_CALLBACK); /* free the inserted object */
2635  return tmp;
2636  }
2637  FOR_INV_FINISH();
2638 
2639  /* the item couldn't merge. */
2640  object_add_weight(where, op->weight*op->nrof);
2641  } else
2642  object_add_weight(where, op->weight+op->carrying);
2643 
2644  op->map = NULL;
2645  op->env = where;
2646  op->above = NULL;
2647  op->below = NULL;
2648  op->x = 0,
2649  op->y = 0;
2650  op->ox = 0,
2651  op->oy = 0;
2652 
2653  /* Client has no idea of ordering so lets not bother ordering it here.
2654  * It sure simplifies this function...
2655  */
2656  if (where->inv == NULL)
2657  where->inv = op;
2658  else {
2659  op->below = where->inv;
2660  op->below->above = op;
2661  where->inv = op;
2662  }
2663 
2664  /* Update in 2 cases: object goes into player's inventory, or object goes into container the player
2665  * is looking into. */
2666  if (where->contr != NULL)
2667  esrv_send_item(where, op);
2668  else if (where->type == CONTAINER && QUERY_FLAG(where, FLAG_APPLIED)) {
2669  object *pl = NULL;
2670 
2671  if (op->env->env && op->env->env->contr)
2672  /* Container is in player's inventory. */
2673  pl = op->env->env;
2674  else if (op->env->map) {
2675  /* Container on map, look above for player. */
2676  FOR_ABOVE_PREPARE(op->env, above)
2677  if (above->contr) {
2678  pl = above;
2679  break;
2680  }
2681  FOR_ABOVE_FINISH();
2682  }
2683  if (pl)
2684  esrv_send_item(pl, op);
2685  }
2686 
2687  otmp = object_get_player_container(where);
2688  if (otmp && otmp->contr != NULL) {
2689  if (!QUERY_FLAG(otmp, FLAG_NO_FIX_PLAYER)
2690  && (QUERY_FLAG(op, FLAG_APPLIED) || op->type == SKILL || op->glow_radius != 0))
2691  /* fix_object will only consider applied items, or skills, or items with a glow radius.
2692  thus no need to call it if our object hasn't that. */
2693  fix_object(otmp);
2694  }
2695 
2696  /* reset the light list and los of the players on the map */
2697  if (op->glow_radius != 0 && where->map) {
2698 #ifdef DEBUG_LIGHTS
2699  LOG(llevDebug, " object_insert_in_ob(): got %s to insert in map/op\n", op->name);
2700 #endif /* DEBUG_LIGHTS */
2701  if (MAP_DARKNESS(where->map)) {
2702  SET_MAP_FLAGS(where->map, where->x, where->y, P_NEED_UPDATE);
2703  update_position(where->map, where->x, where->y);
2704  update_all_los(where->map, where->x, where->y);
2705  }
2706  }
2707 
2708  return op;
2709 }
2710 
2733 int object_check_move_on(object *op, object *originator) {
2734  object *tmp;
2735  tag_t tag;
2736  mapstruct *m = op->map;
2737  int x = op->x, y = op->y;
2738  MoveType move_on, move_slow, move_block;
2739 
2740  if (QUERY_FLAG(op, FLAG_NO_APPLY))
2741  return 0;
2742 
2743  tag = op->count;
2744 
2745  move_on = GET_MAP_MOVE_ON(op->map, op->x, op->y);
2746  move_slow = GET_MAP_MOVE_SLOW(op->map, op->x, op->y);
2747  move_block = GET_MAP_MOVE_BLOCK(op->map, op->x, op->y);
2748 
2749  /* if nothing on this space will slow op down or be applied,
2750  * no need to do checking below. have to make sure move_type
2751  * is set, as lots of objects don't have it set - we treat that
2752  * as walking.
2753  */
2754  if (op->move_type
2755  && !(op->move_type&move_on)
2756  && !(op->move_type&move_slow))
2757  return 0;
2758 
2759  /* This is basically inverse logic of that below - basically,
2760  * if the object can avoid the move on or slow move, they do so,
2761  * but can't do it if the alternate movement they are using is
2762  * blocked. Logic on this seems confusing, but does seem correct.
2763  */
2764  if ((op->move_type&~move_on&~move_block) != 0
2765  && (op->move_type&~move_slow&~move_block) != 0)
2766  return 0;
2767 
2768  /* The objects have to be checked from top to bottom.
2769  * Hence, we first go to the top:
2770  */
2771 
2772  tmp = GET_MAP_OB(op->map, op->x, op->y);
2774  if (tmp->above == NULL)
2775  break;
2776  /* Trim the search when we find the first other spell effect
2777  * this helps performance so that if a space has 50 spell objects,
2778  * we don't need to check all of them.
2779  */
2780  if ((tmp->move_type&MOVE_FLY_LOW) && QUERY_FLAG(tmp, FLAG_NO_PICK))
2781  break;
2784  if (tmp == op)
2785  continue; /* Can't apply yourself */
2786 
2787  /* Check to see if one of the movement types should be slowed down.
2788  * Second check makes sure that the movement types not being slowed
2789  * (~slow_move) is not blocked on this space - just because the
2790  * space doesn't slow down swimming (for example), if you can't actually
2791  * swim on that space, can't use it to avoid the penalty.
2792  */
2793  if (!QUERY_FLAG(op, FLAG_WIZPASS)) {
2794  if ((!op->move_type && tmp->move_slow&MOVE_WALK)
2795  || ((op->move_type&tmp->move_slow) && (op->move_type&~tmp->move_slow&~tmp->move_block) == 0)) {
2796  float diff;
2797 
2798  diff = tmp->move_slow_penalty*FABS(op->speed);
2799  if (op->type == PLAYER) {
2802  diff /= 4.0;
2803  }
2804  }
2805  op->speed_left -= diff;
2806  }
2807  }
2808 
2809  /* Basically same logic as above, except now for actual apply. */
2810  if ((!op->move_type && tmp->move_on&MOVE_WALK)
2811  || ((op->move_type&tmp->move_on) && (op->move_type&~tmp->move_on&~tmp->move_block) == 0)) {
2812  ob_move_on(tmp, op, originator);
2813  if (object_was_destroyed(op, tag))
2814  return 1;
2815 
2816  /* what the person/creature stepped onto has moved the object
2817  * someplace new. Don't process any further - if we did,
2818  * have a feeling strange problems would result.
2819  */
2820  if (op->map != m || op->x != x || op->y != y)
2821  return 0;
2822  }
2824  return 0;
2825 }
2826 
2839 object *map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at) {
2840  if (m == NULL || OUT_OF_REAL_MAP(m, x, y)) {
2841  LOG(llevError, "Present_arch called outside map.\n");
2842  return NULL;
2843  }
2844 
2845  FOR_MAP_PREPARE(m, x, y, tmp)
2846  if (tmp->arch == at)
2847  return tmp;
2848  FOR_MAP_FINISH();
2849 
2850  return NULL;
2851 }
2852 
2866 object *map_find_by_type(mapstruct *m, int x, int y, uint8_t type) {
2867  if (OUT_OF_REAL_MAP(m, x, y)) {
2868  return NULL;
2869  }
2870 
2871  FOR_MAP_PREPARE(m, x, y, tmp)
2872  if (tmp->type == type)
2873  return tmp;
2874  FOR_MAP_FINISH();
2875 
2876  return NULL;
2877 }
2878 
2889 object *object_present_in_ob(uint8_t type, const object *op) {
2890  object *tmp;
2891 
2892  for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
2893  if (tmp->type == type)
2894  return tmp;
2895 
2896  return NULL;
2897 }
2898 
2924 object *object_present_in_ob_by_name(int type, const char *str, const object *op) {
2925  object *tmp;
2926 
2927  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
2928  if ((type == -1 || tmp->type == type) && !strcmp(str, tmp->name))
2929  return tmp;
2930  }
2931  return NULL;
2932 }
2933 
2943 object *arch_present_in_ob(const archetype *at, const object *op) {
2944  object *tmp;
2945 
2946  for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
2947  if (tmp->arch == at)
2948  return tmp;
2949  return NULL;
2950 }
2951 
2960 void object_set_flag_inv(object*op, int flag) {
2961  object *tmp;
2962 
2963  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
2964  SET_FLAG(tmp, flag);
2965  object_set_flag_inv(tmp, flag);
2966  }
2967 }
2968 
2977 void object_unset_flag_inv(object*op, int flag) {
2978  object *tmp;
2979 
2980  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
2981  CLEAR_FLAG(tmp, flag);
2982  object_unset_flag_inv(tmp, flag);
2983  }
2984 }
2985 
2995 void object_set_cheat(object *op) {
2996  SET_FLAG(op, FLAG_WAS_WIZ);
2998 }
2999 
3017 int object_find_multi_free_spot_around(const object *ob, const object *gen, int16_t *hx, int16_t *hy) {
3018  int genx, geny, genx2, geny2, sx, sy, sx2, sy2, ix, iy, nx, ny, i, flag;
3019  int freecount = 0;
3020 
3021  ob = HEAD(ob);
3022 
3023  object_get_multi_size(ob, &sx, &sy, &sx2, &sy2);
3024  object_get_multi_size(gen, &genx, &geny, &genx2, &geny2);
3025  /*
3026  * sx and sy are now the coords of the bottom right corner of ob relative to the head.
3027  * genx and geny are now the coords of the bottom right corner of gen relative to the head.
3028  * sx2 and sy2 are now the coords of the head of ob relative to the top left corner.
3029  * genx2 and geny2 are now the coords of the head of gen relative to the top left corner.
3030  */
3031 
3032  sx++;
3033  sy++;
3034  genx++;
3035  geny++;
3036  /*
3037  * sx, sy, genx, and geny, are now the size of the object, excluding parts left and above
3038  * the head.
3039  */
3040 
3041  ix = gen->x-sx-genx2;
3042  iy = gen->y-sy-geny2;
3043  sx += genx+sx2;
3044  sy += geny+sy2;
3045  /*
3046  * ix and iy are the map coords of the top left square where the head of ob could possibly
3047  * be placed. sx and sy are now the size of the square to search for placement of the head
3048  * relative to ix and iy.
3049  */
3050 
3051  /*
3052  * Loop around the square of possible positions for the head of ob object:
3053  */
3054  for (i = 0; i < (sx+sx+sy+sy); i++) {
3055  if (i <= sx) {
3056  nx = i+ix;
3057  ny = iy;
3058  } else if (i <= sx+sy) {
3059  nx = ix+sx;
3060  ny = iy+i-sx;
3061  } else if (i <= sx+sy+sx) {
3062  nx = ix+sx-(i-(sx+sy));
3063  ny = iy+sy;
3064  } else {
3065  nx = ix;
3066  ny = iy+sy-(i-(sx+sy+sx));
3067  }
3068  /* Check if the spot is free. */
3069  flag = ob_blocked(ob, gen->map, nx, ny);
3070  if (!flag) {
3071  freecount++;
3072  }
3073  }
3074  /* If no free spaces, return. */
3075  if (!freecount)
3076  return -1;
3077 
3078  /* Choose a random valid position */
3079  freecount = RANDOM()%freecount;
3080  for (i = 0; i < sx+sx+sy+sy; i++) {
3081  if (i <= sx) {
3082  nx = i+ix;
3083  ny = iy;
3084  } else if (i <= sx+sy) {
3085  nx = ix+sx;
3086  ny = iy+i-sx;
3087  } else if (i <= sx+sy+sx) {
3088  nx = ix+sx-(i-(sx+sy));
3089  ny = iy+sy;
3090  } else {
3091  nx = ix;
3092  ny = iy+sy-(i-(sx+sy+sx));
3093  }
3094 
3095  /* Make sure it's within map. */
3096  if (nx < 0 || nx >= MAP_WIDTH(gen->map)
3097  || ny < 0 || ny >= MAP_HEIGHT(gen->map))
3098  continue;
3099 
3100  /* Check if the spot is free.*/
3101  flag = ob_blocked(ob, gen->map, nx, ny);
3102  if (!flag) {
3103  freecount--;
3104  if (freecount <= 0) {
3105  *hx = nx;
3106  *hy = ny;
3107  return 0;
3108  }
3109  }
3110  }
3111  return -1;
3112 }
3113 
3133 int object_find_multi_free_spot_within_radius(const object *ob, const object *gen, int *hx, int *hy) {
3134  int genx, geny, genx2, geny2, sx, sy, sx2, sy2, ix, iy, nx, ny, i, flag;
3135  int8_t x, y, radius;
3136  int freecount = 0, freecountstop = 0;
3137  const char *value;
3138  int8_t *x_array;
3139  int8_t *y_array;
3140 
3141  /* If radius is not set, default to 1 */
3142  value = object_get_value(gen, "generator_radius");
3143  if (value) {
3144  radius = (int8_t)strtol(value, NULL, 10);
3145  if (radius < 1) {
3146  radius = 1;
3147  }
3148  } else {
3149  radius = 1;
3150  }
3151 
3152  ob = HEAD(ob);
3153 
3154  object_get_multi_size(ob, &sx, &sy, &sx2, &sy2);
3155  object_get_multi_size(gen, &genx, &geny, &genx2, &geny2);
3156  /*
3157  * sx and sy are now the coords of the bottom right corner
3158  * of ob relative to the head.
3159  * genx and geny are now the coords of the bottom right corner
3160  * of gen relative to the head.
3161  * sx2 and sy2 are now the coords of the head of ob relative
3162  * to the top left corner.
3163  * genx2 and geny2 are now the coords of the head of gen relative
3164  * to the top left corner.
3165  */
3166 
3167  sx++;
3168  sy++;
3169  genx++;
3170  geny++;
3171  /*
3172  * sx, sy, genx, and geny, are now the size of the object,
3173  * excluding parts left and above the head.
3174  */
3175 
3176  ix = gen->x-sx-genx2-radius+1;
3177  iy = gen->y-sy-geny2-radius+1;
3178  sx += genx+sx2+radius*2-1;
3179  sy += geny+sy2+radius*2-1;
3180 
3181  /*
3182  * ix and iy are the map coords of the top left square where
3183  * the head of ob could possibly be placed. sx and sy are now
3184  * the size of the square to search for placement of the head
3185  * relative to ix and iy.
3186  */
3187 
3188  /* Create arrays large enough to hold free space coordinates */
3189  x_array = malloc(sx*sy*sizeof(int8_t));
3190  y_array = malloc(sx*sy*sizeof(int8_t));
3191 
3192  /*
3193  * Loop through the area of possible positions for the head of ob object:
3194  */
3195  for (x = 0; x < sx; x++) {
3196  for (y = 0; y < sy; y++) {
3197  nx = ix+x;
3198  ny = iy+y;
3199 
3200 
3201  /* Make sure it's within map. */
3202  if (get_map_flags(gen->map, NULL, nx, ny, NULL, NULL)&P_OUT_OF_MAP) {
3203  continue;
3204  }
3205 
3206  /* Check if the spot is free. */
3207  flag = ob_blocked(ob, gen->map, nx, ny);
3208  if (!flag) {
3209  x_array[freecount] = nx;
3210  y_array[freecount] = ny;
3211  freecount++;
3212  }
3213  }
3214  }
3215  /* If no free spaces, return. */
3216  if (!freecount) {
3217  free(x_array);
3218  free(y_array);
3219  return -1;
3220  }
3221 
3222  /* Choose a random valid position */
3223  freecountstop = RANDOM()%freecount;
3224  for (i = 0; i < freecount; i++) {
3225  nx = x_array[i];
3226  ny = y_array[i];
3227 
3228  /* Check if the spot is free.*/
3229  flag = ob_blocked(ob, gen->map, nx, ny);
3230  if (!flag) {
3231  freecountstop--;
3232  if (freecountstop <= 0) {
3233  *hx = nx;
3234  *hy = ny;
3235  free(x_array);
3236  free(y_array);
3237  return 0;
3238  }
3239  }
3240  }
3241  free(x_array);
3242  free(y_array);
3243  return -1;
3244 }
3245 
3280 int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop) {
3281  int i, index = 0, flag;
3282  static int altern[SIZEOFFREE];
3283 
3284  for (i = start; i < stop; i++) {
3285  flag = ob_blocked(ob, m, x+freearr_x[i], y+freearr_y[i]);
3286  if (!flag)
3287  altern[index++] = i;
3288 
3289  /* Basically, if we find a wall on a space, we cut down the search size.
3290  * In this way, we won't return spaces that are on another side of a wall.
3291  * This mostly work, but it cuts down the search size in all directions -
3292  * if the space being examined only has a wall to the north and empty
3293  * spaces in all the other directions, this will reduce the search space
3294  * to only the spaces immediately surrounding the target area, and
3295  * won't look 2 spaces south of the target space.
3296  */
3297  else if ((flag&AB_NO_PASS) && maxfree[i] < stop)
3298  stop = maxfree[i];
3299  }
3300  if (!index)
3301  return -1;
3302  return altern[RANDOM()%index];
3303 }
3304 
3320 int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y) {
3321  int i;
3322 
3323  for (i = 0; i < SIZEOFFREE; i++) {
3324  if (!ob_blocked(ob, m, x+freearr_x[i], y+freearr_y[i]))
3325  return i;
3326  }
3327  return -1;
3328 }
3329 
3339 static void permute(int *arr, int begin, int end) {
3340  int i, j, tmp, len;
3341 
3342  len = end-begin;
3343  for (i = begin; i < end; i++) {
3344  j = begin+RANDOM()%len;
3345 
3346  tmp = arr[i];
3347  arr[i] = arr[j];
3348  arr[j] = tmp;
3349  }
3350 }
3351 
3363 void get_search_arr(int *search_arr) {
3364  int i;
3365 
3366  for (i = 0; i < SIZEOFFREE; i++) {
3367  search_arr[i] = i;
3368  }
3369 
3370  permute(search_arr, 1, SIZEOFFREE1+1);
3371  permute(search_arr, SIZEOFFREE1+1, SIZEOFFREE2+1);
3372  permute(search_arr, SIZEOFFREE2+1, SIZEOFFREE);
3373 }
3374 
3393 int map_find_dir(mapstruct *m, int x, int y, object *exclude) {
3394  int i, max = SIZEOFFREE, mflags;
3395  int16_t nx, ny;
3396  mapstruct *mp;
3397  MoveType blocked, move_type;
3398 
3399  if (exclude && exclude->head) {
3400  exclude = exclude->head;
3401  move_type = exclude->move_type;
3402  } else {
3403  /* If we don't have anything, presume it can use all movement types. */
3404  move_type = MOVE_ALL;
3405  }
3406 
3407  for (i = 1; i < max; i++) {
3408  mp = m;
3409  nx = x+freearr_x[i];
3410  ny = y+freearr_y[i];
3411 
3412  mflags = get_map_flags(m, &mp, nx, ny, &nx, &ny);
3413  if (mflags&P_OUT_OF_MAP) {
3414  max = maxfree[i];
3415  } else {
3416  blocked = GET_MAP_MOVE_BLOCK(mp, nx, ny);
3417 
3418  if ((move_type&blocked) == move_type) {
3419  max = maxfree[i];
3420  } else if (mflags&P_IS_ALIVE) {
3421  FOR_MAP_PREPARE(mp, nx, ny, tmp) {
3422  if ((QUERY_FLAG(tmp, FLAG_MONSTER) || tmp->type == PLAYER)
3423  && (tmp != exclude || (tmp->head && tmp->head != exclude))) {
3424  return freedir[i];
3425  }
3426  } FOR_MAP_FINISH();
3427  }
3428  }
3429  }
3430  return 0;
3431 }
3432 
3440 int object_distance(const object *ob1, const object *ob2) {
3441  int i;
3442 
3443  i = (ob1->x-ob2->x)*(ob1->x-ob2->x)+
3444  (ob1->y-ob2->y)*(ob1->y-ob2->y);
3445  return i;
3446 }
3447 
3456 int find_dir_2(int x, int y) {
3457  int q;
3458 
3459  if (!y)
3460  q = -300*x;
3461  else
3462  q = x*100/y;
3463  if (y > 0) {
3464  if (q < -242)
3465  return 3;
3466  if (q < -41)
3467  return 2;
3468  if (q < 41)
3469  return 1;
3470  if (q < 242)
3471  return 8;
3472  return 7;
3473  }
3474  if (q < -242)
3475  return 7;
3476  if (q < -41)
3477  return 6;
3478  if (q < 41)
3479  return 5;
3480  if (q < 242)
3481  return 4;
3482  return 3;
3483 }
3484 
3493 int absdir(int d) {
3494  // Shortcut for modulus that work becuase we have a power of 2
3495  d &= 7;
3496  // 0 needs to be 8
3497  if (!d)
3498  d = 8;
3499  return d;
3500 }
3501 
3511 int dirdiff(int dir1, int dir2) {
3512  int d;
3513 
3514  d = abs(dir1-dir2);
3515  if (d > 4)
3516  d = 8-d;
3517  return d;
3518 }
3519 
3531 static const int reduction_dir[SIZEOFFREE][3] = {
3532  { 0, 0, 0 }, /* 0 */
3533  { 0, 0, 0 }, /* 1 */
3534  { 0, 0, 0 }, /* 2 */
3535  { 0, 0, 0 }, /* 3 */
3536  { 0, 0, 0 }, /* 4 */
3537  { 0, 0, 0 }, /* 5 */
3538  { 0, 0, 0 }, /* 6 */
3539  { 0, 0, 0 }, /* 7 */
3540  { 0, 0, 0 }, /* 8 */
3541  { 8, 1, 2 }, /* 9 */
3542  { 1, 2, -1 }, /* 10 */
3543  { 2, 10, 12 }, /* 11 */
3544  { 2, 3, -1 }, /* 12 */
3545  { 2, 3, 4 }, /* 13 */
3546  { 3, 4, -1 }, /* 14 */
3547  { 4, 14, 16 }, /* 15 */
3548  { 5, 4, -1 }, /* 16 */
3549  { 4, 5, 6 }, /* 17 */
3550  { 6, 5, -1 }, /* 18 */
3551  { 6, 20, 18 }, /* 19 */
3552  { 7, 6, -1 }, /* 20 */
3553  { 6, 7, 8 }, /* 21 */
3554  { 7, 8, -1 }, /* 22 */
3555  { 8, 22, 24 }, /* 23 */
3556  { 8, 1, -1 }, /* 24 */
3557  { 24, 9, 10 }, /* 25 */
3558  { 9, 10, -1 }, /* 26 */
3559  { 10, 11, -1 }, /* 27 */
3560  { 27, 11, 29 }, /* 28 */
3561  { 11, 12, -1 }, /* 29 */
3562  { 12, 13, -1 }, /* 30 */
3563  { 12, 13, 14 }, /* 31 */
3564  { 13, 14, -1 }, /* 32 */
3565  { 14, 15, -1 }, /* 33 */
3566  { 33, 15, 35 }, /* 34 */
3567  { 16, 15, -1 }, /* 35 */
3568  { 17, 16, -1 }, /* 36 */
3569  { 18, 17, 16 }, /* 37 */
3570  { 18, 17, -1 }, /* 38 */
3571  { 18, 19, -1 }, /* 39 */
3572  { 41, 19, 39 }, /* 40 */
3573  { 19, 20, -1 }, /* 41 */
3574  { 20, 21, -1 }, /* 42 */
3575  { 20, 21, 22 }, /* 43 */
3576  { 21, 22, -1 }, /* 44 */
3577  { 23, 22, -1 }, /* 45 */
3578  { 45, 47, 23 }, /* 46 */
3579  { 23, 24, -1 }, /* 47 */
3580  { 24, 9, -1 } /* 48 */
3581 };
3582 
3601 int can_see_monsterP(mapstruct *m, int x, int y, int dir) {
3602  int16_t dx, dy;
3603  int mflags;
3604 
3605  if (dir < 0)
3606  return 0; /* exit condition: invalid direction */
3607 
3608  dx = x+freearr_x[dir];
3609  dy = y+freearr_y[dir];
3610 
3611  mflags = get_map_flags(m, &m, dx, dy, &dx, &dy);
3612 
3613  /* This functional arguably was incorrect before - it was
3614  * checking for P_WALL - that was basically seeing if
3615  * we could move to the monster - this is being more
3616  * literal on if we can see it. To know if we can actually
3617  * move to the monster, we'd need the monster passed in or
3618  * at least its move type.
3619  */
3620  if (mflags&(P_OUT_OF_MAP|P_BLOCKSVIEW))
3621  return 0;
3622 
3623  /* yes, can see. */
3624  if (dir < 9)
3625  return 1;
3626  return can_see_monsterP(m, x, y, reduction_dir[dir][0])|
3627  can_see_monsterP(m, x, y, reduction_dir[dir][1])|
3628  can_see_monsterP(m, x, y, reduction_dir[dir][2]);
3629 }
3630 
3646 int object_can_pick(const object *who, const object *item) {
3647  /* I re-wrote this as a series of if statements
3648  * instead of a nested return (foo & bar && yaz)
3649  * - I think this is much more readable,
3650  * and likely compiler effectively optimizes it the
3651  * same.
3652  */
3653  if (item->weight <= 0)
3654  return 0;
3655  if (QUERY_FLAG(item, FLAG_NO_PICK))
3656  return 0;
3657  if (QUERY_FLAG(item, FLAG_ALIVE))
3658  return 0;
3659  if (item->invisible)
3660  return 0;
3661  if (item->type == TRANSPORT && item->contr != NULL) {
3662  return 0;
3663  }
3664 
3665  /* Weight limit for monsters */
3666  if (who->type != PLAYER && ((uint32_t)(who->weight+who->carrying+item->weight)) > get_weight_limit(who->stats.Str))
3667  return 0;
3668 
3669  /* Can not pick up multipart objects */
3670  if (item->head || item->more)
3671  return 0;
3672 
3673  /* Everything passes, so OK to pick up */
3674  return 1;
3675 }
3676 
3688 object *object_create_clone(object *asrc) {
3689  object *dst = NULL, *tmp, *src, *part, *prev;
3690 
3691  if (!asrc)
3692  return NULL;
3693  src = HEAD(asrc);
3694 
3695  prev = NULL;
3696  for (part = src; part; part = part->more) {
3697  tmp = object_new();
3698  object_copy(part, tmp);
3699  /*
3700  * Need to reset the weight, since object_insert_in_ob() later will
3701  * recompute this field.
3702  */
3703  tmp->carrying = tmp->arch->clone.carrying;
3704  tmp->x -= src->x;
3705  tmp->y -= src->y;
3706  if (!part->head) {
3707  dst = tmp;
3708  tmp->head = NULL;
3709  } else {
3710  tmp->head = dst;
3711  }
3712  tmp->more = NULL;
3713  if (prev)
3714  prev->more = tmp;
3715  prev = tmp;
3716  }
3717  /*** copy inventory ***/
3718  FOR_INV_PREPARE(src, item)
3719  (void)object_insert_in_ob(object_create_clone(item), dst);
3720  FOR_INV_FINISH();
3721 
3722  return dst;
3723 }
3724 
3735 object *object_find_by_name(const object *who, const char *name) {
3736  const char *name_shared = add_string(name);
3737  object *tmp;
3738 
3739  for (tmp = who->inv; tmp; tmp = tmp->below)
3740  if (tmp->name == name_shared)
3741  break;
3742  free_string(name_shared);
3743  return tmp;
3744 }
3745 
3759 object *object_find_by_type(const object *who, int type) {
3760  object *tmp;
3761 
3762  for (tmp = who->inv; tmp; tmp = tmp->below)
3763  if (tmp->type == type)
3764  return tmp;
3765 
3766  return NULL;
3767 }
3768 
3783 object *object_find_by_type_without_flags(const object *who, int type, int *flags, int num_flags) {
3784  int flag_okay;
3785  for (object *tmp = who->inv; tmp; tmp = tmp->below)
3786  if (tmp->type == type) {
3787  flag_okay = 1;
3788  for (int i = 0; i < num_flags; ++i) {
3789  if (QUERY_FLAG(tmp, flags[i])) {
3790  flag_okay = 0; // A flag we didn't want set was set. Skip this item.
3791  break;
3792  }
3793  }
3794  if (flag_okay) // If flag_okay == 1, then the flags specified were not set
3795  return tmp; // If we reach here, none of the flags specified were set. Just like we wanted.
3796  }
3797 
3798  return NULL;
3799 }
3800 
3816 object *object_find_by_type2(const object *who, int type1, int type2) {
3817  object *tmp;
3818 
3819  for (tmp = who->inv; tmp; tmp = tmp->below)
3820  if (tmp->type == type1 || tmp->type == type2)
3821  return tmp;
3822 
3823  return NULL;
3824 }
3825 
3839 object *object_find_by_tag(const object *who, tag_t tag) {
3840  object *tmp;
3841 
3842  for (tmp = who->inv; tmp; tmp = tmp->below)
3843  if (tmp->count == tag)
3844  return tmp;
3845 
3846  return NULL;
3847 }
3848 
3862 object *object_find_by_type_applied(const object *who, int type) {
3863  object *tmp;
3864 
3865  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
3866  if (tmp->type == type && QUERY_FLAG(tmp, FLAG_APPLIED))
3867  return tmp;
3868 
3869  return NULL;
3870 }
3871 
3887 object *object_find_by_type_and_name(const object *who, int type, const char *name) {
3888  object *tmp;
3889 
3890  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
3891  if (tmp->type == type && strcmp(tmp->name, name) == 0)
3892  return tmp;
3893 
3894  return NULL;
3895 }
3896 
3912 object *object_find_by_type_and_race(const object *who, int type, const char *race) {
3913  object *tmp;
3914 
3915  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
3916  if (tmp->type == type && strcmp(tmp->race, race) == 0)
3917  return tmp;
3918 
3919  return NULL;
3920 }
3921 
3937 object *object_find_by_type_and_slaying(const object *who, int type, const char *slaying) {
3938  object *tmp;
3939 
3940  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
3941  if (tmp->type == type && tmp->slaying != NULL && strcmp(tmp->slaying, slaying) == 0)
3942  return tmp;
3943 
3944  return NULL;
3945 }
3946 
3962 object *object_find_by_type_and_skill(const object *who, int type, const char *skill) {
3963  object *tmp;
3964 
3965  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
3966  if (tmp->type == type && tmp->skill != NULL && strcmp(tmp->skill, skill) == 0)
3967  return tmp;
3968 
3969  return NULL;
3970 }
3971 
3985 object *object_find_by_flag(const object *who, int flag) {
3986  object *tmp;
3987 
3988  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
3989  if (QUERY_FLAG(tmp, flag))
3990  return tmp;
3991 
3992  return NULL;
3993 }
3994 
4008 object *object_find_by_flag_applied(const object *who, int flag) {
4009  object *tmp;
4010 
4011  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4012  if (QUERY_FLAG(tmp, FLAG_APPLIED) && QUERY_FLAG(tmp, flag))
4013  return tmp;
4014 
4015  return NULL;
4016 }
4017 
4031 object *object_find_by_arch_name(const object *who, const char *name) {
4032  object *tmp;
4033 
4034  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4035  if (strcmp(tmp->arch->name, name) == 0)
4036  return tmp;
4037 
4038  return NULL;
4039 }
4040 
4056 object *object_find_by_type_and_arch_name(const object *who, int type, const char *name) {
4057  object *tmp;
4058 
4059  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4060  if (tmp->type == type && strcmp(tmp->arch->name, name) == 0)
4061  return tmp;
4062 
4063  return NULL;
4064 }
4065 
4080 object *object_find_by_type_subtype(const object *who, int type, int subtype) {
4081  object *tmp;
4082 
4083  for (tmp = who->inv; tmp; tmp = tmp->below)
4084  if (tmp->type == type && tmp->subtype == subtype)
4085  return tmp;
4086 
4087  return NULL;
4088 }
4089 
4100 key_value *object_get_key_value(const object *ob, const char *key) {
4101  key_value *link;
4102 
4103  for (link = ob->key_values; link != NULL; link = link->next) {
4104  if (link->key == key) {
4105  return link;
4106  }
4107  }
4108 
4109  return NULL;
4110 }
4111 
4125 const char *object_get_value(const object *op, const char *const key) {
4126  key_value *link;
4127  const char *canonical_key;
4128 
4129  canonical_key = find_string(key);
4130 
4131  if (canonical_key == NULL) {
4132  /* 1. There being a field named key on any object
4133  * implies there'd be a shared string to find.
4134  * 2. Since there isn't, no object has this field.
4135  * 3. Therefore, *this *object doesn't have this field.
4136  */
4137  return NULL;
4138  }
4139 
4140  /* This is copied from object_get_key_value() above -
4141  * only 4 lines, and saves the function call overhead.
4142  */
4143  for (link = op->key_values; link != NULL; link = link->next) {
4144  if (link->key == canonical_key) {
4145  return link->value;
4146  }
4147  }
4148  return NULL;
4149 }
4150 
4165 static int object_set_value_s(object *op, const char *canonical_key, const char *value, int add_key) {
4166  key_value *field = NULL, *last = NULL;
4167 
4168  for (field = op->key_values; field != NULL; field = field->next) {
4169  if (field->key != canonical_key) {
4170  last = field;
4171  continue;
4172  }
4173 
4174  if (field->value)
4175  FREE_AND_CLEAR_STR(field->value);
4176  if (value)
4177  field->value = add_string(value);
4178  else {
4179  /* Basically, if the archetype has this key set,
4180  * we need to store the null value so when we save
4181  * it, we save the empty value so that when we load,
4182  * we get this value back again.
4183  */
4184  if (object_get_key_value(&op->arch->clone, canonical_key))
4185  field->value = NULL;
4186  else {
4187  /* Delete this link */
4188  if (field->key)
4189  FREE_AND_CLEAR_STR(field->key);
4190  if (field->value)
4191  FREE_AND_CLEAR_STR(field->value);
4192  if (last)
4193  last->next = field->next;
4194  else
4195  op->key_values = field->next;
4196  free(field);
4197  }
4198  }
4199  return TRUE;
4200  }
4201  /* IF we get here, key doesn't exist */
4202 
4203  /* No field, we'll have to add it. */
4204 
4205  if (!add_key) {
4206  return FALSE;
4207  }
4208  /* There isn't any good reason to store a null
4209  * value in the key/value list. If the archetype has
4210  * this key, then we should also have it, so shouldn't
4211  * be here. If user wants to store empty strings,
4212  * should pass in ""
4213  */
4214  if (value == NULL)
4215  return TRUE;
4216 
4217  field = malloc(sizeof(key_value));
4218 
4219  field->key = add_refcount(canonical_key);
4220  field->value = add_string(value);
4221  /* Usual prepend-addition. */
4222  field->next = op->key_values;
4223  op->key_values = field;
4224 
4225  return TRUE;
4226 }
4227 
4248 int object_set_value(object *op, const char *key, const char *value, int add_key) {
4249  const char *canonical_key = NULL;
4250  int floating_ref = FALSE;
4251  int ret;
4252 
4253  /* HACK This mess is to make sure set_ob_value() passes a shared string
4254  * to object_get_key_value(), without leaving a leaked refcount.
4255  */
4256 
4257  canonical_key = find_string(key);
4258  if (canonical_key == NULL) {
4259  canonical_key = add_string(key);
4260  floating_ref = TRUE;
4261  }
4262 
4263  ret = object_set_value_s(op, canonical_key, value, add_key);
4264 
4265  if (floating_ref) {
4266  free_string(canonical_key);
4267  }
4268 
4269  return ret;
4270 }
4271 
4323 int object_matches_string(object *pl, object *op, const char *name) {
4324  char *cp, local_name[MAX_BUF], name_op[MAX_BUF], name_short[HUGE_BUF], bname_s[MAX_BUF], bname_p[MAX_BUF];
4325  int count, retval = 0;
4326  /* strtok is destructive to name */
4327  safe_strncpy(local_name, name, sizeof(local_name));
4328 
4329  for (cp = strtok(local_name, ","); cp; cp = strtok(NULL, ",")) {
4330  while (cp[0] == ' ')
4331  ++cp; /* get rid of spaces */
4332 
4333  /* LOG(llevDebug, "Trying to match %s\n", cp);*/
4334  /* All is a very generic match - low match value */
4335  if (!strcmp(cp, "all"))
4336  return 1;
4337 
4338  /* unpaid is a little more specific */
4339  if (!strcmp(cp, "unpaid") && QUERY_FLAG(op, FLAG_UNPAID))
4340  return 2;
4341  if (!strcmp(cp, "cursed")
4343  && (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED)))
4344  return 2;
4345 
4346  if (!strcmp(cp, "unlocked") && !QUERY_FLAG(op, FLAG_INV_LOCKED))
4347  return 2;
4348 
4349  /* Allow for things like '100 arrows' */
4350  count = atoi(cp);
4351  if (count != 0) {
4352  cp = strchr(cp, ' ');
4353  while (cp && cp[0] == ' ')
4354  ++cp; /* get rid of spaces */
4355  } else {
4356  if (pl->type == PLAYER)
4357  count = pl->contr->count;
4358  else
4359  count = 0;
4360  }
4361 
4362  if (!cp || cp[0] == '\0' || count < 0)
4363  return 0;
4364 
4365  /* The code here should go from highest retval to lowest. That
4366  * is because of the 'else' handling - we don't want to match on
4367  * something and set a low retval, even though it may match a higher retcal
4368  * later. So keep it in descending order here, so we try for the best
4369  * match first, and work downward.
4370  */
4371  query_name(op, name_op, MAX_BUF);
4372  query_short_name(op, name_short, HUGE_BUF);
4373  query_base_name(op, 0, bname_s, MAX_BUF);
4374  query_base_name(op, 1, bname_p, MAX_BUF);
4375 
4376  if (!strcasecmp(cp, name_op))
4377  retval = 20;
4378  else if (!strcasecmp(cp, name_short))
4379  retval = 18;
4380  else if (!strcasecmp(cp, bname_s))
4381  retval = 16;
4382  else if (!strcasecmp(cp, bname_p))
4383  retval = 16;
4384  else if (op->custom_name && !strcasecmp(cp, op->custom_name))
4385  retval = 15;
4386  else if (!strncasecmp(cp, bname_s, strlen(cp)))
4387  retval = 14;
4388  else if (!strncasecmp(cp, bname_p, strlen(cp)))
4389  retval = 14;
4390  /* Do substring checks, so things like 'Str+1' will match.
4391  * retval of these should perhaps be lower - they are lower
4392  * then the specific strcasecmp aboves, but still higher than
4393  * some other match criteria.
4394  */
4395  else if (strstr(bname_p, cp))
4396  retval = 12;
4397  else if (strstr(bname_s, cp))
4398  retval = 12;
4399  else if (strstr(name_short, cp))
4400  retval = 12;
4401  /* Check against plural/non plural based on count. */
4402  else if (count > 1 && !strcasecmp(cp, op->name_pl)) {
4403  retval = 6;
4404  } else if (count == 1 && !strcasecmp(op->name, cp)) {
4405  retval = 6;
4406  }
4407  /* base name matched - not bad */
4408  else if (strcasecmp(cp, op->name) == 0 && !count)
4409  retval = 4;
4410  /* Check for partial custom name, but give a real low priority */
4411  else if (op->custom_name && strstr(op->custom_name, cp))
4412  retval = 3;
4413 
4414  if (retval) {
4415  if (pl->type == PLAYER)
4416  pl->contr->count = count;
4417  return retval;
4418  }
4419  }
4420  return 0;
4421 }
4422 
4431 void object_fix_multipart(object *tmp) {
4432  archetype *at;
4433  object *op, *last;
4434 
4435  if (!tmp->map) {
4436  LOG(llevError, "object_fix_multipart: not on a map!\n");
4437  return;
4438  }
4439 
4440  /* already multipart - don't do anything more */
4441  if (tmp->head || tmp->more)
4442  return;
4443 
4444  /* If there is nothing more to this object, this for loop
4445  * won't do anything.
4446  */
4447  for (at = tmp->arch->more, last = tmp; at != NULL; at = at->more, last = op) {
4448  op = arch_to_object(at);
4449 
4450  /* update x,y coordinates */
4451  op->x += tmp->x;
4452  op->y += tmp->y;
4453  op->head = tmp;
4454  op->map = tmp->map;
4455  last->more = op;
4456  if (tmp->name != op->name) {
4457  if (op->name)
4458  free_string(op->name);
4459  op->name = add_string(tmp->name);
4460  }
4461  if (tmp->title != op->title) {
4462  if (op->title)
4463  free_string(op->title);
4464  op->title = add_string(tmp->title);
4465  }
4466  /* we could link all the parts onto tmp, and then just
4467  * call object_insert_in_map once, but the effect is the same,
4468  * as object_insert_in_map will call itself with each part, and
4469  * the coding is simpler to just to it here with each part.
4470  */
4472  } /* for at = tmp->arch->more */
4473 }
4474 
4490 void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy) {
4491  archetype *part;
4492  int maxx = 0, maxy = 0, minx = 0, miny = 0;
4493 
4494  ob = HEAD(ob);
4495  *sx = 1;
4496  *sy = 1;
4497  if (ob->arch->more) {
4498  for (part = ob->arch; part; part = part->more) {
4499  if (part->clone.x > maxx)
4500  maxx = part->clone.x;
4501  if (part->clone.y > maxy)
4502  maxy = part->clone.y;
4503  if (part->clone.x < minx)
4504  minx = part->clone.x;
4505  if (part->clone.y < miny)
4506  miny = part->clone.y;
4507  }
4508  }
4509  if (sx)
4510  *sx = maxx;
4511  if (sy)
4512  *sy = maxy;
4513  if (hx)
4514  *hx = -minx;
4515  if (hy)
4516  *hy = -miny;
4517 }
4518 
4539 void object_insert_to_free_spot_or_free(object *op, mapstruct *map, int x, int y, int start, int stop, object *originator) {
4540  int pos;
4541 
4542  pos = object_find_free_spot(op, map, x, y, start, stop);
4543  if (pos == -1) {
4545  return;
4546  }
4547 
4548  object_insert_in_map_at(op, map, originator, 0, x+freearr_x[pos], y+freearr_y[pos]);
4549 }
4550 
4559 void object_set_msg(object *op, const char *msg) {
4560  if (op->msg != NULL) {
4561  free_string(op->msg);
4562  }
4563 
4564  if (msg != NULL) {
4565  // If the message does not have a trailing newline, add one.
4566  if (*msg != '\0' && strchr(msg, '\0')[-1] != '\n') {
4568  stringbuffer_append_string(sb, msg);
4569  stringbuffer_append_string(sb, "\n");
4570  op->msg = stringbuffer_finish_shared(sb);
4571  } else {
4572  op->msg = add_string(msg);
4573  }
4574  } else {
4575  op->msg = NULL;
4576  }
4577 }
4578 
4580 const char *const move_name[] = {
4581  "walk",
4582  "fly_low",
4583  "fly_high",
4584  "swim",
4585  "boat",
4586  NULL
4587 };
4588 
4589 /* This array equates the FLAG_ values with the V_ values. Use -1 to
4590  * put gaps in the array that should not be processed.
4591  * The order matches the order of the define values in 'define.h'.
4592  */
4599 static const char *const flag_names[NUM_FLAGS+1] = {
4600  "alive", "wiz", NULL, NULL, "was_wiz", "applied", "unpaid",
4601  "can_use_shield", "no_pick", "client_anim_sync", "client_anim_random", /* 10 */
4602  "is_animated", NULL /* FLAG_DIALOG_PARSED, not saved */,
4603  NULL /* flying */, "monster", "friendly", "generator",
4604  "is_thrown", "auto_apply", "treasure", "player sold", /* 20 */
4605  "see_invisible", "can_roll", "overlay_floor",
4606  "is_turnable", NULL /* walk_off */, NULL /* fly_on */,
4607  NULL /*fly_off*/, "is_used_up", "identified", "reflecting", /* 30 */
4608  "changing", "splitting", "hitback", "startequip",
4609  "blocksview", "undead", "scared", "unaggressive",
4610  "reflect_missile", "reflect_spell", /* 40 */
4611  "no_magic", "no_fix_player", "is_lightable", "tear_down",
4612  "run_away", NULL /*pass_thru */, NULL /*can_pass_thru*/,
4613  NULL /*"pick_up"*/, "unique", "no_drop", /* 50 */
4614  NULL /* wizcast*/, "can_cast_spell", "can_use_scroll", "can_use_range",
4615  "can_use_bow", "can_use_armour", "can_use_weapon",
4616  "can_use_ring", "has_ready_range", "has_ready_bow", /* 60 */
4617  "xrays", NULL, "is_floor", "lifesave", "no_strength", "sleep",
4618  "stand_still", "random_movement", "only_attack", "confused", /* 70 */
4619  "stealth", NULL, NULL, "cursed", "damned",
4620  "see_anywhere", "known_magical", "known_cursed",
4621  "can_use_skill", "been_applied", /* 80 */
4622  "has_ready_scroll", NULL, NULL,
4623  NULL, "make_invisible", "inv_locked", "is_wooded",
4624  "is_hilly", "has_ready_skill", "has_ready_weapon", /* 90 */
4625  "no_skill_ident", "is_blind", "can_see_in_dark", "is_cauldron",
4626  NULL, "no_steal", "one_hit", NULL, "berserk", "neutral", /* 100 */
4627  "no_attack", "no_damage", NULL, NULL, "activate_on_push",
4628  "activate_on_release", "is_water", "use_content_on_gen", NULL, "is_buildable", /* 110 */
4629  NULL, "blessed", "known_blessed"
4630 };
4631 
4641 {
4642  static char retbuf[MAX_BUF], retbuf_all[MAX_BUF];
4643  int i, all_count = 0, count;
4644 
4645  strcpy(retbuf, "");
4646  strcpy(retbuf_all, " all");
4647 
4648  /* Quick check, and probably fairly common */
4649  if (mt == MOVE_ALL) {
4650  stringbuffer_append_string(sb, "all");
4651  return;
4652  }
4653  if (mt == 0) {
4654  stringbuffer_append_string(sb, "0");
4655  return;
4656  }
4657 
4658  /* We basically slide the bits down. Why look at MOVE_ALL?
4659  * because we may want to return a string like 'all -swim',
4660  * and if we just looked at mt, we couldn't get that.
4661  */
4662  for (i = MOVE_ALL, count = 0; i != 0; i >>= 1, count++) {
4663  if (mt&(1<<count)) {
4664  strcat(retbuf, " ");
4665  strcat(retbuf, move_name[count]);
4666  } else {
4667  strcat(retbuf_all, " -");
4668  strcat(retbuf_all, move_name[count]);
4669  all_count++;
4670  }
4671  }
4672  /* Basically, if there is a single negation, return it, eg
4673  * 'all -swim'. But more than that, just return the
4674  * enumerated values. It doesn't make sense to return
4675  * 'all -walk -fly_low' - it is shorter to return 'fly_high swim'
4676  */
4677  if (all_count <= 1)
4678  stringbuffer_append_string(sb, retbuf_all+1);
4679  else
4680  stringbuffer_append_string(sb, retbuf+1);
4681 }
4682 
4684 static inline void ADD_STRINGLINE_ENTRY(StringBuffer *sb, const char *name, const char *value) {
4685  stringbuffer_append_string(sb, name);
4686  stringbuffer_append_string(sb, value);
4687  stringbuffer_append_string(sb, "\n");
4688 }
4689 
4691 static inline void FAST_SAVE_LONG(StringBuffer *sb, const char *name, const long value) {
4692  stringbuffer_append_printf(sb, "%s%ld\n", name, (long int)value);
4693 }
4694 
4696 static inline void FAST_SAVE_DOUBLE(StringBuffer *sb, const char *name, const double value) {
4697  stringbuffer_append_printf(sb, "%s%f\n", name, value);
4698 }
4699 
4713 void get_ob_diff(StringBuffer *sb, const object *op, const object *op2) {
4714  static char buf2[64];
4715  int tmp;
4716  int i;
4717  key_value *my_field;
4718  key_value *arch_field;
4719 
4720  /* This saves the key/value lists. We do it first so that any
4721  * keys that match field names will be overwritten by the loader.
4722  */
4723  for (my_field = op->key_values; my_field != NULL; my_field = my_field->next) {
4724  /* Find the field in the opposing member. */
4725  arch_field = object_get_key_value(op2, my_field->key);
4726 
4727  /* If there's no partnering field, or it's got a different value, save our field. */
4728  if (arch_field == NULL || my_field->value != arch_field->value) {
4729  stringbuffer_append_string(sb, my_field->key);
4730  stringbuffer_append_string(sb, " ");
4731  /* If this is null, then saving it as a space should
4732  * cause it to be null again.
4733  */
4734  if (my_field->value)
4735  stringbuffer_append_string(sb, my_field->value);
4736  stringbuffer_append_string(sb, "\n");
4737  }
4738  }
4739  /* We don't need to worry about the arch's extra fields - they
4740  * will get taken care of the object_copy() function.
4741  */
4742 
4743  if (op->name && op->name != op2->name) {
4744  ADD_STRINGLINE_ENTRY(sb, "name ", op->name);
4745  }
4746  if (op->name_pl && op->name_pl != op2->name_pl) {
4747  ADD_STRINGLINE_ENTRY(sb, "name_pl ", op->name_pl);
4748  }
4749  if (op->anim_suffix && op->anim_suffix != op2->anim_suffix) {
4750  ADD_STRINGLINE_ENTRY(sb, "anim_suffix ", op->anim_suffix);
4751  }
4752  if (op->custom_name && op->custom_name != op2->custom_name) {
4753  ADD_STRINGLINE_ENTRY(sb, "custom_name ", op->custom_name);
4754  }
4755  if (op->title && op->title != op2->title) {
4756  ADD_STRINGLINE_ENTRY(sb, "title ", op->title);
4757  }
4758  if (op->race && op->race != op2->race) {
4759  ADD_STRINGLINE_ENTRY(sb, "race ", op->race);
4760  }
4761  if (op->slaying && op->slaying != op2->slaying) {
4762  ADD_STRINGLINE_ENTRY(sb, "slaying ", op->slaying);
4763  }
4764  if (op->skill && op->skill != op2->skill) {
4765  ADD_STRINGLINE_ENTRY(sb, "skill ", op->skill);
4766  }
4767  if (op->msg && op->msg != op2->msg) {
4768  stringbuffer_append_string(sb, "msg\n");
4770  stringbuffer_append_string(sb, "endmsg\n");
4771  }
4772  if (op->lore && op->lore != op2->lore) {
4773  stringbuffer_append_string(sb, "lore\n");
4775  stringbuffer_append_string(sb, "endlore\n");
4776  }
4777  if (op->other_arch != op2->other_arch && op->other_arch != NULL && op->other_arch->name) {
4778  ADD_STRINGLINE_ENTRY(sb, "other_arch ", op->other_arch->name);
4779  }
4780  if (op->face != op2->face) {
4781  ADD_STRINGLINE_ENTRY(sb, "face ", op->face->name);
4782  }
4783 
4784  if (op->animation != op2->animation) {
4785  if (op->animation) {
4786  ADD_STRINGLINE_ENTRY(sb, "animation ", animations[GET_ANIM_ID(op)].name);
4787  if (!QUERY_FLAG (op, FLAG_ANIMATE)) {
4788  stringbuffer_append_string(sb, "is_animated 0\n");
4789  }
4790  } else {
4791  stringbuffer_append_string(sb, "animation NONE\n");
4792  }
4793  }
4794  if (op->stats.Str != op2->stats.Str)
4795  FAST_SAVE_LONG(sb, "Str ", op->stats.Str);
4796  if (op->stats.Dex != op2->stats.Dex)
4797  FAST_SAVE_LONG(sb, "Dex ", op->stats.Dex);
4798  if (op->stats.Con != op2->stats.Con)
4799  FAST_SAVE_LONG(sb, "Con ", op->stats.Con);
4800  if (op->stats.Wis != op2->stats.Wis)
4801  FAST_SAVE_LONG(sb, "Wis ", op->stats.Wis);
4802  if (op->stats.Pow != op2->stats.Pow)
4803  FAST_SAVE_LONG(sb, "Pow ", op->stats.Pow);
4804  if (op->stats.Cha != op2->stats.Cha)
4805  FAST_SAVE_LONG(sb, "Cha ", op->stats.Cha);
4806  if (op->stats.Int != op2->stats.Int)
4807  FAST_SAVE_LONG(sb, "Int ", op->stats.Int);
4808  if (op->stats.hp != op2->stats.hp)
4809  FAST_SAVE_LONG(sb, "hp ", op->stats.hp);
4810  if (op->stats.maxhp != op2->stats.maxhp)
4811  FAST_SAVE_LONG(sb, "maxhp ", op->stats.maxhp);
4812  if (op->stats.sp != op2->stats.sp)
4813  FAST_SAVE_LONG(sb, "sp ", op->stats.sp);
4814  if (op->stats.maxsp != op2->stats.maxsp)
4815  FAST_SAVE_LONG(sb, "maxsp ", op->stats.maxsp);
4816  if (op->stats.grace != op2->stats.grace)
4817  FAST_SAVE_LONG(sb, "grace ", op->stats.grace);
4818  if (op->stats.maxgrace != op2->stats.maxgrace)
4819  FAST_SAVE_LONG(sb, "maxgrace ", op->stats.maxgrace);
4820 
4821  if (op->stats.exp != op2->stats.exp) {
4822  snprintf(buf2, sizeof(buf2), "%"FMT64, op->stats.exp);
4823  ADD_STRINGLINE_ENTRY(sb, "exp ", buf2);
4824  }
4825 
4826  if (op->total_exp != op2->total_exp) {
4827  snprintf(buf2, sizeof(buf2), "%"FMT64, op->total_exp);
4828  ADD_STRINGLINE_ENTRY(sb, "total_exp ", buf2);
4829  }
4830 
4831  if (op->expmul != op2->expmul)
4832  FAST_SAVE_DOUBLE(sb, "expmul ", op->expmul);
4833  if (op->stats.food != op2->stats.food)
4834  FAST_SAVE_LONG(sb, "food ", op->stats.food);
4835  if (op->stats.dam != op2->stats.dam)
4836  FAST_SAVE_LONG(sb, "dam ", op->stats.dam);
4837  if (op->stats.luck != op2->stats.luck)
4838  FAST_SAVE_LONG(sb, "luck ", op->stats.luck);
4839  if (op->stats.wc != op2->stats.wc)
4840  FAST_SAVE_LONG(sb, "wc ", op->stats.wc);
4841  if (op->stats.ac != op2->stats.ac)
4842  FAST_SAVE_LONG(sb, "ac ", op->stats.ac);
4843  if (op->x != op2->x)
4844  FAST_SAVE_LONG(sb, "x ", op->x);
4845  if (op->y != op2->y)
4846  FAST_SAVE_LONG(sb, "y ", op->y);
4847  if (op->speed != op2->speed) {
4848  FAST_SAVE_DOUBLE(sb, "speed ", op->speed);
4849  }
4850  if (op->speed > 0 && op->speed_left != op2->speed_left) {
4851  FAST_SAVE_DOUBLE(sb, "speed_left ", op->speed_left);
4852  }
4853  if (op->weapon_speed != op2->weapon_speed) {
4854  FAST_SAVE_DOUBLE(sb, "weapon_speed ", op->weapon_speed);
4855  }
4856  if (op->weapon_speed > 0 && op->weapon_speed_left != op2->weapon_speed_left) {
4857  FAST_SAVE_DOUBLE(sb, "weapon_speed_left ", op->weapon_speed_left);
4858  }
4859  if (op->move_status != op2->move_status)
4860  FAST_SAVE_LONG(sb, "move_state ", op->move_status);
4861  if (op->attack_movement != op2->attack_movement)
4862  FAST_SAVE_LONG(sb, "attack_movement ", op->attack_movement);
4863  if (op->nrof != op2->nrof)
4864  FAST_SAVE_LONG(sb, "nrof ", op->nrof);
4865  if (op->level != op2->level)
4866  FAST_SAVE_LONG(sb, "level ", op->level);
4867  if (op->direction != op2->direction)
4868  FAST_SAVE_LONG(sb, "direction ", op->direction);
4869  if (op->type != op2->type)
4870  FAST_SAVE_LONG(sb, "type ", op->type);
4871  if (op->subtype != op2->subtype)
4872  FAST_SAVE_LONG(sb, "subtype ", op->subtype);
4873  if (op->attacktype != op2->attacktype)
4874  FAST_SAVE_LONG(sb, "attacktype ", op->attacktype);
4875 
4876  for (tmp = 0; tmp < NROFATTACKS; tmp++) {
4877  if (op->resist[tmp] != op2->resist[tmp]) {
4878  stringbuffer_append_string(sb, "resist_");
4879  FAST_SAVE_LONG(sb, resist_save[tmp], op->resist[tmp]);
4880  }
4881  }
4882 
4883  if (op->path_attuned != op2->path_attuned)
4884  FAST_SAVE_LONG(sb, "path_attuned ", op->path_attuned);
4885  if (op->path_repelled != op2->path_repelled)
4886  FAST_SAVE_LONG(sb, "path_repelled ", op->path_repelled);
4887  if (op->path_denied != op2->path_denied)
4888  FAST_SAVE_LONG(sb, "path_denied ", op->path_denied);
4889  if (op->material != op2->material)
4890  FAST_SAVE_LONG(sb, "material ", op->material);
4891  if (op->materialname && op->materialname != op2->materialname) {
4892  ADD_STRINGLINE_ENTRY(sb, "materialname ", op->materialname);
4893  }
4894  if (op->value != op2->value)
4895  FAST_SAVE_LONG(sb, "value ", op->value);
4896  if (op->carrying != op2->carrying)
4897  FAST_SAVE_LONG(sb, "carrying ", op->carrying);
4898  if (op->weight != op2->weight)
4899  FAST_SAVE_LONG(sb, "weight ", op->weight);
4900  if (op->invisible != op2->invisible)
4901  FAST_SAVE_LONG(sb, "invisible ", op->invisible);
4902  if (op->state != op2->state)
4903  FAST_SAVE_LONG(sb, "state ", op->state);
4904  if (op->magic != op2->magic)
4905  FAST_SAVE_LONG(sb, "magic ", op->magic);
4906  if (op->last_heal != op2->last_heal)
4907  FAST_SAVE_LONG(sb, "last_heal ", op->last_heal);
4908  if (op->last_sp != op2->last_sp)
4909  FAST_SAVE_LONG(sb, "last_sp ", op->last_sp);
4910  if (op->last_grace != op2->last_grace)
4911  FAST_SAVE_LONG(sb, "last_grace ", op->last_grace);
4912  if (op->last_eat != op2->last_eat)
4913  FAST_SAVE_LONG(sb, "last_eat ", op->last_eat);
4914  if (QUERY_FLAG(op, FLAG_IS_LINKED) && (tmp = get_button_value(op)))
4915  FAST_SAVE_LONG(sb, "connected ", tmp);
4916  if (op->glow_radius != op2->glow_radius)
4917  FAST_SAVE_LONG(sb, "glow_radius ", op->glow_radius);
4918  if (op->randomitems != op2->randomitems) {
4919  ADD_STRINGLINE_ENTRY(sb, "randomitems ", op->randomitems ? op->randomitems->name : "none");
4920  }
4921 
4922  if (op->run_away != op2->run_away)
4923  FAST_SAVE_LONG(sb, "run_away ", op->run_away);
4924  if (op->pick_up != op2->pick_up)
4925  FAST_SAVE_LONG(sb, "pick_up ", op->pick_up);
4926  if (op->weight_limit != op2->weight_limit)
4927  FAST_SAVE_LONG(sb, "container ", op->weight_limit);
4928  if (op->will_apply != op2->will_apply)
4929  FAST_SAVE_LONG(sb, "will_apply ", op->will_apply);
4930  if (op->smoothlevel != op2->smoothlevel)
4931  FAST_SAVE_LONG(sb, "smoothlevel ", op->smoothlevel);
4932 
4933  if (op->map_layer != op2->map_layer)
4934  ADD_STRINGLINE_ENTRY(sb, "map_layer ", map_layer_name[op->map_layer]);
4935 
4936  if (op->weapontype && op->weapontype != op2->weapontype) {
4937  FAST_SAVE_LONG(sb, "weapontype ", op->weapontype);
4938  }
4939  if (op->client_type && op->client_type != op2->client_type) {
4940  FAST_SAVE_LONG(sb, "client_type ", op->client_type);
4941  }
4942 
4943  if (op->item_power != op2->item_power) {
4944  FAST_SAVE_LONG(sb, "item_power ", op->item_power);
4945  }
4946 
4947  if (op->duration != op2->duration)
4948  FAST_SAVE_LONG(sb, "duration ", op->duration);
4949 
4950  if (op->range != op2->range)
4951  FAST_SAVE_LONG(sb, "range ", op->range);
4952 
4953  if (op->range_modifier != op2->range_modifier)
4954  FAST_SAVE_LONG(sb, "range_modifier ", op->range_modifier);
4955 
4956  if (op->duration_modifier != op2->duration_modifier)
4957  FAST_SAVE_LONG(sb, "duration_modifier ", op->duration_modifier);
4958 
4959  if (op->dam_modifier != op2->dam_modifier)
4960  FAST_SAVE_LONG(sb, "dam_modifier ", op->dam_modifier);
4961 
4962  if (op->gen_sp_armour != op2->gen_sp_armour) {
4963  FAST_SAVE_LONG(sb, "gen_sp_armour ", op->gen_sp_armour);
4964  }
4965 
4966  /* I've kept the old int move type saving code commented out.
4967  * In an ideal world, we'd know if we want to do a quick
4968  * save (say to a temp map, where we don't care about strings),
4969  * or a slower save/dm dump, where printing out strings is handy.
4970  */
4971  if (op->move_type != op2->move_type) {
4972  /*FAST_SAVE_LONG(sb, "move_type ", op->move_type)*/
4973  stringbuffer_append_string(sb, "move_type ");
4975  stringbuffer_append_string(sb, "\n");
4976  }
4977  if (op->move_block != op2->move_block) {
4978  /*FAST_SAVE_LONG(sb, "move_block ", op->move_block)*/
4979  stringbuffer_append_string(sb, "move_block ");
4981  stringbuffer_append_string(sb, "\n");
4982  }
4983  if (op->move_allow != op2->move_allow) {
4984  /*FAST_SAVE_LONG(sb, "move_allow ", op->move_allow);*/
4985  stringbuffer_append_string(sb, "move_allow ");
4987  stringbuffer_append_string(sb, "\n");
4988  }
4989  if (op->move_on != op2->move_on) {
4990  /*FAST_SAVE_LONG(sb, "move_on ", op->move_on);*/
4991  stringbuffer_append_string(sb, "move_on ");
4992  get_string_move_type(sb, op->move_on);
4993  stringbuffer_append_string(sb, "\n");
4994  }
4995  if (op->move_off != op2->move_off) {
4996  /*FAST_SAVE_LONG(sb, "move_off ", op->move_off);*/
4997  stringbuffer_append_string(sb, "move_off ");
4998  get_string_move_type(sb, op->move_off);
4999  stringbuffer_append_string(sb, "\n");
5000  }
5001  if (op->move_slow != op2->move_slow) {
5002  /*FAST_SAVE_LONG(sb, "move_slow ", op->move_slow);*/
5003  stringbuffer_append_string(sb, "move_slow ");
5005  stringbuffer_append_string(sb, "\n");
5006  }
5007 
5008  if (op->move_slow_penalty != op2->move_slow_penalty) {
5009  FAST_SAVE_DOUBLE(sb, "move_slow_penalty ", op->move_slow_penalty);
5010  }
5011 
5012  if (!COMPARE_FLAGS(op, op2)) {
5013  for (tmp = 0; tmp <= NUM_FLAGS; tmp++) {
5014  if (flag_names[tmp] && (QUERY_FLAG(op, tmp) != QUERY_FLAG(op2, tmp))) {
5015  ADD_STRINGLINE_ENTRY(sb, flag_names[tmp], QUERY_FLAG(op, tmp) ? " 1" : " 0");
5016  }
5017  }
5018  }
5019 
5020  /* Save body locations */
5021  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
5022  if (op->body_info[i] != op2->body_info[i]) {
5023  stringbuffer_append_string(sb, body_locations[i].save_name);
5024  FAST_SAVE_LONG(sb, " ", op->body_info[i]);
5025  }
5026  }
5027 
5028 }
5029 
5034 void save_object_in_sb(StringBuffer *sb, const object *op, const int flag) {
5035  archetype *at = op->arch;
5036  if (at == NULL)
5037  at = empty_archetype;
5038 
5039  stringbuffer_append_printf(sb, "arch %s\n", at->name);
5040 
5041  if (op->arch->reference_count > 0) {
5042  /* The object is a custom item/monster, so we handle its save differently.
5043  * We compare the custom archetype to the "original" one, then only save hp/gr/sp
5044  * which are the only values we can't recompute later - all others are modified by items in inventory.
5045  * Note that hp/gr/sp will appear twice in save, but last value will take precedence.
5046  */
5047  archetype *original = find_archetype(op->arch->name);
5048  if (!original) {
5049  LOG(llevError, "could not find original archetype %s for custom monster!\n", op->arch->name);
5050  abort();
5051  }
5052  get_ob_diff(sb, &op->arch->clone, &original->clone);
5053  if (op->stats.hp != op->arch->clone.stats.hp)
5054  FAST_SAVE_LONG(sb, "hp ", op->stats.hp);
5055  if (op->stats.sp != op->arch->clone.stats.sp)
5056  FAST_SAVE_LONG(sb, "sp ", op->stats.sp);
5057  if (op->stats.grace != op->arch->clone.stats.grace)
5058  FAST_SAVE_LONG(sb, "grace ", op->stats.grace);
5059  if (op->x != op->arch->clone.x)
5060  FAST_SAVE_LONG(sb, "x ", op->x);
5061  if (op->y != op->arch->clone.y)
5062  FAST_SAVE_LONG(sb, "y ", op->y);
5063  } else if (op->artifact != NULL) {
5064  /* if op is an artifact, then find the "standard" artifact to use that for the diff */
5065  object *base;
5066  const artifact *artifact;
5067 
5068  artifact = find_artifact(op, op->artifact);
5069  if (artifact == NULL) {
5070  LOG(llevError, "could not find artifact %s [%d] to save data\n", op->artifact, op->type);
5071  get_ob_diff(sb, op, &at->clone);
5072  } else {
5073  stringbuffer_append_printf(sb, "artifact %s\n", op->artifact);
5074  base = arch_to_object(at);
5075  give_artifact_abilities(base, artifact->item);
5076  get_ob_diff(sb, op, base);
5078  }
5079  } else {
5080  get_ob_diff(sb, op, &at->clone);
5081  }
5082 
5083  /* Eneq(@csd.uu.se): Added this to allow containers being saved with contents*/
5084  FOR_INV_PREPARE(op, tmp)
5085  save_object_in_sb(sb, tmp, flag);
5086  FOR_INV_FINISH();
5087 
5088  stringbuffer_append_string(sb, "end\n");
5089 }
5090 
5103 int save_object(FILE *fp, object *op, int flag) {
5104  /* Even if the object does have an owner, it would seem that we should
5105  * still save it.
5106  */
5107  if (object_get_owner(op) != NULL || fp == NULL)
5108  return SAVE_ERROR_OK;
5109 
5110  /* If it is unpaid and we don't want to save those, just return. */
5111  if (!(flag&SAVE_FLAG_SAVE_UNPAID) && (QUERY_FLAG(op, FLAG_UNPAID))) {
5112  return SAVE_ERROR_OK;
5113  }
5114 
5115  /* If the object has no_save set, just return */
5116  if (QUERY_FLAG(op, FLAG_NO_SAVE))
5117  return SAVE_ERROR_OK;
5118 
5120  save_object_in_sb(sb, op, flag);
5121  char *cp = stringbuffer_finish(sb);
5122  if (fputs(cp, fp) == EOF) {
5123  free(cp);
5124  return SAVE_ERROR_WRITE;
5125  } else {
5126  free(cp);
5127  return SAVE_ERROR_OK;
5128  }
5129 }
float weapon_speed_left
Definition: object.h:332
static int compare_ob_value_lists(const object *, const object *)
Definition: object.c:170
int object_distance(const object *ob1, const object *ob2)
Definition: object.c:3440
object * object_find_by_type_and_name(const object *who, int type, const char *name)
Definition: object.c:3887
#define FLAG_NO_MAGIC
Definition: define.h:276
char path[HUGE_BUF]
Definition: map.h:365
int find_dir_2(int x, int y)
Definition: object.c:3456
#define SET_MAP_OB(M, X, Y, tmp)
Definition: map.h:177
int reference_count
Definition: object.h:475
#define FLAG_NO_DROP
Definition: define.h:289
int8_t Int
Definition: living.h:36
#define NUM_BODY_LOCATIONS
Definition: object.h:13
Definition: player.h:92
archetype * find_archetype(const char *name)
Definition: arch.c:695
#define FLAG_DAMNED
Definition: define.h:318
#define FLAG_IS_FLOOR
Definition: define.h:303
#define FLAG_UNPAID
Definition: define.h:236
int8_t ac
Definition: living.h:38
struct _key_value * next
Definition: object.h:43
#define MOVE_WALK
Definition: define.h:407
int32_t weight_limit
Definition: object.h:368
#define UP_OBJ_FACE
Definition: object.h:519
tag_t ownercount
Definition: object.h:383
#define FLAG_IS_LINKED
Definition: define.h:316
MoveType move_type
Definition: object.h:427
#define INS_BELOW_ORIGINATOR
Definition: object.h:572
#define GET_MAP_MOVE_OFF(M, X, Y)
Definition: map.h:207
void object_free(object *ob, int flags)
Definition: object.c:1336
uint8_t dam_modifier
Definition: object.h:410
MoveType move_on
Definition: object.h:430
EXTERN long ob_count
Definition: global.h:152
#define P_PLAYER
Definition: map.h:236
#define SAVE_ERROR_OK
Definition: map.h:143
struct Statistics statistics
Definition: init.c:98
const char * race
Definition: object.h:318
#define P_NEED_UPDATE
Definition: map.h:239
#define FOR_OB_AND_ABOVE_PREPARE(op_)
Definition: define.h:776
uint16_t attack_movement
Definition: object.h:394
#define OBJ_EXPAND
Definition: config.h:524
void esrv_send_item(object *pl, object *op)
Definition: main.c:340
tag_t attacked_by_count
Definition: object.h:386
#define SET_FLAG(xyz, p)
Definition: define.h:223
sstring add_refcount(sstring str)
Definition: shstr.c:210
void object_clear_owner(object *op)
Definition: object.c:587
MoveType move_allow
Definition: object.h:429
void object_sub_weight(object *op, signed long weight)
Definition: object.c:1551
object * object_find_by_type_applied(const object *who, int type)
Definition: object.c:3862
#define FABS(x)
Definition: define.h:22
unsigned char uint8_t
Definition: win32.h:161
Definition: object.h:221
void object_free_all_data(void)
Definition: object.c:531
void object_copy_owner(object *op, object *clone)
Definition: object.c:657
uint16_t material
Definition: object.h:349
tag_t * spell_tags
Definition: object.h:438
sstring artifact
Definition: object.h:314
object * object_find_by_type(const object *who, int type)
Definition: object.c:3759
uint64_t spell_merges
Definition: global.h:352
#define EVENT_DESTROY
Definition: plugin.h:70
object * object_get_env_recursive(object *op)
Definition: object.c:360
struct obj * container
Definition: object.h:291
const Face * blank_face
Definition: image.c:39
#define FLAG_FRIENDLY
Definition: define.h:246
void object_copy_with_inv(const object *src_ob, object *dest_ob)
Definition: object.c:952
sstring stringbuffer_finish_shared(StringBuffer *sb)
Definition: stringbuffer.c:85
#define P_NO_MAGIC
Definition: map.h:227
int16_t players
Definition: map.h:344
void fatal(enum fatal_error err)
Definition: utils.c:597
static object * find_insert_pos(object *op, const int flag)
Definition: object.c:2035
static void get_string_move_type(StringBuffer *sb, MoveType mt)
Definition: object.c:4640
int8_t range
Definition: object.h:408
void init_objects(void)
Definition: object.c:93
#define FLAG_NO_FIX_PLAYER
Definition: define.h:277
#define LOOK_OBJ(ob)
Definition: object.h:507
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
uint32_t in_memory
Definition: map.h:345
void get_search_arr(int *search_arr)
Definition: object.c:3363
unsigned char MoveType
Definition: define.h:432
int32_t last_heal
Definition: object.h:359
int16_t maxgrace
Definition: living.h:45
void free_string(sstring str)
Definition: shstr.c:280
#define UP_OBJ_INSERT
Definition: object.h:516
signed long object_sum_weight(object *op)
Definition: object.c:338
static void FAST_SAVE_LONG(StringBuffer *sb, const char *name, const long value)
Definition: object.c:4691
#define HUGE_BUF
Definition: define.h:37
void object_fix_multipart(object *tmp)
Definition: object.c:4431
mapstruct * get_map_from_coord(mapstruct *m, int16_t *x, int16_t *y)
Definition: map.c:2379
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.c:343
const char * object_get_value(const object *op, const char *const key)
Definition: object.c:4125
struct treasureliststruct * randomitems
Definition: object.h:388
static uint32_t NROF(const object *const ob)
Definition: object.h:612
void query_base_name(const object *op, int plural, char *buf, size_t size)
Definition: item.c:680
#define MAP_HEIGHT(m)
Definition: map.h:80
object clone
Definition: object.h:472
int16_t duration
Definition: object.h:406
socket_struct socket
Definition: player.h:94
int16_t invisible
Definition: object.h:362
short freearr_x[SIZEOFFREE]
Definition: object.c:65
int object_find_multi_free_spot_within_radius(const object *ob, const object *gen, int *hx, int *hy)
Definition: object.c:3133
uint8_t duration_modifier
Definition: object.h:407
Definition: object.h:240
int object_count_active(void)
Definition: object.c:1527
const char * key
Definition: object.h:41
struct obj * prev
Definition: object.h:278
const char * slaying
Definition: object.h:319
object * object_find_by_flag(const object *who, int flag)
Definition: object.c:3985
const char * name
Definition: face.h:19
int32_t last_sp
Definition: object.h:360
int object_check_move_on(object *op, object *originator)
Definition: object.c:2733
uint8_t subtype
Definition: object.h:341
int64_t exp
Definition: living.h:47
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:533
int arch_init
Definition: arch.c:41
struct obj * above
Definition: object.h:288
object * object_find_by_type_without_flags(const object *who, int type, int *flags, int num_flags)
Definition: object.c:3783
void object_dump_all(void)
Definition: object.c:468
double expmul
Definition: object.h:398
object * object_find_by_type_and_slaying(const object *who, int type, const char *slaying)
Definition: object.c:3937
#define OUT_OF_REAL_MAP(M, X, Y)
Definition: map.h:217
#define object_was_destroyed(op, old_tag)
Definition: object.h:68
#define TRUE
Definition: compat.h:10
int freedir[SIZEOFFREE]
Definition: object.c:83
object * arch_present_in_ob(const archetype *at, const object *op)
Definition: object.c:2943
body_locations_struct body_locations[NUM_BODY_LOCATIONS]
Definition: item.c:54
#define FALSE
Definition: compat.h:11
void remove_friendly_object(object *op)
Definition: friend.c:56
uint32_t path_attuned
Definition: object.h:345
#define MAX(x, y)
Definition: compat.h:20
void object_update(object *op, int action)
Definition: object.c:1190
int16_t sp
Definition: living.h:42
uint32_t get_weight_limit(int stat)
Definition: living.c:2356
int object_can_merge(object *ob1, object *ob2)
Definition: object.c:199
uint8_t smoothlevel
Definition: object.h:424
uint32_t path_repelled
Definition: object.h:346
#define safe_strncpy
Definition: compat.h:23
uint32_t hidden
Definition: player.h:132
void free_dialog_information(object *op)
Definition: dialog.c:32
struct obj * enemy
Definition: object.h:384
struct archt * other_arch
Definition: object.h:416
int absdir(int d)
Definition: object.c:3493
object * object_find_by_name(const object *who, const char *name)
Definition: object.c:3735
Definition: object.h:467
uint8_t casting_time
Definition: global.h:271
uint64_t spell_hash_full
Definition: global.h:353
#define FOR_OB_AND_BELOW_FINISH()
Definition: define.h:791
int16_t maxsp
Definition: living.h:43
int8_t Con
Definition: living.h:36
#define FLAG_REMOVED
Definition: define.h:232
int16_t hp
Definition: living.h:40
#define CALLOC(x, y)
Definition: compat.h:27
int nrofallocobjects
Definition: object.c:57
short freearr_y[SIZEOFFREE]
Definition: object.c:71
object * active_objects
Definition: object.c:62
static const int reduction_dir[SIZEOFFREE][3]
Definition: object.c:3531
#define SAVE_ERROR_WRITE
Definition: map.h:146
void object_set_flag_inv(object *op, int flag)
Definition: object.c:2960
#define MOVE_ALL
Definition: define.h:413
void esrv_del_item(player *pl, object *ob)
Definition: main.c:356
int object_find_multi_free_spot_around(const object *ob, const object *gen, int16_t *hx, int16_t *hy)
Definition: object.c:3017
void object_set_owner(object *op, object *owner)
Definition: object.c:604
#define SAVE_FLAG_SAVE_UNPAID
Definition: map.h:110
Definition: object.h:241
const char * lore
Definition: object.h:324
#define MAP_IN_MEMORY
Definition: map.h:130
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.c:4248
uint32_t update_look
Definition: newserver.h:104
void object_free_drop_inventory(object *ob)
Definition: object.c:1316
const char * title
Definition: object.h:317
int16_t y
Definition: object.h:327
key_value * object_get_key_value(const object *ob, const char *key)
Definition: object.c:4100
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:1838
int16_t maxhp
Definition: living.h:41
sstring find_string(const char *str)
Definition: shstr.c:236
void object_replace_insert_in_map(const char *arch_string, object *op)
Definition: object.c:2331
int dirdiff(int dir1, int dir2)
Definition: object.c:3511
void object_update_turn_face(object *op)
Definition: object.c:1069
#define FREE_OBJ_FREE_INVENTORY
Definition: object.h:532
void object_dump(const object *op, StringBuffer *sb)
Definition: object.c:415
#define FLAG_CLIENT_ANIM_RANDOM
Definition: define.h:241
EXTERN archetype * empty_archetype
Definition: global.h:147
uint32_t path_denied
Definition: object.h:347
int maxfree[SIZEOFFREE]
Definition: object.c:77
#define STARTMAX
Definition: config.h:523
#define FLAG_ALIVE
Definition: define.h:230
object * object_new(void)
Definition: object.c:1011
const char * name_pl
Definition: object.h:315
#define FLAG_OBJ_ORIGINAL
Definition: define.h:365
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.c:95
int8_t direction
Definition: object.h:336
object * object_find_by_tag_global(tag_t i)
Definition: object.c:491
#define FOR_OB_AND_ABOVE_FINISH()
Definition: define.h:780
int object_can_pick(const object *who, const object *item)
Definition: object.c:3646
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2591
float speed_left
Definition: object.h:330
#define MAP_DARKNESS(m)
Definition: map.h:75
#define INS_ON_TOP
Definition: object.h:571
#define FLAG_NO_STEAL
Definition: define.h:343
signed short int16_t
Definition: win32.h:160
int16_t ox
Definition: object.h:328
const char * materialname
Definition: object.h:348
int32_t weight
Definition: object.h:367
#define MOVE_FLY_LOW
Definition: define.h:408
const char * anim_suffix
Definition: object.h:316
#define FOR_ABOVE_FINISH()
Definition: define.h:731
void update_all_los(const mapstruct *map, int x, int y)
Definition: los.c:536
uint8_t range_modifier
Definition: object.h:409
int8_t Wis
Definition: living.h:36
uint32_t flags[4]
Definition: object.h:418
struct mapdef * map
Definition: object.h:297
void free_arch(archetype *at)
Definition: arch.c:266
#define snprintf
Definition: win32.h:46
struct obj * active_prev
Definition: object.h:283
#define FLAG_NO_SAVE
Definition: define.h:244
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
Definition: map.c:497
const char *const move_name[]
Definition: object.c:4580
const artifact * find_artifact(const object *op, const char *name)
Definition: artifact.c:671
#define FLAG_CLIENT_ANIM_SYNC
Definition: define.h:240
object * transport
Definition: player.h:195
#define FLAG_IDENTIFIED
Definition: define.h:261
#define FOR_INV_FINISH()
Definition: define.h:714
object * object_find_by_flag_applied(const object *who, int flag)
Definition: object.c:4008
void object_remove_from_active_list(object *op)
Definition: object.c:1148
#define FMT64
Definition: compat.h:12
void update_position(mapstruct *m, int x, int y)
Definition: map.c:2127
int16_t dam
Definition: living.h:46
int object_count_free(void)
Definition: object.c:1495
int32_t carrying
Definition: object.h:369
object * objects
Definition: object.c:60
#define FLAG_BLOCKSVIEW
Definition: define.h:269
struct artifactstruct artifact
static const char *const flag_names[NUM_FLAGS+1]
Definition: object.c:4599
const char * name
Definition: object.h:311
struct obj * env
Definition: object.h:293
static void FAST_SAVE_DOUBLE(StringBuffer *sb, const char *name, const double value)
Definition: object.c:4696
#define FOR_ABOVE_PREPARE(op_, it_)
Definition: define.h:724
int8_t gen_sp_armour
Definition: object.h:365
#define OB_SPELL_TAG_MATCH(op, count)
Definition: object.h:93
int save_object(FILE *fp, object *op, int flag)
Definition: object.c:5103
uint8_t state
Definition: object.h:351
struct obj * below
Definition: object.h:287
struct archt * more
Definition: object.h:471
#define INS_NO_WALK_ON
Definition: object.h:570
object * object_present_in_ob(uint8_t type, const object *op)
Definition: object.c:2889
#define offsetof(type, member)
Definition: shstr.h:37
#define FLAG_IS_A_TEMPLATE
Definition: define.h:375
int16_t last_grace
Definition: object.h:361
void object_reset(object *op)
Definition: object.c:698
#define GET_MAP_TOP(M, X, Y)
Definition: map.h:174
object * object_create_clone(object *asrc)
Definition: object.c:3688
#define NUM_FLAGS
Definition: define.h:385
uint32_t nrof
Definition: object.h:334
int8_t Cha
Definition: living.h:36
#define GET_MAP_MOVE_ON(M, X, Y)
Definition: map.h:202
#define FLAG_OVERLAY_FLOOR
Definition: define.h:255
#define SIZEOFFREE
Definition: define.h:154
#define P_OUT_OF_MAP
Definition: map.h:251
MoveType move_off
Definition: object.h:431
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:192
object * object_find_by_name_global(const char *str)
Definition: object.c:511
EXTERN Animations * animations
Definition: global.h:161
struct pl * contr
Definition: object.h:276
int8_t item_power
Definition: object.h:364
object * object_insert_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:2099
void object_clear(object *op)
Definition: object.c:747
int16_t oy
Definition: object.h:328
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:205
#define MAP_SAVING
Definition: map.h:133
#define UPD_WEIGHT
Definition: newclient.h:291
uint32_t tag_t
Definition: object.h:12
static void ADD_STRINGLINE_ENTRY(StringBuffer *sb, const char *name, const char *value)
Definition: object.c:4684
object * object_find_by_type_and_race(const object *who, int type, const char *race)
Definition: object.c:3912
int8_t luck
Definition: living.h:39
float speed
Definition: object.h:329
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
#define HEAD(op)
Definition: object.h:594
#define INS_ABOVE_FLOOR_ONLY
Definition: object.h:569
#define FLAG_BEEN_APPLIED
Definition: define.h:324
void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy)
Definition: object.c:4490
#define MAX_BUF
Definition: define.h:35
const Animations * animation
Definition: object.h:419
static object * free_objects
Definition: object.c:61
struct obj * active_next
Definition: object.h:279
static void expand_objects(void)
Definition: object.c:970
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.c:203
method_ret ob_move_on(object *op, object *victim, object *originator)
Definition: ob_methods.c:112
int16_t x
Definition: object.h:327
int strncasecmp(const char *s1, const char *s2, int n)
Definition: porting.c:224
const char *const map_layer_name[MAP_LAYERS]
Definition: map.c:54
int nroffreeobjects
Definition: object.c:56
int64_t total_exp
Definition: object.h:372
MoveType move_slow
Definition: object.h:432
const char * skill
Definition: object.h:321
int32_t last_eat
Definition: object.h:358
Definition: object.h:201
int8_t wc
Definition: living.h:37
int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y)
Definition: object.c:3320
void object_insert_to_free_spot_or_free(object *op, mapstruct *map, int x, int y, int start, int stop, object *originator)
Definition: object.c:4539
static const flag_definition flags[]
#define FOR_MAP_FINISH()
Definition: define.h:767
key_value * key_values
Definition: object.h:436
struct obj * next
Definition: object.h:277
int8_t Str
Definition: living.h:36
#define COMPARE_FLAGS(p, q)
Definition: define.h:226
void animate_object(object *op, int dir)
Definition: anim.c:212
#define FLAG_NO_APPLY
Definition: define.h:302
int16_t resist[NROFATTACKS]
Definition: object.h:343
#define FLAG_KNOWN_CURSED
Definition: define.h:321
object * ob
Definition: player.h:158
object * object_find_by_tag(const object *who, tag_t tag)
Definition: object.c:3839
#define GET_MAP_FLAGS(M, X, Y)
Definition: map.h:161
#define FLAG_IS_HILLY
Definition: define.h:333
#define SPELL_TAG_SIZE
Definition: object.h:81
#define FLAG_CURSED
Definition: define.h:317
Definition: object.h:107
unsigned int uint32_t
Definition: win32.h:162
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Definition: object.c:4080
#define SET_MAP_FLAGS(M, X, Y, C)
Definition: map.h:163
#define FLAG_ANIMATE
Definition: define.h:242
int8_t body_info[NUM_BODY_LOCATIONS]
Definition: object.h:375
const char * name
Definition: treasure.h:83
object * object_find_by_type_and_skill(const object *who, int type, const char *skill)
Definition: object.c:3962
uint32_t attacktype
Definition: object.h:344
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
Definition: object.c:2371
uint8_t map_layer
Definition: object.h:425
#define INS_NO_MERGE
Definition: object.h:568
object * object_decrease_nrof(object *op, uint32_t i)
Definition: object.c:2410
void save_object_in_sb(StringBuffer *sb, const object *op, const int flag)
Definition: object.c:5034
#define UP_OBJ_CHANGE
Definition: object.h:518
struct obj * owner
Definition: object.h:380
#define RANDOM()
Definition: define.h:681
int16_t grace
Definition: living.h:44
#define UPD_NROF
Definition: newclient.h:296
signed char int8_t
Definition: win32.h:158
Definition: object.h:143
#define GET_MAP_PLAYER(M, X, Y)
Definition: map.h:168
const char * custom_name
Definition: object.h:435
#define UP_OBJ_REMOVE
Definition: object.h:517
int get_button_value(const object *button)
Definition: button.c:754
tag_t count
Definition: object.h:299
living stats
Definition: object.h:370
uint16_t client_type
Definition: object.h:342
int8_t Dex
Definition: living.h:36
struct archt * arch
Definition: object.h:415
#define AB_NO_PASS
Definition: map.h:235
#define UPD_FACE
Definition: newclient.h:292
#define MAP_WIDTH(m)
Definition: map.h:78
uint8_t will_apply
Definition: object.h:395
uint8_t type
Definition: object.h:340
uint32_t do_los
Definition: player.h:126
struct Settings settings
Definition: init.c:39
void object_set_enemy(object *op, object *enemy)
Definition: object.c:679
uint32_t weapontype
Definition: object.h:374
#define FLAG_APPLIED
Definition: define.h:235
#define NROFATTACKS
Definition: attack.h:17
object * object_merge(object *op, object *top)
Definition: object.c:1789
void query_short_name(const object *op, char *buf, size_t size)
Definition: item.c:508
object * object_get_player_container(object *op)
Definition: object.c:377
int out_of_map(mapstruct *m, int x, int y)
Definition: map.c:2306
int execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Definition: main.c:365
static object objarray[STARTMAX]
Definition: object.c:55
#define SIZEOFFREE2
Definition: define.h:153
#define OB_SPELL_TAG_HASH(op, count)
Definition: object.h:87
int object_count_used(void)
Definition: object.c:1511
static const object * object_get_owner_const(const object *op)
Definition: object.c:394
const char * msg
Definition: object.h:322
const char * value
Definition: object.h:42
static void permute(int *, int, int)
Definition: object.c:3339
int16_t casting_time
Definition: object.h:405
void object_unset_flag_inv(object *op, int flag)
Definition: object.c:2977
int object_matches_string(object *pl, object *op, const char *name)
Definition: object.c:4323
#define FOR_OB_AND_BELOW_PREPARE(op_)
Definition: define.h:787
#define FLAG_STARTEQUIP
Definition: define.h:268
void object_merge_spell(object *op, int16_t x, int16_t y)
Definition: object.c:1867
int map_find_dir(mapstruct *m, int x, int y, object *exclude)
Definition: object.c:3393
#define GET_ANIM_ID(ob)
Definition: global.h:170
sstring add_string(const char *str)
Definition: shstr.c:124
EXTERN player * first_player
Definition: global.h:115
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.c:104
struct pl * next
Definition: player.h:93
#define MIN_ACTIVE_SPEED
Definition: define.h:676
void object_add_weight(object *op, signed long weight)
Definition: object.c:2567
#define GET_MAP_OB(M, X, Y)
Definition: map.h:172
int strcasecmp(const char *s1, const char *s2)
Definition: porting.c:256
int8_t glow_radius
Definition: object.h:366
#define FLAG_MONSTER
Definition: define.h:245
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.c:824
int8_t Pow
Definition: living.h:36
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
Definition: map.c:310
struct obj * inv
Definition: object.h:290
void object_set_cheat(object *op)
Definition: object.c:2995
#define SIZEOFFREE1
Definition: define.h:152
struct obj * head
Definition: object.h:296
#define MOVE_FLY_HIGH
Definition: define.h:409
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
static void object_increase_nrof(object *op, uint32_t i)
Definition: object.c:2497
EXTERN const char *const resist_save[NROFATTACKS]
Definition: attack.h:139
#define SET_MAP_TOP(M, X, Y, tmp)
Definition: map.h:179
#define FLAG_WAS_WIZ
Definition: define.h:234
uint8_t pick_up
Definition: object.h:363
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:760
#define FREE_OBJ_DROP_ABOVE_FLOOR
Definition: object.h:534
MoveType move_block
Definition: object.h:428
uint8_t run_away
Definition: object.h:387
#define GET_MAP_MOVE_SLOW(M, X, Y)
Definition: map.h:197
#define P_BLOCKSVIEW
Definition: map.h:226
void object_set_msg(object *op, const char *msg)
Definition: object.c:4559
int can_see_monsterP(mapstruct *m, int x, int y, int dir)
Definition: object.c:3601
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.c:3280
#define FLAG_DIALOG_PARSED
Definition: define.h:243
#define P_NO_ERROR
Definition: map.h:240
float move_slow_penalty
Definition: object.h:433
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:583
object * item
Definition: artifact.h:15
object * find_skill_by_number(object *who, int skillno)
Definition: main.c:352
object * map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at)
Definition: object.c:2839
Definition: map.h:325
#define P_IS_ALIVE
Definition: map.h:237
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Definition: object.c:4713
const Face * face
Definition: object.h:333
#define FREE_AND_CLEAR(xyz)
Definition: global.h:200
#define FLAG_IS_WOODED
Definition: define.h:331
#define FLAG_NO_PICK
Definition: define.h:239
object * object_find_by_type_and_arch_name(const object *who, int type, const char *name)
Definition: object.c:4056
#define FLAG_WIZPASS
Definition: define.h:315
int32_t move_status
Definition: object.h:393
void object_free_key_values(object *op)
Definition: object.c:718
int16_t level
Definition: object.h:353
#define FLAG_INV_LOCKED
Definition: define.h:330
void fix_object(object *op)
Definition: living.c:1120
float weapon_speed
Definition: object.h:331
struct obj * more
Definition: object.h:295
object * arch_to_object(archetype *at)
Definition: arch.c:571
void object_update_speed(object *op)
Definition: object.c:1086
#define SCRIPT_FIX_NOTHING
Definition: global.h:368
int32_t value
Definition: object.h:352
object * object_get_owner(object *op)
Definition: object.c:568
int8_t magic
Definition: object.h:350
const char * name
Definition: object.h:468
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
#define P_NO_CLERIC
Definition: map.h:238
object * object_find_by_arch_name(const object *who, const char *name)
Definition: object.c:4031
object * object_present_in_ob_by_name(int type, const char *str, const object *op)
Definition: object.c:2924
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:707
void object_remove(object *op)
Definition: object.c:1577
object * map_find_by_type(mapstruct *m, int x, int y, uint8_t type)
Definition: object.c:2866
static int compare_ob_value_lists_one(const object *, const object *)
Definition: object.c:129
#define INS_MAP_LOAD
Definition: object.h:573
object * object_find_by_type2(const object *who, int type1, int type2)
Definition: object.c:3816
int32_t food
Definition: living.h:48
#define FLAG_FREED
Definition: define.h:233
uint32_t count
Definition: player.h:109
static int object_set_value_s(object *, const char *, const char *, int)
Definition: object.c:4165
#define FLAG_IS_TURNABLE
Definition: define.h:256