ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.c
Revision: 1.6
Committed: Sun Jun 4 19:46:55 2006 UTC (18 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.5: +6 -11 lines
Log Message:
Fix a crash bug that happens with non-euclidean maps: when you end up on
the same map as you started but coordinates haven't change some stupid
useless microptimisation assumed that the coordinates had not changed,
either, leaving them outside the map, leading to an abort().

File Contents

# User Rev Content
1 root 1.1 /*
2     * static char *rcsid_object_c =
3 elmex 1.3 * "$Id$";
4 root 1.1 */
5    
6     /*
7     CrossFire, A Multiplayer game for X-windows
8    
9     Copyright (C) 2001 Mark Wedel & Crossfire Development Team
10     Copyright (C) 1992 Frank Tore Johansen
11    
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; either version 2 of the License, or
15     (at your option) any later version.
16    
17     This program is distributed in the hope that it will be useful,
18     but WITHOUT ANY WARRANTY; without even the implied warranty of
19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20     GNU General Public License for more details.
21    
22     You should have received a copy of the GNU General Public License
23     along with this program; if not, write to the Free Software
24     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25    
26     The authors can be reached via e-mail at crossfire-devel@real-time.com
27     */
28    
29     /* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects.
30     sub/add_weight will transcend the environment updating the carrying
31     variable. */
32     #include <global.h>
33     #ifndef WIN32 /* ---win32 exclude headers */
34     #include <stdio.h>
35     #include <sys/types.h>
36     #include <sys/uio.h>
37     #endif /* win32 */
38     #include <object.h>
39     #include <funcpoint.h>
40     #include <skills.h>
41     #include <loader.h>
42     #ifdef MEMORY_DEBUG
43     int nroffreeobjects = 0;
44     int nrofallocobjects = 0;
45     #undef OBJ_EXPAND
46     #define OBJ_EXPAND 1
47     #else
48     object objarray[STARTMAX]; /* All objects, allocated this way at first */
49     int nroffreeobjects = STARTMAX; /* How many OBs allocated and free (free) */
50     int nrofallocobjects = STARTMAX; /* How many OBs allocated (free + used) */
51     #endif
52    
53     object *objects; /* Pointer to the list of used objects */
54     object *free_objects; /* Pointer to the list of unused objects */
55     object *active_objects; /* List of active objects that need to be processed */
56    
57 root 1.2 void (*object_free_callback)(object *ob);
58 root 1.1
59     short freearr_x[SIZEOFFREE]=
60     {0,0,1,1,1,0,-1,-1,-1,0,1,2,2,2,2,2,1,0,-1,-2,-2,-2,-2,-2,-1,
61     0,1,2,3,3,3,3,3,3,3,2,1,0,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1};
62     short freearr_y[SIZEOFFREE]=
63     {0,-1,-1,0,1,1,1,0,-1,-2,-2,-2,-1,0,1,2,2,2,2,2,1,0,-1,-2,-2,
64     -3,-3,-3,-3,-2,-1,0,1,2,3,3,3,3,3,3,3,2,1,0,-1,-2,-3,-3,-3};
65     int maxfree[SIZEOFFREE]=
66     {0,9,10,13,14,17,18,21,22,25,26,27,30,31,32,33,36,37,39,39,42,43,44,45,
67     48,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49};
68     int freedir[SIZEOFFREE]= {
69     0,1,2,3,4,5,6,7,8,1,2,2,2,3,4,4,4,5,6,6,6,7,8,8,8,
70     1,2,2,2,2,2,3,4,4,4,4,4,5,6,6,6,6,6,7,8,8,8,8,8};
71    
72    
73     /* Returns TRUE if every key_values in wants has a partner with the same value in has. */
74 elmex 1.3 static int compare_ob_value_lists_one(const object * wants, const object * has) {
75 root 1.1 key_value * wants_field;
76    
77     /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both
78     * objects with lists are rare, and lists stay short. If not, use a
79     * different structure or at least keep the lists sorted...
80     */
81    
82     /* For each field in wants, */
83     for (wants_field = wants->key_values; wants_field != NULL; wants_field = wants_field->next) {
84     key_value * has_field;
85    
86     /* Look for a field in has with the same key. */
87     has_field = get_ob_key_link(has, wants_field->key);
88    
89     if (has_field == NULL) {
90     /* No field with that name. */
91     return FALSE;
92     }
93    
94     /* Found the matching field. */
95     if (has_field->value != wants_field->value) {
96     /* Values don't match, so this half of the comparison is false. */
97     return FALSE;
98     }
99    
100     /* If we get here, we found a match. Now for the next field in wants. */
101     }
102    
103     /* If we get here, every field in wants has a matching field in has. */
104     return TRUE;
105     }
106    
107     /* Returns TRUE if ob1 has the same key_values as ob2. */
108 elmex 1.3 static int compare_ob_value_lists(const object * ob1, const object * ob2) {
109 root 1.1 /* However, there may be fields in has which aren't partnered in wants,
110     * so we need to run the comparison *twice*. :(
111     */
112     return compare_ob_value_lists_one(ob1, ob2) && compare_ob_value_lists_one(ob2, ob1);
113     }
114    
115     /* Function examines the 2 objects given to it, and returns true if
116     * they can be merged together.
117     *
118     * Note that this function appears a lot longer than the macro it
119     * replaces - this is mostly for clarity - a decent compiler should hopefully
120     * reduce this to the same efficiency.
121     *
122     * Check nrof variable *before* calling CAN_MERGE()
123     *
124     * Improvements made with merge: Better checking on potion, and also
125     * check weight
126     */
127    
128     int CAN_MERGE(object *ob1, object *ob2) {
129    
130     /* A couple quicksanity checks */
131     if ((ob1 == ob2) || (ob1->type != ob2->type)) return 0;
132    
133     if (ob1->speed != ob2->speed) return 0;
134     /* Note sure why the following is the case - either the object has to
135     * be animated or have a very low speed. Is this an attempted monster
136     * check?
137     */
138     if (!QUERY_FLAG(ob1,FLAG_ANIMATE) && FABS((ob1)->speed) > MIN_ACTIVE_SPEED)
139     return 0;
140    
141     /* Do not merge objects if nrof would overflow. We use 1UL<<31 since that
142     * value could not be stored in a sint32 (which unfortunately sometimes is
143     * used to store nrof).
144     */
145     if (ob1->nrof+ob2->nrof >= 1UL<<31)
146     return 0;
147    
148     /* This is really a spellbook check - really, we should
149     * check all objects in the inventory.
150     */
151     if (ob1->inv || ob2->inv) {
152     /* if one object has inventory but the other doesn't, not equiv */
153     if ((ob1->inv && !ob2->inv) || (ob2->inv && !ob1->inv)) return 0;
154    
155     /* Now check to see if the two inventory objects could merge */
156     if (!CAN_MERGE(ob1->inv, ob2->inv)) return 0;
157    
158     /* inventory ok - still need to check rest of this object to see
159     * if it is valid.
160     */
161     }
162    
163     /* If the objects have been identified, set the BEEN_APPLIED flag.
164     * This is to the comparison of the flags below will be OK. We
165     * just can't ignore the been applied or identified flags, as they
166     * are not equal - just if it has been identified, the been_applied
167     * flags lose any meaning.
168     */
169     if (QUERY_FLAG(ob1, FLAG_IDENTIFIED))
170     SET_FLAG(ob1, FLAG_BEEN_APPLIED);
171    
172     if (QUERY_FLAG(ob2, FLAG_IDENTIFIED))
173     SET_FLAG(ob2, FLAG_BEEN_APPLIED);
174    
175    
176     /* the 0x400000 on flags2 is FLAG_INV_LOCK. I don't think something
177     * being locked in inventory should prevent merging.
178     * 0x4 in flags3 is CLIENT_SENT
179     */
180     if ((ob1->arch != ob2->arch) ||
181     (ob1->flags[0] != ob2->flags[0]) ||
182     (ob1->flags[1] != ob2->flags[1]) ||
183     ((ob1->flags[2] & ~0x400000) != (ob2->flags[2] & ~ 0x400000)) ||
184     ((ob1->flags[3] & ~0x4) != (ob2->flags[3] & ~0x4)) ||
185     (ob1->name != ob2->name) ||
186     (ob1->title != ob2->title) ||
187     (ob1->msg != ob2->msg) ||
188     (ob1->weight != ob2->weight) ||
189     (memcmp(&ob1->resist, &ob2->resist, sizeof(ob1->resist))!=0) ||
190     (memcmp(&ob1->stats, &ob2->stats, sizeof(ob1->stats))!=0) ||
191     (ob1->attacktype != ob2->attacktype) ||
192     (ob1->magic != ob2->magic) ||
193     (ob1->slaying != ob2->slaying) ||
194     (ob1->skill != ob2->skill) ||
195     (ob1->value != ob2->value) ||
196     (ob1->animation_id != ob2->animation_id) ||
197     (ob1->client_type != ob2->client_type) ||
198     (ob1->materialname != ob2->materialname) ||
199     (ob1->lore != ob2->lore) ||
200     (ob1->subtype != ob2->subtype) ||
201     (ob1->move_type != ob2->move_type) ||
202     (ob1->move_block != ob2->move_block) ||
203 elmex 1.3 (ob1->move_allow != ob2->move_allow) ||
204 root 1.1 (ob1->move_on != ob2->move_on) ||
205     (ob1->move_off != ob2->move_off) ||
206     (ob1->move_slow != ob2->move_slow) ||
207     (ob1->move_slow_penalty != ob2->move_slow_penalty)
208     )
209     return 0;
210    
211     /* Don't merge objects that are applied. With the new 'body' code,
212     * it is possible for most any character to have more than one of
213     * some items equipped, and we don't want those to merge.
214     */
215     if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED))
216     return 0;
217    
218 root 1.5 switch (ob1->type) {
219     case SCROLL:
220     if (ob1->level != ob2->level) return 0;
221     break;
222    
223     }
224 root 1.1 if (ob1->key_values != NULL || ob2->key_values != NULL) {
225     /* At least one of these has key_values. */
226     if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) {
227     /* One has fields, but the other one doesn't. */
228     return 0;
229 root 1.5 } else if (!compare_ob_value_lists(ob1, ob2)) {
230     return 0;
231 root 1.1 }
232     }
233    
234     /* Everything passes, must be OK. */
235     return 1;
236     }
237    
238     /*
239     * sum_weight() is a recursive function which calculates the weight
240     * an object is carrying. It goes through in figures out how much
241     * containers are carrying, and sums it up.
242     */
243     signed long sum_weight(object *op) {
244     signed long sum;
245     object *inv;
246     for(sum = 0, inv = op->inv; inv != NULL; inv = inv->below) {
247     if (inv->inv)
248     sum_weight(inv);
249     sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1);
250     }
251     if (op->type == CONTAINER && op->stats.Str)
252     sum = (sum * (100 - op->stats.Str))/100;
253     if(op->carrying != sum)
254     op->carrying = sum;
255     return sum;
256     }
257    
258     /**
259     * Return the outermost environment object for a given object.
260     */
261    
262     object *object_get_env_recursive (object *op) {
263     while (op->env != NULL)
264     op = op->env;
265     return op;
266     }
267    
268     /*
269     * Eneq(@csd.uu.se): Since we can have items buried in a character we need
270     * a better check. We basically keeping traversing up until we can't
271     * or find a player.
272     */
273    
274     object *is_player_inv (object *op) {
275     for (;op!=NULL&&op->type!=PLAYER; op=op->env)
276     if (op->env==op)
277     op->env = NULL;
278     return op;
279     }
280    
281     /*
282     * Used by: Crossedit: dump. Server DM commands: dumpbelow, dump.
283     * Some error messages.
284     * The result of the dump is stored in the static global errmsg array.
285     */
286    
287     void dump_object2(object *op) {
288     char *cp;
289     /* object *tmp;*/
290    
291     if(op->arch!=NULL) {
292     strcat(errmsg,"arch ");
293     strcat(errmsg,op->arch->name?op->arch->name:"(null)");
294     strcat(errmsg,"\n");
295     if((cp=get_ob_diff(op,&empty_archetype->clone))!=NULL)
296     strcat(errmsg,cp);
297     #if 0
298     /* Don't dump player diffs - they are too long, mostly meaningless, and
299     * will overflow the buffer.
300     * Changed so that we don't dump inventory either. This may
301     * also overflow the buffer.
302     */
303     if(op->type!=PLAYER && (cp=get_ob_diff(op,&empty_archetype->clone))!=NULL)
304     strcat(errmsg,cp);
305     for (tmp=op->inv; tmp; tmp=tmp->below)
306     dump_object2(tmp);
307     #endif
308     strcat(errmsg,"end\n");
309     } else {
310     strcat(errmsg,"Object ");
311     if (op->name==NULL) strcat(errmsg, "(null)");
312     else strcat(errmsg,op->name);
313     strcat(errmsg,"\n");
314     #if 0
315     if((cp=get_ob_diff(op,&empty_archetype->clone))!=NULL)
316     strcat(errmsg,cp);
317     for (tmp=op->inv; tmp; tmp=tmp->below)
318     dump_object2(tmp);
319     #endif
320     strcat(errmsg,"end\n");
321     }
322     }
323    
324     /*
325     * Dumps an object. Returns output in the static global errmsg array.
326     */
327    
328     void dump_object(object *op) {
329     if(op==NULL) {
330     strcpy(errmsg,"[NULL pointer]");
331     return;
332     }
333     errmsg[0]='\0';
334     dump_object2(op);
335     }
336    
337     /* GROS - Dumps an object. Return the result into a string */
338     /* Note that no checking is done for the validity of the target string, so */
339     /* you need to be sure that you allocated enough space for it. */
340     void dump_me(object *op, char *outstr)
341     {
342     char *cp;
343    
344     if(op==NULL)
345     {
346     strcpy(outstr,"[NULL pointer]");
347     return;
348     }
349     outstr[0]='\0';
350    
351     if(op->arch!=NULL)
352     {
353     strcat(outstr,"arch ");
354     strcat(outstr,op->arch->name?op->arch->name:"(null)");
355     strcat(outstr,"\n");
356     if((cp=get_ob_diff(op,&empty_archetype->clone))!=NULL)
357     strcat(outstr,cp);
358     strcat(outstr,"end\n");
359     }
360     else
361     {
362     strcat(outstr,"Object ");
363     if (op->name==NULL)
364     strcat(outstr, "(null)");
365     else
366     strcat(outstr,op->name);
367     strcat(outstr,"\n");
368     strcat(outstr,"end\n");
369     }
370     }
371    
372     /*
373     * This is really verbose...Can be triggered by the P key while in DM mode.
374     * All objects are dumped to stderr (or alternate logfile, if in server-mode)
375     */
376    
377     void dump_all_objects(void) {
378     object *op;
379     for(op=objects;op!=NULL;op=op->next) {
380     dump_object(op);
381     fprintf(logfile, "Object %d\n:%s\n", op->count, errmsg);
382     }
383     }
384    
385     /*
386     * get_nearest_part(multi-object, object 2) returns the part of the
387     * multi-object 1 which is closest to the second object.
388     * If it's not a multi-object, it is returned.
389     */
390    
391 elmex 1.3 object *get_nearest_part(object *op, const object *pl) {
392 root 1.1 object *tmp,*closest;
393     int last_dist,i;
394     if(op->more==NULL)
395     return op;
396     for(last_dist=distance(op,pl),closest=op,tmp=op->more;tmp!=NULL;tmp=tmp->more)
397     if((i=distance(tmp,pl))<last_dist)
398     closest=tmp,last_dist=i;
399     return closest;
400     }
401    
402     /*
403     * Returns the object which has the count-variable equal to the argument.
404     */
405    
406     object *find_object(tag_t i) {
407     object *op;
408     for(op=objects;op!=NULL;op=op->next)
409     if(op->count==i)
410     break;
411     return op;
412     }
413    
414     /*
415     * Returns the first object which has a name equal to the argument.
416     * Used only by the patch command, but not all that useful.
417     * Enables features like "patch <name-of-other-player> food 999"
418     */
419    
420 elmex 1.3 object *find_object_name(const char *str) {
421 root 1.1 const char *name=add_string(str);
422     object *op;
423     for(op=objects;op!=NULL;op=op->next)
424     if(op->name==name)
425     break;
426     free_string(name);
427     return op;
428     }
429    
430     void free_all_object_data(void) {
431     #ifdef MEMORY_DEBUG
432     object *op, *next;
433    
434     for (op=free_objects; op!=NULL; ) {
435     next=op->next;
436     free(op);
437     nrofallocobjects--;
438     nroffreeobjects--;
439     op=next;
440     }
441     #endif
442     LOG(llevDebug,"%d allocated objects, %d free objects, STARMAX=%d\n",
443     nrofallocobjects, nroffreeobjects,STARTMAX);
444     }
445    
446     /*
447     * Returns the object which this object marks as being the owner.
448     * A id-scheme is used to avoid pointing to objects which have been
449     * freed and are now reused. If this is detected, the owner is
450     * set to NULL, and NULL is returned.
451     * Changed 2004-02-12 - if the player is setting at the play again
452     * prompt, he is removed, and we don't want to treat him as an owner of
453     * anything, so check removed flag. I don't expect that this should break
454     * anything - once an object is removed, it is basically dead anyways.
455     */
456    
457     object *get_owner(object *op) {
458     if(op->owner==NULL)
459     return NULL;
460    
461     if (!QUERY_FLAG(op->owner,FLAG_FREED) && !QUERY_FLAG(op->owner, FLAG_REMOVED) &&
462     op->owner->count==op->ownercount)
463     return op->owner;
464    
465     op->owner=NULL;
466     op->ownercount=0;
467     return NULL;
468     }
469    
470     void clear_owner(object *op)
471     {
472     if (!op) return;
473    
474     if (op->owner && op->ownercount == op->owner->count)
475     op->owner->refcount--;
476    
477     op->owner = NULL;
478     op->ownercount = 0;
479     }
480    
481    
482    
483     /*
484     * Sets the owner and sets the skill and exp pointers to owner's current
485     * skill and experience objects.
486     */
487     void set_owner (object *op, object *owner)
488     {
489     if(owner==NULL||op==NULL)
490     return;
491    
492     /* next line added to allow objects which own objects */
493     /* Add a check for ownercounts in here, as I got into an endless loop
494     * with the fireball owning a poison cloud which then owned the
495     * fireball. I believe that was caused by one of the objects getting
496     * freed and then another object replacing it. Since the ownercounts
497     * didn't match, this check is valid and I believe that cause is valid.
498     */
499     while (owner->owner && owner!=owner->owner &&
500     owner->ownercount==owner->owner->count) owner=owner->owner;
501    
502     /* IF the owner still has an owner, we did not resolve to a final owner.
503     * so lets not add to that.
504     */
505     if (owner->owner) return;
506    
507     op->owner=owner;
508    
509     op->ownercount=owner->count;
510     owner->refcount++;
511    
512     }
513    
514     /* Set the owner to clone's current owner and set the skill and experience
515     * objects to clone's objects (typically those objects that where the owner's
516     * current skill and experience objects at the time when clone's owner was
517     * set - not the owner's current skill and experience objects).
518     *
519     * Use this function if player created an object (e.g. fire bullet, swarm
520     * spell), and this object creates further objects whose kills should be
521     * accounted for the player's original skill, even if player has changed
522     * skills meanwhile.
523     */
524     void copy_owner (object *op, object *clone)
525     {
526     object *owner = get_owner (clone);
527     if (owner == NULL) {
528     /* players don't have owners - they own themselves. Update
529     * as appropriate.
530     */
531     if (clone->type == PLAYER) owner=clone;
532     else return;
533     }
534     set_owner(op, owner);
535    
536     }
537    
538     /*
539     * Resets vital variables in an object
540     */
541    
542     void reset_object(object *op) {
543    
544     op->name = NULL;
545     op->name_pl = NULL;
546     op->title = NULL;
547     op->race = NULL;
548     op->slaying = NULL;
549     op->skill = NULL;
550     op->msg = NULL;
551     op->materialname = NULL;
552     op->lore = NULL;
553     op->current_weapon_script = NULL;
554     clear_object(op);
555     }
556    
557     /* Zero the key_values on op, decrementing the shared-string
558     * refcounts and freeing the links.
559     */
560     static void free_key_values(object * op) {
561     key_value * i;
562     key_value * next = NULL;
563    
564     if (op->key_values == NULL) return;
565    
566     for (i = op->key_values; i != NULL; i = next) {
567     /* Store next *first*. */
568     next = i->next;
569    
570     if (i->key) FREE_AND_CLEAR_STR(i->key);
571     if (i->value) FREE_AND_CLEAR_STR(i->value);
572     i->next = NULL;
573     free(i);
574     }
575    
576     op->key_values = NULL;
577     }
578    
579    
580     /*
581     * clear_object() frees everything allocated by an object, and also
582     * clears all variables and flags to default settings.
583     */
584    
585     void clear_object(object *op) {
586    
587     event *evt;
588     event *evt2;
589    
590     /* redo this to be simpler/more efficient. Was also seeing
591     * crashes in the old code. Move this to the top - am
592     * seeing periodic crashes in this code, and would like to have
593     * as much info available as possible (eg, object name).
594     */
595     for (evt = op->events; evt; evt=evt2) {
596     evt2 = evt->next;
597    
598     if (evt->hook != NULL) FREE_AND_CLEAR_STR(evt->hook);
599     if (evt->plugin != NULL) FREE_AND_CLEAR_STR(evt->plugin);
600     if (evt->options != NULL) FREE_AND_CLEAR_STR(evt->options);
601    
602     free(evt);
603     }
604     op->events = NULL;
605    
606     free_key_values(op);
607    
608     /* the memset will clear all these values for us, but we need
609     * to reduce the refcount on them.
610     */
611     if (op->name!=NULL) FREE_AND_CLEAR_STR(op->name);
612     if (op->name_pl!=NULL) FREE_AND_CLEAR_STR(op->name_pl);
613     if (op->title != NULL) FREE_AND_CLEAR_STR(op->title);
614     if (op->race!=NULL) FREE_AND_CLEAR_STR(op->race);
615     if (op->slaying!=NULL) FREE_AND_CLEAR_STR(op->slaying);
616     if (op->skill!=NULL) FREE_AND_CLEAR_STR(op->skill);
617     if (op->msg!=NULL) FREE_AND_CLEAR_STR(op->msg);
618     if (op->lore!=NULL) FREE_AND_CLEAR_STR(op->lore);
619     if (op->materialname!= NULL) FREE_AND_CLEAR_STR(op->materialname);
620    
621    
622     memset((void*)((char*)op + offsetof(object, name)),
623     0, sizeof(object)-offsetof(object, name));
624     /* Below here, we clear things that are not done by the memset,
625     * or set default values that are not zero.
626     */
627     /* This is more or less true */
628     SET_FLAG(op, FLAG_REMOVED);
629    
630    
631     op->contr = NULL;
632     op->below=NULL;
633     op->above=NULL;
634     op->inv=NULL;
635     op->events=NULL;
636     op->container=NULL;
637     op->env=NULL;
638     op->more=NULL;
639     op->head=NULL;
640     op->map=NULL;
641     op->refcount=0;
642     op->active_next = NULL;
643     op->active_prev = NULL;
644     /* What is not cleared is next, prev, and count */
645    
646     op->expmul=1.0;
647     op->face = blank_face;
648     op->attacked_by_count= -1;
649     if (settings.casting_time)
650     op->casting_time = -1;
651    
652     }
653    
654     /*
655     * copy object first frees everything allocated by the second object,
656     * and then copies the contends of the first object into the second
657     * object, allocating what needs to be allocated. Basically, any
658     * data that is malloc'd needs to be re-malloc/copied. Otherwise,
659     * if the first object is freed, the pointers in the new object
660     * will point at garbage.
661     */
662    
663     void copy_object(object *op2, object *op) {
664     int is_freed=QUERY_FLAG(op,FLAG_FREED),is_removed=QUERY_FLAG(op,FLAG_REMOVED);
665     event *evt, *evt2, *evt_new;
666    
667     /* Decrement the refcounts, but don't bother zeroing the fields;
668     they'll be overwritten by memcpy. */
669     if(op->name!=NULL) free_string(op->name);
670     if(op->name_pl!=NULL) free_string(op->name_pl);
671     if(op->title!=NULL) free_string(op->title);
672     if(op->race!=NULL) free_string(op->race);
673     if(op->slaying!=NULL) free_string(op->slaying);
674     if(op->skill!=NULL) free_string(op->skill);
675     if(op->msg!=NULL) free_string(op->msg);
676     if(op->lore!=NULL) free_string(op->lore);
677     if(op->materialname != NULL) free_string(op->materialname);
678     if(op->custom_name != NULL) free_string(op->custom_name);
679    
680     /* Basically, same code as from clear_object() */
681     for (evt = op->events; evt; evt=evt2) {
682     evt2 = evt->next;
683    
684     if (evt->hook != NULL) FREE_AND_CLEAR_STR(evt->hook);
685     if (evt->plugin != NULL) FREE_AND_CLEAR_STR(evt->plugin);
686     if (evt->options != NULL) FREE_AND_CLEAR_STR(evt->options);
687    
688     free(evt);
689     }
690     op->events = NULL;
691    
692     free_key_values(op);
693    
694     /* op is the destination, op2 is the source. */
695     (void) memcpy((void *)((char *) op +offsetof(object,name)),
696     (void *)((char *) op2+offsetof(object,name)),
697     sizeof(object)-offsetof(object, name));
698    
699     if(is_freed) SET_FLAG(op,FLAG_FREED);
700     if(is_removed) SET_FLAG(op,FLAG_REMOVED);
701     if(op->name!=NULL) add_refcount(op->name);
702     if(op->name_pl!=NULL) add_refcount(op->name_pl);
703     if(op->title!=NULL) add_refcount(op->title);
704     if(op->race!=NULL) add_refcount(op->race);
705     if(op->slaying!=NULL) add_refcount(op->slaying);
706     if(op->skill!=NULL) add_refcount(op->skill);
707     if(op->lore!=NULL) add_refcount(op->lore);
708     if(op->msg!=NULL) add_refcount(op->msg);
709     if(op->custom_name!=NULL) add_refcount(op->custom_name);
710     if (op->materialname != NULL) add_refcount(op->materialname);
711    
712     if((op2->speed<0) && !editor)
713     op->speed_left=op2->speed_left-RANDOM()%200/100.0;
714    
715     /* Copy over event information */
716     evt2 = NULL;
717     for (evt = op2->events; evt; evt=evt->next) {
718     evt_new = malloc(sizeof(event));
719     memcpy(evt_new, evt, sizeof(event));
720     if (evt_new->hook) add_refcount(evt_new->hook);
721     if (evt_new->plugin) add_refcount(evt_new->plugin);
722     if (evt_new->options) add_refcount(evt_new->options);
723     evt_new->next = NULL;
724    
725     /* Try to be a little clever here, and store away the
726     * last event we copied, so that its simpler to update the
727     * pointer.
728     */
729     if (evt2)
730     evt2->next = evt_new;
731     else
732     op->events = evt_new;
733    
734     evt2 = evt_new;
735     }
736     /* Copy over key_values, if any. */
737     if (op2->key_values != NULL) {
738     key_value * tail = NULL;
739     key_value * i;
740    
741     op->key_values = NULL;
742    
743     for (i = op2->key_values; i != NULL; i = i->next) {
744     key_value * new_link = malloc(sizeof(key_value));
745    
746     new_link->next = NULL;
747     new_link->key = add_refcount(i->key);
748     if (i->value)
749     new_link->value = add_refcount(i->value);
750     else
751     new_link->value = NULL;
752    
753     /* Try and be clever here, too. */
754     if (op->key_values == NULL) {
755     op->key_values = new_link;
756     tail = new_link;
757     } else {
758     tail->next = new_link;
759     tail = new_link;
760     }
761     }
762     }
763    
764     update_ob_speed(op);
765     }
766    
767     /*
768     * expand_objects() allocates more objects for the list of unused objects.
769     * It is called from get_object() if the unused list is empty.
770     */
771    
772     void expand_objects(void) {
773     int i;
774     object *new;
775     new = (object *) CALLOC(OBJ_EXPAND,sizeof(object));
776    
777     if(new==NULL)
778     fatal(OUT_OF_MEMORY);
779     free_objects=new;
780     new[0].prev=NULL;
781     new[0].next= &new[1],
782     SET_FLAG(&(new[0]), FLAG_REMOVED);
783     SET_FLAG(&(new[0]), FLAG_FREED);
784    
785     for(i=1;i<OBJ_EXPAND-1;i++) {
786     new[i].next= &new[i+1],
787     new[i].prev= &new[i-1],
788     SET_FLAG(&(new[i]), FLAG_REMOVED);
789     SET_FLAG(&(new[i]), FLAG_FREED);
790     }
791     new[OBJ_EXPAND-1].prev= &new[OBJ_EXPAND-2],
792     new[OBJ_EXPAND-1].next=NULL,
793     SET_FLAG(&(new[OBJ_EXPAND-1]), FLAG_REMOVED);
794     SET_FLAG(&(new[OBJ_EXPAND-1]), FLAG_FREED);
795    
796     nrofallocobjects += OBJ_EXPAND;
797     nroffreeobjects += OBJ_EXPAND;
798     }
799    
800     /*
801     * get_object() grabs an object from the list of unused objects, makes
802     * sure it is initialised, and returns it.
803     * If there are no free objects, expand_objects() is called to get more.
804     */
805    
806     object *get_object(void) {
807     object *op;
808    
809     if(free_objects==NULL) {
810     expand_objects();
811     }
812     op=free_objects;
813     #ifdef MEMORY_DEBUG
814     /* The idea is hopefully by doing a realloc, the memory
815     * debugging program will now use the current stack trace to
816     * report leaks.
817     */
818     op = realloc(op, sizeof(object));
819     SET_FLAG(op, FLAG_REMOVED);
820     SET_FLAG(op, FLAG_FREED);
821     #endif
822    
823     if(!QUERY_FLAG(op,FLAG_FREED)) {
824     LOG(llevError,"Fatal: Getting busy object.\n");
825     }
826     free_objects=op->next;
827     if(free_objects!=NULL)
828     free_objects->prev=NULL;
829     op->count= ++ob_count;
830     op->name=NULL;
831     op->name_pl=NULL;
832     op->title=NULL;
833     op->race=NULL;
834     op->slaying=NULL;
835     op->skill = NULL;
836     op->lore=NULL;
837     op->msg=NULL;
838     op->materialname=NULL;
839     op->next=objects;
840     op->prev=NULL;
841     op->active_next = NULL;
842     op->active_prev = NULL;
843     if(objects!=NULL)
844     objects->prev=op;
845     objects=op;
846     clear_object(op);
847     SET_FLAG(op,FLAG_REMOVED);
848     nroffreeobjects--;
849     return op;
850     }
851    
852     /*
853     * If an object with the IS_TURNABLE() flag needs to be turned due
854     * to the closest player being on the other side, this function can
855     * be called to update the face variable, _and_ how it looks on the map.
856     */
857    
858     void update_turn_face(object *op) {
859     if(!QUERY_FLAG(op,FLAG_IS_TURNABLE)||op->arch==NULL)
860     return;
861     SET_ANIMATION(op, op->direction);
862     update_object(op,UP_OBJ_FACE);
863     }
864    
865     /*
866     * Updates the speed of an object. If the speed changes from 0 to another
867     * value, or vice versa, then add/remove the object from the active list.
868     * This function needs to be called whenever the speed of an object changes.
869     */
870    
871     void update_ob_speed(object *op) {
872     extern int arch_init;
873    
874     /* No reason putting the archetypes objects on the speed list,
875     * since they never really need to be updated.
876     */
877    
878     if (QUERY_FLAG(op, FLAG_FREED) && op->speed) {
879     LOG(llevError,"Object %s is freed but has speed.\n", op->name);
880     #ifdef MANY_CORES
881     abort();
882     #else
883     op->speed = 0;
884     #endif
885     }
886     if (arch_init) {
887     return;
888     }
889     if (FABS(op->speed)>MIN_ACTIVE_SPEED) {
890     /* If already on active list, don't do anything */
891     if (op->active_next || op->active_prev || op==active_objects)
892     return;
893    
894     /* process_events() expects us to insert the object at the beginning
895     * of the list. */
896     op->active_next = active_objects;
897     if (op->active_next!=NULL)
898     op->active_next->active_prev = op;
899     active_objects = op;
900     }
901     else {
902     /* If not on the active list, nothing needs to be done */
903     if (!op->active_next && !op->active_prev && op!=active_objects)
904     return;
905    
906     if (op->active_prev==NULL) {
907     active_objects = op->active_next;
908     if (op->active_next!=NULL)
909     op->active_next->active_prev = NULL;
910     }
911     else {
912     op->active_prev->active_next = op->active_next;
913     if (op->active_next)
914     op->active_next->active_prev = op->active_prev;
915     }
916     op->active_next = NULL;
917     op->active_prev = NULL;
918     }
919     }
920    
921     /* This function removes object 'op' from the list of active
922     * objects.
923     * This should only be used for style maps or other such
924     * reference maps where you don't want an object that isn't
925     * in play chewing up cpu time getting processed.
926     * The reverse of this is to call update_ob_speed, which
927     * will do the right thing based on the speed of the object.
928     */
929     void remove_from_active_list(object *op)
930     {
931     /* If not on the active list, nothing needs to be done */
932     if (!op->active_next && !op->active_prev && op!=active_objects)
933     return;
934    
935     if (op->active_prev==NULL) {
936     active_objects = op->active_next;
937     if (op->active_next!=NULL)
938     op->active_next->active_prev = NULL;
939     }
940     else {
941     op->active_prev->active_next = op->active_next;
942     if (op->active_next)
943     op->active_next->active_prev = op->active_prev;
944     }
945     op->active_next = NULL;
946     op->active_prev = NULL;
947     }
948    
949     /*
950     * update_object() updates the array which represents the map.
951     * It takes into account invisible objects (and represent squares covered
952     * by invisible objects by whatever is below them (unless it's another
953     * invisible object, etc...)
954     * If the object being updated is beneath a player, the look-window
955     * of that player is updated (this might be a suboptimal way of
956     * updating that window, though, since update_object() is called _often_)
957     *
958     * action is a hint of what the caller believes need to be done.
959     * For example, if the only thing that has changed is the face (due to
960     * an animation), we don't need to call update_position until that actually
961     * comes into view of a player. OTOH, many other things, like addition/removal
962     * of walls or living creatures may need us to update the flags now.
963     * current action are:
964     * UP_OBJ_INSERT: op was inserted
965     * UP_OBJ_REMOVE: op was removed
966     * UP_OBJ_CHANGE: object has somehow changed. In this case, we always update
967     * as that is easier than trying to look at what may have changed.
968     * UP_OBJ_FACE: only the objects face has changed.
969     */
970    
971     void update_object(object *op, int action) {
972     int update_now=0, flags;
973     MoveType move_on, move_off, move_block, move_slow;
974    
975     if (op == NULL) {
976     /* this should never happen */
977     LOG(llevDebug,"update_object() called for NULL object.\n");
978     return;
979     }
980    
981     if(op->env!=NULL) {
982     /* Animation is currently handled by client, so nothing
983     * to do in this case.
984     */
985     return;
986     }
987    
988     /* If the map is saving, don't do anything as everything is
989     * going to get freed anyways.
990     */
991     if (!op->map || op->map->in_memory == MAP_SAVING) return;
992    
993     /* make sure the object is within map boundaries */
994     if (op->x < 0 || op->x >= MAP_WIDTH(op->map) ||
995     op->y < 0 || op->y >= MAP_HEIGHT(op->map)) {
996     LOG(llevError,"update_object() called for object out of map!\n");
997     #ifdef MANY_CORES
998     abort();
999     #endif
1000     return;
1001     }
1002    
1003     flags = GET_MAP_FLAGS(op->map, op->x, op->y);
1004     SET_MAP_FLAGS(op->map, op->x, op->y, flags | P_NEED_UPDATE);
1005     move_slow = GET_MAP_MOVE_SLOW(op->map, op->x, op->y);
1006     move_on = GET_MAP_MOVE_ON(op->map, op->x, op->y);
1007     move_block = GET_MAP_MOVE_BLOCK(op->map, op->x, op->y);
1008     move_off = GET_MAP_MOVE_OFF(op->map, op->x, op->y);
1009    
1010     if (action == UP_OBJ_INSERT) {
1011     if (QUERY_FLAG(op, FLAG_BLOCKSVIEW) && !(flags & P_BLOCKSVIEW))
1012     update_now=1;
1013    
1014     if (QUERY_FLAG(op, FLAG_NO_MAGIC) && !(flags & P_NO_MAGIC))
1015     update_now=1;
1016    
1017     if (QUERY_FLAG(op, FLAG_DAMNED) && !(flags & P_NO_CLERIC))
1018     update_now=1;
1019    
1020     if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags & P_IS_ALIVE))
1021     update_now=1;
1022    
1023     if ((move_on | op->move_on) != move_on) update_now=1;
1024     if ((move_off | op->move_off) != move_off) update_now=1;
1025 elmex 1.3 /* This isn't perfect, but I don't expect a lot of objects to
1026     * to have move_allow right now.
1027     */
1028     if (((move_block | op->move_block) & ~op->move_allow) != move_block)
1029     update_now=1;
1030 root 1.1 if ((move_slow | op->move_slow) != move_slow) update_now=1;
1031     }
1032     /* if the object is being removed, we can't make intelligent
1033     * decisions, because remove_ob can't really pass the object
1034     * that is being removed.
1035     */
1036     else if (action == UP_OBJ_CHANGE || action == UP_OBJ_REMOVE) {
1037     update_now=1;
1038     } else if (action == UP_OBJ_FACE) {
1039     /* Nothing to do for that case */
1040     }
1041     else {
1042     LOG(llevError,"update_object called with invalid action: %d\n", action);
1043     }
1044    
1045     if (update_now) {
1046     SET_MAP_FLAGS(op->map, op->x, op->y, flags | P_NO_ERROR | P_NEED_UPDATE);
1047     update_position(op->map, op->x, op->y);
1048     }
1049    
1050     if(op->more!=NULL)
1051     update_object(op->more, action);
1052     }
1053    
1054    
1055     /*
1056     * free_object() frees everything allocated by an object, removes
1057     * it from the list of used objects, and puts it on the list of
1058     * free objects. The IS_FREED() flag is set in the object.
1059     * The object must have been removed by remove_ob() first for
1060     * this function to succeed.
1061     *
1062     * If free_inventory is set, free inventory as well. Else drop items in
1063     * inventory to the ground.
1064     */
1065    
1066     void free_object(object *ob) {
1067     free_object2(ob, 0);
1068     }
1069     void free_object2(object *ob, int free_inventory) {
1070     object *tmp,*op;
1071    
1072 root 1.2 if (object_free_callback)
1073     object_free_callback (ob);
1074    
1075 root 1.1 if (!QUERY_FLAG(ob,FLAG_REMOVED)) {
1076     LOG(llevDebug,"Free object called with non removed object\n");
1077     dump_object(ob);
1078     #ifdef MANY_CORES
1079     abort();
1080     #endif
1081     }
1082     if(QUERY_FLAG(ob,FLAG_FRIENDLY)) {
1083     LOG(llevMonster,"Warning: tried to free friendly object.\n");
1084     remove_friendly_object(ob);
1085     }
1086     if(QUERY_FLAG(ob,FLAG_FREED)) {
1087     dump_object(ob);
1088     LOG(llevError,"Trying to free freed object.\n%s\n",errmsg);
1089     return;
1090     }
1091     if(ob->more!=NULL) {
1092     free_object2(ob->more, free_inventory);
1093     ob->more=NULL;
1094     }
1095     if (ob->inv) {
1096     /* Only if the space blocks everything do we not process -
1097     * if some form of movemnt is allowed, let objects
1098     * drop on that space.
1099     */
1100     if (free_inventory || ob->map==NULL || ob->map->in_memory!=MAP_IN_MEMORY ||
1101     (GET_MAP_MOVE_BLOCK(ob->map, ob->x, ob->y) == MOVE_ALL))
1102     {
1103     op=ob->inv;
1104     while(op!=NULL) {
1105     tmp=op->below;
1106     remove_ob(op);
1107     free_object2(op, free_inventory);
1108     op=tmp;
1109     }
1110     }
1111     else { /* Put objects in inventory onto this space */
1112     op=ob->inv;
1113     while(op!=NULL) {
1114     tmp=op->below;
1115     remove_ob(op);
1116     if(QUERY_FLAG(op,FLAG_STARTEQUIP)||QUERY_FLAG(op,FLAG_NO_DROP) ||
1117     op->type==RUNE || op->type==TRAP || QUERY_FLAG(op,FLAG_IS_A_TEMPLATE))
1118     free_object(op);
1119     else {
1120     op->x=ob->x;
1121     op->y=ob->y;
1122     insert_ob_in_map(op,ob->map,NULL,0); /* Insert in same map as the envir */
1123     }
1124     op=tmp;
1125     }
1126     }
1127     }
1128     /* Remove object from the active list */
1129     ob->speed = 0;
1130     update_ob_speed(ob);
1131    
1132     SET_FLAG(ob, FLAG_FREED);
1133     ob->count = 0;
1134    
1135     /* Remove this object from the list of used objects */
1136     if(ob->prev==NULL) {
1137     objects=ob->next;
1138     if(objects!=NULL)
1139     objects->prev=NULL;
1140     }
1141     else {
1142     ob->prev->next=ob->next;
1143     if(ob->next!=NULL)
1144     ob->next->prev=ob->prev;
1145     }
1146    
1147     if(ob->name!=NULL) FREE_AND_CLEAR_STR(ob->name);
1148     if(ob->name_pl!=NULL) FREE_AND_CLEAR_STR(ob->name_pl);
1149     if(ob->title!=NULL) FREE_AND_CLEAR_STR(ob->title);
1150     if(ob->race!=NULL) FREE_AND_CLEAR_STR(ob->race);
1151     if(ob->slaying!=NULL) FREE_AND_CLEAR_STR(ob->slaying);
1152     if(ob->skill!=NULL) FREE_AND_CLEAR_STR(ob->skill);
1153     if(ob->lore!=NULL) FREE_AND_CLEAR_STR(ob->lore);
1154     if(ob->msg!=NULL) FREE_AND_CLEAR_STR(ob->msg);
1155     if(ob->materialname!=NULL) FREE_AND_CLEAR_STR(ob->materialname);
1156    
1157    
1158     /* Why aren't events freed? */
1159     free_key_values(ob);
1160    
1161     #if 0 /* MEMORY_DEBUG*/
1162     /* This is a nice idea. Unfortunately, a lot of the code in crossfire
1163     * presumes the freed_object will stick around for at least a little
1164     * bit
1165     */
1166     /* this is necessary so that memory debugging programs will
1167     * be able to accurately report source of malloc. If we recycle
1168     * objects, then some other area may be doing the get_object
1169     * and not freeing it, but the original one that malloc'd the
1170     * object will get the blame.
1171     */
1172     free(ob);
1173     #else
1174    
1175     /* Now link it with the free_objects list: */
1176     ob->prev=NULL;
1177     ob->next=free_objects;
1178     if(free_objects!=NULL)
1179     free_objects->prev=ob;
1180     free_objects=ob;
1181     nroffreeobjects++;
1182     #endif
1183     }
1184    
1185     /*
1186     * count_free() returns the number of objects on the list of free objects.
1187     */
1188    
1189     int count_free(void) {
1190     int i=0;
1191     object *tmp=free_objects;
1192     while(tmp!=NULL)
1193     tmp=tmp->next, i++;
1194     return i;
1195     }
1196    
1197     /*
1198     * count_used() returns the number of objects on the list of used objects.
1199     */
1200    
1201     int count_used(void) {
1202     int i=0;
1203     object *tmp=objects;
1204     while(tmp!=NULL)
1205     tmp=tmp->next, i++;
1206     return i;
1207     }
1208    
1209     /*
1210     * count_active() returns the number of objects on the list of active objects.
1211     */
1212    
1213     int count_active(void) {
1214     int i=0;
1215     object *tmp=active_objects;
1216     while(tmp!=NULL)
1217     tmp=tmp->active_next, i++;
1218     return i;
1219     }
1220    
1221     /*
1222     * sub_weight() recursively (outwards) subtracts a number from the
1223     * weight of an object (and what is carried by it's environment(s)).
1224     */
1225    
1226     void sub_weight (object *op, signed long weight) {
1227     while (op != NULL) {
1228     if (op->type == CONTAINER) {
1229     weight=(signed long)(weight*(100-op->stats.Str)/100);
1230     }
1231     op->carrying-=weight;
1232     op = op->env;
1233     }
1234     }
1235    
1236     /* remove_ob(op):
1237     * This function removes the object op from the linked list of objects
1238     * which it is currently tied to. When this function is done, the
1239     * object will have no environment. If the object previously had an
1240     * environment, the x and y coordinates will be updated to
1241     * the previous environment.
1242     * Beware: This function is called from the editor as well!
1243     */
1244    
1245     void remove_ob(object *op) {
1246     object *tmp,*last=NULL;
1247     object *otmp;
1248     tag_t tag;
1249     int check_walk_off;
1250     mapstruct *m;
1251     sint16 x,y;
1252    
1253    
1254     if(QUERY_FLAG(op,FLAG_REMOVED)) {
1255     dump_object(op);
1256     LOG(llevError,"Trying to remove removed object.\n%s\n",errmsg);
1257    
1258     /* Changed it to always dump core in this case. As has been learned
1259     * in the past, trying to recover from errors almost always
1260     * make things worse, and this is a real error here - something
1261     * that should not happen.
1262     * Yes, if this was a mission critical app, trying to do something
1263     * to recover may make sense, but that is because failure of the app
1264     * may have other disastrous problems. Cf runs out of a script
1265     * so is easily enough restarted without any real problems.
1266     * MSW 2001-07-01
1267     */
1268     abort();
1269     }
1270     if(op->more!=NULL)
1271     remove_ob(op->more);
1272    
1273     SET_FLAG(op, FLAG_REMOVED);
1274    
1275     /*
1276     * In this case, the object to be removed is in someones
1277     * inventory.
1278     */
1279     if(op->env!=NULL) {
1280     if(op->nrof)
1281     sub_weight(op->env, op->weight*op->nrof);
1282     else
1283     sub_weight(op->env, op->weight+op->carrying);
1284    
1285     /* NO_FIX_PLAYER is set when a great many changes are being
1286     * made to players inventory. If set, avoiding the call
1287     * to save cpu time.
1288     */
1289     if ((otmp=is_player_inv(op->env))!=NULL && otmp->contr &&
1290     !QUERY_FLAG(otmp,FLAG_NO_FIX_PLAYER))
1291     fix_player(otmp);
1292    
1293     if(op->above!=NULL)
1294     op->above->below=op->below;
1295     else
1296     op->env->inv=op->below;
1297    
1298     if(op->below!=NULL)
1299     op->below->above=op->above;
1300    
1301     /* we set up values so that it could be inserted into
1302     * the map, but we don't actually do that - it is up
1303     * to the caller to decide what we want to do.
1304     */
1305     op->x=op->env->x,op->y=op->env->y;
1306     op->ox=op->x,op->oy=op->y;
1307     op->map=op->env->map;
1308     op->above=NULL,op->below=NULL;
1309     op->env=NULL;
1310     return;
1311     }
1312    
1313     /* If we get here, we are removing it from a map */
1314     if (op->map == NULL) return;
1315    
1316     x = op->x;
1317     y = op->y;
1318     m = get_map_from_coord(op->map, &x, &y);
1319    
1320     if (!m) {
1321     LOG(llevError,"remove_ob called when object was on map but appears to not be within valid coordinates? %s (%d,%d)\n",
1322     op->map->path, op->x, op->y);
1323     /* in old days, we used to set x and y to 0 and continue.
1324     * it seems if we get into this case, something is probablye
1325     * screwed up and should be fixed.
1326     */
1327     abort();
1328     }
1329     if (op->map != m) {
1330     LOG(llevDebug,"remove_ob: Object not really on map it claimed to be on? %s != %s, %d,%d != %d,%d\n",
1331     op->map->path, m->path, op->x, op->y, x, y);
1332     }
1333    
1334     /* Re did the following section of code - it looks like it had
1335     * lots of logic for things we no longer care about
1336     */
1337    
1338     /* link the object above us */
1339     if (op->above)
1340     op->above->below=op->below;
1341     else
1342     SET_MAP_TOP(m,x,y,op->below); /* we were top, set new top */
1343    
1344     /* Relink the object below us, if there is one */
1345     if(op->below) {
1346     op->below->above=op->above;
1347     } else {
1348     /* Nothing below, which means we need to relink map object for this space
1349     * use translated coordinates in case some oddness with map tiling is
1350     * evident
1351     */
1352     if(GET_MAP_OB(m,x,y)!=op) {
1353     dump_object(op);
1354     LOG(llevError,"remove_ob: GET_MAP_OB does not return object to be removed even though it appears to be on the bottom?\n%s\n", errmsg);
1355     dump_object(GET_MAP_OB(m,x,y));
1356     LOG(llevError,"%s\n",errmsg);
1357     }
1358     SET_MAP_OB(m,x,y,op->above); /* goes on above it. */
1359     }
1360     op->above=NULL;
1361     op->below=NULL;
1362    
1363     if (op->map->in_memory == MAP_SAVING)
1364     return;
1365    
1366     tag = op->count;
1367     check_walk_off = ! QUERY_FLAG (op, FLAG_NO_APPLY);
1368     for(tmp=GET_MAP_OB(m,x,y);tmp!=NULL;tmp=tmp->above) {
1369     /* No point updating the players look faces if he is the object
1370     * being removed.
1371     */
1372    
1373     if(tmp->type==PLAYER && tmp!=op) {
1374     /* If a container that the player is currently using somehow gets
1375     * removed (most likely destroyed), update the player view
1376     * appropriately.
1377     */
1378     if (tmp->container==op) {
1379     CLEAR_FLAG(op, FLAG_APPLIED);
1380     tmp->container=NULL;
1381     }
1382     tmp->contr->socket.update_look=1;
1383     }
1384     /* See if player moving off should effect something */
1385     if (check_walk_off && ((op->move_type & tmp->move_off) &&
1386     (op->move_type & ~tmp->move_off & ~tmp->move_block)==0)) {
1387    
1388     move_apply(tmp, op, NULL);
1389     if (was_destroyed (op, tag)) {
1390     LOG (llevError, "BUG: remove_ob(): name %s, archname %s destroyed "
1391     "leaving object\n", tmp->name, tmp->arch->name);
1392     }
1393     }
1394    
1395     /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */
1396    
1397     if(tmp->above == tmp)
1398     tmp->above = NULL;
1399     last=tmp;
1400     }
1401     /* last == NULL of there are no objects on this space */
1402     if (last==NULL) {
1403     /* set P_NEED_UPDATE, otherwise update_position will complain. In theory,
1404     * we could preserve the flags (GET_MAP_FLAGS), but update_position figures
1405     * those out anyways, and if there are any flags set right now, they won't
1406     * be correct anyways.
1407     */
1408     SET_MAP_FLAGS(op->map, op->x, op->y, P_NEED_UPDATE);
1409     update_position(op->map, op->x, op->y);
1410     }
1411     else
1412     update_object(last, UP_OBJ_REMOVE);
1413    
1414     if(QUERY_FLAG(op,FLAG_BLOCKSVIEW)|| (op->glow_radius != 0))
1415     update_all_los(op->map, op->x, op->y);
1416    
1417     }
1418    
1419     /*
1420     * merge_ob(op,top):
1421     *
1422     * This function goes through all objects below and including top, and
1423     * merges op to the first matching object.
1424     * If top is NULL, it is calculated.
1425     * Returns pointer to object if it succeded in the merge, otherwise NULL
1426     */
1427    
1428     object *merge_ob(object *op, object *top) {
1429     if(!op->nrof)
1430     return 0;
1431     if(top==NULL)
1432     for(top=op;top!=NULL&&top->above!=NULL;top=top->above);
1433     for(;top!=NULL;top=top->below) {
1434     if(top==op)
1435     continue;
1436     if (CAN_MERGE(op,top))
1437     {
1438     top->nrof+=op->nrof;
1439     /* CLEAR_FLAG(top,FLAG_STARTEQUIP);*/
1440     op->weight = 0; /* Don't want any adjustements now */
1441     remove_ob(op);
1442     free_object(op);
1443     return top;
1444     }
1445     }
1446     return NULL;
1447     }
1448    
1449     /*
1450     * same as insert_ob_in_map except it handle separate coordinates and do a clean
1451     * job preparing multi-part monsters
1452     */
1453     object *insert_ob_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y){
1454     object* tmp;
1455     if (op->head)
1456     op=op->head;
1457     for (tmp=op;tmp;tmp=tmp->more){
1458     tmp->x=x+tmp->arch->clone.x;
1459     tmp->y=y+tmp->arch->clone.y;
1460     }
1461     return insert_ob_in_map (op, m, originator, flag);
1462     }
1463    
1464     /*
1465     * insert_ob_in_map (op, map, originator, flag):
1466     * This function inserts the object in the two-way linked list
1467     * which represents what is on a map.
1468     * The second argument specifies the map, and the x and y variables
1469     * in the object about to be inserted specifies the position.
1470     *
1471     * originator: Player, monster or other object that caused 'op' to be inserted
1472     * into 'map'. May be NULL.
1473     *
1474     * flag is a bitmask about special things to do (or not do) when this
1475     * function is called. see the object.h file for the INS_ values.
1476     * Passing 0 for flag gives proper default values, so flag really only needs
1477     * to be set if special handling is needed.
1478     *
1479     * Return value:
1480     * new object if 'op' was merged with other object
1481     * NULL if 'op' was destroyed
1482     * just 'op' otherwise
1483     */
1484    
1485     object *insert_ob_in_map (object *op, mapstruct *m, object *originator, int flag)
1486     {
1487     object *tmp, *top, *floor=NULL;
1488     sint16 x,y;
1489    
1490     if (QUERY_FLAG (op, FLAG_FREED)) {
1491     LOG (llevError, "Trying to insert freed object!\n");
1492     return NULL;
1493     }
1494     if(m==NULL) {
1495     dump_object(op);
1496     LOG(llevError,"Trying to insert in null-map!\n%s\n",errmsg);
1497     return op;
1498     }
1499     if(out_of_map(m,op->x,op->y)) {
1500     dump_object(op);
1501     LOG(llevError,"Trying to insert object outside the map.\n%s\n", errmsg);
1502     #ifdef MANY_CORES
1503     /* Better to catch this here, as otherwise the next use of this object
1504     * is likely to cause a crash. Better to find out where it is getting
1505     * improperly inserted.
1506     */
1507     abort();
1508     #endif
1509     return op;
1510     }
1511     if(!QUERY_FLAG(op,FLAG_REMOVED)) {
1512     dump_object(op);
1513     LOG(llevError,"Trying to insert (map) inserted object.\n%s\n", errmsg);
1514     return op;
1515     }
1516     if(op->more!=NULL) {
1517     /* The part may be on a different map. */
1518    
1519     object *more = op->more;
1520    
1521 elmex 1.3 /* We really need the caller to normalize coordinates - if
1522     * we set the map, that doesn't work if the location is within
1523     * a map and this is straddling an edge. So only if coordinate
1524     * is clear wrong do we normalize it.
1525     */
1526     if (OUT_OF_REAL_MAP(more->map, more->x, more->y)) {
1527     /* Debugging information so you can see the last coordinates this object had */
1528     more->ox = more->x;
1529     more->oy = more->y;
1530     more->map = get_map_from_coord(m, &more->x, &more->y);
1531     } else if (!more->map) {
1532     /* For backwards compatibility - when not dealing with tiled maps,
1533     * more->map should always point to the parent.
1534     */
1535     more->map = m;
1536     }
1537 root 1.1
1538     if (insert_ob_in_map(more, more->map, originator, flag) == NULL) {
1539     if ( ! op->head)
1540     LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n");
1541     return NULL;
1542     }
1543     }
1544     CLEAR_FLAG(op,FLAG_REMOVED);
1545    
1546     /* Debugging information so you can see the last coordinates this object had */
1547     op->ox=op->x;
1548     op->oy=op->y;
1549 root 1.6
1550     /* Ideally, the caller figures this out. However, it complicates a lot
1551     * of areas of callers (eg, anything that uses find_free_spot would now
1552     * need extra work
1553     */
1554     op->map=get_map_from_coord(m, &op->x, &op->y);
1555 root 1.1 x = op->x;
1556     y = op->y;
1557    
1558     /* this has to be done after we translate the coordinates.
1559     */
1560     if(op->nrof && !(flag & INS_NO_MERGE)) {
1561     for(tmp=GET_MAP_OB(op->map,x,y);tmp!=NULL;tmp=tmp->above)
1562     if (CAN_MERGE(op,tmp)) {
1563     op->nrof+=tmp->nrof;
1564     remove_ob(tmp);
1565     free_object(tmp);
1566     }
1567     }
1568    
1569     CLEAR_FLAG(op,FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */
1570     CLEAR_FLAG(op, FLAG_INV_LOCKED);
1571     if (!QUERY_FLAG(op, FLAG_ALIVE))
1572     CLEAR_FLAG(op, FLAG_NO_STEAL);
1573    
1574     if (flag & INS_BELOW_ORIGINATOR) {
1575     if (originator->map != op->map || originator->x != op->x ||
1576     originator->y != op->y) {
1577     LOG(llevError,"insert_ob_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n");
1578     abort();
1579     }
1580     op->above = originator;
1581     op->below = originator->below;
1582     if (op->below) op->below->above = op;
1583     else SET_MAP_OB(op->map, op->x, op->y, op);
1584     /* since *below* originator, no need to update top */
1585     originator->below = op;
1586     } else {
1587     /* If there are other objects, then */
1588     if((! (flag & INS_MAP_LOAD)) && ((top=GET_MAP_OB(op->map,op->x,op->y))!=NULL)) {
1589     object *last=NULL;
1590     /*
1591     * If there are multiple objects on this space, we do some trickier handling.
1592     * We've already dealt with merging if appropriate.
1593     * Generally, we want to put the new object on top. But if
1594     * flag contains INS_ABOVE_FLOOR_ONLY, once we find the last
1595     * floor, we want to insert above that and no further.
1596     * Also, if there are spell objects on this space, we stop processing
1597     * once we get to them. This reduces the need to traverse over all of
1598     * them when adding another one - this saves quite a bit of cpu time
1599     * when lots of spells are cast in one area. Currently, it is presumed
1600     * that flying non pickable objects are spell objects.
1601     */
1602    
1603     while (top != NULL) {
1604     if (QUERY_FLAG(top, FLAG_IS_FLOOR) ||
1605     QUERY_FLAG(top, FLAG_OVERLAY_FLOOR)) floor = top;
1606     if (QUERY_FLAG(top, FLAG_NO_PICK) &&
1607     (top->move_type & (MOVE_FLY_LOW |MOVE_FLY_HIGH))) {
1608     /* We insert above top, so we want this object below this */
1609     top=top->below;
1610     break;
1611     }
1612     last = top;
1613     top = top->above;
1614     }
1615     /* Don't want top to be NULL, so set it to the last valid object */
1616     top = last;
1617    
1618     /* We let update_position deal with figuring out what the space
1619     * looks like instead of lots of conditions here.
1620     * makes things faster, and effectively the same result.
1621     */
1622    
1623     /* Have object 'fall below' other objects that block view.
1624     * Unless those objects are exits, type 66
1625     * If INS_ON_TOP is used, don't do this processing
1626     * Need to find the object that in fact blocks view, otherwise
1627     * stacking is a bit odd.
1628     */
1629     if (!(flag & INS_ON_TOP) &&
1630     (get_map_flags(op->map, NULL, op->x, op->y, NULL, NULL) & P_BLOCKSVIEW) &&
1631     (op->face && !op->face->visibility)) {
1632     for (last=top; last != floor; last=last->below)
1633     if (QUERY_FLAG(last, FLAG_BLOCKSVIEW)&&(last->type != EXIT)) break;
1634     /* Check to see i we found the object that blocks view,
1635     * and make sure we have a below pointer for it so that
1636     * we can get inserted below this one, which requires we
1637     * set top to the object below us.
1638     */
1639     if (last && last->below && last != floor) top=last->below;
1640     }
1641     } /* If objects on this space */
1642     if (flag & INS_MAP_LOAD)
1643     top = GET_MAP_TOP(op->map,op->x,op->y);
1644     if (flag & INS_ABOVE_FLOOR_ONLY) top = floor;
1645    
1646     /* Top is the object that our object (op) is going to get inserted above.
1647     */
1648    
1649     /* First object on this space */
1650     if (!top) {
1651     op->above = GET_MAP_OB(op->map, op->x, op->y);
1652     if (op->above) op->above->below = op;
1653     op->below = NULL;
1654     SET_MAP_OB(op->map, op->x, op->y, op);
1655     } else { /* get inserted into the stack above top */
1656     op->above = top->above;
1657     if (op->above) op->above->below = op;
1658     op->below = top;
1659     top->above = op;
1660     }
1661     if (op->above==NULL)
1662     SET_MAP_TOP(op->map,op->x, op->y, op);
1663     } /* else not INS_BELOW_ORIGINATOR */
1664    
1665     if(op->type==PLAYER)
1666     op->contr->do_los=1;
1667    
1668     /* If we have a floor, we know the player, if any, will be above
1669     * it, so save a few ticks and start from there.
1670     */
1671     if (!(flag & INS_MAP_LOAD))
1672     for(tmp=floor?floor:GET_MAP_OB(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above) {
1673     if (tmp->type == PLAYER)
1674     tmp->contr->socket.update_look=1;
1675     }
1676    
1677     /* If this object glows, it may affect lighting conditions that are
1678     * visible to others on this map. But update_all_los is really
1679     * an inefficient way to do this, as it means los for all players
1680     * on the map will get recalculated. The players could very well
1681     * be far away from this change and not affected in any way -
1682     * this should get redone to only look for players within range,
1683     * or just updating the P_NEED_UPDATE for spaces within this area
1684     * of effect may be sufficient.
1685     */
1686     if(MAP_DARKNESS(op->map) && (op->glow_radius != 0))
1687     update_all_los(op->map, op->x, op->y);
1688    
1689    
1690     /* updates flags (blocked, alive, no magic, etc) for this map space */
1691     update_object(op,UP_OBJ_INSERT);
1692    
1693    
1694     /* Don't know if moving this to the end will break anything. However,
1695     * we want to have update_look set above before calling this.
1696     *
1697     * check_move_on() must be after this because code called from
1698     * check_move_on() depends on correct map flags (so functions like
1699     * blocked() and wall() work properly), and these flags are updated by
1700     * update_object().
1701     */
1702    
1703     /* if this is not the head or flag has been passed, don't check walk on status */
1704    
1705     if (!(flag & INS_NO_WALK_ON) && !op->head) {
1706     if (check_move_on(op, originator))
1707     return NULL;
1708    
1709     /* If we are a multi part object, lets work our way through the check
1710     * walk on's.
1711     */
1712     for (tmp=op->more; tmp!=NULL; tmp=tmp->more)
1713     if (check_move_on (tmp, originator))
1714     return NULL;
1715     }
1716     return op;
1717     }
1718    
1719     /* this function inserts an object in the map, but if it
1720     * finds an object of its own type, it'll remove that one first.
1721     * op is the object to insert it under: supplies x and the map.
1722     */
1723 elmex 1.3 void replace_insert_ob_in_map(const char *arch_string, object *op) {
1724 root 1.1 object *tmp;
1725     object *tmp1;
1726    
1727     /* first search for itself and remove any old instances */
1728    
1729     for(tmp=GET_MAP_OB(op->map,op->x,op->y); tmp!=NULL; tmp=tmp->above) {
1730     if(!strcmp(tmp->arch->name,arch_string)) /* same archetype */ {
1731     remove_ob(tmp);
1732     free_object(tmp);
1733     }
1734     }
1735    
1736     tmp1=arch_to_object(find_archetype(arch_string));
1737    
1738    
1739     tmp1->x = op->x; tmp1->y = op->y;
1740     insert_ob_in_map(tmp1,op->map,op,0);
1741     }
1742    
1743     /*
1744     * get_split_ob(ob,nr) splits up ob into two parts. The part which
1745     * is returned contains nr objects, and the remaining parts contains
1746     * the rest (or is removed and freed if that number is 0).
1747     * On failure, NULL is returned, and the reason put into the
1748     * global static errmsg array.
1749     */
1750    
1751     object *get_split_ob(object *orig_ob, uint32 nr) {
1752     object *newob;
1753     int is_removed = (QUERY_FLAG (orig_ob, FLAG_REMOVED) != 0);
1754    
1755     if(orig_ob->nrof<nr) {
1756     sprintf(errmsg,"There are only %d %ss.",
1757     orig_ob->nrof?orig_ob->nrof:1, orig_ob->name);
1758     return NULL;
1759     }
1760     newob = object_create_clone(orig_ob);
1761     if((orig_ob->nrof-=nr)<1) {
1762     if ( ! is_removed)
1763     remove_ob(orig_ob);
1764     free_object2(orig_ob, 1);
1765     }
1766     else if ( ! is_removed) {
1767     if(orig_ob->env!=NULL)
1768     sub_weight (orig_ob->env,orig_ob->weight*nr);
1769     if (orig_ob->env == NULL && orig_ob->map->in_memory!=MAP_IN_MEMORY) {
1770     strcpy(errmsg, "Tried to split object whose map is not in memory.");
1771     LOG(llevDebug,
1772     "Error, Tried to split object whose map is not in memory.\n");
1773     return NULL;
1774     }
1775     }
1776     newob->nrof=nr;
1777    
1778     return newob;
1779     }
1780    
1781     /*
1782     * decrease_ob_nr(object, number) decreases a specified number from
1783     * the amount of an object. If the amount reaches 0, the object
1784     * is subsequently removed and freed.
1785     *
1786     * Return value: 'op' if something is left, NULL if the amount reached 0
1787     */
1788    
1789     object *decrease_ob_nr (object *op, uint32 i)
1790     {
1791     object *tmp;
1792     player *pl;
1793    
1794     if (i == 0) /* objects with op->nrof require this check */
1795     return op;
1796    
1797     if (i > op->nrof)
1798     i = op->nrof;
1799    
1800     if (QUERY_FLAG (op, FLAG_REMOVED))
1801     {
1802     op->nrof -= i;
1803     }
1804     else if (op->env != NULL)
1805     {
1806     /* is this object in the players inventory, or sub container
1807     * therein?
1808     */
1809     tmp = is_player_inv (op->env);
1810     /* nope. Is this a container the player has opened?
1811     * If so, set tmp to that player.
1812     * IMO, searching through all the players will mostly
1813     * likely be quicker than following op->env to the map,
1814     * and then searching the map for a player.
1815     */
1816     if (!tmp) {
1817     for (pl=first_player; pl; pl=pl->next)
1818     if (pl->ob->container == op->env) break;
1819     if (pl) tmp=pl->ob;
1820     else tmp=NULL;
1821     }
1822    
1823     if (i < op->nrof) {
1824     sub_weight (op->env, op->weight * i);
1825     op->nrof -= i;
1826     if (tmp) {
1827     esrv_send_item(tmp, op);
1828     }
1829     } else {
1830     remove_ob (op);
1831     op->nrof = 0;
1832     if (tmp) {
1833     esrv_del_item(tmp->contr, op->count);
1834     }
1835     }
1836     }
1837     else
1838     {
1839     object *above = op->above;
1840    
1841     if (i < op->nrof) {
1842     op->nrof -= i;
1843     } else {
1844     remove_ob (op);
1845     op->nrof = 0;
1846     }
1847     /* Since we just removed op, op->above is null */
1848     for (tmp = above; tmp != NULL; tmp = tmp->above)
1849     if (tmp->type == PLAYER) {
1850     if (op->nrof)
1851     esrv_send_item(tmp, op);
1852     else
1853     esrv_del_item(tmp->contr, op->count);
1854     }
1855     }
1856    
1857     if (op->nrof) {
1858     return op;
1859     } else {
1860     free_object (op);
1861     return NULL;
1862     }
1863     }
1864    
1865     /*
1866     * add_weight(object, weight) adds the specified weight to an object,
1867     * and also updates how much the environment(s) is/are carrying.
1868     */
1869    
1870     void add_weight (object *op, signed long weight) {
1871     while (op!=NULL) {
1872     if (op->type == CONTAINER) {
1873     weight=(signed long)(weight*(100-op->stats.Str)/100);
1874     }
1875     op->carrying+=weight;
1876     op=op->env;
1877     }
1878     }
1879    
1880     /*
1881     * insert_ob_in_ob(op,environment):
1882     * This function inserts the object op in the linked list
1883     * inside the object environment.
1884     *
1885     * Eneq(@csd.uu.se): Altered insert_ob_in_ob to make things picked up enter
1886     * the inventory at the last position or next to other objects of the same
1887     * type.
1888     * Frank: Now sorted by type, archetype and magic!
1889     *
1890     * The function returns now pointer to inserted item, and return value can
1891     * be != op, if items are merged. -Tero
1892     */
1893    
1894     object *insert_ob_in_ob(object *op,object *where) {
1895     object *tmp, *otmp;
1896    
1897     if(!QUERY_FLAG(op,FLAG_REMOVED)) {
1898     dump_object(op);
1899     LOG(llevError,"Trying to insert (ob) inserted object.\n%s\n", errmsg);
1900     return op;
1901     }
1902     if(where==NULL) {
1903     dump_object(op);
1904     LOG(llevError,"Trying to put object in NULL.\n%s\n", errmsg);
1905     return op;
1906     }
1907     if (where->head) {
1908     LOG(llevDebug,
1909     "Warning: Tried to insert object wrong part of multipart object.\n");
1910     where = where->head;
1911     }
1912     if (op->more) {
1913     LOG(llevError, "Tried to insert multipart object %s (%d)\n",
1914     op->name, op->count);
1915     return op;
1916     }
1917     CLEAR_FLAG(op, FLAG_OBJ_ORIGINAL);
1918     CLEAR_FLAG(op, FLAG_REMOVED);
1919     if(op->nrof) {
1920     for(tmp=where->inv;tmp!=NULL;tmp=tmp->below)
1921     if ( CAN_MERGE(tmp,op) ) {
1922     /* return the original object and remove inserted object
1923     (client needs the original object) */
1924     tmp->nrof += op->nrof;
1925     /* Weight handling gets pretty funky. Since we are adding to
1926     * tmp->nrof, we need to increase the weight.
1927     */
1928     add_weight (where, op->weight*op->nrof);
1929     SET_FLAG(op, FLAG_REMOVED);
1930     free_object(op); /* free the inserted object */
1931     op = tmp;
1932     remove_ob (op); /* and fix old object's links */
1933     CLEAR_FLAG(op, FLAG_REMOVED);
1934     break;
1935     }
1936    
1937     /* I assume combined objects have no inventory
1938     * We add the weight - this object could have just been removed
1939     * (if it was possible to merge). calling remove_ob will subtract
1940     * the weight, so we need to add it in again, since we actually do
1941     * the linking below
1942     */
1943     add_weight (where, op->weight*op->nrof);
1944     } else
1945     add_weight (where, (op->weight+op->carrying));
1946    
1947     otmp=is_player_inv(where);
1948     if (otmp&&otmp->contr!=NULL) {
1949     if (!QUERY_FLAG(otmp,FLAG_NO_FIX_PLAYER))
1950     fix_player(otmp);
1951     }
1952    
1953     op->map=NULL;
1954     op->env=where;
1955     op->above=NULL;
1956     op->below=NULL;
1957     op->x=0,op->y=0;
1958     op->ox=0,op->oy=0;
1959    
1960     /* reset the light list and los of the players on the map */
1961     if((op->glow_radius!=0)&&where->map)
1962     {
1963     #ifdef DEBUG_LIGHTS
1964     LOG(llevDebug, " insert_ob_in_ob(): got %s to insert in map/op\n",
1965     op->name);
1966     #endif /* DEBUG_LIGHTS */
1967     if (MAP_DARKNESS(where->map)) update_all_los(where->map, where->x, where->y);
1968     }
1969    
1970     /* Client has no idea of ordering so lets not bother ordering it here.
1971     * It sure simplifies this function...
1972     */
1973     if (where->inv==NULL)
1974     where->inv=op;
1975     else {
1976     op->below = where->inv;
1977     op->below->above = op;
1978     where->inv = op;
1979     }
1980     return op;
1981     }
1982    
1983     /*
1984     * Checks if any objects has a move_type that matches objects
1985     * that effect this object on this space. Call apply() to process
1986     * these events.
1987     *
1988     * Any speed-modification due to SLOW_MOVE() of other present objects
1989     * will affect the speed_left of the object.
1990     *
1991     * originator: Player, monster or other object that caused 'op' to be inserted
1992     * into 'map'. May be NULL.
1993     *
1994     * Return value: 1 if 'op' was destroyed, 0 otherwise.
1995     *
1996     * 4-21-95 added code to check if appropriate skill was readied - this will
1997     * permit faster movement by the player through this terrain. -b.t.
1998     *
1999     * MSW 2001-07-08: Check all objects on space, not just those below
2000     * object being inserted. insert_ob_in_map may not put new objects
2001     * on top.
2002     */
2003    
2004     int check_move_on (object *op, object *originator)
2005     {
2006     object *tmp;
2007     tag_t tag;
2008     mapstruct *m=op->map;
2009     int x=op->x, y=op->y;
2010     MoveType move_on, move_slow, move_block;
2011    
2012     if(QUERY_FLAG(op,FLAG_NO_APPLY))
2013     return 0;
2014    
2015     tag = op->count;
2016    
2017     move_on = GET_MAP_MOVE_ON(op->map, op->x, op->y);
2018     move_slow = GET_MAP_MOVE_SLOW(op->map, op->x, op->y);
2019     move_block = GET_MAP_MOVE_BLOCK(op->map, op->x, op->y);
2020    
2021     /* if nothing on this space will slow op down or be applied,
2022     * no need to do checking below. have to make sure move_type
2023     * is set, as lots of objects don't have it set - we treat that
2024     * as walking.
2025     */
2026     if (op->move_type && !(op->move_type & move_on) && !(op->move_type & move_slow))
2027     return 0;
2028    
2029     /* This is basically inverse logic of that below - basically,
2030     * if the object can avoid the move on or slow move, they do so,
2031     * but can't do it if the alternate movement they are using is
2032     * blocked. Logic on this seems confusing, but does seem correct.
2033     */
2034     if ((op->move_type & ~move_on & ~move_block) != 0 &&
2035     (op->move_type & ~move_slow & ~move_block) != 0) return 0;
2036    
2037     /* The objects have to be checked from top to bottom.
2038     * Hence, we first go to the top:
2039     */
2040    
2041     for (tmp=GET_MAP_OB(op->map, op->x, op->y); tmp!=NULL &&
2042     tmp->above!=NULL; tmp=tmp->above) {
2043     /* Trim the search when we find the first other spell effect
2044     * this helps performance so that if a space has 50 spell objects,
2045     * we don't need to check all of them.
2046     */
2047     if ((tmp->move_type & MOVE_FLY_LOW) && QUERY_FLAG(tmp, FLAG_NO_PICK)) break;
2048     }
2049     for(;tmp!=NULL; tmp=tmp->below) {
2050     if (tmp == op) continue; /* Can't apply yourself */
2051    
2052     /* Check to see if one of the movement types should be slowed down.
2053     * Second check makes sure that the movement types not being slowed
2054     * (~slow_move) is not blocked on this space - just because the
2055     * space doesn't slow down swimming (for example), if you can't actually
2056     * swim on that space, can't use it to avoid the penalty.
2057     */
2058     if (!QUERY_FLAG(op, FLAG_WIZPASS)) {
2059     if ((!op->move_type && tmp->move_slow & MOVE_WALK) ||
2060     ((op->move_type & tmp->move_slow) &&
2061     (op->move_type & ~tmp->move_slow & ~tmp->move_block) == 0)) {
2062    
2063     float diff;
2064    
2065     diff = tmp->move_slow_penalty*FABS(op->speed);
2066     if (op->type == PLAYER) {
2067     if ((QUERY_FLAG(tmp, FLAG_IS_HILLY) && find_skill_by_number(op, SK_CLIMBING)) ||
2068     (QUERY_FLAG(tmp, FLAG_IS_WOODED) && find_skill_by_number(op, SK_WOODSMAN))) {
2069     diff /= 4.0;
2070     }
2071     }
2072     op->speed_left -= diff;
2073     }
2074     }
2075    
2076     /* Basically same logic as above, except now for actual apply. */
2077     if ((!op->move_type && tmp->move_on & MOVE_WALK) ||
2078     ((op->move_type & tmp->move_on) &&
2079     (op->move_type & ~tmp->move_on & ~tmp->move_block)==0)) {
2080    
2081     move_apply(tmp, op, originator);
2082     if (was_destroyed (op, tag))
2083     return 1;
2084    
2085     /* what the person/creature stepped onto has moved the object
2086     * someplace new. Don't process any further - if we did,
2087     * have a feeling strange problems would result.
2088     */
2089     if (op->map != m || op->x != x || op->y != y) return 0;
2090     }
2091     }
2092     return 0;
2093     }
2094    
2095     /*
2096     * present_arch(arch, map, x, y) searches for any objects with
2097     * a matching archetype at the given map and coordinates.
2098     * The first matching object is returned, or NULL if none.
2099     */
2100    
2101 elmex 1.3 object *present_arch(const archetype *at, mapstruct *m, int x, int y) {
2102 root 1.1 object *tmp;
2103     if(m==NULL || out_of_map(m,x,y)) {
2104     LOG(llevError,"Present_arch called outside map.\n");
2105     return NULL;
2106     }
2107     for(tmp=GET_MAP_OB(m,x,y); tmp != NULL; tmp = tmp->above)
2108     if(tmp->arch == at)
2109     return tmp;
2110     return NULL;
2111     }
2112    
2113     /*
2114     * present(type, map, x, y) searches for any objects with
2115     * a matching type variable at the given map and coordinates.
2116     * The first matching object is returned, or NULL if none.
2117     */
2118    
2119     object *present(unsigned char type,mapstruct *m, int x,int y) {
2120     object *tmp;
2121     if(out_of_map(m,x,y)) {
2122     LOG(llevError,"Present called outside map.\n");
2123     return NULL;
2124     }
2125     for(tmp=GET_MAP_OB(m,x,y);tmp!=NULL;tmp=tmp->above)
2126     if(tmp->type==type)
2127     return tmp;
2128     return NULL;
2129     }
2130    
2131     /*
2132     * present_in_ob(type, object) searches for any objects with
2133     * a matching type variable in the inventory of the given object.
2134     * The first matching object is returned, or NULL if none.
2135     */
2136    
2137 elmex 1.3 object *present_in_ob(unsigned char type, const object *op) {
2138 root 1.1 object *tmp;
2139     for(tmp=op->inv;tmp!=NULL;tmp=tmp->below)
2140     if(tmp->type==type)
2141     return tmp;
2142     return NULL;
2143     }
2144    
2145     /*
2146     * present_in_ob (type, str, object) searches for any objects with
2147     * a matching type & name variable in the inventory of the given object.
2148     * The first matching object is returned, or NULL if none.
2149     * This is mostly used by spell effect code, so that we only
2150     * have one spell effect at a time.
2151     * type can be used to narrow the search - if type is set,
2152     * the type must also match. -1 can be passed for the type,
2153     * in which case the type does not need to pass.
2154     * str is the string to match against. Note that we match against
2155     * the object name, not the archetype name. this is so that the
2156     * spell code can use one object type (force), but change it's name
2157     * to be unique.
2158     */
2159    
2160 elmex 1.3 object *present_in_ob_by_name(int type, const char *str, const object *op) {
2161 root 1.1 object *tmp;
2162    
2163     for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) {
2164     if ((type==-1 || tmp->type==type) && (!strcmp(str, tmp->name)))
2165     return tmp;
2166     }
2167     return NULL;
2168     }
2169    
2170     /*
2171     * present_arch_in_ob(archetype, object) searches for any objects with
2172     * a matching archetype in the inventory of the given object.
2173     * The first matching object is returned, or NULL if none.
2174     */
2175    
2176 elmex 1.3 object *present_arch_in_ob(const archetype *at, const object *op) {
2177 root 1.1 object *tmp;
2178     for(tmp=op->inv;tmp!=NULL;tmp=tmp->below)
2179     if( tmp->arch == at)
2180     return tmp;
2181     return NULL;
2182     }
2183    
2184     /*
2185     * activate recursively a flag on an object inventory
2186     */
2187     void flag_inv(object*op, int flag){
2188     object *tmp;
2189     if(op->inv)
2190     for(tmp = op->inv; tmp != NULL; tmp = tmp->below){
2191     SET_FLAG(tmp, flag);
2192     flag_inv(tmp,flag);
2193     }
2194     }/*
2195     * desactivate recursively a flag on an object inventory
2196     */
2197     void unflag_inv(object*op, int flag){
2198     object *tmp;
2199     if(op->inv)
2200     for(tmp = op->inv; tmp != NULL; tmp = tmp->below){
2201     CLEAR_FLAG(tmp, flag);
2202     unflag_inv(tmp,flag);
2203     }
2204     }
2205    
2206     /*
2207     * set_cheat(object) sets the cheat flag (WAS_WIZ) in the object and in
2208     * all it's inventory (recursively).
2209     * If checksums are used, a player will get set_cheat called for
2210     * him/her-self and all object carried by a call to this function.
2211     */
2212    
2213     void set_cheat(object *op) {
2214     SET_FLAG(op, FLAG_WAS_WIZ);
2215     flag_inv(op, FLAG_WAS_WIZ);
2216     }
2217    
2218     /*
2219     * find_free_spot(object, map, x, y, start, stop) will search for
2220     * a spot at the given map and coordinates which will be able to contain
2221     * the given object. start and stop specifies how many squares
2222     * to search (see the freearr_x/y[] definition).
2223     * It returns a random choice among the alternatives found.
2224     * start and stop are where to start relative to the free_arr array (1,9
2225     * does all 4 immediate directions). This returns the index into the
2226     * array of the free spot, -1 if no spot available (dir 0 = x,y)
2227     * Note - this only checks to see if there is space for the head of the
2228     * object - if it is a multispace object, this should be called for all
2229     * pieces.
2230     * Note2: This function does correctly handle tiled maps, but does not
2231     * inform the caller. However, insert_ob_in_map will update as
2232     * necessary, so the caller shouldn't need to do any special work.
2233     * Note - updated to take an object instead of archetype - this is necessary
2234     * because arch_blocked (now ob_blocked) needs to know the movement type
2235     * to know if the space in question will block the object. We can't use
2236     * the archetype because that isn't correct if the monster has been
2237     * customized, changed states, etc.
2238     */
2239    
2240 elmex 1.3 int find_free_spot(const object *ob, mapstruct *m,int x,int y,int start,int stop) {
2241 root 1.1 int i,index=0, flag;
2242     static int altern[SIZEOFFREE];
2243    
2244     for(i=start;i<stop;i++) {
2245     flag = ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]);
2246     if(!flag)
2247     altern[index++]=i;
2248    
2249     /* Basically, if we find a wall on a space, we cut down the search size.
2250     * In this way, we won't return spaces that are on another side of a wall.
2251     * This mostly work, but it cuts down the search size in all directions -
2252     * if the space being examined only has a wall to the north and empty
2253     * spaces in all the other directions, this will reduce the search space
2254     * to only the spaces immediately surrounding the target area, and
2255     * won't look 2 spaces south of the target space.
2256     */
2257     else if ((flag & AB_NO_PASS) && maxfree[i]<stop)
2258     stop=maxfree[i];
2259     }
2260     if(!index) return -1;
2261     return altern[RANDOM()%index];
2262     }
2263    
2264     /*
2265     * find_first_free_spot(archetype, mapstruct, x, y) works like
2266     * find_free_spot(), but it will search max number of squares.
2267     * But it will return the first available spot, not a random choice.
2268     * Changed 0.93.2: Have it return -1 if there is no free spot available.
2269     */
2270    
2271 elmex 1.3 int find_first_free_spot(const object *ob, mapstruct *m,int x,int y) {
2272 root 1.1 int i;
2273     for(i=0;i<SIZEOFFREE;i++) {
2274     if(!ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]))
2275     return i;
2276     }
2277     return -1;
2278     }
2279    
2280     /*
2281     * The function permute(arr, begin, end) randomly reorders the array
2282     * arr[begin..end-1].
2283     */
2284     static void permute(int *arr, int begin, int end)
2285     {
2286     int i, j, tmp, len;
2287    
2288     len = end-begin;
2289     for(i = begin; i < end; i++)
2290     {
2291     j = begin+RANDOM()%len;
2292    
2293     tmp = arr[i];
2294     arr[i] = arr[j];
2295     arr[j] = tmp;
2296     }
2297     }
2298    
2299     /* new function to make monster searching more efficient, and effective!
2300     * This basically returns a randomized array (in the passed pointer) of
2301     * the spaces to find monsters. In this way, it won't always look for
2302     * monsters to the north first. However, the size of the array passed
2303     * covers all the spaces, so within that size, all the spaces within
2304     * the 3x3 area will be searched, just not in a predictable order.
2305     */
2306     void get_search_arr(int *search_arr)
2307     {
2308     int i;
2309    
2310     for(i = 0; i < SIZEOFFREE; i++)
2311     {
2312     search_arr[i] = i;
2313     }
2314    
2315     permute(search_arr, 1, SIZEOFFREE1+1);
2316     permute(search_arr, SIZEOFFREE1+1, SIZEOFFREE2+1);
2317     permute(search_arr, SIZEOFFREE2+1, SIZEOFFREE);
2318     }
2319    
2320     /*
2321     * find_dir(map, x, y, exclude) will search some close squares in the
2322     * given map at the given coordinates for live objects.
2323     * It will not considered the object given as exclude among possible
2324     * live objects.
2325     * It returns the direction toward the first/closest live object if finds
2326     * any, otherwise 0.
2327     * Perhaps incorrectly, but I'm making the assumption that exclude
2328     * is actually want is going to try and move there. We need this info
2329     * because we have to know what movement the thing looking to move
2330     * there is capable of.
2331     */
2332    
2333     int find_dir(mapstruct *m, int x, int y, object *exclude) {
2334     int i,max=SIZEOFFREE, mflags;
2335     sint16 nx, ny;
2336     object *tmp;
2337     mapstruct *mp;
2338     MoveType blocked, move_type;
2339    
2340     if (exclude && exclude->head) {
2341     exclude = exclude->head;
2342     move_type = exclude->move_type;
2343     } else {
2344     /* If we don't have anything, presume it can use all movement types. */
2345     move_type=MOVE_ALL;
2346     }
2347    
2348     for(i=1;i<max;i++) {
2349     mp = m;
2350     nx = x + freearr_x[i];
2351     ny = y + freearr_y[i];
2352    
2353     mflags = get_map_flags(m, &mp, nx, ny, &nx, &ny);
2354     if (mflags & P_OUT_OF_MAP) {
2355     max = maxfree[i];
2356     } else {
2357     blocked = GET_MAP_MOVE_BLOCK(mp, nx, ny);
2358    
2359     if ((move_type & blocked) == move_type) {
2360     max=maxfree[i];
2361     } else if (mflags & P_IS_ALIVE) {
2362     for (tmp=GET_MAP_OB(mp,nx,ny); tmp!= NULL; tmp=tmp->above) {
2363     if ((QUERY_FLAG(tmp,FLAG_MONSTER) || tmp->type==PLAYER) &&
2364     (tmp != exclude ||(tmp->head && tmp->head != exclude))) {
2365     break;
2366     }
2367     }
2368     if(tmp) {
2369     return freedir[i];
2370     }
2371     }
2372     }
2373     }
2374     return 0;
2375     }
2376    
2377     /*
2378     * distance(object 1, object 2) will return the square of the
2379     * distance between the two given objects.
2380     */
2381    
2382 elmex 1.3 int distance(const object *ob1, const object *ob2) {
2383 root 1.1 int i;
2384     i= (ob1->x - ob2->x)*(ob1->x - ob2->x)+
2385     (ob1->y - ob2->y)*(ob1->y - ob2->y);
2386     return i;
2387     }
2388    
2389     /*
2390     * find_dir_2(delta-x,delta-y) will return a direction in which
2391     * an object which has subtracted the x and y coordinates of another
2392     * object, needs to travel toward it.
2393     */
2394    
2395     int find_dir_2(int x, int y) {
2396     int q;
2397     if(!y)
2398     q= -300*x;
2399     else
2400     q=x*100/y;
2401     if(y>0) {
2402     if(q < -242)
2403     return 3 ;
2404     if (q < -41)
2405     return 2 ;
2406     if (q < 41)
2407     return 1 ;
2408     if (q < 242)
2409     return 8 ;
2410     return 7 ;
2411     }
2412     if (q < -242)
2413     return 7 ;
2414     if (q < -41)
2415     return 6 ;
2416     if (q < 41)
2417     return 5 ;
2418     if (q < 242)
2419     return 4 ;
2420     return 3 ;
2421     }
2422    
2423     /*
2424     * absdir(int): Returns a number between 1 and 8, which represent
2425     * the "absolute" direction of a number (it actually takes care of
2426     * "overflow" in previous calculations of a direction).
2427     */
2428    
2429     int absdir(int d) {
2430     while(d<1) d+=8;
2431     while(d>8) d-=8;
2432     return d;
2433     }
2434    
2435     /*
2436     * dirdiff(dir1, dir2) returns how many 45-degrees differences there is
2437     * between two directions (which are expected to be absolute (see absdir())
2438     */
2439    
2440     int dirdiff(int dir1, int dir2) {
2441     int d;
2442     d = abs(dir1 - dir2);
2443     if(d>4)
2444     d = 8 - d;
2445     return d;
2446     }
2447    
2448     /* peterm:
2449     * do LOS stuff for ball lightning. Go after the closest VISIBLE monster.
2450     * Basically, this is a table of directions, and what directions
2451     * one could go to go back to us. Eg, entry 15 below is 4, 14, 16.
2452     * This basically means that if direction is 15, then it could either go
2453     * direction 4, 14, or 16 to get back to where we are.
2454     * Moved from spell_util.c to object.c with the other related direction
2455     * functions.
2456     */
2457    
2458     int reduction_dir[SIZEOFFREE][3] = {
2459     {0,0,0}, /* 0 */
2460     {0,0,0}, /* 1 */
2461     {0,0,0}, /* 2 */
2462     {0,0,0}, /* 3 */
2463     {0,0,0}, /* 4 */
2464     {0,0,0}, /* 5 */
2465     {0,0,0}, /* 6 */
2466     {0,0,0}, /* 7 */
2467     {0,0,0}, /* 8 */
2468     {8,1,2}, /* 9 */
2469     {1,2,-1}, /* 10 */
2470     {2,10,12}, /* 11 */
2471     {2,3,-1}, /* 12 */
2472     {2,3,4}, /* 13 */
2473     {3,4,-1}, /* 14 */
2474     {4,14,16}, /* 15 */
2475     {5,4,-1}, /* 16 */
2476     {4,5,6}, /* 17 */
2477     {6,5,-1}, /* 18 */
2478     {6,20,18}, /* 19 */
2479     {7,6,-1}, /* 20 */
2480     {6,7,8}, /* 21 */
2481     {7,8,-1}, /* 22 */
2482     {8,22,24}, /* 23 */
2483     {8,1,-1}, /* 24 */
2484     {24,9,10}, /* 25 */
2485     {9,10,-1}, /* 26 */
2486     {10,11,-1}, /* 27 */
2487     {27,11,29}, /* 28 */
2488     {11,12,-1}, /* 29 */
2489     {12,13,-1}, /* 30 */
2490     {12,13,14}, /* 31 */
2491     {13,14,-1}, /* 32 */
2492     {14,15,-1}, /* 33 */
2493     {33,15,35}, /* 34 */
2494     {16,15,-1}, /* 35 */
2495     {17,16,-1}, /* 36 */
2496     {18,17,16}, /* 37 */
2497     {18,17,-1}, /* 38 */
2498     {18,19,-1}, /* 39 */
2499     {41,19,39}, /* 40 */
2500     {19,20,-1}, /* 41 */
2501     {20,21,-1}, /* 42 */
2502     {20,21,22}, /* 43 */
2503     {21,22,-1}, /* 44 */
2504     {23,22,-1}, /* 45 */
2505     {45,47,23}, /* 46 */
2506     {23,24,-1}, /* 47 */
2507     {24,9,-1}}; /* 48 */
2508    
2509     /* Recursive routine to step back and see if we can
2510     * find a path to that monster that we found. If not,
2511     * we don't bother going toward it. Returns 1 if we
2512     * can see a direct way to get it
2513     * Modified to be map tile aware -.MSW
2514     */
2515    
2516    
2517     int can_see_monsterP(mapstruct *m, int x, int y,int dir) {
2518     sint16 dx, dy;
2519     int mflags;
2520    
2521     if(dir<0) return 0; /* exit condition: invalid direction */
2522    
2523     dx = x + freearr_x[dir];
2524     dy = y + freearr_y[dir];
2525    
2526     mflags = get_map_flags(m, &m, dx, dy, &dx, &dy);
2527    
2528     /* This functional arguably was incorrect before - it was
2529     * checking for P_WALL - that was basically seeing if
2530     * we could move to the monster - this is being more
2531     * literal on if we can see it. To know if we can actually
2532     * move to the monster, we'd need the monster passed in or
2533     * at least its move type.
2534     */
2535     if (mflags & (P_OUT_OF_MAP | P_BLOCKSVIEW)) return 0;
2536    
2537     /* yes, can see. */
2538     if(dir < 9) return 1;
2539     return can_see_monsterP(m, x, y, reduction_dir[dir][0]) |
2540     can_see_monsterP(m,x,y, reduction_dir[dir][1]) |
2541     can_see_monsterP(m,x,y, reduction_dir[dir][2]);
2542     }
2543    
2544    
2545    
2546     /*
2547     * can_pick(picker, item): finds out if an object is possible to be
2548     * picked up by the picker. Returnes 1 if it can be
2549     * picked up, otherwise 0.
2550     *
2551     * Cf 0.91.3 - don't let WIZ's pick up anything - will likely cause
2552     * core dumps if they do.
2553     *
2554     * Add a check so we can't pick up invisible objects (0.93.8)
2555     */
2556    
2557 elmex 1.3 int can_pick(const object *who, const object *item) {
2558 root 1.1 return /*QUERY_FLAG(who,FLAG_WIZ)||*/
2559     (item->weight>0&&!QUERY_FLAG(item,FLAG_NO_PICK)&&
2560     !QUERY_FLAG(item,FLAG_ALIVE)&&!item->invisible &&
2561     (who->type==PLAYER||item->weight<who->weight/3));
2562     }
2563    
2564    
2565     /*
2566     * create clone from object to another
2567     */
2568     object *object_create_clone (object *asrc) {
2569     object *dst = NULL,*tmp,*src,*part,*prev, *item;
2570    
2571     if(!asrc) return NULL;
2572     src = asrc;
2573     if(src->head)
2574     src = src->head;
2575    
2576     prev = NULL;
2577     for(part = src; part; part = part->more) {
2578     tmp = get_object();
2579     copy_object(part,tmp);
2580     tmp->x -= src->x;
2581     tmp->y -= src->y;
2582     if(!part->head) {
2583     dst = tmp;
2584     tmp->head = NULL;
2585     } else {
2586     tmp->head = dst;
2587     }
2588     tmp->more = NULL;
2589     if(prev)
2590     prev->more = tmp;
2591     prev = tmp;
2592     }
2593     /*** copy inventory ***/
2594     for(item = src->inv; item; item = item->below) {
2595     (void) insert_ob_in_ob(object_create_clone(item),dst);
2596     }
2597    
2598     return dst;
2599     }
2600    
2601     /* return true if the object was destroyed, 0 otherwise */
2602 elmex 1.3 int was_destroyed (const object *op, tag_t old_tag)
2603 root 1.1 {
2604     /* checking for FLAG_FREED isn't necessary, but makes this function more
2605     * robust */
2606     return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED);
2607     }
2608    
2609     /* GROS - Creates an object using a string representing its content. */
2610     /* Basically, we save the content of the string to a temp file, then call */
2611     /* load_object on it. I admit it is a highly inefficient way to make things, */
2612     /* but it was simple to make and allows reusing the load_object function. */
2613     /* Remember not to use load_object_str in a time-critical situation. */
2614     /* Also remember that multiparts objects are not supported for now. */
2615    
2616 elmex 1.3 object* load_object_str(const char *obstr)
2617 root 1.1 {
2618     object *op;
2619     FILE *tempfile;
2620     char filename[MAX_BUF];
2621     sprintf(filename,"%s/cfloadobstr2044",settings.tmpdir);
2622     tempfile=fopen(filename,"w");
2623     if (tempfile == NULL)
2624     {
2625     LOG(llevError,"Error - Unable to access load object temp file\n");
2626     return NULL;
2627     };
2628     fprintf(tempfile,obstr);
2629     fclose(tempfile);
2630    
2631     op=get_object();
2632    
2633     tempfile=fopen(filename,"r");
2634     if (tempfile == NULL)
2635     {
2636     LOG(llevError,"Error - Unable to read object temp file\n");
2637     return NULL;
2638     };
2639     load_object(tempfile,op,LO_NEWFILE,0);
2640     LOG(llevDebug," load str completed, object=%s\n",op->name);
2641     CLEAR_FLAG(op,FLAG_REMOVED);
2642     fclose(tempfile);
2643     return op;
2644     }
2645    
2646     /* This returns the first object in who's inventory that
2647     * has the same type and subtype match.
2648     * returns NULL if no match.
2649     */
2650 elmex 1.3 object *find_obj_by_type_subtype(const object *who, int type, int subtype)
2651 root 1.1 {
2652     object *tmp;
2653    
2654     for (tmp=who->inv; tmp; tmp=tmp->below)
2655     if (tmp->type == type && tmp->subtype == subtype) return tmp;
2656    
2657     return NULL;
2658     }
2659    
2660     /* If ob has a field named key, return the link from the list,
2661     * otherwise return NULL.
2662     *
2663     * key must be a passed in shared string - otherwise, this won't
2664     * do the desired thing.
2665     */
2666 elmex 1.3 key_value * get_ob_key_link(const object * ob, const char * key) {
2667 root 1.1 key_value * link;
2668    
2669     for (link = ob->key_values; link != NULL; link = link->next) {
2670     if (link->key == key) {
2671     return link;
2672     }
2673     }
2674    
2675     return NULL;
2676     }
2677    
2678     /*
2679     * Returns the value of op has an extra_field for key, or NULL.
2680     *
2681     * The argument doesn't need to be a shared string.
2682     *
2683     * The returned string is shared.
2684     */
2685 elmex 1.3 const char * get_ob_key_value(const object * op, const char * const key) {
2686 root 1.1 key_value * link;
2687     const char * canonical_key;
2688    
2689     canonical_key = find_string(key);
2690    
2691     if (canonical_key == NULL) {
2692     /* 1. There being a field named key on any object
2693     * implies there'd be a shared string to find.
2694     * 2. Since there isn't, no object has this field.
2695     * 3. Therefore, *this* object doesn't have this field.
2696     */
2697     return NULL;
2698     }
2699    
2700     /* This is copied from get_ob_key_link() above -
2701     * only 4 lines, and saves the function call overhead.
2702     */
2703     for (link = op->key_values; link != NULL; link = link->next) {
2704     if (link->key == canonical_key) {
2705     return link->value;
2706     }
2707     }
2708     return NULL;
2709     }
2710    
2711    
2712     /*
2713     * Updates the canonical_key in op to value.
2714     *
2715     * canonical_key is a shared string (value doesn't have to be).
2716     *
2717     * Unless add_key is TRUE, it won't add fields, only change the value of existing
2718     * keys.
2719     *
2720     * Returns TRUE on success.
2721     */
2722     int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) {
2723     key_value * field = NULL, *last=NULL;
2724    
2725     for (field=op->key_values; field != NULL; field=field->next) {
2726     if (field->key != canonical_key) {
2727     last = field;
2728     continue;
2729     }
2730    
2731     if (field->value) FREE_AND_CLEAR_STR(field->value);
2732     if (value)
2733     field->value = add_string(value);
2734     else {
2735     /* Basically, if the archetype has this key set,
2736     * we need to store the null value so when we save
2737     * it, we save the empty value so that when we load,
2738     * we get this value back again.
2739     */
2740     if (get_ob_key_link(&op->arch->clone, canonical_key))
2741     field->value = NULL;
2742     else {
2743     /* Delete this link */
2744     if (field->key) FREE_AND_CLEAR_STR(field->key);
2745     if (field->value) FREE_AND_CLEAR_STR(field->value);
2746     if (last) last->next = field->next;
2747     else op->key_values = field->next;
2748     free(field);
2749     }
2750     }
2751     return TRUE;
2752     }
2753     /* IF we get here, key doesn't exist */
2754    
2755     /* No field, we'll have to add it. */
2756    
2757     if (!add_key) {
2758     return FALSE;
2759     }
2760     /* There isn't any good reason to store a null
2761     * value in the key/value list. If the archetype has
2762     * this key, then we should also have it, so shouldn't
2763     * be here. If user wants to store empty strings,
2764     * should pass in ""
2765     */
2766     if (value == NULL) return TRUE;
2767    
2768     field = malloc(sizeof(key_value));
2769    
2770     field->key = add_refcount(canonical_key);
2771     field->value = add_string(value);
2772     /* Usual prepend-addition. */
2773     field->next = op->key_values;
2774     op->key_values = field;
2775    
2776     return TRUE;
2777     }
2778    
2779     /*
2780     * Updates the key in op to value.
2781     *
2782     * If add_key is FALSE, this will only update existing keys,
2783     * and not add new ones.
2784     * In general, should be little reason FALSE is ever passed in for add_key
2785     *
2786     * Returns TRUE on success.
2787     */
2788     int set_ob_key_value(object * op, const char * key, const char * value, int add_key) {
2789     const char * canonical_key = NULL;
2790     int floating_ref = FALSE;
2791     int ret;
2792    
2793     /* HACK This mess is to make sure set_ob_value() passes a shared string
2794     * to get_ob_key_link(), without leaving a leaked refcount.
2795     */
2796    
2797     canonical_key = find_string(key);
2798     if (canonical_key == NULL) {
2799     canonical_key = add_string(key);
2800     floating_ref = TRUE;
2801     }
2802    
2803     ret = set_ob_key_value_s(op, canonical_key, value, add_key);
2804    
2805     if (floating_ref) {
2806     free_string(canonical_key);
2807     }
2808    
2809     return ret;
2810     }