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.33 by root, Tue Sep 12 00:53:56 2006 UTC vs.
Revision 1.52 by root, Wed Sep 27 00:36:08 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. */
32#include <object.h> 31#include <object.h>
33#include <funcpoint.h> 32#include <funcpoint.h>
34#include <loader.h> 33#include <loader.h>
35 34
36int nrofallocobjects = 0; 35int nrofallocobjects = 0;
36static UUID uuid;
37const uint64 UUID_SKIP = 1<<19;
37 38
38object *objects; /* Pointer to the list of used objects */
39object *active_objects; /* List of active objects that need to be processed */ 39object *active_objects; /* List of active objects that need to be processed */
40 40
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, 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,
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 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
43}; 43};
49}; 49};
50int freedir[SIZEOFFREE] = { 50int freedir[SIZEOFFREE] = {
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, 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,
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 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
53}; 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}
54 131
55/* 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. */
56static int 133static int
57compare_ob_value_lists_one (const object *wants, const object *has) 134compare_ob_value_lists_one (const object *wants, const object *has)
58{ 135{
254 { 331 {
255 if (inv->inv) 332 if (inv->inv)
256 sum_weight (inv); 333 sum_weight (inv);
257 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1); 334 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1);
258 } 335 }
336
259 if (op->type == CONTAINER && op->stats.Str) 337 if (op->type == CONTAINER && op->stats.Str)
260 sum = (sum * (100 - op->stats.Str)) / 100; 338 sum = (sum * (100 - op->stats.Str)) / 100;
339
261 if (op->carrying != sum) 340 if (op->carrying != sum)
262 op->carrying = sum; 341 op->carrying = sum;
342
263 return sum; 343 return sum;
264} 344}
265 345
266/** 346/**
267 * Return the outermost environment object for a given object. 347 * Return the outermost environment object for a given object.
365void 445void
366dump_all_objects (void) 446dump_all_objects (void)
367{ 447{
368 object *op; 448 object *op;
369 449
370 for (op = objects; op != NULL; op = op->next) 450 for (op = object::first; op != NULL; op = op->next)
371 { 451 {
372 dump_object (op); 452 dump_object (op);
373 fprintf (logfile, "Object %d\n:%s\n", op->count, errmsg); 453 fprintf (logfile, "Object %s\n", errmsg);
374 } 454 }
375} 455}
376 456
377/* 457/*
378 * get_nearest_part(multi-object, object 2) returns the part of the 458 * get_nearest_part(multi-object, object 2) returns the part of the
401object * 481object *
402find_object (tag_t i) 482find_object (tag_t i)
403{ 483{
404 object *op; 484 object *op;
405 485
406 for (op = objects; op != NULL; op = op->next) 486 for (op = object::first; op != NULL; op = op->next)
407 if (op->count == i) 487 if (op->count == i)
408 break; 488 break;
489
409 return op; 490 return op;
410} 491}
411 492
412/* 493/*
413 * Returns the first object which has a name equal to the argument. 494 * Returns the first object which has a name equal to the argument.
416 */ 497 */
417 498
418object * 499object *
419find_object_name (const char *str) 500find_object_name (const char *str)
420{ 501{
421 const char *name = shstr::find (str); 502 shstr_cmp str_ (str);
422 object *op; 503 object *op;
423 504
424 for (op = objects; op != NULL; op = op->next) 505 for (op = object::first; op != NULL; op = op->next)
425 if (&op->name == name) 506 if (op->name == str_)
426 break; 507 break;
427 508
428 return op; 509 return op;
429} 510}
430 511
431void 512void
432free_all_object_data () 513free_all_object_data ()
433{ 514{
434 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects); 515 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects);
435}
436
437/*
438 * Returns the object which this object marks as being the owner.
439 * A id-scheme is used to avoid pointing to objects which have been
440 * freed and are now reused. If this is detected, the owner is
441 * set to NULL, and NULL is returned.
442 * Changed 2004-02-12 - if the player is setting at the play again
443 * prompt, he is removed, and we don't want to treat him as an owner of
444 * anything, so check removed flag. I don't expect that this should break
445 * anything - once an object is removed, it is basically dead anyways.
446 */
447object *
448object::get_owner ()
449{
450 if (!owner
451 || QUERY_FLAG (owner, FLAG_FREED)
452 || QUERY_FLAG (owner, FLAG_REMOVED))
453 owner = 0;
454
455 return owner;
456} 516}
457 517
458/* 518/*
459 * Sets the owner and sets the skill and exp pointers to owner's current 519 * Sets the owner and sets the skill and exp pointers to owner's current
460 * skill and experience objects. 520 * skill and experience objects.
530 590
531 /* What is not cleared is next, prev, and count */ 591 /* What is not cleared is next, prev, and count */
532 592
533 expmul = 1.0; 593 expmul = 1.0;
534 face = blank_face; 594 face = blank_face;
535 attacked_by_count = -1;
536 595
537 if (settings.casting_time) 596 if (settings.casting_time)
538 casting_time = -1; 597 casting_time = -1;
539} 598}
540 599
835 894
836 if (op->more != NULL) 895 if (op->more != NULL)
837 update_object (op->more, action); 896 update_object (op->more, action);
838} 897}
839 898
840static unordered_vector<object *> mortals; 899object::vector object::mortals;
841static std::vector<object *> freed; 900object::vector object::objects; // not yet used
901object *object::first;
842 902
843void object::free_mortals () 903void object::free_mortals ()
844{ 904{
845 for (unordered_vector<object *>::iterator i = mortals.begin (); i != mortals.end ();) 905 for (AUTODECL (i, mortals.begin ()); i != mortals.end ();)
846 if ((*i)->refcnt) 906 if ((*i)->refcnt)
847 ++i; // further delay freeing 907 ++i; // further delay freeing
848 else 908 else
849 { 909 {
850 freed.push_back (*i);//D
851 //delete *i; 910 delete *i;
852 mortals.erase (i); 911 mortals.erase (i);
853 } 912 }
854 913
855 if (mortals.size())//D 914 static int lastmortals = 0;//D
915
916 if (mortals.size() != lastmortals && lastmortals > 100)//D
917 {
918 lastmortals = mortals.size ();//D
856 LOG (llevDebug, "%d objects in mortal queue\n", mortals.size());//D 919 LOG (llevDebug, "%d objects in mortal queue\n", lastmortals);//D
920 }
857} 921}
858 922
859object::object () 923object::object ()
860{ 924{
861 SET_FLAG (this, FLAG_REMOVED); 925 SET_FLAG (this, FLAG_REMOVED);
862 926
863 expmul = 1.0; 927 expmul = 1.0;
864 face = blank_face; 928 face = blank_face;
865 attacked_by_count = -1;
866} 929}
867 930
868object::~object () 931object::~object ()
869{ 932{
870 free_key_values (this); 933 free_key_values (this);
871} 934}
872 935
873void object::link () 936void object::link ()
874{ 937{
875 count = ++ob_count; 938 count = ++ob_count;
939 uuid = gen_uuid ();
876 940
877 prev = 0; 941 prev = 0;
878 next = objects; 942 next = object::first;
879 943
880 if (objects) 944 if (object::first)
881 objects->prev = this; 945 object::first->prev = this;
882 946
883 objects = this; 947 object::first = this;
884} 948}
885 949
886void object::unlink () 950void object::unlink ()
887{ 951{
888 count = 0; 952 if (this == object::first)
953 object::first = next;
889 954
890 /* Remove this object from the list of used objects */ 955 /* Remove this object from the list of used objects */
891 if (prev)
892 {
893 prev->next = next; 956 if (prev) prev->next = next;
957 if (next) next->prev = prev;
958
894 prev = 0; 959 prev = 0;
895 }
896
897 if (next)
898 {
899 next->prev = prev;
900 next = 0; 960 next = 0;
901 }
902
903 if (this == objects)
904 objects = next;
905} 961}
906 962
907object *object::create () 963object *object::create ()
908{ 964{
909 object *op;
910
911 if (freed.empty ())
912 op = new object; 965 object *op = new object;
913 else
914 {
915 // highly annoying, but the only way to get it stable right now
916 op = freed.back ();
917 freed.pop_back ();
918 op->~object ();
919 new ((void *) op) object;
920 }
921
922 op->link (); 966 op->link ();
923 return op; 967 return op;
924} 968}
925 969
926/* 970/*
928 * it from the list of used objects, and puts it on the list of 972 * it from the list of used objects, and puts it on the list of
929 * free objects. The IS_FREED() flag is set in the object. 973 * free objects. The IS_FREED() flag is set in the object.
930 * The object must have been removed by remove_ob() first for 974 * The object must have been removed by remove_ob() first for
931 * this function to succeed. 975 * this function to succeed.
932 * 976 *
933 * If free_inventory is set, free inventory as well. Else drop items in 977 * If destroy_inventory is set, free inventory as well. Else drop items in
934 * inventory to the ground. 978 * inventory to the ground.
935 */ 979 */
936void object::free (bool free_inventory) 980void object::destroy (bool destroy_inventory)
937{ 981{
938 if (QUERY_FLAG (this, FLAG_FREED)) 982 if (QUERY_FLAG (this, FLAG_FREED))
939 return; 983 return;
940 984
941 if (QUERY_FLAG (this, FLAG_FRIENDLY)) 985 if (QUERY_FLAG (this, FLAG_FRIENDLY))
946 990
947 SET_FLAG (this, FLAG_FREED); 991 SET_FLAG (this, FLAG_FREED);
948 992
949 if (more) 993 if (more)
950 { 994 {
951 more->free (free_inventory); 995 more->destroy (destroy_inventory);
952 more = 0; 996 more = 0;
953 } 997 }
954 998
955 if (inv) 999 if (inv)
956 { 1000 {
957 /* Only if the space blocks everything do we not process - 1001 /* Only if the space blocks everything do we not process -
958 * if some form of movement is allowed, let objects 1002 * if some form of movement is allowed, let objects
959 * drop on that space. 1003 * drop on that space.
960 */ 1004 */
961 if (free_inventory || !map || map->in_memory != MAP_IN_MEMORY || GET_MAP_MOVE_BLOCK (map, x, y) == MOVE_ALL) 1005 if (destroy_inventory || !map || map->in_memory != MAP_IN_MEMORY || GET_MAP_MOVE_BLOCK (map, x, y) == MOVE_ALL)
962 { 1006 {
963 object *op = inv; 1007 object *op = inv;
964 1008
965 while (op) 1009 while (op)
966 { 1010 {
967 object *tmp = op->below; 1011 object *tmp = op->below;
968 op->free (free_inventory); 1012 op->destroy (destroy_inventory);
969 op = tmp; 1013 op = tmp;
970 } 1014 }
971 } 1015 }
972 else 1016 else
973 { /* Put objects in inventory onto this space */ 1017 { /* Put objects in inventory onto this space */
992 op = tmp; 1036 op = tmp;
993 } 1037 }
994 } 1038 }
995 } 1039 }
996 1040
1041 // clear those pointers that likely might have circular references to us
997 owner = 0; 1042 owner = 0;
1043 enemy = 0;
1044 attacked_by = 0;
1045
1046 // only relevant for players(?), but make sure of it anyways
1047 contr = 0;
998 1048
999 /* Remove object from the active list */ 1049 /* Remove object from the active list */
1000 speed = 0; 1050 speed = 0;
1001 update_ob_speed (this); 1051 update_ob_speed (this);
1002 1052
1014sub_weight (object *op, signed long weight) 1064sub_weight (object *op, signed long weight)
1015{ 1065{
1016 while (op != NULL) 1066 while (op != NULL)
1017 { 1067 {
1018 if (op->type == CONTAINER) 1068 if (op->type == CONTAINER)
1019 {
1020 weight = (signed long) (weight * (100 - op->stats.Str) / 100); 1069 weight = (signed long) (weight * (100 - op->stats.Str) / 100);
1021 } 1070
1022 op->carrying -= weight; 1071 op->carrying -= weight;
1023 op = op->env; 1072 op = op->env;
1024 } 1073 }
1025} 1074}
1026 1075
1034 */ 1083 */
1035 1084
1036void 1085void
1037remove_ob (object *op) 1086remove_ob (object *op)
1038{ 1087{
1088 object *tmp, *last = 0;
1039 object * 1089 object *otmp;
1040 tmp, *
1041 last = NULL;
1042 object *
1043 otmp;
1044 1090
1045 tag_t
1046 tag;
1047 int
1048 check_walk_off; 1091 int check_walk_off;
1049 mapstruct * 1092 maptile *m;
1050 m;
1051 1093
1052 sint16 1094 sint16 x, y;
1053 x,
1054 y;
1055 1095
1056 if (QUERY_FLAG (op, FLAG_REMOVED)) 1096 if (QUERY_FLAG (op, FLAG_REMOVED))
1057 return; 1097 return;
1058 1098
1059 SET_FLAG (op, FLAG_REMOVED); 1099 SET_FLAG (op, FLAG_REMOVED);
1152 op->below = 0; 1192 op->below = 0;
1153 1193
1154 if (op->map->in_memory == MAP_SAVING) 1194 if (op->map->in_memory == MAP_SAVING)
1155 return; 1195 return;
1156 1196
1157 tag = op->count;
1158 check_walk_off = !QUERY_FLAG (op, FLAG_NO_APPLY); 1197 check_walk_off = !QUERY_FLAG (op, FLAG_NO_APPLY);
1159 1198
1160 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) 1199 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
1161 { 1200 {
1162 /* No point updating the players look faces if he is the object 1201 /* No point updating the players look faces if he is the object
1177 1216
1178 tmp->contr->socket.update_look = 1; 1217 tmp->contr->socket.update_look = 1;
1179 } 1218 }
1180 1219
1181 /* See if player moving off should effect something */ 1220 /* See if player moving off should effect something */
1182 if (check_walk_off && ((op->move_type & tmp->move_off) && (op->move_type & ~tmp->move_off & ~tmp->move_block) == 0)) 1221 if (check_walk_off
1222 && ((op->move_type & tmp->move_off)
1223 && (op->move_type & ~tmp->move_off & ~tmp->move_block) == 0))
1183 { 1224 {
1184 move_apply (tmp, op, NULL); 1225 move_apply (tmp, op, NULL);
1185 1226
1186 if (was_destroyed (op, tag)) 1227 if (op->destroyed ())
1187 {
1188 LOG (llevError, "BUG: remove_ob(): name %s, archname %s destroyed " "leaving object\n", &tmp->name, &tmp->arch->name); 1228 LOG (llevError, "BUG: remove_ob(): name %s, destroyed leaving object\n", tmp->debug_desc ());
1189 }
1190 } 1229 }
1191 1230
1192 /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */ 1231 /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */
1193 1232
1194 if (tmp->above == tmp) 1233 if (tmp->above == tmp)
1222 * This function goes through all objects below and including top, and 1261 * This function goes through all objects below and including top, and
1223 * merges op to the first matching object. 1262 * merges op to the first matching object.
1224 * If top is NULL, it is calculated. 1263 * If top is NULL, it is calculated.
1225 * Returns pointer to object if it succeded in the merge, otherwise NULL 1264 * Returns pointer to object if it succeded in the merge, otherwise NULL
1226 */ 1265 */
1227
1228object * 1266object *
1229merge_ob (object *op, object *top) 1267merge_ob (object *op, object *top)
1230{ 1268{
1231 if (!op->nrof) 1269 if (!op->nrof)
1232 return 0; 1270 return 0;
1248 free_object (op); 1286 free_object (op);
1249 return top; 1287 return top;
1250 } 1288 }
1251 } 1289 }
1252 1290
1253 return NULL; 1291 return 0;
1254} 1292}
1255 1293
1256/* 1294/*
1257 * same as insert_ob_in_map except it handle separate coordinates and do a clean 1295 * same as insert_ob_in_map except it handle separate coordinates and do a clean
1258 * job preparing multi-part monsters 1296 * job preparing multi-part monsters
1259 */ 1297 */
1260object * 1298object *
1261insert_ob_in_map_at (object *op, mapstruct *m, object *originator, int flag, int x, int y) 1299insert_ob_in_map_at (object *op, maptile *m, object *originator, int flag, int x, int y)
1262{ 1300{
1263 object *tmp; 1301 object *tmp;
1264 1302
1265 if (op->head) 1303 if (op->head)
1266 op = op->head; 1304 op = op->head;
1294 * NULL if 'op' was destroyed 1332 * NULL if 'op' was destroyed
1295 * just 'op' otherwise 1333 * just 'op' otherwise
1296 */ 1334 */
1297 1335
1298object * 1336object *
1299insert_ob_in_map (object *op, mapstruct *m, object *originator, int flag) 1337insert_ob_in_map (object *op, maptile *m, object *originator, int flag)
1300{ 1338{
1301 object *tmp, *top, *floor = NULL; 1339 object *tmp, *top, *floor = NULL;
1302 sint16 x, y; 1340 sint16 x, y;
1303 1341
1304 if (QUERY_FLAG (op, FLAG_FREED)) 1342 if (QUERY_FLAG (op, FLAG_FREED))
1585 remove_ob (tmp); 1623 remove_ob (tmp);
1586 free_object (tmp); 1624 free_object (tmp);
1587 } 1625 }
1588 } 1626 }
1589 1627
1590 tmp1 = arch_to_object (find_archetype (arch_string)); 1628 tmp1 = arch_to_object (archetype::find (arch_string));
1591 1629
1592 tmp1->x = op->x; 1630 tmp1->x = op->x;
1593 tmp1->y = op->y; 1631 tmp1->y = op->y;
1594 insert_ob_in_map (tmp1, op->map, op, 0); 1632 insert_ob_in_map (tmp1, op->map, op, 0);
1595} 1633}
1894 */ 1932 */
1895 1933
1896int 1934int
1897check_move_on (object *op, object *originator) 1935check_move_on (object *op, object *originator)
1898{ 1936{
1899 object * 1937 object *tmp;
1900 tmp; 1938 maptile *m = op->map;
1901 tag_t
1902 tag;
1903 mapstruct *
1904 m = op->map;
1905 int
1906 x = op->x, y = op->y; 1939 int x = op->x, y = op->y;
1907 1940
1908 MoveType 1941 MoveType move_on, move_slow, move_block;
1909 move_on,
1910 move_slow,
1911 move_block;
1912 1942
1913 if (QUERY_FLAG (op, FLAG_NO_APPLY)) 1943 if (QUERY_FLAG (op, FLAG_NO_APPLY))
1914 return 0; 1944 return 0;
1915
1916 tag = op->count;
1917 1945
1918 move_on = GET_MAP_MOVE_ON (op->map, op->x, op->y); 1946 move_on = GET_MAP_MOVE_ON (op->map, op->x, op->y);
1919 move_slow = GET_MAP_MOVE_SLOW (op->map, op->x, op->y); 1947 move_slow = GET_MAP_MOVE_SLOW (op->map, op->x, op->y);
1920 move_block = GET_MAP_MOVE_BLOCK (op->map, op->x, op->y); 1948 move_block = GET_MAP_MOVE_BLOCK (op->map, op->x, op->y);
1921 1949
1982 if ((!op->move_type && tmp->move_on & MOVE_WALK) || 2010 if ((!op->move_type && tmp->move_on & MOVE_WALK) ||
1983 ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0)) 2011 ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0))
1984 { 2012 {
1985 move_apply (tmp, op, originator); 2013 move_apply (tmp, op, originator);
1986 2014
1987 if (was_destroyed (op, tag)) 2015 if (op->destroyed ())
1988 return 1; 2016 return 1;
1989 2017
1990 /* what the person/creature stepped onto has moved the object 2018 /* what the person/creature stepped onto has moved the object
1991 * someplace new. Don't process any further - if we did, 2019 * someplace new. Don't process any further - if we did,
1992 * have a feeling strange problems would result. 2020 * have a feeling strange problems would result.
2004 * a matching archetype at the given map and coordinates. 2032 * a matching archetype at the given map and coordinates.
2005 * The first matching object is returned, or NULL if none. 2033 * The first matching object is returned, or NULL if none.
2006 */ 2034 */
2007 2035
2008object * 2036object *
2009present_arch (const archetype *at, mapstruct *m, int x, int y) 2037present_arch (const archetype *at, maptile *m, int x, int y)
2010{ 2038{
2011 object * 2039 object *
2012 tmp; 2040 tmp;
2013 2041
2014 if (m == NULL || out_of_map (m, x, y)) 2042 if (m == NULL || out_of_map (m, x, y))
2027 * a matching type variable at the given map and coordinates. 2055 * a matching type variable at the given map and coordinates.
2028 * The first matching object is returned, or NULL if none. 2056 * The first matching object is returned, or NULL if none.
2029 */ 2057 */
2030 2058
2031object * 2059object *
2032present (unsigned char type, mapstruct *m, int x, int y) 2060present (unsigned char type, maptile *m, int x, int y)
2033{ 2061{
2034 object * 2062 object *
2035 tmp; 2063 tmp;
2036 2064
2037 if (out_of_map (m, x, y)) 2065 if (out_of_map (m, x, y))
2177 * the archetype because that isn't correct if the monster has been 2205 * the archetype because that isn't correct if the monster has been
2178 * customized, changed states, etc. 2206 * customized, changed states, etc.
2179 */ 2207 */
2180 2208
2181int 2209int
2182find_free_spot (const object *ob, mapstruct *m, int x, int y, int start, int stop) 2210find_free_spot (const object *ob, maptile *m, int x, int y, int start, int stop)
2183{ 2211{
2184 int 2212 int
2185 i, 2213 i,
2186 index = 0, flag; 2214 index = 0, flag;
2187 static int 2215 static int
2208 return -1; 2236 return -1;
2209 return altern[RANDOM () % index]; 2237 return altern[RANDOM () % index];
2210} 2238}
2211 2239
2212/* 2240/*
2213 * find_first_free_spot(archetype, mapstruct, x, y) works like 2241 * find_first_free_spot(archetype, maptile, x, y) works like
2214 * find_free_spot(), but it will search max number of squares. 2242 * find_free_spot(), but it will search max number of squares.
2215 * But it will return the first available spot, not a random choice. 2243 * But it will return the first available spot, not a random choice.
2216 * Changed 0.93.2: Have it return -1 if there is no free spot available. 2244 * Changed 0.93.2: Have it return -1 if there is no free spot available.
2217 */ 2245 */
2218 2246
2219int 2247int
2220find_first_free_spot (const object *ob, mapstruct *m, int x, int y) 2248find_first_free_spot (const object *ob, maptile *m, int x, int y)
2221{ 2249{
2222 int 2250 int
2223 i; 2251 i;
2224 2252
2225 for (i = 0; i < SIZEOFFREE; i++) 2253 for (i = 0; i < SIZEOFFREE; i++)
2289 * because we have to know what movement the thing looking to move 2317 * because we have to know what movement the thing looking to move
2290 * there is capable of. 2318 * there is capable of.
2291 */ 2319 */
2292 2320
2293int 2321int
2294find_dir (mapstruct *m, int x, int y, object *exclude) 2322find_dir (maptile *m, int x, int y, object *exclude)
2295{ 2323{
2296 int 2324 int
2297 i, 2325 i,
2298 max = SIZEOFFREE, mflags; 2326 max = SIZEOFFREE, mflags;
2299 2327
2300 sint16 nx, ny; 2328 sint16 nx, ny;
2301 object * 2329 object *
2302 tmp; 2330 tmp;
2303 mapstruct * 2331 maptile *
2304 mp; 2332 mp;
2305 2333
2306 MoveType blocked, move_type; 2334 MoveType blocked, move_type;
2307 2335
2308 if (exclude && exclude->head) 2336 if (exclude && exclude->head)
2516 * Modified to be map tile aware -.MSW 2544 * Modified to be map tile aware -.MSW
2517 */ 2545 */
2518 2546
2519 2547
2520int 2548int
2521can_see_monsterP (mapstruct *m, int x, int y, int dir) 2549can_see_monsterP (maptile *m, int x, int y, int dir)
2522{ 2550{
2523 sint16 dx, dy; 2551 sint16 dx, dy;
2524 int 2552 int
2525 mflags; 2553 mflags;
2526 2554
2606 if (prev) 2634 if (prev)
2607 prev->more = tmp; 2635 prev->more = tmp;
2608 prev = tmp; 2636 prev = tmp;
2609 } 2637 }
2610 2638
2611 /*** copy inventory ***/
2612 for (item = src->inv; item; item = item->below) 2639 for (item = src->inv; item; item = item->below)
2613 {
2614 (void) insert_ob_in_ob (object_create_clone (item), dst); 2640 insert_ob_in_ob (object_create_clone (item), dst);
2615 }
2616 2641
2617 return dst; 2642 return dst;
2618} 2643}
2619 2644
2620/* return true if the object was destroyed, 0 otherwise */
2621int
2622was_destroyed (const object *op, tag_t old_tag)
2623{
2624 /* checking for FLAG_FREED isn't necessary, but makes this function more
2625 * robust */
2626 return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED);
2627}
2628
2629/* GROS - Creates an object using a string representing its content. */ 2645/* GROS - Creates an object using a string representing its content. */
2630
2631/* Basically, we save the content of the string to a temp file, then call */ 2646/* Basically, we save the content of the string to a temp file, then call */
2632
2633/* load_object on it. I admit it is a highly inefficient way to make things, */ 2647/* load_object on it. I admit it is a highly inefficient way to make things, */
2634
2635/* but it was simple to make and allows reusing the load_object function. */ 2648/* but it was simple to make and allows reusing the load_object function. */
2636
2637/* Remember not to use load_object_str in a time-critical situation. */ 2649/* Remember not to use load_object_str in a time-critical situation. */
2638
2639/* Also remember that multiparts objects are not supported for now. */ 2650/* Also remember that multiparts objects are not supported for now. */
2640 2651
2641object * 2652object *
2642load_object_str (const char *obstr) 2653load_object_str (const char *obstr)
2643{ 2654{
2644 object * 2655 object *op;
2645 op;
2646 char
2647 filename[MAX_BUF]; 2656 char filename[MAX_BUF];
2648 2657
2649 sprintf (filename, "%s/cfloadobstr2044", settings.tmpdir); 2658 sprintf (filename, "%s/cfloadobstr2044", settings.tmpdir);
2650 2659
2651 FILE *
2652 tempfile = fopen (filename, "w"); 2660 FILE *tempfile = fopen (filename, "w");
2653 2661
2654 if (tempfile == NULL) 2662 if (tempfile == NULL)
2655 { 2663 {
2656 LOG (llevError, "Error - Unable to access load object temp file\n"); 2664 LOG (llevError, "Error - Unable to access load object temp file\n");
2657 return NULL; 2665 return NULL;
2658 }; 2666 }
2667
2659 fprintf (tempfile, obstr); 2668 fprintf (tempfile, obstr);
2660 fclose (tempfile); 2669 fclose (tempfile);
2661 2670
2662 op = get_object (); 2671 op = get_object ();
2663 2672
2677 * returns NULL if no match. 2686 * returns NULL if no match.
2678 */ 2687 */
2679object * 2688object *
2680find_obj_by_type_subtype (const object *who, int type, int subtype) 2689find_obj_by_type_subtype (const object *who, int type, int subtype)
2681{ 2690{
2682 object * 2691 object *tmp;
2683 tmp;
2684 2692
2685 for (tmp = who->inv; tmp; tmp = tmp->below) 2693 for (tmp = who->inv; tmp; tmp = tmp->below)
2686 if (tmp->type == type && tmp->subtype == subtype) 2694 if (tmp->type == type && tmp->subtype == subtype)
2687 return tmp; 2695 return tmp;
2688 2696
2696 * do the desired thing. 2704 * do the desired thing.
2697 */ 2705 */
2698key_value * 2706key_value *
2699get_ob_key_link (const object *ob, const char *key) 2707get_ob_key_link (const object *ob, const char *key)
2700{ 2708{
2701 key_value * 2709 key_value *link;
2702 link;
2703 2710
2704 for (link = ob->key_values; link != NULL; link = link->next) 2711 for (link = ob->key_values; link != NULL; link = link->next)
2705 {
2706 if (link->key == key) 2712 if (link->key == key)
2707 {
2708 return link; 2713 return link;
2709 }
2710 }
2711 2714
2712 return NULL; 2715 return NULL;
2713} 2716}
2714 2717
2715/* 2718/*
2720 * The returned string is shared. 2723 * The returned string is shared.
2721 */ 2724 */
2722const char * 2725const char *
2723get_ob_key_value (const object *op, const char *const key) 2726get_ob_key_value (const object *op, const char *const key)
2724{ 2727{
2725 key_value * 2728 key_value *link;
2726 link; 2729 shstr_cmp canonical_key (key);
2727 const char *
2728 canonical_key;
2729 2730
2730 canonical_key = shstr::find (key);
2731
2732 if (canonical_key == NULL) 2731 if (!canonical_key)
2733 { 2732 {
2734 /* 1. There being a field named key on any object 2733 /* 1. There being a field named key on any object
2735 * implies there'd be a shared string to find. 2734 * implies there'd be a shared string to find.
2736 * 2. Since there isn't, no object has this field. 2735 * 2. Since there isn't, no object has this field.
2737 * 3. Therefore, *this* object doesn't have this field. 2736 * 3. Therefore, *this* object doesn't have this field.
2738 */ 2737 */
2739 return NULL; 2738 return 0;
2740 } 2739 }
2741 2740
2742 /* This is copied from get_ob_key_link() above - 2741 /* This is copied from get_ob_key_link() above -
2743 * only 4 lines, and saves the function call overhead. 2742 * only 4 lines, and saves the function call overhead.
2744 */ 2743 */
2745 for (link = op->key_values; link != NULL; link = link->next) 2744 for (link = op->key_values; link; link = link->next)
2746 {
2747 if (link->key == canonical_key) 2745 if (link->key == canonical_key)
2748 {
2749 return link->value; 2746 return link->value;
2750 } 2747
2751 }
2752 return NULL; 2748 return 0;
2753} 2749}
2754 2750
2755 2751
2756/* 2752/*
2757 * Updates the canonical_key in op to value. 2753 * Updates the canonical_key in op to value.
2843 shstr key_ (key); 2839 shstr key_ (key);
2844 2840
2845 return set_ob_key_value_s (op, key_, value, add_key); 2841 return set_ob_key_value_s (op, key_, value, add_key);
2846} 2842}
2847 2843
2844object::depth_iterator::depth_iterator (object *container)
2845: iterator_base (container)
2846{
2847 while (item->inv)
2848 item = item->inv;
2849}
2850
2848void 2851void
2849object::deep_iterator::next () 2852object::depth_iterator::next ()
2850{ 2853{
2851 if (item->inv)
2852 item = item->inv;
2853 else if (item->below) 2854 if (item->below)
2855 {
2854 item = item->below; 2856 item = item->below;
2857
2858 while (item->inv)
2859 item = item->inv;
2860 }
2855 else 2861 else
2856 item = item->env->below; 2862 item = item->env;
2857} 2863}
2864
2865// return a suitable string describing an objetc in enough detail to find it
2866const char *
2867object::debug_desc (char *info) const
2868{
2869 char info2[256 * 3];
2870 char *p = info;
2871
2872 p += snprintf (p, 256, "%d=\"%s%s%s\"",
2873 count,
2874 &name,
2875 title ? " " : "",
2876 title ? (const char *)title : "");
2877
2878 if (env)
2879 p += snprintf (p, 256, "(in %s)", env->debug_desc (info2));
2880
2881 if (map)
2882 p += snprintf (p, 256, "(on %s@%d+%d)", map->path, x, y);
2883
2884 return info;
2885}
2886
2887const char *
2888object::debug_desc () const
2889{
2890 static char info[256 * 3];
2891 return debug_desc (info);
2892}
2893

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines