Crossfire Server, Trunk  R20513
mapper.c
Go to the documentation of this file.
1 /*
2  * Crossfire map browser generator.
3  *
4  * Author: Nicolas Weeger <nicolas.weeger@laposte.net>, (C) 2006, 2007, 2008.
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 
213 #include <ctype.h>
214 #include <errno.h>
215 #include <stdio.h>
216 #include <stdlib.h>
217 #include <string.h>
218 #include <strings.h>
219 #include <sys/stat.h>
220 #include <sys/types.h>
221 #include <time.h>
222 
223 #include "global.h"
224 #include "sproto.h"
225 #include "image.h"
226 
227 #include <gd.h>
228 #include <gdfonts.h>
229 #include <gdfontl.h>
230 #include <gdfontg.h>
231 
232 static gdImagePtr *gdfaces;
233 
235 typedef struct struct_npc_info {
236  const char *name;
237  const char *message;
238  int x, y;
240 
242 typedef struct struct_npc_list {
244  int count;
247 
249 typedef struct struct_race_list {
250  struct struct_race **races;
251  int count;
252  int allocated;
254 
256 typedef struct {
258  int count;
261 
263 typedef struct {
265  int count;
268 
270 typedef struct struct_map_info {
271  char *path;
272  char *name;
273  char *filename;
274  char *lore;
276  int level, pic_was_done, max_monster, min_monster;
280 
282 
284 
287 
289  int height, width;
291  struct struct_map_info *tiles[4];
293 
296 
299 
301 typedef struct struct_equipment {
302  char *name;
303  int power;
305  char *diff;
308 
311 static int equipment_count = 0;
313 static int equipment_allocated = 0;
317 typedef struct struct_race {
318  char *name;
319  int count;
321 } struct_race;
322 
330 static void init_race_list(struct_race_list *list) {
331  list->races = NULL;
332  list->count = 0;
333  list->allocated = 0;
334 }
335 
346 static void add_race_to_list(struct_race *race, struct_race_list *list, int check) {
347  if (check) {
348  int test;
349 
350  for (test = 0; test < list->count; test++) {
351  if (list->races[test] == race)
352  return;
353  }
354  }
355 
356  if (list->allocated == list->count) {
357  list->allocated += 50;
358  list->races = realloc(list->races, sizeof(struct_race *)*list->allocated);
359  }
360  list->races[list->count] = race;
361  list->count++;
362 }
363 
365 static char root[500];
366 
368 static int pics_allocated;
369 
370 /* Options */
371 static int generate_pics = 1;
372 static int force_pics = 0;
373 static int generate_index = 1;
374 static int size_small = 16;
375 static int map_limit = -1;
376 static int show_maps = 0;
377 static int world_map = 1;
378 static int world_exit_info = 1;
379 static int tileset = 0;
381 static char *world_template;
382 static char *world_row_template;
383 static char *world_map_template;
385 static char *map_template;
386 static char *map_no_exit_template;
388 static char *map_exit_template;
391 static char *map_exit_to_template;
392 static char *map_lore_template;
393 static char *map_no_lore_template;
400 static char *index_template;
401 static char *index_letter;
402 static char *index_map;
404 static char *region_template;
406 static char *region_map_template;
408 static char *index_region_template;
411 static char *level_template;
412 static char *level_value_template;
413 static char *level_map_template;
414 
415 static char *index_quest_template;
416 static char *quest_template;
417 static char *quest_map_template;
418 
422 
424 static int created_pics = 0;
425 static int cached_pics = 0;
429  OF_PNG = 0,
430  OF_JPG = 1
431 };
432 
434 static const char *output_extensions[] = {
435  ".png",
436  ".jpg"
437 };
438 
441 
443 static int jpeg_quality = -1;
444 
446 static int rawmaps = 0;
447 
449 static int warn_no_path = 0;
450 
452 typedef struct struct_region_info {
455  int sum_x, sum_y, sum;
456  int is_world;
458 
459 static struct struct_region_info **regions = NULL;
460 static int region_count = 0;
461 static int region_allocated = 0;
463 static int list_unused_maps = 0;
464 static char **found_maps = NULL;
465 static int found_maps_count = 0;
466 static int found_maps_allocated = 0;
468 /* Path/exit info */
469 static gdImagePtr infomap;
471 static int color_linked_exit;
472 static int color_road;
473 static int color_blocking;
474 static int color_slowing;
476 static int **elevation_info;
477 static int elevation_min;
478 static int elevation_max;
480 /* Links between regions */
481 static int do_regions_link = 0;
482 static char **regions_link;
483 static int regions_link_count = 0;
484 static int regions_link_allocated = 0;
485 
487 #define S_DOOR 0
488 #define S_KEY 1
489 #define S_CONTAINER 2
490 #define S_DETECTOR 3
491 #define S_CONNECT 4
492 #define S_MAX 5
493 
495 typedef struct {
496  char *slaying;
499 
501 static int slaying_count = 0;
502 static int slaying_allocated = 0;
509 static void init_map_list(struct_map_list *list) {
510  list->maps = NULL;
511  list->count = 0;
512  list->allocated = 0;
513 }
514 
515 static void add_map(struct_map_info *info, struct_map_list *list);
516 
517 static int is_special_equipment(object *item) {
518  if (item->name == item->arch->clone.name && item->title == item->arch->clone.title)
519  return 0;
520  if (QUERY_FLAG(item, FLAG_NO_PICK))
521  return 0;
522  if (item->move_block == MOVE_ALL)
523  return 0;
524 
525  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))
526  return 1;
527 
528  return 0;
529 }
530 
537  struct_equipment *add = calloc(1, sizeof(struct_equipment));
538 
539  init_map_list(&add->origin);
540  return add;
541 }
542 
549 static void free_equipment(struct_equipment *equip) {
550  free(equip->diff);
551  free(equip->name);
552  free(equip);
553 }
554 
564  int check;
565  struct_equipment *comp;
566 
567  for (check = 0; check < equipment_count; check++) {
568  comp = special_equipment[check];
569 
570  if (strcmp(comp->name, item->name))
571  continue;
572  if (comp->power != item->power)
573  continue;
574  if (comp->calc_power != item->calc_power)
575  continue;
576  if (strcmp(comp->diff, item->diff))
577  continue;
578 
579  free_equipment(item);
580  return comp;
581  }
582 
583  if (equipment_count == equipment_allocated) {
584  equipment_allocated += 50;
585  special_equipment = realloc(special_equipment, sizeof(struct_equipment *)*equipment_allocated);
586  }
587  special_equipment[equipment_count] = item;
588  equipment_count++;
589 
590  return item;
591 }
592 
602 static void add_one_item(object *item, struct_map_info *map) {
605  int x, y;
606  sstring name, namepl;
607  uint32_t nrof;
608  object *base;
609 
610  x = item->x;
611  y = item->y;
612  name = item->name;
613  namepl = item->name_pl;
614  nrof = item->nrof;
615 
616  if (item->artifact != NULL) {
617  const artifact *artifact;
618 
619  artifact = find_artifact(item, item->artifact);
620  if (artifact == NULL) {
621  LOG(llevError, "could not find artifact %s [%d] to save data\n", item->artifact, item->type);
622  base = arch_to_object(item->arch);
623  } else {
624  base = arch_to_object(item->arch);
625  give_artifact_abilities(base, artifact->item);
626  }
627  }
628  else {
629  base = arch_to_object(item->arch);
630  }
631 
632  item->x = base->x;
633  item->y = base->y;
634  item->name = base->name;
635  item->name_pl = base->name_pl;
636  item->nrof = base->nrof;
637 
638  if (QUERY_FLAG(item, FLAG_IDENTIFIED) && !QUERY_FLAG(base, FLAG_IDENTIFIED)) {
640  SET_FLAG(base, FLAG_IDENTIFIED);
641  }
642  if (QUERY_FLAG(item, FLAG_UNPAID))
643  SET_FLAG(base, FLAG_UNPAID);
644  get_ob_diff(bf, item, base);
646 
647  add->diff = stringbuffer_finish(bf);
648 
649  item->x = x;
650  item->y = y;
651  item->name = name;
652  item->name_pl = namepl;
653  item->nrof = nrof;
654 
655  if (add->diff == NULL || strcmp(add->diff, "") == 0) {
656  free_equipment(add);
657  return;
658  }
659 
660  add->name = strdup(item->name);
661  add->power = item->item_power;
662  add->calc_power = calc_item_power(item);
663 
664  add = ensure_unique(add);
665  add_map(map, &add->origin);
666 }
667 
676 static void check_equipment(object *item, struct_map_info *map) {
677  if (is_special_equipment(item))
678  add_one_item(item, map);
679 
680  FOR_INV_PREPARE(item, inv)
681  check_equipment(inv, map);
682  FOR_INV_FINISH();
683 }
684 
693 static int sort_equipment(const void *a, const void *b) {
694  const struct_equipment *l = *(const struct_equipment **)a;
695  const struct_equipment *r = *(const struct_equipment **)b;
696  int c = l->power-r->power;
697 
698  if (c)
699  return c;
700  return strcasecmp(l->name, r->name);
701 }
702 
711 static struct_race *get_race(const char *name) {
712  int test;
713  struct_race *item;
714 
715  for (test = 0; test < races.count; test++) {
716  if (strcmp(races.races[test]->name, name) == 0) {
717  races.races[test]->count++;
718  return races.races[test];
719  }
720  }
721 
722  item = calloc(1, sizeof(struct_race));
723  item->name = strdup(name);
724  item->count = 1;
725  init_map_list(&item->origin);
726 
727  add_race_to_list(item, &races, 0);
728 
729  return item;
730 }
731 
740 static void add_monster(object *monster, struct_map_info *map) {
741  struct_race *race;
742 
743  if (monster->head && monster != monster->head)
744  return;
745 
746  map->min_monster = MIN(monster->level, map->min_monster);
747  map->max_monster = MAX(monster->level, map->max_monster);
748 
749  race = get_race(monster->name);
750  add_map(map, &race->origin);
751  add_race_to_list(race, &map->monsters, 1);
752 }
753 
762 static int sort_race(const void *a, const void *b) {
763  const struct_race *l = *(const struct_race **)a;
764  const struct_race *r = *(const struct_race **)b;
765  return strcasecmp(l->name, r->name);
766 }
767 
775 static int is_road(object *item) {
776  int test;
777  /* Archetypes used as roads. */
778  const char *roads[] = {
779  "cobblestones",
780  "flagstone",
781  "ice_stone",
782  "snow",
783  NULL };
784  const char *partial[] = {
785  "dirtroad_",
786  NULL };
787 
788  for (test = 0; partial[test] != NULL; test++) {
789  if (strstr(item->arch->name, partial[test]) != NULL)
790  return 1;
791  }
792 
793  if (!QUERY_FLAG(item, FLAG_IS_FLOOR))
794  return 0;
795 
796  for (test = 0; roads[test] != NULL; test++) {
797  if (strcmp(item->arch->name, roads[test]) == 0)
798  return 1;
799  }
800 
801  return 0;
802 }
803 
811 static int is_blocking(object *item) {
812  return item->move_block == MOVE_ALL ? 1 : 0;
813 }
814 
825 static int get_elevation_color(int elevation, gdImagePtr elevationmap) {
826  if (elevation > 0)
827  return gdImageColorResolve(elevationmap, 200*elevation/elevation_max, 0, 0);
828  else
829  return gdImageColorResolve(elevationmap, 0, 0, 200*elevation/elevation_min);
830 }
831 
840 static void do_exit_map(mapstruct *map) {
841  int tx, ty, x, y;
842  object *test;
843  sstring selevation;
844 
845  if (sscanf(map->path, "/world/world_%d_%d", &x, &y) != 2)
846  return;
847 
848  x -= 100;
849  y -= 100;
850 
851  for (tx = 0; tx < MAP_WIDTH(map); tx++) {
852  for (ty = 0; ty < MAP_HEIGHT(map); ty++) {
853  FOR_MAP_PREPARE(map, tx, ty, item) {
854  test = HEAD(item);
855 
856  if (test->type == EXIT || test->type == TELEPORTER) {
857  if (!test->slaying)
858  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_unlinked_exit);
859  else
860  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_linked_exit);
861  } else if (is_road(test))
862  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_road);
863  else if (is_blocking(test)) {
864  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_blocking);
865  /* can't get on the spot, so no need to go on. */
866  break;
867  } else if (test->move_slow != 0)
868  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_slowing);
869 
870  selevation = object_get_value(item, "elevation");
871  if (selevation) {
872  int32_t elevation = atoi(selevation);
873  elevation_min = MIN(elevation_min, elevation);
874  elevation_max = MAX(elevation_max, elevation);
875  elevation_info[x*50+tx][y*50+ty] = elevation;
876  }
877  } FOR_MAP_FINISH();
878  }
879  }
880 }
881 
882 void do_auto_apply(mapstruct *m);
883 
894 static int sortbyname(const void *a, const void *b) {
895  return (strcmp(*(const char **)a, *(const char **)b));
896 }
897 
908 static char *cat_template(char *source, char *add) {
909  if (!source)
910  return add;
911  source = realloc(source, strlen(source)+strlen(add)+1);
912  strcat(source, add);
913  free(add);
914  return source;
915 }
916 
927 static void read_template(const char *name, char **buffer) {
928  FILE *file;
929  struct stat info;
930 
931  if (stat(name, &info)) {
932  printf("Couldn't stat template %s!\n", name);
933  exit(1);
934  }
935 
936  (*buffer) = calloc(1, info.st_size+1);
937  if (!(*buffer)) {
938  printf("Template %s calloc failed!\n", name);
939  exit(1);
940  }
941 
942  if (info.st_size == 0) {
943  (*buffer)[0] = '\0';
944  return;
945  }
946 
947  file = fopen(name, "rb");
948  if (!file) {
949  printf("Couldn't open template %s!\n", name);
950  free(*buffer);
951  exit(1);
952  }
953  if (fread(*buffer, info.st_size, 1, file) != 1) {
954  printf("Couldn't read template %s!\n", name);
955  free(*buffer);
956  fclose(file);
957  exit(1);
958  }
959  fclose(file);
960 }
961 
979 static char *do_template(const char *template, const char **vars, const char **values) {
980  int count = 0;
981  const char *sharp = template;
982  int maxlen = 0;
983  int var = 0;
984  char *result;
985  char *current_result;
986  const char *end;
987 
988  while ((sharp = strchr(sharp, '#')) != NULL) {
989  sharp++;
990  count++;
991  }
992  if (!count)
993  return strdup(template);
994  if (count%2) {
995  printf("Malformed template, mismatched #!\n");
996  return strdup(template);
997  }
998 
999  while (vars[var] != NULL) {
1000  if (strlen(values[var]) > maxlen)
1001  maxlen = strlen(values[var]);
1002  var++;
1003  }
1004  result = calloc(1, strlen(template)+maxlen*(count/2)+1);
1005  if (!result)
1006  return NULL;
1007  current_result = result;
1008 
1009  sharp = template;
1010  while ((sharp = strchr(sharp, '#')) != NULL) {
1011  end = strchr(sharp+1, '#');
1012  strncpy(current_result, template, sharp-template);
1013  if (end == sharp+1) {
1014  strcat(current_result, "#");
1015  }
1016  else {
1017  current_result = current_result+strlen(current_result);
1018  var = 0;
1019  while (vars[var] != NULL && (strncmp(vars[var], sharp+1, end-sharp-1) || (strlen(vars[var]) != end-sharp-1)))
1020  /* tag must be the same length, else can take a wrong tag */
1021  var++;
1022  if (vars[var] == NULL)
1023  printf("Wrong tag: %s\n", sharp);
1024  else
1025  strcpy(current_result, values[var]);
1026  }
1027  current_result = current_result+strlen(current_result);
1028  sharp = end+1;
1029  template = sharp;
1030  }
1031  strcat(current_result, template);
1032  return result;
1033 }
1034 
1047 static void relative_path(const char *from, const char *to, char *result) {
1048  const char *fslash;
1049  const char *rslash;
1050 
1051  result[0] = '\0';
1052 
1053  fslash = strchr(from+1, '/');
1054  if (!fslash) {
1055  strcpy(result, to+1);
1056  return;
1057  }
1058 
1059  rslash = strchr(to+1, '/');
1060  while (fslash && rslash && (fslash-from == rslash-to) && strncmp(from, to, fslash-from+1) == 0) {
1061  from = fslash+1;
1062  to = rslash+1;
1063  fslash = strchr(fslash+1, '/');
1064  rslash = strchr(rslash+1, '/');
1065  }
1066 
1067  while (fslash) {
1068  strcat(result, "../");
1069  fslash = strchr(fslash+1, '/');
1070  }
1071  if (strlen(result) && result[strlen(result)-1] == '/' && *to == '/')
1072  result[strlen(result)-1] = '\0';
1073  strcat(result, to);
1074 }
1075 
1086 static int sort_mapname(const void *left, const void *right) {
1087  const char *l = *(const char **)left;
1088  const char *r = *(const char **)right;
1089  const char *sl = strrchr(l, '/');
1090  const char *sr = strrchr(r, '/');
1091  int c;
1092 
1093  if (!sl)
1094  sl = l;
1095  if (!sr)
1096  sr = r;
1097  c = strcasecmp(sl, sr);
1098  if (c)
1099  return c;
1100 
1101  return strcasecmp(l, r);
1102 }
1103 
1114 static int compare_map_info(const struct_map_info *left, const struct_map_info *right) {
1115  int c;
1116 
1117  if (left->tiled_group)
1118  left = left->tiled_group;
1119  if (right->tiled_group)
1120  right = right->tiled_group;
1121 
1122  c = strcasecmp(left->name, right->name);
1123  if (c)
1124  return c;
1125 
1126  return strcasecmp(left->path, right->path);
1127 }
1128 
1139 static int sort_map_info(const void *left, const void *right) {
1140  const struct_map_info *l = *(const struct_map_info **)left;
1141  const struct_map_info *r = *(const struct_map_info **)right;
1142  return compare_map_info(l, r);
1143 }
1144 
1155 static int sort_map_info_by_level(const void *left, const void *right) {
1156  const struct_map_info *l = *(const struct_map_info **)left;
1157  const struct_map_info *r = *(const struct_map_info **)right;
1158  int c = l->level-r->level;
1159  if (c)
1160  return c;
1161  return compare_map_info(l, r);
1162 }
1163 
1174 static int sort_region(const void *left, const void *right) {
1175  return strcmp((*((struct_region_info **)left))->reg->name, (*((struct_region_info **)right))->reg->name);
1176 }
1177 
1178 /************************************
1179  Start of quest-related definitions.
1180 ************************************/
1181 
1183 typedef struct struct_map_in_quest {
1185  char *description;
1188 
1190 typedef struct struct_quest {
1191  char *name;
1192  char *description;
1193  int number;
1196 } struct_quest;
1197 
1198 static struct_quest **quests = NULL;
1200 static int quests_count = 0;
1202 static int quests_allocated = 0;
1205  list->list = NULL;
1206  list->count = 0;
1207  list->allocated = 0;
1208 }
1209 
1211  if (list->count == list->allocated) {
1212  list->allocated += 10;
1213  list->list = realloc(list->list, sizeof(struct_map_in_quest *)*list->allocated);
1214  }
1215  list->list[list->count++] = item;
1216 }
1217 
1226 static struct_quest *get_quest_info(const char *name) {
1227  int test;
1228  struct_quest *add;
1229 
1230  for (test = 0; test < quests_count; test++) {
1231  if (strcmp(quests[test]->name, name) == 0)
1232  return quests[test];
1233  }
1234 
1235  if (quests_count == quests_allocated) {
1236  quests_allocated += 10;
1237  quests = realloc(quests, sizeof(struct_quest *)*quests_allocated);
1238  }
1239  add = calloc(1, sizeof(struct_quest));
1240  add->name = strdup(name);
1241  add->number = quests_count;
1243  quests[quests_count] = add;
1244  quests_count++;
1245  return add;
1246 }
1247 
1258 static void add_map_to_quest(struct_map_info *map, const char *name, const char *description) {
1259  struct_map_in_quest *add;
1260  struct_quest *quest = get_quest_info(name);
1261 
1262  add = calloc(1, sizeof(struct_map_in_quest));
1263  add->map = map;
1264  add->quest = quest;
1265  add->description = strdup(description);
1266  while (strlen(add->description) && add->description[strlen(add->description)-1] == '\n')
1267  add->description[strlen(add->description)-1] = '\0';
1268  add_to_struct_map_in_quest_list(&quest->maps, add);
1270 }
1271 
1280 static int sort_struct_map_in_quest(const void *left, const void *right) {
1281  int c;
1282 
1283  const struct_map_in_quest *l = *(const struct_map_in_quest **)left;
1284  const struct_map_in_quest *r = *(const struct_map_in_quest **)right;
1285  const struct_map_info *ml = l->map;
1286  const struct_map_info *mr = r->map;
1287 
1288  if (ml->tiled_group)
1289  ml = ml->tiled_group;
1290  if (mr->tiled_group)
1291  mr = mr->tiled_group;
1292 
1293  c = strcasecmp(ml->name, mr->name);
1294  if (c)
1295  return c;
1296 
1297  return strcasecmp(ml->path, mr->path);
1298 }
1299 
1310 static void define_quest(const char *name, struct_map_info *mainmap, const char *description) {
1311  struct_quest *quest = get_quest_info(name);
1312 
1313  if (quest->description || quest->mainmap) {
1314  printf("warning, multiple quest definition for %s, found in %s and %s.\n", quest->name, quest->mainmap ? quest->mainmap->path : "(unknown map)", mainmap->path);
1315  return;
1316  }
1317  quest->description = strdup(description);
1318  while (strlen(quest->description) && quest->description[strlen(quest->description)-1] == '\n')
1319  quest->description[strlen(quest->description)-1] = '\0';
1320  quest->mainmap = mainmap;
1321 }
1322 
1330  char *start, *end, *next;
1331  char name[500];
1332  char description[500];
1333 
1334  start = strstr(map->lore, "@def");
1335  while (start) {
1336  description[0] = '\0';
1337  /* find name */
1338  end = strstr(start, "\n");
1339  if (end) {
1340  strncpy(name, start+5, end-start-5);
1341  name[end-start-5] = '\0';
1342  next = end+1;
1343  end = strstr(next, "@end");
1344  if (end) {
1345  strncpy(description, next, end-next);
1346  description[end-next] = '\0';
1347  /* need to erase the text. */
1348  memcpy(start, end+4, strlen(map->lore)-(end-start+3));
1349  end = start;
1350  }
1351  else {
1352  strcpy(description, next);
1353  *start = '\0';
1354  end = NULL;
1355  }
1356  } else {
1357  strcpy(name, start);
1358  *start = '\0';
1359  end = NULL;
1360  }
1361 
1362  define_quest(name, map, description);
1363  start = end ? strstr(end, "@def") : NULL;
1364  }
1365 
1366  start = strstr(map->lore, "@quest");
1367  while (start) {
1368  description[0] = '\0';
1369  /* find name */
1370  end = strstr(start, "\n");
1371  if (end) {
1372  strncpy(name, start+7, end-start-7);
1373  name[end-start-7] = '\0';
1374  next = end+1;
1375  end = strstr(next, "@end");
1376  if (end) {
1377  strncpy(description, next, end-next);
1378  description[end-next] = '\0';
1379  /* need to erase the text. */
1380  memcpy(start, end+4, strlen(map->lore)-(end-start+3));
1381  end = start;
1382  }
1383  else {
1384  strcpy(description, next);
1385  *start = '\0';
1386  end = NULL;
1387  }
1388  } else {
1389  strcpy(name, start);
1390  *start = '\0';
1391  end = NULL;
1392  }
1393 
1394  add_map_to_quest(map, name, description);
1395  start = end ? strstr(end, "@quest") : NULL;
1396  }
1397 }
1398 
1402 static void write_quests_page(void) {
1403  int quest, map;
1404  FILE *out;
1405  char path[500];
1406  char mappath[500];
1407  char mainmappath[500];
1408  char questid[500];
1409  const char *map_vars[] = { "MAPPATH", "MAPNAME", "MAPTEXT", NULL };
1410  const char *map_vals[] = { mappath, NULL, NULL, NULL };
1411  const char *quest_vars[] = { "QUESTNAME", "QUESTTEXT", "QUESTMAPS", "QUESTID", "MAINMAPPATH", "MAINMAPNAME", NULL };
1412  const char *quest_vals[] = { NULL, NULL, NULL, questid, mainmappath, NULL, NULL };
1413  const char *idx_vars[] = { "QUESTS", NULL };
1414  const char *idx_vals[] = { NULL, NULL };
1415  char *text_map = NULL;
1416  char *text_quest = NULL;
1417  char *text_idx = NULL;
1418 
1419  printf("Writing quest index...");
1420 
1421  for (quest = 0; quest < quests_count; quest++) {
1422  qsort(quests[quest]->maps.list, quests[quest]->maps.count, sizeof(struct_map_in_quest *), sort_struct_map_in_quest);
1423  for (map = 0; map < quests[quest]->maps.count; map++) {
1424  snprintf(mappath, sizeof(mappath), "%s.html", quests[quest]->maps.list[map]->map->path+1);
1425  map_vals[1] = quests[quest]->maps.list[map]->map->name;
1426  map_vals[2] = quests[quest]->maps.list[map]->description ? quests[quest]->maps.list[map]->description : "(no description)";
1427  text_map = cat_template(text_map, do_template(quest_map_template, map_vars, map_vals));
1428  }
1429  if (!text_map)
1430  text_map = strdup("");
1431 
1432  quest_vals[0] = quests[quest]->name;
1433  quest_vals[1] = quests[quest]->description ? quests[quest]->description : "(main map not processed)";
1434  quest_vals[2] = text_map;
1435  snprintf(questid, sizeof(questid), "quest_%d", quests[quest]->number);
1436  if (quests[quest]->mainmap) {
1437  snprintf(mainmappath, sizeof(mainmappath), "%s.html", quests[quest]->mainmap->path+1);
1438  quest_vals[5] = quests[quest]->mainmap->name;
1439  } else {
1440  snprintf(mainmappath, sizeof(mainmappath), "#");
1441  quest_vals[5] = "";
1442  }
1443  text_quest = cat_template(text_quest, do_template(quest_template, quest_vars, quest_vals));
1444  free(text_map);
1445  text_map = NULL;
1446  }
1447 
1448  if (!text_quest)
1449  text_quest = strdup("No quest.");
1450 
1451  idx_vals[0] = text_quest;
1452  text_idx = do_template(index_quest_template, idx_vars, idx_vals);
1453  free(text_quest);
1454 
1455  snprintf(path, sizeof(path), "%s/quests.html", root);
1456  out = fopen(path, "w+");
1457  fprintf(out, "%s", text_idx);
1458  fclose(out);
1459  free(text_idx);
1460 
1461  printf(" done.\n");
1462 }
1463 
1464 /************************************
1465  End of quest-related definitions.
1466 ************************************/
1467 
1468 /*********
1469 NPC-related stuff
1470 ********/
1471 
1477 static void init_npc_list(struct_npc_list *list) {
1478  list->allocated = 0;
1479  list->count = 0;
1480  list->npc = NULL;
1481 }
1482 
1490 static struct_npc_info *create_npc_info(const object *npc) {
1491  struct_npc_info *info = calloc(1, sizeof(struct_npc_info));
1492 
1493  info->name = strdup(npc->name);
1494  info->message = strdup(npc->msg);
1495  info->x = npc->x;
1496  info->y = npc->y;
1497 
1498  return info;
1499 }
1500 
1508 static void add_npc_to_map(struct_npc_list *list, const object *npc) {
1509  if (list->count == list->allocated) {
1510  list->allocated += 50;
1511  list->npc = realloc(list->npc, list->allocated*sizeof(struct_npc_info *));
1512  }
1513 
1514  list->npc[list->count] = create_npc_info(npc);
1515  list->count++;
1516 }
1517 /* end of NPC stuff */
1518 
1530 static void add_map(struct_map_info *info, struct_map_list *list) {
1531  int map;
1532 
1533  for (map = 0; map < list->count; map++)
1534  if (list->maps[map] == info)
1535  return;
1536 
1537  if (list->count == list->allocated) {
1538  list->allocated += 50;
1539  list->maps = realloc(list->maps, list->allocated*sizeof(struct_map_info *));
1540  }
1541  list->maps[list->count] = info;
1542  list->count++;
1543 }
1544 
1552  struct_map_info *add = calloc(1, sizeof(struct_map_info));
1553 
1554  add->min_monster = 2000;
1555  init_map_list(&add->exits_to);
1556  init_map_list(&add->exits_from);
1557  init_map_list(&add->tiled_maps);
1559  init_race_list(&add->monsters);
1560  init_npc_list(&add->npcs);
1561  init_npc_list(&add->readable);
1562  add->tiled_group = NULL;
1563 
1564  return add;
1565 }
1566 
1575 
1576  add_map(add, &tiled_map_list);
1577  return add;
1578 }
1579 
1591 static void merge_tiled_maps(struct_map_info *map, int tile, struct_map_info *tiled_map) {
1592  int g;
1593  struct_map_info *group = tiled_map->tiled_group;
1594  struct_map_info *change;
1595 
1596  while (group->tiled_maps.count > 0) {
1597  change = group->tiled_maps.maps[group->tiled_maps.count-1];
1598  change->tiled_group = map->tiled_group;
1599  add_map(change, &map->tiled_group->tiled_maps);
1600  group->tiled_maps.count--;
1601  }
1602 
1603  for (g = 0; g < tiled_map_list.count; g++) {
1604  if (tiled_map_list.maps[g] == group) {
1605  if (g < tiled_map_list.count-1)
1606  tiled_map_list.maps[g] = tiled_map_list.maps[tiled_map_list.count-1];
1607  tiled_map_list.count--;
1608  free(group);
1609  return;
1610  }
1611  }
1612  printf("tiled_map not in tiled_map_list!");
1613  abort();
1614 
1615 }
1616 
1625 static struct_map_info *get_map_info(const char *path) {
1626  int map;
1627  struct_map_info *add;
1628  char *tmp;
1629 
1630  for (map = 0; map < maps_list.count; map++) {
1631  if (strcmp(maps_list.maps[map]->path, path) == 0)
1632  return maps_list.maps[map];
1633  }
1634 
1635  add = create_map_info();
1636  add->path = strdup(path);
1637  tmp = strrchr(path, '/');
1638  if (tmp)
1639  add->filename = strdup(tmp+1);
1640  else
1641  add->filename = strdup(path);
1642 
1643  add_map(add, &maps_list);
1644  return add;
1645 }
1646 
1653 static void list_map(const char *path) {
1654  int index;
1655 
1656  for (index = 0; index < found_maps_count; index++) {
1657  if (found_maps[index] && strcmp(path, found_maps[index]) == 0) {
1658  free(found_maps[index]);
1659  found_maps[index] = NULL;
1660  return;
1661  }
1662  }
1663  printf("Map processed but not found in directory reading? %s\n", path);
1664 }
1665 
1676 static void add_map_to_region(struct_map_info *map, region *reg) {
1677  int test;
1678  int x, y;
1679 
1680  for (test = 0; test < region_count; test++) {
1681  if (regions[test]->reg == reg)
1682  break;
1683  }
1684  if (test == region_count) {
1685  if (test == region_allocated) {
1686  region_allocated++;
1687  regions = realloc(regions, sizeof(struct_region_info *)*region_allocated);
1688  regions[test] = calloc(1, sizeof(struct_region_info));
1689  }
1690  region_count++;
1691  regions[test]->reg = reg;
1692  }
1693  add_map(map, &regions[test]->maps_list);
1694  if (sscanf(map->path, "/world/world_%d_%d", &x, &y) == 2) {
1695  regions[test]->sum_x += (x-100);
1696  regions[test]->sum_y += (y-100);
1697  regions[test]->sum++;
1698  regions[test]->is_world = 1;
1699  }
1700 }
1701 
1710 static void save_picture(FILE *file, gdImagePtr pic) {
1711  if (output_format == OF_PNG)
1712  gdImagePng(pic, file);
1713  else
1714  gdImageJpeg(pic, file, jpeg_quality);
1715 }
1716 
1726 static void add_region_link(mapstruct *source, mapstruct *dest, const char *linkname) {
1727  int search = 0;
1728  char entry[500];
1729  region *s, *d;
1730 
1731  s = get_region_by_map(source);
1732  d = get_region_by_map(dest);
1733  if (s == d)
1734  return;
1735 
1736  if (linkname && 0)
1737  snprintf(entry, sizeof(entry), "%s -> %s [ label = \"%s\" ]\n", s->name, d->name, linkname);
1738  else
1739  snprintf(entry, sizeof(entry), "%s -> %s\n", s->name, d->name);
1740 
1741  for (search = 0; search < regions_link_count; search++) {
1742  if (strcmp(regions_link[search], entry) == 0)
1743  return;
1744  }
1745 
1746  if (regions_link_count == regions_link_allocated) {
1747  regions_link_allocated += 10;
1748  regions_link = realloc(regions_link, sizeof(const char *)*regions_link_allocated);
1749  }
1751  regions_link_count++;
1752 }
1753 
1762 static int is_slaying(object *item) {
1763  return (item->type == LOCKED_DOOR || item->type == SPECIAL_KEY || item->type == CONTAINER || item->type == CHECK_INV);
1764 }
1765 
1766 
1775 static struct_slaying_info *get_slaying_struct(const char *slaying) {
1776  struct_slaying_info *add;
1777  int l;
1778 
1779  for (l = 0; l < slaying_count; l++) {
1780  if (!strcmp(slaying_info[l]->slaying, slaying))
1781  return slaying_info[l];
1782  }
1783  if (slaying_count == slaying_allocated) {
1784  slaying_allocated += 10;
1785  slaying_info = (struct_slaying_info **)realloc(slaying_info, sizeof(struct_slaying_info *)*slaying_allocated);
1786  }
1787 
1788  add = (struct_slaying_info *)calloc(1, sizeof(struct_slaying_info));
1789  add->slaying = strdup(slaying);
1790  for (l = 0; l < S_MAX; l++)
1791  init_map_list(&add->maps[l]);
1792 
1793  slaying_info[slaying_count] = add;
1794  slaying_count++;
1795 
1796  return add;
1797 }
1798 
1809 static void add_map_to_slaying(struct_slaying_info *info, int item, struct_map_info *map) {
1810  add_map(map, &info->maps[item]);
1811 }
1812 
1821 static void add_slaying(struct_map_info *map, object *item) {
1822  struct_slaying_info *info;
1823 
1824  if (!item->slaying)
1825  /* can be undefined */
1826  return;
1827 
1828  info = get_slaying_struct(item->slaying);
1829  if (item->type == LOCKED_DOOR)
1830  add_map_to_slaying(info, S_DOOR, map);
1831  else if (item->type == SPECIAL_KEY)
1832  add_map_to_slaying(info, S_KEY, map);
1833  else if (item->type == CONTAINER)
1834  add_map_to_slaying(info, S_CONTAINER, map);
1835  else
1836  add_map_to_slaying(info, S_CONNECT, map);
1837 }
1838 
1847 static void check_slaying_inventory(struct_map_info *map, object *item) {
1848  FOR_INV_PREPARE(item, inv) {
1849  if (is_slaying(inv))
1850  add_slaying(map, inv);
1851  check_slaying_inventory(map, inv);
1852  } FOR_INV_FINISH();
1853 }
1854 
1863 static void process_map(struct_map_info *info) {
1864  mapstruct *m;
1865  int x, y, isworld;
1866  FILE *out;
1867  gdImagePtr pic;
1868  gdImagePtr small;
1869  struct stat stats;
1870  struct stat statspic;
1871  char exit_path[500];
1872  char tmppath[MAX_BUF];
1873  char picpath[MAX_BUF], smallpicpath[MAX_BUF];
1874  int needpic = 0;
1875  struct_map_info *link;
1876 
1877  if (list_unused_maps)
1878  list_map(info->path);
1879 
1880  if (show_maps)
1881  printf(" processing map %s\n", info->path);
1882 
1883  m = ready_map_name(info->path, 0);
1884  if (!m) {
1885  printf("couldn't load map %s\n", info->path);
1886  return;
1887  }
1888 
1889  do_exit_map(m);
1890 
1891  if (!rawmaps)
1892  do_auto_apply(m);
1893 
1894  info->level = m->difficulty;
1895  if (m->maplore) {
1896  info->lore = strdup(m->maplore);
1897  process_map_lore(info);
1898  }
1899 
1900  isworld = (sscanf(info->path, "/world/world_%d_%d", &x, &y) == 2);
1901 
1902  if (m->name)
1903  info->name = strdup(m->name);
1904  else
1905  info->name = strdup(info->filename);
1906 
1907  info->cfregion = get_region_by_map(m);
1908  add_map_to_region(info, info->cfregion);
1909 
1910  snprintf(picpath, sizeof(picpath), "%s%s%s", root, info->path, output_extensions[output_format]);
1911  snprintf(smallpicpath, sizeof(smallpicpath), "%s%s.small%s", root, info->path, output_extensions[output_format]);
1912 
1913  if (force_pics)
1914  needpic = 1;
1915  else if (generate_pics) {
1916  create_pathname(info->path, tmppath, MAX_BUF);
1917  stat(tmppath, &stats);
1918  if (stat(picpath, &statspic) || (statspic.st_mtime < stats.st_mtime))
1919  needpic = 1;
1920  else if (stat(smallpicpath, &statspic) || (statspic.st_mtime < stats.st_mtime))
1921  needpic = 1;
1922  }
1923  else
1924  needpic = 0;
1925 
1926  if (needpic) {
1927  pic = gdImageCreateTrueColor(MAP_WIDTH(m)*32, MAP_HEIGHT(m)*32);
1928  created_pics++;
1929  }
1930  else
1931  cached_pics++;
1932 
1933  for (x = 0; x < 4; x++)
1934  if (m->tile_path[x] != NULL) {
1935  path_combine_and_normalize(m->path, m->tile_path[x], exit_path, sizeof(exit_path));
1936  create_pathname(exit_path, tmppath, MAX_BUF);
1937  if (stat(tmppath, &stats)) {
1938  printf(" map %s doesn't exist in map %s, for tile %d.\n", exit_path, info->path, x);
1939  }
1940 
1941  if (isworld) {
1942  link = get_map_info(exit_path);
1943  add_map(link, &info->exits_from);
1944  add_map(info, &link->exits_to);
1945 
1946  if (do_regions_link) {
1947  mapstruct *link = ready_map_name(exit_path, 0);
1948 
1949  if (link && link != m) {
1950  /* no need to link a map with itself. Also, if the exit points to the same map, we don't
1951  * want to reset it. */
1952  add_region_link(m, link, NULL);
1953  link->reset_time = 1;
1954  link->in_memory = MAP_IN_MEMORY;
1955  delete_map(link);
1956  }
1957  }
1958  } else {
1959  link = get_map_info(exit_path);
1960  info->tiles[x] = link;
1961  if (link->tiled_group) {
1962  if (info->tiled_group && link->tiled_group != info->tiled_group) {
1963  merge_tiled_maps(info, x, link);
1964  continue;
1965  }
1966  if (link->tiled_group == info->tiled_group) {
1967  continue;
1968  }
1969  if (!info->tiled_group) {
1970  add_map(info, &link->tiled_group->tiled_maps);
1971  continue;
1972  }
1973  }
1974 
1975  if (!info->tiled_group) {
1976  info->tiled_group = create_tiled_map();
1977  add_map(info, &info->tiled_group->tiled_maps);
1978  }
1979  link->tiled_group = info->tiled_group;
1980  add_map(link, &info->tiled_group->tiled_maps);
1981  }
1982  }
1983 
1984  info->width = MAP_WIDTH(m);
1985  info->height = MAP_HEIGHT(m);
1986 
1987  for (x = MAP_WIDTH(m)-1; x >= 0; x--)
1988  for (y = MAP_HEIGHT(m)-1; y >= 0; y--) {
1989  FOR_MAP_PREPARE(m, x, y, item) {
1990  if (item->type == EXIT || item->type == TELEPORTER || item->type == PLAYER_CHANGER) {
1991  char ep[500];
1992  const char *start;
1993 
1994  if (!item->slaying) {
1995  ep[0] = '\0';
1996  if (warn_no_path)
1997  printf(" exit without any path at %d, %d on %s\n", item->x, item->y, info->path);
1998  } else {
1999  memset(ep, 0, 500);
2000  if (strcmp(item->slaying, "/!"))
2001  strcpy(ep, EXIT_PATH(item));
2002  else {
2003  if (!item->msg) {
2004  printf(" random map without message in %s at %d, %d\n", info->path, item->x, item->y);
2005  } else {
2006  /* Some maps have a 'exit_on_final_map' flag, ignore it. */
2007  start = strstr(item->msg, "\nfinal_map ");
2008  if (!start && strncmp(item->msg, "final_map", strlen("final_map")) == 0)
2009  /* Message start is final_map, nice */
2010  start = item->msg;
2011  if (start) {
2012  char *end = strchr(start+1, '\n');
2013 
2014  start += strlen("final_map")+2;
2015  strncpy(ep, start, end-start);
2016  }
2017  }
2018  }
2019 
2020  if (strlen(ep)) {
2021  path_combine_and_normalize(m->path, ep, exit_path, 500);
2022  create_pathname(exit_path, tmppath, MAX_BUF);
2023  if (stat(tmppath, &stats)) {
2024  printf(" map %s doesn't exist in map %s, at %d, %d.\n", ep, info->path, item->x, item->y);
2025  } else {
2026  link = get_map_info(exit_path);
2027  add_map(link, &info->exits_from);
2028  add_map(info, &link->exits_to);
2029 
2030  if (do_regions_link) {
2031  mapstruct *link = ready_map_name(exit_path, 0);
2032 
2033  if (link && link != m) {
2034  /* no need to link a map with itself. Also, if the exit points to the same map, we don't
2035  * want to reset it. */
2036  add_region_link(m, link, item->arch->clone.name);
2037  link->reset_time = 1;
2038  link->in_memory = MAP_IN_MEMORY;
2039  delete_map(link);
2040  }
2041  }
2042  }
2043  }
2044  }
2045  } else if (is_slaying(item))
2046  add_slaying(info, item);
2047 
2048  check_equipment(item, info);
2049 
2050  check_slaying_inventory(info, item);
2051 
2052  if (QUERY_FLAG(item, FLAG_MONSTER)) {
2053  /* need to get the "real" archetype, as the item's archetype can certainly be a temporary one. */
2054  archetype *arch = find_archetype(item->arch->name);
2055 
2056  add_monster(item, info);
2057  if ((QUERY_FLAG(item, FLAG_UNAGGRESSIVE) || QUERY_FLAG(item, FLAG_FRIENDLY)) && (item->msg != arch->clone.msg) && (item->msg != NULL))
2058  add_npc_to_map(&info->npcs, item);
2059  } else if ((item->type == SIGN || item->type == BOOK) && (item->msg != item->arch->clone.msg) && (item->msg != NULL)) {
2060  add_npc_to_map(&info->readable, item);
2061  }
2062 
2063  if (item->invisible)
2064  continue;
2065 
2066  if (needpic) {
2067  int sx, sy, hx, hy;
2068 
2069  if (gdfaces[item->face->number] == NULL) {
2070  int set = get_face_fallback(tileset, item->face->number);
2071 
2072  gdfaces[item->face->number] = gdImageCreateFromPngPtr(facesets[set].faces[item->face->number].datalen, facesets[set].faces[item->face->number].data);
2073  pics_allocated++;
2074  }
2075  if (item->head || item->more) {
2076  object_get_multi_size(item, &sx, &sy, &hx, &hy);
2077  } else {
2078  hx = 0;
2079  hy = 0;
2080  }
2081  if (gdfaces[item->face->number] != NULL && ((!item->head && !item->more) || (item->arch->clone.x+hx == 0 && item->arch->clone.y+hy == 0))) {
2082  gdImageCopy(pic, gdfaces[item->face->number], x*32, y*32, 0, 0, gdfaces[item->face->number]->sx, gdfaces[item->face->number]->sy);
2083  }
2084  }
2085  } FOR_MAP_FINISH();
2086  }
2087 
2088  if (needpic) {
2089  make_path_to_file(picpath);
2090  out = fopen(picpath, "wb+");
2091  save_picture(out, pic);
2092  fclose(out);
2093 
2094  small = gdImageCreateTrueColor(MAP_WIDTH(m)*size_small, MAP_HEIGHT(m)*size_small);
2095  gdImageCopyResampled(small, pic, 0, 0, 0, 0, MAP_WIDTH(m)*size_small, MAP_HEIGHT(m)*size_small, MAP_WIDTH(m)*32, MAP_HEIGHT(m)*32);
2096 
2097  out = fopen(smallpicpath, "wb+");
2098  save_picture(out, small);
2099  fclose(out);
2100  gdImageDestroy(small);
2101 
2102  gdImageDestroy(pic);
2103 
2104  info->pic_was_done = 1;
2105  }
2106 
2107  m->reset_time = 1;
2108  m->in_memory = MAP_IN_MEMORY;
2109  delete_map(m);
2110 }
2111 
2132 static char *do_map_index(const char *dest, struct_map_list *maps_list,
2133  const char *template_page, const char *template_letter,
2134  const char *template_map, const char **vars,
2135  const char **values) {
2136 #define VARSADD 6
2137  int map;
2138  char *string;
2139  char mappath[500];
2140  char maphtml[500];
2141  char count[50];
2142  char lettercount[50];
2143  char *tmp;
2144  const char **idx_vars;
2145  const char **idx_values;
2146  char str_letter[2];
2147  char last_letter;
2148  char index_path[500];
2149  char *mapstext = NULL;
2150  int byletter;
2151  int basevalues, realcount = 0;
2152  struct_map_info *last_group = NULL;
2153 
2154  if (!generate_index)
2155  return strdup("");
2156 
2157  if (vars)
2158  for (basevalues = 0; vars[basevalues] != NULL; basevalues++)
2159  ;
2160  else
2161  basevalues = 0;
2162 
2163  idx_vars = malloc(sizeof(char *)*(basevalues+VARSADD));
2164  idx_vars[0] = "MAPCOUNT";
2165  memcpy(&idx_vars[1], vars, sizeof(char *)*basevalues);
2166  idx_vars[basevalues+VARSADD-1] = NULL;
2167 
2168  idx_values = malloc(sizeof(char *)*(basevalues+VARSADD-1));
2169  memcpy(&idx_values[1], values, sizeof(char *)*basevalues);
2170 
2171  string = NULL;
2172 
2173  idx_values[0] = count;
2174  /* wrong value, but in case the template needs to display something... */
2175  snprintf(count, sizeof(count), "%d", maps_list->count);
2176 
2177  idx_vars[basevalues+1] = "MAPNAME";
2178  idx_vars[basevalues+2] = "MAPPATH";
2179  idx_vars[basevalues+3] = "MAPHTML";
2180  idx_vars[basevalues+4] = NULL;
2181 
2182  qsort(maps_list->maps, maps_list->count, sizeof(const char *), sort_map_info);
2183 
2184  last_letter = '\0';
2185  str_letter[0] = '\0';
2186  str_letter[1] = '\0';
2187 
2188  strcpy(index_path, "/");
2189  strcat(index_path, dest);
2190 
2191  string = NULL;
2192  for (map = 0; map < maps_list->count; map++) {
2193  if (tolower(maps_list->maps[map]->name[0]) != last_letter) {
2194  if (mapstext != NULL) {
2195  idx_vars[basevalues+1] = "MAPS";
2196  idx_vars[basevalues+2] = "LETTER";
2197  idx_vars[basevalues+3] = "LETTERCOUNT";
2198  idx_vars[basevalues+4] = NULL;
2199  idx_values[basevalues+1] = mapstext;
2200  idx_values[basevalues+2] = str_letter;
2201  snprintf(lettercount, sizeof(lettercount), "%d", byletter);
2202  idx_values[basevalues+3] = lettercount;
2203  string = cat_template(string, do_template(template_letter, idx_vars, idx_values));
2204  free(mapstext);
2205  mapstext = NULL;
2206  idx_values[basevalues+2] = NULL;
2207  }
2208  last_letter = tolower(maps_list->maps[map]->name[0]);
2209  str_letter[0] = last_letter;
2210  byletter = 0;
2211  last_group = NULL;
2212  }
2213 
2214  if (last_group && last_group == maps_list->maps[map]->tiled_group)
2215  continue;
2216  else
2217  last_group = maps_list->maps[map]->tiled_group;
2218 
2219  realcount++;
2220  idx_vars[basevalues+1] = "MAPNAME";
2221  idx_vars[basevalues+2] = "MAPPATH";
2222  idx_vars[basevalues+3] = "MAPHTML";
2223  idx_values[basevalues+1] = last_group ? last_group->name : (maps_list->maps[map]->name ? maps_list->maps[map]->name : maps_list->maps[map]->path);
2224  relative_path(index_path, last_group ? last_group->path : maps_list->maps[map]->path, mappath);
2225  strcpy(maphtml, mappath);
2226  strcat(maphtml, ".html");
2227  idx_values[basevalues+2] = mappath;
2228  idx_values[basevalues+3] = maphtml;
2229  mapstext = cat_template(mapstext, do_template(template_map, idx_vars, idx_values));
2230  byletter++;
2231  }
2232  if (last_letter != '\0') {
2233  idx_vars[basevalues+1] = "MAPS";
2234  idx_vars[basevalues+2] = "LETTER";
2235  idx_vars[basevalues+3] = "LETTERCOUNT";
2236  idx_vars[basevalues+4] = NULL;
2237  idx_values[basevalues+1] = mapstext;
2238  idx_values[basevalues+2] = str_letter;
2239  snprintf(lettercount, sizeof(lettercount), "%d", byletter);
2240  idx_values[basevalues+3] = lettercount;
2241  string = cat_template(string, do_template(template_letter, idx_vars, idx_values));
2242  free(mapstext);
2243  mapstext = NULL;
2244  idx_values[basevalues+2] = NULL;
2245  }
2246 
2247  snprintf(count, sizeof(count), "%d", realcount);
2248  idx_values[basevalues+1] = string;
2249  idx_vars[basevalues+1] = "LETTERS";
2250  idx_vars[basevalues+2] = NULL;
2251  tmp = do_template(template_page, idx_vars, idx_values);
2252  free(string);
2253  free(idx_vars);
2254  free(idx_values);
2255  return tmp;
2256 }
2257 
2268  char *string;
2269  FILE *index;
2270  char html[500];
2271  const char *vars[] = { "REGIONNAME", "REGIONHTML", "REGIONLONGNAME", "REGIONDESC", NULL };
2272  const char *values[] = { reg->reg->name, html, NULL, NULL };
2273 
2274  printf("Generating map index for region %s...", reg->reg->name);
2275 
2276  values[2] = get_region_longname(reg->reg);
2277  values[3] = get_region_msg(reg->reg);
2278 
2279  strcpy(html, reg->reg->name);
2280  strcat(html, ".html");
2281 
2282  string = do_map_index(html, &reg->maps_list, region_template, region_letter_template, region_map_template, vars, values);
2283 
2284  strcpy(html, root);
2285  strcat(html, "/");
2286  strcat(html, reg->reg->name);
2287  strcat(html, ".html");
2288  index = fopen(html, "w+");
2289  fprintf(index, "%s", string);
2290  fclose(index);
2291  free(string);
2292 
2293  printf(" done.\n");
2294 
2295 }
2296 
2300 static void write_all_regions(void) {
2301  int reg;
2302 
2303  qsort(regions, region_count, sizeof(struct_region_info *), sort_region);
2304 
2305  for (reg = 0; reg < region_count; reg++)
2306  write_region_page(regions[reg]);
2307 }
2308 
2312 static void write_maps_index(void) {
2313  char index_path[500];
2314  char *tmp;
2315  FILE *index;
2316 
2317  printf("Generating global map index in maps.html...");
2318 
2319  tmp = do_map_index("maps.html", &maps_list, index_template, index_letter, index_map, NULL, NULL);
2320 
2321  strcpy(index_path, root);
2322  strcat(index_path, "/maps.html");
2323  index = fopen(index_path, "w+");
2324  fprintf(index, "%s", tmp);
2325  fclose(index);
2326  free(tmp);
2327 
2328  printf(" done.\n");
2329 }
2330 
2334 static void write_region_index(void) {
2335  char *txt;
2336  char *final;
2337  char count[10];
2339  int reg;
2340  char file[500];
2341  const char *vars[] = { "REGIONCOUNT", "REGIONFILE", "REGIONNAME", NULL };
2342  const char *values[] = { count, file, NULL };
2343  FILE *out;
2344 
2345  printf("Generating regions index in regions.html...");
2346 
2347  snprintf(count, sizeof(count), "%d", region_count);
2348  txt = NULL;
2349 
2350  for (reg = 0; reg < region_count; reg++) {
2351  region = regions[reg];
2352  snprintf(file, sizeof(file), "%s.html", region->reg->name);
2353  values[2] = get_region_longname(region->reg);
2354  txt = cat_template(txt, do_template(index_region_region_template, vars, values));
2355  }
2356  vars[1] = "REGIONS";
2357  values[1] = txt;
2358  vars[2] = NULL;
2359  final = do_template(index_region_template, vars, values);
2360  free(txt);
2361 
2362  strcpy(file, root);
2363  strcat(file, "/regions.html");
2364  out = fopen(file, "w+");
2365  fprintf(out, "%s", final);
2366  fclose(out);
2367  free(final);
2368 
2369  printf(" done.\n");
2370 }
2371 
2375 static void write_world_map(void) {
2376 #define SIZE 50
2377  int x, y;
2378  FILE *out;
2379  int wx, wy;
2380  char file[500];
2381  char *map = NULL;
2382  char *total;
2383  char *row = NULL;
2384  char mapleft[10], maptop[10], mapright[10], mapbottom[10];
2385  const char *vars[] = { NULL, NULL, "MAPLEFT", "MAPTOP", "MAPRIGHT", "MAPBOTTOM", NULL };
2386  const char *values[] = { NULL, NULL, mapleft, maptop, mapright, mapbottom, NULL };
2387  char name[100];
2388  char mappath[500], mapraw[500], mapregion[500];
2389  gdImagePtr pic;
2390  gdImagePtr small;
2391  gdFontPtr font;
2392  int region, color;
2393 
2394  if (!world_map)
2395  return;
2396 
2397  printf("Generating world map in world.html...");
2398  fflush(stdout);
2399 
2400  pic = gdImageCreateTrueColor(SIZE*30, SIZE*30);
2401 
2402  strcpy(file, root);
2403  strcat(file, "/world.html");
2404 
2405  wx = 100;
2406  wy = 100;
2407 
2408  for (y = 0; y < 30; y++) {
2409  for (x = 0; x < 30; x++) {
2410  values[0] = name;
2411  vars[0] = "MAPNAME";
2412  vars[1] = "MAPPATH";
2413  values[1] = mappath,
2414  snprintf(name, sizeof(name), "world_%d_%d", wx, wy);
2415  snprintf(mappath, sizeof(mappath), "world/%s.html", name);
2416  snprintf(mapleft, sizeof(mapleft), "%d", SIZE*x);
2417  snprintf(maptop, sizeof(maptop), "%d", SIZE*y);
2418  snprintf(mapright, sizeof(mapright), "%d", SIZE*(x+1)-1);
2419  snprintf(mapbottom, sizeof(mapbottom), "%d", SIZE*(y+1)-1);
2420 
2421  map = cat_template(map, do_template(world_map_template, vars, values));
2422 
2423  snprintf(mappath, sizeof(mappath), "%s/world/%s%s", root, name, output_extensions[output_format]);
2424 
2425  out = fopen(mappath, "rb");
2426  if (!out) {
2427  printf("\n warning: large pic not found for world_%d_%d", wx, wy);
2428  wx++;
2429  continue;
2430  }
2431  if (output_format == OF_PNG)
2432  small = gdImageCreateFromPng(out);
2433  else
2434  small = gdImageCreateFromJpeg(out);
2435  fclose(out);
2436  if (!small) {
2437  printf("\n warning: pic not found for world_%d_%d", wx, wy);
2438  wx++;
2439  continue;
2440  }
2441  gdImageCopyResized(pic, small, SIZE*x, SIZE*y, 0, 0, SIZE, SIZE, small->sx, small->sy);
2442  gdImageDestroy(small);
2443 
2444  wx++;
2445  }
2446  wy++;
2447  wx = 100;
2448  values[0] = map;
2449  vars[0] = "MAPS";
2450  vars[1] = NULL;
2451  row = cat_template(row, do_template(world_row_template, vars, values));
2452  free(map);
2453  map = NULL;
2454  }
2455  snprintf(mappath, sizeof(mappath), "world%s", output_extensions[output_format]);
2456  snprintf(mapraw, sizeof(mapraw), "world_raw%s", output_extensions[output_format]);
2457  snprintf(mapregion, sizeof(mapregion), "world_regions%s", output_extensions[output_format]);
2458 
2459  values[0] = row;
2460  vars[0] = "MAPS";
2461  values[1] = mappath;
2462  vars[1] = "WORLDMAP";
2463  values[2] = mapraw;
2464  vars[2] = "WORLDRAW";
2465  values[3] = mapregion;
2466  vars[3] = "WORLDREGIONS";
2467  vars[4] = NULL;
2468  total = do_template(world_template, vars, values);
2469  free(row);
2470  out = fopen(file, "w+");
2471  fprintf(out, "%s", total);
2472  free(total);
2473  fclose(out);
2474 
2475  snprintf(mappath, sizeof(mappath), "%s/world_raw%s", root, output_extensions[output_format]);
2476  out = fopen(mappath, "wb+");
2477  save_picture(out, pic);
2478  fclose(out);
2479 
2480  /* Write region names. */
2481  small = gdImageCreateTrueColor(SIZE*30, SIZE*30);
2482  font = gdFontGetGiant();
2483  color = gdImageColorAllocateAlpha(pic, 255, 0, 0, 20);
2484  for (region = 0; region < region_allocated; region++) {
2485  if (!regions[region]->is_world || regions[region]->sum == 0)
2486  continue;
2487 
2488  x = regions[region]->sum_x*SIZE/regions[region]->sum+SIZE/2-strlen(regions[region]->reg->name)*font->w/2;
2489  y = regions[region]->sum_y*SIZE/regions[region]->sum+SIZE/2-font->h/2;
2490  gdImageString(small, font, x, y, (unsigned char *)regions[region]->reg->name, color);
2491  gdImageString(pic, font, x, y, (unsigned char *)regions[region]->reg->name, color);
2492 
2493  /* For exit/road map, size isn't the same. */
2494  x = regions[region]->sum_x*50/regions[region]->sum+50/2-strlen(regions[region]->reg->name)*font->w/2;
2495  y = regions[region]->sum_y*50/regions[region]->sum+50/2-font->h/2;
2496  gdImageString(infomap, font, x, y, (unsigned char *)regions[region]->reg->name, color);
2497  }
2498 
2499  snprintf(mappath, sizeof(mappath), "%s/world_regions%s", root, output_extensions[output_format]);
2500  out = fopen(mappath, "wb+");
2501  save_picture(out, small);
2502  fclose(out);
2503  gdImageDestroy(small);
2504 
2505  snprintf(mappath, sizeof(mappath), "%s/world%s", root, output_extensions[output_format]);
2506  out = fopen(mappath, "wb+");
2507  save_picture(out, pic);
2508  fclose(out);
2509  gdImageDestroy(pic);
2510 
2511  printf(" done.\n");
2512 #undef SIZE
2513 }
2514 
2521 static void write_map_page(struct_map_info *map) {
2522  char *exits_text;
2523  char *exits_to;
2524  char *maplore;
2525  char *tmp;
2526  char *quests, *quest;
2527  char *monsters;
2528 
2529  char htmlpath[500]; /* Map file path. */
2530  char mappic[500]; /* Name of map's full size picture. */
2531  char mapsmallpic[500]; /* Name of map's small size picture. */
2532  char indexpath[500]; /* Relative path of full index. */
2533  char regionpath[500]; /* Path to region's filename. */
2534  char regionname[500]; /* Name of map's region. */
2535  char regionindexpath[500]; /* Path to region index file. */
2536  char worldmappath[500]; /* Path to world map. */
2537  char exit_path[500];
2538  char maplevel[5], minmonster[5], maxmonster[5];
2539  FILE *out;
2540  char questpath[500], questtemp[500];
2541  const char *quest_vars[] = { "NAME", "PATH", "TEXT", NULL };
2542  const char *quest_vals[] = { NULL, questpath, NULL, NULL };
2543  const char *q_vars[] = { "QUESTS", NULL };
2544  const char *q_vals[] = { NULL, NULL };
2545  const char *m_vars[] = { "NAME", NULL };
2546  const char *m_vals[] = { NULL, NULL };
2547  const char *vars[] = { "NAME", "MAPPATH", "MAPNAME", "MAPPIC", "MAPSMALLPIC", "MAPEXITFROM", "INDEXPATH", "REGIONPATH", "REGIONNAME", "REGIONINDEXPATH", "WORLDMAPPATH", "MAPLORE", "MAPEXITTO", "MAPLEVEL", "QUESTS", "MONSTERS", "MINMONSTER", "MAXMONSTER", NULL, NULL, NULL };
2548  const char *values[] = { map->path, htmlpath, map->name, mappic, mapsmallpic, "", indexpath, regionpath, regionname, regionindexpath, worldmappath, "", "", maplevel, NULL, "", minmonster, maxmonster, NULL, NULL, NULL };
2549  int vars_count = 0;
2550 
2551  while (vars[vars_count])
2552  vars_count++;
2553 
2554  snprintf(minmonster, sizeof(minmonster), "%d", map->min_monster);
2555  snprintf(maxmonster, sizeof(maxmonster), "%d", map->max_monster);
2556 
2557  relative_path(map->path, "/maps.html", indexpath);
2558  relative_path(map->path, "/world.html", worldmappath);
2559  relative_path(map->path, "/regions.html", regionindexpath);
2560 
2561  if (map->cfregion) {
2562  strcpy(regionname, get_region_longname(map->cfregion));
2563  strcpy(exit_path, "/");
2564  strcat(exit_path, map->cfregion->name);
2565  strcat(exit_path, ".html");
2566  relative_path(map->path, exit_path, regionpath);
2567  } else {
2568  regionpath[0]='\0';
2569  snprintf(regionname, sizeof(regionname), "(map was not processed)");
2570  }
2571 
2572  snprintf(mappic, sizeof(mappic), "%s%s", map->filename, output_extensions[output_format]);
2573  snprintf(mapsmallpic, sizeof(mapsmallpic), "%s.small%s", map->filename, output_extensions[output_format]);
2574 
2575  snprintf(htmlpath, sizeof(htmlpath), "%s%s.html", root, map->path);
2576  make_path_to_file(htmlpath);
2577 
2578  values[14] = "";
2579 
2580  snprintf(maplevel, sizeof(maplevel), "%d", map->level);
2581  if (map->lore && map->lore[0] != '\0') {
2582  values[11] = map->lore;
2583  maplore = do_template(map_lore_template, vars, values);
2584  } else {
2585  maplore = do_template(map_no_lore_template, vars, values);
2586  }
2587  values[11] = maplore;
2588 
2589  if (map->exits_from.count) {
2590  char *one_exit = NULL;
2591  int exit;
2592  char relative[500];
2593 
2594  vars[vars_count] = "EXITNAME";
2595  vars[vars_count+1] = "EXITFILE";
2596 
2597  qsort(map->exits_from.maps, map->exits_from.count, sizeof(const char *), sort_map_info);
2598  for (exit = 0; exit < map->exits_from.count; exit++) {
2599  relative_path(map->path, map->exits_from.maps[exit]->path, relative);
2600  values[vars_count] = map->exits_from.maps[exit]->name;
2601  strcat(relative, ".html");
2602  values[vars_count+1] = relative;
2603  one_exit = cat_template(one_exit, do_template(map_exit_template, vars, values));
2604  }
2605  vars[vars_count] = "EXIT";
2606  vars[vars_count+1] = NULL;
2607  values[vars_count] = one_exit;
2608  exits_text = do_template(map_with_exit_template, vars, values);
2609  free(one_exit);
2610  }
2611  else
2612  exits_text = do_template(map_no_exit_template, vars, values);
2613 
2614  values[5] = exits_text;
2615 
2616  if (map->exits_to.count) {
2617  char *one_exit = NULL;
2618  int exit;
2619  char relative[500];
2620 
2621  vars[vars_count] = "EXITNAME";
2622  vars[vars_count+1] = "EXITFILE";
2623 
2624  qsort(map->exits_to.maps, map->exits_to.count, sizeof(struct_map_info *), sort_map_info);
2625  for (exit = 0; exit < map->exits_to.count; exit++) {
2626  relative_path(map->path, map->exits_to.maps[exit]->path, relative);
2627  values[vars_count] = map->exits_to.maps[exit]->name;
2628  strcat(relative, ".html");
2629  values[vars_count+1] = relative;
2630  one_exit = cat_template(one_exit, do_template(map_exit_to_template, vars, values));
2631  }
2632  vars[vars_count] = "EXIT";
2633  vars[vars_count+1] = NULL;
2634  values[vars_count] = one_exit;
2635  exits_to = do_template(map_with_exit_to_template, vars, values);
2636  free(one_exit);
2637  } else
2638  exits_to = do_template(map_no_exit_to_template, vars, values);
2639 
2640  values[12] = exits_to;
2641 
2642  if (map->quests.count) {
2643  int q;
2644 
2645  quest = NULL;
2646  for (q = 0; q < map->quests.count; q++) {
2647  quest_vals[0] = map->quests.list[q]->quest->name;
2648  relative_path(map->path, "/quests.html", questtemp);
2649  snprintf(questpath, sizeof(questpath), "%s#quest_%d", questtemp, map->quests.list[q]->quest->number);
2650  quest_vals[2] = map->quests.list[q]->description;
2651  quest = cat_template(quest, do_template(map_one_quest_template, quest_vars, quest_vals));
2652  }
2653 
2654  q_vals[0] = quest;
2655  quests = do_template(map_with_quests_template, q_vars, q_vals);
2656  free(quest);
2657  quest = NULL;
2658  } else
2659  quests = strdup(map_no_quest_template);
2660  values[14] = quests;
2661 
2662  if (map->monsters.count) {
2663  int m;
2664 
2665  qsort(map->monsters.races, map->monsters.count, sizeof(struct_race *), sort_race);
2666 
2667  monsters = do_template(map_monster_before_template, vars, values);
2668  for (m = 0; m < map->monsters.count; m++) {
2669  m_vals[0] = map->monsters.races[m]->name;
2670  monsters = cat_template(monsters, do_template(map_monster_one_template, m_vars, m_vals));
2671  if (m != map->monsters.count-1)
2672  monsters = cat_template(monsters, do_template(map_monster_between_template, vars, values));
2673  }
2674  monsters = cat_template(monsters, do_template(map_monster_after_template, vars, values));
2675  } else
2676  monsters = do_template(map_no_monster_template, vars, values);
2677  values[15] = monsters;
2678 
2679  vars[vars_count] = NULL;
2680  out = fopen(htmlpath, "w+");
2681  tmp = do_template(map_template, vars, values);
2682  fprintf(out, "%s", tmp);
2683  fclose(out);
2684  free(tmp);
2685  free(exits_text);
2686  free(exits_to);
2687  free(maplore);
2688  free(quests);
2689  free(monsters);
2690 }
2691 
2693 static void fix_map_names(void) {
2694  int map;
2695 
2696  for (map = 0; map < maps_list.count; map++) {
2697  if (maps_list.maps[map]->name)
2698  continue;
2699  if (!maps_list.maps[map]->filename) {
2700  printf("map without path!\n");
2701  abort();
2702  }
2703  maps_list.maps[map]->name = strdup(maps_list.maps[map]->filename);
2704  }
2705 }
2706 
2713 static void fix_tiled_map(void) {
2714  int map, tile;
2715  char name[500];
2716  char *slash, *test;
2717  region *cfregion;
2718 
2719  for (map = 0; map < tiled_map_list.count; map++) {
2720  if (tiled_map_list.maps[map]->tiled_maps.count == 0) {
2721  printf("empty tiled map group!");
2722  abort();
2723  }
2724 
2725  snprintf(name, sizeof(name), "tiled_map_group_%d", map);
2726  tiled_map_list.maps[map]->filename = strdup(name);
2727 
2728  cfregion = NULL;
2729  test = NULL;
2730 
2731  for (tile = 0; tile < tiled_map_list.maps[map]->tiled_maps.count; tile++) {
2732  if (tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion == NULL)
2733  /* map not processed, ignore it. */
2734  continue;
2735 
2736  if (!cfregion)
2737  cfregion = tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion;
2738  else if (cfregion != tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion) {
2739  printf("*** warning: tiled maps %s and %s not in same region (%s and %s).\n",
2740  tiled_map_list.maps[map]->tiled_maps.maps[0]->path, tiled_map_list.maps[map]->tiled_maps.maps[tile]->path,
2741  tiled_map_list.maps[map]->tiled_maps.maps[0]->cfregion->name, tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion->name);
2742  cfregion = NULL;
2743  }
2744 
2745  if (strcmp(tiled_map_list.maps[map]->tiled_maps.maps[tile]->name, tiled_map_list.maps[map]->tiled_maps.maps[tile]->filename)) {
2746  /* map has a custom name, use it */
2747  if (!test)
2748  test = tiled_map_list.maps[map]->tiled_maps.maps[tile]->name;
2749  }
2750  }
2751 
2752  if (!test) {
2753  /* this can happen of course if only partial maps were processed, but well... */
2754  printf("*** warning: tiled map without any name. First map path %s\n", tiled_map_list.maps[map]->tiled_maps.maps[0]->path);
2755  test = name;
2756  }
2757 
2758  tiled_map_list.maps[map]->name = strdup(test);
2759  tiled_map_list.maps[map]->cfregion = cfregion;
2760 
2761  strncpy(name, tiled_map_list.maps[map]->tiled_maps.maps[0]->path, sizeof(name));
2762  slash = strrchr(name, '/');
2763  if (!slash)
2764  snprintf(name, sizeof(name), "/");
2765  else
2766  *(slash+1) = '\0';
2767  strncat(name, tiled_map_list.maps[map]->filename, sizeof(name));
2768  tiled_map_list.maps[map]->path = strdup(name);
2769  }
2770 }
2771 
2782 static void fix_exits_for_map(struct_map_info *current, struct_map_list *from, int is_from) {
2783  int map, max;
2784  struct_map_info *group;
2785 
2786  max = from->count-1;
2787  for (map = max; map >= 0; map--) {
2788  if (from->maps[map]->tiled_group) {
2789  group = from->maps[map]->tiled_group;
2790  if (map != max)
2791  from->maps[map] = from->maps[max];
2792  from->count--;
2793  max--;
2794  add_map(group, from);
2795  add_map(current->tiled_group ? current->tiled_group : current, is_from ? &group->exits_to : &group->exits_from);
2796  }
2797  }
2798 }
2799 
2801 static void fix_exits_to_tiled_maps(void) {
2802  int map, region, max;
2803  struct_map_info *group;
2804 
2805  for (map = 0; map < maps_list.count; map++) {
2806  fix_exits_for_map(maps_list.maps[map], &maps_list.maps[map]->exits_from, 1);
2807  fix_exits_for_map(maps_list.maps[map], &maps_list.maps[map]->exits_to, 0);
2808  }
2809 
2810  for (region = 0; region < region_count; region++) {
2811  max = regions[region]->maps_list.count-1;
2812  for (map = max; map >= 0; map--) {
2813  if (regions[region]->maps_list.maps[map]->tiled_group) {
2814  group = regions[region]->maps_list.maps[map]->tiled_group;
2815  if (map != max)
2816  regions[region]->maps_list.maps[map] = regions[region]->maps_list.maps[max];
2817  regions[region]->maps_list.count--;
2818  max--;
2819  add_map(group, &regions[region]->maps_list);
2820  }
2821  }
2822  }
2823 }
2824 
2829 static void fix_tiled_map_monsters(void) {
2830  int map, race, max;
2831  struct_map_info *group;
2832 
2833  for (race = 0; race < races.count; race++) {
2834  max = races.races[race]->origin.count-1;
2835  for (map = max; map >= 0; map--) {
2836  if (races.races[race]->origin.maps[map]->tiled_group) {
2837  group = races.races[race]->origin.maps[map]->tiled_group;
2838  if (map != max)
2839  races.races[race]->origin.maps[map] = races.races[race]->origin.maps[max];
2840  races.races[race]->origin.count--;
2841  max--;
2842  add_map(group, &races.races[race]->origin);
2843  }
2844  }
2845  }
2846 
2847  for (map = 0; map < maps_list.count; map++) {
2848  if (maps_list.maps[map]->tiled_group) {
2849  for (race = 0; race < maps_list.maps[map]->monsters.count; race++) {
2850  add_race_to_list(maps_list.maps[map]->monsters.races[race], &maps_list.maps[map]->tiled_group->monsters, 1);
2851  }
2852  }
2853  }
2854 }
2855 
2857 static void write_all_maps(void) {
2858  int map;
2859 
2860  printf("Writing map pages...");
2861 
2862  for (map = 0; map < maps_list.count; map++)
2863  if (!maps_list.maps[map]->tiled_group)
2864  write_map_page(maps_list.maps[map]);
2865 
2866  printf(" done.\n");
2867 }
2868 
2870  int test;
2871  char picpath[500];
2872  struct stat stats;
2873 
2874  snprintf(picpath, sizeof(picpath), "%s%s%s", root, map->path, output_extensions[output_format]);
2875  if (stat(picpath, &stats))
2876  return 1;
2877 
2878  snprintf(picpath, sizeof(picpath), "%s%s.small%s", root, map->path, output_extensions[output_format]);
2879  if (stat(picpath, &stats))
2880  return 1;
2881 
2882  for (test = 0; test < map->tiled_maps.count; test++) {
2883  if (map->tiled_maps.maps[test]->pic_was_done)
2884  return 1;
2885  }
2886 
2887  return 0;
2888 }
2889 
2902  int xmin = 0, xmax = 0, ymin = 0, ymax = 0, tiled, count, last;
2903  char picpath[500];
2904  gdImagePtr small, large, load;
2905  FILE *out;
2906  struct_map_info *current;
2907 
2908  if (!generate_pics)
2909  return;
2910 
2911  printf(" Generating composite map for %s...", map->name);
2912  fflush(stdout);
2913 
2914  if (!tiled_map_need_pic(map)) {
2915  printf(" already uptodate.\n");
2916  return;
2917  }
2918 
2919  count = map->tiled_maps.count;
2920  if (count == 0) {
2921  printf("Tiled map without tiled maps?\n");
2922  abort();
2923  }
2924  map->tiled_maps.maps[0]->processed = 1;
2925  map->tiled_maps.maps[0]->tiled_x_from = 0;
2926  map->tiled_maps.maps[0]->tiled_y_from = 0;
2927 
2928  while (count > 0) {
2929  last = count;
2930 
2931  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2932  current = map->tiled_maps.maps[tiled];
2933  if (current->processed != 1)
2934  continue;
2935 
2936  count--;
2937 
2938  if ((current->tiles[0]) && (current->tiles[0]->processed == 0)) {
2939  current->tiles[0]->processed = 1;
2940  current->tiles[0]->tiled_x_from = current->tiled_x_from;
2941  current->tiles[0]->tiled_y_from = current->tiled_y_from-current->tiles[0]->height;
2942  }
2943  if ((current->tiles[1]) && (current->tiles[1]->processed == 0)) {
2944  current->tiles[1]->processed = 1;
2945  current->tiles[1]->tiled_x_from = current->tiled_x_from+current->width;
2946  current->tiles[1]->tiled_y_from = current->tiled_y_from;
2947  }
2948  if ((current->tiles[2]) && (current->tiles[2]->processed == 0)) {
2949  current->tiles[2]->processed = 1;
2950  current->tiles[2]->tiled_x_from = current->tiled_x_from;
2951  current->tiles[2]->tiled_y_from = current->tiled_y_from+current->height;
2952  }
2953  if ((current->tiles[3]) && (current->tiles[3]->processed == 0)) {
2954  current->tiles[3]->processed = 1;
2955  current->tiles[3]->tiled_x_from = current->tiled_x_from-current->tiles[3]->width;
2956  current->tiles[3]->tiled_y_from = current->tiled_y_from;
2957  }
2958  }
2959 
2960  if (last == count) {
2961  printf("do_tiled_map_picture: didn't process any map in %s (%d left)??\n", map->path, last);
2962  abort();
2963  }
2964  }
2965 
2966  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2967  if (map->tiled_maps.maps[tiled]->tiled_x_from < xmin)
2968  xmin = map->tiled_maps.maps[tiled]->tiled_x_from;
2969  if (map->tiled_maps.maps[tiled]->tiled_y_from < ymin)
2970  ymin = map->tiled_maps.maps[tiled]->tiled_y_from;
2971  if (map->tiled_maps.maps[tiled]->tiled_x_from+map->tiled_maps.maps[tiled]->width > xmax)
2972  xmax = map->tiled_maps.maps[tiled]->tiled_x_from+map->tiled_maps.maps[tiled]->width;
2973  if (map->tiled_maps.maps[tiled]->tiled_y_from+map->tiled_maps.maps[tiled]->height > ymax)
2974  ymax = map->tiled_maps.maps[tiled]->tiled_y_from+map->tiled_maps.maps[tiled]->height;
2975  }
2976 
2977  large = gdImageCreateTrueColor(32*(xmax-xmin), 32*(ymax-ymin));
2978  small = gdImageCreateTrueColor(size_small*(xmax-xmin), size_small*(ymax-ymin));
2979 
2980  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2981  snprintf(picpath, sizeof(picpath), "%s%s%s", root, map->tiled_maps.maps[tiled]->path, output_extensions[output_format]);
2982 
2983  out = fopen(picpath, "rb");
2984  if (!out) {
2985  printf("\n do_tiled_map_picture: warning: pic file not found for %s (errno=%d)\n", map->tiled_maps.maps[tiled]->path, errno);
2986  continue;
2987  }
2988  if (output_format == OF_PNG)
2989  load = gdImageCreateFromPng(out);
2990  else
2991  load = gdImageCreateFromJpeg(out);
2992  fclose(out);
2993  if (!load) {
2994  printf("\n do_tiled_map_picture: warning: pic not found for %s\n", map->tiled_maps.maps[tiled]->path);
2995  continue;
2996  }
2997  gdImageCopy(large, load, 32*(map->tiled_maps.maps[tiled]->tiled_x_from-xmin), 32*(map->tiled_maps.maps[tiled]->tiled_y_from-ymin), 0, 0, load->sx, load->sy);
2998  gdImageDestroy(load);
2999 
3000  snprintf(picpath, sizeof(picpath), "%s%s.small%s", root, map->tiled_maps.maps[tiled]->path, output_extensions[output_format]);
3001  out = fopen(picpath, "rb");
3002  if (output_format == OF_PNG)
3003  load = gdImageCreateFromPng(out);
3004  else
3005  load = gdImageCreateFromJpeg(out);
3006  fclose(out);
3007  if (!load) {
3008  printf("\n do_tiled_map_picture: warning: small pic not found for %s\n", map->tiled_maps.maps[tiled]->path);
3009  continue;
3010  }
3011  gdImageCopy(small, load, size_small*(map->tiled_maps.maps[tiled]->tiled_x_from-xmin), size_small*(map->tiled_maps.maps[tiled]->tiled_y_from-ymin), 0, 0, load->sx, load->sy);
3012  gdImageDestroy(load);
3013  }
3014 
3015  snprintf(picpath, sizeof(picpath), "%s%s%s", root, map->path, output_extensions[output_format]);
3016  out = fopen(picpath, "wb+");
3017  save_picture(out, large);
3018  fclose(out);
3019 
3020  snprintf(picpath, sizeof(picpath), "%s%s.small%s", root, map->path, output_extensions[output_format]);
3021  out = fopen(picpath, "wb+");
3022  save_picture(out, small);
3023  fclose(out);
3024 
3025  gdImageDestroy(small);
3026  gdImageDestroy(large);
3027 
3028  printf(" done.\n");
3029 }
3030 
3033 
3034  do_tiled_map_picture(map);
3035 
3038  write_map_page(map);
3039 }
3040 
3042 static void write_tiled_maps(void) {
3043  int map;
3044 
3045  printf("Writing tiled map information...\n");
3046 
3047  for (map = 0; map < tiled_map_list.count; map++)
3048  write_tiled_map_page(tiled_map_list.maps[map]);
3049 
3050  printf(" done.\n");
3051 }
3052 
3054 static void write_maps_by_level(void) {
3055  int map;
3056  FILE *out;
3057  char name[500];
3058  char mappath[500];
3059  char *letters = NULL;
3060  char *maps = NULL;
3061  char *level = NULL;
3062  int lastlevel = -1;
3063  char strlevel[10];
3064  char strcount[10];
3065  const char *val_vars[] = { "LEVEL", "MAPS", NULL };
3066  const char *val_values[] = { strlevel, NULL, NULL };
3067  const char *map_vars[] = { "MAPNAME", "MAPPATH", NULL };
3068  const char *map_values[] = { NULL, mappath, NULL };
3069  const char *idx_vars[] = { "COUNT", "LEVELS", NULL };
3070  const char *idx_values[] = { strcount, NULL, NULL };
3071  int levelcount = 0;
3072  struct_map_info *last_tiled = NULL;
3073  struct_map_info *process;
3074 
3075  printf("Writing map index by level...");
3076 
3077  snprintf(name, sizeof(name), "%s/index_by_level.html", root);
3078 
3079  qsort(maps_list.maps, maps_list.count, sizeof(struct_map_info *), sort_map_info_by_level);
3080 
3081  for (map = 0; map < maps_list.count; map++) {
3082  process = maps_list.maps[map];
3083  if (maps_list.maps[map]->level != lastlevel) {
3084  if (maps) {
3085  snprintf(strlevel, sizeof(strlevel), "%d", lastlevel);
3086  val_values[1] = maps;
3087  letters = cat_template(letters, do_template(level_value_template, val_vars, val_values));
3088  free(maps);
3089  maps = NULL;
3090  }
3091  lastlevel = process->level;
3092  levelcount++;
3093  last_tiled = NULL;
3094  } else
3095  if (last_tiled && last_tiled == process->tiled_group)
3096  /* Group maps of same tiled group and level, but make them appear in different levels if applicable. */
3097  continue;
3098 
3099  if (process->tiled_group) {
3100  process = process->tiled_group;
3101  last_tiled = process;
3102  } else
3103  last_tiled = process->tiled_group;
3104 
3105  map_values[0] = process->name;
3106  snprintf(mappath, sizeof(mappath), "%s.html", process->path+1); /* don't want the leading / */
3107  maps = cat_template(maps, do_template(level_map_template, map_vars, map_values));
3108  }
3109 
3110  snprintf(strlevel, sizeof(strlevel), "%d", lastlevel);
3111  val_values[1] = maps;
3112  letters = cat_template(letters, do_template(level_value_template, val_vars, val_values));
3113  free(maps);
3114  maps = NULL;
3115 
3116  snprintf(strcount, sizeof(strcount), "%d", levelcount);
3117  idx_values[1] = letters;
3118  level = do_template(level_template, idx_vars, idx_values);
3119  free(letters);
3120 
3121  out = fopen(name, "w+");
3122  fprintf(out, "%s", level);
3123  fclose(out);
3124  free(level);
3125 
3126  printf(" done.\n");
3127 }
3128 
3132 static void write_equipment_index(void) {
3133  int item, map;
3134  FILE *out;
3135  char name[500];
3136 
3137  printf("Generating special equipment list..");
3138  fflush(stdout);
3139 
3140  qsort(special_equipment, equipment_count, sizeof(struct_equipment *), sort_equipment);
3141 
3142  snprintf(name, sizeof(name), "%s/items.html", root);
3143  out = fopen(name, "w+");
3144 
3145  fprintf(out, "<html><head><title>Item list</title></head><body><h1>Special items found in maps</h1>\n");
3146  fprintf(out, "<table border=\"1\"><tr><th>Name</th><th>Map(s)</th><th>Item power</th><th>Calc item power</th><th>Description</th></tr>\n");
3147 
3148  for (item = 0; item < equipment_count; item++) {
3149  fprintf(out, "<tr><td>%s</td><td><ul>", special_equipment[item]->name);
3150 
3151  for (map = 0; map < special_equipment[item]->origin.count; map++)
3152  fprintf(out, "<li>%s</li>\n", special_equipment[item]->origin.maps[map]->path);
3153 
3154  fprintf(out, "</ul></td><td>%d</td><td>%d</td><td><pre>%s</pre></td></tr>\n", special_equipment[item]->power, special_equipment[item]->calc_power, special_equipment[item]->diff);
3155  }
3156  fprintf(out, "</table></body></html>\n");
3157  fclose(out);
3158 
3159  printf(" done.\n");
3160 }
3161 
3165 static void write_race_index(void) {
3166  int item, map;
3167  FILE *out;
3168  char name[500];
3169 
3170  printf("Generating monster list...");
3171  fflush(stdout);
3172 
3173  qsort(races.races, races.count, sizeof(struct_race *), sort_race);
3174 
3175  snprintf(name, sizeof(name), "%s/monsters.html", root);
3176  out = fopen(name, "w+");
3177 
3178  fprintf(out, "<html><head><title>Monster list</title></head><body><h1>Monsters found in maps</h1>\n");
3179  fprintf(out, "<table border=\"1\"><tr><th>Name</th><th>Count</th><th>Map(s)</th></tr>\n");
3180 
3181  for (item = 0; item < races.count; item++) {
3182  fprintf(out, "<tr><td>%s</td><td>%d</td><td>Found on %d maps:<ul>", races.races[item]->name, races.races[item]->count, races.races[item]->origin.count);
3183 
3184  qsort(races.races[item]->origin.maps, races.races[item]->origin.count, sizeof(struct_map_info *), sort_map_info);
3185 
3186  for (map = 0; map < races.races[item]->origin.count; map++)
3187  fprintf(out, "<li>%s</li>\n", races.races[item]->origin.maps[map]->path);
3188 
3189  fprintf(out, "</ul></td></tr>\n");
3190  }
3191  fprintf(out, "</table></body></html>\n");
3192  fclose(out);
3193 
3194  printf(" done.\n");
3195 }
3196 
3198 static const char *ignore_path[] = {
3199  "/Info",
3200  "/editor",
3201  "/python",
3202  "/styles",
3203  "/templates",
3204  "/test",
3205  "/unlinked",
3206  NULL };
3207 
3209 static const char *ignore_name[] = {
3210  ".",
3211  "..",
3212  ".svn",
3213  "README",
3214  NULL };
3215 
3222 static void find_maps(const char *from) {
3223  struct dirent *file;
3224  struct stat statbuf;
3225  int status, ignore;
3226  char path[1024], full[1024];
3227  DIR *dir;
3228 
3229  for (ignore = 0; ignore_path[ignore] != NULL; ignore++) {
3230  if (strcmp(from, ignore_path[ignore]) == 0)
3231  return;
3232  }
3233 
3234  snprintf(path, sizeof(path), "%s/%s%s", settings.datadir, settings.mapdir, from);
3235  dir = opendir(path);
3236 
3237  if (dir) {
3238  for (file = readdir(dir); file; file = readdir(dir)) {
3239 
3240  for (ignore = 0; ignore_name[ignore] != NULL; ignore++) {
3241  if (strcmp(file->d_name, ignore_name[ignore]) == 0)
3242  break;
3243  }
3244  if (ignore_name[ignore] != NULL)
3245  continue;
3246 
3247  snprintf(full, sizeof(full), "%s/%s", path, file->d_name);
3248 
3249  status = stat(full, &statbuf);
3250  if ((status != -1) && (S_ISDIR(statbuf.st_mode))) {
3251  snprintf(full, sizeof(full), "%s/%s", from, file->d_name);
3252  find_maps(full);
3253  continue;
3254  }
3256  found_maps_allocated += 50;
3257  found_maps = realloc(found_maps, found_maps_allocated*sizeof(char *));
3258  }
3259  snprintf(full, sizeof(full), "%s/%s", from, file->d_name);
3260  found_maps[found_maps_count++] = strdup(full);
3261  }
3262  closedir(dir);
3263  }
3264 }
3265 
3267 static void dump_unused_maps(void) {
3268  FILE *dump;
3269  char path[1024];
3270  int index, found = 0;
3271 
3272  snprintf(path, sizeof(path), "%s/%s", root, "maps.unused");
3273  dump = fopen(path, "w+");
3274  if (dump == NULL) {
3275  printf("Unable to open file maps.unused!\n");
3276  return;
3277  }
3278  for (index = 0; index < found_maps_count; index++) {
3279  if (found_maps[index] != NULL) {
3280  fprintf(dump, "%s\n", found_maps[index]);
3281  free(found_maps[index]);
3282  found++;
3283  }
3284  }
3285  fclose(dump);
3286  printf("%d unused maps.\n", found);
3287 }
3288 
3290 static void write_world_info(void) {
3291  FILE *file;
3292  char path[MAX_BUF];
3293  int x, y;
3294  gdImagePtr elevationmap;
3295 
3296  if (!world_exit_info)
3297  return;
3298 
3299  printf("Saving exit/blocking/road information...");
3300  snprintf(path, sizeof(path), "%s/%s%s", root, "world_info", output_extensions[output_format]);
3301  file = fopen(path, "wb+");
3302  save_picture(file, infomap);
3303  fclose(file);
3304  printf("done.\n");
3305  gdImageDestroy(infomap);
3306  infomap = NULL;
3307 
3308  if (elevation_min == 0 || elevation_max == 0) {
3309  puts("Error: Could not save elevation world map due to not finding any minimum or maximum elevation.");
3310  return;
3311  }
3312 
3313  elevationmap = gdImageCreateTrueColor(30*50, 30*50);;
3314 
3315  for (x = 0; x < 30*50; x++) {
3316  for (y = 0; y < 30*50; y++) {
3317  gdImageSetPixel(elevationmap, x, y, get_elevation_color(elevation_info[x][y], elevationmap));
3318  }
3319  }
3320 
3321  printf("Saving elevation world map...");
3322  snprintf(path, sizeof(path), "%s/%s%s", root, "world_elevation", output_extensions[output_format]);
3323  file = fopen(path, "wb+");
3324  save_picture(file, elevationmap);
3325  fclose(file);
3326  printf("done.\n");
3327  gdImageDestroy(elevationmap);
3328  elevationmap = NULL;
3329 }
3330 
3332 static void write_regions_link(void) {
3333  FILE *file;
3334  char path[MAX_BUF];
3335  int link;
3336 
3337  if (!do_regions_link)
3338  return;
3339 
3340  printf("Writing regions link file...");
3341  snprintf(path, sizeof(path), "%s/%s", root, "region_links.dot");
3342  file = fopen(path, "wb+");
3343  fprintf(file, "digraph {\n");
3344  for (link = 0; link < regions_link_count; link++)
3345  fprintf(file, "%s", regions_link[link]);
3346  fprintf(file, "}\n");
3347  fclose(file);
3348  printf("done.\n");
3349 }
3350 
3359 static void write_slaying_map_name(FILE *file, struct_map_info *map) {
3360  fprintf(file, "<a href=\"%s.html\">%s</a> (full map path: %s)", map->tiled_group ? map->tiled_group->path+1 : map->path+1, map->name, map->path);
3361 }
3362 
3377 static void write_one_slaying_info(FILE *file, struct_slaying_info *info, int item, const char *with, const char *without) {
3378  int map;
3379 
3380  if (info->maps[item].count == 0) {
3381  if (without)
3382  fprintf(file, "%s", without);
3383  return;
3384  }
3385 
3386  qsort(info->maps[item].maps, info->maps[item].count, sizeof(const char *), sort_mapname);
3387 
3388  fprintf(file, "%s", with);
3389  fprintf(file, "<ul>\n");
3390  for (map = 0; map < info->maps[item].count; map++) {
3391  fprintf(file, "\t<li>");
3392  write_slaying_map_name(file, info->maps[item].maps[map]);
3393  fprintf(file, "</li>\n");
3394  }
3395  fprintf(file, "</ul>\n");
3396 }
3397 
3408 static int sort_slaying(const void *left, const void *right) {
3410  struct_slaying_info *r = *(struct_slaying_info **)right;
3411 
3412  return strcasecmp(l->slaying, r->slaying);
3413 }
3414 
3418 static void write_slaying_info(void) {
3419  FILE *file;
3420  char path[MAX_BUF];
3421  int lock;
3422  struct_slaying_info *info;
3423 
3424  printf("Writing slaying info file...");
3425 
3426  qsort(slaying_info, slaying_count, sizeof(struct_slaying_info *), sort_slaying);
3427 
3428  snprintf(path, sizeof(path), "%s/%s", root, "slaying_info.html");
3429  file = fopen(path, "wb+");
3430 
3431  fprintf(file, "<html>\n<head>\n<title>Slaying information</title>\n</head>\n<body>\n");
3432  fprintf(file, "<p>This is a list of various slaying fields on keys, containers, doors, detectors.</p>");
3433 
3434  for (lock = 0; lock < slaying_count; lock++) {
3435  info = slaying_info[lock];
3436  fprintf(file, "<h1>%s</h1>\n", info->slaying);
3437 
3438  if (info->maps[S_DOOR].count == 0 && info->maps[S_CONTAINER].count == 0 && info->maps[S_CONNECT].count == 0) {
3439  fprintf(file, "No door, container or detector matching this slaying.<br />\n");
3440  } else {
3441  write_one_slaying_info(file, info, S_DOOR, "Connected doors:\n", NULL);
3442  write_one_slaying_info(file, info, S_CONTAINER, "Matching containers:\n", NULL);
3443  write_one_slaying_info(file, info, S_CONNECT, "Detectors and such:\n", NULL);
3444  }
3445  write_one_slaying_info(file, info, S_KEY, "Matching keys:\n", "No key with this slaying.<br />\n");
3446  }
3447 
3448  fprintf(file, "</body>\n</html>\n");
3449 
3450  fclose(file);
3451  printf("done.\n");
3452 }
3453 
3457 static void write_npc_list(void) {
3458  FILE *file;
3459  char path[MAX_BUF];
3460  int map, npc;
3461 
3462  printf("Writing NPC info file...");
3463 
3464  qsort(slaying_info, slaying_count, sizeof(struct_slaying_info *), sort_slaying);
3465 
3466  snprintf(path, sizeof(path), "%s/%s", root, "npc_info.html");
3467  file = fopen(path, "wb+");
3468 
3469  fprintf(file, "<html>\n<head>\n<title>NPCs who have a special message</title>\n</head>\n<body>\n");
3470  fprintf(file, "<p>This is a list of NPCs having a special message.</p>");
3471  fprintf(file, "<ul>\n");
3472 
3473  for (map = 0; map < maps_list.count; map++) {
3474  if (maps_list.maps[map]->npcs.count == 0)
3475  continue;
3476  fprintf(file, "<li>%s</li>\n<ul>", maps_list.maps[map]->path);
3477  for (npc = 0; npc < maps_list.maps[map]->npcs.count; npc++) {
3478  fprintf(file, "<li>%s (%d,%d): <br /><pre>%s</pre></li>\n", maps_list.maps[map]->npcs.npc[npc]->name, maps_list.maps[map]->npcs.npc[npc]->x, maps_list.maps[map]->npcs.npc[npc]->y, maps_list.maps[map]->npcs.npc[npc]->message);
3479  }
3480  fprintf(file, "</ul>\n</li>\n");
3481  }
3482 
3483  fprintf(file, "</ul>\n");
3484  fprintf(file, "</body>\n</html>\n");
3485 
3486  fclose(file);
3487  printf("done.\n");
3488 }
3489 
3493 static void write_readable_list(void) {
3494  FILE *file;
3495  char path[MAX_BUF];
3496  int map, readable;
3497 
3498  printf("Writing readable info file...");
3499 
3500  snprintf(path, sizeof(path), "%s/%s", root, "readable_info.html");
3501  file = fopen(path, "wb+");
3502 
3503  fprintf(file, "<html>\n<head>\n<title>SIGN and BOOK with a special message</title>\n</head>\n<body>\n");
3504  fprintf(file, "<p>This is a list of SIGN and BOOK with a special message.</p>");
3505  fprintf(file, "<ul>\n");
3506 
3507  for (map = 0; map < maps_list.count; map++) {
3508  if (maps_list.maps[map]->readable.count == 0)
3509  continue;
3510  fprintf(file, "<li>%s</li>\n<ul>", maps_list.maps[map]->path);
3511  for (readable = 0; readable < maps_list.maps[map]->readable.count; readable++) {
3512  fprintf(file, "<li>%s (%d,%d): <br /><pre>%s</pre></li>\n", maps_list.maps[map]->readable.npc[readable]->name, maps_list.maps[map]->readable.npc[readable]->x, maps_list.maps[map]->readable.npc[readable]->y, maps_list.maps[map]->readable.npc[readable]->message);
3513  }
3514  fprintf(file, "</ul>\n</li>\n");
3515  }
3516 
3517  fprintf(file, "</ul>\n");
3518  fprintf(file, "</body>\n</html>\n");
3519 
3520  fclose(file);
3521  printf("done.\n");
3522 }
3523 
3530 static void do_help(const char *program) {
3531  printf("Crossfire Mapper will generate pictures of maps, and create indexes for all maps and regions.\n\n");
3532  printf("Syntax: %s\n\n", program);
3533  printf("Optional arguments:\n");
3534  printf(" -nopics don't generate pictures.\n");
3535  printf(" -noindex don't generate global map index.\n");
3536  printf(" -root=<path> destination path. Default 'html'.\n");
3537  printf(" -limit=<number> stop processing after this number of maps, -1 to do all maps (default).\n");
3538  printf(" -showmaps outputs the name of maps as they are processed.\n");
3539  printf(" -jpg[=quality] generate jpg pictures, instead of default png. Quality should be 0-95, -1 for automatic.\n");
3540  printf(" -forcepics force to regenerate pics, even if pics's date is after map's.\n");
3541  printf(" -addmap=<map> adds a map to process. Path is relative to map's directory root.\n");
3542  printf(" -rawmaps generates maps pics without items on random (shop, treasure) tiles.\n");
3543  printf(" -warnnopath inform when an exit has no path set.\n");
3544  printf(" -listunusedmaps finds all unused maps in the maps directory.\n");
3545  printf(" -noworldmap don't write the world map in world.png.\n");
3546  printf(" -noregionslink don't generate regions relation file.\n");
3547  printf(" -regionslink generate regions relation file.\n");
3548  printf(" -noexitmap don't generate map of exits.\n");
3549  printf(" -exitmap generate map of exits.\n");
3550  printf(" -tileset=<number> use specified tileset to generate the pictures. Default 0 (standard).\n");
3551  printf("\n\n");
3552  exit(0);
3553 }
3554 
3563 static void do_parameters(int argc, char **argv) {
3564  int arg = 1;
3565  char path[500];
3566 
3567  root[0] = '\0';
3568 
3569  while (arg < argc) {
3570  if (strcmp(argv[arg], "-nopics") == 0)
3571  generate_pics = 0;
3572  else if (strcmp(argv[arg], "-noindex") == 0)
3573  generate_index = 0;
3574  else if (strncmp(argv[arg], "-root=", 6) == 0)
3575  strncpy(root, argv[arg]+6, 500);
3576  else if (strncmp(argv[arg], "-limit=", 7) == 0)
3577  map_limit = atoi(argv[arg]+7);
3578  else if (strcmp(argv[arg], "-showmaps") == 0)
3579  show_maps = 1;
3580  else if (strcmp(argv[arg], "-jpg") == 0) {
3582  if (argv[arg][4] == '=') {
3583  jpeg_quality = atoi(argv[arg]+5);
3584  if (jpeg_quality < 0)
3585  jpeg_quality = -1;
3586  }
3587  }
3588  else if (strcmp(argv[arg], "-forcepics") == 0)
3589  force_pics = 1;
3590  else if (strncmp(argv[arg], "-addmap=", 8) == 0) {
3591  if (*(argv[arg]+8) == '/')
3592  strncpy(path, argv[arg]+8, 500);
3593  else
3594  snprintf(path, 500, "/%s", argv[arg]+8);
3595  add_map(get_map_info(path), &maps_list);
3596  }
3597  else if (strcmp(argv[arg], "-rawmaps") == 0)
3598  rawmaps = 1;
3599  else if (strcmp(argv[arg], "-warnnopath") == 0)
3600  warn_no_path = 1;
3601  else if (strcmp(argv[arg], "-listunusedmaps") == 0)
3602  list_unused_maps = 1;
3603  else if (strcmp(argv[arg], "-noworldmap") == 0)
3604  world_map = 0;
3605  else if (strcmp(argv[arg], "-noregionslink") == 0)
3606  do_regions_link = 0;
3607  else if (strcmp(argv[arg], "-regionslink") == 0)
3608  do_regions_link = 1;
3609  else if (strcmp(argv[arg], "-noexitmap") == 0)
3610  world_exit_info = 0;
3611  else if (strcmp(argv[arg], "-exitmap") == 0)
3612  world_exit_info = 1;
3613  else if (strncmp(argv[arg], "-tileset=", 9) == 0) {
3614  tileset = atoi(argv[arg]+9);
3615  /* check of validity is done in main() as we need to actually have the sets loaded. */
3616  } else
3617  do_help(argv[0]);
3618  arg++;
3619  }
3620  if (!strlen(root))
3621  strcpy(root, "html");
3622  if (root[strlen(root)-1] == '/')
3623  root[strlen(root)-1] = '\0';
3624  if (map_limit < -1)
3625  map_limit = -1;
3626 }
3627 
3631 static void create_destination(void) {
3632  char dummy[502];
3633 
3634  strcpy(dummy, root);
3635  strcat(dummy, "/a");
3636  make_path_to_file(dummy);
3637 }
3638 
3647 static const char *yesno(int value) {
3648  return (value ? "yes" : "no");
3649 }
3650 
3651 int main(int argc, char **argv) {
3652  int current_map = 0, i;
3653  char max[50];
3654  region *dummy;
3655 
3656  init_map_list(&maps_list);
3657  init_map_list(&tiled_map_list);
3658  init_race_list(&races);
3659  pics_allocated = 0;
3660 
3661  do_parameters(argc, argv);
3662 
3663  printf("Initializing Crossfire data...\n");
3664 
3665  settings.debug = 0;
3666 
3667  init_globals();
3668  init_library();
3669  init_archetypes();
3670  init_artifacts();
3671  init_formulae();
3672  init_readable();
3673  init_regions();
3674 
3675  init_gods();
3677 
3678  /* Add a dummy region so unlinked maps can be identified. */
3679  dummy = get_region_struct();
3680  dummy->fallback = 1;
3681  dummy->name = strdup_local("unlinked");
3682  dummy->longname = strdup_local("This dummy region contains all maps without a region set.");
3683  dummy->longname = strdup_local("This dummy region contains all maps without a region set.");
3684  dummy->next = first_region;
3685  first_region = dummy;
3686 
3687  printf("\n\n done.\n\n");
3688 
3689  if (!is_valid_faceset(tileset)) {
3690  printf("Erreor: invalid tileset %d!\n", tileset);
3691  exit(1);
3692  }
3693 
3695  gdfaces = calloc(nrofpixmaps, sizeof(gdImagePtr));
3696 
3697  read_template("templates/map.template", &map_template);
3698  read_template("templates/map_no_exit.template", &map_no_exit_template);
3699  read_template("templates/map_with_exit.template", &map_with_exit_template);
3700  read_template("templates/map_exit.template", &map_exit_template);
3701  read_template("templates/map_no_exit_to.template", &map_no_exit_to_template);
3702  read_template("templates/map_with_exit_to.template", &map_with_exit_to_template);
3703  read_template("templates/map_exit_to.template", &map_exit_to_template);
3704  read_template("templates/map_lore.template", &map_lore_template);
3705  read_template("templates/map_no_lore.template", &map_no_lore_template);
3706  read_template("templates/map_no_monster.template", &map_no_monster_template);
3707  read_template("templates/map_monster_before.template", &map_monster_before_template);
3708  read_template("templates/map_monster_between.template", &map_monster_between_template);
3709  read_template("templates/map_monster_one.template", &map_monster_one_template);
3710  read_template("templates/map_monster_after.template", &map_monster_after_template);
3711 
3712  read_template("templates/index.template", &index_template);
3713  read_template("templates/index_letter.template", &index_letter);
3714  read_template("templates/index_map.template", &index_map);
3715 
3716  read_template("templates/region.template", &region_template);
3717  read_template("templates/region_letter.template", &region_letter_template);
3718  read_template("templates/region_map.template", &region_map_template);
3719 
3720  read_template("templates/index_region.template", &index_region_template);
3721  read_template("templates/index_region_region.template", &index_region_region_template);
3722 
3723  read_template("templates/world.template", &world_template);
3724  read_template("templates/world_row.template", &world_row_template);
3725  read_template("templates/world_map.template", &world_map_template);
3726 
3727  read_template("templates/level.template", &level_template);
3728  read_template("templates/level_value.template", &level_value_template);
3729  read_template("templates/level_map.template", &level_map_template);
3730 
3731  read_template("templates/quests.template", &index_quest_template);
3732  read_template("templates/quests_quest.template", &quest_template);
3733  read_template("templates/quests_map.template", &quest_map_template);
3734 
3735  read_template("templates/map_with_quests.template", &map_with_quests_template);
3736  read_template("templates/map_one_quest.template", &map_one_quest_template);
3737  read_template("templates/map_no_quest.template", &map_no_quest_template);
3738 
3739  if (map_limit != -1)
3740  snprintf(max, sizeof(max), "%d", map_limit);
3741  else
3742  strcpy(max, "(none)");
3743  printf("Crossfire map browser generator\n");
3744  printf("-------------------------------\n\n");
3745  printf("Parameters:\n");
3746  printf(" path to write files: %s\n", root);
3747  printf(" maximum number of maps to process: %s\n", max);
3748  printf(" will generate map picture: %s\n", yesno(generate_pics));
3749  printf(" will always generate map picture: %s\n", yesno(force_pics));
3750  printf(" picture output format: %s\n", output_extensions[output_format]);
3751  if (output_format == OF_JPG)
3752  printf(" JPEG quality: %d\n", jpeg_quality);
3753  printf(" will generate map index: %s\n", yesno(generate_index));
3754  printf(" show map being processed: %s\n", yesno(show_maps));
3755  printf(" generate raw maps: %s\n", yesno(rawmaps));
3756  printf(" warn of exit without path: %s\n", yesno(warn_no_path));
3757  printf(" list unused maps: %s\n", yesno(list_unused_maps));
3758  printf(" generate world map: %s\n", yesno(world_map));
3759  printf(" generate exit map: %s\n", yesno(world_exit_info));
3760  printf(" generate regions link file: %s\n", yesno(do_regions_link));
3761  printf(" tileset: %s\n", facesets[tileset].fullname);
3762  printf("\n");
3763 
3764  if (list_unused_maps) {
3765  printf("listing all maps...");
3766  find_maps("");
3767  printf("done, %d maps found.\n", found_maps_count);
3768  qsort(found_maps, found_maps_count, sizeof(char *), sortbyname);
3769  }
3770 
3771  /* exit/blocking information. */
3772  infomap = gdImageCreateTrueColor(30*50, 30*50);
3773  color_unlinked_exit = gdImageColorResolve(infomap, 255, 0, 0);
3774  color_linked_exit = gdImageColorResolve(infomap, 255, 255, 255);
3775  color_road = gdImageColorResolve(infomap, 0, 255, 0);
3776  color_blocking = gdImageColorResolve(infomap, 0, 0, 255);
3777  color_slowing = gdImageColorResolve(infomap, 0, 0, 127);
3778  elevation_info = calloc(50*30, sizeof(int *));
3779  for (i = 0; i < 50*30; i++)
3780  elevation_info[i] = calloc(50*30, sizeof(int));
3781  elevation_min = 0;
3782  elevation_max = 0;
3783 
3784  printf("browsing maps...\n");
3785 
3787 
3788  while (current_map < maps_list.count) {
3789  process_map(maps_list.maps[current_map++]);
3790  if (current_map%100 == 0) {
3791  printf(" %d maps processed, %d map pictures created, %d map pictures were uptodate. %d faces used.\n", current_map, created_pics, cached_pics, pics_allocated);
3792  }
3793  if ((map_limit != -1) && (current_map == map_limit)) {
3794  printf(" --- map limit reached, stopping ---\n");
3795  break;
3796  }
3797  }
3798 
3799  printf(" finished map parsing, %d maps processed, %d map pictures created, %d map pictures were uptodate. Total %d faces used.\n", current_map, created_pics, cached_pics, pics_allocated);
3800 
3801  if (list_unused_maps)
3802  dump_unused_maps();
3803 
3805  fix_map_names();
3806  fix_tiled_map();
3808 
3809  write_all_maps();
3810  write_maps_index();
3812  write_tiled_maps();
3813 
3816 
3817  write_world_map();
3818  write_world_info();
3819 
3822 
3824 
3826  write_race_index();
3827  write_npc_list();
3829 
3830  return 0;
3831 }
3832 
3834  int x, y;
3835 
3836  if (m == NULL)
3837  return;
3838 
3839  for (x = 0; x < MAP_WIDTH(m); x++)
3840  for (y = 0; y < MAP_HEIGHT(m); y++)
3841  FOR_MAP_PREPARE(m, x, y, tmp) {
3842  if (tmp->inv) {
3843  FOR_INV_PREPARE(tmp, invtmp) {
3844  if (QUERY_FLAG(invtmp, FLAG_AUTO_APPLY))
3845  apply_auto(invtmp);
3846  else if (invtmp->type == TREASURE && HAS_RANDOM_ITEMS(invtmp)) {
3847  while ((invtmp->stats.hp--) > 0)
3848  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3849  invtmp->randomitems = NULL;
3850  } else if (invtmp
3851  && invtmp->arch
3852  && invtmp->type != TREASURE
3853  && invtmp->type != SPELL
3854  && invtmp->type != CLASS
3855  && HAS_RANDOM_ITEMS(invtmp)) {
3856  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3857  /* Need to clear this so that we never try to create
3858  * treasure again for this object
3859  */
3860  invtmp->randomitems = NULL;
3861  }
3862  } FOR_INV_FINISH();
3863  /* This is really temporary - the code at the bottom will
3864  * also set randomitems to null. The problem is there are bunches
3865  * of maps/players already out there with items that have spells
3866  * which haven't had the randomitems set to null yet.
3867  * MSW 2004-05-13
3868  *
3869  * And if it's a spellbook, it's better to set randomitems to NULL too,
3870  * else you get two spells in the book ^_-
3871  * Ryo 2004-08-16
3872  */
3873  if (tmp->type == WAND
3874  || tmp->type == ROD
3875  || tmp->type == SCROLL
3876  || tmp->type == FIREWALL
3877  || tmp->type == POTION
3878  || tmp->type == ALTAR
3879  || tmp->type == SPELLBOOK)
3880  tmp->randomitems = NULL;
3881  }
3882 
3883  if (QUERY_FLAG(tmp, FLAG_AUTO_APPLY))
3884  apply_auto(tmp);
3885  else if ((tmp->type == TREASURE || (tmp->type == CONTAINER)) && HAS_RANDOM_ITEMS(tmp)) {
3886  while ((tmp->stats.hp--) > 0)
3887  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
3888  tmp->randomitems = NULL;
3889  } else if (tmp->type == TIMED_GATE) {
3890  object *head = HEAD(tmp);
3891 
3892  if (QUERY_FLAG(head, FLAG_IS_LINKED)) {
3893  tmp->speed = 0;
3894  object_update_speed(tmp);
3895  }
3896  /* This function can be called everytime a map is loaded, even when
3897  * swapping back in. As such, we don't want to create the treasure
3898  * over and ove again, so after we generate the treasure, blank out
3899  * randomitems so if it is swapped in again, it won't make anything.
3900  * This is a problem for the above objects, because they have counters
3901  * which say how many times to make the treasure.
3902  */
3903  } else if (tmp
3904  && tmp->arch
3905  && tmp->type != PLAYER
3906  && tmp->type != TREASURE
3907  && tmp->type != SPELL
3908  && tmp->type != PLAYER_CHANGER
3909  && tmp->type != CLASS
3910  && HAS_RANDOM_ITEMS(tmp)) {
3911  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
3912  tmp->randomitems = NULL;
3913  }
3914  } FOR_MAP_FINISH();
3915 
3916  for (x = 0; x < MAP_WIDTH(m); x++)
3917  for (y = 0; y < MAP_HEIGHT(m); y++)
3918  FOR_MAP_PREPARE(m, x, y, tmp) {
3919  if (tmp->above
3920  && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL))
3921  check_trigger(tmp, tmp->above);
3922  } FOR_MAP_FINISH();
3923 }
3924 
3925 #ifndef DOXYGEN_SHOULD_SKIP_THIS
3926 
3931 void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *txt) {
3932  fprintf(logfile, "%s\n", txt);
3933 }
3934 
3935 void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format, ...) {
3936  va_list ap;
3937 
3938  va_start(ap, format);
3939  vfprintf(logfile, format, ap);
3940  va_end(ap);
3941 }
3942 
3943 void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1) {
3944  fprintf(logfile, "ext_info_map: %s\n", str1);
3945 }
3946 
3947 void move_firewall(object *ob) {
3948 }
3949 
3950 void emergency_save(int x) {
3951 }
3952 
3953 void clean_tmp_files(void) {
3954 }
3955 
3956 void esrv_send_item(object *ob, object *obx) {
3957 }
3958 
3959 void dragon_ability_gain(object *ob, int x, int y) {
3960 }
3961 
3963 }
3964 
3965 object *find_skill_by_number(object *who, int skillno) {
3966  return NULL;
3967 }
3968 
3969 void esrv_del_item(player *pl, object *ob) {
3970 }
3971 
3972 void esrv_update_item(int flags, object *pl, object *op) {
3973 }
3974 
3976 }
3977 
3978 void rod_adjust(object *rod) {
3979 }
3980 
3981 int execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix) {
3982  return 0;
3983 }
3984 
3985 int execute_global_event(int eventcode, ...) {
3986  return 0;
3987 }
3988 /*
3989  * This a modified version of apply_auto: BOOK are not generated, so they don't pollute
3990  * the readable list.
3991  */
3992 int apply_auto(object *op) {
3993  object *tmp = NULL;
3994  int i;
3995 
3996  switch (op->type) {
3997  case SHOP_FLOOR:
3998  if (!HAS_RANDOM_ITEMS(op))
3999  return 0;
4000  do {
4001  i = 10; /* let's give it 10 tries */
4002  while ((tmp = generate_treasure(op->randomitems, op->stats.exp ? (int)op->stats.exp : MAX(op->map->difficulty, 5))) == NULL && --i)
4003  ;
4004  if (tmp == NULL)
4005  return 0;
4006  if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED) || tmp->type == BOOK) {
4008  tmp = NULL;
4009  }
4010  } while (!tmp);
4011  SET_FLAG(tmp, FLAG_UNPAID);
4012  object_insert_in_map_at(tmp, op->map, NULL, 0, op->x, op->y);
4014  tmp = identify(tmp);
4015  break;
4016 
4017  case TREASURE:
4018  if (QUERY_FLAG(op, FLAG_IS_A_TEMPLATE))
4019  return 0;
4020 
4021  while ((op->stats.hp--) > 0)
4022  create_treasure(op->randomitems, op, 0, op->stats.exp ? (int)op->stats.exp : op->map == NULL ? 14 : op->map->difficulty, 0);
4023 
4024  /* If we generated an object and put it in this object inventory,
4025  * move it to the parent object as the current object is about
4026  * to disappear. An example of this item is the random_ *stuff
4027  * that is put inside other objects.
4028  */
4029  FOR_INV_PREPARE(op, tmp) {
4030  object_remove(tmp);
4031  if (op->env && tmp->type != BOOK)
4032  object_insert_in_ob(tmp, op->env);
4033  else
4035  }
4036  FOR_INV_FINISH();
4037  object_remove(op);
4039  break;
4040  }
4041  return tmp ? 1 : 0;
4042 }
4043 
4045 }
4046 
4047 #endif /* dummy DOXYGEN_SHOULD_SKIP_THIS */
struct struct_npc_info struct_npc_info
Information about a NPC with a custom message.
EXTERN FILE * logfile
Used by server/daemon.c.
Definition: global.h:144
struct_map_in_quest_list quests
Definition: mapper.c:279
struct struct_equipment struct_equipment
One special item (weapon, shield, ...).
Error, serious thing.
Definition: logger.h:11
object * find_skill_by_number(object *who, int skillno)
This returns the skill pointer of the given name (the one that accumulates exp, has the level...
Definition: mapper.c:3965
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:365
static void free_equipment(struct_equipment *equip)
Frees a struct_equipment.
Definition: mapper.c:549
static void find_maps(const char *from)
Recursively find all all maps in a directory.
Definition: mapper.c:3222
static int region_allocated
Allocated size of regions.
Definition: mapper.c:461
char * slaying
Slaying value.
Definition: mapper.c:496
static int tiled_map_need_pic(struct_map_info *map)
Definition: mapper.c:2869
static int elevation_min
Maximal elevation found.
Definition: mapper.c:477
static char * map_exit_to_template
Map template: one exit leading to this map.
Definition: mapper.c:391
One player.
Definition: player.h:92
static char * level_map_template
Definition: mapper.c:413
archetype * find_archetype(const char *name)
Finds, using the hashtable, which archetype matches the given name.
Definition: arch.c:695
static void init_map_list(struct_map_list *list)
Initialises a list structure.
Definition: mapper.c:509
#define FLAG_DAMNED
The object is very cursed.
Definition: define.h:318
#define FLAG_IS_FLOOR
Can&#39;t see what&#39;s underneath this object.
Definition: define.h:303
#define FLAG_UNPAID
Object hasn&#39;t been paid for yet.
Definition: define.h:236
#define FLAG_IS_LINKED
The object is linked with other objects.
Definition: define.h:316
struct_map_info * map
Linked map.
Definition: mapper.c:1184
#define S_MAX
Definition: mapper.c:492
static char * map_no_exit_to_template
World map template: no exit leading to this map.
Definition: mapper.c:389
int init_regions(void)
Initialises regions from the regions file.
Definition: region.c:292
static char * region_template
Region page template.
Definition: mapper.c:404
See Ring.
Definition: object.h:185
static int warn_no_path
Whether to warn of exits without a path.
Definition: mapper.c:449
static void process_map_lore(struct_map_info *map)
Extracts from the map&#39;s lore quest information if found.
Definition: mapper.c:1329
face_info * faces
images in this faceset
Definition: image.h:24
static char * region_letter_template
One letter for the region.
Definition: mapper.c:405
static int generate_index
Whether to do the map index or not.
Definition: mapper.c:373
static char * world_map_template
One map in a row.
Definition: mapper.c:383
List of maps.
Definition: mapper.c:263
int tiled_y_from
Definition: mapper.c:290
void esrv_update_spells(player *pl)
This looks for any spells the player may have that have changed their stats.
Definition: mapper.c:3975
void object_give_identified_properties(object *op)
Ensure op has all its "identified" properties set.
Definition: item.c:1375
#define SET_FLAG(xyz, p)
Definition: define.h:223
static int sort_mapname(const void *left, const void *right)
Sorts the strings according to the last part of the filename (after the last /).
Definition: mapper.c:1086
static char * map_lore_template
Map template: lore.
Definition: mapper.c:392
static char ** regions_link
Definition: mapper.c:482
struct struct_map_in_quest ** list
Definition: mapper.c:257
unsigned char uint8_t
Definition: win32.h:161
See Scroll.
Definition: object.h:221
Region information.
Definition: mapper.c:452
static struct_equipment ** special_equipment
Special equipment list.
Definition: mapper.c:309
static int tileset
Tileset to use to generate pics.
Definition: mapper.c:379
void make_path_to_file(const char *filename)
Checks if any directories in the given path doesn&#39;t exist, and creates if necessary.
Definition: porting.c:312
static int compare_map_info(const struct_map_info *left, const struct_map_info *right)
Compares struct_map_info according to the map name or the path if equal.
Definition: mapper.c:1114
struct_race_list monsters
Definition: mapper.c:283
static void write_tiled_maps(void)
Outputs all tiled map pages.
Definition: mapper.c:3042
static void add_map_to_region(struct_map_info *map, region *reg)
Links a map to a region.
Definition: mapper.c:1676
#define strdup_local
Definition: compat.h:25
sstring artifact
If set, the item is the artifact with this name and the matching type.
Definition: object.h:314
struct_map_list maps[S_MAX]
Definition: mapper.c:497
static int jpeg_quality
Quality for jpg pictures.
Definition: mapper.c:443
char * lore
Definition: mapper.c:274
struct_map_list tiled_maps
Definition: mapper.c:281
static char * cat_template(char *source, char *add)
Concatenates a string, and free concatenated string.
Definition: mapper.c:908
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:246
int count
Number of races.
Definition: mapper.c:251
char * name
Quest&#39;s name.
Definition: mapper.c:1191
static int equipment_allocated
Allocated items in special_equipment.
Definition: mapper.c:313
static void add_slaying(struct_map_info *map, object *item)
Adds the item&#39;s information to the map.
Definition: mapper.c:1821
static struct_equipment * ensure_unique(struct_equipment *item)
Searches the item list for an identical item, except maps.
Definition: mapper.c:563
char * create_pathname(const char *name, char *buf, size_t size)
Get the full path to a map file.
Definition: map.c:104
static char * map_with_exit_template
Map template: exit template.
Definition: mapper.c:387
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.c:57
uint32_t in_memory
Combination of IN_MEMORY_xxx flags.
Definition: map.h:345
mapstruct * ready_map_name(const char *name, int flags)
Makes sure the given map is loaded and swapped in.
Definition: map.c:1803
int tiled_x_from
Definition: mapper.c:290
static void write_maps_index(void)
Generates global map index, file maps.html.
Definition: mapper.c:2312
static char * do_template(const char *template, const char **vars, const char **values)
Processes a template.
Definition: mapper.c:979
JPG.
Definition: mapper.c:430
static int rawmaps
Whether to generate raw pics or instancied ones.
Definition: mapper.c:446
void dragon_ability_gain(object *ob, int x, int y)
When a dragon-player gains a new stage of evolution, he gets some treasure.
Definition: mapper.c:3959
void rod_adjust(object *rod)
Adjusts rod attributes.
Definition: mapper.c:3978
static char * map_with_quests_template
Definition: mapper.c:420
See Spellbook.
Definition: object.h:203
const char * object_get_value(const object *op, const char *const key)
Get an extra value by key.
Definition: object.c:4246
struct treasureliststruct * randomitems
Items to be generated.
Definition: object.h:385
static void write_maps_by_level(void)
Outputs the list of maps sorted by level.
Definition: mapper.c:3054
#define MAP_HEIGHT(m)
Map height.
Definition: map.h:80
static struct_slaying_info ** slaying_info
Found slaying fields.
Definition: mapper.c:500
object clone
An object from which to do object_copy()
Definition: object.h:470
void set_darkness_map(mapstruct *m)
Set the darkness level for a map, based on the time of the day.
Definition: mapper.c:3962
struct_map_info * mainmap
Map defining the quest.
Definition: mapper.c:1194
int8_t fallback
Whether, in the event of a region not existing, this should be the one we fall back on as the default...
Definition: map.h:295
uint32_t reset_time
When this map should reset.
Definition: map.h:332
struct_map_in_quest_list maps
Maps part of this quest.
Definition: mapper.c:1195
static void list_map(const char *path)
Marks specified path as processed.
Definition: mapper.c:1653
const char * slaying
Which race to do double damage to.
Definition: object.h:319
region * get_region_by_map(mapstruct *m)
Gets a region from a map.
Definition: region.c:74
#define IS_WEAPON(op)
Definition: define.h:162
static char * map_no_quest_template
Definition: mapper.c:419
static void init_npc_list(struct_npc_list *list)
Initialise a list of NPCs.
Definition: mapper.c:1477
void init_archetypes(void)
Initialises the internal linked list of archetypes (read from file).
Definition: arch.c:182
static gdImagePtr infomap
World map with exits / roads / blocking / ...
Definition: mapper.c:469
DIR * opendir(const char *)
Opens a directory for reading.
Definition: win32.c:37
Object for applying character class modifications to someone.
Definition: object.h:138
static void merge_tiled_maps(struct_map_info *map, int tile, struct_map_info *tiled_map)
Merge two tiled maps groups.
Definition: mapper.c:1591
void init_globals(void)
Initialises all global variables.
Definition: init.c:272
See Rod.
Definition: object.h:109
static const char * output_extensions[]
Extensions depending on output format.
Definition: mapper.c:434
int is_valid_faceset(int fsn)
Checks specified faceset is valid.
Definition: image.c:563
static void save_picture(FILE *file, gdImagePtr pic)
Saves a map to a file, based on jpg/png settings.
Definition: mapper.c:1710
int64_t exp
Experience.
Definition: living.h:46
static char * map_no_lore_template
Map template: no lore.
Definition: mapper.c:393
static const char * yesno(int value)
Helper to write yes/no.
Definition: mapper.c:3647
#define FREE_OBJ_NO_DESTROY_CALLBACK
Do not run the destroy callback.
Definition: object.h:533
static void do_help(const char *program)
Prints usage information, and exit.
Definition: mapper.c:3530
char * description
Description, from the main map&#39;s lore.
Definition: mapper.c:1192
int count
Number found on map.
Definition: mapper.c:319
void init_library(void)
It is vital that init_library() is called by any functions using this library.
Definition: init.c:201
int number
Unique quest identifier.
Definition: mapper.c:1193
See Button Trigger.
Definition: object.h:132
static void relative_path(const char *from, const char *to, char *result)
Computes the shortest path from one file to another.
Definition: mapper.c:1047
char * maplore
Map lore information.
Definition: map.h:362
static void do_parameters(int argc, char **argv)
Handles command-line parameters.
Definition: mapper.c:3563
static int sort_slaying(const void *left, const void *right)
Helper function to sort an array of struct_slaying_info.
Definition: mapper.c:3408
LogLevel debug
Default debugging level.
Definition: global.h:240
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Sends message to player(s).
Definition: mapper.c:3935
See Amulet.
Definition: object.h:139
static int color_unlinked_exit
Color for exits without a path set.
Definition: mapper.c:470
#define MAX(x, y)
Definition: compat.h:20
static void write_npc_list(void)
Write the list of all found NPCs in maps.
Definition: mapper.c:3457
const char * name
NPC&#39;s name.
Definition: mapper.c:236
static struct struct_region_info ** regions
Found regions.
Definition: mapper.c:459
static void write_quests_page(void)
Writes the global quests page.
Definition: mapper.c:1402
struct struct_race_list struct_race_list
Collection of races.
static void fix_tiled_map_monsters(void)
Makes all monsters point to tiled maps instead of map when appliable, and merge map monster to tiled ...
Definition: mapper.c:2829
static void process_map(struct_map_info *info)
Processes a map.
Definition: mapper.c:1863
Definition: win32.h:110
Global type definitions and header inclusions.
static struct_race_list races
Monsters found in maps.
Definition: mapper.c:323
#define S_KEY
Definition: mapper.c:488
static int is_special_equipment(object *item)
Definition: mapper.c:517
const char * message
NPC&#39;s message.
Definition: mapper.c:237
static int regions_link_count
Definition: mapper.c:483
int main(int argc, char **argv)
Definition: mapper.c:3651
struct struct_quest * quest
Point back to the quest.
Definition: mapper.c:1186
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:465
static void dump_unused_maps(void)
Writes the list of unused maps, maps found in the directories but not linked from the other maps...
Definition: mapper.c:3267
struct_map_list exits_to
Definition: mapper.c:278
See Wand & Staff.
Definition: object.h:220
static int slaying_allocated
Allocated size of slaying_info.
Definition: mapper.c:502
#define MIN(x, y)
Definition: compat.h:17
unsigned int nrofpixmaps
Number of bitmaps loaded from the "bmaps" file.
Definition: image.c:45
static char * quest_map_template
Definition: mapper.c:417
int16_t hp
Hit Points.
Definition: living.h:39
static void init_race_list(struct_race_list *list)
Blanks a struct_race_list.
Definition: mapper.c:330
One special item (weapon, shield, ...).
Definition: mapper.c:301
void init_formulae(void)
Builds up the lists of formula from the file in the libdir.
Definition: recipe.c:161
struct_npc_list readable
Definition: mapper.c:286
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
This calls the appropriate treasure creation function.
Definition: treasure.c:490
static int color_linked_exit
Exit leading to another map.
Definition: mapper.c:471
#define MOVE_ALL
Mask of all movement types.
Definition: define.h:413
static void define_quest(const char *name, struct_map_info *mainmap, const char *description)
Sets the main map for a quest.
Definition: mapper.c:1310
output_format_type
Map output formats.
Definition: mapper.c:428
region * reg
Region.
Definition: mapper.c:453
const char * get_region_longname(const region *r)
Gets the longname of a region.
Definition: region.c:217
static void add_map_to_quest(struct_map_info *map, const char *name, const char *description)
Links a map to a quest.
Definition: mapper.c:1258
One quest.
Definition: mapper.c:1190
static int color_slowing
Slows movement.
Definition: mapper.c:474
char * name
Name of map as given by its creator.
Definition: map.h:328
static int sort_map_info(const void *left, const void *right)
Sorts the struct_map_info according to the map name or the path if equal.
Definition: mapper.c:1139
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
Definition: mapper.c:3972
#define MAP_IN_MEMORY
Map is fully loaded.
Definition: map.h:130
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1368
const char * title
Of foo, etc.
Definition: object.h:317
static int sort_struct_map_in_quest(const void *left, const void *right)
Sorts 2 struct_map_in_quest, on the map&#39;s name or path.
Definition: mapper.c:1280
int16_t y
Position in the map for this object.
Definition: object.h:326
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.c:1921
static void add_to_struct_map_in_quest_list(struct_map_in_quest_list *list, struct_map_in_quest *item)
Definition: mapper.c:1210
char * name
Shortend name of the region as maps refer to it.
Definition: map.h:278
static void write_map_page(struct_map_info *map)
Write a map page.
Definition: mapper.c:2521
#define FREE_OBJ_FREE_INVENTORY
Free inventory objects; if not set, drop inventory.
Definition: object.h:532
#define SIZE
See Sign & Magic Mouth.
Definition: object.h:211
void clean_tmp_files(void)
Remove temporary map files.
Definition: mapper.c:3953
Link between a quest and a map.
Definition: mapper.c:1183
Definition: win32.h:120
static void fix_exits_to_tiled_maps(void)
Changes all exits to maps in a tiled map to point directly to the tiled map.
Definition: mapper.c:2801
See Book.
Definition: object.h:114
static char * map_monster_after_template
Map template: after the monster list.
Definition: mapper.c:398
static int list_unused_maps
If set, program will list maps found in directory but not linked from the first maps.
Definition: mapper.c:463
static char * level_value_template
Definition: mapper.c:412
See Exit.
Definition: object.h:181
const char * name_pl
The plural name of the object.
Definition: object.h:315
static void write_slaying_info(void)
Writes all slaying info to file.
Definition: mapper.c:3418
struct_npc_list npcs
Definition: mapper.c:285
static char * index_template
Index page template.
Definition: mapper.c:400
Image-related structures.
static struct_map_info * create_map_info(void)
Returns an initialised struct_map_info.
Definition: mapper.c:1551
#define S_CONNECT
Definition: mapper.c:491
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.c:2690
static struct_map_list maps_list
Maps to process or found.
Definition: mapper.c:295
static int region_count
Count of regions.
Definition: mapper.c:460
static char * index_letter
Index page template: one letter, including the maps it contains.
Definition: mapper.c:401
static int created_pics
Picture statistics.
Definition: mapper.c:424
static int pics_allocated
Number of created pictures for GD.
Definition: mapper.c:368
See Treasure.
Definition: object.h:110
See Special Key.
Definition: object.h:124
static int is_road(object *item)
Checks if object is considered a road or not.
Definition: mapper.c:775
int allocated
Allocated space.
Definition: mapper.c:252
static void write_one_slaying_info(FILE *file, struct_slaying_info *info, int item, const char *with, const char *without)
Writes all maps of the specified slaying information.
Definition: mapper.c:3377
region * cfregion
Definition: mapper.c:275
void apply_auto_fix(mapstruct *m)
Go through the entire map (only the first time when an original map is loaded) and performs special a...
Definition: mapper.c:4044
static int color_road
Road or equivalent.
Definition: mapper.c:472
static char root[500]
Path to store generated files.
Definition: mapper.c:365
uint8_t * data
Image data.
Definition: image.h:11
#define FLAG_UNAGGRESSIVE
Monster doesn&#39;t attack players.
Definition: define.h:272
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
struct_npc_info ** npc
Definition: mapper.c:243
struct regiondef * next
Pointer to next region, NULL for the last one.
Definition: map.h:277
struct struct_quest struct_quest
One quest.
This is a game region.
Definition: map.h:276
static struct_slaying_info * get_slaying_struct(const char *slaying)
Returns a struct_slaying_info for specified slaying.
Definition: mapper.c:1775
#define snprintf
Definition: win32.h:46
static char * index_region_template
Region index template.
Definition: mapper.c:408
struct struct_map_info * tiled_group
Definition: mapper.c:288
static int force_pics
To force picture regeneration even if map didn&#39;t change.
Definition: mapper.c:372
static char * map_monster_before_template
Map template: before the monster list.
Definition: mapper.c:395
Information about a NPC with a custom message.
Definition: mapper.c:235
const artifact * find_artifact(const object *op, const char *name)
Searches and returns a specific artifact, NULL if not found.
Definition: artifact.c:640
region * get_region_struct(void)
Allocates and zeros a region struct, this isn&#39;t free()&#39;d anywhere, so might be a memory leak...
Definition: region.c:325
#define FLAG_IDENTIFIED
Player knows full info about item.
Definition: define.h:261
void emergency_save(int x)
Save all players.
Definition: mapper.c:3950
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Combines the 2 paths.
Definition: path.c:172
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:712
int is_world
If set, this region has at least one map part of the world, thus region name should be written...
Definition: mapper.c:456
char * name
Monster&#39;s name.
Definition: mapper.c:318
struct struct_map_info * tiles[4]
Definition: mapper.c:291
static char * map_monster_between_template
Map template: between each monster.
Definition: mapper.c:396
static void write_readable_list(void)
Write the list of all found SIGN and BOOK in maps.
Definition: mapper.c:3493
static void do_tiled_map_picture(struct_map_info *map)
Generates the large and small pictures for a tiled map.
Definition: mapper.c:2901
struct artifactstruct artifact
This is one artifact, ie one special item.
const char * name
The name of the object, obviously...
Definition: object.h:311
struct obj * env
Pointer to the object which is the environment.
Definition: object.h:293
static char * map_monster_one_template
Map template: one monster.
Definition: mapper.c:397
static void write_equipment_index(void)
Writes the item page.
Definition: mapper.c:3132
static int ** elevation_info
All elevation spots in the "world_" maps.
Definition: mapper.c:476
int power
Item power as declared by the item itself.
Definition: mapper.c:303
static int elevation_max
Lowest elevation found.
Definition: mapper.c:478
static char * index_region_region_template
One region in the region index template.
Definition: mapper.c:409
#define EXIT_PATH(xyz)
Definition: define.h:455
char * tile_path[4]
Path to adjoining maps.
Definition: map.h:363
char * name
Item&#39;s name.
Definition: mapper.c:302
#define FLAG_IS_A_TEMPLATE
Object has no ingame life until instantiated.
Definition: define.h:375
static char * level_template
Definition: mapper.c:411
struct struct_npc_list struct_npc_list
List of NPCs with a custom message.
uint32_t nrof
How many of the objects.
Definition: object.h:333
static gdImagePtr * gdfaces
Definition: mapper.c:232
Map information.
Definition: mapper.c:270
See Potion.
Definition: object.h:111
int8_t item_power
Power rating of the object.
Definition: object.h:362
static enum output_format_type output_format
Selected output format.
Definition: mapper.c:440
static void check_slaying_inventory(struct_map_info *map, object *item)
Recursively checks if the object should be considered for slaying information.
Definition: mapper.c:1847
static void add_one_item(object *item, struct_map_info *map)
Adds an item to the list of special items.
Definition: mapper.c:602
static char * world_template
World map template.
Definition: mapper.c:381
static int world_map
If set, will generate a world map.
Definition: mapper.c:377
static void fix_map_names(void)
Ensures all maps have a name (if there was a limit to map processing, some maps will have a NULL name...
Definition: mapper.c:2693
void read_client_images(void)
Loads all the image types into memory.
Definition: image.c:448
char d_name[_MAX_FNAME+1]
Definition: win32.h:114
static void add_monster(object *monster, struct_map_info *map)
Adds a monster to the monster list.
Definition: mapper.c:740
See Spell.
Definition: object.h:214
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
static int quests_count
Count of quests.
Definition: mapper.c:1200
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
static int sortbyname(const void *a, const void *b)
Sort values alphabetically Used by qsort to sort values alphabetically.
Definition: mapper.c:894
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:594
int execute_global_event(int eventcode,...)
Definition: mapper.c:3985
static char * index_quest_template
Definition: mapper.c:415
static void add_map_to_slaying(struct_slaying_info *info, int item, struct_map_info *map)
Adds the specified map to the slaying information if not already present.
Definition: mapper.c:1809
int min_monster
Definition: mapper.c:276
static int regions_link_allocated
Definition: mapper.c:484
static int size_small
Tile size for small map.
Definition: mapper.c:374
static void add_region_link(mapstruct *source, mapstruct *dest, const char *linkname)
Creates a link between two maps if they are on different regions.
Definition: mapper.c:1726
See Locked Door.
Definition: object.h:123
void init_readable(void)
Initialize linked lists utilized by message functions in tailor_readable_ob()
Definition: readable.c:1005
void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy)
Computes the size of a multitile object.
Definition: object.c:4626
static void create_destination(void)
Ensures destination directory exists.
Definition: mapper.c:3631
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
static int sort_race(const void *a, const void *b)
Sort 2 struct_race.
Definition: mapper.c:762
This is one artifact, ie one special item.
Definition: artifact.h:14
static int sort_region(const void *left, const void *right)
Sorts an array of struct_region_info by region name.
Definition: mapper.c:1174
#define IS_SHIELD(op)
Definition: define.h:169
static char * map_exit_template
Map template: one exit.
Definition: mapper.c:388
void give_artifact_abilities(object *op, const object *artifact)
Fixes the given object, giving it the abilities and titles it should have due to the second artifact-...
Definition: artifact.c:203
See Magic Wall.
Definition: object.h:168
int16_t x
Definition: object.h:326
MoveType move_slow
Movement types this slows down.
Definition: object.h:429
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *txt)
Dummy functions to link the library.
Definition: mapper.c:3931
char * filename
Definition: mapper.c:273
char * description
Description associated with the map for the quest.
Definition: mapper.c:1185
slaying information.
Definition: mapper.c:495
int calc_item_power(const object *op)
This takes an object &#39;op&#39; and figures out what its item_power rating should be.
Definition: item.c:246
struct struct_map_in_quest struct_map_in_quest
Link between a quest and a map.
static void write_all_regions(void)
Generates all map indexes for a region.
Definition: mapper.c:2300
void move_firewall(object *ob)
Move for FIREWALL.
Definition: mapper.c:3947
#define tolower(C)
Simple macro to convert a letter to lowercase.
Definition: c_new.c:29
static void write_slaying_map_name(FILE *file, struct_map_info *map)
Helper function to write a map to a file with its link and full path.
Definition: mapper.c:3359
void esrv_send_item(object *ob, object *obx)
Sends item&#39;s info to player.
Definition: mapper.c:3956
static int map_limit
Maximum number of maps to browse, -1 for all.
Definition: mapper.c:375
See Container.
Definition: object.h:231
uint16_t difficulty
What level the player should be to play here.
Definition: map.h:343
static char * map_template
Map template.
Definition: mapper.c:385
struct_map_list maps_list
Maps in the region.
Definition: mapper.c:454
static const flag_definition flags[]
Flag mapping.
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:765
static char * region_map_template
Region page template: one map.
Definition: mapper.c:406
PNG, default value.
Definition: mapper.c:429
static int sort_equipment(const void *a, const void *b)
Sort 2 struct_equipment, first on item power then name.
Definition: mapper.c:693
const char * sstring
Strings that should be manipulated through add_string() and free_string().
Definition: global.h:40
static char * map_no_monster_template
Map template: no monster.
Definition: mapper.c:394
char * diff
Result of get_ob_diff() with the item&#39;s clone.
Definition: mapper.c:305
#define FLAG_CURSED
The object is cursed.
Definition: define.h:317
See Player.
Definition: object.h:107
unsigned int uint32_t
Definition: win32.h:162
const char * datadir
Read only data files.
Definition: global.h:244
int apply_auto(object *op)
Map was just loaded, handle op&#39;s initialization.
Definition: mapper.c:3992
#define FLAG_AUTO_APPLY
Will be applied when created.
Definition: define.h:250
static void write_regions_link(void)
Write the .dot file representing links between regions.
Definition: mapper.c:3332
See Altar.
Definition: object.h:122
struct struct_region_info struct_region_info
Region information.
face_sets facesets[MAX_FACE_SETS]
All facesets.
Definition: image.c:47
struct struct_race ** races
Races on the list.
Definition: mapper.c:250
static void init_struct_map_in_quest_list(struct_map_in_quest_list *list)
Definition: mapper.c:1204
living stats
Str, Con, Dex, etc.
Definition: object.h:368
static int slaying_count
Count of items in slaying_info.
Definition: mapper.c:501
static int do_regions_link
Definition: mapper.c:481
struct archt * arch
Pointer to archetype.
Definition: object.h:412
See Shop Floor.
Definition: object.h:183
#define MAP_WIDTH(m)
Map width.
Definition: map.h:78
static int show_maps
If set, will generate much information on map loaded.
Definition: mapper.c:376
static void write_world_info(void)
Writes the exit information world map.
Definition: mapper.c:3290
static int equipment_count
Number of items in special_equipment.
Definition: mapper.c:311
static void check_equipment(object *item, struct_map_info *map)
Checks if item and its inventory are worthy to be listed.
Definition: mapper.c:676
static char * index_map
Index page template: one map.
Definition: mapper.c:402
const char * mapdir
Where the map files are.
Definition: global.h:247
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
struct Settings settings
Server settings.
Definition: init.c:40
static void write_all_maps(void)
Ensures all maps have a name, and writes all map pages.
Definition: mapper.c:2857
Utility structure to group map-quest link structure.
Definition: mapper.c:256
void object_free2(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1391
struct dirent * readdir(DIR *)
Returns the next file/directory for specified directory handle, obtained through a call to opendir()...
Definition: win32.c:75
See Timed Gate.
Definition: object.h:128
void init_gods(void)
This takes a look at all of the archetypes to find the objects which correspond to the GODS (type GOD...
Definition: holy.c:53
signed int int32_t
Definition: win32.h:159
void delete_map(mapstruct *m)
Frees the map, including the mapstruct.
Definition: map.c:1741
int execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Definition: mapper.c:3981
List of NPCs with a custom message.
Definition: mapper.c:242
static const char * ignore_path[]
Directories to ignore for map search.
Definition: mapper.c:3198
void esrv_del_item(player *pl, object *ob)
Tells the client to delete an item.
Definition: mapper.c:3969
const char * msg
If this is a book/sign/magic mouth/etc.
Definition: object.h:322
int calc_power
Item power calculated via calc_item_power().
Definition: mapper.c:304
EXTERN char first_map_path[MAX_BUF]
The start-level.
Definition: global.h:153
static void fix_tiled_map(void)
Ensures all tiled maps have a name, a region, a filename and a path.
Definition: mapper.c:2713
static int get_elevation_color(int elevation, gdImagePtr elevationmap)
Gets the color for an elevation.
Definition: mapper.c:825
static void do_exit_map(mapstruct *map)
Proceses exit / road / blocking information for specified map into the global infomap map...
Definition: mapper.c:840
static struct_map_list tiled_map_list
Pseudo-maps grouping other maps.
Definition: mapper.c:298
object * identify(object *op)
Identifies an item.
Definition: item.c:1437
static char * do_map_index(const char *dest, struct_map_list *maps_list, const char *template_page, const char *template_letter, const char *template_map, const char **vars, const char **values)
Creates the page for a map index.
Definition: mapper.c:2132
static struct_equipment * get_equipment(void)
Gets an empty struct_equipment.
Definition: mapper.c:536
int strcasecmp(const char *s1, const char *s2)
Case-insensitive comparaison of strings.
Definition: porting.c:256
static void read_template(const char *name, char **buffer)
Reads a file in memory.
Definition: mapper.c:927
#define FLAG_MONSTER
Will attack players.
Definition: define.h:245
static char * world_row_template
One row in the world map.
Definition: mapper.c:382
int max_monster
Definition: mapper.c:276
int closedir(DIR *)
Dispose of a directory handle.
Definition: win32.c:108
char * strdup(const char *str)
Portable implementation of strdup(3).
Definition: porting.c:200
static char * map_one_quest_template
Definition: mapper.c:421
struct obj * head
Points to the main object of a large body.
Definition: object.h:296
#define S_ISDIR(x)
Definition: win32.h:69
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
char * name
Definition: mapper.c:272
struct struct_race struct_race
One monster race in the maps.
static struct_race * get_race(const char *name)
Returns the race for specified name.
Definition: mapper.c:711
static int world_exit_info
If set, will generate a world map of exits.
Definition: mapper.c:378
EXTERN region * first_region
First region.
Definition: global.h:119
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:758
static struct_map_info * create_tiled_map(void)
Create a new tiled map and link it to the tiled map list.
Definition: mapper.c:1573
MoveType move_block
What movement types this blocks.
Definition: object.h:425
static int color_blocking
Block all movement.
Definition: mapper.c:473
struct struct_map_info ** maps
Definition: mapper.c:264
#define IS_ARMOR(op)
Definition: define.h:165
static char * map_no_exit_template
World map template: no exit.
Definition: mapper.c:386
int check_trigger(object *op, object *cause)
Definition: button.c:523
static char * map_with_exit_to_template
Map template: exits leading to this map.
Definition: mapper.c:390
struct_map_list origin
Maps to find said monster.
Definition: mapper.c:320
int get_face_fallback(int faceset, int imageno)
This returns the set we will actually use when sending a face.
Definition: image.c:602
One monster race in the maps.
Definition: mapper.c:317
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.c:25
object * item
Special values of the artifact.
Definition: artifact.h:15
static int sort_map_info_by_level(const void *left, const void *right)
Sorts the struct_map_info according to the map&#39;s level, and if equal the name or the path...
Definition: mapper.c:1155
object * generate_treasure(treasurelist *t, int difficulty)
Generate a treasure from a list generating a single item.
Definition: treasure.c:518
static int found_maps_count
Number of items in found_maps.
Definition: mapper.c:465
int sum
Sum of locations, to compute name position.
Definition: mapper.c:455
This is a game-map.
Definition: map.h:325
static void write_world_map(void)
Generates a big world map.
Definition: mapper.c:2375
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Returns a pointer to a static string which contains all variables which are different in the two give...
Definition: object.c:4845
struct_map_list origin
Map(s) this item is found in.
Definition: mapper.c:306
static char ** found_maps
Maps found in directories.
Definition: mapper.c:464
static struct_map_info * get_map_info(const char *path)
Gets or creates if required the info structure for a map.
Definition: mapper.c:1625
static void add_race_to_list(struct_race *race, struct_race_list *list, int check)
Appends a race to a race list.
Definition: mapper.c:346
#define FLAG_NO_PICK
Object can&#39;t be picked up.
Definition: define.h:239
static void write_race_index(void)
Writes the monster information page.
Definition: mapper.c:3165
void do_auto_apply(mapstruct *m)
Definition: mapper.c:3833
static void write_region_page(struct_region_info *reg)
Generates the web page for a region.
Definition: mapper.c:2267
static struct_npc_info * create_npc_info(const object *npc)
Create the struct_npc_info from the specified NPC.
Definition: mapper.c:1490
#define IS_ARROW(op)
Definition: define.h:177
#define S_DOOR
Connection/slaying information.
Definition: mapper.c:487
int16_t level
Level of creature or object.
Definition: object.h:351
struct_map_list exits_from
Definition: mapper.c:277
static int is_blocking(object *item)
Checks if item blocks movement or not.
Definition: mapper.c:811
static void fix_exits_for_map(struct_map_info *current, struct_map_list *from, int is_from)
Changes for the list all maps to the tiled map they are part of, if applicable.
Definition: mapper.c:2782
#define VARSADD
void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1)
Writes to everyone on the specified map.
Definition: mapper.c:3943
char * longname
Official title of the region, this might be defined to be the same as name.
Definition: map.h:291
static void write_tiled_map_page(struct_map_info *map)
Writes the page for a tiled map group.
Definition: mapper.c:3032
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.c:571
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.c:1129
static struct_quest ** quests
All quests in the game.
Definition: mapper.c:1198
static char * quest_template
Definition: mapper.c:416
int pic_was_done
Definition: mapper.c:276
See Teleporter.
Definition: object.h:141
static void add_map(struct_map_info *info, struct_map_list *list)
Adds a map to specified array, if it isn&#39;t already.
Definition: mapper.c:1530
static int cached_pics
Non recreated pics.
Definition: mapper.c:425
const char * name
More definite name, like "generate_kobold".
Definition: object.h:466
#define S_CONTAINER
Definition: mapper.c:489
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.c:76
static void add_npc_to_map(struct_npc_list *list, const object *npc)
Add the specified NPC to the list.
Definition: mapper.c:1508
static int is_slaying(object *item)
Is the slaying field relevant for this item?
Definition: mapper.c:1762
void init_artifacts(void)
Builds up the lists of artifacts from the file in the libdir.
Definition: artifact.c:513
Collection of races.
Definition: mapper.c:249
#define HAS_RANDOM_ITEMS(op)
This return TRUE if object has still randomitems which could be expanded.
Definition: define.h:183
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:705
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.c:1654
const char * get_region_msg(const region *r)
Gets a message for a region.
Definition: region.c:238
static struct_quest * get_quest_info(const char *name)
Gets the information for a quest, create the field if needed.
Definition: mapper.c:1226
static int quests_allocated
Allocated items in quests.
Definition: mapper.c:1202
static int generate_pics
Whether to generate the picture or not.
Definition: mapper.c:371
static void write_region_index(void)
Generates region index.
Definition: mapper.c:2334
struct regiondef region
This is a game region.
char * path
Definition: mapper.c:271
int y
Coordinates in the map.
Definition: mapper.c:238
b.t.
Definition: object.h:169
struct struct_map_info struct_map_info
Map information.
static const char * ignore_name[]
File names to ignore for map search.
Definition: mapper.c:3209
static int found_maps_allocated
Allocated size of found_maps.
Definition: mapper.c:466