ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.318
Committed: Sat Apr 3 02:27:24 2010 UTC (14 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.317: +0 -32 lines
Log Message:
interim check-in

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