Crossfire Server, Trunk
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 #ifdef CF_MXE_CROSS_COMPILE
43 # define ffs(word) (__builtin_constant_p (word) \
44  ? __builtin_ffs (word) \
45  : ({ int __cnt, __tmp; \
46  __asm__ __volatile__ \
47  ("bsfl %2,%0\n\t" \
48  "cmovel %1,%0" \
49  : "=&r" (__cnt), "=r" (__tmp) \
50  : "rm" (word), "1" (-1)); \
51  __cnt + 1; }))
52 #endif
53 
54 static int compare_ob_value_lists_one(const object *, const object *);
55 static int compare_ob_value_lists(const object *, const object *);
56 static void permute(int *, int, int);
57 static int object_set_value_s(object *, const char *, const char *, int);
58 static void object_increase_nrof(object *op, uint32_t i);
59 
74 const char *const spell_mapping[SPELL_MAPPINGS] = {
75  "spell_magic_bullet", /* 0 */
76  "spell_small_fireball", /* 1 */
77  "spell_medium_fireball", /* 2 */
78  "spell_large_fireball", /* 3 */
79  "spell_burning_hands", /* 4 */
80  "spell_sm_lightning", /* 5 */
81  "spell_large_lightning", /* 6 */
82  "spell_magic_missile", /* 7 */
83  "spell_create_bomb", /* 8 */
84  "spell_summon_golem", /* 9 */
85  "spell_summon_fire_elemental", /* 10 */
86  "spell_summon_earth_elemental", /* 11 */
87  "spell_summon_water_elemental", /* 12 */
88  "spell_summon_air_elemental", /* 13 */
89  "spell_dimension_door", /* 14 */
90  "spell_create_earth_wall", /* 15 */
91  "spell_paralyze", /* 16 */
92  "spell_icestorm", /* 17 */
93  "spell_magic_mapping", /* 18 */
94  "spell_turn_undead", /* 19 */
95  "spell_fear", /* 20 */
96  "spell_poison_cloud", /* 21 */
97  "spell_wonder", /* 22 */
98  "spell_destruction", /* 23 */
99  "spell_perceive_self", /* 24 */
100  "spell_word_of_recall", /* 25 */
101  "spell_invisible", /* 26 */
102  "spell_invisible_to_undead", /* 27 */
103  "spell_probe", /* 28 */
104  "spell_lg_magic_bullet", /* 29 */
105  "spell_improved_invisibility", /* 30 */
106  "spell_holy_word", /* 31 */
107  "spell_minor_healing", /* 32 */
108  "spell_medium_healing", /* 33 */
109  "spell_major_healing", /* 34 */
110  "spell_heal", /* 35 */
111  "spell_create_food", /* 36 */
112  "spell_earth_to_dust", /* 37 */
113  "spell_armour", /* 38 */
114  "spell_strength", /* 39 */
115  "spell_dexterity", /* 40 */
116  "spell_constitution", /* 41 */
117  "spell_charisma", /* 42 */
118  "spell_create_fire_wall", /* 43 */
119  "spell_create_frost_wall", /* 44 */
120  "spell_protection_from_cold", /* 45 */
121  "spell_protection_from_electricity", /* 46 */
122  "spell_protection_from_fire", /* 47 */
123  "spell_protection_from_poison", /* 48 */
124  "spell_protection_from_slow", /* 49 */
125  "spell_protection_from_paralysis", /* 50 */
126  "spell_protection_from_draining", /* 51 */
127  "spell_protection_from_magic", /* 52 */
128  "spell_protection_from_attack", /* 53 */
129  "spell_levitate", /* 54 */
130  "spell_small_speedball", /* 55 */
131  "spell_large_speedball", /* 56 */
132  "spell_hellfire", /* 57 */
133  "spell_dragonbreath", /* 58 */
134  "spell_large_icestorm", /* 59 */
135  "spell_charging", /* 60 */
136  "spell_polymorph", /* 61 */
137  "spell_cancellation", /* 62 */
138  "spell_confusion", /* 63 */
139  "spell_mass_confusion", /* 64 */
140  "spell_summon_pet_monster", /* 65 */
141  "spell_slow", /* 66 */
142  "spell_regenerate_spellpoints", /* 67 */
143  "spell_cure_poison", /* 68 */
144  "spell_protection_from_confusion", /* 69 */
145  "spell_protection_from_cancellation", /* 70 */
146  "spell_protection_from_depletion", /* 71 */
147  "spell_alchemy", /* 72 */
148  "spell_remove_curse", /* 73 */
149  "spell_remove_damnation", /* 74 */
150  "spell_identify", /* 75 */
151  "spell_detect_magic", /* 76 */
152  "spell_detect_monster", /* 77 */
153  "spell_detect_evil", /* 78 */
154  "spell_detect_curse", /* 79 */
155  "spell_heroism", /* 80 */
156  "spell_aggravation", /* 81 */
157  "spell_firebolt", /* 82 */
158  "spell_frostbolt", /* 83 */
159  "spell_shockwave", /* 84 */
160  "spell_color_spray", /* 85 */
161  "spell_haste", /* 86 */
162  "spell_face_of_death", /* 87 */
163  "spell_ball_lightning", /* 88 */
164  "spell_meteor_swarm", /* 89 */
165  "spell_comet", /* 90 */
166  "spell_mystic_fist", /* 91 */
167  "spell_raise_dead", /* 92 */
168  "spell_resurrection", /* 93 */
169  "spell_reincarnation", /* 94 */
170  NULL, /* 95 spell_immunity_to_cold */
171  NULL, /* 96 spell_immunity_to_electricity */
172  NULL, /* 97 spell_immunity_to_fire */
173  NULL, /* 98 spell_immunity_to_poison */
174  NULL, /* 99 spell_immunity_to_slow */
175  NULL, /* 100 spell_immunity_to_paralysis */
176  NULL, /* 101 spell_immunity_to_draining */
177  NULL, /* 102 spell_immunity_to_magic */
178  NULL, /* 103 spell_immunity_to_attack */
179  "spell_invulnerability", /* 104 */
180  "spell_defense", /* 105 */
181  "spell_rune_of_fire", /* 106 */
182  "spell_rune_of_frost", /* 107 */
183  "spell_rune_of_shocking", /* 108 */
184  "spell_rune_of_blasting", /* 109 */
185  "spell_rune_of_death", /* 110 */
186  "spell_marking_rune", /* 111 */
187  "spell_build_director", /* 112 */
188  "spell_create_pool_of_chaos", /* 113 */
189  "spell_build_bullet_wall", /* 114 */
190  "spell_build_lightning_wall", /* 115 */
191  "spell_build_fireball_wall", /* 116 */
192  "spell_magic_rune", /* 117 */
193  "spell_rune_of_magic_drain", /* 118 */
194  "spell_antimagic_rune", /* 119 */
195  "spell_rune_of_transference", /* 120 */
196  "spell_transference", /* 121 */
197  "spell_magic_drain", /* 122 */
198  "spell_counterspell", /* 123 */
199  "spell_disarm", /* 124 */
200  "spell_cure_confusion", /* 125 */
201  "spell_restoration", /* 126 */
202  NULL, /* 127 */ /* Was summon evil monster */
203  "spell_counterwall", /* 128 */
204  "spell_cause_light_wounds", /* 129 */
205  "spell_cause_medium_wounds", /* 130 */
206  "spell_cause_heavy_wounds", /* 131 */
207  "spell_charm_monsters", /* 132 */
208  "spell_banishment", /* 133 */
209  "spell_create_missile", /* 134 */
210  "spell_show_invisible", /* 135 */
211  "spell_xray", /* 136 */
212  "spell_pacify", /* 137 */
213  "spell_summon_fog", /* 138 */
214  "spell_steambolt", /* 139 */
215  "spell_command_undead", /* 140 */
216  "spell_holy_orb", /* 141 */
217  "spell_summon_avatar", /* 142 */
218  "spell_holy_possession", /* 143 */
219  "spell_bless", /* 144 */
220  "spell_curse", /* 145 */
221  "spell_regeneration", /* 146 */
222  "spell_consecrate", /* 147 */
223  "spell_summon_cult_monsters", /* 148 */
224  "spell_cause_critical_wounds", /* 149 */
225  "spell_holy_wrath", /* 150 */
226  "spell_retributive_strike", /* 151 */
227  "spell_finger_of_death", /* 152 */
228  "spell_insect_plague", /* 153 */
229  "spell_call_holy_servant", /* 154 */
230  "spell_wall_of_thorns", /* 155 */
231  "spell_staff_to_snake", /* 156 */
232  "spell_light", /* 157 */
233  "spell_darkness", /* 158 */
234  "spell_nightfall", /* 159 */
235  "spell_daylight", /* 160 */
236  "spell_sunspear", /* 161 */
237  "spell_faery_fire", /* 162 */
238  "spell_cure_blindness", /* 163 */
239  "spell_dark_vision", /* 164 */
240  "spell_bullet_swarm", /* 165 */
241  "spell_bullet_storm", /* 166 */
242  "spell_cause_many_wounds", /* 167 */
243  "spell_small_snowstorm", /* 168 */
244  "spell_medium_snowstorm", /* 169 */
245  "spell_large_snowstorm", /* 170 */
246  "spell_cure_disease", /* 171 */
247  "spell_cause_red_death", /* 172 */
248  "spell_cause_flu", /* 173 */
249  "spell_cause_black_death", /* 174 */
250  "spell_cause_leprosy", /* 175 */
251  "spell_cause_smallpox", /* 176 */
252  "spell_cause_white_death", /* 177 */
253  "spell_cause_anthrax", /* 178 */
254  "spell_cause_typhoid", /* 179 */
255  "spell_mana_blast", /* 180 */
256  "spell_small_manaball", /* 181 */
257  "spell_medium_manaball", /* 182 */
258  "spell_large_manaball", /* 183 */
259  "spell_manabolt", /* 184 */
260  "spell_dancing_sword", /* 185 */
261  "spell_animate_weapon", /* 186 */
262  "spell_cause_cold", /* 187 */
263  "spell_divine_shock", /* 188 */
264  "spell_windstorm", /* 189 */
265  "spell_sanctuary", /* 190 */
266  "spell_peace", /* 191 */
267  "spell_spiderweb", /* 192 */
268  "spell_conflict", /* 193 */
269  "spell_rage", /* 194 */
270  "spell_forked_lightning", /* 195 */
271  "spell_poison_fog", /* 196 */
272  "spell_flaming_aura", /* 197 */
273  "spell_vitriol", /* 198 */
274  "spell_vitriol_splash", /* 199 */
275  "spell_iron_skin", /* 200 */
276  "spell_wrathful_eye", /* 201 */
277  "spell_town_portal", /* 202 */
278  "spell_missile_swarm", /* 203 */
279  "spell_cause_rabies", /* 204 */
280  "spell_glyph", /* 205 */
281 };
282 
283 #ifdef MEMORY_DEBUG
284 int nroffreeobjects = 0;
285 int nrofallocobjects = 0;
286 #undef OBJ_EXPAND
287 #define OBJ_EXPAND 1
288 #else
289 static object objarray[STARTMAX];
292 #endif
293 
294 object *objects;
295 static object *free_objects;
296 object *active_objects;
300  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,
301  0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -3, -3, -3, -3, -2, -1
302 };
303 
306  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,
307  -3, -3, -3, -3, -2, -1, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3
308 };
309 
312  0, 9, 10, 13, 14, 17, 18, 21, 22, 25, 26, 27, 30, 31, 32, 33, 36, 37, 39, 39, 42, 43, 44, 45,
313  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
314 };
315 
318  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,
319  1, 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8
320 };
321 
327 void init_objects(void) {
328  /* Initialize all objects: */
329  objects = NULL;
330  active_objects = NULL;
331 
332 #ifdef MEMORY_DEBUG
333  free_objects = NULL;
334 #else
336  objarray[0].prev = NULL,
337  objarray[0].next = &objarray[1],
340  for (int i = 1; i < STARTMAX-1; i++) {
341  objarray[i].next = &objarray[i+1];
342  objarray[i].prev = &objarray[i-1];
345  }
346  objarray[STARTMAX-1].next = NULL;
350 #endif
351 }
352 
363 static int compare_ob_value_lists_one(const object *wants, const object *has) {
364  key_value *wants_field;
365 
366  /* n-squared behaviour (see object_get_key_value()), but I'm hoping both
367  * objects with lists are rare, and lists stay short. If not, use a
368  * different structure or at least keep the lists sorted...
369  */
370 
371  /* For each field in wants, */
372  for (wants_field = wants->key_values; wants_field != NULL; wants_field = wants_field->next) {
373  key_value *has_field;
374 
375  /* Look for a field in has with the same key. */
376  has_field = object_get_key_value(has, wants_field->key);
377 
378  if (has_field == NULL) {
379  /* No field with that name. */
380  return FALSE;
381  }
382 
383  /* Found the matching field. */
384  if (has_field->value != wants_field->value) {
385  /* Values don't match, so this half of the comparison is false. */
386  return FALSE;
387  }
388 
389  /* If we get here, we found a match. Now for the next field in wants. */
390  }
391 
392  /* If we get here, every field in wants has a matching field in has. */
393  return TRUE;
394 }
395 
404 static int compare_ob_value_lists(const object *ob1, const object *ob2) {
405  /* However, there may be fields in has which aren't partnered in wants,
406  * so we need to run the comparison *twice*. :(
407  */
409 }
410 
433 int object_can_merge(object *ob1, object *ob2) {
434  /* A couple quicksanity checks */
435  if (ob1 == ob2 || ob1->type != ob2->type)
436  return 0;
437 
438  if (ob1->speed != ob2->speed)
439  return 0;
440  /* Note sure why the following is the case - either the object has to
441  * be animated or have a very low speed. Is this an attempted monster
442  * check?
443  */
444  /*TODO is this check really needed?*/
445  if (!QUERY_FLAG(ob1, FLAG_ANIMATE) && FABS((ob1)->speed) > MIN_ACTIVE_SPEED)
446  return 0;
447 
448  /* Do not merge objects if nrof would overflow. We use 1UL<<31 since that
449  * value could not be stored in a int32_t (which unfortunately sometimes is
450  * used to store nrof).
451  */
452  if (ob1->nrof+ob2->nrof >= 1UL<<31)
453  return 0;
454 
455  /* This is really a spellbook check - really, we should
456  * check all objects in the inventory.
457  */
458  /*TODO is this check really needed?*/
459  if (ob1->inv || ob2->inv) {
460  /* if one object has inventory but the other doesn't, not equiv */
461  if ((ob1->inv && !ob2->inv) || (ob2->inv && !ob1->inv))
462  return 0;
463 
464  /* Now check to see if the two inventory objects could merge */
465  if (!object_can_merge(ob1->inv, ob2->inv))
466  return 0;
467 
468  /* inventory ok - still need to check rest of this object to see
469  * if it is valid.
470  */
471  }
472 
473  /* If the objects have been identified, set the BEEN_APPLIED flag.
474  * This is to the comparison of the flags below will be OK. We
475  * just can't ignore the been applied or identified flags, as they
476  * are not equal - just if it has been identified, the been_applied
477  * flags lose any meaning.
478  */
479 
480  /*TODO is this hack on BEEN_APPLIED really needed? */
483 
486 
487 
488  /* Note: FLAG_INV_LOCKED is ignored for merging purposes */
489  if ((ob1->arch != ob2->arch)
490  || (ob1->flags[0] != ob2->flags[0])
491  || (ob1->flags[1] != ob2->flags[1])
492  || (ob1->flags[2] != ob2->flags[2])
493  || ((ob1->flags[3]&~0x84) != (ob2->flags[3]&~0x84)) /* ignore CLIENT_SENT and FLAG_OBJ_ORIGINAL */
494  || (ob1->name != ob2->name)
495  || (ob1->title != ob2->title)
496  || (ob1->msg != ob2->msg)
497  || (ob1->weight != ob2->weight)
498  || (ob1->item_power != ob2->item_power)
499  || (memcmp(&ob1->resist, &ob2->resist, sizeof(ob1->resist)) != 0)
500  || (memcmp(&ob1->stats, &ob2->stats, sizeof(ob1->stats)) != 0)
501  || (ob1->attacktype != ob2->attacktype)
502  || (ob1->magic != ob2->magic)
503  || (ob1->slaying != ob2->slaying)
504  || (ob1->skill != ob2->skill)
505  || (ob1->value != ob2->value)
506  || (ob1->animation != ob2->animation)
507  || (ob1->client_type != ob2->client_type)
508  || (ob1->materialname != ob2->materialname)
509  || (ob1->lore != ob2->lore)
510  || (ob1->subtype != ob2->subtype)
511  || (ob1->move_type != ob2->move_type)
512  || (ob1->move_block != ob2->move_block)
513  || (ob1->move_allow != ob2->move_allow)
514  || (ob1->move_on != ob2->move_on)
515  || (ob1->move_off != ob2->move_off)
516  || (ob1->move_slow != ob2->move_slow)
517  || (ob1->move_slow_penalty != ob2->move_slow_penalty)
518  || (ob1->map_layer != ob2->map_layer))
519  return 0;
520 
521  /* Don't merge objects that are applied. With the new 'body' code,
522  * it is possible for most any character to have more than one of
523  * some items equipped, and we don't want those to merge.
524  */
526  return 0;
527 
528  if (ob1->key_values != NULL || ob2->key_values != NULL) {
529  /* At least one of these has key_values. */
530  if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) {
531  /* One has fields, but the other one doesn't. */
532  return 0;
533  } else {
534  if (!compare_ob_value_lists(ob1, ob2)) {
535  return 0;
536  }
537  }
538  }
539 
540  /*TODO should this really be limited to scrolls?*/
541  switch (ob1->type) {
542  case SCROLL:
543  if (ob1->level != ob2->level)
544  return 0;
545  break;
546  }
547 
548  /* Don't merge items with differing custom names. */
549  if (ob1->custom_name != ob2->custom_name)
550  return 0;
551 
552  /* Everything passes, must be OK. */
553  return 1;
554 }
555 
571 /* TODO should check call this this are made a place where we really need reevaluaton of whole tree */
572 signed long object_sum_weight(object *op) {
573  signed long sum;
574 
575  sum = 0;
577  if (inv->inv)
579  sum += inv->carrying+inv->weight*NROF(inv);
580  } FOR_INV_FINISH();
581  if (op->type == CONTAINER && op->stats.Str)
582  sum = (sum*(100-op->stats.Str))/100;
583  op->carrying = sum;
584  return sum;
585 }
586 
594 object *object_get_env_recursive(object *op) {
595  while (op->env != NULL)
596  op = op->env;
597  return op;
598 }
599 
611 object *object_get_player_container(object *op) {
612  for (; op != NULL && op->type != PLAYER; op = op->env)
613  /*TODO this is patching the structure on the flight as side effect. Shoudln't be needed in clean code */
614  if (op->env == op)
615  op->env = NULL;
616  return op;
617 }
618 
628 static const object *object_get_owner_const(const object *op) {
629  if (op->owner == NULL)
630  return NULL;
631 
632  if (!QUERY_FLAG(op->owner, FLAG_FREED)
633  && !QUERY_FLAG(op->owner, FLAG_REMOVED)
634  && op->owner->count == op->ownercount)
635  return op->owner;
636 
637  LOG(llevError, "Warning, no owner found\n");
638  return NULL;
639 }
640 
649 void object_dump(const object *op, StringBuffer *sb) {
650  if (op == NULL) {
651  stringbuffer_append_string(sb, "[NULL pointer]");
652  return;
653  }
654 
655  /* object *tmp;*/
656 
657  if (op->arch != NULL) {
658  const object *owner;
659 
660  stringbuffer_append_string(sb, "arch ");
661  stringbuffer_append_string(sb, op->arch->name ? op->arch->name : "(null)");
662  stringbuffer_append_string(sb, "\n");
663 
664  if (op->artifact != NULL) {
665  stringbuffer_append_string(sb, "artifact ");
666  stringbuffer_append_string(sb, op->artifact);
667  stringbuffer_append_string(sb, "\n");
668  }
669 
671  if (op->more) {
672  stringbuffer_append_printf(sb, "more %u\n", op->more->count);
673  }
674  if (op->head) {
675  stringbuffer_append_printf(sb, "head %u\n", op->head->count);
676  }
677  if (op->env) {
678  stringbuffer_append_printf(sb, "env %u\n", op->env->count);
679  }
680  if (op->inv) {
681  stringbuffer_append_printf(sb, "inv %u\n", op->inv->count);
682  }
683  if (op->enemy) {
684  stringbuffer_append_printf(sb, "enemy %u\n", op->enemy->count);
685  }
686  if (op->attacked_by) {
687  stringbuffer_append_printf(sb, "attacked_by %u\n", op->attacked_by->count);
688  }
689  owner = object_get_owner_const(op);
690  if (owner != NULL) {
691  stringbuffer_append_printf(sb, "owner %u\n", owner->count);
692  }
693  stringbuffer_append_string(sb, "end\n");
694  } else {
695  stringbuffer_append_string(sb, "Object ");
696  stringbuffer_append_string(sb, op->name == NULL ? "(null)" : op->name);
697  stringbuffer_append_string(sb, "\nend\n");
698  }
699 }
700 
708 void object_dump_all(void) {
709  object *op;
710 
711  for (op = objects; op != NULL; op = op->next) {
712  StringBuffer *sb;
713  char *diff;
714 
715  sb = stringbuffer_new();
716  object_dump(op, sb);
717  diff = stringbuffer_finish(sb);
718  LOG(llevDebug, "Object %u\n:%s\n", op->count, diff);
719  free(diff);
720  }
721 }
722 
732  object *op;
733 
734  for (op = objects; op != NULL; op = op->next)
735  if (op->count == i)
736  break;
737  return op;
738 }
739 
751 object *object_find_by_name_global(const char *str) {
752  const char *name = add_string(str);
753  object *op;
754 
755  for (op = objects; op != NULL; op = op->next)
756  if (op->name == name)
757  break;
758  free_string(name);
759  return op;
760 }
761 
772 #ifdef MEMORY_DEBUG
773  object *op, *next;
774 
775  for (op = free_objects; op != NULL; ) {
776  next = op->next;
777  free(op);
779  nroffreeobjects--;
780  op = next;
781  }
782  free_objects = NULL;
783 
784  for (op = objects; op != NULL; ) {
785  next = op->next;
786  if (!QUERY_FLAG(op, FLAG_FREED)) {
787  LOG(llevDebug, "non freed object: %s\n", op->name);
788  }
789  op = next;
790  }
791 #endif
792 
793  LOG(llevDebug, "%d allocated objects, %d free objects, STARMAX=%d\n", nrofallocobjects, nroffreeobjects, STARTMAX);
794 }
795 
808 object *object_get_owner(object *op) {
809  if (op->owner == NULL)
810  return NULL;
811 
812  if (!QUERY_FLAG(op->owner, FLAG_FREED)
813  && !QUERY_FLAG(op->owner, FLAG_REMOVED)
814  && op->owner->count == op->ownercount)
815  return op->owner;
816 
818  return NULL;
819 }
820 
827 void object_clear_owner(object *op) {
828  if (!op)
829  return;
830 
831  op->owner = NULL;
832  op->ownercount = 0;
833 }
834 
844 void object_set_owner(object *op, object *owner) {
845  /* Assign temp to something, so it can't accidentally be NULL */
846  object *tmp = owner;
847  if (op == NULL)
848  return;
849  if (owner == NULL) {
851  return;
852  }
853 
854  /* next line added to allow objects which own objects */
855  /* Add a check for ownercounts in here, as I got into an endless loop
856  * with the fireball owning a poison cloud which then owned the
857  * fireball. I believe that was caused by one of the objects getting
858  * freed and then another object replacing it. Since the ownercounts
859  * didn't match, this check is valid and I believe that cause is valid.
860  */
861  /*
862  * if owner is NULL, function will have already returned,
863  * so loop should still function as before.
864  */
865  while (tmp) {
866  tmp = object_get_owner(owner);
867  if (tmp)
868  owner = tmp;
869  }
870 
871  /* must not cause owner cycles */
872  assert(op != owner);
873 
874  if (op->owner != NULL)
876 
877  op->owner = owner;
878  op->ownercount = owner->count;
879 }
880 
897 void object_copy_owner(object *op, object *clone) {
898  object *owner = object_get_owner(clone);
899  if (owner == NULL) {
900  /* players don't have owners - they own themselves. Update
901  * as appropriate.
902  */
903  /*TODO owner=self is dangerous and should be avoided*/
904  if (clone->type != PLAYER)
905  return;
906  owner = clone;
907  }
908  object_set_owner(op, owner);
909 }
910 
919 void object_set_enemy(object *op, object *enemy) {
920  if (op->enemy == enemy) {
921  return;
922  }
923 
924 #if 0
925  if (op->type != PLAYER) {
926  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);
927  }
928 #endif
929  op->enemy = enemy;
930 }
931 
938 void object_reset(object *op) {
939  op->name = NULL;
940  op->name_pl = NULL;
941  op->title = NULL;
942  op->race = NULL;
943  op->slaying = NULL;
944  op->skill = NULL;
945  op->msg = NULL;
946  op->materialname = NULL;
947  op->lore = NULL;
948  object_clear(op);
949 }
950 
958 void object_free_key_values(object *op) {
959  key_value *i;
960  key_value *next = NULL;
961 
962  if (op->key_values == NULL)
963  return;
964 
965  for (i = op->key_values; i != NULL; i = next) {
966  /* Store next *first*. */
967  next = i->next;
968 
969  if (i->key)
971  if (i->value)
973  i->next = NULL;
974  free(i);
975  }
976 
977  op->key_values = NULL;
978 }
979 
987 void object_clear(object *op) {
988  /*TODO this comment must be investigated*/
989  /* redo this to be simpler/more efficient. Was also seeing
990  * crashes in the old code. Move this to the top - am
991  * seeing periodic crashes in this code, and would like to have
992  * as much info available as possible (eg, object name).
993  */
996 
997  /* the memset will clear all these values for us, but we need
998  * to reduce the refcount on them.
999  */
1000  if (op->name != NULL)
1001  FREE_AND_CLEAR_STR(op->name);
1002  if (op->name_pl != NULL)
1003  FREE_AND_CLEAR_STR(op->name_pl);
1004  if (op->title != NULL)
1005  FREE_AND_CLEAR_STR(op->title);
1006  if (op->race != NULL)
1007  FREE_AND_CLEAR_STR(op->race);
1008  if (op->slaying != NULL)
1009  FREE_AND_CLEAR_STR(op->slaying);
1010  if (op->skill != NULL)
1011  FREE_AND_CLEAR_STR(op->skill);
1012  if (op->msg != NULL)
1013  FREE_AND_CLEAR_STR(op->msg);
1014  if (op->lore != NULL)
1015  FREE_AND_CLEAR_STR(op->lore);
1016  if (op->materialname != NULL)
1017  FREE_AND_CLEAR_STR(op->materialname);
1018 
1019  /* Remove object from friendly list if needed. */
1020  if (QUERY_FLAG(op, FLAG_FRIENDLY))
1022 
1023  memset((void *)((char *)op+offsetof(object, name)), 0, sizeof(object)-offsetof(object, name));
1024  /* Below here, we clear things that are not done by the memset,
1025  * or set default values that are not zero.
1026  */
1027  /* This is more or less true */
1029 
1030 
1031  op->contr = NULL;
1032  op->below = NULL;
1033  op->above = NULL;
1034  op->inv = NULL;
1035  op->container = NULL;
1036  op->env = NULL;
1037  op->more = NULL;
1038  op->head = NULL;
1039  op->map = NULL;
1040  op->active_next = NULL;
1041  op->active_prev = NULL;
1042  /* What is not cleared is next, prev, and count */
1043 
1044  op->expmul = 1.0;
1045  op->face = blank_face;
1046  op->attacked_by_count = -1;
1047  if (settings.casting_time)
1048  op->casting_time = -1;
1049 }
1050 
1064 void object_copy(const object *src_ob, object *dest_ob) {
1065  int is_freed = QUERY_FLAG(dest_ob, FLAG_FREED), is_removed = QUERY_FLAG(dest_ob, FLAG_REMOVED);
1066 
1067  /* Decrement the refcounts, but don't bother zeroing the fields;
1068  they'll be overwritten by memcpy. */
1069  if (dest_ob->artifact != NULL)
1070  free_string(dest_ob->artifact);
1071  if (dest_ob->name != NULL)
1072  free_string(dest_ob->name);
1073  if (dest_ob->name_pl != NULL)
1074  free_string(dest_ob->name_pl);
1075  if (dest_ob->anim_suffix != NULL)
1076  free_string(dest_ob->anim_suffix);
1077  if (dest_ob->title != NULL)
1078  free_string(dest_ob->title);
1079  if (dest_ob->race != NULL)
1080  free_string(dest_ob->race);
1081  if (dest_ob->slaying != NULL)
1082  free_string(dest_ob->slaying);
1083  if (dest_ob->skill != NULL)
1084  free_string(dest_ob->skill);
1085  if (dest_ob->msg != NULL)
1086  free_string(dest_ob->msg);
1087  if (dest_ob->lore != NULL)
1088  free_string(dest_ob->lore);
1089  if (dest_ob->materialname != NULL)
1090  free_string(dest_ob->materialname);
1091  if (dest_ob->custom_name != NULL)
1092  free_string(dest_ob->custom_name);
1093  if (dest_ob->spell_tags != NULL)
1094  FREE_AND_CLEAR(dest_ob->spell_tags);
1095 
1096  /* Basically, same code as from object_clear() */
1097 
1098  object_free_key_values(dest_ob);
1099  free_dialog_information(dest_ob);
1100 
1101  /* Copy all attributes below name (name included). */
1102  (void)memcpy((void *)((char *)dest_ob+offsetof(object, name)),
1103  (void *)((char *)src_ob+offsetof(object, name)),
1104  sizeof(object)-offsetof(object, name));
1105 
1106  if (is_freed)
1107  SET_FLAG(dest_ob, FLAG_FREED);
1108  if (is_removed)
1109  SET_FLAG(dest_ob, FLAG_REMOVED);
1110  if (dest_ob->artifact != NULL)
1111  add_refcount(dest_ob->artifact);
1112  if (dest_ob->name != NULL)
1113  add_refcount(dest_ob->name);
1114  if (dest_ob->name_pl != NULL)
1115  add_refcount(dest_ob->name_pl);
1116  if (dest_ob->anim_suffix != NULL)
1117  add_refcount(dest_ob->anim_suffix);
1118  if (dest_ob->title != NULL)
1119  add_refcount(dest_ob->title);
1120  if (dest_ob->race != NULL)
1121  add_refcount(dest_ob->race);
1122  if (dest_ob->slaying != NULL)
1123  add_refcount(dest_ob->slaying);
1124  if (dest_ob->skill != NULL)
1125  add_refcount(dest_ob->skill);
1126  if (dest_ob->lore != NULL)
1127  add_refcount(dest_ob->lore);
1128  if (dest_ob->msg != NULL)
1129  add_refcount(dest_ob->msg);
1130  if (dest_ob->custom_name != NULL)
1131  add_refcount(dest_ob->custom_name);
1132  if (dest_ob->materialname != NULL)
1133  add_refcount(dest_ob->materialname);
1134 
1135  if (dest_ob->spell_tags != NULL) {
1136  dest_ob->spell_tags = malloc(sizeof(tag_t)*SPELL_TAG_SIZE);
1137  memcpy(dest_ob->spell_tags, src_ob->spell_tags, sizeof(tag_t)*SPELL_TAG_SIZE);
1138  }
1139 
1140  /* If archetype is a temporary one, we need to update reference count, because
1141  * that archetype will be freed by object_free_drop_inventory() when the last object is removed.
1142  */
1143  if (dest_ob->arch != NULL) {
1144  if (dest_ob->arch->reference_count > 0)
1145  dest_ob->arch->reference_count++;
1146  }
1147 
1148  if (src_ob->speed < 0)
1149  dest_ob->speed_left = src_ob->speed_left-RANDOM()%200/100.0;
1150 
1151  /* Copy over key_values, if any. */
1152  if (src_ob->key_values != NULL) {
1153  key_value *tail = NULL;
1154  key_value *i;
1155 
1156  dest_ob->key_values = NULL;
1157 
1158  for (i = src_ob->key_values; i != NULL; i = i->next) {
1159  key_value *new_link = malloc(sizeof(key_value));
1160 
1161  new_link->next = NULL;
1162  new_link->key = add_refcount(i->key);
1163  if (i->value)
1164  new_link->value = add_refcount(i->value);
1165  else
1166  new_link->value = NULL;
1167 
1168  /* Try and be clever here, too. */
1169  if (dest_ob->key_values == NULL) {
1170  dest_ob->key_values = new_link;
1171  tail = new_link;
1172  } else {
1173  tail->next = new_link;
1174  tail = new_link;
1175  }
1176  }
1177  }
1178 
1179  /* This way, dialog information will be parsed again when/if needed. */
1180  CLEAR_FLAG(dest_ob, FLAG_DIALOG_PARSED);
1181 
1182  object_update_speed(dest_ob);
1183 }
1184 
1194 void object_copy_with_inv(const object *src_ob, object *dest_ob) {
1195  object_copy(src_ob, dest_ob);
1196  FOR_INV_PREPARE(src_ob, walk) {
1197  object *tmp;
1198 
1199  tmp = object_new();
1200  object_copy_with_inv(walk, tmp);
1201  object_insert_in_ob(tmp, dest_ob);
1202  } FOR_INV_FINISH();
1203 }
1204 
1205 #ifndef MEMORY_DEBUG
1206 
1213 static void expand_objects(void) {
1214  int i;
1215  object *new;
1216 
1217  new = (object *)CALLOC(OBJ_EXPAND, sizeof(object));
1218 
1219  if (new == NULL)
1221  free_objects = new;
1222  new[0].prev = NULL;
1223  new[0].next = &new[1],
1224  SET_FLAG(&new[0], FLAG_REMOVED);
1225  SET_FLAG(&new[0], FLAG_FREED);
1226 
1227  for (i = 1; i < OBJ_EXPAND-1; i++) {
1228  new[i].next = &new[i+1],
1229  new[i].prev = &new[i-1],
1230  SET_FLAG(&new[i], FLAG_REMOVED);
1231  SET_FLAG(&new[i], FLAG_FREED);
1232  }
1233  new[OBJ_EXPAND-1].prev = &new[OBJ_EXPAND-2],
1234  new[OBJ_EXPAND-1].next = NULL,
1235  SET_FLAG(&new[OBJ_EXPAND-1], FLAG_REMOVED);
1236  SET_FLAG(&new[OBJ_EXPAND-1], FLAG_FREED);
1237 
1240 }
1241 #endif
1242 
1255 object *object_new(void) {
1256  object *op;
1257 #ifdef MEMORY_DEBUG
1258  /* FIXME: However this doesn't work since object_free() sometimes add
1259  * objects back to the free_objects linked list, and some functions mess
1260  * with the object after return of object_free(). This is bad and should be
1261  * fixed. But it would need fairly extensive changes and a lot of debugging.
1262  */
1263  op = calloc(1, sizeof(object));
1264  if (op == NULL)
1266 #else
1267  if (free_objects == NULL) {
1268  expand_objects();
1269  }
1270  op = free_objects;
1271  if (!QUERY_FLAG(op, FLAG_FREED)) {
1272  LOG(llevError, "Fatal: Getting busy object.\n");
1273 #ifdef MANY_CORES
1274  abort();
1275 #endif
1276  }
1277  free_objects = op->next;
1278  if (free_objects != NULL)
1279  free_objects->prev = NULL;
1280  nroffreeobjects--;
1281 #endif
1282  op->count = ++ob_count;
1283  op->name = NULL;
1284  op->name_pl = NULL;
1285  op->title = NULL;
1286  op->race = NULL;
1287  op->slaying = NULL;
1288  op->skill = NULL;
1289  op->lore = NULL;
1290  op->msg = NULL;
1291  op->materialname = NULL;
1292  op->next = objects;
1293  op->prev = NULL;
1294  op->active_next = NULL;
1295  op->active_prev = NULL;
1296  op->spell_tags = NULL;
1297  if (objects != NULL)
1298  objects->prev = op;
1299  objects = op;
1300  object_clear(op);
1302  return op;
1303 }
1304 
1314  if (op->animation == 0 || !QUERY_FLAG(op, FLAG_IS_TURNABLE))
1315  return;
1316  animate_object(op, op->direction);
1317 }
1318 
1330 void object_update_speed(object *op) {
1331  /* FIXME what the hell is this crappy hack?*/
1332  extern int arch_init;
1333 
1334  /* No reason putting the archetypes objects on the speed list,
1335  * since they never really need to be updated.
1336  */
1337 
1338  if (QUERY_FLAG(op, FLAG_FREED) && op->speed) {
1339  LOG(llevError, "Object %s is freed but has speed.\n", op->name);
1340 #ifdef MANY_CORES
1341  abort();
1342 #else
1343  op->speed = 0;
1344 #endif
1345  }
1346  if (arch_init) {
1347  return;
1348  }
1349  if (FABS(op->speed) > MIN_ACTIVE_SPEED) {
1350  /* If already on active list, don't do anything */
1351  /* TODO this check can probably be simplified a lot */
1352  if (op->active_next || op->active_prev || op == active_objects)
1353  return;
1354 
1355  /* process_events() expects us to insert the object at the beginning
1356  * of the list. */
1357  op->active_next = active_objects;
1358  if (op->active_next != NULL)
1359  op->active_next->active_prev = op;
1360  active_objects = op;
1361  } else {
1363  }
1364 }
1365 
1379  /* If not on the active list, nothing needs to be done */
1380  if (!op->active_next && !op->active_prev && op != active_objects)
1381  return;
1382 
1383  if (op->active_prev == NULL) {
1384  active_objects = op->active_next;
1385  if (op->active_next != NULL)
1386  op->active_next->active_prev = NULL;
1387  } else {
1388  op->active_prev->active_next = op->active_next;
1389  if (op->active_next)
1390  op->active_next->active_prev = op->active_prev;
1391  }
1392  op->active_next = NULL;
1393  op->active_prev = NULL;
1394 }
1395 
1420 void object_update(object *op, int action) {
1421  int update_now = 0, flags;
1422  MoveType move_on, move_off, move_block, move_slow;
1423  object *pl;
1424 
1425  if (op == NULL) {
1426  /* this should never happen */
1427  LOG(llevDebug, "object_update() called for NULL object.\n");
1428  return;
1429  }
1430 
1431  if (op->env != NULL) {
1432  /* Animation is currently handled by client, so nothing
1433  * to do in this case.
1434  */
1435  return;
1436  }
1437 
1438  /* If the map is saving, don't do anything as everything is
1439  * going to get freed anyways.
1440  */
1441  if (!op->map || op->map->in_memory == MAP_SAVING)
1442  return;
1443 
1444  /* make sure the object is within map boundaries */
1445  if (op->x < 0 || op->x >= MAP_WIDTH(op->map)
1446  || op->y < 0 || op->y >= MAP_HEIGHT(op->map)) {
1447  LOG(llevError, "object_update() called for object out of map!\n");
1448 #ifdef MANY_CORES
1449  abort();
1450 #endif
1451  return;
1452  }
1453 
1454  flags = GET_MAP_FLAGS(op->map, op->x, op->y);
1455  SET_MAP_FLAGS(op->map, op->x, op->y, flags|P_NEED_UPDATE);
1456  move_slow = GET_MAP_MOVE_SLOW(op->map, op->x, op->y);
1457  move_on = GET_MAP_MOVE_ON(op->map, op->x, op->y);
1458  move_block = GET_MAP_MOVE_BLOCK(op->map, op->x, op->y);
1459  move_off = GET_MAP_MOVE_OFF(op->map, op->x, op->y);
1460 
1461  if (action == UP_OBJ_INSERT) {
1463  update_now = 1;
1464 
1466  update_now = 1;
1467 
1469  update_now = 1;
1470 
1471  if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags&P_IS_ALIVE))
1472  update_now = 1;
1473 
1474  if ((move_on|op->move_on) != move_on)
1475  update_now = 1;
1476  if ((move_off|op->move_off) != move_off)
1477  update_now = 1;
1478  /* This isn't perfect, but I don't expect a lot of objects to
1479  * to have move_allow right now.
1480  */
1481  if (((move_block|op->move_block)&~op->move_allow) != move_block)
1482  update_now = 1;
1483  if ((move_slow|op->move_slow) != move_slow)
1484  update_now = 1;
1485 
1486  if (op->type == PLAYER)
1487  update_now = 1;
1488  /* if the object is being removed, we can't make intelligent
1489  * decisions, because object_remove() can't really pass the object
1490  * that is being removed.
1491  */
1492  } else if (action == UP_OBJ_REMOVE) {
1493  update_now = 1;
1494  } else if (action == UP_OBJ_FACE || action == UP_OBJ_CHANGE) {
1495  /* In addition to sending info to client, need to update space
1496  * information.
1497  */
1498  if (action == UP_OBJ_CHANGE)
1499  update_now = 1;
1500 
1501  /* There is a player on this space - we may need to send an
1502  * update to the client.
1503  * If this object is supposed to be animated by the client,
1504  * nothing to do here - let the client animate it.
1505  * We can't use FLAG_ANIMATE, as that is basically set for
1506  * all objects with multiple faces, regardless if they are animated.
1507  * (levers have it set for example).
1508  */
1509  if (flags&P_PLAYER
1512  pl = GET_MAP_PLAYER(op->map, op->x, op->y);
1513 
1514  /* If update_look is set, we're going to send this entire space
1515  * to the client, so no reason to send face information now.
1516  */
1517  if (!pl->contr->socket.update_look) {
1519  }
1520  }
1521  } else {
1522  LOG(llevError, "object_update called with invalid action: %d\n", action);
1523  }
1524 
1525  if (update_now) {
1527  update_position(op->map, op->x, op->y);
1528  }
1529 
1530  if (op->more != NULL)
1531  object_update(op->more, action);
1532 }
1533 
1547  object_free(ob, 0);
1548 }
1549 
1554 void object_free_inventory(object *ob) {
1555  while (ob->inv) {
1556  object *inv = ob->inv;
1557  object_remove(inv);
1559  }
1560 }
1561 
1578 void object_free(object *ob, int flags) {
1579  if (!QUERY_FLAG(ob, FLAG_REMOVED)) {
1580  StringBuffer *sb;
1581  char *diff;
1582 
1583  LOG(llevError, "Free object called with non removed object\n");
1584  sb = stringbuffer_new();
1585  object_dump(ob, sb);
1586  diff = stringbuffer_finish(sb);
1587  LOG(llevError, "%s", diff);
1588  free(diff);
1589 #ifdef MANY_CORES
1590  abort();
1591 #endif
1592  }
1593  if (QUERY_FLAG(ob, FLAG_FRIENDLY)) {
1594  LOG(llevMonster, "Warning: tried to free friendly object.\n");
1596  }
1597  if (QUERY_FLAG(ob, FLAG_FREED)) {
1598  StringBuffer *sb;
1599  char *diff;
1600 
1601  sb = stringbuffer_new();
1602  object_dump(ob, sb);
1603  diff = stringbuffer_finish(sb);
1604  LOG(llevError, "Trying to free freed object.\n%s\n", diff);
1605  free(diff);
1606  return;
1607  }
1608 
1609  if ((flags & FREE_OBJ_NO_DESTROY_CALLBACK) == 0) {
1611  }
1612 
1613  if (ob->inv) {
1614  /* Only if the space blocks everything do we not process -
1615  * if some form of movemnt is allowed, let objects
1616  * drop on that space.
1617  */
1618  if ((flags & FREE_OBJ_FREE_INVENTORY) != 0
1619  || ob->map == NULL
1620  || ob->map->in_memory != MAP_IN_MEMORY
1621  || (GET_MAP_MOVE_BLOCK(ob->map, ob->x, ob->y) == MOVE_ALL)) {
1622  FOR_INV_PREPARE(ob, op) {
1623  object_remove(op);
1624  object_free(op, flags);
1625  } FOR_INV_FINISH();
1626  } else { /* Put objects in inventory onto this space */
1627  FOR_INV_PREPARE(ob, op) {
1628  object_remove(op);
1629  /* No drop means no drop, including its inventory */
1630  if (QUERY_FLAG(op, FLAG_NO_DROP))
1632  else if (QUERY_FLAG(op, FLAG_STARTEQUIP)
1634  || op->type == RUNE
1635  || op->type == TRAP
1638  else {
1639  object *part;
1640 
1641  /* If it's a multi-tile object, scatter dropped items randomly */
1642  if (ob->more) {
1643  int partcount = 0;
1644  /* Get the number of non-head parts */
1645  for (part = ob; part; part = part->more) {
1646  partcount++;
1647  }
1648  /* Select a random part */
1649  partcount = RANDOM()%partcount;
1650  for (part = ob; partcount > 0; partcount--) {
1651  part = part->more;
1652  }
1653  } else {
1654  part = ob;
1655  }
1656 
1657  if (QUERY_FLAG(op, FLAG_ALIVE)) {
1658  object_insert_to_free_spot_or_free(op, part->map, part->x, part->y, 0, SIZEOFFREE, NULL);
1659  } else {
1660  int f = 0;
1663  object_insert_in_map_at(op, part->map, NULL, f, part->x, part->y); /* Insert in same map as the envir */
1664  }
1665  }
1666  } FOR_INV_FINISH();
1667  }
1668  }
1669 
1670  if (ob->more != NULL) {
1671  object_free(ob->more, flags);
1672  ob->more = NULL;
1673  }
1674 
1675  /* Remove object from the active list */
1676  ob->speed = 0;
1678 
1680  ob->count = 0;
1681 
1682  /* Remove this object from the list of used objects */
1683  if (ob->prev == NULL) {
1684  objects = ob->next;
1685  if (objects != NULL)
1686  objects->prev = NULL;
1687  } else {
1688  ob->prev->next = ob->next;
1689  if (ob->next != NULL)
1690  ob->next->prev = ob->prev;
1691  }
1692 
1693  if (ob->artifact != NULL) FREE_AND_CLEAR_STR(ob->artifact);
1694  if (ob->name != NULL) FREE_AND_CLEAR_STR(ob->name);
1695  if (ob->name_pl != NULL) FREE_AND_CLEAR_STR(ob->name_pl);
1696  if (ob->title != NULL) FREE_AND_CLEAR_STR(ob->title);
1697  if (ob->race != NULL) FREE_AND_CLEAR_STR(ob->race);
1698  if (ob->slaying != NULL) FREE_AND_CLEAR_STR(ob->slaying);
1699  if (ob->skill != NULL) FREE_AND_CLEAR_STR(ob->skill);
1700  if (ob->lore != NULL) FREE_AND_CLEAR_STR(ob->lore);
1701  if (ob->msg != NULL) FREE_AND_CLEAR_STR(ob->msg);
1702  if (ob->materialname != NULL) FREE_AND_CLEAR_STR(ob->materialname);
1703  if (ob->spell_tags) FREE_AND_CLEAR(ob->spell_tags);
1704  FREE_AND_CLEAR_STR_IF(ob->anim_suffix);
1705 
1706  /* Why aren't events freed? */
1708 
1710 
1711  /* Test whether archetype is a temporary one, and if so look whether it should be trashed. */
1712  if (ob->arch && ob->arch->reference_count > 0) {
1713  if (--ob->arch->reference_count == 0) {
1714  free_arch(ob->arch);
1715  }
1716  }
1717 
1718 #ifdef MEMORY_DEBUG
1719  free(ob);
1720 #else
1721  /* Now link it with the free_objects list: */
1722  ob->prev = NULL;
1723  ob->next = free_objects;
1724  if (free_objects != NULL)
1725  free_objects->prev = ob;
1726  free_objects = ob;
1727  nroffreeobjects++;
1728 #endif
1729 }
1730 
1738  int i = 0;
1739  object *tmp = free_objects;
1740 
1741  while (tmp != NULL)
1742  tmp = tmp->next,
1743  i++;
1744  return i;
1745 }
1746 
1754  int i = 0;
1755  object *tmp = objects;
1756 
1757  while (tmp != NULL)
1758  tmp = tmp->next,
1759  i++;
1760  return i;
1761 }
1762 
1770  int i = 0;
1771  object *tmp = active_objects;
1772 
1773  while (tmp != NULL)
1774  tmp = tmp->active_next,
1775  i++;
1776  return i;
1777 }
1778 
1793 void object_sub_weight(object *op, signed long weight) {
1794  while (op != NULL) {
1795  if (op->type == CONTAINER) {
1796  weight = (signed long)(weight*(100-op->stats.Str)/100);
1797  }
1798  op->carrying -= weight;
1799  op = op->env;
1800  }
1801 }
1802 
1819 void object_remove(object *op) {
1820  object *last = NULL;
1821  object *otmp;
1822  tag_t tag;
1823  int check_walk_off;
1824  mapstruct *m;
1825  int16_t x, y;
1826 
1827  if (QUERY_FLAG(op, FLAG_REMOVED)) {
1828  StringBuffer *sb;
1829  char *diff;
1830 
1831  sb = stringbuffer_new();
1832  object_dump(op, sb);
1833  diff = stringbuffer_finish(sb);
1834  LOG(llevError, "Trying to remove removed object.\n%s\n", diff);
1835  free(diff);
1836  abort();
1837  }
1838  if (op->more != NULL)
1839  object_remove(op->more);
1840 
1842 
1843  /*
1844  * In this case, the object to be removed is in someones
1845  * inventory.
1846  */
1847  /* TODO try to call a generic inventory weight adjusting function like object_sub_weight */
1848  if (op->env != NULL) {
1849  player *pl = NULL;
1850 
1851  if (op->nrof)
1852  object_sub_weight(op->env, op->weight*op->nrof);
1853  else
1854  object_sub_weight(op->env, op->weight+op->carrying);
1855 
1856  /* Update in two cases: item is in a player, or in a container the player is looking into. */
1857  if (op->env->contr != NULL && op->head == NULL) {
1858  pl = op->env->contr;
1859  } else if (op->env->type == CONTAINER && QUERY_FLAG(op->env, FLAG_APPLIED)) {
1860 
1861  if (op->env->env && op->env->env->contr)
1862  /* Container is in player's inventory. */
1863  pl = op->env->env->contr;
1864  else if (op->env->map) {
1865  /* Container on map, look above for player. */
1866  object *above = op->env->above;
1867 
1868  while (above && !above->contr)
1869  above = above->above;
1870  if (above)
1871  pl = above->contr;
1872  }
1873  }
1874 
1875  /* NO_FIX_PLAYER is set when a great many changes are being
1876  * made to players inventory. If set, avoiding the call
1877  * to save cpu time.
1878  */
1879  otmp = object_get_player_container(op->env);
1880  if (otmp != NULL
1881  && otmp->contr
1882  && !QUERY_FLAG(otmp, FLAG_NO_FIX_PLAYER))
1883  fix_object(otmp);
1884 
1885  if (op->above != NULL)
1886  op->above->below = op->below;
1887  else
1888  op->env->inv = op->below;
1889 
1890  if (op->below != NULL)
1891  op->below->above = op->above;
1892 
1893  /* we set up values so that it could be inserted into
1894  * the map, but we don't actually do that - it is up
1895  * to the caller to decide what we want to do.
1896  */
1897  op->x = op->env->x;
1898  op->y = op->env->y;
1899  op->ox = op->x;
1900  op->oy = op->y;
1901  op->map = op->env->map;
1902  op->above = NULL;
1903  op->below = NULL;
1904  /* send the delitem before resetting env, so container's contents be may
1905  * refreshed */
1906  if (LOOK_OBJ(op) && pl != NULL)
1907  esrv_del_item(pl, op);
1908  op->env = NULL;
1909  return;
1910  }
1911 
1912  /* If we get here, we are removing it from a map */
1913  if (op->map == NULL)
1914  return;
1915 
1916  if (op->contr != NULL && !op->contr->hidden)
1917  op->map->players--;
1918 
1919  x = op->x;
1920  y = op->y;
1921  m = get_map_from_coord(op->map, &x, &y);
1922 
1923  if (!m) {
1924  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);
1925  abort();
1926  }
1927  if (op->map != m) {
1928  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);
1929  }
1930 
1931  /* link the object above us */
1932  if (op->above)
1933  op->above->below = op->below;
1934  else
1935  SET_MAP_TOP(m, x, y, op->below); /* we were top, set new top */
1936 
1937  /* Relink the object below us, if there is one */
1938  if (op->below) {
1939  op->below->above = op->above;
1940  } else {
1941  /* Nothing below, which means we need to relink map object for this space
1942  * use translated coordinates in case some oddness with map tiling is
1943  * evident
1944  */
1945  /*TODO is this check really needed?*/
1946  if (GET_MAP_OB(m, x, y) != op) {
1947  StringBuffer *sb;
1948  char *diff;
1949 
1950  sb = stringbuffer_new();
1951  object_dump(op, sb);
1952  diff = stringbuffer_finish(sb);
1953  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);
1954  free(diff);
1955 
1956  sb = stringbuffer_new();
1957  object_dump(GET_MAP_OB(m, x, y), sb);
1958  diff = stringbuffer_finish(sb);
1959  LOG(llevError, "%s\n", diff);
1960  free(diff);
1961  }
1962  SET_MAP_OB(m, x, y, op->above); /* goes on above it. */
1963  }
1964  op->above = NULL;
1965  op->below = NULL;
1966 
1967  if (op->map->in_memory == MAP_SAVING)
1968  return;
1969 
1970  tag = op->count;
1971  check_walk_off = !QUERY_FLAG(op, FLAG_NO_APPLY);
1972  FOR_MAP_PREPARE(m, x, y, tmp) {
1973  /* No point updating the players look faces if he is the object
1974  * being removed.
1975  */
1976 
1977  if (tmp->type == PLAYER && tmp != op) {
1978  /* If a container that the player is currently using somehow gets
1979  * removed (most likely destroyed), update the player view
1980  * appropriately.
1981  */
1982  if (tmp->container == op) {
1984  tmp->container = NULL;
1985  }
1986  tmp->contr->socket.update_look = 1;
1987  }
1988  /* See if player moving off should effect something */
1989  if (check_walk_off
1990  && ((op->move_type&tmp->move_off) && (op->move_type&~tmp->move_off&~tmp->move_block) == 0)) {
1991  ob_move_on(tmp, op, NULL);
1992  if (object_was_destroyed(op, tag)) {
1993  LOG(llevError, "BUG: object_remove(): name %s, archname %s destroyed leaving object\n", tmp->name, tmp->arch->name);
1994  }
1995  }
1996 
1997  /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */
1998  if (tmp->above == tmp)
1999  tmp->above = NULL;
2000  last = tmp;
2001  } FOR_MAP_FINISH();
2002  /* last == NULL or there are no objects on this space */
2003  if (last == NULL) {
2004  /* set P_NEED_UPDATE, otherwise update_position will complain. In theory,
2005  * we could preserve the flags (GET_MAP_FLAGS), but update_position figures
2006  * those out anyways, and if there are any flags set right now, they won't
2007  * be correct anyways.
2008  */
2009  SET_MAP_FLAGS(op->map, op->x, op->y, P_NEED_UPDATE);
2010  update_position(op->map, op->x, op->y);
2011  } else
2013 
2014  if (QUERY_FLAG(op, FLAG_BLOCKSVIEW) || (op->glow_radius != 0))
2015  update_all_los(op->map, op->x, op->y);
2016 }
2017 
2031 object *object_merge(object *op, object *top) {
2032  if (!op->nrof)
2033  return NULL;
2034 
2035  if (top == NULL)
2036  for (top = op; top != NULL && top->above != NULL; top = top->above)
2037  ;
2039  if (top == op)
2040  continue;
2041  if (object_can_merge(op, top)) {
2042  object_increase_nrof(top, op->nrof);
2043  /*
2044  * Previous behavior set weight to zero here.
2045  * This, however, caused the object_sub_weight
2046  * call in object_remove to subtract zero weight
2047  * when removing the object. Thus, until inventory
2048  * weight is next recalculated, the object merged
2049  * into another pile added weight in object_increase_nrof
2050  * but did not remove the weight from the original
2051  * instance of itself in object_remove, essentially
2052  * counting for double weight for several minutes.
2053  *
2054  * SilverNexus 2014-05-27
2055  */
2056  object_remove(op);
2058  return top;
2059  }
2061  return NULL;
2062 }
2063 
2080 object *object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y) {
2081  object *tmp;
2082 
2083  op = HEAD(op);
2084  for (tmp = op; tmp; tmp = tmp->more) {
2085  tmp->x = x+tmp->arch->clone.x;
2086  tmp->y = y+tmp->arch->clone.y;
2087  tmp->map = m;
2088  }
2089  return object_insert_in_map(op, m, originator, flag);
2090 }
2091 
2109 void object_merge_spell(object *op, int16_t x, int16_t y) {
2110  int i;
2111 
2112  /* We try to do some merging of spell objects - if something has same owner,
2113  * is same type of spell, and going in the same direction, it is somewhat
2114  * mergable.
2115  *
2116  * If the spell object has an other_arch, don't merge - when the spell
2117  * does something, like explodes, it will use this other_arch, and
2118  * if we merge, there is no easy way to make the correct values be
2119  * set on this new object (values should be doubled, tripled, etc.)
2120  *
2121  * We also care about speed - only process objects that will not be
2122  * active this tick. Without this, the results are incorrect - think
2123  * of a case where tmp would normally get processed this tick, but
2124  * get merges with op, which does not get processed.
2125  */
2126  FOR_MAP_PREPARE(op->map, x, y, tmp) {
2127  if (op->type == tmp->type
2128  && op->subtype == tmp->subtype
2129  && op->direction == tmp->direction
2130  && op->owner == tmp->owner && op->ownercount == tmp->ownercount
2131  && op->range == tmp->range
2132  && op->stats.wc == tmp->stats.wc
2133  && op->level == tmp->level
2134  && op->attacktype == tmp->attacktype
2135  && op->speed == tmp->speed
2136  && !tmp->other_arch
2137  && (tmp->speed_left+tmp->speed) < 0.0
2138  && op != tmp) {
2139  /* Quick test - if one or the other objects already have hash tables
2140  * set up, and that hash bucket contains a value that doesn't
2141  * match what we want to set it up, we won't be able to merge.
2142  * Note that these two if statements are the same, except
2143  * for which object they are checking against. They could
2144  * be merged, but the line wrapping would be large enough
2145  * that IMO it would become difficult to read the different clauses
2146  * so its cleaner just to do 2 statements - MSW
2147  */
2148  if (op->spell_tags
2149  && !OB_SPELL_TAG_MATCH(op, (tag_t)tmp->stats.maxhp)
2150  && OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) != 0)
2151  continue;
2152 
2153  if (tmp->spell_tags
2154  && !OB_SPELL_TAG_MATCH(tmp, (tag_t)op->stats.maxhp)
2155  && OB_SPELL_TAG_HASH(tmp, op->stats.maxhp) != 0)
2156  continue;
2157 
2158  /* If we merge, the data from tmp->spell_tags gets copied into op.
2159  * so we need to make sure that slot isn't filled up.
2160  */
2161  if (tmp->spell_tags
2162  && !OB_SPELL_TAG_MATCH(tmp, (tag_t)tmp->stats.maxhp)
2163  && OB_SPELL_TAG_HASH(tmp, tmp->stats.maxhp) != 0)
2164  continue;
2165 
2166  /* If both objects have spell_tags, we need to see if there are conflicting
2167  * values - if there are, we won't be able to merge then.
2168  */
2169  if (tmp->spell_tags && op->spell_tags) {
2170  int need_copy = 0;
2171 
2172  for (i = 0; i < SPELL_TAG_SIZE; i++) {
2173  /* If the two tag values in the hash are set, but are
2174  * not set to the same value, then these objects
2175  * can not be merged.
2176  */
2177  if (op->spell_tags[i] && tmp->spell_tags[i]
2178  && op->spell_tags[i] != tmp->spell_tags[i]) {
2180  break;
2181  }
2182  /* If one tag is set and the other is not, that is
2183  * fine, but we have to note that we need to copy
2184  * the data in that case.
2185  */
2186  if ((!op->spell_tags[i] && tmp->spell_tags[i])
2187  || (op->spell_tags[i] && !tmp->spell_tags[i])) {
2188  need_copy = 1;
2189  }
2190  }
2191  /* If we did not get through entire array, it means
2192  * we got a conflicting hash, and so we won't be
2193  * able to merge these - just continue processing
2194  * object on this space.
2195  */
2196  if (i <= SPELL_TAG_SIZE)
2197  continue;
2198 
2199  /* Ok - everything checked out - we should be able to
2200  * merge tmp in op. So lets copy the tag data if
2201  * needed. Note that this is a selective copy, as
2202  * we don't want to clear values that may be set in op.
2203  */
2204  if (need_copy) {
2205  for (i = 0; i < SPELL_TAG_SIZE; i++)
2206  if (!op->spell_tags[i]
2207  && tmp->spell_tags[i]
2208  && tmp->spell_tags[i] != (tag_t)op->stats.maxhp)
2209  op->spell_tags[i] = tmp->spell_tags[i];
2210  }
2211  FREE_AND_CLEAR(tmp->spell_tags);
2212  }
2213 
2214  /* if tmp has a spell_tags table, copy it to op and free tmps */
2215  if (tmp->spell_tags && !op->spell_tags) {
2216  op->spell_tags = tmp->spell_tags;
2217  tmp->spell_tags = NULL;
2218 
2219  /* We don't need to keep a copy of our maxhp value
2220  * in the copied over value
2221  */
2222  if (OB_SPELL_TAG_MATCH(op, (tag_t)op->stats.maxhp))
2223  OB_SPELL_TAG_HASH(op, op->stats.maxhp) = 0;
2224  }
2225 
2226  /* For spells to work correctly, we need to record what spell
2227  * tags we've merged in with this effect. This is used
2228  * in ok_to_put_more() to see if a spell effect is already on
2229  * the space.
2230  */
2231  if (op->stats.maxhp != tmp->stats.maxhp) {
2232 #ifdef OBJECT_DEBUG
2233  /* This if statement should never happen - the logic above should
2234  * have prevented it. It is a problem, because by now its possible
2235  * we've destroyed the spell_tags in tmp, so we can't really
2236  * just bail out.
2237  */
2238 
2239  if (op->spell_tags
2240  && OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) != 0
2241  && !OB_SPELL_TAG_MATCH(op, tmp->stats.maxhp)) {
2242  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);
2243  }
2244 #endif
2245  if (!op->spell_tags)
2246  op->spell_tags = calloc(SPELL_TAG_SIZE, sizeof(tag_t));
2247 
2248  OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) = tmp->stats.maxhp;
2249  }
2250 
2252  op->speed_left = MAX(op->speed_left, tmp->speed_left);
2253 
2254  if (tmp->duration != op->duration) {
2255  /* We need to use tmp_dam here because otherwise the
2256  * calculations can overflow the size of stats.dam.
2257  */
2258  int tmp_dam = tmp->stats.dam*(tmp->duration+1)+
2259  op->stats.dam*(op->duration+1);
2260 
2261  op->duration = MAX(op->duration, tmp->duration);
2262  tmp_dam /= op->duration+1;
2263  op->stats.dam = tmp_dam+1;
2264  } else {
2265  /* in this case, duration is the same, so simply adding
2266  * up damage works.
2267  */
2268  op->stats.dam += tmp->stats.dam;
2269  }
2270 
2271  object_remove(tmp);
2273  }
2274  } FOR_MAP_FINISH();
2275 }
2276 
2277 static object *find_insert_pos(object *op, const int flag) {
2278  object *floor = NULL;
2279  /*
2280  * If there are multiple objects on this space, we do some trickier handling.
2281  * We've already dealt with merging if appropriate.
2282  * Generally, we want to put the new object on top. But if
2283  * flag contains INS_ABOVE_FLOOR_ONLY, once we find the last
2284  * floor, we want to insert above that and no further.
2285  * Also, if there are spell objects on this space, we stop processing
2286  * once we get to them. This reduces the need to traverse over all of
2287  * them when adding another one - this saves quite a bit of cpu time
2288  * when lots of spells are cast in one area. Currently, it is presumed
2289  * that flying non pickable objects are spell objects.
2290  */
2291  if (flag&INS_ON_TOP) {
2292  return GET_MAP_TOP(op->map, op->x, op->y);
2293  }
2294  object *last = NULL;
2295  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp) {
2298  floor = tmp;
2299 
2301  && (tmp->move_type&(MOVE_FLY_LOW|MOVE_FLY_HIGH))
2302  && !QUERY_FLAG(tmp, FLAG_IS_FLOOR)) {
2303  /* We insert above tmp, so we want this object below this */
2304  break;
2305  }
2306  last = tmp;
2307  } FOR_MAP_FINISH();
2308  if (flag&INS_ABOVE_FLOOR_ONLY)
2309  return floor;
2310  return last;
2311 }
2312 
2341 object *object_insert_in_map(object *op, mapstruct *m, object *originator, int flag) {
2342  object *tmp, *top, *floor = NULL;
2343  int16_t x, y;
2344 
2345  if (QUERY_FLAG(op, FLAG_FREED)) {
2346  LOG(llevError, "Trying to insert freed object!\n");
2347  return NULL;
2348  }
2349  if (m == NULL) {
2350  StringBuffer *sb;
2351  char *diff;
2352 
2353  sb = stringbuffer_new();
2354  object_dump(op, sb);
2355  diff = stringbuffer_finish(sb);
2356  LOG(llevError, "Trying to insert in null-map!\n%s\n", diff);
2357  free(diff);
2358  return op;
2359  }
2360  if (out_of_map(m, op->x, op->y)) {
2361  StringBuffer *sb;
2362  char *diff;
2363 
2364  sb = stringbuffer_new();
2365  object_dump(op, sb);
2366  diff = stringbuffer_finish(sb);
2367  LOG(llevError, "Trying to insert object outside the map.\n%s\n", diff);
2368  free(diff);
2369 #ifdef MANY_CORES
2370  /* Better to catch this here, as otherwise the next use of this object
2371  * is likely to cause a crash. Better to find out where it is getting
2372  * improperly inserted.
2373  */
2374  abort();
2375 #endif
2376  return op;
2377  }
2378  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
2379  StringBuffer *sb;
2380  char *diff;
2381 
2382  sb = stringbuffer_new();
2383  object_dump(op, sb);
2384  diff = stringbuffer_finish(sb);
2385  LOG(llevError, "Trying to insert (map) inserted object.\n%s\n", diff);
2386  free(diff);
2387  return op;
2388  }
2389  if (op->more != NULL) {
2390  /* The part may be on a different map. */
2391 
2392  object *more = op->more;
2393 
2394  /* We really need the caller to normalize coordinates - if
2395  * we set the map, that doesn't work if the location is within
2396  * a map and this is straddling an edge. So only if coordinate
2397  * is clear wrong do we normalize it.
2398  */
2399  if (OUT_OF_REAL_MAP(more->map, more->x, more->y)) {
2400  /* Debugging information so you can see the last coordinates this object had */
2401  more->ox = more->x;
2402  more->oy = more->y;
2403  more->map = get_map_from_coord(more->map, &more->x, &more->y);
2404  } else if (!more->map) {
2405  /* For backwards compatibility - when not dealing with tiled maps,
2406  * more->map should always point to the parent.
2407  */
2408  more->map = m;
2409  }
2410 
2411  if (object_insert_in_map(more, more->map, originator, flag) == NULL) {
2412  if (!op->head)
2413  LOG(llevError, "BUG: object_insert_in_map(): inserting op->more killed op\n");
2414  return NULL;
2415  }
2416  }
2418 
2419  /* Debugging information so you can see the last coordinates this object had */
2420  op->ox = op->x;
2421  op->oy = op->y;
2422  x = op->x;
2423  y = op->y;
2424  op->map = get_map_from_coord(m, &x, &y);
2425 
2426  /* this has to be done after we translate the coordinates. */
2427  if (op->nrof
2428  && !(flag&INS_NO_MERGE)
2429  && op->type != SPELL_EFFECT) {
2430  FOR_MAP_PREPARE(op->map, x, y, spot) {
2431  if (object_can_merge(op, spot)) {
2432  op->nrof += spot->nrof;
2433  object_remove(spot);
2435  }
2436  } FOR_MAP_FINISH();
2437  } else if (op->type == SPELL_EFFECT
2438  && !op->range
2439  && !op->other_arch
2440  && (op->speed_left+op->speed) < 0.0) {
2441  object_merge_spell(op, x, y);
2442  }
2443 
2444  /* Ideally, the caller figures this out. However, it complicates a lot
2445  * of areas of callers (eg, anything that uses object_find_free_spot() would now
2446  * need extra work
2447  */
2448  if (op->map != m) {
2449  /* coordinates should not change unless map also changes */
2450  op->x = x;
2451  op->y = y;
2452  }
2453 
2454  if (op->type != LAMP)
2455  /* lamps use the FLAG_APPLIED to keep the light/unlit status, so don't reset it.
2456  Other objects just get unapplied, since the container "drops" them. */
2459  if (!QUERY_FLAG(op, FLAG_ALIVE))
2461 
2462  /* In many places, a player is passed as the originator, which
2463  * is fine. However, if the player is on a transport, they are not
2464  * actually on the map, so we can't use them for the linked pointers,
2465  * nor should the walk on function below use them either.
2466  */
2467  if (originator && originator->contr && originator->contr->transport)
2468  originator = originator->contr->transport;
2469 
2470  if (flag&INS_BELOW_ORIGINATOR) {
2471  if (originator->map != op->map
2472  || originator->x != op->x
2473  || originator->y != op->y) {
2474  LOG(llevError, "object_insert_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n");
2475  abort();
2476  }
2477  op->above = originator;
2478  op->below = originator->below;
2479  if (op->below)
2480  op->below->above = op;
2481  else
2482  SET_MAP_OB(op->map, op->x, op->y, op);
2483  /* since *below *originator, no need to update top */
2484  originator->below = op;
2485  } else {
2486  /* Top is the object that our object (op) is going to get inserted above. */
2487  top = find_insert_pos(op, flag);
2488 
2489  /* First object on this space */
2490  if (!top) {
2491  op->above = GET_MAP_OB(op->map, op->x, op->y);
2492  if (op->above)
2493  op->above->below = op;
2494  op->below = NULL;
2495  SET_MAP_OB(op->map, op->x, op->y, op);
2496  } else { /* get inserted into the stack above top */
2497  op->above = top->above;
2498  if (op->above)
2499  op->above->below = op;
2500  op->below = top;
2501  top->above = op;
2502  }
2503  if (op->above == NULL)
2504  SET_MAP_TOP(op->map, op->x, op->y, op);
2505  } /* else not INS_BELOW_ORIGINATOR */
2506 
2507  if (!(flag&INS_MAP_LOAD)) {
2508  if (op->type == PLAYER)
2509  op->contr->do_los = 1;
2510 
2511  /* If we have a floor, we know the player, if any, will be above
2512  * it, so save a few ticks and start from there.
2513  */
2514  tmp = floor ? floor : GET_MAP_OB(op->map, op->x, op->y);
2516  if (tmp->type == PLAYER)
2517  tmp->contr->socket.update_look = 1;
2519 
2520  /* If this object glows, it may affect lighting conditions that are
2521  * visible to others on this map. But update_all_los is really
2522  * an inefficient way to do this, as it means los for all players
2523  * on the map will get recalculated. The players could very well
2524  * be far away from this change and not affected in any way -
2525  * this should get redone to only look for players within range,
2526  * or just updating the P_NEED_UPDATE for spaces within this area
2527  * of effect may be sufficient.
2528  */
2529  if (MAP_DARKNESS(op->map) && (op->glow_radius != 0))
2530  update_all_los(op->map, op->x, op->y);
2531 
2532  if (op->contr && !op->contr->hidden)
2533  op->map->players++;
2534  }
2535 
2536  /* updates flags (blocked, alive, no magic, etc) for this map space */
2538 
2539  /* Don't know if moving this to the end will break anything. However,
2540  * we want to have update_look set above before calling this.
2541  *
2542  * object_check_move_on() must be after this because code called from
2543  * object_check_move_on() depends on correct map flags (so functions like
2544  * blocked() and wall() work properly), and these flags are updated by
2545  * object_update().
2546  */
2547 
2548  /* if this is not the head or flag has been passed, don't check walk on status */
2549 
2550  if (!(flag&INS_NO_WALK_ON) && !op->head) {
2551  if (object_check_move_on(op, originator))
2552  return NULL;
2553 
2554  /* If we are a multi part object, lets work our way through the check
2555  * walk on's.
2556  */
2557  for (tmp = op->more; tmp != NULL; tmp = tmp->more)
2558  if (object_check_move_on(tmp, originator))
2559  return NULL;
2560  }
2561  return op;
2562 }
2563 
2573 void object_replace_insert_in_map(const char *arch_string, object *op) {
2574  object *tmp1;
2575  archetype *at;
2576 
2577  /* first search for itself and remove any old instances */
2578  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp) {
2579  if (!strcmp(tmp->arch->name, arch_string)) { /* same archetype */
2580  object_remove(tmp);
2582  }
2583  } FOR_MAP_FINISH();
2584 
2585  at = find_archetype(arch_string);
2586  if (at == NULL) {
2587  return;
2588  }
2589  tmp1 = arch_to_object(at);
2590  object_insert_in_map_at(tmp1, op->map, op, INS_BELOW_ORIGINATOR, op->x, op->y);
2591 }
2592 
2613 object *object_split(object *orig_ob, uint32_t nr, char *err, size_t size) {
2614  object *newob;
2615 
2616  if (MAX(1, orig_ob->nrof) < nr) {
2617  /* If err is set, the caller knows that nr can be wrong (player trying to drop items), thus don't log that. */
2618  if (err)
2619  snprintf(err, size, "There are only %u %ss.", NROF(orig_ob), orig_ob->name);
2620  else
2621  LOG(llevDebug, "There are only %u %ss.\n", NROF(orig_ob), orig_ob->name);
2622  return NULL;
2623  }
2624  newob = object_create_clone(orig_ob);
2625  if (orig_ob->nrof == 0) {
2626  if (!QUERY_FLAG(orig_ob, FLAG_REMOVED)) {
2627  object_remove(orig_ob);
2628  }
2630  } else {
2631  newob->nrof = nr;
2632  object_decrease_nrof(orig_ob, nr);
2633  }
2634 
2635  return newob;
2636 }
2637 
2652 object *object_decrease_nrof(object *op, uint32_t i) {
2653  object *tmp;
2654 
2655  if (i == 0) /* objects with op->nrof require this check */
2656  return op;
2657 
2658  if (i > op->nrof)
2659  i = op->nrof;
2660 
2661  if (QUERY_FLAG(op, FLAG_REMOVED)) {
2662  op->nrof -= i;
2663  } else if (op->env != NULL) {
2664  if (i < op->nrof) {
2665  player *pl;
2666  /* is this object in the players inventory, or sub container
2667  * therein?
2668  */
2670  /* nope. Is this a container the player has opened?
2671  * If so, set tmp to that player.
2672  * IMO, searching through all the players will mostly
2673  * likely be quicker than following op->env to the map,
2674  * and then searching the map for a player.
2675  */
2676  if (!tmp) {
2677  for (pl = first_player; pl; pl = pl->next)
2678  if (pl->ob->container == op->env)
2679  break;
2680  if (pl)
2681  tmp = pl->ob;
2682  else
2683  tmp = NULL;
2684  }
2685 
2686  /* Because of weight reduction by container and integer arithmetic,
2687  * there is no guarantee the rounded weight of combined items will be
2688  * the same as the sum of rounded weights.
2689  * Therefore just remove the current weight, and add the new.
2690  * Same adjustment done in object_increase_nrof().
2691  */
2692  object_sub_weight(op->env, op->weight * op->nrof);
2693  op->nrof -= i;
2694  object_add_weight(op->env, op->weight * op->nrof);
2695  if (tmp) {
2698  fix_object(tmp);
2699  }
2700  } else {
2701  object_remove(op);
2702  op->nrof = 0;
2703  }
2704  } else {
2705  /* On a map. */
2706  if (i < op->nrof) {
2707  op->nrof -= i;
2708 
2709  FOR_MAP_PREPARE(op->map, op->x, op->y, pl)
2710  if (pl->contr) {
2711  pl->contr->socket.update_look = 1;
2712  break;
2713  }
2714  FOR_MAP_FINISH();
2715  } else {
2716  object_remove(op);
2717  op->nrof = 0;
2718  }
2719  }
2720 
2721  if (op->nrof) {
2722  return op;
2723  } else {
2725  return NULL;
2726  }
2727 }
2728 
2739 static void object_increase_nrof(object *op, uint32_t i) {
2740  object *tmp;
2741 
2742  if (i == 0) /* objects with op->nrof require this check */
2743  return;
2744 
2745  if (QUERY_FLAG(op, FLAG_REMOVED)) {
2746  op->nrof += i;
2747  } else if (op->env != NULL) {
2748  player *pl;
2749  /* is this object in the players inventory, or sub container
2750  * therein?
2751  */
2753  /* nope. Is this a container the player has opened?
2754  * If so, set tmp to that player.
2755  * IMO, searching through all the players will mostly
2756  * likely be quicker than following op->env to the map,
2757  * and then searching the map for a player.
2758  */
2759  if (!tmp) {
2760  for (pl = first_player; pl; pl = pl->next)
2761  if (pl->ob->container == op->env)
2762  break;
2763  if (pl)
2764  tmp = pl->ob;
2765  else
2766  tmp = NULL;
2767  }
2768 
2769  /* Because of weight reduction by container and integer arithmetic,
2770  * there is no guarantee the rounded weight of combined items will be
2771  * the same as the sum of rounded weights.
2772  * Therefore just remove the current weight, and add the new.
2773  * Same adjustment done in object_decrease_nrof().
2774  */
2775  object_sub_weight(op->env, op->weight * op->nrof);
2776  op->nrof += i;
2777  object_add_weight(op->env, op->weight * op->nrof);
2778  if (tmp) {
2780  // Why don't we need to update weight of op->env here?
2781  }
2782  } else {
2783  /* On a map. */
2784  op->nrof += i;
2785 
2786  FOR_MAP_PREPARE(op->map, op->x, op->y, pl)
2787  if (pl->contr) {
2788  pl->contr->socket.update_look = 1;
2789  break;
2790  }
2791  FOR_MAP_FINISH();
2792  }
2793 }
2794 
2809 void object_add_weight(object *op, signed long weight) {
2810  while (op != NULL) {
2811  if (op->type == CONTAINER) {
2812  weight = (signed long)(weight*(100-op->stats.Str)/100);
2813  }
2814  op->carrying += weight;
2815  op = op->env;
2816  }
2817 }
2818 
2833 object *object_insert_in_ob(object *op, object *where) {
2834  object *otmp;
2835 
2836  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
2837  StringBuffer *sb;
2838  char *diff;
2839 
2840  sb = stringbuffer_new();
2841  object_dump(op, sb);
2842  diff = stringbuffer_finish(sb);
2843  LOG(llevError, "Trying to insert (ob) inserted object.\n%s\n", diff);
2844  free(diff);
2845  return op;
2846  }
2847 
2848  if (where == NULL) {
2849  StringBuffer *sb;
2850  char *diff;
2851 
2852  sb = stringbuffer_new();
2853  object_dump(op, sb);
2854  diff = stringbuffer_finish(sb);
2855  LOG(llevError, "Trying to put object in NULL.\n%s\n", diff);
2856  free(diff);
2857  return op;
2858  }
2859  if (where->head) {
2860  LOG(llevDebug, "Warning: Tried to insert object wrong part of multipart object.\n");
2861  }
2862  where = HEAD(where);
2863  if (op->more) {
2864  LOG(llevError, "Tried to insert multipart object %s (%u)\n", op->name, op->count);
2865  return op;
2866  }
2869  if (op->nrof || op->type == SKILL) {
2871  if (op->type == SKILL && tmp->type == SKILL && op->subtype == tmp->subtype) {
2872  // Duplicate skill. Sum exp and total_exp.
2873  LOG(llevDebug, "Merged duplicate skill %s for %s\n", op->arch->name, where->name);
2874  tmp->stats.exp += op->stats.exp;
2875  tmp->total_exp += op->total_exp;
2877  object_free(op, FREE_OBJ_FREE_INVENTORY | FREE_OBJ_NO_DESTROY_CALLBACK); /* free the inserted object */
2878  return tmp;
2879  } else if (object_can_merge(tmp, op)) {
2880  /* return the original object and remove inserted object
2881  * (client needs the original object) */
2882  object_increase_nrof(tmp, op->nrof);
2884  object_free(op, FREE_OBJ_FREE_INVENTORY | FREE_OBJ_NO_DESTROY_CALLBACK); /* free the inserted object */
2885  return tmp;
2886  }
2887  FOR_INV_FINISH();
2888 
2889  /* the item couldn't merge. */
2890  object_add_weight(where, op->weight*op->nrof);
2891  } else
2892  object_add_weight(where, op->weight+op->carrying);
2893 
2894  op->map = NULL;
2895  op->env = where;
2896  op->above = NULL;
2897  op->below = NULL;
2898  op->x = 0,
2899  op->y = 0;
2900  op->ox = 0,
2901  op->oy = 0;
2902 
2903  /* Client has no idea of ordering so lets not bother ordering it here.
2904  * It sure simplifies this function...
2905  */
2906  if (where->inv == NULL)
2907  where->inv = op;
2908  else {
2909  op->below = where->inv;
2910  op->below->above = op;
2911  where->inv = op;
2912  }
2913 
2914  /* Update in 2 cases: object goes into player's inventory, or object goes into container the player
2915  * is looking into. */
2916  if (where->contr != NULL)
2918  else if (where->type == CONTAINER && QUERY_FLAG(where, FLAG_APPLIED)) {
2919  object *pl = NULL;
2920 
2921  if (op->env->env && op->env->env->contr)
2922  /* Container is in player's inventory. */
2923  pl = op->env->env;
2924  else if (op->env->map) {
2925  /* Container on map, look above for player. */
2926  FOR_ABOVE_PREPARE(op->env, above)
2927  if (above->contr) {
2928  pl = above;
2929  break;
2930  }
2931  FOR_ABOVE_FINISH();
2932  }
2933  if (pl)
2934  esrv_send_item(pl, op);
2935  }
2936 
2938  if (otmp && otmp->contr != NULL) {
2939  if (!QUERY_FLAG(otmp, FLAG_NO_FIX_PLAYER)
2940  && (QUERY_FLAG(op, FLAG_APPLIED) || op->type == SKILL || op->glow_radius != 0))
2941  /* fix_object will only consider applied items, or skills, or items with a glow radius.
2942  thus no need to call it if our object hasn't that. */
2943  fix_object(otmp);
2944  }
2945 
2946  /* reset the light list and los of the players on the map */
2947  if (op->glow_radius != 0 && where->map) {
2948 #ifdef DEBUG_LIGHTS
2949  LOG(llevDebug, " object_insert_in_ob(): got %s to insert in map/op\n", op->name);
2950 #endif /* DEBUG_LIGHTS */
2951  if (MAP_DARKNESS(where->map)) {
2952  SET_MAP_FLAGS(where->map, where->x, where->y, P_NEED_UPDATE);
2953  update_position(where->map, where->x, where->y);
2954  update_all_los(where->map, where->x, where->y);
2955  }
2956  }
2957 
2958  return op;
2959 }
2960 
2983 int object_check_move_on(object *op, object *originator) {
2984  object *tmp;
2985  tag_t tag;
2986  mapstruct *m = op->map;
2987  int x = op->x, y = op->y;
2988  MoveType move_on, move_slow, move_block;
2989 
2990  if (QUERY_FLAG(op, FLAG_NO_APPLY))
2991  return 0;
2992 
2993  tag = op->count;
2994 
2995  move_on = GET_MAP_MOVE_ON(op->map, op->x, op->y);
2996  move_slow = GET_MAP_MOVE_SLOW(op->map, op->x, op->y);
2997  move_block = GET_MAP_MOVE_BLOCK(op->map, op->x, op->y);
2998 
2999  /* if nothing on this space will slow op down or be applied,
3000  * no need to do checking below. have to make sure move_type
3001  * is set, as lots of objects don't have it set - we treat that
3002  * as walking.
3003  */
3004  if (op->move_type
3005  && !(op->move_type&move_on)
3006  && !(op->move_type&move_slow))
3007  return 0;
3008 
3009  /* This is basically inverse logic of that below - basically,
3010  * if the object can avoid the move on or slow move, they do so,
3011  * but can't do it if the alternate movement they are using is
3012  * blocked. Logic on this seems confusing, but does seem correct.
3013  */
3014  if ((op->move_type&~move_on&~move_block) != 0
3015  && (op->move_type&~move_slow&~move_block) != 0)
3016  return 0;
3017 
3018  /* The objects have to be checked from top to bottom.
3019  * Hence, we first go to the top:
3020  */
3021 
3022  tmp = GET_MAP_OB(op->map, op->x, op->y);
3024  if (tmp->above == NULL)
3025  break;
3026  /* Trim the search when we find the first other spell effect
3027  * this helps performance so that if a space has 50 spell objects,
3028  * we don't need to check all of them.
3029  */
3030  if ((tmp->move_type&MOVE_FLY_LOW) && QUERY_FLAG(tmp, FLAG_NO_PICK))
3031  break;
3034  if (tmp == op)
3035  continue; /* Can't apply yourself */
3036 
3037  /* Check to see if one of the movement types should be slowed down.
3038  * Second check makes sure that the movement types not being slowed
3039  * (~slow_move) is not blocked on this space - just because the
3040  * space doesn't slow down swimming (for example), if you can't actually
3041  * swim on that space, can't use it to avoid the penalty.
3042  */
3043  if (!QUERY_FLAG(op, FLAG_WIZPASS)) {
3044  if ((!op->move_type && tmp->move_slow&MOVE_WALK)
3045  || ((op->move_type&tmp->move_slow) && (op->move_type&~tmp->move_slow&~tmp->move_block) == 0)) {
3046  float diff;
3047 
3048  diff = tmp->move_slow_penalty*FABS(op->speed);
3049  if (op->type == PLAYER) {
3052  diff /= 4.0;
3053  }
3054  }
3055  op->speed_left -= diff;
3056  }
3057  }
3058 
3059  /* Basically same logic as above, except now for actual apply. */
3060  if ((!op->move_type && tmp->move_on&MOVE_WALK)
3061  || ((op->move_type&tmp->move_on) && (op->move_type&~tmp->move_on&~tmp->move_block) == 0)) {
3062  ob_move_on(tmp, op, originator);
3063  if (object_was_destroyed(op, tag))
3064  return 1;
3065 
3066  /* what the person/creature stepped onto has moved the object
3067  * someplace new. Don't process any further - if we did,
3068  * have a feeling strange problems would result.
3069  */
3070  if (op->map != m || op->x != x || op->y != y)
3071  return 0;
3072  }
3074  return 0;
3075 }
3076 
3089 object *map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at) {
3090  if (m == NULL || OUT_OF_REAL_MAP(m, x, y)) {
3091  LOG(llevError, "Present_arch called outside map.\n");
3092  return NULL;
3093  }
3094 
3095  FOR_MAP_PREPARE(m, x, y, tmp)
3096  if (tmp->arch == at)
3097  return tmp;
3098  FOR_MAP_FINISH();
3099 
3100  return NULL;
3101 }
3102 
3116 object *map_find_by_type(mapstruct *m, int x, int y, uint8_t type) {
3117  if (OUT_OF_REAL_MAP(m, x, y)) {
3118  return NULL;
3119  }
3120 
3121  FOR_MAP_PREPARE(m, x, y, tmp)
3122  if (tmp->type == type)
3123  return tmp;
3124  FOR_MAP_FINISH();
3125 
3126  return NULL;
3127 }
3128 
3139 object *object_present_in_ob(uint8_t type, const object *op) {
3140  object *tmp;
3141 
3142  for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
3143  if (tmp->type == type)
3144  return tmp;
3145 
3146  return NULL;
3147 }
3148 
3174 object *object_present_in_ob_by_name(int type, const char *str, const object *op) {
3175  object *tmp;
3176 
3177  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
3178  if ((type == -1 || tmp->type == type) && !strcmp(str, tmp->name))
3179  return tmp;
3180  }
3181  return NULL;
3182 }
3183 
3193 object *arch_present_in_ob(const archetype *at, const object *op) {
3194  object *tmp;
3195 
3196  for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
3197  if (tmp->arch == at)
3198  return tmp;
3199  return NULL;
3200 }
3201 
3210 void object_set_flag_inv(object*op, int flag) {
3211  object *tmp;
3212 
3213  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
3214  SET_FLAG(tmp, flag);
3215  object_set_flag_inv(tmp, flag);
3216  }
3217 }
3218 
3227 void object_unset_flag_inv(object*op, int flag) {
3228  object *tmp;
3229 
3230  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
3231  CLEAR_FLAG(tmp, flag);
3232  object_unset_flag_inv(tmp, flag);
3233  }
3234 }
3235 
3245 void object_set_cheat(object *op) {
3248 }
3249 
3267 int object_find_multi_free_spot_around(const object *ob, const object *gen, int16_t *hx, int16_t *hy) {
3268  int genx, geny, genx2, geny2, sx, sy, sx2, sy2, ix, iy, nx, ny, i, flag;
3269  int freecount = 0;
3270 
3271  ob = HEAD(ob);
3272 
3273  object_get_multi_size(ob, &sx, &sy, &sx2, &sy2);
3274  object_get_multi_size(gen, &genx, &geny, &genx2, &geny2);
3275  /*
3276  * sx and sy are now the coords of the bottom right corner of ob relative to the head.
3277  * genx and geny are now the coords of the bottom right corner of gen relative to the head.
3278  * sx2 and sy2 are now the coords of the head of ob relative to the top left corner.
3279  * genx2 and geny2 are now the coords of the head of gen relative to the top left corner.
3280  */
3281 
3282  sx++;
3283  sy++;
3284  genx++;
3285  geny++;
3286  /*
3287  * sx, sy, genx, and geny, are now the size of the object, excluding parts left and above
3288  * the head.
3289  */
3290 
3291  ix = gen->x-sx-genx2;
3292  iy = gen->y-sy-geny2;
3293  sx += genx+sx2;
3294  sy += geny+sy2;
3295  /*
3296  * ix and iy are the map coords of the top left square where the head of ob could possibly
3297  * be placed. sx and sy are now the size of the square to search for placement of the head
3298  * relative to ix and iy.
3299  */
3300 
3301  /*
3302  * Loop around the square of possible positions for the head of ob object:
3303  */
3304  for (i = 0; i < (sx+sx+sy+sy); i++) {
3305  if (i <= sx) {
3306  nx = i+ix;
3307  ny = iy;
3308  } else if (i <= sx+sy) {
3309  nx = ix+sx;
3310  ny = iy+i-sx;
3311  } else if (i <= sx+sy+sx) {
3312  nx = ix+sx-(i-(sx+sy));
3313  ny = iy+sy;
3314  } else {
3315  nx = ix;
3316  ny = iy+sy-(i-(sx+sy+sx));
3317  }
3318  /* Check if the spot is free. */
3319  flag = ob_blocked(ob, gen->map, nx, ny);
3320  if (!flag) {
3321  freecount++;
3322  }
3323  }
3324  /* If no free spaces, return. */
3325  if (!freecount)
3326  return -1;
3327 
3328  /* Choose a random valid position */
3329  freecount = RANDOM()%freecount;
3330  for (i = 0; i < sx+sx+sy+sy; i++) {
3331  if (i <= sx) {
3332  nx = i+ix;
3333  ny = iy;
3334  } else if (i <= sx+sy) {
3335  nx = ix+sx;
3336  ny = iy+i-sx;
3337  } else if (i <= sx+sy+sx) {
3338  nx = ix+sx-(i-(sx+sy));
3339  ny = iy+sy;
3340  } else {
3341  nx = ix;
3342  ny = iy+sy-(i-(sx+sy+sx));
3343  }
3344 
3345  /* Make sure it's within map. */
3346  if (nx < 0 || nx >= MAP_WIDTH(gen->map)
3347  || ny < 0 || ny >= MAP_HEIGHT(gen->map))
3348  continue;
3349 
3350  /* Check if the spot is free.*/
3351  flag = ob_blocked(ob, gen->map, nx, ny);
3352  if (!flag) {
3353  freecount--;
3354  if (freecount <= 0) {
3355  *hx = nx;
3356  *hy = ny;
3357  return 0;
3358  }
3359  }
3360  }
3361  return -1;
3362 }
3363 
3383 int object_find_multi_free_spot_within_radius(const object *ob, const object *gen, int *hx, int *hy) {
3384  int genx, geny, genx2, geny2, sx, sy, sx2, sy2, ix, iy, nx, ny, i, flag;
3385  int8_t x, y, radius;
3386  int freecount = 0, freecountstop = 0;
3387  const char *value;
3388  int8_t *x_array;
3389  int8_t *y_array;
3390 
3391  /* If radius is not set, default to 1 */
3392  value = object_get_value(gen, "generator_radius");
3393  if (value) {
3394  radius = (int8_t)strtol(value, NULL, 10);
3395  if (radius < 1) {
3396  radius = 1;
3397  }
3398  } else {
3399  radius = 1;
3400  }
3401 
3402  ob = HEAD(ob);
3403 
3404  object_get_multi_size(ob, &sx, &sy, &sx2, &sy2);
3405  object_get_multi_size(gen, &genx, &geny, &genx2, &geny2);
3406  /*
3407  * sx and sy are now the coords of the bottom right corner
3408  * of ob relative to the head.
3409  * genx and geny are now the coords of the bottom right corner
3410  * of gen relative to the head.
3411  * sx2 and sy2 are now the coords of the head of ob relative
3412  * to the top left corner.
3413  * genx2 and geny2 are now the coords of the head of gen relative
3414  * to the top left corner.
3415  */
3416 
3417  sx++;
3418  sy++;
3419  genx++;
3420  geny++;
3421  /*
3422  * sx, sy, genx, and geny, are now the size of the object,
3423  * excluding parts left and above the head.
3424  */
3425 
3426  ix = gen->x-sx-genx2-radius+1;
3427  iy = gen->y-sy-geny2-radius+1;
3428  sx += genx+sx2+radius*2-1;
3429  sy += geny+sy2+radius*2-1;
3430 
3431  /*
3432  * ix and iy are the map coords of the top left square where
3433  * the head of ob could possibly be placed. sx and sy are now
3434  * the size of the square to search for placement of the head
3435  * relative to ix and iy.
3436  */
3437 
3438  /* Create arrays large enough to hold free space coordinates */
3439  x_array = malloc(sx*sy*sizeof(int8_t));
3440  y_array = malloc(sx*sy*sizeof(int8_t));
3441 
3442  /*
3443  * Loop through the area of possible positions for the head of ob object:
3444  */
3445  for (x = 0; x < sx; x++) {
3446  for (y = 0; y < sy; y++) {
3447  nx = ix+x;
3448  ny = iy+y;
3449 
3450 
3451  /* Make sure it's within map. */
3452  if (get_map_flags(gen->map, NULL, nx, ny, NULL, NULL)&P_OUT_OF_MAP) {
3453  continue;
3454  }
3455 
3456  /* Check if the spot is free. */
3457  flag = ob_blocked(ob, gen->map, nx, ny);
3458  if (!flag) {
3459  x_array[freecount] = nx;
3460  y_array[freecount] = ny;
3461  freecount++;
3462  }
3463  }
3464  }
3465  /* If no free spaces, return. */
3466  if (!freecount) {
3467  free(x_array);
3468  free(y_array);
3469  return -1;
3470  }
3471 
3472  /* Choose a random valid position */
3473  freecountstop = RANDOM()%freecount;
3474  for (i = 0; i < freecount; i++) {
3475  nx = x_array[i];
3476  ny = y_array[i];
3477 
3478  /* Check if the spot is free.*/
3479  flag = ob_blocked(ob, gen->map, nx, ny);
3480  if (!flag) {
3481  freecountstop--;
3482  if (freecountstop <= 0) {
3483  *hx = nx;
3484  *hy = ny;
3485  free(x_array);
3486  free(y_array);
3487  return 0;
3488  }
3489  }
3490  }
3491  free(x_array);
3492  free(y_array);
3493  return -1;
3494 }
3495 
3530 int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop) {
3531  int i, index = 0, flag;
3532  static int altern[SIZEOFFREE];
3533 
3534  for (i = start; i < stop; i++) {
3535  flag = ob_blocked(ob, m, x+freearr_x[i], y+freearr_y[i]);
3536  if (!flag)
3537  altern[index++] = i;
3538 
3539  /* Basically, if we find a wall on a space, we cut down the search size.
3540  * In this way, we won't return spaces that are on another side of a wall.
3541  * This mostly work, but it cuts down the search size in all directions -
3542  * if the space being examined only has a wall to the north and empty
3543  * spaces in all the other directions, this will reduce the search space
3544  * to only the spaces immediately surrounding the target area, and
3545  * won't look 2 spaces south of the target space.
3546  */
3547  else if ((flag&AB_NO_PASS) && maxfree[i] < stop)
3548  stop = maxfree[i];
3549  }
3550  if (!index)
3551  return -1;
3552  return altern[RANDOM()%index];
3553 }
3554 
3570 int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y) {
3571  int i;
3572 
3573  for (i = 0; i < SIZEOFFREE; i++) {
3574  if (!ob_blocked(ob, m, x+freearr_x[i], y+freearr_y[i]))
3575  return i;
3576  }
3577  return -1;
3578 }
3579 
3589 static void permute(int *arr, int begin, int end) {
3590  int i, j, tmp, len;
3591 
3592  len = end-begin;
3593  for (i = begin; i < end; i++) {
3594  j = begin+RANDOM()%len;
3595 
3596  tmp = arr[i];
3597  arr[i] = arr[j];
3598  arr[j] = tmp;
3599  }
3600 }
3601 
3613 void get_search_arr(int *search_arr) {
3614  int i;
3615 
3616  for (i = 0; i < SIZEOFFREE; i++) {
3617  search_arr[i] = i;
3618  }
3619 
3620  permute(search_arr, 1, SIZEOFFREE1+1);
3621  permute(search_arr, SIZEOFFREE1+1, SIZEOFFREE2+1);
3622  permute(search_arr, SIZEOFFREE2+1, SIZEOFFREE);
3623 }
3624 
3632 int object_distance(const object *ob1, const object *ob2) {
3633  int i;
3634 
3635  i = (ob1->x-ob2->x)*(ob1->x-ob2->x)+
3636  (ob1->y-ob2->y)*(ob1->y-ob2->y);
3637  return i;
3638 }
3639 
3648 int find_dir_2(int x, int y) {
3649  int q;
3650 
3651  if (!y)
3652  q = -300*x;
3653  else
3654  q = x*100/y;
3655  if (y > 0) {
3656  if (q < -242)
3657  return 3;
3658  if (q < -41)
3659  return 2;
3660  if (q < 41)
3661  return 1;
3662  if (q < 242)
3663  return 8;
3664  return 7;
3665  }
3666  if (q < -242)
3667  return 7;
3668  if (q < -41)
3669  return 6;
3670  if (q < 41)
3671  return 5;
3672  if (q < 242)
3673  return 4;
3674  return 3;
3675 }
3676 
3685 int absdir(int d) {
3686  // Shortcut for modulus that work becuase we have a power of 2
3687  d &= 7;
3688  // 0 needs to be 8
3689  if (!d)
3690  d = 8;
3691  return d;
3692 }
3693 
3703 int dirdiff(int dir1, int dir2) {
3704  int d;
3705 
3706  d = abs(dir1-dir2);
3707  if (d > 4)
3708  d = 8-d;
3709  return d;
3710 }
3711 
3723 static const int reduction_dir[SIZEOFFREE][3] = {
3724  { 0, 0, 0 }, /* 0 */
3725  { 0, 0, 0 }, /* 1 */
3726  { 0, 0, 0 }, /* 2 */
3727  { 0, 0, 0 }, /* 3 */
3728  { 0, 0, 0 }, /* 4 */
3729  { 0, 0, 0 }, /* 5 */
3730  { 0, 0, 0 }, /* 6 */
3731  { 0, 0, 0 }, /* 7 */
3732  { 0, 0, 0 }, /* 8 */
3733  { 8, 1, 2 }, /* 9 */
3734  { 1, 2, -1 }, /* 10 */
3735  { 2, 10, 12 }, /* 11 */
3736  { 2, 3, -1 }, /* 12 */
3737  { 2, 3, 4 }, /* 13 */
3738  { 3, 4, -1 }, /* 14 */
3739  { 4, 14, 16 }, /* 15 */
3740  { 5, 4, -1 }, /* 16 */
3741  { 4, 5, 6 }, /* 17 */
3742  { 6, 5, -1 }, /* 18 */
3743  { 6, 20, 18 }, /* 19 */
3744  { 7, 6, -1 }, /* 20 */
3745  { 6, 7, 8 }, /* 21 */
3746  { 7, 8, -1 }, /* 22 */
3747  { 8, 22, 24 }, /* 23 */
3748  { 8, 1, -1 }, /* 24 */
3749  { 24, 9, 10 }, /* 25 */
3750  { 9, 10, -1 }, /* 26 */
3751  { 10, 11, -1 }, /* 27 */
3752  { 27, 11, 29 }, /* 28 */
3753  { 11, 12, -1 }, /* 29 */
3754  { 12, 13, -1 }, /* 30 */
3755  { 12, 13, 14 }, /* 31 */
3756  { 13, 14, -1 }, /* 32 */
3757  { 14, 15, -1 }, /* 33 */
3758  { 33, 15, 35 }, /* 34 */
3759  { 16, 15, -1 }, /* 35 */
3760  { 17, 16, -1 }, /* 36 */
3761  { 18, 17, 16 }, /* 37 */
3762  { 18, 17, -1 }, /* 38 */
3763  { 18, 19, -1 }, /* 39 */
3764  { 41, 19, 39 }, /* 40 */
3765  { 19, 20, -1 }, /* 41 */
3766  { 20, 21, -1 }, /* 42 */
3767  { 20, 21, 22 }, /* 43 */
3768  { 21, 22, -1 }, /* 44 */
3769  { 23, 22, -1 }, /* 45 */
3770  { 45, 47, 23 }, /* 46 */
3771  { 23, 24, -1 }, /* 47 */
3772  { 24, 9, -1 } /* 48 */
3773 };
3774 
3793 int can_see_monsterP(mapstruct *m, int x, int y, int dir) {
3794  int16_t dx, dy;
3795  int mflags;
3796 
3797  if (dir < 0)
3798  return 0; /* exit condition: invalid direction */
3799 
3800  dx = x+freearr_x[dir];
3801  dy = y+freearr_y[dir];
3802 
3803  mflags = get_map_flags(m, &m, dx, dy, &dx, &dy);
3804 
3805  /* This functional arguably was incorrect before - it was
3806  * checking for P_WALL - that was basically seeing if
3807  * we could move to the monster - this is being more
3808  * literal on if we can see it. To know if we can actually
3809  * move to the monster, we'd need the monster passed in or
3810  * at least its move type.
3811  */
3812  if (mflags&(P_OUT_OF_MAP|P_BLOCKSVIEW))
3813  return 0;
3814 
3815  /* yes, can see. */
3816  if (dir < 9)
3817  return 1;
3818  return can_see_monsterP(m, x, y, reduction_dir[dir][0])|
3819  can_see_monsterP(m, x, y, reduction_dir[dir][1])|
3820  can_see_monsterP(m, x, y, reduction_dir[dir][2]);
3821 }
3822 
3838 int object_can_pick(const object *who, const object *item) {
3839  /* I re-wrote this as a series of if statements
3840  * instead of a nested return (foo & bar && yaz)
3841  * - I think this is much more readable,
3842  * and likely compiler effectively optimizes it the
3843  * same.
3844  */
3845  if (item->weight <= 0)
3846  return 0;
3848  return 0;
3849  if (QUERY_FLAG(item, FLAG_ALIVE))
3850  return 0;
3851  if (item->invisible)
3852  return 0;
3853  if (item->type == TRANSPORT && item->contr != NULL) {
3854  return 0;
3855  }
3856 
3857  /* Weight limit for monsters */
3858  if (who->type != PLAYER && ((uint32_t)(who->weight+who->carrying+item->weight)) > get_weight_limit(who->stats.Str))
3859  return 0;
3860 
3861  /* Can not pick up multipart objects */
3862  if (item->head || item->more)
3863  return 0;
3864 
3865  /* Everything passes, so OK to pick up */
3866  return 1;
3867 }
3868 
3880 object *object_create_clone(object *asrc) {
3881  object *dst = NULL, *tmp, *src, *part, *prev;
3882 
3883  if (!asrc)
3884  return NULL;
3885  src = HEAD(asrc);
3886 
3887  prev = NULL;
3888  for (part = src; part; part = part->more) {
3889  tmp = object_new();
3890  object_copy(part, tmp);
3891  /*
3892  * Need to reset the weight, since object_insert_in_ob() later will
3893  * recompute this field.
3894  */
3895  tmp->carrying = tmp->arch->clone.carrying;
3896  tmp->x -= src->x;
3897  tmp->y -= src->y;
3898  if (!part->head) {
3899  dst = tmp;
3900  tmp->head = NULL;
3901  } else {
3902  tmp->head = dst;
3903  }
3904  tmp->more = NULL;
3905  if (prev)
3906  prev->more = tmp;
3907  prev = tmp;
3908  }
3909  /*** copy inventory ***/
3910  FOR_INV_PREPARE(src, item)
3912  FOR_INV_FINISH();
3913 
3914  return dst;
3915 }
3916 
3927 object *object_find_by_name(const object *who, const char *name) {
3928  const char *name_shared = add_string(name);
3929  object *tmp;
3930 
3931  for (tmp = who->inv; tmp; tmp = tmp->below)
3932  if (tmp->name == name_shared)
3933  break;
3934  free_string(name_shared);
3935  return tmp;
3936 }
3937 
3951 object *object_find_by_type(const object *who, int type) {
3952  object *tmp;
3953 
3954  for (tmp = who->inv; tmp; tmp = tmp->below)
3955  if (tmp->type == type)
3956  return tmp;
3957 
3958  return NULL;
3959 }
3960 
3975 object *object_find_by_type_without_flags(const object *who, int type, int *flags, int num_flags) {
3976  int flag_okay;
3977  for (object *tmp = who->inv; tmp; tmp = tmp->below)
3978  if (tmp->type == type) {
3979  flag_okay = 1;
3980  for (int i = 0; i < num_flags; ++i) {
3981  if (QUERY_FLAG(tmp, flags[i])) {
3982  flag_okay = 0; // A flag we didn't want set was set. Skip this item.
3983  break;
3984  }
3985  }
3986  if (flag_okay) // If flag_okay == 1, then the flags specified were not set
3987  return tmp; // If we reach here, none of the flags specified were set. Just like we wanted.
3988  }
3989 
3990  return NULL;
3991 }
3992 
4008 object *object_find_by_type2(const object *who, int type1, int type2) {
4009  object *tmp;
4010 
4011  for (tmp = who->inv; tmp; tmp = tmp->below)
4012  if (tmp->type == type1 || tmp->type == type2)
4013  return tmp;
4014 
4015  return NULL;
4016 }
4017 
4031 object *object_find_by_tag(const object *who, tag_t tag) {
4032  object *tmp;
4033 
4034  for (tmp = who->inv; tmp; tmp = tmp->below)
4035  if (tmp->count == tag)
4036  return tmp;
4037 
4038  return NULL;
4039 }
4040 
4054 object *object_find_by_type_applied(const object *who, int type) {
4055  object *tmp;
4056 
4057  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4058  if (tmp->type == type && QUERY_FLAG(tmp, FLAG_APPLIED))
4059  return tmp;
4060 
4061  return NULL;
4062 }
4063 
4079 object *object_find_by_type_and_name(const object *who, int type, const char *name) {
4080  object *tmp;
4081 
4082  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4083  if (tmp->type == type && strcmp(tmp->name, name) == 0)
4084  return tmp;
4085 
4086  return NULL;
4087 }
4088 
4104 object *object_find_by_type_and_race(const object *who, int type, const char *race) {
4105  object *tmp;
4106 
4107  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4108  if (tmp->type == type && strcmp(tmp->race, race) == 0)
4109  return tmp;
4110 
4111  return NULL;
4112 }
4113 
4129 object *object_find_by_type_and_slaying(const object *who, int type, const char *slaying) {
4130  object *tmp;
4131 
4132  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4133  if (tmp->type == type && tmp->slaying != NULL && strcmp(tmp->slaying, slaying) == 0)
4134  return tmp;
4135 
4136  return NULL;
4137 }
4138 
4154 object *object_find_by_type_and_skill(const object *who, int type, const char *skill) {
4155  object *tmp;
4156 
4157  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4158  if (tmp->type == type && tmp->skill != NULL && strcmp(tmp->skill, skill) == 0)
4159  return tmp;
4160 
4161  return NULL;
4162 }
4163 
4177 object *object_find_by_flag(const object *who, int flag) {
4178  object *tmp;
4179 
4180  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4181  if (QUERY_FLAG(tmp, flag))
4182  return tmp;
4183 
4184  return NULL;
4185 }
4186 
4200 object *object_find_by_flag_applied(const object *who, int flag) {
4201  object *tmp;
4202 
4203  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4204  if (QUERY_FLAG(tmp, FLAG_APPLIED) && QUERY_FLAG(tmp, flag))
4205  return tmp;
4206 
4207  return NULL;
4208 }
4209 
4223 object *object_find_by_arch_name(const object *who, const char *name) {
4224  object *tmp;
4225 
4226  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4227  if (strcmp(tmp->arch->name, name) == 0)
4228  return tmp;
4229 
4230  return NULL;
4231 }
4232 
4248 object *object_find_by_type_and_arch_name(const object *who, int type, const char *name) {
4249  object *tmp;
4250 
4251  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4252  if (tmp->type == type && strcmp(tmp->arch->name, name) == 0)
4253  return tmp;
4254 
4255  return NULL;
4256 }
4257 
4272 object *object_find_by_type_subtype(const object *who, int type, int subtype) {
4273  object *tmp;
4274 
4275  for (tmp = who->inv; tmp; tmp = tmp->below)
4276  if (tmp->type == type && tmp->subtype == subtype)
4277  return tmp;
4278 
4279  return NULL;
4280 }
4281 
4292 key_value *object_get_key_value(const object *ob, const char *key) {
4293  key_value *link;
4294 
4295  for (link = ob->key_values; link != NULL; link = link->next) {
4296  if (link->key == key) {
4297  return link;
4298  }
4299  }
4300 
4301  return NULL;
4302 }
4303 
4317 const char *object_get_value(const object *op, const char *const key) {
4318  key_value *link;
4319  const char *canonical_key;
4320 
4321  canonical_key = find_string(key);
4322 
4323  if (canonical_key == NULL) {
4324  /* 1. There being a field named key on any object
4325  * implies there'd be a shared string to find.
4326  * 2. Since there isn't, no object has this field.
4327  * 3. Therefore, *this *object doesn't have this field.
4328  */
4329  return NULL;
4330  }
4331 
4332  /* This is copied from object_get_key_value() above -
4333  * only 4 lines, and saves the function call overhead.
4334  */
4335  for (link = op->key_values; link != NULL; link = link->next) {
4336  if (link->key == canonical_key) {
4337  return link->value;
4338  }
4339  }
4340  return NULL;
4341 }
4342 
4347 bool object_value_set(const object *op, const char *const key) {
4348  const char *ret = object_get_value(op, key);
4349  if (ret == NULL || (strcmp(ret, "") == 0) || (strcmp(ret, "0") == 0)) {
4350  return false;
4351  }
4352  return true;
4353 }
4354 
4361 bool object_value_set_shared(const object *op, sstring key) {
4362  for (key_value *link = op->key_values; link != NULL; link = link->next) {
4363  if (link->key == key) {
4364  if ((strcmp(link->value, "") == 0) || (strcmp(link->value, "0") == 0)) {
4365  return false;
4366  }
4367  return true;
4368  }
4369  }
4370  return false;
4371 }
4372 
4387 static int object_set_value_s(object *op, const char *canonical_key, const char *value, int add_key) {
4388  key_value *field = NULL, *last = NULL;
4389 
4390  for (field = op->key_values; field != NULL; field = field->next) {
4391  if (field->key != canonical_key) {
4392  last = field;
4393  continue;
4394  }
4395 
4396  if (field->value)
4397  FREE_AND_CLEAR_STR(field->value);
4398  if (value)
4399  field->value = add_string(value);
4400  else {
4401  /* Basically, if the archetype has this key set,
4402  * we need to store the null value so when we save
4403  * it, we save the empty value so that when we load,
4404  * we get this value back again.
4405  */
4406  if (object_get_key_value(&op->arch->clone, canonical_key))
4407  field->value = NULL;
4408  else {
4409  /* Delete this link */
4410  if (field->key)
4411  FREE_AND_CLEAR_STR(field->key);
4412  if (field->value)
4413  FREE_AND_CLEAR_STR(field->value);
4414  if (last)
4415  last->next = field->next;
4416  else
4417  op->key_values = field->next;
4418  free(field);
4419  }
4420  }
4421  return TRUE;
4422  }
4423  /* IF we get here, key doesn't exist */
4424 
4425  /* No field, we'll have to add it. */
4426 
4427  if (!add_key) {
4428  return FALSE;
4429  }
4430  /* There isn't any good reason to store a null
4431  * value in the key/value list. If the archetype has
4432  * this key, then we should also have it, so shouldn't
4433  * be here. If user wants to store empty strings,
4434  * should pass in ""
4435  */
4436  if (value == NULL)
4437  return TRUE;
4438 
4439  field = malloc(sizeof(key_value));
4440 
4441  field->key = add_refcount(canonical_key);
4442  field->value = add_string(value);
4443  /* Usual prepend-addition. */
4444  field->next = op->key_values;
4445  op->key_values = field;
4446 
4447  return TRUE;
4448 }
4449 
4470 int object_set_value(object *op, const char *key, const char *value, int add_key) {
4471  const char *canonical_key = NULL;
4472  int floating_ref = FALSE;
4473  int ret;
4474 
4475  /* HACK This mess is to make sure set_ob_value() passes a shared string
4476  * to object_get_key_value(), without leaving a leaked refcount.
4477  */
4478 
4479  canonical_key = find_string(key);
4480  if (canonical_key == NULL) {
4481  canonical_key = add_string(key);
4482  floating_ref = TRUE;
4483  }
4484 
4485  ret = object_set_value_s(op, canonical_key, value, add_key);
4486 
4487  if (floating_ref) {
4488  free_string(canonical_key);
4489  }
4490 
4491  return ret;
4492 }
4493 
4545 int object_matches_string(object *pl, object *op, const char *name) {
4546  char *cp, local_name[MAX_BUF], name_op[MAX_BUF], name_short[HUGE_BUF], bname_s[MAX_BUF], bname_p[MAX_BUF];
4547  int count, retval = 0;
4548  /* strtok is destructive to name */
4549  safe_strncpy(local_name, name, sizeof(local_name));
4550 
4551  for (cp = strtok(local_name, ","); cp; cp = strtok(NULL, ",")) {
4552  while (cp[0] == ' ')
4553  ++cp; /* get rid of spaces */
4554 
4555  /* LOG(llevDebug, "Trying to match %s\n", cp);*/
4556  /* All is a very generic match - low match value */
4557  if (!strcmp(cp, "all"))
4558  return 1;
4559 
4560  /* unpaid is a little more specific */
4561  if (!strcmp(cp, "unpaid") && QUERY_FLAG(op, FLAG_UNPAID))
4562  return 2;
4563  if (!strcmp(cp, "cursed")
4566  return 2;
4567 
4568  if (!strcmp(cp, "unlocked") && !QUERY_FLAG(op, FLAG_INV_LOCKED))
4569  return 2;
4570 
4571  /* Allow for things like '100 arrows' */
4572  count = atoi(cp);
4573  if (*cp == '+' || *cp == '-')
4574  count=0; // Let +/- searches look in description for magic bonuses
4575  if (count != 0) {
4576  cp = strchr(cp, ' ');
4577  while (cp && cp[0] == ' ')
4578  ++cp; /* get rid of spaces */
4579  } else {
4580  if (pl->type == PLAYER)
4581  count = pl->contr->count;
4582  else
4583  count = 0;
4584  }
4585 
4586  if (!cp || cp[0] == '\0' || count < 0)
4587  continue;
4588 
4589  /* The code here should go from highest retval to lowest. That
4590  * is because of the 'else' handling - we don't want to match on
4591  * something and set a low retval, even though it may match a higher retcal
4592  * later. So keep it in descending order here, so we try for the best
4593  * match first, and work downward.
4594  */
4595  query_name(op, name_op, MAX_BUF);
4596  query_short_name(op, name_short, HUGE_BUF);
4597  query_base_name(op, 0, bname_s, MAX_BUF);
4598  query_base_name(op, 1, bname_p, MAX_BUF);
4599 
4600  if (!strcasecmp(cp, name_op))
4601  retval = 20;
4602  else if (!strcasecmp(cp, name_short))
4603  retval = 18;
4604  else if (!strcasecmp(cp, bname_s))
4605  retval = 16;
4606  else if (!strcasecmp(cp, bname_p))
4607  retval = 16;
4608  else if (op->custom_name && !strcasecmp(cp, op->custom_name))
4609  retval = 15;
4610  else if (!strncasecmp(cp, bname_s, strlen(cp)))
4611  retval = 14;
4612  else if (!strncasecmp(cp, bname_p, strlen(cp)))
4613  retval = 14;
4614  /* Do substring checks, so things like 'Str+1' will match.
4615  * retval of these should perhaps be lower - they are lower
4616  * then the specific strcasecmp aboves, but still higher than
4617  * some other match criteria.
4618  */
4619  else if (strstr(bname_p, cp))
4620  retval = 12;
4621  else if (strstr(bname_s, cp))
4622  retval = 12;
4623  else if (strstr(name_short, cp))
4624  retval = 12;
4625  /* Check against plural/non plural based on count. */
4626  else if (count > 1 && !strcasecmp(cp, op->name_pl)) {
4627  retval = 6;
4628  } else if (count == 1 && !strcasecmp(op->name, cp)) {
4629  retval = 6;
4630  }
4631  /* base name matched - not bad */
4632  else if (strcasecmp(cp, op->name) == 0 && !count)
4633  retval = 4;
4634  /* Check for partial custom name, but give a real low priority */
4635  else if (op->custom_name && strstr(op->custom_name, cp))
4636  retval = 3;
4637 
4638  if (retval) {
4639  if (pl->type == PLAYER)
4640  pl->contr->count = count;
4641  return retval;
4642  }
4643  }
4644  return 0;
4645 }
4646 
4655 void object_fix_multipart(object *tmp) {
4656  archetype *at;
4657  object *op, *last;
4658 
4659  if (!tmp->map) {
4660  LOG(llevError, "object_fix_multipart: not on a map!\n");
4661  return;
4662  }
4663 
4664  /* already multipart - don't do anything more */
4665  if (tmp->head || tmp->more)
4666  return;
4667 
4668  /* If there is nothing more to this object, this for loop
4669  * won't do anything.
4670  */
4671  for (at = tmp->arch->more, last = tmp; at != NULL; at = at->more, last = op) {
4672  op = arch_to_object(at);
4673 
4674  /* update x,y coordinates */
4675  op->x += tmp->x;
4676  op->y += tmp->y;
4677  op->head = tmp;
4678  op->map = tmp->map;
4679  last->more = op;
4680  if (tmp->name != op->name) {
4681  if (op->name)
4682  free_string(op->name);
4683  op->name = add_string(tmp->name);
4684  }
4685  if (tmp->title != op->title) {
4686  if (op->title)
4687  free_string(op->title);
4688  op->title = add_string(tmp->title);
4689  }
4690  /* we could link all the parts onto tmp, and then just
4691  * call object_insert_in_map once, but the effect is the same,
4692  * as object_insert_in_map will call itself with each part, and
4693  * the coding is simpler to just to it here with each part.
4694  */
4696  } /* for at = tmp->arch->more */
4697 }
4698 
4714 void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy) {
4715  archetype *part;
4716  int maxx = 0, maxy = 0, minx = 0, miny = 0;
4717 
4718  ob = HEAD(ob);
4719  *sx = 1;
4720  *sy = 1;
4721  if (ob->arch->more) {
4722  for (part = ob->arch; part; part = part->more) {
4723  if (part->clone.x > maxx)
4724  maxx = part->clone.x;
4725  if (part->clone.y > maxy)
4726  maxy = part->clone.y;
4727  if (part->clone.x < minx)
4728  minx = part->clone.x;
4729  if (part->clone.y < miny)
4730  miny = part->clone.y;
4731  }
4732  }
4733  *sx = maxx;
4734  *sy = maxy;
4735  if (hx)
4736  *hx = -minx;
4737  if (hy)
4738  *hy = -miny;
4739 }
4740 
4761 void object_insert_to_free_spot_or_free(object *op, mapstruct *map, int x, int y, int start, int stop, object *originator) {
4762  int pos;
4763 
4764  pos = object_find_free_spot(op, map, x, y, start, stop);
4765  if (pos == -1) {
4767  return;
4768  }
4769 
4770  object_insert_in_map_at(op, map, originator, 0, x+freearr_x[pos], y+freearr_y[pos]);
4771 }
4772 
4781 void object_set_msg(object *op, const char *msg) {
4782  if (op->msg != NULL) {
4783  free_string(op->msg);
4784  }
4785 
4786  if (msg != NULL) {
4787  // If the message does not have a trailing newline, add one.
4788  if (*msg != '\0' && strchr(msg, '\0')[-1] != '\n') {
4791  stringbuffer_append_string(sb, "\n");
4792  op->msg = stringbuffer_finish_shared(sb);
4793  } else {
4794  op->msg = add_string(msg);
4795  }
4796  } else {
4797  op->msg = NULL;
4798  }
4799 }
4800 
4802 const char *const move_name[] = {
4803  "walk",
4804  "fly_low",
4805  "fly_high",
4806  "swim",
4807  "boat",
4808  NULL
4809 };
4810 
4811 /* This array equates the FLAG_ values with the V_ values. Use -1 to
4812  * put gaps in the array that should not be processed.
4813  * The order matches the order of the define values in 'define.h'.
4814  */
4821 static const char *const flag_names[NUM_FLAGS+1] = {
4822  "alive", "wiz", NULL, NULL, "was_wiz", "applied", "unpaid",
4823  "can_use_shield", "no_pick", "client_anim_sync", "client_anim_random", /* 10 */
4824  "is_animated", NULL /* FLAG_DIALOG_PARSED, not saved */,
4825  NULL /* flying */, "monster", "friendly", "generator",
4826  "is_thrown", "auto_apply", "treasure", "player sold", /* 20 */
4827  "see_invisible", "can_roll", "overlay_floor",
4828  "is_turnable", NULL /* walk_off */, NULL /* fly_on */,
4829  NULL /*fly_off*/, "is_used_up", "identified", "reflecting", /* 30 */
4830  "changing", "splitting", "hitback", "startequip",
4831  "blocksview", "undead", "scared", "unaggressive",
4832  "reflect_missile", "reflect_spell", /* 40 */
4833  "no_magic", "no_fix_player", "is_lightable", "tear_down",
4834  "run_away", NULL /*pass_thru */, NULL /*can_pass_thru*/,
4835  NULL /*"pick_up"*/, "unique", "no_drop", /* 50 */
4836  NULL /* wizcast*/, "can_cast_spell", "can_use_scroll", "can_use_range",
4837  "can_use_bow", "can_use_armour", "can_use_weapon",
4838  "can_use_ring", "has_ready_range", "has_ready_bow", /* 60 */
4839  "xrays", NULL, "is_floor", "lifesave", "no_strength", "sleep",
4840  "stand_still", "random_movement", "only_attack", "confused", /* 70 */
4841  "stealth", NULL, NULL, "cursed", "damned",
4842  "see_anywhere", "known_magical", "known_cursed",
4843  "can_use_skill", "been_applied", /* 80 */
4844  "has_ready_scroll", NULL, NULL,
4845  NULL, "make_invisible", "inv_locked", "is_wooded",
4846  "is_hilly", "has_ready_skill", "has_ready_weapon", /* 90 */
4847  "no_skill_ident", "is_blind", "can_see_in_dark", "is_cauldron",
4848  NULL, "no_steal", "one_hit", NULL, "berserk", "neutral", /* 100 */
4849  "no_attack", "no_damage", NULL, NULL, "activate_on_push",
4850  "activate_on_release", "is_water", "use_content_on_gen", NULL, "is_buildable", /* 110 */
4851  NULL, "blessed", "known_blessed"
4852 };
4853 
4863 {
4864  static char retbuf[MAX_BUF], retbuf_all[MAX_BUF];
4865  int i, all_count = 0, count;
4866 
4867  strcpy(retbuf, "");
4868  strcpy(retbuf_all, " all");
4869 
4870  /* Quick check, and probably fairly common */
4871  if (mt == MOVE_ALL) {
4872  stringbuffer_append_string(sb, "all");
4873  return;
4874  }
4875  if (mt == 0) {
4876  stringbuffer_append_string(sb, "0");
4877  return;
4878  }
4879 
4880  /* We basically slide the bits down. Why look at MOVE_ALL?
4881  * because we may want to return a string like 'all -swim',
4882  * and if we just looked at mt, we couldn't get that.
4883  */
4884  for (i = MOVE_ALL, count = 0; i != 0; i >>= 1, count++) {
4885  if (mt&(1<<count)) {
4886  strcat(retbuf, " ");
4887  strcat(retbuf, move_name[count]);
4888  } else {
4889  strcat(retbuf_all, " -");
4890  strcat(retbuf_all, move_name[count]);
4891  all_count++;
4892  }
4893  }
4894  /* Basically, if there is a single negation, return it, eg
4895  * 'all -swim'. But more than that, just return the
4896  * enumerated values. It doesn't make sense to return
4897  * 'all -walk -fly_low' - it is shorter to return 'fly_high swim'
4898  */
4899  if (all_count <= 1)
4900  stringbuffer_append_string(sb, retbuf_all+1);
4901  else
4902  stringbuffer_append_string(sb, retbuf+1);
4903 }
4904 
4906 static inline void ADD_STRINGLINE_ENTRY(StringBuffer *sb, const char *name, const char *value) {
4909  stringbuffer_append_string(sb, "\n");
4910 }
4911 
4913 static inline void FAST_SAVE_LONG(StringBuffer *sb, const char *name, const long value) {
4916  stringbuffer_append_char(sb, '\n');
4917 }
4918 
4920 static inline void FAST_SAVE_DOUBLE(StringBuffer *sb, const char *name, const double value) {
4921  stringbuffer_append_printf(sb, "%s%f\n", name, value);
4922 }
4923 
4931  for (int i = 0; i < 4; i++) {
4932  int idx = ffs((*diff)[i]);
4933  if (idx != 0) {
4934  int bit = idx - 1;
4935  // Clear difference bit.
4936  (*diff)[i] &= ~(1 << bit);
4937  return 32*i + bit;
4938  }
4939  }
4940  return -1;
4941 }
4942 
4956 void get_ob_diff(StringBuffer *sb, const object *op, const object *op2) {
4957  static char buf2[64];
4958  int tmp;
4959  int i;
4960  key_value *my_field;
4961  key_value *arch_field;
4962 
4963  /* This saves the key/value lists. We do it first so that any
4964  * keys that match field names will be overwritten by the loader.
4965  */
4966  for (my_field = op->key_values; my_field != NULL; my_field = my_field->next) {
4967  /* Find the field in the opposing member. */
4968  arch_field = object_get_key_value(op2, my_field->key);
4969 
4970  /* If there's no partnering field, or it's got a different value, save our field. */
4971  if (arch_field == NULL || my_field->value != arch_field->value) {
4972  stringbuffer_append_string(sb, my_field->key);
4973  stringbuffer_append_string(sb, " ");
4974  /* If this is null, then saving it as a space should
4975  * cause it to be null again.
4976  */
4977  if (my_field->value)
4978  stringbuffer_append_string(sb, my_field->value);
4979  stringbuffer_append_string(sb, "\n");
4980  }
4981  }
4982  /* We don't need to worry about the arch's extra fields - they
4983  * will get taken care of the object_copy() function.
4984  */
4985 
4986  if (op->name && op->name != op2->name) {
4987  ADD_STRINGLINE_ENTRY(sb, "name ", op->name);
4988  }
4989  if (op->name_pl && op->name_pl != op2->name_pl) {
4990  ADD_STRINGLINE_ENTRY(sb, "name_pl ", op->name_pl);
4991  }
4992  if (op->anim_suffix && op->anim_suffix != op2->anim_suffix) {
4993  ADD_STRINGLINE_ENTRY(sb, "anim_suffix ", op->anim_suffix);
4994  }
4995  if (op->custom_name && op->custom_name != op2->custom_name) {
4996  ADD_STRINGLINE_ENTRY(sb, "custom_name ", op->custom_name);
4997  }
4998  if (op->title && op->title != op2->title) {
4999  ADD_STRINGLINE_ENTRY(sb, "title ", op->title);
5000  }
5001  if (op->race && op->race != op2->race) {
5002  ADD_STRINGLINE_ENTRY(sb, "race ", op->race);
5003  }
5004  if (op->slaying && op->slaying != op2->slaying) {
5005  ADD_STRINGLINE_ENTRY(sb, "slaying ", op->slaying);
5006  }
5007  if (op->skill && op->skill != op2->skill) {
5008  ADD_STRINGLINE_ENTRY(sb, "skill ", op->skill);
5009  }
5010  if (op->msg && op->msg != op2->msg) {
5011  stringbuffer_append_string(sb, "msg\n");
5012  stringbuffer_append_string(sb, op->msg);
5013  stringbuffer_append_string(sb, "endmsg\n");
5014  }
5015  if (op->lore && op->lore != op2->lore) {
5016  stringbuffer_append_string(sb, "lore\n");
5017  stringbuffer_append_string(sb, op->lore);
5018  stringbuffer_append_string(sb, "endlore\n");
5019  }
5020  if (op->other_arch != op2->other_arch && op->other_arch != NULL && op->other_arch->name) {
5021  ADD_STRINGLINE_ENTRY(sb, "other_arch ", op->other_arch->name);
5022  }
5023  if (op->face != op2->face) {
5024  ADD_STRINGLINE_ENTRY(sb, "face ", op->face->name);
5025  }
5026 
5027  if (op->animation != op2->animation) {
5028  if (op->animation) {
5029  ADD_STRINGLINE_ENTRY(sb, "animation ", op->animation->name);
5030  if (!QUERY_FLAG (op, FLAG_ANIMATE)) {
5031  stringbuffer_append_string(sb, "is_animated 0\n");
5032  }
5033  } else {
5034  stringbuffer_append_string(sb, "animation NONE\n");
5035  }
5036  }
5037  if (op->stats.Str != op2->stats.Str)
5038  FAST_SAVE_LONG(sb, "Str ", op->stats.Str);
5039  if (op->stats.Dex != op2->stats.Dex)
5040  FAST_SAVE_LONG(sb, "Dex ", op->stats.Dex);
5041  if (op->stats.Con != op2->stats.Con)
5042  FAST_SAVE_LONG(sb, "Con ", op->stats.Con);
5043  if (op->stats.Wis != op2->stats.Wis)
5044  FAST_SAVE_LONG(sb, "Wis ", op->stats.Wis);
5045  if (op->stats.Pow != op2->stats.Pow)
5046  FAST_SAVE_LONG(sb, "Pow ", op->stats.Pow);
5047  if (op->stats.Cha != op2->stats.Cha)
5048  FAST_SAVE_LONG(sb, "Cha ", op->stats.Cha);
5049  if (op->stats.Int != op2->stats.Int)
5050  FAST_SAVE_LONG(sb, "Int ", op->stats.Int);
5051  if (op->stats.hp != op2->stats.hp)
5052  FAST_SAVE_LONG(sb, "hp ", op->stats.hp);
5053  if (op->stats.maxhp != op2->stats.maxhp)
5054  FAST_SAVE_LONG(sb, "maxhp ", op->stats.maxhp);
5055  if (op->stats.sp != op2->stats.sp)
5056  FAST_SAVE_LONG(sb, "sp ", op->stats.sp);
5057  if (op->stats.maxsp != op2->stats.maxsp)
5058  FAST_SAVE_LONG(sb, "maxsp ", op->stats.maxsp);
5059  if (op->stats.grace != op2->stats.grace)
5060  FAST_SAVE_LONG(sb, "grace ", op->stats.grace);
5061  if (op->stats.maxgrace != op2->stats.maxgrace)
5062  FAST_SAVE_LONG(sb, "maxgrace ", op->stats.maxgrace);
5063 
5064  if (op->stats.exp != op2->stats.exp) {
5065  snprintf(buf2, sizeof(buf2), "%"FMT64, op->stats.exp);
5066  ADD_STRINGLINE_ENTRY(sb, "exp ", buf2);
5067  }
5068 
5069  if (op->total_exp != op2->total_exp) {
5070  snprintf(buf2, sizeof(buf2), "%"FMT64, op->total_exp);
5071  ADD_STRINGLINE_ENTRY(sb, "total_exp ", buf2);
5072  }
5073 
5074  if (op->expmul != op2->expmul)
5075  FAST_SAVE_DOUBLE(sb, "expmul ", op->expmul);
5076  if (op->stats.food != op2->stats.food)
5077  FAST_SAVE_LONG(sb, "food ", op->stats.food);
5078  if (op->stats.dam != op2->stats.dam)
5079  FAST_SAVE_LONG(sb, "dam ", op->stats.dam);
5080  if (op->stats.luck != op2->stats.luck)
5081  FAST_SAVE_LONG(sb, "luck ", op->stats.luck);
5082  if (op->stats.wc != op2->stats.wc)
5083  FAST_SAVE_LONG(sb, "wc ", op->stats.wc);
5084  if (op->stats.ac != op2->stats.ac)
5085  FAST_SAVE_LONG(sb, "ac ", op->stats.ac);
5086  if (op->x != op2->x)
5087  FAST_SAVE_LONG(sb, "x ", op->x);
5088  if (op->y != op2->y)
5089  FAST_SAVE_LONG(sb, "y ", op->y);
5090  if (op->speed != op2->speed) {
5091  FAST_SAVE_DOUBLE(sb, "speed ", op->speed);
5092  }
5093  if (op->speed > 0 && op->speed_left != op2->speed_left) {
5094  FAST_SAVE_DOUBLE(sb, "speed_left ", op->speed_left);
5095  }
5096  if (op->weapon_speed != op2->weapon_speed) {
5097  FAST_SAVE_DOUBLE(sb, "weapon_speed ", op->weapon_speed);
5098  }
5099  if (op->weapon_speed > 0 && op->weapon_speed_left != op2->weapon_speed_left) {
5100  FAST_SAVE_DOUBLE(sb, "weapon_speed_left ", op->weapon_speed_left);
5101  }
5102  if (op->move_status != op2->move_status)
5103  FAST_SAVE_LONG(sb, "move_state ", op->move_status);
5104  if (op->attack_movement != op2->attack_movement)
5105  FAST_SAVE_LONG(sb, "attack_movement ", op->attack_movement);
5106  if (op->nrof != op2->nrof)
5107  FAST_SAVE_LONG(sb, "nrof ", op->nrof);
5108  if (op->level != op2->level)
5109  FAST_SAVE_LONG(sb, "level ", op->level);
5110  if (op->direction != op2->direction)
5111  FAST_SAVE_LONG(sb, "direction ", op->direction);
5112  if (op->type != op2->type)
5113  FAST_SAVE_LONG(sb, "type ", op->type);
5114  if (op->subtype != op2->subtype)
5115  FAST_SAVE_LONG(sb, "subtype ", op->subtype);
5116  if (op->attacktype != op2->attacktype)
5117  FAST_SAVE_LONG(sb, "attacktype ", op->attacktype);
5118 
5119  for (tmp = 0; tmp < NROFATTACKS; tmp++) {
5120  if (op->resist[tmp] != op2->resist[tmp]) {
5121  stringbuffer_append_string(sb, "resist_");
5122  FAST_SAVE_LONG(sb, resist_save[tmp], op->resist[tmp]);
5123  }
5124  }
5125 
5126  if (op->path_attuned != op2->path_attuned)
5127  FAST_SAVE_LONG(sb, "path_attuned ", op->path_attuned);
5128  if (op->path_repelled != op2->path_repelled)
5129  FAST_SAVE_LONG(sb, "path_repelled ", op->path_repelled);
5130  if (op->path_denied != op2->path_denied)
5131  FAST_SAVE_LONG(sb, "path_denied ", op->path_denied);
5132  if (op->material != op2->material)
5133  FAST_SAVE_LONG(sb, "material ", op->material);
5134  if (op->materialname && op->materialname != op2->materialname) {
5135  ADD_STRINGLINE_ENTRY(sb, "materialname ", op->materialname);
5136  }
5137  if (op->value != op2->value)
5138  FAST_SAVE_LONG(sb, "value ", op->value);
5139  if (op->carrying != op2->carrying)
5140  FAST_SAVE_LONG(sb, "carrying ", op->carrying);
5141  if (op->weight != op2->weight)
5142  FAST_SAVE_LONG(sb, "weight ", op->weight);
5143  if (op->invisible != op2->invisible)
5144  FAST_SAVE_LONG(sb, "invisible ", op->invisible);
5145  if (op->state != op2->state)
5146  FAST_SAVE_LONG(sb, "state ", op->state);
5147  if (op->magic != op2->magic)
5148  FAST_SAVE_LONG(sb, "magic ", op->magic);
5149  if (op->last_heal != op2->last_heal)
5150  FAST_SAVE_LONG(sb, "last_heal ", op->last_heal);
5151  if (op->last_sp != op2->last_sp)
5152  FAST_SAVE_LONG(sb, "last_sp ", op->last_sp);
5153  if (op->last_grace != op2->last_grace)
5154  FAST_SAVE_LONG(sb, "last_grace ", op->last_grace);
5155  if (op->last_eat != op2->last_eat)
5156  FAST_SAVE_LONG(sb, "last_eat ", op->last_eat);
5158  FAST_SAVE_LONG(sb, "connected ", tmp);
5159  if (op->glow_radius != op2->glow_radius)
5160  FAST_SAVE_LONG(sb, "glow_radius ", op->glow_radius);
5161  if (op->randomitems != op2->randomitems) {
5162  ADD_STRINGLINE_ENTRY(sb, "randomitems ", op->randomitems ? op->randomitems->name : "none");
5163  }
5164 
5165  if (op->run_away != op2->run_away)
5166  FAST_SAVE_LONG(sb, "run_away ", op->run_away);
5167  if (op->pick_up != op2->pick_up)
5168  FAST_SAVE_LONG(sb, "pick_up ", op->pick_up);
5169  if (op->weight_limit != op2->weight_limit)
5170  FAST_SAVE_LONG(sb, "container ", op->weight_limit);
5171  if (op->will_apply != op2->will_apply)
5172  FAST_SAVE_LONG(sb, "will_apply ", op->will_apply);
5173  if (op->smoothlevel != op2->smoothlevel)
5174  FAST_SAVE_LONG(sb, "smoothlevel ", op->smoothlevel);
5175 
5176  if (op->map_layer != op2->map_layer)
5177  ADD_STRINGLINE_ENTRY(sb, "map_layer ", map_layer_name[op->map_layer]);
5178 
5179  if (op->weapontype && op->weapontype != op2->weapontype) {
5180  FAST_SAVE_LONG(sb, "weapontype ", op->weapontype);
5181  }
5182  if (op->client_type && op->client_type != op2->client_type) {
5183  FAST_SAVE_LONG(sb, "client_type ", op->client_type);
5184  }
5185 
5186  if (op->item_power != op2->item_power) {
5187  FAST_SAVE_LONG(sb, "item_power ", op->item_power);
5188  }
5189 
5190  if (op->duration != op2->duration)
5191  FAST_SAVE_LONG(sb, "duration ", op->duration);
5192 
5193  if (op->range != op2->range)
5194  FAST_SAVE_LONG(sb, "range ", op->range);
5195 
5196  if (op->range_modifier != op2->range_modifier)
5197  FAST_SAVE_LONG(sb, "range_modifier ", op->range_modifier);
5198 
5199  if (op->duration_modifier != op2->duration_modifier)
5200  FAST_SAVE_LONG(sb, "duration_modifier ", op->duration_modifier);
5201 
5202  if (op->dam_modifier != op2->dam_modifier)
5203  FAST_SAVE_LONG(sb, "dam_modifier ", op->dam_modifier);
5204 
5205  if (op->gen_sp_armour != op2->gen_sp_armour) {
5206  FAST_SAVE_LONG(sb, "gen_sp_armour ", op->gen_sp_armour);
5207  }
5208 
5209  /* I've kept the old int move type saving code commented out.
5210  * In an ideal world, we'd know if we want to do a quick
5211  * save (say to a temp map, where we don't care about strings),
5212  * or a slower save/dm dump, where printing out strings is handy.
5213  */
5214  if (op->move_type != op2->move_type) {
5215  /*FAST_SAVE_LONG(sb, "move_type ", op->move_type)*/
5216  stringbuffer_append_string(sb, "move_type ");
5217  get_string_move_type(sb, op->move_type);
5218  stringbuffer_append_string(sb, "\n");
5219  }
5220  if (op->move_block != op2->move_block) {
5221  /*FAST_SAVE_LONG(sb, "move_block ", op->move_block)*/
5222  stringbuffer_append_string(sb, "move_block ");
5223  get_string_move_type(sb, op->move_block);
5224  stringbuffer_append_string(sb, "\n");
5225  }
5226  if (op->move_allow != op2->move_allow) {
5227  /*FAST_SAVE_LONG(sb, "move_allow ", op->move_allow);*/
5228  stringbuffer_append_string(sb, "move_allow ");
5229  get_string_move_type(sb, op->move_allow);
5230  stringbuffer_append_string(sb, "\n");
5231  }
5232  if (op->move_on != op2->move_on) {
5233  /*FAST_SAVE_LONG(sb, "move_on ", op->move_on);*/
5234  stringbuffer_append_string(sb, "move_on ");
5235  get_string_move_type(sb, op->move_on);
5236  stringbuffer_append_string(sb, "\n");
5237  }
5238  if (op->move_off != op2->move_off) {
5239  /*FAST_SAVE_LONG(sb, "move_off ", op->move_off);*/
5240  stringbuffer_append_string(sb, "move_off ");
5241  get_string_move_type(sb, op->move_off);
5242  stringbuffer_append_string(sb, "\n");
5243  }
5244  if (op->move_slow != op2->move_slow) {
5245  /*FAST_SAVE_LONG(sb, "move_slow ", op->move_slow);*/
5246  stringbuffer_append_string(sb, "move_slow ");
5247  get_string_move_type(sb, op->move_slow);
5248  stringbuffer_append_string(sb, "\n");
5249  }
5250 
5251  if (op->move_slow_penalty != op2->move_slow_penalty) {
5252  FAST_SAVE_DOUBLE(sb, "move_slow_penalty ", op->move_slow_penalty);
5253  }
5254 
5255  ob_flags diff_flags;
5256  compare_flags(&diff_flags, op, op2);
5257  int flag;
5258  while ((flag = flags_differ(&diff_flags)) != -1) {
5259  if (flag_names[flag]) {
5260  ADD_STRINGLINE_ENTRY(sb, flag_names[flag], QUERY_FLAG(op, flag) ? " 1" : " 0");
5261  }
5262  }
5263 
5264  /* Save body locations */
5265  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
5266  if (op->body_info[i] != op2->body_info[i]) {
5267  stringbuffer_append_string(sb, body_locations[i].save_name);
5268  FAST_SAVE_LONG(sb, " ", op->body_info[i]);
5269  }
5270  }
5271 }
5272 
5277 void save_object_in_sb(StringBuffer *sb, object *op, const int flag) {
5278  /* If the object has no_save set, just return */
5279  if (QUERY_FLAG(op, FLAG_NO_SAVE)) {
5280  return;
5281  }
5282 
5283  /* Even if the object does have an owner, it would seem that we should
5284  * still save it.
5285  */
5286  if (object_get_owner(op) != NULL) {
5287  return;
5288  }
5289 
5290  /* If it is unpaid and we don't want to save those, just return. */
5291  if (!(flag&SAVE_FLAG_SAVE_UNPAID) && (QUERY_FLAG(op, FLAG_UNPAID))) {
5292  return;
5293  }
5294 
5295  archetype *at = op->arch;
5296  if (at == NULL)
5297  at = empty_archetype;
5298 
5299  ADD_STRINGLINE_ENTRY(sb, "arch ", at->name);
5300 
5301  if (op->arch->reference_count > 0) {
5302  /* The object is a custom item/monster, so we handle its save differently.
5303  * We compare the custom archetype to the "original" one, then only save hp/gr/sp
5304  * which are the only values we can't recompute later - all others are modified by items in inventory.
5305  * Note that hp/gr/sp will appear twice in save, but last value will take precedence.
5306  */
5307  archetype *original = find_archetype(op->arch->name);
5308  if (!original) {
5309  LOG(llevError, "could not find original archetype %s for custom monster!\n", op->arch->name);
5310  abort();
5311  }
5312  get_ob_diff(sb, &op->arch->clone, &original->clone);
5313  if (op->stats.hp != op->arch->clone.stats.hp)
5314  FAST_SAVE_LONG(sb, "hp ", op->stats.hp);
5315  if (op->stats.sp != op->arch->clone.stats.sp)
5316  FAST_SAVE_LONG(sb, "sp ", op->stats.sp);
5317  if (op->stats.grace != op->arch->clone.stats.grace)
5318  FAST_SAVE_LONG(sb, "grace ", op->stats.grace);
5319  if (op->x != op->arch->clone.x)
5320  FAST_SAVE_LONG(sb, "x ", op->x);
5321  if (op->y != op->arch->clone.y)
5322  FAST_SAVE_LONG(sb, "y ", op->y);
5323  } else if (op->artifact != NULL) {
5324  /* if op is an artifact, then find the "standard" artifact to use that for the diff */
5325  object *base;
5326  const artifact *artifact;
5327 
5328  artifact = find_artifact(op, op->artifact);
5329  if (artifact == NULL) {
5330  LOG(llevError, "could not find artifact %s [%d] to save data\n", op->artifact, op->type);
5331  get_ob_diff(sb, op, &at->clone);
5332  } else {
5333  ADD_STRINGLINE_ENTRY(sb, "artifact ", op->artifact);
5334  base = arch_to_object(at);
5336  get_ob_diff(sb, op, base);
5338  }
5339  } else {
5340  get_ob_diff(sb, op, &at->clone);
5341  }
5342 
5343  /* Eneq(@csd.uu.se): Added this to allow containers being saved with contents*/
5345  save_object_in_sb(sb, tmp, flag);
5346  FOR_INV_FINISH();
5347 
5348  stringbuffer_append_string(sb, "end\n");
5349 }
5350 
5363 int save_object(FILE *fp, object *op, int flag) {
5365  save_object_in_sb(sb, op, flag);
5366  char *cp = stringbuffer_finish(sb);
5367  if (fputs(cp, fp) == EOF) {
5368  free(cp);
5369  return SAVE_ERROR_WRITE;
5370  } else {
5371  free(cp);
5372  return SAVE_ERROR_OK;
5373  }
5374 }
5375 
5377  if (op->map) {
5378  sstring death_animation = object_get_value(op, "death_animation");
5379  if (death_animation != NULL) {
5380  object *death = create_archetype(death_animation);
5381 
5382  if (death != NULL) {
5383  object_insert_in_map_at(death, op->map, op, 0, op->x, op->y);
5384  if (death->arch->more)
5385  object_fix_multipart(death);
5386  }
5387  }
5388  }
5389 }
5390 
5391 object *find_force(object *op, const char *name) {
5392  assert(op != NULL);
5394 }
5395 
5396 object *add_force(object *op, const char *name, int duration) {
5397  assert(op != NULL);
5398  object *force = find_force(op, name);
5399  if (force == NULL) {
5401  force->slaying = add_string(name);
5403  }
5404 
5405  if (duration != 0) {
5406  force->speed = 0.01;
5407  force->speed_left = -duration;
5408  } else {
5409  force->speed = 0;
5410  }
5411 
5412  // Even if duration is zero, a force could be set previously.
5414 
5415  return force;
5416 }
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Definition: object.h:68
Settings::casting_time
uint8_t casting_time
Definition: global.h:267
obj::weapon_speed
float weapon_speed
Definition: object.h:334
give.next
def next
Definition: give.py:44
obj::move_off
MoveType move_off
Definition: object.h:434
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Definition: map.h:173
get_weight_limit
uint32_t get_weight_limit(int stat)
Definition: living.c:2362
object_find_first_free_spot
int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y)
Definition: object.c:3570
UP_OBJ_FACE
#define UP_OBJ_FACE
Definition: object.h:520
empty_archetype
EXTERN archetype * empty_archetype
Definition: global.h:142
PLAYER
@ PLAYER
Definition: object.h:107
obj::attack_movement
uint16_t attack_movement
Definition: object.h:397
artifact
struct artifactstruct artifact
FREE_AND_CLEAR_STR_IF
#define FREE_AND_CLEAR_STR_IF(xyz)
Definition: global.h:199
freedir
int freedir[SIZEOFFREE]
Definition: object.c:317
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:532
UPD_FACE
#define UPD_FACE
Definition: newclient.h:317
add_refcount
sstring add_refcount(sstring str)
Definition: shstr.c:210
liv::dam
int16_t dam
Definition: living.h:46
object_free
void object_free(object *ob, int flags)
Definition: object.c:1578
INS_NO_WALK_ON
#define INS_NO_WALK_ON
Definition: object.h:569
add_string
sstring add_string(const char *str)
Definition: shstr.c:124
pl::count
uint32_t count
Definition: player.h:122
object_find_by_flag_applied
object * object_find_by_flag_applied(const object *who, int flag)
Definition: object.c:4200
object_remove
void object_remove(object *op)
Definition: object.c:1819
UP_OBJ_REMOVE
#define UP_OBJ_REMOVE
Definition: object.h:518
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
permute
static void permute(int *, int, int)
Definition: object.c:3589
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
object_sum_weight
signed long object_sum_weight(object *op)
Definition: object.c:572
object_set_enemy
void object_set_enemy(object *op, object *enemy)
Definition: object.c:919
pl::transport
object * transport
Definition: player.h:213
NUM_BODY_LOCATIONS
#define NUM_BODY_LOCATIONS
Definition: object.h:13
objarray
static object objarray[STARTMAX]
Definition: object.c:289
MAP_SAVING
#define MAP_SAVING
Definition: map.h:134
obj::face
const Face * face
Definition: object.h:336
obj::move_block
MoveType move_block
Definition: object.h:431
object_find_by_type2
object * object_find_by_type2(const object *who, int type1, int type2)
Definition: object.c:4008
object_free_key_values
void object_free_key_values(object *op)
Definition: object.c:958
GET_MAP_TOP
#define GET_MAP_TOP(M, X, Y)
Definition: map.h:175
object_find_by_type_and_skill
object * object_find_by_type_and_skill(const object *who, int type, const char *skill)
Definition: object.c:4154
llevError
@ llevError
Definition: logger.h:11
give_artifact_abilities
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.c:238
FABS
#define FABS(x)
Definition: define.h:22
FLAG_CLIENT_ANIM_RANDOM
#define FLAG_CLIENT_ANIM_RANDOM
Definition: define.h:241
find_skill_by_number
object * find_skill_by_number(object *who, int skillno)
Definition: main.c:376
MOVE_ALL
#define MOVE_ALL
Definition: define.h:398
object_reset
void object_reset(object *op)
Definition: object.c:938
object_copy_owner
void object_copy_owner(object *op, object *clone)
Definition: object.c:897
object_create_clone
object * object_create_clone(object *asrc)
Definition: object.c:3880
FLAG_OVERLAY_FLOOR
#define FLAG_OVERLAY_FLOOR
Definition: define.h:255
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
stringbuffer_append_char
void stringbuffer_append_char(StringBuffer *sb, const char c)
Definition: stringbuffer.c:104
object_find_by_type_and_arch_name
object * object_find_by_type_and_arch_name(const object *who, int type, const char *name)
Definition: object.c:4248
object_add_weight
void object_add_weight(object *op, signed long weight)
Definition: object.c:2809
object_update
void object_update(object *op, int action)
Definition: object.c:1420
diamondslots.x
x
Definition: diamondslots.py:15
FLAG_STARTEQUIP
#define FLAG_STARTEQUIP
Definition: define.h:268
obj::count
tag_t count
Definition: object.h:302
Statistics::spell_merges
uint64_t spell_merges
Definition: global.h:353
obj::map
struct mapdef * map
Definition: object.h:300
SIZEOFFREE1
#define SIZEOFFREE1
Definition: define.h:153
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
obj::race
sstring race
Definition: object.h:321
liv::maxgrace
int16_t maxgrace
Definition: living.h:45
ob_count
EXTERN long ob_count
Definition: global.h:146
obj::value
int32_t value
Definition: object.h:355
liv::wc
int8_t wc
Definition: living.h:37
FLAG_IS_TURNABLE
#define FLAG_IS_TURNABLE
Definition: define.h:256
STARTMAX
#define STARTMAX
Definition: config.h:515
out_of_map
int out_of_map(mapstruct *m, int x, int y)
Definition: map.c:2312
liv::Str
int8_t Str
Definition: living.h:36
FALSE
#define FALSE
Definition: compat.h:14
SET_MAP_TOP
#define SET_MAP_TOP(M, X, Y, tmp)
Definition: map.h:180
object_new
object * object_new(void)
Definition: object.c:1255
obj::gen_sp_armour
int8_t gen_sp_armour
Definition: object.h:368
object_find_by_arch_name
object * object_find_by_arch_name(const object *who, const char *name)
Definition: object.c:4223
UPD_WEIGHT
#define UPD_WEIGHT
Definition: newclient.h:316
obj::path_attuned
uint32_t path_attuned
Definition: object.h:348
liv::maxhp
int16_t maxhp
Definition: living.h:41
objects
object * objects
Definition: object.c:294
pl::socket
socket_struct socket
Definition: player.h:107
flag_names
static const char *const flag_names[NUM_FLAGS+1]
Definition: object.c:4821
pl
Definition: player.h:105
FLAG_OBJ_ORIGINAL
#define FLAG_OBJ_ORIGINAL
Definition: define.h:357
TRAP
@ TRAP
Definition: object.h:241
object_distance
int object_distance(const object *ob1, const object *ob2)
Definition: object.c:3632
OB_SPELL_TAG_MATCH
#define OB_SPELL_TAG_MATCH(op, count)
Definition: object.h:93
obj::artifact
sstring artifact
Definition: object.h:317
get_ob_diff
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Definition: object.c:4956
object_merge_spell
void object_merge_spell(object *op, int16_t x, int16_t y)
Definition: object.c:2109
obj::invisible
int16_t invisible
Definition: object.h:365
arch_present_in_ob
object * arch_present_in_ob(const archetype *at, const object *op)
Definition: object.c:3193
object_set_flag_inv
void object_set_flag_inv(object *op, int flag)
Definition: object.c:3210
MoveType
unsigned char MoveType
Definition: define.h:417
object_matches_string
int object_matches_string(object *pl, object *op, const char *name)
Definition: object.c:4545
_key_value::key
const char * key
Definition: object.h:41
guildjoin.ob
ob
Definition: guildjoin.py:42
liv::hp
int16_t hp
Definition: living.h:40
obj::range_modifier
uint8_t range_modifier
Definition: object.h:412
commongive.inv
inv
Definition: commongive.py:28
blank_face
const Face * blank_face
Definition: image.c:35
obj::custom_name
sstring custom_name
Definition: object.h:438
CALLOC
#define CALLOC(x, y)
Definition: compat.h:31
NUM_FLAGS
#define NUM_FLAGS
Definition: define.h:374
GET_MAP_MOVE_SLOW
#define GET_MAP_MOVE_SLOW(M, X, Y)
Definition: map.h:198
pl::ob
object * ob
Definition: player.h:176
SKILL
@ SKILL
Definition: object.h:143
compare_ob_value_lists_one
static int compare_ob_value_lists_one(const object *, const object *)
Definition: object.c:363
object_find_by_type_applied
object * object_find_by_type_applied(const object *who, int type)
Definition: object.c:4054
object_can_merge
int object_can_merge(object *ob1, object *ob2)
Definition: object.c:433
RUNE
@ RUNE
Definition: object.h:240
init_objects
void init_objects(void)
Definition: object.c:327
give.top
def top
Definition: give.py:42
ob_blocked
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
Definition: map.c:488
obj::path_denied
uint32_t path_denied
Definition: object.h:350
Ice.tmp
int tmp
Definition: Ice.py:207
flags_differ
int flags_differ(ob_flags *diff)
Definition: object.c:4930
GET_MAP_PLAYER
#define GET_MAP_PLAYER(M, X, Y)
Definition: map.h:169
FLAG_NO_MAGIC
#define FLAG_NO_MAGIC
Definition: define.h:276
remove_friendly_object
void remove_friendly_object(object *op)
Definition: friend.c:56
P_NO_MAGIC
#define P_NO_MAGIC
Definition: map.h:228
object_set_value_s
static int object_set_value_s(object *, const char *, const char *, int)
Definition: object.c:4387
llevMonster
@ llevMonster
Definition: logger.h:14
obj::smoothlevel
uint8_t smoothlevel
Definition: object.h:427
TRANSPORT
@ TRANSPORT
Definition: object.h:108
UPD_NROF
#define UPD_NROF
Definition: newclient.h:321
FOR_ABOVE_PREPARE
#define FOR_ABOVE_PREPARE(op_, it_)
Definition: define.h:687
flags
static const flag_definition flags[]
Definition: gridarta-types-convert.c:101
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
obj::msg
sstring msg
Definition: object.h:325
FLAG_BLOCKSVIEW
#define FLAG_BLOCKSVIEW
Definition: define.h:269
obj::body_info
int8_t body_info[NUM_BODY_LOCATIONS]
Definition: object.h:378
skills.h
object_free_all_data
void object_free_all_data(void)
Definition: object.c:771
free_arch
void free_arch(archetype *at)
Definition: arch.cpp:172
MAP_DARKNESS
#define MAP_DARKNESS(m)
Definition: map.h:75
FLAG_INV_LOCKED
#define FLAG_INV_LOCKED
Definition: define.h:329
FOR_OB_AND_ABOVE_FINISH
#define FOR_OB_AND_ABOVE_FINISH()
Definition: define.h:743
P_IS_ALIVE
#define P_IS_ALIVE
Definition: map.h:238
Statistics::spell_hash_full
uint64_t spell_hash_full
Definition: global.h:354
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
events_execute_object_event
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Definition: events.cpp:274
resist_save
const EXTERN char *const resist_save[NROFATTACKS]
Definition: attack.h:139
obj::randomitems
struct treasureliststruct * randomitems
Definition: object.h:391
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
AB_NO_PASS
#define AB_NO_PASS
Definition: map.h:236
MAX
#define MAX(x, y)
Definition: compat.h:24
obj::expmul
double expmul
Definition: object.h:401
active_objects
object * active_objects
Definition: object.c:296
freearr_x
short freearr_x[SIZEOFFREE]
Definition: object.c:299
SAVE_ERROR_WRITE
#define SAVE_ERROR_WRITE
Definition: map.h:147
map_layer_name
const char *const map_layer_name[MAP_LAYERS]
Definition: map.c:45
obj::nrof
uint32_t nrof
Definition: object.h:337
FLAG_NO_PICK
#define FLAG_NO_PICK
Definition: define.h:239
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.c:305
obj::ox
int16_t ox
Definition: object.h:331
obj::duration_modifier
uint8_t duration_modifier
Definition: object.h:410
obj::duration
int16_t duration
Definition: object.h:409
find_artifact
const artifact * find_artifact(const object *op, const char *name)
Definition: artifact.c:590
FLAG_DIALOG_PARSED
#define FLAG_DIALOG_PARSED
Definition: define.h:243
archt
Definition: object.h:470
settings
struct Settings settings
Definition: init.c:39
FLAG_ALIVE
#define FLAG_ALIVE
Definition: define.h:230
animate_object
void animate_object(object *op, int dir)
Definition: anim.c:43
obj::last_heal
int32_t last_heal
Definition: object.h:362
esrv_send_item
void esrv_send_item(object *pl, object *op)
Definition: main.c:355
socket_struct::update_look
uint32_t update_look
Definition: newserver.h:104
INS_ABOVE_FLOOR_ONLY
#define INS_ABOVE_FLOOR_ONLY
Definition: object.h:568
object_merge
object * object_merge(object *op, object *top)
Definition: object.c:2031
FOR_OB_AND_ABOVE_PREPARE
#define FOR_OB_AND_ABOVE_PREPARE(op_)
Definition: define.h:739
FAST_SAVE_LONG
static void FAST_SAVE_LONG(StringBuffer *sb, const char *name, const long value)
Definition: object.c:4913
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.c:4317
FLAG_IS_A_TEMPLATE
#define FLAG_IS_A_TEMPLATE
Definition: define.h:366
obj::slaying
sstring slaying
Definition: object.h:322
LOOK_OBJ
#define LOOK_OBJ(ob)
Definition: object.h:508
free_string
void free_string(sstring str)
Definition: shstr.c:280
stringbuffer.h
m
static event_registration m
Definition: citylife.cpp:427
liv::maxsp
int16_t maxsp
Definition: living.h:43
object_free_inventory
void object_free_inventory(object *ob)
Definition: object.c:1554
liv::luck
int8_t luck
Definition: living.h:39
find_force
object * find_force(object *op, const char *name)
Definition: object.c:5391
autojail.who
who
Definition: autojail.py:3
object_get_key_value
key_value * object_get_key_value(const object *ob, const char *key)
Definition: object.c:4292
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Definition: map.h:131
obj::spell_tags
tag_t * spell_tags
Definition: object.h:441
OBJ_EXPAND
#define OBJ_EXPAND
Definition: config.h:516
object_find_by_type_subtype
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Definition: object.c:4272
liv::exp
int64_t exp
Definition: living.h:47
object_unset_flag_inv
void object_unset_flag_inv(object *op, int flag)
Definition: object.c:3227
object_find_by_type_without_flags
object * object_find_by_type_without_flags(const object *who, int type, int *flags, int num_flags)
Definition: object.c:3975
item.q
q
Definition: item.py:32
pl::next
struct pl * next
Definition: player.h:106
FMT64
#define FMT64
Definition: compat.h:16
NROF
static uint32_t NROF(const object *const ob)
Definition: object.h:612
expand_objects
static void expand_objects(void)
Definition: object.c:1213
object_sub_weight
void object_sub_weight(object *op, signed long weight)
Definition: object.c:1793
object_find_by_flag
object * object_find_by_flag(const object *who, int flag)
Definition: object.c:4177
object_dump_all
void object_dump_all(void)
Definition: object.c:708
disinfect.map
map
Definition: disinfect.py:4
ob_flags
uint32_t ob_flags[4]
Definition: object.h:254
object_copy_with_inv
void object_copy_with_inv(const object *src_ob, object *dest_ob)
Definition: object.c:1194
object_find_by_type_and_slaying
object * object_find_by_type_and_slaying(const object *who, int type, const char *slaying)
Definition: object.c:4129
FLAG_WAS_WIZ
#define FLAG_WAS_WIZ
Definition: define.h:234
obj::name
sstring name
Definition: object.h:314
P_NO_ERROR
#define P_NO_ERROR
Definition: map.h:241
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.c:1064
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:585
stringbuffer_finish_shared
sstring stringbuffer_finish_shared(StringBuffer *sb)
Definition: stringbuffer.c:85
object_update_turn_face
void object_update_turn_face(object *op)
Definition: object.c:1313
MOVE_WALK
#define MOVE_WALK
Definition: define.h:392
FLAG_KNOWN_CURSED
#define FLAG_KNOWN_CURSED
Definition: define.h:320
obj::path_repelled
uint32_t path_repelled
Definition: object.h:349
FOR_ABOVE_FINISH
#define FOR_ABOVE_FINISH()
Definition: define.h:694
obj::total_exp
int64_t total_exp
Definition: object.h:375
object_dump
void object_dump(const object *op, StringBuffer *sb)
Definition: object.c:649
liv::Cha
int8_t Cha
Definition: living.h:36
obj::name_pl
sstring name_pl
Definition: object.h:318
FOR_OB_AND_BELOW_FINISH
#define FOR_OB_AND_BELOW_FINISH()
Definition: define.h:754
HEAD
#define HEAD(op)
Definition: object.h:594
fatal
void fatal(enum fatal_error err)
Definition: utils.c:580
object_fix_multipart
void object_fix_multipart(object *tmp)
Definition: object.c:4655
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.c:95
object_can_pick
int object_can_pick(const object *who, const object *item)
Definition: object.c:3838
CONTAINER
@ CONTAINER
Definition: object.h:231
object_clear
void object_clear(object *op)
Definition: object.c:987
make_face_from_files.str
str
Definition: make_face_from_files.py:24
obj::speed_left
float speed_left
Definition: object.h:333
FLAG_FREED
#define FLAG_FREED
Definition: define.h:233
ADD_STRINGLINE_ENTRY
static void ADD_STRINGLINE_ENTRY(StringBuffer *sb, const char *name, const char *value)
Definition: object.c:4906
convert.action
action
Definition: convert.py:25
find_string
sstring find_string(const char *str)
Definition: shstr.c:236
query_short_name
void query_short_name(const object *op, char *buf, size_t size)
Definition: item.c:510
obj::prev
struct obj * prev
Definition: object.h:281
object_present_in_ob
object * object_present_in_ob(uint8_t type, const object *op)
Definition: object.c:3139
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
absdir
int absdir(int d)
Definition: object.c:3685
obj::carrying
int32_t carrying
Definition: object.h:372
FAST_SAVE_DOUBLE
static void FAST_SAVE_DOUBLE(StringBuffer *sb, const char *name, const double value)
Definition: object.c:4920
first_player
EXTERN player * first_player
Definition: global.h:115
FLAG_IS_WOODED
#define FLAG_IS_WOODED
Definition: define.h:330
obj::container
struct obj * container
Definition: object.h:294
obj::x
int16_t x
Definition: object.h:330
INS_NO_MERGE
#define INS_NO_MERGE
Definition: object.h:567
FLAG_DAMNED
#define FLAG_DAMNED
Definition: define.h:317
SET_MAP_FLAGS
#define SET_MAP_FLAGS(M, X, Y, C)
Definition: map.h:164
fix_object
void fix_object(object *op)
Definition: living.c:1126
CFweardisguise.tag
tag
Definition: CFweardisguise.py:25
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
object_increase_nrof
static void object_increase_nrof(object *op, uint32_t i)
Definition: object.c:2739
nrofallocobjects
int nrofallocobjects
Definition: object.c:291
FLAG_WIZPASS
#define FLAG_WIZPASS
Definition: define.h:314
maxfree
int maxfree[SIZEOFFREE]
Definition: object.c:311
LAMP
@ LAMP
Definition: object.h:201
GET_MAP_MOVE_BLOCK
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:193
obj::other_arch
struct archt * other_arch
Definition: object.h:419
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
get_string_move_type
static void get_string_move_type(StringBuffer *sb, MoveType mt)
Definition: object.c:4862
archt::more
struct archt * more
Definition: object.h:473
INS_BELOW_ORIGINATOR
#define INS_BELOW_ORIGINATOR
Definition: object.h:571
object_set_value
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.c:4470
sstring
const typedef char * sstring
Definition: global.h:40
disinfect.count
int count
Definition: disinfect.py:7
obj::speed
float speed
Definition: object.h:332
obj::weapontype
uint32_t weapontype
Definition: object.h:377
tag_t
uint32_t tag_t
Definition: object.h:12
P_PLAYER
#define P_PLAYER
Definition: map.h:237
liv::Con
int8_t Con
Definition: living.h:36
obj::client_type
uint16_t client_type
Definition: object.h:345
obj::below
struct obj * below
Definition: object.h:290
sproto.h
liv::food
int32_t food
Definition: living.h:48
free_dialog_information
void free_dialog_information(object *op)
Definition: dialog.c:32
FLAG_NO_DROP
#define FLAG_NO_DROP
Definition: define.h:288
FLAG_NO_SAVE
#define FLAG_NO_SAVE
Definition: define.h:244
obj::move_slow_penalty
float move_slow_penalty
Definition: object.h:436
FLAG_NO_STEAL
#define FLAG_NO_STEAL
Definition: define.h:342
FOR_OB_AND_BELOW_PREPARE
#define FOR_OB_AND_BELOW_PREPARE(op_)
Definition: define.h:750
mapdef
Definition: map.h:324
compare_flags
static void compare_flags(ob_flags *ret, const object *p, const object *q)
Definition: object.h:486
GET_MAP_MOVE_ON
#define GET_MAP_MOVE_ON(M, X, Y)
Definition: map.h:203
liv::Int
int8_t Int
Definition: living.h:36
obj::map_layer
uint8_t map_layer
Definition: object.h:428
free_objects
static object * free_objects
Definition: object.c:295
obj::animation
const Animations * animation
Definition: object.h:422
FREE_OBJ_DROP_ABOVE_FLOOR
#define FREE_OBJ_DROP_ABOVE_FLOOR
Definition: object.h:533
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
object_check_move_on
int object_check_move_on(object *op, object *originator)
Definition: object.c:2983
obj::material
uint16_t material
Definition: object.h:352
object_find_multi_free_spot_around
int object_find_multi_free_spot_around(const object *ob, const object *gen, int16_t *hx, int16_t *hy)
Definition: object.c:3267
ob_move_on
method_ret ob_move_on(object *op, object *victim, object *originator)
Definition: ob_methods.c:111
object_set_owner
void object_set_owner(object *op, object *owner)
Definition: object.c:844
MAP_WIDTH
#define MAP_WIDTH(m)
Definition: map.h:78
reduction_dir
static const int reduction_dir[SIZEOFFREE][3]
Definition: object.c:3723
SIZEOFFREE
#define SIZEOFFREE
Definition: define.h:155
stringbuffer_append_int64
void stringbuffer_append_int64(StringBuffer *sb, int64_t x)
Definition: stringbuffer.c:111
move_name
const char *const move_name[]
Definition: object.c:4802
P_OUT_OF_MAP
#define P_OUT_OF_MAP
Definition: map.h:250
MAX_BUF
#define MAX_BUF
Definition: define.h:35
artifactstruct
Definition: artifact.h:14
object_get_multi_size
void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy)
Definition: object.c:4714
INS_ON_TOP
#define INS_ON_TOP
Definition: object.h:570
find_insert_pos
static object * find_insert_pos(object *op, const int flag)
Definition: object.c:2277
obj::item_power
int8_t item_power
Definition: object.h:367
obj::lore
sstring lore
Definition: object.h:327
esrv_del_item
void esrv_del_item(player *pl, object *ob)
Definition: main.c:382
UP_OBJ_INSERT
#define UP_OBJ_INSERT
Definition: object.h:517
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:281
object_insert_to_free_spot_or_free
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:4761
obj::next
struct obj * next
Definition: object.h:280
offsetof
#define offsetof(type, member)
Definition: shstr.h:37
RANDOM
#define RANDOM()
Definition: define.h:644
StringBuffer
Definition: stringbuffer.c:25
statistics
struct Statistics statistics
Definition: init.c:100
FREE_AND_CLEAR_STR
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:197
MOVE_FLY_LOW
#define MOVE_FLY_LOW
Definition: define.h:393
FLAG_CLIENT_ANIM_SYNC
#define FLAG_CLIENT_ANIM_SYNC
Definition: define.h:240
guildbuy.ob2
ob2
Definition: guildbuy.py:23
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
obj::y
int16_t y
Definition: object.h:330
object_count_used
int object_count_used(void)
Definition: object.c:1753
obj::glow_radius
int8_t glow_radius
Definition: object.h:369
OUT_OF_REAL_MAP
#define OUT_OF_REAL_MAP(M, X, Y)
Definition: map.h:218
dirdiff
int dirdiff(int dir1, int dir2)
Definition: object.c:3703
obj::title
sstring title
Definition: object.h:320
obj::arch
struct archt * arch
Definition: object.h:418
object_set_msg
void object_set_msg(object *op, const char *msg)
Definition: object.c:4781
obj::oy
int16_t oy
Definition: object.h:331
object_count_active
int object_count_active(void)
Definition: object.c:1769
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
INS_MAP_LOAD
#define INS_MAP_LOAD
Definition: object.h:572
SK_WOODSMAN
@ SK_WOODSMAN
Definition: skills.h:40
obj::type
uint8_t type
Definition: object.h:343
obj::last_grace
int16_t last_grace
Definition: object.h:364
object_count_free
int object_count_free(void)
Definition: object.c:1737
object_find_by_tag_global
object * object_find_by_tag_global(tag_t i)
Definition: object.c:731
roll-o-matic.stop
def stop()
Definition: roll-o-matic.py:78
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Definition: define.h:246
guildbuy.ob1
ob1
Definition: guildbuy.py:22
object_find_by_tag
object * object_find_by_tag(const object *who, tag_t tag)
Definition: object.c:4031
obj::move_slow
MoveType move_slow
Definition: object.h:435
obj::stats
living stats
Definition: object.h:373
SPELL_MAPPINGS
#define SPELL_MAPPINGS
Definition: global.h:147
obj::direction
int8_t direction
Definition: object.h:339
FREE_AND_CLEAR
#define FREE_AND_CLEAR(xyz)
Definition: global.h:192
archt::clone
object clone
Definition: object.h:474
obj::state
uint8_t state
Definition: object.h:354
SIZEOFFREE2
#define SIZEOFFREE2
Definition: define.h:154
obj::contr
struct pl * contr
Definition: object.h:279
SCRIPT_FIX_NOTHING
#define SCRIPT_FIX_NOTHING
Definition: global.h:380
map_find_by_archetype
object * map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at)
Definition: object.c:3089
obj::weight
int32_t weight
Definition: object.h:370
liv::Dex
int8_t Dex
Definition: living.h:36
item
Definition: item.py:1
object_remove_from_active_list
void object_remove_from_active_list(object *op)
Definition: object.c:1378
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
P_NEED_UPDATE
#define P_NEED_UPDATE
Definition: map.h:240
liv::Wis
int8_t Wis
Definition: living.h:36
archt::reference_count
int reference_count
Definition: object.h:477
get_button_value
int get_button_value(const object *button)
Definition: button.c:749
liv::grace
int16_t grace
Definition: living.h:44
object_set_cheat
void object_set_cheat(object *op)
Definition: object.c:3245
give.op
op
Definition: give.py:33
object_find_free_spot
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.c:3530
autojail.value
value
Definition: autojail.py:6
object_insert_in_map
object * object_insert_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:2341
object_value_set
bool object_value_set(const object *op, const char *const key)
Definition: object.c:4347
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:282
object_value_set_shared
bool object_value_set_shared(const object *op, sstring key)
Definition: object.c:4361
obj::key_values
key_value * key_values
Definition: object.h:439
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.c:360
query_base_name
void query_base_name(const object *op, int plural, char *buf, size_t size)
Definition: item.c:686
SPELL_EFFECT
@ SPELL_EFFECT
Definition: object.h:215
obj::weapon_speed_left
float weapon_speed_left
Definition: object.h:335
_key_value
Definition: object.h:40
map_find_by_type
object * map_find_by_type(mapstruct *m, int x, int y, uint8_t type)
Definition: object.c:3116
obj::last_sp
int32_t last_sp
Definition: object.h:363
FLAG_NO_FIX_PLAYER
#define FLAG_NO_FIX_PLAYER
Definition: define.h:277
diamondslots.y
y
Definition: diamondslots.py:16
FLAG_BEEN_APPLIED
#define FLAG_BEEN_APPLIED
Definition: define.h:323
python_pickup.where
where
Definition: python_pickup.py:7
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
npc_dialog.index
int index
Definition: npc_dialog.py:102
object_find_by_type
object * object_find_by_type(const object *who, int type)
Definition: object.c:3951
SET_MAP_OB
#define SET_MAP_OB(M, X, Y, tmp)
Definition: map.h:178
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.c:138
MAP_HEIGHT
#define MAP_HEIGHT(m)
Definition: map.h:80
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2833
update_all_los
void update_all_los(const mapstruct *map, int x, int y)
Definition: los.c:536
object_update_speed
void object_update_speed(object *op)
Definition: object.c:1330
object_handle_death_animation
void object_handle_death_animation(object *op)
Definition: object.c:5376
object_get_owner_const
static const object * object_get_owner_const(const object *op)
Definition: object.c:628
obj::subtype
uint8_t subtype
Definition: object.h:344
obj::more
struct obj * more
Definition: object.h:298
object_get_env_recursive
object * object_get_env_recursive(object *op)
Definition: object.c:594
object_find_by_name_global
object * object_find_by_name_global(const char *str)
Definition: object.c:751
obj::last_eat
int32_t last_eat
Definition: object.h:361
obj::move_type
MoveType move_type
Definition: object.h:430
obj::weight_limit
int32_t weight_limit
Definition: object.h:371
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:232
obj::materialname
sstring materialname
Definition: object.h:351
strcasecmp
int strcasecmp(const char *s1, const char *s2)
artifactstruct::item
object * item
Definition: artifact.h:15
castle_read.key
key
Definition: castle_read.py:64
MIN_ACTIVE_SPEED
#define MIN_ACTIVE_SPEED
Definition: define.h:639
find_dir_2
int find_dir_2(int x, int y)
Definition: object.c:3648
object_present_in_ob_by_name
object * object_present_in_ob_by_name(int type, const char *str, const object *op)
Definition: object.c:3174
FLAG_ANIMATE
#define FLAG_ANIMATE
Definition: define.h:242
obj::pick_up
uint8_t pick_up
Definition: object.h:366
liv::ac
int8_t ac
Definition: living.h:38
obj::skill
sstring skill
Definition: object.h:324
SAVE_ERROR_OK
#define SAVE_ERROR_OK
Definition: map.h:144
loader.h
nroffreeobjects
int nroffreeobjects
Definition: object.c:290
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:2080
obj::move_status
int32_t move_status
Definition: object.h:396
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.c:1546
GET_MAP_MOVE_OFF
#define GET_MAP_MOVE_OFF(M, X, Y)
Definition: map.h:208
update_position
void update_position(mapstruct *m, int x, int y)
Definition: map.c:2133
FLAG_IS_HILLY
#