Crossfire Server, Trunk
mapper.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire map browser generator.
3  *
4  * Author: Nicolas Weeger <nicolas.weeger@laposte.net>, (C) 2006-2021.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
150 #include <ctype.h>
151 #include <errno.h>
152 #include <stdio.h>
153 #include <stdlib.h>
154 #include <string.h>
155 #include <strings.h>
156 #include <sys/stat.h>
157 #include <sys/types.h>
158 #include <time.h>
159 
160 #include "global.h"
161 #include "sproto.h"
162 #include "image.h"
163 #include "quest.h"
164 
165 extern "C" {
166 #include <gd.h>
167 #include <gdfonts.h>
168 #include <gdfontl.h>
169 #include <gdfontg.h>
170 }
171 
172 #include "inja.hpp"
173 #include <map>
174 #include <set>
175 
176 static std::vector<gdImagePtr> gdfaces;
177 
180  const char *name;
181  const char *message;
182  int x, y;
183 };
184 
186 typedef std::vector<struct_npc_info *> npc_list;
187 
190  struct struct_race **races;
191  size_t count;
192  size_t allocated;
193 };
194 
198  size_t count;
199  size_t allocated;
200 };
201 
205  size_t count;
206  size_t allocated;
207 };
208 
211  char *path;
212  char *name;
213  char *filename;
214  char *lore;
221 
223 
225 
228 
230  int height, width;
232  struct struct_map_info *tiles[4];
233 };
234 
237 
240 
243  char *name;
244  int power;
246  char *diff;
248 };
249 
250 static std::vector<struct_equipment *> special_equipment;
254 struct struct_race {
255  char *name;
256  int count;
258 };
259 
262 static std::set<std::string> reset_groups;
270  list->races = NULL;
271  list->count = 0;
272  list->allocated = 0;
273 }
274 
286  if (check) {
287  size_t test;
288 
289  for (test = 0; test < list->count; test++) {
290  if (list->races[test] == race)
291  return;
292  }
293  }
294 
295  if (list->allocated == list->count) {
296  list->allocated += 50;
297  list->races = (struct_race **)realloc(list->races, sizeof(struct_race *)*list->allocated);
298  }
299  list->races[list->count] = race;
300  list->count++;
301 }
302 
304 static char root[500];
305 
307 static int pics_allocated;
308 
309 /* Options */
310 static int generate_pics = 1;
311 static int force_pics = 0;
312 static int sizes[] = {32, 16, 8, 4, 2};
313 static const int num_sizes = sizeof(sizes)/sizeof(int);
314 #define size_large sizes[0]
315 #define size_small sizes[1]
316 static int map_limit = -1;
317 static int show_maps = 0;
318 static int world_map = 1;
319 static int world_exit_info = 1;
320 static int tileset = 0;
321 static bool detail_quests = false;
322 static bool list_system_quests = false;
323 static bool display_rendered_template = false;
326 static int created_pics = 0;
327 static int cached_pics = 0;
331  OF_PNG = 0,
332  OF_JPG = 1
333 };
334 
336 static const char *output_extensions[] = {
337  ".png",
338  ".jpg"
339 };
340 
343 
345 static int jpeg_quality = -1;
346 
348 static int rawmaps = 0;
349 
351 static int warn_no_path = 0;
352 
357  int sum_x, sum_y, sum;
358  int is_world;
359 };
360 
361 static struct struct_region_info **regions = NULL;
362 static size_t region_count = 0;
363 static size_t region_allocated = 0;
365 static int list_unused_maps = 0;
366 static std::vector<char *> found_maps;
368 /* Path/exit info */
369 static gdImagePtr infomap;
371 static int color_linked_exit;
372 static int color_road;
373 static int color_blocking;
374 static int color_slowing;
376 static int **elevation_info;
377 static int elevation_min;
378 static int elevation_max;
380 /* Whether to compute links between regions or not (expensive). */
381 static bool do_regions_link = false;
382 /* Links between regions, key is source, value are destinations. */
383 static std::map<region *, std::set<region *>> region_links;
384 
386 #define S_DOOR 0
387 #define S_KEY 1
388 #define S_CONTAINER 2
389 #define S_DETECTOR 3
390 #define S_CONNECT 4
391 #define S_MAX 5
392 
395  char *slaying;
397 };
398 
400 static size_t slaying_count = 0;
401 static size_t slaying_allocated = 0;
409  list->maps = NULL;
410  list->count = 0;
411  list->allocated = 0;
412 }
413 
414 static void add_map(struct_map_info *info, struct_map_list *list);
415 
416 static int is_special_equipment(object *item) {
417  if (item->name == item->arch->clone.name && item->title == item->arch->clone.title)
418  return 0;
420  return 0;
421  if (item->move_block == MOVE_ALL)
422  return 0;
423 
424  if (IS_SHIELD(item) || IS_WEAPON(item) || IS_ARMOR(item) || IS_ARROW(item) || (item->type == ROD) || (item->type == WAND) || (item->type == RING) || (item->type == AMULET))
425  return 1;
426 
427  return 0;
428 }
429 
436  struct_equipment *add = (struct_equipment *)calloc(1, sizeof(struct_equipment));
437 
438  init_map_list(&add->origin);
439  return add;
440 }
441 
448 static void free_equipment(struct_equipment *equip) {
449  free(equip->diff);
450  free(equip->name);
451  free(equip);
452 }
453 
462 static bool sort_equipment(const struct_equipment *l, const struct_equipment *r) {
463  int cmp = strcasecmp(l->name, r->name);
464  if (cmp)
465  return cmp < 0;
466  if (l->power != r->power)
467  return l->power < r->power;
468  if (l->calc_power != r->calc_power)
469  return l->calc_power < r->calc_power;
470 
471  return strcasecmp(l->diff, r->diff) < 0;
472 }
473 
483  assert(item);
484  auto existing = std::find_if(special_equipment.begin(), special_equipment.end(),
485  [&] (const auto *e) { return !sort_equipment(e, item) && !sort_equipment(item, e); });
486 
487  if (existing != special_equipment.end()) {
489  return *existing;
490  }
491 
492  special_equipment.push_back(item);
493 
494  return item;
495 }
496 
506 static void add_one_item(object *item, struct_map_info *map) {
509  int x, y;
510  sstring name, namepl;
511  uint32_t nrof;
512  object *base;
513 
514  x = item->x;
515  y = item->y;
516  name = item->name;
517  namepl = item->name_pl;
518  nrof = item->nrof;
519 
520  if (item->artifact != NULL) {
521  const artifact *artifact;
522 
523  artifact = find_artifact(item, item->artifact);
524  if (artifact == NULL) {
525  LOG(llevError, "could not find artifact %s [%d] to save data\n", item->artifact, item->type);
526  base = arch_to_object(item->arch);
527  } else {
528  base = arch_to_object(item->arch);
530  }
531  }
532  else {
533  base = arch_to_object(item->arch);
534  }
535 
536  item->x = base->x;
537  item->y = base->y;
538  item->name = base->name;
539  item->name_pl = base->name_pl;
540  item->nrof = base->nrof;
541 
544  SET_FLAG(base, FLAG_IDENTIFIED);
545  }
547  SET_FLAG(base, FLAG_UNPAID);
548  get_ob_diff(bf, item, base);
550 
551  add->diff = stringbuffer_finish(bf);
552 
553  item->x = x;
554  item->y = y;
555  item->name = name;
556  item->name_pl = namepl;
557  item->nrof = nrof;
558 
559  if (add->diff == NULL || strcmp(add->diff, "") == 0) {
560  free_equipment(add);
561  return;
562  }
563 
564  add->name = strdup(item->name);
565  add->power = item->item_power;
567 
568  add = ensure_unique(add);
569  add_map(map, &add->origin);
570 }
571 
580 static void check_equipment(object *item, struct_map_info *map) {
583 
586  FOR_INV_FINISH();
587 }
588 
597 static struct_race *get_race(const char *name) {
598  size_t test;
599  struct_race *item;
600 
601  for (test = 0; test < races.count; test++) {
602  if (strcmp(races.races[test]->name, name) == 0) {
603  races.races[test]->count++;
604  return races.races[test];
605  }
606  }
607 
608  item = (struct_race *)calloc(1, sizeof(struct_race));
609  item->name = strdup(name);
610  item->count = 1;
611  init_map_list(&item->origin);
612 
614 
615  return item;
616 }
617 
626 static void add_monster(object *monster, struct_map_info *map) {
627  struct_race *race;
628 
629  if (monster->head && monster != monster->head)
630  return;
631 
632  map->min_monster = MIN(monster->level, map->min_monster);
633  map->max_monster = MAX(monster->level, map->max_monster);
634 
635  race = get_race(monster->name ? monster->name : "(null race)");
636  add_map(map, &race->origin);
637  add_race_to_list(race, &map->monsters, 1);
638 }
639 
648 static int sort_race(const void *a, const void *b) {
649  const struct_race *l = *(const struct_race **)a;
650  const struct_race *r = *(const struct_race **)b;
651  return strcasecmp(l->name, r->name);
652 }
653 
661 static int is_road(object *item) {
662  int test;
663  /* Archetypes used as roads. */
664  const char *roads[] = {
665  "cobblestones",
666  "flagstone",
667  "ice_stone",
668  "snow",
669  NULL };
670  const char *partial[] = {
671  "dirtroad_",
672  NULL };
673 
674  for (test = 0; partial[test] != NULL; test++) {
675  if (strstr(item->arch->name, partial[test]) != NULL)
676  return 1;
677  }
678 
680  return 0;
681 
682  for (test = 0; roads[test] != NULL; test++) {
683  if (strcmp(item->arch->name, roads[test]) == 0)
684  return 1;
685  }
686 
687  return 0;
688 }
689 
697 static int is_blocking(object *item) {
698  return item->move_block == MOVE_ALL ? 1 : 0;
699 }
700 
711 static int get_elevation_color(int elevation, gdImagePtr elevationmap) {
712  if (elevation > 0)
713  return gdImageColorResolve(elevationmap, 200*elevation/elevation_max, 0, 0);
714  else
715  return gdImageColorResolve(elevationmap, 0, 0, 200*elevation/elevation_min);
716 }
717 
726 static void do_exit_map(mapstruct *map) {
727  int tx, ty, x, y;
728  object *test;
729 
730  if (sscanf(map->path, "/world/world_%d_%d", &x, &y) != 2)
731  return;
732 
733  x -= 100;
734  y -= 100;
735 
736  for (tx = 0; tx < MAP_WIDTH(map); tx++) {
737  for (ty = 0; ty < MAP_HEIGHT(map); ty++) {
738  FOR_MAP_PREPARE(map, tx, ty, item) {
739  test = HEAD(item);
740 
741  // Do this before we check for blocked tiles,
742  // otherwise we don't receive elevation data for blocked tiles.
743  int elevation = item->elevation;
744  if (elevation != 0) {
745  elevation_min = MIN(elevation_min, elevation);
746  elevation_max = MAX(elevation_max, elevation);
747  elevation_info[x*50+tx][y*50+ty] = elevation;
748  }
749 
750  if (test->type == EXIT || test->type == TELEPORTER) {
751  if (!test->slaying)
752  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_unlinked_exit);
753  else
754  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_linked_exit);
755  } else if (is_road(test))
756  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_road);
757  else if (is_blocking(test)) {
758  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_blocking);
759  /* can't get on the spot, so no need to go on. */
760  break;
761  } else if (test->move_slow != 0)
762  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_slowing);
763 
764  } FOR_MAP_FINISH();
765  }
766  }
767 }
768 
769 void do_auto_apply(mapstruct *m);
770 
783 static void relative_path(const char *from, const char *to, char *result) {
784  const char *fslash;
785  const char *rslash;
786 
787  result[0] = '\0';
788 
789  fslash = strchr(from+1, '/');
790  if (!fslash) {
791  strcpy(result, to+1);
792  return;
793  }
794 
795  rslash = strchr(to+1, '/');
796  while (fslash && rslash && (fslash-from == rslash-to) && strncmp(from, to, fslash-from+1) == 0) {
797  from = fslash+1;
798  to = rslash+1;
799  fslash = strchr(fslash+1, '/');
800  rslash = strchr(rslash+1, '/');
801  }
802 
803  while (fslash) {
804  strcat(result, "../");
805  fslash = strchr(fslash+1, '/');
806  }
807  if (strlen(result) && result[strlen(result)-1] == '/' && *to == '/')
808  result[strlen(result)-1] = '\0';
809  strcat(result, to);
810 }
811 
822 static int compare_map_info(const struct_map_info *left, const struct_map_info *right) {
823  int c;
824 
825  if (left->tiled_group)
826  left = left->tiled_group;
827  if (right->tiled_group)
828  right = right->tiled_group;
829 
830  // Shortcut -- if both are the same pointer, return 0.
831  // This occurs when tiled maps of the same set are compared to each other.
832  if (left == right)
833  return 0;
834 
835  c = strcasecmp(left->name, right->name);
836  if (c)
837  return c;
838 
839  return strcasecmp(left->path, right->path);
840 }
841 
852 static int sort_map_info(const void *left, const void *right) {
853  const struct_map_info *l = *(const struct_map_info **)left;
854  const struct_map_info *r = *(const struct_map_info **)right;
855  return compare_map_info(l, r);
856 }
857 
868 static int sort_region(const void *left, const void *right) {
869  return strcmp((*((struct_region_info **)left))->reg->name, (*((struct_region_info **)right))->reg->name);
870 }
871 
872 /************************************
873  Start of quest-related definitions.
874 ************************************/
875 
879  char *description;
880  struct struct_quest *quest;
881 };
882 
884 struct struct_quest {
885  char *name;
886  char *description;
887  int number;
890 };
891 
892 static struct_quest **quests = NULL;
894 static int quests_count = 0;
896 static int quests_allocated = 0;
899  list->list = NULL;
900  list->count = 0;
901  list->allocated = 0;
902 }
903 
905  if (list->count == list->allocated) {
906  list->allocated += 10;
907  list->list = (struct_map_in_quest **)realloc(list->list, sizeof(struct_map_in_quest *)*list->allocated);
908  }
909  list->list[list->count++] = item;
910 }
911 
917 static struct_quest *find_quest_info(const char *name) {
918  int test;
919  for (test = 0; test < quests_count; test++) {
920  if (strcmp(quests[test]->name, name) == 0)
921  return quests[test];
922  }
923  return NULL;
924 }
925 
934 static struct_quest *get_quest_info(const char *name) {
936  if (add) {
937  return add;
938  }
939 
941  quests_allocated += 10;
942  quests = (struct_quest **)realloc(quests, sizeof(struct_quest *)*quests_allocated);
943  }
944  add = (struct_quest *)calloc(1, sizeof(struct_quest));
945  add->name = strdup(name);
946  add->number = quests_count;
948  quests[quests_count] = add;
949  quests_count++;
950  return add;
951 }
952 
963 static void add_map_to_quest(struct_map_info *map, const char *name, const char *description) {
964  struct_map_in_quest *add;
966 
967  add = (struct_map_in_quest *)calloc(1, sizeof(struct_map_in_quest));
968  add->map = map;
969  add->quest = quest;
970  add->description = strdup(description);
971  while (strlen(add->description) && add->description[strlen(add->description)-1] == '\n')
972  add->description[strlen(add->description)-1] = '\0';
974  add_to_struct_map_in_quest_list(&map->quests, add);
975 }
976 
985 static int sort_struct_map_in_quest(const void *left, const void *right) {
986  int c;
987 
988  const struct_map_in_quest *l = *(const struct_map_in_quest **)left;
989  const struct_map_in_quest *r = *(const struct_map_in_quest **)right;
990  const struct_map_info *ml = l->map;
991  const struct_map_info *mr = r->map;
992 
993  if (ml->tiled_group)
994  ml = ml->tiled_group;
995  if (mr->tiled_group)
996  mr = mr->tiled_group;
997 
998  c = strcasecmp(ml->name, mr->name);
999  if (c)
1000  return c;
1001 
1002  return strcasecmp(ml->path, mr->path);
1003 }
1004 
1013 static int sort_struct_quest(const void *left, const void *right) {
1014  const struct_quest *l = *(const struct_quest **)left;
1015  const struct_quest *r = *(const struct_quest **)right;
1016  return strcasecmp(l->name, r->name);
1017 }
1018 
1029 static void define_quest(const char *name, struct_map_info *mainmap, const char *description) {
1031 
1032  if (quest->description || quest->mainmap) {
1033  printf("warning, multiple quest definition for %s, found in %s and %s.\n", quest->name, quest->mainmap ? quest->mainmap->path : "(unknown map)", mainmap->path);
1034  return;
1035  }
1036  quest->description = strdup(description);
1037  while (strlen(quest->description) && quest->description[strlen(quest->description)-1] == '\n')
1038  quest->description[strlen(quest->description)-1] = '\0';
1039  quest->mainmap = mainmap;
1040 }
1041 
1049  char *start, *end, *next;
1050  char name[500];
1051  char description[500];
1052 
1053  start = strstr(map->lore, "@def");
1054  while (start) {
1055  description[0] = '\0';
1056  /* find name */
1057  end = strstr(start, "\n");
1058  if (end) {
1059  strncpy(name, start+5, end-start-5);
1060  name[end-start-5] = '\0';
1061  next = end+1;
1062  end = strstr(next, "@end");
1063  if (end) {
1064  strncpy(description, next, end-next);
1065  description[end-next] = '\0';
1066  /* need to erase the text. */
1067  memmove(start, end+4, strlen(map->lore)-(end-start+3));
1068  end = start;
1069  }
1070  else {
1071  strcpy(description, next);
1072  *start = '\0';
1073  end = NULL;
1074  }
1075  } else {
1076  strcpy(name, start);
1077  *start = '\0';
1078  end = NULL;
1079  }
1080 
1081  define_quest(name, map, description);
1082  start = end ? strstr(end, "@def") : NULL;
1083  }
1084 
1085  start = strstr(map->lore, "@quest");
1086  while (start) {
1087  description[0] = '\0';
1088  /* find name */
1089  end = strstr(start, "\n");
1090  if (end) {
1091  strncpy(name, start+7, end-start-7);
1092  name[end-start-7] = '\0';
1093  next = end+1;
1094  end = strstr(next, "@end");
1095  if (end) {
1096  strncpy(description, next, end-next);
1097  description[end-next] = '\0';
1098  /* need to erase the text. */
1099  memmove(start, end+4, strlen(map->lore)-(end-start+3));
1100  end = start;
1101  }
1102  else {
1103  strcpy(description, next);
1104  *start = '\0';
1105  end = NULL;
1106  }
1107  } else {
1108  strcpy(name, start);
1109  *start = '\0';
1110  end = NULL;
1111  }
1112 
1113  add_map_to_quest(map, name, description);
1114  start = end ? strstr(end, "@quest") : NULL;
1115  }
1116 }
1117 
1118 /************************************
1119  End of quest-related definitions.
1120 ************************************/
1121 
1122 /*********
1123 NPC-related stuff
1124 ********/
1125 
1133 static struct_npc_info *create_npc_info(const object *npc) {
1134  struct_npc_info *info = (struct_npc_info *)calloc(1, sizeof(struct_npc_info));
1135 
1136  info->name = strdup(npc->name ? npc->name : "(null name)");
1137  info->message = strdup(npc->msg ? npc->msg : "(null msg)");
1138  info->x = npc->x;
1139  info->y = npc->y;
1140 
1141  return info;
1142 }
1143 
1151 static void add_npc_to_map(npc_list *list, const object *npc) {
1152  list->push_back(create_npc_info(npc));
1153 }
1154 /* end of NPC stuff */
1155 
1168  size_t map;
1169 
1170  for (map = 0; map < list->count; map++)
1171  if (list->maps[map] == info)
1172  return;
1173 
1174  if (list->count == list->allocated) {
1175  list->allocated += 50;
1176  list->maps = (struct_map_info **)realloc(list->maps, list->allocated*sizeof(struct_map_info *));
1177  }
1178  list->maps[list->count] = info;
1179  list->count++;
1180 }
1181 
1189  struct_map_info *add = (struct_map_info *)calloc(1, sizeof(struct_map_info));
1190 
1191  add->min_monster = 2000;
1192  init_map_list(&add->exits_to);
1193  init_map_list(&add->exits_from);
1194  init_map_list(&add->tiled_maps);
1196  init_race_list(&add->monsters);
1197  add->npcs = new npc_list();
1198  add->readable = new npc_list();
1199  add->tiled_group = NULL;
1200 
1201  return add;
1202 }
1203 
1212 
1213  add_map(add, &tiled_map_list);
1214  return add;
1215 }
1216 
1227  size_t g;
1228  struct_map_info *group = tiled_map->tiled_group;
1229  struct_map_info *change;
1230 
1231  while (group->tiled_maps.count > 0) {
1232  change = group->tiled_maps.maps[group->tiled_maps.count-1];
1233  change->tiled_group = map->tiled_group;
1234  add_map(change, &map->tiled_group->tiled_maps);
1235  group->tiled_maps.count--;
1236  }
1237 
1238  for (g = 0; g < tiled_map_list.count; g++) {
1239  if (tiled_map_list.maps[g] == group) {
1240  if (g < tiled_map_list.count-1)
1243  free(group);
1244  return;
1245  }
1246  }
1247  printf("tiled_map not in tiled_map_list!");
1248  abort();
1249 
1250 }
1251 
1260 static struct_map_info *get_map_info(const char *path) {
1261  struct_map_info *add;
1262  char *tmp;
1263 
1264  for (size_t map = 0; map < maps_list.count; map++) {
1265  if (strcmp(maps_list.maps[map]->path, path) == 0)
1266  return maps_list.maps[map];
1267  }
1268 
1269  add = create_map_info();
1270  add->path = strdup(path);
1271  tmp = strrchr((char *)path, '/');
1272  if (tmp)
1273  add->filename = strdup(tmp+1);
1274  else
1275  add->filename = strdup(path);
1276 
1277  add_map(add, &maps_list);
1278  return add;
1279 }
1280 
1287 static void list_map(const char *path) {
1288  for (auto map = found_maps.begin(); map != found_maps.end(); ++map) {
1289  if (strcmp(path, *map) == 0) {
1290  free(*map);
1291  found_maps.erase(map);
1292  return;
1293  }
1294  }
1295  printf("Map processed but not found in directory reading? %s\n", path);
1296 }
1297 
1309  size_t test;
1310  int x, y;
1311 
1312  for (test = 0; test < region_count; test++) {
1313  if (regions[test]->reg == reg)
1314  break;
1315  }
1316  if (test == region_count) {
1317  if (test == region_allocated) {
1318  region_allocated++;
1320  regions[test] = (struct_region_info *)calloc(1, sizeof(struct_region_info));
1321  }
1322  region_count++;
1323  regions[test]->reg = reg;
1324  }
1325  add_map(map, &regions[test]->maps_list);
1326  if (sscanf(map->path, "/world/world_%d_%d", &x, &y) == 2) {
1327  regions[test]->sum_x += (x-100);
1328  regions[test]->sum_y += (y-100);
1329  regions[test]->sum++;
1330  regions[test]->is_world = 1;
1331  }
1332 }
1333 
1342 static void save_picture(FILE *file, gdImagePtr pic) {
1343  if (output_format == OF_PNG)
1344  gdImagePng(pic, file);
1345  else
1346  gdImageJpeg(pic, file, jpeg_quality);
1347 }
1348 
1356 static void add_region_link(mapstruct *source, mapstruct *dest) {
1357  region *s, *d;
1358 
1359  s = get_region_by_map(source);
1360  d = get_region_by_map(dest);
1361  if (s == d)
1362  return;
1363 
1364  region_links[s].insert(d);
1365 }
1366 
1375 static int is_slaying(object *item) {
1376  return (item->type == LOCKED_DOOR || item->type == SPECIAL_KEY || item->type == CONTAINER || item->type == CHECK_INV);
1377 }
1378 
1379 
1388 static struct_slaying_info *get_slaying_struct(const char *slaying) {
1389  for (size_t l = 0; l < slaying_count; l++) {
1390  if (!strcmp(slaying_info[l]->slaying, slaying))
1391  return slaying_info[l];
1392  }
1394  slaying_allocated += 10;
1396  }
1397 
1398  struct_slaying_info *add = (struct_slaying_info *)calloc(1, sizeof(struct_slaying_info));
1399  add->slaying = strdup(slaying);
1400  for (size_t l = 0; l < S_MAX; l++)
1401  init_map_list(&add->maps[l]);
1402 
1403  slaying_info[slaying_count] = add;
1404  slaying_count++;
1405 
1406  return add;
1407 }
1408 
1420  add_map(map, &info->maps[item]);
1421 }
1422 
1431 static void add_slaying(struct_map_info *map, object *item) {
1432  struct_slaying_info *info;
1433 
1434  if (!item->slaying)
1435  /* can be undefined */
1436  return;
1437 
1438  info = get_slaying_struct(item->slaying);
1439  if (item->type == LOCKED_DOOR)
1440  add_map_to_slaying(info, S_DOOR, map);
1441  else if (item->type == SPECIAL_KEY)
1442  add_map_to_slaying(info, S_KEY, map);
1443  else if (item->type == CONTAINER)
1445  else if (item->type == DETECTOR)
1447  else
1449 }
1450 
1461  if (is_slaying(inv))
1462  add_slaying(map, inv);
1464  } FOR_INV_FINISH();
1465 }
1466 
1467 static void generate_picture_path(const char *path, size_t pic_size, char *out, size_t len) {
1468  snprintf(out, len, "%s%s.x%zu%s", root, path, pic_size + 1, output_extensions[output_format]);
1469 }
1470 
1471 static void write_pictures_from_real_size(const char *path, gdImagePtr real, int width, int height) {
1472  char picpath[MAX_BUF];
1473 
1474  generate_picture_path(path, 0, picpath, sizeof(picpath));
1475  make_path_to_file(picpath);
1476  FILE *out = fopen(picpath, "wb+");
1477  save_picture(out, real);
1478  fclose(out);
1479 
1480  for (size_t i = 1; i < num_sizes; i++) {
1481  generate_picture_path(path, i, picpath, sizeof(picpath));
1482  gdImagePtr small = gdImageCreateTrueColor(width*sizes[i], height*sizes[i]);
1483  gdImageCopyResampled(small, real, 0, 0, 0, 0, width*sizes[i], height*sizes[i], width*size_large, height*size_large);
1484  out = fopen(picpath, "wb+");
1485  save_picture(out, small);
1486  fclose(out);
1487  gdImageDestroy(small);
1488  }
1489 }
1490 
1499 static void process_map(struct_map_info *info) {
1500  mapstruct *m;
1501  int x, y, isworld;
1502  gdImagePtr pic = nullptr;
1503  struct stat stats;
1504  struct stat statspic;
1505  char exit_path[500];
1506  char tmppath[MAX_BUF];
1507  char picpath[num_sizes][MAX_BUF];
1508  int needpic = 0;
1509  struct_map_info *link;
1510 
1511  if (list_unused_maps)
1512  list_map(info->path);
1513 
1514  if (show_maps)
1515  printf(" processing map %s\n", info->path);
1516 
1517  m = ready_map_name(info->path, 0);
1518  if (!m) {
1519  printf("couldn't load map %s\n", info->path);
1520  return;
1521  }
1522 
1523  do_exit_map(m);
1524 
1525  if (!rawmaps)
1526  do_auto_apply(m);
1527 
1528  info->level = m->difficulty;
1529  if (m->maplore) {
1530  info->lore = strdup(m->maplore);
1531  process_map_lore(info);
1532  }
1533  if (m->reset_group) {
1534  info->reset_group = add_string(m->reset_group);
1535  reset_groups.insert(m->reset_group);
1536  }
1537 
1538  isworld = (sscanf(info->path, "/world/world_%d_%d", &x, &y) == 2);
1539 
1540  if (m->name)
1541  info->name = strdup(m->name);
1542  else
1543  info->name = strdup(info->filename);
1544 
1545  info->cfregion = get_region_by_map(m);
1546  add_map_to_region(info, info->cfregion);
1547 
1548  for (int i = 0; i < num_sizes; i++) {
1549  generate_picture_path(info->path, i, picpath[i], sizeof(picpath[i]));
1550  }
1551 
1552  if (force_pics)
1553  needpic = 1;
1554  else if (generate_pics) {
1555  create_pathname(info->path, tmppath, MAX_BUF);
1556  stat(tmppath, &stats);
1557  if (stat(picpath[0], &statspic) || (statspic.st_mtime < stats.st_mtime))
1558  needpic = 1;
1559  }
1560  else
1561  needpic = 0;
1562 
1563  if (needpic) {
1564  pic = gdImageCreateTrueColor(MAP_WIDTH(m)*size_large, MAP_HEIGHT(m)*size_large);
1565  created_pics++;
1566  }
1567  else
1568  cached_pics++;
1569 
1570  for (x = 0; x < 4; x++)
1571  if (m->tile_path[x] != NULL) {
1572  path_combine_and_normalize(m->path, m->tile_path[x], exit_path, sizeof(exit_path));
1573  create_pathname(exit_path, tmppath, MAX_BUF);
1574  if (stat(tmppath, &stats)) {
1575  printf(" map %s doesn't exist in map %s, for tile %d.\n", exit_path, info->path, x);
1576  }
1577 
1578  if (isworld) {
1579  link = get_map_info(exit_path);
1580  add_map(link, &info->exits_from);
1581  add_map(info, &link->exits_to);
1582 
1583  if (do_regions_link) {
1584  mapstruct *link = ready_map_name(exit_path, 0);
1585 
1586  if (link && link != m) {
1587  /* no need to link a map with itself. Also, if the exit points to the same map, we don't
1588  * want to reset it. */
1589  add_region_link(m, link);
1590  link->reset_time = 1;
1591  link->in_memory = MAP_IN_MEMORY;
1592  delete_map(link);
1593  }
1594  }
1595  } else {
1596  link = get_map_info(exit_path);
1597  info->tiles[x] = link;
1598  if (link->tiled_group) {
1599  if (info->tiled_group && link->tiled_group != info->tiled_group) {
1600  merge_tiled_maps(info, link);
1601  continue;
1602  }
1603  if (link->tiled_group == info->tiled_group) {
1604  continue;
1605  }
1606  if (!info->tiled_group) {
1607  add_map(info, &link->tiled_group->tiled_maps);
1608  continue;
1609  }
1610  }
1611 
1612  if (!info->tiled_group) {
1613  info->tiled_group = create_tiled_map();
1614  add_map(info, &info->tiled_group->tiled_maps);
1615  }
1616  link->tiled_group = info->tiled_group;
1617  add_map(link, &info->tiled_group->tiled_maps);
1618  }
1619  }
1620 
1621  info->width = MAP_WIDTH(m);
1622  info->height = MAP_HEIGHT(m);
1623 
1624  for (x = MAP_WIDTH(m)-1; x >= 0; x--)
1625  for (y = MAP_HEIGHT(m)-1; y >= 0; y--) {
1626  FOR_MAP_PREPARE(m, x, y, item) {
1627  if (item->type == EXIT || item->type == TELEPORTER || item->type == PLAYER_CHANGER) {
1628  char ep[500];
1629  const char *start;
1630 
1631  if (!item->slaying) {
1632  ep[0] = '\0';
1633  if (warn_no_path)
1634  printf(" exit without any path at %d, %d on %s\n", item->x, item->y, info->path);
1635  } else {
1636  memset(ep, 0, 500);
1637  if (strcmp(item->slaying, "/!"))
1638  strcpy(ep, EXIT_PATH(item));
1639  else {
1640  if (!item->msg) {
1641  printf(" random map without message in %s at %d, %d\n", info->path, item->x, item->y);
1642  } else {
1643  /* Some maps have a 'exit_on_final_map' flag, ignore it. */
1644  start = strstr(item->msg, "\nfinal_map ");
1645  if (!start && strncmp(item->msg, "final_map", strlen("final_map")) == 0)
1646  /* Message start is final_map, nice */
1647  start = item->msg;
1648  if (start) {
1649  char *end = strchr((char *)start+1, '\n');
1650 
1651  start += strlen("final_map")+2;
1652  strncpy(ep, start, end-start);
1653  }
1654  }
1655  }
1656 
1657  if (strlen(ep)) {
1658  path_combine_and_normalize(m->path, ep, exit_path, 500);
1659  create_pathname(exit_path, tmppath, MAX_BUF);
1660  if (stat(tmppath, &stats)) {
1661  printf(" map %s doesn't exist in map %s, at %d, %d.\n", ep, info->path, item->x, item->y);
1662  } else {
1663  link = get_map_info(exit_path);
1664  add_map(link, &info->exits_from);
1665  add_map(info, &link->exits_to);
1666 
1667  if (do_regions_link) {
1668  mapstruct *link = ready_map_name(exit_path, 0);
1669 
1670  if (link && link != m) {
1671  /* no need to link a map with itself. Also, if the exit points to the same map, we don't
1672  * want to reset it. */
1673  add_region_link(m, link);
1674  link->reset_time = 1;
1675  link->in_memory = MAP_IN_MEMORY;
1676  delete_map(link);
1677  }
1678  }
1679  }
1680  }
1681  }
1682  } else if (is_slaying(item))
1683  add_slaying(info, item);
1684 
1685  check_equipment(item, info);
1686 
1688 
1689  if (QUERY_FLAG(item, FLAG_MONSTER)) {
1690  /* need to get the "real" archetype, as the item's archetype can certainly be a temporary one. */
1691  archetype *arch = find_archetype(item->arch->name);
1692 
1693  add_monster(item, info);
1694  if (arch != NULL && (QUERY_FLAG(item, FLAG_UNAGGRESSIVE) || QUERY_FLAG(item, FLAG_FRIENDLY)) && (item->msg != arch->clone.msg) && (item->msg != NULL))
1695  add_npc_to_map(info->npcs, item);
1696  } else if ((item->type == SIGN || item->type == BOOK) && (item->msg != item->arch->clone.msg) && (item->msg != NULL)) {
1697  add_npc_to_map(info->readable, item);
1698  }
1699 
1700  if (item->invisible)
1701  continue;
1702 
1703  if (needpic) {
1704  int sx, sy, hx, hy;
1705 
1706  if (gdfaces.size() <= item->face->number)
1707  gdfaces.resize(item->face->number + 1, nullptr);
1708 
1709  if (gdfaces[item->face->number] == NULL) {
1710  face_sets *fs = find_faceset(get_face_fallback(tileset, item->face->number));
1711 
1712  gdfaces[item->face->number] = gdImageCreateFromPngPtr(fs->faces[item->face->number].datalen, fs->faces[item->face->number].data);
1713  pics_allocated++;
1714  }
1715  if (item->head || item->more) {
1716  object_get_multi_size(item, &sx, &sy, &hx, &hy);
1717  } else {
1718  hx = 0;
1719  hy = 0;
1720  }
1721  if (gdfaces[item->face->number] != NULL && ((!item->head && !item->more) || (item->arch->clone.x+hx == 0 && item->arch->clone.y+hy == 0))) {
1722  gdImageCopy(pic, gdfaces[item->face->number], x*size_large, y*size_large, 0, 0, gdfaces[item->face->number]->sx, gdfaces[item->face->number]->sy);
1723  }
1724  }
1725  } FOR_MAP_FINISH();
1726  }
1727 
1728  if (needpic) {
1730  gdImageDestroy(pic);
1731  info->pic_was_done = 1;
1732  }
1733 
1734  m->reset_time = 1;
1735  m->in_memory = MAP_IN_MEMORY;
1736  delete_map(m);
1737 }
1738 
1742 static void write_world_map(void) {
1743 #define SIZE 50
1744  int x, y;
1745  FILE *out;
1746  int wx, wy;
1747  char file[500];
1748  char mapleft[10], maptop[10], mapright[10], mapbottom[10], mappath[5000];
1749  char name[100];
1750  gdImagePtr pic;
1751  gdImagePtr small;
1752  gdFontPtr font;
1753  int color;
1754 
1755  if (!world_map)
1756  return;
1757 
1758  printf("Generating world map in world.html...");
1759  fflush(stdout);
1760 
1761  pic = gdImageCreateTrueColor(SIZE*30, SIZE*30);
1762 
1763  strcpy(file, root);
1764  strcat(file, "/world.html");
1765 
1766  wx = 100;
1767  wy = 100;
1768 
1769  for (y = 0; y < 30; y++) {
1770  for (x = 0; x < 30; x++) {
1771  snprintf(name, sizeof(name), "world_%d_%d", wx, wy);
1772  snprintf(mapleft, sizeof(mapleft), "%d", SIZE*x);
1773  snprintf(maptop, sizeof(maptop), "%d", SIZE*y);
1774  snprintf(mapright, sizeof(mapright), "%d", SIZE*(x+1)-1);
1775  snprintf(mapbottom, sizeof(mapbottom), "%d", SIZE*(y+1)-1);
1776 
1777  snprintf(mappath, sizeof(mappath), "%s/world/%s.x1%s", root, name, output_extensions[output_format]);
1778 
1779  out = fopen(mappath, "rb");
1780  if (!out) {
1781  printf("\n warning: large pic not found for world_%d_%d", wx, wy);
1782  wx++;
1783  continue;
1784  }
1785  if (output_format == OF_PNG)
1786  small = gdImageCreateFromPng(out);
1787  else
1788  small = gdImageCreateFromJpeg(out);
1789  fclose(out);
1790  if (!small) {
1791  printf("\n warning: pic not found for world_%d_%d", wx, wy);
1792  wx++;
1793  continue;
1794  }
1795  gdImageCopyResized(pic, small, SIZE*x, SIZE*y, 0, 0, SIZE, SIZE, small->sx, small->sy);
1796  gdImageDestroy(small);
1797 
1798  wx++;
1799  }
1800  wy++;
1801  wx = 100;
1802  }
1803 
1804  snprintf(mappath, sizeof(mappath), "%s/world_raw%s", root, output_extensions[output_format]);
1805  out = fopen(mappath, "wb+");
1806  save_picture(out, pic);
1807  fclose(out);
1808 
1809  /* Write region names. */
1810  small = gdImageCreateTrueColor(SIZE*30, SIZE*30);
1811  font = gdFontGetGiant();
1812  color = gdImageColorAllocateAlpha(pic, 255, 0, 0, 20);
1813  for (size_t region = 0; region < region_allocated; region++) {
1814  if (!regions[region]->is_world || regions[region]->sum == 0)
1815  continue;
1816 
1817  x = regions[region]->sum_x*SIZE/regions[region]->sum+SIZE/2-strlen(regions[region]->reg->name)*font->w/2;
1818  y = regions[region]->sum_y*SIZE/regions[region]->sum+SIZE/2-font->h/2;
1819  gdImageString(small, font, x, y, (unsigned char *)regions[region]->reg->name, color);
1820  gdImageString(pic, font, x, y, (unsigned char *)regions[region]->reg->name, color);
1821 
1822  /* For exit/road map, size isn't the same. */
1823  x = regions[region]->sum_x*50/regions[region]->sum+50/2-strlen(regions[region]->reg->name)*font->w/2;
1824  y = regions[region]->sum_y*50/regions[region]->sum+50/2-font->h/2;
1825  gdImageString(infomap, font, x, y, (unsigned char *)regions[region]->reg->name, color);
1826  }
1827 
1828  snprintf(mappath, sizeof(mappath), "%s/world_regions%s", root, output_extensions[output_format]);
1829  out = fopen(mappath, "wb+");
1830  save_picture(out, small);
1831  fclose(out);
1832  gdImageDestroy(small);
1833 
1834  snprintf(mappath, sizeof(mappath), "%s/world%s", root, output_extensions[output_format]);
1835  out = fopen(mappath, "wb+");
1836  save_picture(out, pic);
1837  fclose(out);
1838  gdImageDestroy(pic);
1839 
1840  printf(" done.\n");
1841 #undef SIZE
1842 }
1843 
1845 static void fix_map_names(void) {
1846  for (size_t map = 0; map < maps_list.count; map++) {
1847  if (maps_list.maps[map]->name)
1848  continue;
1849  if (!maps_list.maps[map]->filename) {
1850  printf("map without path!\n");
1851  abort();
1852  }
1853  maps_list.maps[map]->name = strdup(maps_list.maps[map]->filename);
1854  }
1855 }
1856 
1863 static void fix_tiled_map(void) {
1864  size_t map, tile;
1865  char name[500];
1866  char *slash, *test;
1867  region *cfregion;
1868 
1869  for (map = 0; map < tiled_map_list.count; map++) {
1870  if (tiled_map_list.maps[map]->tiled_maps.count == 0) {
1871  printf("empty tiled map group!");
1872  abort();
1873  }
1874 
1875  snprintf(name, sizeof(name), "tiled_map_group_%zu", map);
1876  tiled_map_list.maps[map]->filename = strdup(name);
1877 
1878  cfregion = NULL;
1879  test = NULL;
1880 
1881  for (tile = 0; tile < tiled_map_list.maps[map]->tiled_maps.count; tile++) {
1883  /* map not processed, ignore it. */
1884  continue;
1885 
1886  if (!cfregion)
1888  else if (cfregion != tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion) {
1889  printf("*** warning: tiled maps %s and %s not in same region (%s and %s).\n",
1892  cfregion = NULL;
1893  }
1894 
1896  /* map has a custom name, use it */
1897  if (!test)
1899  }
1900  }
1901 
1902  if (!test) {
1903  /* this can happen of course if only partial maps were processed, but well... */
1904  printf("*** warning: tiled map without any name. First map path %s\n", tiled_map_list.maps[map]->tiled_maps.maps[0]->path);
1905  test = name;
1906  }
1907 
1908  tiled_map_list.maps[map]->name = strdup(test);
1909  tiled_map_list.maps[map]->cfregion = cfregion;
1910 
1911  strncpy(name, tiled_map_list.maps[map]->tiled_maps.maps[0]->path, sizeof(name));
1912  slash = strrchr(name, '/');
1913  if (!slash)
1914  snprintf(name, sizeof(name), "/");
1915  else
1916  *(slash+1) = '\0';
1917  strncat(name, tiled_map_list.maps[map]->filename, sizeof(name) - strlen(name) - 1);
1918  tiled_map_list.maps[map]->path = strdup(name);
1919  }
1920 }
1921 
1932 static void fix_exits_for_map(struct_map_info *current, struct_map_list *from, int is_from) {
1933  int map, max;
1934  struct_map_info *group;
1935 
1936  max = from->count-1;
1937  for (map = max; map >= 0; map--) {
1938  if (from->maps[map]->tiled_group) {
1939  group = from->maps[map]->tiled_group;
1940  if (map != max)
1941  from->maps[map] = from->maps[max];
1942  from->count--;
1943  max--;
1944  add_map(group, from);
1945  add_map(current->tiled_group ? current->tiled_group : current, is_from ? &group->exits_to : &group->exits_from);
1946  }
1947  }
1948 }
1949 
1951 static void fix_exits_to_tiled_maps(void) {
1952  int map, max;
1953  struct_map_info *group;
1954 
1955  for (map = 0; static_cast<size_t>(map) < maps_list.count; map++) {
1958  }
1959 
1960  for (size_t region = 0; region < region_count; region++) {
1962  for (map = max; map >= 0; map--) {
1965  if (map != max)
1968  max--;
1969  add_map(group, &regions[region]->maps_list);
1970  }
1971  }
1972  }
1973 }
1974 
1979 static void fix_tiled_map_monsters(void) {
1980  int map, max;
1981  struct_map_info *group;
1982 
1983  for (size_t race = 0; race < races.count; race++) {
1984  max = races.races[race]->origin.count-1;
1985  for (map = max; map >= 0; map--) {
1986  if (races.races[race]->origin.maps[map]->tiled_group) {
1987  group = races.races[race]->origin.maps[map]->tiled_group;
1988  if (map != max)
1989  races.races[race]->origin.maps[map] = races.races[race]->origin.maps[max];
1990  races.races[race]->origin.count--;
1991  max--;
1992  add_map(group, &races.races[race]->origin);
1993  }
1994  }
1995  }
1996 
1997  for (map = 0; static_cast<size_t>(map) < maps_list.count; map++) {
1998  if (maps_list.maps[map]->tiled_group) {
1999  for (size_t race = 0; race < maps_list.maps[map]->monsters.count; race++) {
2001  }
2002  }
2003  }
2004 }
2005 
2007  size_t test;
2008  char picpath[500];
2009  struct stat stats;
2010 
2011  for (size_t size = 0; size < num_sizes; size++) {
2012  generate_picture_path(map->path, size, picpath, sizeof(picpath));
2013  if (stat(picpath, &stats))
2014  return 1;
2015  }
2016 
2017  for (test = 0; test < map->tiled_maps.count; test++) {
2018  if (map->tiled_maps.maps[test]->pic_was_done)
2019  return 1;
2020  }
2021 
2022  return 0;
2023 }
2024 
2037  int xmin = 0, xmax = 0, ymin = 0, ymax = 0, count, last;
2038  size_t tiled;
2039  char picpath[500];
2040  gdImagePtr large, load;
2041  FILE *out;
2043 
2044  if (!generate_pics)
2045  return;
2046 
2047  printf(" Generating composite map for %s...", map->name);
2048  fflush(stdout);
2049 
2050  if (!tiled_map_need_pic(map)) {
2051  printf(" already uptodate.\n");
2052  return;
2053  }
2054 
2055  count = map->tiled_maps.count;
2056  if (count == 0) {
2057  printf("Tiled map without tiled maps?\n");
2058  abort();
2059  }
2060  map->tiled_maps.maps[0]->processed = 1;
2061  map->tiled_maps.maps[0]->tiled_x_from = 0;
2062  map->tiled_maps.maps[0]->tiled_y_from = 0;
2063 
2064  while (count > 0) {
2065  last = count;
2066 
2067  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2068  current = map->tiled_maps.maps[tiled];
2069  if (current->processed != 1)
2070  continue;
2071 
2072  count--;
2073 
2074  if ((current->tiles[0]) && (current->tiles[0]->processed == 0)) {
2075  current->tiles[0]->processed = 1;
2076  current->tiles[0]->tiled_x_from = current->tiled_x_from;
2077  current->tiles[0]->tiled_y_from = current->tiled_y_from-current->tiles[0]->height;
2078  }
2079  if ((current->tiles[1]) && (current->tiles[1]->processed == 0)) {
2080  current->tiles[1]->processed = 1;
2081  current->tiles[1]->tiled_x_from = current->tiled_x_from+current->width;
2082  current->tiles[1]->tiled_y_from = current->tiled_y_from;
2083  }
2084  if ((current->tiles[2]) && (current->tiles[2]->processed == 0)) {
2085  current->tiles[2]->processed = 1;
2086  current->tiles[2]->tiled_x_from = current->tiled_x_from;
2087  current->tiles[2]->tiled_y_from = current->tiled_y_from+current->height;
2088  }
2089  if ((current->tiles[3]) && (current->tiles[3]->processed == 0)) {
2090  current->tiles[3]->processed = 1;
2091  current->tiles[3]->tiled_x_from = current->tiled_x_from-current->tiles[3]->width;
2092  current->tiles[3]->tiled_y_from = current->tiled_y_from;
2093  }
2094  }
2095 
2096  if (last == count) {
2097  printf("do_tiled_map_picture: didn't process any map in %s (%d left)??\n", map->path, last);
2098  abort();
2099  }
2100  }
2101 
2102  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2103  if (map->tiled_maps.maps[tiled]->tiled_x_from < xmin)
2104  xmin = map->tiled_maps.maps[tiled]->tiled_x_from;
2105  if (map->tiled_maps.maps[tiled]->tiled_y_from < ymin)
2106  ymin = map->tiled_maps.maps[tiled]->tiled_y_from;
2107  if (map->tiled_maps.maps[tiled]->tiled_x_from+map->tiled_maps.maps[tiled]->width > xmax)
2108  xmax = map->tiled_maps.maps[tiled]->tiled_x_from+map->tiled_maps.maps[tiled]->width;
2109  if (map->tiled_maps.maps[tiled]->tiled_y_from+map->tiled_maps.maps[tiled]->height > ymax)
2110  ymax = map->tiled_maps.maps[tiled]->tiled_y_from+map->tiled_maps.maps[tiled]->height;
2111  }
2112 
2113  large = gdImageCreateTrueColor(size_large*(xmax-xmin), size_large*(ymax-ymin));
2114 
2115  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2116  generate_picture_path(map->tiled_maps.maps[tiled]->path, 0, picpath, sizeof(picpath));
2117 
2118  out = fopen(picpath, "rb");
2119  if (!out) {
2120  printf("\n do_tiled_map_picture: warning: pic file %s not found for %s (errno=%d)\n", picpath, map->tiled_maps.maps[tiled]->path, errno);
2121  continue;
2122  }
2123  if (output_format == OF_PNG)
2124  load = gdImageCreateFromPng(out);
2125  else
2126  load = gdImageCreateFromJpeg(out);
2127  fclose(out);
2128  if (!load) {
2129  printf("\n do_tiled_map_picture: warning: pic not found for %s\n", map->tiled_maps.maps[tiled]->path);
2130  continue;
2131  }
2132  gdImageCopy(large, load, size_large*(map->tiled_maps.maps[tiled]->tiled_x_from-xmin), size_large*(map->tiled_maps.maps[tiled]->tiled_y_from-ymin), 0, 0, load->sx, load->sy);
2133  gdImageDestroy(load);
2134  }
2135 
2136  write_pictures_from_real_size(map->path, large, xmax-xmin, ymax-ymin);
2137 
2138  gdImageDestroy(large);
2139 
2140  printf(" done.\n");
2141 }
2142 
2145 
2147 
2150 // write_map_page(map);
2151 }
2152 
2154 static void write_tiled_maps(void) {
2155  printf("Writing tiled map information...\n");
2156 
2157  for (size_t map = 0; map < tiled_map_list.count; map++)
2159 
2160  printf(" done.\n");
2161 }
2162 
2163 static std::vector<quest_definition *> system_quests;
2164 
2165 static void quest_callback(const quest_definition *quest, void *) {
2166  if (list_system_quests || !quest->quest_is_system) {
2167  system_quests.push_back(const_cast<quest_definition *>(quest));
2168  }
2169 }
2170 
2171 static std::shared_ptr<inja::Environment> env;
2173 static std::set<std::string> rendered_templates;
2174 static std::map<struct_map_info *, std::string> reverse_maps;
2175 static std::map<region *, std::string> reverse_regions;
2182 static struct_map_info *find_map_by_key(const std::string &key) {
2183  auto found = std::find_if(reverse_maps.cbegin(), reverse_maps.cend(), [&key] (auto c) { return c.second == key; });
2184  if (found != reverse_maps.cend())
2185  return found->first;
2186  return nullptr;
2187 }
2188 
2194 static region *find_region_by_key(const std::string &key) {
2195  auto found = std::find_if(reverse_regions.cbegin(), reverse_regions.cend(), [&key] (auto c) { return c.second == key; });
2196  if (found != reverse_regions.cend())
2197  return found->first;
2198  return nullptr;
2199 }
2200 
2208  for (size_t m = 0; m < maps.count; m++) {
2209  auto map = reverse_maps.find(maps.maps[m]);
2210  if (map != reverse_maps.end()) {
2211  result.push_back(map->second);
2212  }
2213  }
2214  return result;
2215 }
2216 
2224  for (size_t n = 0; n < list.size(); n++) {
2225  auto npc = list[n];
2226  result.push_back({
2227  { "name", npc->name },
2228  { "x", npc->x },
2229  { "y", npc->y },
2230  { "message", npc->message },
2231  });
2232  }
2233  return result;
2234 }
2235 
2243  for (size_t n = 0; n < list.count; n++) {
2244  auto race = list.races[n];
2245  result.push_back({
2246  { "name", race->name },
2247  { "count", race->count },
2248  });
2249  }
2250  return result;
2251 }
2252 
2260  for (size_t m = 0; m < list.count; m++) {
2261  auto q = list.list[m];
2262  if (!q->map || !q->description)
2263  continue;
2264  ret.push_back({
2265  { "map", reverse_maps.find(q->map)->second },
2266  { "description", q->description },
2267  { "quest", q->quest->name },
2268  { "number", q->quest->number },
2269  });
2270  }
2271 
2272  return ret;
2273 }
2274 
2282  return {
2283  { "_key", key },
2284  { "name", map->name },
2285  { "path", map->path },
2286  { "region", map->cfregion ? reverse_regions[map->cfregion] : "reg_ffff" },
2287  { "level", map->level },
2288  { "reset_group", map->reset_group ? map->reset_group : "" },
2289  { "lore", map->lore && map->lore[0] ? map->lore : "" },
2290  { "exits_to", create_maps_array(map->exits_to) },
2291  { "exits_from", create_maps_array(map->exits_from) },
2292  { "npcs", create_npc_array(*map->npcs) },
2293  { "readables", create_npc_array(*map->readable) },
2294  { "monsters", create_race_array(map->monsters) },
2295  { "quests", create_map_in_quest_array(map->quests) },
2296  };
2297 }
2298 
2306  return {
2307  { "_key", key },
2308  { "number", quest->number },
2309  { "name", quest->name ? quest->name : "" },
2310  { "description", quest->description ? quest->description : "" },
2311  { "main_map", quest->mainmap ? reverse_maps.find(quest->mainmap)->second : "" },
2312  { "maps", create_map_in_quest_array(quest->maps) },
2313  };
2314 }
2315 
2321  char buf[50];
2322  for (size_t map = 0; map < list.count; map++) {
2323  auto cur = list.maps[map];
2324  if (cur->tiled_group)
2325  continue;
2326  snprintf(buf, sizeof(buf), "map_%04lu", map);
2327  reverse_maps.insert(std::make_pair(cur, buf));
2328  qsort(cur->exits_to.maps, cur->exits_to.count, sizeof(struct_map_info *), sort_map_info);
2329  qsort(cur->exits_from.maps, cur->exits_from.count, sizeof(struct_map_info *), sort_map_info);
2330  qsort(cur->monsters.races, cur->monsters.count, sizeof(struct_race *), sort_race);
2331  }
2332 }
2333 
2340  for (size_t map = 0; map < src.count; map++)
2341  add_map(src.maps[map], &dest);
2342 }
2343 
2349 static nlohmann::json create_region_array(const std::set<region *> &regions) {
2351  for (auto reg : regions) {
2352  auto r = reverse_regions.find(reg);
2353  if (r != reverse_regions.end()) {
2354  ret.push_back((*r).second);
2355  }
2356  }
2357  return ret;
2358 }
2359 
2366  char buf[10];
2367  struct_map_list all_maps;
2368  bool need_unknown_region = false;
2369 
2370  init_map_list(&all_maps);
2371  append_map_list(all_maps, maps_list);
2372  append_map_list(all_maps, tiled_map_list);
2373  qsort(all_maps.maps, all_maps.count, sizeof(struct_map_info *), sort_map_info);
2374 
2375  fill_reverse_maps(all_maps);
2376 
2377  for (size_t reg = 0; reg < region_count; reg++) {
2378  auto region = regions[reg];
2379  snprintf(buf, sizeof(buf), "reg_%04lu", reg);
2380  reverse_regions.insert(std::make_pair(region->reg, buf));
2381  }
2382 
2383  for (size_t reg = 0; reg < region_count; reg++) {
2384  auto region = regions[reg];
2385  qsort(region->maps_list.maps, region->maps_list.count, sizeof(struct_map_info *), sort_map_info);
2386 
2387  json["regions"].push_back({
2388  { "_key", reverse_regions[region->reg] },
2389  { "name", region->reg->name },
2390  { "longname", region->reg->longname },
2391  { "description", region->reg->msg ? region->reg->msg : "" },
2392  { "maps", create_maps_array(region->maps_list) },
2393  { "links", create_region_array(region_links[region->reg]) },
2394  });
2395  }
2396 
2397  for (auto map : reverse_maps) {
2398  auto cur = map.first;
2399  if (cur->tiled_group)
2400  continue;
2401  if (cur->cfregion == nullptr)
2402  need_unknown_region = true;
2403  json["maps"].push_back(create_map_object(cur, map.second));
2404  }
2405 
2406  if (need_unknown_region) {
2407  json["regions"].push_back({
2408  { "_key", "reg_ffff" },
2409  { "name", "unknown" },
2410  { "longname", "unknown" },
2411  { "description", "unknown" },
2412  { "maps", nlohmann::json::array() },
2413  { "links", nlohmann::json::array() },
2414  });
2415  }
2416 
2417  json["reset_groups"] = nlohmann::json::array();
2418  for (const auto &rg : reset_groups) {
2419  json["reset_groups"].push_back(rg);
2420  }
2421 
2422  json["items"] = nlohmann::json::array();
2423  for (size_t idx = 0; idx < special_equipment.size(); idx++) {
2424  auto eq = special_equipment[idx];
2425  json["items"][idx] = {
2426  { "name", eq->name },
2427  { "power", eq->power },
2428  { "calc_power", eq->calc_power },
2429  { "diff", eq->diff },
2430  { "maps", create_maps_array(eq->origin) },
2431  };
2432  }
2433 
2434  json["monsters"] = nlohmann::json::array();
2435  for (size_t item = 0; item < races.count; item++) {
2436  auto race = races.races[item];
2437  qsort(race->origin.maps, race->origin.count, sizeof(struct_map_info *), sort_map_info);
2438  json["monsters"].push_back({
2439  { "name", race->name },
2440  { "count", race->count },
2441  { "maps", create_maps_array(race->origin) },
2442  });
2443  }
2444 
2445  json["system_quests"] = nlohmann::json::array();
2446  for (size_t q = 0; q < system_quests.size(); q++) {
2447  auto quest = system_quests[q];
2448  nlohmann::json j({
2449  { "code", quest->quest_code },
2450  { "title", quest->quest_title },
2451  { "description", quest->quest_description ? quest->quest_description : "" },
2452  { "replayable", quest->quest_restart },
2453  { "steps", nlohmann::json::array() },
2454  { "maps", nlohmann::json::array() },
2455  });
2456 
2457  if (detail_quests) {
2458  std::sort(quest->steps.begin(), quest->steps.end(), [] (auto left, auto right) { return left->step < right->step; });
2459  for (size_t s = 0; s < quest->steps.size(); s++) {
2460  j["steps"].push_back({
2461  { "description", quest->steps[s]->step_description ? quest->steps[s]->step_description : "" },
2462  { "is_completion", quest->steps[s]->is_completion_step ? true : false },
2463  });
2464  }
2465 
2466  auto qim = find_quest_info(quest->quest_code);
2467  if (qim) {
2468  for (size_t m = 0; m < qim->maps.count; m++) {
2469  auto map = reverse_maps.find(qim->maps.list[m]->map);
2470  assert(map != reverse_maps.end());
2471  j["maps"].push_back({
2472  { "description", qim->maps.list[m]->description },
2473  { "map", map->second },
2474  });
2475  }
2476  }
2477  }
2478  json["system_quests"].push_back(j);
2479  }
2480 
2481  json["slaying"] = nlohmann::json::array();
2482  for (size_t s = 0; s < slaying_count; s++) {
2483  auto info = slaying_info[s];
2484  json["slaying"].push_back({
2485  { "slaying", info->slaying },
2486  { "doors", create_maps_array(info->maps[S_DOOR]) },
2487  { "keys", create_maps_array(info->maps[S_KEY]) },
2488  { "containers", create_maps_array(info->maps[S_CONTAINER]) },
2489  { "detectors", create_maps_array(info->maps[S_DETECTOR]) },
2490  { "connections", create_maps_array(info->maps[S_CONNECT]) },
2491  });
2492  }
2493 
2494  json["quests"] = nlohmann::json::array();
2495  for (int quest = 0; quest < quests_count; quest++) {
2497  char buf[100];
2498  snprintf(buf, sizeof(buf), "quest_%d", quests[quest]->number);
2500  }
2501 }
2502 
2504 static std::vector<std::string> path_stack;
2505 
2506 void add_template_to_render(const std::string &template_name, const std::string &output_name, const std::string &param);
2507 
2513 static std::string path_from_current(const std::string &path) {
2514  auto p(path);
2515  char rel[1000];
2516  if (p[0] != '/')
2517  p = '/' + p;
2518  auto current(path_stack.back());
2519  if (current[0] != '/')
2520  current = '/' + current;
2521  relative_path(current.c_str(), p.c_str(), rel);
2522  return rel;
2523 }
2524 
2531  auto template_name = args.at(0)->get<std::string>();
2532  auto output_name(template_name);
2533  auto param = (args.size() > 1 ? args.at(1)->get<std::string>() : "");
2534 
2535  if (!param.empty()) {
2536  output_name = param + "_" + output_name;
2537  if (param.substr(0, 4) == "map_") {
2538  auto map = find_map_by_key(param);
2539  if (map != nullptr) {
2540  output_name = std::string(map->path + 1) + ".html";
2541  }
2542  }
2543  if (param.substr(0, 4) == "reg_") {
2544  auto reg = find_region_by_key(param);
2545  if (reg != nullptr) {
2546  output_name = std::string(reg->name) + ".html";
2547  }
2548  }
2549  }
2550 
2551  add_template_to_render(template_name, output_name, param);
2552  return path_from_current(output_name);
2553 }
2554 
2561  auto what = args.at(0)->get<std::string>();
2562  if (what.substr(0, 4) == "map_") {
2563  auto map = find_map_by_key(what);
2564  if (map == nullptr)
2565  return "";
2566  int size = 0;
2567  if (args.size() > 1) {
2568  size = args.at(1)->get<int>() - 1;
2569  }
2570  char picpath[1000];
2571  snprintf(picpath, sizeof(picpath), "%s.x%d%s", map->path, size + 1, output_extensions[output_format]);
2572  return path_from_current(picpath);
2573  }
2574  return "";
2575 }
2576 
2581 public:
2582  std::string template_name;
2583  std::string output_name;
2584  std::string param;
2585 };
2586 static std::vector<pageToRender> pages;
2594 void add_template_to_render(const std::string &template_name, const std::string &output_name, const std::string &param) {
2595  auto on(output_name);
2596  if (on[0] != '/')
2597  on = '/' + on;
2598  if (rendered_templates.find(on) != rendered_templates.end())
2599  return;
2600 
2601  rendered_templates.insert(on);
2602  pageToRender r;
2603  r.template_name = template_name;
2604  r.output_name = on;
2605  r.param = param;
2606  pages.push_back(r);
2607 }
2608 
2609 static std::vector<std::string> split(const std::string &field, const std::string &by) {
2610  std::vector<std::string> result;
2611  size_t start = 0, found;
2612  while ((found = field.find(by, start)) != std::string::npos) {
2613  result.push_back(field.substr(start, found - start));
2614  start = found + 1;
2615  }
2616  result.push_back(field.substr(start));
2617  return result;
2618 }
2619 
2620 static std::string templates_root("templates/");
2621 static std::vector<std::string> templates;
2626 static void init_renderer_env() {
2627  env = std::make_shared<inja::Environment>(templates_root, std::string(root) + "/");
2628  env->add_callback("link_to_page", generate_page_and_link);
2629  env->add_callback("substr", [] (inja::Arguments &args) {
2630  std::string str = args.at(0)->get<std::string>();
2631  size_t start = args.at(1)->get<size_t>();
2632  size_t len = args.size() > 2 ? args.at(2)->get<size_t>() : std::string::npos;
2633  return str.substr(start, len);
2634  });
2635  env->add_callback("picture", generate_picture_link);
2636  env->add_callback("pad", [] (inja::Arguments &args) {
2637  char buf[50];
2638  int val = args.at(0)->get<int>(), digits = args.at(1)->get<int>();
2639  snprintf(buf, sizeof(buf), "%0*d", digits, val);
2640  return std::string(buf);
2641  });
2642  env->add_callback("path_to_root", 0, [] (inja::Arguments &) {
2643  std::string r(root);
2644  char rel[1000];
2645  auto current(path_stack.back() + '/');
2646  if (current[0] != '/')
2647  current = '/' + current;
2648  relative_path(current.c_str(), r.c_str(), rel);
2649  return std::string(rel);
2650  });
2651  env->add_callback("get_by_field", 3, [] (inja::Arguments &args) {
2652  const auto &src = args.at(0);
2653  auto field = args.at(1)->get<std::string>();
2654  const auto &value = args.at(2);
2655  auto found = std::find_if(src->begin(), src->end(), [&field, &value] (auto item) {
2656  return item[field] == *value;
2657  });
2658  if (found == src->end()) {
2659  return nlohmann::json();
2660  }
2661  return *found;
2662  });
2663  env->add_callback("get_list_by_field", 3, [] (inja::Arguments &args) {
2665  const auto &src = args.at(0);
2666  auto field = args.at(1)->get<std::string>();
2667  const auto filter = args.at(2);
2668  if (filter->is_array()) {
2669  std::copy_if(src->begin(), src->end(), std::back_inserter(ret), [&] (auto &item) {
2670  auto val = item[field];
2671  return std::find_if(filter->begin(), filter->end(), [&] (auto li) { return val == li; }) != filter->end();
2672  });
2673  } else {
2674  std::copy_if(src->begin(), src->end(), std::back_inserter(ret), [&] (auto &item) {
2675  return filter->get<std::string>() == item[field];
2676  });
2677  }
2678  return ret;
2679  });
2680  env->add_callback("sort", [] (inja::Arguments &args) {
2681  const auto &src = args.at(0);
2682  std::vector<nlohmann::json> ret;
2683  for (auto i : *src) {
2684  ret.push_back(i);
2685  }
2686  auto fields = split(args.at(1)->get<std::string>(), ",");
2687  bool invert = args.size() > 2 ? args.at(2)->get<bool>() : false;
2688  bool ignore_case = args.size() > 3 ? args.at(3)->get<bool>() : true;
2689  std::sort(ret.begin(), ret.end(), [&] (auto left, auto right) {
2690  for (auto field : fields) {
2691  nlohmann::json l = left[field], r = right[field];
2692  if (ignore_case && l.is_string() && r.is_string()) {
2693  std::string ls(l.get<std::string>()), rs(r.get<std::string>());
2694  std::transform(ls.begin(), ls.end(), ls.begin(), [](unsigned char c){ return std::tolower(c); });
2695  std::transform(rs.begin(), rs.end(), rs.begin(), [](unsigned char c){ return std::tolower(c); });
2696  if (ls == rs) {
2697  continue;
2698  }
2699  return invert ? (rs < ls) : (ls < rs);
2700  }
2701  if (r == l) {
2702  continue;
2703  }
2704  return invert ? (r < l) : (l < r);
2705  }
2706  return false;
2707  });
2708  return ret;
2709  });
2710 
2711  env->set_trim_blocks(true);
2712  env->set_lstrip_blocks(true);
2713 }
2714 
2716 static const char *ignore_path[] = {
2717  "/Info",
2718  "/editor",
2719  "/python",
2720  "/styles",
2721  "/templates",
2722  "/test",
2723  "/unlinked",
2724  NULL };
2725 
2727 static const char *ignore_name[] = {
2728  ".",
2729  "..",
2730  ".git",
2731  ".svn",
2732  "README",
2733  NULL };
2734 
2741 static void find_maps(const char *from) {
2742  struct dirent *file;
2743  struct stat statbuf;
2744  int status, ignore;
2745  char path[1024], full[HUGE_BUF];
2746  DIR *dir;
2747 
2748  for (ignore = 0; ignore_path[ignore] != NULL; ignore++) {
2749  if (strcmp(from, ignore_path[ignore]) == 0)
2750  return;
2751  }
2752 
2753  snprintf(path, sizeof(path), "%s/%s%s", settings.datadir, settings.mapdir, from);
2754  dir = opendir(path);
2755 
2756  if (dir) {
2757  for (file = readdir(dir); file; file = readdir(dir)) {
2758 
2759  for (ignore = 0; ignore_name[ignore] != NULL; ignore++) {
2760  if (strcmp(file->d_name, ignore_name[ignore]) == 0)
2761  break;
2762  }
2763  if (ignore_name[ignore] != NULL)
2764  continue;
2765 
2766  snprintf(full, sizeof(full), "%s/%s", path, file->d_name);
2767 
2768  status = stat(full, &statbuf);
2769  snprintf(full, sizeof(full), "%s/%s", from, file->d_name);
2770  if ((status != -1) && (S_ISDIR(statbuf.st_mode))) {
2771  find_maps(full);
2772  continue;
2773  }
2774  found_maps.push_back(strdup(full));
2775  }
2776  closedir(dir);
2777  }
2778 }
2779 
2781 static void dump_unused_maps(void) {
2782  FILE *dump;
2783  char path[1024];
2784 
2785  snprintf(path, sizeof(path), "%s/%s", root, "maps.unused");
2786  dump = fopen(path, "w+");
2787  if (dump == NULL) {
2788  printf("Unable to open file maps.unused!\n");
2789  return;
2790  }
2791  for (auto map = found_maps.cbegin(); map != found_maps.cend(); ++map) {
2792  fprintf(dump, "%s\n", *map);
2793  }
2794  fclose(dump);
2795  printf("%ld unused maps.\n", found_maps.size());
2796 }
2797 
2799 static void write_world_info(void) {
2800  FILE *file;
2801  char path[strlen(root) + 150 + strlen(output_extensions[output_format])];
2802  int x, y;
2803  gdImagePtr elevationmap;
2804 
2805  if (!world_exit_info)
2806  return;
2807 
2808 
2809  printf("Saving exit/blocking/road information...");
2810  snprintf(path, sizeof(path), "%s/%s%s", root, "world_info", output_extensions[output_format]);
2811  file = fopen(path, "wb+");
2813  fclose(file);
2814  printf("done.\n");
2815  gdImageDestroy(infomap);
2816  infomap = NULL;
2817 
2818  if (elevation_min == 0 || elevation_max == 0) {
2819  puts("Error: Could not save elevation world map due to not finding any minimum or maximum elevation.");
2820  return;
2821  }
2822 
2823  elevationmap = gdImageCreateTrueColor(30*50, 30*50);;
2824 
2825  for (x = 0; x < 30*50; x++) {
2826  for (y = 0; y < 30*50; y++) {
2827  gdImageSetPixel(elevationmap, x, y, get_elevation_color(elevation_info[x][y], elevationmap));
2828  }
2829  }
2830 
2831  printf("Saving elevation world map...");
2832  snprintf(path, sizeof(path), "%s/%s%s", root, "world_elevation", output_extensions[output_format]);
2833  file = fopen(path, "wb+");
2834  save_picture(file, elevationmap);
2835  fclose(file);
2836  printf("done.\n");
2837  gdImageDestroy(elevationmap);
2838  elevationmap = NULL;
2839 }
2840 
2851 static int sort_slaying(const void *left, const void *right) {
2854 
2855  return strcasecmp(l->slaying, r->slaying);
2856 }
2857 
2864 static void do_help(const char *program) {
2865  printf("Crossfire Mapper will generate pictures of maps, and create indexes for all maps and regions.\n\n");
2866  printf("Syntax: %s\n\n", program);
2867  printf("Optional arguments:\n");
2868  printf(" -nopics don't generate pictures.\n");
2869  printf(" -root=<path> destination path. Default 'html'.\n");
2870  printf(" -limit=<number> stop processing after this number of maps, -1 to do all maps (default).\n");
2871  printf(" -showmaps outputs the name of maps as they are processed.\n");
2872  printf(" -jpg[=quality] generate jpg pictures, instead of default png. Quality should be 0-95, -1 for automatic.\n");
2873  printf(" -forcepics force to regenerate pics, even if pics's date is after map's.\n");
2874  printf(" -addmap=<map> adds a map to process. Path is relative to map's directory root.\n");
2875  printf(" -rawmaps generates maps pics without items on random (shop, treasure) tiles.\n");
2876  printf(" -warnnopath inform when an exit has no path set.\n");
2877  printf(" -listunusedmaps finds all unused maps in the maps directory.\n");
2878  printf(" -noworldmap don't write the world map in world.png.\n");
2879  printf(" -noregionslink don't generate regions relation file.\n");
2880  printf(" -regionslink generate regions relation file.\n");
2881  printf(" -noexitmap don't generate map of exits.\n");
2882  printf(" -exitmap generate map of exits.\n");
2883  printf(" -tileset=<number> use specified tileset to generate the pictures. Default 0 (standard).\n");
2884  printf(" -details-quests list all quests steps. Default no.\n");
2885  printf(" -list-system-quests include 'system' quests in quest list. Default no.\n");
2886  printf(" -templates-dir=[dir] set the directory to get templates from. Default 'templates/'.\n");
2887  printf(" -add-template=[file] add a template to process. May be specified multiple times. If empty, 'index.html' is used.\n");
2888  printf(" -list-template-to-process display the name of the template about to be rendered. Useful for debugging.");
2889  printf("\n\n");
2890  exit(0);
2891 }
2892 
2901 static void do_parameters(int argc, char **argv) {
2902  int arg = 1;
2903  char path[500];
2904 
2905  root[0] = '\0';
2906 
2907  while (arg < argc) {
2908  if (strcmp(argv[arg], "-nopics") == 0)
2909  generate_pics = 0;
2910  else if (strncmp(argv[arg], "-root=", 6) == 0)
2911  strncpy(root, argv[arg]+6, 500);
2912  else if (strncmp(argv[arg], "-limit=", 7) == 0)
2913  map_limit = atoi(argv[arg]+7);
2914  else if (strcmp(argv[arg], "-showmaps") == 0)
2915  show_maps = 1;
2916  else if (strcmp(argv[arg], "-jpg") == 0) {
2918  if (argv[arg][4] == '=') {
2919  jpeg_quality = atoi(argv[arg]+5);
2920  if (jpeg_quality < 0)
2921  jpeg_quality = -1;
2922  }
2923  }
2924  else if (strcmp(argv[arg], "-forcepics") == 0)
2925  force_pics = 1;
2926  else if (strncmp(argv[arg], "-addmap=", 8) == 0) {
2927  if (*(argv[arg]+8) == '/')
2928  strncpy(path, argv[arg]+8, 500);
2929  else
2930  snprintf(path, 500, "/%s", argv[arg]+8);
2932  }
2933  else if (strcmp(argv[arg], "-rawmaps") == 0)
2934  rawmaps = 1;
2935  else if (strcmp(argv[arg], "-warnnopath") == 0)
2936  warn_no_path = 1;
2937  else if (strcmp(argv[arg], "-listunusedmaps") == 0)
2938  list_unused_maps = 1;
2939  else if (strcmp(argv[arg], "-noworldmap") == 0)
2940  world_map = 0;
2941  else if (strcmp(argv[arg], "-noregionslink") == 0)
2942  do_regions_link = false;
2943  else if (strcmp(argv[arg], "-regionslink") == 0)
2944  do_regions_link = true;
2945  else if (strcmp(argv[arg], "-noexitmap") == 0)
2946  world_exit_info = 0;
2947  else if (strcmp(argv[arg], "-exitmap") == 0)
2948  world_exit_info = 1;
2949  else if (strncmp(argv[arg], "-tileset=", 9) == 0) {
2950  tileset = atoi(argv[arg]+9);
2951  /* check of validity is done in main() as we need to actually have the sets loaded. */
2952  } else if (strcmp(argv[arg], "-detail-quests") == 0) {
2953  detail_quests = 1;
2954  } else if (strcmp(argv[arg], "-list-system-quests") == 0) {
2955  list_system_quests = 1;
2956  } else if (strncmp(argv[arg], "-templates-dir=", 15) == 0) {
2957  templates_root = argv[arg] + 15;
2958  } else if (strncmp(argv[arg], "-add-template=", 14) == 0) {
2959  templates.push_back(argv[arg] + 14);
2960  } else if (strcmp(argv[arg], "-list-template-to-process") == 0) {
2962  } else
2963  do_help(argv[0]);
2964  arg++;
2965  }
2966  if (!strlen(root))
2967  strcpy(root, "html");
2968  if (root[strlen(root)-1] == '/')
2969  root[strlen(root)-1] = '\0';
2970  if (map_limit < -1)
2971  map_limit = -1;
2972 
2973  if (templates_root.empty()) {
2974  templates_root = "templates/";
2975  } else if (templates_root[templates_root.length() - 1] != '/') {
2976  templates_root.append("/");
2977  }
2978 }
2979 
2983 static void create_destination(void) {
2984  char dummy[502];
2985 
2986  strcpy(dummy, root);
2987  strcat(dummy, "/a");
2988  make_path_to_file(dummy);
2989 }
2990 
2999 static const char *yesno(int value) {
3000  return (value ? "yes" : "no");
3001 }
3002 
3004 static inja::Template get_template(const std::string &filename) {
3005  auto find = templateCache.find(filename);
3006  if (find != templateCache.end()) {
3007  return find->second;
3008  }
3009  inja::Template parsed = env->parse_template(filename);
3010  templateCache[filename] = parsed;
3011  return parsed;
3012 }
3013 
3014 int main(int argc, char **argv) {
3015  size_t current_map = 0, i;
3016  char max[50];
3017  region *dummy;
3018 
3022  pics_allocated = 0;
3023 
3024  do_parameters(argc, argv);
3025 
3026  printf("Initializing Crossfire data...\n");
3027 
3029 
3030  init_globals();
3031  init_library();
3032  init_readable();
3033 
3034  init_gods();
3035 
3036  /* Add a dummy region so unlinked maps can be identified. */
3037  dummy = get_region_struct();
3038  dummy->fallback = 1;
3039  dummy->name = strdup_local("unlinked");
3040  dummy->longname = strdup_local("This dummy region contains all maps without a region set.");
3041  dummy->longname = strdup_local("This dummy region contains all maps without a region set.");
3042  all_regions.push_back(dummy);
3043 
3044  printf("\n\n done.\n\n");
3045 
3046  if (!is_valid_faceset(tileset)) {
3047  printf("Erreor: invalid tileset %d!\n", tileset);
3048  exit(1);
3049  }
3050 
3051  if (templates.empty()) {
3052  templates.push_back("index.html");
3053  }
3054 
3056  gdfaces.resize(get_faces_count(), nullptr);
3057 
3058  if (map_limit != -1)
3059  snprintf(max, sizeof(max), "%d", map_limit);
3060  else
3061  strcpy(max, "(none)");
3062  printf("Crossfire map browser generator\n");
3063  printf("-------------------------------\n\n");
3064  printf("Parameters:\n");
3065  printf(" path to write files: %s\n", root);
3066  printf(" maximum number of maps to process: %s\n", max);
3067  printf(" will generate map picture: %s\n", yesno(generate_pics));
3068  printf(" will always generate map picture: %s\n", yesno(force_pics));
3069  printf(" picture output format: %s\n", output_extensions[output_format]);
3070  if (output_format == OF_JPG)
3071  printf(" JPEG quality: %d\n", jpeg_quality);
3072  printf(" show map being processed: %s\n", yesno(show_maps));
3073  printf(" generate raw maps: %s\n", yesno(rawmaps));
3074  printf(" warn of exit without path: %s\n", yesno(warn_no_path));
3075  printf(" list unused maps: %s\n", yesno(list_unused_maps));
3076  printf(" generate world map: %s\n", yesno(world_map));
3077  printf(" generate exit map: %s\n", yesno(world_exit_info));
3078  printf(" generate regions link file: %s\n", yesno(do_regions_link));
3079  printf(" tileset: %s\n", find_faceset(tileset)->fullname);
3080  printf(" detail quest steps: %s\n", yesno(detail_quests));
3081  printf(" list system quests: %s\n", yesno(list_system_quests));
3082  printf(" templates directory: %s\n", templates_root.c_str());
3083  printf(" templates to process: ");
3084  const char *sep = "";
3085  for (auto f : templates) {
3086  printf("%s%s", sep, f.c_str());
3087  sep = ", ";
3088  }
3089  printf("\n");
3090  printf(" display template to process: %s\n", yesno(display_rendered_template));
3091  printf("\n");
3092 
3093  if (list_unused_maps) {
3094  printf("listing all maps...");
3095  find_maps("");
3096  printf("done, %ld maps found.\n", found_maps.size());
3097  }
3098 
3099  /* exit/blocking information. */
3100  infomap = gdImageCreateTrueColor(30*50, 30*50);
3101  color_unlinked_exit = gdImageColorResolve(infomap, 255, 0, 0);
3102  color_linked_exit = gdImageColorResolve(infomap, 255, 255, 255);
3103  color_road = gdImageColorResolve(infomap, 0, 255, 0);
3104  color_blocking = gdImageColorResolve(infomap, 0, 0, 255);
3105  color_slowing = gdImageColorResolve(infomap, 0, 0, 127);
3106  elevation_info = (int **)calloc(50*30, sizeof(int *));
3107  for (i = 0; i < 50*30; i++)
3108  elevation_info[i] = (int *)calloc(50*30, sizeof(int));
3109  elevation_min = 0;
3110  elevation_max = 0;
3111 
3112  printf("browsing maps...\n");
3113 
3115 
3116  while (current_map < maps_list.count) {
3118  if (current_map%100 == 0) {
3119  printf(" %zu maps processed, %d map pictures created, %d map pictures were uptodate. %d faces used.\n", current_map, created_pics, cached_pics, pics_allocated);
3120  }
3121  if ((map_limit != -1) && (current_map == static_cast<size_t>(map_limit))) {
3122  printf(" --- map limit reached, stopping ---\n");
3123  break;
3124  }
3125  }
3126 
3127  printf(" finished map parsing, %zu maps processed, %d map pictures created, %d map pictures were uptodate. Total %d faces used.\n", current_map, created_pics, cached_pics, pics_allocated);
3128 
3129  if (list_unused_maps)
3130  dump_unused_maps();
3131 
3133  fix_map_names();
3134  fix_tiled_map();
3136  write_tiled_maps();
3137 
3138  write_world_map();
3139  write_world_info();
3140 
3142  qsort(regions, region_count, sizeof(struct_region_info *), sort_region);
3143  std::sort(special_equipment.begin(), special_equipment.end(), sort_equipment);
3145  qsort(races.races, races.count, sizeof(struct_race *), sort_race);
3146  qsort(quests, quests_count, sizeof(struct_quest *), sort_struct_quest);
3147 
3149  std::sort(system_quests.begin(), system_quests.end(), [] (const auto &left, const auto &right) { return strcmp(left->quest_code, right->quest_code) < 0; });
3150 
3152 
3154 
3155  for (auto file : templates) {
3156  if (!file.empty()) {
3158  }
3159  }
3160 
3161  const auto fullStart = time(nullptr);
3162  printf("rendering pages...");
3164  printf("\n");
3165  fflush(stdout);
3166 
3167  while (!pages.empty()) {
3168  auto p = pages.back();
3169  pages.pop_back();
3170  if (p.param.empty())
3171  all_data.erase("param");
3172  else
3173  all_data["param"] = p.param;
3174  const auto start = time(nullptr);
3176  printf(" rendering page %s (%s)... ", p.template_name.c_str(), p.param.c_str());
3177  fflush(stdout);
3178  }
3179  path_stack.push_back(p.output_name);
3180  inja::Template temp = get_template(p.template_name);
3181  env->write(temp, all_data, p.output_name);
3182  path_stack.pop_back();
3183  const auto elapsed = time(nullptr) - start;
3185  printf("took %ld seconds\n", elapsed);
3186  }
3187  }
3188 
3189  const auto elapsed = time(nullptr) - fullStart;
3190  printf(" done, took %ld seconds\n", elapsed);
3191 
3192  return 0;
3193 }
3194 
3196  int x, y;
3197 
3198  if (m == NULL)
3199  return;
3200 
3201  for (x = 0; x < MAP_WIDTH(m); x++)
3202  for (y = 0; y < MAP_HEIGHT(m); y++)
3203  FOR_MAP_PREPARE(m, x, y, tmp) {
3204  if (tmp->inv) {
3205  FOR_INV_PREPARE(tmp, invtmp) {
3206  if (QUERY_FLAG(invtmp, FLAG_AUTO_APPLY))
3207  apply_auto(invtmp);
3208  else if (invtmp->type == TREASURE && HAS_RANDOM_ITEMS(invtmp)) {
3209  while ((invtmp->stats.hp--) > 0)
3210  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3211  invtmp->randomitems = NULL;
3212  } else if (invtmp
3213  && invtmp->arch
3214  && invtmp->type != TREASURE
3215  && invtmp->type != SPELL
3216  && invtmp->type != CLASS
3217  && HAS_RANDOM_ITEMS(invtmp)) {
3218  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3219  /* Need to clear this so that we never try to create
3220  * treasure again for this object
3221  */
3222  invtmp->randomitems = NULL;
3223  }
3224  } FOR_INV_FINISH();
3225  /* This is really temporary - the code at the bottom will
3226  * also set randomitems to null. The problem is there are bunches
3227  * of maps/players already out there with items that have spells
3228  * which haven't had the randomitems set to null yet.
3229  * MSW 2004-05-13
3230  *
3231  * And if it's a spellbook, it's better to set randomitems to NULL too,
3232  * else you get two spells in the book ^_-
3233  * Ryo 2004-08-16
3234  */
3235  if (tmp->type == WAND
3236  || tmp->type == ROD
3237  || tmp->type == SCROLL
3238  || tmp->type == FIREWALL
3239  || tmp->type == POTION
3240  || tmp->type == ALTAR
3241  || tmp->type == SPELLBOOK)
3242  tmp->randomitems = NULL;
3243  }
3244 
3246  apply_auto(tmp);
3247  else if ((tmp->type == TREASURE || (tmp->type == CONTAINER)) && HAS_RANDOM_ITEMS(tmp)) {
3248  while ((tmp->stats.hp--) > 0)
3249  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
3250  tmp->randomitems = NULL;
3251  } else if (tmp->type == TIMED_GATE) {
3252  object *head = HEAD(tmp);
3253 
3254  if (QUERY_FLAG(head, FLAG_IS_LINKED)) {
3255  tmp->speed = 0;
3257  }
3258  /* This function can be called everytime a map is loaded, even when
3259  * swapping back in. As such, we don't want to create the treasure
3260  * over and ove again, so after we generate the treasure, blank out
3261  * randomitems so if it is swapped in again, it won't make anything.
3262  * This is a problem for the above objects, because they have counters
3263  * which say how many times to make the treasure.
3264  */
3265  } else if (tmp
3266  && tmp->arch
3267  && tmp->type != PLAYER
3268  && tmp->type != TREASURE
3269  && tmp->type != SPELL
3270  && tmp->type != PLAYER_CHANGER
3271  && tmp->type != CLASS
3272  && HAS_RANDOM_ITEMS(tmp)) {
3273  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
3274  tmp->randomitems = NULL;
3275  }
3276  } FOR_MAP_FINISH();
3277 
3278  for (x = 0; x < MAP_WIDTH(m); x++)
3279  for (y = 0; y < MAP_HEIGHT(m); y++)
3280  FOR_MAP_PREPARE(m, x, y, tmp) {
3281  if (tmp->above
3282  && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL))
3283  check_trigger(tmp, tmp->above);
3284  } FOR_MAP_FINISH();
3285 }
3286 
3287 #ifndef DOXYGEN_SHOULD_SKIP_THIS
3288 
3293 void draw_ext_info(int, int, const object *, uint8_t, uint8_t, const char *txt) {
3294  fprintf(logfile, "%s\n", txt);
3295 }
3296 
3297 void draw_ext_info_format(int, int, const object *, uint8_t, uint8_t, const char *format, ...) {
3298  va_list ap;
3299 
3300  va_start(ap, format);
3301  vfprintf(logfile, format, ap);
3302  va_end(ap);
3303 }
3304 
3305 void ext_info_map(int, const mapstruct *, uint8_t, uint8_t, const char *str1) {
3306  fprintf(logfile, "ext_info_map: %s\n", str1);
3307 }
3308 
3309 void move_firewall(object *) {
3310 }
3311 
3312 void emergency_save(int) {
3313 }
3314 
3315 void clean_tmp_files(void) {
3316 }
3317 
3318 void esrv_send_item(object *, object *) {
3319 }
3320 
3321 void dragon_ability_gain(object *, int, int) {
3322 }
3323 
3325 }
3326 
3327 object *find_skill_by_number(object *, int) {
3328  return NULL;
3329 }
3330 
3331 void esrv_del_item(player *, object *) {
3332 }
3333 
3334 void esrv_update_item(int, object *, object *) {
3335 }
3336 
3338 }
3339 
3340 void rod_adjust(object *) {
3341 }
3342 
3343 /*
3344  * This a modified version of apply_auto: BOOK are not generated, so they don't pollute
3345  * the readable list.
3346  */
3347 int apply_auto(object *op) {
3348  object *tmp = NULL;
3349  int i;
3350 
3351  switch (op->type) {
3352  case SHOP_FLOOR:
3353  if (!HAS_RANDOM_ITEMS(op))
3354  return 0;
3355  do {
3356  i = 10; /* let's give it 10 tries */
3357  while ((tmp = generate_treasure(op->randomitems, op->stats.exp ? (int)op->stats.exp : MAX(op->map->difficulty, 5))) == NULL && --i)
3358  ;
3359  if (tmp == NULL)
3360  return 0;
3361  if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED) || tmp->type == BOOK) {
3363  tmp = NULL;
3364  }
3365  } while (!tmp);
3367  object_insert_in_map_at(tmp, op->map, NULL, 0, op->x, op->y);
3369  tmp = identify(tmp);
3370  break;
3371 
3372  case TREASURE:
3374  return 0;
3375 
3376  while ((op->stats.hp--) > 0)
3377  create_treasure(op->randomitems, op, 0, op->stats.exp ? (int)op->stats.exp : op->map == NULL ? 14 : op->map->difficulty, 0);
3378 
3379  /* If we generated an object and put it in this object inventory,
3380  * move it to the parent object as the current object is about
3381  * to disappear. An example of this item is the random_ *stuff
3382  * that is put inside other objects.
3383  */
3384  FOR_INV_PREPARE(op, tmp) {
3385  object_remove(tmp);
3386  if (op->env && tmp->type != BOOK)
3387  object_insert_in_ob(tmp, op->env);
3388  else
3390  }
3391  FOR_INV_FINISH();
3392  object_remove(op);
3394  break;
3395  }
3396  return tmp ? 1 : 0;
3397 }
3398 
3400 }
3401 
3403  return NULL;
3404 }
3405 
3407  return NULL;
3408 }
3409 
3411  return NULL;
3412 }
3413 
3415 }
3416 
3418 }
3419 
3420 void command_help(object *, const char *) {
3421 }
3422 
3423 void account_logout(const char *) {
3424 }
3425 
3426 #endif /* dummy DOXYGEN_SHOULD_SKIP_THIS */
get_race
static struct_race * get_race(const char *name)
Definition: mapper.cpp:597
struct_map_info::tiles
struct struct_map_info * tiles[4]
Definition: mapper.cpp:232
CLASS
@ CLASS
Definition: object.h:143
object::name_pl
sstring name_pl
Definition: object.h:323
struct_region_info::sum_x
int sum_x
Definition: mapper.cpp:357
give.next
def next
Definition: give.py:44
move_firewall
void move_firewall(object *)
Definition: mapper.cpp:3309
init_globals
void init_globals(void)
Definition: init.cpp:396
write_tiled_map_page
static void write_tiled_map_page(struct_map_info *map)
Definition: mapper.cpp:2144
fix_tiled_map_monsters
static void fix_tiled_map_monsters(void)
Definition: mapper.cpp:1979
do_auto_apply
void do_auto_apply(mapstruct *m)
Definition: mapper.cpp:3195
add_map
static void add_map(struct_map_info *info, struct_map_list *list)
Definition: mapper.cpp:1167
HAS_RANDOM_ITEMS
#define HAS_RANDOM_ITEMS(op)
Definition: define.h:184
PLAYER
@ PLAYER
Definition: object.h:112
Settings::mapdir
const char * mapdir
Definition: global.h:251
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:545
settings
struct Settings settings
Definition: init.cpp:139
ignore_name
static const char * ignore_name[]
Definition: mapper.cpp:2727
struct_equipment::diff
char * diff
Definition: mapper.cpp:246
banquet.l
l
Definition: banquet.py:164
get_quest_info
static struct_quest * get_quest_info(const char *name)
Definition: mapper.cpp:934
find_region_by_key
static region * find_region_by_key(const std::string &key)
Definition: mapper.cpp:2194
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
process_map_lore
static void process_map_lore(struct_map_info *map)
Definition: mapper.cpp:1048
find_artifact
const artifact * find_artifact(const object *op, const char *name)
Definition: artifact.cpp:589
llevError
@ llevError
Definition: logger.h:11
get_region_struct
region * get_region_struct(void)
Definition: region.cpp:294
maps
static std::unordered_map< std::string, mapzone * > maps
Definition: citylife.cpp:92
region::fallback
int8_t fallback
Definition: map.h:283
compare_map_info
static int compare_map_info(const struct_map_info *left, const struct_map_info *right)
Definition: mapper.cpp:822
path_from_current
static std::string path_from_current(const std::string &path)
Definition: mapper.cpp:2513
MOVE_ALL
#define MOVE_ALL
Definition: define.h:398
WAND
@ WAND
Definition: object.h:225
quest_for_each
void quest_for_each(quest_op op, void *user)
Definition: assets.cpp:539
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:58
struct_region_info::is_world
int is_world
Definition: mapper.cpp:358
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
generate_picture_link
static nlohmann::json generate_picture_link(inja::Arguments &args)
Definition: mapper.cpp:2560
struct_map_info::tiled_group
struct struct_map_info * tiled_group
Definition: mapper.cpp:229
struct_map_info::filename
char * filename
Definition: mapper.cpp:213
num_sizes
static const int num_sizes
Definition: mapper.cpp:313
player
Definition: player.h:105
add_slaying
static void add_slaying(struct_map_info *map, object *item)
Definition: mapper.cpp:1431
strdup_local
#define strdup_local
Definition: compat.h:29
diamondslots.x
x
Definition: diamondslots.py:15
ready_map_name
mapstruct * ready_map_name(const char *name, int flags)
Definition: map.cpp:1768
write_tiled_maps
static void write_tiled_maps(void)
Definition: mapper.cpp:2154
first_map_path
char first_map_path[MAX_BUF]
Definition: init.cpp:120
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
struct_quest::maps
struct_map_in_quest_list maps
Definition: mapper.cpp:889
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
create_quest_object
static nlohmann::json create_quest_object(struct_quest *quest, const std::string &key)
Definition: mapper.cpp:2305
create_map_info
static struct_map_info * create_map_info(void)
Definition: mapper.cpp:1188
struct_race::count
int count
Definition: mapper.cpp:256
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:139
nlohmann::json
basic_json<> json
default JSON class
Definition: json.hpp:3404
struct_map_in_quest::map
struct_map_info * map
Definition: mapper.cpp:880
esrv_del_item
void esrv_del_item(player *, object *)
Definition: mapper.cpp:3331
pageToRender::param
std::string param
Definition: mapper.cpp:2584
S_CONNECT
#define S_CONNECT
Definition: mapper.cpp:390
write_pictures_from_real_size
static void write_pictures_from_real_size(const char *path, gdImagePtr real, int width, int height)
Definition: mapper.cpp:1471
region_links
static std::map< region *, std::set< region * > > region_links
Definition: mapper.cpp:383
get_face_fallback
int get_face_fallback(int faceset, uint16_t imageno)
Definition: image.cpp:133
Settings::datadir
const char * datadir
Definition: global.h:248
c
static event_registration c
Definition: citylife.cpp:425
filter
Definition: filter.py:1
disinfect.a
a
Definition: disinfect.py:13
output_format
static enum output_format_type output_format
Definition: mapper.cpp:342
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
quests_count
static int quests_count
Definition: mapper.cpp:894
SHOP_FLOOR
@ SHOP_FLOOR
Definition: object.h:188
Ice.g
def g
Definition: Ice.py:63
create_npc_array
static nlohmann::json create_npc_array(npc_list &list)
Definition: mapper.cpp:2222
get_map_info
static struct_map_info * get_map_info(const char *path)
Definition: mapper.cpp:1260
EXIT_PATH
#define EXIT_PATH(xyz)
Definition: define.h:439
fix_exits_to_tiled_maps
static void fix_exits_to_tiled_maps(void)
Definition: mapper.cpp:1951
object::x
int16_t x
Definition: object.h:335
reverse_maps
static std::map< struct_map_info *, std::string > reverse_maps
Definition: mapper.cpp:2174
dump
static int dump(const std::set< std::string > &items, const char *name)
Definition: AssetsManager.cpp:42
gdfaces
static std::vector< gdImagePtr > gdfaces
Definition: mapper.cpp:176
guildoracle.list
list
Definition: guildoracle.py:87
struct_map_in_quest
Definition: mapper.cpp:877
slaying_allocated
static size_t slaying_allocated
Definition: mapper.cpp:401
give_artifact_abilities
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.cpp:230
get_equipment
static struct_equipment * get_equipment(void)
Definition: mapper.cpp:435
is_special_equipment
static int is_special_equipment(object *item)
Definition: mapper.cpp:416
TIMED_GATE
@ TIMED_GATE
Definition: object.h:133
region_allocated
static size_t region_allocated
Definition: mapper.cpp:363
struct_map_list
Definition: mapper.cpp:203
generate_page_and_link
static nlohmann::json generate_page_and_link(inja::Arguments &args)
Definition: mapper.cpp:2530
struct_equipment::origin
struct_map_list origin
Definition: mapper.cpp:247
generate_treasure
object * generate_treasure(treasurelist *t, int difficulty)
Definition: treasure.cpp:295
find_faceset
face_sets * find_faceset(int id)
Definition: assets.cpp:328
artifact::item
object * item
Definition: artifact.h:15
commongive.inv
inv
Definition: commongive.py:29
root
static char root[500]
Definition: mapper.cpp:304
create_map_in_quest_array
static nlohmann::json create_map_in_quest_array(struct_map_in_quest_list &list)
Definition: mapper.cpp:2258
yesno
static const char * yesno(int value)
Definition: mapper.cpp:2999
AMULET
@ AMULET
Definition: object.h:144
CHECK_INV
@ CHECK_INV
Definition: object.h:174
struct_map_info::name
char * name
Definition: mapper.cpp:212
fix_map_names
static void fix_map_names(void)
Definition: mapper.cpp:1845
mad_mage_user.file
file
Definition: mad_mage_user.py:15
struct_slaying_info::maps
struct_map_list maps[S_MAX]
Definition: mapper.cpp:396
MIN
#define MIN(x, y)
Definition: compat.h:21
SIZE
#define SIZE
maps_list
static struct_map_list maps_list
Definition: mapper.cpp:236
TREASURE
@ TREASURE
Definition: object.h:115
color_unlinked_exit
static int color_unlinked_exit
Definition: mapper.cpp:370
struct_region_info::sum_y
int sum_y
Definition: mapper.cpp:357
pages
static std::vector< pageToRender > pages
Definition: mapper.cpp:2586
list_unused_maps
static int list_unused_maps
Definition: mapper.cpp:365
struct_map_info
Definition: mapper.cpp:210
draw_ext_info_format
void draw_ext_info_format(int, int, const object *, uint8_t, uint8_t, const char *format,...)
Definition: mapper.cpp:3297
esrv_send_item
void esrv_send_item(object *, object *)
Definition: mapper.cpp:3318
struct_map_info::min_monster
int min_monster
Definition: mapper.cpp:216
Ice.tmp
int tmp
Definition: Ice.py:207
nlohmann::basic_json::push_back
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:22807
create_region_array
static nlohmann::json create_region_array(const std::set< region * > &regions)
Definition: mapper.cpp:2349
struct_region_info
Definition: mapper.cpp:354
clean_tmp_files
void clean_tmp_files(void)
Definition: mapper.cpp:3315
inja::Template
The main inja Template.
Definition: inja.hpp:2836
add_npc_to_map
static void add_npc_to_map(npc_list *list, const object *npc)
Definition: mapper.cpp:1151
region::name
char * name
Definition: map.h:273
nlohmann::basic_json::diff
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Definition: json.hpp:26097
SIGN
@ SIGN
Definition: object.h:216
struct_equipment::name
char * name
Definition: mapper.cpp:243
TRIGGER_BUTTON
@ TRIGGER_BUTTON
Definition: object.h:137
smoking_pipe.color
color
Definition: smoking_pipe.py:5
struct_map_info::max_monster
int max_monster
Definition: mapper.cpp:216
object::level
int16_t level
Definition: object.h:361
struct_slaying_info
Definition: mapper.cpp:394
buf
StringBuffer * buf
Definition: readable.cpp:1565
struct_equipment::calc_power
int calc_power
Definition: mapper.cpp:245
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2857
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
MAX
#define MAX(x, y)
Definition: compat.h:24
apply_auto_fix
void apply_auto_fix(mapstruct *)
Definition: mapper.cpp:3399
account_char_save
void account_char_save(Account_Chars *)
Definition: mapper.cpp:3414
FLAG_NO_PICK
#define FLAG_NO_PICK
Definition: define.h:239
force_pics
static int force_pics
Definition: mapper.cpp:311
FLAG_IS_FLOOR
#define FLAG_IS_FLOOR
Definition: define.h:302
world_exit_info
static int world_exit_info
Definition: mapper.cpp:319
sort_struct_quest
static int sort_struct_quest(const void *left, const void *right)
Definition: mapper.cpp:1013
struct_quest
Definition: mapper.cpp:884
struct_map_in_quest_list
Definition: mapper.cpp:196
region::longname
char * longname
Definition: map.h:279
struct_region_info::reg
region * reg
Definition: mapper.cpp:355
struct_map_in_quest::quest
struct struct_quest * quest
Definition: mapper.cpp:882
FLAG_IS_A_TEMPLATE
#define FLAG_IS_A_TEMPLATE
Definition: define.h:366
init_renderer_env
static void init_renderer_env()
Definition: mapper.cpp:2626
struct_quest::description
char * description
Definition: mapper.cpp:886
init_gods
void init_gods(void)
Definition: holy.cpp:59
object::y
int16_t y
Definition: object.h:335
m
static event_registration m
Definition: citylife.cpp:425
quest
Definition: quest.py:1
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Definition: map.h:126
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
S_CONTAINER
#define S_CONTAINER
Definition: mapper.cpp:388
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.cpp:1560
item.q
q
Definition: item.py:32
opendir
DIR * opendir(const char *)
struct_map_info::reset_group
sstring reset_group
Definition: mapper.cpp:220
templateCache
static inja::TemplateStorage templateCache
Definition: mapper.cpp:3003
disinfect.map
map
Definition: disinfect.py:4
regions
static struct struct_region_info ** regions
Definition: mapper.cpp:361
struct_npc_info::y
int y
Definition: mapper.cpp:182
struct_map_info::exits_from
struct_map_list exits_from
Definition: mapper.cpp:217
Settings::debug
LogLevel debug
Definition: global.h:243
detail_quests
static bool detail_quests
Definition: mapper.cpp:321
ensure_unique
static struct_equipment * ensure_unique(struct_equipment *item)
Definition: mapper.cpp:482
struct_npc_info::message
const char * message
Definition: mapper.cpp:181
get_slaying_struct
static struct_slaying_info * get_slaying_struct(const char *slaying)
Definition: mapper.cpp:1388
generate_picture_path
static void generate_picture_path(const char *path, size_t pic_size, char *out, size_t len)
Definition: mapper.cpp:1467
make_face_from_files.args
args
Definition: make_face_from_files.py:37
OF_JPG
@ OF_JPG
Definition: mapper.cpp:332
rotate-tower.result
bool result
Definition: rotate-tower.py:13
elevation_max
static int elevation_max
Definition: mapper.cpp:378
struct_map_info::pic_was_done
int pic_was_done
Definition: mapper.cpp:216
set_darkness_map
void set_darkness_map(mapstruct *)
Definition: mapper.cpp:3324
POTION
@ POTION
Definition: object.h:116
struct_npc_info
Definition: mapper.cpp:179
define_quest
static void define_quest(const char *name, struct_map_info *mainmap, const char *description)
Definition: mapper.cpp:1029
path_combine_and_normalize
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Definition: path.cpp:172
add_to_struct_map_in_quest_list
static void add_to_struct_map_in_quest_list(struct_map_in_quest_list *list, struct_map_in_quest *item)
Definition: mapper.cpp:904
do_tiled_map_picture
static void do_tiled_map_picture(struct_map_info *map)
Definition: mapper.cpp:2036
slaying_info
static struct_slaying_info ** slaying_info
Definition: mapper.cpp:399
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
races
static struct_race_list races
Definition: mapper.cpp:260
npc_list
std::vector< struct_npc_info * > npc_list
Definition: mapper.cpp:186
object_get_multi_size
void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy)
Definition: object.cpp:4744
main
int main(int argc, char **argv)
Definition: mapper.cpp:3014
HEAD
#define HEAD(op)
Definition: object.h:607
output_extensions
static const char * output_extensions[]
Definition: mapper.cpp:336
create_maps_array
static nlohmann::json create_maps_array(struct_map_list &maps)
Definition: mapper.cpp:2206
ROD
@ ROD
Definition: object.h:114
show_maps
static int show_maps
Definition: mapper.cpp:317
CONTAINER
@ CONTAINER
Definition: object.h:236
system_quests
static std::vector< quest_definition * > system_quests
Definition: mapper.cpp:2163
get_elevation_color
static int get_elevation_color(int elevation, gdImagePtr elevationmap)
Definition: mapper.cpp:711
reset_groups
static std::set< std::string > reset_groups
Definition: mapper.cpp:262
region::msg
char * msg
Definition: map.h:281
init_readable
void init_readable(void)
Definition: readable.cpp:904
make_face_from_files.str
str
Definition: make_face_from_files.py:30
S_MAX
#define S_MAX
Definition: mapper.cpp:391
quest_callback
static void quest_callback(const quest_definition *quest, void *)
Definition: mapper.cpp:2165
readdir
struct dirent * readdir(DIR *)
python_init.path
path
Definition: python_init.py:8
LOCKED_DOOR
@ LOCKED_DOOR
Definition: object.h:128
struct_race::name
char * name
Definition: mapper.cpp:255
dump
Definition: quest.cpp:847
is_slaying
static int is_slaying(object *item)
Definition: mapper.cpp:1375
struct_equipment::power
int power
Definition: mapper.cpp:244
create_race_array
static nlohmann::json create_race_array(struct_race_list &list)
Definition: mapper.cpp:2241
account_char_load
Account_Chars * account_char_load(const char *)
Definition: mapper.cpp:3410
dragon_ability_gain
void dragon_ability_gain(object *, int, int)
Definition: mapper.cpp:3321
nlohmann::basic_json::array
array_t * array
array (stored with pointer to save storage)
Definition: json.hpp:18360
SPECIAL_KEY
@ SPECIAL_KEY
Definition: object.h:129
inja::json
nlohmann::json json
Definition: inja.hpp:1565
object_update_speed
void object_update_speed(object *op)
Definition: object.cpp:1349
struct_race::origin
struct_map_list origin
Definition: mapper.cpp:257
color_slowing
static int color_slowing
Definition: mapper.cpp:374
Ice.b
b
Definition: Ice.py:48
object::type
uint8_t type
Definition: object.h:348
struct_map_info::quests
struct_map_in_quest_list quests
Definition: mapper.cpp:219
write_world_map
static void write_world_map(void)
Definition: mapper.cpp:1742
FLAG_DAMNED
#define FLAG_DAMNED
Definition: define.h:317
struct_map_info::width
int width
Definition: mapper.cpp:230
add_map_to_quest
static void add_map_to_quest(struct_map_info *map, const char *name, const char *description)
Definition: mapper.cpp:963
create_npc_info
static struct_npc_info * create_npc_info(const object *npc)
Definition: mapper.cpp:1133
face_info::data
uint8_t * data
Definition: image.h:11
color_road
static int color_road
Definition: mapper.cpp:372
tileset
static int tileset
Definition: mapper.cpp:320
esrv_update_item
void esrv_update_item(int, object *, object *)
Definition: mapper.cpp:3334
object_free
void object_free(object *ob, int flags)
Definition: object.cpp:1592
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
is_blocking
static int is_blocking(object *item)
Definition: mapper.cpp:697
do_exit_map
static void do_exit_map(mapstruct *map)
Definition: mapper.cpp:726
create_destination
static void create_destination(void)
Definition: mapper.cpp:2983
struct_map_info::tiled_y_from
int tiled_y_from
Definition: mapper.cpp:231
struct_race_list::races
struct struct_race ** races
Definition: mapper.cpp:190
disinfect.count
int count
Definition: disinfect.py:7
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
check_slaying_inventory
static void check_slaying_inventory(struct_map_info *map, object *item)
Definition: mapper.cpp:1459
say.max
dictionary max
Definition: say.py:148
archetype
Definition: object.h:483
jpeg_quality
static int jpeg_quality
Definition: mapper.cpp:345
sproto.h
append_map_list
static void append_map_list(struct_map_list &dest, struct_map_list &src)
Definition: mapper.cpp:2339
struct_map_info::npcs
npc_list * npcs
Definition: mapper.cpp:226
IS_SHIELD
#define IS_SHIELD(op)
Definition: define.h:170
logfile
FILE * logfile
Definition: init.cpp:114
BOOK
@ BOOK
Definition: object.h:119
rawmaps
static int rawmaps
Definition: mapper.cpp:348
init_struct_map_in_quest_list
static void init_struct_map_in_quest_list(struct_map_in_quest_list *list)
Definition: mapper.cpp:898
struct_race_list
Definition: mapper.cpp:189
struct_race
Definition: mapper.cpp:254
emergency_save
void emergency_save(int)
Definition: mapper.cpp:3312
delete_map
void delete_map(mapstruct *m)
Definition: map.cpp:1696
struct_race_list::allocated
size_t allocated
Definition: mapper.cpp:192
struct_map_list::maps
struct struct_map_info ** maps
Definition: mapper.cpp:204
RING
@ RING
Definition: object.h:190
struct_race_list::count
size_t count
Definition: mapper.cpp:191
fill_json
static void fill_json(nlohmann::json &json)
Definition: mapper.cpp:2364
add_map_to_region
static void add_map_to_region(struct_map_info *map, region *reg)
Definition: mapper.cpp:1308
image.h
struct_map_info::level
int level
Definition: mapper.cpp:216
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.cpp:2100
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
list_system_quests
static bool list_system_quests
Definition: mapper.cpp:322
generate_pics
static int generate_pics
Definition: mapper.cpp:310
MAP_WIDTH
#define MAP_WIDTH(m)
Definition: map.h:73
create_map_object
static nlohmann::json create_map_object(struct_map_info *map, const std::string &key)
Definition: mapper.cpp:2281
struct_quest::mainmap
struct_map_info * mainmap
Definition: mapper.cpp:888
env
static std::shared_ptr< inja::Environment > env
Definition: mapper.cpp:2171
MAX_BUF
#define MAX_BUF
Definition: define.h:35
S_KEY
#define S_KEY
Definition: mapper.cpp:387
sort_map_info
static int sort_map_info(const void *left, const void *right)
Definition: mapper.cpp:852
fill_reverse_maps
static void fill_reverse_maps(struct_map_list &list)
Definition: mapper.cpp:2320
is_valid_faceset
int is_valid_faceset(int fsn)
Definition: image.cpp:117
struct_map_info::tiled_x_from
int tiled_x_from
Definition: mapper.cpp:231
object::head
object * head
Definition: object.h:304
pageToRender
Definition: mapper.cpp:2580
IS_WEAPON
#define IS_WEAPON(op)
Definition: define.h:163
object::move_slow
MoveType move_slow
Definition: object.h:441
sort_slaying
static int sort_slaying(const void *left, const void *right)
Definition: mapper.cpp:2851
tiled_map_list
static struct_map_list tiled_map_list
Definition: mapper.cpp:239
add_race_to_list
static void add_race_to_list(struct_race *race, struct_race_list *list, int check)
Definition: mapper.cpp:285
StringBuffer
Definition: stringbuffer.cpp:25
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
check_equipment
static void check_equipment(object *item, struct_map_info *map)
Definition: mapper.cpp:580
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
EXIT
@ EXIT
Definition: object.h:186
path_stack
static std::vector< std::string > path_stack
Definition: mapper.cpp:2504
merge_tiled_maps
static void merge_tiled_maps(struct_map_info *map, struct_map_info *tiled_map)
Definition: mapper.cpp:1226
cached_pics
static int cached_pics
Definition: mapper.cpp:327
struct_map_list::allocated
size_t allocated
Definition: mapper.cpp:206
list_map
static void list_map(const char *path)
Definition: mapper.cpp:1287
struct_map_info::exits_to
struct_map_list exits_to
Definition: mapper.cpp:218
region
Definition: map.h:272
struct_map_info::lore
char * lore
Definition: mapper.cpp:214
rendered_templates
static std::set< std::string > rendered_templates
Definition: mapper.cpp:2173
apply_auto
int apply_auto(object *op)
Definition: mapper.cpp:3347
check_trigger
int check_trigger(object *op, object *cause)
Definition: button.cpp:518
make_face_from_files.out
out
Definition: make_face_from_files.py:81
quest.h
S_DETECTOR
#define S_DETECTOR
Definition: mapper.cpp:389
struct_map_info::path
char * path
Definition: mapper.cpp:211
struct_map_in_quest_list::count
size_t count
Definition: mapper.cpp:198
object::slaying
sstring slaying
Definition: object.h:327
init_map_list
static void init_map_list(struct_map_list *list)
Definition: mapper.cpp:408
all_regions
std::vector< region * > all_regions
Definition: init.cpp:108
add_region_link
static void add_region_link(mapstruct *source, mapstruct *dest)
Definition: mapper.cpp:1356
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Definition: define.h:246
init_library
void init_library(void)
Definition: init.cpp:324
object::name
sstring name
Definition: object.h:319
free_equipment
static void free_equipment(struct_equipment *equip)
Definition: mapper.cpp:448
esrv_update_spells
void esrv_update_spells(player *)
Definition: mapper.cpp:3337
created_pics
static int created_pics
Definition: mapper.cpp:326
bigchest.check
check
Definition: bigchest.py:10
size_large
#define size_large
Definition: mapper.cpp:314
add_map_to_slaying
static void add_map_to_slaying(struct_slaying_info *info, int item, struct_map_info *map)
Definition: mapper.cpp:1419
struct_region_info::sum
int sum
Definition: mapper.cpp:357
inja::TemplateStorage
std::map< std::string, Template > TemplateStorage
Definition: inja.hpp:2852
struct_map_info::readable
npc_list * readable
Definition: mapper.cpp:227
IS_ARMOR
#define IS_ARMOR(op)
Definition: define.h:166
OF_PNG
@ OF_PNG
Definition: mapper.cpp:331
account_char_free
void account_char_free(Account_Chars *)
Definition: mapper.cpp:3417
struct_region_info::maps_list
struct_map_list maps_list
Definition: mapper.cpp:356
item
Definition: item.py:1
struct_map_info::processed
int processed
Definition: mapper.cpp:231
FIREWALL
@ FIREWALL
Definition: object.h:173
PLAYER_CHANGER
@ PLAYER_CHANGER
Definition: object.h:167
mapstruct
Definition: map.h:313
inja::Arguments
std::vector< const json * > Arguments
Definition: inja.hpp:1567
create_pathname
char * create_pathname(const char *name, char *buf, size_t size)
Definition: map.cpp:104
sstring
const typedef char * sstring
Definition: sstring.h:2
nlohmann::basic_json
a class to store JSON values
Definition: json.hpp:3380
give.op
op
Definition: give.py:33
autojail.value
value
Definition: autojail.py:6
save_picture
static void save_picture(FILE *file, gdImagePtr pic)
Definition: mapper.cpp:1342
create-tower.current_map
current_map
Definition: create-tower.py:7
display_rendered_template
static bool display_rendered_template
Definition: mapper.cpp:323
templates_root
static std::string templates_root("templates/")
FLAG_AUTO_APPLY
#define FLAG_AUTO_APPLY
Definition: define.h:250
quest_definition
Definition: quest.h:37
struct_map_info::monsters
struct_race_list monsters
Definition: mapper.cpp:224
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:266
elevation_info
static int ** elevation_info
Definition: mapper.cpp:376
color_blocking
static int color_blocking
Definition: mapper.cpp:373
struct_map_in_quest::description
char * description
Definition: mapper.cpp:881
get_template
static inja::Template get_template(const std::string &filename)
Definition: mapper.cpp:3004
mapstruct::in_memory
uint32_t in_memory
Definition: map.h:333
convert.dest
dest
Definition: convert.py:25
struct_map_info::tiled_maps
struct_map_list tiled_maps
Definition: mapper.cpp:222
inja.hpp
diamondslots.y
y
Definition: diamondslots.py:16
ext_info_map
void ext_info_map(int, const mapstruct *, uint8_t, uint8_t, const char *str1)
Definition: mapper.cpp:3305
region_count
static size_t region_count
Definition: mapper.cpp:362
command_help
void command_help(object *, const char *)
Definition: mapper.cpp:3420
do_parameters
static void do_parameters(int argc, char **argv)
Definition: mapper.cpp:2901
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
all_data
static nlohmann::json all_data
Definition: mapper.cpp:2172
face_info::datalen
uint16_t datalen
Definition: image.h:12
add_monster
static void add_monster(object *monster, struct_map_info *map)
Definition: mapper.cpp:626
struct_map_in_quest_list::list
struct struct_map_in_quest ** list
Definition: mapper.cpp:197
MAP_HEIGHT
#define MAP_HEIGHT(m)
Definition: map.h:75
struct_quest::number
int number
Definition: mapper.cpp:887
pageToRender::template_name
std::string template_name
Definition: mapper.cpp:2582
struct_map_info::cfregion
region * cfregion
Definition: mapper.cpp:215
get_ob_diff
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Definition: object.cpp:4986
sort_race
static int sort_race(const void *a, const void *b)
Definition: mapper.cpp:648
do_regions_link
static bool do_regions_link
Definition: mapper.cpp:381
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:229
object_give_identified_properties
void object_give_identified_properties(object *op)
Definition: item.cpp:1361
init_race_list
static void init_race_list(struct_race_list *list)
Definition: mapper.cpp:269
create-tower.tile
tile
Definition: create-tower.py:8
process_map
static void process_map(struct_map_info *info)
Definition: mapper.cpp:1499
quests_allocated
static int quests_allocated
Definition: mapper.cpp:896
strcasecmp
int strcasecmp(const char *s1, const char *s2)
castle_read.key
key
Definition: castle_read.py:64
npc_dialog.npc
npc
Definition: npc_dialog.py:98
find_skill_by_number
object * find_skill_by_number(object *, int)
Definition: mapper.cpp:3327
sizes
static int sizes[]
Definition: mapper.cpp:312
account_logout
void account_logout(const char *)
Definition: mapper.cpp:3423
reverse_regions
static std::map< region *, std::string > reverse_regions
Definition: mapper.cpp:2175
get_region_by_map
region * get_region_by_map(mapstruct *m)
Definition: region.cpp:72
S_DOOR
#define S_DOOR
Definition: mapper.cpp:386
create_tiled_map
static struct_map_info * create_tiled_map(void)
Definition: mapper.cpp:1210
world_map
static int world_map
Definition: mapper.cpp:318
templates
static std::vector< std::string > templates
Definition: mapper.cpp:2621
ignore_path
static const char * ignore_path[]
Definition: mapper.cpp:2716
Account_Chars
Definition: account_char.h:27
struct_map_list::count
size_t count
Definition: mapper.cpp:205
slaying_count
static size_t slaying_count
Definition: mapper.cpp:400
player_get_delayed_buffer
SockList * player_get_delayed_buffer(player *)
Definition: mapper.cpp:3402
add_template_to_render
void add_template_to_render(const std::string &template_name, const std::string &output_name, const std::string &param)
Definition: mapper.cpp:2594
object_remove
void object_remove(object *op)
Definition: object.cpp:1833
infomap
static gdImagePtr infomap
Definition: mapper.cpp:369
sort_struct_map_in_quest
static int sort_struct_map_in_quest(const void *left, const void *right)
Definition: mapper.cpp:985
struct_map_info::height
int height
Definition: mapper.cpp:230
ALTAR
@ ALTAR
Definition: object.h:127
struct_npc_info::x
int x
Definition: mapper.cpp:182
relative_path
static void relative_path(const char *from, const char *to, char *result)
Definition: mapper.cpp:783
FLAG_UNPAID
#define FLAG_UNPAID
Definition: define.h:236
dump_unused_maps
static void dump_unused_maps(void)
Definition: mapper.cpp:2781
rod_adjust
void rod_adjust(object *)
Definition: mapper.cpp:3340
sort_region
static int sort_region(const void *left, const void *right)
Definition: mapper.cpp:868
special_equipment
static std::vector< struct_equipment * > special_equipment
Definition: mapper.cpp:250
make_path_to_file
void make_path_to_file(const char *filename)
Definition: porting.cpp:164
FREE_OBJ_FREE_INVENTORY
#define FREE_OBJ_FREE_INVENTORY
Definition: object.h:544
fix_exits_for_map
static void fix_exits_for_map(struct_map_info *current, struct_map_list *from, int is_from)
Definition: mapper.cpp:1932
SCROLL
@ SCROLL
Definition: object.h:226
FLAG_IS_LINKED
#define FLAG_IS_LINKED
Definition: define.h:315
struct_npc_info::name
const char * name
Definition: mapper.cpp:180
object::nrof
uint32_t nrof
Definition: object.h:342
draw_ext_info
void draw_ext_info(int, int, const object *, uint8_t, uint8_t, const char *txt)
Definition: mapper.cpp:3293
split
static std::vector< std::string > split(const std::string &field, const std::string &by)
Definition: mapper.cpp:2609
mapstruct::reset_time
uint32_t reset_time
Definition: map.h:320
say.item
dictionary item
Definition: say.py:149
do_help
static void do_help(const char *program)
Definition: mapper.cpp:2864
artifact
Definition: artifact.h:14
struct_quest::name
char * name
Definition: mapper.cpp:885
nlohmann::basic_json::erase
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:21582
get_faces_count
size_t get_faces_count()
Definition: assets.cpp:293
calc_item_power
int calc_item_power(const object *op)
Definition: item.cpp:235
write_world_info
static void write_world_info(void)
Definition: mapper.cpp:2799
struct_map_in_quest_list::allocated
size_t allocated
Definition: mapper.cpp:199
tiled_map_need_pic
static int tiled_map_need_pic(struct_map_info *map)
Definition: mapper.cpp:2006
face_sets
Definition: image.h:17
SPELL
@ SPELL
Definition: object.h:219
map_limit
static int map_limit
Definition: mapper.cpp:316
replace.current
current
Definition: replace.py:64
closedir
int closedir(DIR *)
quests
static struct_quest ** quests
Definition: mapper.cpp:892
guildbuy.temp
def temp
Definition: guildbuy.py:26
fix_tiled_map
static void fix_tiled_map(void)
Definition: mapper.cpp:1863
FLAG_CURSED
#define FLAG_CURSED
Definition: define.h:316
output_format_type
output_format_type
Definition: mapper.cpp:330
TELEPORTER
@ TELEPORTER
Definition: object.h:146
pics_allocated
static int pics_allocated
Definition: mapper.cpp:307
struct_equipment
Definition: mapper.cpp:242
face_sets::faces
face_info * faces
Definition: image.h:26
SockList
Definition: newclient.h:684
IS_ARROW
#define IS_ARROW(op)
Definition: define.h:178
SPELLBOOK
@ SPELLBOOK
Definition: object.h:208
found_maps
static std::vector< char * > found_maps
Definition: mapper.cpp:366
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
takeitem.status
status
Definition: takeitem.py:38
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.cpp:263
find_player_partial_name
player * find_player_partial_name(const char *)
Definition: mapper.cpp:3406
find_map_by_key
static struct_map_info * find_map_by_key(const std::string &key)
Definition: mapper.cpp:2182
warn_no_path
static int warn_no_path
Definition: mapper.cpp:351
find_quest_info
static struct_quest * find_quest_info(const char *name)
Definition: mapper.cpp:917
DETECTOR
@ DETECTOR
Definition: object.h:154
find_maps
static void find_maps(const char *from)
Definition: mapper.cpp:2741
struct_slaying_info::slaying
char * slaying
Definition: mapper.cpp:395
ring_occidental_mages.r
r
Definition: ring_occidental_mages.py:6
is_road
static int is_road(object *item)
Definition: mapper.cpp:661
elevation_min
static int elevation_min
Definition: mapper.cpp:377
color_linked_exit
static int color_linked_exit
Definition: mapper.cpp:371
sort_equipment
static bool sort_equipment(const struct_equipment *l, const struct_equipment *r)
Definition: mapper.cpp:462
add_one_item
static void add_one_item(object *item, struct_map_info *map)
Definition: mapper.cpp:506
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Definition: define.h:261
give.name
name
Definition: give.py:27
pageToRender::output_name
std::string output_name
Definition: mapper.cpp:2583
identify
object * identify(object *op)
Definition: item.cpp:1426