ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.368
Committed: Wed Dec 5 19:03:26 2018 UTC (5 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.367: +6 -4 lines
Log Message:
some bugfixes

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