ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.254
Committed: Sun Aug 31 01:17:11 2008 UTC (15 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.253: +3 -6 lines
Log Message:
fix merge bug

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