ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.213
Committed: Tue Apr 22 01:18:10 2008 UTC (16 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.212: +9 -9 lines
Log Message:
- automaticaly esrv_del items on remove

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