ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.222
Committed: Wed Apr 30 05:06:36 2008 UTC (16 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.221: +3 -9 lines
Log Message:
*** empty log message ***

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.137 bool is_freed = flag [FLAG_FREED];
612     bool is_removed = flag [FLAG_REMOVED];
613 root 1.59
614 root 1.137 *(object_copy *)this = src;
615 elmex 1.1
616 root 1.137 flag [FLAG_FREED] = is_freed;
617     flag [FLAG_REMOVED] = is_removed;
618 elmex 1.1
619 root 1.11 /* Copy over key_values, if any. */
620 root 1.137 if (src.key_values)
621 root 1.14 {
622 root 1.23 key_value *tail = 0;
623 root 1.137 key_values = 0;
624 elmex 1.1
625 root 1.137 for (key_value *i = src.key_values; i; i = i->next)
626 root 1.11 {
627     key_value *new_link = new key_value;
628 root 1.8
629 root 1.24 new_link->next = 0;
630     new_link->key = i->key;
631 root 1.11 new_link->value = i->value;
632    
633     /* Try and be clever here, too. */
634 root 1.137 if (!key_values)
635 root 1.11 {
636 root 1.137 key_values = new_link;
637 root 1.11 tail = new_link;
638 root 1.8 }
639 root 1.11 else
640     {
641     tail->next = new_link;
642     tail = new_link;
643     }
644 root 1.14 }
645     }
646 root 1.137 }
647    
648     /*
649     * copy_to first frees everything allocated by the dst object,
650     * and then copies the contents of itself into the second
651     * object, allocating what needs to be allocated. Basically, any
652     * data that is malloc'd needs to be re-malloc/copied. Otherwise,
653     * if the first object is freed, the pointers in the new object
654     * will point at garbage.
655     */
656     void
657     object::copy_to (object *dst)
658     {
659     *dst = *this;
660    
661     if (speed < 0)
662 root 1.185 dst->speed_left -= rndm ();
663 root 1.2
664 root 1.87 dst->set_speed (dst->speed);
665 elmex 1.1 }
666    
667 root 1.133 void
668     object::instantiate ()
669     {
670     if (!uuid.seq) // HACK
671 root 1.202 uuid = UUID::gen ();
672 root 1.133
673     speed_left = -0.1f;
674     /* copy the body_info to the body_used - this is only really
675     * need for monsters, but doesn't hurt to do it for everything.
676     * by doing so, when a monster is created, it has good starting
677     * values for the body_used info, so when items are created
678     * for it, they can be properly equipped.
679     */
680 root 1.145 for (int i = NUM_BODY_LOCATIONS; i--; )
681     slot[i].used = slot[i].info;
682 root 1.133
683     attachable::instantiate ();
684     }
685    
686 root 1.65 object *
687     object::clone ()
688     {
689     object *neu = create ();
690     copy_to (neu);
691     return neu;
692     }
693    
694 elmex 1.1 /*
695     * If an object with the IS_TURNABLE() flag needs to be turned due
696     * to the closest player being on the other side, this function can
697     * be called to update the face variable, _and_ how it looks on the map.
698     */
699 root 1.24 void
700     update_turn_face (object *op)
701     {
702 root 1.96 if (!QUERY_FLAG (op, FLAG_IS_TURNABLE) || !op->arch)
703 root 1.24 return;
704 root 1.96
705 root 1.24 SET_ANIMATION (op, op->direction);
706     update_object (op, UP_OBJ_FACE);
707 elmex 1.1 }
708    
709     /*
710     * Updates the speed of an object. If the speed changes from 0 to another
711     * value, or vice versa, then add/remove the object from the active list.
712     * This function needs to be called whenever the speed of an object changes.
713     */
714 root 1.24 void
715 root 1.87 object::set_speed (float speed)
716 root 1.24 {
717 root 1.87 if (flag [FLAG_FREED] && speed)
718 root 1.24 {
719 root 1.87 LOG (llevError, "Object %s is freed but has speed.\n", &name);
720     speed = 0;
721 elmex 1.1 }
722 root 1.31
723 root 1.87 this->speed = speed;
724    
725 elmex 1.97 if (has_active_speed ())
726 root 1.98 activate ();
727 root 1.24 else
728 root 1.98 deactivate ();
729 elmex 1.1 }
730    
731     /*
732 root 1.75 * update_object() updates the the map.
733 elmex 1.1 * It takes into account invisible objects (and represent squares covered
734     * by invisible objects by whatever is below them (unless it's another
735     * invisible object, etc...)
736     * If the object being updated is beneath a player, the look-window
737     * of that player is updated (this might be a suboptimal way of
738     * updating that window, though, since update_object() is called _often_)
739     *
740     * action is a hint of what the caller believes need to be done.
741     * current action are:
742     * UP_OBJ_INSERT: op was inserted
743     * UP_OBJ_REMOVE: op was removed
744     * UP_OBJ_CHANGE: object has somehow changed. In this case, we always update
745     * as that is easier than trying to look at what may have changed.
746     * UP_OBJ_FACE: only the objects face has changed.
747     */
748 root 1.24 void
749     update_object (object *op, int action)
750     {
751 root 1.222 if (!op)
752 root 1.24 {
753     /* this should never happen */
754 root 1.222 LOG (llevError | logBacktrace, "update_object() called for NULL object.\n");
755 root 1.24 return;
756 elmex 1.1 }
757 root 1.24
758 root 1.222 if (!op->is_on_map ())
759 root 1.24 {
760     /* Animation is currently handled by client, so nothing
761     * to do in this case.
762     */
763     return;
764 elmex 1.1 }
765    
766 root 1.24 /* make sure the object is within map boundaries */
767 root 1.83 if (op->x < 0 || op->x >= op->map->width || op->y < 0 || op->y >= op->map->height)
768 root 1.24 {
769     LOG (llevError, "update_object() called for object out of map!\n");
770 elmex 1.1 #ifdef MANY_CORES
771 root 1.24 abort ();
772 elmex 1.1 #endif
773 root 1.24 return;
774 elmex 1.1 }
775    
776 root 1.76 mapspace &m = op->ms ();
777 elmex 1.1
778 root 1.99 if (!(m.flags_ & P_UPTODATE))
779 root 1.75 /* nop */;
780     else if (action == UP_OBJ_INSERT)
781     {
782     // this is likely overkill, TODO: revisit (schmorp)
783     if ((QUERY_FLAG (op, FLAG_BLOCKSVIEW) && !(m.flags_ & P_BLOCKSVIEW))
784     || (QUERY_FLAG (op, FLAG_NO_MAGIC) && !(m.flags_ & P_NO_MAGIC))
785     || (op->type == PLAYER && !(m.flags_ & P_PLAYER))
786     || (op->type == SAFE_GROUND && !(m.flags_ & P_SAFE))
787     || (QUERY_FLAG (op, FLAG_ALIVE) && !(m.flags_ & P_IS_ALIVE))
788     || (QUERY_FLAG (op, FLAG_DAMNED) && !(m.flags_ & P_NO_CLERIC))
789     || (m.move_on | op->move_on ) != m.move_on
790     || (m.move_off | op->move_off ) != m.move_off
791     || (m.move_slow | op->move_slow) != m.move_slow
792     /* This isn't perfect, but I don't expect a lot of objects to
793     * to have move_allow right now.
794     */
795     || ((m.move_block | op->move_block) & ~op->move_allow) != m.move_block
796     || 1) // the above is not strong enough a test to skip updating. los maybe? TODO (Schmorp)
797 root 1.99 m.flags_ = 0;
798 root 1.75 }
799     /* if the object is being removed, we can't make intelligent
800     * decisions, because remove_ob can't really pass the object
801     * that is being removed.
802     */
803 root 1.24 else if (action == UP_OBJ_CHANGE || action == UP_OBJ_REMOVE)
804 root 1.99 m.flags_ = 0;
805 root 1.24 else if (action == UP_OBJ_FACE)
806 root 1.29 /* Nothing to do for that case */ ;
807 root 1.24 else
808 root 1.27 LOG (llevError, "update_object called with invalid action: %d\n", action);
809 elmex 1.1
810 root 1.75 if (op->more)
811 root 1.24 update_object (op->more, action);
812 elmex 1.1 }
813    
814 root 1.21 object::object ()
815     {
816 root 1.22 SET_FLAG (this, FLAG_REMOVED);
817    
818     expmul = 1.0;
819     face = blank_face;
820     }
821    
822     object::~object ()
823     {
824 root 1.121 unlink ();
825 root 1.119
826 root 1.22 free_key_values (this);
827     }
828    
829 root 1.112 static int object_count;
830    
831 root 1.24 void object::link ()
832 root 1.22 {
833 root 1.112 assert (!index);//D
834 root 1.202 uuid = UUID::gen ();
835 root 1.112 count = ++object_count;
836 root 1.21
837 root 1.109 refcnt_inc ();
838 root 1.108 objects.insert (this);
839 root 1.21 }
840    
841 root 1.24 void object::unlink ()
842 root 1.21 {
843 root 1.121 if (!index)
844     return;
845    
846 root 1.108 objects.erase (this);
847 root 1.109 refcnt_dec ();
848 root 1.98 }
849    
850 root 1.96 void
851 root 1.98 object::activate ()
852 root 1.96 {
853 root 1.98 /* If already on active list, don't do anything */
854 root 1.108 if (active)
855 root 1.98 return;
856    
857 elmex 1.97 if (has_active_speed ())
858 root 1.108 actives.insert (this);
859 root 1.98 }
860 root 1.96
861 root 1.98 void
862     object::activate_recursive ()
863     {
864     activate ();
865    
866 root 1.104 for (object *op = inv; op; op = op->below)
867 root 1.98 op->activate_recursive ();
868 root 1.96 }
869    
870     /* This function removes object 'op' from the list of active
871     * objects.
872     * This should only be used for style maps or other such
873     * reference maps where you don't want an object that isn't
874     * in play chewing up cpu time getting processed.
875     * The reverse of this is to call update_ob_speed, which
876     * will do the right thing based on the speed of the object.
877     */
878     void
879 root 1.98 object::deactivate ()
880 root 1.96 {
881     /* If not on the active list, nothing needs to be done */
882 root 1.108 if (!active)
883 root 1.96 return;
884    
885 root 1.108 actives.erase (this);
886 root 1.98 }
887 root 1.96
888 root 1.98 void
889     object::deactivate_recursive ()
890     {
891 root 1.104 for (object *op = inv; op; op = op->below)
892 root 1.98 op->deactivate_recursive ();
893    
894     deactivate ();
895 root 1.96 }
896    
897 root 1.106 void
898     object::set_flag_inv (int flag, int value)
899     {
900     for (object *op = inv; op; op = op->below)
901     {
902     op->flag [flag] = value;
903     op->set_flag_inv (flag, value);
904     }
905     }
906    
907 root 1.89 /*
908     * Remove and free all objects in the inventory of the given object.
909     * object.c ?
910     */
911     void
912     object::destroy_inv (bool drop_to_ground)
913     {
914 root 1.94 // need to check first, because the checks below might segfault
915     // as we might be on an invalid mapspace and crossfire code
916     // is too buggy to ensure that the inventory is empty.
917 root 1.217 // corollary: if you create arrows etc. with stuff in its inventory,
918 root 1.94 // cf will crash below with off-map x and y
919     if (!inv)
920     return;
921    
922 root 1.89 /* Only if the space blocks everything do we not process -
923     * if some form of movement is allowed, let objects
924     * drop on that space.
925     */
926 root 1.92 if (!drop_to_ground
927     || !map
928 root 1.206 || map->in_memory != MAP_ACTIVE
929 root 1.122 || map->nodrop
930 root 1.95 || ms ().move_block == MOVE_ALL)
931 root 1.89 {
932     while (inv)
933 root 1.92 {
934 root 1.217 inv->destroy_inv (false);
935 root 1.92 inv->destroy ();
936     }
937 root 1.89 }
938     else
939     { /* Put objects in inventory onto this space */
940     while (inv)
941     {
942     object *op = inv;
943    
944     if (op->flag [FLAG_STARTEQUIP]
945     || op->flag [FLAG_NO_DROP]
946     || op->type == RUNE
947     || op->type == TRAP
948 root 1.110 || op->flag [FLAG_IS_A_TEMPLATE]
949     || op->flag [FLAG_DESTROY_ON_DEATH])
950 root 1.217 op->destroy (true);
951 root 1.89 else
952 root 1.93 map->insert (op, x, y);
953 root 1.89 }
954     }
955     }
956    
957 root 1.21 object *object::create ()
958     {
959 root 1.42 object *op = new object;
960 root 1.22 op->link ();
961     return op;
962 root 1.21 }
963 elmex 1.1
964 root 1.82 void
965     object::do_destroy ()
966 root 1.14 {
967 root 1.82 if (flag [FLAG_IS_LINKED])
968     remove_button_link (this);
969 root 1.29
970 root 1.82 if (flag [FLAG_FRIENDLY])
971 root 1.140 remove_friendly_object (this);
972 root 1.32
973 root 1.213 remove ();
974    
975     attachable::do_destroy ();
976 root 1.14
977 root 1.112 deactivate ();
978     unlink ();
979 root 1.92
980 root 1.82 flag [FLAG_FREED] = 1;
981 root 1.14
982 root 1.57 // hack to ensure that freed objects still have a valid map
983     {
984     static maptile *freed_map; // freed objects are moved here to avoid crashes
985    
986     if (!freed_map)
987     {
988     freed_map = new maptile;
989    
990 root 1.186 freed_map->path = "<freed objects map>";
991 root 1.57 freed_map->name = "/internal/freed_objects_map";
992     freed_map->width = 3;
993     freed_map->height = 3;
994 root 1.201 freed_map->nodrop = 1;
995 root 1.57
996 root 1.96 freed_map->alloc ();
997 root 1.206 freed_map->in_memory = MAP_ACTIVE;
998 root 1.57 }
999    
1000     map = freed_map;
1001     x = 1;
1002     y = 1;
1003     }
1004    
1005 root 1.88 if (more)
1006     {
1007     more->destroy ();
1008     more = 0;
1009     }
1010 root 1.82
1011 root 1.162 head = 0;
1012    
1013     // clear those pointers that likely might cause circular references
1014     owner = 0;
1015     enemy = 0;
1016     attacked_by = 0;
1017     current_weapon = 0;
1018 root 1.82 }
1019    
1020     void
1021     object::destroy (bool destroy_inventory)
1022     {
1023     if (destroyed ())
1024     return;
1025    
1026 root 1.219 if (!is_head () && !head->destroyed ())
1027     {
1028     LOG (llevError | logBacktrace, "tried to destroy the tail of an object");
1029     head->destroy (destroy_inventory);
1030     }
1031    
1032 root 1.217 destroy_inv (!destroy_inventory);
1033 root 1.22
1034 root 1.173 if (is_head ())
1035     if (sound_destroy)
1036     play_sound (sound_destroy);
1037     else if (flag [FLAG_MONSTER])
1038     play_sound (sound_find ("monster_destroy")); // quick hack, too lazy to create a generic mechanism
1039 root 1.169
1040 root 1.82 attachable::destroy ();
1041 elmex 1.1 }
1042    
1043 root 1.63 /* op->remove ():
1044 elmex 1.1 * This function removes the object op from the linked list of objects
1045     * which it is currently tied to. When this function is done, the
1046     * object will have no environment. If the object previously had an
1047     * environment, the x and y coordinates will be updated to
1048     * the previous environment.
1049     */
1050 root 1.24 void
1051 root 1.128 object::do_remove ()
1052 root 1.24 {
1053 root 1.45 object *tmp, *last = 0;
1054     object *otmp;
1055 root 1.26
1056 root 1.213 if (flag [FLAG_REMOVED])
1057 root 1.29 return;
1058 root 1.24
1059 root 1.82 INVOKE_OBJECT (REMOVE, this);
1060 root 1.26
1061 root 1.213 flag [FLAG_REMOVED] = true;
1062    
1063 root 1.59 if (more)
1064     more->remove ();
1065 root 1.24
1066     /*
1067     * In this case, the object to be removed is in someones
1068     * inventory.
1069     */
1070 root 1.59 if (env)
1071 root 1.24 {
1072 root 1.221 flag [FLAG_REMOVED] = false; // hack around the issue of visible_to checking flag_removed
1073 root 1.220 if (object *pl = visible_to ())
1074     esrv_del_item (pl->contr, count);
1075 root 1.221 flag [FLAG_REMOVED] = true; // hack around the issue of visible_to checking flag_removed
1076 root 1.220
1077 root 1.208 adjust_weight (env, -total_weight ());
1078 root 1.24
1079 root 1.208 *(above ? &above->below : &env->inv) = below;
1080 root 1.24
1081 root 1.96 if (below)
1082 root 1.59 below->above = above;
1083 root 1.24
1084     /* we set up values so that it could be inserted into
1085     * the map, but we don't actually do that - it is up
1086     * to the caller to decide what we want to do.
1087     */
1088 root 1.208 map = env->map;
1089     x = env->x;
1090     y = env->y;
1091     above = 0;
1092     below = 0;
1093     env = 0;
1094    
1095     /* NO_FIX_PLAYER is set when a great many changes are being
1096     * made to players inventory. If set, avoiding the call
1097     * to save cpu time.
1098     */
1099     if ((otmp = in_player ()) && otmp->contr && !QUERY_FLAG (otmp, FLAG_NO_FIX_PLAYER))
1100     otmp->update_stats ();
1101 root 1.59 }
1102     else if (map)
1103     {
1104 root 1.220 map->dirty = true;
1105     mapspace &ms = this->ms ();
1106    
1107     if (object *pl = ms.player ())
1108 root 1.96 {
1109 root 1.220 if (type == PLAYER) // this == pl(!)
1110     {
1111     // leaving a spot always closes any open container on the ground
1112     if (container && !container->env)
1113     // this causes spurious floorbox updates, but it ensures
1114     // that the CLOSE event is being sent.
1115     close_container ();
1116    
1117     --map->players;
1118     map->touch ();
1119     }
1120     else if (pl->container == this)
1121     {
1122     // removing a container should close it
1123     close_container ();
1124     }
1125 root 1.130
1126 root 1.220 esrv_del_item (pl->contr, count);
1127 root 1.96 }
1128    
1129 root 1.29 /* link the object above us */
1130 root 1.59 if (above)
1131     above->below = below;
1132 root 1.29 else
1133 root 1.117 ms.top = below; /* we were top, set new top */
1134 root 1.24
1135 root 1.29 /* Relink the object below us, if there is one */
1136 root 1.59 if (below)
1137     below->above = above;
1138 root 1.29 else
1139     {
1140     /* Nothing below, which means we need to relink map object for this space
1141     * use translated coordinates in case some oddness with map tiling is
1142     * evident
1143     */
1144 root 1.59 if (GET_MAP_OB (map, x, y) != this)
1145 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 ());
1146 elmex 1.1
1147 root 1.117 ms.bot = above; /* goes on above it. */
1148 root 1.8 }
1149 root 1.26
1150 root 1.59 above = 0;
1151     below = 0;
1152 root 1.26
1153 root 1.59 if (map->in_memory == MAP_SAVING)
1154 root 1.29 return;
1155 elmex 1.1
1156 root 1.82 int check_walk_off = !flag [FLAG_NO_APPLY];
1157 elmex 1.1
1158 root 1.175 if (object *pl = ms.player ())
1159     {
1160     if (pl->container == this)
1161     /* If a container that the player is currently using somehow gets
1162     * removed (most likely destroyed), update the player view
1163     * appropriately.
1164     */
1165     pl->close_container ();
1166    
1167 root 1.218 //TODO: the floorbox prev/next might need updating
1168     esrv_del_item (pl->contr, count);
1169 root 1.175 }
1170    
1171 root 1.117 for (tmp = ms.bot; tmp; tmp = tmp->above)
1172 root 1.24 {
1173 root 1.29 /* No point updating the players look faces if he is the object
1174     * being removed.
1175 root 1.24 */
1176 root 1.29
1177 root 1.96 /* See if object moving off should effect something */
1178 root 1.50 if (check_walk_off
1179 root 1.59 && ((move_type & tmp->move_off)
1180     && (move_type & ~tmp->move_off & ~tmp->move_block) == 0))
1181 root 1.29 {
1182 elmex 1.72 move_apply (tmp, this, 0);
1183 root 1.24
1184 root 1.59 if (destroyed ())
1185 root 1.50 LOG (llevError, "BUG: remove_ob(): name %s, destroyed leaving object\n", tmp->debug_desc ());
1186 root 1.8 }
1187    
1188 root 1.29 last = tmp;
1189     }
1190 root 1.26
1191 root 1.96 /* last == NULL if there are no objects on this space */
1192     //TODO: this makes little sense, why only update the topmost object?
1193 root 1.59 if (!last)
1194 root 1.99 map->at (x, y).flags_ = 0;
1195 root 1.29 else
1196     update_object (last, UP_OBJ_REMOVE);
1197 root 1.26
1198 root 1.82 if (flag [FLAG_BLOCKSVIEW] || glow_radius)
1199 root 1.59 update_all_los (map, x, y);
1200 elmex 1.1 }
1201     }
1202    
1203     /*
1204     * merge_ob(op,top):
1205     *
1206     * This function goes through all objects below and including top, and
1207     * merges op to the first matching object.
1208     * If top is NULL, it is calculated.
1209     * Returns pointer to object if it succeded in the merge, otherwise NULL
1210     */
1211 root 1.24 object *
1212     merge_ob (object *op, object *top)
1213     {
1214     if (!op->nrof)
1215 elmex 1.1 return 0;
1216 root 1.29
1217 root 1.194 if (!top)
1218 root 1.82 for (top = op; top && top->above; top = top->above)
1219     ;
1220 root 1.29
1221 root 1.82 for (; top; top = top->below)
1222 root 1.214 if (object::can_merge (op, top))
1223     {
1224     top->nrof += op->nrof;
1225    
1226     if (object *pl = top->visible_to ())
1227     esrv_update_item (UPD_NROF, pl, top);
1228    
1229     op->weight = 0; // cancel the addition above
1230     op->carrying = 0; // must be 0 already
1231 root 1.66
1232 root 1.214 op->destroy (1);
1233 root 1.24
1234 root 1.214 return top;
1235     }
1236 root 1.29
1237 root 1.45 return 0;
1238 elmex 1.1 }
1239    
1240 root 1.138 void
1241     object::expand_tail ()
1242     {
1243     if (more)
1244     return;
1245    
1246     object *prev = this;
1247    
1248 root 1.160 for (archetype *at = (archetype *)arch->more; at; at = (archetype *)at->more)
1249 root 1.138 {
1250     object *op = arch_to_object (at);
1251    
1252     op->name = name;
1253     op->name_pl = name_pl;
1254     op->title = title;
1255    
1256     op->head = this;
1257     prev->more = op;
1258    
1259     prev = op;
1260     }
1261     }
1262    
1263 elmex 1.1 /*
1264 root 1.117 * same as insert_ob_in_map except it handles separate coordinates and does a clean
1265     * job preparing multi-part monsters.
1266 elmex 1.1 */
1267 root 1.24 object *
1268 root 1.49 insert_ob_in_map_at (object *op, maptile *m, object *originator, int flag, int x, int y)
1269 root 1.24 {
1270 root 1.93 for (object *tmp = op->head_ (); tmp; tmp = tmp->more)
1271 root 1.24 {
1272 root 1.159 tmp->x = x + tmp->arch->x;
1273     tmp->y = y + tmp->arch->y;
1274 elmex 1.1 }
1275 root 1.29
1276 root 1.24 return insert_ob_in_map (op, m, originator, flag);
1277 elmex 1.1 }
1278    
1279     /*
1280     * insert_ob_in_map (op, map, originator, flag):
1281     * This function inserts the object in the two-way linked list
1282     * which represents what is on a map.
1283     * The second argument specifies the map, and the x and y variables
1284     * in the object about to be inserted specifies the position.
1285     *
1286     * originator: Player, monster or other object that caused 'op' to be inserted
1287     * into 'map'. May be NULL.
1288     *
1289     * flag is a bitmask about special things to do (or not do) when this
1290     * function is called. see the object.h file for the INS_ values.
1291     * Passing 0 for flag gives proper default values, so flag really only needs
1292     * to be set if special handling is needed.
1293     *
1294     * Return value:
1295     * new object if 'op' was merged with other object
1296     * NULL if 'op' was destroyed
1297     * just 'op' otherwise
1298     */
1299 root 1.24 object *
1300 root 1.49 insert_ob_in_map (object *op, maptile *m, object *originator, int flag)
1301 elmex 1.1 {
1302 root 1.138 assert (!op->flag [FLAG_FREED]);
1303    
1304 root 1.117 op->remove ();
1305    
1306 root 1.187 /* Ideally, the caller figures this out. However, it complicates a lot
1307     * of areas of callers (eg, anything that uses find_free_spot would now
1308     * need extra work
1309     */
1310     if (!xy_normalise (m, op->x, op->y))
1311 root 1.24 {
1312 root 1.217 op->destroy (1);
1313 root 1.187 return 0;
1314 elmex 1.1 }
1315 root 1.25
1316 root 1.117 if (object *more = op->more)
1317 root 1.155 if (!insert_ob_in_map (more, m, originator, flag))
1318     return 0;
1319 root 1.25
1320 root 1.24 CLEAR_FLAG (op, FLAG_REMOVED);
1321 root 1.8
1322 root 1.117 op->map = m;
1323     mapspace &ms = op->ms ();
1324 root 1.24
1325     /* this has to be done after we translate the coordinates.
1326     */
1327     if (op->nrof && !(flag & INS_NO_MERGE))
1328 root 1.155 for (object *tmp = ms.bot; tmp; tmp = tmp->above)
1329 root 1.66 if (object::can_merge (op, tmp))
1330 root 1.25 {
1331 root 1.218 // TODO: we atcually want to update tmp, not op,
1332     // but some caller surely breaks when we return tmp
1333     // from here :/
1334 root 1.25 op->nrof += tmp->nrof;
1335 root 1.208 tmp->destroy (1);
1336 root 1.25 }
1337 root 1.24
1338     CLEAR_FLAG (op, FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */
1339     CLEAR_FLAG (op, FLAG_INV_LOCKED);
1340 root 1.25
1341 root 1.24 if (!QUERY_FLAG (op, FLAG_ALIVE))
1342     CLEAR_FLAG (op, FLAG_NO_STEAL);
1343    
1344     if (flag & INS_BELOW_ORIGINATOR)
1345     {
1346     if (originator->map != op->map || originator->x != op->x || originator->y != op->y)
1347     {
1348     LOG (llevError, "insert_ob_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n");
1349     abort ();
1350     }
1351 root 1.25
1352 root 1.24 op->above = originator;
1353     op->below = originator->below;
1354 root 1.25
1355 root 1.24 if (op->below)
1356     op->below->above = op;
1357     else
1358 root 1.117 ms.bot = op;
1359 root 1.25
1360 root 1.24 /* since *below* originator, no need to update top */
1361     originator->below = op;
1362 elmex 1.1 }
1363 root 1.24 else
1364     {
1365 root 1.218 object *top, *floor = NULL;
1366    
1367 root 1.117 top = ms.bot;
1368    
1369 root 1.24 /* If there are other objects, then */
1370 root 1.191 if (top)
1371 root 1.24 {
1372 root 1.96 object *last = 0;
1373 root 1.24
1374     /*
1375     * If there are multiple objects on this space, we do some trickier handling.
1376     * We've already dealt with merging if appropriate.
1377     * Generally, we want to put the new object on top. But if
1378     * flag contains INS_ABOVE_FLOOR_ONLY, once we find the last
1379     * floor, we want to insert above that and no further.
1380     * Also, if there are spell objects on this space, we stop processing
1381     * once we get to them. This reduces the need to traverse over all of
1382     * them when adding another one - this saves quite a bit of cpu time
1383     * when lots of spells are cast in one area. Currently, it is presumed
1384     * that flying non pickable objects are spell objects.
1385     */
1386 root 1.117 for (top = ms.bot; top; top = top->above)
1387 root 1.24 {
1388     if (QUERY_FLAG (top, FLAG_IS_FLOOR) || QUERY_FLAG (top, FLAG_OVERLAY_FLOOR))
1389     floor = top;
1390 root 1.26
1391 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))
1392     {
1393     /* We insert above top, so we want this object below this */
1394     top = top->below;
1395     break;
1396     }
1397 root 1.26
1398 root 1.24 last = top;
1399     }
1400 root 1.26
1401 root 1.24 /* Don't want top to be NULL, so set it to the last valid object */
1402     top = last;
1403 root 1.8
1404 root 1.24 /* We let update_position deal with figuring out what the space
1405     * looks like instead of lots of conditions here.
1406     * makes things faster, and effectively the same result.
1407     */
1408    
1409     /* Have object 'fall below' other objects that block view.
1410 root 1.135 * Unless those objects are exits.
1411 root 1.24 * If INS_ON_TOP is used, don't do this processing
1412     * Need to find the object that in fact blocks view, otherwise
1413     * stacking is a bit odd.
1414     */
1415 root 1.117 if (!(flag & INS_ON_TOP)
1416     && ms.flags () & P_BLOCKSVIEW
1417 root 1.135 && (op->face && !faces [op->face].visibility))
1418 root 1.24 {
1419     for (last = top; last != floor; last = last->below)
1420     if (QUERY_FLAG (last, FLAG_BLOCKSVIEW) && (last->type != EXIT))
1421     break;
1422 root 1.117
1423 root 1.24 /* Check to see if we found the object that blocks view,
1424     * and make sure we have a below pointer for it so that
1425     * we can get inserted below this one, which requires we
1426     * set top to the object below us.
1427     */
1428     if (last && last->below && last != floor)
1429     top = last->below;
1430 root 1.8 }
1431 root 1.24 } /* If objects on this space */
1432 root 1.25
1433 root 1.24 if (flag & INS_ABOVE_FLOOR_ONLY)
1434     top = floor;
1435    
1436     /* Top is the object that our object (op) is going to get inserted above.
1437     */
1438    
1439     /* First object on this space */
1440     if (!top)
1441     {
1442 root 1.117 op->above = ms.bot;
1443 root 1.25
1444 root 1.24 if (op->above)
1445     op->above->below = op;
1446 root 1.25
1447 root 1.96 op->below = 0;
1448 root 1.117 ms.bot = op;
1449 root 1.24 }
1450     else
1451     { /* get inserted into the stack above top */
1452     op->above = top->above;
1453 root 1.25
1454 root 1.24 if (op->above)
1455     op->above->below = op;
1456 root 1.25
1457 root 1.24 op->below = top;
1458     top->above = op;
1459     }
1460 root 1.25
1461 root 1.96 if (!op->above)
1462 root 1.117 ms.top = op;
1463 root 1.24 } /* else not INS_BELOW_ORIGINATOR */
1464 root 1.8
1465 root 1.24 if (op->type == PLAYER)
1466 root 1.96 {
1467     op->contr->do_los = 1;
1468     ++op->map->players;
1469 root 1.100 op->map->touch ();
1470 root 1.96 }
1471 root 1.24
1472 root 1.98 op->map->dirty = true;
1473    
1474 root 1.191 if (object *pl = ms.player ())
1475 root 1.218 //TODO: the floorbox prev/next might need updating
1476 root 1.217 esrv_send_item (pl, op);
1477 root 1.24
1478     /* If this object glows, it may affect lighting conditions that are
1479     * visible to others on this map. But update_all_los is really
1480     * an inefficient way to do this, as it means los for all players
1481     * on the map will get recalculated. The players could very well
1482     * be far away from this change and not affected in any way -
1483     * this should get redone to only look for players within range,
1484 root 1.99 * or just updating the P_UPTODATE for spaces within this area
1485 root 1.24 * of effect may be sufficient.
1486     */
1487 root 1.84 if (op->map->darkness && (op->glow_radius != 0))
1488 root 1.24 update_all_los (op->map, op->x, op->y);
1489    
1490     /* updates flags (blocked, alive, no magic, etc) for this map space */
1491     update_object (op, UP_OBJ_INSERT);
1492    
1493 root 1.82 INVOKE_OBJECT (INSERT, op);
1494    
1495 root 1.24 /* Don't know if moving this to the end will break anything. However,
1496 root 1.70 * we want to have floorbox_update called before calling this.
1497 root 1.24 *
1498     * check_move_on() must be after this because code called from
1499     * check_move_on() depends on correct map flags (so functions like
1500     * blocked() and wall() work properly), and these flags are updated by
1501     * update_object().
1502     */
1503    
1504     /* if this is not the head or flag has been passed, don't check walk on status */
1505 root 1.155 if (!(flag & INS_NO_WALK_ON) && op->head_ () == op)
1506 root 1.24 {
1507     if (check_move_on (op, originator))
1508 root 1.82 return 0;
1509 elmex 1.1
1510 root 1.24 /* If we are a multi part object, lets work our way through the check
1511     * walk on's.
1512     */
1513 root 1.155 for (object *tmp = op->more; tmp; tmp = tmp->more)
1514 root 1.24 if (check_move_on (tmp, originator))
1515 root 1.82 return 0;
1516 elmex 1.1 }
1517 root 1.25
1518 root 1.24 return op;
1519 elmex 1.1 }
1520    
1521     /* this function inserts an object in the map, but if it
1522 root 1.75 * finds an object of its own type, it'll remove that one first.
1523     * op is the object to insert it under: supplies x and the map.
1524 elmex 1.1 */
1525 root 1.24 void
1526     replace_insert_ob_in_map (const char *arch_string, object *op)
1527     {
1528     /* first search for itself and remove any old instances */
1529 elmex 1.1
1530 root 1.208 for (object *tmp = op->ms ().bot; tmp; tmp = tmp->above)
1531 root 1.158 if (!strcmp (tmp->arch->archname, arch_string)) /* same archetype */
1532 root 1.208 tmp->destroy (1);
1533    
1534     object *tmp = arch_to_object (archetype::find (arch_string));
1535 elmex 1.1
1536 root 1.208 tmp->x = op->x;
1537     tmp->y = op->y;
1538 elmex 1.1
1539 root 1.208 insert_ob_in_map (tmp, op->map, op, 0);
1540 root 1.24 }
1541 elmex 1.1
1542 root 1.93 object *
1543     object::insert_at (object *where, object *originator, int flags)
1544     {
1545 root 1.205 if (where->env)
1546     return where->env->insert (this);
1547     else
1548     return where->map->insert (this, where->x, where->y, originator, flags);
1549 root 1.93 }
1550    
1551 elmex 1.1 /*
1552 root 1.209 * decrease(object, number) decreases a specified number from
1553 root 1.208 * the amount of an object. If the amount reaches 0, the object
1554 elmex 1.1 * is subsequently removed and freed.
1555     *
1556     * Return value: 'op' if something is left, NULL if the amount reached 0
1557     */
1558 root 1.208 bool
1559 root 1.209 object::decrease (sint32 nr)
1560 elmex 1.1 {
1561 root 1.212 if (!nr)
1562     return true;
1563    
1564 root 1.208 nr = min (nr, nrof);
1565 elmex 1.1
1566 root 1.208 nrof -= nr;
1567 root 1.24
1568 root 1.208 if (nrof)
1569 elmex 1.1 {
1570 root 1.208 adjust_weight (env, -weight * nr); // carrying == 0
1571 elmex 1.1
1572 root 1.212 if (object *pl = visible_to ())
1573     esrv_update_item (UPD_NROF, pl, this);
1574 root 1.29
1575 root 1.212 return true;
1576 elmex 1.1 }
1577 root 1.24 else
1578     {
1579 root 1.212 destroy (1);
1580     return false;
1581 elmex 1.1 }
1582     }
1583    
1584 root 1.209 /*
1585 root 1.210 * split(ob,nr) splits up ob into two parts. The part which
1586 root 1.209 * is returned contains nr objects, and the remaining parts contains
1587 root 1.210 * the rest (or is removed and returned if that number is 0).
1588     * On failure, NULL is returned.
1589 root 1.209 */
1590 root 1.208 object *
1591 root 1.209 object::split (sint32 nr)
1592 root 1.208 {
1593 root 1.212 int have = number_of ();
1594    
1595     if (have < nr)
1596 root 1.209 return 0;
1597 root 1.212 else if (have == nr)
1598 root 1.209 {
1599     remove ();
1600     return this;
1601     }
1602     else
1603     {
1604     decrease (nr);
1605    
1606     object *op = object_create_clone (this);
1607     op->nrof = nr;
1608     return op;
1609     }
1610     }
1611    
1612 root 1.24 object *
1613     insert_ob_in_ob (object *op, object *where)
1614     {
1615 root 1.59 if (!where)
1616 root 1.24 {
1617 root 1.53 char *dump = dump_object (op);
1618     LOG (llevError, "Trying to put object in NULL.\n%s\n", dump);
1619     free (dump);
1620 root 1.24 return op;
1621     }
1622 root 1.29
1623 root 1.154 if (where->head_ () != where)
1624 root 1.24 {
1625 root 1.153 LOG (llevError | logBacktrace, "Warning: Tried to insert object into wrong part of multipart object.\n");
1626 root 1.24 where = where->head;
1627     }
1628 root 1.29
1629 root 1.59 return where->insert (op);
1630     }
1631    
1632     /*
1633     * env->insert (op)
1634     * This function inserts the object op in the linked list
1635     * inside the object environment.
1636     *
1637     * The function returns now pointer to inserted item, and return value can
1638     * be != op, if items are merged. -Tero
1639     */
1640     object *
1641     object::insert (object *op)
1642     {
1643 root 1.24 if (op->more)
1644     {
1645     LOG (llevError, "Tried to insert multipart object %s (%d)\n", &op->name, op->count);
1646     return op;
1647     }
1648 root 1.29
1649 root 1.208 op->remove ();
1650    
1651     op->flag [FLAG_OBJ_ORIGINAL] = 0;
1652 root 1.182
1653 root 1.24 if (op->nrof)
1654 root 1.208 for (object *tmp = inv; tmp; tmp = tmp->below)
1655     if (object::can_merge (tmp, op))
1656     {
1657     /* return the original object and remove inserted object
1658     (client needs the original object) */
1659     tmp->nrof += op->nrof;
1660 root 1.214
1661     if (object *pl = tmp->visible_to ())
1662     esrv_update_item (UPD_NROF, pl, tmp);
1663    
1664 root 1.210 adjust_weight (this, op->total_weight ());
1665    
1666 root 1.208 op->destroy (1);
1667     op = tmp;
1668     goto inserted;
1669     }
1670    
1671     op->owner = 0; // it's his/hers now. period.
1672     op->map = 0;
1673     op->x = 0;
1674     op->y = 0;
1675    
1676     op->above = 0;
1677     op->below = inv;
1678     op->env = this;
1679    
1680     if (inv)
1681     inv->above = op;
1682 root 1.24
1683 root 1.208 inv = op;
1684 elmex 1.1
1685 root 1.208 op->flag [FLAG_REMOVED] = 0;
1686 elmex 1.1
1687 root 1.214 if (object *pl = op->visible_to ())
1688     esrv_send_item (pl, op);
1689    
1690 root 1.208 adjust_weight (this, op->total_weight ());
1691 elmex 1.1
1692 root 1.208 inserted:
1693 elmex 1.1 /* reset the light list and los of the players on the map */
1694 root 1.208 if (op->glow_radius && map && map->darkness)
1695     update_all_los (map, x, y);
1696 elmex 1.1
1697 root 1.214 // if this is a player's inventory, update stats
1698     if (type == PLAYER && !flag [FLAG_NO_FIX_PLAYER])
1699     update_stats ();
1700 root 1.59
1701 root 1.82 INVOKE_OBJECT (INSERT, this);
1702    
1703 elmex 1.1 return op;
1704     }
1705    
1706     /*
1707     * Checks if any objects has a move_type that matches objects
1708     * that effect this object on this space. Call apply() to process
1709     * these events.
1710     *
1711     * Any speed-modification due to SLOW_MOVE() of other present objects
1712     * will affect the speed_left of the object.
1713     *
1714     * originator: Player, monster or other object that caused 'op' to be inserted
1715     * into 'map'. May be NULL.
1716     *
1717     * Return value: 1 if 'op' was destroyed, 0 otherwise.
1718     *
1719     * 4-21-95 added code to check if appropriate skill was readied - this will
1720     * permit faster movement by the player through this terrain. -b.t.
1721     *
1722     * MSW 2001-07-08: Check all objects on space, not just those below
1723     * object being inserted. insert_ob_in_map may not put new objects
1724     * on top.
1725     */
1726 root 1.24 int
1727     check_move_on (object *op, object *originator)
1728 elmex 1.1 {
1729 root 1.48 object *tmp;
1730 root 1.49 maptile *m = op->map;
1731 root 1.48 int x = op->x, y = op->y;
1732 root 1.26
1733 root 1.48 MoveType move_on, move_slow, move_block;
1734 root 1.24
1735     if (QUERY_FLAG (op, FLAG_NO_APPLY))
1736     return 0;
1737    
1738     move_on = GET_MAP_MOVE_ON (op->map, op->x, op->y);
1739     move_slow = GET_MAP_MOVE_SLOW (op->map, op->x, op->y);
1740     move_block = GET_MAP_MOVE_BLOCK (op->map, op->x, op->y);
1741    
1742     /* if nothing on this space will slow op down or be applied,
1743     * no need to do checking below. have to make sure move_type
1744     * is set, as lots of objects don't have it set - we treat that
1745     * as walking.
1746     */
1747     if (op->move_type && !(op->move_type & move_on) && !(op->move_type & move_slow))
1748     return 0;
1749 elmex 1.1
1750 root 1.24 /* This is basically inverse logic of that below - basically,
1751     * if the object can avoid the move on or slow move, they do so,
1752     * but can't do it if the alternate movement they are using is
1753     * blocked. Logic on this seems confusing, but does seem correct.
1754     */
1755     if ((op->move_type & ~move_on & ~move_block) != 0 && (op->move_type & ~move_slow & ~move_block) != 0)
1756     return 0;
1757    
1758     /* The objects have to be checked from top to bottom.
1759     * Hence, we first go to the top:
1760     */
1761    
1762 root 1.104 for (tmp = op->ms ().bot; tmp && tmp->above; tmp = tmp->above)
1763 root 1.24 {
1764     /* Trim the search when we find the first other spell effect
1765     * this helps performance so that if a space has 50 spell objects,
1766     * we don't need to check all of them.
1767     */
1768     if ((tmp->move_type & MOVE_FLY_LOW) && QUERY_FLAG (tmp, FLAG_NO_PICK))
1769     break;
1770     }
1771 root 1.26
1772     for (; tmp; tmp = tmp->below)
1773 root 1.24 {
1774     if (tmp == op)
1775     continue; /* Can't apply yourself */
1776 elmex 1.1
1777 root 1.24 /* Check to see if one of the movement types should be slowed down.
1778     * Second check makes sure that the movement types not being slowed
1779     * (~slow_move) is not blocked on this space - just because the
1780     * space doesn't slow down swimming (for example), if you can't actually
1781     * swim on that space, can't use it to avoid the penalty.
1782     */
1783     if (!QUERY_FLAG (op, FLAG_WIZPASS))
1784     {
1785     if ((!op->move_type && tmp->move_slow & MOVE_WALK) ||
1786     ((op->move_type & tmp->move_slow) && (op->move_type & ~tmp->move_slow & ~tmp->move_block) == 0))
1787     {
1788 elmex 1.1
1789 root 1.29 float
1790 root 1.120 diff = tmp->move_slow_penalty * fabs (op->speed);
1791 elmex 1.1
1792 root 1.24 if (op->type == PLAYER)
1793 root 1.26 if ((QUERY_FLAG (tmp, FLAG_IS_HILLY) && find_skill_by_number (op, SK_CLIMBING)) ||
1794     (QUERY_FLAG (tmp, FLAG_IS_WOODED) && find_skill_by_number (op, SK_WOODSMAN)))
1795     diff /= 4.0;
1796    
1797 root 1.24 op->speed_left -= diff;
1798 root 1.8 }
1799     }
1800 elmex 1.1
1801 root 1.24 /* Basically same logic as above, except now for actual apply. */
1802     if ((!op->move_type && tmp->move_on & MOVE_WALK) ||
1803     ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0))
1804     {
1805 elmex 1.72 move_apply (tmp, op, originator);
1806 root 1.24
1807 root 1.48 if (op->destroyed ())
1808 root 1.24 return 1;
1809    
1810     /* what the person/creature stepped onto has moved the object
1811     * someplace new. Don't process any further - if we did,
1812     * have a feeling strange problems would result.
1813     */
1814     if (op->map != m || op->x != x || op->y != y)
1815     return 0;
1816 root 1.8 }
1817 elmex 1.1 }
1818 root 1.26
1819 root 1.24 return 0;
1820 elmex 1.1 }
1821    
1822     /*
1823     * present_arch(arch, map, x, y) searches for any objects with
1824     * a matching archetype at the given map and coordinates.
1825     * The first matching object is returned, or NULL if none.
1826     */
1827 root 1.24 object *
1828 root 1.49 present_arch (const archetype *at, maptile *m, int x, int y)
1829 root 1.24 {
1830 root 1.104 if (!m || out_of_map (m, x, y))
1831 root 1.24 {
1832     LOG (llevError, "Present_arch called outside map.\n");
1833     return NULL;
1834     }
1835 root 1.84
1836 root 1.104 for (object *tmp = m->at (x, y).bot; tmp; tmp = tmp->above)
1837 root 1.24 if (tmp->arch == at)
1838 elmex 1.1 return tmp;
1839 root 1.84
1840 elmex 1.1 return NULL;
1841     }
1842    
1843     /*
1844     * present(type, map, x, y) searches for any objects with
1845     * a matching type variable at the given map and coordinates.
1846     * The first matching object is returned, or NULL if none.
1847     */
1848 root 1.24 object *
1849 root 1.49 present (unsigned char type, maptile *m, int x, int y)
1850 root 1.24 {
1851     if (out_of_map (m, x, y))
1852     {
1853     LOG (llevError, "Present called outside map.\n");
1854     return NULL;
1855     }
1856 root 1.84
1857 root 1.104 for (object *tmp = m->at (x, y).bot; tmp; tmp = tmp->above)
1858 root 1.24 if (tmp->type == type)
1859 elmex 1.1 return tmp;
1860 root 1.84
1861 elmex 1.1 return NULL;
1862     }
1863    
1864     /*
1865     * present_in_ob(type, object) searches for any objects with
1866     * a matching type variable in the inventory of the given object.
1867     * The first matching object is returned, or NULL if none.
1868     */
1869 root 1.24 object *
1870     present_in_ob (unsigned char type, const object *op)
1871     {
1872 root 1.84 for (object *tmp = op->inv; tmp != NULL; tmp = tmp->below)
1873 root 1.24 if (tmp->type == type)
1874 elmex 1.1 return tmp;
1875 root 1.84
1876 elmex 1.1 return NULL;
1877     }
1878    
1879     /*
1880     * present_in_ob (type, str, object) searches for any objects with
1881     * a matching type & name variable in the inventory of the given object.
1882     * The first matching object is returned, or NULL if none.
1883     * This is mostly used by spell effect code, so that we only
1884     * have one spell effect at a time.
1885     * type can be used to narrow the search - if type is set,
1886     * the type must also match. -1 can be passed for the type,
1887     * in which case the type does not need to pass.
1888     * str is the string to match against. Note that we match against
1889     * the object name, not the archetype name. this is so that the
1890     * spell code can use one object type (force), but change it's name
1891     * to be unique.
1892     */
1893 root 1.24 object *
1894     present_in_ob_by_name (int type, const char *str, const object *op)
1895     {
1896 root 1.84 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1897 root 1.82 if ((type == -1 || tmp->type == type) && (!strcmp (str, tmp->name)))
1898     return tmp;
1899 elmex 1.1
1900 root 1.82 return 0;
1901 elmex 1.1 }
1902    
1903     /*
1904     * present_arch_in_ob(archetype, object) searches for any objects with
1905     * a matching archetype in the inventory of the given object.
1906     * The first matching object is returned, or NULL if none.
1907     */
1908 root 1.24 object *
1909     present_arch_in_ob (const archetype *at, const object *op)
1910     {
1911 root 1.82 for (object *tmp = op->inv; tmp != NULL; tmp = tmp->below)
1912 root 1.24 if (tmp->arch == at)
1913 elmex 1.1 return tmp;
1914 root 1.82
1915 elmex 1.1 return NULL;
1916     }
1917    
1918     /*
1919     * activate recursively a flag on an object inventory
1920     */
1921 root 1.24 void
1922     flag_inv (object *op, int flag)
1923     {
1924 root 1.197 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1925     {
1926     SET_FLAG (tmp, flag);
1927     flag_inv (tmp, flag);
1928     }
1929 root 1.82 }
1930    
1931     /*
1932     * deactivate recursively a flag on an object inventory
1933     */
1934 root 1.24 void
1935     unflag_inv (object *op, int flag)
1936     {
1937 root 1.197 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1938     {
1939     CLEAR_FLAG (tmp, flag);
1940     unflag_inv (tmp, flag);
1941     }
1942 elmex 1.1 }
1943    
1944     /*
1945     * find_free_spot(object, map, x, y, start, stop) will search for
1946     * a spot at the given map and coordinates which will be able to contain
1947     * the given object. start and stop specifies how many squares
1948     * to search (see the freearr_x/y[] definition).
1949     * It returns a random choice among the alternatives found.
1950     * start and stop are where to start relative to the free_arr array (1,9
1951     * does all 4 immediate directions). This returns the index into the
1952     * array of the free spot, -1 if no spot available (dir 0 = x,y)
1953 root 1.196 * Note: This function does correctly handle tiled maps, but does not
1954 elmex 1.1 * inform the caller. However, insert_ob_in_map will update as
1955     * necessary, so the caller shouldn't need to do any special work.
1956     * Note - updated to take an object instead of archetype - this is necessary
1957     * because arch_blocked (now ob_blocked) needs to know the movement type
1958     * to know if the space in question will block the object. We can't use
1959     * the archetype because that isn't correct if the monster has been
1960     * customized, changed states, etc.
1961     */
1962 root 1.24 int
1963 root 1.49 find_free_spot (const object *ob, maptile *m, int x, int y, int start, int stop)
1964 root 1.24 {
1965 root 1.190 int altern[SIZEOFFREE];
1966 root 1.82 int index = 0, flag;
1967 root 1.24
1968 root 1.82 for (int i = start; i < stop; i++)
1969 root 1.24 {
1970 root 1.188 mapxy pos (m, x, y); pos.move (i);
1971    
1972     if (!pos.normalise ())
1973     continue;
1974    
1975     mapspace &ms = *pos;
1976 root 1.189
1977     if (ms.flags () & P_IS_ALIVE)
1978     continue;
1979 root 1.188
1980     /* However, often
1981     * ob doesn't have any move type (when used to place exits)
1982     * so the AND operation in OB_TYPE_MOVE_BLOCK doesn't work.
1983     */
1984 root 1.200 if (ob && ob->move_type == 0 && ms.move_block != MOVE_ALL)
1985 root 1.190 {
1986     altern [index++] = i;
1987     continue;
1988     }
1989 root 1.24
1990     /* Basically, if we find a wall on a space, we cut down the search size.
1991     * In this way, we won't return spaces that are on another side of a wall.
1992     * This mostly work, but it cuts down the search size in all directions -
1993     * if the space being examined only has a wall to the north and empty
1994     * spaces in all the other directions, this will reduce the search space
1995     * to only the spaces immediately surrounding the target area, and
1996     * won't look 2 spaces south of the target space.
1997     */
1998 root 1.188 if (ms.move_block == MOVE_ALL && maxfree[i] < stop)
1999     {
2000     stop = maxfree[i];
2001     continue;
2002     }
2003    
2004     /* Note it is intentional that we check ob - the movement type of the
2005     * head of the object should correspond for the entire object.
2006     */
2007     if (OB_TYPE_MOVE_BLOCK (ob, ms.move_block))
2008     continue;
2009    
2010 root 1.196 if (ob->blocked (m, pos.x, pos.y))
2011     continue;
2012    
2013 root 1.188 altern [index++] = i;
2014 elmex 1.1 }
2015 root 1.74
2016 root 1.24 if (!index)
2017     return -1;
2018 root 1.74
2019 root 1.124 return altern [rndm (index)];
2020 elmex 1.1 }
2021    
2022     /*
2023 root 1.49 * find_first_free_spot(archetype, maptile, x, y) works like
2024 elmex 1.1 * find_free_spot(), but it will search max number of squares.
2025     * But it will return the first available spot, not a random choice.
2026     * Changed 0.93.2: Have it return -1 if there is no free spot available.
2027     */
2028 root 1.24 int
2029 root 1.49 find_first_free_spot (const object *ob, maptile *m, int x, int y)
2030 root 1.24 {
2031 root 1.82 for (int i = 0; i < SIZEOFFREE; i++)
2032 root 1.188 if (!ob->blocked (m, x + freearr_x[i], y + freearr_y[i]))
2033 root 1.82 return i;
2034 root 1.24
2035     return -1;
2036 elmex 1.1 }
2037    
2038     /*
2039     * The function permute(arr, begin, end) randomly reorders the array
2040     * arr[begin..end-1].
2041 root 1.82 * now uses a fisher-yates shuffle, old permute was broken
2042 elmex 1.1 */
2043 root 1.24 static void
2044     permute (int *arr, int begin, int end)
2045 elmex 1.1 {
2046 root 1.82 arr += begin;
2047     end -= begin;
2048    
2049     while (--end)
2050 root 1.124 swap (arr [end], arr [rndm (end + 1)]);
2051 elmex 1.1 }
2052    
2053     /* new function to make monster searching more efficient, and effective!
2054     * This basically returns a randomized array (in the passed pointer) of
2055     * the spaces to find monsters. In this way, it won't always look for
2056     * monsters to the north first. However, the size of the array passed
2057     * covers all the spaces, so within that size, all the spaces within
2058     * the 3x3 area will be searched, just not in a predictable order.
2059     */
2060 root 1.24 void
2061     get_search_arr (int *search_arr)
2062 elmex 1.1 {
2063 root 1.82 int i;
2064 elmex 1.1
2065 root 1.24 for (i = 0; i < SIZEOFFREE; i++)
2066 root 1.82 search_arr[i] = i;
2067 elmex 1.1
2068 root 1.24 permute (search_arr, 1, SIZEOFFREE1 + 1);
2069     permute (search_arr, SIZEOFFREE1 + 1, SIZEOFFREE2 + 1);
2070     permute (search_arr, SIZEOFFREE2 + 1, SIZEOFFREE);
2071 elmex 1.1 }
2072    
2073     /*
2074     * find_dir(map, x, y, exclude) will search some close squares in the
2075     * given map at the given coordinates for live objects.
2076     * It will not considered the object given as exclude among possible
2077     * live objects.
2078     * It returns the direction toward the first/closest live object if finds
2079     * any, otherwise 0.
2080     * Perhaps incorrectly, but I'm making the assumption that exclude
2081     * is actually want is going to try and move there. We need this info
2082     * because we have to know what movement the thing looking to move
2083     * there is capable of.
2084     */
2085 root 1.24 int
2086 root 1.49 find_dir (maptile *m, int x, int y, object *exclude)
2087 root 1.24 {
2088 root 1.82 int i, max = SIZEOFFREE, mflags;
2089 root 1.29
2090     sint16 nx, ny;
2091 root 1.82 object *tmp;
2092     maptile *mp;
2093 root 1.29
2094     MoveType blocked, move_type;
2095 root 1.24
2096 root 1.155 if (exclude && exclude->head_ () != exclude)
2097 root 1.24 {
2098     exclude = exclude->head;
2099     move_type = exclude->move_type;
2100     }
2101     else
2102     {
2103     /* If we don't have anything, presume it can use all movement types. */
2104     move_type = MOVE_ALL;
2105     }
2106    
2107     for (i = 1; i < max; i++)
2108     {
2109     mp = m;
2110     nx = x + freearr_x[i];
2111     ny = y + freearr_y[i];
2112    
2113     mflags = get_map_flags (m, &mp, nx, ny, &nx, &ny);
2114 root 1.75
2115 root 1.24 if (mflags & P_OUT_OF_MAP)
2116 root 1.75 max = maxfree[i];
2117 root 1.24 else
2118     {
2119 root 1.82 mapspace &ms = mp->at (nx, ny);
2120    
2121     blocked = ms.move_block;
2122 root 1.24
2123     if ((move_type & blocked) == move_type)
2124 root 1.75 max = maxfree[i];
2125 root 1.24 else if (mflags & P_IS_ALIVE)
2126     {
2127 root 1.84 for (tmp = ms.bot; tmp; tmp = tmp->above)
2128 root 1.82 if ((tmp->flag [FLAG_MONSTER] || tmp->type == PLAYER)
2129 root 1.155 && (tmp != exclude || (tmp->head_ () != tmp && tmp->head_ () != exclude)))
2130 root 1.75 break;
2131    
2132 root 1.24 if (tmp)
2133 root 1.75 return freedir[i];
2134 root 1.8 }
2135     }
2136 elmex 1.1 }
2137 root 1.75
2138 root 1.24 return 0;
2139 elmex 1.1 }
2140    
2141     /*
2142     * distance(object 1, object 2) will return the square of the
2143     * distance between the two given objects.
2144     */
2145 root 1.24 int
2146     distance (const object *ob1, const object *ob2)
2147     {
2148 root 1.82 return (ob1->x - ob2->x) * (ob1->x - ob2->x) + (ob1->y - ob2->y) * (ob1->y - ob2->y);
2149 elmex 1.1 }
2150    
2151     /*
2152     * find_dir_2(delta-x,delta-y) will return a direction in which
2153     * an object which has subtracted the x and y coordinates of another
2154     * object, needs to travel toward it.
2155     */
2156 root 1.24 int
2157     find_dir_2 (int x, int y)
2158     {
2159 root 1.75 int q;
2160 elmex 1.1
2161 root 1.24 if (y)
2162     q = x * 100 / y;
2163 elmex 1.1 else if (x)
2164 root 1.24 q = -300 * x;
2165 elmex 1.1 else
2166     return 0;
2167    
2168 root 1.24 if (y > 0)
2169     {
2170     if (q < -242)
2171     return 3;
2172     if (q < -41)
2173     return 2;
2174     if (q < 41)
2175     return 1;
2176     if (q < 242)
2177     return 8;
2178     return 7;
2179     }
2180 elmex 1.1
2181     if (q < -242)
2182 root 1.24 return 7;
2183 elmex 1.1 if (q < -41)
2184 root 1.24 return 6;
2185 elmex 1.1 if (q < 41)
2186 root 1.24 return 5;
2187 elmex 1.1 if (q < 242)
2188 root 1.24 return 4;
2189 elmex 1.1
2190 root 1.24 return 3;
2191 elmex 1.1 }
2192    
2193     /*
2194     * dirdiff(dir1, dir2) returns how many 45-degrees differences there is
2195     * between two directions (which are expected to be absolute (see absdir())
2196     */
2197 root 1.24 int
2198     dirdiff (int dir1, int dir2)
2199     {
2200 root 1.82 int d;
2201 root 1.24
2202     d = abs (dir1 - dir2);
2203     if (d > 4)
2204 elmex 1.1 d = 8 - d;
2205 root 1.82
2206 elmex 1.1 return d;
2207     }
2208    
2209     /* peterm:
2210     * do LOS stuff for ball lightning. Go after the closest VISIBLE monster.
2211     * Basically, this is a table of directions, and what directions
2212     * one could go to go back to us. Eg, entry 15 below is 4, 14, 16.
2213     * This basically means that if direction is 15, then it could either go
2214     * direction 4, 14, or 16 to get back to where we are.
2215     * Moved from spell_util.c to object.c with the other related direction
2216     * functions.
2217     */
2218 root 1.82 int reduction_dir[SIZEOFFREE][3] = {
2219 root 1.24 {0, 0, 0}, /* 0 */
2220     {0, 0, 0}, /* 1 */
2221     {0, 0, 0}, /* 2 */
2222     {0, 0, 0}, /* 3 */
2223     {0, 0, 0}, /* 4 */
2224     {0, 0, 0}, /* 5 */
2225     {0, 0, 0}, /* 6 */
2226     {0, 0, 0}, /* 7 */
2227     {0, 0, 0}, /* 8 */
2228     {8, 1, 2}, /* 9 */
2229     {1, 2, -1}, /* 10 */
2230     {2, 10, 12}, /* 11 */
2231     {2, 3, -1}, /* 12 */
2232     {2, 3, 4}, /* 13 */
2233     {3, 4, -1}, /* 14 */
2234     {4, 14, 16}, /* 15 */
2235     {5, 4, -1}, /* 16 */
2236     {4, 5, 6}, /* 17 */
2237     {6, 5, -1}, /* 18 */
2238     {6, 20, 18}, /* 19 */
2239     {7, 6, -1}, /* 20 */
2240     {6, 7, 8}, /* 21 */
2241     {7, 8, -1}, /* 22 */
2242     {8, 22, 24}, /* 23 */
2243     {8, 1, -1}, /* 24 */
2244     {24, 9, 10}, /* 25 */
2245     {9, 10, -1}, /* 26 */
2246     {10, 11, -1}, /* 27 */
2247     {27, 11, 29}, /* 28 */
2248     {11, 12, -1}, /* 29 */
2249     {12, 13, -1}, /* 30 */
2250     {12, 13, 14}, /* 31 */
2251     {13, 14, -1}, /* 32 */
2252     {14, 15, -1}, /* 33 */
2253     {33, 15, 35}, /* 34 */
2254     {16, 15, -1}, /* 35 */
2255     {17, 16, -1}, /* 36 */
2256     {18, 17, 16}, /* 37 */
2257     {18, 17, -1}, /* 38 */
2258     {18, 19, -1}, /* 39 */
2259     {41, 19, 39}, /* 40 */
2260     {19, 20, -1}, /* 41 */
2261     {20, 21, -1}, /* 42 */
2262     {20, 21, 22}, /* 43 */
2263     {21, 22, -1}, /* 44 */
2264     {23, 22, -1}, /* 45 */
2265     {45, 47, 23}, /* 46 */
2266     {23, 24, -1}, /* 47 */
2267     {24, 9, -1}
2268     }; /* 48 */
2269 elmex 1.1
2270     /* Recursive routine to step back and see if we can
2271     * find a path to that monster that we found. If not,
2272     * we don't bother going toward it. Returns 1 if we
2273     * can see a direct way to get it
2274     * Modified to be map tile aware -.MSW
2275     */
2276 root 1.24 int
2277 root 1.49 can_see_monsterP (maptile *m, int x, int y, int dir)
2278 root 1.24 {
2279 root 1.29 sint16 dx, dy;
2280 root 1.75 int mflags;
2281 root 1.24
2282     if (dir < 0)
2283     return 0; /* exit condition: invalid direction */
2284    
2285     dx = x + freearr_x[dir];
2286     dy = y + freearr_y[dir];
2287    
2288     mflags = get_map_flags (m, &m, dx, dy, &dx, &dy);
2289    
2290     /* This functional arguably was incorrect before - it was
2291     * checking for P_WALL - that was basically seeing if
2292     * we could move to the monster - this is being more
2293     * literal on if we can see it. To know if we can actually
2294     * move to the monster, we'd need the monster passed in or
2295     * at least its move type.
2296     */
2297     if (mflags & (P_OUT_OF_MAP | P_BLOCKSVIEW))
2298     return 0;
2299    
2300     /* yes, can see. */
2301     if (dir < 9)
2302     return 1;
2303 root 1.75
2304     return can_see_monsterP (m, x, y, reduction_dir[dir][0])
2305     | can_see_monsterP (m, x, y, reduction_dir[dir][1])
2306     | can_see_monsterP (m, x, y, reduction_dir[dir][2]);
2307 root 1.24 }
2308    
2309 elmex 1.1 /*
2310     * can_pick(picker, item): finds out if an object is possible to be
2311     * picked up by the picker. Returnes 1 if it can be
2312     * picked up, otherwise 0.
2313     *
2314     * Cf 0.91.3 - don't let WIZ's pick up anything - will likely cause
2315     * core dumps if they do.
2316     *
2317     * Add a check so we can't pick up invisible objects (0.93.8)
2318     */
2319 root 1.24 int
2320     can_pick (const object *who, const object *item)
2321     {
2322     return /*QUERY_FLAG(who,FLAG_WIZ)|| */
2323     (item->weight > 0 && !QUERY_FLAG (item, FLAG_NO_PICK) &&
2324     !QUERY_FLAG (item, FLAG_ALIVE) && !item->invisible && (who->type == PLAYER || item->weight < who->weight / 3));
2325 elmex 1.1 }
2326    
2327     /*
2328     * create clone from object to another
2329     */
2330 root 1.24 object *
2331     object_create_clone (object *asrc)
2332     {
2333 root 1.155 object *dst = 0, *tmp, *src, *prev, *item;
2334 elmex 1.1
2335 root 1.24 if (!asrc)
2336 root 1.62 return 0;
2337    
2338 root 1.155 src = asrc->head_ ();
2339 root 1.24
2340 root 1.62 prev = 0;
2341 root 1.155 for (object *part = src; part; part = part->more)
2342 root 1.24 {
2343 root 1.65 tmp = part->clone ();
2344 root 1.24 tmp->x -= src->x;
2345     tmp->y -= src->y;
2346 root 1.62
2347 root 1.24 if (!part->head)
2348     {
2349     dst = tmp;
2350 root 1.62 tmp->head = 0;
2351 root 1.24 }
2352     else
2353 root 1.75 tmp->head = dst;
2354 root 1.62
2355     tmp->more = 0;
2356    
2357 root 1.24 if (prev)
2358     prev->more = tmp;
2359 root 1.62
2360 root 1.24 prev = tmp;
2361 elmex 1.1 }
2362 root 1.24
2363     for (item = src->inv; item; item = item->below)
2364 root 1.48 insert_ob_in_ob (object_create_clone (item), dst);
2365 elmex 1.1
2366 root 1.24 return dst;
2367 elmex 1.1 }
2368    
2369     /* This returns the first object in who's inventory that
2370     * has the same type and subtype match.
2371     * returns NULL if no match.
2372     */
2373 root 1.24 object *
2374     find_obj_by_type_subtype (const object *who, int type, int subtype)
2375 elmex 1.1 {
2376 root 1.82 for (object *tmp = who->inv; tmp; tmp = tmp->below)
2377 root 1.24 if (tmp->type == type && tmp->subtype == subtype)
2378     return tmp;
2379 elmex 1.1
2380 root 1.82 return 0;
2381 elmex 1.1 }
2382    
2383     /* If ob has a field named key, return the link from the list,
2384     * otherwise return NULL.
2385     *
2386     * key must be a passed in shared string - otherwise, this won't
2387     * do the desired thing.
2388     */
2389 root 1.24 key_value *
2390     get_ob_key_link (const object *ob, const char *key)
2391     {
2392 root 1.82 for (key_value *link = ob->key_values; link; link = link->next)
2393 root 1.48 if (link->key == key)
2394     return link;
2395 root 1.24
2396 root 1.82 return 0;
2397 root 1.24 }
2398 elmex 1.1
2399     /*
2400     * Returns the value of op has an extra_field for key, or NULL.
2401     *
2402     * The argument doesn't need to be a shared string.
2403     *
2404     * The returned string is shared.
2405     */
2406 root 1.24 const char *
2407     get_ob_key_value (const object *op, const char *const key)
2408     {
2409 root 1.35 key_value *link;
2410     shstr_cmp canonical_key (key);
2411 root 1.24
2412 root 1.35 if (!canonical_key)
2413 root 1.24 {
2414     /* 1. There being a field named key on any object
2415     * implies there'd be a shared string to find.
2416     * 2. Since there isn't, no object has this field.
2417     * 3. Therefore, *this* object doesn't have this field.
2418     */
2419 root 1.35 return 0;
2420 elmex 1.1 }
2421    
2422 root 1.24 /* This is copied from get_ob_key_link() above -
2423     * only 4 lines, and saves the function call overhead.
2424     */
2425 root 1.35 for (link = op->key_values; link; link = link->next)
2426     if (link->key == canonical_key)
2427     return link->value;
2428    
2429     return 0;
2430 elmex 1.1 }
2431    
2432     /*
2433     * Updates the canonical_key in op to value.
2434     *
2435     * canonical_key is a shared string (value doesn't have to be).
2436     *
2437     * Unless add_key is TRUE, it won't add fields, only change the value of existing
2438     * keys.
2439     *
2440     * Returns TRUE on success.
2441     */
2442 root 1.24 int
2443     set_ob_key_value_s (object *op, const shstr & canonical_key, const char *value, int add_key)
2444     {
2445 root 1.82 key_value *field = NULL, *last = NULL;
2446 root 1.24
2447     for (field = op->key_values; field != NULL; field = field->next)
2448     {
2449     if (field->key != canonical_key)
2450     {
2451     last = field;
2452     continue;
2453     }
2454    
2455     if (value)
2456     field->value = value;
2457     else
2458     {
2459     /* Basically, if the archetype has this key set,
2460     * we need to store the null value so when we save
2461     * it, we save the empty value so that when we load,
2462     * we get this value back again.
2463     */
2464 root 1.159 if (get_ob_key_link (op->arch, canonical_key))
2465 root 1.24 field->value = 0;
2466     else
2467     {
2468     if (last)
2469     last->next = field->next;
2470     else
2471     op->key_values = field->next;
2472    
2473 root 1.29 delete field;
2474 root 1.24 }
2475     }
2476     return TRUE;
2477     }
2478     /* IF we get here, key doesn't exist */
2479    
2480     /* No field, we'll have to add it. */
2481    
2482     if (!add_key)
2483 root 1.82 return FALSE;
2484    
2485 root 1.24 /* There isn't any good reason to store a null
2486     * value in the key/value list. If the archetype has
2487     * this key, then we should also have it, so shouldn't
2488     * be here. If user wants to store empty strings,
2489     * should pass in ""
2490     */
2491     if (value == NULL)
2492 elmex 1.1 return TRUE;
2493 root 1.24
2494     field = new key_value;
2495    
2496     field->key = canonical_key;
2497     field->value = value;
2498     /* Usual prepend-addition. */
2499     field->next = op->key_values;
2500     op->key_values = field;
2501    
2502     return TRUE;
2503 elmex 1.1 }
2504    
2505     /*
2506     * Updates the key in op to value.
2507     *
2508     * If add_key is FALSE, this will only update existing keys,
2509     * and not add new ones.
2510     * In general, should be little reason FALSE is ever passed in for add_key
2511     *
2512     * Returns TRUE on success.
2513     */
2514 root 1.24 int
2515     set_ob_key_value (object *op, const char *key, const char *value, int add_key)
2516 root 1.11 {
2517 root 1.29 shstr key_ (key);
2518 root 1.24
2519 root 1.11 return set_ob_key_value_s (op, key_, value, add_key);
2520 elmex 1.1 }
2521 root 1.31
2522 root 1.34 object::depth_iterator::depth_iterator (object *container)
2523     : iterator_base (container)
2524     {
2525     while (item->inv)
2526     item = item->inv;
2527     }
2528    
2529 root 1.31 void
2530 root 1.34 object::depth_iterator::next ()
2531 root 1.31 {
2532 root 1.34 if (item->below)
2533     {
2534     item = item->below;
2535    
2536     while (item->inv)
2537     item = item->inv;
2538     }
2539 root 1.31 else
2540 root 1.34 item = item->env;
2541 root 1.31 }
2542 root 1.34
2543 elmex 1.97 const char *
2544     object::flag_desc (char *desc, int len) const
2545     {
2546     char *p = desc;
2547     bool first = true;
2548    
2549 root 1.101 *p = 0;
2550    
2551 elmex 1.97 for (int i = 0; i < NUM_FLAGS; i++)
2552     {
2553     if (len <= 10) // magic constant!
2554     {
2555     snprintf (p, len, ",...");
2556     break;
2557     }
2558    
2559 root 1.101 if (flag [i])
2560 elmex 1.97 {
2561     int cnt = snprintf (p, len, "%s%d", first ? "" : ",", i);
2562     len -= cnt;
2563     p += cnt;
2564     first = false;
2565     }
2566     }
2567    
2568     return desc;
2569     }
2570    
2571 root 1.101 // return a suitable string describing an object in enough detail to find it
2572 root 1.36 const char *
2573     object::debug_desc (char *info) const
2574     {
2575 elmex 1.97 char flagdesc[512];
2576     char info2[256 * 4];
2577 root 1.36 char *p = info;
2578    
2579 root 1.203 p += snprintf (p, 512, "{cnt:%d,uuid:%s,name:\"%s\"%s%s,flags:[%s],type:%d}",
2580     count,
2581     uuid.c_str (),
2582 root 1.36 &name,
2583 root 1.117 title ? "\",title:\"" : "",
2584 elmex 1.97 title ? (const char *)title : "",
2585     flag_desc (flagdesc, 512), type);
2586 root 1.36
2587 root 1.217 if (!flag[FLAG_REMOVED] && env)
2588 root 1.36 p += snprintf (p, 256, "(in %s)", env->debug_desc (info2));
2589    
2590     if (map)
2591 root 1.96 p += snprintf (p, 256, "(on %s@%d+%d)", &map->path, x, y);
2592 root 1.36
2593     return info;
2594     }
2595    
2596     const char *
2597     object::debug_desc () const
2598     {
2599 root 1.143 static char info[3][256 * 4];
2600     static int info_idx;
2601 root 1.36
2602 root 1.143 return debug_desc (info [++info_idx % 3]);
2603 root 1.114 }
2604    
2605 root 1.125 struct region *
2606     object::region () const
2607     {
2608     return map ? map->region (x, y)
2609     : region::default_region ();
2610     }
2611    
2612 root 1.129 const materialtype_t *
2613     object::dominant_material () const
2614     {
2615 root 1.165 if (materialtype_t *mt = name_to_material (materialname))
2616     return mt;
2617 root 1.129
2618 root 1.165 return name_to_material (shstr_unknown);
2619 root 1.129 }
2620    
2621 root 1.130 void
2622     object::open_container (object *new_container)
2623     {
2624     if (container == new_container)
2625     return;
2626    
2627 root 1.220 object *old_container = container;
2628    
2629     if (old_container)
2630 root 1.130 {
2631     if (INVOKE_OBJECT (CLOSE, old_container, ARG_OBJECT (this)))
2632     return;
2633    
2634     #if 0
2635     // remove the "Close old_container" object.
2636     if (object *closer = old_container->inv)
2637     if (closer->type == CLOSE_CON)
2638     closer->destroy ();
2639     #endif
2640    
2641 root 1.220 // make sure the container is available
2642     esrv_send_item (this, old_container);
2643    
2644 root 1.216 old_container->flag [FLAG_APPLIED] = false;
2645 root 1.130 container = 0;
2646    
2647 root 1.220 // client needs item update to make it work, client bug requires this to be separate
2648 root 1.130 esrv_update_item (UPD_FLAGS, this, old_container);
2649 root 1.220
2650 root 1.130 new_draw_info_format (NDI_UNIQUE, 0, this, "You close %s.", query_name (old_container));
2651 root 1.177 play_sound (sound_find ("chest_close"));
2652 root 1.130 }
2653    
2654     if (new_container)
2655     {
2656     if (INVOKE_OBJECT (OPEN, new_container, ARG_OBJECT (this)))
2657     return;
2658    
2659     // TODO: this does not seem to serve any purpose anymore?
2660     #if 0
2661     // insert the "Close Container" object.
2662     if (archetype *closer = new_container->other_arch)
2663     {
2664     object *closer = arch_to_object (new_container->other_arch);
2665     closer->flag [FLAG_NO_MAP_SAVE] = 1;
2666     new_container->insert (closer);
2667     }
2668     #endif
2669    
2670 root 1.132 new_draw_info_format (NDI_UNIQUE, 0, this, "You open %s.", query_name (new_container));
2671    
2672 root 1.220 // make sure the container is available, client bug requires this to be separate
2673     esrv_send_item (this, new_container);
2674    
2675 root 1.216 new_container->flag [FLAG_APPLIED] = true;
2676 root 1.130 container = new_container;
2677    
2678 root 1.220 // client needs flag change
2679 root 1.130 esrv_update_item (UPD_FLAGS, this, new_container);
2680 root 1.131 esrv_send_inventory (this, new_container);
2681 root 1.177 play_sound (sound_find ("chest_open"));
2682 root 1.130 }
2683 root 1.220 // else if (!old_container->env && contr && contr->ns)
2684     // contr->ns->floorbox_reset ();
2685 root 1.130 }
2686    
2687 root 1.164 object *
2688     object::force_find (const shstr name)
2689     {
2690     /* cycle through his inventory to look for the MARK we want to
2691     * place
2692     */
2693     for (object *tmp = inv; tmp; tmp = tmp->below)
2694     if (tmp->type == FORCE && tmp->slaying == name)
2695     return splay (tmp);
2696    
2697     return 0;
2698     }
2699    
2700     void
2701     object::force_add (const shstr name, int duration)
2702     {
2703     if (object *force = force_find (name))
2704     force->destroy ();
2705    
2706     object *force = get_archetype (FORCE_NAME);
2707    
2708     force->slaying = name;
2709     force->stats.food = 1;
2710     force->speed_left = -1.f;
2711    
2712     force->set_speed (duration ? 1.f / duration : 0.f);
2713     force->flag [FLAG_IS_USED_UP] = true;
2714     force->flag [FLAG_APPLIED] = true;
2715    
2716     insert (force);
2717     }
2718    
2719 root 1.178 void
2720 root 1.208 object::play_sound (faceidx sound)
2721 root 1.178 {
2722     if (!sound)
2723     return;
2724    
2725     if (flag [FLAG_REMOVED])
2726     return;
2727    
2728     if (env)
2729     {
2730     if (object *pl = in_player ())
2731     pl->contr->play_sound (sound);
2732     }
2733     else
2734     map->play_sound (sound, x, y);
2735     }
2736