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.2 by root, Wed Feb 8 03:46:15 2006 UTC vs.
Revision 1.12.2.1 by elmex, Thu Aug 10 08:26:28 2006 UTC

1/* 1/*
2 * static char *rcsid_map_c = 2 * static char *rcsid_map_c =
3 * "$Id: map.c,v 1.2 2006/02/08 03:46:15 root Exp $"; 3 * "$Id: map.c,v 1.12.2.1 2006/08/10 08:26:28 elmex Exp $";
4 */ 4 */
5 5
6/* 6/*
7 CrossFire, A Multiplayer game for X-windows 7 CrossFire, A Multiplayer game for X-windows
8 8
38#include "path.h" 38#include "path.h"
39 39
40 40
41extern int nrofallocobjects,nroffreeobjects; 41extern int nrofallocobjects,nroffreeobjects;
42 42
43void (*load_original_map_callback)(mapstruct *map);
44void (*load_temporary_map_callback)(mapstruct *map);
45void (*clean_temporary_map_callback)(mapstruct *map);
43 46
44/* 47/*
45 * Returns the mapstruct which has a name matching the given argument. 48 * Returns the mapstruct which has a name matching the given argument.
46 * return NULL if no match is found. 49 * return NULL if no match is found.
47 */ 50 */
207 * Prints out debug-information about a map. 210 * Prints out debug-information about a map.
208 * Dumping these at llevError doesn't seem right, but is 211 * Dumping these at llevError doesn't seem right, but is
209 * necessary to make sure the information is in fact logged. 212 * necessary to make sure the information is in fact logged.
210 */ 213 */
211 214
212void dump_map(mapstruct *m) { 215void dump_map(const mapstruct *m) {
213 LOG(llevError,"Map %s status: %d.\n",m->path,m->in_memory); 216 LOG(llevError,"Map %s status: %d.\n",m->path,m->in_memory);
214 LOG(llevError,"Size: %dx%d Start: %d,%d\n", 217 LOG(llevError,"Size: %dx%d Start: %d,%d\n",
215 MAP_WIDTH(m), MAP_HEIGHT(m), 218 MAP_WIDTH(m), MAP_HEIGHT(m),
216 MAP_ENTER_X(m), MAP_ENTER_Y(m)); 219 MAP_ENTER_X(m), MAP_ENTER_Y(m));
217 220
218 if(m->msg!=NULL) 221 if(m->msg!=NULL)
219 LOG(llevError,"Message:\n%s",m->msg); 222 LOG(llevError,"Message:\n%s",m->msg);
223
224 if(m->maplore!=NULL)
225 LOG(llevError,"Lore:\n%s",m->maplore);
220 226
221 if(m->tmpname!=NULL) 227 if(m->tmpname!=NULL)
222 LOG(llevError,"Tmpname: %s\n",m->tmpname); 228 LOG(llevError,"Tmpname: %s\n",m->tmpname);
223 229
224 LOG(llevError,"Difficulty: %d\n",m->difficulty); 230 LOG(llevError,"Difficulty: %d\n",m->difficulty);
304 * go further. Not true for players - all sorts of special 310 * go further. Not true for players - all sorts of special
305 * things we need to do for players. 311 * things we need to do for players.
306 */ 312 */
307 if (ob->type != PLAYER && ! (mflags & P_IS_ALIVE) && (blocked==0)) return 0; 313 if (ob->type != PLAYER && ! (mflags & P_IS_ALIVE) && (blocked==0)) return 0;
308 314
315 /* if there isn't anytyhing alive on this space, and this space isn't
316 * otherwise blocked, we can return now. Only if there is a living
317 * creature do we need to investigate if it is part of this creature
318 * or another. Likewise, only if something is blocking us do we
319 * need to investigate if there is a special circumstance that would
320 * let the player through (inventory checkers for example)
321 */
322 if (!(mflags & P_IS_ALIVE) && !OB_TYPE_MOVE_BLOCK(ob, blocked)) return 0;
309 323
310 if(ob->head != NULL) 324 if(ob->head != NULL)
311 ob=ob->head; 325 ob=ob->head;
312 326
313 /* We basically go through the stack of objects, and if there is 327 /* We basically go through the stack of objects, and if there is
381 * Note this used to be arch_blocked, but with new movement 395 * Note this used to be arch_blocked, but with new movement
382 * code, we need to have actual object to check its move_type 396 * code, we need to have actual object to check its move_type
383 * against the move_block values. 397 * against the move_block values.
384 */ 398 */
385 399
386int ob_blocked(object *ob,mapstruct *m,sint16 x,sint16 y) { 400int ob_blocked(const object *ob,mapstruct *m,sint16 x,sint16 y) {
387 archetype *tmp; 401 archetype *tmp;
388 int flag; 402 int flag;
389 mapstruct *m1; 403 mapstruct *m1;
390 sint16 sx, sy; 404 sint16 sx, sy;
391 405
401 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);
402 416
403 if (flag & P_OUT_OF_MAP) return P_OUT_OF_MAP; 417 if (flag & P_OUT_OF_MAP) return P_OUT_OF_MAP;
404 if (flag & P_IS_ALIVE) return P_IS_ALIVE; 418 if (flag & P_IS_ALIVE) return P_IS_ALIVE;
405 419
420 /* find_first_free_spot() calls this function. However, often
421 * ob doesn't have any move type (when used to place exits)
422 * so the AND operation in OB_TYPE_MOVE_BLOCK doesn't work.
423 */
424
425 if (ob->move_type == 0 && GET_MAP_MOVE_BLOCK(m1, sx, sy) != MOVE_ALL) continue;
426
406 /* Note it is intentional that we check ob - the movement type of the 427 /* Note it is intentional that we check ob - the movement type of the
407 * head of the object should correspond for the entire object. 428 * head of the object should correspond for the entire object.
408 */ 429 */
409
410 if (OB_TYPE_MOVE_BLOCK(ob, GET_MAP_MOVE_BLOCK(m1, sx, sy))) 430 if (OB_TYPE_MOVE_BLOCK(ob, GET_MAP_MOVE_BLOCK(m1, sx, sy)))
411 return AB_NO_PASS; 431 return AB_NO_PASS;
412 432
413 } 433 }
414 return 0; 434 return 0;
570 * and we only save the head of multi part objects - this is needed 590 * and we only save the head of multi part objects - this is needed
571 * in order to do map tiling properly. 591 * in order to do map tiling properly.
572 */ 592 */
573void save_objects (mapstruct *m, FILE *fp, FILE *fp2, int flag) { 593void save_objects (mapstruct *m, FILE *fp, FILE *fp2, int flag) {
574 int i, j = 0,unique=0; 594 int i, j = 0,unique=0;
575 object *op, *otmp; 595 object *op;
576 /* first pass - save one-part objects */ 596 /* first pass - save one-part objects */
577 for(i = 0; i < MAP_WIDTH(m); i++) 597 for(i = 0; i < MAP_WIDTH(m); i++)
578 for (j = 0; j < MAP_HEIGHT(m); j++) { 598 for (j = 0; j < MAP_HEIGHT(m); j++) {
579 unique=0; 599 unique=0;
580 for(op = get_map_ob (m, i, j); op; op = otmp) { 600 for(op = get_map_ob (m, i, j); op; op = op->above) {
581 otmp = op->above;
582
583 if (QUERY_FLAG(op,FLAG_IS_FLOOR) && QUERY_FLAG(op, FLAG_UNIQUE)) 601 if (QUERY_FLAG(op,FLAG_IS_FLOOR) && QUERY_FLAG(op, FLAG_UNIQUE))
584 unique=1; 602 unique=1;
585 603
586 if(op->type == PLAYER) { 604 if(op->type == PLAYER) {
587 LOG(llevDebug, "Player on map that is being saved\n"); 605 LOG(llevDebug, "Player on map that is being saved\n");
659 677
660 if(m->spaces==NULL) 678 if(m->spaces==NULL)
661 fatal(OUT_OF_MEMORY); 679 fatal(OUT_OF_MEMORY);
662} 680}
663 681
664/* Creatures and returns a map of the specific size. Used 682/* Create and returns a map of the specific size. Used
665 * in random map code and the editor. 683 * in random map code and the editor.
666 */ 684 */
667mapstruct *get_empty_map(int sizex, int sizey) { 685mapstruct *get_empty_map(int sizex, int sizey) {
668 mapstruct *m = get_linked_map(); 686 mapstruct *m = get_linked_map();
669 m->width = sizex; 687 m->width = sizex;
685 int i=0, number_of_entries=0; 703 int i=0, number_of_entries=0;
686 const typedata *current_type; 704 const typedata *current_type;
687 705
688 shop_string=strdup_local(input_string); 706 shop_string=strdup_local(input_string);
689 p=shop_string; 707 p=shop_string;
690 LOG(llevDebug, "parsing %s\n", input_string);
691 /* first we'll count the entries, we'll need that for allocating the array shortly */ 708 /* first we'll count the entries, we'll need that for allocating the array shortly */
692 while (p) { 709 while (p) {
693 p=strchr(p, ';'); 710 p=strchr(p, ';');
694 number_of_entries++; 711 number_of_entries++;
695 if (p) p++; 712 if (p) p++;
778 * return 0 on success, 1 on failure. 795 * return 0 on success, 1 on failure.
779 */ 796 */
780 797
781static int load_map_header(FILE *fp, mapstruct *m) 798static int load_map_header(FILE *fp, mapstruct *m)
782{ 799{
783 char buf[HUGE_BUF], msgbuf[HUGE_BUF], *key=NULL, *value, *end; 800 char buf[HUGE_BUF], msgbuf[HUGE_BUF], maplorebuf[HUGE_BUF], *key=NULL, *value, *end;
784 int msgpos=0; 801 int msgpos=0;
802 int maplorepos=0;
785 803
786 while (fgets(buf, HUGE_BUF-1, fp)!=NULL) { 804 while (fgets(buf, HUGE_BUF-1, fp)!=NULL) {
787 buf[HUGE_BUF-1] = 0; 805 buf[HUGE_BUF-1] = 0;
788 key = buf; 806 key = buf;
789 while (isspace(*key)) key++; 807 while (isspace(*key)) key++;
843 * keep the empty message. Also, msgbuf contains garbage data 861 * keep the empty message. Also, msgbuf contains garbage data
844 * when msgpos is zero, so copying it results in crashes 862 * when msgpos is zero, so copying it results in crashes
845 */ 863 */
846 if (msgpos != 0) 864 if (msgpos != 0)
847 m->msg = strdup_local(msgbuf); 865 m->msg = strdup_local(msgbuf);
866 }
867 else if (!strcmp(key,"maplore")) {
868 while (fgets(buf, HUGE_BUF-1, fp)!=NULL) {
869 if (!strcmp(buf,"endmaplore\n")) break;
870 else {
871 /* slightly more efficient than strcat */
872 strcpy(maplorebuf+maplorepos, buf);
873 maplorepos += strlen(buf);
874 }
875 }
876 if (maplorepos != 0)
877 m->maplore = strdup_local(maplorebuf);
848 } 878 }
849 else if (!strcmp(key,"end")) { 879 else if (!strcmp(key,"end")) {
850 break; 880 break;
851 } 881 }
852 else if (value == NULL) { 882 else if (value == NULL) {
1019 close_and_delete(fp, comp); 1049 close_and_delete(fp, comp);
1020 m->in_memory=MAP_IN_MEMORY; 1050 m->in_memory=MAP_IN_MEMORY;
1021 if (!MAP_DIFFICULTY(m)) 1051 if (!MAP_DIFFICULTY(m))
1022 MAP_DIFFICULTY(m)=calculate_difficulty(m); 1052 MAP_DIFFICULTY(m)=calculate_difficulty(m);
1023 set_map_reset_time(m); 1053 set_map_reset_time(m);
1054 if (load_original_map_callback)
1055 load_original_map_callback(m);
1024 return (m); 1056 return (m);
1025} 1057}
1026 1058
1027/* 1059/*
1028 * Loads a map, which has been loaded earlier, from file. 1060 * Loads a map, which has been loaded earlier, from file.
1068 1100
1069 m->in_memory=MAP_LOADING; 1101 m->in_memory=MAP_LOADING;
1070 load_objects (m, fp, 0); 1102 load_objects (m, fp, 0);
1071 close_and_delete(fp, comp); 1103 close_and_delete(fp, comp);
1072 m->in_memory=MAP_IN_MEMORY; 1104 m->in_memory=MAP_IN_MEMORY;
1105 if (load_temporary_map_callback)
1106 load_temporary_map_callback(m);
1073 return m; 1107 return m;
1074} 1108}
1075 1109
1076/* 1110/*
1077 * Loads a map, which has been loaded earlier, from file. 1111 * Loads a map, which has been loaded earlier, from file.
1113 *****************************************************************************/ 1147 *****************************************************************************/
1114 1148
1115/* This goes through map 'm' and removed any unique items on the map. */ 1149/* This goes through map 'm' and removed any unique items on the map. */
1116static void delete_unique_items(mapstruct *m) 1150static void delete_unique_items(mapstruct *m)
1117{ 1151{
1118 int i,j,unique=0; 1152 int i,j,unique;
1119 object *op, *next; 1153 object *op, *next;
1120 1154
1121 for(i=0; i<MAP_WIDTH(m); i++) 1155 for(i=0; i<MAP_WIDTH(m); i++)
1122 for(j=0; j<MAP_HEIGHT(m); j++) { 1156 for(j=0; j<MAP_HEIGHT(m); j++) {
1123 unique=0; 1157 unique=0;
1214 strcpy(filename, m->tmpname); 1248 strcpy(filename, m->tmpname);
1215 } 1249 }
1216 LOG(llevDebug,"Saving map %s\n",m->path); 1250 LOG(llevDebug,"Saving map %s\n",m->path);
1217 m->in_memory = MAP_SAVING; 1251 m->in_memory = MAP_SAVING;
1218 1252
1253 unlink (filename); // do not overwrite backups if done via hardlinks
1254
1219 /* Compress if it isn't a temporary save. Do compress if unique */ 1255 /* Compress if it isn't a temporary save. Do compress if unique */
1220 if (m->compressed && (m->unique || m->template || flag)) { 1256 if (m->compressed && (m->unique || m->template || flag)) {
1221 char buf[MAX_BUF]; 1257 char buf[MAX_BUF];
1222 strcpy(buf, uncomp[m->compressed][2]); 1258 strcpy(buf, uncomp[m->compressed][2]);
1223 strcat(buf, " > "); 1259 strcat(buf, " > ");
1259 if (m->width) fprintf(fp,"width %d\n", m->width); 1295 if (m->width) fprintf(fp,"width %d\n", m->width);
1260 if (m->height) fprintf(fp,"height %d\n", m->height); 1296 if (m->height) fprintf(fp,"height %d\n", m->height);
1261 if (m->enter_x) fprintf(fp,"enter_x %d\n", m->enter_x); 1297 if (m->enter_x) fprintf(fp,"enter_x %d\n", m->enter_x);
1262 if (m->enter_y) fprintf(fp,"enter_y %d\n", m->enter_y); 1298 if (m->enter_y) fprintf(fp,"enter_y %d\n", m->enter_y);
1263 if (m->msg) fprintf(fp,"msg\n%sendmsg\n", m->msg); 1299 if (m->msg) fprintf(fp,"msg\n%sendmsg\n", m->msg);
1300 if (m->maplore) fprintf(fp,"maplore\n%sendmaplore\n", m->maplore);
1264 if (m->unique) fprintf(fp,"unique %d\n", m->unique); 1301 if (m->unique) fprintf(fp,"unique %d\n", m->unique);
1265 if (m->template) fprintf(fp,"template %d\n", m->template); 1302 if (m->template) fprintf(fp,"template %d\n", m->template);
1266 if (m->outdoor) fprintf(fp,"outdoor %d\n", m->outdoor); 1303 if (m->outdoor) fprintf(fp,"outdoor %d\n", m->outdoor);
1267 if (m->temp) fprintf(fp, "temp %d\n", m->temp); 1304 if (m->temp) fprintf(fp, "temp %d\n", m->temp);
1268 if (m->pressure) fprintf(fp, "pressure %d\n", m->pressure); 1305 if (m->pressure) fprintf(fp, "pressure %d\n", m->pressure);
1395 } 1432 }
1396 if (flag && m->spaces) free_all_objects(m); 1433 if (flag && m->spaces) free_all_objects(m);
1397 if (m->name) FREE_AND_CLEAR(m->name); 1434 if (m->name) FREE_AND_CLEAR(m->name);
1398 if (m->spaces) FREE_AND_CLEAR(m->spaces); 1435 if (m->spaces) FREE_AND_CLEAR(m->spaces);
1399 if (m->msg) FREE_AND_CLEAR(m->msg); 1436 if (m->msg) FREE_AND_CLEAR(m->msg);
1437 if (m->maplore) FREE_AND_CLEAR(m->maplore);
1400 if (m->shopitems) FREE_AND_CLEAR(m->shopitems); 1438 if (m->shopitems) FREE_AND_CLEAR(m->shopitems);
1401 if (m->shoprace) FREE_AND_CLEAR(m->shoprace); 1439 if (m->shoprace) FREE_AND_CLEAR(m->shoprace);
1402 if (m->buttons) 1440 if (m->buttons)
1403 free_objectlinkpt(m->buttons); 1441 free_objectlinkpt(m->buttons);
1404 m->buttons = NULL; 1442 m->buttons = NULL;
1579 * have a difficulty set than using this function - human calculation 1617 * have a difficulty set than using this function - human calculation
1580 * is much better than this functions guesswork. 1618 * is much better than this functions guesswork.
1581 */ 1619 */
1582 1620
1583int calculate_difficulty(mapstruct *m) { 1621int calculate_difficulty(mapstruct *m) {
1584 object *op; 1622 object *op;
1585 archetype *at; 1623 archetype *at;
1586 int x,y; 1624 int x, y, i, diff;
1587 int diff=0; 1625 long monster_cnt = 0;
1588 int i; 1626 double avgexp = 0;
1589 sint64 exp_pr_sq, total_exp=0; 1627 sint64 total_exp = 0;
1590 1628
1591 if (MAP_DIFFICULTY(m)) { 1629 if (MAP_DIFFICULTY (m))
1630 {
1592 LOG(llevDebug, "Using stored map difficulty: %d\n", MAP_DIFFICULTY(m)); 1631 LOG(llevDebug, "Using stored map difficulty: %d\n", MAP_DIFFICULTY (m));
1593 return MAP_DIFFICULTY(m); 1632 return MAP_DIFFICULTY (m);
1594 }
1595
1596 for(x=0;x<MAP_WIDTH(m);x++)
1597 for(y=0;y<MAP_HEIGHT(m);y++)
1598 for(op=get_map_ob(m,x,y);op!=NULL;op=op->above) {
1599 if(QUERY_FLAG(op,FLAG_MONSTER))
1600 total_exp+=op->stats.exp;
1601 if(QUERY_FLAG(op,FLAG_GENERATOR)) {
1602 total_exp+=op->stats.exp;
1603 at=type_to_archetype(GENERATE_TYPE(op));
1604 if(at!=NULL)
1605 total_exp+=at->clone.stats.exp*8;
1606 }
1607 } 1633 }
1608#ifdef NEWCALC 1634
1609 (int)exp_pr_sq=((double)1000*total_exp)/(m->map_object->x*m->map_object->y+1); 1635 for(x = 0; x < MAP_WIDTH(m); x++)
1610 for(i=20;i>0;i--) 1636 for(y = 0; y < MAP_HEIGHT(m); y++)
1611 if(exp_pr_sq>level_exp(i,1.0)) { 1637 for(op = get_map_ob(m, x, y); op != NULL; op = op->above)
1612 diff=i; 1638 {
1613 break; 1639 if(QUERY_FLAG (op, FLAG_MONSTER))
1614 } 1640 {
1615#else 1641 total_exp += op->stats.exp;
1616 exp_pr_sq=((double)1000*total_exp)/(MAP_WIDTH(m)*MAP_HEIGHT(m)+1); 1642 monster_cnt++;
1617 diff=20; 1643 }
1618 for(i=1;i<20;i++) 1644
1619 if(exp_pr_sq<=level_exp(i,1.0)) { 1645 if(QUERY_FLAG (op, FLAG_GENERATOR))
1620 diff=i; 1646 {
1621 break; 1647 total_exp += op->stats.exp;
1622 } 1648 at = type_to_archetype(GENERATE_TYPE (op));
1623#endif 1649
1624 return diff; 1650 if(at != NULL)
1651 total_exp += at->clone.stats.exp * 8;
1652
1653 monster_cnt++;
1654 }
1655 }
1656
1657 avgexp = (double) total_exp / monster_cnt;
1658
1659 for (i = 1; i <= settings.max_level; i++)
1660 {
1661 if ((level_exp (i, 1) - level_exp (i - 1, 1)) > (100 * avgexp))
1662 {
1663 LOG(llevError, "Calculated difficulty for map: %s: %d\n", m->name, i);
1664 return i;
1665 }
1666 }
1625} 1667}
1626 1668
1627void clean_tmp_map(mapstruct *m) { 1669void clean_tmp_map(mapstruct *m) {
1628 if(m->tmpname == NULL) 1670 if(m->tmpname == NULL)
1629 return; 1671 return;
1672 if (clean_temporary_map_callback)
1673 clean_temporary_map_callback (m);
1630 (void) unlink(m->tmpname); 1674 (void) unlink(m->tmpname);
1631} 1675}
1632 1676
1633void free_all_maps(void) 1677void free_all_maps(void)
1634{ 1678{
1662 return 0; 1706 return 0;
1663 } 1707 }
1664 1708
1665 /* inform all players on the map */ 1709 /* inform all players on the map */
1666 if (change>0) 1710 if (change>0)
1667 new_info_map(NDI_BLACK, m,"It becomes darker."); 1711 new_info_map(NDI_BLACK|NDI_UNIQUE, m,"It becomes darker.");
1668 else 1712 else
1669 new_info_map(NDI_BLACK, m,"It becomes brighter."); 1713 new_info_map(NDI_BLACK|NDI_UNIQUE, m,"It becomes brighter.");
1670 1714
1671 /* Do extra checking. since m->darkness is a unsigned value, 1715 /* Do extra checking. since m->darkness is a unsigned value,
1672 * we need to be extra careful about negative values. 1716 * we need to be extra careful about negative values.
1673 * In general, the checks below are only needed if change 1717 * In general, the checks below are only needed if change
1674 * is not +/-1 1718 * is not +/-1
1692void update_position (mapstruct *m, int x, int y) { 1736void update_position (mapstruct *m, int x, int y) {
1693 object *tmp, *last = NULL; 1737 object *tmp, *last = NULL;
1694 uint8 flags = 0, oldflags, light=0, anywhere=0; 1738 uint8 flags = 0, oldflags, light=0, anywhere=0;
1695 New_Face *top,*floor, *middle; 1739 New_Face *top,*floor, *middle;
1696 object *top_obj, *floor_obj, *middle_obj; 1740 object *top_obj, *floor_obj, *middle_obj;
1697 MoveType move_block=0, move_slow=0, move_on=0, move_off=0; 1741 MoveType move_block=0, move_slow=0, move_on=0, move_off=0, move_allow=0;
1698 1742
1699 oldflags = GET_MAP_FLAGS(m,x,y); 1743 oldflags = GET_MAP_FLAGS(m,x,y);
1700 if (!(oldflags & P_NEED_UPDATE)) { 1744 if (!(oldflags & P_NEED_UPDATE)) {
1701 LOG(llevDebug,"update_position called with P_NEED_UPDATE not set: %s (%d, %d)\n", 1745 LOG(llevDebug,"update_position called with P_NEED_UPDATE not set: %s (%d, %d)\n",
1702 m->path, x, y); 1746 m->path, x, y);
1765 1809
1766 move_slow |= tmp->move_slow; 1810 move_slow |= tmp->move_slow;
1767 move_block |= tmp->move_block; 1811 move_block |= tmp->move_block;
1768 move_on |= tmp->move_on; 1812 move_on |= tmp->move_on;
1769 move_off |= tmp->move_off; 1813 move_off |= tmp->move_off;
1814 move_allow |= tmp->move_allow;
1770 1815
1771 if (QUERY_FLAG(tmp,FLAG_ALIVE)) 1816 if (QUERY_FLAG(tmp,FLAG_ALIVE))
1772 flags |= P_IS_ALIVE; 1817 flags |= P_IS_ALIVE;
1773 if (QUERY_FLAG(tmp,FLAG_NO_MAGIC)) 1818 if (QUERY_FLAG(tmp,FLAG_NO_MAGIC))
1774 flags |= P_NO_MAGIC; 1819 flags |= P_NO_MAGIC;
1788 LOG(llevDebug,"update_position: updated flags do not match old flags: %s (old=%d,new=%d) %x != %x\n", 1833 LOG(llevDebug,"update_position: updated flags do not match old flags: %s (old=%d,new=%d) %x != %x\n",
1789 m->path, x, y, 1834 m->path, x, y,
1790 (oldflags & ~P_NEED_UPDATE), flags); 1835 (oldflags & ~P_NEED_UPDATE), flags);
1791 } 1836 }
1792 SET_MAP_FLAGS(m, x, y, flags); 1837 SET_MAP_FLAGS(m, x, y, flags);
1793 SET_MAP_MOVE_BLOCK(m, x, y, move_block); 1838 SET_MAP_MOVE_BLOCK(m, x, y, move_block & ~move_allow);
1794 SET_MAP_MOVE_ON(m, x, y, move_on); 1839 SET_MAP_MOVE_ON(m, x, y, move_on);
1795 SET_MAP_MOVE_OFF(m, x, y, move_off); 1840 SET_MAP_MOVE_OFF(m, x, y, move_off);
1796 SET_MAP_MOVE_SLOW(m, x, y, move_slow); 1841 SET_MAP_MOVE_SLOW(m, x, y, move_slow);
1797 1842
1798 /* At this point, we have a floor face (if there is a floor), 1843 /* At this point, we have a floor face (if there is a floor),
1918 * case. This generally shouldn't happen, but if the 1963 * case. This generally shouldn't happen, but if the
1919 * map loads fail below, it could happen. 1964 * map loads fail below, it could happen.
1920 */ 1965 */
1921 if (!m) return 0; 1966 if (!m) return 0;
1922 1967
1923 /* Simple case - coordinates are within this local
1924 * map.
1925 */
1926 if ( x>=0 && x<MAP_WIDTH(m) && y>=0 && y < MAP_HEIGHT(m))
1927 return 0;
1928
1929 if (x<0) { 1968 if (x<0) {
1930 if (!m->tile_path[3]) return 1; 1969 if (!m->tile_path[3]) return 1;
1931 if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY) { 1970 if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY) {
1932 load_and_link_tiled_map(m, 3); 1971 load_and_link_tiled_map(m, 3);
1933 } 1972 }
1952 if (!m->tile_map[2] || m->tile_map[2]->in_memory != MAP_IN_MEMORY) { 1991 if (!m->tile_map[2] || m->tile_map[2]->in_memory != MAP_IN_MEMORY) {
1953 load_and_link_tiled_map(m, 2); 1992 load_and_link_tiled_map(m, 2);
1954 } 1993 }
1955 return (out_of_map(m->tile_map[2], x, y - MAP_HEIGHT(m))); 1994 return (out_of_map(m->tile_map[2], x, y - MAP_HEIGHT(m)));
1956 } 1995 }
1996
1997 /* Simple case - coordinates are within this local
1998 * map.
1999 */
1957 return 1; 2000 return 0;
1958} 2001}
1959 2002
1960/* This is basically the same as out_of_map above, but 2003/* This is basically the same as out_of_map above, but
1961 * instead we return NULL if no map is valid (coordinates 2004 * instead we return NULL if no map is valid (coordinates
1962 * out of bounds and no tiled map), otherwise it returns 2005 * out of bounds and no tiled map), otherwise it returns
1966 * and then figuring out what the real map is 2009 * and then figuring out what the real map is
1967 */ 2010 */
1968mapstruct *get_map_from_coord(mapstruct *m, sint16 *x, sint16 *y) 2011mapstruct *get_map_from_coord(mapstruct *m, sint16 *x, sint16 *y)
1969{ 2012{
1970 2013
1971 /* Simple case - coordinates are within this local
1972 * map.
1973 */
1974
1975 if (*x>=0 && *x<MAP_WIDTH(m) && *y>=0 && *y < MAP_HEIGHT(m))
1976 return m;
1977
1978 if (*x<0) { 2014 if (*x<0) {
1979 if (!m->tile_path[3]) return NULL; 2015 if (!m->tile_path[3]) return NULL;
1980 if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY) 2016 if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY)
1981 load_and_link_tiled_map(m, 3); 2017 load_and_link_tiled_map(m, 3);
1982 2018
2005 load_and_link_tiled_map(m, 2); 2041 load_and_link_tiled_map(m, 2);
2006 2042
2007 *y -= MAP_HEIGHT(m); 2043 *y -= MAP_HEIGHT(m);
2008 return (get_map_from_coord(m->tile_map[2], x, y)); 2044 return (get_map_from_coord(m->tile_map[2], x, y));
2009 } 2045 }
2010 return NULL; /* Shouldn't get here */
2011}
2012 2046
2047 /* Simple case - coordinates are within this local
2048 * map.
2049 */
2050
2051 return m;
2052}
2053
2054/**
2013// return wether map2 is adjacent to map1 and store their distance 2055 * Return whether map2 is adjacent to map1. If so, store the distance from
2014// in dx/dy if yes. 2056 * map1 to map2 in dx/dy.
2057 */
2015static int adjacent_map (mapstruct *map1, mapstruct *map2, int *dx, int *dy) 2058static int adjacent_map(const mapstruct *map1, const mapstruct *map2, int *dx, int *dy) {
2016{
2017 if (!map1 || !map2) 2059 if (!map1 || !map2)
2018 return 0; 2060 return 0;
2019 2061
2020 else if (map1 == map2) 2062 if (map1 == map2) {
2063 *dx = 0;
2021 *dx = *dy = 0; 2064 *dy = 0;
2022 2065
2023 else if (map1->tile_map[0] == map2) // up 2066 } else if (map1->tile_map[0] == map2) { /* up */
2067 *dx = 0;
2024 (*dx = 0), (*dy = -MAP_HEIGHT (map2)); 2068 *dy = -MAP_HEIGHT(map2);
2025 else if (map1->tile_map[1] == map2) // right 2069 } else if (map1->tile_map[1] == map2) { /* right */
2026 (*dx = MAP_WIDTH (map2)), (*dy = 0); 2070 *dx = MAP_WIDTH(map1);
2071 *dy = 0;
2027 else if (map1->tile_map[2] == map2) // down 2072 } else if (map1->tile_map[2] == map2) { /* down */
2028 (*dx = 0), (*dy = MAP_HEIGHT (map2)); 2073 *dx = 0;
2074 *dy = MAP_HEIGHT(map1);
2029 else if (map1->tile_map[3] == map2) // left 2075 } else if (map1->tile_map[3] == map2) { /* left */
2030 (*dx = -MAP_WIDTH (map2)), (*dy = 0); 2076 *dx = -MAP_WIDTH(map2);
2077 *dy = 0;
2031 2078
2032 else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[1] == map2) // up right 2079 } else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[1] == map2) { /* up right */
2033 (*dx = MAP_WIDTH (map2)), (*dy = -MAP_HEIGHT (map1->tile_map[0])); 2080 *dx = MAP_WIDTH(map1->tile_map[0]);
2081 *dy = -MAP_HEIGHT(map1->tile_map[0]);
2034 else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[3] == map2) // up left 2082 } else if (map1->tile_map[0] && map1->tile_map[0]->tile_map[3] == map2) { /* up left */
2035 (*dx = -MAP_WIDTH (map2)), (*dy = -MAP_HEIGHT (map1->tile_map[0])); 2083 *dx = -MAP_WIDTH(map2);
2084 *dy = -MAP_HEIGHT(map1->tile_map[0]);
2036 else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[0] == map2) // right up 2085 } else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[0] == map2) { /* right up */
2037 (*dx = MAP_HEIGHT (map1->tile_map[1])), (*dy = -MAP_WIDTH (map2)); 2086 *dx = MAP_WIDTH(map1);
2087 *dy = -MAP_HEIGHT(map2);
2038 else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[2] == map2) // right down 2088 } else if (map1->tile_map[1] && map1->tile_map[1]->tile_map[2] == map2) { /* right down */
2039 (*dx = MAP_HEIGHT (map1->tile_map[1])), (*dy = MAP_WIDTH (map2)); 2089 *dx = MAP_WIDTH(map1);
2090 *dy = MAP_HEIGHT(map1->tile_map[1]);
2040 else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[1] == map2) // down right 2091 } else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[1] == map2) { /* down right */
2041 (*dx = MAP_WIDTH (map2)), (*dy = MAP_HEIGHT (map1->tile_map[2])); 2092 *dx = MAP_WIDTH(map1->tile_map[2]);
2093 *dy = MAP_HEIGHT(map1);
2042 else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[3] == map2) // down left 2094 } else if (map1->tile_map[2] && map1->tile_map[2]->tile_map[3] == map2) { /* down left */
2043 (*dx = -MAP_WIDTH (map2)), (*dy = MAP_HEIGHT (map1->tile_map[2])); 2095 *dx = -MAP_WIDTH(map2);
2096 *dy = MAP_HEIGHT(map1);
2044 else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[0] == map2) // left up 2097 } else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[0] == map2) { /* left up */
2045 (*dx = -MAP_HEIGHT (map1->tile_map[3])), (*dy = -MAP_WIDTH (map2)); 2098 *dx = -MAP_WIDTH(map1->tile_map[3]);
2099 *dy = -MAP_HEIGHT(map2);
2046 else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[2] == map2) // left down 2100 } else if (map1->tile_map[3] && map1->tile_map[3]->tile_map[2] == map2) { /* left down */
2047 (*dx = MAP_HEIGHT (map1->tile_map[3])), (*dy = MAP_WIDTH (map2)); 2101 *dx = -MAP_WIDTH(map1->tile_map[3]);
2102 *dy = MAP_HEIGHT(map1->tile_map[3]);
2048 2103
2049 else // not "adjacent" enough 2104 } else { /* not "adjacent" enough */
2105 return 0;
2106 }
2107
2050 return 0; 2108 return 1;
2051
2052 return 1;
2053} 2109}
2054 2110
2055/* From map.c 2111/* From map.c
2056 * This is used by get_player to determine where the other 2112 * This is used by get_player to determine where the other
2057 * creature is. get_rangevector takes into account map tiling, 2113 * creature is. get_rangevector takes into account map tiling,
2071 * 2127 *
2072 * currently, the only flag supported (0x1) is don't translate for 2128 * currently, the only flag supported (0x1) is don't translate for
2073 * closest body part of 'op1' 2129 * closest body part of 'op1'
2074 */ 2130 */
2075 2131
2076void get_rangevector(object *op1, object *op2, rv_vector *retval, int flags) 2132void get_rangevector(object *op1, object *op2, rv_vector *retval, int flags) {
2077{
2078 if (!adjacent_map (op1->map, op2->map, &(retval->distance_x), &(retval->distance_y))) 2133 if (!adjacent_map(op1->map, op2->map, &retval->distance_x, &retval->distance_y)) {
2079 {
2080 // be conservative and fill in _some_ data 2134 /* be conservative and fill in _some_ data */
2081 retval->distance = 100000; 2135 retval->distance = 100000;
2082 retval->distance_x = 32767; 2136 retval->distance_x = 32767;
2083 retval->distance_y = 32767; 2137 retval->distance_y = 32767;
2084 retval->direction = 0; 2138 retval->direction = 0;
2085 retval->part = 0; 2139 retval->part = 0;
2086 }
2087 else 2140 } else {
2088 {
2089 object *best; 2141 object *best;
2090 2142
2091 retval->distance_x += op2->x - op1->x; 2143 retval->distance_x += op2->x-op1->x;
2092 retval->distance_y += op2->y - op1->y; 2144 retval->distance_y += op2->y-op1->y;
2093 2145
2094 best = op1; 2146 best = op1;
2095 /* If this is multipart, find the closest part now */ 2147 /* If this is multipart, find the closest part now */
2096 if (!(flags & 0x1) && op1->more) { 2148 if (!(flags&0x1) && op1->more) {
2097 object *tmp; 2149 object *tmp;
2098 int best_distance = retval->distance_x * retval->distance_x + 2150 int best_distance = retval->distance_x*retval->distance_x+
2099 retval->distance_y * retval->distance_y, tmpi; 2151 retval->distance_y*retval->distance_y, tmpi;
2100 2152
2101 /* we just tkae the offset of the piece to head to figure 2153 /* we just take the offset of the piece to head to figure
2102 * distance instead of doing all that work above again 2154 * distance instead of doing all that work above again
2103 * since the distance fields we set above are positive in the 2155 * since the distance fields we set above are positive in the
2104 * same axis as is used for multipart objects, the simply arithemetic 2156 * same axis as is used for multipart objects, the simply arithmetic
2105 * below works. 2157 * below works.
2106 */ 2158 */
2107 for (tmp=op1->more; tmp; tmp=tmp->more) { 2159 for (tmp = op1->more; tmp != NULL; tmp = tmp->more) {
2108 tmpi = (op1->x - tmp->x + retval->distance_x) * (op1->x - tmp->x + retval->distance_x) + 2160 tmpi = (op1->x-tmp->x+retval->distance_x)*(op1->x-tmp->x+retval->distance_x)+
2109 (op1->y - tmp->y + retval->distance_y) * (op1->y - tmp->y + retval->distance_y); 2161 (op1->y-tmp->y+retval->distance_y)*(op1->y-tmp->y+retval->distance_y);
2110 if (tmpi < best_distance) { 2162 if (tmpi < best_distance) {
2111 best_distance = tmpi; 2163 best_distance = tmpi;
2112 best = tmp; 2164 best = tmp;
2113 } 2165 }
2114 } 2166 }
2115 if (best != op1) { 2167 if (best != op1) {
2116 retval->distance_x += op1->x - best->x; 2168 retval->distance_x += op1->x-best->x;
2117 retval->distance_y += op1->y - best->y; 2169 retval->distance_y += op1->y-best->y;
2118 } 2170 }
2119 } 2171 }
2120 retval->part = best; 2172 retval->part = best;
2121 retval->distance = isqrt(retval->distance_x*retval->distance_x + retval->distance_y*retval->distance_y); 2173 retval->distance = isqrt(retval->distance_x*retval->distance_x+retval->distance_y*retval->distance_y);
2122 retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y); 2174 retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y);
2123 } 2175 }
2124} 2176}
2125 2177
2126/* this is basically the same as get_rangevector above, but instead of 2178/* this is basically the same as get_rangevector above, but instead of
2127 * the first parameter being an object, it instead is the map 2179 * the first parameter being an object, it instead is the map
2128 * and x,y coordinates - this is used for path to player - 2180 * and x,y coordinates - this is used for path to player -
2132 * be more consistant with the above function and also in case they are needed 2184 * be more consistant with the above function and also in case they are needed
2133 * for something in the future. Also, since no object is pasted, the best 2185 * for something in the future. Also, since no object is pasted, the best
2134 * field of the rv_vector is set to NULL. 2186 * field of the rv_vector is set to NULL.
2135 */ 2187 */
2136 2188
2137void get_rangevector_from_mapcoord(mapstruct *m, int x, int y, object *op2, rv_vector *retval,int flags) 2189void get_rangevector_from_mapcoord(const mapstruct *m, int x, int y, const object *op2, rv_vector *retval, int flags) {
2138{
2139 if (!adjacent_map (m, op2->map, &(retval->distance_x), &(retval->distance_y))) 2190 if (!adjacent_map(m, op2->map, &retval->distance_x, &retval->distance_y)) {
2140 {
2141 // be conservative and fill in _some_ data 2191 /* be conservative and fill in _some_ data */
2142 retval->distance = 100000; 2192 retval->distance = 100000;
2143 retval->distance_x = 32767; 2193 retval->distance_x = 32767;
2144 retval->distance_y = 32767; 2194 retval->distance_y = 32767;
2145 retval->direction = 0; 2195 retval->direction = 0;
2146 retval->part = 0; 2196 retval->part = 0;
2147 }
2148 else 2197 } else {
2149 {
2150 retval->distance_x += op2->x - x; 2198 retval->distance_x += op2->x-x;
2151 retval->distance_y += op2->y - y; 2199 retval->distance_y += op2->y-y;
2152 2200
2153 retval->part = NULL; 2201 retval->part = NULL;
2154 retval->distance = isqrt(retval->distance_x*retval->distance_x + retval->distance_y*retval->distance_y); 2202 retval->distance = isqrt(retval->distance_x*retval->distance_x+retval->distance_y*retval->distance_y);
2155 retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y); 2203 retval->direction = find_dir_2(-retval->distance_x, -retval->distance_y);
2156 } 2204 }
2157} 2205}
2158 2206
2159/* Returns true of op1 and op2 are effectively on the same map 2207/* Returns true of op1 and op2 are effectively on the same map
2160 * (as related to map tiling). Note that this looks for a path from 2208 * (as related to map tiling). Note that this looks for a path from
2161 * op1 to op2, so if the tiled maps are assymetric and op2 has a path 2209 * op1 to op2, so if the tiled maps are assymetric and op2 has a path
2162 * to op1, this will still return false. 2210 * to op1, this will still return false.
2163 * Note we only look one map out to keep the processing simple 2211 * Note we only look one map out to keep the processing simple
2164 * and efficient. This could probably be a macro. 2212 * and efficient. This could probably be a macro.
2165 * MSW 2001-08-05 2213 * MSW 2001-08-05
2166 */ 2214 */
2167int on_same_map(object *op1, object *op2) 2215int on_same_map(const object *op1, const object *op2) {
2168{
2169 int dx, dy; 2216 int dx, dy;
2170 2217
2171 return adjacent_map (op1->map, op2->map, &dx, &dy); 2218 return adjacent_map(op1->map, op2->map, &dx, &dy);
2172} 2219}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines