1 | /* |
1 | /* |
2 | * static char *rcsid_map_c = |
2 | * static char *rcsid_map_c = |
3 | * "$Id: map.C,v 1.17 2006/08/31 06:23:19 root Exp $"; |
3 | * "$Id: map.C,v 1.27 2006/09/08 12:56:42 root 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 | |
… | |
… | |
155 | { |
155 | { |
156 | char buf[MAX_BUF]; |
156 | char buf[MAX_BUF]; |
157 | #ifndef WIN32 |
157 | #ifndef WIN32 |
158 | char *endbuf; |
158 | char *endbuf; |
159 | struct stat statbuf; |
159 | struct stat statbuf; |
160 | int mode = 0, i; |
160 | int mode = 0; |
161 | #endif |
161 | #endif |
162 | |
162 | |
163 | if (prepend_dir) |
163 | if (prepend_dir) |
164 | strcpy (buf, create_pathname(name)); |
164 | strcpy (buf, create_pathname(name)); |
165 | else |
165 | else |
… | |
… | |
482 | op->x += tmp->x; |
482 | op->x += tmp->x; |
483 | op->y += tmp->y; |
483 | op->y += tmp->y; |
484 | op->head = tmp; |
484 | op->head = tmp; |
485 | op->map = m; |
485 | op->map = m; |
486 | last->more = op; |
486 | last->more = op; |
487 | if (tmp->name != op->name) { |
|
|
488 | if (op->name) free_string(op->name); |
|
|
489 | op->name = add_string(tmp->name); |
487 | op->name = tmp->name; |
490 | } |
|
|
491 | if (tmp->title != op->title) { |
|
|
492 | if (op->title) free_string(op->title); |
|
|
493 | op->title = add_string(tmp->title); |
488 | op->title = tmp->title; |
494 | } |
|
|
495 | /* we could link all the parts onto tmp, and then just |
489 | /* we could link all the parts onto tmp, and then just |
496 | * call insert_ob_in_map once, but the effect is the same, |
490 | * call insert_ob_in_map once, but the effect is the same, |
497 | * as insert_ob_in_map will call itself with each part, and |
491 | * as insert_ob_in_map will call itself with each part, and |
498 | * the coding is simpler to just to it here with each part. |
492 | * the coding is simpler to just to it here with each part. |
499 | */ |
493 | */ |
500 | insert_ob_in_map(op, op->map, tmp,INS_NO_MERGE|INS_ABOVE_FLOOR_ONLY|INS_NO_WALK_ON); |
494 | insert_ob_in_map(op, op->map, tmp,INS_NO_MERGE|INS_ABOVE_FLOOR_ONLY|INS_NO_WALK_ON); |
501 | } /* for at = tmp->arch->more */ |
495 | } /* for at = tmp->arch->more */ |
502 | } /* for objects on this space */ |
496 | } /* for objects on this space */ |
503 | } |
497 | } |
504 | |
498 | |
505 | |
|
|
506 | |
|
|
507 | /* |
499 | /* |
508 | * Loads (ands parses) the objects into a given map from the specified |
500 | * Loads (ands parses) the objects into a given map from the specified |
509 | * file pointer. |
501 | * file pointer. |
510 | * mapflags is the same as we get with load_original_map |
502 | * mapflags is the same as we get with load_original_map |
511 | */ |
503 | */ |
512 | |
504 | void |
513 | void load_objects (mapstruct *m, object_thawer &fp, int mapflags) { |
505 | load_objects (mapstruct *m, object_thawer &fp, int mapflags) |
514 | int i,j,bufstate=LO_NEWFILE; |
506 | { |
|
|
507 | int i, j; |
515 | int unique; |
508 | int unique; |
516 | object *op, *prev=NULL,*last_more=NULL, *otmp; |
509 | object *op, *prev = NULL, *last_more = NULL, *otmp; |
517 | |
510 | |
518 | op=get_object(); |
511 | op = get_object (); |
519 | op->map = m; /* To handle buttons correctly */ |
512 | op->map = m; /* To handle buttons correctly */ |
520 | |
513 | |
521 | while((i = load_object (fp, op, bufstate, mapflags))) { |
514 | while ((i = load_object (fp, op, mapflags))) |
522 | /* Since the loading of the map header does not load an object |
515 | { |
523 | * anymore, we need to pass LO_NEWFILE for the first object loaded, |
|
|
524 | * and then switch to LO_REPEAT for faster loading. |
|
|
525 | */ |
|
|
526 | bufstate = LO_REPEAT; |
|
|
527 | |
|
|
528 | /* if the archetype for the object is null, means that we |
516 | /* if the archetype for the object is null, means that we |
529 | * got an invalid object. Don't do anything with it - the game |
517 | * got an invalid object. Don't do anything with it - the game |
530 | * or editor will not be able to do anything with it either. |
518 | * or editor will not be able to do anything with it either. |
531 | */ |
519 | */ |
532 | if (op->arch==NULL) { |
520 | if (op->arch == NULL) |
|
|
521 | { |
533 | LOG(llevDebug,"Discarding object without arch: %s\n", op->name?op->name:"(null)"); |
522 | LOG (llevDebug, "Discarding object without arch: %s\n", |
|
|
523 | op->name ? (const char *) op->name : "(null)"); |
534 | continue; |
524 | continue; |
|
|
525 | } |
|
|
526 | |
|
|
527 | |
|
|
528 | switch (i) |
535 | } |
529 | { |
536 | |
|
|
537 | |
|
|
538 | switch(i) { |
|
|
539 | case LL_NORMAL: |
530 | case LL_NORMAL: |
540 | /* if we are loading an overlay, put the floors on the bottom */ |
531 | /* if we are loading an overlay, put the floors on the bottom */ |
541 | if ((QUERY_FLAG(op, FLAG_IS_FLOOR) || |
532 | if ((QUERY_FLAG (op, FLAG_IS_FLOOR) || |
542 | QUERY_FLAG(op, FLAG_OVERLAY_FLOOR)) && mapflags & MAP_OVERLAY) |
533 | QUERY_FLAG (op, FLAG_OVERLAY_FLOOR)) && mapflags & MAP_OVERLAY) |
543 | insert_ob_in_map(op,m,op,INS_NO_MERGE | INS_NO_WALK_ON | INS_ABOVE_FLOOR_ONLY | INS_MAP_LOAD); |
534 | insert_ob_in_map (op, m, op, |
|
|
535 | INS_NO_MERGE | INS_NO_WALK_ON | |
|
|
536 | INS_ABOVE_FLOOR_ONLY | INS_MAP_LOAD); |
544 | else |
537 | else |
545 | insert_ob_in_map(op,m,op,INS_NO_MERGE | INS_NO_WALK_ON | INS_ON_TOP | INS_MAP_LOAD); |
538 | insert_ob_in_map (op, m, op, |
|
|
539 | INS_NO_MERGE | INS_NO_WALK_ON | INS_ON_TOP | |
|
|
540 | INS_MAP_LOAD); |
546 | |
541 | |
547 | if (op->inv) |
542 | if (op->inv) |
548 | sum_weight(op); |
543 | sum_weight (op); |
549 | |
544 | |
550 | prev=op,last_more=op; |
545 | prev = op, last_more = op; |
551 | break; |
546 | break; |
552 | |
547 | |
553 | case LL_MORE: |
548 | case LL_MORE: |
554 | insert_ob_in_map(op,m, op, INS_NO_MERGE | INS_NO_WALK_ON | INS_ABOVE_FLOOR_ONLY); |
549 | insert_ob_in_map (op, m, op, |
|
|
550 | INS_NO_MERGE | INS_NO_WALK_ON | |
|
|
551 | INS_ABOVE_FLOOR_ONLY); |
555 | op->head=prev,last_more->more=op,last_more=op; |
552 | op->head = prev, last_more->more = op, last_more = op; |
556 | break; |
553 | break; |
557 | } |
554 | } |
|
|
555 | |
558 | if (mapflags & MAP_STYLE) { |
556 | if (mapflags & MAP_STYLE) |
559 | remove_from_active_list(op); |
557 | remove_from_active_list (op); |
560 | } |
558 | |
561 | op=get_object(); |
559 | op = get_object (); |
562 | op->map = m; |
560 | op->map = m; |
563 | } |
561 | } |
|
|
562 | |
564 | for (i=0;i<m->width;i++){ |
563 | for (i = 0; i < m->width; i++) |
|
|
564 | { |
565 | for (j=0;j<m->height;j++){ |
565 | for (j = 0; j < m->height; j++) |
|
|
566 | { |
566 | unique =0; |
567 | unique = 0; |
567 | /* check for unique items, or unique squares */ |
568 | /* check for unique items, or unique squares */ |
568 | for (otmp = get_map_ob(m, i, j); otmp; otmp = otmp->above) { |
569 | for (otmp = get_map_ob (m, i, j); otmp; otmp = otmp->above) |
569 | if (QUERY_FLAG(otmp, FLAG_UNIQUE) || QUERY_FLAG(otmp, FLAG_OBJ_SAVE_ON_OVL)) |
570 | { |
|
|
571 | if (QUERY_FLAG (otmp, FLAG_UNIQUE) |
|
|
572 | || QUERY_FLAG (otmp, FLAG_OBJ_SAVE_ON_OVL)) |
570 | unique = 1; |
573 | unique = 1; |
571 | if (!(mapflags & (MAP_OVERLAY|MAP_PLAYER_UNIQUE) || unique)) |
574 | if (!(mapflags & (MAP_OVERLAY | MAP_PLAYER_UNIQUE) || unique)) |
572 | SET_FLAG(otmp, FLAG_OBJ_ORIGINAL); |
575 | SET_FLAG (otmp, FLAG_OBJ_ORIGINAL); |
573 | } |
576 | } |
574 | } |
577 | } |
575 | } |
578 | } |
|
|
579 | |
576 | free_object(op); |
580 | free_object (op); |
577 | link_multipart_objects(m); |
581 | link_multipart_objects (m); |
578 | } |
582 | } |
579 | |
583 | |
580 | /* This saves all the objects on the map in a non destructive fashion. |
584 | /* This saves all the objects on the map in a non destructive fashion. |
581 | * Modified by MSW 2001-07-01 to do in a single pass - reduces code, |
585 | * Modified by MSW 2001-07-01 to do in a single pass - reduces code, |
582 | * and we only save the head of multi part objects - this is needed |
586 | * and we only save the head of multi part objects - this is needed |
… | |
… | |
618 | * Modified to no longer take a path option which was not being |
622 | * Modified to no longer take a path option which was not being |
619 | * used anyways. MSW 2001-07-01 |
623 | * used anyways. MSW 2001-07-01 |
620 | */ |
624 | */ |
621 | |
625 | |
622 | mapstruct *get_linked_map(void) { |
626 | mapstruct *get_linked_map(void) { |
623 | mapstruct *map=(mapstruct *) calloc(1,sizeof(mapstruct)); |
627 | mapstruct *map = new mapstruct; |
624 | mapstruct *mp; |
628 | mapstruct *mp; |
625 | |
|
|
626 | if(map==NULL) |
|
|
627 | fatal(OUT_OF_MEMORY); |
|
|
628 | |
629 | |
629 | for(mp=first_map;mp!=NULL&&mp->next!=NULL;mp=mp->next); |
630 | for(mp=first_map;mp!=NULL&&mp->next!=NULL;mp=mp->next); |
630 | if(mp==NULL) |
631 | if(mp==NULL) |
631 | first_map=map; |
632 | first_map=map; |
632 | else |
633 | else |
… | |
… | |
703 | number_of_entries++; |
704 | number_of_entries++; |
704 | if (p) p++; |
705 | if (p) p++; |
705 | } |
706 | } |
706 | p=shop_string; |
707 | p=shop_string; |
707 | strip_endline(p); |
708 | strip_endline(p); |
708 | items=(shopitems *) CALLOC(number_of_entries+1, sizeof(shopitems)); |
709 | items = new shopitems [number_of_entries + 1]; |
709 | memset(items, 0, (sizeof(shopitems) * number_of_entries+1)); |
|
|
710 | for (i=0; i<number_of_entries; i++) { |
710 | for (i=0; i<number_of_entries; i++) { |
711 | if (!p) { |
711 | if (!p) { |
712 | LOG(llevError, "parse_shop_string: I seem to have run out of string, that shouldn't happen.\n"); |
712 | LOG(llevError, "parse_shop_string: I seem to have run out of string, that shouldn't happen.\n"); |
713 | break; |
713 | break; |
714 | } |
714 | } |
… | |
… | |
815 | value = NULL; |
815 | value = NULL; |
816 | break; |
816 | break; |
817 | } |
817 | } |
818 | } |
818 | } |
819 | } |
819 | } |
|
|
820 | |
820 | if (!end) { |
821 | if (!end) { |
821 | LOG(llevError, "Error loading map header - did not find a newline - perhaps file is truncated? Buf=%s\n", |
822 | LOG(llevError, "Error loading map header - did not find a newline - perhaps file is truncated? Buf=%s\n", |
822 | buf); |
823 | buf); |
823 | return 1; |
824 | return 1; |
824 | } |
825 | } |
825 | |
|
|
826 | |
826 | |
827 | /* key is the field name, value is what it should be set |
827 | /* key is the field name, value is what it should be set |
828 | * to. We've already done the work to null terminate key, |
828 | * to. We've already done the work to null terminate key, |
829 | * and strip off any leading spaces for both of these. |
829 | * and strip off any leading spaces for both of these. |
830 | * We have not touched the newline at the end of the line - |
830 | * We have not touched the newline at the end of the line - |
… | |
… | |
888 | * what really should be used. |
888 | * what really should be used. |
889 | */ |
889 | */ |
890 | else if (!strcmp(key,"oid")) { |
890 | else if (!strcmp(key,"oid")) { |
891 | fp.get (m, atoi(value)); |
891 | fp.get (m, atoi(value)); |
892 | } else if (!strcmp(key, "attach")) { |
892 | } else if (!strcmp(key, "attach")) { |
893 | m->attach = add_string (value); |
893 | m->attach = value; |
894 | } else if (!strcmp(key,"hp") || !strcmp(key, "enter_x")) { |
894 | } else if (!strcmp(key,"hp") || !strcmp(key, "enter_x")) { |
895 | m->enter_x = atoi(value); |
895 | m->enter_x = atoi(value); |
896 | } else if (!strcmp(key,"sp") || !strcmp(key, "enter_y")) { |
896 | } else if (!strcmp(key,"sp") || !strcmp(key, "enter_y")) { |
897 | m->enter_y = atoi(value); |
897 | m->enter_y = atoi(value); |
898 | } else if (!strcmp(key,"x") || !strcmp(key, "width")) { |
898 | } else if (!strcmp(key,"x") || !strcmp(key, "width")) { |
… | |
… | |
1010 | |
1010 | |
1011 | mapstruct *load_original_map(const char *filename, int flags) { |
1011 | mapstruct *load_original_map(const char *filename, int flags) { |
1012 | mapstruct *m; |
1012 | mapstruct *m; |
1013 | char pathname[MAX_BUF]; |
1013 | char pathname[MAX_BUF]; |
1014 | |
1014 | |
1015 | LOG(llevDebug, "load_original_map: %s (%x)\n", filename,flags); |
|
|
1016 | if (flags & MAP_PLAYER_UNIQUE) |
1015 | if (flags & MAP_PLAYER_UNIQUE) |
1017 | strcpy(pathname, filename); |
1016 | strcpy(pathname, filename); |
1018 | else if (flags & MAP_OVERLAY) |
1017 | else if (flags & MAP_OVERLAY) |
1019 | strcpy(pathname, create_overlay_pathname(filename)); |
1018 | strcpy(pathname, create_overlay_pathname(filename)); |
1020 | else |
1019 | else |
1021 | strcpy(pathname, create_pathname(filename)); |
1020 | strcpy(pathname, create_pathname(filename)); |
1022 | |
1021 | |
|
|
1022 | LOG(llevDebug, "load_original_map(%x): %s (%s)\n", flags, filename, pathname); |
|
|
1023 | |
1023 | object_thawer thawer (pathname); |
1024 | object_thawer thawer (pathname); |
1024 | |
1025 | |
1025 | if (!thawer) |
1026 | if (!thawer) |
1026 | return 0; |
1027 | return 0; |
1027 | |
1028 | |
… | |
… | |
1053 | * Return the map object we load into (this can change from the passed |
1054 | * Return the map object we load into (this can change from the passed |
1054 | * option if we can't find the original map) |
1055 | * option if we can't find the original map) |
1055 | */ |
1056 | */ |
1056 | |
1057 | |
1057 | static mapstruct *load_temporary_map(mapstruct *m) { |
1058 | static mapstruct *load_temporary_map(mapstruct *m) { |
1058 | int comp; |
|
|
1059 | char buf[MAX_BUF]; |
1059 | char buf[MAX_BUF]; |
1060 | |
1060 | |
1061 | if (!m->tmpname) { |
1061 | if (!m->tmpname) { |
1062 | LOG(llevError, "No temporary filename for map %s\n", m->path); |
1062 | LOG(llevError, "No temporary filename for map %s\n", m->path); |
1063 | strcpy(buf, m->path); |
1063 | strcpy(buf, m->path); |
… | |
… | |
1179 | return; |
1179 | return; |
1180 | |
1180 | |
1181 | m->in_memory=MAP_LOADING; |
1181 | m->in_memory=MAP_LOADING; |
1182 | if (m->tmpname == NULL) /* if we have loaded unique items from */ |
1182 | if (m->tmpname == NULL) /* if we have loaded unique items from */ |
1183 | delete_unique_items(m); /* original map before, don't duplicate them */ |
1183 | delete_unique_items(m); /* original map before, don't duplicate them */ |
1184 | load_object(thawer, NULL, LO_NOREAD,0); |
|
|
1185 | load_objects (m, thawer, 0); |
1184 | load_objects (m, thawer, 0); |
1186 | |
1185 | |
1187 | m->in_memory=MAP_IN_MEMORY; |
1186 | m->in_memory=MAP_IN_MEMORY; |
1188 | } |
1187 | } |
1189 | |
1188 | |
… | |
… | |
1198 | */ |
1197 | */ |
1199 | |
1198 | |
1200 | int |
1199 | int |
1201 | new_save_map (mapstruct * m, int flag) |
1200 | new_save_map (mapstruct * m, int flag) |
1202 | { |
1201 | { |
1203 | char filename[MAX_BUF], buf[MAX_BUF], buf_s[MAX_BUF], shop[MAX_BUF]; |
1202 | char filename[MAX_BUF], buf[MAX_BUF], shop[MAX_BUF]; |
1204 | int i; |
1203 | int i; |
1205 | |
1204 | |
1206 | if (flag && !*m->path) |
1205 | if (flag && !*m->path) |
1207 | { |
1206 | { |
1208 | LOG (llevError, "Tried to save map without path.\n"); |
1207 | LOG (llevError, "Tried to save map without path.\n"); |
… | |
… | |
1393 | clean_object(op); |
1392 | clean_object(op); |
1394 | remove_ob(op); |
1393 | remove_ob(op); |
1395 | free_object(op); |
1394 | free_object(op); |
1396 | } |
1395 | } |
1397 | } |
1396 | } |
1398 | #ifdef MANY_CORES |
|
|
1399 | /* I see periodic cores on metalforge where a map has been swapped out, but apparantly |
|
|
1400 | * an item on that map was not saved - look for that condition and die as appropriate - |
|
|
1401 | * this leaves more of the map data intact for better debugging. |
|
|
1402 | */ |
|
|
1403 | for (op=objects; op!=NULL; op=op->next) { |
|
|
1404 | if (!QUERY_FLAG(op, FLAG_REMOVED) && op->map == m) { |
|
|
1405 | LOG(llevDebug,"free_all_objects: object %s still on map after it should have been freed\n", op->name); |
|
|
1406 | abort(); |
|
|
1407 | } |
|
|
1408 | } |
|
|
1409 | #endif |
|
|
1410 | } |
1397 | } |
1411 | |
1398 | |
1412 | /* |
1399 | /* |
1413 | * Frees everything allocated by the given mapstructure. |
1400 | * Frees everything allocated by the given mapstructure. |
1414 | * don't free tmpname - our caller is left to do that |
1401 | * don't free tmpname - our caller is left to do that |
… | |
… | |
1424 | if (flag && m->spaces) free_all_objects(m); |
1411 | if (flag && m->spaces) free_all_objects(m); |
1425 | if (m->name) FREE_AND_CLEAR(m->name); |
1412 | if (m->name) FREE_AND_CLEAR(m->name); |
1426 | if (m->spaces) FREE_AND_CLEAR(m->spaces); |
1413 | if (m->spaces) FREE_AND_CLEAR(m->spaces); |
1427 | if (m->msg) FREE_AND_CLEAR(m->msg); |
1414 | if (m->msg) FREE_AND_CLEAR(m->msg); |
1428 | if (m->maplore) FREE_AND_CLEAR(m->maplore); |
1415 | if (m->maplore) FREE_AND_CLEAR(m->maplore); |
1429 | if (m->shopitems) FREE_AND_CLEAR(m->shopitems); |
1416 | if (m->shopitems) delete [] m->shopitems; m->shopitems = 0; |
1430 | if (m->shoprace) FREE_AND_CLEAR(m->shoprace); |
1417 | if (m->shoprace) FREE_AND_CLEAR(m->shoprace); |
1431 | if (m->buttons) |
1418 | if (m->buttons) |
1432 | free_objectlinkpt(m->buttons); |
1419 | free_objectlinkpt(m->buttons); |
1433 | m->buttons = NULL; |
1420 | m->buttons = NULL; |
1434 | for (i=0; i<4; i++) { |
1421 | for (i=0; i<4; i++) { |
… | |
… | |
1494 | m->path); |
1481 | m->path); |
1495 | } |
1482 | } |
1496 | else |
1483 | else |
1497 | last->next = m->next; |
1484 | last->next = m->next; |
1498 | |
1485 | |
1499 | free (m); |
1486 | delete m; |
1500 | } |
1487 | } |
1501 | |
1488 | |
1502 | |
1489 | |
1503 | |
1490 | |
1504 | /* |
1491 | /* |
… | |
… | |
1547 | if (flags & MAP_PLAYER_UNIQUE) |
1534 | if (flags & MAP_PLAYER_UNIQUE) |
1548 | LOG(llevDebug, "Trying to load map %s.\n", name); |
1535 | LOG(llevDebug, "Trying to load map %s.\n", name); |
1549 | else |
1536 | else |
1550 | LOG(llevDebug, "Trying to load map %s.\n", create_pathname(name)); |
1537 | LOG(llevDebug, "Trying to load map %s.\n", create_pathname(name)); |
1551 | |
1538 | |
|
|
1539 | //eval_pv ("$x = Event::time", 1);//D |
1552 | if (!(m = load_original_map(name, (flags & MAP_PLAYER_UNIQUE)))) |
1540 | if (!(m = load_original_map(name, (flags & MAP_PLAYER_UNIQUE)))) |
1553 | return (NULL); |
1541 | return (NULL); |
|
|
1542 | //eval_pv ("warn \"LOAD \", Event::time - $x", 1);//D |
1554 | |
1543 | |
1555 | fix_auto_apply(m); /* Chests which open as default */ |
1544 | fix_auto_apply(m); /* Chests which open as default */ |
1556 | |
1545 | |
1557 | /* If a player unique map, no extra unique object file to load. |
1546 | /* If a player unique map, no extra unique object file to load. |
1558 | * if from the editor, likewise. |
1547 | * if from the editor, likewise. |
1559 | */ |
1548 | */ |
1560 | if (! (flags & (MAP_FLUSH|MAP_PLAYER_UNIQUE))) |
1549 | if (!(flags & (MAP_FLUSH|MAP_PLAYER_UNIQUE))) |
1561 | load_unique_objects(m); |
1550 | load_unique_objects(m); |
1562 | |
1551 | |
1563 | if (! (flags & (MAP_FLUSH|MAP_PLAYER_UNIQUE|MAP_OVERLAY))) { |
1552 | if (! (flags & (MAP_FLUSH|MAP_PLAYER_UNIQUE|MAP_OVERLAY))) { |
1564 | m=load_overlay_map(name, m); |
1553 | m=load_overlay_map(name, m); |
1565 | if (m==NULL) |
1554 | if (m==NULL) |
… | |
… | |
1616 | */ |
1605 | */ |
1617 | |
1606 | |
1618 | int calculate_difficulty(mapstruct *m) { |
1607 | int calculate_difficulty(mapstruct *m) { |
1619 | object *op; |
1608 | object *op; |
1620 | archetype *at; |
1609 | archetype *at; |
1621 | int x, y, i, diff; |
1610 | int x, y, i; |
1622 | long monster_cnt = 0; |
1611 | long monster_cnt = 0; |
1623 | double avgexp = 0; |
1612 | double avgexp = 0; |
1624 | sint64 total_exp = 0; |
1613 | sint64 total_exp = 0; |
1625 | |
1614 | |
1626 | if (MAP_DIFFICULTY (m)) |
1615 | if (MAP_DIFFICULTY (m)) |