ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
(Generate patch)

Comparing deliantra/server/common/object.C (file contents):
Revision 1.30 by root, Mon Sep 11 20:28:37 2006 UTC vs.
Revision 1.47 by root, Thu Sep 14 22:33:59 2006 UTC

1
2/* 1/*
3 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
4 3
5 Copyright (C) 2001 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2001 Mark Wedel & Crossfire Development Team
6 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
17 16
18 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 20
22 The authors can be reached via e-mail at crossfire-devel@real-time.com 21 The authors can be reached via e-mail at <crossfire@schmorp.de>
23*/ 22*/
24 23
25/* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects. 24/* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects.
26 sub/add_weight will transcend the environment updating the carrying 25 sub/add_weight will transcend the environment updating the carrying
27 variable. */ 26 variable. */
29#include <stdio.h> 28#include <stdio.h>
30#include <sys/types.h> 29#include <sys/types.h>
31#include <sys/uio.h> 30#include <sys/uio.h>
32#include <object.h> 31#include <object.h>
33#include <funcpoint.h> 32#include <funcpoint.h>
34#include <skills.h>
35#include <loader.h> 33#include <loader.h>
36 34
37int nrofallocobjects = 0; 35int nrofallocobjects = 0;
36static UUID uuid;
37const uint64 UUID_SKIP = 1<<19;
38 38
39object *objects; /* Pointer to the list of used objects */
40object *active_objects; /* List of active objects that need to be processed */ 39object *active_objects; /* List of active objects that need to be processed */
41 40
42short freearr_x[SIZEOFFREE] = { 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, 41short freearr_x[SIZEOFFREE] = { 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,
43 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -3, -3, -3, -3, -2, -1 42 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -3, -3, -3, -3, -2, -1
44}; 43};
50}; 49};
51int freedir[SIZEOFFREE] = { 50int freedir[SIZEOFFREE] = {
52 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, 51 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,
53 1, 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8 52 1, 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8
54}; 53};
54
55static void
56write_uuid (void)
57{
58 char filename1[MAX_BUF], filename2[MAX_BUF];
59
60 sprintf (filename1, "%s/uuid", settings.localdir);
61 sprintf (filename2, "%s/uuid~", settings.localdir);
62
63 FILE *fp;
64
65 if (!(fp = fopen (filename2, "w")))
66 {
67 LOG (llevError, "ERROR: cannot open %s for writing, unable to write UUID!\n", filename2);
68 return;
69 }
70
71 fprintf (fp, "<1,%llx>\n", (unsigned long long)uuid.seq + UUID_SKIP * 2);
72 fclose (fp);
73 rename (filename2, filename1);
74}
75
76static void
77read_uuid (void)
78{
79 char filename[MAX_BUF];
80
81 sprintf (filename, "%s/uuid", settings.localdir);
82
83 FILE *fp;
84
85 if (!(fp = fopen (filename, "r")))
86 {
87 if (errno == ENOENT)
88 {
89 LOG (llevInfo, "RESET uid to 1\n");
90 uuid.seq = 0;
91 write_uuid ();
92 return;
93 }
94
95 LOG (llevError, "FATAL: cannot open %s for reading!\n", filename);
96 _exit (1);
97 }
98
99 int version;
100 unsigned long long uid;
101 if (2 != fscanf (fp, "<%d,%llx>\n", &version, &uid) || version != 1)
102 {
103 LOG (llevError, "FATAL: error reading uid from %s!\n", filename);
104 _exit (1);
105 }
106
107 uuid.seq = uid;
108 write_uuid ();
109 LOG (llevDebug, "read UID: %lld\n", uid);
110 fclose (fp);
111}
112
113UUID
114gen_uuid ()
115{
116 UUID uid;
117
118 uid.seq = ++uuid.seq;
119
120 if (!(uuid.seq & (UUID_SKIP - 1)))
121 write_uuid ();
122
123 return uid;
124}
125
126void
127init_uuid ()
128{
129 read_uuid ();
130}
55 131
56/* Returns TRUE if every key_values in wants has a partner with the same value in has. */ 132/* Returns TRUE if every key_values in wants has a partner with the same value in has. */
57static int 133static int
58compare_ob_value_lists_one (const object *wants, const object *has) 134compare_ob_value_lists_one (const object *wants, const object *has)
59{ 135{
255 { 331 {
256 if (inv->inv) 332 if (inv->inv)
257 sum_weight (inv); 333 sum_weight (inv);
258 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1); 334 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1);
259 } 335 }
336
260 if (op->type == CONTAINER && op->stats.Str) 337 if (op->type == CONTAINER && op->stats.Str)
261 sum = (sum * (100 - op->stats.Str)) / 100; 338 sum = (sum * (100 - op->stats.Str)) / 100;
339
262 if (op->carrying != sum) 340 if (op->carrying != sum)
263 op->carrying = sum; 341 op->carrying = sum;
342
264 return sum; 343 return sum;
265} 344}
266 345
267/** 346/**
268 * Return the outermost environment object for a given object. 347 * Return the outermost environment object for a given object.
366void 445void
367dump_all_objects (void) 446dump_all_objects (void)
368{ 447{
369 object *op; 448 object *op;
370 449
371 for (op = objects; op != NULL; op = op->next) 450 for (op = object::first; op != NULL; op = op->next)
372 { 451 {
373 dump_object (op); 452 dump_object (op);
374 fprintf (logfile, "Object %d\n:%s\n", op->count, errmsg); 453 fprintf (logfile, "Object %d\n:%s\n", op->count, errmsg);
375 } 454 }
376} 455}
402object * 481object *
403find_object (tag_t i) 482find_object (tag_t i)
404{ 483{
405 object *op; 484 object *op;
406 485
407 for (op = objects; op != NULL; op = op->next) 486 for (op = object::first; op != NULL; op = op->next)
408 if (op->count == i) 487 if (op->count == i)
409 break; 488 break;
410 return op; 489 return op;
411} 490}
412 491
417 */ 496 */
418 497
419object * 498object *
420find_object_name (const char *str) 499find_object_name (const char *str)
421{ 500{
422 const char *name = shstr::find (str); 501 shstr_cmp str_ (str);
423 object *op; 502 object *op;
424 503
425 for (op = objects; op != NULL; op = op->next) 504 for (op = object::first; op != NULL; op = op->next)
426 if (&op->name == name) 505 if (op->name == str_)
427 break; 506 break;
428 507
429 return op; 508 return op;
430} 509}
431 510
432void 511void
433free_all_object_data () 512free_all_object_data ()
434{ 513{
435 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects); 514 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects);
436}
437
438/*
439 * Returns the object which this object marks as being the owner.
440 * A id-scheme is used to avoid pointing to objects which have been
441 * freed and are now reused. If this is detected, the owner is
442 * set to NULL, and NULL is returned.
443 * Changed 2004-02-12 - if the player is setting at the play again
444 * prompt, he is removed, and we don't want to treat him as an owner of
445 * anything, so check removed flag. I don't expect that this should break
446 * anything - once an object is removed, it is basically dead anyways.
447 */
448object *
449object::get_owner ()
450{
451 if (!owner
452 || QUERY_FLAG (owner, FLAG_FREED)
453 || QUERY_FLAG (owner, FLAG_REMOVED))
454 owner = 0;
455
456 return owner;
457} 515}
458 516
459/* 517/*
460 * Sets the owner and sets the skill and exp pointers to owner's current 518 * Sets the owner and sets the skill and exp pointers to owner's current
461 * skill and experience objects. 519 * skill and experience objects.
531 589
532 /* What is not cleared is next, prev, and count */ 590 /* What is not cleared is next, prev, and count */
533 591
534 expmul = 1.0; 592 expmul = 1.0;
535 face = blank_face; 593 face = blank_face;
536 attacked_by_count = -1;
537 594
538 if (settings.casting_time) 595 if (settings.casting_time)
539 casting_time = -1; 596 casting_time = -1;
540} 597}
541 598
623/* 680/*
624 * Updates the speed of an object. If the speed changes from 0 to another 681 * Updates the speed of an object. If the speed changes from 0 to another
625 * value, or vice versa, then add/remove the object from the active list. 682 * value, or vice versa, then add/remove the object from the active list.
626 * This function needs to be called whenever the speed of an object changes. 683 * This function needs to be called whenever the speed of an object changes.
627 */ 684 */
628
629void 685void
630update_ob_speed (object *op) 686update_ob_speed (object *op)
631{ 687{
632 extern int arch_init; 688 extern int arch_init;
633 689
642 abort (); 698 abort ();
643#else 699#else
644 op->speed = 0; 700 op->speed = 0;
645#endif 701#endif
646 } 702 }
703
647 if (arch_init) 704 if (arch_init)
648 {
649 return; 705 return;
650 } 706
651 if (FABS (op->speed) > MIN_ACTIVE_SPEED) 707 if (FABS (op->speed) > MIN_ACTIVE_SPEED)
652 { 708 {
653 /* If already on active list, don't do anything */ 709 /* If already on active list, don't do anything */
654 if (op->active_next || op->active_prev || op == active_objects) 710 if (op->active_next || op->active_prev || op == active_objects)
655 return; 711 return;
656 712
657 /* process_events() expects us to insert the object at the beginning 713 /* process_events() expects us to insert the object at the beginning
658 * of the list. */ 714 * of the list. */
659 op->active_next = active_objects; 715 op->active_next = active_objects;
716
660 if (op->active_next != NULL) 717 if (op->active_next != NULL)
661 op->active_next->active_prev = op; 718 op->active_next->active_prev = op;
719
662 active_objects = op; 720 active_objects = op;
663 } 721 }
664 else 722 else
665 { 723 {
666 /* If not on the active list, nothing needs to be done */ 724 /* If not on the active list, nothing needs to be done */
668 return; 726 return;
669 727
670 if (op->active_prev == NULL) 728 if (op->active_prev == NULL)
671 { 729 {
672 active_objects = op->active_next; 730 active_objects = op->active_next;
731
673 if (op->active_next != NULL) 732 if (op->active_next != NULL)
674 op->active_next->active_prev = NULL; 733 op->active_next->active_prev = NULL;
675 } 734 }
676 else 735 else
677 { 736 {
678 op->active_prev->active_next = op->active_next; 737 op->active_prev->active_next = op->active_next;
738
679 if (op->active_next) 739 if (op->active_next)
680 op->active_next->active_prev = op->active_prev; 740 op->active_next->active_prev = op->active_prev;
681 } 741 }
742
682 op->active_next = NULL; 743 op->active_next = NULL;
683 op->active_prev = NULL; 744 op->active_prev = NULL;
684 } 745 }
685} 746}
686 747
832 893
833 if (op->more != NULL) 894 if (op->more != NULL)
834 update_object (op->more, action); 895 update_object (op->more, action);
835} 896}
836 897
837static unordered_vector<object *> mortals; 898object::vector object::mortals;
838static std::vector<object *> freed; 899object::vector object::objects; // not yet used
900object *object::first;
839 901
840void object::free_mortals () 902void object::free_mortals ()
841{ 903{
842 for (unordered_vector<object *>::iterator i = mortals.begin (); i != mortals.end ();) 904 for (AUTODECL (i, mortals.begin ()); i != mortals.end ();)
843 if ((*i)->refcnt) 905 if ((*i)->refcnt)
844 ++i; // further delay freeing 906 ++i; // further delay freeing
845 else 907 else
846 { 908 {
847 freed.push_back (*i);//D
848 //delete *i; 909 delete *i;
849 mortals.erase (i); 910 mortals.erase (i);
850 } 911 }
851 912
913 static int lastmortals = 0;//D
914
852 if (mortals.size())//D 915 if (mortals.size() != lastmortals)//D
916 {
917 lastmortals = mortals.size ();//D
853 LOG (llevDebug, "%d objects in mortal queue\n", mortals.size());//D 918 LOG (llevDebug, "%d objects in mortal queue\n", lastmortals);//D
919 }
854} 920}
855 921
856object::object () 922object::object ()
857{ 923{
858 SET_FLAG (this, FLAG_REMOVED); 924 SET_FLAG (this, FLAG_REMOVED);
859 925
860 expmul = 1.0; 926 expmul = 1.0;
861 face = blank_face; 927 face = blank_face;
862 attacked_by_count = -1;
863} 928}
864 929
865object::~object () 930object::~object ()
866{ 931{
867 free_key_values (this); 932 free_key_values (this);
868} 933}
869 934
870void object::link () 935void object::link ()
871{ 936{
872 count = ++ob_count; 937 count = ++ob_count;
938 uuid = gen_uuid ();
873 939
874 prev = 0; 940 prev = 0;
875 next = objects; 941 next = object::first;
876 942
877 if (objects) 943 if (object::first)
878 objects->prev = this; 944 object::first->prev = this;
879 945
880 objects = this; 946 object::first = this;
881} 947}
882 948
883void object::unlink () 949void object::unlink ()
884{ 950{
885 count = 0; 951 //count = 0;//D
952 if (!prev && !next) return;//D
953
954 if (this == object::first)
955 object::first = next;
886 956
887 /* Remove this object from the list of used objects */ 957 /* Remove this object from the list of used objects */
888 if (prev)
889 {
890 prev->next = next; 958 if (prev) prev->next = next;
959 if (next) next->prev = prev;
960
891 prev = 0; 961 prev = 0;
892 }
893
894 if (next)
895 {
896 next->prev = prev;
897 next = 0; 962 next = 0;
898 }
899
900 if (this == objects)
901 objects = next;
902} 963}
903 964
904object *object::create () 965object *object::create ()
905{ 966{
906 object *
907 op;
908
909 if (freed.empty ())
910 op = new object; 967 object *op = new object;
911 else
912 {
913 // highly annoying, but the only way to get it stable right now
914 op = freed.back ();
915 freed.pop_back ();
916 op->~object ();
917 new ((void *) op) object;
918 }
919
920 op->link (); 968 op->link ();
921 return op; 969 return op;
922} 970}
923 971
924/* 972/*
934void object::free (bool free_inventory) 982void object::free (bool free_inventory)
935{ 983{
936 if (QUERY_FLAG (this, FLAG_FREED)) 984 if (QUERY_FLAG (this, FLAG_FREED))
937 return; 985 return;
938 986
987 if (QUERY_FLAG (this, FLAG_FRIENDLY))
988 remove_friendly_object (this);
989
939 if (!QUERY_FLAG (this, FLAG_REMOVED)) 990 if (!QUERY_FLAG (this, FLAG_REMOVED))
940 remove_ob (this); 991 remove_ob (this);
941
942 if (QUERY_FLAG (this, FLAG_FRIENDLY))
943 remove_friendly_object (this);
944 992
945 SET_FLAG (this, FLAG_FREED); 993 SET_FLAG (this, FLAG_FREED);
946 994
947 if (more) 995 if (more)
948 { 996 {
954 { 1002 {
955 /* Only if the space blocks everything do we not process - 1003 /* Only if the space blocks everything do we not process -
956 * if some form of movement is allowed, let objects 1004 * if some form of movement is allowed, let objects
957 * drop on that space. 1005 * drop on that space.
958 */ 1006 */
959 if (free_inventory || !map || map->in_memory != MAP_IN_MEMORY || (GET_MAP_MOVE_BLOCK (map, x, y) == MOVE_ALL)) 1007 if (free_inventory || !map || map->in_memory != MAP_IN_MEMORY || GET_MAP_MOVE_BLOCK (map, x, y) == MOVE_ALL)
960 { 1008 {
961 object *op = inv; 1009 object *op = inv;
962 1010
963 while (op) 1011 while (op)
964 { 1012 {
990 op = tmp; 1038 op = tmp;
991 } 1039 }
992 } 1040 }
993 } 1041 }
994 1042
1043 // clear those pointers that likely might have circular references to us
995 owner = 0; 1044 owner = 0;
1045 enemy = 0;
1046 attacked_by = 0;
996 1047
997 /* Remove object from the active list */ 1048 /* Remove object from the active list */
998 speed = 0; 1049 speed = 0;
999 update_ob_speed (this); 1050 update_ob_speed (this);
1000 1051
1012sub_weight (object *op, signed long weight) 1063sub_weight (object *op, signed long weight)
1013{ 1064{
1014 while (op != NULL) 1065 while (op != NULL)
1015 { 1066 {
1016 if (op->type == CONTAINER) 1067 if (op->type == CONTAINER)
1017 {
1018 weight = (signed long) (weight * (100 - op->stats.Str) / 100); 1068 weight = (signed long) (weight * (100 - op->stats.Str) / 100);
1019 } 1069
1020 op->carrying -= weight; 1070 op->carrying -= weight;
1021 op = op->env; 1071 op = op->env;
1022 } 1072 }
1023} 1073}
1024 1074
1032 */ 1082 */
1033 1083
1034void 1084void
1035remove_ob (object *op) 1085remove_ob (object *op)
1036{ 1086{
1087 object *tmp, *last = 0;
1037 object * 1088 object *otmp;
1038 tmp, *
1039 last = NULL;
1040 object *
1041 otmp;
1042 1089
1043 tag_t 1090 tag_t tag;
1044 tag;
1045 int
1046 check_walk_off; 1091 int check_walk_off;
1047 mapstruct * 1092 mapstruct *m;
1048 m;
1049 1093
1050 sint16 1094 sint16 x, y;
1051 x,
1052 y;
1053 1095
1054 if (QUERY_FLAG (op, FLAG_REMOVED)) 1096 if (QUERY_FLAG (op, FLAG_REMOVED))
1055 return; 1097 return;
1056 1098
1057 SET_FLAG (op, FLAG_REMOVED); 1099 SET_FLAG (op, FLAG_REMOVED);
1220 * This function goes through all objects below and including top, and 1262 * This function goes through all objects below and including top, and
1221 * merges op to the first matching object. 1263 * merges op to the first matching object.
1222 * If top is NULL, it is calculated. 1264 * If top is NULL, it is calculated.
1223 * Returns pointer to object if it succeded in the merge, otherwise NULL 1265 * Returns pointer to object if it succeded in the merge, otherwise NULL
1224 */ 1266 */
1225
1226object * 1267object *
1227merge_ob (object *op, object *top) 1268merge_ob (object *op, object *top)
1228{ 1269{
1229 if (!op->nrof) 1270 if (!op->nrof)
1230 return 0; 1271 return 0;
1246 free_object (op); 1287 free_object (op);
1247 return top; 1288 return top;
1248 } 1289 }
1249 } 1290 }
1250 1291
1251 return NULL; 1292 return 0;
1252} 1293}
1253 1294
1254/* 1295/*
1255 * same as insert_ob_in_map except it handle separate coordinates and do a clean 1296 * same as insert_ob_in_map except it handle separate coordinates and do a clean
1256 * job preparing multi-part monsters 1297 * job preparing multi-part monsters
1583 remove_ob (tmp); 1624 remove_ob (tmp);
1584 free_object (tmp); 1625 free_object (tmp);
1585 } 1626 }
1586 } 1627 }
1587 1628
1588 tmp1 = arch_to_object (find_archetype (arch_string)); 1629 tmp1 = arch_to_object (archetype::find (arch_string));
1589 1630
1590 tmp1->x = op->x; 1631 tmp1->x = op->x;
1591 tmp1->y = op->y; 1632 tmp1->y = op->y;
1592 insert_ob_in_map (tmp1, op->map, op, 0); 1633 insert_ob_in_map (tmp1, op->map, op, 0);
1593} 1634}
2651 2692
2652 if (tempfile == NULL) 2693 if (tempfile == NULL)
2653 { 2694 {
2654 LOG (llevError, "Error - Unable to access load object temp file\n"); 2695 LOG (llevError, "Error - Unable to access load object temp file\n");
2655 return NULL; 2696 return NULL;
2656 }; 2697 }
2698
2657 fprintf (tempfile, obstr); 2699 fprintf (tempfile, obstr);
2658 fclose (tempfile); 2700 fclose (tempfile);
2659 2701
2660 op = get_object (); 2702 op = get_object ();
2661 2703
2718 * The returned string is shared. 2760 * The returned string is shared.
2719 */ 2761 */
2720const char * 2762const char *
2721get_ob_key_value (const object *op, const char *const key) 2763get_ob_key_value (const object *op, const char *const key)
2722{ 2764{
2723 key_value * 2765 key_value *link;
2724 link; 2766 shstr_cmp canonical_key (key);
2725 const char *
2726 canonical_key;
2727 2767
2728 canonical_key = shstr::find (key);
2729
2730 if (canonical_key == NULL) 2768 if (!canonical_key)
2731 { 2769 {
2732 /* 1. There being a field named key on any object 2770 /* 1. There being a field named key on any object
2733 * implies there'd be a shared string to find. 2771 * implies there'd be a shared string to find.
2734 * 2. Since there isn't, no object has this field. 2772 * 2. Since there isn't, no object has this field.
2735 * 3. Therefore, *this* object doesn't have this field. 2773 * 3. Therefore, *this* object doesn't have this field.
2736 */ 2774 */
2737 return NULL; 2775 return 0;
2738 } 2776 }
2739 2777
2740 /* This is copied from get_ob_key_link() above - 2778 /* This is copied from get_ob_key_link() above -
2741 * only 4 lines, and saves the function call overhead. 2779 * only 4 lines, and saves the function call overhead.
2742 */ 2780 */
2743 for (link = op->key_values; link != NULL; link = link->next) 2781 for (link = op->key_values; link; link = link->next)
2744 {
2745 if (link->key == canonical_key) 2782 if (link->key == canonical_key)
2746 {
2747 return link->value; 2783 return link->value;
2748 } 2784
2749 }
2750 return NULL; 2785 return 0;
2751} 2786}
2752 2787
2753 2788
2754/* 2789/*
2755 * Updates the canonical_key in op to value. 2790 * Updates the canonical_key in op to value.
2840{ 2875{
2841 shstr key_ (key); 2876 shstr key_ (key);
2842 2877
2843 return set_ob_key_value_s (op, key_, value, add_key); 2878 return set_ob_key_value_s (op, key_, value, add_key);
2844} 2879}
2880
2881object::depth_iterator::depth_iterator (object *container)
2882: iterator_base (container)
2883{
2884 while (item->inv)
2885 item = item->inv;
2886}
2887
2888void
2889object::depth_iterator::next ()
2890{
2891 if (item->below)
2892 {
2893 item = item->below;
2894
2895 while (item->inv)
2896 item = item->inv;
2897 }
2898 else
2899 item = item->env;
2900}
2901
2902// return a suitable string describing an objetc in enough detail to find it
2903const char *
2904object::debug_desc (char *info) const
2905{
2906 char info2[256 * 3];
2907 char *p = info;
2908
2909 p += snprintf (p, 256, "%d=\"%s%s%s\"",
2910 count,
2911 &name,
2912 title ? " " : "",
2913 title ? (const char *)title : "");
2914
2915 if (env)
2916 p += snprintf (p, 256, "(in %s)", env->debug_desc (info2));
2917
2918 if (map)
2919 p += snprintf (p, 256, "(on %s@%d+%d)", map->path, x, y);
2920
2921 return info;
2922}
2923
2924const char *
2925object::debug_desc () const
2926{
2927 static char info[256 * 3];
2928 return debug_desc (info);
2929}
2930

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines