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 
1061 void object_copy_no_speed(const object *src_ob, object *dest_ob) {
1062  int is_freed = QUERY_FLAG(dest_ob, FLAG_FREED), is_removed = QUERY_FLAG(dest_ob, FLAG_REMOVED);
1063 
1064  /* Decrement the refcounts, but don't bother zeroing the fields;
1065  they'll be overwritten by memcpy. */
1066  if (dest_ob->artifact != NULL)
1067  free_string(dest_ob->artifact);
1068  if (dest_ob->name != NULL)
1069  free_string(dest_ob->name);
1070  if (dest_ob->name_pl != NULL)
1071  free_string(dest_ob->name_pl);
1072  if (dest_ob->anim_suffix != NULL)
1073  free_string(dest_ob->anim_suffix);
1074  if (dest_ob->title != NULL)
1075  free_string(dest_ob->title);
1076  if (dest_ob->race != NULL)
1077  free_string(dest_ob->race);
1078  if (dest_ob->slaying != NULL)
1079  free_string(dest_ob->slaying);
1080  if (dest_ob->skill != NULL)
1081  free_string(dest_ob->skill);
1082  if (dest_ob->msg != NULL)
1083  free_string(dest_ob->msg);
1084  if (dest_ob->lore != NULL)
1085  free_string(dest_ob->lore);
1086  if (dest_ob->materialname != NULL)
1087  free_string(dest_ob->materialname);
1088  if (dest_ob->spell_tags != NULL)
1089  FREE_AND_CLEAR(dest_ob->spell_tags);
1090 
1091  /* Basically, same code as from object_clear() */
1092 
1093  object_free_key_values(dest_ob);
1094  free_dialog_information(dest_ob);
1095 
1096  /* Copy all attributes below name (name included). */
1097  (void)memcpy((void *)((char *)dest_ob+offsetof(object, name)),
1098  (void *)((char *)src_ob+offsetof(object, name)),
1099  sizeof(object)-offsetof(object, name));
1100 
1101  if (is_freed)
1102  SET_FLAG(dest_ob, FLAG_FREED);
1103  if (is_removed)
1104  SET_FLAG(dest_ob, FLAG_REMOVED);
1105  if (dest_ob->artifact != NULL)
1106  add_refcount(dest_ob->artifact);
1107  if (dest_ob->name != NULL)
1108  add_refcount(dest_ob->name);
1109  if (dest_ob->name_pl != NULL)
1110  add_refcount(dest_ob->name_pl);
1111  if (dest_ob->anim_suffix != NULL)
1112  add_refcount(dest_ob->anim_suffix);
1113  if (dest_ob->title != NULL)
1114  add_refcount(dest_ob->title);
1115  if (dest_ob->race != NULL)
1116  add_refcount(dest_ob->race);
1117  if (dest_ob->slaying != NULL)
1118  add_refcount(dest_ob->slaying);
1119  if (dest_ob->skill != NULL)
1120  add_refcount(dest_ob->skill);
1121  if (dest_ob->lore != NULL)
1122  add_refcount(dest_ob->lore);
1123  if (dest_ob->msg != NULL)
1124  add_refcount(dest_ob->msg);
1125  if (dest_ob->materialname != NULL)
1126  add_refcount(dest_ob->materialname);
1127 
1128  if (dest_ob->spell_tags != NULL) {
1129  dest_ob->spell_tags = static_cast<tag_t *>(malloc(sizeof(tag_t)*SPELL_TAG_SIZE));
1130  memcpy(dest_ob->spell_tags, src_ob->spell_tags, sizeof(tag_t)*SPELL_TAG_SIZE);
1131  }
1132 
1133  /* If archetype is a temporary one, we need to update reference count, because
1134  * that archetype will be freed by object_free_drop_inventory() when the last object is removed.
1135  */
1136  if (dest_ob->arch != NULL) {
1137  if (dest_ob->arch->reference_count > 0)
1138  dest_ob->arch->reference_count++;
1139  }
1140 
1141  if (src_ob->speed < 0)
1142  dest_ob->speed_left = src_ob->speed_left-RANDOM()%200/100.0;
1143 
1144  /* Copy over key_values, if any. */
1145  if (src_ob->key_values != NULL) {
1146  key_value *tail = NULL;
1147  key_value *i;
1148 
1149  dest_ob->key_values = NULL;
1150 
1151  for (i = src_ob->key_values; i != NULL; i = i->next) {
1152  key_value *new_link = static_cast<key_value *>(malloc(sizeof(key_value)));
1153 
1154  new_link->next = NULL;
1155  new_link->key = add_refcount(i->key);
1156  if (i->value)
1157  new_link->value = add_refcount(i->value);
1158  else
1159  new_link->value = NULL;
1160 
1161  /* Try and be clever here, too. */
1162  if (dest_ob->key_values == NULL) {
1163  dest_ob->key_values = new_link;
1164  tail = new_link;
1165  } else {
1166  tail->next = new_link;
1167  tail = new_link;
1168  }
1169  }
1170  }
1171 
1172  /* This way, dialog information will be parsed again when/if needed. */
1173  CLEAR_FLAG(dest_ob, FLAG_DIALOG_PARSED);
1174 
1175  dest_ob->event_bitmask = BITMASK_VALID; // Empty inventory so valid
1176 }
1177 
1192 void object_copy(const object *src_ob, object *dest_ob) {
1193  object_copy_no_speed(src_ob, dest_ob);
1194  object_update_speed(dest_ob);
1195 }
1196 
1208 void object_copy_with_inv(const object *src_ob, object *dest_ob, bool update_speed) {
1209  if (update_speed) {
1210  object_copy(src_ob, dest_ob);
1211  } else {
1212  object_copy_no_speed(src_ob, dest_ob);
1213  }
1214  FOR_INV_PREPARE(src_ob, walk) {
1215  object *tmp;
1216 
1217  tmp = object_new();
1218  object_copy_with_inv(walk, tmp, update_speed);
1219  object_insert_in_ob(tmp, dest_ob);
1220  } FOR_INV_FINISH();
1221 }
1222 
1223 #ifndef MEMORY_DEBUG
1224 
1231 static void expand_objects(void) {
1232  int i;
1233  object *add;
1234 
1235  add = (object *)CALLOC(OBJ_EXPAND, sizeof(object));
1236 
1237  if (add == NULL)
1239  free_objects = add;
1240  add[0].prev = NULL;
1241  add[0].next = &add[1],
1242  SET_FLAG(&add[0], FLAG_REMOVED);
1243  SET_FLAG(&add[0], FLAG_FREED);
1244 
1245  for (i = 1; i < OBJ_EXPAND-1; i++) {
1246  add[i].next = &add[i+1],
1247  add[i].prev = &add[i-1],
1248  SET_FLAG(&add[i], FLAG_REMOVED);
1249  SET_FLAG(&add[i], FLAG_FREED);
1250  }
1251  add[OBJ_EXPAND-1].prev = &add[OBJ_EXPAND-2],
1252  add[OBJ_EXPAND-1].next = NULL,
1253  SET_FLAG(&add[OBJ_EXPAND-1], FLAG_REMOVED);
1254  SET_FLAG(&add[OBJ_EXPAND-1], FLAG_FREED);
1255 
1258 }
1259 #endif
1260 
1273 object *object_new(void) {
1274  object *op;
1275 #ifdef MEMORY_DEBUG
1276  /* FIXME: However this doesn't work since object_free() sometimes add
1277  * objects back to the free_objects linked list, and some functions mess
1278  * with the object after return of object_free(). This is bad and should be
1279  * fixed. But it would need fairly extensive changes and a lot of debugging.
1280  */
1281  op = static_cast<object *>(calloc(1, sizeof(object)));
1282  if (op == NULL)
1284 #else
1285  if (free_objects == NULL) {
1286  expand_objects();
1287  }
1288  op = free_objects;
1289  if (!QUERY_FLAG(op, FLAG_FREED)) {
1290  LOG(llevError, "Fatal: Getting busy object.\n");
1291 #ifdef MANY_CORES
1292  abort();
1293 #endif
1294  }
1295  free_objects = op->next;
1296  if (free_objects != NULL)
1297  free_objects->prev = NULL;
1298  nroffreeobjects--;
1299 #endif
1300  op->count = ++ob_count;
1301  op->name = NULL;
1302  op->name_pl = NULL;
1303  op->title = NULL;
1304  op->race = NULL;
1305  op->slaying = NULL;
1306  op->skill = NULL;
1307  op->lore = NULL;
1308  op->msg = NULL;
1309  op->materialname = NULL;
1310  op->next = objects;
1311  op->prev = NULL;
1312  op->active_next = NULL;
1313  op->active_prev = NULL;
1314  op->spell_tags = NULL;
1315  op->event_bitmask = BITMASK_VALID;
1316  if (objects != NULL)
1317  objects->prev = op;
1318  objects = op;
1319  object_clear(op);
1321  return op;
1322 }
1323 
1333  if (op->animation == 0 || !QUERY_FLAG(op, FLAG_IS_TURNABLE))
1334  return;
1335  animate_object(op, op->direction);
1336 }
1337 
1349 void object_update_speed(object *op) {
1350 
1351  /* No reason putting the archetypes objects on the speed list,
1352  * since they never really need to be updated.
1353  */
1354 
1355  if (QUERY_FLAG(op, FLAG_FREED) && op->speed) {
1356  LOG(llevError, "Object %s is freed but has speed.\n", op->name);
1357 #ifdef MANY_CORES
1358  abort();
1359 #else
1360  op->speed = 0;
1361 #endif
1362  }
1363  if (FABS(op->speed) > MIN_ACTIVE_SPEED) {
1364  /* If already on active list, don't do anything */
1365  /* TODO this check can probably be simplified a lot */
1366  if (op->active_next || op->active_prev || op == active_objects)
1367  return;
1368 
1369  /* process_events() expects us to insert the object at the beginning
1370  * of the list. */
1371  op->active_next = active_objects;
1372  if (op->active_next != NULL)
1373  op->active_next->active_prev = op;
1374  active_objects = op;
1375  } else {
1377  }
1378 }
1379 
1393  /* If not on the active list, nothing needs to be done */
1394  if (!op->active_next && !op->active_prev && op != active_objects)
1395  return;
1396 
1397  if (op->active_prev == NULL) {
1398  active_objects = op->active_next;
1399  if (op->active_next != NULL)
1400  op->active_next->active_prev = NULL;
1401  } else {
1402  op->active_prev->active_next = op->active_next;
1403  if (op->active_next)
1404  op->active_next->active_prev = op->active_prev;
1405  }
1406  op->active_next = NULL;
1407  op->active_prev = NULL;
1408 }
1409 
1434 void object_update(object *op, int action) {
1435  int update_now = 0, flags;
1436  MoveType move_on, move_off, move_block, move_slow;
1437  object *pl;
1438 
1439  if (op == NULL) {
1440  /* this should never happen */
1441  LOG(llevDebug, "object_update() called for NULL object.\n");
1442  return;
1443  }
1444 
1445  if (op->env != NULL) {
1446  /* Animation is currently handled by client, so nothing
1447  * to do in this case.
1448  */
1449  return;
1450  }
1451 
1452  /* If the map is saving, don't do anything as everything is
1453  * going to get freed anyways.
1454  */
1455  if (!op->map || op->map->in_memory == MAP_SAVING)
1456  return;
1457 
1458  /* make sure the object is within map boundaries */
1459  if (op->x < 0 || op->x >= MAP_WIDTH(op->map)
1460  || op->y < 0 || op->y >= MAP_HEIGHT(op->map)) {
1461  LOG(llevError, "object_update() called for object out of map!\n");
1462 #ifdef MANY_CORES
1463  abort();
1464 #endif
1465  return;
1466  }
1467 
1468  flags = GET_MAP_FLAGS(op->map, op->x, op->y);
1469  SET_MAP_FLAGS(op->map, op->x, op->y, flags|P_NEED_UPDATE);
1470  move_slow = GET_MAP_MOVE_SLOW(op->map, op->x, op->y);
1471  move_on = GET_MAP_MOVE_ON(op->map, op->x, op->y);
1472  move_block = GET_MAP_MOVE_BLOCK(op->map, op->x, op->y);
1473  move_off = GET_MAP_MOVE_OFF(op->map, op->x, op->y);
1474 
1475  if (action == UP_OBJ_INSERT) {
1477  update_now = 1;
1478 
1480  update_now = 1;
1481 
1483  update_now = 1;
1484 
1485  if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags&P_IS_ALIVE))
1486  update_now = 1;
1487 
1488  if ((move_on|op->move_on) != move_on)
1489  update_now = 1;
1490  if ((move_off|op->move_off) != move_off)
1491  update_now = 1;
1492  /* This isn't perfect, but I don't expect a lot of objects to
1493  * to have move_allow right now.
1494  */
1495  if (((move_block|op->move_block)&~op->move_allow) != move_block)
1496  update_now = 1;
1497  if ((move_slow|op->move_slow) != move_slow)
1498  update_now = 1;
1499 
1500  if (op->type == PLAYER)
1501  update_now = 1;
1502  /* if the object is being removed, we can't make intelligent
1503  * decisions, because object_remove() can't really pass the object
1504  * that is being removed.
1505  */
1506  } else if (action == UP_OBJ_REMOVE) {
1507  update_now = 1;
1508  } else if (action == UP_OBJ_FACE || action == UP_OBJ_CHANGE) {
1509  /* In addition to sending info to client, need to update space
1510  * information.
1511  */
1512  if (action == UP_OBJ_CHANGE)
1513  update_now = 1;
1514 
1515  /* There is a player on this space - we may need to send an
1516  * update to the client.
1517  * If this object is supposed to be animated by the client,
1518  * nothing to do here - let the client animate it.
1519  * We can't use FLAG_ANIMATE, as that is basically set for
1520  * all objects with multiple faces, regardless if they are animated.
1521  * (levers have it set for example).
1522  */
1523  if (flags&P_PLAYER
1526  pl = GET_MAP_PLAYER(op->map, op->x, op->y);
1527 
1528  /* If update_look is set, we're going to send this entire space
1529  * to the client, so no reason to send face information now.
1530  */
1531  if (!pl->contr->socket->update_look) {
1533  }
1534  }
1535  } else {
1536  LOG(llevError, "object_update called with invalid action: %d\n", action);
1537  }
1538 
1539  if (update_now) {
1541  update_position(op->map, op->x, op->y);
1542  }
1543 
1544  if (op->more != NULL)
1545  object_update(op->more, action);
1546 }
1547 
1561  object_free(ob, 0);
1562 }
1563 
1568 void object_free_inventory(object *ob) {
1569  while (ob->inv) {
1570  object *inv = ob->inv;
1571  object_remove(inv);
1573  }
1574 }
1575 
1592 void object_free(object *ob, int flags) {
1593  if (!QUERY_FLAG(ob, FLAG_REMOVED)) {
1594  StringBuffer *sb;
1595  char *diff;
1596 
1597  LOG(llevError, "Free object called with non removed object\n");
1598  sb = stringbuffer_new();
1599  object_dump(ob, sb);
1600  diff = stringbuffer_finish(sb);
1601  LOG(llevError, "%s", diff);
1602  free(diff);
1603 #ifdef MANY_CORES
1604  abort();
1605 #endif
1606  }
1607  if (QUERY_FLAG(ob, FLAG_FRIENDLY)) {
1608  LOG(llevMonster, "Warning: tried to free friendly object.\n");
1610  }
1611  if (QUERY_FLAG(ob, FLAG_FREED)) {
1612  StringBuffer *sb;
1613  char *diff;
1614 
1615  sb = stringbuffer_new();
1616  object_dump(ob, sb);
1617  diff = stringbuffer_finish(sb);
1618  LOG(llevError, "Trying to free freed object.\n%s\n", diff);
1619  free(diff);
1620  return;
1621  }
1622 
1623  if ((flags & FREE_OBJ_NO_DESTROY_CALLBACK) == 0) {
1625  }
1626 
1627  if (ob->inv) {
1628  /* Only if the space blocks everything do we not process -
1629  * if some form of movemnt is allowed, let objects
1630  * drop on that space.
1631  */
1632  if ((flags & FREE_OBJ_FREE_INVENTORY) != 0
1633  || ob->map == NULL
1634  || ob->map->in_memory != MAP_IN_MEMORY
1635  || (GET_MAP_MOVE_BLOCK(ob->map, ob->x, ob->y) == MOVE_ALL)) {
1636  FOR_INV_PREPARE(ob, op) {
1637  object_remove(op);
1638  object_free(op, flags);
1639  } FOR_INV_FINISH();
1640  } else { /* Put objects in inventory onto this space */
1641  FOR_INV_PREPARE(ob, op) {
1642  object_remove(op);
1643  /* No drop means no drop, including its inventory */
1644  if (QUERY_FLAG(op, FLAG_NO_DROP))
1646  else if (QUERY_FLAG(op, FLAG_STARTEQUIP)
1648  || op->type == RUNE
1649  || op->type == TRAP
1652  else {
1653  object *part;
1654 
1655  /* If it's a multi-tile object, scatter dropped items randomly */
1656  if (ob->more) {
1657  int partcount = 0;
1658  /* Get the number of non-head parts */
1659  for (part = ob; part; part = part->more) {
1660  partcount++;
1661  }
1662  /* Select a random part */
1663  partcount = RANDOM()%partcount;
1664  for (part = ob; partcount > 0; partcount--) {
1665  part = part->more;
1666  }
1667  } else {
1668  part = ob;
1669  }
1670 
1671  if (QUERY_FLAG(op, FLAG_ALIVE)) {
1672  object_insert_to_free_spot_or_free(op, part->map, part->x, part->y, 0, SIZEOFFREE, NULL);
1673  } else {
1674  int f = 0;
1677  object_insert_in_map_at(op, part->map, NULL, f, part->x, part->y); /* Insert in same map as the envir */
1678  }
1679  }
1680  } FOR_INV_FINISH();
1681  }
1682  }
1683 
1684  if (ob->more != NULL) {
1685  object_free(ob->more, flags);
1686  ob->more = NULL;
1687  }
1688 
1689  /* Remove object from the active list */
1690  ob->speed = 0;
1692 
1694  ob->count = 0;
1695 
1696  /* Remove this object from the list of used objects */
1697  if (ob->prev == NULL) {
1698  objects = ob->next;
1699  if (objects != NULL)
1700  objects->prev = NULL;
1701  } else {
1702  ob->prev->next = ob->next;
1703  if (ob->next != NULL)
1704  ob->next->prev = ob->prev;
1705  }
1706 
1707  if (ob->artifact != NULL) FREE_AND_CLEAR_STR(ob->artifact);
1708  if (ob->name != NULL) FREE_AND_CLEAR_STR(ob->name);
1709  if (ob->name_pl != NULL) FREE_AND_CLEAR_STR(ob->name_pl);
1710  if (ob->title != NULL) FREE_AND_CLEAR_STR(ob->title);
1711  if (ob->race != NULL) FREE_AND_CLEAR_STR(ob->race);
1712  if (ob->slaying != NULL) FREE_AND_CLEAR_STR(ob->slaying);
1713  if (ob->skill != NULL) FREE_AND_CLEAR_STR(ob->skill);
1714  if (ob->lore != NULL) FREE_AND_CLEAR_STR(ob->lore);
1715  if (ob->msg != NULL) FREE_AND_CLEAR_STR(ob->msg);
1716  if (ob->materialname != NULL) FREE_AND_CLEAR_STR(ob->materialname);
1717  if (ob->spell_tags) FREE_AND_CLEAR(ob->spell_tags);
1718  FREE_AND_CLEAR_STR_IF(ob->anim_suffix);
1719 
1720  /* Why aren't events freed? */
1722 
1724 
1725  /* Test whether archetype is a temporary one, and if so look whether it should be trashed. */
1726  if (ob->arch && ob->arch->reference_count > 0) {
1727  if (--ob->arch->reference_count == 0) {
1728  free_arch(ob->arch);
1729  }
1730  }
1731 
1732 #ifdef MEMORY_DEBUG
1733  free(ob);
1734 #else
1735  /* Now link it with the free_objects list: */
1736  ob->prev = NULL;
1737  ob->next = free_objects;
1738  if (free_objects != NULL)
1739  free_objects->prev = ob;
1740  free_objects = ob;
1741  nroffreeobjects++;
1742 #endif
1743 }
1744 
1752  int i = 0;
1753  object *tmp = free_objects;
1754 
1755  while (tmp != NULL)
1756  tmp = tmp->next,
1757  i++;
1758  return i;
1759 }
1760 
1768  int i = 0;
1769  object *tmp = objects;
1770 
1771  while (tmp != NULL)
1772  tmp = tmp->next,
1773  i++;
1774  return i;
1775 }
1776 
1784  int i = 0;
1785  object *tmp = active_objects;
1786 
1787  while (tmp != NULL)
1788  tmp = tmp->active_next,
1789  i++;
1790  return i;
1791 }
1792 
1807 void object_sub_weight(object *op, signed long weight) {
1808  while (op != NULL) {
1809  if (op->type == CONTAINER) {
1810  weight = (signed long)(weight*(100-op->stats.Str)/100);
1811  }
1812  op->carrying -= weight;
1813  op = op->env;
1814  }
1815 }
1816 
1833 void object_remove(object *op) {
1834  object *last = NULL;
1835  object *otmp;
1836  tag_t tag;
1837  int check_walk_off;
1838  mapstruct *m;
1839  int16_t x, y;
1840 
1841  if (QUERY_FLAG(op, FLAG_REMOVED)) {
1842  StringBuffer *sb;
1843  char *diff;
1844 
1845  sb = stringbuffer_new();
1846  object_dump(op, sb);
1847  diff = stringbuffer_finish(sb);
1848  LOG(llevError, "Trying to remove removed object.\n%s\n", diff);
1849  free(diff);
1850  abort();
1851  }
1852  if (op->more != NULL)
1853  object_remove(op->more);
1854 
1856 
1857  /*
1858  * In this case, the object to be removed is in someones
1859  * inventory.
1860  */
1861  /* TODO try to call a generic inventory weight adjusting function like object_sub_weight */
1862  if (op->env != NULL) {
1863  player *pl = NULL;
1864 
1865  if (op->nrof)
1866  object_sub_weight(op->env, op->weight*op->nrof);
1867  else
1868  object_sub_weight(op->env, op->weight+op->carrying);
1869 
1870  /* Update in two cases: item is in a player, or in a container the player is looking into. */
1871  if (op->env->contr != NULL && op->head == NULL) {
1872  pl = op->env->contr;
1873  } else if (op->env->type == CONTAINER && QUERY_FLAG(op->env, FLAG_APPLIED)) {
1874 
1875  if (op->env->env && op->env->env->contr)
1876  /* Container is in player's inventory. */
1877  pl = op->env->env->contr;
1878  else if (op->env->map) {
1879  /* Container on map, look above for player. */
1880  object *above = op->env->above;
1881 
1882  while (above && !above->contr)
1883  above = above->above;
1884  if (above)
1885  pl = above->contr;
1886  }
1887  }
1888 
1889  /* NO_FIX_PLAYER is set when a great many changes are being
1890  * made to players inventory. If set, avoiding the call
1891  * to save cpu time.
1892  */
1893  otmp = object_get_player_container(op->env);
1894  if (otmp != NULL
1895  && otmp->contr
1896  && !QUERY_FLAG(otmp, FLAG_NO_FIX_PLAYER))
1897  fix_object(otmp);
1898 
1899  if (op->above != NULL)
1900  op->above->below = op->below;
1901  else
1902  op->env->inv = op->below;
1903 
1904  if (op->below != NULL)
1905  op->below->above = op->above;
1906 
1907  if (op->type == EVENT_CONNECTOR) {
1908  op->env->event_bitmask = 0; // Will be recomputed if needed
1909  }
1910 
1911  /* we set up values so that it could be inserted into
1912  * the map, but we don't actually do that - it is up
1913  * to the caller to decide what we want to do.
1914  */
1915  op->x = op->env->x;
1916  op->y = op->env->y;
1917  op->ox = op->x;
1918  op->oy = op->y;
1919  op->map = op->env->map;
1920  op->above = NULL;
1921  op->below = NULL;
1922  /* send the delitem before resetting env, so container's contents be may
1923  * refreshed */
1924  if (LOOK_OBJ(op) && pl != NULL)
1925  esrv_del_item(pl, op);
1926  op->env = NULL;
1927  return;
1928  }
1929 
1930  /* If we get here, we are removing it from a map */
1931  if (op->map == NULL)
1932  return;
1933 
1934  if (op->contr != NULL && !op->contr->hidden)
1935  op->map->players--;
1936 
1937  x = op->x;
1938  y = op->y;
1939  m = get_map_from_coord(op->map, &x, &y);
1940 
1941  if (!m) {
1942  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);
1943  abort();
1944  }
1945  if (op->map != m) {
1946  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);
1947  }
1948 
1949  /* link the object above us */
1950  if (op->above)
1951  op->above->below = op->below;
1952  else
1953  SET_MAP_TOP(m, x, y, op->below); /* we were top, set new top */
1954 
1955  /* Relink the object below us, if there is one */
1956  if (op->below) {
1957  op->below->above = op->above;
1958  } else {
1959  /* Nothing below, which means we need to relink map object for this space
1960  * use translated coordinates in case some oddness with map tiling is
1961  * evident
1962  */
1963  /*TODO is this check really needed?*/
1964  if (GET_MAP_OB(m, x, y) != op) {
1965  StringBuffer *sb;
1966  char *diff;
1967 
1968  sb = stringbuffer_new();
1969  object_dump(op, sb);
1970  diff = stringbuffer_finish(sb);
1971  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);
1972  free(diff);
1973 
1974  sb = stringbuffer_new();
1975  object_dump(GET_MAP_OB(m, x, y), sb);
1976  diff = stringbuffer_finish(sb);
1977  LOG(llevError, "%s\n", diff);
1978  free(diff);
1979  }
1980  SET_MAP_OB(m, x, y, op->above); /* goes on above it. */
1981  }
1982  op->above = NULL;
1983  op->below = NULL;
1984 
1985  if (op->map->in_memory == MAP_SAVING)
1986  return;
1987 
1988  tag = op->count;
1989  check_walk_off = !QUERY_FLAG(op, FLAG_NO_APPLY);
1990  FOR_MAP_PREPARE(m, x, y, tmp) {
1991  /* No point updating the players look faces if he is the object
1992  * being removed.
1993  */
1994 
1995  if (tmp->type == PLAYER && tmp != op) {
1996  /* If a container that the player is currently using somehow gets
1997  * removed (most likely destroyed), update the player view
1998  * appropriately.
1999  */
2000  if (tmp->container == op) {
2002  tmp->container = NULL;
2003  }
2004  tmp->contr->socket->update_look = 1;
2005  }
2006  /* See if player moving off should effect something */
2007  if (check_walk_off
2008  && ((op->move_type&tmp->move_off) && (op->move_type&~tmp->move_off&~tmp->move_block) == 0)) {
2009  ob_move_on(tmp, op, NULL);
2010  if (object_was_destroyed(op, tag)) {
2011  LOG(llevError, "BUG: object_remove(): name %s, archname %s destroyed leaving object\n", tmp->name, tmp->arch->name);
2012  }
2013  }
2014 
2015  /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */
2016  if (tmp->above == tmp)
2017  tmp->above = NULL;
2018  last = tmp;
2019  } FOR_MAP_FINISH();
2020  /* last == NULL or there are no objects on this space */
2021  if (last == NULL) {
2022  /* set P_NEED_UPDATE, otherwise update_position will complain. In theory,
2023  * we could preserve the flags (GET_MAP_FLAGS), but update_position figures
2024  * those out anyways, and if there are any flags set right now, they won't
2025  * be correct anyways.
2026  */
2027  SET_MAP_FLAGS(op->map, op->x, op->y, P_NEED_UPDATE);
2028  update_position(op->map, op->x, op->y);
2029  } else
2031 
2032  if (QUERY_FLAG(op, FLAG_BLOCKSVIEW) || (op->glow_radius != 0))
2033  update_all_los(op->map, op->x, op->y);
2034 }
2035 
2049 object *object_merge(object *op, object *top) {
2050  if (!op->nrof)
2051  return NULL;
2052 
2053  if (top == NULL)
2054  for (top = op; top != NULL && top->above != NULL; top = top->above)
2055  ;
2057  if (top == op)
2058  continue;
2059  if (object_can_merge(op, top)) {
2060  object_increase_nrof(top, op->nrof);
2061  /*
2062  * Previous behavior set weight to zero here.
2063  * This, however, caused the object_sub_weight
2064  * call in object_remove to subtract zero weight
2065  * when removing the object. Thus, until inventory
2066  * weight is next recalculated, the object merged
2067  * into another pile added weight in object_increase_nrof
2068  * but did not remove the weight from the original
2069  * instance of itself in object_remove, essentially
2070  * counting for double weight for several minutes.
2071  *
2072  * SilverNexus 2014-05-27
2073  */
2074  object_remove(op);
2076  return top;
2077  }
2079  return NULL;
2080 }
2081 
2098 object *object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y) {
2099  object *tmp;
2100 
2101  op = HEAD(op);
2102  for (tmp = op; tmp; tmp = tmp->more) {
2103  tmp->x = x+tmp->arch->clone.x;
2104  tmp->y = y+tmp->arch->clone.y;
2105  tmp->map = m;
2106  }
2107  return object_insert_in_map(op, m, originator, flag);
2108 }
2109 
2127 void object_merge_spell(object *op, int16_t x, int16_t y) {
2128  int i;
2129 
2130  /* We try to do some merging of spell objects - if something has same owner,
2131  * is same type of spell, and going in the same direction, it is somewhat
2132  * mergable.
2133  *
2134  * If the spell object has an other_arch, don't merge - when the spell
2135  * does something, like explodes, it will use this other_arch, and
2136  * if we merge, there is no easy way to make the correct values be
2137  * set on this new object (values should be doubled, tripled, etc.)
2138  *
2139  * We also care about speed - only process objects that will not be
2140  * active this tick. Without this, the results are incorrect - think
2141  * of a case where tmp would normally get processed this tick, but
2142  * get merges with op, which does not get processed.
2143  */
2144  FOR_MAP_PREPARE(op->map, x, y, tmp) {
2145  if (op->type == tmp->type
2146  && op->subtype == tmp->subtype
2147  && op->direction == tmp->direction
2148  && op->owner == tmp->owner && op->ownercount == tmp->ownercount
2149  && op->range == tmp->range
2150  && op->stats.wc == tmp->stats.wc
2151  && op->level == tmp->level
2152  && op->attacktype == tmp->attacktype
2153  && op->speed == tmp->speed
2154  && !tmp->other_arch
2155  && (tmp->speed_left+tmp->speed) < 0.0
2156  && op != tmp) {
2157  /* Quick test - if one or the other objects already have hash tables
2158  * set up, and that hash bucket contains a value that doesn't
2159  * match what we want to set it up, we won't be able to merge.
2160  * Note that these two if statements are the same, except
2161  * for which object they are checking against. They could
2162  * be merged, but the line wrapping would be large enough
2163  * that IMO it would become difficult to read the different clauses
2164  * so its cleaner just to do 2 statements - MSW
2165  */
2166  if (op->spell_tags
2167  && !OB_SPELL_TAG_MATCH(op, (tag_t)tmp->stats.maxhp)
2168  && OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) != 0)
2169  continue;
2170 
2171  if (tmp->spell_tags
2172  && !OB_SPELL_TAG_MATCH(tmp, (tag_t)op->stats.maxhp)
2173  && OB_SPELL_TAG_HASH(tmp, op->stats.maxhp) != 0)
2174  continue;
2175 
2176  /* If we merge, the data from tmp->spell_tags gets copied into op.
2177  * so we need to make sure that slot isn't filled up.
2178  */
2179  if (tmp->spell_tags
2180  && !OB_SPELL_TAG_MATCH(tmp, (tag_t)tmp->stats.maxhp)
2181  && OB_SPELL_TAG_HASH(tmp, tmp->stats.maxhp) != 0)
2182  continue;
2183 
2184  /* If both objects have spell_tags, we need to see if there are conflicting
2185  * values - if there are, we won't be able to merge then.
2186  */
2187  if (tmp->spell_tags && op->spell_tags) {
2188  int need_copy = 0;
2189 
2190  for (i = 0; i < SPELL_TAG_SIZE; i++) {
2191  /* If the two tag values in the hash are set, but are
2192  * not set to the same value, then these objects
2193  * can not be merged.
2194  */
2195  if (op->spell_tags[i] && tmp->spell_tags[i]
2196  && op->spell_tags[i] != tmp->spell_tags[i]) {
2198  break;
2199  }
2200  /* If one tag is set and the other is not, that is
2201  * fine, but we have to note that we need to copy
2202  * the data in that case.
2203  */
2204  if ((!op->spell_tags[i] && tmp->spell_tags[i])
2205  || (op->spell_tags[i] && !tmp->spell_tags[i])) {
2206  need_copy = 1;
2207  }
2208  }
2209  /* If we did not get through entire array, it means
2210  * we got a conflicting hash, and so we won't be
2211  * able to merge these - just continue processing
2212  * object on this space.
2213  */
2214  if (i <= SPELL_TAG_SIZE)
2215  continue;
2216 
2217  /* Ok - everything checked out - we should be able to
2218  * merge tmp in op. So lets copy the tag data if
2219  * needed. Note that this is a selective copy, as
2220  * we don't want to clear values that may be set in op.
2221  */
2222  if (need_copy) {
2223  for (i = 0; i < SPELL_TAG_SIZE; i++)
2224  if (!op->spell_tags[i]
2225  && tmp->spell_tags[i]
2226  && tmp->spell_tags[i] != (tag_t)op->stats.maxhp)
2227  op->spell_tags[i] = tmp->spell_tags[i];
2228  }
2229  FREE_AND_CLEAR(tmp->spell_tags);
2230  }
2231 
2232  /* if tmp has a spell_tags table, copy it to op and free tmps */
2233  if (tmp->spell_tags && !op->spell_tags) {
2234  op->spell_tags = tmp->spell_tags;
2235  tmp->spell_tags = NULL;
2236 
2237  /* We don't need to keep a copy of our maxhp value
2238  * in the copied over value
2239  */
2240  if (OB_SPELL_TAG_MATCH(op, (tag_t)op->stats.maxhp))
2241  OB_SPELL_TAG_HASH(op, op->stats.maxhp) = 0;
2242  }
2243 
2244  /* For spells to work correctly, we need to record what spell
2245  * tags we've merged in with this effect. This is used
2246  * in ok_to_put_more() to see if a spell effect is already on
2247  * the space.
2248  */
2249  if (op->stats.maxhp != tmp->stats.maxhp) {
2250 #ifdef OBJECT_DEBUG
2251  /* This if statement should never happen - the logic above should
2252  * have prevented it. It is a problem, because by now its possible
2253  * we've destroyed the spell_tags in tmp, so we can't really
2254  * just bail out.
2255  */
2256 
2257  if (op->spell_tags
2258  && OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) != 0
2259  && !OB_SPELL_TAG_MATCH(op, tmp->stats.maxhp)) {
2260  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);
2261  }
2262 #endif
2263  if (!op->spell_tags)
2264  op->spell_tags = static_cast<tag_t *>(calloc(SPELL_TAG_SIZE, sizeof(tag_t)));
2265 
2266  OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) = tmp->stats.maxhp;
2267  }
2268 
2270  op->speed_left = MAX(op->speed_left, tmp->speed_left);
2271 
2272  if (tmp->duration != op->duration) {
2273  /* We need to use tmp_dam here because otherwise the
2274  * calculations can overflow the size of stats.dam.
2275  */
2276  int tmp_dam = tmp->stats.dam*(tmp->duration+1)+
2277  op->stats.dam*(op->duration+1);
2278 
2279  op->duration = MAX(op->duration, tmp->duration);
2280  tmp_dam /= op->duration+1;
2281  op->stats.dam = tmp_dam+1;
2282  } else {
2283  /* in this case, duration is the same, so simply adding
2284  * up damage works.
2285  */
2286  op->stats.dam += tmp->stats.dam;
2287  }
2288 
2289  object_remove(tmp);
2291  }
2292  } FOR_MAP_FINISH();
2293 }
2294 
2295 static object *find_insert_pos(object *op, const int flag) {
2296  object *floor = NULL;
2297  /*
2298  * If there are multiple objects on this space, we do some trickier handling.
2299  * We've already dealt with merging if appropriate.
2300  * Generally, we want to put the new object on top. But if
2301  * flag contains INS_ABOVE_FLOOR_ONLY, once we find the last
2302  * floor, we want to insert above that and no further.
2303  * Also, if there are spell objects on this space, we stop processing
2304  * once we get to them. This reduces the need to traverse over all of
2305  * them when adding another one - this saves quite a bit of cpu time
2306  * when lots of spells are cast in one area. Currently, it is presumed
2307  * that flying non pickable objects are spell objects.
2308  */
2309  if (flag&INS_ON_TOP) {
2310  return GET_MAP_TOP(op->map, op->x, op->y);
2311  }
2312  object *last = NULL;
2313  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp) {
2316  floor = tmp;
2317 
2319  && (tmp->move_type&(MOVE_FLY_LOW|MOVE_FLY_HIGH))
2320  && !QUERY_FLAG(tmp, FLAG_IS_FLOOR)) {
2321  /* We insert above tmp, so we want this object below this */
2322  break;
2323  }
2324  last = tmp;
2325  } FOR_MAP_FINISH();
2326  if (flag&INS_ABOVE_FLOOR_ONLY)
2327  return floor;
2328  return last;
2329 }
2330 
2359 object *object_insert_in_map(object *op, mapstruct *m, object *originator, int flag) {
2360  object *tmp, *top, *floor = NULL;
2361  int16_t x, y;
2362 
2363  if (QUERY_FLAG(op, FLAG_FREED)) {
2364  LOG(llevError, "Trying to insert freed object!\n");
2365  return NULL;
2366  }
2367  if (m == NULL) {
2368  StringBuffer *sb;
2369  char *diff;
2370 
2371  sb = stringbuffer_new();
2372  object_dump(op, sb);
2373  diff = stringbuffer_finish(sb);
2374  LOG(llevError, "Trying to insert in null-map!\n%s\n", diff);
2375  free(diff);
2376  return op;
2377  }
2378  if (out_of_map(m, op->x, op->y)) {
2379  StringBuffer *sb;
2380  char *diff;
2381 
2382  sb = stringbuffer_new();
2383  object_dump(op, sb);
2384  diff = stringbuffer_finish(sb);
2385  LOG(llevError, "Trying to insert object outside the map.\n%s\n", diff);
2386  free(diff);
2387 #ifdef MANY_CORES
2388  /* Better to catch this here, as otherwise the next use of this object
2389  * is likely to cause a crash. Better to find out where it is getting
2390  * improperly inserted.
2391  */
2392  abort();
2393 #endif
2394  return op;
2395  }
2396  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
2397  StringBuffer *sb;
2398  char *diff;
2399 
2400  sb = stringbuffer_new();
2401  object_dump(op, sb);
2402  diff = stringbuffer_finish(sb);
2403  LOG(llevError, "Trying to insert (map) inserted object.\n%s\n", diff);
2404  free(diff);
2405  return op;
2406  }
2407  if (op->more != NULL) {
2408  /* The part may be on a different map. */
2409 
2410  object *more = op->more;
2411 
2412  /* We really need the caller to normalize coordinates - if
2413  * we set the map, that doesn't work if the location is within
2414  * a map and this is straddling an edge. So only if coordinate
2415  * is clear wrong do we normalize it.
2416  */
2417  if (OUT_OF_REAL_MAP(more->map, more->x, more->y)) {
2418  /* Debugging information so you can see the last coordinates this object had */
2419  more->ox = more->x;
2420  more->oy = more->y;
2421  more->map = get_map_from_coord(more->map, &more->x, &more->y);
2422  } else if (!more->map) {
2423  /* For backwards compatibility - when not dealing with tiled maps,
2424  * more->map should always point to the parent.
2425  */
2426  more->map = m;
2427  }
2428 
2429  if (object_insert_in_map(more, more->map, originator, flag) == NULL) {
2430  if (!op->head)
2431  LOG(llevError, "BUG: object_insert_in_map(): inserting op->more killed op\n");
2432  return NULL;
2433  }
2434  }
2436 
2437  /* Debugging information so you can see the last coordinates this object had */
2438  op->ox = op->x;
2439  op->oy = op->y;
2440  x = op->x;
2441  y = op->y;
2442  op->map = get_map_from_coord(m, &x, &y);
2443 
2444  /* this has to be done after we translate the coordinates. */
2445  if (op->nrof
2446  && !(flag&INS_NO_MERGE)
2447  && op->type != SPELL_EFFECT) {
2448  FOR_MAP_PREPARE(op->map, x, y, spot) {
2449  if (object_can_merge(op, spot)) {
2450  op->nrof += spot->nrof;
2451  object_remove(spot);
2453  }
2454  } FOR_MAP_FINISH();
2455  } else if (op->type == SPELL_EFFECT
2456  && !op->range
2457  && !op->other_arch
2458  && (op->speed_left+op->speed) < 0.0) {
2459  object_merge_spell(op, x, y);
2460  }
2461 
2462  /* Ideally, the caller figures this out. However, it complicates a lot
2463  * of areas of callers (eg, anything that uses object_find_free_spot() would now
2464  * need extra work
2465  */
2466  if (op->map != m) {
2467  /* coordinates should not change unless map also changes */
2468  op->x = x;
2469  op->y = y;
2470  }
2471 
2472  if (op->type != LAMP)
2473  /* lamps use the FLAG_APPLIED to keep the light/unlit status, so don't reset it.
2474  Other objects just get unapplied, since the container "drops" them. */
2477  if (!QUERY_FLAG(op, FLAG_ALIVE))
2479 
2480  /* In many places, a player is passed as the originator, which
2481  * is fine. However, if the player is on a transport, they are not
2482  * actually on the map, so we can't use them for the linked pointers,
2483  * nor should the walk on function below use them either.
2484  */
2485  if (originator && originator->contr && originator->contr->transport)
2486  originator = originator->contr->transport;
2487 
2488  if (flag&INS_BELOW_ORIGINATOR) {
2489  if (originator->map != op->map
2490  || originator->x != op->x
2491  || originator->y != op->y) {
2492  LOG(llevError, "object_insert_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n");
2493  abort();
2494  }
2495  op->above = originator;
2496  op->below = originator->below;
2497  if (op->below)
2498  op->below->above = op;
2499  else
2500  SET_MAP_OB(op->map, op->x, op->y, op);
2501  /* since *below *originator, no need to update top */
2502  originator->below = op;
2503  } else {
2504  /* Top is the object that our object (op) is going to get inserted above. */
2505  top = find_insert_pos(op, flag);
2506 
2507  /* First object on this space */
2508  if (!top) {
2509  op->above = GET_MAP_OB(op->map, op->x, op->y);
2510  if (op->above)
2511  op->above->below = op;
2512  op->below = NULL;
2513  SET_MAP_OB(op->map, op->x, op->y, op);
2514  } else { /* get inserted into the stack above top */
2515  op->above = top->above;
2516  if (op->above)
2517  op->above->below = op;
2518  op->below = top;
2519  top->above = op;
2520  }
2521  if (op->above == NULL)
2522  SET_MAP_TOP(op->map, op->x, op->y, op);
2523  } /* else not INS_BELOW_ORIGINATOR */
2524 
2525  if (!(flag&INS_MAP_LOAD)) {
2526  if (op->type == PLAYER)
2527  op->contr->do_los = 1;
2528 
2529  /* If we have a floor, we know the player, if any, will be above
2530  * it, so save a few ticks and start from there.
2531  */
2532  tmp = floor ? floor : GET_MAP_OB(op->map, op->x, op->y);
2534  if (tmp->type == PLAYER)
2535  tmp->contr->socket->update_look = 1;
2537 
2538  /* If this object glows, it may affect lighting conditions that are
2539  * visible to others on this map. But update_all_los is really
2540  * an inefficient way to do this, as it means los for all players
2541  * on the map will get recalculated. The players could very well
2542  * be far away from this change and not affected in any way -
2543  * this should get redone to only look for players within range,
2544  * or just updating the P_NEED_UPDATE for spaces within this area
2545  * of effect may be sufficient.
2546  */
2547  if (MAP_DARKNESS(op->map) && (op->glow_radius != 0))
2548  update_all_los(op->map, op->x, op->y);
2549 
2550  if (op->contr && !op->contr->hidden)
2551  op->map->players++;
2552  }
2553 
2554  /* updates flags (blocked, alive, no magic, etc) for this map space */
2556 
2557  /* Don't know if moving this to the end will break anything. However,
2558  * we want to have update_look set above before calling this.
2559  *
2560  * object_check_move_on() must be after this because code called from
2561  * object_check_move_on() depends on correct map flags (so functions like
2562  * blocked() and wall() work properly), and these flags are updated by
2563  * object_update().
2564  */
2565 
2566  /* if this is not the head or flag has been passed, don't check walk on status */
2567 
2568  if (!(flag&INS_NO_WALK_ON) && !op->head) {
2569  if (object_check_move_on(op, originator))
2570  return NULL;
2571 
2572  /* If we are a multi part object, lets work our way through the check
2573  * walk on's.
2574  */
2575  for (tmp = op->more; tmp != NULL; tmp = tmp->more)
2576  if (object_check_move_on(tmp, originator))
2577  return NULL;
2578  }
2579  return op;
2580 }
2581 
2591 void object_replace_insert_in_map(const char *arch_string, object *op) {
2592  object *tmp1;
2593  archetype *at;
2594 
2595  /* first search for itself and remove any old instances */
2596  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp) {
2597  if (!strcmp(tmp->arch->name, arch_string)) { /* same archetype */
2598  object_remove(tmp);
2600  }
2601  } FOR_MAP_FINISH();
2602 
2603  at = find_archetype(arch_string);
2604  if (at == NULL) {
2605  return;
2606  }
2607  tmp1 = arch_to_object(at);
2608  object_insert_in_map_at(tmp1, op->map, op, INS_BELOW_ORIGINATOR, op->x, op->y);
2609 }
2610 
2631 object *object_split(object *orig_ob, uint32_t nr, char *err, size_t size) {
2632  object *newob;
2633 
2634  if (MAX(1, orig_ob->nrof) < nr) {
2635  /* If err is set, the caller knows that nr can be wrong (player trying to drop items), thus don't log that. */
2636  if (err)
2637  snprintf(err, size, "There are only %u %ss.", NROF(orig_ob), orig_ob->name);
2638  else
2639  LOG(llevDebug, "There are only %u %ss.\n", NROF(orig_ob), orig_ob->name);
2640  return NULL;
2641  }
2642  newob = object_create_clone(orig_ob);
2643  if (orig_ob->nrof == 0) {
2644  if (!QUERY_FLAG(orig_ob, FLAG_REMOVED)) {
2645  object_remove(orig_ob);
2646  }
2648  } else {
2649  newob->nrof = nr;
2650  object_decrease_nrof(orig_ob, nr);
2651  }
2652 
2653  return newob;
2654 }
2655 
2670 object *object_decrease_nrof(object *op, uint32_t i) {
2671  object *tmp;
2672 
2673  if (i == 0) /* objects with op->nrof require this check */
2674  return op;
2675 
2676  if (i > op->nrof)
2677  i = op->nrof;
2678 
2679  if (QUERY_FLAG(op, FLAG_REMOVED)) {
2680  op->nrof -= i;
2681  } else if (op->env != NULL) {
2682  if (i < op->nrof) {
2683  player *pl;
2684  /* is this object in the players inventory, or sub container
2685  * therein?
2686  */
2688  /* nope. Is this a container the player has opened?
2689  * If so, set tmp to that player.
2690  * IMO, searching through all the players will mostly
2691  * likely be quicker than following op->env to the map,
2692  * and then searching the map for a player.
2693  */
2694  if (!tmp) {
2695  for (pl = first_player; pl; pl = pl->next)
2696  if (pl->ob->container == op->env)
2697  break;
2698  if (pl)
2699  tmp = pl->ob;
2700  else
2701  tmp = NULL;
2702  }
2703 
2704  /* Because of weight reduction by container and integer arithmetic,
2705  * there is no guarantee the rounded weight of combined items will be
2706  * the same as the sum of rounded weights.
2707  * Therefore just remove the current weight, and add the new.
2708  * Same adjustment done in object_increase_nrof().
2709  */
2710  object_sub_weight(op->env, op->weight * op->nrof);
2711  op->nrof -= i;
2712  object_add_weight(op->env, op->weight * op->nrof);
2713  if (tmp) {
2716  fix_object(tmp);
2717  }
2718  } else {
2719  object_remove(op);
2720  op->nrof = 0;
2721  }
2722  } else {
2723  /* On a map. */
2724  if (i < op->nrof) {
2725  op->nrof -= i;
2726 
2727  FOR_MAP_PREPARE(op->map, op->x, op->y, pl)
2728  if (pl->contr) {
2729  pl->contr->socket->update_look = 1;
2730  break;
2731  }
2732  FOR_MAP_FINISH();
2733  } else {
2734  object_remove(op);
2735  op->nrof = 0;
2736  }
2737  }
2738 
2739  if (op->nrof) {
2740  return op;
2741  } else {
2743  return NULL;
2744  }
2745 }
2746 
2757 static void object_increase_nrof(object *op, uint32_t i) {
2758  object *tmp;
2759 
2760  if (i == 0) /* objects with op->nrof require this check */
2761  return;
2762 
2763  if (QUERY_FLAG(op, FLAG_REMOVED)) {
2764  op->nrof += i;
2765  } else if (op->env != NULL) {
2766  player *pl;
2767  /* is this object in the players inventory, or sub container
2768  * therein?
2769  */
2771  /* nope. Is this a container the player has opened?
2772  * If so, set tmp to that player.
2773  * IMO, searching through all the players will mostly
2774  * likely be quicker than following op->env to the map,
2775  * and then searching the map for a player.
2776  */
2777  if (!tmp) {
2778  for (pl = first_player; pl; pl = pl->next)
2779  if (pl->ob->container == op->env)
2780  break;
2781  if (pl)
2782  tmp = pl->ob;
2783  else
2784  tmp = NULL;
2785  }
2786 
2787  /* Because of weight reduction by container and integer arithmetic,
2788  * there is no guarantee the rounded weight of combined items will be
2789  * the same as the sum of rounded weights.
2790  * Therefore just remove the current weight, and add the new.
2791  * Same adjustment done in object_decrease_nrof().
2792  */
2793  object_sub_weight(op->env, op->weight * op->nrof);
2794  op->nrof += i;
2795  object_add_weight(op->env, op->weight * op->nrof);
2796  if (tmp) {
2798  // Why don't we need to update weight of op->env here?
2799  }
2800  } else {
2801  /* On a map. */
2802  op->nrof += i;
2803 
2804  FOR_MAP_PREPARE(op->map, op->x, op->y, pl)
2805  if (pl->contr) {
2806  pl->contr->socket->update_look = 1;
2807  break;
2808  }
2809  FOR_MAP_FINISH();
2810  }
2811 }
2812 
2827 void object_add_weight(object *op, signed long weight) {
2828  while (op != NULL) {
2829  if (op->type == CONTAINER) {
2830  weight = (signed long)(weight*(100-op->stats.Str)/100);
2831  }
2832  op->carrying += weight;
2833  op = op->env;
2834  }
2835 }
2836 
2851 object *object_insert_in_ob(object *op, object *where) {
2852  object *otmp;
2853 
2854  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
2855  StringBuffer *sb;
2856  char *diff;
2857 
2858  sb = stringbuffer_new();
2859  object_dump(op, sb);
2860  diff = stringbuffer_finish(sb);
2861  LOG(llevError, "Trying to insert (ob) inserted object.\n%s\n", diff);
2862  free(diff);
2863  return op;
2864  }
2865 
2866  if (where == NULL) {
2867  StringBuffer *sb;
2868  char *diff;
2869 
2870  sb = stringbuffer_new();
2871  object_dump(op, sb);
2872  diff = stringbuffer_finish(sb);
2873  LOG(llevError, "Trying to put object in NULL.\n%s\n", diff);
2874  free(diff);
2875  return op;
2876  }
2877  if (where->head) {
2878  LOG(llevDebug, "Warning: Tried to insert object wrong part of multipart object.\n");
2879  }
2880  where = HEAD(where);
2881  if (op->more) {
2882  LOG(llevError, "Tried to insert multipart object %s (%u)\n", op->name, op->count);
2883  return op;
2884  }
2887  if (op->nrof || op->type == SKILL) {
2889  if (op->type == SKILL && tmp->type == SKILL && op->subtype == tmp->subtype) {
2890  // Duplicate skill. Sum exp and total_exp.
2891  LOG(llevDebug, "Merged duplicate skill %s for %s\n", op->arch->name, where->name);
2892  tmp->stats.exp += op->stats.exp;
2893  tmp->total_exp += op->total_exp;
2895  object_free(op, FREE_OBJ_FREE_INVENTORY | FREE_OBJ_NO_DESTROY_CALLBACK); /* free the inserted object */
2896  return tmp;
2897  } else if (object_can_merge(tmp, op)) {
2898  /* return the original object and remove inserted object
2899  * (client needs the original object) */
2900  object_increase_nrof(tmp, op->nrof);
2902  object_free(op, FREE_OBJ_FREE_INVENTORY | FREE_OBJ_NO_DESTROY_CALLBACK); /* free the inserted object */
2903  return tmp;
2904  }
2905  FOR_INV_FINISH();
2906 
2907  /* the item couldn't merge. */
2908  object_add_weight(where, op->weight*op->nrof);
2909  } else
2910  object_add_weight(where, op->weight+op->carrying);
2911 
2912  op->map = NULL;
2913  op->env = where;
2914  op->above = NULL;
2915  op->below = NULL;
2916  op->x = 0,
2917  op->y = 0;
2918  op->ox = 0,
2919  op->oy = 0;
2920 
2921  /* Client has no idea of ordering so lets not bother ordering it here.
2922  * It sure simplifies this function...
2923  */
2924  if (where->inv == NULL)
2925  where->inv = op;
2926  else {
2927  op->below = where->inv;
2928  op->below->above = op;
2929  where->inv = op;
2930  }
2931 
2932  if (op->type == EVENT_CONNECTOR) {
2933  where->event_bitmask |= BITMASK_EVENT(op->subtype);
2934  }
2935 
2936  /* Update in 2 cases: object goes into player's inventory, or object goes into container the player
2937  * is looking into. */
2938  if (where->contr != NULL)
2940  else if (where->type == CONTAINER && QUERY_FLAG(where, FLAG_APPLIED)) {
2941  object *pl = NULL;
2942 
2943  if (op->env->env && op->env->env->contr)
2944  /* Container is in player's inventory. */
2945  pl = op->env->env;
2946  else if (op->env->map) {
2947  /* Container on map, look above for player. */
2948  FOR_ABOVE_PREPARE(op->env, above)
2949  if (above->contr) {
2950  pl = above;
2951  break;
2952  }
2953  FOR_ABOVE_FINISH();
2954  }
2955  if (pl)
2956  esrv_send_item(pl, op);
2957  }
2958 
2960  if (otmp && otmp->contr != NULL) {
2961  if (!QUERY_FLAG(otmp, FLAG_NO_FIX_PLAYER)
2962  && (QUERY_FLAG(op, FLAG_APPLIED) || op->type == SKILL || op->glow_radius != 0))
2963  /* fix_object will only consider applied items, or skills, or items with a glow radius.
2964  thus no need to call it if our object hasn't that. */
2965  fix_object(otmp);
2966  }
2967 
2968  /* reset the light list and los of the players on the map */
2969  if (op->glow_radius != 0 && where->map) {
2970 #ifdef DEBUG_LIGHTS
2971  LOG(llevDebug, " object_insert_in_ob(): got %s to insert in map/op\n", op->name);
2972 #endif /* DEBUG_LIGHTS */
2973  if (MAP_DARKNESS(where->map)) {
2974  SET_MAP_FLAGS(where->map, where->x, where->y, P_NEED_UPDATE);
2975  update_position(where->map, where->x, where->y);
2976  update_all_los(where->map, where->x, where->y);
2977  }
2978  }
2979 
2980  return op;
2981 }
2982 
3005 int object_check_move_on(object *op, object *originator) {
3006  object *tmp;
3007  tag_t tag;
3008  mapstruct *m = op->map;
3009  int x = op->x, y = op->y;
3010  MoveType move_on, move_slow, move_block;
3011 
3012  if (QUERY_FLAG(op, FLAG_NO_APPLY))
3013  return 0;
3014 
3015  tag = op->count;
3016 
3017  move_on = GET_MAP_MOVE_ON(op->map, op->x, op->y);
3018  move_slow = GET_MAP_MOVE_SLOW(op->map, op->x, op->y);
3019  move_block = GET_MAP_MOVE_BLOCK(op->map, op->x, op->y);
3020 
3021  /* if nothing on this space will slow op down or be applied,
3022  * no need to do checking below. have to make sure move_type
3023  * is set, as lots of objects don't have it set - we treat that
3024  * as walking.
3025  */
3026  if (op->move_type
3027  && !(op->move_type&move_on)
3028  && !(op->move_type&move_slow))
3029  return 0;
3030 
3031  /* This is basically inverse logic of that below - basically,
3032  * if the object can avoid the move on or slow move, they do so,
3033  * but can't do it if the alternate movement they are using is
3034  * blocked. Logic on this seems confusing, but does seem correct.
3035  */
3036  if ((op->move_type&~move_on&~move_block) != 0
3037  && (op->move_type&~move_slow&~move_block) != 0)
3038  return 0;
3039 
3040  /* The objects have to be checked from top to bottom.
3041  * Hence, we first go to the top:
3042  */
3043 
3044  tmp = GET_MAP_OB(op->map, op->x, op->y);
3046  if (tmp->above == NULL)
3047  break;
3048  /* Trim the search when we find the first other spell effect
3049  * this helps performance so that if a space has 50 spell objects,
3050  * we don't need to check all of them.
3051  */
3052  if ((tmp->move_type&MOVE_FLY_LOW) && QUERY_FLAG(tmp, FLAG_NO_PICK))
3053  break;
3056  if (tmp == op)
3057  continue; /* Can't apply yourself */
3058 
3059  /* Check to see if one of the movement types should be slowed down.
3060  * Second check makes sure that the movement types not being slowed
3061  * (~slow_move) is not blocked on this space - just because the
3062  * space doesn't slow down swimming (for example), if you can't actually
3063  * swim on that space, can't use it to avoid the penalty.
3064  */
3065  if (!QUERY_FLAG(op, FLAG_WIZPASS)) {
3066  if ((!op->move_type && tmp->move_slow&MOVE_WALK)
3067  || ((op->move_type&tmp->move_slow) && (op->move_type&~tmp->move_slow&~tmp->move_block) == 0)) {
3068  float diff;
3069 
3070  diff = tmp->move_slow_penalty*FABS(op->speed);
3071  if (op->type == PLAYER) {
3074  diff /= 4.0;
3075  }
3076  }
3077  op->speed_left -= diff;
3078  }
3079  }
3080 
3081  /* Basically same logic as above, except now for actual apply. */
3082  if ((!op->move_type && tmp->move_on&MOVE_WALK)
3083  || ((op->move_type&tmp->move_on) && (op->move_type&~tmp->move_on&~tmp->move_block) == 0)) {
3084  ob_move_on(tmp, op, originator);
3085  if (object_was_destroyed(op, tag))
3086  return 1;
3087 
3088  /* what the person/creature stepped onto has moved the object
3089  * someplace new. Don't process any further - if we did,
3090  * have a feeling strange problems would result.
3091  */
3092  if (op->map != m || op->x != x || op->y != y)
3093  return 0;
3094  }
3096  return 0;
3097 }
3098 
3111 object *map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at) {
3112  if (m == NULL || OUT_OF_REAL_MAP(m, x, y)) {
3113  LOG(llevError, "Present_arch called outside map.\n");
3114  return NULL;
3115  }
3116 
3117  FOR_MAP_PREPARE(m, x, y, tmp)
3118  if (tmp->arch == at)
3119  return tmp;
3120  FOR_MAP_FINISH();
3121 
3122  return NULL;
3123 }
3124 
3138 object *map_find_by_type(mapstruct *m, int x, int y, uint8_t type) {
3139  if (OUT_OF_REAL_MAP(m, x, y)) {
3140  return NULL;
3141  }
3142 
3143  FOR_MAP_PREPARE(m, x, y, tmp)
3144  if (tmp->type == type)
3145  return tmp;
3146  FOR_MAP_FINISH();
3147 
3148  return NULL;
3149 }
3150 
3161 object *object_present_in_ob(uint8_t type, const object *op) {
3162  object *tmp;
3163 
3164  for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
3165  if (tmp->type == type)
3166  return tmp;
3167 
3168  return NULL;
3169 }
3170 
3196 object *object_present_in_ob_by_name(int type, const char *str, const object *op) {
3197  object *tmp;
3198 
3199  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
3200  if ((type == -1 || tmp->type == type) && !strcmp(str, tmp->name))
3201  return tmp;
3202  }
3203  return NULL;
3204 }
3205 
3215 object *arch_present_in_ob(const archetype *at, const object *op) {
3216  object *tmp;
3217 
3218  for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
3219  if (tmp->arch == at)
3220  return tmp;
3221  return NULL;
3222 }
3223 
3232 void object_set_flag_inv(object*op, int flag) {
3233  object *tmp;
3234 
3235  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
3236  SET_FLAG(tmp, flag);
3237  object_set_flag_inv(tmp, flag);
3238  }
3239 }
3240 
3249 void object_unset_flag_inv(object*op, int flag) {
3250  object *tmp;
3251 
3252  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
3253  CLEAR_FLAG(tmp, flag);
3254  object_unset_flag_inv(tmp, flag);
3255  }
3256 }
3257 
3267 void object_set_cheat(object *op) {
3270 }
3271 
3289 int object_find_multi_free_spot_around(const object *ob, const object *gen, int16_t *hx, int16_t *hy) {
3290  int genx, geny, genx2, geny2, sx, sy, sx2, sy2, ix, iy, nx, ny, i, flag;
3291  int freecount = 0;
3292 
3293  ob = HEAD(ob);
3294 
3295  object_get_multi_size(ob, &sx, &sy, &sx2, &sy2);
3296  object_get_multi_size(gen, &genx, &geny, &genx2, &geny2);
3297  /*
3298  * sx and sy are now the coords of the bottom right corner of ob relative to the head.
3299  * genx and geny are now the coords of the bottom right corner of gen relative to the head.
3300  * sx2 and sy2 are now the coords of the head of ob relative to the top left corner.
3301  * genx2 and geny2 are now the coords of the head of gen relative to the top left corner.
3302  */
3303 
3304  sx++;
3305  sy++;
3306  genx++;
3307  geny++;
3308  /*
3309  * sx, sy, genx, and geny, are now the size of the object, excluding parts left and above
3310  * the head.
3311  */
3312 
3313  ix = gen->x-sx-genx2;
3314  iy = gen->y-sy-geny2;
3315  sx += genx+sx2;
3316  sy += geny+sy2;
3317  /*
3318  * ix and iy are the map coords of the top left square where the head of ob could possibly
3319  * be placed. sx and sy are now the size of the square to search for placement of the head
3320  * relative to ix and iy.
3321  */
3322 
3323  /*
3324  * Loop around the square of possible positions for the head of ob object:
3325  */
3326  for (i = 0; i < (sx+sx+sy+sy); i++) {
3327  if (i <= sx) {
3328  nx = i+ix;
3329  ny = iy;
3330  } else if (i <= sx+sy) {
3331  nx = ix+sx;
3332  ny = iy+i-sx;
3333  } else if (i <= sx+sy+sx) {
3334  nx = ix+sx-(i-(sx+sy));
3335  ny = iy+sy;
3336  } else {
3337  nx = ix;
3338  ny = iy+sy-(i-(sx+sy+sx));
3339  }
3340  /* Check if the spot is free. */
3341  flag = ob_blocked(ob, gen->map, nx, ny);
3342  if (!flag) {
3343  freecount++;
3344  }
3345  }
3346  /* If no free spaces, return. */
3347  if (!freecount)
3348  return -1;
3349 
3350  /* Choose a random valid position */
3351  freecount = RANDOM()%freecount;
3352  for (i = 0; i < sx+sx+sy+sy; i++) {
3353  if (i <= sx) {
3354  nx = i+ix;
3355  ny = iy;
3356  } else if (i <= sx+sy) {
3357  nx = ix+sx;
3358  ny = iy+i-sx;
3359  } else if (i <= sx+sy+sx) {
3360  nx = ix+sx-(i-(sx+sy));
3361  ny = iy+sy;
3362  } else {
3363  nx = ix;
3364  ny = iy+sy-(i-(sx+sy+sx));
3365  }
3366 
3367  /* Make sure it's within map. */
3368  if (nx < 0 || nx >= MAP_WIDTH(gen->map)
3369  || ny < 0 || ny >= MAP_HEIGHT(gen->map))
3370  continue;
3371 
3372  /* Check if the spot is free.*/
3373  flag = ob_blocked(ob, gen->map, nx, ny);
3374  if (!flag) {
3375  freecount--;
3376  if (freecount <= 0) {
3377  *hx = nx;
3378  *hy = ny;
3379  return 0;
3380  }
3381  }
3382  }
3383  return -1;
3384 }
3385 
3405 int object_find_multi_free_spot_within_radius(const object *ob, const object *gen, int *hx, int *hy) {
3406  int genx, geny, genx2, geny2, sx, sy, sx2, sy2, ix, iy, nx, ny, i, flag;
3407  int8_t x, y, radius;
3408  int freecount = 0, freecountstop = 0;
3409  const char *value;
3410  int8_t *x_array;
3411  int8_t *y_array;
3412 
3413  /* If radius is not set, default to 1 */
3414  value = object_get_value(gen, "generator_radius");
3415  if (value) {
3416  radius = (int8_t)strtol(value, NULL, 10);
3417  if (radius < 1) {
3418  radius = 1;
3419  }
3420  } else {
3421  radius = 1;
3422  }
3423 
3424  ob = HEAD(ob);
3425 
3426  object_get_multi_size(ob, &sx, &sy, &sx2, &sy2);
3427  object_get_multi_size(gen, &genx, &geny, &genx2, &geny2);
3428  /*
3429  * sx and sy are now the coords of the bottom right corner
3430  * of ob relative to the head.
3431  * genx and geny are now the coords of the bottom right corner
3432  * of gen relative to the head.
3433  * sx2 and sy2 are now the coords of the head of ob relative
3434  * to the top left corner.
3435  * genx2 and geny2 are now the coords of the head of gen relative
3436  * to the top left corner.
3437  */
3438 
3439  sx++;
3440  sy++;
3441  genx++;
3442  geny++;
3443  /*
3444  * sx, sy, genx, and geny, are now the size of the object,
3445  * excluding parts left and above the head.
3446  */
3447 
3448  ix = gen->x-sx-genx2-radius+1;
3449  iy = gen->y-sy-geny2-radius+1;
3450  sx += genx+sx2+radius*2-1;
3451  sy += geny+sy2+radius*2-1;
3452 
3453  /*
3454  * ix and iy are the map coords of the top left square where
3455  * the head of ob could possibly be placed. sx and sy are now
3456  * the size of the square to search for placement of the head
3457  * relative to ix and iy.
3458  */
3459 
3460  /* Create arrays large enough to hold free space coordinates */
3461  x_array = static_cast<int8_t *>(malloc(sx*sy*sizeof(int8_t)));
3462  y_array = static_cast<int8_t *>(malloc(sx*sy*sizeof(int8_t)));
3463 
3464  /*
3465  * Loop through the area of possible positions for the head of ob object:
3466  */
3467  for (x = 0; x < sx; x++) {
3468  for (y = 0; y < sy; y++) {
3469  nx = ix+x;
3470  ny = iy+y;
3471 
3472 
3473  /* Make sure it's within map. */
3474  if (get_map_flags(gen->map, NULL, nx, ny, NULL, NULL)&P_OUT_OF_MAP) {
3475  continue;
3476  }
3477 
3478  /* Check if the spot is free. */
3479  flag = ob_blocked(ob, gen->map, nx, ny);
3480  if (!flag) {
3481  x_array[freecount] = nx;
3482  y_array[freecount] = ny;
3483  freecount++;
3484  }
3485  }
3486  }
3487  /* If no free spaces, return. */
3488  if (!freecount) {
3489  free(x_array);
3490  free(y_array);
3491  return -1;
3492  }
3493 
3494  /* Choose a random valid position */
3495  freecountstop = RANDOM()%freecount;
3496  for (i = 0; i < freecount; i++) {
3497  nx = x_array[i];
3498  ny = y_array[i];
3499 
3500  /* Check if the spot is free.*/
3501  flag = ob_blocked(ob, gen->map, nx, ny);
3502  if (!flag) {
3503  freecountstop--;
3504  if (freecountstop <= 0) {
3505  *hx = nx;
3506  *hy = ny;
3507  free(x_array);
3508  free(y_array);
3509  return 0;
3510  }
3511  }
3512  }
3513  free(x_array);
3514  free(y_array);
3515  return -1;
3516 }
3517 
3552 int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop) {
3553  int i, index = 0, flag;
3554  static int altern[SIZEOFFREE];
3555 
3556  for (i = start; i < stop; i++) {
3557  flag = ob_blocked(ob, m, x+freearr_x[i], y+freearr_y[i]);
3558  if (!flag)
3559  altern[index++] = i;
3560 
3561  /* Basically, if we find a wall on a space, we cut down the search size.
3562  * In this way, we won't return spaces that are on another side of a wall.
3563  * This mostly work, but it cuts down the search size in all directions -
3564  * if the space being examined only has a wall to the north and empty
3565  * spaces in all the other directions, this will reduce the search space
3566  * to only the spaces immediately surrounding the target area, and
3567  * won't look 2 spaces south of the target space.
3568  */
3569  else if ((flag&AB_NO_PASS) && maxfree[i] < stop)
3570  stop = maxfree[i];
3571  }
3572  if (!index)
3573  return -1;
3574  return altern[RANDOM()%index];
3575 }
3576 
3592 int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y) {
3593  int i;
3594 
3595  for (i = 0; i < SIZEOFFREE; i++) {
3596  if (!ob_blocked(ob, m, x+freearr_x[i], y+freearr_y[i]))
3597  return i;
3598  }
3599  return -1;
3600 }
3601 
3611 static void permute(int *arr, int begin, int end) {
3612  int i, j, tmp, len;
3613 
3614  len = end-begin;
3615  for (i = begin; i < end; i++) {
3616  j = begin+RANDOM()%len;
3617 
3618  tmp = arr[i];
3619  arr[i] = arr[j];
3620  arr[j] = tmp;
3621  }
3622 }
3623 
3635 void get_search_arr(int *search_arr) {
3636  int i;
3637 
3638  for (i = 0; i < SIZEOFFREE; i++) {
3639  search_arr[i] = i;
3640  }
3641 
3642  permute(search_arr, 1, SIZEOFFREE1+1);
3643  permute(search_arr, SIZEOFFREE1+1, SIZEOFFREE2+1);
3644  permute(search_arr, SIZEOFFREE2+1, SIZEOFFREE);
3645 }
3646 
3654 int object_distance(const object *ob1, const object *ob2) {
3655  int i;
3656 
3657  i = (ob1->x-ob2->x)*(ob1->x-ob2->x)+
3658  (ob1->y-ob2->y)*(ob1->y-ob2->y);
3659  return i;
3660 }
3661 
3670 int find_dir_2(int x, int y) {
3671  int q;
3672 
3673  if (!y)
3674  q = -300*x;
3675  else
3676  q = x*100/y;
3677  if (y > 0) {
3678  if (q < -242)
3679  return 3;
3680  if (q < -41)
3681  return 2;
3682  if (q < 41)
3683  return 1;
3684  if (q < 242)
3685  return 8;
3686  return 7;
3687  }
3688  if (q < -242)
3689  return 7;
3690  if (q < -41)
3691  return 6;
3692  if (q < 41)
3693  return 5;
3694  if (q < 242)
3695  return 4;
3696  return 3;
3697 }
3698 
3707 int absdir(int d) {
3708  // Shortcut for modulus that work becuase we have a power of 2
3709  d &= 7;
3710  // 0 needs to be 8
3711  if (!d)
3712  d = 8;
3713  return d;
3714 }
3715 
3725 int dirdiff(int dir1, int dir2) {
3726  int d;
3727 
3728  d = abs(dir1-dir2);
3729  if (d > 4)
3730  d = 8-d;
3731  return d;
3732 }
3733 
3745 static const int reduction_dir[SIZEOFFREE][3] = {
3746  { 0, 0, 0 }, /* 0 */
3747  { 0, 0, 0 }, /* 1 */
3748  { 0, 0, 0 }, /* 2 */
3749  { 0, 0, 0 }, /* 3 */
3750  { 0, 0, 0 }, /* 4 */
3751  { 0, 0, 0 }, /* 5 */
3752  { 0, 0, 0 }, /* 6 */
3753  { 0, 0, 0 }, /* 7 */
3754  { 0, 0, 0 }, /* 8 */
3755  { 8, 1, 2 }, /* 9 */
3756  { 1, 2, -1 }, /* 10 */
3757  { 2, 10, 12 }, /* 11 */
3758  { 2, 3, -1 }, /* 12 */
3759  { 2, 3, 4 }, /* 13 */
3760  { 3, 4, -1 }, /* 14 */
3761  { 4, 14, 16 }, /* 15 */
3762  { 5, 4, -1 }, /* 16 */
3763  { 4, 5, 6 }, /* 17 */
3764  { 6, 5, -1 }, /* 18 */
3765  { 6, 20, 18 }, /* 19 */
3766  { 7, 6, -1 }, /* 20 */
3767  { 6, 7, 8 }, /* 21 */
3768  { 7, 8, -1 }, /* 22 */
3769  { 8, 22, 24 }, /* 23 */
3770  { 8, 1, -1 }, /* 24 */
3771  { 24, 9, 10 }, /* 25 */
3772  { 9, 10, -1 }, /* 26 */
3773  { 10, 11, -1 }, /* 27 */
3774  { 27, 11, 29 }, /* 28 */
3775  { 11, 12, -1 }, /* 29 */
3776  { 12, 13, -1 }, /* 30 */
3777  { 12, 13, 14 }, /* 31 */
3778  { 13, 14, -1 }, /* 32 */
3779  { 14, 15, -1 }, /* 33 */
3780  { 33, 15, 35 }, /* 34 */
3781  { 16, 15, -1 }, /* 35 */
3782  { 17, 16, -1 }, /* 36 */
3783  { 18, 17, 16 }, /* 37 */
3784  { 18, 17, -1 }, /* 38 */
3785  { 18, 19, -1 }, /* 39 */
3786  { 41, 19, 39 }, /* 40 */
3787  { 19, 20, -1 }, /* 41 */
3788  { 20, 21, -1 }, /* 42 */
3789  { 20, 21, 22 }, /* 43 */
3790  { 21, 22, -1 }, /* 44 */
3791  { 23, 22, -1 }, /* 45 */
3792  { 45, 47, 23 }, /* 46 */
3793  { 23, 24, -1 }, /* 47 */
3794  { 24, 9, -1 } /* 48 */
3795 };
3796 
3815 int can_see_monsterP(mapstruct *m, int x, int y, int dir) {
3816  int16_t dx, dy;
3817  int mflags;
3818 
3819  if (dir < 0)
3820  return 0; /* exit condition: invalid direction */
3821 
3822  dx = x+freearr_x[dir];
3823  dy = y+freearr_y[dir];
3824 
3825  mflags = get_map_flags(m, &m, dx, dy, &dx, &dy);
3826 
3827  /* This functional arguably was incorrect before - it was
3828  * checking for P_WALL - that was basically seeing if
3829  * we could move to the monster - this is being more
3830  * literal on if we can see it. To know if we can actually
3831  * move to the monster, we'd need the monster passed in or
3832  * at least its move type.
3833  */
3834  if (mflags&(P_OUT_OF_MAP|P_BLOCKSVIEW))
3835  return 0;
3836 
3837  /* yes, can see. */
3838  if (dir < 9)
3839  return 1;
3840  return can_see_monsterP(m, x, y, reduction_dir[dir][0])|
3841  can_see_monsterP(m, x, y, reduction_dir[dir][1])|
3842  can_see_monsterP(m, x, y, reduction_dir[dir][2]);
3843 }
3844 
3860 int object_can_pick(const object *who, const object *item) {
3861  /* I re-wrote this as a series of if statements
3862  * instead of a nested return (foo & bar && yaz)
3863  * - I think this is much more readable,
3864  * and likely compiler effectively optimizes it the
3865  * same.
3866  */
3867  if (item->weight <= 0)
3868  return 0;
3870  return 0;
3871  if (QUERY_FLAG(item, FLAG_ALIVE))
3872  return 0;
3873  if (item->invisible)
3874  return 0;
3875  if (item->type == TRANSPORT && item->contr != NULL) {
3876  return 0;
3877  }
3878 
3879  /* Weight limit for monsters */
3880  if (who->type != PLAYER && ((uint32_t)(who->weight+who->carrying+item->weight)) > get_weight_limit(who->stats.Str))
3881  return 0;
3882 
3883  /* Can not pick up multipart objects */
3884  if (item->head || item->more)
3885  return 0;
3886 
3887  /* Everything passes, so OK to pick up */
3888  return 1;
3889 }
3890 
3902 object *object_create_clone(object *asrc) {
3903  object *dst = NULL, *tmp, *src, *part, *prev;
3904 
3905  if (!asrc)
3906  return NULL;
3907  src = HEAD(asrc);
3908 
3909  prev = NULL;
3910  for (part = src; part; part = part->more) {
3911  tmp = object_new();
3912  object_copy(part, tmp);
3913  /*
3914  * Need to reset the weight, since object_insert_in_ob() later will
3915  * recompute this field.
3916  */
3917  tmp->carrying = tmp->arch->clone.carrying;
3918  tmp->x -= src->x;
3919  tmp->y -= src->y;
3920  if (!part->head) {
3921  dst = tmp;
3922  tmp->head = NULL;
3923  } else {
3924  tmp->head = dst;
3925  }
3926  tmp->more = NULL;
3927  if (prev)
3928  prev->more = tmp;
3929  prev = tmp;
3930  }
3931  /*** copy inventory ***/
3932  FOR_INV_PREPARE(src, item)
3934  FOR_INV_FINISH();
3935 
3936  return dst;
3937 }
3938 
3949 object *object_find_by_name(const object *who, const char *name) {
3950  const char *name_shared = add_string(name);
3951  object *tmp;
3952 
3953  for (tmp = who->inv; tmp; tmp = tmp->below)
3954  if (tmp->name == name_shared)
3955  break;
3956  free_string(name_shared);
3957  return tmp;
3958 }
3959 
3973 object *object_find_by_type(const object *who, int type) {
3974  object *tmp;
3975 
3976  for (tmp = who->inv; tmp; tmp = tmp->below)
3977  if (tmp->type == type)
3978  return tmp;
3979 
3980  return NULL;
3981 }
3982 
3997 object *object_find_by_type_without_flags(const object *who, int type, int *flags, int num_flags) {
3998  int flag_okay;
3999  for (object *tmp = who->inv; tmp; tmp = tmp->below)
4000  if (tmp->type == type) {
4001  flag_okay = 1;
4002  for (int i = 0; i < num_flags; ++i) {
4003  if (QUERY_FLAG(tmp, flags[i])) {
4004  flag_okay = 0; // A flag we didn't want set was set. Skip this item.
4005  break;
4006  }
4007  }
4008  if (flag_okay) // If flag_okay == 1, then the flags specified were not set
4009  return tmp; // If we reach here, none of the flags specified were set. Just like we wanted.
4010  }
4011 
4012  return NULL;
4013 }
4014 
4030 object *object_find_by_type2(const object *who, int type1, int type2) {
4031  object *tmp;
4032 
4033  for (tmp = who->inv; tmp; tmp = tmp->below)
4034  if (tmp->type == type1 || tmp->type == type2)
4035  return tmp;
4036 
4037  return NULL;
4038 }
4039 
4053 object *object_find_by_tag(const object *who, tag_t tag) {
4054  object *tmp;
4055 
4056  for (tmp = who->inv; tmp; tmp = tmp->below)
4057  if (tmp->count == tag)
4058  return tmp;
4059 
4060  return NULL;
4061 }
4062 
4076 object *object_find_by_type_applied(const object *who, int type) {
4077  object *tmp;
4078 
4079  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4080  if (tmp->type == type && QUERY_FLAG(tmp, FLAG_APPLIED))
4081  return tmp;
4082 
4083  return NULL;
4084 }
4085 
4101 object *object_find_by_type_and_name(const object *who, int type, const char *name) {
4102  object *tmp;
4103 
4104  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4105  if (tmp->type == type && strcmp(tmp->name, name) == 0)
4106  return tmp;
4107 
4108  return NULL;
4109 }
4110 
4126 object *object_find_by_type_and_race(const object *who, int type, const char *race) {
4127  object *tmp;
4128 
4129  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4130  if (tmp->type == type && strcmp(tmp->race, race) == 0)
4131  return tmp;
4132 
4133  return NULL;
4134 }
4135 
4151 object *object_find_by_type_and_slaying(const object *who, int type, const char *slaying) {
4152  object *tmp;
4153 
4154  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4155  if (tmp->type == type && tmp->slaying != NULL && strcmp(tmp->slaying, slaying) == 0)
4156  return tmp;
4157 
4158  return NULL;
4159 }
4160 
4176 object *object_find_by_type_and_skill(const object *who, int type, const char *skill) {
4177  object *tmp;
4178 
4179  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4180  if (tmp->type == type && tmp->skill != NULL && strcmp(tmp->skill, skill) == 0)
4181  return tmp;
4182 
4183  return NULL;
4184 }
4185 
4199 object *object_find_by_flag(const object *who, int flag) {
4200  object *tmp;
4201 
4202  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4203  if (QUERY_FLAG(tmp, flag))
4204  return tmp;
4205 
4206  return NULL;
4207 }
4208 
4222 object *object_find_by_flag_applied(const object *who, int flag) {
4223  object *tmp;
4224 
4225  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4226  if (QUERY_FLAG(tmp, FLAG_APPLIED) && QUERY_FLAG(tmp, flag))
4227  return tmp;
4228 
4229  return NULL;
4230 }
4231 
4245 object *object_find_by_arch_name(const object *who, const char *name) {
4246  object *tmp;
4247 
4248  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4249  if (strcmp(tmp->arch->name, name) == 0)
4250  return tmp;
4251 
4252  return NULL;
4253 }
4254 
4270 object *object_find_by_type_and_arch_name(const object *who, int type, const char *name) {
4271  object *tmp;
4272 
4273  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4274  if (tmp->type == type && strcmp(tmp->arch->name, name) == 0)
4275  return tmp;
4276 
4277  return NULL;
4278 }
4279 
4294 object *object_find_by_type_subtype(const object *who, int type, int subtype) {
4295  object *tmp;
4296 
4297  for (tmp = who->inv; tmp; tmp = tmp->below)
4298  if (tmp->type == type && tmp->subtype == subtype)
4299  return tmp;
4300 
4301  return NULL;
4302 }
4303 
4314 key_value *object_get_key_value(const object *ob, const char *key) {
4315  key_value *link;
4316 
4317  for (link = ob->key_values; link != NULL; link = link->next) {
4318  if (link->key == key) {
4319  return link;
4320  }
4321  }
4322 
4323  return NULL;
4324 }
4325 
4339 const char *object_get_value(const object *op, const char *const key) {
4340  key_value *link;
4341  const char *canonical_key;
4342 
4343  canonical_key = find_string(key);
4344 
4345  if (canonical_key == NULL) {
4346  /* 1. There being a field named key on any object
4347  * implies there'd be a shared string to find.
4348  * 2. Since there isn't, no object has this field.
4349  * 3. Therefore, *this *object doesn't have this field.
4350  */
4351  return NULL;
4352  }
4353 
4354  /* This is copied from object_get_key_value() above -
4355  * only 4 lines, and saves the function call overhead.
4356  */
4357  for (link = op->key_values; link != NULL; link = link->next) {
4358  if (link->key == canonical_key) {
4359  return link->value;
4360  }
4361  }
4362  return NULL;
4363 }
4364 
4369 bool object_value_set(const object *op, const char *const key) {
4370  const char *ret = object_get_value(op, key);
4371  if (ret == NULL || (strcmp(ret, "") == 0) || (strcmp(ret, "0") == 0)) {
4372  return false;
4373  }
4374  return true;
4375 }
4376 
4383 bool object_value_set_shared(const object *op, sstring key) {
4384  for (key_value *link = op->key_values; link != NULL; link = link->next) {
4385  if (link->key == key) {
4386  if ((strcmp(link->value, "") == 0) || (strcmp(link->value, "0") == 0)) {
4387  return false;
4388  }
4389  return true;
4390  }
4391  }
4392  return false;
4393 }
4394 
4409 static int object_set_value_s(object *op, const char *canonical_key, const char *value, int add_key) {
4410  key_value *field = NULL, *last = NULL;
4411 
4412  for (field = op->key_values; field != NULL; field = field->next) {
4413  if (field->key != canonical_key) {
4414  last = field;
4415  continue;
4416  }
4417 
4418  if (field->value)
4419  FREE_AND_CLEAR_STR(field->value);
4420  if (value)
4421  field->value = add_string(value);
4422  else {
4423  /* Basically, if the archetype has this key set,
4424  * we need to store the null value so when we save
4425  * it, we save the empty value so that when we load,
4426  * we get this value back again.
4427  */
4428  if (object_get_key_value(&op->arch->clone, canonical_key))
4429  field->value = NULL;
4430  else {
4431  /* Delete this link */
4432  if (field->key)
4433  FREE_AND_CLEAR_STR(field->key);
4434  if (field->value)
4435  FREE_AND_CLEAR_STR(field->value);
4436  if (last)
4437  last->next = field->next;
4438  else
4439  op->key_values = field->next;
4440  free(field);
4441  }
4442  }
4443  return TRUE;
4444  }
4445  /* IF we get here, key doesn't exist */
4446 
4447  /* No field, we'll have to add it. */
4448 
4449  if (!add_key) {
4450  return FALSE;
4451  }
4452  /* There isn't any good reason to store a null
4453  * value in the key/value list. If the archetype has
4454  * this key, then we should also have it, so shouldn't
4455  * be here. If user wants to store empty strings,
4456  * should pass in ""
4457  */
4458  if (value == NULL)
4459  return TRUE;
4460 
4461  field = static_cast<key_value *>(malloc(sizeof(key_value)));
4462 
4463  field->key = add_refcount(canonical_key);
4464  field->value = add_string(value);
4465  /* Usual prepend-addition. */
4466  field->next = op->key_values;
4467  op->key_values = field;
4468 
4469  return TRUE;
4470 }
4471 
4492 int object_set_value(object *op, const char *key, const char *value, int add_key) {
4493  const char *canonical_key = NULL;
4494  int floating_ref = FALSE;
4495  int ret;
4496 
4497  /* HACK This mess is to make sure set_ob_value() passes a shared string
4498  * to object_get_key_value(), without leaving a leaked refcount.
4499  */
4500 
4501  canonical_key = find_string(key);
4502  if (canonical_key == NULL) {
4503  canonical_key = add_string(key);
4504  floating_ref = TRUE;
4505  }
4506 
4507  ret = object_set_value_s(op, canonical_key, value, add_key);
4508 
4509  if (floating_ref) {
4510  free_string(canonical_key);
4511  }
4512 
4513  return ret;
4514 }
4515 
4567 int object_matches_string(object *pl, object *op, const char *name) {
4568  char *cp, local_name[MAX_BUF], name_op[MAX_BUF], name_short[HUGE_BUF], bname_s[MAX_BUF], bname_p[MAX_BUF];
4569  int count, retval = 0;
4570  /* strtok is destructive to name */
4571  safe_strncpy(local_name, name, sizeof(local_name));
4572  sstring custom_name = object_get_value(op, CUSTOM_NAME_FIELD);
4573 
4574  for (cp = strtok(local_name, ","); cp; cp = strtok(NULL, ",")) {
4575  while (cp[0] == ' ')
4576  ++cp; /* get rid of spaces */
4577 
4578  /* LOG(llevDebug, "Trying to match %s\n", cp);*/
4579  /* All is a very generic match - low match value */
4580  if (!strcmp(cp, "all"))
4581  return 1;
4582 
4583  /* unpaid is a little more specific */
4584  if (!strcmp(cp, "unpaid") && QUERY_FLAG(op, FLAG_UNPAID))
4585  return 2;
4586  if (!strcmp(cp, "cursed")
4589  return 2;
4590 
4591  if (!strcmp(cp, "unlocked") && !QUERY_FLAG(op, FLAG_INV_LOCKED))
4592  return 2;
4593 
4594  /* Allow for things like '100 arrows' */
4595  count = atoi(cp);
4596  if (*cp == '+' || *cp == '-')
4597  count=0; // Let +/- searches look in description for magic bonuses
4598  if (count != 0) {
4599  cp = strchr(cp, ' ');
4600  while (cp && cp[0] == ' ')
4601  ++cp; /* get rid of spaces */
4602  } else {
4603  if (pl->type == PLAYER)
4604  count = pl->contr->count;
4605  else
4606  count = 0;
4607  }
4608 
4609  if (!cp || cp[0] == '\0' || count < 0)
4610  continue;
4611 
4612  /* The code here should go from highest retval to lowest. That
4613  * is because of the 'else' handling - we don't want to match on
4614  * something and set a low retval, even though it may match a higher retcal
4615  * later. So keep it in descending order here, so we try for the best
4616  * match first, and work downward.
4617  */
4618  query_name(op, name_op, MAX_BUF);
4619  query_short_name(op, name_short, HUGE_BUF);
4620  query_base_name(op, 0, bname_s, MAX_BUF);
4621  query_base_name(op, 1, bname_p, MAX_BUF);
4622 
4623  if (!strcasecmp(cp, name_op))
4624  retval = 20;
4625  else if (!strcasecmp(cp, name_short))
4626  retval = 18;
4627  else if (!strcasecmp(cp, bname_s))
4628  retval = 16;
4629  else if (!strcasecmp(cp, bname_p))
4630  retval = 16;
4631  else if (custom_name && !strcasecmp(cp, custom_name))
4632  retval = 15;
4633  else if (!strncasecmp(cp, bname_s, strlen(cp)))
4634  retval = 14;
4635  else if (!strncasecmp(cp, bname_p, strlen(cp)))
4636  retval = 14;
4637  /* Do substring checks, so things like 'Str+1' will match.
4638  * retval of these should perhaps be lower - they are lower
4639  * then the specific strcasecmp aboves, but still higher than
4640  * some other match criteria.
4641  */
4642  else if (strstr(bname_p, cp))
4643  retval = 12;
4644  else if (strstr(bname_s, cp))
4645  retval = 12;
4646  else if (strstr(name_short, cp))
4647  retval = 12;
4648  /* Check against plural/non plural based on count. */
4649  else if (count > 1 && !strcasecmp(cp, op->name_pl)) {
4650  retval = 6;
4651  } else if (count == 1 && !strcasecmp(op->name, cp)) {
4652  retval = 6;
4653  }
4654  /* base name matched - not bad */
4655  else if (strcasecmp(cp, op->name) == 0 && !count)
4656  retval = 4;
4657  /* Check for partial custom name, but give a real low priority */
4658  else if (custom_name && strstr(custom_name, cp))
4659  retval = 3;
4660 
4661  if (retval) {
4662  if (pl->type == PLAYER)
4663  pl->contr->count = count;
4664  return retval;
4665  }
4666  }
4667  return 0;
4668 }
4669 
4678 void object_fix_multipart(object *tmp) {
4679  archetype *at;
4680  object *op, *last;
4681 
4682  if (!tmp->map) {
4683  LOG(llevError, "object_fix_multipart: not on a map!\n");
4684  return;
4685  }
4686 
4687  /* already multipart - don't do anything more */
4688  if (tmp->head || tmp->more)
4689  return;
4690 
4691  /* If there is nothing more to this object, this for loop
4692  * won't do anything.
4693  */
4694  for (at = tmp->arch->more, last = tmp; at != NULL; at = at->more, last = op) {
4695  op = arch_to_object(at);
4696 
4697  /* update x,y coordinates */
4698  op->x += tmp->x;
4699  op->y += tmp->y;
4700  op->head = tmp;
4701  op->map = tmp->map;
4702  last->more = op;
4703  if (tmp->name != op->name) {
4704  if (op->name)
4705  free_string(op->name);
4706  op->name = add_string(tmp->name);
4707  }
4708  if (tmp->title != op->title) {
4709  if (op->title)
4710  free_string(op->title);
4711  op->title = add_string(tmp->title);
4712  }
4713  /* we could link all the parts onto tmp, and then just
4714  * call object_insert_in_map once, but the effect is the same,
4715  * as object_insert_in_map will call itself with each part, and
4716  * the coding is simpler to just to it here with each part.
4717  */
4719  } /* for at = tmp->arch->more */
4720 }
4721 
4737 void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy) {
4738  archetype *part;
4739  int maxx = 0, maxy = 0, minx = 0, miny = 0;
4740 
4741  ob = HEAD(ob);
4742  *sx = 1;
4743  *sy = 1;
4744  if (ob->arch->more) {
4745  for (part = ob->arch; part; part = part->more) {
4746  if (part->clone.x > maxx)
4747  maxx = part->clone.x;
4748  if (part->clone.y > maxy)
4749  maxy = part->clone.y;
4750  if (part->clone.x < minx)
4751  minx = part->clone.x;
4752  if (part->clone.y < miny)
4753  miny = part->clone.y;
4754  }
4755  }
4756  *sx = maxx;
4757  *sy = maxy;
4758  if (hx)
4759  *hx = -minx;
4760  if (hy)
4761  *hy = -miny;
4762 }
4763 
4784 void object_insert_to_free_spot_or_free(object *op, mapstruct *map, int x, int y, int start, int stop, object *originator) {
4785  int pos;
4786 
4787  pos = object_find_free_spot(op, map, x, y, start, stop);
4788  if (pos == -1) {
4790  return;
4791  }
4792 
4793  object_insert_in_map_at(op, map, originator, 0, x+freearr_x[pos], y+freearr_y[pos]);
4794 }
4795 
4804 void object_set_msg(object *op, const char *msg) {
4805  if (op->msg != NULL) {
4806  free_string(op->msg);
4807  }
4808 
4809  if (msg != NULL) {
4810  // If the message does not have a trailing newline, add one.
4811  if (*msg != '\0' && strchr(msg, '\0')[-1] != '\n') {
4814  stringbuffer_append_string(sb, "\n");
4815  op->msg = stringbuffer_finish_shared(sb);
4816  } else {
4817  op->msg = add_string(msg);
4818  }
4819  } else {
4820  op->msg = NULL;
4821  }
4822 }
4823 
4825 const char *const move_name[] = {
4826  "walk",
4827  "fly_low",
4828  "fly_high",
4829  "swim",
4830  "boat",
4831  NULL
4832 };
4833 
4834 /* This array equates the FLAG_ values with the V_ values. Use -1 to
4835  * put gaps in the array that should not be processed.
4836  * The order matches the order of the define values in 'define.h'.
4837  */
4844 static const char *const flag_names[NUM_FLAGS+1] = {
4845  "alive", "wiz", NULL, NULL, "was_wiz", "applied", "unpaid",
4846  "can_use_shield", "no_pick", "client_anim_sync", "client_anim_random", /* 10 */
4847  "is_animated", NULL /* FLAG_DIALOG_PARSED, not saved */,
4848  NULL /* flying */, "monster", "friendly", "generator",
4849  "is_thrown", "auto_apply", "treasure", "player sold", /* 20 */
4850  "see_invisible", "can_roll", "overlay_floor",
4851  "is_turnable", NULL /* walk_off */, NULL /* fly_on */,
4852  NULL /*fly_off*/, "is_used_up", "identified", "reflecting", /* 30 */
4853  "changing", "splitting", "hitback", "startequip",
4854  "blocksview", "undead", "scared", "unaggressive",
4855  "reflect_missile", "reflect_spell", /* 40 */
4856  "no_magic", "no_fix_player", "is_lightable", "tear_down",
4857  "run_away", NULL /*pass_thru */, NULL /*can_pass_thru*/,
4858  NULL /*"pick_up"*/, "unique", "no_drop", /* 50 */
4859  NULL /* wizcast*/, "can_cast_spell", "can_use_scroll", "can_use_range",
4860  "can_use_bow", "can_use_armour", "can_use_weapon",
4861  "can_use_ring", "has_ready_range", "has_ready_bow", /* 60 */
4862  "xrays", NULL, "is_floor", "lifesave", "no_strength", "sleep",
4863  "stand_still", "random_movement", "only_attack", "confused", /* 70 */
4864  "stealth", NULL, NULL, "cursed", "damned",
4865  "see_anywhere", "known_magical", "known_cursed",
4866  "can_use_skill", "been_applied", /* 80 */
4867  "has_ready_scroll", NULL, NULL,
4868  NULL, "make_invisible", "inv_locked", "is_wooded",
4869  "is_hilly", "has_ready_skill", "has_ready_weapon", /* 90 */
4870  "no_skill_ident", "is_blind", "can_see_in_dark", "is_cauldron",
4871  NULL, "no_steal", "one_hit", NULL, "berserk", "neutral", /* 100 */
4872  "no_attack", "no_damage", NULL, NULL, "activate_on_push",
4873  "activate_on_release", "is_water", "use_content_on_gen", NULL, "is_buildable", /* 110 */
4874  NULL, "blessed", "known_blessed"
4875 };
4876 
4886 {
4887  static char retbuf[MAX_BUF], retbuf_all[MAX_BUF];
4888  int i, all_count = 0, count;
4889 
4890  strcpy(retbuf, "");
4891  strcpy(retbuf_all, " all");
4892 
4893  /* Quick check, and probably fairly common */
4894  if (mt == MOVE_ALL) {
4895  stringbuffer_append_string(sb, "all");
4896  return;
4897  }
4898  if (mt == 0) {
4899  stringbuffer_append_string(sb, "0");
4900  return;
4901  }
4902 
4903  /* We basically slide the bits down. Why look at MOVE_ALL?
4904  * because we may want to return a string like 'all -swim',
4905  * and if we just looked at mt, we couldn't get that.
4906  */
4907  for (i = MOVE_ALL, count = 0; i != 0; i >>= 1, count++) {
4908  if (mt&(1<<count)) {
4909  strcat(retbuf, " ");
4910  strcat(retbuf, move_name[count]);
4911  } else {
4912  strcat(retbuf_all, " -");
4913  strcat(retbuf_all, move_name[count]);
4914  all_count++;
4915  }
4916  }
4917  /* Basically, if there is a single negation, return it, eg
4918  * 'all -swim'. But more than that, just return the
4919  * enumerated values. It doesn't make sense to return
4920  * 'all -walk -fly_low' - it is shorter to return 'fly_high swim'
4921  */
4922  if (all_count <= 1)
4923  stringbuffer_append_string(sb, retbuf_all+1);
4924  else
4925  stringbuffer_append_string(sb, retbuf+1);
4926 }
4927 
4929 static inline void ADD_STRINGLINE_ENTRY(StringBuffer *sb, const char *name, const char *value) {
4932  stringbuffer_append_string(sb, "\n");
4933 }
4934 
4936 static inline void FAST_SAVE_LONG(StringBuffer *sb, const char *name, const long value) {
4939  stringbuffer_append_char(sb, '\n');
4940 }
4941 
4943 static inline void FAST_SAVE_DOUBLE(StringBuffer *sb, const char *name, const double value) {
4944  stringbuffer_append_printf(sb, "%s%f\n", name, value);
4945 }
4946 
4954  for (int i = 0; i < 4; i++) {
4955  int idx = ffs((*diff)[i]);
4956  if (idx != 0) {
4957  int bit = idx - 1;
4958  // Clear difference bit.
4959  (*diff)[i] &= ~(1 << bit);
4960  return 32*i + bit;
4961  }
4962  }
4963  return -1;
4964 }
4965 
4979 void get_ob_diff(StringBuffer *sb, const object *op, const object *op2) {
4980  static char buf2[64];
4981  int tmp;
4982  int i;
4983  key_value *my_field;
4984  key_value *arch_field;
4985 
4986  /* This saves the key/value lists. We do it first so that any
4987  * keys that match field names will be overwritten by the loader.
4988  */
4989  for (my_field = op->key_values; my_field != NULL; my_field = my_field->next) {
4990  /* Find the field in the opposing member. */
4991  arch_field = object_get_key_value(op2, my_field->key);
4992 
4993  /* If there's no partnering field, or it's got a different value, save our field. */
4994  if (arch_field == NULL || my_field->value != arch_field->value) {
4995  stringbuffer_append_string(sb, my_field->key);
4996  stringbuffer_append_string(sb, " ");
4997  /* If this is null, then saving it as a space should
4998  * cause it to be null again.
4999  */
5000  if (my_field->value)
5001  stringbuffer_append_string(sb, my_field->value);
5002  stringbuffer_append_string(sb, "\n");
5003  }
5004  }
5005  /* We don't need to worry about the arch's extra fields - they
5006  * will get taken care of the object_copy() function.
5007  */
5008 
5009  if (op->name && op->name != op2->name) {
5010  ADD_STRINGLINE_ENTRY(sb, "name ", op->name);
5011  }
5012  if (op->name_pl && op->name_pl != op2->name_pl) {
5013  ADD_STRINGLINE_ENTRY(sb, "name_pl ", op->name_pl);
5014  }
5015  if (op->anim_suffix && op->anim_suffix != op2->anim_suffix) {
5016  ADD_STRINGLINE_ENTRY(sb, "anim_suffix ", op->anim_suffix);
5017  }
5018  if (op->title && op->title != op2->title) {
5019  ADD_STRINGLINE_ENTRY(sb, "title ", op->title);
5020  }
5021  if (op->race && op->race != op2->race) {
5022  ADD_STRINGLINE_ENTRY(sb, "race ", op->race);
5023  }
5024  if (op->slaying && op->slaying != op2->slaying) {
5025  ADD_STRINGLINE_ENTRY(sb, "slaying ", op->slaying);
5026  }
5027  if (op->skill && op->skill != op2->skill) {
5028  ADD_STRINGLINE_ENTRY(sb, "skill ", op->skill);
5029  }
5030  if (op->msg && op->msg != op2->msg) {
5031  stringbuffer_append_string(sb, "msg\n");
5032  stringbuffer_append_string(sb, op->msg);
5033  stringbuffer_append_string(sb, "endmsg\n");
5034  }
5035  if (op->lore && op->lore != op2->lore) {
5036  stringbuffer_append_string(sb, "lore\n");
5037  stringbuffer_append_string(sb, op->lore);
5038  stringbuffer_append_string(sb, "endlore\n");
5039  }
5040  if (op->other_arch != op2->other_arch && op->other_arch != NULL && op->other_arch->name) {
5041  ADD_STRINGLINE_ENTRY(sb, "other_arch ", op->other_arch->name);
5042  }
5043  if (op->face != op2->face) {
5044  ADD_STRINGLINE_ENTRY(sb, "face ", op->face->name);
5045  }
5046 
5047  if (op->animation != op2->animation) {
5048  if (op->animation) {
5049  ADD_STRINGLINE_ENTRY(sb, "animation ", op->animation->name);
5050  if (!QUERY_FLAG (op, FLAG_ANIMATE)) {
5051  stringbuffer_append_string(sb, "is_animated 0\n");
5052  }
5053  } else {
5054  stringbuffer_append_string(sb, "animation NONE\n");
5055  }
5056  }
5057  if (op->stats.Str != op2->stats.Str)
5058  FAST_SAVE_LONG(sb, "Str ", op->stats.Str);
5059  if (op->stats.Dex != op2->stats.Dex)
5060  FAST_SAVE_LONG(sb, "Dex ", op->stats.Dex);
5061  if (op->stats.Con != op2->stats.Con)
5062  FAST_SAVE_LONG(sb, "Con ", op->stats.Con);
5063  if (op->stats.Wis != op2->stats.Wis)
5064  FAST_SAVE_LONG(sb, "Wis ", op->stats.Wis);
5065  if (op->stats.Pow != op2->stats.Pow)
5066  FAST_SAVE_LONG(sb, "Pow ", op->stats.Pow);
5067  if (op->stats.Cha != op2->stats.Cha)
5068  FAST_SAVE_LONG(sb, "Cha ", op->stats.Cha);
5069  if (op->stats.Int != op2->stats.Int)
5070  FAST_SAVE_LONG(sb, "Int ", op->stats.Int);
5071  if (op->stats.hp != op2->stats.hp)
5072  FAST_SAVE_LONG(sb, "hp ", op->stats.hp);
5073  if (op->stats.maxhp != op2->stats.maxhp)
5074  FAST_SAVE_LONG(sb, "maxhp ", op->stats.maxhp);
5075  if (op->stats.sp != op2->stats.sp)
5076  FAST_SAVE_LONG(sb, "sp ", op->stats.sp);
5077  if (op->stats.maxsp != op2->stats.maxsp)
5078  FAST_SAVE_LONG(sb, "maxsp ", op->stats.maxsp);
5079  if (op->stats.grace != op2->stats.grace)
5080  FAST_SAVE_LONG(sb, "grace ", op->stats.grace);
5081  if (op->stats.maxgrace != op2->stats.maxgrace)
5082  FAST_SAVE_LONG(sb, "maxgrace ", op->stats.maxgrace);
5083 
5084  if (op->stats.exp != op2->stats.exp) {
5085  snprintf(buf2, sizeof(buf2), "%" FMT64, op->stats.exp);
5086  ADD_STRINGLINE_ENTRY(sb, "exp ", buf2);
5087  }
5088 
5089  if (op->total_exp != op2->total_exp) {
5090  snprintf(buf2, sizeof(buf2), "%" FMT64, op->total_exp);
5091  ADD_STRINGLINE_ENTRY(sb, "total_exp ", buf2);
5092  }
5093 
5094  if (op->expmul != op2->expmul)
5095  FAST_SAVE_DOUBLE(sb, "expmul ", op->expmul);
5096  if (op->stats.food != op2->stats.food)
5097  FAST_SAVE_LONG(sb, "food ", op->stats.food);
5098  if (op->stats.dam != op2->stats.dam)
5099  FAST_SAVE_LONG(sb, "dam ", op->stats.dam);
5100  if (op->stats.luck != op2->stats.luck)
5101  FAST_SAVE_LONG(sb, "luck ", op->stats.luck);
5102  if (op->stats.wc != op2->stats.wc)
5103  FAST_SAVE_LONG(sb, "wc ", op->stats.wc);
5104  if (op->stats.ac != op2->stats.ac)
5105  FAST_SAVE_LONG(sb, "ac ", op->stats.ac);
5106  if (op->x != op2->x)
5107  FAST_SAVE_LONG(sb, "x ", op->x);
5108  if (op->y != op2->y)
5109  FAST_SAVE_LONG(sb, "y ", op->y);
5110  if (op->speed != op2->speed) {
5111  FAST_SAVE_DOUBLE(sb, "speed ", op->speed);
5112  }
5113  if (op->speed > 0 && op->speed_left != op2->speed_left) {
5114  FAST_SAVE_DOUBLE(sb, "speed_left ", op->speed_left);
5115  }
5116  if (op->weapon_speed != op2->weapon_speed) {
5117  FAST_SAVE_DOUBLE(sb, "weapon_speed ", op->weapon_speed);
5118  }
5119  if (op->weapon_speed > 0 && op->weapon_speed_left != op2->weapon_speed_left) {
5120  FAST_SAVE_DOUBLE(sb, "weapon_speed_left ", op->weapon_speed_left);
5121  }
5122  if (op->move_status != op2->move_status)
5123  FAST_SAVE_LONG(sb, "move_state ", op->move_status);
5124  if (op->attack_movement != op2->attack_movement)
5125  FAST_SAVE_LONG(sb, "attack_movement ", op->attack_movement);
5126  if (op->nrof != op2->nrof)
5127  FAST_SAVE_LONG(sb, "nrof ", op->nrof);
5128  if (op->level != op2->level)
5129  FAST_SAVE_LONG(sb, "level ", op->level);
5130  if (op->direction != op2->direction)
5131  FAST_SAVE_LONG(sb, "direction ", op->direction);
5132  if (op->type != op2->type)
5133  FAST_SAVE_LONG(sb, "type ", op->type);
5134  if (op->subtype != op2->subtype)
5135  FAST_SAVE_LONG(sb, "subtype ", op->subtype);
5136  if (op->attacktype != op2->attacktype)
5137  FAST_SAVE_LONG(sb, "attacktype ", op->attacktype);
5138 
5139  for (tmp = 0; tmp < NROFATTACKS; tmp++) {
5140  if (op->resist[tmp] != op2->resist[tmp]) {
5141  stringbuffer_append_string(sb, "resist_");
5142  FAST_SAVE_LONG(sb, resist_save[tmp], op->resist[tmp]);
5143  }
5144  }
5145 
5146  if (op->path_attuned != op2->path_attuned)
5147  FAST_SAVE_LONG(sb, "path_attuned ", op->path_attuned);
5148  if (op->path_repelled != op2->path_repelled)
5149  FAST_SAVE_LONG(sb, "path_repelled ", op->path_repelled);
5150  if (op->path_denied != op2->path_denied)
5151  FAST_SAVE_LONG(sb, "path_denied ", op->path_denied);
5152  if (op->material != op2->material)
5153  FAST_SAVE_LONG(sb, "material ", op->material);
5154  if (op->materialname && op->materialname != op2->materialname) {
5155  ADD_STRINGLINE_ENTRY(sb, "materialname ", op->materialname);
5156  }
5157  if (op->value != op2->value)
5158  FAST_SAVE_LONG(sb, "value ", op->value);
5159  if (op->carrying != op2->carrying)
5160  FAST_SAVE_LONG(sb, "carrying ", op->carrying);
5161  if (op->weight != op2->weight)
5162  FAST_SAVE_LONG(sb, "weight ", op->weight);
5163  if (op->invisible != op2->invisible)
5164  FAST_SAVE_LONG(sb, "invisible ", op->invisible);
5165  if (op->state != op2->state)
5166  FAST_SAVE_LONG(sb, "state ", op->state);
5167  if (op->magic != op2->magic)
5168  FAST_SAVE_LONG(sb, "magic ", op->magic);
5169  if (op->last_heal != op2->last_heal)
5170  FAST_SAVE_LONG(sb, "last_heal ", op->last_heal);
5171  if (op->last_sp != op2->last_sp)
5172  FAST_SAVE_LONG(sb, "last_sp ", op->last_sp);
5173  if (op->last_grace != op2->last_grace)
5174  FAST_SAVE_LONG(sb, "last_grace ", op->last_grace);
5175  if (op->last_eat != op2->last_eat)
5176  FAST_SAVE_LONG(sb, "last_eat ", op->last_eat);
5178  FAST_SAVE_LONG(sb, "connected ", tmp);
5179  if (op->glow_radius != op2->glow_radius)
5180  FAST_SAVE_LONG(sb, "glow_radius ", op->glow_radius);
5181  if (op->randomitems != op2->randomitems) {
5182  ADD_STRINGLINE_ENTRY(sb, "randomitems ", op->randomitems ? op->randomitems->name : "none");
5183  }
5184 
5185  if (op->run_away != op2->run_away)
5186  FAST_SAVE_LONG(sb, "run_away ", op->run_away);
5187  if (op->pick_up != op2->pick_up)
5188  FAST_SAVE_LONG(sb, "pick_up ", op->pick_up);
5189  if (op->weight_limit != op2->weight_limit)
5190  FAST_SAVE_LONG(sb, "container ", op->weight_limit);
5191  if (op->will_apply != op2->will_apply)
5192  FAST_SAVE_LONG(sb, "will_apply ", op->will_apply);
5193  if (op->smoothlevel != op2->smoothlevel)
5194  FAST_SAVE_LONG(sb, "smoothlevel ", op->smoothlevel);
5195 
5196  if (op->map_layer != op2->map_layer)
5197  ADD_STRINGLINE_ENTRY(sb, "map_layer ", map_layer_name[op->map_layer]);
5198 
5199  if (op->weapontype && op->weapontype != op2->weapontype) {
5200  FAST_SAVE_LONG(sb, "weapontype ", op->weapontype);
5201  }
5202  if (op->client_type && op->client_type != op2->client_type) {
5203  FAST_SAVE_LONG(sb, "client_type ", op->client_type);
5204  }
5205 
5206  if (op->item_power != op2->item_power) {
5207  FAST_SAVE_LONG(sb, "item_power ", op->item_power);
5208  }
5209 
5210  if (op->duration != op2->duration)
5211  FAST_SAVE_LONG(sb, "duration ", op->duration);
5212 
5213  if (op->range != op2->range)
5214  FAST_SAVE_LONG(sb, "range ", op->range);
5215 
5216  if (op->range_modifier != op2->range_modifier)
5217  FAST_SAVE_LONG(sb, "range_modifier ", op->range_modifier);
5218 
5219  if (op->duration_modifier != op2->duration_modifier)
5220  FAST_SAVE_LONG(sb, "duration_modifier ", op->duration_modifier);
5221 
5222  if (op->dam_modifier != op2->dam_modifier)
5223  FAST_SAVE_LONG(sb, "dam_modifier ", op->dam_modifier);
5224 
5225  if (op->gen_sp_armour != op2->gen_sp_armour) {
5226  FAST_SAVE_LONG(sb, "gen_sp_armour ", op->gen_sp_armour);
5227  }
5228 
5229  /* I've kept the old int move type saving code commented out.
5230  * In an ideal world, we'd know if we want to do a quick
5231  * save (say to a temp map, where we don't care about strings),
5232  * or a slower save/dm dump, where printing out strings is handy.
5233  */
5234  if (op->move_type != op2->move_type) {
5235  /*FAST_SAVE_LONG(sb, "move_type ", op->move_type)*/
5236  stringbuffer_append_string(sb, "move_type ");
5237  get_string_move_type(sb, op->move_type);
5238  stringbuffer_append_string(sb, "\n");
5239  }
5240  if (op->move_block != op2->move_block) {
5241  /*FAST_SAVE_LONG(sb, "move_block ", op->move_block)*/
5242  stringbuffer_append_string(sb, "move_block ");
5243  get_string_move_type(sb, op->move_block);
5244  stringbuffer_append_string(sb, "\n");
5245  }
5246  if (op->move_allow != op2->move_allow) {
5247  /*FAST_SAVE_LONG(sb, "move_allow ", op->move_allow);*/
5248  stringbuffer_append_string(sb, "move_allow ");
5249  get_string_move_type(sb, op->move_allow);
5250  stringbuffer_append_string(sb, "\n");
5251  }
5252  if (op->move_on != op2->move_on) {
5253  /*FAST_SAVE_LONG(sb, "move_on ", op->move_on);*/
5254  stringbuffer_append_string(sb, "move_on ");
5255  get_string_move_type(sb, op->move_on);
5256  stringbuffer_append_string(sb, "\n");
5257  }
5258  if (op->move_off != op2->move_off) {
5259  /*FAST_SAVE_LONG(sb, "move_off ", op->move_off);*/
5260  stringbuffer_append_string(sb, "move_off ");
5261  get_string_move_type(sb, op->move_off);
5262  stringbuffer_append_string(sb, "\n");
5263  }
5264  if (op->move_slow != op2->move_slow) {
5265  /*FAST_SAVE_LONG(sb, "move_slow ", op->move_slow);*/
5266  stringbuffer_append_string(sb, "move_slow ");
5267  get_string_move_type(sb, op->move_slow);
5268  stringbuffer_append_string(sb, "\n");
5269  }
5270 
5271  if (op->move_slow_penalty != op2->move_slow_penalty) {
5272  FAST_SAVE_DOUBLE(sb, "move_slow_penalty ", op->move_slow_penalty);
5273  }
5274 
5275  ob_flags diff_flags;
5276  compare_flags(&diff_flags, op, op2);
5277  int flag;
5278  while ((flag = flags_differ(&diff_flags)) != -1) {
5279  if (flag_names[flag]) {
5280  ADD_STRINGLINE_ENTRY(sb, flag_names[flag], QUERY_FLAG(op, flag) ? " 1" : " 0");
5281  }
5282  }
5283 
5284  /* Save body locations */
5285  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
5286  if (op->body_info[i] != op2->body_info[i]) {
5287  stringbuffer_append_string(sb, body_locations[i].save_name);
5288  FAST_SAVE_LONG(sb, " ", op->body_info[i]);
5289  }
5290  }
5291 }
5292 
5297 void save_object_in_sb(StringBuffer *sb, object *op, const int flag) {
5298  /* If the object has no_save set, just return */
5299  if (QUERY_FLAG(op, FLAG_NO_SAVE)) {
5300  return;
5301  }
5302 
5303  /* Even if the object does have an owner, it would seem that we should
5304  * still save it.
5305  */
5306  if (object_get_owner(op) != NULL) {
5307  return;
5308  }
5309 
5310  /* If it is unpaid and we don't want to save those, just return. */
5311  if (!(flag&SAVE_FLAG_SAVE_UNPAID) && (QUERY_FLAG(op, FLAG_UNPAID))) {
5312  return;
5313  }
5314 
5315  archetype *at = op->arch;
5316  if (at == NULL)
5317  at = empty_archetype;
5318 
5319  ADD_STRINGLINE_ENTRY(sb, "arch ", at->name);
5320 
5321  if (at->reference_count > 0) {
5322  /* The object is a custom item/monster, so we handle its save differently.
5323  * We compare the custom archetype to the "original" one, then only save hp/gr/sp
5324  * which are the only values we can't recompute later - all others are modified by items in inventory.
5325  * Note that hp/gr/sp will appear twice in save, but last value will take precedence.
5326  */
5327  archetype *original = find_archetype(at->name);
5328  if (!original) {
5329  LOG(llevError, "could not find original archetype %s for custom monster!\n", at->name);
5330  abort();
5331  }
5332  get_ob_diff(sb, &at->clone, &original->clone);
5333  if (op->stats.hp != at->clone.stats.hp)
5334  FAST_SAVE_LONG(sb, "hp ", op->stats.hp);
5335  if (op->stats.sp != at->clone.stats.sp)
5336  FAST_SAVE_LONG(sb, "sp ", op->stats.sp);
5337  if (op->stats.grace != at->clone.stats.grace)
5338  FAST_SAVE_LONG(sb, "grace ", op->stats.grace);
5339  if (op->x != at->clone.x)
5340  FAST_SAVE_LONG(sb, "x ", op->x);
5341  if (op->y != at->clone.y)
5342  FAST_SAVE_LONG(sb, "y ", op->y);
5343  } else if (op->artifact != NULL) {
5344  /* if op is an artifact, then find the "standard" artifact to use that for the diff */
5345  object *base;
5346  const artifact *artifact;
5347 
5348  artifact = find_artifact(op, op->artifact);
5349  if (artifact == NULL) {
5350  LOG(llevError, "could not find artifact %s [%d] to save data\n", op->artifact, op->type);
5351  get_ob_diff(sb, op, &at->clone);
5352  } else {
5353  ADD_STRINGLINE_ENTRY(sb, "artifact ", op->artifact);
5354  base = arch_to_object(at);
5356  get_ob_diff(sb, op, base);
5358  }
5359  } else {
5360  get_ob_diff(sb, op, &at->clone);
5361  }
5362 
5363  /* Eneq(@csd.uu.se): Added this to allow containers being saved with contents*/
5365  save_object_in_sb(sb, tmp, flag);
5366  FOR_INV_FINISH();
5367 
5368  stringbuffer_append_string(sb, "end\n");
5369 }
5370 
5383 int save_object(FILE *fp, object *op, int flag) {
5385  save_object_in_sb(sb, op, flag);
5386  char *cp = stringbuffer_finish(sb);
5387  if (fputs(cp, fp) == EOF) {
5388  free(cp);
5389  return SAVE_ERROR_WRITE;
5390  } else {
5391  free(cp);
5392  return SAVE_ERROR_OK;
5393  }
5394 }
5395 
5397  if (op->map) {
5398  sstring death_animation = object_get_value(op, "death_animation");
5399  if (death_animation != NULL) {
5400  object *death = create_archetype(death_animation);
5401 
5402  if (death != NULL) {
5403  object_insert_in_map_at(death, op->map, op, 0, op->x, op->y);
5404  if (death->arch->more)
5405  object_fix_multipart(death);
5406  }
5407  }
5408  }
5409 }
5410 
5411 object *find_force(object *op, const char *name) {
5412  assert(op != NULL);
5414 }
5415 
5416 object *add_force(object *op, const char *name, int duration) {
5417  assert(op != NULL);
5418  object *force = find_force(op, name);
5419  if (force == NULL) {
5421  force->slaying = add_string(name);
5423  }
5424 
5425  if (duration != 0) {
5426  force->speed = 0.01;
5427  force->speed_left = -duration;
5428  } else {
5429  force->speed = 0;
5430  }
5431 
5432  // Even if duration is zero, a force could be set previously.
5434 
5435  return force;
5436 }
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
object_value_set
bool object_value_set(const object *op, const char *const key)
Definition: object.cpp:4369
free_objects
static object * free_objects
Definition: object.cpp:295
object::name_pl
sstring name_pl
Definition: object.h:321
give.next
def next
Definition: give.py:44
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Definition: map.h:173
init_objects
void init_objects(void)
Definition: object.cpp:327
living::exp
int64_t exp
Definition: living.h:47
UP_OBJ_FACE
#define UP_OBJ_FACE
Definition: object.h:522
object::weapon_speed_left
float weapon_speed_left
Definition: object.h:338
PLAYER
@ PLAYER
Definition: object.h:110
object_get_owner_const
static const object * object_get_owner_const(const object *op)
Definition: object.cpp:624
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:4294
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:138
permute
static void permute(int *, int, int)
Definition: object.cpp:3611
object::range_modifier
uint8_t range_modifier
Definition: object.h:414
object::move_status
int32_t move_status
Definition: object.h:398
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
object_update_turn_face
void object_update_turn_face(object *op)
Definition: object.cpp:1332
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:52
living::maxhp
int16_t maxhp
Definition: living.h:41
object_count_active
int object_count_active(void)
Definition: object.cpp:1783
object_find_by_type_applied
object * object_find_by_type_applied(const object *who, int type)
Definition: object.cpp:4076
NUM_BODY_LOCATIONS
#define NUM_BODY_LOCATIONS
Definition: object.h:13
MAP_SAVING
#define MAP_SAVING
Definition: map.h:134
object::weapontype
uint32_t weapontype
Definition: object.h:379
object::map_layer
uint8_t map_layer
Definition: object.h:430
find_artifact
const artifact * find_artifact(const object *op, const char *name)
Definition: artifact.cpp:589
GET_MAP_TOP
#define GET_MAP_TOP(M, X, Y)
Definition: map.h:175
statistics
struct Statistics statistics
Definition: init.cpp:231
llevError
@ llevError
Definition: logger.h:11
object_set_flag_inv
void object_set_flag_inv(object *op, int flag)
Definition: object.cpp:3232
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
object::path_attuned
uint32_t path_attuned
Definition: object.h:351
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:4929
FLAG_OVERLAY_FLOOR
#define FLAG_OVERLAY_FLOOR
Definition: define.h:255
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
archetype::more
archetype * more
Definition: object.h:475
player
Definition: player.h:105
object::client_type
uint16_t client_type
Definition: object.h:348
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
Statistics::spell_merges
uint64_t spell_merges
Definition: global.h:362
SIZEOFFREE1
#define SIZEOFFREE1
Definition: define.h:153
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
map_find_by_archetype
object * map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at)
Definition: object.cpp:3111
FLAG_IS_TURNABLE
#define FLAG_IS_TURNABLE
Definition: define.h:256
object_merge
object * object_merge(object *op, object *top)
Definition: object.cpp:2049
STARTMAX
#define STARTMAX
Definition: config.h:523
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.cpp:138
FALSE
#define FALSE
Definition: compat.h:14
update_position
void update_position(mapstruct *m, int x, int y)
Definition: map.cpp:2141
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
object::item_power
int8_t item_power
Definition: object.h:370
object::arch
struct archetype * arch
Definition: object.h:420
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
object::attack_movement
uint16_t attack_movement
Definition: object.h:399
absdir
int absdir(int d)
Definition: object.cpp:3707
UPD_WEIGHT
#define UPD_WEIGHT
Definition: newclient.h:316
flag_names
static const char *const flag_names[NUM_FLAGS+1]
Definition: object.cpp:4844
object::range
int8_t range
Definition: object.h:413
object::speed
float speed
Definition: object.h:335
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:4784
object::invisible
int16_t invisible
Definition: object.h:368
living::Dex
int8_t Dex
Definition: living.h:36
FLAG_OBJ_ORIGINAL
#define FLAG_OBJ_ORIGINAL
Definition: define.h:357
TRAP
@ TRAP
Definition: object.h:244
object::x
int16_t x
Definition: object.h:333
OB_SPELL_TAG_MATCH
#define OB_SPELL_TAG_MATCH(op, count)
Definition: object.h:93
object_dump_all
void object_dump_all(void)
Definition: object.cpp:704
player::transport
object * transport
Definition: player.h:213
object::speed_left
float speed_left
Definition: object.h:336
give_artifact_abilities
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.cpp:230
object::pick_up
uint8_t pick_up
Definition: object.h:369
object::map
struct mapstruct * map
Definition: object.h:303
object::anim_suffix
sstring anim_suffix
Definition: object.h:322
key_value
Definition: object.h:40
object_find_first_free_spot
int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y)
Definition: object.cpp:3592
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:3215
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:4409
guildjoin.ob
ob
Definition: guildjoin.py:42
object::expmul
double expmul
Definition: object.h:403
object_handle_death_animation
void object_handle_death_animation(object *op)
Definition: object.cpp:5396
artifact::item
object * item
Definition: artifact.h:15
commongive.inv
inv
Definition: commongive.py:29
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
SKILL
@ SKILL
Definition: object.h:146
object::direction
int8_t direction
Definition: object.h:342
flags
static const flag_definition flags[]
Definition: gridarta-types-convert.cpp:101
object::count
tag_t count
Definition: object.h:305
object::last_grace
int16_t last_grace
Definition: object.h:367
RUNE
@ RUNE
Definition: object.h:243
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.cpp:1192
object::smoothlevel
uint8_t smoothlevel
Definition: object.h:429
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:4222
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:3405
object_find_by_type_and_skill
object * object_find_by_type_and_skill(const object *who, int type, const char *skill)
Definition: object.cpp:4176
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
flags_differ
int flags_differ(ob_flags *diff)
Definition: object.cpp:4953
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
object_copy_with_inv
void object_copy_with_inv(const object *src_ob, object *dest_ob, bool update_speed)
Definition: object.cpp:1208
object::key_values
key_value * key_values
Definition: object.h:440
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
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
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:169
object::title
sstring title
Definition: object.h:323
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:4339
P_IS_ALIVE
#define P_IS_ALIVE
Definition: map.h:238
Statistics::spell_hash_full
uint64_t spell_hash_full
Definition: global.h:363
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
object::level
int16_t level
Definition: object.h:359
expand_objects
static void expand_objects(void)
Definition: object.cpp:1231
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:2127
active_objects
object * active_objects
Definition: object.cpp:296
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2851
object::will_apply
uint8_t will_apply
Definition: object.h:400
object::above
object * above
Definition: object.h:294
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:4943
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
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
object::resist
int16_t resist[NROFATTACKS]
Definition: object.h:349
FLAG_NO_PICK
#define FLAG_NO_PICK
Definition: define.h:239
FLAG_DIALOG_PARSED
#define FLAG_DIALOG_PARSED
Definition: define.h:243
FLAG_ALIVE
#define FLAG_ALIVE
Definition: define.h:230
object::path_denied
uint32_t path_denied
Definition: object.h:353
object_clear
void object_clear(object *op)
Definition: object.cpp:983
esrv_send_item
void esrv_send_item(object *pl, object *op)
Definition: main.cpp:354
INS_ABOVE_FLOOR_ONLY
#define INS_ABOVE_FLOOR_ONLY
Definition: object.h:570
key_value::value
const char * value
Definition: object.h:42
FOR_OB_AND_ABOVE_PREPARE
#define FOR_OB_AND_ABOVE_PREPARE(op_)
Definition: define.h:739
object::carrying
int32_t carrying
Definition: object.h:375
FLAG_IS_A_TEMPLATE
#define FLAG_IS_A_TEMPLATE
Definition: define.h:366
LOOK_OBJ
#define LOOK_OBJ(ob)
Definition: object.h:510
stringbuffer.h
object::path_repelled
uint32_t path_repelled
Definition: object.h:352
object::y
int16_t y
Definition: object.h:333
object_find_by_type_and_race
object * object_find_by_type_and_race(const object *who, int type, const char *race)
Definition: object.cpp:4126
m
static event_registration m
Definition: citylife.cpp:425
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_EXPAND
#define OBJ_EXPAND
Definition: config.h:524
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:1560
object_update
void object_update(object *op, int action)
Definition: object.cpp:1434
object::contr
struct player * contr
Definition: object.h:282
item.q
q
Definition: item.py:32
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:3949
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:4314
object::last_heal
int32_t last_heal
Definition: object.h:365
object_find_by_type2
object * object_find_by_type2(const object *who, int type1, int type2)
Definition: object.cpp:4030
object::subtype
uint8_t subtype
Definition: object.h:347
FLAG_WAS_WIZ
#define FLAG_WAS_WIZ
Definition: define.h:234
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:4383
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.cpp:305
key_value::next
key_value * next
Definition: object.h:43
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:3196
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:3138
object::weapon_speed
float weapon_speed
Definition: object.h:337
can_see_monsterP
int can_see_monsterP(mapstruct *m, int x, int y, int dir)
Definition: object.cpp:3815
MOVE_WALK
#define MOVE_WALK
Definition: define.h:392
FLAG_KNOWN_CURSED
#define FLAG_KNOWN_CURSED
Definition: define.h:320
object::prev
object * prev
Definition: object.h:284
stringbuffer_finish_shared
sstring stringbuffer_finish_shared(StringBuffer *sb)
Definition: stringbuffer.cpp:85
FOR_ABOVE_FINISH
#define FOR_ABOVE_FINISH()
Definition: define.h:694
archetype::clone
object clone
Definition: object.h:476
object::run_away
uint8_t run_away
Definition: object.h:392
object_dump
void object_dump(const object *op, StringBuffer *sb)
Definition: object.cpp:645
object::ox
int16_t ox
Definition: object.h:334
object::weight_limit
int32_t weight_limit
Definition: object.h:374
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
object_count_free
int object_count_free(void)
Definition: object.cpp:1751
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:4737
HEAD
#define HEAD(op)
Definition: object.h:596
CONTAINER
@ CONTAINER
Definition: object.h:234
object::below
object * below
Definition: object.h:293
make_face_from_files.str
str
Definition: make_face_from_files.py:24
object::move_type
MoveType move_type
Definition: object.h:432
object_find_by_type_and_name
object * object_find_by_type_and_name(const object *who, int type, const char *name)
Definition: object.cpp:4101
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
object::event_bitmask
uint64_t event_bitmask
Definition: object.h:443
convert.action
action
Definition: convert.py:25
object::face
const Face * face
Definition: object.h:339
out_of_map
int out_of_map(mapstruct *m, int x, int y)
Definition: map.cpp:2320
find_string
sstring find_string(const char *str)
Definition: shstr.cpp:236
object::last_eat
int32_t last_eat
Definition: object.h:364
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
object::value
int32_t value
Definition: object.h:358
object_update_speed
void object_update_speed(object *op)
Definition: object.cpp:1349
FLAG_IS_WOODED
#define FLAG_IS_WOODED
Definition: define.h:330
object::type
uint8_t type
Definition: object.h:346
INS_NO_MERGE
#define INS_NO_MERGE
Definition: object.h:569
FLAG_DAMNED
#define FLAG_DAMNED
Definition: define.h:317
living::dam
int16_t dam
Definition: living.h:46
object::magic
int8_t magic
Definition: object.h:356
SET_MAP_FLAGS
#define SET_MAP_FLAGS(M, X, Y, C)
Definition: map.h:164
object::materialname
sstring materialname
Definition: object.h:354
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:4053
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:4199
object_free
void object_free(object *ob, int flags)
Definition: object.cpp:1592
LAMP
@ LAMP
Definition: object.h:204
GET_MAP_MOVE_BLOCK
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:193
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
INS_BELOW_ORIGINATOR
#define INS_BELOW_ORIGINATOR
Definition: object.h:573
object::move_on
MoveType move_on
Definition: object.h:435
living::food
int32_t food
Definition: living.h:48
resist_save
const char *const resist_save[NROFATTACKS]
Definition: init.cpp:31
sstring
const typedef char * sstring
Definition: global.h:47
disinfect.count
int count
Definition: disinfect.py:7
tag_t
uint32_t tag_t
Definition: object.h:12
body_locations
body_locations_struct body_locations[NUM_BODY_LOCATIONS]
Definition: item.cpp:54
archetype
Definition: object.h:472
P_PLAYER
#define P_PLAYER
Definition: map.h:237
object_matches_string
int object_matches_string(object *pl, object *op, const char *name)
Definition: object.cpp:4567
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:3289
sproto.h
FLAG_NO_DROP
#define FLAG_NO_DROP
Definition: define.h:288
FLAG_NO_SAVE
#define FLAG_NO_SAVE
Definition: define.h:244
living::sp
int16_t sp
Definition: living.h:42
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:2393
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
living::Int
int8_t Int
Definition: living.h:36
object::race
sstring race
Definition: object.h:324
compare_flags
static void compare_flags(ob_flags *ret, const object *p, const object *q)
Definition: object.h:488
object::animation
const Animations * animation
Definition: object.h:424
GET_MAP_MOVE_ON
#define GET_MAP_MOVE_ON(M, X, Y)
Definition: map.h:203
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
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:3997
reduction_dir
static const int reduction_dir[SIZEOFFREE][3]
Definition: object.cpp:3745
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:2098
object::other_arch
struct archetype * other_arch
Definition: object.h:421
object_create_clone
object * object_create_clone(object *asrc)
Definition: object.cpp:3902
object_copy_no_speed
void object_copy_no_speed(const object *src_ob, object *dest_ob)
Definition: object.cpp:1061
fatal
void fatal(enum fatal_error err)
Definition: utils.cpp:570
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
INS_ON_TOP
#define INS_ON_TOP
Definition: object.h:572
move_name
const char *const move_name[]
Definition: object.cpp:4825
object_set_cheat
void object_set_cheat(object *op)
Definition: object.cpp:3267
object_new
object * object_new(void)
Definition: object.cpp:1273
object_insert_in_map
object * object_insert_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.cpp:2359
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:278
object_present_in_ob
object * object_present_in_ob(uint8_t type, const object *op)
Definition: object.cpp:3161
get_weight_limit
uint32_t get_weight_limit(int stat)
Definition: living.cpp:2360
object::weight
int32_t weight
Definition: object.h:373
nroffreeobjects
int nroffreeobjects
Definition: object.cpp:290
free_string
void free_string(sstring str)
Definition: shstr.cpp:280
object::move_slow
MoveType move_slow
Definition: object.h:437
object::spell_tags
tag_t * spell_tags
Definition: object.h:442
living::wc
int8_t wc
Definition: living.h:37
offsetof
#define offsetof(type, member)
Definition: shstr.h:37
object::move_slow_penalty
float move_slow_penalty
Definition: object.h:438
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
living::maxgrace
int16_t maxgrace
Definition: living.h:45
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
ob_count
long ob_count
Definition: init.cpp:123
OUT_OF_REAL_MAP
#define OUT_OF_REAL_MAP(M, X, Y)
Definition: map.h:218
get_search_arr
void get_search_arr(int *search_arr)
Definition: object.cpp:3635
find_dir_2
int find_dir_2(int x, int y)
Definition: object.cpp:3670
living::Wis
int8_t Wis
Definition: living.h:36
key_value::key
const char * key
Definition: object.h:41
object_add_weight
void object_add_weight(object *op, signed long weight)
Definition: object.cpp:2827
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
object_decrease_nrof
object * object_decrease_nrof(object *op, uint32_t i)
Definition: object.cpp:2670
object_find_by_type_and_slaying
object * object_find_by_type_and_slaying(const object *who, int type, const char *slaying)
Definition: object.cpp:4151
INS_MAP_LOAD
#define INS_MAP_LOAD
Definition: object.h:574
BITMASK_VALID
#define BITMASK_VALID
Definition: events.h:64
object::lore
sstring lore
Definition: object.h:330
object::dam_modifier
uint8_t dam_modifier
Definition: object.h:415
SK_WOODSMAN
@ SK_WOODSMAN
Definition: skills.h:40
object::slaying
sstring slaying
Definition: object.h:325
object::glow_radius
int8_t glow_radius
Definition: object.h:372
roll-o-matic.stop
def stop()
Definition: roll-o-matic.py:78
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Definition: define.h:246
guildbuy.ob1
ob1
Definition: guildbuy.py:22
object::duration_modifier
uint8_t duration_modifier
Definition: object.h:412
object::name
sstring name
Definition: object.h:317
SPELL_MAPPINGS
#define SPELL_MAPPINGS
Definition: global.h:152
object_count_used
int object_count_used(void)
Definition: object.cpp:1767
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:4245
SIZEOFFREE2
#define SIZEOFFREE2
Definition: define.h:154
object_can_pick
int object_can_pick(const object *who, const object *item)
Definition: object.cpp:3860
SCRIPT_FIX_NOTHING
#define SCRIPT_FIX_NOTHING
Definition: global.h:389
objarray
static object objarray[STARTMAX]
Definition: object.cpp:289
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::artifact
sstring artifact
Definition: object.h:320
object_find_by_type
object * object_find_by_type(const object *who, int type)
Definition: object.cpp:3973
item
Definition: item.py:1
living::maxsp
int16_t maxsp
Definition: living.h:43
P_NEED_UPDATE
#define P_NEED_UPDATE
Definition: map.h:240
mapstruct
Definition: map.h:316
object_find_by_name_global
object * object_find_by_name_global(const char *str)
Definition: object.cpp:747
object::last_sp
int32_t last_sp
Definition: object.h:366
living::Cha
int8_t Cha
Definition: living.h:36
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:4885
object::gen_sp_armour
int8_t gen_sp_armour
Definition: object.h:371
object::skill
sstring skill
Definition: object.h:327
animate_object
void animate_object(object *op, int dir)
Definition: anim.cpp:44
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:266
object_split
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
Definition: object.cpp:2631
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:3552
object_set_msg
void object_set_msg(object *op, const char *msg)
Definition: object.cpp:4804
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
object::msg
sstring msg
Definition: object.h:328
spell_mapping
const char *const spell_mapping[SPELL_MAPPINGS]
Definition: object.cpp:74
objects
object * objects
Definition: object.cpp:294
archetype::reference_count
int reference_count
Definition: object.h:479
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:3249
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:5416
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
living::ac
int8_t ac
Definition: living.h:38
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:5297
get_ob_diff
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Definition: object.cpp:4979
object::duration
int16_t duration
Definition: object.h:411
object_remove_from_active_list
void object_remove_from_active_list(object *op)
Definition: object.cpp:1392
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:4270
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:229
find_insert_pos
static object * find_insert_pos(object *op, const int flag)