ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.366
Committed: Sat Nov 17 23:40:00 2018 UTC (5 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.365: +1 -0 lines
Log Message:
copyright update 2018

File Contents

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