Crossfire Server, Trunk
object.cpp
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  /* Everything passes, must be OK. */
549  return 1;
550 }
551 
567 /* TODO should check call this this are made a place where we really need reevaluaton of whole tree */
568 signed long object_sum_weight(object *op) {
569  signed long sum;
570 
571  sum = 0;
573  if (inv->inv)
575  sum += inv->carrying+inv->weight*NROF(inv);
576  } FOR_INV_FINISH();
577  if (op->type == CONTAINER && op->stats.Str)
578  sum = (sum*(100-op->stats.Str))/100;
579  op->carrying = sum;
580  return sum;
581 }
582 
590 object *object_get_env_recursive(object *op) {
591  while (op->env != NULL)
592  op = op->env;
593  return op;
594 }
595 
607 object *object_get_player_container(object *op) {
608  for (; op != NULL && op->type != PLAYER; op = op->env)
609  /*TODO this is patching the structure on the flight as side effect. Shoudln't be needed in clean code */
610  if (op->env == op)
611  op->env = NULL;
612  return op;
613 }
614 
624 static const object *object_get_owner_const(const object *op) {
625  if (op->owner == NULL)
626  return NULL;
627 
628  if (!QUERY_FLAG(op->owner, FLAG_FREED)
629  && !QUERY_FLAG(op->owner, FLAG_REMOVED)
630  && op->owner->count == op->ownercount)
631  return op->owner;
632 
633  LOG(llevError, "Warning, no owner found\n");
634  return NULL;
635 }
636 
645 void object_dump(const object *op, StringBuffer *sb) {
646  if (op == NULL) {
647  stringbuffer_append_string(sb, "[NULL pointer]");
648  return;
649  }
650 
651  /* object *tmp;*/
652 
653  if (op->arch != NULL) {
654  const object *owner;
655 
656  stringbuffer_append_string(sb, "arch ");
657  stringbuffer_append_string(sb, op->arch->name ? op->arch->name : "(null)");
658  stringbuffer_append_string(sb, "\n");
659 
660  if (op->artifact != NULL) {
661  stringbuffer_append_string(sb, "artifact ");
662  stringbuffer_append_string(sb, op->artifact);
663  stringbuffer_append_string(sb, "\n");
664  }
665 
667  if (op->more) {
668  stringbuffer_append_printf(sb, "more %u\n", op->more->count);
669  }
670  if (op->head) {
671  stringbuffer_append_printf(sb, "head %u\n", op->head->count);
672  }
673  if (op->env) {
674  stringbuffer_append_printf(sb, "env %u\n", op->env->count);
675  }
676  if (op->inv) {
677  stringbuffer_append_printf(sb, "inv %u\n", op->inv->count);
678  }
679  if (op->enemy) {
680  stringbuffer_append_printf(sb, "enemy %u\n", op->enemy->count);
681  }
682  if (op->attacked_by) {
683  stringbuffer_append_printf(sb, "attacked_by %u\n", op->attacked_by->count);
684  }
685  owner = object_get_owner_const(op);
686  if (owner != NULL) {
687  stringbuffer_append_printf(sb, "owner %u\n", owner->count);
688  }
689  stringbuffer_append_string(sb, "end\n");
690  } else {
691  stringbuffer_append_string(sb, "Object ");
692  stringbuffer_append_string(sb, op->name == NULL ? "(null)" : op->name);
693  stringbuffer_append_string(sb, "\nend\n");
694  }
695 }
696 
704 void object_dump_all(void) {
705  object *op;
706 
707  for (op = objects; op != NULL; op = op->next) {
708  StringBuffer *sb;
709  char *diff;
710 
711  sb = stringbuffer_new();
712  object_dump(op, sb);
713  diff = stringbuffer_finish(sb);
714  LOG(llevDebug, "Object %u\n:%s\n", op->count, diff);
715  free(diff);
716  }
717 }
718 
728  object *op;
729 
730  for (op = objects; op != NULL; op = op->next)
731  if (op->count == i)
732  break;
733  return op;
734 }
735 
747 object *object_find_by_name_global(const char *str) {
748  const char *name = add_string(str);
749  object *op;
750 
751  for (op = objects; op != NULL; op = op->next)
752  if (op->name == name)
753  break;
754  free_string(name);
755  return op;
756 }
757 
768 #ifdef MEMORY_DEBUG
769  object *op, *next;
770 
771  for (op = free_objects; op != NULL; ) {
772  next = op->next;
773  free(op);
775  nroffreeobjects--;
776  op = next;
777  }
778  free_objects = NULL;
779 
780  for (op = objects; op != NULL; ) {
781  next = op->next;
782  if (!QUERY_FLAG(op, FLAG_FREED)) {
783  LOG(llevDebug, "non freed object: %s\n", op->name);
784  }
785  op = next;
786  }
787 #endif
788 
789  LOG(llevDebug, "%d allocated objects, %d free objects, STARMAX=%d\n", nrofallocobjects, nroffreeobjects, STARTMAX);
790 }
791 
804 object *object_get_owner(object *op) {
805  if (op->owner == NULL)
806  return NULL;
807 
808  if (!QUERY_FLAG(op->owner, FLAG_FREED)
809  && !QUERY_FLAG(op->owner, FLAG_REMOVED)
810  && op->owner->count == op->ownercount)
811  return op->owner;
812 
814  return NULL;
815 }
816 
823 void object_clear_owner(object *op) {
824  if (!op)
825  return;
826 
827  op->owner = NULL;
828  op->ownercount = 0;
829 }
830 
840 void object_set_owner(object *op, object *owner) {
841  /* Assign temp to something, so it can't accidentally be NULL */
842  object *tmp = owner;
843  if (op == NULL)
844  return;
845  if (owner == NULL) {
847  return;
848  }
849 
850  /* next line added to allow objects which own objects */
851  /* Add a check for ownercounts in here, as I got into an endless loop
852  * with the fireball owning a poison cloud which then owned the
853  * fireball. I believe that was caused by one of the objects getting
854  * freed and then another object replacing it. Since the ownercounts
855  * didn't match, this check is valid and I believe that cause is valid.
856  */
857  /*
858  * if owner is NULL, function will have already returned,
859  * so loop should still function as before.
860  */
861  while (tmp) {
862  tmp = object_get_owner(owner);
863  if (tmp)
864  owner = tmp;
865  }
866 
867  /* must not cause owner cycles */
868  assert(op != owner);
869 
870  if (op->owner != NULL)
872 
873  op->owner = owner;
874  op->ownercount = owner->count;
875 }
876 
893 void object_copy_owner(object *op, object *clone) {
894  object *owner = object_get_owner(clone);
895  if (owner == NULL) {
896  /* players don't have owners - they own themselves. Update
897  * as appropriate.
898  */
899  /*TODO owner=self is dangerous and should be avoided*/
900  if (clone->type != PLAYER)
901  return;
902  owner = clone;
903  }
904  object_set_owner(op, owner);
905 }
906 
915 void object_set_enemy(object *op, object *enemy) {
916  if (op->enemy == enemy) {
917  return;
918  }
919 
920 #if 0
921  if (op->type != PLAYER) {
922  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);
923  }
924 #endif
925  op->enemy = enemy;
926 }
927 
934 void object_reset(object *op) {
935  op->name = NULL;
936  op->name_pl = NULL;
937  op->title = NULL;
938  op->race = NULL;
939  op->slaying = NULL;
940  op->skill = NULL;
941  op->msg = NULL;
942  op->materialname = NULL;
943  op->lore = NULL;
944  object_clear(op);
945 }
946 
954 void object_free_key_values(object *op) {
955  key_value *i;
956  key_value *next = NULL;
957 
958  if (op->key_values == NULL)
959  return;
960 
961  for (i = op->key_values; i != NULL; i = next) {
962  /* Store next *first*. */
963  next = i->next;
964 
965  if (i->key)
967  if (i->value)
969  i->next = NULL;
970  free(i);
971  }
972 
973  op->key_values = NULL;
974 }
975 
983 void object_clear(object *op) {
984  /*TODO this comment must be investigated*/
985  /* redo this to be simpler/more efficient. Was also seeing
986  * crashes in the old code. Move this to the top - am
987  * seeing periodic crashes in this code, and would like to have
988  * as much info available as possible (eg, object name).
989  */
992 
993  /* the memset will clear all these values for us, but we need
994  * to reduce the refcount on them.
995  */
996  if (op->name != NULL)
997  FREE_AND_CLEAR_STR(op->name);
998  if (op->name_pl != NULL)
999  FREE_AND_CLEAR_STR(op->name_pl);
1000  if (op->title != NULL)
1001  FREE_AND_CLEAR_STR(op->title);
1002  if (op->race != NULL)
1003  FREE_AND_CLEAR_STR(op->race);
1004  if (op->slaying != NULL)
1005  FREE_AND_CLEAR_STR(op->slaying);
1006  if (op->skill != NULL)
1007  FREE_AND_CLEAR_STR(op->skill);
1008  if (op->msg != NULL)
1009  FREE_AND_CLEAR_STR(op->msg);
1010  if (op->lore != NULL)
1011  FREE_AND_CLEAR_STR(op->lore);
1012  if (op->materialname != NULL)
1013  FREE_AND_CLEAR_STR(op->materialname);
1014 
1015  /* Remove object from friendly list if needed. */
1016  if (QUERY_FLAG(op, FLAG_FRIENDLY))
1018 
1019  memset((void *)((char *)op+offsetof(object, name)), 0, sizeof(object)-offsetof(object, name));
1020  /* Below here, we clear things that are not done by the memset,
1021  * or set default values that are not zero.
1022  */
1023  /* This is more or less true */
1025 
1026 
1027  op->contr = NULL;
1028  op->below = NULL;
1029  op->above = NULL;
1030  op->inv = NULL;
1031  op->container = NULL;
1032  op->env = NULL;
1033  op->more = NULL;
1034  op->head = NULL;
1035  op->map = NULL;
1036  op->active_next = NULL;
1037  op->active_prev = NULL;
1038  /* What is not cleared is next, prev, and count */
1039 
1040  op->expmul = 1.0;
1041  op->face = blank_face;
1042  op->attacked_by_count = -1;
1043  if (settings.casting_time)
1044  op->casting_time = -1;
1045 }
1046 
1060 void object_copy(const object *src_ob, object *dest_ob) {
1061  int is_freed = QUERY_FLAG(dest_ob, FLAG_FREED), is_removed = QUERY_FLAG(dest_ob, FLAG_REMOVED);
1062 
1063  /* Decrement the refcounts, but don't bother zeroing the fields;
1064  they'll be overwritten by memcpy. */
1065  if (dest_ob->artifact != NULL)
1066  free_string(dest_ob->artifact);
1067  if (dest_ob->name != NULL)
1068  free_string(dest_ob->name);
1069  if (dest_ob->name_pl != NULL)
1070  free_string(dest_ob->name_pl);
1071  if (dest_ob->anim_suffix != NULL)
1072  free_string(dest_ob->anim_suffix);
1073  if (dest_ob->title != NULL)
1074  free_string(dest_ob->title);
1075  if (dest_ob->race != NULL)
1076  free_string(dest_ob->race);
1077  if (dest_ob->slaying != NULL)
1078  free_string(dest_ob->slaying);
1079  if (dest_ob->skill != NULL)
1080  free_string(dest_ob->skill);
1081  if (dest_ob->msg != NULL)
1082  free_string(dest_ob->msg);
1083  if (dest_ob->lore != NULL)
1084  free_string(dest_ob->lore);
1085  if (dest_ob->materialname != NULL)
1086  free_string(dest_ob->materialname);
1087  if (dest_ob->spell_tags != NULL)
1088  FREE_AND_CLEAR(dest_ob->spell_tags);
1089 
1090  /* Basically, same code as from object_clear() */
1091 
1092  object_free_key_values(dest_ob);
1093  free_dialog_information(dest_ob);
1094 
1095  /* Copy all attributes below name (name included). */
1096  (void)memcpy((void *)((char *)dest_ob+offsetof(object, name)),
1097  (void *)((char *)src_ob+offsetof(object, name)),
1098  sizeof(object)-offsetof(object, name));
1099 
1100  if (is_freed)
1101  SET_FLAG(dest_ob, FLAG_FREED);
1102  if (is_removed)
1103  SET_FLAG(dest_ob, FLAG_REMOVED);
1104  if (dest_ob->artifact != NULL)
1105  add_refcount(dest_ob->artifact);
1106  if (dest_ob->name != NULL)
1107  add_refcount(dest_ob->name);
1108  if (dest_ob->name_pl != NULL)
1109  add_refcount(dest_ob->name_pl);
1110  if (dest_ob->anim_suffix != NULL)
1111  add_refcount(dest_ob->anim_suffix);
1112  if (dest_ob->title != NULL)
1113  add_refcount(dest_ob->title);
1114  if (dest_ob->race != NULL)
1115  add_refcount(dest_ob->race);
1116  if (dest_ob->slaying != NULL)
1117  add_refcount(dest_ob->slaying);
1118  if (dest_ob->skill != NULL)
1119  add_refcount(dest_ob->skill);
1120  if (dest_ob->lore != NULL)
1121  add_refcount(dest_ob->lore);
1122  if (dest_ob->msg != NULL)
1123  add_refcount(dest_ob->msg);
1124  if (dest_ob->materialname != NULL)
1125  add_refcount(dest_ob->materialname);
1126 
1127  if (dest_ob->spell_tags != NULL) {
1128  dest_ob->spell_tags = static_cast<tag_t *>(malloc(sizeof(tag_t)*SPELL_TAG_SIZE));
1129  memcpy(dest_ob->spell_tags, src_ob->spell_tags, sizeof(tag_t)*SPELL_TAG_SIZE);
1130  }
1131 
1132  /* If archetype is a temporary one, we need to update reference count, because
1133  * that archetype will be freed by object_free_drop_inventory() when the last object is removed.
1134  */
1135  if (dest_ob->arch != NULL) {
1136  if (dest_ob->arch->reference_count > 0)
1137  dest_ob->arch->reference_count++;
1138  }
1139 
1140  if (src_ob->speed < 0)
1141  dest_ob->speed_left = src_ob->speed_left-RANDOM()%200/100.0;
1142 
1143  /* Copy over key_values, if any. */
1144  if (src_ob->key_values != NULL) {
1145  key_value *tail = NULL;
1146  key_value *i;
1147 
1148  dest_ob->key_values = NULL;
1149 
1150  for (i = src_ob->key_values; i != NULL; i = i->next) {
1151  key_value *new_link = static_cast<key_value *>(malloc(sizeof(key_value)));
1152 
1153  new_link->next = NULL;
1154  new_link->key = add_refcount(i->key);
1155  if (i->value)
1156  new_link->value = add_refcount(i->value);
1157  else
1158  new_link->value = NULL;
1159 
1160  /* Try and be clever here, too. */
1161  if (dest_ob->key_values == NULL) {
1162  dest_ob->key_values = new_link;
1163  tail = new_link;
1164  } else {
1165  tail->next = new_link;
1166  tail = new_link;
1167  }
1168  }
1169  }
1170 
1171  /* This way, dialog information will be parsed again when/if needed. */
1172  CLEAR_FLAG(dest_ob, FLAG_DIALOG_PARSED);
1173 
1174  dest_ob->event_bitmask = BITMASK_VALID; // Empty inventory so valid
1175 
1176  object_update_speed(dest_ob);
1177 }
1178 
1188 void object_copy_with_inv(const object *src_ob, object *dest_ob) {
1189  object_copy(src_ob, dest_ob);
1190  FOR_INV_PREPARE(src_ob, walk) {
1191  object *tmp;
1192 
1193  tmp = object_new();
1194  object_copy_with_inv(walk, tmp);
1195  object_insert_in_ob(tmp, dest_ob);
1196  } FOR_INV_FINISH();
1197 }
1198 
1199 #ifndef MEMORY_DEBUG
1200 
1207 static void expand_objects(void) {
1208  int i;
1209  object *add;
1210 
1211  add = (object *)CALLOC(OBJ_EXPAND, sizeof(object));
1212 
1213  if (add == NULL)
1215  free_objects = add;
1216  add[0].prev = NULL;
1217  add[0].next = &add[1],
1218  SET_FLAG(&add[0], FLAG_REMOVED);
1219  SET_FLAG(&add[0], FLAG_FREED);
1220 
1221  for (i = 1; i < OBJ_EXPAND-1; i++) {
1222  add[i].next = &add[i+1],
1223  add[i].prev = &add[i-1],
1224  SET_FLAG(&add[i], FLAG_REMOVED);
1225  SET_FLAG(&add[i], FLAG_FREED);
1226  }
1227  add[OBJ_EXPAND-1].prev = &add[OBJ_EXPAND-2],
1228  add[OBJ_EXPAND-1].next = NULL,
1229  SET_FLAG(&add[OBJ_EXPAND-1], FLAG_REMOVED);
1230  SET_FLAG(&add[OBJ_EXPAND-1], FLAG_FREED);
1231 
1234 }
1235 #endif
1236 
1249 object *object_new(void) {
1250  object *op;
1251 #ifdef MEMORY_DEBUG
1252  /* FIXME: However this doesn't work since object_free() sometimes add
1253  * objects back to the free_objects linked list, and some functions mess
1254  * with the object after return of object_free(). This is bad and should be
1255  * fixed. But it would need fairly extensive changes and a lot of debugging.
1256  */
1257  op = static_cast<object *>(calloc(1, sizeof(object)));
1258  if (op == NULL)
1260 #else
1261  if (free_objects == NULL) {
1262  expand_objects();
1263  }
1264  op = free_objects;
1265  if (!QUERY_FLAG(op, FLAG_FREED)) {
1266  LOG(llevError, "Fatal: Getting busy object.\n");
1267 #ifdef MANY_CORES
1268  abort();
1269 #endif
1270  }
1271  free_objects = op->next;
1272  if (free_objects != NULL)
1273  free_objects->prev = NULL;
1274  nroffreeobjects--;
1275 #endif
1276  op->count = ++ob_count;
1277  op->name = NULL;
1278  op->name_pl = NULL;
1279  op->title = NULL;
1280  op->race = NULL;
1281  op->slaying = NULL;
1282  op->skill = NULL;
1283  op->lore = NULL;
1284  op->msg = NULL;
1285  op->materialname = NULL;
1286  op->next = objects;
1287  op->prev = NULL;
1288  op->active_next = NULL;
1289  op->active_prev = NULL;
1290  op->spell_tags = NULL;
1291  op->event_bitmask = BITMASK_VALID;
1292  if (objects != NULL)
1293  objects->prev = op;
1294  objects = op;
1295  object_clear(op);
1297  return op;
1298 }
1299 
1309  if (op->animation == 0 || !QUERY_FLAG(op, FLAG_IS_TURNABLE))
1310  return;
1311  animate_object(op, op->direction);
1312 }
1313 
1325 void object_update_speed(object *op) {
1326  /* FIXME what the hell is this crappy hack?*/
1327  extern int arch_init;
1328 
1329  /* No reason putting the archetypes objects on the speed list,
1330  * since they never really need to be updated.
1331  */
1332 
1333  if (QUERY_FLAG(op, FLAG_FREED) && op->speed) {
1334  LOG(llevError, "Object %s is freed but has speed.\n", op->name);
1335 #ifdef MANY_CORES
1336  abort();
1337 #else
1338  op->speed = 0;
1339 #endif
1340  }
1341  if (arch_init) {
1342  return;
1343  }
1344  if (FABS(op->speed) > MIN_ACTIVE_SPEED) {
1345  /* If already on active list, don't do anything */
1346  /* TODO this check can probably be simplified a lot */
1347  if (op->active_next || op->active_prev || op == active_objects)
1348  return;
1349 
1350  /* process_events() expects us to insert the object at the beginning
1351  * of the list. */
1352  op->active_next = active_objects;
1353  if (op->active_next != NULL)
1354  op->active_next->active_prev = op;
1355  active_objects = op;
1356  } else {
1358  }
1359 }
1360 
1374  /* If not on the active list, nothing needs to be done */
1375  if (!op->active_next && !op->active_prev && op != active_objects)
1376  return;
1377 
1378  if (op->active_prev == NULL) {
1379  active_objects = op->active_next;
1380  if (op->active_next != NULL)
1381  op->active_next->active_prev = NULL;
1382  } else {
1383  op->active_prev->active_next = op->active_next;
1384  if (op->active_next)
1385  op->active_next->active_prev = op->active_prev;
1386  }
1387  op->active_next = NULL;
1388  op->active_prev = NULL;
1389 }
1390 
1415 void object_update(object *op, int action) {
1416  int update_now = 0, flags;
1417  MoveType move_on, move_off, move_block, move_slow;
1418  object *pl;
1419 
1420  if (op == NULL) {
1421  /* this should never happen */
1422  LOG(llevDebug, "object_update() called for NULL object.\n");
1423  return;
1424  }
1425 
1426  if (op->env != NULL) {
1427  /* Animation is currently handled by client, so nothing
1428  * to do in this case.
1429  */
1430  return;
1431  }
1432 
1433  /* If the map is saving, don't do anything as everything is
1434  * going to get freed anyways.
1435  */
1436  if (!op->map || op->map->in_memory == MAP_SAVING)
1437  return;
1438 
1439  /* make sure the object is within map boundaries */
1440  if (op->x < 0 || op->x >= MAP_WIDTH(op->map)
1441  || op->y < 0 || op->y >= MAP_HEIGHT(op->map)) {
1442  LOG(llevError, "object_update() called for object out of map!\n");
1443 #ifdef MANY_CORES
1444  abort();
1445 #endif
1446  return;
1447  }
1448 
1449  flags = GET_MAP_FLAGS(op->map, op->x, op->y);
1450  SET_MAP_FLAGS(op->map, op->x, op->y, flags|P_NEED_UPDATE);
1451  move_slow = GET_MAP_MOVE_SLOW(op->map, op->x, op->y);
1452  move_on = GET_MAP_MOVE_ON(op->map, op->x, op->y);
1453  move_block = GET_MAP_MOVE_BLOCK(op->map, op->x, op->y);
1454  move_off = GET_MAP_MOVE_OFF(op->map, op->x, op->y);
1455 
1456  if (action == UP_OBJ_INSERT) {
1458  update_now = 1;
1459 
1461  update_now = 1;
1462 
1464  update_now = 1;
1465 
1466  if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags&P_IS_ALIVE))
1467  update_now = 1;
1468 
1469  if ((move_on|op->move_on) != move_on)
1470  update_now = 1;
1471  if ((move_off|op->move_off) != move_off)
1472  update_now = 1;
1473  /* This isn't perfect, but I don't expect a lot of objects to
1474  * to have move_allow right now.
1475  */
1476  if (((move_block|op->move_block)&~op->move_allow) != move_block)
1477  update_now = 1;
1478  if ((move_slow|op->move_slow) != move_slow)
1479  update_now = 1;
1480 
1481  if (op->type == PLAYER)
1482  update_now = 1;
1483  /* if the object is being removed, we can't make intelligent
1484  * decisions, because object_remove() can't really pass the object
1485  * that is being removed.
1486  */
1487  } else if (action == UP_OBJ_REMOVE) {
1488  update_now = 1;
1489  } else if (action == UP_OBJ_FACE || action == UP_OBJ_CHANGE) {
1490  /* In addition to sending info to client, need to update space
1491  * information.
1492  */
1493  if (action == UP_OBJ_CHANGE)
1494  update_now = 1;
1495 
1496  /* There is a player on this space - we may need to send an
1497  * update to the client.
1498  * If this object is supposed to be animated by the client,
1499  * nothing to do here - let the client animate it.
1500  * We can't use FLAG_ANIMATE, as that is basically set for
1501  * all objects with multiple faces, regardless if they are animated.
1502  * (levers have it set for example).
1503  */
1504  if (flags&P_PLAYER
1507  pl = GET_MAP_PLAYER(op->map, op->x, op->y);
1508 
1509  /* If update_look is set, we're going to send this entire space
1510  * to the client, so no reason to send face information now.
1511  */
1512  if (!pl->contr->socket->update_look) {
1514  }
1515  }
1516  } else {
1517  LOG(llevError, "object_update called with invalid action: %d\n", action);
1518  }
1519 
1520  if (update_now) {
1522  update_position(op->map, op->x, op->y);
1523  }
1524 
1525  if (op->more != NULL)
1526  object_update(op->more, action);
1527 }
1528 
1542  object_free(ob, 0);
1543 }
1544 
1549 void object_free_inventory(object *ob) {
1550  while (ob->inv) {
1551  object *inv = ob->inv;
1552  object_remove(inv);
1554  }
1555 }
1556 
1573 void object_free(object *ob, int flags) {
1574  if (!QUERY_FLAG(ob, FLAG_REMOVED)) {
1575  StringBuffer *sb;
1576  char *diff;
1577 
1578  LOG(llevError, "Free object called with non removed object\n");
1579  sb = stringbuffer_new();
1580  object_dump(ob, sb);
1581  diff = stringbuffer_finish(sb);
1582  LOG(llevError, "%s", diff);
1583  free(diff);
1584 #ifdef MANY_CORES
1585  abort();
1586 #endif
1587  }
1588  if (QUERY_FLAG(ob, FLAG_FRIENDLY)) {
1589  LOG(llevMonster, "Warning: tried to free friendly object.\n");
1591  }
1592  if (QUERY_FLAG(ob, FLAG_FREED)) {
1593  StringBuffer *sb;
1594  char *diff;
1595 
1596  sb = stringbuffer_new();
1597  object_dump(ob, sb);
1598  diff = stringbuffer_finish(sb);
1599  LOG(llevError, "Trying to free freed object.\n%s\n", diff);
1600  free(diff);
1601  return;
1602  }
1603 
1604  if ((flags & FREE_OBJ_NO_DESTROY_CALLBACK) == 0) {
1606  }
1607 
1608  if (ob->inv) {
1609  /* Only if the space blocks everything do we not process -
1610  * if some form of movemnt is allowed, let objects
1611  * drop on that space.
1612  */
1613  if ((flags & FREE_OBJ_FREE_INVENTORY) != 0
1614  || ob->map == NULL
1615  || ob->map->in_memory != MAP_IN_MEMORY
1616  || (GET_MAP_MOVE_BLOCK(ob->map, ob->x, ob->y) == MOVE_ALL)) {
1617  FOR_INV_PREPARE(ob, op) {
1618  object_remove(op);
1619  object_free(op, flags);
1620  } FOR_INV_FINISH();
1621  } else { /* Put objects in inventory onto this space */
1622  FOR_INV_PREPARE(ob, op) {
1623  object_remove(op);
1624  /* No drop means no drop, including its inventory */
1625  if (QUERY_FLAG(op, FLAG_NO_DROP))
1627  else if (QUERY_FLAG(op, FLAG_STARTEQUIP)
1629  || op->type == RUNE
1630  || op->type == TRAP
1633  else {
1634  object *part;
1635 
1636  /* If it's a multi-tile object, scatter dropped items randomly */
1637  if (ob->more) {
1638  int partcount = 0;
1639  /* Get the number of non-head parts */
1640  for (part = ob; part; part = part->more) {
1641  partcount++;
1642  }
1643  /* Select a random part */
1644  partcount = RANDOM()%partcount;
1645  for (part = ob; partcount > 0; partcount--) {
1646  part = part->more;
1647  }
1648  } else {
1649  part = ob;
1650  }
1651 
1652  if (QUERY_FLAG(op, FLAG_ALIVE)) {
1653  object_insert_to_free_spot_or_free(op, part->map, part->x, part->y, 0, SIZEOFFREE, NULL);
1654  } else {
1655  int f = 0;
1658  object_insert_in_map_at(op, part->map, NULL, f, part->x, part->y); /* Insert in same map as the envir */
1659  }
1660  }
1661  } FOR_INV_FINISH();
1662  }
1663  }
1664 
1665  if (ob->more != NULL) {
1666  object_free(ob->more, flags);
1667  ob->more = NULL;
1668  }
1669 
1670  /* Remove object from the active list */
1671  ob->speed = 0;
1673 
1675  ob->count = 0;
1676 
1677  /* Remove this object from the list of used objects */
1678  if (ob->prev == NULL) {
1679  objects = ob->next;
1680  if (objects != NULL)
1681  objects->prev = NULL;
1682  } else {
1683  ob->prev->next = ob->next;
1684  if (ob->next != NULL)
1685  ob->next->prev = ob->prev;
1686  }
1687 
1688  if (ob->artifact != NULL) FREE_AND_CLEAR_STR(ob->artifact);
1689  if (ob->name != NULL) FREE_AND_CLEAR_STR(ob->name);
1690  if (ob->name_pl != NULL) FREE_AND_CLEAR_STR(ob->name_pl);
1691  if (ob->title != NULL) FREE_AND_CLEAR_STR(ob->title);
1692  if (ob->race != NULL) FREE_AND_CLEAR_STR(ob->race);
1693  if (ob->slaying != NULL) FREE_AND_CLEAR_STR(ob->slaying);
1694  if (ob->skill != NULL) FREE_AND_CLEAR_STR(ob->skill);
1695  if (ob->lore != NULL) FREE_AND_CLEAR_STR(ob->lore);
1696  if (ob->msg != NULL) FREE_AND_CLEAR_STR(ob->msg);
1697  if (ob->materialname != NULL) FREE_AND_CLEAR_STR(ob->materialname);
1698  if (ob->spell_tags) FREE_AND_CLEAR(ob->spell_tags);
1699  FREE_AND_CLEAR_STR_IF(ob->anim_suffix);
1700 
1701  /* Why aren't events freed? */
1703 
1705 
1706  /* Test whether archetype is a temporary one, and if so look whether it should be trashed. */
1707  if (ob->arch && ob->arch->reference_count > 0) {
1708  if (--ob->arch->reference_count == 0) {
1709  free_arch(ob->arch);
1710  }
1711  }
1712 
1713 #ifdef MEMORY_DEBUG
1714  free(ob);
1715 #else
1716  /* Now link it with the free_objects list: */
1717  ob->prev = NULL;
1718  ob->next = free_objects;
1719  if (free_objects != NULL)
1720  free_objects->prev = ob;
1721  free_objects = ob;
1722  nroffreeobjects++;
1723 #endif
1724 }
1725 
1733  int i = 0;
1734  object *tmp = free_objects;
1735 
1736  while (tmp != NULL)
1737  tmp = tmp->next,
1738  i++;
1739  return i;
1740 }
1741 
1749  int i = 0;
1750  object *tmp = objects;
1751 
1752  while (tmp != NULL)
1753  tmp = tmp->next,
1754  i++;
1755  return i;
1756 }
1757 
1765  int i = 0;
1766  object *tmp = active_objects;
1767 
1768  while (tmp != NULL)
1769  tmp = tmp->active_next,
1770  i++;
1771  return i;
1772 }
1773 
1788 void object_sub_weight(object *op, signed long weight) {
1789  while (op != NULL) {
1790  if (op->type == CONTAINER) {
1791  weight = (signed long)(weight*(100-op->stats.Str)/100);
1792  }
1793  op->carrying -= weight;
1794  op = op->env;
1795  }
1796 }
1797 
1814 void object_remove(object *op) {
1815  object *last = NULL;
1816  object *otmp;
1817  tag_t tag;
1818  int check_walk_off;
1819  mapstruct *m;
1820  int16_t x, y;
1821 
1822  if (QUERY_FLAG(op, FLAG_REMOVED)) {
1823  StringBuffer *sb;
1824  char *diff;
1825 
1826  sb = stringbuffer_new();
1827  object_dump(op, sb);
1828  diff = stringbuffer_finish(sb);
1829  LOG(llevError, "Trying to remove removed object.\n%s\n", diff);
1830  free(diff);
1831  abort();
1832  }
1833  if (op->more != NULL)
1834  object_remove(op->more);
1835 
1837 
1838  /*
1839  * In this case, the object to be removed is in someones
1840  * inventory.
1841  */
1842  /* TODO try to call a generic inventory weight adjusting function like object_sub_weight */
1843  if (op->env != NULL) {
1844  player *pl = NULL;
1845 
1846  if (op->nrof)
1847  object_sub_weight(op->env, op->weight*op->nrof);
1848  else
1849  object_sub_weight(op->env, op->weight+op->carrying);
1850 
1851  /* Update in two cases: item is in a player, or in a container the player is looking into. */
1852  if (op->env->contr != NULL && op->head == NULL) {
1853  pl = op->env->contr;
1854  } else if (op->env->type == CONTAINER && QUERY_FLAG(op->env, FLAG_APPLIED)) {
1855 
1856  if (op->env->env && op->env->env->contr)
1857  /* Container is in player's inventory. */
1858  pl = op->env->env->contr;
1859  else if (op->env->map) {
1860  /* Container on map, look above for player. */
1861  object *above = op->env->above;
1862 
1863  while (above && !above->contr)
1864  above = above->above;
1865  if (above)
1866  pl = above->contr;
1867  }
1868  }
1869 
1870  /* NO_FIX_PLAYER is set when a great many changes are being
1871  * made to players inventory. If set, avoiding the call
1872  * to save cpu time.
1873  */
1874  otmp = object_get_player_container(op->env);
1875  if (otmp != NULL
1876  && otmp->contr
1877  && !QUERY_FLAG(otmp, FLAG_NO_FIX_PLAYER))
1878  fix_object(otmp);
1879 
1880  if (op->above != NULL)
1881  op->above->below = op->below;
1882  else
1883  op->env->inv = op->below;
1884 
1885  if (op->below != NULL)
1886  op->below->above = op->above;
1887 
1888  if (op->type == EVENT_CONNECTOR) {
1889  op->env->event_bitmask = 0; // Will be recomputed if needed
1890  }
1891 
1892  /* we set up values so that it could be inserted into
1893  * the map, but we don't actually do that - it is up
1894  * to the caller to decide what we want to do.
1895  */
1896  op->x = op->env->x;
1897  op->y = op->env->y;
1898  op->ox = op->x;
1899  op->oy = op->y;
1900  op->map = op->env->map;
1901  op->above = NULL;
1902  op->below = NULL;
1903  /* send the delitem before resetting env, so container's contents be may
1904  * refreshed */
1905  if (LOOK_OBJ(op) && pl != NULL)
1906  esrv_del_item(pl, op);
1907  op->env = NULL;
1908  return;
1909  }
1910 
1911  /* If we get here, we are removing it from a map */
1912  if (op->map == NULL)
1913  return;
1914 
1915  if (op->contr != NULL && !op->contr->hidden)
1916  op->map->players--;
1917 
1918  x = op->x;
1919  y = op->y;
1920  m = get_map_from_coord(op->map, &x, &y);
1921 
1922  if (!m) {
1923  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);
1924  abort();
1925  }
1926  if (op->map != m) {
1927  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);
1928  }
1929 
1930  /* link the object above us */
1931  if (op->above)
1932  op->above->below = op->below;
1933  else
1934  SET_MAP_TOP(m, x, y, op->below); /* we were top, set new top */
1935 
1936  /* Relink the object below us, if there is one */
1937  if (op->below) {
1938  op->below->above = op->above;
1939  } else {
1940  /* Nothing below, which means we need to relink map object for this space
1941  * use translated coordinates in case some oddness with map tiling is
1942  * evident
1943  */
1944  /*TODO is this check really needed?*/
1945  if (GET_MAP_OB(m, x, y) != op) {
1946  StringBuffer *sb;
1947  char *diff;
1948 
1949  sb = stringbuffer_new();
1950  object_dump(op, sb);
1951  diff = stringbuffer_finish(sb);
1952  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);
1953  free(diff);
1954 
1955  sb = stringbuffer_new();
1956  object_dump(GET_MAP_OB(m, x, y), sb);
1957  diff = stringbuffer_finish(sb);
1958  LOG(llevError, "%s\n", diff);
1959  free(diff);
1960  }
1961  SET_MAP_OB(m, x, y, op->above); /* goes on above it. */
1962  }
1963  op->above = NULL;
1964  op->below = NULL;
1965 
1966  if (op->map->in_memory == MAP_SAVING)
1967  return;
1968 
1969  tag = op->count;
1970  check_walk_off = !QUERY_FLAG(op, FLAG_NO_APPLY);
1971  FOR_MAP_PREPARE(m, x, y, tmp) {
1972  /* No point updating the players look faces if he is the object
1973  * being removed.
1974  */
1975 
1976  if (tmp->type == PLAYER && tmp != op) {
1977  /* If a container that the player is currently using somehow gets
1978  * removed (most likely destroyed), update the player view
1979  * appropriately.
1980  */
1981  if (tmp->container == op) {
1983  tmp->container = NULL;
1984  }
1985  tmp->contr->socket->update_look = 1;
1986  }
1987  /* See if player moving off should effect something */
1988  if (check_walk_off
1989  && ((op->move_type&tmp->move_off) && (op->move_type&~tmp->move_off&~tmp->move_block) == 0)) {
1990  ob_move_on(tmp, op, NULL);
1991  if (object_was_destroyed(op, tag)) {
1992  LOG(llevError, "BUG: object_remove(): name %s, archname %s destroyed leaving object\n", tmp->name, tmp->arch->name);
1993  }
1994  }
1995 
1996  /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */
1997  if (tmp->above == tmp)
1998  tmp->above = NULL;
1999  last = tmp;
2000  } FOR_MAP_FINISH();
2001  /* last == NULL or there are no objects on this space */
2002  if (last == NULL) {
2003  /* set P_NEED_UPDATE, otherwise update_position will complain. In theory,
2004  * we could preserve the flags (GET_MAP_FLAGS), but update_position figures
2005  * those out anyways, and if there are any flags set right now, they won't
2006  * be correct anyways.
2007  */
2008  SET_MAP_FLAGS(op->map, op->x, op->y, P_NEED_UPDATE);
2009  update_position(op->map, op->x, op->y);
2010  } else
2012 
2013  if (QUERY_FLAG(op, FLAG_BLOCKSVIEW) || (op->glow_radius != 0))
2014  update_all_los(op->map, op->x, op->y);
2015 }
2016 
2030 object *object_merge(object *op, object *top) {
2031  if (!op->nrof)
2032  return NULL;
2033 
2034  if (top == NULL)
2035  for (top = op; top != NULL && top->above != NULL; top = top->above)
2036  ;
2038  if (top == op)
2039  continue;
2040  if (object_can_merge(op, top)) {
2041  object_increase_nrof(top, op->nrof);
2042  /*
2043  * Previous behavior set weight to zero here.
2044  * This, however, caused the object_sub_weight
2045  * call in object_remove to subtract zero weight
2046  * when removing the object. Thus, until inventory
2047  * weight is next recalculated, the object merged
2048  * into another pile added weight in object_increase_nrof
2049  * but did not remove the weight from the original
2050  * instance of itself in object_remove, essentially
2051  * counting for double weight for several minutes.
2052  *
2053  * SilverNexus 2014-05-27
2054  */
2055  object_remove(op);
2057  return top;
2058  }
2060  return NULL;
2061 }
2062 
2079 object *object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y) {
2080  object *tmp;
2081 
2082  op = HEAD(op);
2083  for (tmp = op; tmp; tmp = tmp->more) {
2084  tmp->x = x+tmp->arch->clone.x;
2085  tmp->y = y+tmp->arch->clone.y;
2086  tmp->map = m;
2087  }
2088  return object_insert_in_map(op, m, originator, flag);
2089 }
2090 
2108 void object_merge_spell(object *op, int16_t x, int16_t y) {
2109  int i;
2110 
2111  /* We try to do some merging of spell objects - if something has same owner,
2112  * is same type of spell, and going in the same direction, it is somewhat
2113  * mergable.
2114  *
2115  * If the spell object has an other_arch, don't merge - when the spell
2116  * does something, like explodes, it will use this other_arch, and
2117  * if we merge, there is no easy way to make the correct values be
2118  * set on this new object (values should be doubled, tripled, etc.)
2119  *
2120  * We also care about speed - only process objects that will not be
2121  * active this tick. Without this, the results are incorrect - think
2122  * of a case where tmp would normally get processed this tick, but
2123  * get merges with op, which does not get processed.
2124  */
2125  FOR_MAP_PREPARE(op->map, x, y, tmp) {
2126  if (op->type == tmp->type
2127  && op->subtype == tmp->subtype
2128  && op->direction == tmp->direction
2129  && op->owner == tmp->owner && op->ownercount == tmp->ownercount
2130  && op->range == tmp->range
2131  && op->stats.wc == tmp->stats.wc
2132  && op->level == tmp->level
2133  && op->attacktype == tmp->attacktype
2134  && op->speed == tmp->speed
2135  && !tmp->other_arch
2136  && (tmp->speed_left+tmp->speed) < 0.0
2137  && op != tmp) {
2138  /* Quick test - if one or the other objects already have hash tables
2139  * set up, and that hash bucket contains a value that doesn't
2140  * match what we want to set it up, we won't be able to merge.
2141  * Note that these two if statements are the same, except
2142  * for which object they are checking against. They could
2143  * be merged, but the line wrapping would be large enough
2144  * that IMO it would become difficult to read the different clauses
2145  * so its cleaner just to do 2 statements - MSW
2146  */
2147  if (op->spell_tags
2148  && !OB_SPELL_TAG_MATCH(op, (tag_t)tmp->stats.maxhp)
2149  && OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) != 0)
2150  continue;
2151 
2152  if (tmp->spell_tags
2153  && !OB_SPELL_TAG_MATCH(tmp, (tag_t)op->stats.maxhp)
2154  && OB_SPELL_TAG_HASH(tmp, op->stats.maxhp) != 0)
2155  continue;
2156 
2157  /* If we merge, the data from tmp->spell_tags gets copied into op.
2158  * so we need to make sure that slot isn't filled up.
2159  */
2160  if (tmp->spell_tags
2161  && !OB_SPELL_TAG_MATCH(tmp, (tag_t)tmp->stats.maxhp)
2162  && OB_SPELL_TAG_HASH(tmp, tmp->stats.maxhp) != 0)
2163  continue;
2164 
2165  /* If both objects have spell_tags, we need to see if there are conflicting
2166  * values - if there are, we won't be able to merge then.
2167  */
2168  if (tmp->spell_tags && op->spell_tags) {
2169  int need_copy = 0;
2170 
2171  for (i = 0; i < SPELL_TAG_SIZE; i++) {
2172  /* If the two tag values in the hash are set, but are
2173  * not set to the same value, then these objects
2174  * can not be merged.
2175  */
2176  if (op->spell_tags[i] && tmp->spell_tags[i]
2177  && op->spell_tags[i] != tmp->spell_tags[i]) {
2179  break;
2180  }
2181  /* If one tag is set and the other is not, that is
2182  * fine, but we have to note that we need to copy
2183  * the data in that case.
2184  */
2185  if ((!op->spell_tags[i] && tmp->spell_tags[i])
2186  || (op->spell_tags[i] && !tmp->spell_tags[i])) {
2187  need_copy = 1;
2188  }
2189  }
2190  /* If we did not get through entire array, it means
2191  * we got a conflicting hash, and so we won't be
2192  * able to merge these - just continue processing
2193  * object on this space.
2194  */
2195  if (i <= SPELL_TAG_SIZE)
2196  continue;
2197 
2198  /* Ok - everything checked out - we should be able to
2199  * merge tmp in op. So lets copy the tag data if
2200  * needed. Note that this is a selective copy, as
2201  * we don't want to clear values that may be set in op.
2202  */
2203  if (need_copy) {
2204  for (i = 0; i < SPELL_TAG_SIZE; i++)
2205  if (!op->spell_tags[i]
2206  && tmp->spell_tags[i]
2207  && tmp->spell_tags[i] != (tag_t)op->stats.maxhp)
2208  op->spell_tags[i] = tmp->spell_tags[i];
2209  }
2210  FREE_AND_CLEAR(tmp->spell_tags);
2211  }
2212 
2213  /* if tmp has a spell_tags table, copy it to op and free tmps */
2214  if (tmp->spell_tags && !op->spell_tags) {
2215  op->spell_tags = tmp->spell_tags;
2216  tmp->spell_tags = NULL;
2217 
2218  /* We don't need to keep a copy of our maxhp value
2219  * in the copied over value
2220  */
2221  if (OB_SPELL_TAG_MATCH(op, (tag_t)op->stats.maxhp))
2222  OB_SPELL_TAG_HASH(op, op->stats.maxhp) = 0;
2223  }
2224 
2225  /* For spells to work correctly, we need to record what spell
2226  * tags we've merged in with this effect. This is used
2227  * in ok_to_put_more() to see if a spell effect is already on
2228  * the space.
2229  */
2230  if (op->stats.maxhp != tmp->stats.maxhp) {
2231 #ifdef OBJECT_DEBUG
2232  /* This if statement should never happen - the logic above should
2233  * have prevented it. It is a problem, because by now its possible
2234  * we've destroyed the spell_tags in tmp, so we can't really
2235  * just bail out.
2236  */
2237 
2238  if (op->spell_tags
2239  && OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) != 0
2240  && !OB_SPELL_TAG_MATCH(op, tmp->stats.maxhp)) {
2241  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);
2242  }
2243 #endif
2244  if (!op->spell_tags)
2245  op->spell_tags = static_cast<tag_t *>(calloc(SPELL_TAG_SIZE, sizeof(tag_t)));
2246 
2247  OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) = tmp->stats.maxhp;
2248  }
2249 
2251  op->speed_left = MAX(op->speed_left, tmp->speed_left);
2252 
2253  if (tmp->duration != op->duration) {
2254  /* We need to use tmp_dam here because otherwise the
2255  * calculations can overflow the size of stats.dam.
2256  */
2257  int tmp_dam = tmp->stats.dam*(tmp->duration+1)+
2258  op->stats.dam*(op->duration+1);
2259 
2260  op->duration = MAX(op->duration, tmp->duration);
2261  tmp_dam /= op->duration+1;
2262  op->stats.dam = tmp_dam+1;
2263  } else {
2264  /* in this case, duration is the same, so simply adding
2265  * up damage works.
2266  */
2267  op->stats.dam += tmp->stats.dam;
2268  }
2269 
2270  object_remove(tmp);
2272  }
2273  } FOR_MAP_FINISH();
2274 }
2275 
2276 static object *find_insert_pos(object *op, const int flag) {
2277  object *floor = NULL;
2278  /*
2279  * If there are multiple objects on this space, we do some trickier handling.
2280  * We've already dealt with merging if appropriate.
2281  * Generally, we want to put the new object on top. But if
2282  * flag contains INS_ABOVE_FLOOR_ONLY, once we find the last
2283  * floor, we want to insert above that and no further.
2284  * Also, if there are spell objects on this space, we stop processing
2285  * once we get to them. This reduces the need to traverse over all of
2286  * them when adding another one - this saves quite a bit of cpu time
2287  * when lots of spells are cast in one area. Currently, it is presumed
2288  * that flying non pickable objects are spell objects.
2289  */
2290  if (flag&INS_ON_TOP) {
2291  return GET_MAP_TOP(op->map, op->x, op->y);
2292  }
2293  object *last = NULL;
2294  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp) {
2297  floor = tmp;
2298 
2300  && (tmp->move_type&(MOVE_FLY_LOW|MOVE_FLY_HIGH))
2301  && !QUERY_FLAG(tmp, FLAG_IS_FLOOR)) {
2302  /* We insert above tmp, so we want this object below this */
2303  break;
2304  }
2305  last = tmp;
2306  } FOR_MAP_FINISH();
2307  if (flag&INS_ABOVE_FLOOR_ONLY)
2308  return floor;
2309  return last;
2310 }
2311 
2340 object *object_insert_in_map(object *op, mapstruct *m, object *originator, int flag) {
2341  object *tmp, *top, *floor = NULL;
2342  int16_t x, y;
2343 
2344  if (QUERY_FLAG(op, FLAG_FREED)) {
2345  LOG(llevError, "Trying to insert freed object!\n");
2346  return NULL;
2347  }
2348  if (m == NULL) {
2349  StringBuffer *sb;
2350  char *diff;
2351 
2352  sb = stringbuffer_new();
2353  object_dump(op, sb);
2354  diff = stringbuffer_finish(sb);
2355  LOG(llevError, "Trying to insert in null-map!\n%s\n", diff);
2356  free(diff);
2357  return op;
2358  }
2359  if (out_of_map(m, op->x, op->y)) {
2360  StringBuffer *sb;
2361  char *diff;
2362 
2363  sb = stringbuffer_new();
2364  object_dump(op, sb);
2365  diff = stringbuffer_finish(sb);
2366  LOG(llevError, "Trying to insert object outside the map.\n%s\n", diff);
2367  free(diff);
2368 #ifdef MANY_CORES
2369  /* Better to catch this here, as otherwise the next use of this object
2370  * is likely to cause a crash. Better to find out where it is getting
2371  * improperly inserted.
2372  */
2373  abort();
2374 #endif
2375  return op;
2376  }
2377  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
2378  StringBuffer *sb;
2379  char *diff;
2380 
2381  sb = stringbuffer_new();
2382  object_dump(op, sb);
2383  diff = stringbuffer_finish(sb);
2384  LOG(llevError, "Trying to insert (map) inserted object.\n%s\n", diff);
2385  free(diff);
2386  return op;
2387  }
2388  if (op->more != NULL) {
2389  /* The part may be on a different map. */
2390 
2391  object *more = op->more;
2392 
2393  /* We really need the caller to normalize coordinates - if
2394  * we set the map, that doesn't work if the location is within
2395  * a map and this is straddling an edge. So only if coordinate
2396  * is clear wrong do we normalize it.
2397  */
2398  if (OUT_OF_REAL_MAP(more->map, more->x, more->y)) {
2399  /* Debugging information so you can see the last coordinates this object had */
2400  more->ox = more->x;
2401  more->oy = more->y;
2402  more->map = get_map_from_coord(more->map, &more->x, &more->y);
2403  } else if (!more->map) {
2404  /* For backwards compatibility - when not dealing with tiled maps,
2405  * more->map should always point to the parent.
2406  */
2407  more->map = m;
2408  }
2409 
2410  if (object_insert_in_map(more, more->map, originator, flag) == NULL) {
2411  if (!op->head)
2412  LOG(llevError, "BUG: object_insert_in_map(): inserting op->more killed op\n");
2413  return NULL;
2414  }
2415  }
2417 
2418  /* Debugging information so you can see the last coordinates this object had */
2419  op->ox = op->x;
2420  op->oy = op->y;
2421  x = op->x;
2422  y = op->y;
2423  op->map = get_map_from_coord(m, &x, &y);
2424 
2425  /* this has to be done after we translate the coordinates. */
2426  if (op->nrof
2427  && !(flag&INS_NO_MERGE)
2428  && op->type != SPELL_EFFECT) {
2429  FOR_MAP_PREPARE(op->map, x, y, spot) {
2430  if (object_can_merge(op, spot)) {
2431  op->nrof += spot->nrof;
2432  object_remove(spot);
2434  }
2435  } FOR_MAP_FINISH();
2436  } else if (op->type == SPELL_EFFECT
2437  && !op->range
2438  && !op->other_arch
2439  && (op->speed_left+op->speed) < 0.0) {
2440  object_merge_spell(op, x, y);
2441  }
2442 
2443  /* Ideally, the caller figures this out. However, it complicates a lot
2444  * of areas of callers (eg, anything that uses object_find_free_spot() would now
2445  * need extra work
2446  */
2447  if (op->map != m) {
2448  /* coordinates should not change unless map also changes */
2449  op->x = x;
2450  op->y = y;
2451  }
2452 
2453  if (op->type != LAMP)
2454  /* lamps use the FLAG_APPLIED to keep the light/unlit status, so don't reset it.
2455  Other objects just get unapplied, since the container "drops" them. */
2458  if (!QUERY_FLAG(op, FLAG_ALIVE))
2460 
2461  /* In many places, a player is passed as the originator, which
2462  * is fine. However, if the player is on a transport, they are not
2463  * actually on the map, so we can't use them for the linked pointers,
2464  * nor should the walk on function below use them either.
2465  */
2466  if (originator && originator->contr && originator->contr->transport)
2467  originator = originator->contr->transport;
2468 
2469  if (flag&INS_BELOW_ORIGINATOR) {
2470  if (originator->map != op->map
2471  || originator->x != op->x
2472  || originator->y != op->y) {
2473  LOG(llevError, "object_insert_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n");
2474  abort();
2475  }
2476  op->above = originator;
2477  op->below = originator->below;
2478  if (op->below)
2479  op->below->above = op;
2480  else
2481  SET_MAP_OB(op->map, op->x, op->y, op);
2482  /* since *below *originator, no need to update top */
2483  originator->below = op;
2484  } else {
2485  /* Top is the object that our object (op) is going to get inserted above. */
2486  top = find_insert_pos(op, flag);
2487 
2488  /* First object on this space */
2489  if (!top) {
2490  op->above = GET_MAP_OB(op->map, op->x, op->y);
2491  if (op->above)
2492  op->above->below = op;
2493  op->below = NULL;
2494  SET_MAP_OB(op->map, op->x, op->y, op);
2495  } else { /* get inserted into the stack above top */
2496  op->above = top->above;
2497  if (op->above)
2498  op->above->below = op;
2499  op->below = top;
2500  top->above = op;
2501  }
2502  if (op->above == NULL)
2503  SET_MAP_TOP(op->map, op->x, op->y, op);
2504  } /* else not INS_BELOW_ORIGINATOR */
2505 
2506  if (!(flag&INS_MAP_LOAD)) {
2507  if (op->type == PLAYER)
2508  op->contr->do_los = 1;
2509 
2510  /* If we have a floor, we know the player, if any, will be above
2511  * it, so save a few ticks and start from there.
2512  */
2513  tmp = floor ? floor : GET_MAP_OB(op->map, op->x, op->y);
2515  if (tmp->type == PLAYER)
2516  tmp->contr->socket->update_look = 1;
2518 
2519  /* If this object glows, it may affect lighting conditions that are
2520  * visible to others on this map. But update_all_los is really
2521  * an inefficient way to do this, as it means los for all players
2522  * on the map will get recalculated. The players could very well
2523  * be far away from this change and not affected in any way -
2524  * this should get redone to only look for players within range,
2525  * or just updating the P_NEED_UPDATE for spaces within this area
2526  * of effect may be sufficient.
2527  */
2528  if (MAP_DARKNESS(op->map) && (op->glow_radius != 0))
2529  update_all_los(op->map, op->x, op->y);
2530 
2531  if (op->contr && !op->contr->hidden)
2532  op->map->players++;
2533  }
2534 
2535  /* updates flags (blocked, alive, no magic, etc) for this map space */
2537 
2538  /* Don't know if moving this to the end will break anything. However,
2539  * we want to have update_look set above before calling this.
2540  *
2541  * object_check_move_on() must be after this because code called from
2542  * object_check_move_on() depends on correct map flags (so functions like
2543  * blocked() and wall() work properly), and these flags are updated by
2544  * object_update().
2545  */
2546 
2547  /* if this is not the head or flag has been passed, don't check walk on status */
2548 
2549  if (!(flag&INS_NO_WALK_ON) && !op->head) {
2550  if (object_check_move_on(op, originator))
2551  return NULL;
2552 
2553  /* If we are a multi part object, lets work our way through the check
2554  * walk on's.
2555  */
2556  for (tmp = op->more; tmp != NULL; tmp = tmp->more)
2557  if (object_check_move_on(tmp, originator))
2558  return NULL;
2559  }
2560  return op;
2561 }
2562 
2572 void object_replace_insert_in_map(const char *arch_string, object *op) {
2573  object *tmp1;
2574  archetype *at;
2575 
2576  /* first search for itself and remove any old instances */
2577  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp) {
2578  if (!strcmp(tmp->arch->name, arch_string)) { /* same archetype */
2579  object_remove(tmp);
2581  }
2582  } FOR_MAP_FINISH();
2583 
2584  at = find_archetype(arch_string);
2585  if (at == NULL) {
2586  return;
2587  }
2588  tmp1 = arch_to_object(at);
2589  object_insert_in_map_at(tmp1, op->map, op, INS_BELOW_ORIGINATOR, op->x, op->y);
2590 }
2591 
2612 object *object_split(object *orig_ob, uint32_t nr, char *err, size_t size) {
2613  object *newob;
2614 
2615  if (MAX(1, orig_ob->nrof) < nr) {
2616  /* If err is set, the caller knows that nr can be wrong (player trying to drop items), thus don't log that. */
2617  if (err)
2618  snprintf(err, size, "There are only %u %ss.", NROF(orig_ob), orig_ob->name);
2619  else
2620  LOG(llevDebug, "There are only %u %ss.\n", NROF(orig_ob), orig_ob->name);
2621  return NULL;
2622  }
2623  newob = object_create_clone(orig_ob);
2624  if (orig_ob->nrof == 0) {
2625  if (!QUERY_FLAG(orig_ob, FLAG_REMOVED)) {
2626  object_remove(orig_ob);
2627  }
2629  } else {
2630  newob->nrof = nr;
2631  object_decrease_nrof(orig_ob, nr);
2632  }
2633 
2634  return newob;
2635 }
2636 
2651 object *object_decrease_nrof(object *op, uint32_t i) {
2652  object *tmp;
2653 
2654  if (i == 0) /* objects with op->nrof require this check */
2655  return op;
2656 
2657  if (i > op->nrof)
2658  i = op->nrof;
2659 
2660  if (QUERY_FLAG(op, FLAG_REMOVED)) {
2661  op->nrof -= i;
2662  } else if (op->env != NULL) {
2663  if (i < op->nrof) {
2664  player *pl;
2665  /* is this object in the players inventory, or sub container
2666  * therein?
2667  */
2669  /* nope. Is this a container the player has opened?
2670  * If so, set tmp to that player.
2671  * IMO, searching through all the players will mostly
2672  * likely be quicker than following op->env to the map,
2673  * and then searching the map for a player.
2674  */
2675  if (!tmp) {
2676  for (pl = first_player; pl; pl = pl->next)
2677  if (pl->ob->container == op->env)
2678  break;
2679  if (pl)
2680  tmp = pl->ob;
2681  else
2682  tmp = NULL;
2683  }
2684 
2685  /* Because of weight reduction by container and integer arithmetic,
2686  * there is no guarantee the rounded weight of combined items will be
2687  * the same as the sum of rounded weights.
2688  * Therefore just remove the current weight, and add the new.
2689  * Same adjustment done in object_increase_nrof().
2690  */
2691  object_sub_weight(op->env, op->weight * op->nrof);
2692  op->nrof -= i;
2693  object_add_weight(op->env, op->weight * op->nrof);
2694  if (tmp) {
2697  fix_object(tmp);
2698  }
2699  } else {
2700  object_remove(op);
2701  op->nrof = 0;
2702  }
2703  } else {
2704  /* On a map. */
2705  if (i < op->nrof) {
2706  op->nrof -= i;
2707 
2708  FOR_MAP_PREPARE(op->map, op->x, op->y, pl)
2709  if (pl->contr) {
2710  pl->contr->socket->update_look = 1;
2711  break;
2712  }
2713  FOR_MAP_FINISH();
2714  } else {
2715  object_remove(op);
2716  op->nrof = 0;
2717  }
2718  }
2719 
2720  if (op->nrof) {
2721  return op;
2722  } else {
2724  return NULL;
2725  }
2726 }
2727 
2738 static void object_increase_nrof(object *op, uint32_t i) {
2739  object *tmp;
2740 
2741  if (i == 0) /* objects with op->nrof require this check */
2742  return;
2743 
2744  if (QUERY_FLAG(op, FLAG_REMOVED)) {
2745  op->nrof += i;
2746  } else if (op->env != NULL) {
2747  player *pl;
2748  /* is this object in the players inventory, or sub container
2749  * therein?
2750  */
2752  /* nope. Is this a container the player has opened?
2753  * If so, set tmp to that player.
2754  * IMO, searching through all the players will mostly
2755  * likely be quicker than following op->env to the map,
2756  * and then searching the map for a player.
2757  */
2758  if (!tmp) {
2759  for (pl = first_player; pl; pl = pl->next)
2760  if (pl->ob->container == op->env)
2761  break;
2762  if (pl)
2763  tmp = pl->ob;
2764  else
2765  tmp = NULL;
2766  }
2767 
2768  /* Because of weight reduction by container and integer arithmetic,
2769  * there is no guarantee the rounded weight of combined items will be
2770  * the same as the sum of rounded weights.
2771  * Therefore just remove the current weight, and add the new.
2772  * Same adjustment done in object_decrease_nrof().
2773  */
2774  object_sub_weight(op->env, op->weight * op->nrof);
2775  op->nrof += i;
2776  object_add_weight(op->env, op->weight * op->nrof);
2777  if (tmp) {
2779  // Why don't we need to update weight of op->env here?
2780  }
2781  } else {
2782  /* On a map. */
2783  op->nrof += i;
2784 
2785  FOR_MAP_PREPARE(op->map, op->x, op->y, pl)
2786  if (pl->contr) {
2787  pl->contr->socket->update_look = 1;
2788  break;
2789  }
2790  FOR_MAP_FINISH();
2791  }
2792 }
2793 
2808 void object_add_weight(object *op, signed long weight) {
2809  while (op != NULL) {
2810  if (op->type == CONTAINER) {
2811  weight = (signed long)(weight*(100-op->stats.Str)/100);
2812  }
2813  op->carrying += weight;
2814  op = op->env;
2815  }
2816 }
2817 
2832 object *object_insert_in_ob(object *op, object *where) {
2833  object *otmp;
2834 
2835  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
2836  StringBuffer *sb;
2837  char *diff;
2838 
2839  sb = stringbuffer_new();
2840  object_dump(op, sb);
2841  diff = stringbuffer_finish(sb);
2842  LOG(llevError, "Trying to insert (ob) inserted object.\n%s\n", diff);
2843  free(diff);
2844  return op;
2845  }
2846 
2847  if (where == NULL) {
2848  StringBuffer *sb;
2849  char *diff;
2850 
2851  sb = stringbuffer_new();
2852  object_dump(op, sb);
2853  diff = stringbuffer_finish(sb);
2854  LOG(llevError, "Trying to put object in NULL.\n%s\n", diff);
2855  free(diff);
2856  return op;
2857  }
2858  if (where->head) {
2859  LOG(llevDebug, "Warning: Tried to insert object wrong part of multipart object.\n");
2860  }
2861  where = HEAD(where);
2862  if (op->more) {
2863  LOG(llevError, "Tried to insert multipart object %s (%u)\n", op->name, op->count);
2864  return op;
2865  }
2868  if (op->nrof || op->type == SKILL) {
2870  if (op->type == SKILL && tmp->type == SKILL && op->subtype == tmp->subtype) {
2871  // Duplicate skill. Sum exp and total_exp.
2872  LOG(llevDebug, "Merged duplicate skill %s for %s\n", op->arch->name, where->name);
2873  tmp->stats.exp += op->stats.exp;
2874  tmp->total_exp += op->total_exp;
2876  object_free(op, FREE_OBJ_FREE_INVENTORY | FREE_OBJ_NO_DESTROY_CALLBACK); /* free the inserted object */
2877  return tmp;
2878  } else if (object_can_merge(tmp, op)) {
2879  /* return the original object and remove inserted object
2880  * (client needs the original object) */
2881  object_increase_nrof(tmp, op->nrof);
2883  object_free(op, FREE_OBJ_FREE_INVENTORY | FREE_OBJ_NO_DESTROY_CALLBACK); /* free the inserted object */
2884  return tmp;
2885  }
2886  FOR_INV_FINISH();
2887 
2888  /* the item couldn't merge. */
2889  object_add_weight(where, op->weight*op->nrof);
2890  } else
2891  object_add_weight(where, op->weight+op->carrying);
2892 
2893  op->map = NULL;
2894  op->env = where;
2895  op->above = NULL;
2896  op->below = NULL;
2897  op->x = 0,
2898  op->y = 0;
2899  op->ox = 0,
2900  op->oy = 0;
2901 
2902  /* Client has no idea of ordering so lets not bother ordering it here.
2903  * It sure simplifies this function...
2904  */
2905  if (where->inv == NULL)
2906  where->inv = op;
2907  else {
2908  op->below = where->inv;
2909  op->below->above = op;
2910  where->inv = op;
2911  }
2912 
2913  if (op->type == EVENT_CONNECTOR) {
2914  where->event_bitmask |= BITMASK_EVENT(op->subtype);
2915  }
2916 
2917  /* Update in 2 cases: object goes into player's inventory, or object goes into container the player
2918  * is looking into. */
2919  if (where->contr != NULL)
2921  else if (where->type == CONTAINER && QUERY_FLAG(where, FLAG_APPLIED)) {
2922  object *pl = NULL;
2923 
2924  if (op->env->env && op->env->env->contr)
2925  /* Container is in player's inventory. */
2926  pl = op->env->env;
2927  else if (op->env->map) {
2928  /* Container on map, look above for player. */
2929  FOR_ABOVE_PREPARE(op->env, above)
2930  if (above->contr) {
2931  pl = above;
2932  break;
2933  }
2934  FOR_ABOVE_FINISH();
2935  }
2936  if (pl)
2937  esrv_send_item(pl, op);
2938  }
2939 
2941  if (otmp && otmp->contr != NULL) {
2942  if (!QUERY_FLAG(otmp, FLAG_NO_FIX_PLAYER)
2943  && (QUERY_FLAG(op, FLAG_APPLIED) || op->type == SKILL || op->glow_radius != 0))
2944  /* fix_object will only consider applied items, or skills, or items with a glow radius.
2945  thus no need to call it if our object hasn't that. */
2946  fix_object(otmp);
2947  }
2948 
2949  /* reset the light list and los of the players on the map */
2950  if (op->glow_radius != 0 && where->map) {
2951 #ifdef DEBUG_LIGHTS
2952  LOG(llevDebug, " object_insert_in_ob(): got %s to insert in map/op\n", op->name);
2953 #endif /* DEBUG_LIGHTS */
2954  if (MAP_DARKNESS(where->map)) {
2955  SET_MAP_FLAGS(where->map, where->x, where->y, P_NEED_UPDATE);
2956  update_position(where->map, where->x, where->y);
2957  update_all_los(where->map, where->x, where->y);
2958  }
2959  }
2960 
2961  return op;
2962 }
2963 
2986 int object_check_move_on(object *op, object *originator) {
2987  object *tmp;
2988  tag_t tag;
2989  mapstruct *m = op->map;
2990  int x = op->x, y = op->y;
2991  MoveType move_on, move_slow, move_block;
2992 
2993  if (QUERY_FLAG(op, FLAG_NO_APPLY))
2994  return 0;
2995 
2996  tag = op->count;
2997 
2998  move_on = GET_MAP_MOVE_ON(op->map, op->x, op->y);
2999  move_slow = GET_MAP_MOVE_SLOW(op->map, op->x, op->y);
3000  move_block = GET_MAP_MOVE_BLOCK(op->map, op->x, op->y);
3001 
3002  /* if nothing on this space will slow op down or be applied,
3003  * no need to do checking below. have to make sure move_type
3004  * is set, as lots of objects don't have it set - we treat that
3005  * as walking.
3006  */
3007  if (op->move_type
3008  && !(op->move_type&move_on)
3009  && !(op->move_type&move_slow))
3010  return 0;
3011 
3012  /* This is basically inverse logic of that below - basically,
3013  * if the object can avoid the move on or slow move, they do so,
3014  * but can't do it if the alternate movement they are using is
3015  * blocked. Logic on this seems confusing, but does seem correct.
3016  */
3017  if ((op->move_type&~move_on&~move_block) != 0
3018  && (op->move_type&~move_slow&~move_block) != 0)
3019  return 0;
3020 
3021  /* The objects have to be checked from top to bottom.
3022  * Hence, we first go to the top:
3023  */
3024 
3025  tmp = GET_MAP_OB(op->map, op->x, op->y);
3027  if (tmp->above == NULL)
3028  break;
3029  /* Trim the search when we find the first other spell effect
3030  * this helps performance so that if a space has 50 spell objects,
3031  * we don't need to check all of them.
3032  */
3033  if ((tmp->move_type&MOVE_FLY_LOW) && QUERY_FLAG(tmp, FLAG_NO_PICK))
3034  break;
3037  if (tmp == op)
3038  continue; /* Can't apply yourself */
3039 
3040  /* Check to see if one of the movement types should be slowed down.
3041  * Second check makes sure that the movement types not being slowed
3042  * (~slow_move) is not blocked on this space - just because the
3043  * space doesn't slow down swimming (for example), if you can't actually
3044  * swim on that space, can't use it to avoid the penalty.
3045  */
3046  if (!QUERY_FLAG(op, FLAG_WIZPASS)) {
3047  if ((!op->move_type && tmp->move_slow&MOVE_WALK)
3048  || ((op->move_type&tmp->move_slow) && (op->move_type&~tmp->move_slow&~tmp->move_block) == 0)) {
3049  float diff;
3050 
3051  diff = tmp->move_slow_penalty*FABS(op->speed);
3052  if (op->type == PLAYER) {
3055  diff /= 4.0;
3056  }
3057  }
3058  op->speed_left -= diff;
3059  }
3060  }
3061 
3062  /* Basically same logic as above, except now for actual apply. */
3063  if ((!op->move_type && tmp->move_on&MOVE_WALK)
3064  || ((op->move_type&tmp->move_on) && (op->move_type&~tmp->move_on&~tmp->move_block) == 0)) {
3065  ob_move_on(tmp, op, originator);
3066  if (object_was_destroyed(op, tag))
3067  return 1;
3068 
3069  /* what the person/creature stepped onto has moved the object
3070  * someplace new. Don't process any further - if we did,
3071  * have a feeling strange problems would result.
3072  */
3073  if (op->map != m || op->x != x || op->y != y)
3074  return 0;
3075  }
3077  return 0;
3078 }
3079 
3092 object *map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at) {
3093  if (m == NULL || OUT_OF_REAL_MAP(m, x, y)) {
3094  LOG(llevError, "Present_arch called outside map.\n");
3095  return NULL;
3096  }
3097 
3098  FOR_MAP_PREPARE(m, x, y, tmp)
3099  if (tmp->arch == at)
3100  return tmp;
3101  FOR_MAP_FINISH();
3102 
3103  return NULL;
3104 }
3105 
3119 object *map_find_by_type(mapstruct *m, int x, int y, uint8_t type) {
3120  if (OUT_OF_REAL_MAP(m, x, y)) {
3121  return NULL;
3122  }
3123 
3124  FOR_MAP_PREPARE(m, x, y, tmp)
3125  if (tmp->type == type)
3126  return tmp;
3127  FOR_MAP_FINISH();
3128 
3129  return NULL;
3130 }
3131 
3142 object *object_present_in_ob(uint8_t type, const object *op) {
3143  object *tmp;
3144 
3145  for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
3146  if (tmp->type == type)
3147  return tmp;
3148 
3149  return NULL;
3150 }
3151 
3177 object *object_present_in_ob_by_name(int type, const char *str, const object *op) {
3178  object *tmp;
3179 
3180  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
3181  if ((type == -1 || tmp->type == type) && !strcmp(str, tmp->name))
3182  return tmp;
3183  }
3184  return NULL;
3185 }
3186 
3196 object *arch_present_in_ob(const archetype *at, const object *op) {
3197  object *tmp;
3198 
3199  for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
3200  if (tmp->arch == at)
3201  return tmp;
3202  return NULL;
3203 }
3204 
3213 void object_set_flag_inv(object*op, int flag) {
3214  object *tmp;
3215 
3216  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
3217  SET_FLAG(tmp, flag);
3218  object_set_flag_inv(tmp, flag);
3219  }
3220 }
3221 
3230 void object_unset_flag_inv(object*op, int flag) {
3231  object *tmp;
3232 
3233  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
3234  CLEAR_FLAG(tmp, flag);
3235  object_unset_flag_inv(tmp, flag);
3236  }
3237 }
3238 
3248 void object_set_cheat(object *op) {
3251 }
3252 
3270 int object_find_multi_free_spot_around(const object *ob, const object *gen, int16_t *hx, int16_t *hy) {
3271  int genx, geny, genx2, geny2, sx, sy, sx2, sy2, ix, iy, nx, ny, i, flag;
3272  int freecount = 0;
3273 
3274  ob = HEAD(ob);
3275 
3276  object_get_multi_size(ob, &sx, &sy, &sx2, &sy2);
3277  object_get_multi_size(gen, &genx, &geny, &genx2, &geny2);
3278  /*
3279  * sx and sy are now the coords of the bottom right corner of ob relative to the head.
3280  * genx and geny are now the coords of the bottom right corner of gen relative to the head.
3281  * sx2 and sy2 are now the coords of the head of ob relative to the top left corner.
3282  * genx2 and geny2 are now the coords of the head of gen relative to the top left corner.
3283  */
3284 
3285  sx++;
3286  sy++;
3287  genx++;
3288  geny++;
3289  /*
3290  * sx, sy, genx, and geny, are now the size of the object, excluding parts left and above
3291  * the head.
3292  */
3293 
3294  ix = gen->x-sx-genx2;
3295  iy = gen->y-sy-geny2;
3296  sx += genx+sx2;
3297  sy += geny+sy2;
3298  /*
3299  * ix and iy are the map coords of the top left square where the head of ob could possibly
3300  * be placed. sx and sy are now the size of the square to search for placement of the head
3301  * relative to ix and iy.
3302  */
3303 
3304  /*
3305  * Loop around the square of possible positions for the head of ob object:
3306  */
3307  for (i = 0; i < (sx+sx+sy+sy); i++) {
3308  if (i <= sx) {
3309  nx = i+ix;
3310  ny = iy;
3311  } else if (i <= sx+sy) {
3312  nx = ix+sx;
3313  ny = iy+i-sx;
3314  } else if (i <= sx+sy+sx) {
3315  nx = ix+sx-(i-(sx+sy));
3316  ny = iy+sy;
3317  } else {
3318  nx = ix;
3319  ny = iy+sy-(i-(sx+sy+sx));
3320  }
3321  /* Check if the spot is free. */
3322  flag = ob_blocked(ob, gen->map, nx, ny);
3323  if (!flag) {
3324  freecount++;
3325  }
3326  }
3327  /* If no free spaces, return. */
3328  if (!freecount)
3329  return -1;
3330 
3331  /* Choose a random valid position */
3332  freecount = RANDOM()%freecount;
3333  for (i = 0; i < sx+sx+sy+sy; i++) {
3334  if (i <= sx) {
3335  nx = i+ix;
3336  ny = iy;
3337  } else if (i <= sx+sy) {
3338  nx = ix+sx;
3339  ny = iy+i-sx;
3340  } else if (i <= sx+sy+sx) {
3341  nx = ix+sx-(i-(sx+sy));
3342  ny = iy+sy;
3343  } else {
3344  nx = ix;
3345  ny = iy+sy-(i-(sx+sy+sx));
3346  }
3347 
3348  /* Make sure it's within map. */
3349  if (nx < 0 || nx >= MAP_WIDTH(gen->map)
3350  || ny < 0 || ny >= MAP_HEIGHT(gen->map))
3351  continue;
3352 
3353  /* Check if the spot is free.*/
3354  flag = ob_blocked(ob, gen->map, nx, ny);
3355  if (!flag) {
3356  freecount--;
3357  if (freecount <= 0) {
3358  *hx = nx;
3359  *hy = ny;
3360  return 0;
3361  }
3362  }
3363  }
3364  return -1;
3365 }
3366 
3386 int object_find_multi_free_spot_within_radius(const object *ob, const object *gen, int *hx, int *hy) {
3387  int genx, geny, genx2, geny2, sx, sy, sx2, sy2, ix, iy, nx, ny, i, flag;
3388  int8_t x, y, radius;
3389  int freecount = 0, freecountstop = 0;
3390  const char *value;
3391  int8_t *x_array;
3392  int8_t *y_array;
3393 
3394  /* If radius is not set, default to 1 */
3395  value = object_get_value(gen, "generator_radius");
3396  if (value) {
3397  radius = (int8_t)strtol(value, NULL, 10);
3398  if (radius < 1) {
3399  radius = 1;
3400  }
3401  } else {
3402  radius = 1;
3403  }
3404 
3405  ob = HEAD(ob);
3406 
3407  object_get_multi_size(ob, &sx, &sy, &sx2, &sy2);
3408  object_get_multi_size(gen, &genx, &geny, &genx2, &geny2);
3409  /*
3410  * sx and sy are now the coords of the bottom right corner
3411  * of ob relative to the head.
3412  * genx and geny are now the coords of the bottom right corner
3413  * of gen relative to the head.
3414  * sx2 and sy2 are now the coords of the head of ob relative
3415  * to the top left corner.
3416  * genx2 and geny2 are now the coords of the head of gen relative
3417  * to the top left corner.
3418  */
3419 
3420  sx++;
3421  sy++;
3422  genx++;
3423  geny++;
3424  /*
3425  * sx, sy, genx, and geny, are now the size of the object,
3426  * excluding parts left and above the head.
3427  */
3428 
3429  ix = gen->x-sx-genx2-radius+1;
3430  iy = gen->y-sy-geny2-radius+1;
3431  sx += genx+sx2+radius*2-1;
3432  sy += geny+sy2+radius*2-1;
3433 
3434  /*
3435  * ix and iy are the map coords of the top left square where
3436  * the head of ob could possibly be placed. sx and sy are now
3437  * the size of the square to search for placement of the head
3438  * relative to ix and iy.
3439  */
3440 
3441  /* Create arrays large enough to hold free space coordinates */
3442  x_array = static_cast<int8_t *>(malloc(sx*sy*sizeof(int8_t)));
3443  y_array = static_cast<int8_t *>(malloc(sx*sy*sizeof(int8_t)));
3444 
3445  /*
3446  * Loop through the area of possible positions for the head of ob object:
3447  */
3448  for (x = 0; x < sx; x++) {
3449  for (y = 0; y < sy; y++) {
3450  nx = ix+x;
3451  ny = iy+y;
3452 
3453 
3454  /* Make sure it's within map. */
3455  if (get_map_flags(gen->map, NULL, nx, ny, NULL, NULL)&P_OUT_OF_MAP) {
3456  continue;
3457  }
3458 
3459  /* Check if the spot is free. */
3460  flag = ob_blocked(ob, gen->map, nx, ny);
3461  if (!flag) {
3462  x_array[freecount] = nx;
3463  y_array[freecount] = ny;
3464  freecount++;
3465  }
3466  }
3467  }
3468  /* If no free spaces, return. */
3469  if (!freecount) {
3470  free(x_array);
3471  free(y_array);
3472  return -1;
3473  }
3474 
3475  /* Choose a random valid position */
3476  freecountstop = RANDOM()%freecount;
3477  for (i = 0; i < freecount; i++) {
3478  nx = x_array[i];
3479  ny = y_array[i];
3480 
3481  /* Check if the spot is free.*/
3482  flag = ob_blocked(ob, gen->map, nx, ny);
3483  if (!flag) {
3484  freecountstop--;
3485  if (freecountstop <= 0) {
3486  *hx = nx;
3487  *hy = ny;
3488  free(x_array);
3489  free(y_array);
3490  return 0;
3491  }
3492  }
3493  }
3494  free(x_array);
3495  free(y_array);
3496  return -1;
3497 }
3498 
3533 int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop) {
3534  int i, index = 0, flag;
3535  static int altern[SIZEOFFREE];
3536 
3537  for (i = start; i < stop; i++) {
3538  flag = ob_blocked(ob, m, x+freearr_x[i], y+freearr_y[i]);
3539  if (!flag)
3540  altern[index++] = i;
3541 
3542  /* Basically, if we find a wall on a space, we cut down the search size.
3543  * In this way, we won't return spaces that are on another side of a wall.
3544  * This mostly work, but it cuts down the search size in all directions -
3545  * if the space being examined only has a wall to the north and empty
3546  * spaces in all the other directions, this will reduce the search space
3547  * to only the spaces immediately surrounding the target area, and
3548  * won't look 2 spaces south of the target space.
3549  */
3550  else if ((flag&AB_NO_PASS) && maxfree[i] < stop)
3551  stop = maxfree[i];
3552  }
3553  if (!index)
3554  return -1;
3555  return altern[RANDOM()%index];
3556 }
3557 
3573 int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y) {
3574  int i;
3575 
3576  for (i = 0; i < SIZEOFFREE; i++) {
3577  if (!ob_blocked(ob, m, x+freearr_x[i], y+freearr_y[i]))
3578  return i;
3579  }
3580  return -1;
3581 }
3582 
3592 static void permute(int *arr, int begin, int end) {
3593  int i, j, tmp, len;
3594 
3595  len = end-begin;
3596  for (i = begin; i < end; i++) {
3597  j = begin+RANDOM()%len;
3598 
3599  tmp = arr[i];
3600  arr[i] = arr[j];
3601  arr[j] = tmp;
3602  }
3603 }
3604 
3616 void get_search_arr(int *search_arr) {
3617  int i;
3618 
3619  for (i = 0; i < SIZEOFFREE; i++) {
3620  search_arr[i] = i;
3621  }
3622 
3623  permute(search_arr, 1, SIZEOFFREE1+1);
3624  permute(search_arr, SIZEOFFREE1+1, SIZEOFFREE2+1);
3625  permute(search_arr, SIZEOFFREE2+1, SIZEOFFREE);
3626 }
3627 
3635 int object_distance(const object *ob1, const object *ob2) {
3636  int i;
3637 
3638  i = (ob1->x-ob2->x)*(ob1->x-ob2->x)+
3639  (ob1->y-ob2->y)*(ob1->y-ob2->y);
3640  return i;
3641 }
3642 
3651 int find_dir_2(int x, int y) {
3652  int q;
3653 
3654  if (!y)
3655  q = -300*x;
3656  else
3657  q = x*100/y;
3658  if (y > 0) {
3659  if (q < -242)
3660  return 3;
3661  if (q < -41)
3662  return 2;
3663  if (q < 41)
3664  return 1;
3665  if (q < 242)
3666  return 8;
3667  return 7;
3668  }
3669  if (q < -242)
3670  return 7;
3671  if (q < -41)
3672  return 6;
3673  if (q < 41)
3674  return 5;
3675  if (q < 242)
3676  return 4;
3677  return 3;
3678 }
3679 
3688 int absdir(int d) {
3689  // Shortcut for modulus that work becuase we have a power of 2
3690  d &= 7;
3691  // 0 needs to be 8
3692  if (!d)
3693  d = 8;
3694  return d;
3695 }
3696 
3706 int dirdiff(int dir1, int dir2) {
3707  int d;
3708 
3709  d = abs(dir1-dir2);
3710  if (d > 4)
3711  d = 8-d;
3712  return d;
3713 }
3714 
3726 static const int reduction_dir[SIZEOFFREE][3] = {
3727  { 0, 0, 0 }, /* 0 */
3728  { 0, 0, 0 }, /* 1 */
3729  { 0, 0, 0 }, /* 2 */
3730  { 0, 0, 0 }, /* 3 */
3731  { 0, 0, 0 }, /* 4 */
3732  { 0, 0, 0 }, /* 5 */
3733  { 0, 0, 0 }, /* 6 */
3734  { 0, 0, 0 }, /* 7 */
3735  { 0, 0, 0 }, /* 8 */
3736  { 8, 1, 2 }, /* 9 */
3737  { 1, 2, -1 }, /* 10 */
3738  { 2, 10, 12 }, /* 11 */
3739  { 2, 3, -1 }, /* 12 */
3740  { 2, 3, 4 }, /* 13 */
3741  { 3, 4, -1 }, /* 14 */
3742  { 4, 14, 16 }, /* 15 */
3743  { 5, 4, -1 }, /* 16 */
3744  { 4, 5, 6 }, /* 17 */
3745  { 6, 5, -1 }, /* 18 */
3746  { 6, 20, 18 }, /* 19 */
3747  { 7, 6, -1 }, /* 20 */
3748  { 6, 7, 8 }, /* 21 */
3749  { 7, 8, -1 }, /* 22 */
3750  { 8, 22, 24 }, /* 23 */
3751  { 8, 1, -1 }, /* 24 */
3752  { 24, 9, 10 }, /* 25 */
3753  { 9, 10, -1 }, /* 26 */
3754  { 10, 11, -1 }, /* 27 */
3755  { 27, 11, 29 }, /* 28 */
3756  { 11, 12, -1 }, /* 29 */
3757  { 12, 13, -1 }, /* 30 */
3758  { 12, 13, 14 }, /* 31 */
3759  { 13, 14, -1 }, /* 32 */
3760  { 14, 15, -1 }, /* 33 */
3761  { 33, 15, 35 }, /* 34 */
3762  { 16, 15, -1 }, /* 35 */
3763  { 17, 16, -1 }, /* 36 */
3764  { 18, 17, 16 }, /* 37 */
3765  { 18, 17, -1 }, /* 38 */
3766  { 18, 19, -1 }, /* 39 */
3767  { 41, 19, 39 }, /* 40 */
3768  { 19, 20, -1 }, /* 41 */
3769  { 20, 21, -1 }, /* 42 */
3770  { 20, 21, 22 }, /* 43 */
3771  { 21, 22, -1 }, /* 44 */
3772  { 23, 22, -1 }, /* 45 */
3773  { 45, 47, 23 }, /* 46 */
3774  { 23, 24, -1 }, /* 47 */
3775  { 24, 9, -1 } /* 48 */
3776 };
3777 
3796 int can_see_monsterP(mapstruct *m, int x, int y, int dir) {
3797  int16_t dx, dy;
3798  int mflags;
3799 
3800  if (dir < 0)
3801  return 0; /* exit condition: invalid direction */
3802 
3803  dx = x+freearr_x[dir];
3804  dy = y+freearr_y[dir];
3805 
3806  mflags = get_map_flags(m, &m, dx, dy, &dx, &dy);
3807 
3808  /* This functional arguably was incorrect before - it was
3809  * checking for P_WALL - that was basically seeing if
3810  * we could move to the monster - this is being more
3811  * literal on if we can see it. To know if we can actually
3812  * move to the monster, we'd need the monster passed in or
3813  * at least its move type.
3814  */
3815  if (mflags&(P_OUT_OF_MAP|P_BLOCKSVIEW))
3816  return 0;
3817 
3818  /* yes, can see. */
3819  if (dir < 9)
3820  return 1;
3821  return can_see_monsterP(m, x, y, reduction_dir[dir][0])|
3822  can_see_monsterP(m, x, y, reduction_dir[dir][1])|
3823  can_see_monsterP(m, x, y, reduction_dir[dir][2]);
3824 }
3825 
3841 int object_can_pick(const object *who, const object *item) {
3842  /* I re-wrote this as a series of if statements
3843  * instead of a nested return (foo & bar && yaz)
3844  * - I think this is much more readable,
3845  * and likely compiler effectively optimizes it the
3846  * same.
3847  */
3848  if (item->weight <= 0)
3849  return 0;
3851  return 0;
3852  if (QUERY_FLAG(item, FLAG_ALIVE))
3853  return 0;
3854  if (item->invisible)
3855  return 0;
3856  if (item->type == TRANSPORT && item->contr != NULL) {
3857  return 0;
3858  }
3859 
3860  /* Weight limit for monsters */
3861  if (who->type != PLAYER && ((uint32_t)(who->weight+who->carrying+item->weight)) > get_weight_limit(who->stats.Str))
3862  return 0;
3863 
3864  /* Can not pick up multipart objects */
3865  if (item->head || item->more)
3866  return 0;
3867 
3868  /* Everything passes, so OK to pick up */
3869  return 1;
3870 }
3871 
3883 object *object_create_clone(object *asrc) {
3884  object *dst = NULL, *tmp, *src, *part, *prev;
3885 
3886  if (!asrc)
3887  return NULL;
3888  src = HEAD(asrc);
3889 
3890  prev = NULL;
3891  for (part = src; part; part = part->more) {
3892  tmp = object_new();
3893  object_copy(part, tmp);
3894  /*
3895  * Need to reset the weight, since object_insert_in_ob() later will
3896  * recompute this field.
3897  */
3898  tmp->carrying = tmp->arch->clone.carrying;
3899  tmp->x -= src->x;
3900  tmp->y -= src->y;
3901  if (!part->head) {
3902  dst = tmp;
3903  tmp->head = NULL;
3904  } else {
3905  tmp->head = dst;
3906  }
3907  tmp->more = NULL;
3908  if (prev)
3909  prev->more = tmp;
3910  prev = tmp;
3911  }
3912  /*** copy inventory ***/
3913  FOR_INV_PREPARE(src, item)
3915  FOR_INV_FINISH();
3916 
3917  return dst;
3918 }
3919 
3930 object *object_find_by_name(const object *who, const char *name) {
3931  const char *name_shared = add_string(name);
3932  object *tmp;
3933 
3934  for (tmp = who->inv; tmp; tmp = tmp->below)
3935  if (tmp->name == name_shared)
3936  break;
3937  free_string(name_shared);
3938  return tmp;
3939 }
3940 
3954 object *object_find_by_type(const object *who, int type) {
3955  object *tmp;
3956 
3957  for (tmp = who->inv; tmp; tmp = tmp->below)
3958  if (tmp->type == type)
3959  return tmp;
3960 
3961  return NULL;
3962 }
3963 
3978 object *object_find_by_type_without_flags(const object *who, int type, int *flags, int num_flags) {
3979  int flag_okay;
3980  for (object *tmp = who->inv; tmp; tmp = tmp->below)
3981  if (tmp->type == type) {
3982  flag_okay = 1;
3983  for (int i = 0; i < num_flags; ++i) {
3984  if (QUERY_FLAG(tmp, flags[i])) {
3985  flag_okay = 0; // A flag we didn't want set was set. Skip this item.
3986  break;
3987  }
3988  }
3989  if (flag_okay) // If flag_okay == 1, then the flags specified were not set
3990  return tmp; // If we reach here, none of the flags specified were set. Just like we wanted.
3991  }
3992 
3993  return NULL;
3994 }
3995 
4011 object *object_find_by_type2(const object *who, int type1, int type2) {
4012  object *tmp;
4013 
4014  for (tmp = who->inv; tmp; tmp = tmp->below)
4015  if (tmp->type == type1 || tmp->type == type2)
4016  return tmp;
4017 
4018  return NULL;
4019 }
4020 
4034 object *object_find_by_tag(const object *who, tag_t tag) {
4035  object *tmp;
4036 
4037  for (tmp = who->inv; tmp; tmp = tmp->below)
4038  if (tmp->count == tag)
4039  return tmp;
4040 
4041  return NULL;
4042 }
4043 
4057 object *object_find_by_type_applied(const object *who, int type) {
4058  object *tmp;
4059 
4060  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4061  if (tmp->type == type && QUERY_FLAG(tmp, FLAG_APPLIED))
4062  return tmp;
4063 
4064  return NULL;
4065 }
4066 
4082 object *object_find_by_type_and_name(const object *who, int type, const char *name) {
4083  object *tmp;
4084 
4085  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4086  if (tmp->type == type && strcmp(tmp->name, name) == 0)
4087  return tmp;
4088 
4089  return NULL;
4090 }
4091 
4107 object *object_find_by_type_and_race(const object *who, int type, const char *race) {
4108  object *tmp;
4109 
4110  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4111  if (tmp->type == type && strcmp(tmp->race, race) == 0)
4112  return tmp;
4113 
4114  return NULL;
4115 }
4116 
4132 object *object_find_by_type_and_slaying(const object *who, int type, const char *slaying) {
4133  object *tmp;
4134 
4135  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4136  if (tmp->type == type && tmp->slaying != NULL && strcmp(tmp->slaying, slaying) == 0)
4137  return tmp;
4138 
4139  return NULL;
4140 }
4141 
4157 object *object_find_by_type_and_skill(const object *who, int type, const char *skill) {
4158  object *tmp;
4159 
4160  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4161  if (tmp->type == type && tmp->skill != NULL && strcmp(tmp->skill, skill) == 0)
4162  return tmp;
4163 
4164  return NULL;
4165 }
4166 
4180 object *object_find_by_flag(const object *who, int flag) {
4181  object *tmp;
4182 
4183  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4184  if (QUERY_FLAG(tmp, flag))
4185  return tmp;
4186 
4187  return NULL;
4188 }
4189 
4203 object *object_find_by_flag_applied(const object *who, int flag) {
4204  object *tmp;
4205 
4206  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4207  if (QUERY_FLAG(tmp, FLAG_APPLIED) && QUERY_FLAG(tmp, flag))
4208  return tmp;
4209 
4210  return NULL;
4211 }
4212 
4226 object *object_find_by_arch_name(const object *who, const char *name) {
4227  object *tmp;
4228 
4229  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4230  if (strcmp(tmp->arch->name, name) == 0)
4231  return tmp;
4232 
4233  return NULL;
4234 }
4235 
4251 object *object_find_by_type_and_arch_name(const object *who, int type, const char *name) {
4252  object *tmp;
4253 
4254  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4255  if (tmp->type == type && strcmp(tmp->arch->name, name) == 0)
4256  return tmp;
4257 
4258  return NULL;
4259 }
4260 
4275 object *object_find_by_type_subtype(const object *who, int type, int subtype) {
4276  object *tmp;
4277 
4278  for (tmp = who->inv; tmp; tmp = tmp->below)
4279  if (tmp->type == type && tmp->subtype == subtype)
4280  return tmp;
4281 
4282  return NULL;
4283 }
4284 
4295 key_value *object_get_key_value(const object *ob, const char *key) {
4296  key_value *link;
4297 
4298  for (link = ob->key_values; link != NULL; link = link->next) {
4299  if (link->key == key) {
4300  return link;
4301  }
4302  }
4303 
4304  return NULL;
4305 }
4306 
4320 const char *object_get_value(const object *op, const char *const key) {
4321  key_value *link;
4322  const char *canonical_key;
4323 
4324  canonical_key = find_string(key);
4325 
4326  if (canonical_key == NULL) {
4327  /* 1. There being a field named key on any object
4328  * implies there'd be a shared string to find.
4329  * 2. Since there isn't, no object has this field.
4330  * 3. Therefore, *this *object doesn't have this field.
4331  */
4332  return NULL;
4333  }
4334 
4335  /* This is copied from object_get_key_value() above -
4336  * only 4 lines, and saves the function call overhead.
4337  */
4338  for (link = op->key_values; link != NULL; link = link->next) {
4339  if (link->key == canonical_key) {
4340  return link->value;
4341  }
4342  }
4343  return NULL;
4344 }
4345 
4350 bool object_value_set(const object *op, const char *const key) {
4351  const char *ret = object_get_value(op, key);
4352  if (ret == NULL || (strcmp(ret, "") == 0) || (strcmp(ret, "0") == 0)) {
4353  return false;
4354  }
4355  return true;
4356 }
4357 
4364 bool object_value_set_shared(const object *op, sstring key) {
4365  for (key_value *link = op->key_values; link != NULL; link = link->next) {
4366  if (link->key == key) {
4367  if ((strcmp(link->value, "") == 0) || (strcmp(link->value, "0") == 0)) {
4368  return false;
4369  }
4370  return true;
4371  }
4372  }
4373  return false;
4374 }
4375 
4390 static int object_set_value_s(object *op, const char *canonical_key, const char *value, int add_key) {
4391  key_value *field = NULL, *last = NULL;
4392 
4393  for (field = op->key_values; field != NULL; field = field->next) {
4394  if (field->key != canonical_key) {
4395  last = field;
4396  continue;
4397  }
4398 
4399  if (field->value)
4400  FREE_AND_CLEAR_STR(field->value);
4401  if (value)
4402  field->value = add_string(value);
4403  else {
4404  /* Basically, if the archetype has this key set,
4405  * we need to store the null value so when we save
4406  * it, we save the empty value so that when we load,
4407  * we get this value back again.
4408  */
4409  if (object_get_key_value(&op->arch->clone, canonical_key))
4410  field->value = NULL;
4411  else {
4412  /* Delete this link */
4413  if (field->key)
4414  FREE_AND_CLEAR_STR(field->key);
4415  if (field->value)
4416  FREE_AND_CLEAR_STR(field->value);
4417  if (last)
4418  last->next = field->next;
4419  else
4420  op->key_values = field->next;
4421  free(field);
4422  }
4423  }
4424  return TRUE;
4425  }
4426  /* IF we get here, key doesn't exist */
4427 
4428  /* No field, we'll have to add it. */
4429 
4430  if (!add_key) {
4431  return FALSE;
4432  }
4433  /* There isn't any good reason to store a null
4434  * value in the key/value list. If the archetype has
4435  * this key, then we should also have it, so shouldn't
4436  * be here. If user wants to store empty strings,
4437  * should pass in ""
4438  */
4439  if (value == NULL)
4440  return TRUE;
4441 
4442  field = static_cast<key_value *>(malloc(sizeof(key_value)));
4443 
4444  field->key = add_refcount(canonical_key);
4445  field->value = add_string(value);
4446  /* Usual prepend-addition. */
4447  field->next = op->key_values;
4448  op->key_values = field;
4449 
4450  return TRUE;
4451 }
4452 
4473 int object_set_value(object *op, const char *key, const char *value, int add_key) {
4474  const char *canonical_key = NULL;
4475  int floating_ref = FALSE;
4476  int ret;
4477 
4478  /* HACK This mess is to make sure set_ob_value() passes a shared string
4479  * to object_get_key_value(), without leaving a leaked refcount.
4480  */
4481 
4482  canonical_key = find_string(key);
4483  if (canonical_key == NULL) {
4484  canonical_key = add_string(key);
4485  floating_ref = TRUE;
4486  }
4487 
4488  ret = object_set_value_s(op, canonical_key, value, add_key);
4489 
4490  if (floating_ref) {
4491  free_string(canonical_key);
4492  }
4493 
4494  return ret;
4495 }
4496 
4548 int object_matches_string(object *pl, object *op, const char *name) {
4549  char *cp, local_name[MAX_BUF], name_op[MAX_BUF], name_short[HUGE_BUF], bname_s[MAX_BUF], bname_p[MAX_BUF];
4550  int count, retval = 0;
4551  /* strtok is destructive to name */
4552  safe_strncpy(local_name, name, sizeof(local_name));
4553  sstring custom_name = object_get_value(op, CUSTOM_NAME_FIELD);
4554 
4555  for (cp = strtok(local_name, ","); cp; cp = strtok(NULL, ",")) {
4556  while (cp[0] == ' ')
4557  ++cp; /* get rid of spaces */
4558 
4559  /* LOG(llevDebug, "Trying to match %s\n", cp);*/
4560  /* All is a very generic match - low match value */
4561  if (!strcmp(cp, "all"))
4562  return 1;
4563 
4564  /* unpaid is a little more specific */
4565  if (!strcmp(cp, "unpaid") && QUERY_FLAG(op, FLAG_UNPAID))
4566  return 2;
4567  if (!strcmp(cp, "cursed")
4570  return 2;
4571 
4572  if (!strcmp(cp, "unlocked") && !QUERY_FLAG(op, FLAG_INV_LOCKED))
4573  return 2;
4574 
4575  /* Allow for things like '100 arrows' */
4576  count = atoi(cp);
4577  if (*cp == '+' || *cp == '-')
4578  count=0; // Let +/- searches look in description for magic bonuses
4579  if (count != 0) {
4580  cp = strchr(cp, ' ');
4581  while (cp && cp[0] == ' ')
4582  ++cp; /* get rid of spaces */
4583  } else {
4584  if (pl->type == PLAYER)
4585  count = pl->contr->count;
4586  else
4587  count = 0;
4588  }
4589 
4590  if (!cp || cp[0] == '\0' || count < 0)
4591  continue;
4592 
4593  /* The code here should go from highest retval to lowest. That
4594  * is because of the 'else' handling - we don't want to match on
4595  * something and set a low retval, even though it may match a higher retcal
4596  * later. So keep it in descending order here, so we try for the best
4597  * match first, and work downward.
4598  */
4599  query_name(op, name_op, MAX_BUF);
4600  query_short_name(op, name_short, HUGE_BUF);
4601  query_base_name(op, 0, bname_s, MAX_BUF);
4602  query_base_name(op, 1, bname_p, MAX_BUF);
4603 
4604  if (!strcasecmp(cp, name_op))
4605  retval = 20;
4606  else if (!strcasecmp(cp, name_short))
4607  retval = 18;
4608  else if (!strcasecmp(cp, bname_s))
4609  retval = 16;
4610  else if (!strcasecmp(cp, bname_p))
4611  retval = 16;
4612  else if (custom_name && !strcasecmp(cp, custom_name))
4613  retval = 15;
4614  else if (!strncasecmp(cp, bname_s, strlen(cp)))
4615  retval = 14;
4616  else if (!strncasecmp(cp, bname_p, strlen(cp)))
4617  retval = 14;
4618  /* Do substring checks, so things like 'Str+1' will match.
4619  * retval of these should perhaps be lower - they are lower
4620  * then the specific strcasecmp aboves, but still higher than
4621  * some other match criteria.
4622  */
4623  else if (strstr(bname_p, cp))
4624  retval = 12;
4625  else if (strstr(bname_s, cp))
4626  retval = 12;
4627  else if (strstr(name_short, cp))
4628  retval = 12;
4629  /* Check against plural/non plural based on count. */
4630  else if (count > 1 && !strcasecmp(cp, op->name_pl)) {
4631  retval = 6;
4632  } else if (count == 1 && !strcasecmp(op->name, cp)) {
4633  retval = 6;
4634  }
4635  /* base name matched - not bad */
4636  else if (strcasecmp(cp, op->name) == 0 && !count)
4637  retval = 4;
4638  /* Check for partial custom name, but give a real low priority */
4639  else if (custom_name && strstr(custom_name, cp))
4640  retval = 3;
4641 
4642  if (retval) {
4643  if (pl->type == PLAYER)
4644  pl->contr->count = count;
4645  return retval;
4646  }
4647  }
4648  return 0;
4649 }
4650 
4659 void object_fix_multipart(object *tmp) {
4660  archetype *at;
4661  object *op, *last;
4662 
4663  if (!tmp->map) {
4664  LOG(llevError, "object_fix_multipart: not on a map!\n");
4665  return;
4666  }
4667 
4668  /* already multipart - don't do anything more */
4669  if (tmp->head || tmp->more)
4670  return;
4671 
4672  /* If there is nothing more to this object, this for loop
4673  * won't do anything.
4674  */
4675  for (at = tmp->arch->more, last = tmp; at != NULL; at = at->more, last = op) {
4676  op = arch_to_object(at);
4677 
4678  /* update x,y coordinates */
4679  op->x += tmp->x;
4680  op->y += tmp->y;
4681  op->head = tmp;
4682  op->map = tmp->map;
4683  last->more = op;
4684  if (tmp->name != op->name) {
4685  if (op->name)
4686  free_string(op->name);
4687  op->name = add_string(tmp->name);
4688  }
4689  if (tmp->title != op->title) {
4690  if (op->title)
4691  free_string(op->title);
4692  op->title = add_string(tmp->title);
4693  }
4694  /* we could link all the parts onto tmp, and then just
4695  * call object_insert_in_map once, but the effect is the same,
4696  * as object_insert_in_map will call itself with each part, and
4697  * the coding is simpler to just to it here with each part.
4698  */
4700  } /* for at = tmp->arch->more */
4701 }
4702 
4718 void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy) {
4719  archetype *part;
4720  int maxx = 0, maxy = 0, minx = 0, miny = 0;
4721 
4722  ob = HEAD(ob);
4723  *sx = 1;
4724  *sy = 1;
4725  if (ob->arch->more) {
4726  for (part = ob->arch; part; part = part->more) {
4727  if (part->clone.x > maxx)
4728  maxx = part->clone.x;
4729  if (part->clone.y > maxy)
4730  maxy = part->clone.y;
4731  if (part->clone.x < minx)
4732  minx = part->clone.x;
4733  if (part->clone.y < miny)
4734  miny = part->clone.y;
4735  }
4736  }
4737  *sx = maxx;
4738  *sy = maxy;
4739  if (hx)
4740  *hx = -minx;
4741  if (hy)
4742  *hy = -miny;
4743 }
4744 
4765 void object_insert_to_free_spot_or_free(object *op, mapstruct *map, int x, int y, int start, int stop, object *originator) {
4766  int pos;
4767 
4768  pos = object_find_free_spot(op, map, x, y, start, stop);
4769  if (pos == -1) {
4771  return;
4772  }
4773 
4774  object_insert_in_map_at(op, map, originator, 0, x+freearr_x[pos], y+freearr_y[pos]);
4775 }
4776 
4785 void object_set_msg(object *op, const char *msg) {
4786  if (op->msg != NULL) {
4787  free_string(op->msg);
4788  }
4789 
4790  if (msg != NULL) {
4791  // If the message does not have a trailing newline, add one.
4792  if (*msg != '\0' && strchr(msg, '\0')[-1] != '\n') {
4795  stringbuffer_append_string(sb, "\n");
4796  op->msg = stringbuffer_finish_shared(sb);
4797  } else {
4798  op->msg = add_string(msg);
4799  }
4800  } else {
4801  op->msg = NULL;
4802  }
4803 }
4804 
4806 const char *const move_name[] = {
4807  "walk",
4808  "fly_low",
4809  "fly_high",
4810  "swim",
4811  "boat",
4812  NULL
4813 };
4814 
4815 /* This array equates the FLAG_ values with the V_ values. Use -1 to
4816  * put gaps in the array that should not be processed.
4817  * The order matches the order of the define values in 'define.h'.
4818  */
4825 static const char *const flag_names[NUM_FLAGS+1] = {
4826  "alive", "wiz", NULL, NULL, "was_wiz", "applied", "unpaid",
4827  "can_use_shield", "no_pick", "client_anim_sync", "client_anim_random", /* 10 */
4828  "is_animated", NULL /* FLAG_DIALOG_PARSED, not saved */,
4829  NULL /* flying */, "monster", "friendly", "generator",
4830  "is_thrown", "auto_apply", "treasure", "player sold", /* 20 */
4831  "see_invisible", "can_roll", "overlay_floor",
4832  "is_turnable", NULL /* walk_off */, NULL /* fly_on */,
4833  NULL /*fly_off*/, "is_used_up", "identified", "reflecting", /* 30 */
4834  "changing", "splitting", "hitback", "startequip",
4835  "blocksview", "undead", "scared", "unaggressive",
4836  "reflect_missile", "reflect_spell", /* 40 */
4837  "no_magic", "no_fix_player", "is_lightable", "tear_down",
4838  "run_away", NULL /*pass_thru */, NULL /*can_pass_thru*/,
4839  NULL /*"pick_up"*/, "unique", "no_drop", /* 50 */
4840  NULL /* wizcast*/, "can_cast_spell", "can_use_scroll", "can_use_range",
4841  "can_use_bow", "can_use_armour", "can_use_weapon",
4842  "can_use_ring", "has_ready_range", "has_ready_bow", /* 60 */
4843  "xrays", NULL, "is_floor", "lifesave", "no_strength", "sleep",
4844  "stand_still", "random_movement", "only_attack", "confused", /* 70 */
4845  "stealth", NULL, NULL, "cursed", "damned",
4846  "see_anywhere", "known_magical", "known_cursed",
4847  "can_use_skill", "been_applied", /* 80 */
4848  "has_ready_scroll", NULL, NULL,
4849  NULL, "make_invisible", "inv_locked", "is_wooded",
4850  "is_hilly", "has_ready_skill", "has_ready_weapon", /* 90 */
4851  "no_skill_ident", "is_blind", "can_see_in_dark", "is_cauldron",
4852  NULL, "no_steal", "one_hit", NULL, "berserk", "neutral", /* 100 */
4853  "no_attack", "no_damage", NULL, NULL, "activate_on_push",
4854  "activate_on_release", "is_water", "use_content_on_gen", NULL, "is_buildable", /* 110 */
4855  NULL, "blessed", "known_blessed"
4856 };
4857 
4867 {
4868  static char retbuf[MAX_BUF], retbuf_all[MAX_BUF];
4869  int i, all_count = 0, count;
4870 
4871  strcpy(retbuf, "");
4872  strcpy(retbuf_all, " all");
4873 
4874  /* Quick check, and probably fairly common */
4875  if (mt == MOVE_ALL) {
4876  stringbuffer_append_string(sb, "all");
4877  return;
4878  }
4879  if (mt == 0) {
4880  stringbuffer_append_string(sb, "0");
4881  return;
4882  }
4883 
4884  /* We basically slide the bits down. Why look at MOVE_ALL?
4885  * because we may want to return a string like 'all -swim',
4886  * and if we just looked at mt, we couldn't get that.
4887  */
4888  for (i = MOVE_ALL, count = 0; i != 0; i >>= 1, count++) {
4889  if (mt&(1<<count)) {
4890  strcat(retbuf, " ");
4891  strcat(retbuf, move_name[count]);
4892  } else {
4893  strcat(retbuf_all, " -");
4894  strcat(retbuf_all, move_name[count]);
4895  all_count++;
4896  }
4897  }
4898  /* Basically, if there is a single negation, return it, eg
4899  * 'all -swim'. But more than that, just return the
4900  * enumerated values. It doesn't make sense to return
4901  * 'all -walk -fly_low' - it is shorter to return 'fly_high swim'
4902  */
4903  if (all_count <= 1)
4904  stringbuffer_append_string(sb, retbuf_all+1);
4905  else
4906  stringbuffer_append_string(sb, retbuf+1);
4907 }
4908 
4910 static inline void ADD_STRINGLINE_ENTRY(StringBuffer *sb, const char *name, const char *value) {
4913  stringbuffer_append_string(sb, "\n");
4914 }
4915 
4917 static inline void FAST_SAVE_LONG(StringBuffer *sb, const char *name, const long value) {
4920  stringbuffer_append_char(sb, '\n');
4921 }
4922 
4924 static inline void FAST_SAVE_DOUBLE(StringBuffer *sb, const char *name, const double value) {
4925  stringbuffer_append_printf(sb, "%s%f\n", name, value);
4926 }
4927 
4935  for (int i = 0; i < 4; i++) {
4936  int idx = ffs((*diff)[i]);
4937  if (idx != 0) {
4938  int bit = idx - 1;
4939  // Clear difference bit.
4940  (*diff)[i] &= ~(1 << bit);
4941  return 32*i + bit;
4942  }
4943  }
4944  return -1;
4945 }
4946 
4960 void get_ob_diff(StringBuffer *sb, const object *op, const object *op2) {
4961  static char buf2[64];
4962  int tmp;
4963  int i;
4964  key_value *my_field;
4965  key_value *arch_field;
4966 
4967  /* This saves the key/value lists. We do it first so that any
4968  * keys that match field names will be overwritten by the loader.
4969  */
4970  for (my_field = op->key_values; my_field != NULL; my_field = my_field->next) {
4971  /* Find the field in the opposing member. */
4972  arch_field = object_get_key_value(op2, my_field->key);
4973 
4974  /* If there's no partnering field, or it's got a different value, save our field. */
4975  if (arch_field == NULL || my_field->value != arch_field->value) {
4976  stringbuffer_append_string(sb, my_field->key);
4977  stringbuffer_append_string(sb, " ");
4978  /* If this is null, then saving it as a space should
4979  * cause it to be null again.
4980  */
4981  if (my_field->value)
4982  stringbuffer_append_string(sb, my_field->value);
4983  stringbuffer_append_string(sb, "\n");
4984  }
4985  }
4986  /* We don't need to worry about the arch's extra fields - they
4987  * will get taken care of the object_copy() function.
4988  */
4989 
4990  if (op->name && op->name != op2->name) {
4991  ADD_STRINGLINE_ENTRY(sb, "name ", op->name);
4992  }
4993  if (op->name_pl && op->name_pl != op2->name_pl) {
4994  ADD_STRINGLINE_ENTRY(sb, "name_pl ", op->name_pl);
4995  }
4996  if (op->anim_suffix && op->anim_suffix != op2->anim_suffix) {
4997  ADD_STRINGLINE_ENTRY(sb, "anim_suffix ", op->anim_suffix);
4998  }
4999  if (op->title && op->title != op2->title) {
5000  ADD_STRINGLINE_ENTRY(sb, "title ", op->title);
5001  }
5002  if (op->race && op->race != op2->race) {
5003  ADD_STRINGLINE_ENTRY(sb, "race ", op->race);
5004  }
5005  if (op->slaying && op->slaying != op2->slaying) {
5006  ADD_STRINGLINE_ENTRY(sb, "slaying ", op->slaying);
5007  }
5008  if (op->skill && op->skill != op2->skill) {
5009  ADD_STRINGLINE_ENTRY(sb, "skill ", op->skill);
5010  }
5011  if (op->msg && op->msg != op2->msg) {
5012  stringbuffer_append_string(sb, "msg\n");
5013  stringbuffer_append_string(sb, op->msg);
5014  stringbuffer_append_string(sb, "endmsg\n");
5015  }
5016  if (op->lore && op->lore != op2->lore) {
5017  stringbuffer_append_string(sb, "lore\n");
5018  stringbuffer_append_string(sb, op->lore);
5019  stringbuffer_append_string(sb, "endlore\n");
5020  }
5021  if (op->other_arch != op2->other_arch && op->other_arch != NULL && op->other_arch->name) {
5022  ADD_STRINGLINE_ENTRY(sb, "other_arch ", op->other_arch->name);
5023  }
5024  if (op->face != op2->face) {
5025  ADD_STRINGLINE_ENTRY(sb, "face ", op->face->name);
5026  }
5027 
5028  if (op->animation != op2->animation) {
5029  if (op->animation) {
5030  ADD_STRINGLINE_ENTRY(sb, "animation ", op->animation->name);
5031  if (!QUERY_FLAG (op, FLAG_ANIMATE)) {
5032  stringbuffer_append_string(sb, "is_animated 0\n");
5033  }
5034  } else {
5035  stringbuffer_append_string(sb, "animation NONE\n");
5036  }
5037  }
5038  if (op->stats.Str != op2->stats.Str)
5039  FAST_SAVE_LONG(sb, "Str ", op->stats.Str);
5040  if (op->stats.Dex != op2->stats.Dex)
5041  FAST_SAVE_LONG(sb, "Dex ", op->stats.Dex);
5042  if (op->stats.Con != op2->stats.Con)
5043  FAST_SAVE_LONG(sb, "Con ", op->stats.Con);
5044  if (op->stats.Wis != op2->stats.Wis)
5045  FAST_SAVE_LONG(sb, "Wis ", op->stats.Wis);
5046  if (op->stats.Pow != op2->stats.Pow)
5047  FAST_SAVE_LONG(sb, "Pow ", op->stats.Pow);
5048  if (op->stats.Cha != op2->stats.Cha)
5049  FAST_SAVE_LONG(sb, "Cha ", op->stats.Cha);
5050  if (op->stats.Int != op2->stats.Int)
5051  FAST_SAVE_LONG(sb, "Int ", op->stats.Int);
5052  if (op->stats.hp != op2->stats.hp)
5053  FAST_SAVE_LONG(sb, "hp ", op->stats.hp);
5054  if (op->stats.maxhp != op2->stats.maxhp)
5055  FAST_SAVE_LONG(sb, "maxhp ", op->stats.maxhp);
5056  if (op->stats.sp != op2->stats.sp)
5057  FAST_SAVE_LONG(sb, "sp ", op->stats.sp);
5058  if (op->stats.maxsp != op2->stats.maxsp)
5059  FAST_SAVE_LONG(sb, "maxsp ", op->stats.maxsp);
5060  if (op->stats.grace != op2->stats.grace)
5061  FAST_SAVE_LONG(sb, "grace ", op->stats.grace);
5062  if (op->stats.maxgrace != op2->stats.maxgrace)
5063  FAST_SAVE_LONG(sb, "maxgrace ", op->stats.maxgrace);
5064 
5065  if (op->stats.exp != op2->stats.exp) {
5066  snprintf(buf2, sizeof(buf2), "%" FMT64, op->stats.exp);
5067  ADD_STRINGLINE_ENTRY(sb, "exp ", buf2);
5068  }
5069 
5070  if (op->total_exp != op2->total_exp) {
5071  snprintf(buf2, sizeof(buf2), "%" FMT64, op->total_exp);
5072  ADD_STRINGLINE_ENTRY(sb, "total_exp ", buf2);
5073  }
5074 
5075  if (op->expmul != op2->expmul)
5076  FAST_SAVE_DOUBLE(sb, "expmul ", op->expmul);
5077  if (op->stats.food != op2->stats.food)
5078  FAST_SAVE_LONG(sb, "food ", op->stats.food);
5079  if (op->stats.dam != op2->stats.dam)
5080  FAST_SAVE_LONG(sb, "dam ", op->stats.dam);
5081  if (op->stats.luck != op2->stats.luck)
5082  FAST_SAVE_LONG(sb, "luck ", op->stats.luck);
5083  if (op->stats.wc != op2->stats.wc)
5084  FAST_SAVE_LONG(sb, "wc ", op->stats.wc);
5085  if (op->stats.ac != op2->stats.ac)
5086  FAST_SAVE_LONG(sb, "ac ", op->stats.ac);
5087  if (op->x != op2->x)
5088  FAST_SAVE_LONG(sb, "x ", op->x);
5089  if (op->y != op2->y)
5090  FAST_SAVE_LONG(sb, "y ", op->y);
5091  if (op->speed != op2->speed) {
5092  FAST_SAVE_DOUBLE(sb, "speed ", op->speed);
5093  }
5094  if (op->speed > 0 && op->speed_left != op2->speed_left) {
5095  FAST_SAVE_DOUBLE(sb, "speed_left ", op->speed_left);
5096  }
5097  if (op->weapon_speed != op2->weapon_speed) {
5098  FAST_SAVE_DOUBLE(sb, "weapon_speed ", op->weapon_speed);
5099  }
5100  if (op->weapon_speed > 0 && op->weapon_speed_left != op2->weapon_speed_left) {
5101  FAST_SAVE_DOUBLE(sb, "weapon_speed_left ", op->weapon_speed_left);
5102  }
5103  if (op->move_status != op2->move_status)
5104  FAST_SAVE_LONG(sb, "move_state ", op->move_status);
5105  if (op->attack_movement != op2->attack_movement)
5106  FAST_SAVE_LONG(sb, "attack_movement ", op->attack_movement);
5107  if (op->nrof != op2->nrof)
5108  FAST_SAVE_LONG(sb, "nrof ", op->nrof);
5109  if (op->level != op2->level)
5110  FAST_SAVE_LONG(sb, "level ", op->level);
5111  if (op->direction != op2->direction)
5112  FAST_SAVE_LONG(sb, "direction ", op->direction);
5113  if (op->type != op2->type)
5114  FAST_SAVE_LONG(sb, "type ", op->type);
5115  if (op->subtype != op2->subtype)
5116  FAST_SAVE_LONG(sb, "subtype ", op->subtype);
5117  if (op->attacktype != op2->attacktype)
5118  FAST_SAVE_LONG(sb, "attacktype ", op->attacktype);
5119 
5120  for (tmp = 0; tmp < NROFATTACKS; tmp++) {
5121  if (op->resist[tmp] != op2->resist[tmp]) {
5122  stringbuffer_append_string(sb, "resist_");
5123  FAST_SAVE_LONG(sb, resist_save[tmp], op->resist[tmp]);
5124  }
5125  }
5126 
5127  if (op->path_attuned != op2->path_attuned)
5128  FAST_SAVE_LONG(sb, "path_attuned ", op->path_attuned);
5129  if (op->path_repelled != op2->path_repelled)
5130  FAST_SAVE_LONG(sb, "path_repelled ", op->path_repelled);
5131  if (op->path_denied != op2->path_denied)
5132  FAST_SAVE_LONG(sb, "path_denied ", op->path_denied);
5133  if (op->material != op2->material)
5134  FAST_SAVE_LONG(sb, "material ", op->material);
5135  if (op->materialname && op->materialname != op2->materialname) {
5136  ADD_STRINGLINE_ENTRY(sb, "materialname ", op->materialname);
5137  }
5138  if (op->value != op2->value)
5139  FAST_SAVE_LONG(sb, "value ", op->value);
5140  if (op->carrying != op2->carrying)
5141  FAST_SAVE_LONG(sb, "carrying ", op->carrying);
5142  if (op->weight != op2->weight)
5143  FAST_SAVE_LONG(sb, "weight ", op->weight);
5144  if (op->invisible != op2->invisible)
5145  FAST_SAVE_LONG(sb, "invisible ", op->invisible);
5146  if (op->state != op2->state)
5147  FAST_SAVE_LONG(sb, "state ", op->state);
5148  if (op->magic != op2->magic)
5149  FAST_SAVE_LONG(sb, "magic ", op->magic);
5150  if (op->last_heal != op2->last_heal)
5151  FAST_SAVE_LONG(sb, "last_heal ", op->last_heal);
5152  if (op->last_sp != op2->last_sp)
5153  FAST_SAVE_LONG(sb, "last_sp ", op->last_sp);
5154  if (op->last_grace != op2->last_grace)
5155  FAST_SAVE_LONG(sb, "last_grace ", op->last_grace);
5156  if (op->last_eat != op2->last_eat)
5157  FAST_SAVE_LONG(sb, "last_eat ", op->last_eat);
5159  FAST_SAVE_LONG(sb, "connected ", tmp);
5160  if (op->glow_radius != op2->glow_radius)
5161  FAST_SAVE_LONG(sb, "glow_radius ", op->glow_radius);
5162  if (op->randomitems != op2->randomitems) {
5163  ADD_STRINGLINE_ENTRY(sb, "randomitems ", op->randomitems ? op->randomitems->name : "none");
5164  }
5165 
5166  if (op->run_away != op2->run_away)
5167  FAST_SAVE_LONG(sb, "run_away ", op->run_away);
5168  if (op->pick_up != op2->pick_up)
5169  FAST_SAVE_LONG(sb, "pick_up ", op->pick_up);
5170  if (op->weight_limit != op2->weight_limit)
5171  FAST_SAVE_LONG(sb, "container ", op->weight_limit);
5172  if (op->will_apply != op2->will_apply)
5173  FAST_SAVE_LONG(sb, "will_apply ", op->will_apply);
5174  if (op->smoothlevel != op2->smoothlevel)
5175  FAST_SAVE_LONG(sb, "smoothlevel ", op->smoothlevel);
5176 
5177  if (op->map_layer != op2->map_layer)
5178  ADD_STRINGLINE_ENTRY(sb, "map_layer ", map_layer_name[op->map_layer]);
5179 
5180  if (op->weapontype && op->weapontype != op2->weapontype) {
5181  FAST_SAVE_LONG(sb, "weapontype ", op->weapontype);
5182  }
5183  if (op->client_type && op->client_type != op2->client_type) {
5184  FAST_SAVE_LONG(sb, "client_type ", op->client_type);
5185  }
5186 
5187  if (op->item_power != op2->item_power) {
5188  FAST_SAVE_LONG(sb, "item_power ", op->item_power);
5189  }
5190 
5191  if (op->duration != op2->duration)
5192  FAST_SAVE_LONG(sb, "duration ", op->duration);
5193 
5194  if (op->range != op2->range)
5195  FAST_SAVE_LONG(sb, "range ", op->range);
5196 
5197  if (op->range_modifier != op2->range_modifier)
5198  FAST_SAVE_LONG(sb, "range_modifier ", op->range_modifier);
5199 
5200  if (op->duration_modifier != op2->duration_modifier)
5201  FAST_SAVE_LONG(sb, "duration_modifier ", op->duration_modifier);
5202 
5203  if (op->dam_modifier != op2->dam_modifier)
5204  FAST_SAVE_LONG(sb, "dam_modifier ", op->dam_modifier);
5205 
5206  if (op->gen_sp_armour != op2->gen_sp_armour) {
5207  FAST_SAVE_LONG(sb, "gen_sp_armour ", op->gen_sp_armour);
5208  }
5209 
5210  /* I've kept the old int move type saving code commented out.
5211  * In an ideal world, we'd know if we want to do a quick
5212  * save (say to a temp map, where we don't care about strings),
5213  * or a slower save/dm dump, where printing out strings is handy.
5214  */
5215  if (op->move_type != op2->move_type) {
5216  /*FAST_SAVE_LONG(sb, "move_type ", op->move_type)*/
5217  stringbuffer_append_string(sb, "move_type ");
5218  get_string_move_type(sb, op->move_type);
5219  stringbuffer_append_string(sb, "\n");
5220  }
5221  if (op->move_block != op2->move_block) {
5222  /*FAST_SAVE_LONG(sb, "move_block ", op->move_block)*/
5223  stringbuffer_append_string(sb, "move_block ");
5224  get_string_move_type(sb, op->move_block);
5225  stringbuffer_append_string(sb, "\n");
5226  }
5227  if (op->move_allow != op2->move_allow) {
5228  /*FAST_SAVE_LONG(sb, "move_allow ", op->move_allow);*/
5229  stringbuffer_append_string(sb, "move_allow ");
5230  get_string_move_type(sb, op->move_allow);
5231  stringbuffer_append_string(sb, "\n");
5232  }
5233  if (op->move_on != op2->move_on) {
5234  /*FAST_SAVE_LONG(sb, "move_on ", op->move_on);*/
5235  stringbuffer_append_string(sb, "move_on ");
5236  get_string_move_type(sb, op->move_on);
5237  stringbuffer_append_string(sb, "\n");
5238  }
5239  if (op->move_off != op2->move_off) {
5240  /*FAST_SAVE_LONG(sb, "move_off ", op->move_off);*/
5241  stringbuffer_append_string(sb, "move_off ");
5242  get_string_move_type(sb, op->move_off);
5243  stringbuffer_append_string(sb, "\n");
5244  }
5245  if (op->move_slow != op2->move_slow) {
5246  /*FAST_SAVE_LONG(sb, "move_slow ", op->move_slow);*/
5247  stringbuffer_append_string(sb, "move_slow ");
5248  get_string_move_type(sb, op->move_slow);
5249  stringbuffer_append_string(sb, "\n");
5250  }
5251 
5252  if (op->move_slow_penalty != op2->move_slow_penalty) {
5253  FAST_SAVE_DOUBLE(sb, "move_slow_penalty ", op->move_slow_penalty);
5254  }
5255 
5256  ob_flags diff_flags;
5257  compare_flags(&diff_flags, op, op2);
5258  int flag;
5259  while ((flag = flags_differ(&diff_flags)) != -1) {
5260  if (flag_names[flag]) {
5261  ADD_STRINGLINE_ENTRY(sb, flag_names[flag], QUERY_FLAG(op, flag) ? " 1" : " 0");
5262  }
5263  }
5264 
5265  /* Save body locations */
5266  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
5267  if (op->body_info[i] != op2->body_info[i]) {
5268  stringbuffer_append_string(sb, body_locations[i].save_name);
5269  FAST_SAVE_LONG(sb, " ", op->body_info[i]);
5270  }
5271  }
5272 }
5273 
5278 void save_object_in_sb(StringBuffer *sb, object *op, const int flag) {
5279  /* If the object has no_save set, just return */
5280  if (QUERY_FLAG(op, FLAG_NO_SAVE)) {
5281  return;
5282  }
5283 
5284  /* Even if the object does have an owner, it would seem that we should
5285  * still save it.
5286  */
5287  if (object_get_owner(op) != NULL) {
5288  return;
5289  }
5290 
5291  /* If it is unpaid and we don't want to save those, just return. */
5292  if (!(flag&SAVE_FLAG_SAVE_UNPAID) && (QUERY_FLAG(op, FLAG_UNPAID))) {
5293  return;
5294  }
5295 
5296  archetype *at = op->arch;
5297  if (at == NULL)
5298  at = empty_archetype;
5299 
5300  ADD_STRINGLINE_ENTRY(sb, "arch ", at->name);
5301 
5302  if (at->reference_count > 0) {
5303  /* The object is a custom item/monster, so we handle its save differently.
5304  * We compare the custom archetype to the "original" one, then only save hp/gr/sp
5305  * which are the only values we can't recompute later - all others are modified by items in inventory.
5306  * Note that hp/gr/sp will appear twice in save, but last value will take precedence.
5307  */
5308  archetype *original = find_archetype(at->name);
5309  if (!original) {
5310  LOG(llevError, "could not find original archetype %s for custom monster!\n", at->name);
5311  abort();
5312  }
5313  get_ob_diff(sb, &at->clone, &original->clone);
5314  if (op->stats.hp != at->clone.stats.hp)
5315  FAST_SAVE_LONG(sb, "hp ", op->stats.hp);
5316  if (op->stats.sp != at->clone.stats.sp)
5317  FAST_SAVE_LONG(sb, "sp ", op->stats.sp);
5318  if (op->stats.grace != at->clone.stats.grace)
5319  FAST_SAVE_LONG(sb, "grace ", op->stats.grace);
5320  if (op->x != at->clone.x)
5321  FAST_SAVE_LONG(sb, "x ", op->x);
5322  if (op->y != at->clone.y)
5323  FAST_SAVE_LONG(sb, "y ", op->y);
5324  } else if (op->artifact != NULL) {
5325  /* if op is an artifact, then find the "standard" artifact to use that for the diff */
5326  object *base;
5327  const artifact *artifact;
5328 
5329  artifact = find_artifact(op, op->artifact);
5330  if (artifact == NULL) {
5331  LOG(llevError, "could not find artifact %s [%d] to save data\n", op->artifact, op->type);
5332  get_ob_diff(sb, op, &at->clone);
5333  } else {
5334  ADD_STRINGLINE_ENTRY(sb, "artifact ", op->artifact);
5335  base = arch_to_object(at);
5337  get_ob_diff(sb, op, base);
5339  }
5340  } else {
5341  get_ob_diff(sb, op, &at->clone);
5342  }
5343 
5344  /* Eneq(@csd.uu.se): Added this to allow containers being saved with contents*/
5346  save_object_in_sb(sb, tmp, flag);
5347  FOR_INV_FINISH();
5348 
5349  stringbuffer_append_string(sb, "end\n");
5350 }
5351 
5364 int save_object(FILE *fp, object *op, int flag) {
5366  save_object_in_sb(sb, op, flag);
5367  char *cp = stringbuffer_finish(sb);
5368  if (fputs(cp, fp) == EOF) {
5369  free(cp);
5370  return SAVE_ERROR_WRITE;
5371  } else {
5372  free(cp);
5373  return SAVE_ERROR_OK;
5374  }
5375 }
5376 
5378  if (op->map) {
5379  sstring death_animation = object_get_value(op, "death_animation");
5380  if (death_animation != NULL) {
5381  object *death = create_archetype(death_animation);
5382 
5383  if (death != NULL) {
5384  object_insert_in_map_at(death, op->map, op, 0, op->x, op->y);
5385  if (death->arch->more)
5386  object_fix_multipart(death);
5387  }
5388  }
5389  }
5390 }
5391 
5392 object *find_force(object *op, const char *name) {
5393  assert(op != NULL);
5395 }
5396 
5397 object *add_force(object *op, const char *name, int duration) {
5398  assert(op != NULL);
5399  object *force = find_force(op, name);
5400  if (force == NULL) {
5402  force->slaying = add_string(name);
5404  }
5405 
5406  if (duration != 0) {
5407  force->speed = 0.01;
5408  force->speed_left = -duration;
5409  } else {
5410  force->speed = 0;
5411  }
5412 
5413  // Even if duration is zero, a force could be set previously.
5415 
5416  return force;
5417 }
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Definition: object.h:68
Settings::casting_time
uint8_t casting_time
Definition: global.h:270
obj::weapon_speed
float weapon_speed
Definition: object.h:337
object_value_set
bool object_value_set(const object *op, const char *const key)
Definition: object.cpp:4350
free_objects
static object * free_objects
Definition: object.cpp:295
give.next
def next
Definition: give.py:44
obj::move_off
MoveType move_off
Definition: object.h:436
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Definition: map.h:173
object_copy_with_inv
void object_copy_with_inv(const object *src_ob, object *dest_ob)
Definition: object.cpp:1188
init_objects
void init_objects(void)
Definition: object.cpp:327
UP_OBJ_FACE
#define UP_OBJ_FACE
Definition: object.h:522
PLAYER
@ PLAYER
Definition: object.h:110
object_get_owner_const
static const object * object_get_owner_const(const object *op)
Definition: object.cpp:624
obj::attack_movement
uint16_t attack_movement
Definition: object.h:399
artifact
struct artifactstruct artifact
object_get_owner
object * object_get_owner(object *op)
Definition: object.cpp:804
FREE_AND_CLEAR_STR_IF
#define FREE_AND_CLEAR_STR_IF(xyz)
Definition: global.h:200
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:534
UPD_FACE
#define UPD_FACE
Definition: newclient.h:317
object_find_by_type_subtype
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Definition: object.cpp:4275
object_clear_owner
void object_clear_owner(object *op)
Definition: object.cpp:823
first_player
player * first_player
Definition: init.cpp:106
settings
struct Settings settings
Definition: init.cpp:139
permute
static void permute(int *, int, int)
Definition: object.cpp:3592
liv::dam
int16_t dam
Definition: living.h:46
object_get_env_recursive
object * object_get_env_recursive(object *op)
Definition: object.cpp:590
INS_NO_WALK_ON
#define INS_NO_WALK_ON
Definition: object.h:571
pl::count
uint32_t count
Definition: player.h:122
object_update_turn_face
void object_update_turn_face(object *op)
Definition: object.cpp:1308
UP_OBJ_REMOVE
#define UP_OBJ_REMOVE
Definition: object.h:520
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
remove_friendly_object
void remove_friendly_object(object *op)
Definition: friend.cpp:54
object_count_active
int object_count_active(void)
Definition: object.cpp:1764
object_find_by_type_applied
object * object_find_by_type_applied(const object *who, int type)
Definition: object.cpp:4057
pl::transport
object * transport
Definition: player.h:213
NUM_BODY_LOCATIONS
#define NUM_BODY_LOCATIONS
Definition: object.h:13
MAP_SAVING
#define MAP_SAVING
Definition: map.h:134
obj::face
const Face * face
Definition: object.h:339
obj::move_block
MoveType move_block
Definition: object.h:433
find_artifact
const artifact * find_artifact(const object *op, const char *name)
Definition: artifact.cpp:590
GET_MAP_TOP
#define GET_MAP_TOP(M, X, Y)
Definition: map.h:175
statistics
struct Statistics statistics
Definition: init.cpp:232
llevError
@ llevError
Definition: logger.h:11
object_set_flag_inv
void object_set_flag_inv(object *op, int flag)
Definition: object.cpp:3213
FABS
#define FABS(x)
Definition: define.h:22
FLAG_CLIENT_ANIM_RANDOM
#define FLAG_CLIENT_ANIM_RANDOM
Definition: define.h:241
EVENT_CONNECTOR
@ EVENT_CONNECTOR
Definition: object.h:230
find_skill_by_number
object * find_skill_by_number(object *who, int skillno)
Definition: main.cpp:375
MOVE_ALL
#define MOVE_ALL
Definition: define.h:398
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
ADD_STRINGLINE_ENTRY
static void ADD_STRINGLINE_ENTRY(StringBuffer *sb, const char *name, const char *value)
Definition: object.cpp:4910
FLAG_OVERLAY_FLOOR
#define FLAG_OVERLAY_FLOOR
Definition: define.h:255
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
object_free_all_data
void object_free_all_data(void)
Definition: object.cpp:767
diamondslots.x
x
Definition: diamondslots.py:15
FLAG_STARTEQUIP
#define FLAG_STARTEQUIP
Definition: define.h:268
obj::count
tag_t count
Definition: object.h:305
Statistics::spell_merges
uint64_t spell_merges
Definition: global.h:356
obj::map
struct mapdef * map
Definition: object.h:303
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:324
liv::maxgrace
int16_t maxgrace
Definition: living.h:45
obj::value
int32_t value
Definition: object.h:358
liv::wc
int8_t wc
Definition: living.h:37
map_find_by_archetype
object * map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at)
Definition: object.cpp:3092
FLAG_IS_TURNABLE
#define FLAG_IS_TURNABLE
Definition: define.h:256
object_merge
object * object_merge(object *op, object *top)
Definition: object.cpp:2030
STARTMAX
#define STARTMAX
Definition: config.h:515
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.cpp:138
liv::Str
int8_t Str
Definition: living.h:36
FALSE
#define FALSE
Definition: compat.h:14
update_position
void update_position(mapstruct *m, int x, int y)
Definition: map.cpp:2133
BITMASK_EVENT
#define BITMASK_EVENT(evt)
Definition: events.h:62
SET_MAP_TOP
#define SET_MAP_TOP(M, X, Y, tmp)
Definition: map.h:180
obj::gen_sp_armour
int8_t gen_sp_armour
Definition: object.h:371
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
absdir
int absdir(int d)
Definition: object.cpp:3688
UPD_WEIGHT
#define UPD_WEIGHT
Definition: newclient.h:316
obj::path_attuned
uint32_t path_attuned
Definition: object.h:351
flag_names
static const char *const flag_names[NUM_FLAGS+1]
Definition: object.cpp:4825
liv::maxhp
int16_t maxhp
Definition: living.h:41
object_set_enemy
void object_set_enemy(object *op, object *enemy)
Definition: object.cpp:915
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.cpp:4765
pl
Definition: player.h:105
FLAG_OBJ_ORIGINAL
#define FLAG_OBJ_ORIGINAL
Definition: define.h:357
TRAP
@ TRAP
Definition: object.h:244
OB_SPELL_TAG_MATCH
#define OB_SPELL_TAG_MATCH(op, count)
Definition: object.h:93
obj::artifact
sstring artifact
Definition: object.h:320
object_dump_all
void object_dump_all(void)
Definition: object.cpp:704
give_artifact_abilities
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.cpp:238
obj::invisible
int16_t invisible
Definition: object.h:368
object_find_first_free_spot
int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y)
Definition: object.cpp:3573
MoveType
unsigned char MoveType
Definition: define.h:417
arch_present_in_ob
object * arch_present_in_ob(const archetype *at, const object *op)
Definition: object.cpp:3196
_key_value::key
const char * key
Definition: object.h:41
object_set_owner
void object_set_owner(object *op, object *owner)
Definition: object.cpp:840
object_set_value_s
static int object_set_value_s(object *, const char *, const char *, int)
Definition: object.cpp:4390
guildjoin.ob
ob
Definition: guildjoin.py:42
object_handle_death_animation
void object_handle_death_animation(object *op)
Definition: object.cpp:5377
liv::hp
int16_t hp
Definition: living.h:40
obj::range_modifier
uint8_t range_modifier
Definition: object.h:414
commongive.inv
inv
Definition: commongive.py:28
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
object_reset
void object_reset(object *op)
Definition: object.cpp:934
pl::ob
object * ob
Definition: player.h:176
SKILL
@ SKILL
Definition: object.h:146
RUNE
@ RUNE
Definition: object.h:243
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.cpp:1060
give.top
def top
Definition: give.py:42
fix_object
void fix_object(object *op)
Definition: living.cpp:1125
object_find_by_flag_applied
object * object_find_by_flag_applied(const object *who, int flag)
Definition: object.cpp:4203
object_find_multi_free_spot_within_radius
int object_find_multi_free_spot_within_radius(const object *ob, const object *gen, int *hx, int *hy)
Definition: object.cpp:3386
object_find_by_type_and_skill
object * object_find_by_type_and_skill(const object *who, int type, const char *skill)
Definition: object.cpp:4157
obj::path_denied
uint32_t path_denied
Definition: object.h:353
Ice.tmp
int tmp
Definition: Ice.py:207
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
blank_face
const Face * blank_face
Definition: image.cpp:36
P_NO_MAGIC
#define P_NO_MAGIC
Definition: map.h:228
llevMonster
@ llevMonster
Definition: logger.h:14
obj::smoothlevel
uint8_t smoothlevel
Definition: object.h:429
flags_differ
int flags_differ(ob_flags *diff)
Definition: object.cpp:4934
TRANSPORT
@ TRANSPORT
Definition: object.h:111
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:328
stringbuffer_append_char
void stringbuffer_append_char(StringBuffer *sb, const char c)
Definition: stringbuffer.cpp:104
FLAG_BLOCKSVIEW
#define FLAG_BLOCKSVIEW
Definition: define.h:269
obj::body_info
int8_t body_info[NUM_BODY_LOCATIONS]
Definition: object.h:380
skills.h
compare_ob_value_lists
static int compare_ob_value_lists(const object *, const object *)
Definition: object.cpp:404
free_arch
void free_arch(archetype *at)
Definition: arch.cpp:170
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
object_find_by_tag_global
object * object_find_by_tag_global(tag_t i)
Definition: object.cpp:727
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.cpp:4320
P_IS_ALIVE
#define P_IS_ALIVE
Definition: map.h:238
Statistics::spell_hash_full
uint64_t spell_hash_full
Definition: global.h:357
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
expand_objects
static void expand_objects(void)
Definition: object.cpp:1207
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:292
object_merge_spell
void object_merge_spell(object *op, int16_t x, int16_t y)
Definition: object.cpp:2108
active_objects
object * active_objects
Definition: object.cpp:296
obj::randomitems
struct treasureliststruct * randomitems
Definition: object.h:393
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2832
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
FAST_SAVE_DOUBLE
static void FAST_SAVE_DOUBLE(StringBuffer *sb, const char *name, const double value)
Definition: object.cpp:4924
stringbuffer_append_int64
void stringbuffer_append_int64(StringBuffer *sb, int64_t x)
Definition: stringbuffer.cpp:111
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:403
ob_move_on
method_ret ob_move_on(object *op, object *victim, object *originator)
Definition: ob_methods.cpp:111
SAVE_ERROR_WRITE
#define SAVE_ERROR_WRITE
Definition: map.h:147
obj::nrof
uint32_t nrof
Definition: object.h:340
FLAG_NO_PICK
#define FLAG_NO_PICK
Definition: define.h:239
obj::ox
int16_t ox
Definition: object.h:334
obj::duration_modifier
uint8_t duration_modifier
Definition: object.h:412
obj::duration
int16_t duration
Definition: object.h:411
FLAG_DIALOG_PARSED
#define FLAG_DIALOG_PARSED
Definition: define.h:243
archt
Definition: object.h:472
FLAG_ALIVE
#define FLAG_ALIVE
Definition: define.h:230
object_clear
void object_clear(object *op)
Definition: object.cpp:983
obj::last_heal
int32_t last_heal
Definition: object.h:365
esrv_send_item
void esrv_send_item(object *pl, object *op)
Definition: main.cpp:354
socket_struct::update_look
uint32_t update_look
Definition: newserver.h:104
INS_ABOVE_FLOOR_ONLY
#define INS_ABOVE_FLOOR_ONLY
Definition: object.h:570
FOR_OB_AND_ABOVE_PREPARE
#define FOR_OB_AND_ABOVE_PREPARE(op_)
Definition: define.h:739
FLAG_IS_A_TEMPLATE
#define FLAG_IS_A_TEMPLATE
Definition: define.h:366
obj::slaying
sstring slaying
Definition: object.h:325
LOOK_OBJ
#define LOOK_OBJ(ob)
Definition: object.h:510
stringbuffer.h
object_find_by_type_and_race
object * object_find_by_type_and_race(const object *who, int type, const char *race)
Definition: object.cpp:4107
m
static event_registration m
Definition: citylife.cpp:425
liv::maxsp
int16_t maxsp
Definition: living.h:43
liv::luck
int8_t luck
Definition: living.h:39
autojail.who
who
Definition: autojail.py:3
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Definition: map.h:131
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
obj::spell_tags
tag_t * spell_tags
Definition: object.h:442
OBJ_EXPAND
#define OBJ_EXPAND
Definition: config.h:516
liv::exp
int64_t exp
Definition: living.h:47
get_button_value
int get_button_value(const object *button)
Definition: button.cpp:749
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.cpp:1541
object_update
void object_update(object *op, int action)
Definition: object.cpp:1415
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:614
object_find_by_name
object * object_find_by_name(const object *who, const char *name)
Definition: object.cpp:3930
disinfect.map
map
Definition: disinfect.py:4
ob_flags
uint32_t ob_flags[4]
Definition: object.h:257
object_get_key_value
key_value * object_get_key_value(const object *ob, const char *key)
Definition: object.cpp:4295
object_find_by_type2
object * object_find_by_type2(const object *who, int type1, int type2)
Definition: object.cpp:4011
FLAG_WAS_WIZ
#define FLAG_WAS_WIZ
Definition: define.h:234
obj::name
sstring name
Definition: object.h:317
add_refcount
sstring add_refcount(sstring str)
Definition: shstr.cpp:210
object_value_set_shared
bool object_value_set_shared(const object *op, sstring key)
Definition: object.cpp:4364
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.cpp:305
P_NO_ERROR
#define P_NO_ERROR
Definition: map.h:241
object_present_in_ob_by_name
object * object_present_in_ob_by_name(int type, const char *str, const object *op)
Definition: object.cpp:3177
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.cpp:585
map_find_by_type
object * map_find_by_type(mapstruct *m, int x, int y, uint8_t type)
Definition: object.cpp:3119
can_see_monsterP
int can_see_monsterP(mapstruct *m, int x, int y, int dir)
Definition: object.cpp:3796
MOVE_WALK
#define MOVE_WALK
Definition: define.h:392
FLAG_KNOWN_CURSED
#define FLAG_KNOWN_CURSED
Definition: define.h:320
stringbuffer_finish_shared
sstring stringbuffer_finish_shared(StringBuffer *sb)
Definition: stringbuffer.cpp:85
obj::path_repelled
uint32_t path_repelled
Definition: object.h:352
FOR_ABOVE_FINISH
#define FOR_ABOVE_FINISH()
Definition: define.h:694
obj::total_exp
int64_t total_exp
Definition: object.h:377
object_dump
void object_dump(const object *op, StringBuffer *sb)
Definition: object.cpp:645
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
liv::Cha
int8_t Cha
Definition: living.h:36
obj::name_pl
sstring name_pl
Definition: object.h:321
object_count_free
int object_count_free(void)
Definition: object.cpp:1732
FOR_OB_AND_BELOW_FINISH
#define FOR_OB_AND_BELOW_FINISH()
Definition: define.h:754
object_get_multi_size
void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy)
Definition: object.cpp:4718
HEAD
#define HEAD(op)
Definition: object.h:596
CONTAINER
@ CONTAINER
Definition: object.h:234
make_face_from_files.str
str
Definition: make_face_from_files.py:24
obj::speed_left
float speed_left
Definition: object.h:336
object_find_by_type_and_name
object * object_find_by_type_and_name(const object *who, int type, const char *name)
Definition: object.cpp:4082
query_short_name
void query_short_name(const object *op, char *buf, size_t size)
Definition: item.cpp:510
FLAG_FREED
#define FLAG_FREED
Definition: define.h:233
convert.action
action
Definition: convert.py:25
out_of_map
int out_of_map(mapstruct *m, int x, int y)
Definition: map.cpp:2312
find_string
sstring find_string(const char *str)
Definition: shstr.cpp:236
obj::prev
struct obj * prev
Definition: object.h:284
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
object_update_speed
void object_update_speed(object *op)
Definition: object.cpp:1325
obj::carrying
int32_t carrying
Definition: object.h:375
FLAG_IS_WOODED
#define FLAG_IS_WOODED
Definition: define.h:330
obj::container
struct obj * container
Definition: object.h:297
obj::x
int16_t x
Definition: object.h:333
INS_NO_MERGE
#define INS_NO_MERGE
Definition: object.h:569
FLAG_DAMNED
#define FLAG_DAMNED
Definition: define.h:317
SET_MAP_FLAGS
#define SET_MAP_FLAGS(M, X, Y, C)
Definition: map.h:164
CFweardisguise.tag
tag
Definition: CFweardisguise.py:25
object_find_by_tag
object * object_find_by_tag(const object *who, tag_t tag)
Definition: object.cpp:4034
obj::event_bitmask
uint64_t event_bitmask
Definition: object.h:443
FLAG_WIZPASS
#define FLAG_WIZPASS
Definition: define.h:314
object_find_by_flag
object * object_find_by_flag(const object *who, int flag)
Definition: object.cpp:4180
object_free
void object_free(object *ob, int flags)
Definition: object.cpp:1573
LAMP
@ LAMP
Definition: object.h:204
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:421
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
archt::more
struct archt * more
Definition: object.h:475
INS_BELOW_ORIGINATOR
#define INS_BELOW_ORIGINATOR
Definition: object.h:573
resist_save
const char *const resist_save[NROFATTACKS]
Definition: init.cpp:31
sstring
const typedef char * sstring
Definition: global.h:43
disinfect.count
int count
Definition: disinfect.py:7
obj::speed
float speed
Definition: object.h:335
obj::weapontype
uint32_t weapontype
Definition: object.h:379
tag_t
uint32_t tag_t
Definition: object.h:12
body_locations
body_locations_struct body_locations[NUM_BODY_LOCATIONS]
Definition: item.cpp:54
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:348
obj::below
struct obj * below
Definition: object.h:293
object_matches_string
int object_matches_string(object *pl, object *op, const char *name)
Definition: object.cpp:4548
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.cpp:3270
sproto.h
liv::food
int32_t food
Definition: living.h:48
FLAG_NO_DROP
#define FLAG_NO_DROP
Definition: define.h:288
FLAG_NO_SAVE
#define FLAG_NO_SAVE
Definition: define.h:244
nrofallocobjects
int nrofallocobjects
Definition: object.cpp:291
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.cpp:95
get_map_from_coord
mapstruct * get_map_from_coord(mapstruct *m, int16_t *x, int16_t *y)
Definition: map.cpp:2385
obj::move_slow_penalty
float move_slow_penalty
Definition: object.h:438
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:317
compare_flags
static void compare_flags(ob_flags *ret, const object *p, const object *q)
Definition: object.h:488
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:430
obj::animation
const Animations * animation
Definition: object.h:424
FREE_OBJ_DROP_ABOVE_FLOOR
#define FREE_OBJ_DROP_ABOVE_FLOOR
Definition: object.h:535
ob_blocked
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
Definition: map.cpp:488
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
obj::material
uint16_t material
Definition: object.h:355
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.cpp:3978
reduction_dir
static const int reduction_dir[SIZEOFFREE][3]
Definition: object.cpp:3726
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.cpp:2079
object_create_clone
object * object_create_clone(object *asrc)
Definition: object.cpp:3883
fatal
void fatal(enum fatal_error err)
Definition: utils.cpp:580
MAP_WIDTH
#define MAP_WIDTH(m)
Definition: map.h:78
SIZEOFFREE
#define SIZEOFFREE
Definition: define.h:155
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
INS_ON_TOP
#define INS_ON_TOP
Definition: object.h:572
move_name
const char *const move_name[]
Definition: object.cpp:4806
obj::item_power
int8_t item_power
Definition: object.h:370
object_set_cheat
void object_set_cheat(object *op)
Definition: object.cpp:3248
object_new
object * object_new(void)
Definition: object.cpp:1249
obj::lore
sstring lore
Definition: object.h:330
object_insert_in_map
object * object_insert_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.cpp:2340
esrv_del_item
void esrv_del_item(player *pl, object *ob)
Definition: main.cpp:381
UP_OBJ_INSERT
#define UP_OBJ_INSERT
Definition: object.h:519
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:279
object_present_in_ob
object * object_present_in_ob(uint8_t type, const object *op)
Definition: object.cpp:3142
get_weight_limit
uint32_t get_weight_limit(int stat)
Definition: living.cpp:2360
nroffreeobjects
int nroffreeobjects
Definition: object.cpp:290
free_string
void free_string(sstring str)
Definition: shstr.cpp:280
obj::next
struct obj * next
Definition: object.h:283
offsetof
#define offsetof(type, member)
Definition: shstr.h:37
RANDOM
#define RANDOM()
Definition: define.h:644
StringBuffer
Definition: stringbuffer.cpp:25
FREE_AND_CLEAR_STR
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:198
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:333
ob_count
long ob_count
Definition: init.cpp:123
obj::glow_radius
int8_t glow_radius
Definition: object.h:372
OUT_OF_REAL_MAP
#define OUT_OF_REAL_MAP(M, X, Y)
Definition: map.h:218
obj::title
sstring title
Definition: object.h:323
get_search_arr
void get_search_arr(int *search_arr)
Definition: object.cpp:3616
obj::arch
struct archt * arch
Definition: object.h:420
find_dir_2
int find_dir_2(int x, int y)
Definition: object.cpp:3651
object_add_weight
void object_add_weight(object *op, signed long weight)
Definition: object.cpp:2808
obj::oy
int16_t oy
Definition: object.h:334
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
object_decrease_nrof
object * object_decrease_nrof(object *op, uint32_t i)
Definition: object.cpp:2651
object_find_by_type_and_slaying
object * object_find_by_type_and_slaying(const object *who, int type, const char *slaying)
Definition: object.cpp:4132
INS_MAP_LOAD
#define INS_MAP_LOAD
Definition: object.h:574
BITMASK_VALID
#define BITMASK_VALID
Definition: events.h:64
SK_WOODSMAN
@ SK_WOODSMAN
Definition: skills.h:40
obj::type
uint8_t type
Definition: object.h:346
obj::last_grace
int16_t last_grace
Definition: object.h:367
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
obj::move_slow
MoveType move_slow
Definition: object.h:437
obj::stats
living stats
Definition: object.h:376
SPELL_MAPPINGS
#define SPELL_MAPPINGS
Definition: global.h:148
obj::direction
int8_t direction
Definition: object.h:342
object_count_used
int object_count_used(void)
Definition: object.cpp:1748
FREE_AND_CLEAR
#define FREE_AND_CLEAR(xyz)
Definition: global.h:193
object_find_by_arch_name
object * object_find_by_arch_name(const object *who, const char *name)
Definition: object.cpp:4226
archt::clone
object clone
Definition: object.h:476
obj::state
uint8_t state
Definition: object.h:357
SIZEOFFREE2
#define SIZEOFFREE2
Definition: define.h:154
obj::contr
struct pl * contr
Definition: object.h:282
object_can_pick
int object_can_pick(const object *who, const object *item)
Definition: object.cpp:3841
SCRIPT_FIX_NOTHING
#define SCRIPT_FIX_NOTHING
Definition: global.h:383
objarray
static object objarray[STARTMAX]
Definition: object.cpp:289
obj::weight
int32_t weight
Definition: object.h:373
liv::Dex
int8_t Dex
Definition: living.h:36
get_map_flags
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
Definition: map.cpp:301
object_find_by_type
object * object_find_by_type(const object *who, int type)
Definition: object.cpp:3954
item
Definition: item.py:1
P_NEED_UPDATE
#define P_NEED_UPDATE
Definition: map.h:240
object_find_by_name_global
object * object_find_by_name_global(const char *str)
Definition: object.cpp:747
liv::Wis
int8_t Wis
Definition: living.h:36
archt::reference_count
int reference_count
Definition: object.h:479
liv::grace
int16_t grace
Definition: living.h:44
give.op
op
Definition: give.py:33
autojail.value
value
Definition: autojail.py:6
get_string_move_type
static void get_string_move_type(StringBuffer *sb, MoveType mt)
Definition: object.cpp:4866
animate_object
void animate_object(object *op, int dir)
Definition: anim.cpp:44
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:270
object_split
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
Definition: object.cpp:2612
obj::key_values
key_value * key_values
Definition: object.h:440
object_find_free_spot
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.cpp:3533
object_set_msg
void object_set_msg(object *op, const char *msg)
Definition: object.cpp:4785
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.cpp:359
SPELL_EFFECT
@ SPELL_EFFECT
Definition: object.h:218
obj::weapon_speed_left
float weapon_speed_left
Definition: object.h:338
_key_value
Definition: object.h:40
spell_mapping
const char *const spell_mapping[SPELL_MAPPINGS]
Definition: object.cpp:74
objects
object * objects
Definition: object.cpp:294
obj::last_sp
int32_t last_sp
Definition: object.h:366
FLAG_NO_FIX_PLAYER
#define FLAG_NO_FIX_PLAYER
Definition: define.h:277
object_unset_flag_inv
void object_unset_flag_inv(object *op, int flag)
Definition: object.cpp:3230
object_free_key_values
void object_free_key_values(object *op)
Definition: object.cpp:954
diamondslots.y
y
Definition: diamondslots.py:16
add_force
object * add_force(object *op, const char *name, int duration)
Definition: object.cpp:5397
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
SET_MAP_OB
#define SET_MAP_OB(M, X, Y, tmp)
Definition: map.h:178
MAP_HEIGHT
#define MAP_HEIGHT(m)
Definition: map.h:80
save_object_in_sb
void save_object_in_sb(StringBuffer *sb, object *op, const int flag)
Definition: object.cpp:5278
get_ob_diff
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Definition: object.cpp:4960
obj::subtype
uint8_t subtype
Definition: object.h:347
obj::more
struct obj * more
Definition: object.h:301
object_remove_from_active_list
void object_remove_from_active_list(object *op)
Definition: object.cpp:1373
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.cpp:4251
obj::last_eat
int32_t last_eat
Definition: object.h:364
obj::move_type
MoveType move_type
Definition: object.h:432
obj::weight_limit
int32_t weight_limit
Definition: object.h:374
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:230
obj::materialname
sstring materialname
Definition: object.h:354
find_insert_pos
static object * find_insert_pos(object *op, const int flag)
Definition: object.cpp:2276
strcasecmp
int strcasecmp(const char *s1, const char *s2)
artifactstruct::item
object * item
Definition: artifact.h:15
object_distance
int object_distance(const object *ob1, const object *ob2)
Definition: object.cpp:3635
castle_read.key
key
Definition: castle_read.py:64