ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.340
Committed: Fri Jul 2 19:54:41 2010 UTC (13 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.339: +10 -0 lines
Log Message:
curse/identify improvements/changes

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