ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.224
Committed: Fri May 2 20:16:24 2008 UTC (16 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.223: +8 -9 lines
Log Message:
- get rid of the only use of object_copy as an instantiated type,
  saves gobs of code (~4kb) in change_abil, is probably way faster
  and removes some very ugly code.
- this->remove in operator =, as x/y gets overwritten

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.199 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 pippijn 1.116 *
4 root 1.208 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.157 * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.116 *
8 root 1.199 * Deliantra is free software: you can redistribute it and/or modify
9 root 1.163 * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation, either version 3 of the License, or
11     * (at your option) any later version.
12 pippijn 1.116 *
13 root 1.163 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 pippijn 1.116 *
18 root 1.163 * You should have received a copy of the GNU General Public License
19     * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 root 1.157 *
21 root 1.199 * The authors can be reached via e-mail to <support@deliantra.net>
22 pippijn 1.116 */
23 elmex 1.1
24     #include <global.h>
25 root 1.28 #include <stdio.h>
26     #include <sys/types.h>
27     #include <sys/uio.h>
28 elmex 1.1 #include <object.h>
29 root 1.146 #include <sproto.h>
30 elmex 1.1 #include <loader.h>
31 root 1.28
32 root 1.68 #include <bitset>
33    
34 root 1.202 UUID UUID::cur;
35 root 1.204 static uint64_t seq_next_save;
36     static const uint64 UUID_GAP = 1<<19;
37 elmex 1.1
38 root 1.108 objectvec objects;
39     activevec actives;
40 elmex 1.1
41 root 1.203 short freearr_x[SIZEOFFREE] = {
42     0,
43     0, 1, 1, 1, 0, -1, -1, -1,
44     0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2, -1,
45     0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -3, -3, -3, -3, -2, -1
46 root 1.24 };
47 root 1.203 short freearr_y[SIZEOFFREE] = {
48     0,
49     -1, -1, 0, 1, 1, 1, 0, -1,
50     -2, -2, -2, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2,
51     -3, -3, -3, -3, -2, -1, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3
52 root 1.24 };
53 root 1.203 int maxfree[SIZEOFFREE] = {
54     0,
55     9, 10, 13, 14, 17, 18, 21, 22,
56     25, 26, 27, 30, 31, 32, 33, 36, 37, 39, 39, 42, 43, 44, 45, 48,
57     49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49
58 root 1.24 };
59     int freedir[SIZEOFFREE] = {
60 root 1.203 0,
61     1, 2, 3, 4, 5, 6, 7, 8,
62     1, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 7, 8, 8, 8,
63     1, 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8
64 root 1.24 };
65 elmex 1.1
66 root 1.39 static void
67 root 1.203 write_uuid (uval64 skip, bool sync)
68 root 1.39 {
69 root 1.203 CALL_BEGIN (2);
70     CALL_ARG_SV (newSVval64 (skip));
71     CALL_ARG_SV (boolSV (sync));
72     CALL_CALL ("cf::write_uuid", G_DISCARD);
73     CALL_END;
74 root 1.39 }
75    
76     static void
77     read_uuid (void)
78     {
79     char filename[MAX_BUF];
80    
81     sprintf (filename, "%s/uuid", settings.localdir);
82    
83 root 1.204 seq_next_save = 0;
84    
85 root 1.39 FILE *fp;
86    
87     if (!(fp = fopen (filename, "r")))
88     {
89     if (errno == ENOENT)
90     {
91     LOG (llevInfo, "RESET uid to 1\n");
92 root 1.202 UUID::cur.seq = 0;
93 root 1.204 write_uuid (UUID_GAP, true);
94 root 1.39 return;
95     }
96    
97     LOG (llevError, "FATAL: cannot open %s for reading!\n", filename);
98     _exit (1);
99     }
100    
101 root 1.203 UUID::BUF buf;
102     buf[0] = 0;
103     fgets (buf, sizeof (buf), fp);
104    
105     if (!UUID::cur.parse (buf))
106 root 1.39 {
107 root 1.203 LOG (llevError, "FATAL: error reading uid from %s (%s)!\n", filename, buf);
108 root 1.39 _exit (1);
109     }
110    
111 root 1.203 LOG (llevDebug, "read UUID: %s\n", UUID::cur.c_str ());
112    
113 root 1.204 write_uuid (UUID_GAP, true);
114 root 1.39 fclose (fp);
115     }
116    
117     UUID
118 root 1.202 UUID::gen ()
119 root 1.39 {
120     UUID uid;
121    
122 root 1.202 uid.seq = ++cur.seq;
123 root 1.39
124 root 1.204 if (expect_false (cur.seq >= seq_next_save))
125     {
126     seq_next_save = UUID::cur.seq + (UUID_GAP >> 1);
127     write_uuid (UUID_GAP, false);
128     }
129    
130 root 1.39
131     return uid;
132     }
133    
134     void
135 root 1.202 UUID::init ()
136 root 1.39 {
137     read_uuid ();
138     }
139    
140 elmex 1.1 /* Returns TRUE if every key_values in wants has a partner with the same value in has. */
141 root 1.205 static bool
142 root 1.24 compare_ob_value_lists_one (const object *wants, const object *has)
143     {
144     key_value *wants_field;
145    
146     /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both
147     * objects with lists are rare, and lists stay short. If not, use a
148     * different structure or at least keep the lists sorted...
149     */
150    
151     /* For each field in wants, */
152 root 1.86 for (wants_field = wants->key_values; wants_field; wants_field = wants_field->next)
153 root 1.24 {
154     key_value *has_field;
155    
156     /* Look for a field in has with the same key. */
157     has_field = get_ob_key_link (has, wants_field->key);
158    
159 root 1.205 if (!has_field)
160     return 0; /* No field with that name. */
161 root 1.24
162     /* Found the matching field. */
163     if (has_field->value != wants_field->value)
164 root 1.205 return 0; /* Values don't match, so this half of the comparison is false. */
165 root 1.24
166     /* If we get here, we found a match. Now for the next field in wants. */
167 elmex 1.1 }
168 root 1.24
169     /* If we get here, every field in wants has a matching field in has. */
170 root 1.205 return 1;
171 elmex 1.1 }
172    
173     /* Returns TRUE if ob1 has the same key_values as ob2. */
174 root 1.205 static bool
175 root 1.24 compare_ob_value_lists (const object *ob1, const object *ob2)
176     {
177     /* However, there may be fields in has which aren't partnered in wants,
178     * so we need to run the comparison *twice*. :(
179     */
180     return compare_ob_value_lists_one (ob1, ob2) && compare_ob_value_lists_one (ob2, ob1);
181 elmex 1.1 }
182    
183     /* Function examines the 2 objects given to it, and returns true if
184     * they can be merged together.
185     *
186     * Note that this function appears a lot longer than the macro it
187     * replaces - this is mostly for clarity - a decent compiler should hopefully
188     * reduce this to the same efficiency.
189     *
190 root 1.66 * Check nrof variable *before* calling can_merge()
191 elmex 1.1 *
192     * Improvements made with merge: Better checking on potion, and also
193     * check weight
194     */
195 root 1.66 bool object::can_merge_slow (object *ob1, object *ob2)
196 root 1.16 {
197     /* A couple quicksanity checks */
198 root 1.66 if (ob1 == ob2
199     || ob1->type != ob2->type
200     || ob1->speed != ob2->speed
201     || ob1->value != ob2->value
202     || ob1->name != ob2->name)
203 root 1.16 return 0;
204    
205 root 1.205 /* Do not merge objects if nrof would overflow. First part checks
206 root 1.208 * for unsigned overflow (2c), second part checks whether the result
207 root 1.205 * would fit into a 32 bit signed int, which is often used to hold
208     * nrof values.
209 root 1.16 */
210 root 1.205 if (~ob1->nrof < ob2->nrof || ob1->nrof + ob2->nrof > (1UL << 31))
211 root 1.16 return 0;
212    
213     /* If the objects have been identified, set the BEEN_APPLIED flag.
214 root 1.205 * This is to the comparison of the flags below will be OK. We
215 root 1.16 * just can't ignore the been applied or identified flags, as they
216     * are not equal - just if it has been identified, the been_applied
217     * flags lose any meaning.
218     */
219     if (QUERY_FLAG (ob1, FLAG_IDENTIFIED))
220     SET_FLAG (ob1, FLAG_BEEN_APPLIED);
221    
222     if (QUERY_FLAG (ob2, FLAG_IDENTIFIED))
223     SET_FLAG (ob2, FLAG_BEEN_APPLIED);
224 elmex 1.1
225 root 1.208 if (ob1->arch->name != ob2->arch->name
226 root 1.68 || ob1->name != ob2->name
227     || ob1->title != ob2->title
228     || ob1->msg != ob2->msg
229     || ob1->weight != ob2->weight
230     || ob1->attacktype != ob2->attacktype
231     || ob1->magic != ob2->magic
232     || ob1->slaying != ob2->slaying
233     || ob1->skill != ob2->skill
234     || ob1->value != ob2->value
235     || ob1->animation_id != ob2->animation_id
236     || ob1->client_type != ob2->client_type
237     || ob1->materialname != ob2->materialname
238     || ob1->lore != ob2->lore
239     || ob1->subtype != ob2->subtype
240     || ob1->move_type != ob2->move_type
241     || ob1->move_block != ob2->move_block
242     || ob1->move_allow != ob2->move_allow
243     || ob1->move_on != ob2->move_on
244     || ob1->move_off != ob2->move_off
245     || ob1->move_slow != ob2->move_slow
246 root 1.208 || ob1->move_slow_penalty != ob2->move_slow_penalty
247     || memcmp (&ob1->resist, &ob2->resist, sizeof (ob1->resist))
248     || memcmp (&ob1->stats , &ob2->stats , sizeof (ob1->stats)))
249     return 0;
250    
251     if ((ob1->flag ^ ob2->flag)
252     .reset (FLAG_INV_LOCKED)
253     .reset (FLAG_CLIENT_SENT)
254     .reset (FLAG_REMOVED)
255     .any ())
256 root 1.16 return 0;
257    
258 root 1.205 /* This is really a spellbook check - we should in general
259     * not merge objects with real inventories, as splitting them
260     * is hard.
261 root 1.16 */
262     if (ob1->inv || ob2->inv)
263     {
264 root 1.193 if (!(ob1->inv && ob2->inv))
265     return 0; /* inventories differ in length */
266    
267     if (ob1->inv->below || ob2->inv->below)
268     return 0; /* more than one object in inv */
269 root 1.16
270 root 1.66 if (!object::can_merge (ob1->inv, ob2->inv))
271 root 1.205 return 0; /* inventory objects differ */
272 root 1.16
273     /* inventory ok - still need to check rest of this object to see
274     * if it is valid.
275     */
276     }
277 elmex 1.1
278 root 1.16 /* Don't merge objects that are applied. With the new 'body' code,
279     * it is possible for most any character to have more than one of
280     * some items equipped, and we don't want those to merge.
281     */
282     if (QUERY_FLAG (ob1, FLAG_APPLIED) || QUERY_FLAG (ob2, FLAG_APPLIED))
283     return 0;
284 elmex 1.1
285 root 1.16 /* Note sure why the following is the case - either the object has to
286     * be animated or have a very low speed. Is this an attempted monster
287     * check?
288     */
289 elmex 1.97 if (!QUERY_FLAG (ob1, FLAG_ANIMATE) && ob1->has_active_speed ())
290 root 1.16 return 0;
291 elmex 1.1
292 root 1.16 switch (ob1->type)
293     {
294 root 1.29 case SCROLL:
295     if (ob1->level != ob2->level)
296     return 0;
297     break;
298 root 1.16 }
299 elmex 1.1
300 root 1.205 if (ob1->key_values || ob2->key_values)
301 root 1.16 {
302     /* At least one of these has key_values. */
303 root 1.205 if ((!ob1->key_values) != (!ob2->key_values))
304 root 1.208 return 0; /* One has fields, but the other one doesn't. */
305    
306     if (!compare_ob_value_lists (ob1, ob2))
307 root 1.24 return 0;
308 elmex 1.1 }
309 root 1.16
310     if (ob1->self || ob2->self)
311     {
312     ob1->optimise ();
313     ob2->optimise ();
314    
315     if (ob1->self || ob2->self)
316 root 1.192 {
317 root 1.195 int k1 = ob1->self ? HvTOTALKEYS (ob1->self) : 0;
318     int k2 = ob2->self ? HvTOTALKEYS (ob2->self) : 0;
319 root 1.192
320     if (k1 != k2)
321     return 0;
322 root 1.208
323     if (k1 == 0)
324 root 1.192 return 1;
325 root 1.208
326     if (!cfperl_can_merge (ob1, ob2))
327 root 1.192 return 0;
328     }
329 elmex 1.1 }
330    
331 root 1.16 /* Everything passes, must be OK. */
332     return 1;
333 elmex 1.1 }
334 root 1.24
335 root 1.214 // find player who can see this object
336     object *
337     object::visible_to () const
338     {
339 root 1.220 if (client_visible () && !flag [FLAG_REMOVED])
340 root 1.214 {
341     // see if we are in a container of sorts
342     if (env)
343     {
344     // the player inventory itself is always visible
345     if (env->type == PLAYER)
346     return env;
347    
348     // else a player could have our env open
349     object *envest = env->outer_env ();
350    
351     // the player itself is always on a map, so we will find him here
352     // even if our inv is in a player.
353     if (envest->is_on_map ())
354     if (object *pl = envest->ms ().player ())
355     if (pl->container == env)
356     return pl;
357     }
358     else
359     {
360     // maybe there is a player standing on the same mapspace
361     // this will catch the case where "this" is a player
362     if (object *pl = ms ().player ())
363 root 1.220 if (!pl->container || this == pl->container)
364     return pl;
365 root 1.214 }
366     }
367    
368     return 0;
369     }
370    
371 root 1.208 // adjust weight per container type ("of holding")
372 root 1.207 static sint32
373     weight_adjust (object *op, sint32 weight)
374     {
375     return op->type == CONTAINER
376     ? lerp (weight, 0, 100, 0, 100 - op->stats.Str)
377     : weight;
378     }
379    
380 elmex 1.1 /*
381 root 1.208 * adjust_weight(object, weight) adds the specified weight to an object,
382 root 1.207 * and also updates how much the environment(s) is/are carrying.
383 elmex 1.1 */
384 root 1.207 static void
385 root 1.208 adjust_weight (object *op, sint32 weight)
386 root 1.24 {
387 root 1.207 while (op)
388 root 1.24 {
389 root 1.207 weight = weight_adjust (op, weight);
390 root 1.142
391 root 1.212 if (!weight)
392     return;
393    
394 root 1.207 op->carrying += weight;
395 root 1.212
396     if (object *pl = op->visible_to ())
397 root 1.215 if (pl != op) // player is handled lazily
398     esrv_update_item (UPD_WEIGHT, pl, op);
399 root 1.212
400 root 1.207 op = op->env;
401 root 1.24 }
402 root 1.207 }
403 root 1.37
404 root 1.207 /*
405     * this is a recursive function which calculates the weight
406     * an object is carrying. It goes through op and figures out how much
407     * containers are carrying, and sums it up.
408     */
409     void
410     object::update_weight ()
411     {
412     sint32 sum = 0;
413 root 1.37
414 root 1.207 for (object *op = inv; op; op = op->below)
415     {
416     if (op->inv)
417     op->update_weight ();
418 elmex 1.1
419 root 1.207 sum += op->total_weight ();
420     }
421 elmex 1.1
422 root 1.212 sum = weight_adjust (this, sum);
423    
424     if (sum != carrying)
425     {
426     carrying = sum;
427    
428     if (object *pl = visible_to ())
429 root 1.215 if (pl != this) // player is handled lazily
430     esrv_update_item (UPD_WEIGHT, pl, this);
431 root 1.212 }
432 elmex 1.1 }
433    
434     /*
435 root 1.208 * Used by: Server DM commands: dumpbelow, dump. Some error messages.
436 elmex 1.1 */
437 root 1.53 char *
438 root 1.24 dump_object (object *op)
439     {
440 root 1.53 if (!op)
441     return strdup ("[NULLOBJ]");
442 elmex 1.1
443 root 1.53 object_freezer freezer;
444 root 1.133 op->write (freezer);
445 root 1.53 return freezer.as_string ();
446 elmex 1.1 }
447    
448     /*
449     * get_nearest_part(multi-object, object 2) returns the part of the
450     * multi-object 1 which is closest to the second object.
451     * If it's not a multi-object, it is returned.
452     */
453 root 1.24 object *
454     get_nearest_part (object *op, const object *pl)
455     {
456     object *tmp, *closest;
457     int last_dist, i;
458    
459 root 1.208 if (!op->more)
460 elmex 1.1 return op;
461 root 1.208
462     for (last_dist = distance (op, pl), closest = op, tmp = op->more;
463     tmp;
464     tmp = tmp->more)
465 root 1.24 if ((i = distance (tmp, pl)) < last_dist)
466     closest = tmp, last_dist = i;
467 root 1.208
468 elmex 1.1 return closest;
469     }
470    
471     /*
472     * Returns the object which has the count-variable equal to the argument.
473 root 1.208 * VERRRY slow.
474 elmex 1.1 */
475 root 1.24 object *
476     find_object (tag_t i)
477     {
478 root 1.112 for_all_objects (op)
479     if (op->count == i)
480     return op;
481    
482     return 0;
483 elmex 1.1 }
484    
485     /*
486     * Returns the first object which has a name equal to the argument.
487     * Used only by the patch command, but not all that useful.
488     * Enables features like "patch <name-of-other-player> food 999"
489     */
490 root 1.24 object *
491     find_object_name (const char *str)
492     {
493 root 1.35 shstr_cmp str_ (str);
494 elmex 1.1 object *op;
495 root 1.24
496 root 1.108 for_all_objects (op)
497 root 1.35 if (op->name == str_)
498 elmex 1.1 break;
499 root 1.11
500 elmex 1.1 return op;
501     }
502    
503     /*
504     * Sets the owner and sets the skill and exp pointers to owner's current
505     * skill and experience objects.
506 root 1.183 * ACTUALLY NO! investigate! TODO
507 elmex 1.1 */
508 root 1.24 void
509 root 1.30 object::set_owner (object *owner)
510 elmex 1.1 {
511 root 1.183 // allow objects which own objects
512     if (owner)
513     while (owner->owner)
514     owner = owner->owner;
515 elmex 1.1
516 root 1.198 if (flag [FLAG_FREED])
517     {
518     LOG (llevError | logBacktrace, "tried to set owner of %s to %s\n", debug_desc (), owner->debug_desc ());
519     return;
520     }
521    
522 root 1.30 this->owner = owner;
523 elmex 1.1 }
524    
525 root 1.148 int
526     object::slottype () const
527     {
528     if (type == SKILL)
529     {
530     if (IS_COMBAT_SKILL (subtype)) return slot_combat;
531     if (IS_RANGED_SKILL (subtype)) return slot_ranged;
532     }
533     else
534     {
535     if (slot [body_combat].info) return slot_combat;
536     if (slot [body_range ].info) return slot_ranged;
537     }
538    
539     return slot_none;
540     }
541    
542 root 1.147 bool
543     object::change_weapon (object *ob)
544 root 1.144 {
545     if (current_weapon == ob)
546 root 1.147 return true;
547 root 1.146
548 root 1.150 if (chosen_skill)
549     chosen_skill->flag [FLAG_APPLIED] = false;
550    
551 root 1.144 current_weapon = ob;
552 root 1.147 chosen_skill = !ob || ob->type == SKILL ? ob : find_skill_by_name (this, ob->skill);
553 root 1.146
554 root 1.150 if (chosen_skill)
555     chosen_skill->flag [FLAG_APPLIED] = true;
556    
557 root 1.144 update_stats ();
558 root 1.147
559     if (ob)
560     {
561     // now check wether any body locations became invalid, in which case
562     // we cannot apply the weapon at the moment.
563     for (int i = 0; i < NUM_BODY_LOCATIONS; ++i)
564     if (slot[i].used < 0)
565     {
566     current_weapon = chosen_skill = 0;
567     update_stats ();
568    
569     new_draw_info_format (NDI_UNIQUE, 0, this,
570 root 1.156 "You try to balance all your items at once, "
571     "but the %s is just too much for your body. "
572     "[You need to unapply some items first.]", &ob->name);
573 root 1.147 return false;
574     }
575    
576 root 1.148 //new_draw_info_format (NDI_UNIQUE, 0, this, "You switch to your %s.", &ob->name);
577 root 1.147 }
578     else
579 root 1.148 ;//new_draw_info_format (NDI_UNIQUE, 0, this, "You unwield your weapons.");
580 root 1.147
581 root 1.151 if (ob && !ob->flag [FLAG_APPLIED] && ob->type != SPELL)
582     {
583     LOG (llevError | logBacktrace, "%s changed to unapplied weapon %s",
584     &name, ob->debug_desc ());
585     return false;
586     }
587    
588 root 1.147 return true;
589 root 1.144 }
590    
591 elmex 1.1 /* Zero the key_values on op, decrementing the shared-string
592     * refcounts and freeing the links.
593     */
594 root 1.24 static void
595     free_key_values (object *op)
596 root 1.11 {
597 root 1.137 for (key_value *i = op->key_values; i; )
598 root 1.11 {
599     key_value *next = i->next;
600     delete i;
601 root 1.24
602 root 1.11 i = next;
603 elmex 1.1 }
604 root 1.24
605 root 1.11 op->key_values = 0;
606 elmex 1.1 }
607    
608 root 1.137 object &
609     object::operator =(const object &src)
610 root 1.11 {
611 root 1.224 remove ();
612 root 1.59
613 root 1.137 *(object_copy *)this = src;
614 elmex 1.1
615 root 1.224 flag [FLAG_REMOVED] = true;
616 elmex 1.1
617 root 1.11 /* Copy over key_values, if any. */
618 root 1.137 if (src.key_values)
619 root 1.14 {
620 root 1.23 key_value *tail = 0;
621 root 1.137 key_values = 0;
622 elmex 1.1
623 root 1.137 for (key_value *i = src.key_values; i; i = i->next)
624 root 1.11 {
625     key_value *new_link = new key_value;
626 root 1.8
627 root 1.24 new_link->next = 0;
628     new_link->key = i->key;
629 root 1.11 new_link->value = i->value;
630    
631     /* Try and be clever here, too. */
632 root 1.137 if (!key_values)
633 root 1.11 {
634 root 1.137 key_values = new_link;
635 root 1.11 tail = new_link;
636 root 1.8 }
637 root 1.11 else
638     {
639     tail->next = new_link;
640     tail = new_link;
641     }
642 root 1.14 }
643     }
644 root 1.137 }
645    
646     /*
647     * copy_to first frees everything allocated by the dst object,
648     * and then copies the contents of itself into the second
649     * object, allocating what needs to be allocated. Basically, any
650     * data that is malloc'd needs to be re-malloc/copied. Otherwise,
651     * if the first object is freed, the pointers in the new object
652     * will point at garbage.
653     */
654     void
655     object::copy_to (object *dst)
656     {
657     *dst = *this;
658    
659     if (speed < 0)
660 root 1.185 dst->speed_left -= rndm ();
661 root 1.2
662 root 1.87 dst->set_speed (dst->speed);
663 elmex 1.1 }
664    
665 root 1.133 void
666     object::instantiate ()
667     {
668     if (!uuid.seq) // HACK
669 root 1.202 uuid = UUID::gen ();
670 root 1.133
671     speed_left = -0.1f;
672     /* copy the body_info to the body_used - this is only really
673     * need for monsters, but doesn't hurt to do it for everything.
674     * by doing so, when a monster is created, it has good starting
675     * values for the body_used info, so when items are created
676     * for it, they can be properly equipped.
677     */
678 root 1.145 for (int i = NUM_BODY_LOCATIONS; i--; )
679     slot[i].used = slot[i].info;
680 root 1.133
681     attachable::instantiate ();
682     }
683    
684 root 1.65 object *
685     object::clone ()
686     {
687     object *neu = create ();
688     copy_to (neu);
689     return neu;
690     }
691    
692 elmex 1.1 /*
693     * If an object with the IS_TURNABLE() flag needs to be turned due
694     * to the closest player being on the other side, this function can
695     * be called to update the face variable, _and_ how it looks on the map.
696     */
697 root 1.24 void
698     update_turn_face (object *op)
699     {
700 root 1.96 if (!QUERY_FLAG (op, FLAG_IS_TURNABLE) || !op->arch)
701 root 1.24 return;
702 root 1.96
703 root 1.24 SET_ANIMATION (op, op->direction);
704     update_object (op, UP_OBJ_FACE);
705 elmex 1.1 }
706    
707     /*
708     * Updates the speed of an object. If the speed changes from 0 to another
709     * value, or vice versa, then add/remove the object from the active list.
710     * This function needs to be called whenever the speed of an object changes.
711     */
712 root 1.24 void
713 root 1.87 object::set_speed (float speed)
714 root 1.24 {
715 root 1.87 if (flag [FLAG_FREED] && speed)
716 root 1.24 {
717 root 1.87 LOG (llevError, "Object %s is freed but has speed.\n", &name);
718     speed = 0;
719 elmex 1.1 }
720 root 1.31
721 root 1.87 this->speed = speed;
722    
723 elmex 1.97 if (has_active_speed ())
724 root 1.98 activate ();
725 root 1.24 else
726 root 1.98 deactivate ();
727 elmex 1.1 }
728    
729     /*
730 root 1.75 * update_object() updates the the map.
731 elmex 1.1 * It takes into account invisible objects (and represent squares covered
732     * by invisible objects by whatever is below them (unless it's another
733     * invisible object, etc...)
734     * If the object being updated is beneath a player, the look-window
735     * of that player is updated (this might be a suboptimal way of
736     * updating that window, though, since update_object() is called _often_)
737     *
738     * action is a hint of what the caller believes need to be done.
739     * current action are:
740     * UP_OBJ_INSERT: op was inserted
741     * UP_OBJ_REMOVE: op was removed
742     * UP_OBJ_CHANGE: object has somehow changed. In this case, we always update
743     * as that is easier than trying to look at what may have changed.
744     * UP_OBJ_FACE: only the objects face has changed.
745     */
746 root 1.24 void
747     update_object (object *op, int action)
748     {
749 root 1.222 if (!op)
750 root 1.24 {
751     /* this should never happen */
752 root 1.222 LOG (llevError | logBacktrace, "update_object() called for NULL object.\n");
753 root 1.24 return;
754 elmex 1.1 }
755 root 1.24
756 root 1.222 if (!op->is_on_map ())
757 root 1.24 {
758     /* Animation is currently handled by client, so nothing
759     * to do in this case.
760     */
761     return;
762 elmex 1.1 }
763    
764 root 1.24 /* make sure the object is within map boundaries */
765 root 1.83 if (op->x < 0 || op->x >= op->map->width || op->y < 0 || op->y >= op->map->height)
766 root 1.24 {
767     LOG (llevError, "update_object() called for object out of map!\n");
768 elmex 1.1 #ifdef MANY_CORES
769 root 1.24 abort ();
770 elmex 1.1 #endif
771 root 1.24 return;
772 elmex 1.1 }
773    
774 root 1.76 mapspace &m = op->ms ();
775 elmex 1.1
776 root 1.99 if (!(m.flags_ & P_UPTODATE))
777 root 1.75 /* nop */;
778     else if (action == UP_OBJ_INSERT)
779     {
780     // this is likely overkill, TODO: revisit (schmorp)
781     if ((QUERY_FLAG (op, FLAG_BLOCKSVIEW) && !(m.flags_ & P_BLOCKSVIEW))
782     || (QUERY_FLAG (op, FLAG_NO_MAGIC) && !(m.flags_ & P_NO_MAGIC))
783     || (op->type == PLAYER && !(m.flags_ & P_PLAYER))
784     || (op->type == SAFE_GROUND && !(m.flags_ & P_SAFE))
785     || (QUERY_FLAG (op, FLAG_ALIVE) && !(m.flags_ & P_IS_ALIVE))
786     || (QUERY_FLAG (op, FLAG_DAMNED) && !(m.flags_ & P_NO_CLERIC))
787     || (m.move_on | op->move_on ) != m.move_on
788     || (m.move_off | op->move_off ) != m.move_off
789     || (m.move_slow | op->move_slow) != m.move_slow
790     /* This isn't perfect, but I don't expect a lot of objects to
791     * to have move_allow right now.
792     */
793     || ((m.move_block | op->move_block) & ~op->move_allow) != m.move_block
794     || 1) // the above is not strong enough a test to skip updating. los maybe? TODO (Schmorp)
795 root 1.99 m.flags_ = 0;
796 root 1.75 }
797     /* if the object is being removed, we can't make intelligent
798     * decisions, because remove_ob can't really pass the object
799     * that is being removed.
800     */
801 root 1.24 else if (action == UP_OBJ_CHANGE || action == UP_OBJ_REMOVE)
802 root 1.99 m.flags_ = 0;
803 root 1.24 else if (action == UP_OBJ_FACE)
804 root 1.29 /* Nothing to do for that case */ ;
805 root 1.24 else
806 root 1.27 LOG (llevError, "update_object called with invalid action: %d\n", action);
807 elmex 1.1
808 root 1.75 if (op->more)
809 root 1.24 update_object (op->more, action);
810 elmex 1.1 }
811    
812 root 1.21 object::object ()
813     {
814 root 1.22 SET_FLAG (this, FLAG_REMOVED);
815    
816     expmul = 1.0;
817     face = blank_face;
818     }
819    
820     object::~object ()
821     {
822 root 1.121 unlink ();
823 root 1.119
824 root 1.22 free_key_values (this);
825     }
826    
827 root 1.112 static int object_count;
828    
829 root 1.24 void object::link ()
830 root 1.22 {
831 root 1.112 assert (!index);//D
832 root 1.202 uuid = UUID::gen ();
833 root 1.112 count = ++object_count;
834 root 1.21
835 root 1.109 refcnt_inc ();
836 root 1.108 objects.insert (this);
837 root 1.21 }
838    
839 root 1.24 void object::unlink ()
840 root 1.21 {
841 root 1.121 if (!index)
842     return;
843    
844 root 1.108 objects.erase (this);
845 root 1.109 refcnt_dec ();
846 root 1.98 }
847    
848 root 1.96 void
849 root 1.98 object::activate ()
850 root 1.96 {
851 root 1.98 /* If already on active list, don't do anything */
852 root 1.108 if (active)
853 root 1.98 return;
854    
855 elmex 1.97 if (has_active_speed ())
856 root 1.108 actives.insert (this);
857 root 1.98 }
858 root 1.96
859 root 1.98 void
860     object::activate_recursive ()
861     {
862     activate ();
863    
864 root 1.104 for (object *op = inv; op; op = op->below)
865 root 1.98 op->activate_recursive ();
866 root 1.96 }
867    
868     /* This function removes object 'op' from the list of active
869     * objects.
870     * This should only be used for style maps or other such
871     * reference maps where you don't want an object that isn't
872     * in play chewing up cpu time getting processed.
873     * The reverse of this is to call update_ob_speed, which
874     * will do the right thing based on the speed of the object.
875     */
876     void
877 root 1.98 object::deactivate ()
878 root 1.96 {
879     /* If not on the active list, nothing needs to be done */
880 root 1.108 if (!active)
881 root 1.96 return;
882    
883 root 1.108 actives.erase (this);
884 root 1.98 }
885 root 1.96
886 root 1.98 void
887     object::deactivate_recursive ()
888     {
889 root 1.104 for (object *op = inv; op; op = op->below)
890 root 1.98 op->deactivate_recursive ();
891    
892     deactivate ();
893 root 1.96 }
894    
895 root 1.106 void
896     object::set_flag_inv (int flag, int value)
897     {
898     for (object *op = inv; op; op = op->below)
899     {
900     op->flag [flag] = value;
901     op->set_flag_inv (flag, value);
902     }
903     }
904    
905 root 1.89 /*
906     * Remove and free all objects in the inventory of the given object.
907     * object.c ?
908     */
909     void
910     object::destroy_inv (bool drop_to_ground)
911     {
912 root 1.94 // need to check first, because the checks below might segfault
913     // as we might be on an invalid mapspace and crossfire code
914     // is too buggy to ensure that the inventory is empty.
915 root 1.217 // corollary: if you create arrows etc. with stuff in its inventory,
916 root 1.94 // cf will crash below with off-map x and y
917     if (!inv)
918     return;
919    
920 root 1.89 /* Only if the space blocks everything do we not process -
921     * if some form of movement is allowed, let objects
922     * drop on that space.
923     */
924 root 1.92 if (!drop_to_ground
925     || !map
926 root 1.206 || map->in_memory != MAP_ACTIVE
927 root 1.122 || map->nodrop
928 root 1.95 || ms ().move_block == MOVE_ALL)
929 root 1.89 {
930     while (inv)
931 root 1.92 {
932 root 1.217 inv->destroy_inv (false);
933 root 1.92 inv->destroy ();
934     }
935 root 1.89 }
936     else
937     { /* Put objects in inventory onto this space */
938     while (inv)
939     {
940     object *op = inv;
941    
942     if (op->flag [FLAG_STARTEQUIP]
943     || op->flag [FLAG_NO_DROP]
944     || op->type == RUNE
945     || op->type == TRAP
946 root 1.110 || op->flag [FLAG_IS_A_TEMPLATE]
947     || op->flag [FLAG_DESTROY_ON_DEATH])
948 root 1.217 op->destroy (true);
949 root 1.89 else
950 root 1.93 map->insert (op, x, y);
951 root 1.89 }
952     }
953     }
954    
955 root 1.21 object *object::create ()
956     {
957 root 1.42 object *op = new object;
958 root 1.22 op->link ();
959     return op;
960 root 1.21 }
961 elmex 1.1
962 root 1.223 static struct freed_map : maptile
963     {
964     freed_map ()
965     {
966     path = "<freed objects map>";
967     name = "/internal/freed_objects_map";
968     width = 3;
969     height = 3;
970     nodrop = 1;
971    
972     alloc ();
973     in_memory = MAP_ACTIVE;
974     }
975     } freed_map; // freed objects are moved here to avoid crashes
976    
977 root 1.82 void
978     object::do_destroy ()
979 root 1.14 {
980 root 1.82 if (flag [FLAG_IS_LINKED])
981     remove_button_link (this);
982 root 1.29
983 root 1.82 if (flag [FLAG_FRIENDLY])
984 root 1.140 remove_friendly_object (this);
985 root 1.32
986 root 1.213 remove ();
987    
988     attachable::do_destroy ();
989 root 1.14
990 root 1.112 deactivate ();
991     unlink ();
992 root 1.92
993 root 1.82 flag [FLAG_FREED] = 1;
994 root 1.14
995 root 1.57 // hack to ensure that freed objects still have a valid map
996 root 1.223 map = &freed_map;
997     x = 1;
998     y = 1;
999 root 1.57
1000 root 1.88 if (more)
1001     {
1002     more->destroy ();
1003     more = 0;
1004     }
1005 root 1.82
1006 root 1.162 head = 0;
1007    
1008     // clear those pointers that likely might cause circular references
1009     owner = 0;
1010     enemy = 0;
1011     attacked_by = 0;
1012     current_weapon = 0;
1013 root 1.82 }
1014    
1015     void
1016     object::destroy (bool destroy_inventory)
1017     {
1018     if (destroyed ())
1019     return;
1020    
1021 root 1.219 if (!is_head () && !head->destroyed ())
1022     {
1023     LOG (llevError | logBacktrace, "tried to destroy the tail of an object");
1024     head->destroy (destroy_inventory);
1025 root 1.223 return;
1026 root 1.219 }
1027    
1028 root 1.217 destroy_inv (!destroy_inventory);
1029 root 1.22
1030 root 1.173 if (is_head ())
1031     if (sound_destroy)
1032     play_sound (sound_destroy);
1033     else if (flag [FLAG_MONSTER])
1034     play_sound (sound_find ("monster_destroy")); // quick hack, too lazy to create a generic mechanism
1035 root 1.169
1036 root 1.82 attachable::destroy ();
1037 elmex 1.1 }
1038    
1039 root 1.63 /* op->remove ():
1040 elmex 1.1 * This function removes the object op from the linked list of objects
1041     * which it is currently tied to. When this function is done, the
1042     * object will have no environment. If the object previously had an
1043     * environment, the x and y coordinates will be updated to
1044     * the previous environment.
1045     */
1046 root 1.24 void
1047 root 1.128 object::do_remove ()
1048 root 1.24 {
1049 root 1.45 object *tmp, *last = 0;
1050     object *otmp;
1051 root 1.26
1052 root 1.213 if (flag [FLAG_REMOVED])
1053 root 1.29 return;
1054 root 1.24
1055 root 1.82 INVOKE_OBJECT (REMOVE, this);
1056 root 1.26
1057 root 1.213 flag [FLAG_REMOVED] = true;
1058    
1059 root 1.59 if (more)
1060     more->remove ();
1061 root 1.24
1062     /*
1063     * In this case, the object to be removed is in someones
1064     * inventory.
1065     */
1066 root 1.59 if (env)
1067 root 1.24 {
1068 root 1.221 flag [FLAG_REMOVED] = false; // hack around the issue of visible_to checking flag_removed
1069 root 1.220 if (object *pl = visible_to ())
1070     esrv_del_item (pl->contr, count);
1071 root 1.221 flag [FLAG_REMOVED] = true; // hack around the issue of visible_to checking flag_removed
1072 root 1.220
1073 root 1.208 adjust_weight (env, -total_weight ());
1074 root 1.24
1075 root 1.208 *(above ? &above->below : &env->inv) = below;
1076 root 1.24
1077 root 1.96 if (below)
1078 root 1.59 below->above = above;
1079 root 1.24
1080     /* we set up values so that it could be inserted into
1081     * the map, but we don't actually do that - it is up
1082     * to the caller to decide what we want to do.
1083     */
1084 root 1.208 map = env->map;
1085     x = env->x;
1086     y = env->y;
1087     above = 0;
1088     below = 0;
1089     env = 0;
1090    
1091     /* NO_FIX_PLAYER is set when a great many changes are being
1092     * made to players inventory. If set, avoiding the call
1093     * to save cpu time.
1094     */
1095     if ((otmp = in_player ()) && otmp->contr && !QUERY_FLAG (otmp, FLAG_NO_FIX_PLAYER))
1096     otmp->update_stats ();
1097 root 1.59 }
1098     else if (map)
1099     {
1100 root 1.220 map->dirty = true;
1101     mapspace &ms = this->ms ();
1102    
1103     if (object *pl = ms.player ())
1104 root 1.96 {
1105 root 1.220 if (type == PLAYER) // this == pl(!)
1106     {
1107     // leaving a spot always closes any open container on the ground
1108     if (container && !container->env)
1109     // this causes spurious floorbox updates, but it ensures
1110     // that the CLOSE event is being sent.
1111     close_container ();
1112    
1113     --map->players;
1114     map->touch ();
1115     }
1116     else if (pl->container == this)
1117     {
1118     // removing a container should close it
1119     close_container ();
1120     }
1121 root 1.130
1122 root 1.220 esrv_del_item (pl->contr, count);
1123 root 1.96 }
1124    
1125 root 1.29 /* link the object above us */
1126 root 1.59 if (above)
1127     above->below = below;
1128 root 1.29 else
1129 root 1.117 ms.top = below; /* we were top, set new top */
1130 root 1.24
1131 root 1.29 /* Relink the object below us, if there is one */
1132 root 1.59 if (below)
1133     below->above = above;
1134 root 1.29 else
1135     {
1136     /* Nothing below, which means we need to relink map object for this space
1137     * use translated coordinates in case some oddness with map tiling is
1138     * evident
1139     */
1140 root 1.59 if (GET_MAP_OB (map, x, y) != this)
1141 root 1.117 LOG (llevError, "remove_ob: GET_MAP_OB does not return object to be removed even though it appears to be on the bottom? %s\n", debug_desc ());
1142 elmex 1.1
1143 root 1.117 ms.bot = above; /* goes on above it. */
1144 root 1.8 }
1145 root 1.26
1146 root 1.59 above = 0;
1147     below = 0;
1148 root 1.26
1149 root 1.59 if (map->in_memory == MAP_SAVING)
1150 root 1.29 return;
1151 elmex 1.1
1152 root 1.82 int check_walk_off = !flag [FLAG_NO_APPLY];
1153 elmex 1.1
1154 root 1.175 if (object *pl = ms.player ())
1155     {
1156     if (pl->container == this)
1157     /* If a container that the player is currently using somehow gets
1158     * removed (most likely destroyed), update the player view
1159     * appropriately.
1160     */
1161     pl->close_container ();
1162    
1163 root 1.218 //TODO: the floorbox prev/next might need updating
1164     esrv_del_item (pl->contr, count);
1165 root 1.175 }
1166    
1167 root 1.117 for (tmp = ms.bot; tmp; tmp = tmp->above)
1168 root 1.24 {
1169 root 1.29 /* No point updating the players look faces if he is the object
1170     * being removed.
1171 root 1.24 */
1172 root 1.29
1173 root 1.96 /* See if object moving off should effect something */
1174 root 1.50 if (check_walk_off
1175 root 1.59 && ((move_type & tmp->move_off)
1176     && (move_type & ~tmp->move_off & ~tmp->move_block) == 0))
1177 root 1.29 {
1178 elmex 1.72 move_apply (tmp, this, 0);
1179 root 1.24
1180 root 1.59 if (destroyed ())
1181 root 1.50 LOG (llevError, "BUG: remove_ob(): name %s, destroyed leaving object\n", tmp->debug_desc ());
1182 root 1.8 }
1183    
1184 root 1.29 last = tmp;
1185     }
1186 root 1.26
1187 root 1.96 /* last == NULL if there are no objects on this space */
1188     //TODO: this makes little sense, why only update the topmost object?
1189 root 1.59 if (!last)
1190 root 1.99 map->at (x, y).flags_ = 0;
1191 root 1.29 else
1192     update_object (last, UP_OBJ_REMOVE);
1193 root 1.26
1194 root 1.82 if (flag [FLAG_BLOCKSVIEW] || glow_radius)
1195 root 1.59 update_all_los (map, x, y);
1196 elmex 1.1 }
1197     }
1198    
1199     /*
1200     * merge_ob(op,top):
1201     *
1202     * This function goes through all objects below and including top, and
1203     * merges op to the first matching object.
1204     * If top is NULL, it is calculated.
1205     * Returns pointer to object if it succeded in the merge, otherwise NULL
1206     */
1207 root 1.24 object *
1208     merge_ob (object *op, object *top)
1209     {
1210     if (!op->nrof)
1211 elmex 1.1 return 0;
1212 root 1.29
1213 root 1.194 if (!top)
1214 root 1.82 for (top = op; top && top->above; top = top->above)
1215     ;
1216 root 1.29
1217 root 1.82 for (; top; top = top->below)
1218 root 1.214 if (object::can_merge (op, top))
1219     {
1220     top->nrof += op->nrof;
1221    
1222     if (object *pl = top->visible_to ())
1223     esrv_update_item (UPD_NROF, pl, top);
1224    
1225     op->weight = 0; // cancel the addition above
1226     op->carrying = 0; // must be 0 already
1227 root 1.66
1228 root 1.214 op->destroy (1);
1229 root 1.24
1230 root 1.214 return top;
1231     }
1232 root 1.29
1233 root 1.45 return 0;
1234 elmex 1.1 }
1235    
1236 root 1.138 void
1237     object::expand_tail ()
1238     {
1239     if (more)
1240     return;
1241    
1242     object *prev = this;
1243    
1244 root 1.160 for (archetype *at = (archetype *)arch->more; at; at = (archetype *)at->more)
1245 root 1.138 {
1246     object *op = arch_to_object (at);
1247    
1248     op->name = name;
1249     op->name_pl = name_pl;
1250     op->title = title;
1251    
1252     op->head = this;
1253     prev->more = op;
1254    
1255     prev = op;
1256     }
1257     }
1258    
1259 elmex 1.1 /*
1260 root 1.117 * same as insert_ob_in_map except it handles separate coordinates and does a clean
1261     * job preparing multi-part monsters.
1262 elmex 1.1 */
1263 root 1.24 object *
1264 root 1.49 insert_ob_in_map_at (object *op, maptile *m, object *originator, int flag, int x, int y)
1265 root 1.24 {
1266 root 1.93 for (object *tmp = op->head_ (); tmp; tmp = tmp->more)
1267 root 1.24 {
1268 root 1.159 tmp->x = x + tmp->arch->x;
1269     tmp->y = y + tmp->arch->y;
1270 elmex 1.1 }
1271 root 1.29
1272 root 1.24 return insert_ob_in_map (op, m, originator, flag);
1273 elmex 1.1 }
1274    
1275     /*
1276     * insert_ob_in_map (op, map, originator, flag):
1277     * This function inserts the object in the two-way linked list
1278     * which represents what is on a map.
1279     * The second argument specifies the map, and the x and y variables
1280     * in the object about to be inserted specifies the position.
1281     *
1282     * originator: Player, monster or other object that caused 'op' to be inserted
1283     * into 'map'. May be NULL.
1284     *
1285     * flag is a bitmask about special things to do (or not do) when this
1286     * function is called. see the object.h file for the INS_ values.
1287     * Passing 0 for flag gives proper default values, so flag really only needs
1288     * to be set if special handling is needed.
1289     *
1290     * Return value:
1291     * new object if 'op' was merged with other object
1292     * NULL if 'op' was destroyed
1293     * just 'op' otherwise
1294     */
1295 root 1.24 object *
1296 root 1.49 insert_ob_in_map (object *op, maptile *m, object *originator, int flag)
1297 elmex 1.1 {
1298 root 1.138 assert (!op->flag [FLAG_FREED]);
1299    
1300 root 1.117 op->remove ();
1301    
1302 root 1.187 /* Ideally, the caller figures this out. However, it complicates a lot
1303     * of areas of callers (eg, anything that uses find_free_spot would now
1304     * need extra work
1305     */
1306     if (!xy_normalise (m, op->x, op->y))
1307 root 1.24 {
1308 root 1.217 op->destroy (1);
1309 root 1.187 return 0;
1310 elmex 1.1 }
1311 root 1.25
1312 root 1.117 if (object *more = op->more)
1313 root 1.155 if (!insert_ob_in_map (more, m, originator, flag))
1314     return 0;
1315 root 1.25
1316 root 1.24 CLEAR_FLAG (op, FLAG_REMOVED);
1317 root 1.8
1318 root 1.117 op->map = m;
1319     mapspace &ms = op->ms ();
1320 root 1.24
1321     /* this has to be done after we translate the coordinates.
1322     */
1323     if (op->nrof && !(flag & INS_NO_MERGE))
1324 root 1.155 for (object *tmp = ms.bot; tmp; tmp = tmp->above)
1325 root 1.66 if (object::can_merge (op, tmp))
1326 root 1.25 {
1327 root 1.218 // TODO: we atcually want to update tmp, not op,
1328     // but some caller surely breaks when we return tmp
1329     // from here :/
1330 root 1.25 op->nrof += tmp->nrof;
1331 root 1.208 tmp->destroy (1);
1332 root 1.25 }
1333 root 1.24
1334     CLEAR_FLAG (op, FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */
1335     CLEAR_FLAG (op, FLAG_INV_LOCKED);
1336 root 1.25
1337 root 1.24 if (!QUERY_FLAG (op, FLAG_ALIVE))
1338     CLEAR_FLAG (op, FLAG_NO_STEAL);
1339    
1340     if (flag & INS_BELOW_ORIGINATOR)
1341     {
1342     if (originator->map != op->map || originator->x != op->x || originator->y != op->y)
1343     {
1344     LOG (llevError, "insert_ob_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n");
1345     abort ();
1346     }
1347 root 1.25
1348 root 1.24 op->above = originator;
1349     op->below = originator->below;
1350 root 1.25
1351 root 1.24 if (op->below)
1352     op->below->above = op;
1353     else
1354 root 1.117 ms.bot = op;
1355 root 1.25
1356 root 1.24 /* since *below* originator, no need to update top */
1357     originator->below = op;
1358 elmex 1.1 }
1359 root 1.24 else
1360     {
1361 root 1.218 object *top, *floor = NULL;
1362    
1363 root 1.117 top = ms.bot;
1364    
1365 root 1.24 /* If there are other objects, then */
1366 root 1.191 if (top)
1367 root 1.24 {
1368 root 1.96 object *last = 0;
1369 root 1.24
1370     /*
1371     * If there are multiple objects on this space, we do some trickier handling.
1372     * We've already dealt with merging if appropriate.
1373     * Generally, we want to put the new object on top. But if
1374     * flag contains INS_ABOVE_FLOOR_ONLY, once we find the last
1375     * floor, we want to insert above that and no further.
1376     * Also, if there are spell objects on this space, we stop processing
1377     * once we get to them. This reduces the need to traverse over all of
1378     * them when adding another one - this saves quite a bit of cpu time
1379     * when lots of spells are cast in one area. Currently, it is presumed
1380     * that flying non pickable objects are spell objects.
1381     */
1382 root 1.117 for (top = ms.bot; top; top = top->above)
1383 root 1.24 {
1384     if (QUERY_FLAG (top, FLAG_IS_FLOOR) || QUERY_FLAG (top, FLAG_OVERLAY_FLOOR))
1385     floor = top;
1386 root 1.26
1387 root 1.24 if (QUERY_FLAG (top, FLAG_NO_PICK) && (top->move_type & (MOVE_FLY_LOW | MOVE_FLY_HIGH)) && !QUERY_FLAG (top, FLAG_IS_FLOOR))
1388     {
1389     /* We insert above top, so we want this object below this */
1390     top = top->below;
1391     break;
1392     }
1393 root 1.26
1394 root 1.24 last = top;
1395     }
1396 root 1.26
1397 root 1.24 /* Don't want top to be NULL, so set it to the last valid object */
1398     top = last;
1399 root 1.8
1400 root 1.24 /* We let update_position deal with figuring out what the space
1401     * looks like instead of lots of conditions here.
1402     * makes things faster, and effectively the same result.
1403     */
1404    
1405     /* Have object 'fall below' other objects that block view.
1406 root 1.135 * Unless those objects are exits.
1407 root 1.24 * If INS_ON_TOP is used, don't do this processing
1408     * Need to find the object that in fact blocks view, otherwise
1409     * stacking is a bit odd.
1410     */
1411 root 1.117 if (!(flag & INS_ON_TOP)
1412     && ms.flags () & P_BLOCKSVIEW
1413 root 1.135 && (op->face && !faces [op->face].visibility))
1414 root 1.24 {
1415     for (last = top; last != floor; last = last->below)
1416     if (QUERY_FLAG (last, FLAG_BLOCKSVIEW) && (last->type != EXIT))
1417     break;
1418 root 1.117
1419 root 1.24 /* Check to see if we found the object that blocks view,
1420     * and make sure we have a below pointer for it so that
1421     * we can get inserted below this one, which requires we
1422     * set top to the object below us.
1423     */
1424     if (last && last->below && last != floor)
1425     top = last->below;
1426 root 1.8 }
1427 root 1.24 } /* If objects on this space */
1428 root 1.25
1429 root 1.24 if (flag & INS_ABOVE_FLOOR_ONLY)
1430     top = floor;
1431    
1432     /* Top is the object that our object (op) is going to get inserted above.
1433     */
1434    
1435     /* First object on this space */
1436     if (!top)
1437     {
1438 root 1.117 op->above = ms.bot;
1439 root 1.25
1440 root 1.24 if (op->above)
1441     op->above->below = op;
1442 root 1.25
1443 root 1.96 op->below = 0;
1444 root 1.117 ms.bot = op;
1445 root 1.24 }
1446     else
1447     { /* get inserted into the stack above top */
1448     op->above = top->above;
1449 root 1.25
1450 root 1.24 if (op->above)
1451     op->above->below = op;
1452 root 1.25
1453 root 1.24 op->below = top;
1454     top->above = op;
1455     }
1456 root 1.25
1457 root 1.96 if (!op->above)
1458 root 1.117 ms.top = op;
1459 root 1.24 } /* else not INS_BELOW_ORIGINATOR */
1460 root 1.8
1461 root 1.24 if (op->type == PLAYER)
1462 root 1.96 {
1463     op->contr->do_los = 1;
1464     ++op->map->players;
1465 root 1.100 op->map->touch ();
1466 root 1.96 }
1467 root 1.24
1468 root 1.98 op->map->dirty = true;
1469    
1470 root 1.191 if (object *pl = ms.player ())
1471 root 1.218 //TODO: the floorbox prev/next might need updating
1472 root 1.217 esrv_send_item (pl, op);
1473 root 1.24
1474     /* If this object glows, it may affect lighting conditions that are
1475     * visible to others on this map. But update_all_los is really
1476     * an inefficient way to do this, as it means los for all players
1477     * on the map will get recalculated. The players could very well
1478     * be far away from this change and not affected in any way -
1479     * this should get redone to only look for players within range,
1480 root 1.99 * or just updating the P_UPTODATE for spaces within this area
1481 root 1.24 * of effect may be sufficient.
1482     */
1483 root 1.84 if (op->map->darkness && (op->glow_radius != 0))
1484 root 1.24 update_all_los (op->map, op->x, op->y);
1485    
1486     /* updates flags (blocked, alive, no magic, etc) for this map space */
1487     update_object (op, UP_OBJ_INSERT);
1488    
1489 root 1.82 INVOKE_OBJECT (INSERT, op);
1490    
1491 root 1.24 /* Don't know if moving this to the end will break anything. However,
1492 root 1.70 * we want to have floorbox_update called before calling this.
1493 root 1.24 *
1494     * check_move_on() must be after this because code called from
1495     * check_move_on() depends on correct map flags (so functions like
1496     * blocked() and wall() work properly), and these flags are updated by
1497     * update_object().
1498     */
1499    
1500     /* if this is not the head or flag has been passed, don't check walk on status */
1501 root 1.155 if (!(flag & INS_NO_WALK_ON) && op->head_ () == op)
1502 root 1.24 {
1503     if (check_move_on (op, originator))
1504 root 1.82 return 0;
1505 elmex 1.1
1506 root 1.24 /* If we are a multi part object, lets work our way through the check
1507     * walk on's.
1508     */
1509 root 1.155 for (object *tmp = op->more; tmp; tmp = tmp->more)
1510 root 1.24 if (check_move_on (tmp, originator))
1511 root 1.82 return 0;
1512 elmex 1.1 }
1513 root 1.25
1514 root 1.24 return op;
1515 elmex 1.1 }
1516    
1517     /* this function inserts an object in the map, but if it
1518 root 1.75 * finds an object of its own type, it'll remove that one first.
1519     * op is the object to insert it under: supplies x and the map.
1520 elmex 1.1 */
1521 root 1.24 void
1522     replace_insert_ob_in_map (const char *arch_string, object *op)
1523     {
1524     /* first search for itself and remove any old instances */
1525 elmex 1.1
1526 root 1.208 for (object *tmp = op->ms ().bot; tmp; tmp = tmp->above)
1527 root 1.158 if (!strcmp (tmp->arch->archname, arch_string)) /* same archetype */
1528 root 1.208 tmp->destroy (1);
1529    
1530     object *tmp = arch_to_object (archetype::find (arch_string));
1531 elmex 1.1
1532 root 1.208 tmp->x = op->x;
1533     tmp->y = op->y;
1534 elmex 1.1
1535 root 1.208 insert_ob_in_map (tmp, op->map, op, 0);
1536 root 1.24 }
1537 elmex 1.1
1538 root 1.93 object *
1539     object::insert_at (object *where, object *originator, int flags)
1540     {
1541 root 1.205 if (where->env)
1542     return where->env->insert (this);
1543     else
1544     return where->map->insert (this, where->x, where->y, originator, flags);
1545 root 1.93 }
1546    
1547 elmex 1.1 /*
1548 root 1.209 * decrease(object, number) decreases a specified number from
1549 root 1.208 * the amount of an object. If the amount reaches 0, the object
1550 elmex 1.1 * is subsequently removed and freed.
1551     *
1552     * Return value: 'op' if something is left, NULL if the amount reached 0
1553     */
1554 root 1.208 bool
1555 root 1.209 object::decrease (sint32 nr)
1556 elmex 1.1 {
1557 root 1.212 if (!nr)
1558     return true;
1559    
1560 root 1.208 nr = min (nr, nrof);
1561 elmex 1.1
1562 root 1.208 nrof -= nr;
1563 root 1.24
1564 root 1.208 if (nrof)
1565 elmex 1.1 {
1566 root 1.208 adjust_weight (env, -weight * nr); // carrying == 0
1567 elmex 1.1
1568 root 1.212 if (object *pl = visible_to ())
1569     esrv_update_item (UPD_NROF, pl, this);
1570 root 1.29
1571 root 1.212 return true;
1572 elmex 1.1 }
1573 root 1.24 else
1574     {
1575 root 1.212 destroy (1);
1576     return false;
1577 elmex 1.1 }
1578     }
1579    
1580 root 1.209 /*
1581 root 1.210 * split(ob,nr) splits up ob into two parts. The part which
1582 root 1.209 * is returned contains nr objects, and the remaining parts contains
1583 root 1.210 * the rest (or is removed and returned if that number is 0).
1584     * On failure, NULL is returned.
1585 root 1.209 */
1586 root 1.208 object *
1587 root 1.209 object::split (sint32 nr)
1588 root 1.208 {
1589 root 1.212 int have = number_of ();
1590    
1591     if (have < nr)
1592 root 1.209 return 0;
1593 root 1.212 else if (have == nr)
1594 root 1.209 {
1595     remove ();
1596     return this;
1597     }
1598     else
1599     {
1600     decrease (nr);
1601    
1602     object *op = object_create_clone (this);
1603     op->nrof = nr;
1604     return op;
1605     }
1606     }
1607    
1608 root 1.24 object *
1609     insert_ob_in_ob (object *op, object *where)
1610     {
1611 root 1.59 if (!where)
1612 root 1.24 {
1613 root 1.53 char *dump = dump_object (op);
1614     LOG (llevError, "Trying to put object in NULL.\n%s\n", dump);
1615     free (dump);
1616 root 1.24 return op;
1617     }
1618 root 1.29
1619 root 1.154 if (where->head_ () != where)
1620 root 1.24 {
1621 root 1.153 LOG (llevError | logBacktrace, "Warning: Tried to insert object into wrong part of multipart object.\n");
1622 root 1.24 where = where->head;
1623     }
1624 root 1.29
1625 root 1.59 return where->insert (op);
1626     }
1627    
1628     /*
1629     * env->insert (op)
1630     * This function inserts the object op in the linked list
1631     * inside the object environment.
1632     *
1633     * The function returns now pointer to inserted item, and return value can
1634     * be != op, if items are merged. -Tero
1635     */
1636     object *
1637     object::insert (object *op)
1638     {
1639 root 1.24 if (op->more)
1640     {
1641     LOG (llevError, "Tried to insert multipart object %s (%d)\n", &op->name, op->count);
1642     return op;
1643     }
1644 root 1.29
1645 root 1.208 op->remove ();
1646    
1647     op->flag [FLAG_OBJ_ORIGINAL] = 0;
1648 root 1.182
1649 root 1.24 if (op->nrof)
1650 root 1.208 for (object *tmp = inv; tmp; tmp = tmp->below)
1651     if (object::can_merge (tmp, op))
1652     {
1653     /* return the original object and remove inserted object
1654     (client needs the original object) */
1655     tmp->nrof += op->nrof;
1656 root 1.214
1657     if (object *pl = tmp->visible_to ())
1658     esrv_update_item (UPD_NROF, pl, tmp);
1659    
1660 root 1.210 adjust_weight (this, op->total_weight ());
1661    
1662 root 1.208 op->destroy (1);
1663     op = tmp;
1664     goto inserted;
1665     }
1666    
1667     op->owner = 0; // it's his/hers now. period.
1668     op->map = 0;
1669     op->x = 0;
1670     op->y = 0;
1671    
1672     op->above = 0;
1673     op->below = inv;
1674     op->env = this;
1675    
1676     if (inv)
1677     inv->above = op;
1678 root 1.24
1679 root 1.208 inv = op;
1680 elmex 1.1
1681 root 1.208 op->flag [FLAG_REMOVED] = 0;
1682 elmex 1.1
1683 root 1.214 if (object *pl = op->visible_to ())
1684     esrv_send_item (pl, op);
1685    
1686 root 1.208 adjust_weight (this, op->total_weight ());
1687 elmex 1.1
1688 root 1.208 inserted:
1689 elmex 1.1 /* reset the light list and los of the players on the map */
1690 root 1.208 if (op->glow_radius && map && map->darkness)
1691     update_all_los (map, x, y);
1692 elmex 1.1
1693 root 1.214 // if this is a player's inventory, update stats
1694     if (type == PLAYER && !flag [FLAG_NO_FIX_PLAYER])
1695     update_stats ();
1696 root 1.59
1697 root 1.82 INVOKE_OBJECT (INSERT, this);
1698    
1699 elmex 1.1 return op;
1700     }
1701    
1702     /*
1703     * Checks if any objects has a move_type that matches objects
1704     * that effect this object on this space. Call apply() to process
1705     * these events.
1706     *
1707     * Any speed-modification due to SLOW_MOVE() of other present objects
1708     * will affect the speed_left of the object.
1709     *
1710     * originator: Player, monster or other object that caused 'op' to be inserted
1711     * into 'map'. May be NULL.
1712     *
1713     * Return value: 1 if 'op' was destroyed, 0 otherwise.
1714     *
1715     * 4-21-95 added code to check if appropriate skill was readied - this will
1716     * permit faster movement by the player through this terrain. -b.t.
1717     *
1718     * MSW 2001-07-08: Check all objects on space, not just those below
1719     * object being inserted. insert_ob_in_map may not put new objects
1720     * on top.
1721     */
1722 root 1.24 int
1723     check_move_on (object *op, object *originator)
1724 elmex 1.1 {
1725 root 1.48 object *tmp;
1726 root 1.49 maptile *m = op->map;
1727 root 1.48 int x = op->x, y = op->y;
1728 root 1.26
1729 root 1.48 MoveType move_on, move_slow, move_block;
1730 root 1.24
1731     if (QUERY_FLAG (op, FLAG_NO_APPLY))
1732     return 0;
1733    
1734     move_on = GET_MAP_MOVE_ON (op->map, op->x, op->y);
1735     move_slow = GET_MAP_MOVE_SLOW (op->map, op->x, op->y);
1736     move_block = GET_MAP_MOVE_BLOCK (op->map, op->x, op->y);
1737    
1738     /* if nothing on this space will slow op down or be applied,
1739     * no need to do checking below. have to make sure move_type
1740     * is set, as lots of objects don't have it set - we treat that
1741     * as walking.
1742     */
1743     if (op->move_type && !(op->move_type & move_on) && !(op->move_type & move_slow))
1744     return 0;
1745 elmex 1.1
1746 root 1.24 /* This is basically inverse logic of that below - basically,
1747     * if the object can avoid the move on or slow move, they do so,
1748     * but can't do it if the alternate movement they are using is
1749     * blocked. Logic on this seems confusing, but does seem correct.
1750     */
1751     if ((op->move_type & ~move_on & ~move_block) != 0 && (op->move_type & ~move_slow & ~move_block) != 0)
1752     return 0;
1753    
1754     /* The objects have to be checked from top to bottom.
1755     * Hence, we first go to the top:
1756     */
1757    
1758 root 1.104 for (tmp = op->ms ().bot; tmp && tmp->above; tmp = tmp->above)
1759 root 1.24 {
1760     /* Trim the search when we find the first other spell effect
1761     * this helps performance so that if a space has 50 spell objects,
1762     * we don't need to check all of them.
1763     */
1764     if ((tmp->move_type & MOVE_FLY_LOW) && QUERY_FLAG (tmp, FLAG_NO_PICK))
1765     break;
1766     }
1767 root 1.26
1768     for (; tmp; tmp = tmp->below)
1769 root 1.24 {
1770     if (tmp == op)
1771     continue; /* Can't apply yourself */
1772 elmex 1.1
1773 root 1.24 /* Check to see if one of the movement types should be slowed down.
1774     * Second check makes sure that the movement types not being slowed
1775     * (~slow_move) is not blocked on this space - just because the
1776     * space doesn't slow down swimming (for example), if you can't actually
1777     * swim on that space, can't use it to avoid the penalty.
1778     */
1779     if (!QUERY_FLAG (op, FLAG_WIZPASS))
1780     {
1781     if ((!op->move_type && tmp->move_slow & MOVE_WALK) ||
1782     ((op->move_type & tmp->move_slow) && (op->move_type & ~tmp->move_slow & ~tmp->move_block) == 0))
1783     {
1784 elmex 1.1
1785 root 1.29 float
1786 root 1.120 diff = tmp->move_slow_penalty * fabs (op->speed);
1787 elmex 1.1
1788 root 1.24 if (op->type == PLAYER)
1789 root 1.26 if ((QUERY_FLAG (tmp, FLAG_IS_HILLY) && find_skill_by_number (op, SK_CLIMBING)) ||
1790     (QUERY_FLAG (tmp, FLAG_IS_WOODED) && find_skill_by_number (op, SK_WOODSMAN)))
1791     diff /= 4.0;
1792    
1793 root 1.24 op->speed_left -= diff;
1794 root 1.8 }
1795     }
1796 elmex 1.1
1797 root 1.24 /* Basically same logic as above, except now for actual apply. */
1798     if ((!op->move_type && tmp->move_on & MOVE_WALK) ||
1799     ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0))
1800     {
1801 elmex 1.72 move_apply (tmp, op, originator);
1802 root 1.24
1803 root 1.48 if (op->destroyed ())
1804 root 1.24 return 1;
1805    
1806     /* what the person/creature stepped onto has moved the object
1807     * someplace new. Don't process any further - if we did,
1808     * have a feeling strange problems would result.
1809     */
1810     if (op->map != m || op->x != x || op->y != y)
1811     return 0;
1812 root 1.8 }
1813 elmex 1.1 }
1814 root 1.26
1815 root 1.24 return 0;
1816 elmex 1.1 }
1817    
1818     /*
1819     * present_arch(arch, map, x, y) searches for any objects with
1820     * a matching archetype at the given map and coordinates.
1821     * The first matching object is returned, or NULL if none.
1822     */
1823 root 1.24 object *
1824 root 1.49 present_arch (const archetype *at, maptile *m, int x, int y)
1825 root 1.24 {
1826 root 1.104 if (!m || out_of_map (m, x, y))
1827 root 1.24 {
1828     LOG (llevError, "Present_arch called outside map.\n");
1829     return NULL;
1830     }
1831 root 1.84
1832 root 1.104 for (object *tmp = m->at (x, y).bot; tmp; tmp = tmp->above)
1833 root 1.24 if (tmp->arch == at)
1834 elmex 1.1 return tmp;
1835 root 1.84
1836 elmex 1.1 return NULL;
1837     }
1838    
1839     /*
1840     * present(type, map, x, y) searches for any objects with
1841     * a matching type variable at the given map and coordinates.
1842     * The first matching object is returned, or NULL if none.
1843     */
1844 root 1.24 object *
1845 root 1.49 present (unsigned char type, maptile *m, int x, int y)
1846 root 1.24 {
1847     if (out_of_map (m, x, y))
1848     {
1849     LOG (llevError, "Present called outside map.\n");
1850     return NULL;
1851     }
1852 root 1.84
1853 root 1.104 for (object *tmp = m->at (x, y).bot; tmp; tmp = tmp->above)
1854 root 1.24 if (tmp->type == type)
1855 elmex 1.1 return tmp;
1856 root 1.84
1857 elmex 1.1 return NULL;
1858     }
1859    
1860     /*
1861     * present_in_ob(type, object) searches for any objects with
1862     * a matching type variable in the inventory of the given object.
1863     * The first matching object is returned, or NULL if none.
1864     */
1865 root 1.24 object *
1866     present_in_ob (unsigned char type, const object *op)
1867     {
1868 root 1.84 for (object *tmp = op->inv; tmp != NULL; tmp = tmp->below)
1869 root 1.24 if (tmp->type == type)
1870 elmex 1.1 return tmp;
1871 root 1.84
1872 elmex 1.1 return NULL;
1873     }
1874    
1875     /*
1876     * present_in_ob (type, str, object) searches for any objects with
1877     * a matching type & name variable in the inventory of the given object.
1878     * The first matching object is returned, or NULL if none.
1879     * This is mostly used by spell effect code, so that we only
1880     * have one spell effect at a time.
1881     * type can be used to narrow the search - if type is set,
1882     * the type must also match. -1 can be passed for the type,
1883     * in which case the type does not need to pass.
1884     * str is the string to match against. Note that we match against
1885     * the object name, not the archetype name. this is so that the
1886     * spell code can use one object type (force), but change it's name
1887     * to be unique.
1888     */
1889 root 1.24 object *
1890     present_in_ob_by_name (int type, const char *str, const object *op)
1891     {
1892 root 1.84 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1893 root 1.82 if ((type == -1 || tmp->type == type) && (!strcmp (str, tmp->name)))
1894     return tmp;
1895 elmex 1.1
1896 root 1.82 return 0;
1897 elmex 1.1 }
1898    
1899     /*
1900     * present_arch_in_ob(archetype, object) searches for any objects with
1901     * a matching archetype in the inventory of the given object.
1902     * The first matching object is returned, or NULL if none.
1903     */
1904 root 1.24 object *
1905     present_arch_in_ob (const archetype *at, const object *op)
1906     {
1907 root 1.82 for (object *tmp = op->inv; tmp != NULL; tmp = tmp->below)
1908 root 1.24 if (tmp->arch == at)
1909 elmex 1.1 return tmp;
1910 root 1.82
1911 elmex 1.1 return NULL;
1912     }
1913    
1914     /*
1915     * activate recursively a flag on an object inventory
1916     */
1917 root 1.24 void
1918     flag_inv (object *op, int flag)
1919     {
1920 root 1.197 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1921     {
1922     SET_FLAG (tmp, flag);
1923     flag_inv (tmp, flag);
1924     }
1925 root 1.82 }
1926    
1927     /*
1928     * deactivate recursively a flag on an object inventory
1929     */
1930 root 1.24 void
1931     unflag_inv (object *op, int flag)
1932     {
1933 root 1.197 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1934     {
1935     CLEAR_FLAG (tmp, flag);
1936     unflag_inv (tmp, flag);
1937     }
1938 elmex 1.1 }
1939    
1940     /*
1941     * find_free_spot(object, map, x, y, start, stop) will search for
1942     * a spot at the given map and coordinates which will be able to contain
1943     * the given object. start and stop specifies how many squares
1944     * to search (see the freearr_x/y[] definition).
1945     * It returns a random choice among the alternatives found.
1946     * start and stop are where to start relative to the free_arr array (1,9
1947     * does all 4 immediate directions). This returns the index into the
1948     * array of the free spot, -1 if no spot available (dir 0 = x,y)
1949 root 1.196 * Note: This function does correctly handle tiled maps, but does not
1950 elmex 1.1 * inform the caller. However, insert_ob_in_map will update as
1951     * necessary, so the caller shouldn't need to do any special work.
1952     * Note - updated to take an object instead of archetype - this is necessary
1953     * because arch_blocked (now ob_blocked) needs to know the movement type
1954     * to know if the space in question will block the object. We can't use
1955     * the archetype because that isn't correct if the monster has been
1956     * customized, changed states, etc.
1957     */
1958 root 1.24 int
1959 root 1.49 find_free_spot (const object *ob, maptile *m, int x, int y, int start, int stop)
1960 root 1.24 {
1961 root 1.190 int altern[SIZEOFFREE];
1962 root 1.82 int index = 0, flag;
1963 root 1.24
1964 root 1.82 for (int i = start; i < stop; i++)
1965 root 1.24 {
1966 root 1.188 mapxy pos (m, x, y); pos.move (i);
1967    
1968     if (!pos.normalise ())
1969     continue;
1970    
1971     mapspace &ms = *pos;
1972 root 1.189
1973     if (ms.flags () & P_IS_ALIVE)
1974     continue;
1975 root 1.188
1976     /* However, often
1977     * ob doesn't have any move type (when used to place exits)
1978     * so the AND operation in OB_TYPE_MOVE_BLOCK doesn't work.
1979     */
1980 root 1.200 if (ob && ob->move_type == 0 && ms.move_block != MOVE_ALL)
1981 root 1.190 {
1982     altern [index++] = i;
1983     continue;
1984     }
1985 root 1.24
1986     /* Basically, if we find a wall on a space, we cut down the search size.
1987     * In this way, we won't return spaces that are on another side of a wall.
1988     * This mostly work, but it cuts down the search size in all directions -
1989     * if the space being examined only has a wall to the north and empty
1990     * spaces in all the other directions, this will reduce the search space
1991     * to only the spaces immediately surrounding the target area, and
1992     * won't look 2 spaces south of the target space.
1993     */
1994 root 1.188 if (ms.move_block == MOVE_ALL && maxfree[i] < stop)
1995     {
1996     stop = maxfree[i];
1997     continue;
1998     }
1999    
2000     /* Note it is intentional that we check ob - the movement type of the
2001     * head of the object should correspond for the entire object.
2002     */
2003     if (OB_TYPE_MOVE_BLOCK (ob, ms.move_block))
2004     continue;
2005    
2006 root 1.196 if (ob->blocked (m, pos.x, pos.y))
2007     continue;
2008    
2009 root 1.188 altern [index++] = i;
2010 elmex 1.1 }
2011 root 1.74
2012 root 1.24 if (!index)
2013     return -1;
2014 root 1.74
2015 root 1.124 return altern [rndm (index)];
2016 elmex 1.1 }
2017    
2018     /*
2019 root 1.49 * find_first_free_spot(archetype, maptile, x, y) works like
2020 elmex 1.1 * find_free_spot(), but it will search max number of squares.
2021     * But it will return the first available spot, not a random choice.
2022     * Changed 0.93.2: Have it return -1 if there is no free spot available.
2023     */
2024 root 1.24 int
2025 root 1.49 find_first_free_spot (const object *ob, maptile *m, int x, int y)
2026 root 1.24 {
2027 root 1.82 for (int i = 0; i < SIZEOFFREE; i++)
2028 root 1.188 if (!ob->blocked (m, x + freearr_x[i], y + freearr_y[i]))
2029 root 1.82 return i;
2030 root 1.24
2031     return -1;
2032 elmex 1.1 }
2033    
2034     /*
2035     * The function permute(arr, begin, end) randomly reorders the array
2036     * arr[begin..end-1].
2037 root 1.82 * now uses a fisher-yates shuffle, old permute was broken
2038 elmex 1.1 */
2039 root 1.24 static void
2040     permute (int *arr, int begin, int end)
2041 elmex 1.1 {
2042 root 1.82 arr += begin;
2043     end -= begin;
2044    
2045     while (--end)
2046 root 1.124 swap (arr [end], arr [rndm (end + 1)]);
2047 elmex 1.1 }
2048    
2049     /* new function to make monster searching more efficient, and effective!
2050     * This basically returns a randomized array (in the passed pointer) of
2051     * the spaces to find monsters. In this way, it won't always look for
2052     * monsters to the north first. However, the size of the array passed
2053     * covers all the spaces, so within that size, all the spaces within
2054     * the 3x3 area will be searched, just not in a predictable order.
2055     */
2056 root 1.24 void
2057     get_search_arr (int *search_arr)
2058 elmex 1.1 {
2059 root 1.82 int i;
2060 elmex 1.1
2061 root 1.24 for (i = 0; i < SIZEOFFREE; i++)
2062 root 1.82 search_arr[i] = i;
2063 elmex 1.1
2064 root 1.24 permute (search_arr, 1, SIZEOFFREE1 + 1);
2065     permute (search_arr, SIZEOFFREE1 + 1, SIZEOFFREE2 + 1);
2066     permute (search_arr, SIZEOFFREE2 + 1, SIZEOFFREE);
2067 elmex 1.1 }
2068    
2069     /*
2070     * find_dir(map, x, y, exclude) will search some close squares in the
2071     * given map at the given coordinates for live objects.
2072     * It will not considered the object given as exclude among possible
2073     * live objects.
2074     * It returns the direction toward the first/closest live object if finds
2075     * any, otherwise 0.
2076     * Perhaps incorrectly, but I'm making the assumption that exclude
2077     * is actually want is going to try and move there. We need this info
2078     * because we have to know what movement the thing looking to move
2079     * there is capable of.
2080     */
2081 root 1.24 int
2082 root 1.49 find_dir (maptile *m, int x, int y, object *exclude)
2083 root 1.24 {
2084 root 1.82 int i, max = SIZEOFFREE, mflags;
2085 root 1.29
2086     sint16 nx, ny;
2087 root 1.82 object *tmp;
2088     maptile *mp;
2089 root 1.29
2090     MoveType blocked, move_type;
2091 root 1.24
2092 root 1.155 if (exclude && exclude->head_ () != exclude)
2093 root 1.24 {
2094     exclude = exclude->head;
2095     move_type = exclude->move_type;
2096     }
2097     else
2098     {
2099     /* If we don't have anything, presume it can use all movement types. */
2100     move_type = MOVE_ALL;
2101     }
2102    
2103     for (i = 1; i < max; i++)
2104     {
2105     mp = m;
2106     nx = x + freearr_x[i];
2107     ny = y + freearr_y[i];
2108    
2109     mflags = get_map_flags (m, &mp, nx, ny, &nx, &ny);
2110 root 1.75
2111 root 1.24 if (mflags & P_OUT_OF_MAP)
2112 root 1.75 max = maxfree[i];
2113 root 1.24 else
2114     {
2115 root 1.82 mapspace &ms = mp->at (nx, ny);
2116    
2117     blocked = ms.move_block;
2118 root 1.24
2119     if ((move_type & blocked) == move_type)
2120 root 1.75 max = maxfree[i];
2121 root 1.24 else if (mflags & P_IS_ALIVE)
2122     {
2123 root 1.84 for (tmp = ms.bot; tmp; tmp = tmp->above)
2124 root 1.82 if ((tmp->flag [FLAG_MONSTER] || tmp->type == PLAYER)
2125 root 1.155 && (tmp != exclude || (tmp->head_ () != tmp && tmp->head_ () != exclude)))
2126 root 1.75 break;
2127    
2128 root 1.24 if (tmp)
2129 root 1.75 return freedir[i];
2130 root 1.8 }
2131     }
2132 elmex 1.1 }
2133 root 1.75
2134 root 1.24 return 0;
2135 elmex 1.1 }
2136    
2137     /*
2138     * distance(object 1, object 2) will return the square of the
2139     * distance between the two given objects.
2140     */
2141 root 1.24 int
2142     distance (const object *ob1, const object *ob2)
2143     {
2144 root 1.82 return (ob1->x - ob2->x) * (ob1->x - ob2->x) + (ob1->y - ob2->y) * (ob1->y - ob2->y);
2145 elmex 1.1 }
2146    
2147     /*
2148     * find_dir_2(delta-x,delta-y) will return a direction in which
2149     * an object which has subtracted the x and y coordinates of another
2150     * object, needs to travel toward it.
2151     */
2152 root 1.24 int
2153     find_dir_2 (int x, int y)
2154     {
2155 root 1.75 int q;
2156 elmex 1.1
2157 root 1.24 if (y)
2158     q = x * 100 / y;
2159 elmex 1.1 else if (x)
2160 root 1.24 q = -300 * x;
2161 elmex 1.1 else
2162     return 0;
2163    
2164 root 1.24 if (y > 0)
2165     {
2166     if (q < -242)
2167     return 3;
2168     if (q < -41)
2169     return 2;
2170     if (q < 41)
2171     return 1;
2172     if (q < 242)
2173     return 8;
2174     return 7;
2175     }
2176 elmex 1.1
2177     if (q < -242)
2178 root 1.24 return 7;
2179 elmex 1.1 if (q < -41)
2180 root 1.24 return 6;
2181 elmex 1.1 if (q < 41)
2182 root 1.24 return 5;
2183 elmex 1.1 if (q < 242)
2184 root 1.24 return 4;
2185 elmex 1.1
2186 root 1.24 return 3;
2187 elmex 1.1 }
2188    
2189     /*
2190     * dirdiff(dir1, dir2) returns how many 45-degrees differences there is
2191     * between two directions (which are expected to be absolute (see absdir())
2192     */
2193 root 1.24 int
2194     dirdiff (int dir1, int dir2)
2195     {
2196 root 1.82 int d;
2197 root 1.24
2198     d = abs (dir1 - dir2);
2199     if (d > 4)
2200 elmex 1.1 d = 8 - d;
2201 root 1.82
2202 elmex 1.1 return d;
2203     }
2204    
2205     /* peterm:
2206     * do LOS stuff for ball lightning. Go after the closest VISIBLE monster.
2207     * Basically, this is a table of directions, and what directions
2208     * one could go to go back to us. Eg, entry 15 below is 4, 14, 16.
2209     * This basically means that if direction is 15, then it could either go
2210     * direction 4, 14, or 16 to get back to where we are.
2211     * Moved from spell_util.c to object.c with the other related direction
2212     * functions.
2213     */
2214 root 1.82 int reduction_dir[SIZEOFFREE][3] = {
2215 root 1.24 {0, 0, 0}, /* 0 */
2216     {0, 0, 0}, /* 1 */
2217     {0, 0, 0}, /* 2 */
2218     {0, 0, 0}, /* 3 */
2219     {0, 0, 0}, /* 4 */
2220     {0, 0, 0}, /* 5 */
2221     {0, 0, 0}, /* 6 */
2222     {0, 0, 0}, /* 7 */
2223     {0, 0, 0}, /* 8 */
2224     {8, 1, 2}, /* 9 */
2225     {1, 2, -1}, /* 10 */
2226     {2, 10, 12}, /* 11 */
2227     {2, 3, -1}, /* 12 */
2228     {2, 3, 4}, /* 13 */
2229     {3, 4, -1}, /* 14 */
2230     {4, 14, 16}, /* 15 */
2231     {5, 4, -1}, /* 16 */
2232     {4, 5, 6}, /* 17 */
2233     {6, 5, -1}, /* 18 */
2234     {6, 20, 18}, /* 19 */
2235     {7, 6, -1}, /* 20 */
2236     {6, 7, 8}, /* 21 */
2237     {7, 8, -1}, /* 22 */
2238     {8, 22, 24}, /* 23 */
2239     {8, 1, -1}, /* 24 */
2240     {24, 9, 10}, /* 25 */
2241     {9, 10, -1}, /* 26 */
2242     {10, 11, -1}, /* 27 */
2243     {27, 11, 29}, /* 28 */
2244     {11, 12, -1}, /* 29 */
2245     {12, 13, -1}, /* 30 */
2246     {12, 13, 14}, /* 31 */
2247     {13, 14, -1}, /* 32 */
2248     {14, 15, -1}, /* 33 */
2249     {33, 15, 35}, /* 34 */
2250     {16, 15, -1}, /* 35 */
2251     {17, 16, -1}, /* 36 */
2252     {18, 17, 16}, /* 37 */
2253     {18, 17, -1}, /* 38 */
2254     {18, 19, -1}, /* 39 */
2255     {41, 19, 39}, /* 40 */
2256     {19, 20, -1}, /* 41 */
2257     {20, 21, -1}, /* 42 */
2258     {20, 21, 22}, /* 43 */
2259     {21, 22, -1}, /* 44 */
2260     {23, 22, -1}, /* 45 */
2261     {45, 47, 23}, /* 46 */
2262     {23, 24, -1}, /* 47 */
2263     {24, 9, -1}
2264     }; /* 48 */
2265 elmex 1.1
2266     /* Recursive routine to step back and see if we can
2267     * find a path to that monster that we found. If not,
2268     * we don't bother going toward it. Returns 1 if we
2269     * can see a direct way to get it
2270     * Modified to be map tile aware -.MSW
2271     */
2272 root 1.24 int
2273 root 1.49 can_see_monsterP (maptile *m, int x, int y, int dir)
2274 root 1.24 {
2275 root 1.29 sint16 dx, dy;
2276 root 1.75 int mflags;
2277 root 1.24
2278     if (dir < 0)
2279     return 0; /* exit condition: invalid direction */
2280    
2281     dx = x + freearr_x[dir];
2282     dy = y + freearr_y[dir];
2283    
2284     mflags = get_map_flags (m, &m, dx, dy, &dx, &dy);
2285    
2286     /* This functional arguably was incorrect before - it was
2287     * checking for P_WALL - that was basically seeing if
2288     * we could move to the monster - this is being more
2289     * literal on if we can see it. To know if we can actually
2290     * move to the monster, we'd need the monster passed in or
2291     * at least its move type.
2292     */
2293     if (mflags & (P_OUT_OF_MAP | P_BLOCKSVIEW))
2294     return 0;
2295    
2296     /* yes, can see. */
2297     if (dir < 9)
2298     return 1;
2299 root 1.75
2300     return can_see_monsterP (m, x, y, reduction_dir[dir][0])
2301     | can_see_monsterP (m, x, y, reduction_dir[dir][1])
2302     | can_see_monsterP (m, x, y, reduction_dir[dir][2]);
2303 root 1.24 }
2304    
2305 elmex 1.1 /*
2306     * can_pick(picker, item): finds out if an object is possible to be
2307     * picked up by the picker. Returnes 1 if it can be
2308     * picked up, otherwise 0.
2309     *
2310     * Cf 0.91.3 - don't let WIZ's pick up anything - will likely cause
2311     * core dumps if they do.
2312     *
2313     * Add a check so we can't pick up invisible objects (0.93.8)
2314     */
2315 root 1.24 int
2316     can_pick (const object *who, const object *item)
2317     {
2318     return /*QUERY_FLAG(who,FLAG_WIZ)|| */
2319     (item->weight > 0 && !QUERY_FLAG (item, FLAG_NO_PICK) &&
2320     !QUERY_FLAG (item, FLAG_ALIVE) && !item->invisible && (who->type == PLAYER || item->weight < who->weight / 3));
2321 elmex 1.1 }
2322    
2323     /*
2324     * create clone from object to another
2325     */
2326 root 1.24 object *
2327     object_create_clone (object *asrc)
2328     {
2329 root 1.224 object *dst = 0;
2330 elmex 1.1
2331 root 1.24 if (!asrc)
2332 root 1.62 return 0;
2333    
2334 root 1.224 object *src = asrc->head_ ();
2335 root 1.24
2336 root 1.224 object *prev = 0;
2337 root 1.155 for (object *part = src; part; part = part->more)
2338 root 1.24 {
2339 root 1.224 object *tmp = part->clone ();
2340    
2341 root 1.24 tmp->x -= src->x;
2342     tmp->y -= src->y;
2343 root 1.62
2344 root 1.24 if (!part->head)
2345     {
2346     dst = tmp;
2347 root 1.62 tmp->head = 0;
2348 root 1.24 }
2349     else
2350 root 1.75 tmp->head = dst;
2351 root 1.62
2352     tmp->more = 0;
2353    
2354 root 1.24 if (prev)
2355     prev->more = tmp;
2356 root 1.62
2357 root 1.24 prev = tmp;
2358 elmex 1.1 }
2359 root 1.24
2360 root 1.224 for (object *item = src->inv; item; item = item->below)
2361 root 1.48 insert_ob_in_ob (object_create_clone (item), dst);
2362 elmex 1.1
2363 root 1.24 return dst;
2364 elmex 1.1 }
2365    
2366     /* This returns the first object in who's inventory that
2367     * has the same type and subtype match.
2368     * returns NULL if no match.
2369     */
2370 root 1.24 object *
2371     find_obj_by_type_subtype (const object *who, int type, int subtype)
2372 elmex 1.1 {
2373 root 1.82 for (object *tmp = who->inv; tmp; tmp = tmp->below)
2374 root 1.24 if (tmp->type == type && tmp->subtype == subtype)
2375     return tmp;
2376 elmex 1.1
2377 root 1.82 return 0;
2378 elmex 1.1 }
2379    
2380     /* If ob has a field named key, return the link from the list,
2381     * otherwise return NULL.
2382     *
2383     * key must be a passed in shared string - otherwise, this won't
2384     * do the desired thing.
2385     */
2386 root 1.24 key_value *
2387     get_ob_key_link (const object *ob, const char *key)
2388     {
2389 root 1.82 for (key_value *link = ob->key_values; link; link = link->next)
2390 root 1.48 if (link->key == key)
2391     return link;
2392 root 1.24
2393 root 1.82 return 0;
2394 root 1.24 }
2395 elmex 1.1
2396     /*
2397     * Returns the value of op has an extra_field for key, or NULL.
2398     *
2399     * The argument doesn't need to be a shared string.
2400     *
2401     * The returned string is shared.
2402     */
2403 root 1.24 const char *
2404     get_ob_key_value (const object *op, const char *const key)
2405     {
2406 root 1.35 key_value *link;
2407     shstr_cmp canonical_key (key);
2408 root 1.24
2409 root 1.35 if (!canonical_key)
2410 root 1.24 {
2411     /* 1. There being a field named key on any object
2412     * implies there'd be a shared string to find.
2413     * 2. Since there isn't, no object has this field.
2414     * 3. Therefore, *this* object doesn't have this field.
2415     */
2416 root 1.35 return 0;
2417 elmex 1.1 }
2418    
2419 root 1.24 /* This is copied from get_ob_key_link() above -
2420     * only 4 lines, and saves the function call overhead.
2421     */
2422 root 1.35 for (link = op->key_values; link; link = link->next)
2423     if (link->key == canonical_key)
2424     return link->value;
2425    
2426     return 0;
2427 elmex 1.1 }
2428    
2429     /*
2430     * Updates the canonical_key in op to value.
2431     *
2432     * canonical_key is a shared string (value doesn't have to be).
2433     *
2434     * Unless add_key is TRUE, it won't add fields, only change the value of existing
2435     * keys.
2436     *
2437     * Returns TRUE on success.
2438     */
2439 root 1.24 int
2440     set_ob_key_value_s (object *op, const shstr & canonical_key, const char *value, int add_key)
2441     {
2442 root 1.82 key_value *field = NULL, *last = NULL;
2443 root 1.24
2444     for (field = op->key_values; field != NULL; field = field->next)
2445     {
2446     if (field->key != canonical_key)
2447     {
2448     last = field;
2449     continue;
2450     }
2451    
2452     if (value)
2453     field->value = value;
2454     else
2455     {
2456     /* Basically, if the archetype has this key set,
2457     * we need to store the null value so when we save
2458     * it, we save the empty value so that when we load,
2459     * we get this value back again.
2460     */
2461 root 1.159 if (get_ob_key_link (op->arch, canonical_key))
2462 root 1.24 field->value = 0;
2463     else
2464     {
2465     if (last)
2466     last->next = field->next;
2467     else
2468     op->key_values = field->next;
2469    
2470 root 1.29 delete field;
2471 root 1.24 }
2472     }
2473     return TRUE;
2474     }
2475     /* IF we get here, key doesn't exist */
2476    
2477     /* No field, we'll have to add it. */
2478    
2479     if (!add_key)
2480 root 1.82 return FALSE;
2481    
2482 root 1.24 /* There isn't any good reason to store a null
2483     * value in the key/value list. If the archetype has
2484     * this key, then we should also have it, so shouldn't
2485     * be here. If user wants to store empty strings,
2486     * should pass in ""
2487     */
2488     if (value == NULL)
2489 elmex 1.1 return TRUE;
2490 root 1.24
2491     field = new key_value;
2492    
2493     field->key = canonical_key;
2494     field->value = value;
2495     /* Usual prepend-addition. */
2496     field->next = op->key_values;
2497     op->key_values = field;
2498    
2499     return TRUE;
2500 elmex 1.1 }
2501    
2502     /*
2503     * Updates the key in op to value.
2504     *
2505     * If add_key is FALSE, this will only update existing keys,
2506     * and not add new ones.
2507     * In general, should be little reason FALSE is ever passed in for add_key
2508     *
2509     * Returns TRUE on success.
2510     */
2511 root 1.24 int
2512     set_ob_key_value (object *op, const char *key, const char *value, int add_key)
2513 root 1.11 {
2514 root 1.29 shstr key_ (key);
2515 root 1.24
2516 root 1.11 return set_ob_key_value_s (op, key_, value, add_key);
2517 elmex 1.1 }
2518 root 1.31
2519 root 1.34 object::depth_iterator::depth_iterator (object *container)
2520     : iterator_base (container)
2521     {
2522     while (item->inv)
2523     item = item->inv;
2524     }
2525    
2526 root 1.31 void
2527 root 1.34 object::depth_iterator::next ()
2528 root 1.31 {
2529 root 1.34 if (item->below)
2530     {
2531     item = item->below;
2532    
2533     while (item->inv)
2534     item = item->inv;
2535     }
2536 root 1.31 else
2537 root 1.34 item = item->env;
2538 root 1.31 }
2539 root 1.34
2540 elmex 1.97 const char *
2541     object::flag_desc (char *desc, int len) const
2542     {
2543     char *p = desc;
2544     bool first = true;
2545    
2546 root 1.101 *p = 0;
2547    
2548 elmex 1.97 for (int i = 0; i < NUM_FLAGS; i++)
2549     {
2550     if (len <= 10) // magic constant!
2551     {
2552     snprintf (p, len, ",...");
2553     break;
2554     }
2555    
2556 root 1.101 if (flag [i])
2557 elmex 1.97 {
2558     int cnt = snprintf (p, len, "%s%d", first ? "" : ",", i);
2559     len -= cnt;
2560     p += cnt;
2561     first = false;
2562     }
2563     }
2564    
2565     return desc;
2566     }
2567    
2568 root 1.101 // return a suitable string describing an object in enough detail to find it
2569 root 1.36 const char *
2570     object::debug_desc (char *info) const
2571     {
2572 elmex 1.97 char flagdesc[512];
2573     char info2[256 * 4];
2574 root 1.36 char *p = info;
2575    
2576 root 1.203 p += snprintf (p, 512, "{cnt:%d,uuid:%s,name:\"%s\"%s%s,flags:[%s],type:%d}",
2577     count,
2578     uuid.c_str (),
2579 root 1.36 &name,
2580 root 1.117 title ? "\",title:\"" : "",
2581 elmex 1.97 title ? (const char *)title : "",
2582     flag_desc (flagdesc, 512), type);
2583 root 1.36
2584 root 1.217 if (!flag[FLAG_REMOVED] && env)
2585 root 1.36 p += snprintf (p, 256, "(in %s)", env->debug_desc (info2));
2586    
2587     if (map)
2588 root 1.96 p += snprintf (p, 256, "(on %s@%d+%d)", &map->path, x, y);
2589 root 1.36
2590     return info;
2591     }
2592    
2593     const char *
2594     object::debug_desc () const
2595     {
2596 root 1.143 static char info[3][256 * 4];
2597     static int info_idx;
2598 root 1.36
2599 root 1.143 return debug_desc (info [++info_idx % 3]);
2600 root 1.114 }
2601    
2602 root 1.125 struct region *
2603     object::region () const
2604     {
2605     return map ? map->region (x, y)
2606     : region::default_region ();
2607     }
2608    
2609 root 1.129 const materialtype_t *
2610     object::dominant_material () const
2611     {
2612 root 1.165 if (materialtype_t *mt = name_to_material (materialname))
2613     return mt;
2614 root 1.129
2615 root 1.165 return name_to_material (shstr_unknown);
2616 root 1.129 }
2617    
2618 root 1.130 void
2619     object::open_container (object *new_container)
2620     {
2621     if (container == new_container)
2622     return;
2623    
2624 root 1.220 object *old_container = container;
2625    
2626     if (old_container)
2627 root 1.130 {
2628     if (INVOKE_OBJECT (CLOSE, old_container, ARG_OBJECT (this)))
2629     return;
2630    
2631     #if 0
2632     // remove the "Close old_container" object.
2633     if (object *closer = old_container->inv)
2634     if (closer->type == CLOSE_CON)
2635     closer->destroy ();
2636     #endif
2637    
2638 root 1.220 // make sure the container is available
2639     esrv_send_item (this, old_container);
2640    
2641 root 1.216 old_container->flag [FLAG_APPLIED] = false;
2642 root 1.130 container = 0;
2643    
2644 root 1.220 // client needs item update to make it work, client bug requires this to be separate
2645 root 1.130 esrv_update_item (UPD_FLAGS, this, old_container);
2646 root 1.220
2647 root 1.130 new_draw_info_format (NDI_UNIQUE, 0, this, "You close %s.", query_name (old_container));
2648 root 1.177 play_sound (sound_find ("chest_close"));
2649 root 1.130 }
2650    
2651     if (new_container)
2652     {
2653     if (INVOKE_OBJECT (OPEN, new_container, ARG_OBJECT (this)))
2654     return;
2655    
2656     // TODO: this does not seem to serve any purpose anymore?
2657     #if 0
2658     // insert the "Close Container" object.
2659     if (archetype *closer = new_container->other_arch)
2660     {
2661     object *closer = arch_to_object (new_container->other_arch);
2662     closer->flag [FLAG_NO_MAP_SAVE] = 1;
2663     new_container->insert (closer);
2664     }
2665     #endif
2666    
2667 root 1.132 new_draw_info_format (NDI_UNIQUE, 0, this, "You open %s.", query_name (new_container));
2668    
2669 root 1.220 // make sure the container is available, client bug requires this to be separate
2670     esrv_send_item (this, new_container);
2671    
2672 root 1.216 new_container->flag [FLAG_APPLIED] = true;
2673 root 1.130 container = new_container;
2674    
2675 root 1.220 // client needs flag change
2676 root 1.130 esrv_update_item (UPD_FLAGS, this, new_container);
2677 root 1.131 esrv_send_inventory (this, new_container);
2678 root 1.177 play_sound (sound_find ("chest_open"));
2679 root 1.130 }
2680 root 1.220 // else if (!old_container->env && contr && contr->ns)
2681     // contr->ns->floorbox_reset ();
2682 root 1.130 }
2683    
2684 root 1.164 object *
2685     object::force_find (const shstr name)
2686     {
2687     /* cycle through his inventory to look for the MARK we want to
2688     * place
2689     */
2690     for (object *tmp = inv; tmp; tmp = tmp->below)
2691     if (tmp->type == FORCE && tmp->slaying == name)
2692     return splay (tmp);
2693    
2694     return 0;
2695     }
2696    
2697     void
2698     object::force_add (const shstr name, int duration)
2699     {
2700     if (object *force = force_find (name))
2701     force->destroy ();
2702    
2703     object *force = get_archetype (FORCE_NAME);
2704    
2705     force->slaying = name;
2706     force->stats.food = 1;
2707     force->speed_left = -1.f;
2708    
2709     force->set_speed (duration ? 1.f / duration : 0.f);
2710     force->flag [FLAG_IS_USED_UP] = true;
2711     force->flag [FLAG_APPLIED] = true;
2712    
2713     insert (force);
2714     }
2715    
2716 root 1.178 void
2717 root 1.208 object::play_sound (faceidx sound)
2718 root 1.178 {
2719     if (!sound)
2720     return;
2721    
2722     if (flag [FLAG_REMOVED])
2723     return;
2724    
2725     if (env)
2726     {
2727     if (object *pl = in_player ())
2728     pl->contr->play_sound (sound);
2729     }
2730     else
2731     map->play_sound (sound, x, y);
2732     }
2733