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?*/
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  object *add;
1233 
1234  add = (object *)CALLOC(OBJ_EXPAND, sizeof(object));
1235 
1236  if (add == NULL)
1238  free_objects = add;
1239 
1240  // Initialize empty objects
1241  for (int i = 0; i < OBJ_EXPAND; i++) {
1242  add[i].next = &add[i+1],
1243  add[i].prev = &add[i-1],
1244  SET_FLAG(&add[i], FLAG_REMOVED);
1245  SET_FLAG(&add[i], FLAG_FREED);
1246  }
1247  // Go back and fix first and last pointers
1248  add[0].prev = NULL;
1249  add[OBJ_EXPAND-1].next = NULL;
1250 
1253 }
1254 #endif
1255 
1268 object *object_new(void) {
1269  object *op;
1270 #ifdef MEMORY_DEBUG
1271  /* FIXME: However this doesn't work since object_free() sometimes add
1272  * objects back to the free_objects linked list, and some functions mess
1273  * with the object after return of object_free(). This is bad and should be
1274  * fixed. But it would need fairly extensive changes and a lot of debugging.
1275  */
1276  op = static_cast<object *>(calloc(1, sizeof(object)));
1277  if (op == NULL)
1279 #else
1280  if (free_objects == NULL) {
1281  expand_objects();
1282  }
1283  op = free_objects;
1284  if (!QUERY_FLAG(op, FLAG_FREED)) {
1285  LOG(llevError, "Fatal: Getting busy object.\n");
1286 #ifdef MANY_CORES
1287  abort();
1288 #endif
1289  }
1290  free_objects = op->next;
1291  if (free_objects != NULL)
1292  free_objects->prev = NULL;
1293  nroffreeobjects--;
1294 #endif
1295  op->count = ++ob_count;
1296  op->name = NULL;
1297  op->name_pl = NULL;
1298  op->title = NULL;
1299  op->race = NULL;
1300  op->slaying = NULL;
1301  op->skill = NULL;
1302  op->lore = NULL;
1303  op->msg = NULL;
1304  op->materialname = NULL;
1305  op->next = objects;
1306  op->prev = NULL;
1307  op->active_next = NULL;
1308  op->active_prev = NULL;
1309  op->spell_tags = NULL;
1310  op->event_bitmask = BITMASK_VALID;
1311  if (objects != NULL)
1312  objects->prev = op;
1313  objects = op;
1314  object_clear(op);
1316  return op;
1317 }
1318 
1328  if (op->animation == 0 || !QUERY_FLAG(op, FLAG_IS_TURNABLE))
1329  return;
1330  animate_object(op, op->direction);
1331 }
1332 
1344 void object_update_speed(object *op) {
1345 
1346  /* No reason putting the archetypes objects on the speed list,
1347  * since they never really need to be updated.
1348  */
1349 
1350  if (QUERY_FLAG(op, FLAG_FREED) && op->speed) {
1351  LOG(llevError, "Object %s is freed but has speed.\n", op->name);
1352 #ifdef MANY_CORES
1353  abort();
1354 #else
1355  op->speed = 0;
1356 #endif
1357  }
1358  if (FABS(op->speed) > MIN_ACTIVE_SPEED) {
1359  /* If already on active list, don't do anything */
1360  /* TODO this check can probably be simplified a lot */
1361  if (op->active_next || op->active_prev || op == active_objects)
1362  return;
1363 
1364  /* process_events() expects us to insert the object at the beginning
1365  * of the list. */
1366  op->active_next = active_objects;
1367  if (op->active_next != NULL)
1368  op->active_next->active_prev = op;
1369  active_objects = op;
1370  } else {
1372  }
1373 }
1374 
1388  /* If not on the active list, nothing needs to be done */
1389  if (!op->active_next && !op->active_prev && op != active_objects)
1390  return;
1391 
1392  if (op->active_prev == NULL) {
1393  active_objects = op->active_next;
1394  if (op->active_next != NULL)
1395  op->active_next->active_prev = NULL;
1396  } else {
1397  op->active_prev->active_next = op->active_next;
1398  if (op->active_next)
1399  op->active_next->active_prev = op->active_prev;
1400  }
1401  op->active_next = NULL;
1402  op->active_prev = NULL;
1403 }
1404 
1429 void object_update(object *op, int action) {
1430  int update_now = 0, flags;
1431  MoveType move_on, move_off, move_block, move_slow;
1432  object *pl;
1433 
1434  if (op == NULL) {
1435  /* this should never happen */
1436  LOG(llevDebug, "object_update() called for NULL object.\n");
1437  return;
1438  }
1439 
1440  if (op->env != NULL) {
1441  /* Animation is currently handled by client, so nothing
1442  * to do in this case.
1443  */
1444  return;
1445  }
1446 
1447  /* If the map is saving, don't do anything as everything is
1448  * going to get freed anyways.
1449  */
1450  if (!op->map || op->map->in_memory == MAP_SAVING)
1451  return;
1452 
1453  /* make sure the object is within map boundaries */
1454  if (op->x < 0 || op->x >= MAP_WIDTH(op->map)
1455  || op->y < 0 || op->y >= MAP_HEIGHT(op->map)) {
1456  LOG(llevError, "object_update() called for object out of map!\n");
1457 #ifdef MANY_CORES
1458  abort();
1459 #endif
1460  return;
1461  }
1462 
1463  flags = GET_MAP_FLAGS(op->map, op->x, op->y);
1464  SET_MAP_FLAGS(op->map, op->x, op->y, flags|P_NEED_UPDATE);
1465  move_slow = GET_MAP_MOVE_SLOW(op->map, op->x, op->y);
1466  move_on = GET_MAP_MOVE_ON(op->map, op->x, op->y);
1467  move_block = GET_MAP_MOVE_BLOCK(op->map, op->x, op->y);
1468  move_off = GET_MAP_MOVE_OFF(op->map, op->x, op->y);
1469 
1470  if (action == UP_OBJ_INSERT) {
1472  update_now = 1;
1473 
1475  update_now = 1;
1476 
1478  update_now = 1;
1479 
1480  if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags&P_IS_ALIVE))
1481  update_now = 1;
1482 
1483  if ((move_on|op->move_on) != move_on)
1484  update_now = 1;
1485  if ((move_off|op->move_off) != move_off)
1486  update_now = 1;
1487  /* This isn't perfect, but I don't expect a lot of objects to
1488  * to have move_allow right now.
1489  */
1490  if (((move_block|op->move_block)&~op->move_allow) != move_block)
1491  update_now = 1;
1492  if ((move_slow|op->move_slow) != move_slow)
1493  update_now = 1;
1494 
1495  if (op->type == PLAYER)
1496  update_now = 1;
1497  /* if the object is being removed, we can't make intelligent
1498  * decisions, because object_remove() can't really pass the object
1499  * that is being removed.
1500  */
1501  } else if (action == UP_OBJ_REMOVE) {
1502  update_now = 1;
1503  } else if (action == UP_OBJ_FACE || action == UP_OBJ_CHANGE) {
1504  /* In addition to sending info to client, need to update space
1505  * information.
1506  */
1507  if (action == UP_OBJ_CHANGE)
1508  update_now = 1;
1509 
1510  /* There is a player on this space - we may need to send an
1511  * update to the client.
1512  * If this object is supposed to be animated by the client,
1513  * nothing to do here - let the client animate it.
1514  * We can't use FLAG_ANIMATE, as that is basically set for
1515  * all objects with multiple faces, regardless if they are animated.
1516  * (levers have it set for example).
1517  */
1518  if (flags&P_PLAYER
1521  pl = GET_MAP_PLAYER(op->map, op->x, op->y);
1522 
1523  /* If update_look is set, we're going to send this entire space
1524  * to the client, so no reason to send face information now.
1525  */
1526  if (!pl->contr->socket->update_look) {
1528  }
1529  }
1530  } else {
1531  LOG(llevError, "object_update called with invalid action: %d\n", action);
1532  }
1533 
1534  if (update_now) {
1536  update_position(op->map, op->x, op->y);
1537  }
1538 
1539  if (op->more != NULL)
1540  object_update(op->more, action);
1541 }
1542 
1556  object_free(ob, 0);
1557 }
1558 
1563 void object_free_inventory(object *ob) {
1564  while (ob->inv) {
1565  object *inv = ob->inv;
1566  object_remove(inv);
1568  }
1569 }
1570 
1587 void object_free(object *ob, int flags) {
1588  if (!QUERY_FLAG(ob, FLAG_REMOVED)) {
1589  StringBuffer *sb;
1590  char *diff;
1591 
1592  LOG(llevError, "Free object called with non removed object\n");
1593  sb = stringbuffer_new();
1594  object_dump(ob, sb);
1595  diff = stringbuffer_finish(sb);
1596  LOG(llevError, "%s", diff);
1597  free(diff);
1598 #ifdef MANY_CORES
1599  abort();
1600 #endif
1601  }
1602  if (QUERY_FLAG(ob, FLAG_FRIENDLY)) {
1603  LOG(llevMonster, "Warning: tried to free friendly object.\n");
1605  }
1606  if (QUERY_FLAG(ob, FLAG_FREED)) {
1607  StringBuffer *sb;
1608  char *diff;
1609 
1610  sb = stringbuffer_new();
1611  object_dump(ob, sb);
1612  diff = stringbuffer_finish(sb);
1613  LOG(llevError, "Trying to free freed object.\n%s\n", diff);
1614  free(diff);
1615  return;
1616  }
1617 
1618  if ((flags & FREE_OBJ_NO_DESTROY_CALLBACK) == 0) {
1620  }
1621 
1622  if (ob->inv) {
1623  /* Only if the space blocks everything do we not process -
1624  * if some form of movemnt is allowed, let objects
1625  * drop on that space.
1626  */
1627  if ((flags & FREE_OBJ_FREE_INVENTORY) != 0
1628  || ob->map == NULL
1629  || ob->map->in_memory != MAP_IN_MEMORY
1630  || (GET_MAP_MOVE_BLOCK(ob->map, ob->x, ob->y) == MOVE_ALL)) {
1631  FOR_INV_PREPARE(ob, op) {
1632  object_remove(op);
1633  object_free(op, flags);
1634  } FOR_INV_FINISH();
1635  } else { /* Put objects in inventory onto this space */
1636  FOR_INV_PREPARE(ob, op) {
1637  object_remove(op);
1638  /* No drop means no drop, including its inventory */
1639  if (QUERY_FLAG(op, FLAG_NO_DROP))
1641  else if (QUERY_FLAG(op, FLAG_STARTEQUIP)
1643  || op->type == RUNE
1644  || op->type == TRAP
1647  else {
1648  object *part;
1649 
1650  /* If it's a multi-tile object, scatter dropped items randomly */
1651  if (ob->more) {
1652  int partcount = 0;
1653  /* Get the number of non-head parts */
1654  for (part = ob; part; part = part->more) {
1655  partcount++;
1656  }
1657  /* Select a random part */
1658  partcount = RANDOM()%partcount;
1659  for (part = ob; partcount > 0; partcount--) {
1660  part = part->more;
1661  }
1662  } else {
1663  part = ob;
1664  }
1665 
1666  if (QUERY_FLAG(op, FLAG_ALIVE)) {
1667  object_insert_to_free_spot_or_free(op, part->map, part->x, part->y, 0, SIZEOFFREE, NULL);
1668  } else {
1669  int f = 0;
1672  object_insert_in_map_at(op, part->map, NULL, f, part->x, part->y); /* Insert in same map as the envir */
1673  }
1674  }
1675  } FOR_INV_FINISH();
1676  }
1677  }
1678 
1679  if (ob->more != NULL) {
1680  object_free(ob->more, flags);
1681  ob->more = NULL;
1682  }
1683 
1684  /* Remove object from the active list */
1685  ob->speed = 0;
1687 
1689  ob->count = 0;
1690 
1691  /* Remove this object from the list of used objects */
1692  if (ob->prev == NULL) {
1693  objects = ob->next;
1694  if (objects != NULL)
1695  objects->prev = NULL;
1696  } else {
1697  ob->prev->next = ob->next;
1698  if (ob->next != NULL)
1699  ob->next->prev = ob->prev;
1700  }
1701 
1702  if (ob->artifact != NULL) FREE_AND_CLEAR_STR(ob->artifact);
1703  if (ob->name != NULL) FREE_AND_CLEAR_STR(ob->name);
1704  if (ob->name_pl != NULL) FREE_AND_CLEAR_STR(ob->name_pl);
1705  if (ob->title != NULL) FREE_AND_CLEAR_STR(ob->title);
1706  if (ob->race != NULL) FREE_AND_CLEAR_STR(ob->race);
1707  if (ob->slaying != NULL) FREE_AND_CLEAR_STR(ob->slaying);
1708  if (ob->skill != NULL) FREE_AND_CLEAR_STR(ob->skill);
1709  if (ob->lore != NULL) FREE_AND_CLEAR_STR(ob->lore);
1710  if (ob->msg != NULL) FREE_AND_CLEAR_STR(ob->msg);
1711  if (ob->materialname != NULL) FREE_AND_CLEAR_STR(ob->materialname);
1712  if (ob->spell_tags) FREE_AND_CLEAR(ob->spell_tags);
1713  FREE_AND_CLEAR_STR_IF(ob->anim_suffix);
1714 
1715  /* Why aren't events freed? */
1717 
1719 
1720  /* Test whether archetype is a temporary one, and if so look whether it should be trashed. */
1721  if (ob->arch && ob->arch->reference_count > 0) {
1722  if (--ob->arch->reference_count == 0) {
1723  free_arch(ob->arch);
1724  }
1725  }
1726 
1727 #ifdef MEMORY_DEBUG
1728  free(ob);
1729 #else
1730  /* Now link it with the free_objects list: */
1731  ob->prev = NULL;
1732  ob->next = free_objects;
1733  if (free_objects != NULL)
1734  free_objects->prev = ob;
1735  free_objects = ob;
1736  nroffreeobjects++;
1737 #endif
1738 }
1739 
1747  int i = 0;
1748  object *tmp = free_objects;
1749 
1750  while (tmp != NULL)
1751  tmp = tmp->next,
1752  i++;
1753  return i;
1754 }
1755 
1763  int i = 0;
1764  object *tmp = objects;
1765 
1766  while (tmp != NULL)
1767  tmp = tmp->next,
1768  i++;
1769  return i;
1770 }
1771 
1779  int i = 0;
1780  object *tmp = active_objects;
1781 
1782  while (tmp != NULL)
1783  tmp = tmp->active_next,
1784  i++;
1785  return i;
1786 }
1787 
1802 void object_sub_weight(object *op, signed long weight) {
1803  while (op != NULL) {
1804  if (op->type == CONTAINER) {
1805  weight = (signed long)(weight*(100-op->stats.Str)/100);
1806  }
1807  op->carrying -= weight;
1808  op = op->env;
1809  }
1810 }
1811 
1828 void object_remove(object *op) {
1829  object *last = NULL;
1830  object *otmp;
1831  tag_t tag;
1832  int check_walk_off;
1833  mapstruct *m;
1834  int16_t x, y;
1835 
1836  if (QUERY_FLAG(op, FLAG_REMOVED)) {
1837  StringBuffer *sb;
1838  char *diff;
1839 
1840  sb = stringbuffer_new();
1841  object_dump(op, sb);
1842  diff = stringbuffer_finish(sb);
1843  LOG(llevError, "Trying to remove removed object.\n%s\n", diff);
1844  free(diff);
1845  abort();
1846  }
1847  if (op->more != NULL)
1848  object_remove(op->more);
1849 
1851 
1852  /*
1853  * In this case, the object to be removed is in someones
1854  * inventory.
1855  */
1856  /* TODO try to call a generic inventory weight adjusting function like object_sub_weight */
1857  if (op->env != NULL) {
1858  player *pl = NULL;
1859 
1860  if (op->nrof)
1861  object_sub_weight(op->env, op->weight*op->nrof);
1862  else
1863  object_sub_weight(op->env, op->weight+op->carrying);
1864 
1865  /* Update in two cases: item is in a player, or in a container the player is looking into. */
1866  if (op->env->contr != NULL && op->head == NULL) {
1867  pl = op->env->contr;
1868  } else if (op->env->type == CONTAINER && QUERY_FLAG(op->env, FLAG_APPLIED)) {
1869 
1870  if (op->env->env && op->env->env->contr)
1871  /* Container is in player's inventory. */
1872  pl = op->env->env->contr;
1873  else if (op->env->map) {
1874  /* Container on map, look above for player. */
1875  object *above = op->env->above;
1876 
1877  while (above && !above->contr)
1878  above = above->above;
1879  if (above)
1880  pl = above->contr;
1881  }
1882  }
1883 
1884  /* NO_FIX_PLAYER is set when a great many changes are being
1885  * made to players inventory. If set, avoiding the call
1886  * to save cpu time.
1887  */
1888  otmp = object_get_player_container(op->env);
1889  if (otmp != NULL
1890  && otmp->contr
1891  && !QUERY_FLAG(otmp, FLAG_NO_FIX_PLAYER))
1892  fix_object(otmp);
1893 
1894  if (op->above != NULL)
1895  op->above->below = op->below;
1896  else
1897  op->env->inv = op->below;
1898 
1899  if (op->below != NULL)
1900  op->below->above = op->above;
1901 
1902  if (op->type == EVENT_CONNECTOR) {
1903  op->env->event_bitmask = 0; // Will be recomputed if needed
1904  }
1905 
1906  /* we set up values so that it could be inserted into
1907  * the map, but we don't actually do that - it is up
1908  * to the caller to decide what we want to do.
1909  */
1910  op->x = op->env->x;
1911  op->y = op->env->y;
1912  op->ox = op->x;
1913  op->oy = op->y;
1914  op->map = op->env->map;
1915  op->above = NULL;
1916  op->below = NULL;
1917  /* send the delitem before resetting env, so container's contents be may
1918  * refreshed */
1919  if (LOOK_OBJ(op) && pl != NULL)
1920  esrv_del_item(pl, op);
1921  op->env = NULL;
1922  return;
1923  }
1924 
1925  /* If we get here, we are removing it from a map */
1926  if (op->map == NULL)
1927  return;
1928 
1929  if (op->contr != NULL && !op->contr->hidden)
1930  op->map->players--;
1931 
1932  x = op->x;
1933  y = op->y;
1934  m = get_map_from_coord(op->map, &x, &y);
1935 
1936  if (!m) {
1937  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);
1938  abort();
1939  }
1940  if (op->map != m) {
1941  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);
1942  }
1943 
1944  /* link the object above us */
1945  if (op->above)
1946  op->above->below = op->below;
1947  else
1948  SET_MAP_TOP(m, x, y, op->below); /* we were top, set new top */
1949 
1950  /* Relink the object below us, if there is one */
1951  if (op->below) {
1952  op->below->above = op->above;
1953  } else {
1954  /* Nothing below, which means we need to relink map object for this space
1955  * use translated coordinates in case some oddness with map tiling is
1956  * evident
1957  */
1958  /*TODO is this check really needed?*/
1959  if (GET_MAP_OB(m, x, y) != op) {
1960  StringBuffer *sb;
1961  char *diff;
1962 
1963  sb = stringbuffer_new();
1964  object_dump(op, sb);
1965  diff = stringbuffer_finish(sb);
1966  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);
1967  free(diff);
1968 
1969  sb = stringbuffer_new();
1970  object_dump(GET_MAP_OB(m, x, y), sb);
1971  diff = stringbuffer_finish(sb);
1972  LOG(llevError, "%s\n", diff);
1973  free(diff);
1974  }
1975  SET_MAP_OB(m, x, y, op->above); /* goes on above it. */
1976  }
1977  op->above = NULL;
1978  op->below = NULL;
1979 
1980  if (op->map->in_memory == MAP_SAVING)
1981  return;
1982 
1983  tag = op->count;
1984  check_walk_off = !QUERY_FLAG(op, FLAG_NO_APPLY);
1985  FOR_MAP_PREPARE(m, x, y, tmp) {
1986  /* No point updating the players look faces if he is the object
1987  * being removed.
1988  */
1989 
1990  if (tmp->type == PLAYER && tmp != op) {
1991  /* If a container that the player is currently using somehow gets
1992  * removed (most likely destroyed), update the player view
1993  * appropriately.
1994  */
1995  if (tmp->container == op) {
1997  tmp->container = NULL;
1998  // Notify the client the container is gone so it clears its active container.
2000  }
2001  tmp->contr->socket->update_look = 1;
2002  }
2003  /* See if player moving off should effect something */
2004  if (check_walk_off
2005  && ((op->move_type&tmp->move_off) && (op->move_type&~tmp->move_off&~tmp->move_block) == 0)) {
2006  ob_move_on(tmp, op, NULL);
2007  if (object_was_destroyed(op, tag)) {
2008  LOG(llevError, "BUG: object_remove(): name %s, archname %s destroyed leaving object\n", tmp->name, tmp->arch->name);
2009  }
2010  }
2011 
2012  /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */
2013  if (tmp->above == tmp)
2014  tmp->above = NULL;
2015  last = tmp;
2016  } FOR_MAP_FINISH();
2017  /* last == NULL or there are no objects on this space */
2018  if (last == NULL) {
2019  /* set P_NEED_UPDATE, otherwise update_position will complain. In theory,
2020  * we could preserve the flags (GET_MAP_FLAGS), but update_position figures
2021  * those out anyways, and if there are any flags set right now, they won't
2022  * be correct anyways.
2023  */
2024  SET_MAP_FLAGS(op->map, op->x, op->y, P_NEED_UPDATE);
2025  update_position(op->map, op->x, op->y);
2026  } else
2028 
2029  if (QUERY_FLAG(op, FLAG_BLOCKSVIEW) || (op->glow_radius != 0))
2030  update_all_los(op->map, op->x, op->y);
2031 }
2032 
2046 object *object_merge(object *op, object *top) {
2047  if (!op->nrof)
2048  return NULL;
2049 
2050  if (top == NULL)
2051  for (top = op; top != NULL && top->above != NULL; top = top->above)
2052  ;
2054  if (top == op)
2055  continue;
2056  if (object_can_merge(op, top)) {
2057  object_increase_nrof(top, op->nrof);
2058  /*
2059  * Previous behavior set weight to zero here.
2060  * This, however, caused the object_sub_weight
2061  * call in object_remove to subtract zero weight
2062  * when removing the object. Thus, until inventory
2063  * weight is next recalculated, the object merged
2064  * into another pile added weight in object_increase_nrof
2065  * but did not remove the weight from the original
2066  * instance of itself in object_remove, essentially
2067  * counting for double weight for several minutes.
2068  *
2069  * SilverNexus 2014-05-27
2070  */
2071  object_remove(op);
2073  return top;
2074  }
2076  return NULL;
2077 }
2078 
2095 object *object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y) {
2096  object *tmp;
2097 
2098  op = HEAD(op);
2099  for (tmp = op; tmp; tmp = tmp->more) {
2100  tmp->x = x+tmp->arch->clone.x;
2101  tmp->y = y+tmp->arch->clone.y;
2102  tmp->map = m;
2103  }
2104  return object_insert_in_map(op, m, originator, flag);
2105 }
2106 
2124 void object_merge_spell(object *op, int16_t x, int16_t y) {
2125  int i;
2126 
2127  /* We try to do some merging of spell objects - if something has same owner,
2128  * is same type of spell, and going in the same direction, it is somewhat
2129  * mergable.
2130  *
2131  * If the spell object has an other_arch, don't merge - when the spell
2132  * does something, like explodes, it will use this other_arch, and
2133  * if we merge, there is no easy way to make the correct values be
2134  * set on this new object (values should be doubled, tripled, etc.)
2135  *
2136  * We also care about speed - only process objects that will not be
2137  * active this tick. Without this, the results are incorrect - think
2138  * of a case where tmp would normally get processed this tick, but
2139  * get merges with op, which does not get processed.
2140  */
2141  FOR_MAP_PREPARE(op->map, x, y, tmp) {
2142  if (op->type == tmp->type
2143  && op->subtype == tmp->subtype
2144  && op->direction == tmp->direction
2145  && op->owner == tmp->owner && op->ownercount == tmp->ownercount
2146  && op->range == tmp->range
2147  && op->stats.wc == tmp->stats.wc
2148  && op->level == tmp->level
2149  && op->attacktype == tmp->attacktype
2150  && op->speed == tmp->speed
2151  && !tmp->other_arch
2152  && (tmp->speed_left+tmp->speed) < 0.0
2153  && op != tmp) {
2154  /* Quick test - if one or the other objects already have hash tables
2155  * set up, and that hash bucket contains a value that doesn't
2156  * match what we want to set it up, we won't be able to merge.
2157  * Note that these two if statements are the same, except
2158  * for which object they are checking against. They could
2159  * be merged, but the line wrapping would be large enough
2160  * that IMO it would become difficult to read the different clauses
2161  * so its cleaner just to do 2 statements - MSW
2162  */
2163  if (op->spell_tags
2164  && !OB_SPELL_TAG_MATCH(op, (tag_t)tmp->stats.maxhp)
2165  && OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) != 0)
2166  continue;
2167 
2168  if (tmp->spell_tags
2169  && !OB_SPELL_TAG_MATCH(tmp, (tag_t)op->stats.maxhp)
2170  && OB_SPELL_TAG_HASH(tmp, op->stats.maxhp) != 0)
2171  continue;
2172 
2173  /* If we merge, the data from tmp->spell_tags gets copied into op.
2174  * so we need to make sure that slot isn't filled up.
2175  */
2176  if (tmp->spell_tags
2177  && !OB_SPELL_TAG_MATCH(tmp, (tag_t)tmp->stats.maxhp)
2178  && OB_SPELL_TAG_HASH(tmp, tmp->stats.maxhp) != 0)
2179  continue;
2180 
2181  /* If both objects have spell_tags, we need to see if there are conflicting
2182  * values - if there are, we won't be able to merge then.
2183  */
2184  if (tmp->spell_tags && op->spell_tags) {
2185  int need_copy = 0;
2186 
2187  for (i = 0; i < SPELL_TAG_SIZE; i++) {
2188  /* If the two tag values in the hash are set, but are
2189  * not set to the same value, then these objects
2190  * can not be merged.
2191  */
2192  if (op->spell_tags[i] && tmp->spell_tags[i]
2193  && op->spell_tags[i] != tmp->spell_tags[i]) {
2195  break;
2196  }
2197  /* If one tag is set and the other is not, that is
2198  * fine, but we have to note that we need to copy
2199  * the data in that case.
2200  */
2201  if ((!op->spell_tags[i] && tmp->spell_tags[i])
2202  || (op->spell_tags[i] && !tmp->spell_tags[i])) {
2203  need_copy = 1;
2204  }
2205  }
2206  /* If we did not get through entire array, it means
2207  * we got a conflicting hash, and so we won't be
2208  * able to merge these - just continue processing
2209  * object on this space.
2210  */
2211  if (i <= SPELL_TAG_SIZE)
2212  continue;
2213 
2214  /* Ok - everything checked out - we should be able to
2215  * merge tmp in op. So lets copy the tag data if
2216  * needed. Note that this is a selective copy, as
2217  * we don't want to clear values that may be set in op.
2218  */
2219  if (need_copy) {
2220  for (i = 0; i < SPELL_TAG_SIZE; i++)
2221  if (!op->spell_tags[i]
2222  && tmp->spell_tags[i]
2223  && tmp->spell_tags[i] != (tag_t)op->stats.maxhp)
2224  op->spell_tags[i] = tmp->spell_tags[i];
2225  }
2226  FREE_AND_CLEAR(tmp->spell_tags);
2227  }
2228 
2229  /* if tmp has a spell_tags table, copy it to op and free tmps */
2230  if (tmp->spell_tags && !op->spell_tags) {
2231  op->spell_tags = tmp->spell_tags;
2232  tmp->spell_tags = NULL;
2233 
2234  /* We don't need to keep a copy of our maxhp value
2235  * in the copied over value
2236  */
2237  if (OB_SPELL_TAG_MATCH(op, (tag_t)op->stats.maxhp))
2238  OB_SPELL_TAG_HASH(op, op->stats.maxhp) = 0;
2239  }
2240 
2241  /* For spells to work correctly, we need to record what spell
2242  * tags we've merged in with this effect. This is used
2243  * in ok_to_put_more() to see if a spell effect is already on
2244  * the space.
2245  */
2246  if (op->stats.maxhp != tmp->stats.maxhp) {
2247 #ifdef OBJECT_DEBUG
2248  /* This if statement should never happen - the logic above should
2249  * have prevented it. It is a problem, because by now its possible
2250  * we've destroyed the spell_tags in tmp, so we can't really
2251  * just bail out.
2252  */
2253 
2254  if (op->spell_tags
2255  && OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) != 0
2256  && !OB_SPELL_TAG_MATCH(op, tmp->stats.maxhp)) {
2257  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);
2258  }
2259 #endif
2260  if (!op->spell_tags)
2261  op->spell_tags = static_cast<tag_t *>(calloc(SPELL_TAG_SIZE, sizeof(tag_t)));
2262 
2263  OB_SPELL_TAG_HASH(op, tmp->stats.maxhp) = tmp->stats.maxhp;
2264  }
2265 
2267  op->speed_left = MAX(op->speed_left, tmp->speed_left);
2268 
2269  if (tmp->duration != op->duration) {
2270  /* We need to use tmp_dam here because otherwise the
2271  * calculations can overflow the size of stats.dam.
2272  */
2273  int tmp_dam = tmp->stats.dam*(tmp->duration+1)+
2274  op->stats.dam*(op->duration+1);
2275 
2276  op->duration = MAX(op->duration, tmp->duration);
2277  tmp_dam /= op->duration+1;
2278  op->stats.dam = tmp_dam+1;
2279  } else {
2280  /* in this case, duration is the same, so simply adding
2281  * up damage works.
2282  */
2283  op->stats.dam += tmp->stats.dam;
2284  }
2285 
2286  object_remove(tmp);
2288  }
2289  } FOR_MAP_FINISH();
2290 }
2291 
2292 static object *find_insert_pos(object *op, const int flag) {
2293  object *floor = NULL;
2294  /*
2295  * If there are multiple objects on this space, we do some trickier handling.
2296  * We've already dealt with merging if appropriate.
2297  * Generally, we want to put the new object on top. But if
2298  * flag contains INS_ABOVE_FLOOR_ONLY, once we find the last
2299  * floor, we want to insert above that and no further.
2300  * Also, if there are spell objects on this space, we stop processing
2301  * once we get to them. This reduces the need to traverse over all of
2302  * them when adding another one - this saves quite a bit of cpu time
2303  * when lots of spells are cast in one area. Currently, it is presumed
2304  * that flying non pickable objects are spell objects.
2305  */
2306  if (flag&INS_ON_TOP) {
2307  return GET_MAP_TOP(op->map, op->x, op->y);
2308  }
2309  object *last = NULL;
2310  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp) {
2313  floor = tmp;
2314 
2316  && (tmp->move_type&(MOVE_FLY_LOW|MOVE_FLY_HIGH))
2317  && !QUERY_FLAG(tmp, FLAG_IS_FLOOR)) {
2318  /* We insert above tmp, so we want this object below this */
2319  break;
2320  }
2321  last = tmp;
2322  } FOR_MAP_FINISH();
2323  if (flag&INS_ABOVE_FLOOR_ONLY)
2324  return floor;
2325  return last;
2326 }
2327 
2356 object *object_insert_in_map(object *op, mapstruct *m, object *originator, int flag) {
2357  object *tmp, *top, *floor = NULL;
2358  int16_t x, y;
2359 
2360  if (QUERY_FLAG(op, FLAG_FREED)) {
2361  LOG(llevError, "Trying to insert freed object!\n");
2362  return NULL;
2363  }
2364  if (m == NULL) {
2365  StringBuffer *sb;
2366  char *diff;
2367 
2368  sb = stringbuffer_new();
2369  object_dump(op, sb);
2370  diff = stringbuffer_finish(sb);
2371  LOG(llevError, "Trying to insert in null-map!\n%s\n", diff);
2372  free(diff);
2373  return op;
2374  }
2375  if (out_of_map(m, op->x, op->y)) {
2376  StringBuffer *sb;
2377  char *diff;
2378 
2379  sb = stringbuffer_new();
2380  object_dump(op, sb);
2381  diff = stringbuffer_finish(sb);
2382  LOG(llevError, "Trying to insert object outside the map.\n%s\n", diff);
2383  free(diff);
2384 #ifdef MANY_CORES
2385  /* Better to catch this here, as otherwise the next use of this object
2386  * is likely to cause a crash. Better to find out where it is getting
2387  * improperly inserted.
2388  */
2389  abort();
2390 #endif
2391  return op;
2392  }
2393  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
2394  StringBuffer *sb;
2395  char *diff;
2396 
2397  sb = stringbuffer_new();
2398  object_dump(op, sb);
2399  diff = stringbuffer_finish(sb);
2400  LOG(llevError, "Trying to insert (map) inserted object.\n%s\n", diff);
2401  free(diff);
2402  return op;
2403  }
2404  if (op->more != NULL) {
2405  /* The part may be on a different map. */
2406 
2407  object *more = op->more;
2408 
2409  /* We really need the caller to normalize coordinates - if
2410  * we set the map, that doesn't work if the location is within
2411  * a map and this is straddling an edge. So only if coordinate
2412  * is clear wrong do we normalize it.
2413  */
2414  if (OUT_OF_REAL_MAP(more->map, more->x, more->y)) {
2415  /* Debugging information so you can see the last coordinates this object had */
2416  more->ox = more->x;
2417  more->oy = more->y;
2418  more->map = get_map_from_coord(more->map, &more->x, &more->y);
2419  } else if (!more->map) {
2420  /* For backwards compatibility - when not dealing with tiled maps,
2421  * more->map should always point to the parent.
2422  */
2423  more->map = m;
2424  }
2425 
2426  if (object_insert_in_map(more, more->map, originator, flag) == NULL) {
2427  if (!op->head)
2428  LOG(llevError, "BUG: object_insert_in_map(): inserting op->more killed op\n");
2429  return NULL;
2430  }
2431  }
2433 
2434  /* Debugging information so you can see the last coordinates this object had */
2435  op->ox = op->x;
2436  op->oy = op->y;
2437  x = op->x;
2438  y = op->y;
2439  op->map = get_map_from_coord(m, &x, &y);
2440 
2441  /* this has to be done after we translate the coordinates. */
2442  if (op->nrof
2443  && !(flag&INS_NO_MERGE)
2444  && op->type != SPELL_EFFECT) {
2445  FOR_MAP_PREPARE(op->map, x, y, spot) {
2446  if (object_can_merge(op, spot)) {
2447  op->nrof += spot->nrof;
2448  object_remove(spot);
2450  }
2451  } FOR_MAP_FINISH();
2452  } else if (op->type == SPELL_EFFECT
2453  && !op->range
2454  && !op->other_arch
2455  && (op->speed_left+op->speed) < 0.0) {
2456  object_merge_spell(op, x, y);
2457  }
2458 
2459  /* Ideally, the caller figures this out. However, it complicates a lot
2460  * of areas of callers (eg, anything that uses object_find_free_spot() would now
2461  * need extra work
2462  */
2463  if (op->map != m) {
2464  /* coordinates should not change unless map also changes */
2465  op->x = x;
2466  op->y = y;
2467  }
2468 
2469  if (op->type != LAMP)
2470  /* lamps use the FLAG_APPLIED to keep the light/unlit status, so don't reset it.
2471  Other objects just get unapplied, since the container "drops" them. */
2474  if (!QUERY_FLAG(op, FLAG_ALIVE))
2476 
2477  /* In many places, a player is passed as the originator, which
2478  * is fine. However, if the player is on a transport, they are not
2479  * actually on the map, so we can't use them for the linked pointers,
2480  * nor should the walk on function below use them either.
2481  */
2482  if (originator && originator->contr && originator->contr->transport)
2483  originator = originator->contr->transport;
2484 
2485  if (flag&INS_BELOW_ORIGINATOR) {
2486  if (originator->map != op->map
2487  || originator->x != op->x
2488  || originator->y != op->y) {
2489  LOG(llevError, "object_insert_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n");
2490  abort();
2491  }
2492  op->above = originator;
2493  op->below = originator->below;
2494  if (op->below)
2495  op->below->above = op;
2496  else
2497  SET_MAP_OB(op->map, op->x, op->y, op);
2498  /* since *below *originator, no need to update top */
2499  originator->below = op;
2500  } else {
2501  /* Top is the object that our object (op) is going to get inserted above. */
2502  top = find_insert_pos(op, flag);
2503 
2504  /* First object on this space */
2505  if (!top) {
2506  op->above = GET_MAP_OB(op->map, op->x, op->y);
2507  if (op->above)
2508  op->above->below = op;
2509  op->below = NULL;
2510  SET_MAP_OB(op->map, op->x, op->y, op);
2511  } else { /* get inserted into the stack above top */
2512  op->above = top->above;
2513  if (op->above)
2514  op->above->below = op;
2515  op->below = top;
2516  top->above = op;
2517  }
2518  if (op->above == NULL)
2519  SET_MAP_TOP(op->map, op->x, op->y, op);
2520  } /* else not INS_BELOW_ORIGINATOR */
2521 
2522  if (!(flag&INS_MAP_LOAD)) {
2523  if (op->type == PLAYER)
2524  op->contr->do_los = 1;
2525 
2526  /* If we have a floor, we know the player, if any, will be above
2527  * it, so save a few ticks and start from there.
2528  */
2529  tmp = floor ? floor : GET_MAP_OB(op->map, op->x, op->y);
2531  if (tmp->type == PLAYER)
2532  tmp->contr->socket->update_look = 1;
2534 
2535  /* If this object glows, it may affect lighting conditions that are
2536  * visible to others on this map. But update_all_los is really
2537  * an inefficient way to do this, as it means los for all players
2538  * on the map will get recalculated. The players could very well
2539  * be far away from this change and not affected in any way -
2540  * this should get redone to only look for players within range,
2541  * or just updating the P_NEED_UPDATE for spaces within this area
2542  * of effect may be sufficient.
2543  */
2544  if (MAP_DARKNESS(op->map) && (op->glow_radius != 0))
2545  update_all_los(op->map, op->x, op->y);
2546 
2547  if (op->contr && !op->contr->hidden)
2548  op->map->players++;
2549  }
2550 
2551  /* updates flags (blocked, alive, no magic, etc) for this map space */
2553 
2554  /* Don't know if moving this to the end will break anything. However,
2555  * we want to have update_look set above before calling this.
2556  *
2557  * object_check_move_on() must be after this because code called from
2558  * object_check_move_on() depends on correct map flags (so functions like
2559  * blocked() and wall() work properly), and these flags are updated by
2560  * object_update().
2561  */
2562 
2563  /* if this is not the head or flag has been passed, don't check walk on status */
2564 
2565  if (!(flag&INS_NO_WALK_ON) && !op->head) {
2566  if (object_check_move_on(op, originator))
2567  return NULL;
2568 
2569  /* If we are a multi part object, lets work our way through the check
2570  * walk on's.
2571  */
2572  for (tmp = op->more; tmp != NULL; tmp = tmp->more)
2573  if (object_check_move_on(tmp, originator))
2574  return NULL;
2575  }
2576  return op;
2577 }
2578 
2588 void object_replace_insert_in_map(const char *arch_string, object *op) {
2589  object *tmp1;
2590  archetype *at;
2591 
2592  /* first search for itself and remove any old instances */
2593  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp) {
2594  if (!strcmp(tmp->arch->name, arch_string)) { /* same archetype */
2595  object_remove(tmp);
2597  }
2598  } FOR_MAP_FINISH();
2599 
2600  at = find_archetype(arch_string);
2601  if (at == NULL) {
2602  return;
2603  }
2604  tmp1 = arch_to_object(at);
2605  object_insert_in_map_at(tmp1, op->map, op, INS_BELOW_ORIGINATOR, op->x, op->y);
2606 }
2607 
2628 object *object_split(object *orig_ob, uint32_t nr, char *err, size_t size) {
2629  object *newob;
2630 
2631  if (MAX(1, orig_ob->nrof) < nr) {
2632  /* If err is set, the caller knows that nr can be wrong (player trying to drop items), thus don't log that. */
2633  if (err)
2634  snprintf(err, size, "There are only %u %ss.", NROF(orig_ob), orig_ob->name);
2635  else
2636  LOG(llevDebug, "There are only %u %ss.\n", NROF(orig_ob), orig_ob->name);
2637  return NULL;
2638  }
2639  newob = object_create_clone(orig_ob);
2640  if (orig_ob->nrof == 0) {
2641  if (!QUERY_FLAG(orig_ob, FLAG_REMOVED)) {
2642  object_remove(orig_ob);
2643  }
2645  } else {
2646  newob->nrof = nr;
2647  object_decrease_nrof(orig_ob, nr);
2648  }
2649 
2650  return newob;
2651 }
2652 
2667 object *object_decrease_nrof(object *op, uint32_t i) {
2668  object *tmp;
2669 
2670  if (i == 0) /* objects with op->nrof require this check */
2671  return op;
2672 
2673  if (i > op->nrof)
2674  i = op->nrof;
2675 
2676  if (QUERY_FLAG(op, FLAG_REMOVED)) {
2677  op->nrof -= i;
2678  } else if (op->env != NULL) {
2679  if (i < op->nrof) {
2680  player *pl;
2681  /* is this object in the players inventory, or sub container
2682  * therein?
2683  */
2685  /* nope. Is this a container the player has opened?
2686  * If so, set tmp to that player.
2687  * IMO, searching through all the players will mostly
2688  * likely be quicker than following op->env to the map,
2689  * and then searching the map for a player.
2690  */
2691  if (!tmp) {
2692  for (pl = first_player; pl; pl = pl->next)
2693  if (pl->ob->container == op->env)
2694  break;
2695  if (pl)
2696  tmp = pl->ob;
2697  else
2698  tmp = NULL;
2699  }
2700 
2701  /* Because of weight reduction by container and integer arithmetic,
2702  * there is no guarantee the rounded weight of combined items will be
2703  * the same as the sum of rounded weights.
2704  * Therefore just remove the current weight, and add the new.
2705  * Same adjustment done in object_increase_nrof().
2706  */
2707  object_sub_weight(op->env, op->weight * op->nrof);
2708  op->nrof -= i;
2709  object_add_weight(op->env, op->weight * op->nrof);
2710  if (tmp) {
2713  fix_object(tmp);
2714  }
2715  } else {
2716  object_remove(op);
2717  op->nrof = 0;
2718  }
2719  } else {
2720  /* On a map. */
2721  if (i < op->nrof) {
2722  op->nrof -= i;
2723 
2724  FOR_MAP_PREPARE(op->map, op->x, op->y, pl)
2725  if (pl->contr) {
2726  pl->contr->socket->update_look = 1;
2727  break;
2728  }
2729  FOR_MAP_FINISH();
2730  } else {
2731  object_remove(op);
2732  op->nrof = 0;
2733  }
2734  }
2735 
2736  if (op->nrof) {
2737  return op;
2738  } else {
2740  return NULL;
2741  }
2742 }
2743 
2754 static void object_increase_nrof(object *op, uint32_t i) {
2755  object *tmp;
2756 
2757  if (i == 0) /* objects with op->nrof require this check */
2758  return;
2759 
2760  if (QUERY_FLAG(op, FLAG_REMOVED)) {
2761  op->nrof += i;
2762  } else if (op->env != NULL) {
2763  player *pl;
2764  /* is this object in the players inventory, or sub container
2765  * therein?
2766  */
2768  /* nope. Is this a container the player has opened?
2769  * If so, set tmp to that player.
2770  * IMO, searching through all the players will mostly
2771  * likely be quicker than following op->env to the map,
2772  * and then searching the map for a player.
2773  */
2774  if (!tmp) {
2775  for (pl = first_player; pl; pl = pl->next)
2776  if (pl->ob->container == op->env)
2777  break;
2778  if (pl)
2779  tmp = pl->ob;
2780  else
2781  tmp = NULL;
2782  }
2783 
2784  /* Because of weight reduction by container and integer arithmetic,
2785  * there is no guarantee the rounded weight of combined items will be
2786  * the same as the sum of rounded weights.
2787  * Therefore just remove the current weight, and add the new.
2788  * Same adjustment done in object_decrease_nrof().
2789  */
2790  object_sub_weight(op->env, op->weight * op->nrof);
2791  op->nrof += i;
2792  object_add_weight(op->env, op->weight * op->nrof);
2793  if (tmp) {
2795  // Why don't we need to update weight of op->env here?
2796  }
2797  } else {
2798  /* On a map. */
2799  op->nrof += i;
2800 
2801  FOR_MAP_PREPARE(op->map, op->x, op->y, pl)
2802  if (pl->contr) {
2803  pl->contr->socket->update_look = 1;
2804  break;
2805  }
2806  FOR_MAP_FINISH();
2807  }
2808 }
2809 
2824 void object_add_weight(object *op, signed long weight) {
2825  while (op != NULL) {
2826  if (op->type == CONTAINER) {
2827  weight = (signed long)(weight*(100-op->stats.Str)/100);
2828  }
2829  op->carrying += weight;
2830  op = op->env;
2831  }
2832 }
2833 
2848 object *object_insert_in_ob(object *op, object *where) {
2849  object *otmp;
2850 
2851  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
2852  StringBuffer *sb;
2853  char *diff;
2854 
2855  sb = stringbuffer_new();
2856  object_dump(op, sb);
2857  diff = stringbuffer_finish(sb);
2858  LOG(llevError, "Trying to insert (ob) inserted object.\n%s\n", diff);
2859  free(diff);
2860  return op;
2861  }
2862 
2863  if (where == NULL) {
2864  StringBuffer *sb;
2865  char *diff;
2866 
2867  sb = stringbuffer_new();
2868  object_dump(op, sb);
2869  diff = stringbuffer_finish(sb);
2870  LOG(llevError, "Trying to put object in NULL.\n%s\n", diff);
2871  free(diff);
2872  return op;
2873  }
2874  if (where->head) {
2875  LOG(llevDebug, "Warning: Tried to insert object wrong part of multipart object.\n");
2876  }
2877  where = HEAD(where);
2878  if (op->more) {
2879  LOG(llevError, "Tried to insert multipart object %s (%u)\n", op->name, op->count);
2880  return op;
2881  }
2884  if (op->nrof || op->type == SKILL) {
2886  // Since harvesting skills have the same subtype, we need to check our shared string skill name as well
2887  if (op->type == SKILL && tmp->type == SKILL && op->subtype == tmp->subtype && op->skill == tmp->skill) {
2888  // Duplicate skill. Sum exp and total_exp.
2889  LOG(llevDebug, "Merged duplicate skill %s for %s\n", op->arch->name, where->name);
2890  tmp->stats.exp += op->stats.exp;
2891  tmp->total_exp += op->total_exp;
2893  object_free(op, FREE_OBJ_FREE_INVENTORY | FREE_OBJ_NO_DESTROY_CALLBACK); /* free the inserted object */
2894  return tmp;
2895  } else if (object_can_merge(tmp, op)) {
2896  /* return the original object and remove inserted object
2897  * (client needs the original object) */
2898  object_increase_nrof(tmp, op->nrof);
2900  object_free(op, FREE_OBJ_FREE_INVENTORY | FREE_OBJ_NO_DESTROY_CALLBACK); /* free the inserted object */
2901  return tmp;
2902  }
2903  FOR_INV_FINISH();
2904 
2905  /* the item couldn't merge. */
2906  object_add_weight(where, op->weight*op->nrof);
2907  } else
2908  object_add_weight(where, op->weight+op->carrying);
2909 
2910  op->map = NULL;
2911  op->env = where;
2912  op->above = NULL;
2913  op->below = NULL;
2914  op->x = 0,
2915  op->y = 0;
2916  op->ox = 0,
2917  op->oy = 0;
2918 
2919  /* Client has no idea of ordering so lets not bother ordering it here.
2920  * It sure simplifies this function...
2921  */
2922  if (where->inv == NULL)
2923  where->inv = op;
2924  else {
2925  op->below = where->inv;
2926  op->below->above = op;
2927  where->inv = op;
2928  }
2929 
2930  if (op->type == EVENT_CONNECTOR) {
2931  where->event_bitmask |= BITMASK_EVENT(op->subtype);
2932  }
2933 
2934  /* Update in 2 cases: object goes into player's inventory, or object goes into container the player
2935  * is looking into. */
2936  if (where->contr != NULL)
2938  else if (where->type == CONTAINER && QUERY_FLAG(where, FLAG_APPLIED)) {
2939  object *pl = NULL;
2940 
2941  if (op->env->env && op->env->env->contr)
2942  /* Container is in player's inventory. */
2943  pl = op->env->env;
2944  else if (op->env->map) {
2945  /* Container on map, look above for player. */
2946  FOR_ABOVE_PREPARE(op->env, above)
2947  if (above->contr) {
2948  pl = above;
2949  break;
2950  }
2951  FOR_ABOVE_FINISH();
2952  }
2953  if (pl)
2954  esrv_send_item(pl, op);
2955  }
2956 
2958  if (otmp && otmp->contr != NULL) {
2959  if (!QUERY_FLAG(otmp, FLAG_NO_FIX_PLAYER)
2960  && (QUERY_FLAG(op, FLAG_APPLIED) || op->type == SKILL || op->glow_radius != 0))
2961  /* fix_object will only consider applied items, or skills, or items with a glow radius.
2962  thus no need to call it if our object hasn't that. */
2963  fix_object(otmp);
2964  }
2965 
2966  /* reset the light list and los of the players on the map */
2967  if (op->glow_radius != 0 && where->map) {
2968 #ifdef DEBUG_LIGHTS
2969  LOG(llevDebug, " object_insert_in_ob(): got %s to insert in map/op\n", op->name);
2970 #endif /* DEBUG_LIGHTS */
2971  if (MAP_DARKNESS(where->map)) {
2972  SET_MAP_FLAGS(where->map, where->x, where->y, P_NEED_UPDATE);
2973  update_position(where->map, where->x, where->y);
2974  update_all_los(where->map, where->x, where->y);
2975  }
2976  }
2977 
2978  return op;
2979 }
2980 
3003 int object_check_move_on(object *op, object *originator) {
3004  object *tmp;
3005  tag_t tag;
3006  mapstruct *m = op->map;
3007  int x = op->x, y = op->y;
3008  MoveType move_on, move_slow, move_block;
3009 
3010  if (QUERY_FLAG(op, FLAG_NO_APPLY))
3011  return 0;
3012 
3013  tag = op->count;
3014 
3015  move_on = GET_MAP_MOVE_ON(op->map, op->x, op->y);
3016  move_slow = GET_MAP_MOVE_SLOW(op->map, op->x, op->y);
3017  move_block = GET_MAP_MOVE_BLOCK(op->map, op->x, op->y);
3018 
3019  /* if nothing on this space will slow op down or be applied,
3020  * no need to do checking below. have to make sure move_type
3021  * is set, as lots of objects don't have it set - we treat that
3022  * as walking.
3023  */
3024  if (op->move_type
3025  && !(op->move_type&move_on)
3026  && !(op->move_type&move_slow))
3027  return 0;
3028 
3029  /* This is basically inverse logic of that below - basically,
3030  * if the object can avoid the move on or slow move, they do so,
3031  * but can't do it if the alternate movement they are using is
3032  * blocked. Logic on this seems confusing, but does seem correct.
3033  */
3034  if ((op->move_type&~move_on&~move_block) != 0
3035  && (op->move_type&~move_slow&~move_block) != 0)
3036  return 0;
3037 
3038  /* The objects have to be checked from top to bottom.
3039  * Hence, we first go to the top:
3040  */
3041 
3042  tmp = GET_MAP_OB(op->map, op->x, op->y);
3044  if (tmp->above == NULL)
3045  break;
3046  /* Trim the search when we find the first other spell effect
3047  * this helps performance so that if a space has 50 spell objects,
3048  * we don't need to check all of them.
3049  */
3050  if ((tmp->move_type&MOVE_FLY_LOW) && QUERY_FLAG(tmp, FLAG_NO_PICK))
3051  break;
3054  if (tmp == op)
3055  continue; /* Can't apply yourself */
3056 
3057  /* Check to see if one of the movement types should be slowed down.
3058  * Second check makes sure that the movement types not being slowed
3059  * (~slow_move) is not blocked on this space - just because the
3060  * space doesn't slow down swimming (for example), if you can't actually
3061  * swim on that space, can't use it to avoid the penalty.
3062  */
3063  if (!QUERY_FLAG(op, FLAG_WIZPASS)) {
3064  if ((!op->move_type && tmp->move_slow&MOVE_WALK)
3065  || ((op->move_type&tmp->move_slow) && (op->move_type&~tmp->move_slow&~tmp->move_block) == 0)) {
3066  float diff;
3067 
3068  diff = tmp->move_slow_penalty*FABS(op->speed);
3069  if (op->type == PLAYER) {
3072  diff /= 4.0;
3073  }
3074  }
3075  op->speed_left -= diff;
3076  }
3077  }
3078 
3079  /* Basically same logic as above, except now for actual apply. */
3080  if ((!op->move_type && tmp->move_on&MOVE_WALK)
3081  || ((op->move_type&tmp->move_on) && (op->move_type&~tmp->move_on&~tmp->move_block) == 0)) {
3082  ob_move_on(tmp, op, originator);
3083  if (object_was_destroyed(op, tag))
3084  return 1;
3085 
3086  /* what the person/creature stepped onto has moved the object
3087  * someplace new. Don't process any further - if we did,
3088  * have a feeling strange problems would result.
3089  */
3090  if (op->map != m || op->x != x || op->y != y)
3091  return 0;
3092  }
3094  return 0;
3095 }
3096 
3109 object *map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at) {
3110  if (m == NULL || OUT_OF_REAL_MAP(m, x, y)) {
3111  LOG(llevError, "Present_arch called outside map.\n");
3112  return NULL;
3113  }
3114 
3115  FOR_MAP_PREPARE(m, x, y, tmp)
3116  if (tmp->arch == at)
3117  return tmp;
3118  FOR_MAP_FINISH();
3119 
3120  return NULL;
3121 }
3122 
3136 object *map_find_by_type(mapstruct *m, int x, int y, uint8_t type) {
3137  if (OUT_OF_REAL_MAP(m, x, y)) {
3138  return NULL;
3139  }
3140 
3141  FOR_MAP_PREPARE(m, x, y, tmp)
3142  if (tmp->type == type)
3143  return tmp;
3144  FOR_MAP_FINISH();
3145 
3146  return NULL;
3147 }
3148 
3159 object *object_present_in_ob(uint8_t type, const object *op) {
3160  object *tmp;
3161 
3162  for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
3163  if (tmp->type == type)
3164  return tmp;
3165 
3166  return NULL;
3167 }
3168 
3194 object *object_present_in_ob_by_name(int type, const char *str, const object *op) {
3195  object *tmp;
3196 
3197  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
3198  if ((type == -1 || tmp->type == type) && !strcmp(str, tmp->name))
3199  return tmp;
3200  }
3201  return NULL;
3202 }
3203 
3213 object *arch_present_in_ob(const archetype *at, const object *op) {
3214  object *tmp;
3215 
3216  for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
3217  if (tmp->arch == at)
3218  return tmp;
3219  return NULL;
3220 }
3221 
3230 void object_set_flag_inv(object*op, int flag) {
3231  object *tmp;
3232 
3233  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
3234  SET_FLAG(tmp, flag);
3235  object_set_flag_inv(tmp, flag);
3236  }
3237 }
3238 
3247 void object_unset_flag_inv(object*op, int flag) {
3248  object *tmp;
3249 
3250  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
3251  CLEAR_FLAG(tmp, flag);
3252  object_unset_flag_inv(tmp, flag);
3253  }
3254 }
3255 
3265 void object_set_cheat(object *op) {
3268 }
3269 
3287 int object_find_multi_free_spot_around(const object *ob, const object *gen, int16_t *hx, int16_t *hy) {
3288  int genx, geny, genx2, geny2, sx, sy, sx2, sy2, ix, iy, nx, ny, i, flag;
3289  int freecount = 0;
3290 
3291  ob = HEAD(ob);
3292 
3293  object_get_multi_size(ob, &sx, &sy, &sx2, &sy2);
3294  object_get_multi_size(gen, &genx, &geny, &genx2, &geny2);
3295  /*
3296  * sx and sy are now the coords of the bottom right corner of ob relative to the head.
3297  * genx and geny are now the coords of the bottom right corner of gen relative to the head.
3298  * sx2 and sy2 are now the coords of the head of ob relative to the top left corner.
3299  * genx2 and geny2 are now the coords of the head of gen relative to the top left corner.
3300  */
3301 
3302  sx++;
3303  sy++;
3304  genx++;
3305  geny++;
3306  /*
3307  * sx, sy, genx, and geny, are now the size of the object, excluding parts left and above
3308  * the head.
3309  */
3310 
3311  ix = gen->x-sx-genx2;
3312  iy = gen->y-sy-geny2;
3313  sx += genx+sx2;
3314  sy += geny+sy2;
3315  /*
3316  * ix and iy are the map coords of the top left square where the head of ob could possibly
3317  * be placed. sx and sy are now the size of the square to search for placement of the head
3318  * relative to ix and iy.
3319  */
3320 
3321  /*
3322  * Loop around the square of possible positions for the head of ob object:
3323  */
3324  for (i = 0; i < (sx+sx+sy+sy); i++) {
3325  if (i <= sx) {
3326  nx = i+ix;
3327  ny = iy;
3328  } else if (i <= sx+sy) {
3329  nx = ix+sx;
3330  ny = iy+i-sx;
3331  } else if (i <= sx+sy+sx) {
3332  nx = ix+sx-(i-(sx+sy));
3333  ny = iy+sy;
3334  } else {
3335  nx = ix;
3336  ny = iy+sy-(i-(sx+sy+sx));
3337  }
3338  /* Check if the spot is free. */
3339  flag = ob_blocked(ob, gen->map, nx, ny);
3340  if (!flag) {
3341  freecount++;
3342  }
3343  }
3344  /* If no free spaces, return. */
3345  if (!freecount)
3346  return -1;
3347 
3348  /* Choose a random valid position */
3349  freecount = RANDOM()%freecount;
3350  for (i = 0; i < sx+sx+sy+sy; i++) {
3351  if (i <= sx) {
3352  nx = i+ix;
3353  ny = iy;
3354  } else if (i <= sx+sy) {
3355  nx = ix+sx;
3356  ny = iy+i-sx;
3357  } else if (i <= sx+sy+sx) {
3358  nx = ix+sx-(i-(sx+sy));
3359  ny = iy+sy;
3360  } else {
3361  nx = ix;
3362  ny = iy+sy-(i-(sx+sy+sx));
3363  }
3364 
3365  /* Make sure it's within map. */
3366  if (nx < 0 || nx >= MAP_WIDTH(gen->map)
3367  || ny < 0 || ny >= MAP_HEIGHT(gen->map))
3368  continue;
3369 
3370  /* Check if the spot is free.*/
3371  flag = ob_blocked(ob, gen->map, nx, ny);
3372  if (!flag) {
3373  freecount--;
3374  if (freecount <= 0) {
3375  *hx = nx;
3376  *hy = ny;
3377  return 0;
3378  }
3379  }
3380  }
3381  return -1;
3382 }
3383 
3403 int object_find_multi_free_spot_within_radius(const object *ob, const object *gen, int *hx, int *hy) {
3404  int genx, geny, genx2, geny2, sx, sy, sx2, sy2, ix, iy, nx, ny, i, flag;
3405  int8_t x, y, radius;
3406  int freecount = 0, freecountstop = 0;
3407  const char *value;
3408  int8_t *x_array;
3409  int8_t *y_array;
3410 
3411  /* If radius is not set, default to 1 */
3412  value = object_get_value(gen, "generator_radius");
3413  if (value) {
3414  radius = (int8_t)strtol(value, NULL, 10);
3415  if (radius < 1) {
3416  radius = 1;
3417  }
3418  } else {
3419  radius = 1;
3420  }
3421 
3422  ob = HEAD(ob);
3423 
3424  object_get_multi_size(ob, &sx, &sy, &sx2, &sy2);
3425  object_get_multi_size(gen, &genx, &geny, &genx2, &geny2);
3426  /*
3427  * sx and sy are now the coords of the bottom right corner
3428  * of ob relative to the head.
3429  * genx and geny are now the coords of the bottom right corner
3430  * of gen relative to the head.
3431  * sx2 and sy2 are now the coords of the head of ob relative
3432  * to the top left corner.
3433  * genx2 and geny2 are now the coords of the head of gen relative
3434  * to the top left corner.
3435  */
3436 
3437  sx++;
3438  sy++;
3439  genx++;
3440  geny++;
3441  /*
3442  * sx, sy, genx, and geny, are now the size of the object,
3443  * excluding parts left and above the head.
3444  */
3445 
3446  ix = gen->x-sx-genx2-radius+1;
3447  iy = gen->y-sy-geny2-radius+1;
3448  sx += genx+sx2+radius*2-1;
3449  sy += geny+sy2+radius*2-1;
3450 
3451  /*
3452  * ix and iy are the map coords of the top left square where
3453  * the head of ob could possibly be placed. sx and sy are now
3454  * the size of the square to search for placement of the head
3455  * relative to ix and iy.
3456  */
3457 
3458  /* Create arrays large enough to hold free space coordinates */
3459  x_array = static_cast<int8_t *>(malloc(sx*sy*sizeof(int8_t)));
3460  y_array = static_cast<int8_t *>(malloc(sx*sy*sizeof(int8_t)));
3461 
3462  /*
3463  * Loop through the area of possible positions for the head of ob object:
3464  */
3465  for (x = 0; x < sx; x++) {
3466  for (y = 0; y < sy; y++) {
3467  nx = ix+x;
3468  ny = iy+y;
3469 
3470 
3471  /* Make sure it's within map. */
3472  if (get_map_flags(gen->map, NULL, nx, ny, NULL, NULL)&P_OUT_OF_MAP) {
3473  continue;
3474  }
3475 
3476  /* Check if the spot is free. */
3477  flag = ob_blocked(ob, gen->map, nx, ny);
3478  if (!flag) {
3479  x_array[freecount] = nx;
3480  y_array[freecount] = ny;
3481  freecount++;
3482  }
3483  }
3484  }
3485  /* If no free spaces, return. */
3486  if (!freecount) {
3487  free(x_array);
3488  free(y_array);
3489  return -1;
3490  }
3491 
3492  /* Choose a random valid position */
3493  freecountstop = RANDOM()%freecount;
3494  for (i = 0; i < freecount; i++) {
3495  nx = x_array[i];
3496  ny = y_array[i];
3497 
3498  /* Check if the spot is free.*/
3499  flag = ob_blocked(ob, gen->map, nx, ny);
3500  if (!flag) {
3501  freecountstop--;
3502  if (freecountstop <= 0) {
3503  *hx = nx;
3504  *hy = ny;
3505  free(x_array);
3506  free(y_array);
3507  return 0;
3508  }
3509  }
3510  }
3511  free(x_array);
3512  free(y_array);
3513  return -1;
3514 }
3515 
3550 int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop) {
3551  int i, index = 0, flag;
3552  static int altern[SIZEOFFREE];
3553 
3554  for (i = start; i < stop; i++) {
3555  flag = ob_blocked(ob, m, x+freearr_x[i], y+freearr_y[i]);
3556  if (!flag)
3557  altern[index++] = i;
3558 
3559  /* Basically, if we find a wall on a space, we cut down the search size.
3560  * In this way, we won't return spaces that are on another side of a wall.
3561  * This mostly work, but it cuts down the search size in all directions -
3562  * if the space being examined only has a wall to the north and empty
3563  * spaces in all the other directions, this will reduce the search space
3564  * to only the spaces immediately surrounding the target area, and
3565  * won't look 2 spaces south of the target space.
3566  */
3567  else if ((flag&AB_NO_PASS) && maxfree[i] < stop)
3568  stop = maxfree[i];
3569  }
3570  if (!index)
3571  return -1;
3572  return altern[RANDOM()%index];
3573 }
3574 
3590 int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y) {
3591  int i;
3592 
3593  for (i = 0; i < SIZEOFFREE; i++) {
3594  if (!ob_blocked(ob, m, x+freearr_x[i], y+freearr_y[i]))
3595  return i;
3596  }
3597  return -1;
3598 }
3599 
3609 static void permute(int *arr, int begin, int end) {
3610  int i, j, tmp, len;
3611 
3612  len = end-begin;
3613  for (i = begin; i < end; i++) {
3614  j = begin+RANDOM()%len;
3615 
3616  tmp = arr[i];
3617  arr[i] = arr[j];
3618  arr[j] = tmp;
3619  }
3620 }
3621 
3633 void get_search_arr(int *search_arr) {
3634  int i;
3635 
3636  for (i = 0; i < SIZEOFFREE; i++) {
3637  search_arr[i] = i;
3638  }
3639 
3640  permute(search_arr, 1, SIZEOFFREE1+1);
3641  permute(search_arr, SIZEOFFREE1+1, SIZEOFFREE2+1);
3642  permute(search_arr, SIZEOFFREE2+1, SIZEOFFREE);
3643 }
3644 
3652 int object_distance(const object *ob1, const object *ob2) {
3653  int i;
3654 
3655  i = (ob1->x-ob2->x)*(ob1->x-ob2->x)+
3656  (ob1->y-ob2->y)*(ob1->y-ob2->y);
3657  return i;
3658 }
3659 
3668 int find_dir_2(int x, int y) {
3669  int q;
3670 
3671  if (!y)
3672  q = -300*x;
3673  else
3674  q = x*100/y;
3675  if (y > 0) {
3676  if (q < -242)
3677  return 3;
3678  if (q < -41)
3679  return 2;
3680  if (q < 41)
3681  return 1;
3682  if (q < 242)
3683  return 8;
3684  return 7;
3685  }
3686  if (q < -242)
3687  return 7;
3688  if (q < -41)
3689  return 6;
3690  if (q < 41)
3691  return 5;
3692  if (q < 242)
3693  return 4;
3694  return 3;
3695 }
3696 
3705 int absdir(int d) {
3706  // Shortcut for modulus that work becuase we have a power of 2
3707  d &= 7;
3708  // 0 needs to be 8
3709  if (!d)
3710  d = 8;
3711  return d;
3712 }
3713 
3723 int dirdiff(int dir1, int dir2) {
3724  int d;
3725 
3726  d = abs(dir1-dir2);
3727  if (d > 4)
3728  d = 8-d;
3729  return d;
3730 }
3731 
3743 static const int reduction_dir[SIZEOFFREE][3] = {
3744  { 0, 0, 0 }, /* 0 */
3745  { 0, 0, 0 }, /* 1 */
3746  { 0, 0, 0 }, /* 2 */
3747  { 0, 0, 0 }, /* 3 */
3748  { 0, 0, 0 }, /* 4 */
3749  { 0, 0, 0 }, /* 5 */
3750  { 0, 0, 0 }, /* 6 */
3751  { 0, 0, 0 }, /* 7 */
3752  { 0, 0, 0 }, /* 8 */
3753  { 8, 1, 2 }, /* 9 */
3754  { 1, 2, -1 }, /* 10 */
3755  { 2, 10, 12 }, /* 11 */
3756  { 2, 3, -1 }, /* 12 */
3757  { 2, 3, 4 }, /* 13 */
3758  { 3, 4, -1 }, /* 14 */
3759  { 4, 14, 16 }, /* 15 */
3760  { 5, 4, -1 }, /* 16 */
3761  { 4, 5, 6 }, /* 17 */
3762  { 6, 5, -1 }, /* 18 */
3763  { 6, 20, 18 }, /* 19 */
3764  { 7, 6, -1 }, /* 20 */
3765  { 6, 7, 8 }, /* 21 */
3766  { 7, 8, -1 }, /* 22 */
3767  { 8, 22, 24 }, /* 23 */
3768  { 8, 1, -1 }, /* 24 */
3769  { 24, 9, 10 }, /* 25 */
3770  { 9, 10, -1 }, /* 26 */
3771  { 10, 11, -1 }, /* 27 */
3772  { 27, 11, 29 }, /* 28 */
3773  { 11, 12, -1 }, /* 29 */
3774  { 12, 13, -1 }, /* 30 */
3775  { 12, 13, 14 }, /* 31 */
3776  { 13, 14, -1 }, /* 32 */
3777  { 14, 15, -1 }, /* 33 */
3778  { 33, 15, 35 }, /* 34 */
3779  { 16, 15, -1 }, /* 35 */
3780  { 17, 16, -1 }, /* 36 */
3781  { 18, 17, 16 }, /* 37 */
3782  { 18, 17, -1 }, /* 38 */
3783  { 18, 19, -1 }, /* 39 */
3784  { 41, 19, 39 }, /* 40 */
3785  { 19, 20, -1 }, /* 41 */
3786  { 20, 21, -1 }, /* 42 */
3787  { 20, 21, 22 }, /* 43 */
3788  { 21, 22, -1 }, /* 44 */
3789  { 23, 22, -1 }, /* 45 */
3790  { 45, 47, 23 }, /* 46 */
3791  { 23, 24, -1 }, /* 47 */
3792  { 24, 9, -1 } /* 48 */
3793 };
3794 
3813 int can_see_monsterP(mapstruct *m, int x, int y, int dir) {
3814  int16_t dx, dy;
3815  int mflags;
3816 
3817  if (dir < 0)
3818  return 0; /* exit condition: invalid direction */
3819 
3820  dx = x+freearr_x[dir];
3821  dy = y+freearr_y[dir];
3822 
3823  mflags = get_map_flags(m, &m, dx, dy, &dx, &dy);
3824 
3825  /* This functional arguably was incorrect before - it was
3826  * checking for P_WALL - that was basically seeing if
3827  * we could move to the monster - this is being more
3828  * literal on if we can see it. To know if we can actually
3829  * move to the monster, we'd need the monster passed in or
3830  * at least its move type.
3831  */
3832  if (mflags&(P_OUT_OF_MAP|P_BLOCKSVIEW))
3833  return 0;
3834 
3835  /* yes, can see. */
3836  if (dir < 9)
3837  return 1;
3838  return can_see_monsterP(m, x, y, reduction_dir[dir][0])|
3839  can_see_monsterP(m, x, y, reduction_dir[dir][1])|
3840  can_see_monsterP(m, x, y, reduction_dir[dir][2]);
3841 }
3842 
3858 int object_can_pick(const object *who, const object *item) {
3859  /* I re-wrote this as a series of if statements
3860  * instead of a nested return (foo & bar && yaz)
3861  * - I think this is much more readable,
3862  * and likely compiler effectively optimizes it the
3863  * same.
3864  */
3865  if (item->weight <= 0)
3866  return 0;
3868  return 0;
3869  if (QUERY_FLAG(item, FLAG_ALIVE))
3870  return 0;
3871  if (item->invisible)
3872  return 0;
3873  if (item->type == TRANSPORT && item->contr != NULL) {
3874  return 0;
3875  }
3876 
3877  /* Weight limit for monsters */
3878  if (who->type != PLAYER && ((uint32_t)(who->weight+who->carrying+item->weight)) > get_weight_limit(who->stats.Str))
3879  return 0;
3880 
3881  /* Can not pick up multipart objects */
3882  if (item->head || item->more)
3883  return 0;
3884 
3885  /* Everything passes, so OK to pick up */
3886  return 1;
3887 }
3888 
3900 object *object_create_clone(object *asrc) {
3901  object *dst = NULL, *tmp, *src, *part, *prev;
3902 
3903  if (!asrc)
3904  return NULL;
3905  src = HEAD(asrc);
3906 
3907  prev = NULL;
3908  for (part = src; part; part = part->more) {
3909  tmp = object_new();
3910  object_copy(part, tmp);
3911  /*
3912  * Need to reset the weight, since object_insert_in_ob() later will
3913  * recompute this field.
3914  */
3915  tmp->carrying = tmp->arch->clone.carrying;
3916  tmp->x -= src->x;
3917  tmp->y -= src->y;
3918  if (!part->head) {
3919  dst = tmp;
3920  tmp->head = NULL;
3921  } else {
3922  tmp->head = dst;
3923  }
3924  tmp->more = NULL;
3925  if (prev)
3926  prev->more = tmp;
3927  prev = tmp;
3928  }
3929  /*** copy inventory ***/
3930  FOR_INV_PREPARE(src, item)
3932  FOR_INV_FINISH();
3933 
3934  return dst;
3935 }
3936 
3947 object *object_find_by_name(const object *who, const char *name) {
3948  const char *name_shared = add_string(name);
3949  object *tmp;
3950 
3951  for (tmp = who->inv; tmp; tmp = tmp->below)
3952  if (tmp->name == name_shared)
3953  break;
3954  free_string(name_shared);
3955  return tmp;
3956 }
3957 
3971 object *object_find_by_type(const object *who, int type) {
3972  object *tmp;
3973 
3974  for (tmp = who->inv; tmp; tmp = tmp->below)
3975  if (tmp->type == type)
3976  return tmp;
3977 
3978  return NULL;
3979 }
3980 
3995 object *object_find_by_type_without_flags(const object *who, int type, int *flags, int num_flags) {
3996  int flag_okay;
3997  for (object *tmp = who->inv; tmp; tmp = tmp->below)
3998  if (tmp->type == type) {
3999  flag_okay = 1;
4000  for (int i = 0; i < num_flags; ++i) {
4001  if (QUERY_FLAG(tmp, flags[i])) {
4002  flag_okay = 0; // A flag we didn't want set was set. Skip this item.
4003  break;
4004  }
4005  }
4006  if (flag_okay) // If flag_okay == 1, then the flags specified were not set
4007  return tmp; // If we reach here, none of the flags specified were set. Just like we wanted.
4008  }
4009 
4010  return NULL;
4011 }
4012 
4028 object *object_find_by_type2(const object *who, int type1, int type2) {
4029  object *tmp;
4030 
4031  for (tmp = who->inv; tmp; tmp = tmp->below)
4032  if (tmp->type == type1 || tmp->type == type2)
4033  return tmp;
4034 
4035  return NULL;
4036 }
4037 
4051 object *object_find_by_tag(const object *who, tag_t tag) {
4052  object *tmp;
4053 
4054  for (tmp = who->inv; tmp; tmp = tmp->below)
4055  if (tmp->count == tag)
4056  return tmp;
4057 
4058  return NULL;
4059 }
4060 
4074 object *object_find_by_type_applied(const object *who, int type) {
4075  object *tmp;
4076 
4077  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4078  if (tmp->type == type && QUERY_FLAG(tmp, FLAG_APPLIED))
4079  return tmp;
4080 
4081  return NULL;
4082 }
4083 
4099 object *object_find_by_type_and_name(const object *who, int type, const char *name) {
4100  object *tmp;
4101 
4102  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4103  if (tmp->type == type && strcmp(tmp->name, name) == 0)
4104  return tmp;
4105 
4106  return NULL;
4107 }
4108 
4124 object *object_find_by_type_and_race(const object *who, int type, const char *race) {
4125  object *tmp;
4126 
4127  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4128  if (tmp->type == type && strcmp(tmp->race, race) == 0)
4129  return tmp;
4130 
4131  return NULL;
4132 }
4133 
4149 object *object_find_by_type_and_slaying(const object *who, int type, const char *slaying) {
4150  object *tmp;
4151 
4152  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4153  if (tmp->type == type && tmp->slaying != NULL && strcmp(tmp->slaying, slaying) == 0)
4154  return tmp;
4155 
4156  return NULL;
4157 }
4158 
4174 object *object_find_by_type_and_skill(const object *who, int type, const char *skill) {
4175  object *tmp;
4176 
4177  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4178  if (tmp->type == type && tmp->skill != NULL && strcmp(tmp->skill, skill) == 0)
4179  return tmp;
4180 
4181  return NULL;
4182 }
4183 
4197 object *object_find_by_flag(const object *who, int flag) {
4198  object *tmp;
4199 
4200  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4201  if (QUERY_FLAG(tmp, flag))
4202  return tmp;
4203 
4204  return NULL;
4205 }
4206 
4220 object *object_find_by_flag_applied(const object *who, int flag) {
4221  object *tmp;
4222 
4223  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4224  if (QUERY_FLAG(tmp, FLAG_APPLIED) && QUERY_FLAG(tmp, flag))
4225  return tmp;
4226 
4227  return NULL;
4228 }
4229 
4243 object *object_find_by_arch_name(const object *who, const char *name) {
4244  object *tmp;
4245 
4246  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4247  if (strcmp(tmp->arch->name, name) == 0)
4248  return tmp;
4249 
4250  return NULL;
4251 }
4252 
4268 object *object_find_by_type_and_arch_name(const object *who, int type, const char *name) {
4269  object *tmp;
4270 
4271  for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
4272  if (tmp->type == type && strcmp(tmp->arch->name, name) == 0)
4273  return tmp;
4274 
4275  return NULL;
4276 }
4277 
4292 object *object_find_by_type_subtype(const object *who, int type, int subtype) {
4293  object *tmp;
4294 
4295  for (tmp = who->inv; tmp; tmp = tmp->below)
4296  if (tmp->type == type && tmp->subtype == subtype)
4297  return tmp;
4298 
4299  return NULL;
4300 }
4301 
4312 key_value *object_get_key_value(const object *ob, const char *key) {
4313  key_value *link;
4314 
4315  for (link = ob->key_values; link != NULL; link = link->next) {
4316  if (link->key == key) {
4317  return link;
4318  }
4319  }
4320 
4321  return NULL;
4322 }
4323 
4337 const char *object_get_value(const object *op, const char *const key) {
4338  key_value *link;
4339  const char *canonical_key;
4340 
4341  canonical_key = find_string(key);
4342 
4343  if (canonical_key == NULL) {
4344  /* 1. There being a field named key on any object
4345  * implies there'd be a shared string to find.
4346  * 2. Since there isn't, no object has this field.
4347  * 3. Therefore, *this *object doesn't have this field.
4348  */
4349  return NULL;
4350  }
4351 
4352  /* This is copied from object_get_key_value() above -
4353  * only 4 lines, and saves the function call overhead.
4354  */
4355  for (link = op->key_values; link != NULL; link = link->next) {
4356  if (link->key == canonical_key) {
4357  return link->value;
4358  }
4359  }
4360  return NULL;
4361 }
4362 
4367 bool object_value_set(const object *op, const char *const key) {
4368  const char *ret = object_get_value(op, key);
4369  if (ret == NULL || (strcmp(ret, "") == 0) || (strcmp(ret, "0") == 0)) {
4370  return false;
4371  }
4372  return true;
4373 }
4374 
4381 bool object_value_set_shared(const object *op, sstring key) {
4382  for (key_value *link = op->key_values; link != NULL; link = link->next) {
4383  if (link->key == key) {
4384  if ((strcmp(link->value, "") == 0) || (strcmp(link->value, "0") == 0)) {
4385  return false;
4386  }
4387  return true;
4388  }
4389  }
4390  return false;
4391 }
4392 
4407 static int object_set_value_s(object *op, const char *canonical_key, const char *value, int add_key) {
4408  key_value *field = NULL, *last = NULL;
4409 
4410  for (field = op->key_values; field != NULL; field = field->next) {
4411  if (field->key != canonical_key) {
4412  last = field;
4413  continue;
4414  }
4415 
4416  if (field->value)
4417  FREE_AND_CLEAR_STR(field->value);
4418  if (value)
4419  field->value = add_string(value);
4420  else {
4421  /* Basically, if the archetype has this key set,
4422  * we need to store the null value so when we save
4423  * it, we save the empty value so that when we load,
4424  * we get this value back again.
4425  */
4426  if (object_get_key_value(&op->arch->clone, canonical_key))
4427  field->value = NULL;
4428  else {
4429  /* Delete this link */
4430  if (field->key)
4431  FREE_AND_CLEAR_STR(field->key);
4432  if (field->value)
4433  FREE_AND_CLEAR_STR(field->value);
4434  if (last)
4435  last->next = field->next;
4436  else
4437  op->key_values = field->next;
4438  free(field);
4439  }
4440  }
4441  return TRUE;
4442  }
4443  /* IF we get here, key doesn't exist */
4444 
4445  /* No field, we'll have to add it. */
4446 
4447  if (!add_key) {
4448  return FALSE;
4449  }
4450  /* There isn't any good reason to store a null
4451  * value in the key/value list. If the archetype has
4452  * this key, then we should also have it, so shouldn't
4453  * be here. If user wants to store empty strings,
4454  * should pass in ""
4455  */
4456  if (value == NULL)
4457  return TRUE;
4458 
4459  field = static_cast<key_value *>(malloc(sizeof(key_value)));
4460 
4461  field->key = add_refcount(canonical_key);
4462  field->value = add_string(value);
4463  /* Usual prepend-addition. */
4464  field->next = op->key_values;
4465  op->key_values = field;
4466 
4467  return TRUE;
4468 }
4469 
4490 int object_set_value(object *op, const char *key, const char *value, int add_key) {
4491  const char *canonical_key = NULL;
4492  int floating_ref = FALSE;
4493  int ret;
4494 
4495  /* HACK This mess is to make sure set_ob_value() passes a shared string
4496  * to object_get_key_value(), without leaving a leaked refcount.
4497  */
4498 
4499  canonical_key = find_string(key);
4500  if (canonical_key == NULL) {
4501  canonical_key = add_string(key);
4502  floating_ref = TRUE;
4503  }
4504 
4505  ret = object_set_value_s(op, canonical_key, value, add_key);
4506 
4507  if (floating_ref) {
4508  free_string(canonical_key);
4509  }
4510 
4511  return ret;
4512 }
4513 
4565 int object_matches_string(object *pl, object *op, const char *name) {
4566  char *cp, local_name[MAX_BUF], name_op[MAX_BUF], name_short[HUGE_BUF], bname_s[MAX_BUF], bname_p[MAX_BUF];
4567  int count, retval = 0;
4568  /* strtok is destructive to name */
4569  safe_strncpy(local_name, name, sizeof(local_name));
4570  sstring custom_name = object_get_value(op, CUSTOM_NAME_FIELD);
4571 
4572  for (cp = strtok(local_name, ","); cp; cp = strtok(NULL, ",")) {
4573  while (cp[0] == ' ')
4574  ++cp; /* get rid of spaces */
4575 
4576  /* LOG(llevDebug, "Trying to match %s\n", cp);*/
4577  /* All is a very generic match - low match value */
4578  if (!strcmp(cp, "all"))
4579  return 1;
4580 
4581  /* unpaid is a little more specific */
4582  if (!strcmp(cp, "unpaid") && QUERY_FLAG(op, FLAG_UNPAID))
4583  return 2;
4584  if (!strcmp(cp, "cursed")
4587  return 2;
4588 
4589  if (!strcmp(cp, "unlocked") && !QUERY_FLAG(op, FLAG_INV_LOCKED))
4590  return 2;
4591 
4592  /* Allow for things like '100 arrows' */
4593  count = atoi(cp);
4594  if (*cp == '+' || *cp == '-')
4595  count=0; // Let +/- searches look in description for magic bonuses
4596  if (count != 0) {
4597  cp = strchr(cp, ' ');
4598  while (cp && cp[0] == ' ')
4599  ++cp; /* get rid of spaces */
4600  } else {
4601  if (pl->type == PLAYER)
4602  count = pl->contr->count;
4603  else
4604  count = 0;
4605  }
4606 
4607  if (!cp || cp[0] == '\0' || count < 0)
4608  continue;
4609 
4610  /* The code here should go from highest retval to lowest. That
4611  * is because of the 'else' handling - we don't want to match on
4612  * something and set a low retval, even though it may match a higher retcal
4613  * later. So keep it in descending order here, so we try for the best
4614  * match first, and work downward.
4615  */
4616  query_name(op, name_op, MAX_BUF);
4617  query_short_name(op, name_short, HUGE_BUF);
4618  query_base_name(op, 0, bname_s, MAX_BUF);
4619  query_base_name(op, 1, bname_p, MAX_BUF);
4620 
4621  if (!strcasecmp(cp, name_op))
4622  retval = 20;
4623  else if (!strcasecmp(cp, name_short))
4624  retval = 18;
4625  else if (!strcasecmp(cp, bname_s))
4626  retval = 16;
4627  else if (!strcasecmp(cp, bname_p))
4628  retval = 16;
4629  else if (custom_name && !strcasecmp(cp, custom_name))
4630  retval = 15;
4631  else if (!strncasecmp(cp, bname_s, strlen(cp)))
4632  retval = 14;
4633  else if (!strncasecmp(cp, bname_p, strlen(cp)))
4634  retval = 14;
4635  /* Do substring checks, so things like 'Str+1' will match.
4636  * retval of these should perhaps be lower - they are lower
4637  * then the specific strcasecmp aboves, but still higher than
4638  * some other match criteria.
4639  */
4640  else if (strstr(bname_p, cp))
4641  retval = 12;
4642  else if (strstr(bname_s, cp))
4643  retval = 12;
4644  else if (strstr(name_short, cp))
4645  retval = 12;
4646  /* Check against plural/non plural based on count. */
4647  else if (count > 1 && !strcasecmp(cp, op->name_pl)) {
4648  retval = 6;
4649  } else if (count == 1 && !strcasecmp(op->name, cp)) {
4650  retval = 6;
4651  }
4652  /* base name matched - not bad */
4653  else if (strcasecmp(cp, op->name) == 0 && !count)
4654  retval = 4;
4655  /* Check for partial custom name, but give a real low priority */
4656  else if (custom_name && strstr(custom_name, cp))
4657  retval = 3;
4658 
4659  if (retval) {
4660  if (pl->type == PLAYER)
4661  pl->contr->count = count;
4662  return retval;
4663  }
4664  }
4665  return 0;
4666 }
4667 
4676 void object_fix_multipart(object *tmp) {
4677  archetype *at;
4678  object *op, *last;
4679 
4680  if (!tmp->map) {
4681  LOG(llevError, "object_fix_multipart: not on a map!\n");
4682  return;
4683  }
4684 
4685  /* already multipart - don't do anything more */
4686  if (tmp->head || tmp->more)
4687  return;
4688 
4689  /* If there is nothing more to this object, this for loop
4690  * won't do anything.
4691  */
4692  for (at = tmp->arch->more, last = tmp; at != NULL; at = at->more, last = op) {
4693  op = arch_to_object(at);
4694 
4695  /* update x,y coordinates */
4696  op->x += tmp->x;
4697  op->y += tmp->y;
4698  op->head = tmp;
4699  op->map = tmp->map;
4700  last->more = op;
4701  if (tmp->name != op->name) {
4702  if (op->name)
4703  free_string(op->name);
4704  op->name = add_string(tmp->name);
4705  }
4706  if (tmp->title != op->title) {
4707  if (op->title)
4708  free_string(op->title);
4709  op->title = add_string(tmp->title);
4710  }
4711  /* we could link all the parts onto tmp, and then just
4712  * call object_insert_in_map once, but the effect is the same,
4713  * as object_insert_in_map will call itself with each part, and
4714  * the coding is simpler to just to it here with each part.
4715  */
4717  } /* for at = tmp->arch->more */
4718 }
4719 
4735 void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy) {
4736  archetype *part;
4737  int maxx = 0, maxy = 0, minx = 0, miny = 0;
4738 
4739  ob = HEAD(ob);
4740  *sx = 1;
4741  *sy = 1;
4742  if (ob->arch->more) {
4743  for (part = ob->arch; part; part = part->more) {
4744  if (part->clone.x > maxx)
4745  maxx = part->clone.x;
4746  if (part->clone.y > maxy)
4747  maxy = part->clone.y;
4748  if (part->clone.x < minx)
4749  minx = part->clone.x;
4750  if (part->clone.y < miny)
4751  miny = part->clone.y;
4752  }
4753  }
4754  *sx = maxx;
4755  *sy = maxy;
4756  if (hx)
4757  *hx = -minx;
4758  if (hy)
4759  *hy = -miny;
4760 }
4761 
4782 void object_insert_to_free_spot_or_free(object *op, mapstruct *map, int x, int y, int start, int stop, object *originator) {
4783  int pos;
4784 
4785  pos = object_find_free_spot(op, map, x, y, start, stop);
4786  if (pos == -1) {
4788  return;
4789  }
4790 
4791  object_insert_in_map_at(op, map, originator, 0, x+freearr_x[pos], y+freearr_y[pos]);
4792 }
4793 
4802 void object_set_msg(object *op, const char *msg) {
4803  if (op->msg != NULL) {
4804  free_string(op->msg);
4805  }
4806 
4807  if (msg != NULL) {
4808  // If the message does not have a trailing newline, add one.
4809  if (*msg != '\0' && strchr(msg, '\0')[-1] != '\n') {
4812  stringbuffer_append_string(sb, "\n");
4813  op->msg = stringbuffer_finish_shared(sb);
4814  } else {
4815  op->msg = add_string(msg);
4816  }
4817  } else {
4818  op->msg = NULL;
4819  }
4820 }
4821 
4823 const char *const move_name[] = {
4824  "walk",
4825  "fly_low",
4826  "fly_high",
4827  "swim",
4828  "boat",
4829  NULL
4830 };
4831 
4832 /* This array equates the FLAG_ values with the V_ values. Use -1 to
4833  * put gaps in the array that should not be processed.
4834  * The order matches the order of the define values in 'define.h'.
4835  */
4842 static const char *const flag_names[NUM_FLAGS+1] = {
4843  "alive", "wiz", NULL, NULL, "was_wiz", "applied", "unpaid",
4844  "can_use_shield", "no_pick", "client_anim_sync", "client_anim_random", /* 10 */
4845  "is_animated", NULL /* FLAG_DIALOG_PARSED, not saved */,
4846  NULL /* flying */, "monster", "friendly", "generator",
4847  "is_thrown", "auto_apply", "treasure", "player sold", /* 20 */
4848  "see_invisible", "can_roll", "overlay_floor",
4849  "is_turnable", NULL /* walk_off */, NULL /* fly_on */,
4850  NULL /*fly_off*/, "is_used_up", "identified", "reflecting", /* 30 */
4851  "changing", "splitting", "hitback", "startequip",
4852  "blocksview", "undead", "scared", "unaggressive",
4853  "reflect_missile", "reflect_spell", /* 40 */
4854  "no_magic", "no_fix_player", "is_lightable", "tear_down",
4855  "run_away", NULL /*pass_thru */, NULL /*can_pass_thru*/,
4856  NULL /*"pick_up"*/, "unique", "no_drop", /* 50 */
4857  NULL /* wizcast*/, "can_cast_spell", "can_use_scroll", "can_use_range",
4858  "can_use_bow", "can_use_armour", "can_use_weapon",
4859  "can_use_ring", "has_ready_range", "has_ready_bow", /* 60 */
4860  "xrays", NULL, "is_floor", "lifesave", "no_strength", "sleep",
4861  "stand_still", "random_movement", "only_attack", "confused", /* 70 */
4862  "stealth", NULL, NULL, "cursed", "damned",
4863  "see_anywhere", "known_magical", "known_cursed",
4864  "can_use_skill", "been_applied", /* 80 */
4865  "has_ready_scroll", NULL, NULL,
4866  NULL, "make_invisible", "inv_locked", "is_wooded",
4867  "is_hilly", "has_ready_skill", "has_ready_weapon", /* 90 */
4868  "no_skill_ident", "is_blind", "can_see_in_dark", "is_cauldron",
4869  NULL, "no_steal", "one_hit", NULL, "berserk", "neutral", /* 100 */
4870  "no_attack", "no_damage", NULL, NULL, "activate_on_push",
4871  "activate_on_release", "is_water", "use_content_on_gen", NULL, "is_buildable", /* 110 */
4872  NULL, "blessed", "known_blessed"
4873 };
4874 
4884 {
4885  static char retbuf[MAX_BUF], retbuf_all[MAX_BUF];
4886  int i, all_count = 0, count;
4887 
4888  strcpy(retbuf, "");
4889  strcpy(retbuf_all, " all");
4890 
4891  /* Quick check, and probably fairly common */
4892  if (mt == MOVE_ALL) {
4893  stringbuffer_append_string(sb, "all");
4894  return;
4895  }
4896  if (mt == 0) {
4897  stringbuffer_append_string(sb, "0");
4898  return;
4899  }
4900 
4901  /* We basically slide the bits down. Why look at MOVE_ALL?
4902  * because we may want to return a string like 'all -swim',
4903  * and if we just looked at mt, we couldn't get that.
4904  */
4905  for (i = MOVE_ALL, count = 0; i != 0; i >>= 1, count++) {
4906  if (mt&(1<<count)) {
4907  strcat(retbuf, " ");
4908  strcat(retbuf, move_name[count]);
4909  } else {
4910  strcat(retbuf_all, " -");
4911  strcat(retbuf_all, move_name[count]);
4912  all_count++;
4913  }
4914  }
4915  /* Basically, if there is a single negation, return it, eg
4916  * 'all -swim'. But more than that, just return the
4917  * enumerated values. It doesn't make sense to return
4918  * 'all -walk -fly_low' - it is shorter to return 'fly_high swim'
4919  */
4920  if (all_count <= 1)
4921  stringbuffer_append_string(sb, retbuf_all+1);
4922  else
4923  stringbuffer_append_string(sb, retbuf+1);
4924 }
4925 
4927 static inline void ADD_STRINGLINE_ENTRY(StringBuffer *sb, const char *name, const char *value) {
4930  stringbuffer_append_string(sb, "\n");
4931 }
4932 
4934 static inline void FAST_SAVE_LONG(StringBuffer *sb, const char *name, const long value) {
4937  stringbuffer_append_char(sb, '\n');
4938 }
4939 
4941 static inline void FAST_SAVE_DOUBLE(StringBuffer *sb, const char *name, const double value) {
4942  stringbuffer_append_printf(sb, "%s%f\n", name, value);
4943 }
4944 
4952  for (int i = 0; i < 4; i++) {
4953  int idx = ffs((*diff)[i]);
4954  if (idx != 0) {
4955  int bit = idx - 1;
4956  // Clear difference bit.
4957  (*diff)[i] &= ~(1 << bit);
4958  return 32*i + bit;
4959  }
4960  }
4961  return -1;
4962 }
4963 
4977 void get_ob_diff(StringBuffer *sb, const object *op, const object *op2) {
4978  static char buf2[64];
4979  int tmp;
4980  int i;
4981  key_value *my_field;
4982  key_value *arch_field;
4983 
4984  /* This saves the key/value lists. We do it first so that any
4985  * keys that match field names will be overwritten by the loader.
4986  */
4987  for (my_field = op->key_values; my_field != NULL; my_field = my_field->next) {
4988  /* Find the field in the opposing member. */
4989  arch_field = object_get_key_value(op2, my_field->key);
4990 
4991  /* If there's no partnering field, or it's got a different value, save our field. */
4992  if (arch_field == NULL || my_field->value != arch_field->value) {
4993  stringbuffer_append_string(sb, my_field->key);
4994  stringbuffer_append_string(sb, " ");
4995  /* If this is null, then saving it as a space should
4996  * cause it to be null again.
4997  */
4998  if (my_field->value)
4999  stringbuffer_append_string(sb, my_field->value);
5000  stringbuffer_append_string(sb, "\n");
5001  }
5002  }
5003  /* We don't need to worry about the arch's extra fields - they
5004  * will get taken care of the object_copy() function.
5005  */
5006 
5007  if (op->name && op->name != op2->name) {
5008  ADD_STRINGLINE_ENTRY(sb, "name ", op->name);
5009  }
5010  if (op->name_pl && op->name_pl != op2->name_pl) {
5011  ADD_STRINGLINE_ENTRY(sb, "name_pl ", op->name_pl);
5012  }
5013  if (op->anim_suffix && op->anim_suffix != op2->anim_suffix) {
5014  ADD_STRINGLINE_ENTRY(sb, "anim_suffix ", op->anim_suffix);
5015  }
5016  if (op->title && op->title != op2->title) {
5017  ADD_STRINGLINE_ENTRY(sb, "title ", op->title);
5018  }
5019  if (op->race && op->race != op2->race) {
5020  ADD_STRINGLINE_ENTRY(sb, "race ", op->race);
5021  }
5022  if (op->slaying && op->slaying != op2->slaying) {
5023  ADD_STRINGLINE_ENTRY(sb, "slaying ", op->slaying);
5024  }
5025  if (op->skill && op->skill != op2->skill) {
5026  ADD_STRINGLINE_ENTRY(sb, "skill ", op->skill);
5027  }
5028  if (op->msg && op->msg != op2->msg) {
5029  stringbuffer_append_string(sb, "msg\n");
5030  stringbuffer_append_string(sb, op->msg);
5031  stringbuffer_append_string(sb, "endmsg\n");
5032  }
5033  if (op->lore && op->lore != op2->lore) {
5034  stringbuffer_append_string(sb, "lore\n");
5035  stringbuffer_append_string(sb, op->lore);
5036  stringbuffer_append_string(sb, "endlore\n");
5037  }
5038  if (op->other_arch != op2->other_arch && op->other_arch != NULL && op->other_arch->name) {
5039  ADD_STRINGLINE_ENTRY(sb, "other_arch ", op->other_arch->name);
5040  }
5041  if (op->face != op2->face) {
5042  ADD_STRINGLINE_ENTRY(sb, "face ", op->face->name);
5043  }
5044 
5045  if (op->animation != op2->animation) {
5046  if (op->animation) {
5047  ADD_STRINGLINE_ENTRY(sb, "animation ", op->animation->name);
5048  if (!QUERY_FLAG (op, FLAG_ANIMATE)) {
5049  stringbuffer_append_string(sb, "is_animated 0\n");
5050  }
5051  } else {
5052  stringbuffer_append_string(sb, "animation NONE\n");
5053  }
5054  }
5055  if (op->stats.Str != op2->stats.Str)
5056  FAST_SAVE_LONG(sb, "Str ", op->stats.Str);
5057  if (op->stats.Dex != op2->stats.Dex)
5058  FAST_SAVE_LONG(sb, "Dex ", op->stats.Dex);
5059  if (op->stats.Con != op2->stats.Con)
5060  FAST_SAVE_LONG(sb, "Con ", op->stats.Con);
5061  if (op->stats.Wis != op2->stats.Wis)
5062  FAST_SAVE_LONG(sb, "Wis ", op->stats.Wis);
5063  if (op->stats.Pow != op2->stats.Pow)
5064  FAST_SAVE_LONG(sb, "Pow ", op->stats.Pow);
5065  if (op->stats.Cha != op2->stats.Cha)
5066  FAST_SAVE_LONG(sb, "Cha ", op->stats.Cha);
5067  if (op->stats.Int != op2->stats.Int)
5068  FAST_SAVE_LONG(sb, "Int ", op->stats.Int);
5069  if (op->stats.hp != op2->stats.hp)
5070  FAST_SAVE_LONG(sb, "hp ", op->stats.hp);
5071  if (op->stats.maxhp != op2->stats.maxhp)
5072  FAST_SAVE_LONG(sb, "maxhp ", op->stats.maxhp);
5073  if (op->stats.sp != op2->stats.sp)
5074  FAST_SAVE_LONG(sb, "sp ", op->stats.sp);
5075  if (op->stats.maxsp != op2->stats.maxsp)
5076  FAST_SAVE_LONG(sb, "maxsp ", op->stats.maxsp);
5077  if (op->stats.grace != op2->stats.grace)
5078  FAST_SAVE_LONG(sb, "grace ", op->stats.grace);
5079  if (op->stats.maxgrace != op2->stats.maxgrace)
5080  FAST_SAVE_LONG(sb, "maxgrace ", op->stats.maxgrace);
5081 
5082  if (op->stats.exp != op2->stats.exp) {
5083  snprintf(buf2, sizeof(buf2), "%" FMT64, op->stats.exp);
5084  ADD_STRINGLINE_ENTRY(sb, "exp ", buf2);
5085  }
5086 
5087  if (op->total_exp != op2->total_exp) {
5088  snprintf(buf2, sizeof(buf2), "%" FMT64, op->total_exp);
5089  ADD_STRINGLINE_ENTRY(sb, "total_exp ", buf2);
5090  }
5091 
5092  if (op->expmul != op2->expmul)
5093  FAST_SAVE_DOUBLE(sb, "expmul ", op->expmul);
5094  if (op->stats.food != op2->stats.food)
5095  FAST_SAVE_LONG(sb, "food ", op->stats.food);
5096  if (op->stats.dam != op2->stats.dam)
5097  FAST_SAVE_LONG(sb, "dam ", op->stats.dam);
5098  if (op->stats.luck != op2->stats.luck)
5099  FAST_SAVE_LONG(sb, "luck ", op->stats.luck);
5100  if (op->stats.wc != op2->stats.wc)
5101  FAST_SAVE_LONG(sb, "wc ", op->stats.wc);
5102  if (op->stats.ac != op2->stats.ac)
5103  FAST_SAVE_LONG(sb, "ac ", op->stats.ac);
5104  if (op->x != op2->x)
5105  FAST_SAVE_LONG(sb, "x ", op->x);
5106  if (op->y != op2->y)
5107  FAST_SAVE_LONG(sb, "y ", op->y);
5108  if (op->speed != op2->speed) {
5109  FAST_SAVE_DOUBLE(sb, "speed ", op->speed);
5110  }
5111  if (op->speed > 0 && op->speed_left != op2->speed_left) {
5112  FAST_SAVE_DOUBLE(sb, "speed_left ", op->speed_left);
5113  }
5114  if (op->weapon_speed != op2->weapon_speed) {
5115  FAST_SAVE_DOUBLE(sb, "weapon_speed ", op->weapon_speed);
5116  }
5117  if (op->weapon_speed > 0 && op->weapon_speed_left != op2->weapon_speed_left) {
5118  FAST_SAVE_DOUBLE(sb, "weapon_speed_left ", op->weapon_speed_left);
5119  }
5120  if (op->move_status != op2->move_status)
5121  FAST_SAVE_LONG(sb, "move_state ", op->move_status);
5122  if (op->attack_movement != op2->attack_movement)
5123  FAST_SAVE_LONG(sb, "attack_movement ", op->attack_movement);
5124  if (op->nrof != op2->nrof)
5125  FAST_SAVE_LONG(sb, "nrof ", op->nrof);
5126  if (op->level != op2->level)
5127  FAST_SAVE_LONG(sb, "level ", op->level);
5128  if (op->direction != op2->direction)
5129  FAST_SAVE_LONG(sb, "direction ", op->direction);
5130  if (op->type != op2->type)
5131  FAST_SAVE_LONG(sb, "type ", op->type);
5132  if (op->subtype != op2->subtype)
5133  FAST_SAVE_LONG(sb, "subtype ", op->subtype);
5134  if (op->attacktype != op2->attacktype)
5135  FAST_SAVE_LONG(sb, "attacktype ", op->attacktype);
5136 
5137  for (tmp = 0; tmp < NROFATTACKS; tmp++) {
5138  if (op->resist[tmp] != op2->resist[tmp]) {
5139  stringbuffer_append_string(sb, "resist_");
5140  FAST_SAVE_LONG(sb, resist_save[tmp], op->resist[tmp]);
5141  }
5142  }
5143 
5144  if (op->path_attuned != op2->path_attuned)
5145  FAST_SAVE_LONG(sb, "path_attuned ", op->path_attuned);
5146  if (op->path_repelled != op2->path_repelled)
5147  FAST_SAVE_LONG(sb, "path_repelled ", op->path_repelled);
5148  if (op->path_denied != op2->path_denied)
5149  FAST_SAVE_LONG(sb, "path_denied ", op->path_denied);
5150  if (op->material != op2->material)
5151  FAST_SAVE_LONG(sb, "material ", op->material);
5152  if (op->materialname && op->materialname != op2->materialname) {
5153  ADD_STRINGLINE_ENTRY(sb, "materialname ", op->materialname);
5154  }
5155  if (op->value != op2->value)
5156  FAST_SAVE_LONG(sb, "value ", op->value);
5157  if (op->carrying != op2->carrying)
5158  FAST_SAVE_LONG(sb, "carrying ", op->carrying);
5159  if (op->weight != op2->weight)
5160  FAST_SAVE_LONG(sb, "weight ", op->weight);
5161  if (op->invisible != op2->invisible)
5162  FAST_SAVE_LONG(sb, "invisible ", op->invisible);
5163  if (op->state != op2->state)
5164  FAST_SAVE_LONG(sb, "state ", op->state);
5165  if (op->magic != op2->magic)
5166  FAST_SAVE_LONG(sb, "magic ", op->magic);
5167  if (op->last_heal != op2->last_heal)
5168  FAST_SAVE_LONG(sb, "last_heal ", op->last_heal);
5169  if (op->last_sp != op2->last_sp)
5170  FAST_SAVE_LONG(sb, "last_sp ", op->last_sp);
5171  if (op->last_grace != op2->last_grace)
5172  FAST_SAVE_LONG(sb, "last_grace ", op->last_grace);
5173  if (op->last_eat != op2->last_eat)
5174  FAST_SAVE_LONG(sb, "last_eat ", op->last_eat);
5176  FAST_SAVE_LONG(sb, "connected ", tmp);
5177  if (op->glow_radius != op2->glow_radius)
5178  FAST_SAVE_LONG(sb, "glow_radius ", op->glow_radius);
5179  if (op->randomitems != op2->randomitems) {
5180  ADD_STRINGLINE_ENTRY(sb, "randomitems ", op->randomitems ? op->randomitems->name : "none");
5181  }
5182 
5183  if (op->run_away != op2->run_away)
5184  FAST_SAVE_LONG(sb, "run_away ", op->run_away);
5185  if (op->pick_up != op2->pick_up)
5186  FAST_SAVE_LONG(sb, "pick_up ", op->pick_up);
5187  if (op->weight_limit != op2->weight_limit)
5188  FAST_SAVE_LONG(sb, "container ", op->weight_limit);
5189  if (op->will_apply != op2->will_apply)
5190  FAST_SAVE_LONG(sb, "will_apply ", op->will_apply);
5191  if (op->smoothlevel != op2->smoothlevel)
5192  FAST_SAVE_LONG(sb, "smoothlevel ", op->smoothlevel);
5193 
5194  if (op->map_layer != op2->map_layer)
5195  ADD_STRINGLINE_ENTRY(sb, "map_layer ", map_layer_name[op->map_layer]);
5196 
5197  if (op->weapontype && op->weapontype != op2->weapontype) {
5198  FAST_SAVE_LONG(sb, "weapontype ", op->weapontype);
5199  }
5200  if (op->client_type && op->client_type != op2->client_type) {
5201  FAST_SAVE_LONG(sb, "client_type ", op->client_type);
5202  }
5203 
5204  if (op->item_power != op2->item_power) {
5205  FAST_SAVE_LONG(sb, "item_power ", op->item_power);
5206  }
5207 
5208  if (op->duration != op2->duration)
5209  FAST_SAVE_LONG(sb, "duration ", op->duration);
5210 
5211  if (op->range != op2->range)
5212  FAST_SAVE_LONG(sb, "range ", op->range);
5213 
5214  if (op->range_modifier != op2->range_modifier)
5215  FAST_SAVE_LONG(sb, "range_modifier ", op->range_modifier);
5216 
5217  if (op->duration_modifier != op2->duration_modifier)
5218  FAST_SAVE_LONG(sb, "duration_modifier ", op->duration_modifier);
5219 
5220  if (op->dam_modifier != op2->dam_modifier)
5221  FAST_SAVE_LONG(sb, "dam_modifier ", op->dam_modifier);
5222 
5223  if (op->gen_sp_armour != op2->gen_sp_armour) {
5224  FAST_SAVE_LONG(sb, "gen_sp_armour ", op->gen_sp_armour);
5225  }
5226 
5227  /* I've kept the old int move type saving code commented out.
5228  * In an ideal world, we'd know if we want to do a quick
5229  * save (say to a temp map, where we don't care about strings),
5230  * or a slower save/dm dump, where printing out strings is handy.
5231  */
5232  if (op->move_type != op2->move_type) {
5233  /*FAST_SAVE_LONG(sb, "move_type ", op->move_type)*/
5234  stringbuffer_append_string(sb, "move_type ");
5235  get_string_move_type(sb, op->move_type);
5236  stringbuffer_append_string(sb, "\n");
5237  }
5238  if (op->move_block != op2->move_block) {
5239  /*FAST_SAVE_LONG(sb, "move_block ", op->move_block)*/
5240  stringbuffer_append_string(sb, "move_block ");
5241  get_string_move_type(sb, op->move_block);
5242  stringbuffer_append_string(sb, "\n");
5243  }
5244  if (op->move_allow != op2->move_allow) {
5245  /*FAST_SAVE_LONG(sb, "move_allow ", op->move_allow);*/
5246  stringbuffer_append_string(sb, "move_allow ");
5247  get_string_move_type(sb, op->move_allow);
5248  stringbuffer_append_string(sb, "\n");
5249  }
5250  if (op->move_on != op2->move_on) {
5251  /*FAST_SAVE_LONG(sb, "move_on ", op->move_on);*/
5252  stringbuffer_append_string(sb, "move_on ");
5253  get_string_move_type(sb, op->move_on);
5254  stringbuffer_append_string(sb, "\n");
5255  }
5256  if (op->move_off != op2->move_off) {
5257  /*FAST_SAVE_LONG(sb, "move_off ", op->move_off);*/
5258  stringbuffer_append_string(sb, "move_off ");
5259  get_string_move_type(sb, op->move_off);
5260  stringbuffer_append_string(sb, "\n");
5261  }
5262  if (op->move_slow != op2->move_slow) {
5263  /*FAST_SAVE_LONG(sb, "move_slow ", op->move_slow);*/
5264  stringbuffer_append_string(sb, "move_slow ");
5265  get_string_move_type(sb, op->move_slow);
5266  stringbuffer_append_string(sb, "\n");
5267  }
5268 
5269  if (op->move_slow_penalty != op2->move_slow_penalty) {
5270  FAST_SAVE_DOUBLE(sb, "move_slow_penalty ", op->move_slow_penalty);
5271  }
5272 
5273  ob_flags diff_flags;
5274  compare_flags(&diff_flags, op, op2);
5275  int flag;
5276  while ((flag = flags_differ(&diff_flags)) != -1) {
5277  if (flag_names[flag]) {
5278  ADD_STRINGLINE_ENTRY(sb, flag_names[flag], QUERY_FLAG(op, flag) ? " 1" : " 0");
5279  }
5280  }
5281 
5282  /* Save body locations */
5283  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
5284  if (op->body_info[i] != op2->body_info[i]) {
5285  stringbuffer_append_string(sb, body_locations[i].save_name);
5286  FAST_SAVE_LONG(sb, " ", op->body_info[i]);
5287  }
5288  }
5289 }
5290 
5295 void save_object_in_sb(StringBuffer *sb, object *op, const int flag) {
5296  /* If the object has no_save set, just return */
5297  if (QUERY_FLAG(op, FLAG_NO_SAVE)) {
5298  return;
5299  }
5300 
5301  /* Even if the object does have an owner, it would seem that we should
5302  * still save it.
5303  */
5304  if (object_get_owner(op) != NULL) {
5305  return;
5306  }
5307 
5308  /* If it is unpaid and we don't want to save those, just return. */
5309  if (!(flag&SAVE_FLAG_SAVE_UNPAID) && (QUERY_FLAG(op, FLAG_UNPAID))) {
5310  return;
5311  }
5312 
5313  archetype *at = op->arch;
5314  if (at == NULL)
5315  at = empty_archetype;
5316 
5317  ADD_STRINGLINE_ENTRY(sb, "arch ", at->name);
5318 
5319  if (at->reference_count > 0) {
5320  /* The object is a custom item/monster, so we handle its save differently.
5321  * We compare the custom archetype to the "original" one, then only save hp/gr/sp
5322  * which are the only values we can't recompute later - all others are modified by items in inventory.
5323  * Note that hp/gr/sp will appear twice in save, but last value will take precedence.
5324  */
5325  archetype *original = find_archetype(at->name);
5326  if (!original) {
5327  LOG(llevError, "could not find original archetype %s for custom monster!\n", at->name);
5328  abort();
5329  }
5330  get_ob_diff(sb, &at->clone, &original->clone);
5331  if (op->stats.hp != at->clone.stats.hp)
5332  FAST_SAVE_LONG(sb, "hp ", op->stats.hp);
5333  if (op->stats.sp != at->clone.stats.sp)
5334  FAST_SAVE_LONG(sb, "sp ", op->stats.sp);
5335  if (op->stats.grace != at->clone.stats.grace)
5336  FAST_SAVE_LONG(sb, "grace ", op->stats.grace);
5337  if (op->x != at->clone.x)
5338  FAST_SAVE_LONG(sb, "x ", op->x);
5339  if (op->y != at->clone.y)
5340  FAST_SAVE_LONG(sb, "y ", op->y);
5341  } else if (op->artifact != NULL) {
5342  /* if op is an artifact, then find the "standard" artifact to use that for the diff */
5343  object *base;
5344  const artifact *artifact;
5345 
5346  artifact = find_artifact(op, op->artifact);
5347  if (artifact == NULL) {
5348  LOG(llevError, "could not find artifact %s [%d] to save data\n", op->artifact, op->type);
5349  get_ob_diff(sb, op, &at->clone);
5350  } else {
5351  ADD_STRINGLINE_ENTRY(sb, "artifact ", op->artifact);
5352  base = arch_to_object(at);
5354  get_ob_diff(sb, op, base);
5356  }
5357  } else {
5358  get_ob_diff(sb, op, &at->clone);
5359  }
5360 
5361  /* Eneq(@csd.uu.se): Added this to allow containers being saved with contents*/
5363  save_object_in_sb(sb, tmp, flag);
5364  FOR_INV_FINISH();
5365 
5366  stringbuffer_append_string(sb, "end\n");
5367 }
5368 
5381 int save_object(FILE *fp, object *op, int flag) {
5383  save_object_in_sb(sb, op, flag);
5384  char *cp = stringbuffer_finish(sb);
5385  if (fputs(cp, fp) == EOF) {
5386  free(cp);
5387  return SAVE_ERROR_WRITE;
5388  } else {
5389  free(cp);
5390  return SAVE_ERROR_OK;
5391  }
5392 }
5393 
5395  if (op->map) {
5396  sstring death_animation = object_get_value(op, "death_animation");
5397  if (death_animation != NULL) {
5398  object *death = create_archetype(death_animation);
5399 
5400  if (death != NULL) {
5401  object_insert_in_map_at(death, op->map, op, 0, op->x, op->y);
5402  if (death->arch->more)
5403  object_fix_multipart(death);
5404  }
5405  }
5406  }
5407 }
5408 
5409 object *find_force(object *op, const char *name) {
5410  assert(op != NULL);
5412 }
5413 
5414 object *add_force(object *op, const char *name, int duration) {
5415  assert(op != NULL);
5416  object *force = find_force(op, name);
5417  if (force == NULL) {
5419  force->slaying = add_string(name);
5421  }
5422 
5423  if (duration != 0) {
5424  force->speed = 0.01;
5425  force->speed_left = -duration;
5426  } else {
5427  force->speed = 0;
5428  }
5429 
5430  // Even if duration is zero, a force could be set previously.
5432 
5433  return force;
5434 }
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Definition: object.h:70
object_value_set
bool object_value_set(const object *op, const char *const key)
Definition: object.cpp:4367
free_objects
static object * free_objects
Definition: object.cpp:295
object::name_pl
sstring name_pl
Definition: object.h:323
give.next
def next
Definition: give.py:44
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Definition: map.h:171
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:524
object::weapon_speed_left
float weapon_speed_left
Definition: object.h:340
PLAYER
@ PLAYER
Definition: object.h:112
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:536
UPD_FACE
#define UPD_FACE
Definition: newclient.h:306
object_find_by_type_subtype
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Definition: object.cpp:4292
object_clear_owner
void object_clear_owner(object *op)
Definition: object.cpp:823
first_player
player * first_player
Definition: init.cpp:106
settings
struct Settings settings
Definition: init.cpp:139
permute
static void permute(int *, int, int)
Definition: object.cpp:3609
object::range_modifier
uint8_t range_modifier
Definition: object.h:416
object::move_status
int32_t move_status
Definition: object.h:400
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:573
object_update_turn_face
void object_update_turn_face(object *op)
Definition: object.cpp:1327
UP_OBJ_REMOVE
#define UP_OBJ_REMOVE
Definition: object.h:522
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:1778
object_find_by_type_applied
object * object_find_by_type_applied(const object *who, int type)
Definition: object.cpp:4074
NUM_BODY_LOCATIONS
#define NUM_BODY_LOCATIONS
Definition: object.h:15
MAP_SAVING
#define MAP_SAVING
Definition: map.h:130
object::weapontype
uint32_t weapontype
Definition: object.h:381
object::map_layer
uint8_t map_layer
Definition: object.h:432
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:173
statistics
struct Statistics statistics
Definition: init.cpp:232
llevError
@ llevError
Definition: logger.h:11
object_set_flag_inv
void object_set_flag_inv(object *op, int flag)
Definition: object.cpp:3230
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:232
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:353
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:4927
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:477
player
Definition: player.h:105
object::client_type
uint16_t client_type
Definition: object.h:350
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
SIZEOFFREE1
#define SIZEOFFREE1
Definition: define.h:153
CFweardisguise.tag
tag
Definition: CFweardisguise.py:25
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:3109
FLAG_IS_TURNABLE
#define FLAG_IS_TURNABLE
Definition: define.h:256
object_merge
object * object_merge(object *op, object *top)
Definition: object.cpp:2046
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:2107
BITMASK_EVENT
#define BITMASK_EVENT(evt)
Definition: events.h:62
SET_MAP_TOP
#define SET_MAP_TOP(M, X, Y, tmp)
Definition: map.h:178
object::item_power
int8_t item_power
Definition: object.h:372
object::arch
struct archetype * arch
Definition: object.h:422
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
object::attack_movement
uint16_t attack_movement
Definition: object.h:401
absdir
int absdir(int d)
Definition: object.cpp:3705
UPD_WEIGHT
#define UPD_WEIGHT
Definition: newclient.h:305
flag_names
static const char *const flag_names[NUM_FLAGS+1]
Definition: object.cpp:4842
object::range
int8_t range
Definition: object.h:415
object::speed
float speed
Definition: object.h:337
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:4782
object::invisible
int16_t invisible
Definition: object.h:370
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:246
object::x
int16_t x
Definition: object.h:335
OB_SPELL_TAG_MATCH
#define OB_SPELL_TAG_MATCH(op, count)
Definition: object.h:95
object_dump_all
void object_dump_all(void)
Definition: object.cpp:704
player::transport
object * transport
Definition: player.h:214
object::speed_left
float speed_left
Definition: object.h:338
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:371
object::map
struct mapstruct * map
Definition: object.h:305
object::anim_suffix
sstring anim_suffix
Definition: object.h:324
key_value
Definition: object.h:42
object_find_first_free_spot
int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y)
Definition: object.cpp:3590
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:3213
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:4407
guildjoin.ob
ob
Definition: guildjoin.py:42
object::expmul
double expmul
Definition: object.h:405
object_handle_death_animation
void object_handle_death_animation(object *op)
Definition: object.cpp:5394
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:196
object_reset
void object_reset(object *op)
Definition: object.cpp:934
SKILL
@ SKILL
Definition: object.h:148
object::direction
int8_t direction
Definition: object.h:344
flags
static const flag_definition flags[]
Definition: gridarta-types-convert.cpp:101
object::count
tag_t count
Definition: object.h:307
Ice.tmp
int tmp
Definition: Ice.py:207
object::last_grace
int16_t last_grace
Definition: object.h:369
RUNE
@ RUNE
Definition: object.h:245
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.cpp:1192
object::smoothlevel
uint8_t smoothlevel
Definition: object.h:431
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:4220
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:3403
object_find_by_type_and_skill
object * object_find_by_type_and_skill(const object *who, int type, const char *skill)
Definition: object.cpp:4174
GET_MAP_PLAYER
#define GET_MAP_PLAYER(M, X, Y)
Definition: map.h:167
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:226
llevMonster
@ llevMonster
Definition: logger.h:14
flags_differ
int flags_differ(ob_flags *diff)
Definition: object.cpp:4951
TRANSPORT
@ TRANSPORT
Definition: object.h:113
UPD_NROF
#define UPD_NROF
Definition: newclient.h:310
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:442
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:325
MAP_DARKNESS
#define MAP_DARKNESS(m)
Definition: map.h:71
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:4337
P_IS_ALIVE
#define P_IS_ALIVE
Definition: map.h:236
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
object::level
int16_t level
Definition: object.h:361
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:2124
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:2848
object::will_apply
uint8_t will_apply
Definition: object.h:402
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:4941
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:234
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:143
object::resist
int16_t resist[NROFATTACKS]
Definition: object.h:351
FLAG_NO_PICK
#define FLAG_NO_PICK
Definition: define.h:239
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
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:355
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:572
key_value::value
const char * value
Definition: object.h:44
FOR_OB_AND_ABOVE_PREPARE
#define FOR_OB_AND_ABOVE_PREPARE(op_)
Definition: define.h:739
object::carrying
int32_t carrying
Definition: object.h:377
FLAG_IS_A_TEMPLATE
#define FLAG_IS_A_TEMPLATE
Definition: define.h:366
LOOK_OBJ
#define LOOK_OBJ(ob)
Definition: object.h:512
stringbuffer.h
object::path_repelled
uint32_t path_repelled
Definition: object.h:354
object::y
int16_t y
Definition: object.h:335
object_find_by_type_and_race
object * object_find_by_type_and_race(const object *who, int type, const char *race)
Definition: object.cpp:4124
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:127
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:1555
object_update
void object_update(object *op, int action)
Definition: object.cpp:1429
object::contr
struct player * contr
Definition: object.h:284
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:616
object_find_by_name
object * object_find_by_name(const object *who, const char *name)
Definition: object.cpp:3947
disinfect.map
map
Definition: disinfect.py:4
ob_flags
uint32_t ob_flags[4]
Definition: object.h:259
object_get_key_value
key_value * object_get_key_value(const object *ob, const char *key)
Definition: object.cpp:4312
object::last_heal
int32_t last_heal
Definition: object.h:367
object_find_by_type2
object * object_find_by_type2(const object *who, int type1, int type2)
Definition: object.cpp:4028
object::subtype
uint8_t subtype
Definition: object.h:349
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:4381
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.cpp:305
key_value::next
key_value * next
Definition: object.h:45
P_NO_ERROR
#define P_NO_ERROR
Definition: map.h:239
object_present_in_ob_by_name
object * object_present_in_ob_by_name(int type, const char *str, const object *op)
Definition: object.cpp:3194
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.cpp:592
map_find_by_type
object * map_find_by_type(mapstruct *m, int x, int y, uint8_t type)
Definition: object.cpp:3136
object::weapon_speed
float weapon_speed
Definition: object.h:339
can_see_monsterP
int can_see_monsterP(mapstruct *m, int x, int y, int dir)
Definition: object.cpp:3813
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:286
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:478
object::run_away
uint8_t run_away
Definition: object.h:394
object_dump
void object_dump(const object *op, StringBuffer *sb)
Definition: object.cpp:645
object::ox
int16_t ox
Definition: object.h:336
object::weight_limit
int32_t weight_limit
Definition: object.h:376
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
speed
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various what they and how they effect the player s actions Also in this section are the stat modifiers that specific classes professions bring Player and sps the current and maximum the Current and Maximum The Current Sp can go somewhat negative When Sp is negative not all spells can be and a more negative Sp makes spell casting less likey to succeed can affect Damage and how the characters speed
Definition: stats.txt:23
object_count_free
int object_count_free(void)
Definition: object.cpp:1746
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:4735
HEAD
#define HEAD(op)
Definition: object.h:598
CONTAINER
@ CONTAINER
Definition: object.h:236
Statistics::spell_hash_full
uint64_t spell_hash_full
Definition: global.h:363
object::below
object * below
Definition: object.h:295
make_face_from_files.str
str
Definition: make_face_from_files.py:30
object::move_type
MoveType move_type
Definition: object.h:434
object_find_by_type_and_name
object * object_find_by_type_and_name(const object *who, int type, const char *name)
Definition: object.cpp:4099
query_short_name
void query_short_name(const object *op, char *buf, size_t size)
Definition: item.cpp:517
FLAG_FREED
#define FLAG_FREED
Definition: define.h:233
object::event_bitmask
uint64_t event_bitmask
Definition: object.h:445
convert.action
action
Definition: convert.py:25
object::face
const Face * face
Definition: object.h:341
out_of_map
int out_of_map(mapstruct *m, int x, int y)
Definition: map.cpp:2286
find_string
sstring find_string(const char *str)
Definition: shstr.cpp:236
object::last_eat
int32_t last_eat
Definition: object.h:366
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
object::value
int32_t value
Definition: object.h:360
object_update_speed
void object_update_speed(object *op)
Definition: object.cpp:1344
FLAG_IS_WOODED
#define FLAG_IS_WOODED
Definition: define.h:330
object::type
uint8_t type
Definition: object.h:348
INS_NO_MERGE
#define INS_NO_MERGE
Definition: object.h:571
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:358
SET_MAP_FLAGS
#define SET_MAP_FLAGS(M, X, Y, C)
Definition: map.h:160
object::materialname
sstring materialname
Definition: object.h:356
UPD_FLAGS
#define UPD_FLAGS
Definition: newclient.h:304
object_find_by_tag
object * object_find_by_tag(const object *who, tag_t tag)
Definition: object.cpp:4051
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:4197
object_free
void object_free(object *ob, int flags)
Definition: object.cpp:1587
LAMP
@ LAMP
Definition: object.h:206
GET_MAP_MOVE_BLOCK
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:191
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
INS_BELOW_ORIGINATOR
#define INS_BELOW_ORIGINATOR
Definition: object.h:575
object::move_on
MoveType move_on
Definition: object.h:437
living::food
int32_t food
Definition: living.h:48
resist_save
const char *const resist_save[NROFATTACKS]
Definition: init.cpp:31
disinfect.count
int count
Definition: disinfect.py:7
tag_t
uint32_t tag_t
Definition: object.h:14
body_locations
body_locations_struct body_locations[NUM_BODY_LOCATIONS]
Definition: item.cpp:54
archetype
Definition: object.h:474
P_PLAYER
#define P_PLAYER
Definition: map.h:235
object_matches_string
int object_matches_string(object *pl, object *op, const char *name)
Definition: object.cpp:4565
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:3287
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:2359
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
Settings::casting_time
uint8_t casting_time
Definition: global.h:270
object::race
sstring race
Definition: object.h:326
compare_flags
static void compare_flags(ob_flags *ret, const object *p, const object *q)
Definition: object.h:490
object::animation
const Animations * animation
Definition: object.h:426
GET_MAP_MOVE_ON
#define GET_MAP_MOVE_ON(M, X, Y)
Definition: map.h:201
FREE_OBJ_DROP_ABOVE_FLOOR
#define FREE_OBJ_DROP_ABOVE_FLOOR
Definition: object.h:537
ob_blocked
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
Definition: map.cpp:478
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
weight
TIPS on SURVIVING Crossfire is populated with a wealth of different monsters These monsters can have varying immunities and attack types In some of them can be quite a bit smarter than others It will be important for new players to learn the abilities of different monsters and learn just how much it will take to kill them This section discusses how monsters can interact with players Most monsters in the game are out to mindlessly kill and destroy the players These monsters will help boost a player s after he kills them When fighting a large amount of monsters in a single attempt to find a narrower hallway so that you are not being attacked from all sides Charging into a room full of Beholders for instance would not be open the door and fight them one at a time For there are several maps designed for them Find these areas and clear them out All throughout these a player can find signs and books which they can read by stepping onto them and hitting A to apply the book sign These messages will help the player to learn the system One more always keep an eye on your food If your food drops to your character will soon so BE CAREFUL ! NPCs Non Player Character are special monsters which have intelligence Players may be able to interact with these monsters to help solve puzzles and find items of interest To speak with a monster you suspect to be a simply move to an adjacent square to them and push the double ie Enter your and press< Return > You can also use say if you feel like typing a little extra Other NPCs may not speak to but display intelligence with their movement Some monsters can be and may attack the nearest of your enemies Others can be in that they follow you around and help you in your quest to kill enemies and find treasure SPECIAL ITEMS There are many special items which can be found in of these the most important may be the signs all a player must do is apply the handle In the case of the player must move items over the button to hold it down Some of the larger buttons may need very large items to be moved onto before they can be activated Gates and locked but be for you could fall down into a pit full of ghosts or dragons and not be able to get back out Break away sometimes it may be worth a player s time to test the walls of a map for secret doors Fire such as missile weapons and spells you will notice them going up in smoke ! So be careful not to destroy valuable items Spellbooks sometimes a player can learn the other times they cannot There are many different types of books and scrolls out there Improve item have lower weight
Definition: survival-guide.txt:100
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:3995
reduction_dir
static const int reduction_dir[SIZEOFFREE][3]
Definition: object.cpp:3743
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:2095
object::other_arch
struct archetype * other_arch
Definition: object.h:423
d
How to Install a Crossfire Server on you must install a python script engine on your computer Python is the default script engine of Crossfire You can find the python engine you have only to install them The VisualC Crossfire settings are for d
Definition: INSTALL_WIN32.txt:13
object_create_clone
object * object_create_clone(object *asrc)
Definition: object.cpp:3900
object_copy_no_speed
void object_copy_no_speed(const object *src_ob, object *dest_ob)
Definition: object.cpp:1061
MAP_WIDTH
#define MAP_WIDTH(m)
Definition: map.h:74
SIZEOFFREE
#define SIZEOFFREE
Definition: define.h:155
P_OUT_OF_MAP
#define P_OUT_OF_MAP
Definition: map.h:248
MAX_BUF
#define MAX_BUF
Definition: define.h:35
INS_ON_TOP
#define INS_ON_TOP
Definition: object.h:574
move_name
const char *const move_name[]
Definition: object.cpp:4823
object_set_cheat
void object_set_cheat(object *op)
Definition: object.cpp:3265
object_new
object * object_new(void)
Definition: object.cpp:1268
object_insert_in_map
object * object_insert_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.cpp:2356
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:521
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:3159
get_weight_limit
uint32_t get_weight_limit(int stat)
Definition: living.cpp:2362
object::weight
int32_t weight
Definition: object.h:375
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:439
object::spell_tags
tag_t * spell_tags
Definition: object.h:444
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:440
RANDOM
#define RANDOM()
Definition: define.h:644
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:216
get_search_arr
void get_search_arr(int *search_arr)
Definition: object.cpp:3633
find_dir_2
int find_dir_2(int x, int y)
Definition: object.cpp:3668
living::Wis
int8_t Wis
Definition: living.h:36
key_value::key
const char * key
Definition: object.h:43
object_add_weight
void object_add_weight(object *op, signed long weight)
Definition: object.cpp:2824
above
Magical Runes Runes are magical inscriptions on the dungeon which cast a spell or detonate when something steps on them Flying objects don t detonate runes Beware ! Runes are invisible most of the time They are only visible occasionally ! There are several runes which are there are some special runes which may only be called with the invoke and people may apply it to read it Maybe useful for mazes ! This rune will not nor is it ordinarily invisible Partial Visibility of they ll be visible only part of the time They have so the higher your the better hidden the runes you make are Examples of whichever way you re facing invoke magic rune transfer as above
Definition: runes-guide.txt:50
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
object_decrease_nrof
object * object_decrease_nrof(object *op, uint32_t i)
Definition: object.cpp:2667
object_find_by_type_and_slaying
object * object_find_by_type_and_slaying(const object *who, int type, const char *slaying)
Definition: object.cpp:4149
INS_MAP_LOAD
#define INS_MAP_LOAD
Definition: object.h:576
BITMASK_VALID
#define BITMASK_VALID
Definition: events.h:64
object::lore
sstring lore
Definition: object.h:332
object::dam_modifier
uint8_t dam_modifier
Definition: object.h:417
SK_WOODSMAN
@ SK_WOODSMAN
Definition: skills.h:40
fatal
void fatal(enum fatal_error err)
Definition: utils.cpp:570
object::slaying
sstring slaying
Definition: object.h:327
object::glow_radius
int8_t glow_radius
Definition: object.h:374
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:414
object::name
sstring name
Definition: object.h:319
SPELL_MAPPINGS
#define SPELL_MAPPINGS
Definition: global.h:152
object_count_used
int object_count_used(void)
Definition: object.cpp:1762
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:4243
SIZEOFFREE2
#define SIZEOFFREE2
Definition: define.h:154
object_can_pick
int object_can_pick(const object *who, const object *item)
Definition: object.cpp:3858
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:299
object::artifact
sstring artifact
Definition: object.h:322
object_find_by_type
object * object_find_by_type(const object *who, int type)
Definition: object.cpp:3971
item
Definition: item.py:1
living::maxsp
int16_t maxsp
Definition: living.h:43
P_NEED_UPDATE
#define P_NEED_UPDATE
Definition: map.h:238
mapstruct
Definition: map.h:314
object_find_by_name_global
object * object_find_by_name_global(const char *str)
Definition: object.cpp:747
Statistics::spell_merges
uint64_t spell_merges
Definition: global.h:362
object::last_sp
int32_t last_sp
Definition: object.h:368
sstring
const typedef char * sstring
Definition: sstring.h:2
floor
Magical Runes Runes are magical inscriptions on the dungeon floor
Definition: runes-guide.txt:3
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:4883
object::gen_sp_armour
int8_t gen_sp_armour
Definition: object.h:373
object::skill
sstring skill
Definition: object.h:329
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:2628
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:3550
object_set_msg
void object_set_msg(object *op, const char *msg)
Definition: object.cpp:4802
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.cpp:359
SPELL_EFFECT
@ SPELL_EFFECT
Definition: object.h:220
object::msg
sstring msg
Definition: object.h:330
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:481
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:3247
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:5414
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:176
living::ac
int8_t ac
Definition: living.h:38
MAP_HEIGHT
#define MAP_HEIGHT(m)
Definition: map.h:76
save_object_in_sb
void save_object_in_sb(StringBuffer *sb, object *op, const int flag)
Definition: object.cpp:5295
get_ob_diff
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Definition: object.cpp:4977
object::duration
int16_t duration
Definition: object.h:413
object_remove_from_active_list
void object_remove_from_active_list(object *op)
Definition: object.cpp:1387
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:4268
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)
Definition: object.cpp:2292
strcasecmp
int strcasecmp(const char *s1, const char *s2)
object_distance
int object_distance(const object *ob1, const object *ob2)
Definition: object.cpp:3652
castle_read.key
key
Definition: castle_read.py:64
find_force
object * find_force(object *op, const char *name)
Definition: object.cpp:5409
MIN_ACTIVE_SPEED
#define MIN_ACTIVE_SPEED
Definition: define.h:639
object::body_info
int8_t body_info[NUM_BODY_LOCATIONS]
Definition: object.h:382
FLAG_ANIMATE
#define FLAG_ANIMATE
Definition: define.h:242
SAVE_ERROR_OK
#define SAVE_ERROR_OK
Definition: map.h:140
loader.h
object_fix_multipart
void object_fix_multipart(object *tmp)
Definition: object.cpp:4676
object::randomitems
struct treasurelist * randomitems
Definition: object.h:395
GET_MAP_MOVE_OFF
#define GET_MAP_MOVE_OFF(M, X, Y)
Definition: map.h:206
FLAG_IS_HILLY
#define FLAG_IS_HILLY
Definition: define.h:332
skill
skill
Definition: arch-handbook.txt:585
MOVE_FLY_HIGH
#define MOVE_FLY_HIGH
Definition: define.h:394
object_remove
void object_remove(object *op)
Definition: object.cpp:1828
compare_ob_value_lists_one
static int compare_ob_value_lists_one(const object *, const object *)
Definition: object.cpp:363
UP_OBJ_CHANGE
#define UP_OBJ_CHANGE
Definition: object.h:523
GET_MAP_FLAGS
#define GET_MAP_FLAGS(M, X, Y)
Definition: map.h:158
object::move_off
MoveType move_off
Definition: object.h:438
object_sum_weight
signed long object_sum_weight(object *op)
Definition: object.cpp:568
FLAG_UNPAID
#define FLAG_UNPAID
Definition: define.h:236
empty_archetype
archetype * empty_archetype
Definition: init.cpp:119
freedir
int freedir[SIZEOFFREE]
Definition: object.cpp:317
P_NO_CLERIC
#define P_NO_CLERIC
Definition: map.h:237
object_check_move_on
int object_check_move_on(object *op, object *originator)
Definition: object.cpp:3003
FREE_OBJ_FREE_INVENTORY
#define FREE_OBJ_FREE_INVENTORY
Definition: object.h:535
update_all_los
void update_all_los(const mapstruct *map, int x, int y)
Definition: los.cpp:595
object::state
uint8_t state
Definition: object.h:359
object_copy_owner
void object_copy_owner(object *op, object *clone)
Definition: object.cpp:893
archetype::name
sstring name
Definition: object.h:475
SCROLL
@ SCROLL
Definition: object.h:226
FLAG_IS_LINKED
#define FLAG_IS_LINKED
Definition: define.h:315
object::nrof
uint32_t nrof
Definition: object.h:342
object_increase_nrof
static void object_increase_nrof(object *op, uint32_t i)
Definition: object.cpp:2754
living::grace
int16_t grace
Definition: living.h:44
query_base_name
void query_base_name(const object *op, int plural, char *buf, size_t size)
Definition: item.cpp:693
object::stats
living stats
Definition: object.h:378
object::move_allow
MoveType move_allow
Definition: object.h:436
artifact
Definition: artifact.h:14
object_set_value
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.cpp:4490
object::more
object * more
Definition: object.h:303
freearr_x
short freearr_x[SIZEOFFREE]
Definition: object.cpp:299
object::total_exp
int64_t total_exp
Definition: object.h:379
object_sub_weight
void object_sub_weight(object *op, signed long weight)
Definition: object.cpp:1802
StringBuffer
Definition: stringbuffer.cpp:25
TRUE
#define TRUE
Definition: compat.h:11
EVENT_DESTROY
#define EVENT_DESTROY
Definition: events.h:26
living::Pow
int8_t Pow
Definition: living.h:36
commongive.newob
newob
Definition: commongive.py:47
SPELL_TAG_SIZE
#define SPELL_TAG_SIZE
Definition: object.h:83
object::attacktype
uint32_t attacktype
Definition: object.h:352
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
FLAG_CURSED
#define FLAG_CURSED
Definition: define.h:316
maxfree
int maxfree[SIZEOFFREE]
Definition: object.cpp:311
SAVE_FLAG_SAVE_UNPAID
#define SAVE_FLAG_SAVE_UNPAID
Definition: map.h:107
save_object
int save_object(FILE *fp, object *op, int flag)
Definition: object.cpp:5381
SK_CLIMBING
@ SK_CLIMBING
Definition: skills.h:39
object_get_player_container
object * object_get_player_container(object *op)
Definition: object.cpp:607
dirdiff
int dirdiff(int dir1, int dir2)
Definition: object.cpp:3723
OB_SPELL_TAG_HASH
#define OB_SPELL_TAG_HASH(op, count)
Definition: object.h:89
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
object::material
uint16_t material
Definition: object.h:357
map_layer_name
const char *const map_layer_name[MAP_LAYERS]
Definition: map.cpp:45
CUSTOM_NAME_FIELD
#define CUSTOM_NAME_FIELD
Definition: object.h:98
object_free_inventory
void object_free_inventory(object *ob)
Definition: object.cpp:1563
object::move_block
MoveType move_block
Definition: object.h:435
object::next
object * next
Definition: object.h:285
free_dialog_information
void free_dialog_information(object *op)
Definition: dialog.cpp:32
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
FLAG_NO_APPLY
#define FLAG_NO_APPLY
Definition: define.h:301
living::hp
int16_t hp
Definition: living.h:40
living::luck
int8_t luck
Definition: living.h:39
FORCE
@ FORCE
Definition: object.h:229
object::oy
int16_t oy
Definition: object.h:336
object.h
object_replace_insert_in_map
void object_replace_insert_in_map(const char *arch_string, object *op)
Definition: object.cpp:2588
object_can_merge
int object_can_merge(object *ob1, object *ob2)
Definition: object.cpp:433
llevDebug
@ llevDebug
Definition: logger.h:13
is_valid_types_gen.type
list type
Definition: is_valid_types_gen.py:25
FLAG_IS_FLOOR
#define FLAG_IS_FLOOR
Definition: define.h:302
P_BLOCKSVIEW
#define P_BLOCKSVIEW
Definition: map.h:225
FORCE_NAME
#define FORCE_NAME
Definition: spells.h:169
FAST_SAVE_LONG
static void FAST_SAVE_LONG(StringBuffer *sb, const char *name, const long value)
Definition: object.cpp:4934
living::Con
int8_t Con
Definition: living.h:36
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Definition: define.h:261
living::Str
int8_t Str
Definition: living.h:36
dragon_attune.force
force
Definition: dragon_attune.py:45