Go to the documentation of this file.
47 "floor",
"no_pick",
"no_pick",
"item",
"item",
48 "item",
"living",
"living",
"fly",
"fly"
174 snprintf(
t,
buf+size-
t,
"%s", s);
213 return(_access(
buf, 0));
216 if (stat(
buf, &statbuf) != 0)
219 if (!S_ISREG(statbuf.st_mode))
222 if (((statbuf.st_mode&
S_IRGRP) && getegid() == statbuf.st_gid)
223 || ((statbuf.st_mode&
S_IRUSR) && geteuid() == statbuf.st_uid)
227 if ((statbuf.st_mode&
S_IWGRP && getegid() == statbuf.st_gid)
228 || (statbuf.st_mode&
S_IWUSR && geteuid() == statbuf.st_uid)
252 if (
m->maplore != NULL)
255 if (
m->tmpname != NULL)
352 LOG(
llevError,
"blocked_link: Passed map, x, y coordinates outside of map\n");
360 mflags =
m->spaces[sx+
m->width*sy].flags;
542 for (at =
tmp->arch->more, last =
tmp; at != NULL; at = at->
more, last =
op) {
550 if (
tmp->name !=
op->name) {
555 if (
tmp->title !=
op->title) {
585 if (
tmp->head ||
tmp->more)
606 object *
op, *prev = NULL, *last_more = NULL;
612 while ((i =
load_object(fp,
op, bufstate, mapflags,
false))) {
623 if (
op->arch == NULL) {
624 LOG(
llevDebug,
"Discarding object without arch: %s\n",
op->name ?
op->name :
"(null)");
633 LOG(
llevError,
"Discarding invalid item with type PLAYER in map %s\n",
m->path);
639 LOG(
llevError,
" object %s not on valid map position %s:%d:%d\n",
op->name ?
op->name :
"(null)",
m->path,
op->x,
op->y);
682 "load_objects on %s took %ld us\n",
m->path, diff));
683 for (i = 0; i <
m->width; i++) {
684 for (j = 0; j <
m->height; j++) {
716 int i, j = 0, unique = 0;
717 unsigned int count = 0;
722 long serialize_time, write_time;
763 LOG(
llevDebug,
"saved %d objects on %s (%ld us serializing, %ld us writing)\n",
count,
m->path, serialize_time, write_time);
793 map->last_reset_time = 0;
799 return (uint32_t)
m->width * (uint32_t)
m->height;
819 LOG(
llevError,
"allocate_map called with already allocated map (%s)\n",
m->path);
825 if (
m->spaces == NULL)
865 char *shop_string, *p, *
q, *next_semicolon, *next_colon;
867 int i = 0, number_of_entries = 0;
891 for (i = 0; i < number_of_entries; i++) {
893 LOG(
llevError,
"parse_shop_string: I seem to have run out of string, that shouldn't happen.\n");
896 next_semicolon = strchr(p,
';');
897 next_colon = strchr(p,
':');
899 if (next_colon && (!next_semicolon || next_colon < next_semicolon))
900 items[i].
strength = atoi(strchr(p,
':')+1);
902 if (isdigit(*p) || *p ==
'*') {
903 items[i].
typenum = *p ==
'*' ? -1 : atoi(p);
910 q = strpbrk(p,
";:");
922 LOG(
llevError,
"invalid type %s defined in shopitems for %s in string %s\n", p,
map->name, input_string);
925 items[i].
index = number_of_entries;
927 p = ++next_semicolon;
950 output_string[0] =
'\0';
951 for (i = 0; i <
m->shopitems[0].index; i++) {
952 if (
m->shopitems[i].typenum != -1) {
953 if (
m->shopitems[i].strength) {
954 snprintf(
tmp,
sizeof(
tmp),
"%s:%d;",
m->shopitems[i].name,
m->shopitems[i].strength);
956 snprintf(
tmp,
sizeof(
tmp),
"%s;",
m->shopitems[i].name);
958 if (
m->shopitems[i].strength) {
959 snprintf(
tmp,
sizeof(
tmp),
"*:%d;",
m->shopitems[i].strength);
961 snprintf(
tmp,
sizeof(
tmp),
"*;");
963 snprintf(output_string+strlen(output_string), size-strlen(output_string),
"%s",
tmp);
967 if (strlen(output_string) > 0) {
968 output_string[strlen(output_string) - 1] =
'\0';
991 m->width =
m->height = 0;
992 while (fgets(
buf,
sizeof(
buf), fp) != NULL) {
995 p = strchr(
buf,
'\n');
997 LOG(
llevError,
"Error loading map header - did not find a newline - perhaps file is truncated? Buf=%s\n",
buf);
1003 while (isspace(*
key))
1011 while (isspace(*
value)) {
1013 if (*
value ==
'\0') {
1036 if (!strcmp(
key,
"msg")) {
1040 while (fgets(
buf,
sizeof(
buf), fp) != NULL) {
1041 if (!strcmp(
buf,
"endmsg\n"))
1045 msgpos += strlen(
buf);
1058 }
else if (!strcmp(
key,
"maplore")) {
1060 size_t maplorepos = 0;
1063 if (!strcmp(
buf,
"endmaplore\n"))
1066 if (maplorepos >=
sizeof(maplorebuf)) {
1070 snprintf(maplorebuf+maplorepos,
sizeof(maplorebuf)-maplorepos,
"%s",
buf);
1071 maplorepos += strlen(
buf);
1074 if (maplorepos != 0)
1076 }
else if (!strcmp(
key,
"end")) {
1078 }
else if (
value == NULL) {
1079 LOG(
llevError,
"Got '%s' line without parameter in map header\n",
key);
1080 }
else if (!strcmp(
key,
"arch")) {
1082 if (strcmp(
value,
"map")) {
1083 LOG(
llevError,
"load_map_header: expected 'arch map': check line endings?\n");
1086 }
else if (!strcmp(
key,
"name")) {
1094 }
else if (!strcmp(
key,
"enter_x")) {
1095 m->enter_x = atoi(
value);
1096 }
else if (!strcmp(
key,
"enter_y")) {
1097 m->enter_y = atoi(
value);
1098 }
else if (!strcmp(
key,
"width")) {
1100 }
else if (!strcmp(
key,
"height")) {
1102 }
else if (!strcmp(
key,
"reset_timeout")) {
1103 m->reset_timeout = atoi(
value);
1104 }
else if (!strcmp(
key,
"swap_time")) {
1106 }
else if (!strcmp(
key,
"difficulty")) {
1107 m->difficulty = atoi(
value);
1108 }
else if (!strcmp(
key,
"darkness")) {
1109 m->darkness = atoi(
value);
1110 }
else if (!strcmp(
key,
"fixed_resettime")) {
1111 m->fixed_resettime = atoi(
value);
1112 }
else if (!strcmp(
key,
"unique")) {
1114 }
else if (!strcmp(
key,
"template")) {
1115 m->is_template = atoi(
value);
1116 }
else if (!strcmp(
key,
"region")) {
1118 }
else if (!strcmp(
key,
"shopitems")) {
1120 }
else if (!strcmp(
key,
"shopgreed")) {
1121 m->shopgreed = atof(
value);
1122 }
else if (!strcmp(
key,
"shopmin")) {
1123 m->shopmin = atol(
value);
1124 }
else if (!strcmp(
key,
"shopmax")) {
1125 m->shopmax = atol(
value);
1126 }
else if (!strcmp(
key,
"shoprace")) {
1128 }
else if (!strcmp(
key,
"outdoor")) {
1129 m->outdoor = atoi(
value);
1130 }
else if (!strcmp(
key,
"nosmooth")) {
1131 m->nosmooth = atoi(
value);
1132 }
else if (!strcmp(
key,
"first_load")) {
1133 m->last_reset_time = atoi(
value);
1134 }
else if (!strncmp(
key,
"tile_path_", 10)) {
1137 if (tile < 1 || tile > 4) {
1138 LOG(
llevError,
"load_map_header: tile location %d out of bounds (%s)\n",
tile,
m->path);
1140 if (
m->tile_path[
tile-1]) {
1141 LOG(
llevError,
"load_map_header: tile location %d duplicated (%s)\n",
tile,
m->path);
1142 free(
m->tile_path[
tile-1]);
1146 }
else if (!strcmp(
key,
"background_music")) {
1148 }
else if (!strcmp(
key,
"reset_group")) {
1154 if ((
m->width == 0) || (
m->height == 0)) {
1158 if (!
key || strcmp(
key,
"end")) {
1177 if ((fp = fopen(pathname,
"r")) == NULL) {
1179 "Can't open %s: %s\n", pathname, strerror(errno));
1256 LOG(
llevError,
"No temporary filename for map %s\n",
m->path);
1260 if ((fp = fopen(
m->tmpname,
"r")) == NULL) {
1261 LOG(
llevError,
"Cannot open %s: %s\n",
m->tmpname, strerror(errno));
1266 LOG(
llevError,
"Error loading map header for %s (%s)\n",
m->path,
m->tmpname);
1294 if ((fp = fopen(pathname,
"r")) == NULL) {
1300 LOG(
llevError,
"Error loading map header for overlay %s (%s)\n",
m->path, pathname);
1324 int i, j, unique = 0;
1355 snprintf(firstname,
sizeof(firstname),
"%s.v%02d",
name,
count);
1356 if (!access(firstname, R_OK))
1363 if ((fp = fopen(firstname,
"r")) == NULL) {
1372 if (
m->tmpname == NULL)
1401 if (flag && !*
m->path) {
1409 if (!
m->unique && !
m->is_template) {
1415 if (
m->path[0] !=
'~') {
1417 "Cannot save unique map '%s' outside of LOCALDIR. Check "
1418 "that all exits to '%s' have FLAG_UNIQUE set correctly.\n",
1438 fprintf(fp,
"arch map\n");
1440 fprintf(fp,
"name %s\n",
m->name);
1441 if (
m->reset_timeout)
1442 fprintf(fp,
"reset_timeout %u\n",
m->reset_timeout);
1443 if (
m->fixed_resettime)
1444 fprintf(fp,
"fixed_resettime %d\n",
m->fixed_resettime);
1449 fprintf(fp,
"difficulty %d\n",
m->difficulty);
1451 fprintf(fp,
"region %s\n",
m->region->name);
1454 fprintf(fp,
"shopitems %s\n", shop);
1457 fprintf(fp,
"shopgreed %f\n",
m->shopgreed);
1459 fprintf(fp,
"shopmin %" FMT64U "\n",
m->shopmin);
1461 fprintf(fp,
"shopmax %" FMT64U "\n",
m->shopmax);
1463 fprintf(fp,
"shoprace %s\n",
m->shoprace);
1465 fprintf(fp,
"darkness %d\n",
m->darkness);
1467 fprintf(fp,
"width %d\n",
m->width);
1469 fprintf(fp,
"height %d\n",
m->height);
1471 fprintf(fp,
"enter_x %d\n",
m->enter_x);
1473 fprintf(fp,
"enter_y %d\n",
m->enter_y);
1475 fprintf(fp,
"msg\n%sendmsg\n",
m->msg);
1477 fprintf(fp,
"maplore\n%sendmaplore\n",
m->maplore);
1479 fprintf(fp,
"unique %d\n",
m->unique);
1481 fprintf(fp,
"template %d\n",
m->is_template);
1483 fprintf(fp,
"outdoor %d\n",
m->outdoor);
1485 fprintf(fp,
"nosmooth %d\n",
m->nosmooth);
1486 if (
m->last_reset_time)
1487 fprintf(fp,
"first_load %ld\n",
m->last_reset_time);
1488 if (
m->background_music)
1489 fprintf(fp,
"background_music %s\n",
m->background_music);
1491 fprintf(fp,
"reset_group %s\n",
m->reset_group);
1495 for (i = 0; i < 4; i++)
1496 if (
m->tile_path[i])
1497 fprintf(fp,
"tile_path_%d %s\n", i+1,
m->tile_path[i]);
1499 fprintf(fp,
"end\n");
1510 snprintf(final_unique,
sizeof(final_unique),
"%s.v00",
name);
1511 fp2 =
of_open(&of2, final_unique);
1536 if (ftell(fp2) == 0) {
1542 unlink(final_unique);
1549 if (chmod(final_unique,
SAVE_MODE) != 0) {
1572 LOG(
llevDebug,
"save_map on %s" " took %ld us\n",
m->path, diff));
1609 object *previous_obj = NULL;
1612 if (
op == previous_obj) {
1613 LOG(
llevDebug,
"free_all_objects: Link error, bailing out.\n");
1635 LOG(
llevError,
"free_all_objects: object %s still on map after it should have been freed\n",
op->name);
1653 if (!
m->in_memory) {
1674 if (
m->background_music)
1679 for (i = 0; i < 4; i++) {
1680 if (
m->tile_path[i])
1682 m->tile_map[i] = NULL;
1726 for (i = 0; i < 4; i++)
1727 if (
tmp->tile_map[i] ==
m)
1728 tmp->tile_map[i] = NULL;
1739 LOG(
llevError,
"delete_map: Unable to find map %s in list\n",
m->path);
1741 last->
next =
m->next;
1787 snprintf(buf2,
sizeof(buf2),
"~%s",
name+strlen(
buf)+1);
1792 if (
name[0] ==
'~') {
1812 if (
m == NULL)
return NULL;
1870 if (
m->last_reset_time == 0) {
1901 int64_t exp_pr_sq, total_exp = 0;
1911 total_exp +=
op->stats.exp;
1913 total_exp +=
op->stats.exp;
1916 at =
op->other_arch ?
op->other_arch : NULL;
1920 int lim = atoi(val ? val :
"0");
1922 if (!lim || lim >= 16)
1938 for (i = 1; i < 25; i++)
1954 if (
m->tmpname == NULL)
1956 (
void)unlink(
m->tmpname);
1974 LOG(
llevDebug,
"free_all_maps: Freed %d maps\n", real_maps);
1995 int new_level =
m->darkness+change;
1999 || (new_level <= 0 && m->darkness == 0)
2020 m->darkness = new_level;
2049 static inline void add_face_layer(
int low_layer,
int high_layer,
object *
ob,
object *layers[],
int honor_visibility) {
2053 for (
l = low_layer;
l <= high_layer;
l++) {
2059 if (!honor_visibility)
2066 for (l1 = (
l-1); l1 >= low_layer; l1--) {
2067 if (layers[l1]->face->visibility > layers[l1+1]->
face->
visibility) {
2069 layers[l1+1] = layers[l1];
2079 if (!honor_visibility) {
2083 for (
l = low_layer;
l < high_layer;
l++)
2084 layers[
l] = layers[
l+1];
2085 layers[high_layer] =
ob;
2095 for (
l = high_layer;
l >= low_layer;
l--) {
2097 for (l1 = low_layer; l1 <
l; l1++)
2098 layers[l1] = layers[l1+1];
2120 uint8_t
flags = 0, oldflags, light = 0;
2123 MoveType move_block = 0, move_slow = 0, move_on = 0, move_off = 0, move_allow = 0;
2127 LOG(
llevDebug,
"update_position called with P_NEED_UPDATE not set: %s (%d, %d)\n",
m->path,
x,
y);
2131 memset(layers, 0,
MAP_LAYERS*
sizeof(
object *));
2146 if (
tmp->glow_radius > light)
2147 light =
tmp->glow_radius;
2154 if (
tmp->map_layer) {
2164 memset(layers+1, 0, (
MAP_LAYERS-1)*
sizeof(
object *));
2180 move_slow |=
tmp->move_slow;
2181 move_block |=
tmp->move_block;
2182 move_on |=
tmp->move_on;
2183 move_off |=
tmp->move_off;
2184 move_allow |=
tmp->move_allow;
2206 LOG(
llevDebug,
"update_position: updated flags do not match old flags: %s (x=%d,y=%d) %x != %x\n",
2259 int dest_tile = (tile_num+2)%4;
2265 if (orig_map->
tile_map[tile_num] == NULL) {
2277 return orig_map->
tile_map[tile_num];
2294 int16_t xp =
x, yp =
y;
2327 if ( !
m )
return NULL;
2347 if (!
m->tile_path[3])
2352 if (!
m->tile_map[3])
2359 if (!
m->tile_path[1])
2364 if (!
m->tile_map[1])
2373 if (!
m->tile_path[0])
2378 if (!
m->tile_map[0])
2385 if (!
m->tile_path[2])
2390 if (!
m->tile_map[2])
2422 }
else if (map1->
tile_map[0] == map2) {
2425 }
else if (map1->
tile_map[1] == map2) {
2428 }
else if (map1->
tile_map[2] == map2) {
2431 }
else if (map1->
tile_map[3] == map2) {
2499 retval->
part = NULL;
2523 if (tmpi < best_distance) {
2524 best_distance = tmpi;
2533 retval->
part = best;
2567 retval->
part = NULL;
2573 retval->
part = NULL;
2644 if (unlink(
path) != 0) {
2664 if (
item->map != NULL) {
2665 if (strlen(
item->map->path) > 0) {
2666 return item->map->path;
2669 return item->map->name ?
item->map->name :
"(empty path and name)";
2672 if (
item->env != NULL)
2675 return "(no map and no env!)";
2684 return path != NULL &&
path[0] ==
'~';
2688 if (
m->spaces == NULL)
2692 return &
m->spaces[
x +
m->width *
y];
#define GET_MAP_OB(M, X, Y)
object * object_get_owner(object *op)
#define FREE_AND_CLEAR_STR_IF(xyz)
#define FREE_OBJ_NO_DESTROY_CALLBACK
#define MAP_NO_DIFFICULTY
void LOG(LogLevel logLevel, const char *format,...)
mapstruct * get_empty_map(int sizex, int sizey)
#define FLAG_OVERLAY_FLOOR
int of_close(OutputFile *of)
static void create_items_path(const char *s, char *buf, size_t size)
region * get_region_by_name(const char *region_name)
FILE * of_open(OutputFile *of, const char *fname)
#define MAP_RESET_TIMEOUT(m)
int blocked_link(object *ob, mapstruct *m, int16_t sx, int16_t sy)
#define SAVE_FLAG_NO_REMOVE
static void delete_unique_items(mapstruct *m)
mapstruct * ready_map_name(const char *name, int flags)
#define QUERY_FLAG(xyz, p)
static int load_temporary_map(mapstruct *m)
mapstruct * has_been_loaded(const char *name)
static void print_shop_string(mapstruct *m, char *output_string, int size)
void update_position(mapstruct *m, int x, int y)
static void add_face_layer(int low_layer, int high_layer, object *ob, object *layers[], int honor_visibility)
StringBuffer * stringbuffer_new(void)
#define FLAG_OBJ_ORIGINAL
#define SET_MAP_MOVE_ON(M, X, Y, C)
void map_path(const char *map, int flags, char *pathname, size_t bufsize)
static const Map_Layer_Info map_layer_info[MAP_LAYERS]
static const flag_definition flags[]
void clean_object(object *op)
#define MAP_PLAYER_UNIQUE
int load_object(FILE *fp, object *op, int bufstate, int map_flags, bool artifact_init)
#define PROFILE_BEGIN(expr)
void dump_map(const mapstruct *m)
const char * object_get_value(const object *op, const char *const key)
#define GET_MAP_FACE_OBJS(M, X, Y)
#define SAVE_MODE_OVERLAY
#define INS_ABOVE_FLOOR_ONLY
void map_remove_unique_files(const mapstruct *map)
int save_objects(mapstruct *m, FILE *fp, FILE *fp2, int flag)
#define PROFILE_END(var, expr)
static event_registration m
void set_darkness_map(mapstruct *m)
char * stringbuffer_finish(StringBuffer *sb)
void apply_auto_fix(mapstruct *m)
#define MAP_LAYER_NO_PICK2
#define MAP_DIFFICULTY(m)
void object_free_drop_inventory(object *ob)
uint32_t map_size(mapstruct *m)
bool object_value_set_shared(const object *op, sstring key)
void of_cancel(OutputFile *of)
const typedata * get_typedata(int itemtype)
#define MSG_TYPE_ATTACK_NOKEY
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
static void load_unique_objects(mapstruct *m)
sstring add_string(const char *str)
void clean_tmp_map(mapstruct *m)
#define SAVE_ERROR_RCREATION
#define MAP_WHEN_RESET(m)
int change_map_light(mapstruct *m, int change)
void void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1)
mapstruct * mapfile_load_lowlevel(const char *map, const char *pathname, int flags)
int out_of_map(mapstruct *m, int x, int y)
#define SET_MAP_FLAGS(M, X, Y, C)
#define MAP_LAYER_LIVING1
void object_free(object *ob, int flags)
#define GET_MAP_MOVE_BLOCK(M, X, Y)
void free_map(mapstruct *m)
int64_t level_exp(int level, double expmul)
static void free_all_objects(mapstruct *m)
mapstruct * get_map_from_coord(mapstruct *m, int16_t *x, int16_t *y)
int get_rangevector_from_mapcoord(const mapstruct *m, int x, int y, const object *op2, rv_vector *retval)
object * map_find_by_flag(mapstruct *map, int x, int y, int flag)
void delete_map(mapstruct *m)
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
#define SAVE_ERROR_NO_PATH
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
static void link_multipart_objects(mapstruct *m)
const typedata * get_typedata_by_name(const char *name)
void fatal(enum fatal_error err)
mapstruct * get_linked_map(void)
void create_template_pathname(const char *name, char *buf, size_t size)
size_t strlcpy(char *dst, const char *src, size_t size)
MapSpace * map_space(const mapstruct *m, int x, int y)
object * object_new(void)
void create_overlay_pathname(const char *name, char *buf, size_t size)
#define OB_MOVE_BLOCK(ob1, ob2)
void set_map_reset_time(mapstruct *map)
void free_string(sstring str)
#define SAVE_ERROR_UCREATION
#define SET_MAP_MOVE_SLOW(M, X, Y, C)
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
#define OUT_OF_REAL_MAP(M, X, Y)
int find_dir_2(int x, int y)
static mapstruct * load_and_link_tiled_map(mapstruct *orig_map, int tile_num)
#define MAP_LAYER_NO_PICK1
void decay_objects(mapstruct *m)
static int load_map_header(FILE *fp, mapstruct *m)
#define FREE_AND_CLEAR(xyz)
static int adjacent_map(const mapstruct *map1, const mapstruct *map2, int *dx, int *dy)
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
char * create_pathname(const char *name, char *buf, size_t size)
static char msgbuf[HUGE_BUF]
const char * map_get_path(const object *item)
#define SET_MAP_MOVE_BLOCK(M, X, Y, C)
int on_same_map(const object *op1, const object *op2)
#define CLEAR_FLAG(xyz, p)
bool map_path_unique(const char *path)
void save_object_in_sb(StringBuffer *sb, object *op, const int flag)
#define SAVE_ERROR_URENAME
void strip_endline(char *buf)
void object_remove_from_active_list(object *op)
object * arch_to_object(archetype *at)
int get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
void update_all_map_los(mapstruct *map)
void allocate_map(mapstruct *m)
void object_fix_multipart(object *tmp)
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
static void fix_container_multipart(object *container)
void free_objectlinkpt(oblinkpt *obp)
void object_remove(object *op)
#define GET_MAP_FLAGS(M, X, Y)
signed long object_sum_weight(object *op)
#define MAP_LAYER_LIVING2
#define OB_TYPE_MOVE_BLOCK(ob1, type)
void make_path_to_file(const char *filename)
int save_map(mapstruct *m, int flag)
int calculate_difficulty(mapstruct *m)
#define SET_MAP_PLAYER(M, X, Y, C)
mapstruct * mapfile_load(const char *map, int flags)
static shopitems * parse_shop_string(const char *input_string, const mapstruct *map)
#define SAVE_FLAG_SAVE_UNPAID
#define SET_MAP_LIGHT(M, X, Y, L)
void map_reset_swap(mapstruct *m)
const char *const map_layer_name[MAP_LAYERS]
static int load_overlay_map(const char *filename, mapstruct *m)
#define FOR_INV_PREPARE(op_, it_)
int check_path(const char *name, int prepend_dir)
void events_execute_global_event(int eventcode,...)
void load_objects(mapstruct *m, FILE *fp, int mapflags)
#define SET_MAP_MOVE_OFF(M, X, Y, C)