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.49 by root, Mon Dec 25 14:54:44 2006 UTC vs.
Revision 1.55 by root, Wed Dec 27 18:09:48 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>
35 * return NULL if no match is found. 34 * return NULL if no match is found.
36 */ 35 */
37maptile * 36maptile *
38has_been_loaded (const char *name) 37has_been_loaded (const char *name)
39{ 38{
40 maptile *map;
41
42 if (!name || !*name) 39 if (!name || !*name)
43 return 0; 40 return 0;
44 41
45 for (map = first_map; map; map = map->next) 42 for_all_maps (map)
46 if (!strcmp (name, map->path)) 43 if (!strcmp (name, map->path))
47 break;
48
49 return (map); 44 return map;
45
46 return 0;
50} 47}
51 48
52/* 49/*
53 * This makes a path absolute outside the world of Crossfire. 50 * This makes a path absolute outside the world of Crossfire.
54 * In other words, it prepends LIBDIR/MAPDIR/ to the given path 51 * In other words, it prepends LIBDIR/MAPDIR/ to the given path
221 */ 218 */
222 219
223void 220void
224dump_all_maps (void) 221dump_all_maps (void)
225{ 222{
226 maptile *m; 223 for_all_maps (m)
227
228 for (m = first_map; m; m = m->next)
229 dump_map (m); 224 dump_map (m);
230} 225}
231 226
232/* This rolls up wall, blocks_magic, blocks_view, etc, all into 227/* This rolls up wall, blocks_magic, blocks_view, etc, all into
233 * one function that just returns a P_.. value (see map.h) 228 * one function that just returns a P_.. value (see map.h)
476 * 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
477 * 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
478 * 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
479 * the more sections and not re-add sections for them. 474 * the more sections and not re-add sections for them.
480 */ 475 */
481
482static void 476static void
483link_multipart_objects (maptile *m) 477link_multipart_objects (maptile *m)
484{ 478{
485 int x, y; 479 int x, y;
486 object *tmp, *op, *last, *above; 480 object *tmp, *op, *last, *above;
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 < m->width; i++) 606 for (i = 0; i < m->width; i++)
613 for (j = 0; j < m->height; j++) 607 for (j = 0; j < m->height; j++)
614 { 608 {
615 unique = 0; 609 unique = 0;
610
616 for (op = m->at (i, j).bot; op; op = op->above) 611 for (op = m->at (i, j).bot; op; op = op->above)
617 { 612 {
618 if (op->flag [FLAG_IS_FLOOR] && op->flag [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 || op->flag [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 && (!op->flag [FLAG_OBJ_ORIGINAL] && !op->flag [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 this->width = 16; 634 width = 16;
642 this->height = 16; 635 height = 16;
643 this->reset_timeout = 0; 636 reset_timeout = 0;
644 this->timeout = 300; 637 timeout = 300;
645 this->enter_x = 0; 638 enter_x = 0;
646 this->enter_y = 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 this->worldpartx = -1; 641 worldpartx = -1;
649 this->worldparty = -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 {
659 for_all_maps (m)
660 if (m->next = this)
661 {
662 m->next = next;
663 return;
664 }
665
666 LOG (llevError, "maptile::unlink() map not on list: %s\n", path);
667 }
650} 668}
651 669
652/* 670/*
653 * Allocates, initialises, and returns a pointer to a maptile. 671 * Allocates, initialises, and returns a pointer to a maptile.
654 * Modified to no longer take a path option which was not being 672 * Modified to no longer take a path option which was not being
655 * used anyways. MSW 2001-07-01 673 * used anyways. MSW 2001-07-01
656 */ 674 */
657maptile * 675maptile *
658get_linked_map (void) 676get_linked_map (void)
659{ 677{
660 maptile *mp, *map = new maptile; 678 maptile *map = new maptile;
661 679 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; 680 return map;
670} 681}
671 682
672/* 683/*
673 * Allocates the arrays contained in a maptile. 684 * Allocates the arrays contained in a maptile.
684 * that is their poor assumption. 695 * that is their poor assumption.
685 */ 696 */
686 if (spaces) 697 if (spaces)
687 { 698 {
688 LOG (llevError, "allocate_map called with already allocated map (%s)\n", path); 699 LOG (llevError, "allocate_map called with already allocated map (%s)\n", path);
689 free (spaces); 700 sfree (spaces, size ());
690 } 701 }
691 702
692 spaces = (mapspace *) 703 spaces = salloc0<mapspace> (size ());
693 calloc (1, width * height * sizeof (mapspace));
694
695 if (!spaces)
696 fatal (OUT_OF_MEMORY);
697} 704}
698 705
699/* Create and returns a map of the specific size. Used 706/* Create and returns a map of the specific size. Used
700 * in random map code and the editor. 707 * in random map code and the editor.
701 */ 708 */
702maptile * 709maptile *
703get_empty_map (int sizex, int sizey) 710get_empty_map (int sizex, int sizey)
704{ 711{
705 maptile *m = get_linked_map (); 712 maptile *m = get_linked_map ();
706 713
707 m->width = sizex; 714 m->width = sizex;
708 m->height = sizey; 715 m->height = sizey;
709 m->in_memory = MAP_SWAPPED; 716 m->in_memory = MAP_SWAPPED;
717
710 m->allocate (); 718 m->allocate ();
711 719
712 return m; 720 return m;
713} 721}
714 722
715/* Takes a string from a map definition and outputs a pointer to the array of shopitems 723/* Takes a string from a map definition and outputs a pointer to the array of shopitems
716 * corresponding to that string. Memory is allocated for this, it must be freed 724 * corresponding to that string. Memory is allocated for this, it must be freed
717 * at a later date. 725 * at a later date.
718 * Called by parse_map_headers below. 726 * Called by parse_map_headers below.
719 */ 727 */
720
721static shopitems * 728static shopitems *
722parse_shop_string (const char *input_string) 729parse_shop_string (const char *input_string)
723{ 730{
724 char *shop_string, *p, *q, *next_semicolon, *next_colon; 731 char *shop_string, *p, *q, *next_semicolon, *next_colon;
725 shopitems *items = NULL; 732 shopitems *items = NULL;
734 p = strchr (p, ';'); 741 p = strchr (p, ';');
735 number_of_entries++; 742 number_of_entries++;
736 if (p) 743 if (p)
737 p++; 744 p++;
738 } 745 }
746
739 p = shop_string; 747 p = shop_string;
740 strip_endline (p); 748 strip_endline (p);
741 items = new shopitems[number_of_entries + 1]; 749 items = new shopitems[number_of_entries + 1];
742 for (i = 0; i < number_of_entries; i++) 750 for (i = 0; i < number_of_entries; i++)
743 { 751 {
744 if (!p) 752 if (!p)
745 { 753 {
746 LOG (llevError, "parse_shop_string: I seem to have run out of string, that shouldn't happen.\n"); 754 LOG (llevError, "parse_shop_string: I seem to have run out of string, that shouldn't happen.\n");
747 break; 755 break;
748 } 756 }
757
749 next_semicolon = strchr (p, ';'); 758 next_semicolon = strchr (p, ';');
750 next_colon = strchr (p, ':'); 759 next_colon = strchr (p, ':');
751 /* if there is a stregth specified, figure out what it is, we'll need it soon. */ 760 /* 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)) 761 if (next_colon && (!next_semicolon || next_colon < next_semicolon))
753 items[i].strength = atoi (strchr (p, ':') + 1); 762 items[i].strength = atoi (strchr (p, ':') + 1);
780 * the next entry while we're at it, better print a warning 789 * the next entry while we're at it, better print a warning
781 */ 790 */
782 LOG (llevError, "invalid type %s defined in shopitems in string %s\n", p, input_string); 791 LOG (llevError, "invalid type %s defined in shopitems in string %s\n", p, input_string);
783 } 792 }
784 } 793 }
794
785 items[i].index = number_of_entries; 795 items[i].index = number_of_entries;
786 if (next_semicolon) 796 if (next_semicolon)
787 p = ++next_semicolon; 797 p = ++next_semicolon;
788 else 798 else
789 p = NULL; 799 p = NULL;
790 } 800 }
801
791 free (shop_string); 802 free (shop_string);
792 return items; 803 return items;
793} 804}
794 805
795/* opposite of parse string, this puts the string that was originally fed in to 806/* opposite of parse string, this puts the string that was originally fed in to
804 for (i = 0; i < m->shopitems[0].index; i++) 815 for (i = 0; i < m->shopitems[0].index; i++)
805 { 816 {
806 if (m->shopitems[i].typenum) 817 if (m->shopitems[i].typenum)
807 { 818 {
808 if (m->shopitems[i].strength) 819 if (m->shopitems[i].strength)
809 {
810 sprintf (tmp, "%s:%d;", m->shopitems[i].name, m->shopitems[i].strength); 820 sprintf (tmp, "%s:%d;", m->shopitems[i].name, m->shopitems[i].strength);
811 }
812 else 821 else
813 sprintf (tmp, "%s;", m->shopitems[i].name); 822 sprintf (tmp, "%s;", m->shopitems[i].name);
814 } 823 }
815 else 824 else
816 { 825 {
817 if (m->shopitems[i].strength) 826 if (m->shopitems[i].strength)
818 {
819 sprintf (tmp, "*:%d;", m->shopitems[i].strength); 827 sprintf (tmp, "*:%d;", m->shopitems[i].strength);
820 }
821 else 828 else
822 sprintf (tmp, "*"); 829 sprintf (tmp, "*");
823 } 830 }
831
824 strcat (output_string, tmp); 832 strcat (output_string, tmp);
825 } 833 }
826} 834}
827 835
828/* This loads the header information of the map. The header 836/* 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 1104 * 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. 1105 * 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 1106 * MAP_STYLE: style map - don't add active objects, don't add to server
1099 * managed map list. 1107 * managed map list.
1100 */ 1108 */
1101
1102maptile * 1109maptile *
1103load_original_map (const char *filename, int flags) 1110load_original_map (const char *filename, int flags)
1104{ 1111{
1105 maptile *m; 1112 maptile *m;
1106 char pathname[MAX_BUF]; 1113 char pathname[MAX_BUF];
1145/* 1152/*
1146 * Loads a map, which has been loaded earlier, from file. 1153 * Loads a map, which has been loaded earlier, from file.
1147 * Return the map object we load into (this can change from the passed 1154 * Return the map object we load into (this can change from the passed
1148 * option if we can't find the original map) 1155 * option if we can't find the original map)
1149 */ 1156 */
1150
1151static maptile * 1157static maptile *
1152load_temporary_map (maptile *m) 1158load_temporary_map (maptile *m)
1153{ 1159{
1154 char buf[MAX_BUF]; 1160 char buf[MAX_BUF];
1155 1161
1199/* 1205/*
1200 * Loads a map, which has been loaded earlier, from file. 1206 * Loads a map, which has been loaded earlier, from file.
1201 * Return the map object we load into (this can change from the passed 1207 * Return the map object we load into (this can change from the passed
1202 * option if we can't find the original map) 1208 * option if we can't find the original map)
1203 */ 1209 */
1204
1205maptile * 1210maptile *
1206load_overlay_map (const char *filename, maptile *m) 1211load_overlay_map (const char *filename, maptile *m)
1207{ 1212{
1208 char pathname[MAX_BUF]; 1213 char pathname[MAX_BUF];
1209 1214
1260 } 1265 }
1261 } 1266 }
1262 } 1267 }
1263} 1268}
1264 1269
1265
1266/* 1270/*
1267 * Loads unique objects from file(s) into the map which is in memory 1271 * Loads unique objects from file(s) into the map which is in memory
1268 * m is the map to load unique items into. 1272 * m is the map to load unique items into.
1269 */ 1273 */
1270static void 1274static void
1289 return; 1293 return;
1290 1294
1291 m->in_memory = MAP_LOADING; 1295 m->in_memory = MAP_LOADING;
1292 if (m->tmpname == NULL) /* if we have loaded unique items from */ 1296 if (m->tmpname == NULL) /* if we have loaded unique items from */
1293 delete_unique_items (m); /* original map before, don't duplicate them */ 1297 delete_unique_items (m); /* original map before, don't duplicate them */
1298
1294 load_objects (m, thawer, 0); 1299 load_objects (m, thawer, 0);
1295 1300
1296 m->in_memory = MAP_IN_MEMORY; 1301 m->in_memory = MAP_IN_MEMORY;
1297} 1302}
1298
1299 1303
1300/* 1304/*
1301 * Saves a map to file. If flag is set, it is saved into the same 1305 * Saves a map to file. If flag is set, it is saved into the same
1302 * file it was (originally) loaded from. Otherwise a temporary 1306 * file it was (originally) loaded from. Otherwise a temporary
1303 * filename will be genarated, and the file will be stored there. 1307 * filename will be genarated, and the file will be stored there.
1304 * The temporary filename will be stored in the maptileure. 1308 * The temporary filename will be stored in the maptileure.
1305 * If the map is unique, we also save to the filename in the map 1309 * If the map is unique, we also save to the filename in the map
1306 * (this should have been updated when first loaded) 1310 * (this should have been updated when first loaded)
1307 */ 1311 */
1308
1309int 1312int
1310new_save_map (maptile *m, int flag) 1313new_save_map (maptile *m, int flag)
1311{ 1314{
1312 char filename[MAX_BUF], buf[MAX_BUF], shop[MAX_BUF]; 1315 char filename[MAX_BUF], buf[MAX_BUF], shop[MAX_BUF];
1313 int i; 1316 int i;
1477 * don't free tmpname - our caller is left to do that 1480 * don't free tmpname - our caller is left to do that
1478 */ 1481 */
1479void 1482void
1480free_map (maptile *m, int flag) 1483free_map (maptile *m, int flag)
1481{ 1484{
1482 if (m->in_memory != MAP_IN_MEMORY) 1485 if (!m->in_memory) //TODO: makes no sense to me?
1483 return; 1486 return;
1484 1487
1485 m->in_memory = MAP_SAVING; 1488 m->in_memory = MAP_SAVING;
1486 1489
1487 // TODO: use new/delete 1490 // TODO: use new/delete
1488#define FREE_AND_CLEAR(p) { free (p); p = NULL; }
1489 1491
1490 if (flag && m->spaces) 1492 if (flag && m->spaces)
1491 free_all_objects (m); 1493 free_all_objects (m);
1492 if (m->name)
1493 FREE_AND_CLEAR (m->name);
1494 if (m->spaces)
1495 FREE_AND_CLEAR (m->spaces);
1496 if (m->msg)
1497 FREE_AND_CLEAR (m->msg);
1498 if (m->maplore)
1499 FREE_AND_CLEAR (m->maplore);
1500 1494
1501 delete [] m->shopitems; 1495 sfree (m->spaces, m->size ()), m->spaces = 0;
1502 m->shopitems = 0;
1503 1496
1504 if (m->shoprace) 1497 free (m->name), m->name = 0;
1505 FREE_AND_CLEAR (m->shoprace); 1498 free (m->msg), m->msg = 0;
1499 free (m->maplore), m->maplore = 0;
1500 free (m->shoprace), m->shoprace = 0;
1501 delete [] m->shopitems, m->shopitems = 0;
1506 1502
1507 if (m->buttons) 1503 if (m->buttons)
1508 free_objectlinkpt (m->buttons); 1504 free_objectlinkpt (m->buttons), m->buttons = 0;
1509
1510 m->buttons = NULL;
1511 1505
1512 for (int i = 0; i < 4; i++) 1506 for (int i = 0; i < 4; i++)
1513 { 1507 free (m->tile_path[i]), m->tile_path[i] = 0;
1514 if (m->tile_path[i])
1515 FREE_AND_CLEAR (m->tile_path[i]);
1516
1517 m->tile_map[i] = 0;
1518 }
1519 1508
1520 m->in_memory = MAP_SWAPPED; 1509 m->in_memory = MAP_SWAPPED;
1521
1522#undef FREE_AND_CLEAR
1523} 1510}
1524 1511
1525maptile::~maptile () 1512maptile::~maptile ()
1526{ 1513{
1527 free_map (this, 1); 1514 assert (destroyed ());
1528 free (tmpname);
1529} 1515}
1530 1516
1531void 1517void
1532maptile::do_destroy () 1518maptile::do_destroy ()
1533{ 1519{
1534 attachable::do_destroy (); 1520 attachable::do_destroy ();
1535 1521
1536 free_all_objects (this); 1522 unlink ();
1523
1524 free_map (this, 1);
1525 free (tmpname), tmpname = 0;
1537 1526
1538 /* We need to look through all the maps and see if any maps 1527 /* We need to look through all the maps and see if any maps
1539 * are pointing at this one for tiling information. Since 1528 * are pointing at this one for tiling information. Since
1540 * tiling can be asymetric, we just can not look to see which 1529 * tiling can be asymetric, we just can not look to see which
1541 * maps this map tiles with and clears those. 1530 * maps this map tiles with and clears those.
1542 */ 1531 */
1543 //TODO: non-euclidean-tiling MUST GO 1532 //TODO: non-euclidean-tiling MUST GO
1544 for (maptile *m = first_map; m; m = m->next) 1533 for_all_maps (m)
1545 for (int i = 0; i < 4; i++) 1534 for (int i = 0; i < 4; i++)
1546 if (m->tile_map[i] == this) 1535 if (m->tile_map[i] == this)
1547 m->tile_map[i] = 0; 1536 m->tile_map[i] = 0;
1548
1549 if (first_map == this)
1550 first_map = next;
1551 else
1552 for (maptile *m = first_map; m; m = m->next)
1553 if (m->next = this)
1554 {
1555 m->next = next;
1556 break;
1557 }
1558} 1537}
1559 1538
1560//TODO: must go 1539//TODO: must go
1561void 1540void
1562delete_map (maptile *m) 1541delete_map (maptile *m)
1610 if (flags & MAP_PLAYER_UNIQUE) 1589 if (flags & MAP_PLAYER_UNIQUE)
1611 LOG (llevDebug, "Trying to load map %s.\n", name); 1590 LOG (llevDebug, "Trying to load map %s.\n", name);
1612 else 1591 else
1613 LOG (llevDebug, "Trying to load map %s.\n", create_pathname (name)); 1592 LOG (llevDebug, "Trying to load map %s.\n", create_pathname (name));
1614 1593
1615 //eval_pv ("$x = Event::time", 1);//D
1616 if (!(m = load_original_map (name, (flags & MAP_PLAYER_UNIQUE)))) 1594 if (!(m = load_original_map (name, (flags & MAP_PLAYER_UNIQUE))))
1617 return (NULL); 1595 return (NULL);
1618 //eval_pv ("warn \"LOAD \", Event::time - $x", 1);//D
1619 1596
1620 fix_auto_apply (m); /* Chests which open as default */ 1597 fix_auto_apply (m); /* Chests which open as default */
1621 1598
1622 /* If a player unique map, no extra unique object file to load. 1599 /* If a player unique map, no extra unique object file to load.
1623 * if from the editor, likewise. 1600 * if from the editor, likewise.
1759 if (first_map->in_memory == MAP_SAVING) 1736 if (first_map->in_memory == MAP_SAVING)
1760 first_map->in_memory = MAP_IN_MEMORY; 1737 first_map->in_memory = MAP_IN_MEMORY;
1761 delete_map (first_map); 1738 delete_map (first_map);
1762 real_maps++; 1739 real_maps++;
1763 } 1740 }
1741
1764 LOG (llevDebug, "free_all_maps: Freed %d maps\n", real_maps); 1742 LOG (llevDebug, "free_all_maps: Freed %d maps\n", real_maps);
1765} 1743}
1766 1744
1767/* change_map_light() - used to change map light level (darkness) 1745/* change_map_light() - used to change map light level (darkness)
1768 * up or down. Returns true if successful. It should now be 1746 * up or down. Returns true if successful. It should now be
1985} 1963}
1986 1964
1987void 1965void
1988set_map_reset_time (maptile *map) 1966set_map_reset_time (maptile *map)
1989{ 1967{
1990 int timeout;
1991
1992 timeout = map->reset_timeout; 1968 int timeout = map->reset_timeout;
1969
1993 if (timeout <= 0) 1970 if (timeout <= 0)
1994 timeout = MAP_DEFAULTRESET; 1971 timeout = MAP_DEFAULTRESET;
1995 if (timeout >= MAP_MAXRESET) 1972 if (timeout >= MAP_MAXRESET)
1996 timeout = MAP_MAXRESET; 1973 timeout = MAP_MAXRESET;
1974
1997 map->reset_time = time (0) + timeout; 1975 map->reset_time = time (0) + timeout;
1998} 1976}
1999 1977
2000/* this updates the orig_map->tile_map[tile_num] value after loading 1978/* this updates the orig_map->tile_map[tile_num] value after loading
2001 * the map. It also takes care of linking back the freshly loaded 1979 * the map. It also takes care of linking back the freshly loaded
2363{ 2341{
2364 int dx, dy; 2342 int dx, dy;
2365 2343
2366 return adjacent_map (op1->map, op2->map, &dx, &dy); 2344 return adjacent_map (op1->map, op2->map, &dx, &dy);
2367} 2345}
2346
2347object *
2348maptile::insert (object *op, int x, int y, object *originator, int flags)
2349{
2350 if (!op->flag [FLAG_REMOVED])
2351 op->remove ();
2352
2353 return insert_ob_in_map_at (op, this, originator, flags, x, y);
2354}
2355

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines