37 #define PROFILE_BEGIN(expr) { \ 38 struct timespec _begin, _end; \ 39 clock_gettime(CLOCK_MONOTONIC, &_begin); \ 42 #define PROFILE_END(var, expr) \ 43 clock_gettime(CLOCK_MONOTONIC, &_end); \ 44 long var = timespec_diff(&_end, &_begin); \ 55 "floor",
"no_pick",
"no_pick",
"item",
"item",
56 "item",
"living",
"living",
"fly",
"fly" 94 if (!strcmp(name, map->
path))
221 strlcpy(buf, name,
sizeof(buf));
223 return(_access(buf, 0));
226 if (stat(buf, &statbuf) != 0)
232 if (((statbuf.st_mode&
S_IRGRP) && getegid() == statbuf.st_gid)
233 || ((statbuf.st_mode&
S_IRUSR) && geteuid() == statbuf.st_uid)
237 if ((statbuf.st_mode&
S_IWGRP && getegid() == statbuf.st_gid)
238 || (statbuf.st_mode&
S_IWUSR && geteuid() == statbuf.st_uid)
362 LOG(
llevError,
"blocked_link: Passed map, x, y coordinates outside of map\n");
403 tmp_head =
HEAD(tmp);
513 for (tmp = ob->
arch, part = ob; tmp != NULL; tmp = tmp->
more, part = part->
more) {
560 for (at = tmp->arch->
more, last = tmp; at != NULL; at = at->
more, last = op) {
568 if (tmp->name != op->
name) {
573 if (tmp->title != op->
title) {
603 if (tmp->head || tmp->more)
624 object *op, *prev = NULL, *last_more = NULL;
630 while ((i =
load_object(fp, op, bufstate, mapflags))) {
641 if (op->
arch == NULL) {
651 LOG(
llevError,
"Discarding invalid item with type PLAYER in map %s\n", m->
path);
690 last_more->
more = op,
702 "load_objects: while loop took %ld, body took %ld\n",
703 diff, cum_body_time));
704 for (i = 0; i < m->
width; i++) {
705 for (j = 0; j < m->
height; j++) {
738 int i, j = 0, unique = 0, res = 0;
739 unsigned int count = 0;
773 LOG(
llevDebug,
"save_objects on %s took %ld us (%u objects = %f us each)\n", m->
path, diff, count, (
double)diff/count));
846 LOG(
llevError,
"allocate_map called with already allocated map (%s)\n", m->
path);
892 char *shop_string, *p, *q, *next_semicolon, *next_colon;
894 int i = 0, number_of_entries = 0;
922 for (i = 0; i < number_of_entries; i++) {
924 LOG(
llevError,
"parse_shop_string: I seem to have run out of string, that shouldn't happen.\n");
927 next_semicolon = strchr(p,
';');
928 next_colon = strchr(p,
':');
930 if (next_colon && (!next_semicolon || next_colon < next_semicolon))
931 items[i].
strength = atoi(strchr(p,
':')+1);
933 if (isdigit(*p) || *p ==
'*') {
934 items[i].
typenum = *p ==
'*' ? -1 : atoi(p);
941 q = strpbrk(p,
";:");
953 LOG(
llevError,
"invalid type %s defined in shopitems for %s in string %s\n", p, map->
name, input_string);
956 items[i].
index = number_of_entries;
958 p = ++next_semicolon;
981 output_string[0] =
'\0';
994 snprintf(output_string+strlen(output_string), size-strlen(output_string),
"%s", tmp);
998 if (strlen(output_string) > 0) {
999 output_string[strlen(output_string) - 1] =
'\0';
1023 char buf[
HUGE_BUF], *key = NULL, *value;
1026 while (fgets(buf,
sizeof(buf), fp) != NULL) {
1029 p = strchr(buf,
'\n');
1031 LOG(
llevError,
"Error loading map header - did not find a newline - perhaps file is truncated? Buf=%s\n", buf);
1037 while (isspace(*key))
1041 value = strchr(key,
' ');
1045 while (isspace(*value)) {
1047 if (*value ==
'\0') {
1070 if (!strcmp(key,
"msg")) {
1074 while (fgets(buf,
sizeof(buf), fp) != NULL) {
1075 if (!strcmp(buf,
"endmsg\n"))
1078 snprintf(msgbuf+msgpos,
sizeof(msgbuf)-msgpos,
"%s", buf);
1079 msgpos += strlen(buf);
1092 }
else if (!strcmp(key,
"maplore")) {
1094 size_t maplorepos = 0;
1096 while (fgets(buf,
HUGE_BUF-1, fp) != NULL) {
1097 if (!strcmp(buf,
"endmaplore\n"))
1100 if (maplorepos >=
sizeof(maplorebuf)) {
1104 snprintf(maplorebuf+maplorepos,
sizeof(maplorebuf)-maplorepos,
"%s", buf);
1105 maplorepos += strlen(buf);
1108 if (maplorepos != 0)
1110 }
else if (!strcmp(key,
"end")) {
1112 }
else if (value == NULL) {
1113 LOG(
llevError,
"Got '%s' line without parameter in map header\n", key);
1114 }
else if (!strcmp(key,
"arch")) {
1116 if (strcmp(value,
"map")) {
1117 LOG(
llevError,
"load_map_header: expected 'arch map': check line endings?\n");
1120 }
else if (!strcmp(key,
"name")) {
1128 }
else if (!strcmp(key,
"enter_x")) {
1130 }
else if (!strcmp(key,
"enter_y")) {
1132 }
else if (!strcmp(key,
"width")) {
1133 m->
width = atoi(value);
1134 }
else if (!strcmp(key,
"height")) {
1136 }
else if (!strcmp(key,
"reset_timeout")) {
1138 }
else if (!strcmp(key,
"swap_time")) {
1140 }
else if (!strcmp(key,
"difficulty")) {
1142 }
else if (!strcmp(key,
"darkness")) {
1144 }
else if (!strcmp(key,
"fixed_resettime")) {
1146 }
else if (!strcmp(key,
"unique")) {
1148 }
else if (!strcmp(key,
"template")) {
1150 }
else if (!strcmp(key,
"region")) {
1152 }
else if (!strcmp(key,
"shopitems")) {
1154 }
else if (!strcmp(key,
"shopgreed")) {
1156 }
else if (!strcmp(key,
"shopmin")) {
1158 }
else if (!strcmp(key,
"shopmax")) {
1160 }
else if (!strcmp(key,
"shoprace")) {
1162 }
else if (!strcmp(key,
"outdoor")) {
1164 }
else if (!strcmp(key,
"nosmooth")) {
1166 }
else if (!strcmp(key,
"first_load")) {
1168 }
else if (!strncmp(key,
"tile_path_", 10)) {
1169 int tile = atoi(key+10);
1171 if (tile < 1 || tile > 4) {
1172 LOG(
llevError,
"load_map_header: tile location %d out of bounds (%s)\n", tile, m->
path);
1175 LOG(
llevError,
"load_map_header: tile location %d duplicated (%s)\n", tile, m->
path);
1180 }
else if (!strcmp(key,
"background_music")) {
1183 LOG(
llevError,
"Got unknown value in map header: %s %s\n", key, value);
1190 if (!key || strcmp(key,
"end")) {
1227 if ((fp = fopen(pathname,
"r")) == NULL) {
1229 "Can't open %s: %s\n", pathname, strerror(errno));
1237 LOG(
llevError,
"Error loading map header for %s, flags=%d\n", map, flags);
1259 if (!(flags & MAP_STYLE))
1263 LOG(
llevDebug,
"mapfile_load on %s" " took %ld us\n", map, diff));
1284 if ((fp = fopen(m->
tmpname,
"r")) == NULL) {
1318 if ((fp = fopen(pathname,
"r")) == NULL) {
1324 LOG(
llevError,
"Error loading map header for overlay %s (%s)\n", m->
path, pathname);
1348 int i, j, unique = 0;
1378 for (count = 0; count < 10; count++) {
1379 snprintf(firstname,
sizeof(firstname),
"%s.v%02d", name, count);
1380 if (!access(firstname,
R_OK))
1387 if ((fp = fopen(firstname,
"r")) == NULL) {
1391 LOG(
llevDebug,
"Can't open unique items file for %s\n", name);
1420 #define TEMP_EXT ".savefile" 1426 if (flag && !*m->
path) {
1440 if (m->
path[0] !=
'~') {
1442 "Cannot save unique map '%s' outside of LOCALDIR. Check " 1443 "that all exits to '%s' have FLAG_UNIQUE set correctly.\n",
1458 strlcpy(
final, filename,
sizeof(
final));
1465 fprintf(fp,
"arch map\n");
1467 fprintf(fp,
"name %s\n", m->
name);
1469 fprintf(fp,
"swap_time %d\n", m->
swap_time);
1478 fprintf(fp,
"difficulty %d\n", m->
difficulty);
1483 fprintf(fp,
"shopitems %s\n", shop);
1486 fprintf(fp,
"shopgreed %f\n", m->
shopgreed);
1492 fprintf(fp,
"shoprace %s\n", m->
shoprace);
1494 fprintf(fp,
"darkness %d\n", m->
darkness);
1496 fprintf(fp,
"width %d\n", m->
width);
1498 fprintf(fp,
"height %d\n", m->
height);
1500 fprintf(fp,
"enter_x %d\n", m->
enter_x);
1502 fprintf(fp,
"enter_y %d\n", m->
enter_y);
1504 fprintf(fp,
"msg\n%sendmsg\n", m->
msg);
1506 fprintf(fp,
"maplore\n%sendmaplore\n", m->
maplore);
1508 fprintf(fp,
"unique %d\n", m->
unique);
1512 fprintf(fp,
"outdoor %d\n", m->
outdoor);
1514 fprintf(fp,
"nosmooth %d\n", m->
nosmooth);
1522 for (i = 0; i < 4; i++)
1524 fprintf(fp,
"tile_path_%d %s\n", i+1, m->
tile_path[i]);
1526 fprintf(fp,
"end\n");
1537 snprintf(final_unique,
sizeof(final_unique),
"%s.v00", name);
1548 LOG(
llevError,
"Save error during object save: %d\n", res);
1557 LOG(
llevError,
"Save error during object save: %d\n", res);
1564 if (ftell(fp2) == 0) {
1578 if (rename(buf, final_unique) == -1) {
1579 LOG(
llevError,
"Couldn't rename unique file %s to %s\n", buf, final_unique);
1584 if (chmod(final_unique,
SAVE_MODE) != 0) {
1592 LOG(
llevError,
"Save error during object save: %d\n", res);
1602 if (rename(filename,
final) == -1) {
1603 LOG(
llevError,
"Couldn't rename regular file %s to %s\n", filename,
final);
1608 LOG(
llevError,
"Could not set permissions on '%s'\n",
final);
1648 object *previous_obj = NULL;
1651 if (op == previous_obj) {
1652 LOG(
llevDebug,
"free_all_objects: Link error, bailing out.\n");
1674 LOG(
llevDebug,
"free_all_objects: object %s still on map after it should have been freed\n", op->
name);
1719 for (i = 0; i < 4; i++) {
1765 for (i = 0; i < 4; i++)
1815 if (strncmp(name, buf, strlen(buf)) == 0) {
1816 snprintf(buf2,
sizeof(buf2),
"~%s", name+strlen(buf)+1);
1821 if (name[0] ==
'~') {
1841 if (m == NULL)
return NULL;
1846 if (!(flags&(
MAP_FLUSH|MAP_PLAYER_UNIQUE)))
1926 int64_t exp_pr_sq, total_exp = 0;
1936 total_exp += op->stats.exp;
1938 total_exp += op->stats.exp;
1947 for (i = 1; i < 20; i++)
1983 LOG(
llevDebug,
"free_all_maps: Freed %d maps\n", real_maps);
2004 int new_level = m->
darkness+change;
2008 || (new_level <= 0 && m->darkness == 0)
2068 if (!honor_visibility)
2075 for (l1 = (l-1); l1 >= low_layer; l1--) {
2076 if (layers[l1]->face->visibility > layers[l1+1]->
face->
visibility) {
2078 layers[l1+1] = layers[l1];
2088 if (!honor_visibility) {
2093 layers[l] = layers[l+1];
2104 for (l = high_layer; l >= low_layer; l--) {
2106 for (l1 = low_layer; l1 < l; l1++)
2107 layers[l1] = layers[l1+1];
2132 MoveType move_block = 0, move_slow = 0, move_on = 0, move_off = 0, move_allow = 0;
2136 LOG(
llevDebug,
"update_position called with P_NEED_UPDATE not set: %s (%d, %d)\n", m->
path, x, y);
2140 memset(layers, 0,
MAP_LAYERS*
sizeof(
object *));
2155 if (tmp->glow_radius > light)
2162 if (!tmp->invisible && tmp->face !=
blank_face) {
2163 if (tmp->map_layer) {
2173 memset(layers+1, 0, (
MAP_LAYERS-1)*
sizeof(
object *));
2184 if (tmp == tmp->above) {
2189 move_slow |= tmp->move_slow;
2190 move_block |= tmp->move_block;
2191 move_on |= tmp->move_on;
2192 move_off |= tmp->move_off;
2193 move_allow |= tmp->move_allow;
2213 if (((oldflags&~(P_NEED_UPDATE|
P_NO_ERROR)) != flags)
2215 LOG(
llevDebug,
"update_position: updated flags do not match old flags: %s (x=%d,y=%d) %x != %x\n",
2216 m->
path, x, y, (oldflags&~P_NEED_UPDATE), flags);
2268 int dest_tile = (tile_num+2)%4;
2274 if (orig_map->
tile_map[tile_num] == NULL) {
2286 return orig_map->
tile_map[tile_num];
2385 if ( !m )
return NULL;
2469 }
else if (map1->
tile_map[0] == map2) {
2472 }
else if (map1->
tile_map[1] == map2) {
2475 }
else if (map1->
tile_map[2] == map2) {
2478 }
else if (map1->
tile_map[3] == map2) {
2546 retval->
part = NULL;
2556 if (!(flags&0x1) && op1->
more) {
2567 for (tmp = op1->
more; tmp != NULL; tmp = tmp->
more) {
2570 if (tmpi < best_distance) {
2571 best_distance = tmpi;
2580 retval->
part = best;
2620 retval->
part = NULL;
2626 retval->
part = NULL;
2698 LOG(
llevError,
"Could not delete %s: %s\n", path, strerror(errno));
2705 for (count = 0; count < 10; count++) {
2706 snprintf(path,
sizeof(path),
"%s.v%02d", base, count);
2717 if (item->
map != NULL) {
2718 if (strlen(item->
map->
path) > 0) {
2722 return item->
map->
name ? item->
map->
name :
"(empty path and name)";
2725 if (item->
env != NULL)
2728 return "(no map and no env!)";
int find_dir_2(int x, int y)
mapstruct * mapfile_load(const char *map, int flags)
static void allocate_map(mapstruct *m)
mapstruct * get_linked_map(void)
int64_t level_exp(int level, double expmul)
static mapstruct * load_and_link_tiled_map(mapstruct *orig_map, int tile_num)
void of_cancel(OutputFile *of)
mapstruct * get_empty_map(int sizex, int sizey)
region * get_region_by_name(const char *region_name)
int get_rangevector_from_mapcoord(const mapstruct *m, int x, int y, const object *op2, rv_vector *retval, int flags)
void make_path_to_file(const char *filename)
static int save_objects(mapstruct *m, FILE *fp, FILE *fp2, int flag)
uint32_t map_size(mapstruct *m)
static const Map_Layer_Info map_layer_info[MAP_LAYERS]
void fatal(enum fatal_error err)
struct mapdef * tile_map[4]
char * create_pathname(const char *name, char *buf, size_t size)
mapstruct * ready_map_name(const char *name, int flags)
void free_string(sstring str)
signed long object_sum_weight(object *op)
static shopitems * parse_shop_string(const char *input_string, const mapstruct *map)
void object_fix_multipart(object *tmp)
mapstruct * get_map_from_coord(mapstruct *m, int16_t *x, int16_t *y)
#define SET_MAP_LIGHT(M, X, Y, L)
int calculate_difficulty(mapstruct *m)
struct Map_Layer_Info Map_Layer_Info
void decay_objects(mapstruct *m)
#define OUT_OF_REAL_MAP(M, X, Y)
int blocked_link(object *ob, mapstruct *m, int16_t sx, int16_t sy)
const typedata * get_typedata_by_name(const char *name)
void strip_endline(char *buf)
void free_map(mapstruct *m)
static int load_temporary_map(mapstruct *m)
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
void free_objectlinkpt(oblinkpt *obp)
const char * map_get_path(const object *item)
int change_map_light(mapstruct *m, int change)
#define MAP_WHEN_RESET(m)
#define PROFILE_BEGIN(expr)
#define MAP_LAYER_LIVING2
const typedata * get_typedata(int itemtype)
#define SAVE_FLAG_SAVE_UNPAID
void object_free_drop_inventory(object *ob)
#define MAP_LAYER_NO_PICK1
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
static int load_map_header(FILE *fp, mapstruct *m)
object * object_new(void)
#define FLAG_OBJ_ORIGINAL
#define SET_MAP_MOVE_SLOW(M, X, Y, C)
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
static void link_multipart_objects(mapstruct *m)
#define PROFILE_END(var, expr)
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
void object_remove_from_active_list(object *op)
void update_position(mapstruct *m, int x, int y)
#define SET_MAP_PLAYER(M, X, Y, C)
int of_close(OutputFile *of)
int save_object(FILE *fp, object *op, int flag)
int execute_global_event(int eventcode,...)
#define OB_TYPE_MOVE_BLOCK(ob1, type)
#define FLAG_OVERLAY_FLOOR
#define SAVE_ERROR_NO_PATH
#define GET_MAP_MOVE_BLOCK(M, X, Y)
#define MAP_DIFFICULTY(m)
#define SAVE_ERROR_URENAME
static void delete_unique_items(mapstruct *m)
#define SET_MAP_MOVE_OFF(M, X, Y, C)
int on_same_map(const object *op1, const object *op2)
#define QUERY_FLAG(xyz, p)
#define CLEAR_FLAG(xyz, p)
#define INS_ABOVE_FLOOR_ONLY
void dump_map(const mapstruct *m)
#define GENERATE_TYPE(xyz)
const char *const map_layer_name[MAP_LAYERS]
char * tempnam(const char *dir, const char *pfx)
static const flag_definition flags[]
#define MAP_LAYER_NO_PICK2
static int adjacent_map(const mapstruct *map1, const mapstruct *map2, int *dx, int *dy)
#define SAVE_FLAG_NO_REMOVE
int save_map(mapstruct *m, int flag)
#define SAVE_ERROR_UCREATION
#define GET_MAP_FLAGS(M, X, Y)
static void free_all_objects(mapstruct *m)
#define SET_MAP_MOVE_ON(M, X, Y, C)
void set_map_reset_time(mapstruct *map)
#define SET_MAP_FLAGS(M, X, Y, C)
#define MAP_LAYER_LIVING1
static void load_unique_objects(mapstruct *m)
void update_all_map_los(mapstruct *map)
object * map_find_by_flag(mapstruct *map, int x, int y, int flag)
#define MAP_PLAYER_UNIQUE
archetype * get_archetype_by_type_subtype(int type, int subtype)
int load_object(FILE *fp, object *op, int bufstate, int map_flags)
mapstruct * has_been_loaded(const char *name)
static void print_shop_string(mapstruct *m, char *output_string, int size)
static void load_objects(mapstruct *m, FILE *fp, int mapflags)
FILE * of_open(OutputFile *of, const char *fname)
int out_of_map(mapstruct *m, int x, int y)
void delete_map(mapstruct *m)
void apply_auto_fix(mapstruct *m)
#define MAP_RESET_TIMEOUT(m)
#define GET_MAP_FACE_OBJS(M, X, Y)
static void create_items_path(const char *s, char *buf, size_t size)
sstring add_string(const char *str)
#define GET_MAP_OB(M, X, Y)
int check_path(const char *name, int prepend_dir)
static void fix_container_multipart(object *container)
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
#define OB_MOVE_BLOCK(ob1, ob2)
#define SAVE_ERROR_RRENAME
void LOG(LogLevel logLevel, const char *format,...)
#define SAVE_ERROR_RCREATION
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
struct shopitem * shopitems
#define MSG_TYPE_ATTACK_NOKEY
void set_darkness_map(mapstruct *m)
void create_overlay_pathname(const char *name, char *buf, size_t size)
#define FREE_AND_CLEAR(xyz)
#define SET_MAP_MOVE_BLOCK(M, X, Y, C)
static int load_overlay_map(const char *filename, mapstruct *m)
int get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1)
void create_template_pathname(const char *name, char *buf, size_t size)
void map_remove_unique_files(const mapstruct *map)
struct regiondef * region
void clean_tmp_map(mapstruct *m)
EXTERN mapstruct * first_map
object * arch_to_object(archetype *at)
void clean_object(object *op)
object * object_get_owner(object *op)
#define SAVE_MODE_OVERLAY
size_t strlcpy(char *dst, const char *src, size_t size)
#define FOR_INV_PREPARE(op_, it_)
void object_remove(object *op)
static void add_face_layer(int low_layer, int high_layer, object *ob, object *layers[], int honor_visibility)