ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.296
Committed: Fri Nov 6 13:31:47 2009 UTC (14 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_90
Changes since 1.295: +0 -23 lines
Log Message:
remove or document dead code

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