ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.208
Committed: Mon Apr 21 06:16:01 2008 UTC (16 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.207: +164 -206 lines
Log Message:
weight system rewrite, also simplified and streamlined most related functions

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