Go to the documentation of this file.
46 "floor",
"no_pick",
"no_pick",
"item",
"item",
47 "item",
"living",
"living",
"fly",
"fly"
175 snprintf(
t,
buf+size-
t,
"%s", s);
214 return(_access(
buf, 0));
217 if (stat(
buf, &statbuf) != 0)
220 if (!S_ISREG(statbuf.st_mode))
223 if (((statbuf.st_mode&
S_IRGRP) && getegid() == statbuf.st_gid)
224 || ((statbuf.st_mode&
S_IRUSR) && geteuid() == statbuf.st_uid)
228 if ((statbuf.st_mode&
S_IWGRP && getegid() == statbuf.st_gid)
229 || (statbuf.st_mode&
S_IWUSR && geteuid() == statbuf.st_uid)
253 if (
m->maplore != NULL)
256 if (
m->tmpname != NULL)
353 LOG(
llevError,
"blocked_link: Passed map, x, y coordinates outside of map\n");
364 mflags =
m->spaces[sx+
m->width*sy].flags;
551 for (at =
tmp->arch->more, last =
tmp; at != NULL; at = at->
more, last =
op) {
559 if (
tmp->name !=
op->name) {
564 if (
tmp->title !=
op->title) {
594 if (
tmp->head ||
tmp->more)
615 object *
op, *prev = NULL, *last_more = NULL;
632 if (
op->arch == NULL) {
633 LOG(
llevDebug,
"Discarding object without arch: %s\n",
op->name ?
op->name :
"(null)");
642 LOG(
llevError,
"Discarding invalid item with type PLAYER in map %s\n",
m->path);
648 LOG(
llevError,
" object %s not on valid map position %s:%d:%d\n",
op->name ?
op->name :
"(null)",
m->path,
op->x,
op->y);
691 "load_objects on %s took %ld us\n",
m->path, diff));
692 for (i = 0; i <
m->width; i++) {
693 for (j = 0; j <
m->height; j++) {
726 int i, j = 0, unique = 0;
727 unsigned int count = 0;
732 long serialize_time, write_time;
773 LOG(
llevDebug,
"saved %d objects on %s (%d us serializing, %d us writing)\n",
count,
m->path, serialize_time, write_time);
820 map->last_reset_time = 0;
826 return (uint32_t)
m->width * (uint32_t)
m->height;
846 LOG(
llevError,
"allocate_map called with already allocated map (%s)\n",
m->path);
852 if (
m->spaces == NULL)
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';
982 for (i = 0; i <
m->shopitems[0].index; i++) {
983 if (
m->shopitems[i].typenum != -1) {
984 if (
m->shopitems[i].strength) {
985 snprintf(
tmp,
sizeof(
tmp),
"%s:%d;",
m->shopitems[i].name,
m->shopitems[i].strength);
987 snprintf(
tmp,
sizeof(
tmp),
"%s;",
m->shopitems[i].name);
989 if (
m->shopitems[i].strength) {
990 snprintf(
tmp,
sizeof(
tmp),
"*:%d;",
m->shopitems[i].strength);
992 snprintf(
tmp,
sizeof(
tmp),
"*;");
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';
1025 m->width =
m->height = 0;
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))
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"))
1079 msgpos += strlen(
buf);
1092 }
else if (!strcmp(
key,
"maplore")) {
1094 size_t maplorepos = 0;
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")) {
1129 m->enter_x = atoi(
value);
1130 }
else if (!strcmp(
key,
"enter_y")) {
1131 m->enter_y = atoi(
value);
1132 }
else if (!strcmp(
key,
"width")) {
1134 }
else if (!strcmp(
key,
"height")) {
1136 }
else if (!strcmp(
key,
"reset_timeout")) {
1137 m->reset_timeout = atoi(
value);
1138 }
else if (!strcmp(
key,
"swap_time")) {
1139 m->timeout = atoi(
value);
1140 }
else if (!strcmp(
key,
"difficulty")) {
1141 m->difficulty = atoi(
value);
1142 }
else if (!strcmp(
key,
"darkness")) {
1143 m->darkness = atoi(
value);
1144 }
else if (!strcmp(
key,
"fixed_resettime")) {
1145 m->fixed_resettime = atoi(
value);
1146 }
else if (!strcmp(
key,
"unique")) {
1148 }
else if (!strcmp(
key,
"template")) {
1149 m->is_template = atoi(
value);
1150 }
else if (!strcmp(
key,
"region")) {
1152 }
else if (!strcmp(
key,
"shopitems")) {
1154 }
else if (!strcmp(
key,
"shopgreed")) {
1155 m->shopgreed = atof(
value);
1156 }
else if (!strcmp(
key,
"shopmin")) {
1157 m->shopmin = atol(
value);
1158 }
else if (!strcmp(
key,
"shopmax")) {
1159 m->shopmax = atol(
value);
1160 }
else if (!strcmp(
key,
"shoprace")) {
1162 }
else if (!strcmp(
key,
"outdoor")) {
1163 m->outdoor = atoi(
value);
1164 }
else if (!strcmp(
key,
"nosmooth")) {
1165 m->nosmooth = atoi(
value);
1166 }
else if (!strcmp(
key,
"first_load")) {
1167 m->last_reset_time = atoi(
value);
1168 }
else if (!strncmp(
key,
"tile_path_", 10)) {
1171 if (tile < 1 || tile > 4) {
1172 LOG(
llevError,
"load_map_header: tile location %d out of bounds (%s)\n",
tile,
m->path);
1174 if (
m->tile_path[
tile-1]) {
1175 LOG(
llevError,
"load_map_header: tile location %d duplicated (%s)\n",
tile,
m->path);
1176 free(
m->tile_path[
tile-1]);
1180 }
else if (!strcmp(
key,
"background_music")) {
1182 }
else if (!strcmp(
key,
"reset_group")) {
1188 if ((
m->width == 0) || (
m->height == 0)) {
1192 if (!
key || strcmp(
key,
"end")) {
1229 if ((fp = fopen(pathname,
"r")) == NULL) {
1231 "Can't open %s: %s\n", pathname, strerror(errno));
1281 LOG(
llevError,
"No temporary filename for map %s\n",
m->path);
1285 if ((fp = fopen(
m->tmpname,
"r")) == NULL) {
1286 LOG(
llevError,
"Cannot open %s: %s\n",
m->tmpname, strerror(errno));
1291 LOG(
llevError,
"Error loading map header for %s (%s)\n",
m->path,
m->tmpname);
1319 if ((fp = fopen(pathname,
"r")) == NULL) {
1325 LOG(
llevError,
"Error loading map header for overlay %s (%s)\n",
m->path, pathname);
1349 int i, j, unique = 0;
1380 snprintf(firstname,
sizeof(firstname),
"%s.v%02d",
name,
count);
1381 if (!access(firstname, R_OK))
1388 if ((fp = fopen(firstname,
"r")) == NULL) {
1397 if (
m->tmpname == NULL)
1426 if (flag && !*
m->path) {
1434 if (!
m->unique && !
m->is_template) {
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",
1463 fprintf(fp,
"arch map\n");
1465 fprintf(fp,
"name %s\n",
m->name);
1467 fprintf(fp,
"swap_time %d\n",
m->swap_time);
1468 if (
m->reset_timeout)
1469 fprintf(fp,
"reset_timeout %u\n",
m->reset_timeout);
1470 if (
m->fixed_resettime)
1471 fprintf(fp,
"fixed_resettime %d\n",
m->fixed_resettime);
1476 fprintf(fp,
"difficulty %d\n",
m->difficulty);
1478 fprintf(fp,
"region %s\n",
m->region->name);
1481 fprintf(fp,
"shopitems %s\n", shop);
1484 fprintf(fp,
"shopgreed %f\n",
m->shopgreed);
1486 fprintf(fp,
"shopmin %"FMT64U"\n",
m->shopmin);
1488 fprintf(fp,
"shopmax %"FMT64U"\n",
m->shopmax);
1490 fprintf(fp,
"shoprace %s\n",
m->shoprace);
1492 fprintf(fp,
"darkness %d\n",
m->darkness);
1494 fprintf(fp,
"width %d\n",
m->width);
1496 fprintf(fp,
"height %d\n",
m->height);
1498 fprintf(fp,
"enter_x %d\n",
m->enter_x);
1500 fprintf(fp,
"enter_y %d\n",
m->enter_y);
1502 fprintf(fp,
"msg\n%sendmsg\n",
m->msg);
1504 fprintf(fp,
"maplore\n%sendmaplore\n",
m->maplore);
1506 fprintf(fp,
"unique %d\n",
m->unique);
1508 fprintf(fp,
"template %d\n",
m->is_template);
1510 fprintf(fp,
"outdoor %d\n",
m->outdoor);
1512 fprintf(fp,
"nosmooth %d\n",
m->nosmooth);
1513 if (
m->last_reset_time)
1514 fprintf(fp,
"first_load %ld\n",
m->last_reset_time);
1515 if (
m->background_music)
1516 fprintf(fp,
"background_music %s\n",
m->background_music);
1518 fprintf(fp,
"reset_group %s\n",
m->reset_group);
1522 for (i = 0; i < 4; i++)
1523 if (
m->tile_path[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);
1538 fp2 =
of_open(&of2, final_unique);
1563 if (ftell(fp2) == 0) {
1569 unlink(final_unique);
1576 if (chmod(final_unique,
SAVE_MODE) != 0) {
1599 LOG(
llevDebug,
"save_map on %s" " took %ld us\n",
m->path, diff));
1635 object *previous_obj = NULL;
1638 if (
op == previous_obj) {
1639 LOG(
llevDebug,
"free_all_objects: Link error, bailing out.\n");
1661 LOG(
llevError,
"free_all_objects: object %s still on map after it should have been freed\n",
op->name);
1679 if (!
m->in_memory) {
1700 if (
m->background_music)
1705 for (i = 0; i < 4; i++) {
1706 if (
m->tile_path[i])
1708 m->tile_map[i] = NULL;
1752 for (i = 0; i < 4; i++)
1753 if (
tmp->tile_map[i] ==
m)
1754 tmp->tile_map[i] = NULL;
1765 LOG(
llevError,
"delete_map: Unable to find map %s in list\n",
m->path);
1767 last->
next =
m->next;
1803 snprintf(buf2,
sizeof(buf2),
"~%s",
name+strlen(
buf)+1);
1808 if (
name[0] ==
'~') {
1828 if (
m == NULL)
return NULL;
1886 if (
m->last_reset_time == 0) {
1916 int64_t exp_pr_sq, total_exp = 0;
1926 total_exp +=
op->stats.exp;
1928 total_exp +=
op->stats.exp;
1931 at =
op->other_arch ?
op->other_arch : NULL;
1935 int lim = atoi(val ? val :
"0");
1937 if (!lim || lim >= 16)
1953 for (i = 1; i < 25; i++)
1969 if (
m->tmpname == NULL)
1971 (
void)unlink(
m->tmpname);
1989 LOG(
llevDebug,
"free_all_maps: Freed %d maps\n", real_maps);
2010 int new_level =
m->darkness+change;
2014 || (new_level <= 0 && m->darkness == 0)
2035 m->darkness = new_level;
2064 static inline void add_face_layer(
int low_layer,
int high_layer,
object *
ob,
object *layers[],
int honor_visibility) {
2068 for (
l = low_layer;
l <= high_layer;
l++) {
2074 if (!honor_visibility)
2081 for (l1 = (
l-1); l1 >= low_layer; l1--) {
2082 if (layers[l1]->face->visibility > layers[l1+1]->
face->
visibility) {
2084 layers[l1+1] = layers[l1];
2094 if (!honor_visibility) {
2098 for (
l = low_layer;
l < high_layer;
l++)
2099 layers[
l] = layers[
l+1];
2100 layers[high_layer] =
ob;
2110 for (
l = high_layer;
l >= low_layer;
l--) {
2112 for (l1 = low_layer; l1 <
l; l1++)
2113 layers[l1] = layers[l1+1];
2135 uint8_t
flags = 0, oldflags, light = 0;
2138 MoveType move_block = 0, move_slow = 0, move_on = 0, move_off = 0, move_allow = 0;
2142 LOG(
llevDebug,
"update_position called with P_NEED_UPDATE not set: %s (%d, %d)\n",
m->path,
x,
y);
2146 memset(layers, 0,
MAP_LAYERS*
sizeof(
object *));
2161 if (
tmp->glow_radius > light)
2162 light =
tmp->glow_radius;
2169 if (
tmp->map_layer) {
2179 memset(layers+1, 0, (
MAP_LAYERS-1)*
sizeof(
object *));
2195 move_slow |=
tmp->move_slow;
2196 move_block |=
tmp->move_block;
2197 move_on |=
tmp->move_on;
2198 move_off |=
tmp->move_off;
2199 move_allow |=
tmp->move_allow;
2221 LOG(
llevDebug,
"update_position: updated flags do not match old flags: %s (x=%d,y=%d) %x != %x\n",
2274 int dest_tile = (tile_num+2)%4;
2280 if (orig_map->
tile_map[tile_num] == NULL) {
2292 return orig_map->
tile_map[tile_num];
2321 if (!
m->tile_path[3])
2326 if (!
m->tile_map[3])
2331 if (!
m->tile_path[1])
2336 if (!
m->tile_map[1])
2343 if (!
m->tile_path[0])
2348 if (!
m->tile_map[0])
2353 if (!
m->tile_path[2])
2358 if (!
m->tile_map[2])
2391 if ( !
m )
return NULL;
2400 if (!
m->tile_path[3])
2405 if (!
m->tile_map[3])
2412 if (!
m->tile_path[1])
2417 if (!
m->tile_map[1])
2426 if (!
m->tile_path[0])
2431 if (!
m->tile_map[0])
2438 if (!
m->tile_path[2])
2443 if (!
m->tile_map[2])
2475 }
else if (map1->
tile_map[0] == map2) {
2478 }
else if (map1->
tile_map[1] == map2) {
2481 }
else if (map1->
tile_map[2] == map2) {
2484 }
else if (map1->
tile_map[3] == map2) {
2552 retval->
part = NULL;
2576 if (tmpi < best_distance) {
2577 best_distance = tmpi;
2586 retval->
part = best;
2626 retval->
part = NULL;
2632 retval->
part = NULL;
2703 if (unlink(
path) != 0) {
2723 if (
item->map != NULL) {
2724 if (strlen(
item->map->path) > 0) {
2725 return item->map->path;
2728 return item->map->name ?
item->map->name :
"(empty path and name)";
2731 if (
item->env != NULL)
2734 return "(no map and no env!)";
mapstruct * get_linked_map(void)
#define GET_MAP_OB(M, X, Y)
mapstruct * ready_map_name(const char *name, int flags)
void of_cancel(OutputFile *of)
#define FREE_AND_CLEAR_STR_IF(xyz)
#define FREE_OBJ_NO_DESTROY_CALLBACK
void object_free(object *ob, int flags)
sstring add_string(const char *str)
void object_remove(object *op)
StringBuffer * stringbuffer_new(void)
signed long object_sum_weight(object *op)
#define MAP_NO_DIFFICULTY
int check_path(const char *name, int prepend_dir)
#define FLAG_OVERLAY_FLOOR
region * get_region_by_name(const char *region_name)
#define MAP_RESET_TIMEOUT(m)
int load_object(FILE *fp, object *op, int bufstate, int map_flags)
#define SAVE_FLAG_NO_REMOVE
void clean_tmp_map(mapstruct *m)
#define QUERY_FLAG(xyz, p)
void clean_object(object *op)
int out_of_map(mapstruct *m, int x, int y)
void decay_objects(mapstruct *m)
object * object_new(void)
int calculate_difficulty(mapstruct *m)
#define FLAG_OBJ_ORIGINAL
#define SET_MAP_MOVE_ON(M, X, Y, C)
int blocked_link(object *ob, mapstruct *m, int16_t sx, int16_t sy)
char * create_pathname(const char *name, char *buf, size_t size)
struct mapdef * tile_map[4]
static char msgbuf[HUGE_BUF]
static mapstruct * load_and_link_tiled_map(mapstruct *orig_map, int tile_num)
#define MAP_PLAYER_UNIQUE
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
#define PROFILE_BEGIN(expr)
static const flag_definition flags[]
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)
EXTERN mapstruct * first_map
#define GET_MAP_FACE_OBJS(M, X, Y)
void make_path_to_file(const char *filename)
const char *const map_layer_name[MAP_LAYERS]
#define SAVE_MODE_OVERLAY
static shopitems * parse_shop_string(const char *input_string, const mapstruct *map)
#define INS_ABOVE_FLOOR_ONLY
const char * object_get_value(const object *op, const char *const key)
void free_string(sstring str)
static int adjacent_map(const mapstruct *map1, const mapstruct *map2, int *dx, int *dy)
#define PROFILE_END(var, expr)
static event_registration m
void set_darkness_map(mapstruct *m)
void apply_auto_fix(mapstruct *m)
#define MAP_LAYER_NO_PICK2
static int load_temporary_map(mapstruct *m)
#define MAP_DIFFICULTY(m)
int change_map_light(mapstruct *m, int change)
void strip_endline(char *buf)
#define MSG_TYPE_ATTACK_NOKEY
int of_close(OutputFile *of)
static int load_map_header(FILE *fp, mapstruct *m)
void fatal(enum fatal_error err)
void object_fix_multipart(object *tmp)
#define SAVE_ERROR_RCREATION
#define MAP_WHEN_RESET(m)
static const Map_Layer_Info map_layer_info[MAP_LAYERS]
static void create_items_path(const char *s, char *buf, size_t size)
#define SET_MAP_FLAGS(M, X, Y, C)
object * map_find_by_flag(mapstruct *map, int x, int y, int flag)
#define MAP_LAYER_LIVING1
char * stringbuffer_finish(StringBuffer *sb)
#define GET_MAP_MOVE_BLOCK(M, X, Y)
void free_map(mapstruct *m)
static void link_multipart_objects(mapstruct *m)
void load_objects(mapstruct *m, FILE *fp, int mapflags)
const char * map_get_path(const object *item)
struct Map_Layer_Info Map_Layer_Info
EXTERN sstring blocks_prayer
void delete_map(mapstruct *m)
void create_overlay_pathname(const char *name, char *buf, size_t size)
#define SAVE_ERROR_NO_PATH
size_t strlcpy(char *dst, const char *src, size_t size)
void free_objectlinkpt(oblinkpt *obp)
#define OB_MOVE_BLOCK(ob1, ob2)
int64_t level_exp(int level, double expmul)
#define SAVE_ERROR_UCREATION
int save_map(mapstruct *m, int flag)
#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)
const typedata * get_typedata_by_name(const char *name)
static void add_face_layer(int low_layer, int high_layer, object *ob, object *layers[], int honor_visibility)
#define MAP_LAYER_NO_PICK1
int save_objects(mapstruct *m, FILE *fp, FILE *fp2, int flag)
#define FREE_AND_CLEAR(xyz)
void object_remove_from_active_list(object *op)
void LOG(LogLevel logLevel, const char *format,...)
FILE * of_open(OutputFile *of, const char *fname)
bool object_value_set_shared(const object *op, sstring key)
#define SET_MAP_MOVE_BLOCK(M, X, Y, C)
#define CLEAR_FLAG(xyz, p)
const typedata * get_typedata(int itemtype)
#define SAVE_ERROR_URENAME
void dump_map(const mapstruct *m)
static void load_unique_objects(mapstruct *m)
object * arch_to_object(archetype *at)
static void fix_container_multipart(object *container)
uint32_t map_size(mapstruct *m)
int find_dir_2(int x, int y)
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
void object_free_drop_inventory(object *ob)
static void print_shop_string(mapstruct *m, char *output_string, int size)
void update_position(mapstruct *m, int x, int y)
#define GET_MAP_FLAGS(M, X, Y)
#define MAP_LAYER_LIVING2
#define OB_TYPE_MOVE_BLOCK(ob1, type)
#define SET_MAP_PLAYER(M, X, Y, C)
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
static void delete_unique_items(mapstruct *m)
#define SAVE_FLAG_SAVE_UNPAID
#define SET_MAP_LIGHT(M, X, Y, L)
mapstruct * get_empty_map(int sizex, int sizey)
static void free_all_objects(mapstruct *m)
int on_same_map(const object *op1, const object *op2)
void set_map_reset_time(mapstruct *map)
mapstruct * get_map_from_coord(mapstruct *m, int16_t *x, int16_t *y)
#define FOR_INV_PREPARE(op_, it_)
int get_rangevector_from_mapcoord(const mapstruct *m, int x, int y, const object *op2, rv_vector *retval, int flags)
void allocate_map(mapstruct *m)
void save_object_in_sb(StringBuffer *sb, object *op, const int flag)
void events_execute_global_event(int eventcode,...)
void update_all_map_los(mapstruct *map)
mapstruct * mapfile_load(const char *map, int flags)
static int load_overlay_map(const char *filename, mapstruct *m)
mapstruct * has_been_loaded(const char *name)
void create_template_pathname(const char *name, char *buf, size_t size)
void map_remove_unique_files(const mapstruct *map)
#define SET_MAP_MOVE_OFF(M, X, Y, C)
object * object_get_owner(object *op)