ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.228
Committed: Sat May 3 11:14:50 2008 UTC (16 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.227: +36 -147 lines
Log Message:
kv rewrite

File Contents

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