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

Comparing deliantra/server/common/map.C (file contents):
Revision 1.45 by root, Wed Dec 20 09:14:21 2006 UTC vs.
Revision 1.54 by root, Wed Dec 27 13:13:46 2006 UTC

19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 20
21 The authors can be reached via e-mail at <crossfire@schmorp.de> 21 The authors can be reached via e-mail at <crossfire@schmorp.de>
22*/ 22*/
23 23
24
25#include <global.h> 24#include <global.h>
26#include <funcpoint.h> 25#include <funcpoint.h>
27 26
28#include <loader.h> 27#include <loader.h>
29#include <unistd.h> 28#include <unistd.h>
32 31
33/* 32/*
34 * Returns the maptile which has a name matching the given argument. 33 * Returns the maptile which has a name matching the given argument.
35 * return NULL if no match is found. 34 * return NULL if no match is found.
36 */ 35 */
37
38maptile * 36maptile *
39has_been_loaded (const char *name) 37has_been_loaded (const char *name)
40{ 38{
41 maptile *map;
42
43 if (!name || !*name) 39 if (!name || !*name)
44 return 0; 40 return 0;
45 for (map = first_map; map; map = map->next) 41
42 for_all_maps (map)
46 if (!strcmp (name, map->path)) 43 if (!strcmp (name, map->path))
47 break;
48 return (map); 44 return map;
45
46 return 0;
49} 47}
50 48
51/* 49/*
52 * This makes a path absolute outside the world of Crossfire. 50 * This makes a path absolute outside the world of Crossfire.
53 * In other words, it prepends LIBDIR/MAPDIR/ to the given path 51 * In other words, it prepends LIBDIR/MAPDIR/ to the given path
196 194
197void 195void
198dump_map (const maptile *m) 196dump_map (const maptile *m)
199{ 197{
200 LOG (llevError, "Map %s status: %d.\n", m->path, m->in_memory); 198 LOG (llevError, "Map %s status: %d.\n", m->path, m->in_memory);
201 LOG (llevError, "Size: %dx%d Start: %d,%d\n", MAP_WIDTH (m), MAP_HEIGHT (m), MAP_ENTER_X (m), MAP_ENTER_Y (m)); 199 LOG (llevError, "Size: %dx%d Start: %d,%d\n", m->width, m->height, m->enter_x, m->enter_y);
202 200
203 if (m->msg != NULL) 201 if (m->msg != NULL)
204 LOG (llevError, "Message:\n%s", m->msg); 202 LOG (llevError, "Message:\n%s", m->msg);
205 203
206 if (m->maplore != NULL) 204 if (m->maplore != NULL)
220 */ 218 */
221 219
222void 220void
223dump_all_maps (void) 221dump_all_maps (void)
224{ 222{
225 maptile *m; 223 for_all_maps (m)
226
227 for (m = first_map; m != NULL; m = m->next)
228 {
229 dump_map (m); 224 dump_map (m);
230 }
231} 225}
232 226
233/* This rolls up wall, blocks_magic, blocks_view, etc, all into 227/* This rolls up wall, blocks_magic, blocks_view, etc, all into
234 * one function that just returns a P_.. value (see map.h) 228 * one function that just returns a P_.. value (see map.h)
235 * it will also do map translation for tiled maps, returning 229 * it will also do map translation for tiled maps, returning
239 * is needed. The case of not passing values is if we're just 233 * is needed. The case of not passing values is if we're just
240 * checking for the existence of something on those spaces, but 234 * checking for the existence of something on those spaces, but
241 * don't expect to insert/remove anything from those spaces. 235 * don't expect to insert/remove anything from those spaces.
242 */ 236 */
243int 237int
244get_map_flags (maptile *oldmap, maptile **newmap, sint16 x, sint16 y, sint16 * nx, sint16 * ny) 238get_map_flags (maptile *oldmap, maptile **newmap, sint16 x, sint16 y, sint16 *nx, sint16 *ny)
245{ 239{
246 sint16 newx, newy; 240 sint16 newx, newy;
247 int retval = 0; 241 int retval = 0;
248 maptile *mp; 242 maptile *mp;
249 243
250 if (out_of_map (oldmap, x, y))
251 return P_OUT_OF_MAP;
252 newx = x; 244 newx = x;
253 newy = y; 245 newy = y;
246
254 mp = get_map_from_coord (oldmap, &newx, &newy); 247 mp = get_map_from_coord (oldmap, &newx, &newy);
248
249 if (!mp)
250 return P_OUT_OF_MAP;
251
255 if (mp != oldmap) 252 if (mp != oldmap)
256 retval |= P_NEW_MAP; 253 retval |= P_NEW_MAP;
257 if (newmap)
258 *newmap = mp;
259 if (nx)
260 *nx = newx;
261 if (ny)
262 *ny = newy;
263 254
264 retval |= mp->spaces[newx + mp->width * newy].flags; 255 if (newmap) *newmap = mp;
256 if (nx) *nx = newx;
257 if (ny) *ny = newy;
265 258
266 return retval; 259 return retval | mp->at (newx, newy).flags ();
267} 260}
268 261
269/* 262/*
270 * Returns true if the given coordinate is blocked except by the 263 * Returns true if the given coordinate is blocked except by the
271 * object passed is not blocking. This is used with 264 * object passed is not blocking. This is used with
294 } 287 }
295 288
296 /* Save some cycles - instead of calling get_map_flags(), just get the value 289 /* Save some cycles - instead of calling get_map_flags(), just get the value
297 * directly. 290 * directly.
298 */ 291 */
299 mflags = m->spaces[sx + m->width * sy].flags; 292 mflags = m->at (sx, sy).flags ();
300 293
301 blocked = GET_MAP_MOVE_BLOCK (m, sx, sy); 294 blocked = GET_MAP_MOVE_BLOCK (m, sx, sy);
302 295
303 /* If space is currently not blocked by anything, no need to 296 /* If space is currently not blocked by anything, no need to
304 * go further. Not true for players - all sorts of special 297 * go further. Not true for players - all sorts of special
412 flag = get_map_flags (m, &m1, x, y, &sx, &sy); 405 flag = get_map_flags (m, &m1, x, y, &sx, &sy);
413 if (flag & P_OUT_OF_MAP) 406 if (flag & P_OUT_OF_MAP)
414 return P_OUT_OF_MAP; 407 return P_OUT_OF_MAP;
415 408
416 /* don't have object, so don't know what types would block */ 409 /* don't have object, so don't know what types would block */
417 return (GET_MAP_MOVE_BLOCK (m1, sx, sy)); 410 return m1->at (sx, sy).move_block;
418 } 411 }
419 412
420 for (tmp = ob->arch; tmp != NULL; tmp = tmp->more) 413 for (tmp = ob->arch; tmp; tmp = tmp->more)
421 { 414 {
422 flag = get_map_flags (m, &m1, x + tmp->clone.x, y + tmp->clone.y, &sx, &sy); 415 flag = get_map_flags (m, &m1, x + tmp->clone.x, y + tmp->clone.y, &sx, &sy);
423 416
424 if (flag & P_OUT_OF_MAP) 417 if (flag & P_OUT_OF_MAP)
425 return P_OUT_OF_MAP; 418 return P_OUT_OF_MAP;
426 if (flag & P_IS_ALIVE) 419 if (flag & P_IS_ALIVE)
427 return P_IS_ALIVE; 420 return P_IS_ALIVE;
428 421
422 mapspace &ms = m1->at (sx, sy);
423
424
429 /* find_first_free_spot() calls this function. However, often 425 /* find_first_free_spot() calls this function. However, often
430 * ob doesn't have any move type (when used to place exits) 426 * ob doesn't have any move type (when used to place exits)
431 * so the AND operation in OB_TYPE_MOVE_BLOCK doesn't work. 427 * so the AND operation in OB_TYPE_MOVE_BLOCK doesn't work.
432 */ 428 */
433 429
434 if (ob->move_type == 0 && GET_MAP_MOVE_BLOCK (m1, sx, sy) != MOVE_ALL) 430 if (ob->move_type == 0 && ms.move_block != MOVE_ALL)
435 continue; 431 continue;
436 432
437 /* Note it is intentional that we check ob - the movement type of the 433 /* Note it is intentional that we check ob - the movement type of the
438 * head of the object should correspond for the entire object. 434 * head of the object should correspond for the entire object.
439 */ 435 */
440 if (OB_TYPE_MOVE_BLOCK (ob, GET_MAP_MOVE_BLOCK (m1, sx, sy))) 436 if (OB_TYPE_MOVE_BLOCK (ob, ms.move_block))
441 return P_NO_PASS; 437 return P_NO_PASS;
442 } 438 }
443 439
444 return 0; 440 return 0;
445} 441}
475 * for objects whose arch says they are multipart yet according to the 471 * for objects whose arch says they are multipart yet according to the
476 * info we have, they only have the head (as would be expected when 472 * info we have, they only have the head (as would be expected when
477 * they are saved). We do have to look for the old maps that did save 473 * they are saved). We do have to look for the old maps that did save
478 * the more sections and not re-add sections for them. 474 * the more sections and not re-add sections for them.
479 */ 475 */
480
481static void 476static void
482link_multipart_objects (maptile *m) 477link_multipart_objects (maptile *m)
483{ 478{
484 int x, y; 479 int x, y;
485 object *tmp, *op, *last, *above; 480 object *tmp, *op, *last, *above;
486 archetype *at; 481 archetype *at;
487 482
488 for (x = 0; x < MAP_WIDTH (m); x++) 483 for (x = 0; x < m->width; x++)
489 for (y = 0; y < MAP_HEIGHT (m); y++) 484 for (y = 0; y < m->height; y++)
490 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = above) 485 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = above)
491 { 486 {
492 above = tmp->above; 487 above = tmp->above;
493 488
494 /* already multipart - don't do anything more */ 489 /* already multipart - don't do anything more */
545 { 540 {
546 LOG (llevDebug, "Discarding object without arch: %s\n", op->name ? (const char *) op->name : "(null)"); 541 LOG (llevDebug, "Discarding object without arch: %s\n", op->name ? (const char *) op->name : "(null)");
547 continue; 542 continue;
548 } 543 }
549 544
550
551 switch (i) 545 switch (i)
552 { 546 {
553 case LL_NORMAL: 547 case LL_NORMAL:
554 /* if we are loading an overlay, put the floors on the bottom */ 548 /* if we are loading an overlay, put the floors on the bottom */
555 if ((QUERY_FLAG (op, FLAG_IS_FLOOR) || QUERY_FLAG (op, FLAG_OVERLAY_FLOOR)) && mapflags & MAP_OVERLAY) 549 if ((QUERY_FLAG (op, FLAG_IS_FLOOR) || QUERY_FLAG (op, FLAG_OVERLAY_FLOOR)) && mapflags & MAP_OVERLAY)
601 * Modified by MSW 2001-07-01 to do in a single pass - reduces code, 595 * Modified by MSW 2001-07-01 to do in a single pass - reduces code,
602 * and we only save the head of multi part objects - this is needed 596 * and we only save the head of multi part objects - this is needed
603 * in order to do map tiling properly. 597 * in order to do map tiling properly.
604 */ 598 */
605void 599void
606save_objects (maptile *m, object_freezer & fp, object_freezer & fp2, int flag) 600save_objects (maptile *m, object_freezer &fp, object_freezer &fp2, int flag)
607{ 601{
608 int i, j = 0, unique = 0; 602 int i, j = 0, unique = 0;
609 object *op; 603 object *op;
610 604
611 /* first pass - save one-part objects */ 605 /* first pass - save one-part objects */
612 for (i = 0; i < MAP_WIDTH (m); i++) 606 for (i = 0; i < m->width; i++)
613 for (j = 0; j < MAP_HEIGHT (m); j++) 607 for (j = 0; j < m->height; j++)
614 { 608 {
615 unique = 0; 609 unique = 0;
610
616 for (op = GET_MAP_OB (m, i, j); op; op = op->above) 611 for (op = m->at (i, j).bot; op; op = op->above)
617 { 612 {
618 if (QUERY_FLAG (op, FLAG_IS_FLOOR) && QUERY_FLAG (op, FLAG_UNIQUE)) 613 if (op->flag [FLAG_UNIQUE] && op->flag [FLAG_IS_FLOOR])
619 unique = 1; 614 unique = 1;
620 615
621 if (op->type == PLAYER) 616 if (!op->can_map_save ())
622 continue; 617 continue;
623 618
624 if (op->head || op->owner)
625 continue;
626
627 if (unique || QUERY_FLAG (op, FLAG_UNIQUE)) 619 if (unique || op->flag [FLAG_UNIQUE])
628 save_object (fp2, op, 3); 620 save_object (fp2, op, 1);
629 else if (flag == 0 || (flag == 2 && (!QUERY_FLAG (op, FLAG_OBJ_ORIGINAL) && !QUERY_FLAG (op, FLAG_UNPAID)))) 621 else if (flag == 0 || (flag == 2 && (!op->flag [FLAG_OBJ_ORIGINAL] && !op->flag [FLAG_UNPAID])))
630 save_object (fp, op, 3); 622 save_object (fp, op, 1);
631 } 623 }
632 } 624 }
633} 625}
634 626
635maptile::maptile () 627maptile::maptile ()
636{ 628{
637 in_memory = MAP_SWAPPED; 629 in_memory = MAP_SWAPPED;
630
638 /* The maps used to pick up default x and y values from the 631 /* The maps used to pick up default x and y values from the
639 * map archetype. Mimic that behaviour. 632 * map archetype. Mimic that behaviour.
640 */ 633 */
641 MAP_WIDTH (this) = 16; 634 width = 16;
642 MAP_HEIGHT (this) = 16; 635 height = 16;
643 MAP_RESET_TIMEOUT (this) = 0; 636 reset_timeout = 0;
644 MAP_TIMEOUT (this) = 300; 637 timeout = 300;
645 MAP_ENTER_X (this) = 0; 638 enter_x = 0;
646 MAP_ENTER_Y (this) = 0; 639 enter_y = 0;
647 /*set part to -1 indicating conversion to weather map not yet done */ 640 /*set part to -1 indicating conversion to weather map not yet done */
648 MAP_WORLDPARTX (this) = -1; 641 worldpartx = -1;
649 MAP_WORLDPARTY (this) = -1; 642 worldparty = -1;
643}
644
645void
646maptile::link ()
647{
648 next = first_map;
649 first_map = this;
650}
651
652void
653maptile::unlink ()
654{
655 if (first_map == this)
656 first_map = next;
657 else
658 for_all_maps (m)
659 if (m->next = this)
660 {
661 m->next = next;
662 break;
663 }
650} 664}
651 665
652/* 666/*
653 * Allocates, initialises, and returns a pointer to a maptile. 667 * Allocates, initialises, and returns a pointer to a maptile.
654 * Modified to no longer take a path option which was not being 668 * Modified to no longer take a path option which was not being
655 * used anyways. MSW 2001-07-01 669 * used anyways. MSW 2001-07-01
656 */ 670 */
657maptile * 671maptile *
658get_linked_map (void) 672get_linked_map (void)
659{ 673{
660 maptile *mp, *map = new maptile; 674 maptile *map = new maptile;
661 675 map->link ();
662 for (mp = first_map; mp && mp->next; mp = mp->next);
663
664 if (mp == NULL)
665 first_map = map;
666 else
667 mp->next = map;
668
669 return map; 676 return map;
670} 677}
671 678
672/* 679/*
673 * Allocates the arrays contained in a maptile. 680 * Allocates the arrays contained in a maptile.
684 * that is their poor assumption. 691 * that is their poor assumption.
685 */ 692 */
686 if (spaces) 693 if (spaces)
687 { 694 {
688 LOG (llevError, "allocate_map called with already allocated map (%s)\n", path); 695 LOG (llevError, "allocate_map called with already allocated map (%s)\n", path);
689 free (spaces); 696 sfree (spaces, size ());
690 } 697 }
691 698
692 spaces = (mapspace *) 699 spaces = salloc0<mapspace> (size ());
693 calloc (1, width * height * sizeof (mapspace));
694
695 if (!spaces)
696 fatal (OUT_OF_MEMORY);
697} 700}
698 701
699/* Create and returns a map of the specific size. Used 702/* Create and returns a map of the specific size. Used
700 * in random map code and the editor. 703 * in random map code and the editor.
701 */ 704 */
734 p = strchr (p, ';'); 737 p = strchr (p, ';');
735 number_of_entries++; 738 number_of_entries++;
736 if (p) 739 if (p)
737 p++; 740 p++;
738 } 741 }
742
739 p = shop_string; 743 p = shop_string;
740 strip_endline (p); 744 strip_endline (p);
741 items = new shopitems[number_of_entries + 1]; 745 items = new shopitems[number_of_entries + 1];
742 for (i = 0; i < number_of_entries; i++) 746 for (i = 0; i < number_of_entries; i++)
743 { 747 {
744 if (!p) 748 if (!p)
745 { 749 {
746 LOG (llevError, "parse_shop_string: I seem to have run out of string, that shouldn't happen.\n"); 750 LOG (llevError, "parse_shop_string: I seem to have run out of string, that shouldn't happen.\n");
747 break; 751 break;
748 } 752 }
753
749 next_semicolon = strchr (p, ';'); 754 next_semicolon = strchr (p, ';');
750 next_colon = strchr (p, ':'); 755 next_colon = strchr (p, ':');
751 /* if there is a stregth specified, figure out what it is, we'll need it soon. */ 756 /* if there is a stregth specified, figure out what it is, we'll need it soon. */
752 if (next_colon && (!next_semicolon || next_colon < next_semicolon)) 757 if (next_colon && (!next_semicolon || next_colon < next_semicolon))
753 items[i].strength = atoi (strchr (p, ':') + 1); 758 items[i].strength = atoi (strchr (p, ':') + 1);
780 * the next entry while we're at it, better print a warning 785 * the next entry while we're at it, better print a warning
781 */ 786 */
782 LOG (llevError, "invalid type %s defined in shopitems in string %s\n", p, input_string); 787 LOG (llevError, "invalid type %s defined in shopitems in string %s\n", p, input_string);
783 } 788 }
784 } 789 }
790
785 items[i].index = number_of_entries; 791 items[i].index = number_of_entries;
786 if (next_semicolon) 792 if (next_semicolon)
787 p = ++next_semicolon; 793 p = ++next_semicolon;
788 else 794 else
789 p = NULL; 795 p = NULL;
790 } 796 }
797
791 free (shop_string); 798 free (shop_string);
792 return items; 799 return items;
793} 800}
794 801
795/* opposite of parse string, this puts the string that was originally fed in to 802/* opposite of parse string, this puts the string that was originally fed in to
804 for (i = 0; i < m->shopitems[0].index; i++) 811 for (i = 0; i < m->shopitems[0].index; i++)
805 { 812 {
806 if (m->shopitems[i].typenum) 813 if (m->shopitems[i].typenum)
807 { 814 {
808 if (m->shopitems[i].strength) 815 if (m->shopitems[i].strength)
809 {
810 sprintf (tmp, "%s:%d;", m->shopitems[i].name, m->shopitems[i].strength); 816 sprintf (tmp, "%s:%d;", m->shopitems[i].name, m->shopitems[i].strength);
811 }
812 else 817 else
813 sprintf (tmp, "%s;", m->shopitems[i].name); 818 sprintf (tmp, "%s;", m->shopitems[i].name);
814 } 819 }
815 else 820 else
816 { 821 {
817 if (m->shopitems[i].strength) 822 if (m->shopitems[i].strength)
818 {
819 sprintf (tmp, "*:%d;", m->shopitems[i].strength); 823 sprintf (tmp, "*:%d;", m->shopitems[i].strength);
820 }
821 else 824 else
822 sprintf (tmp, "*"); 825 sprintf (tmp, "*");
823 } 826 }
827
824 strcat (output_string, tmp); 828 strcat (output_string, tmp);
825 } 829 }
826} 830}
827 831
828/* This loads the header information of the map. The header 832/* This loads the header information of the map. The header
1096 * MAP_BLOCK, in which case we block on this load. This happens in all 1100 * MAP_BLOCK, in which case we block on this load. This happens in all
1097 * cases, no matter if this flag is set or not. 1101 * cases, no matter if this flag is set or not.
1098 * MAP_STYLE: style map - don't add active objects, don't add to server 1102 * MAP_STYLE: style map - don't add active objects, don't add to server
1099 * managed map list. 1103 * managed map list.
1100 */ 1104 */
1101
1102maptile * 1105maptile *
1103load_original_map (const char *filename, int flags) 1106load_original_map (const char *filename, int flags)
1104{ 1107{
1105 maptile *m; 1108 maptile *m;
1106 char pathname[MAX_BUF]; 1109 char pathname[MAX_BUF];
1124 strcpy (m->path, filename); 1127 strcpy (m->path, filename);
1125 if (load_map_header (thawer, m)) 1128 if (load_map_header (thawer, m))
1126 { 1129 {
1127 LOG (llevError, "Error loading map header for %s, flags=%d\n", filename, flags); 1130 LOG (llevError, "Error loading map header for %s, flags=%d\n", filename, flags);
1128 delete_map (m); 1131 delete_map (m);
1129 return NULL; 1132 return 0;
1130 } 1133 }
1131 1134
1132 m->allocate (); 1135 m->allocate ();
1133 1136
1134 m->in_memory = MAP_LOADING; 1137 m->in_memory = MAP_LOADING;
1135 load_objects (m, thawer, flags & (MAP_BLOCK | MAP_STYLE)); 1138 load_objects (m, thawer, flags & (MAP_BLOCK | MAP_STYLE));
1136 1139
1137 m->in_memory = MAP_IN_MEMORY; 1140 m->in_memory = MAP_IN_MEMORY;
1138 if (!MAP_DIFFICULTY (m)) 1141 if (!m->difficulty)
1139 MAP_DIFFICULTY (m) = calculate_difficulty (m); 1142 m->difficulty = calculate_difficulty (m);
1140 set_map_reset_time (m); 1143 set_map_reset_time (m);
1141 m->instantiate (); 1144 m->instantiate ();
1142 return (m); 1145 return (m);
1143} 1146}
1144 1147
1145/* 1148/*
1146 * Loads a map, which has been loaded earlier, from file. 1149 * Loads a map, which has been loaded earlier, from file.
1147 * Return the map object we load into (this can change from the passed 1150 * Return the map object we load into (this can change from the passed
1148 * option if we can't find the original map) 1151 * option if we can't find the original map)
1149 */ 1152 */
1150
1151static maptile * 1153static maptile *
1152load_temporary_map (maptile *m) 1154load_temporary_map (maptile *m)
1153{ 1155{
1154 char buf[MAX_BUF]; 1156 char buf[MAX_BUF];
1155 1157
1199/* 1201/*
1200 * Loads a map, which has been loaded earlier, from file. 1202 * Loads a map, which has been loaded earlier, from file.
1201 * Return the map object we load into (this can change from the passed 1203 * Return the map object we load into (this can change from the passed
1202 * option if we can't find the original map) 1204 * option if we can't find the original map)
1203 */ 1205 */
1204
1205maptile * 1206maptile *
1206load_overlay_map (const char *filename, maptile *m) 1207load_overlay_map (const char *filename, maptile *m)
1207{ 1208{
1208 char pathname[MAX_BUF]; 1209 char pathname[MAX_BUF];
1209 1210
1217 if (load_map_header (thawer, m)) 1218 if (load_map_header (thawer, m))
1218 { 1219 {
1219 LOG (llevError, "Error loading map header for overlay %s (%s)\n", m->path, pathname); 1220 LOG (llevError, "Error loading map header for overlay %s (%s)\n", m->path, pathname);
1220 delete_map (m); 1221 delete_map (m);
1221 m = load_original_map (m->path, 0); 1222 m = load_original_map (m->path, 0);
1222 return NULL; 1223 return 0;
1223 } 1224 }
1224 /*m->allocate ();*/ 1225 /*m->allocate ();*/
1225 1226
1226 m->in_memory = MAP_LOADING; 1227 m->in_memory = MAP_LOADING;
1227 load_objects (m, thawer, MAP_OVERLAY); 1228 load_objects (m, thawer, MAP_OVERLAY);
1239delete_unique_items (maptile *m) 1240delete_unique_items (maptile *m)
1240{ 1241{
1241 int i, j, unique; 1242 int i, j, unique;
1242 object *op, *next; 1243 object *op, *next;
1243 1244
1244 for (i = 0; i < MAP_WIDTH (m); i++) 1245 for (i = 0; i < m->width; i++)
1245 for (j = 0; j < MAP_HEIGHT (m); j++) 1246 for (j = 0; j < m->height; j++)
1246 { 1247 {
1247 unique = 0; 1248 unique = 0;
1248 1249
1249 for (op = GET_MAP_OB (m, i, j); op; op = next) 1250 for (op = GET_MAP_OB (m, i, j); op; op = next)
1250 { 1251 {
1253 if (QUERY_FLAG (op, FLAG_IS_FLOOR) && QUERY_FLAG (op, FLAG_UNIQUE)) 1254 if (QUERY_FLAG (op, FLAG_IS_FLOOR) && QUERY_FLAG (op, FLAG_UNIQUE))
1254 unique = 1; 1255 unique = 1;
1255 1256
1256 if (op->head == NULL && (QUERY_FLAG (op, FLAG_UNIQUE) || unique)) 1257 if (op->head == NULL && (QUERY_FLAG (op, FLAG_UNIQUE) || unique))
1257 { 1258 {
1258 clean_object (op); 1259 op->destroy_inv (false);
1259
1260 if (QUERY_FLAG (op, FLAG_IS_LINKED))
1261 remove_button_link (op);
1262
1263 op->destroy (); 1260 op->destroy ();
1264 } 1261 }
1265 } 1262 }
1266 } 1263 }
1267} 1264}
1268 1265
1269
1270/* 1266/*
1271 * Loads unique objects from file(s) into the map which is in memory 1267 * Loads unique objects from file(s) into the map which is in memory
1272 * m is the map to load unique items into. 1268 * m is the map to load unique items into.
1273 */ 1269 */
1274static void 1270static void
1293 return; 1289 return;
1294 1290
1295 m->in_memory = MAP_LOADING; 1291 m->in_memory = MAP_LOADING;
1296 if (m->tmpname == NULL) /* if we have loaded unique items from */ 1292 if (m->tmpname == NULL) /* if we have loaded unique items from */
1297 delete_unique_items (m); /* original map before, don't duplicate them */ 1293 delete_unique_items (m); /* original map before, don't duplicate them */
1294
1298 load_objects (m, thawer, 0); 1295 load_objects (m, thawer, 0);
1299 1296
1300 m->in_memory = MAP_IN_MEMORY; 1297 m->in_memory = MAP_IN_MEMORY;
1301} 1298}
1302
1303 1299
1304/* 1300/*
1305 * Saves a map to file. If flag is set, it is saved into the same 1301 * Saves a map to file. If flag is set, it is saved into the same
1306 * file it was (originally) loaded from. Otherwise a temporary 1302 * file it was (originally) loaded from. Otherwise a temporary
1307 * filename will be genarated, and the file will be stored there. 1303 * filename will be genarated, and the file will be stored there.
1308 * The temporary filename will be stored in the maptileure. 1304 * The temporary filename will be stored in the maptileure.
1309 * If the map is unique, we also save to the filename in the map 1305 * If the map is unique, we also save to the filename in the map
1310 * (this should have been updated when first loaded) 1306 * (this should have been updated when first loaded)
1311 */ 1307 */
1312
1313int 1308int
1314new_save_map (maptile *m, int flag) 1309new_save_map (maptile *m, int flag)
1315{ 1310{
1316 char filename[MAX_BUF], buf[MAX_BUF], shop[MAX_BUF]; 1311 char filename[MAX_BUF], buf[MAX_BUF], shop[MAX_BUF];
1317 int i; 1312 int i;
1449 freezer.save (filename); 1444 freezer.save (filename);
1450 1445
1451 return 0; 1446 return 0;
1452} 1447}
1453 1448
1454
1455/*
1456 * Remove and free all objects in the inventory of the given object.
1457 * object.c ?
1458 */
1459
1460void
1461clean_object (object *op)
1462{
1463 object *tmp, *next;
1464
1465 for (tmp = op->inv; tmp; tmp = next)
1466 {
1467 next = tmp->below;
1468
1469 clean_object (tmp);
1470 if (QUERY_FLAG (tmp, FLAG_IS_LINKED))
1471 remove_button_link (tmp);
1472
1473 tmp->destroy ();
1474 }
1475}
1476
1477/* 1449/*
1478 * Remove and free all objects in the given map. 1450 * Remove and free all objects in the given map.
1479 */ 1451 */
1480
1481void 1452void
1482free_all_objects (maptile *m) 1453free_all_objects (maptile *m)
1483{ 1454{
1484 int i, j; 1455 if (!m->spaces)
1485 object *op; 1456 return;
1486 1457
1487 for (i = 0; i < MAP_WIDTH (m); i++) 1458 for (int i = 0; i < m->width; i++)
1488 for (j = 0; j < MAP_HEIGHT (m); j++) 1459 for (int j = 0; j < m->height; j++)
1489 { 1460 {
1490 object *previous_obj = NULL; 1461 mapspace &ms = m->at (i, j);
1491 1462
1492 while ((op = GET_MAP_OB (m, i, j)) != NULL) 1463 while (object *op = ms.bot)
1493 { 1464 {
1494 if (op == previous_obj)
1495 {
1496 LOG (llevDebug, "free_all_objects: Link error, bailing out.\n");
1497 break;
1498 }
1499
1500 previous_obj = op;
1501
1502 if (op->head != NULL) 1465 if (op->head)
1503 op = op->head; 1466 op = op->head;
1504 1467
1505 /* If the map isn't in memory, free_object will remove and 1468 op->destroy_inv (false);
1506 * free objects in op's inventory. So let it do the job.
1507 */
1508 if (m->in_memory == MAP_IN_MEMORY)
1509 clean_object (op);
1510
1511 op->destroy (); 1469 op->destroy ();
1512 } 1470 }
1513 } 1471 }
1514} 1472}
1515 1473
1516/* 1474/*
1517 * Frees everything allocated by the given maptileure. 1475 * Frees everything allocated by the given maptileure.
1518 * don't free tmpname - our caller is left to do that 1476 * don't free tmpname - our caller is left to do that
1519 */ 1477 */
1520
1521void 1478void
1522free_map (maptile *m, int flag) 1479free_map (maptile *m, int flag)
1523{ 1480{
1524 int i; 1481 if (!m->in_memory) //TODO: makes no sense to me?
1525
1526 if (!m->in_memory)
1527 {
1528 LOG (llevError, "Trying to free freed map.\n");
1529 return; 1482 return;
1530 } 1483
1484 m->in_memory = MAP_SAVING;
1531 1485
1532 // TODO: use new/delete 1486 // TODO: use new/delete
1533#define FREE_AND_CLEAR(p) { free (p); p = NULL; }
1534 1487
1535 if (flag && m->spaces) 1488 if (flag && m->spaces)
1536 free_all_objects (m); 1489 free_all_objects (m);
1537 if (m->name)
1538 FREE_AND_CLEAR (m->name);
1539 if (m->spaces)
1540 FREE_AND_CLEAR (m->spaces);
1541 if (m->msg)
1542 FREE_AND_CLEAR (m->msg);
1543 if (m->maplore)
1544 FREE_AND_CLEAR (m->maplore);
1545 1490
1546 delete [] m->shopitems; 1491 sfree (m->spaces, m->size ()), m->spaces = 0;
1547 m->shopitems = 0;
1548 1492
1549 if (m->shoprace) 1493 free (m->name), m->name = 0;
1550 FREE_AND_CLEAR (m->shoprace); 1494 free (m->msg), m->msg = 0;
1495 free (m->maplore), m->maplore = 0;
1496 free (m->shoprace), m->shoprace = 0;
1497 delete [] m->shopitems, m->shopitems = 0;
1551 1498
1552 if (m->buttons) 1499 if (m->buttons)
1553 free_objectlinkpt (m->buttons); 1500 free_objectlinkpt (m->buttons), m->buttons = 0;
1554 1501
1555 m->buttons = NULL;
1556
1557 for (i = 0; i < 4; i++) 1502 for (int i = 0; i < 4; i++)
1558 { 1503 free (m->tile_path[i]), m->tile_path[i] = 0;
1559 if (m->tile_path[i])
1560 FREE_AND_CLEAR (m->tile_path[i]);
1561 m->tile_map[i] = NULL;
1562 }
1563 1504
1564 m->in_memory = MAP_SWAPPED; 1505 m->in_memory = MAP_SWAPPED;
1565
1566#undef FREE_AND_CLEAR
1567
1568} 1506}
1569 1507
1570/* 1508maptile::~maptile ()
1571 * function: vanish maptile 1509{
1572 * m : pointer to maptile, if NULL no action 1510 assert (destroyed ());
1573 * this deletes all the data on the map (freeing pointers) 1511}
1574 * and then removes this map from the global linked list of maps. 1512
1513void
1514maptile::do_destroy ()
1515{
1516 attachable::do_destroy ();
1517
1518 unlink ();
1519
1520 free_map (this, 1);
1521 free (tmpname), tmpname = 0;
1522
1523 /* We need to look through all the maps and see if any maps
1524 * are pointing at this one for tiling information. Since
1525 * tiling can be asymetric, we just can not look to see which
1526 * maps this map tiles with and clears those.
1575 */ 1527 */
1528 //TODO: non-euclidean-tiling MUST GO
1529 for_all_maps (m)
1530 for (int i = 0; i < 4; i++)
1531 if (m->tile_map[i] == this)
1532 m->tile_map[i] = 0;
1533}
1576 1534
1535//TODO: must go
1577void 1536void
1578delete_map (maptile *m) 1537delete_map (maptile *m)
1579{ 1538{
1580 maptile *tmp, *last;
1581 int i;
1582
1583 if (!m) 1539 if (m)
1584 return; 1540 m->destroy ();
1585
1586 m->clear ();
1587
1588 if (m->in_memory == MAP_IN_MEMORY)
1589 {
1590 /* change to MAP_SAVING, even though we are not,
1591 * so that remove_ob doesn't do as much work.
1592 */
1593 m->in_memory = MAP_SAVING;
1594 free_map (m, 1);
1595 }
1596 /* move this out of free_map, since tmpname can still be needed if
1597 * the map is swapped out.
1598 */
1599 if (m->tmpname)
1600 {
1601 free (m->tmpname);
1602 m->tmpname = NULL;
1603 }
1604 last = NULL;
1605 /* We need to look through all the maps and see if any maps
1606 * are pointing at this one for tiling information. Since
1607 * tiling can be assymetric, we just can not look to see which
1608 * maps this map tiles with and clears those.
1609 */
1610 for (tmp = first_map; tmp != NULL; tmp = tmp->next)
1611 {
1612 if (tmp->next == m)
1613 last = tmp;
1614
1615 /* This should hopefully get unrolled on a decent compiler */
1616 for (i = 0; i < 4; i++)
1617 if (tmp->tile_map[i] == m)
1618 tmp->tile_map[i] = NULL;
1619 }
1620
1621 /* If last is null, then this should be the first map in the list */
1622 if (!last)
1623 {
1624 if (m == first_map)
1625 first_map = m->next;
1626 else
1627 /* m->path is a static char, so should hopefully still have
1628 * some useful data in it.
1629 */
1630 LOG (llevError, "delete_map: Unable to find map %s in list\n", m->path);
1631 }
1632 else
1633 last->next = m->next;
1634
1635 delete m;
1636} 1541}
1637 1542
1638/* 1543/*
1639 * Makes sure the given map is loaded and swapped in. 1544 * Makes sure the given map is loaded and swapped in.
1640 * name is path name of the map. 1545 * name is path name of the map.
1647 * Returns a pointer to the given map. 1552 * Returns a pointer to the given map.
1648 */ 1553 */
1649maptile * 1554maptile *
1650ready_map_name (const char *name, int flags) 1555ready_map_name (const char *name, int flags)
1651{ 1556{
1652 maptile *m;
1653
1654 if (!name) 1557 if (!name)
1655 return (NULL); 1558 return 0;
1656 1559
1657 /* Have we been at this level before? */ 1560 /* Have we been at this level before? */
1658 m = has_been_loaded (name); 1561 maptile *m = has_been_loaded (name);
1659 1562
1660 /* Map is good to go, so just return it */ 1563 /* Map is good to go, so just return it */
1661 if (m && (m->in_memory == MAP_LOADING || m->in_memory == MAP_IN_MEMORY)) 1564 if (m && (m->in_memory == MAP_LOADING || m->in_memory == MAP_IN_MEMORY))
1662 {
1663 return m; 1565 return m;
1664 }
1665 1566
1666 /* unique maps always get loaded from their original location, and never 1567 /* unique maps always get loaded from their original location, and never
1667 * a temp location. Likewise, if map_flush is set, or we have never loaded 1568 * a temp location. Likewise, if map_flush is set, or we have never loaded
1668 * this map, load it now. I removed the reset checking from here - 1569 * this map, load it now. I removed the reset checking from here -
1669 * it seems the probability of a player trying to enter a map that should 1570 * it seems the probability of a player trying to enter a map that should
1671 * a bit cleaner (and players probably shouldn't rely on exact timing for 1572 * a bit cleaner (and players probably shouldn't rely on exact timing for
1672 * resets in any case - if they really care, they should use the 'maps command. 1573 * resets in any case - if they really care, they should use the 'maps command.
1673 */ 1574 */
1674 if ((flags & (MAP_FLUSH | MAP_PLAYER_UNIQUE)) || !m) 1575 if ((flags & (MAP_FLUSH | MAP_PLAYER_UNIQUE)) || !m)
1675 { 1576 {
1676
1677 /* first visit or time to reset */ 1577 /* first visit or time to reset */
1678 if (m) 1578 if (m)
1679 { 1579 {
1680 clean_tmp_map (m); /* Doesn't make much difference */ 1580 clean_tmp_map (m); /* Doesn't make much difference */
1681 delete_map (m); 1581 delete_map (m);
1685 if (flags & MAP_PLAYER_UNIQUE) 1585 if (flags & MAP_PLAYER_UNIQUE)
1686 LOG (llevDebug, "Trying to load map %s.\n", name); 1586 LOG (llevDebug, "Trying to load map %s.\n", name);
1687 else 1587 else
1688 LOG (llevDebug, "Trying to load map %s.\n", create_pathname (name)); 1588 LOG (llevDebug, "Trying to load map %s.\n", create_pathname (name));
1689 1589
1690 //eval_pv ("$x = Event::time", 1);//D
1691 if (!(m = load_original_map (name, (flags & MAP_PLAYER_UNIQUE)))) 1590 if (!(m = load_original_map (name, (flags & MAP_PLAYER_UNIQUE))))
1692 return (NULL); 1591 return (NULL);
1693 //eval_pv ("warn \"LOAD \", Event::time - $x", 1);//D
1694 1592
1695 fix_auto_apply (m); /* Chests which open as default */ 1593 fix_auto_apply (m); /* Chests which open as default */
1696 1594
1697 /* If a player unique map, no extra unique object file to load. 1595 /* If a player unique map, no extra unique object file to load.
1698 * if from the editor, likewise. 1596 * if from the editor, likewise.
1768 int x, y, i; 1666 int x, y, i;
1769 long monster_cnt = 0; 1667 long monster_cnt = 0;
1770 double avgexp = 0; 1668 double avgexp = 0;
1771 sint64 total_exp = 0; 1669 sint64 total_exp = 0;
1772 1670
1773 if (MAP_DIFFICULTY (m)) 1671 if (m->difficulty)
1774 { 1672 {
1775 LOG (llevDebug, "Using stored map difficulty: %d\n", MAP_DIFFICULTY (m)); 1673 LOG (llevDebug, "Using stored map difficulty: %d\n", m->difficulty);
1776 return MAP_DIFFICULTY (m); 1674 return m->difficulty;
1777 } 1675 }
1778 1676
1779 for (x = 0; x < MAP_WIDTH (m); x++) 1677 for (x = 0; x < m->width; x++)
1780 for (y = 0; y < MAP_HEIGHT (m); y++) 1678 for (y = 0; y < m->height; y++)
1781 for (op = GET_MAP_OB (m, x, y); op != NULL; op = op->above) 1679 for (op = GET_MAP_OB (m, x, y); op != NULL; op = op->above)
1782 { 1680 {
1783 if (QUERY_FLAG (op, FLAG_MONSTER)) 1681 if (QUERY_FLAG (op, FLAG_MONSTER))
1784 { 1682 {
1785 total_exp += op->stats.exp; 1683 total_exp += op->stats.exp;
1834 if (first_map->in_memory == MAP_SAVING) 1732 if (first_map->in_memory == MAP_SAVING)
1835 first_map->in_memory = MAP_IN_MEMORY; 1733 first_map->in_memory = MAP_IN_MEMORY;
1836 delete_map (first_map); 1734 delete_map (first_map);
1837 real_maps++; 1735 real_maps++;
1838 } 1736 }
1737
1839 LOG (llevDebug, "free_all_maps: Freed %d maps\n", real_maps); 1738 LOG (llevDebug, "free_all_maps: Freed %d maps\n", real_maps);
1840} 1739}
1841 1740
1842/* change_map_light() - used to change map light level (darkness) 1741/* change_map_light() - used to change map light level (darkness)
1843 * up or down. Returns true if successful. It should now be 1742 * up or down. Returns true if successful. It should now be
1886 * on the map (what it looks like, whether it blocks magic, 1785 * on the map (what it looks like, whether it blocks magic,
1887 * has a living creatures, prevents people from passing 1786 * has a living creatures, prevents people from passing
1888 * through, etc) 1787 * through, etc)
1889 */ 1788 */
1890void 1789void
1891update_position (maptile *m, int x, int y) 1790mapspace::update_ ()
1892{ 1791{
1893 object *tmp, *last = 0; 1792 object *tmp, *last = 0;
1894 uint8 flags = 0, oldflags, light = 0, anywhere = 0; 1793 uint8 flags = 0, light = 0, anywhere = 0;
1895 New_Face *top, *floor, *middle; 1794 New_Face *top, *floor, *middle;
1896 object *top_obj, *floor_obj, *middle_obj; 1795 object *top_obj, *floor_obj, *middle_obj;
1897 MoveType move_block = 0, move_slow = 0, move_on = 0, move_off = 0, move_allow = 0; 1796 MoveType move_block = 0, move_slow = 0, move_on = 0, move_off = 0, move_allow = 0;
1898 1797
1899 oldflags = GET_MAP_FLAGS (m, x, y);
1900 if (!(oldflags & P_NEED_UPDATE))
1901 {
1902 LOG (llevDebug, "update_position called with P_NEED_UPDATE not set: %s (%d, %d)\n", m->path, x, y);
1903 return;
1904 }
1905
1906 middle = blank_face; 1798 middle = blank_face;
1907 top = blank_face; 1799 top = blank_face;
1908 floor = blank_face; 1800 floor = blank_face;
1909 1801
1910 middle_obj = 0; 1802 middle_obj = 0;
1911 top_obj = 0; 1803 top_obj = 0;
1912 floor_obj = 0; 1804 floor_obj = 0;
1913 1805
1914 for (tmp = GET_MAP_OB (m, x, y); tmp; last = tmp, tmp = tmp->above) 1806 for (tmp = bot; tmp; last = tmp, tmp = tmp->above)
1915 { 1807 {
1916 /* This could be made additive I guess (two lights better than 1808 /* This could be made additive I guess (two lights better than
1917 * one). But if so, it shouldn't be a simple additive - 2 1809 * one). But if so, it shouldn't be a simple additive - 2
1918 * light bulbs do not illuminate twice as far as once since 1810 * light bulbs do not illuminate twice as far as once since
1919 * it is a dissapation factor that is cubed. 1811 * it is a dissapation factor that is cubed.
1983 if (tmp->type == SAFE_GROUND) flags |= P_SAFE; 1875 if (tmp->type == SAFE_GROUND) flags |= P_SAFE;
1984 if (QUERY_FLAG (tmp, FLAG_ALIVE)) flags |= P_IS_ALIVE; 1876 if (QUERY_FLAG (tmp, FLAG_ALIVE)) flags |= P_IS_ALIVE;
1985 if (QUERY_FLAG (tmp, FLAG_DAMNED)) flags |= P_NO_CLERIC; 1877 if (QUERY_FLAG (tmp, FLAG_DAMNED)) flags |= P_NO_CLERIC;
1986 } 1878 }
1987 1879
1988 /* we don't want to rely on this function to have accurate flags, but 1880 this->light = light;
1989 * since we're already doing the work, we calculate them here.
1990 * if they don't match, logic is broken someplace.
1991 */
1992 if (((oldflags & ~(P_NEED_UPDATE | P_NO_ERROR)) != flags) && (!(oldflags & P_NO_ERROR)))
1993 LOG (llevDebug, "update_position: updated flags do not match old flags: %s (old=%d,new=%d) %x != %x\n",
1994 m->path, x, y, (oldflags & ~P_NEED_UPDATE), flags);
1995
1996 mapspace &s = m->at (x, y);
1997
1998 s.flags = flags; 1881 this->flags_ = flags;
1999 s.move_block = move_block & ~move_allow; 1882 this->move_block = move_block & ~move_allow;
2000 s.move_on = move_on; 1883 this->move_on = move_on;
2001 s.move_off = move_off; 1884 this->move_off = move_off;
2002 s.move_slow = move_slow; 1885 this->move_slow = move_slow;
2003 1886
2004 /* At this point, we have a floor face (if there is a floor), 1887 /* At this point, we have a floor face (if there is a floor),
2005 * and the floor is set - we are not going to touch it at 1888 * and the floor is set - we are not going to touch it at
2006 * this point. 1889 * this point.
2007 * middle contains the highest visibility face. 1890 * middle contains the highest visibility face.
2068 middle = blank_face; 1951 middle = blank_face;
2069 1952
2070 if (top == middle) 1953 if (top == middle)
2071 middle = blank_face; 1954 middle = blank_face;
2072 1955
2073 SET_MAP_FACE (m, x, y, top, 0); 1956 faces [0] = top; faces_obj [0] = top != blank_face ? top_obj : 0;
2074 if (top != blank_face) 1957 faces [1] = middle; faces_obj [1] = middle != blank_face ? middle_obj : 0;
2075 SET_MAP_FACE_OBJ (m, x, y, top_obj, 0); 1958 faces [2] = floor; faces_obj [2] = floor != blank_face ? floor_obj : 0;
2076 else
2077 SET_MAP_FACE_OBJ (m, x, y, NULL, 0);
2078
2079 SET_MAP_FACE (m, x, y, middle, 1);
2080 if (middle != blank_face)
2081 SET_MAP_FACE_OBJ (m, x, y, middle_obj, 1);
2082 else
2083 SET_MAP_FACE_OBJ (m, x, y, NULL, 1);
2084
2085 SET_MAP_FACE (m, x, y, floor, 2);
2086 if (floor != blank_face)
2087 SET_MAP_FACE_OBJ (m, x, y, floor_obj, 2);
2088 else
2089 SET_MAP_FACE_OBJ (m, x, y, NULL, 2);
2090
2091 SET_MAP_LIGHT (m, x, y, light);
2092} 1959}
2093
2094 1960
2095void 1961void
2096set_map_reset_time (maptile *map) 1962set_map_reset_time (maptile *map)
2097{ 1963{
2098 int timeout; 1964 int timeout;
2099 1965
2100 timeout = MAP_RESET_TIMEOUT (map); 1966 timeout = map->reset_timeout;
2101 if (timeout <= 0) 1967 if (timeout <= 0)
2102 timeout = MAP_DEFAULTRESET; 1968 timeout = MAP_DEFAULTRESET;
2103 if (timeout >= MAP_MAXRESET) 1969 if (timeout >= MAP_MAXRESET)
2104 timeout = MAP_MAXRESET; 1970 timeout = MAP_MAXRESET;
2105 MAP_WHEN_RESET (map) = time (0) + timeout; 1971 map->reset_time = time (0) + timeout;
2106} 1972}
2107 1973
2108/* this updates the orig_map->tile_map[tile_num] value after loading 1974/* this updates the orig_map->tile_map[tile_num] value after loading
2109 * the map. It also takes care of linking back the freshly loaded 1975 * the map. It also takes care of linking back the freshly loaded
2110 * maps tile_map values if it tiles back to this one. It returns 1976 * maps tile_map values if it tiles back to this one. It returns
2138 * 2004 *
2139 */ 2005 */
2140int 2006int
2141out_of_map (maptile *m, int x, int y) 2007out_of_map (maptile *m, int x, int y)
2142{ 2008{
2143
2144 /* If we get passed a null map, this is obviously the 2009 /* If we get passed a null map, this is obviously the
2145 * case. This generally shouldn't happen, but if the 2010 * case. This generally shouldn't happen, but if the
2146 * map loads fail below, it could happen. 2011 * map loads fail below, it could happen.
2147 */ 2012 */
2148 if (!m) 2013 if (!m)
2150 2015
2151 if (x < 0) 2016 if (x < 0)
2152 { 2017 {
2153 if (!m->tile_path[3]) 2018 if (!m->tile_path[3])
2154 return 1; 2019 return 1;
2020
2155 if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY) 2021 if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY)
2156 {
2157 load_and_link_tiled_map (m, 3); 2022 load_and_link_tiled_map (m, 3);
2158 } 2023
2159 return (out_of_map (m->tile_map[3], x + MAP_WIDTH (m->tile_map[3]), y)); 2024 return (out_of_map (m->tile_map[3], x + m->tile_map[3]->width, y));
2160 } 2025 }
2161 if (x >= MAP_WIDTH (m)) 2026
2027 if (x >= m->width)
2162 { 2028 {
2163 if (!m->tile_path[1]) 2029 if (!m->tile_path[1])
2164 return 1; 2030 return 1;
2031
2165 if (!m->tile_map[1] || m->tile_map[1]->in_memory != MAP_IN_MEMORY) 2032 if (!m->tile_map[1] || m->tile_map[1]->in_memory != MAP_IN_MEMORY)
2166 {
2167 load_and_link_tiled_map (m, 1); 2033 load_and_link_tiled_map (m, 1);
2168 } 2034
2169 return (out_of_map (m->tile_map[1], x - MAP_WIDTH (m), y)); 2035 return (out_of_map (m->tile_map[1], x - m->width, y));
2170 } 2036 }
2037
2171 if (y < 0) 2038 if (y < 0)
2172 { 2039 {
2173 if (!m->tile_path[0]) 2040 if (!m->tile_path[0])
2174 return 1; 2041 return 1;
2042
2175 if (!m->tile_map[0] || m->tile_map[0]->in_memory != MAP_IN_MEMORY) 2043 if (!m->tile_map[0] || m->tile_map[0]->in_memory != MAP_IN_MEMORY)
2176 {
2177 load_and_link_tiled_map (m, 0); 2044 load_and_link_tiled_map (m, 0);
2178 } 2045
2179 return (out_of_map (m->tile_map[0], x, y + MAP_HEIGHT (m->tile_map[0]))); 2046 return (out_of_map (m->tile_map[0], x, y + m->tile_map[0]->height));
2180 } 2047 }
2181 if (y >= MAP_HEIGHT (m)) 2048
2049 if (y >= m->height)
2182 { 2050 {
2183 if (!m->tile_path[2]) 2051 if (!m->tile_path[2])
2184 return 1; 2052 return 1;
2053
2185 if (!m->tile_map[2] || m->tile_map[2]->in_memory != MAP_IN_MEMORY) 2054 if (!m->tile_map[2] || m->tile_map[2]->in_memory != MAP_IN_MEMORY)
2186 {
2187 load_and_link_tiled_map (m, 2); 2055 load_and_link_tiled_map (m, 2);
2188 } 2056
2189 return (out_of_map (m->tile_map[2], x, y - MAP_HEIGHT (m))); 2057 return (out_of_map (m->tile_map[2], x, y - m->height));
2190 } 2058 }
2191 2059
2192 /* Simple case - coordinates are within this local 2060 /* Simple case - coordinates are within this local
2193 * map. 2061 * map.
2194 */ 2062 */
2208{ 2076{
2209 2077
2210 if (*x < 0) 2078 if (*x < 0)
2211 { 2079 {
2212 if (!m->tile_path[3]) 2080 if (!m->tile_path[3])
2213 return NULL; 2081 return 0;
2214 if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY) 2082 if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY)
2215 load_and_link_tiled_map (m, 3); 2083 load_and_link_tiled_map (m, 3);
2216 2084
2217 *x += MAP_WIDTH (m->tile_map[3]); 2085 *x += m->tile_map[3]->width;
2218 return (get_map_from_coord (m->tile_map[3], x, y)); 2086 return (get_map_from_coord (m->tile_map[3], x, y));
2219 } 2087 }
2220 if (*x >= MAP_WIDTH (m)) 2088
2089 if (*x >= m->width)
2221 { 2090 {
2222 if (!m->tile_path[1]) 2091 if (!m->tile_path[1])
2223 return NULL; 2092 return 0;
2093
2224 if (!m->tile_map[1] || m->tile_map[1]->in_memory != MAP_IN_MEMORY) 2094 if (!m->tile_map[1] || m->tile_map[1]->in_memory != MAP_IN_MEMORY)
2225 load_and_link_tiled_map (m, 1); 2095 load_and_link_tiled_map (m, 1);
2226 2096
2227 *x -= MAP_WIDTH (m); 2097 *x -= m->width;
2228 return (get_map_from_coord (m->tile_map[1], x, y)); 2098 return (get_map_from_coord (m->tile_map[1], x, y));
2229 } 2099 }
2100
2230 if (*y < 0) 2101 if (*y < 0)
2231 { 2102 {
2232 if (!m->tile_path[0]) 2103 if (!m->tile_path[0])
2233 return NULL; 2104 return 0;
2105
2234 if (!m->tile_map[0] || m->tile_map[0]->in_memory != MAP_IN_MEMORY) 2106 if (!m->tile_map[0] || m->tile_map[0]->in_memory != MAP_IN_MEMORY)
2235 load_and_link_tiled_map (m, 0); 2107 load_and_link_tiled_map (m, 0);
2236 2108
2237 *y += MAP_HEIGHT (m->tile_map[0]); 2109 *y += m->tile_map[0]->height;
2238 return (get_map_from_coord (m->tile_map[0], x, y)); 2110 return (get_map_from_coord (m->tile_map[0], x, y));
2239 } 2111 }
2240 if (*y >= MAP_HEIGHT (m)) 2112
2113 if (*y >= m->height)
2241 { 2114 {
2242 if (!m->tile_path[2]) 2115 if (!m->tile_path[2])
2243 return NULL; 2116 return 0;
2117
2244 if (!m->tile_map[2] || m->tile_map[2]->in_memory != MAP_IN_MEMORY) 2118 if (!m->tile_map[2] || m->tile_map[2]->in_memory != MAP_IN_MEMORY)
2245 load_and_link_tiled_map (m, 2); 2119 load_and_link_tiled_map (m, 2);
2246 2120
2247 *y -= MAP_HEIGHT (m); 2121 *y -= m->height;
2248 return (get_map_from_coord (m->tile_map[2], x, y)); 2122 return (get_map_from_coord (m->tile_map[2], x, y));
2249 } 2123 }
2250 2124
2251 /* Simple case - coordinates are within this local 2125 /* Simple case - coordinates are within this local
2252 * map. 2126 * map.
2272 2146
2273 } 2147 }
2274 else if (map1->tile_map[0] == map2) 2148 else if (map1->tile_map[0] == map2)
2275 { /* up */ 2149 { /* up */
2276 *dx = 0; 2150 *dx = 0;
2277 *dy = -MAP_HEIGHT (map2); 2151 *dy = -map2->height;
2278 } 2152 }
2279 else if (map1->tile_map[1] == map2) 2153 else if (map1->tile_map[1] == map2)
2280 { /* right */ 2154 { /* right */
2281 *dx = MAP_WIDTH (map1); 2155 *dx = map1->width;
2282 *dy = 0; 2156 *dy = 0;
2283 } 2157 }
2284 else if (map1->tile_map[2] == map2) 2158 else if (map1->tile_map[2] == map2)
2285 { /* down */ 2159 { /* down */
2286 *dx = 0; 2160 *dx = 0;
2287 *dy = MAP_HEIGHT (map1); 2161 *dy = map1->height;
2288 } 2162 }
2289 else if (map1->tile_map[3] == map2) 2163 else if (map1->tile_map[3] == map2)
2290 { /* left */ 2164 { /* left */
2291 *dx = -MAP_WIDTH (map2); 2165 *dx = -map2->width;
2292 *dy = 0; 2166 *dy = 0;
2293 2167
2294 } 2168 }
2295 else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[1] == map2) 2169 else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[1] == map2)
2296 { /* up right */ 2170 { /* up right */
2297 *dx = MAP_WIDTH (map1->tile_map[0]); 2171 *dx = map1->tile_map[0]->width;
2298 *dy = -MAP_HEIGHT (map1->tile_map[0]); 2172 *dy = -map1->tile_map[0]->height;
2299 } 2173 }
2300 else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[3] == map2) 2174 else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[3] == map2)
2301 { /* up left */ 2175 { /* up left */
2302 *dx = -MAP_WIDTH (map2); 2176 *dx = -map2->width;
2303 *dy = -MAP_HEIGHT (map1->tile_map[0]); 2177 *dy = -map1->tile_map[0]->height;
2304 } 2178 }
2305 else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[0] == map2) 2179 else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[0] == map2)
2306 { /* right up */ 2180 { /* right up */
2307 *dx = MAP_WIDTH (map1); 2181 *dx = map1->width;
2308 *dy = -MAP_HEIGHT (map2); 2182 *dy = -map2->height;
2309 } 2183 }
2310 else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[2] == map2) 2184 else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[2] == map2)
2311 { /* right down */ 2185 { /* right down */
2312 *dx = MAP_WIDTH (map1); 2186 *dx = map1->width;
2313 *dy = MAP_HEIGHT (map1->tile_map[1]); 2187 *dy = map1->tile_map[1]->height;
2314 } 2188 }
2315 else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[1] == map2) 2189 else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[1] == map2)
2316 { /* down right */ 2190 { /* down right */
2317 *dx = MAP_WIDTH (map1->tile_map[2]); 2191 *dx = map1->tile_map[2]->width;
2318 *dy = MAP_HEIGHT (map1); 2192 *dy = map1->height;
2319 } 2193 }
2320 else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[3] == map2) 2194 else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[3] == map2)
2321 { /* down left */ 2195 { /* down left */
2322 *dx = -MAP_WIDTH (map2); 2196 *dx = -map2->width;
2323 *dy = MAP_HEIGHT (map1); 2197 *dy = map1->height;
2324 } 2198 }
2325 else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[0] == map2) 2199 else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[0] == map2)
2326 { /* left up */ 2200 { /* left up */
2327 *dx = -MAP_WIDTH (map1->tile_map[3]); 2201 *dx = -map1->tile_map[3]->width;
2328 *dy = -MAP_HEIGHT (map2); 2202 *dy = -map2->height;
2329 } 2203 }
2330 else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[2] == map2) 2204 else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[2] == map2)
2331 { /* left down */ 2205 { /* left down */
2332 *dx = -MAP_WIDTH (map1->tile_map[3]); 2206 *dx = -map1->tile_map[3]->width;
2333 *dy = MAP_HEIGHT (map1->tile_map[3]); 2207 *dy = map1->tile_map[3]->height;
2334 2208
2335 } 2209 }
2336 else 2210 else
2337 { /* not "adjacent" enough */ 2211 { /* not "adjacent" enough */
2338 return 0; 2212 return 0;
2463{ 2337{
2464 int dx, dy; 2338 int dx, dy;
2465 2339
2466 return adjacent_map (op1->map, op2->map, &dx, &dy); 2340 return adjacent_map (op1->map, op2->map, &dx, &dy);
2467} 2341}
2342
2343object *
2344maptile::insert (object *op, int x, int y, object *originator, int flags)
2345{
2346 if (!op->flag [FLAG_REMOVED])
2347 op->remove ();
2348
2349 return insert_ob_in_map_at (op, this, originator, flags, x, y);
2350}
2351

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines