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 | |
41 | extern int nrofallocobjects,nroffreeobjects; |
41 | extern int nrofallocobjects,nroffreeobjects; |
42 | |
42 | |
|
|
43 | void (*load_original_map_callback)(mapstruct *map); |
|
|
44 | void (*load_temporary_map_callback)(mapstruct *map); |
|
|
45 | void (*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 | |
212 | void dump_map(mapstruct *m) { |
215 | void 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 | |
386 | int ob_blocked(object *ob,mapstruct *m,sint16 x,sint16 y) { |
400 | int 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 | */ |
573 | void save_objects (mapstruct *m, FILE *fp, FILE *fp2, int flag) { |
593 | void 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 | */ |
667 | mapstruct *get_empty_map(int sizex, int sizey) { |
685 | mapstruct *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 | |
781 | static int load_map_header(FILE *fp, mapstruct *m) |
798 | static 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. */ |
1116 | static void delete_unique_items(mapstruct *m) |
1150 | static 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 | |
1583 | int calculate_difficulty(mapstruct *m) { |
1621 | int 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 | |
1627 | void clean_tmp_map(mapstruct *m) { |
1669 | void 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 | |
1633 | void free_all_maps(void) |
1677 | void 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 |
… | |
… | |
1692 | void update_position (mapstruct *m, int x, int y) { |
1736 | void 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 | */ |
1968 | mapstruct *get_map_from_coord(mapstruct *m, sint16 *x, sint16 *y) |
2011 | mapstruct *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 | */ |
2015 | static int adjacent_map (mapstruct *map1, mapstruct *map2, int *dx, int *dy) |
2058 | static 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 | |
2076 | void get_rangevector(object *op1, object *op2, rv_vector *retval, int flags) |
2132 | void 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 | |
2137 | void get_rangevector_from_mapcoord(mapstruct *m, int x, int y, object *op2, rv_vector *retval,int flags) |
2189 | void 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 | */ |
2167 | int on_same_map(object *op1, object *op2) |
2215 | int 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 | } |