Crossfire Server, Branches 1.12  R18729
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 <time.h>
214 #include <stdio.h>
215 /* For strcasecmp(). */
216 #include <strings.h>
217 
218 #include <global.h>
219 #include <sproto.h>
220 #include <image.h>
221 
222 #include <gd.h>
223 #include <gdfonts.h>
224 #include <gdfontl.h>
225 #include <gdfontg.h>
226 
227 static gdImagePtr *gdfaces;
228 
229 extern int nrofpixmaps; /* Found in common/image.c */
230 
232 typedef struct struct_npc_info {
233  const char *name;
234  const char *message;
235  int x, y;
237 
239 typedef struct struct_npc_list {
241  int count;
244 
246 typedef struct struct_race_list {
247  struct struct_race **races;
248  int count;
249  int allocated;
251 
253 typedef struct {
255  int count;
258 
260 typedef struct {
262  int count;
265 
267 typedef struct struct_map_info {
268  char *path;
269  char *name;
270  char *filename;
271  char *lore;
277 
279 
281 
283 
285  int height, width;
287  struct struct_map_info *tiles[4];
289 
292 
295 
297 typedef struct struct_equipment {
298  char *name;
299  int power;
301  char *diff;
304 
307 static int equipment_count = 0;
309 static int equipment_allocated = 0;
313 typedef struct struct_race {
314  char *name;
315  int count;
317 } struct_race;
318 
326 static void init_race_list(struct_race_list *list) {
327  list->races = NULL;
328  list->count = 0;
329  list->allocated = 0;
330 }
331 
342 static void add_race_to_list(struct_race *race, struct_race_list *list, int check) {
343  if (check) {
344  int test;
345 
346  for (test = 0; test < list->count; test++) {
347  if (list->races[test] == race)
348  return;
349  }
350  }
351 
352  if (list->allocated == list->count) {
353  list->allocated += 50;
354  list->races = realloc(list->races, sizeof(struct_race *)*list->allocated);
355  }
356  list->races[list->count] = race;
357  list->count++;
358 }
359 
361 static char root[500];
362 
364 static int pics_allocated;
365 
366 /* Options */
367 static int generate_pics = 1;
368 static int force_pics = 0;
369 static int generate_index = 1;
370 static int size_small = 16;
371 static int map_limit = -1;
372 static int show_maps = 0;
373 static int world_map = 1;
374 static int world_exit_info = 1;
375 static int tileset = 0;
377 static char *world_template;
378 static char *world_row_template;
379 static char *world_map_template;
381 static char *map_template;
382 static char *map_no_exit_template;
384 static char *map_exit_template;
387 static char *map_exit_to_template;
388 static char *map_lore_template;
389 static char *map_no_lore_template;
396 static char *index_template;
397 static char *index_letter;
398 static char *index_map;
400 static char *region_template;
402 static char *region_map_template;
404 static char *index_region_template;
407 static char *level_template;
408 static char *level_value_template;
409 static char *level_map_template;
410 
411 static char *index_quest_template;
412 static char *quest_template;
413 static char *quest_map_template;
414 
418 
420 static int created_pics = 0;
421 static int cached_pics = 0;
425  OF_PNG = 0,
426  OF_JPG = 1
427 };
428 
430 static const char *output_extensions[] = {
431  ".png",
432  ".jpg"
433 };
434 
437 
439 static int jpeg_quality = -1;
440 
442 static int rawmaps = 0;
443 
445 static int warn_no_path = 0;
446 
448 typedef struct struct_region_info {
451  int sum_x, sum_y, sum;
452  int is_world;
454 
455 static struct struct_region_info **regions = NULL;
456 static int region_count = 0;
457 static int region_allocated = 0;
459 static int list_unused_maps = 0;
460 static char **found_maps = NULL;
461 static int found_maps_count = 0;
462 static int found_maps_allocated = 0;
464 /* Path/exit info */
465 static gdImagePtr infomap;
467 static int color_linked_exit;
468 static int color_road;
469 static int color_blocking;
470 static int color_slowing;
472 static int **elevation_info;
473 static int elevation_min;
474 static int elevation_max;
476 /* Links between regions */
477 static int do_regions_link = 0;
478 static char **regions_link;
479 static int regions_link_count = 0;
480 static int regions_link_allocated = 0;
481 
483 #define S_DOOR 0
484 #define S_KEY 1
485 #define S_CONTAINER 2
486 #define S_DETECTOR 3
487 #define S_CONNECT 4
488 #define S_MAX 5
489 
491 typedef struct {
492  char *slaying;
495 
497 static int slaying_count = 0;
498 static int slaying_allocated = 0;
505 static void init_map_list(struct_map_list *list) {
506  list->maps = NULL;
507  list->count = 0;
508  list->allocated = 0;
509 }
510 
511 static void add_map(struct_map_info *info, struct_map_list *list);
512 
513 static int is_special_equipment(object *item) {
514  if (item->name == item->arch->clone.name)
515  return 0;
516  if (QUERY_FLAG(item, FLAG_NO_PICK))
517  return 0;
518  if (item->move_block == MOVE_ALL)
519  return 0;
520 
521  if (IS_SHIELD(item) || IS_WEAPON(item) || IS_ARMOR(item) || IS_ARROW(item) || (item->type == ROD) || (item->type == WAND))
522  return 1;
523 
524  return 0;
525 }
526 
533  struct_equipment *add = calloc(1, sizeof(struct_equipment));
534 
535  init_map_list(&add->origin);
536  return add;
537 }
538 
545 static void free_equipment(struct_equipment *equip) {
546  free(equip->diff);
547  free(equip->name);
548  free(equip);
549 }
550 
560  int check;
561  struct_equipment *comp;
562 
563  for (check = 0; check < equipment_count; check++) {
564  comp = special_equipment[check];
565 
566  if (strcmp(comp->name, item->name))
567  continue;
568  if (comp->power != item->power)
569  continue;
570  if (comp->calc_power != item->calc_power)
571  continue;
572  if (strcmp(comp->diff, item->diff))
573  continue;
574 
575  free_equipment(item);
576  return comp;
577  }
578 
579  if (equipment_count == equipment_allocated) {
580  equipment_allocated += 50;
581  special_equipment = realloc(special_equipment, sizeof(struct_equipment *)*equipment_allocated);
582  }
583  special_equipment[equipment_count] = item;
584  equipment_count++;
585 
586  return item;
587 }
588 
598 static void add_one_item(object *item, struct_map_info *map) {
601  int x, y;
602  sstring name, namepl;
603 
604  x = item->x;
605  y = item->y;
606  name = item->name;
607  namepl = item->name_pl;
608 
609  item->x = item->arch->clone.x;
610  item->y = item->arch->clone.y;
611  item->name = item->arch->clone.name;
612  item->name_pl = item->arch->clone.name_pl;
613  get_ob_diff(bf, item, &item->arch->clone);
614  add->diff = stringbuffer_finish(bf);
615 
616  item->x = x;
617  item->y = y;
618  item->name = name;
619  item->name_pl = namepl;
620 
621  if (add->diff == NULL || strcmp(add->diff, "") == 0) {
622  free_equipment(add);
623  return;
624  }
625 
626  add->name = strdup(item->name);
627  add->power = item->item_power;
628  add->calc_power = calc_item_power(item, 0);
629 
630  add = ensure_unique(add);
631  add_map(map, &add->origin);
632 }
633 
642 static void check_equipment(object *item, struct_map_info *map) {
643  object *inv;
644 
645  if (is_special_equipment(item))
646  add_one_item(item, map);
647 
648  for (inv = item->inv; inv; inv = inv->below) {
649  check_equipment(inv, map);
650  }
651 }
652 
661 static int sort_equipment(const void *a, const void *b) {
662  const struct_equipment *l = *(const struct_equipment **)a;
663  const struct_equipment *r = *(const struct_equipment **)b;
664  int c = l->power-r->power;
665 
666  if (c)
667  return c;
668  return strcasecmp(l->name, r->name);
669 }
670 
679 static struct_race *get_race(const char *name) {
680  int test;
681  struct_race *item;
682 
683  for (test = 0; test < races.count; test++) {
684  if (strcmp(races.races[test]->name, name) == 0) {
685  races.races[test]->count++;
686  return races.races[test];
687  }
688  }
689 
690  item = calloc(1, sizeof(struct_race));
691  item->name = strdup(name);
692  item->count = 1;
693  init_map_list(&item->origin);
694 
695  add_race_to_list(item, &races, 0);
696 
697  return item;
698 }
699 
708 static void add_monster(object *monster, struct_map_info *map) {
709  struct_race *race;
710 
711  if (monster->head && monster != monster->head)
712  return;
713 
714  map->min_monster = MIN(monster->level, map->min_monster);
715  map->max_monster = MAX(monster->level, map->max_monster);
716 
717  race = get_race(monster->name);
718  add_map(map, &race->origin);
719  add_race_to_list(race, &map->monsters, 1);
720 }
721 
730 static int sort_race(const void *a, const void *b) {
731  const struct_race *l = *(const struct_race **)a;
732  const struct_race *r = *(const struct_race **)b;
733  return strcasecmp(l->name, r->name);
734 }
735 
743 static int is_road(object *item) {
744  int test;
745  /* Archetypes used as roads. */
746  const char *roads[] = {
747  "cobblestones",
748  "flagstone",
749  "ice_stone",
750  "snow",
751  NULL };
752  const char *partial[] = {
753  "dirtroad_",
754  NULL };
755 
756  for (test = 0; partial[test] != NULL; test++) {
757  if (strstr(item->arch->name, partial[test]) != NULL)
758  return 1;
759  }
760 
761  if (!QUERY_FLAG(item, FLAG_IS_FLOOR))
762  return 0;
763 
764  for (test = 0; roads[test] != NULL; test++) {
765  if (strcmp(item->arch->name, roads[test]) == 0)
766  return 1;
767  }
768 
769  return 0;
770 }
771 
779 static int is_blocking(object *item) {
780  return item->move_block == MOVE_ALL ? 1 : 0;
781 }
782 
793 static int get_elevation_color(int elevation, gdImagePtr elevationmap) {
794  if (elevation > 0)
795  return gdImageColorResolve(elevationmap, 200*elevation/elevation_max, 0, 0);
796  else
797  return gdImageColorResolve(elevationmap, 0, 0, 200*elevation/elevation_min);
798 }
799 
808 static void do_exit_map(mapstruct *map) {
809  int tx, ty, x, y;
810  object *item, *test;
811 
812  if (sscanf(map->path, "/world/world_%d_%d", &x, &y) != 2)
813  return;
814 
815  x -= 100;
816  y -= 100;
817 
818  for (tx = 0; tx < MAP_WIDTH(map); tx++) {
819  for (ty = 0; ty < MAP_HEIGHT(map); ty++) {
820  item = GET_MAP_OB(map, tx, ty);
821  while (item) {
822  test = item->head ? item->head : item;
823 
824  if (test->type == EXIT || test->type == TELEPORTER) {
825  if (!test->slaying)
826  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_unlinked_exit);
827  else
828  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_linked_exit);
829  } else if (is_road(test))
830  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_road);
831  else if (is_blocking(test)) {
832  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_blocking);
833  /* can't get on the spot, so no need to go on. */
834  break;
835  } else if (test->move_slow != 0)
836  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_slowing);
837 
838  if (item->elevation) {
841  elevation_info[x*50+tx][y*50+ty] = item->elevation;
842  }
843 
844  item = item->above;
845  }
846  }
847  }
848 }
849 
850 void do_auto_apply(mapstruct *m);
851 
862 static int sortbyname(const void *a, const void *b) {
863  return (strcmp(*(const char **)a, *(const char **)b));
864 }
865 
876 static char *cat_template(char *source, char *add) {
877  if (!source)
878  return add;
879  source = realloc(source, strlen(source)+strlen(add)+1);
880  strcat(source, add);
881  free(add);
882  return source;
883 }
884 
895 static void read_template(const char *name, char **buffer) {
896  FILE *file;
897  struct stat info;
898 
899  if (stat(name, &info)) {
900  printf("Couldn't stat template %s!\n", name);
901  exit(1);
902  }
903 
904  (*buffer) = calloc(1, info.st_size+1);
905  if (!(*buffer)) {
906  printf("Template %s calloc failed!\n", name);
907  exit(1);
908  }
909 
910  if (info.st_size == 0) {
911  (*buffer)[0] = '\0';
912  return;
913  }
914 
915  file = fopen(name, "rb");
916  if (!file) {
917  printf("Couldn't open template %s!\n", name);
918  free(*buffer);
919  exit(1);
920  }
921  if (fread(*buffer, info.st_size, 1, file) != 1) {
922  printf("Couldn't read template %s!\n", name);
923  free(*buffer);
924  fclose(file);
925  exit(1);
926  }
927  fclose(file);
928 }
929 
947 static char *do_template(const char *template, const char **vars, const char **values) {
948  int count = 0;
949  const char *sharp = template;
950  int maxlen = 0;
951  int var = 0;
952  char *result;
953  char *current_result;
954  const char *end;
955 
956  while ((sharp = strchr(sharp, '#')) != NULL) {
957  sharp++;
958  count++;
959  }
960  if (!count)
961  return strdup(template);
962  if (count%2) {
963  printf("Malformed template, mismatched #!\n");
964  return strdup(template);
965  }
966 
967  while (vars[var] != NULL) {
968  if (strlen(values[var]) > maxlen)
969  maxlen = strlen(values[var]);
970  var++;
971  }
972  result = calloc(1, strlen(template)+maxlen*(count/2)+1);
973  if (!result)
974  return NULL;
975  current_result = result;
976 
977  sharp = template;
978  while ((sharp = strchr(sharp, '#')) != NULL) {
979  end = strchr(sharp+1, '#');
980  strncpy(current_result, template, sharp-template);
981  if (end == sharp+1) {
982  strcat(current_result, "#");
983  }
984  else {
985  current_result = current_result+strlen(current_result);
986  var = 0;
987  while (vars[var] != NULL && (strncmp(vars[var], sharp+1, end-sharp-1) || (strlen(vars[var]) != end-sharp-1)))
988  /* tag must be the same length, else can take a wrong tag */
989  var++;
990  if (vars[var] == NULL)
991  printf("Wrong tag: %s\n", sharp);
992  else
993  strcpy(current_result, values[var]);
994  }
995  current_result = current_result+strlen(current_result);
996  sharp = end+1;
997  template = sharp;
998  }
999  strcat(current_result, template);
1000  return result;
1001 }
1002 
1015 static void relative_path(const char *from, const char *to, char *result) {
1016  const char *fslash;
1017  const char *rslash;
1018 
1019  result[0] = '\0';
1020 
1021  fslash = strchr(from+1, '/');
1022  if (!fslash) {
1023  strcpy(result, to+1);
1024  return;
1025  }
1026 
1027  rslash = strchr(to+1, '/');
1028  while (fslash && rslash && (fslash-from == rslash-to) && strncmp(from, to, fslash-from+1) == 0) {
1029  from = fslash+1;
1030  to = rslash+1;
1031  fslash = strchr(fslash+1, '/');
1032  rslash = strchr(rslash+1, '/');
1033  }
1034 
1035  while (fslash) {
1036  strcat(result, "../");
1037  fslash = strchr(fslash+1, '/');
1038  }
1039  if (strlen(result) && result[strlen(result)-1] == '/' && *to == '/')
1040  result[strlen(result)-1] = '\0';
1041  strcat(result, to);
1042 }
1043 
1054 static int sort_mapname(const void *left, const void *right) {
1055  const char *l = *(const char **)left;
1056  const char *r = *(const char **)right;
1057  const char *sl = strrchr(l, '/');
1058  const char *sr = strrchr(r, '/');
1059  int c;
1060 
1061  if (!sl)
1062  sl = l;
1063  if (!sr)
1064  sr = r;
1065  c = strcasecmp(sl, sr);
1066  if (c)
1067  return c;
1068 
1069  return strcasecmp(l, r);
1070 }
1071 
1082 static int compare_map_info(const struct_map_info *left, const struct_map_info *right) {
1083  int c;
1084 
1085  if (left->tiled_group)
1086  left = left->tiled_group;
1087  if (right->tiled_group)
1088  right = right->tiled_group;
1089 
1090  c = strcasecmp(left->name, right->name);
1091  if (c)
1092  return c;
1093 
1094  return strcasecmp(left->path, right->path);
1095 }
1096 
1107 static int sort_map_info(const void *left, const void *right) {
1108  const struct_map_info *l = *(const struct_map_info **)left;
1109  const struct_map_info *r = *(const struct_map_info **)right;
1110  return compare_map_info(l, r);
1111 }
1112 
1123 static int sort_map_info_by_level(const void *left, const void *right) {
1124  const struct_map_info *l = *(const struct_map_info **)left;
1125  const struct_map_info *r = *(const struct_map_info **)right;
1126  int c = l->level-r->level;
1127  if (c)
1128  return c;
1129  return compare_map_info(l, r);
1130 }
1131 
1142 static int sort_region(const void *left, const void *right) {
1143  return strcmp((*((struct_region_info **)left))->reg->name, (*((struct_region_info **)right))->reg->name);
1144 }
1145 
1146 /************************************
1147  Start of quest-related definitions.
1148 ************************************/
1149 
1151 typedef struct struct_map_in_quest {
1153  char *description;
1156 
1158 typedef struct struct_quest {
1159  char *name;
1160  char *description;
1161  int number;
1164 } struct_quest;
1165 
1166 static struct_quest **quests = NULL;
1168 static int quests_count = 0;
1170 static int quests_allocated = 0;
1173  list->list = NULL;
1174  list->count = 0;
1175  list->allocated = 0;
1176 }
1177 
1179  if (list->count == list->allocated) {
1180  list->allocated += 10;
1181  list->list = realloc(list->list, sizeof(struct_map_in_quest *)*list->allocated);
1182  }
1183  list->list[list->count++] = item;
1184 }
1185 
1194 static struct_quest *get_quest_info(const char *name) {
1195  int test;
1196  struct_quest *add;
1197 
1198  for (test = 0; test < quests_count; test++) {
1199  if (strcmp(quests[test]->name, name) == 0)
1200  return quests[test];
1201  }
1202 
1203  if (quests_count == quests_allocated) {
1204  quests_allocated += 10;
1205  quests = realloc(quests, sizeof(struct_quest *)*quests_allocated);
1206  }
1207  add = calloc(1, sizeof(struct_quest));
1208  add->name = strdup(name);
1209  add->number = quests_count;
1211  quests[quests_count] = add;
1212  quests_count++;
1213  return add;
1214 }
1215 
1226 static void add_map_to_quest(struct_map_info *map, const char *name, const char *description) {
1227  struct_map_in_quest *add;
1228  struct_quest *quest = get_quest_info(name);
1229 
1230  add = calloc(1, sizeof(struct_map_in_quest));
1231  add->map = map;
1232  add->quest = quest;
1233  add->description = strdup(description);
1234  while (strlen(add->description) && add->description[strlen(add->description)-1] == '\n')
1235  add->description[strlen(add->description)-1] = '\0';
1236  add_to_struct_map_in_quest_list(&quest->maps, add);
1238 }
1239 
1248 static int sort_struct_map_in_quest(const void *left, const void *right) {
1249  int c;
1250 
1251  const struct_map_in_quest *l = *(const struct_map_in_quest **)left;
1252  const struct_map_in_quest *r = *(const struct_map_in_quest **)right;
1253  const struct_map_info *ml = l->map;
1254  const struct_map_info *mr = r->map;
1255 
1256  if (ml->tiled_group)
1257  ml = ml->tiled_group;
1258  if (mr->tiled_group)
1259  mr = mr->tiled_group;
1260 
1261  c = strcasecmp(ml->name, mr->name);
1262  if (c)
1263  return c;
1264 
1265  return strcasecmp(ml->path, mr->path);
1266 }
1267 
1278 static void define_quest(const char *name, struct_map_info *mainmap, const char *description) {
1279  struct_quest *quest = get_quest_info(name);
1280 
1281  if (quest->description || quest->mainmap) {
1282  printf("warning, multiple quest definition for %s, found in %s and %s.\n", quest->name, quest->mainmap ? quest->mainmap->path : "(unknown map)", mainmap->path);
1283  return;
1284  }
1285  quest->description = strdup(description);
1286  while (strlen(quest->description) && quest->description[strlen(quest->description)-1] == '\n')
1287  quest->description[strlen(quest->description)-1] = '\0';
1288  quest->mainmap = mainmap;
1289 }
1290 
1298  char *start, *end, *next;
1299  char name[500];
1300  char description[500];
1301 
1302  start = strstr(map->lore, "@def");
1303  while (start) {
1304  description[0] = '\0';
1305  /* find name */
1306  end = strstr(start, "\n");
1307  if (end) {
1308  strncpy(name, start+5, end-start-5);
1309  name[end-start-5] = '\0';
1310  next = end+1;
1311  end = strstr(next, "@end");
1312  if (end) {
1313  strncpy(description, next, end-next);
1314  description[end-next] = '\0';
1315  /* need to erase the text. */
1316  memcpy(start, end+4, strlen(map->lore)-(end-start+3));
1317  end = start;
1318  }
1319  else {
1320  strcpy(description, next);
1321  *start = '\0';
1322  end = NULL;
1323  }
1324  } else {
1325  strcpy(name, start);
1326  *start = '\0';
1327  end = NULL;
1328  }
1329 
1330  define_quest(name, map, description);
1331  start = end ? strstr(end, "@def") : NULL;
1332  }
1333 
1334  start = strstr(map->lore, "@quest");
1335  while (start) {
1336  description[0] = '\0';
1337  /* find name */
1338  end = strstr(start, "\n");
1339  if (end) {
1340  strncpy(name, start+7, end-start-7);
1341  name[end-start-7] = '\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  add_map_to_quest(map, name, description);
1363  start = end ? strstr(end, "@quest") : NULL;
1364  }
1365 }
1366 
1370 static void write_quests_page(void) {
1371  int quest, map;
1372  FILE *out;
1373  char path[500];
1374  char mappath[500];
1375  char mainmappath[500];
1376  char questid[500];
1377  const char *map_vars[] = { "MAPPATH", "MAPNAME", "MAPTEXT", NULL };
1378  const char *map_vals[] = { mappath, NULL, NULL, NULL };
1379  const char *quest_vars[] = { "QUESTNAME", "QUESTTEXT", "QUESTMAPS", "QUESTID", "MAINMAPPATH", "MAINMAPNAME", NULL };
1380  const char *quest_vals[] = { NULL, NULL, NULL, questid, mainmappath, NULL, NULL };
1381  const char *idx_vars[] = { "QUESTS", NULL };
1382  const char *idx_vals[] = { NULL, NULL };
1383  char *text_map = NULL;
1384  char *text_quest = NULL;
1385  char *text_idx = NULL;
1386 
1387  printf("Writing quest index...");
1388 
1389  for (quest = 0; quest < quests_count; quest++) {
1390  qsort(quests[quest]->maps.list, quests[quest]->maps.count, sizeof(struct_map_in_quest *), sort_struct_map_in_quest);
1391  for (map = 0; map < quests[quest]->maps.count; map++) {
1392  snprintf(mappath, sizeof(mappath), "%s.html", quests[quest]->maps.list[map]->map->path+1);
1393  map_vals[1] = quests[quest]->maps.list[map]->map->name;
1394  map_vals[2] = quests[quest]->maps.list[map]->description ? quests[quest]->maps.list[map]->description : "(no description)";
1395  text_map = cat_template(text_map, do_template(quest_map_template, map_vars, map_vals));
1396  }
1397  if (!text_map)
1398  text_map = strdup("");
1399 
1400  quest_vals[0] = quests[quest]->name;
1401  quest_vals[1] = quests[quest]->description ? quests[quest]->description : "(main map not processed)";
1402  quest_vals[2] = text_map;
1403  snprintf(questid, sizeof(questid), "quest_%d", quests[quest]->number);
1404  if (quests[quest]->mainmap) {
1405  snprintf(mainmappath, sizeof(mainmappath), "%s.html", quests[quest]->mainmap->path+1);
1406  quest_vals[5] = quests[quest]->mainmap->name;
1407  } else {
1408  snprintf(mainmappath, sizeof(mainmappath), "#");
1409  quest_vals[5] = "";
1410  }
1411  text_quest = cat_template(text_quest, do_template(quest_template, quest_vars, quest_vals));
1412  free(text_map);
1413  text_map = NULL;
1414  }
1415 
1416  if (!text_quest)
1417  text_quest = strdup("No quest.");
1418 
1419  idx_vals[0] = text_quest;
1420  text_idx = do_template(index_quest_template, idx_vars, idx_vals);
1421  free(text_quest);
1422 
1423  snprintf(path, sizeof(path), "%s/quests.html", root);
1424  out = fopen(path, "w+");
1425  fprintf(out, text_idx);
1426  fclose(out);
1427  free(text_idx);
1428 
1429  printf(" done.\n");
1430 }
1431 
1432 /************************************
1433  End of quest-related definitions.
1434 ************************************/
1435 
1436 /*********
1437 NPC-related stuff
1438 ********/
1439 
1445 static void init_npc_list(struct_npc_list *list) {
1446  list->allocated = 0;
1447  list->count = 0;
1448  list->npc = NULL;
1449 }
1450 
1458 static struct_npc_info *create_npc_info(const object *npc) {
1459  struct_npc_info *info = calloc(1, sizeof(struct_npc_info));
1460 
1461  info->name = strdup(npc->name);
1462  info->message = strdup(npc->msg);
1463  info->x = npc->x;
1464  info->y = npc->y;
1465 
1466  return info;
1467 }
1468 
1476 static void add_npc_to_map(struct_map_info *map, const object *npc) {
1477  if (map->npcs.count == map->npcs.allocated) {
1478  map->npcs.allocated += 50;
1479  map->npcs.npc = realloc(map->npcs.npc, map->npcs.allocated*sizeof(struct_npc_info *));
1480  }
1481 
1482  map->npcs.npc[map->npcs.count] = create_npc_info(npc);
1483  map->npcs.count++;
1484 }
1485 /* end of NPC stuff */
1486 
1498 static void add_map(struct_map_info *info, struct_map_list *list) {
1499  int map;
1500 
1501  for (map = 0; map < list->count; map++)
1502  if (list->maps[map] == info)
1503  return;
1504 
1505  if (list->count == list->allocated) {
1506  list->allocated += 50;
1507  list->maps = realloc(list->maps, list->allocated*sizeof(struct_map_info *));
1508  }
1509  list->maps[list->count] = info;
1510  list->count++;
1511 }
1512 
1523 static void replace_map(struct_map_info *find, struct_map_info *replace_by, struct_map_list *list) {
1524  int map;
1525 
1526  for (map = 0; map < list->count; map++) {
1527  if (list->maps[map] == find) {
1528  list->maps[map] = replace_by;
1529  return;
1530  }
1531  }
1532  printf("replace_map: couldn't find map %s.\n", find->path);
1533 }
1534 
1542  struct_map_info *add = calloc(1, sizeof(struct_map_info));
1543 
1544  add->min_monster = 2000;
1545  init_map_list(&add->exits_to);
1546  init_map_list(&add->exits_from);
1547  init_map_list(&add->tiled_maps);
1549  init_race_list(&add->monsters);
1550  init_npc_list(&add->npcs);
1551  add->tiled_group = NULL;
1552 
1553  return add;
1554 }
1555 
1564 
1565  add_map(add, &tiled_map_list);
1566  return add;
1567 }
1568 
1580 static void merge_tiled_maps(struct_map_info *map, int tile, struct_map_info *tiled_map) {
1581  int g;
1582  struct_map_info *group = tiled_map->tiled_group;
1583  struct_map_info *change;
1584 
1585  while (group->tiled_maps.count > 0) {
1586  change = group->tiled_maps.maps[group->tiled_maps.count-1];
1587  change->tiled_group = map->tiled_group;
1588  add_map(change, &map->tiled_group->tiled_maps);
1589  group->tiled_maps.count--;
1590  }
1591 
1592  for (g = 0; g < tiled_map_list.count; g++) {
1593  if (tiled_map_list.maps[g] == group) {
1594  if (g < tiled_map_list.count-1)
1595  tiled_map_list.maps[g] = tiled_map_list.maps[tiled_map_list.count-1];
1596  tiled_map_list.count--;
1597  free(group);
1598  return;
1599  }
1600  }
1601  printf("tiled_map not in tiled_map_list!");
1602  abort();
1603 
1604 }
1605 
1614 static struct_map_info *get_map_info(const char *path) {
1615  int map;
1616  struct_map_info *add;
1617  char *tmp;
1618 
1619  for (map = 0; map < maps_list.count; map++) {
1620  if (strcmp(maps_list.maps[map]->path, path) == 0)
1621  return maps_list.maps[map];
1622  }
1623 
1624  add = create_map_info();
1625  add->path = strdup(path);
1626  tmp = strrchr(path, '/');
1627  if (tmp)
1628  add->filename = strdup(tmp+1);
1629  else
1630  add->filename = strdup(path);
1631 
1632  add_map(add, &maps_list);
1633  return add;
1634 }
1635 
1642 static void list_map(const char *path) {
1643  int index;
1644 
1645  for (index = 0; index < found_maps_count; index++) {
1646  if (found_maps[index] && strcmp(path, found_maps[index]) == 0) {
1647  free(found_maps[index]);
1648  found_maps[index] = NULL;
1649  return;
1650  }
1651  }
1652  printf("Map processed but not found in directory reading? %s\n", path);
1653 }
1654 
1665 static void add_map_to_region(struct_map_info *map, region *reg) {
1666  int test;
1667  int x, y;
1668 
1669  for (test = 0; test < region_count; test++) {
1670  if (regions[test]->reg == reg)
1671  break;
1672  }
1673  if (test == region_count) {
1674  if (test == region_allocated) {
1675  region_allocated++;
1676  regions = realloc(regions, sizeof(struct_region_info *)*region_allocated);
1677  regions[test] = calloc(1, sizeof(struct_region_info));
1678  }
1679  region_count++;
1680  regions[test]->reg = reg;
1681  }
1682  add_map(map, &regions[test]->maps_list);
1683  if (sscanf(map->path, "/world/world_%d_%d", &x, &y) == 2) {
1684  regions[test]->sum_x += (x-100);
1685  regions[test]->sum_y += (y-100);
1686  regions[test]->sum++;
1687  regions[test]->is_world = 1;
1688  }
1689 }
1690 
1699 static void save_picture(FILE *file, gdImagePtr pic) {
1700  if (output_format == OF_PNG)
1701  gdImagePng(pic, file);
1702  else
1703  gdImageJpeg(pic, file, jpeg_quality);
1704 }
1705 
1715 static void add_region_link(mapstruct *source, mapstruct *dest, const char *linkname) {
1716  int search = 0;
1717  char entry[500];
1718  region *s, *d;
1719 
1720  s = get_region_by_map(source);
1721  d = get_region_by_map(dest);
1722  if (s == d)
1723  return;
1724 
1725  if (linkname && 0)
1726  snprintf(entry, sizeof(entry), "%s -> %s [ label = \"%s\" ]\n", s->name, d->name, linkname);
1727  else
1728  snprintf(entry, sizeof(entry), "%s -> %s\n", s->name, d->name);
1729 
1730  for (search = 0; search < regions_link_count; search++) {
1731  if (strcmp(regions_link[search], entry) == 0)
1732  return;
1733  }
1734 
1735  if (regions_link_count == regions_link_allocated) {
1736  regions_link_allocated += 10;
1737  regions_link = realloc(regions_link, sizeof(const char *)*regions_link_allocated);
1738  }
1739  regions_link[regions_link_count] = strdup(entry);
1740  regions_link_count++;
1741 }
1742 
1751 static int is_slaying(object *item) {
1752  return (item->type == LOCKED_DOOR || item->type == SPECIAL_KEY || item->type == CONTAINER || item->type == CHECK_INV);
1753 }
1754 
1755 
1764 static struct_slaying_info *get_slaying_struct(const char *slaying) {
1765  struct_slaying_info *add;
1766  int l;
1767 
1768  for (l = 0; l < slaying_count; l++) {
1769  if (!strcmp(slaying_info[l]->slaying, slaying))
1770  return slaying_info[l];
1771  }
1772  if (slaying_count == slaying_allocated) {
1773  slaying_allocated += 10;
1774  slaying_info = (struct_slaying_info **)realloc(slaying_info, sizeof(struct_slaying_info *)*slaying_allocated);
1775  }
1776 
1777  add = (struct_slaying_info *)calloc(1, sizeof(struct_slaying_info));
1778  add->slaying = strdup(slaying);
1779  for (l = 0; l < S_MAX; l++)
1780  init_map_list(&add->maps[l]);
1781 
1782  slaying_info[slaying_count] = add;
1783  slaying_count++;
1784 
1785  return add;
1786 }
1787 
1798 static void add_map_to_slaying(struct_slaying_info *info, int item, struct_map_info *map) {
1799  add_map(map, &info->maps[item]);
1800 }
1801 
1810 static void add_slaying(struct_map_info *map, object *item) {
1811  struct_slaying_info *info;
1812 
1813  if (!item->slaying)
1814  /* can be undefined */
1815  return;
1816 
1817  info = get_slaying_struct(item->slaying);
1818  if (item->type == LOCKED_DOOR)
1819  add_map_to_slaying(info, S_DOOR, map);
1820  else if (item->type == SPECIAL_KEY)
1821  add_map_to_slaying(info, S_KEY, map);
1822  else if (item->type == CONTAINER)
1823  add_map_to_slaying(info, S_CONTAINER, map);
1824  else
1825  add_map_to_slaying(info, S_CONNECT, map);
1826 }
1827 
1836 static void check_slaying_inventory(struct_map_info *map, object *item) {
1837  object *inv;
1838 
1839  for (inv = item->inv; inv; inv = inv->below) {
1840  if (is_slaying(inv))
1841  add_slaying(map, inv);
1842  check_slaying_inventory(map, inv);
1843  }
1844 }
1845 
1854 static void process_map(struct_map_info *info) {
1855  mapstruct *m;
1856  int x, y, isworld;
1857  object *item;
1858  FILE *out;
1859  gdImagePtr pic;
1860  gdImagePtr small;
1861  struct stat stats;
1862  struct stat statspic;
1863  char exit_path[500];
1864  char tmppath[MAX_BUF];
1865  char picpath[MAX_BUF], smallpicpath[MAX_BUF];
1866  int needpic = 0;
1867  struct_map_info *link;
1868 
1869  if (list_unused_maps)
1870  list_map(info->path);
1871 
1872  if (show_maps)
1873  printf(" processing map %s\n", info->path);
1874 
1875  m = ready_map_name(info->path, 0);
1876  if (!m) {
1877  printf("couldn't load map %s\n", info->path);
1878  return;
1879  }
1880 
1881  do_exit_map(m);
1882 
1883  if (!rawmaps)
1884  do_auto_apply(m);
1885 
1886  info->level = m->difficulty;
1887  if (m->maplore) {
1888  info->lore = strdup(m->maplore);
1889  process_map_lore(info);
1890  }
1891 
1892  isworld = (sscanf(info->path, "/world/world_%d_%d", &x, &y) == 2);
1893 
1894  if (m->name)
1895  info->name = strdup(m->name);
1896  else
1897  info->name = strdup(info->filename);
1898 
1899  info->cfregion = get_region_by_map(m);
1900  add_map_to_region(info, info->cfregion);
1901 
1902  snprintf(picpath, sizeof(picpath), "%s%s%s", root, info->path, output_extensions[output_format]);
1903  snprintf(smallpicpath, sizeof(smallpicpath), "%s%s.small%s", root, info->path, output_extensions[output_format]);
1904 
1905  if (force_pics)
1906  needpic = 1;
1907  else if (generate_pics) {
1908  create_pathname(info->path, tmppath, MAX_BUF);
1909  stat(tmppath, &stats);
1910  if (stat(picpath, &statspic) || (statspic.st_mtime < stats.st_mtime))
1911  needpic = 1;
1912  else if (stat(smallpicpath, &statspic) || (statspic.st_mtime < stats.st_mtime))
1913  needpic = 1;
1914  }
1915  else
1916  needpic = 0;
1917 
1918  if (needpic) {
1919  pic = gdImageCreateTrueColor(MAP_WIDTH(m)*32, MAP_HEIGHT(m)*32);
1920  created_pics++;
1921  }
1922  else
1923  cached_pics++;
1924 
1925  for (x = 0; x < 4; x++)
1926  if (m->tile_path[x] != NULL) {
1927  path_combine_and_normalize(m->path, m->tile_path[x], exit_path, sizeof(exit_path));
1928  create_pathname(exit_path, tmppath, MAX_BUF);
1929  if (stat(tmppath, &stats)) {
1930  printf(" map %s doesn't exist in map %s, for tile %d.\n", exit_path, info->path, x);
1931  }
1932 
1933  if (isworld) {
1934  link = get_map_info(exit_path);
1935  add_map(link, &info->exits_from);
1936  add_map(info, &link->exits_to);
1937 
1938  if (do_regions_link) {
1939  mapstruct *link = ready_map_name(exit_path, 0);
1940 
1941  if (link && link != m) {
1942  /* no need to link a map with itself. Also, if the exit points to the same map, we don't
1943  * want to reset it. */
1944  add_region_link(m, link, NULL);
1945  link->reset_time = 1;
1946  link->in_memory = MAP_IN_MEMORY;
1947  delete_map(link);
1948  }
1949  }
1950  } else {
1951  link = get_map_info(exit_path);
1952  info->tiles[x] = link;
1953  if (link->tiled_group) {
1954  if (info->tiled_group && link->tiled_group != info->tiled_group) {
1955  merge_tiled_maps(info, x, link);
1956  continue;
1957  }
1958  if (link->tiled_group == info->tiled_group) {
1959  continue;
1960  }
1961  if (!info->tiled_group) {
1962  add_map(info, &link->tiled_group->tiled_maps);
1963  continue;
1964  }
1965  }
1966 
1967  if (!info->tiled_group) {
1968  info->tiled_group = create_tiled_map();
1969  add_map(info, &info->tiled_group->tiled_maps);
1970  }
1971  link->tiled_group = info->tiled_group;
1972  add_map(link, &info->tiled_group->tiled_maps);
1973  }
1974  }
1975 
1976  info->width = MAP_WIDTH(m);
1977  info->height = MAP_HEIGHT(m);
1978 
1979  for (x = MAP_WIDTH(m)-1; x >= 0; x--)
1980  for (y = MAP_HEIGHT(m)-1; y >= 0; y--) {
1981  for (item = GET_MAP_OB(m, x, y); item; item = item->above) {
1982  if (item->type == EXIT || item->type == TELEPORTER || item->type == PLAYER_CHANGER) {
1983  char ep[500];
1984  const char *start;
1985 
1986  if (!item->slaying) {
1987  ep[0] = '\0';
1988  if (warn_no_path)
1989  printf(" exit without any path at %d, %d on %s\n", item->x, item->y, info->path);
1990  } else {
1991  memset(ep, 0, 500);
1992  if (strcmp(item->slaying, "/!"))
1993  strcpy(ep, EXIT_PATH(item));
1994  else {
1995  if (!item->msg) {
1996  printf(" random map without message in %s at %d, %d\n", info->path, item->x, item->y);
1997  } else {
1998  /* Some maps have a 'exit_on_final_map' flag, ignore it. */
1999  start = strstr(item->msg, "\nfinal_map ");
2000  if (!start && strncmp(item->msg, "final_map", strlen("final_map")) == 0)
2001  /* Message start is final_map, nice */
2002  start = item->msg;
2003  if (start) {
2004  char *end = strchr(start+1, '\n');
2005 
2006  start += strlen("final_map")+2;
2007  strncpy(ep, start, end-start);
2008  }
2009  }
2010  }
2011 
2012  if (strlen(ep)) {
2013  path_combine_and_normalize(m->path, ep, exit_path, 500);
2014  create_pathname(exit_path, tmppath, MAX_BUF);
2015  if (stat(tmppath, &stats)) {
2016  printf(" map %s doesn't exist in map %s, at %d, %d.\n", ep, info->path, item->x, item->y);
2017  } else {
2018  link = get_map_info(exit_path);
2019  add_map(link, &info->exits_from);
2020  add_map(info, &link->exits_to);
2021 
2022  if (do_regions_link) {
2023  mapstruct *link = ready_map_name(exit_path, 0);
2024 
2025  if (link && link != m) {
2026  /* no need to link a map with itself. Also, if the exit points to the same map, we don't
2027  * want to reset it. */
2028  add_region_link(m, link, item->arch->clone.name);
2029  link->reset_time = 1;
2030  link->in_memory = MAP_IN_MEMORY;
2031  delete_map(link);
2032  }
2033  }
2034  }
2035  }
2036  }
2037  } else if (is_slaying(item))
2038  add_slaying(info, item);
2039 
2040  check_equipment(item, info);
2041 
2042  check_slaying_inventory(info, item);
2043 
2044  if (QUERY_FLAG(item, FLAG_MONSTER)) {
2045  /* need to get the "real" archetype, as the item's archetype can certainly be a temporary one. */
2046  archetype *arch = find_archetype(item->arch->name);
2047 
2048  add_monster(item, info);
2049  if ((QUERY_FLAG(item, FLAG_UNAGGRESSIVE) || QUERY_FLAG(item, FLAG_FRIENDLY)) && (item->msg != arch->clone.msg) && (item->msg != NULL))
2050  add_npc_to_map(info, item);
2051  }
2052 
2053  if (item->invisible)
2054  continue;
2055 
2056  if (needpic) {
2057  int sx, sy, hx, hy;
2058 
2059  if (gdfaces[item->face->number] == NULL) {
2060  int set = get_face_fallback(tileset, item->face->number);
2061 
2062  gdfaces[item->face->number] = gdImageCreateFromPngPtr(facesets[set].faces[item->face->number].datalen, facesets[set].faces[item->face->number].data);
2063  pics_allocated++;
2064  }
2065  if (item->head || item->more) {
2066  get_multi_size(item, &sx, &sy, &hx, &hy);
2067  } else {
2068  hx = 0;
2069  hy = 0;
2070  }
2071  if (gdfaces[item->face->number] != NULL && ((!item->head && !item->more) || (item->arch->clone.x+hx == 0 && item->arch->clone.y+hy == 0))) {
2072  gdImageCopy(pic, gdfaces[item->face->number], x*32, y*32, 0, 0, gdfaces[item->face->number]->sx, gdfaces[item->face->number]->sy);
2073  }
2074  }
2075  }
2076  }
2077 
2078  if (needpic) {
2079  make_path_to_file(picpath);
2080  out = fopen(picpath, "wb+");
2081  save_picture(out, pic);
2082  fclose(out);
2083 
2084  small = gdImageCreateTrueColor(MAP_WIDTH(m)*size_small, MAP_HEIGHT(m)*size_small);
2085  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);
2086 
2087  out = fopen(smallpicpath, "wb+");
2088  save_picture(out, small);
2089  fclose(out);
2090  gdImageDestroy(small);
2091 
2092  gdImageDestroy(pic);
2093 
2094  info->pic_was_done = 1;
2095  }
2096 
2097  m->reset_time = 1;
2098  m->in_memory = MAP_IN_MEMORY;
2099  delete_map(m);
2100 }
2101 
2122 static char *do_map_index(const char *dest, struct_map_list *maps_list,
2123  const char *template_page, const char *template_letter,
2124  const char *template_map, const char **vars,
2125  const char **values) {
2126 #define VARSADD 6
2127  int map;
2128  char *string;
2129  char mappath[500];
2130  char maphtml[500];
2131  char count[50];
2132  char lettercount[50];
2133  char *tmp;
2134  const char **idx_vars;
2135  const char **idx_values;
2136  char str_letter[2];
2137  char last_letter;
2138  char index_path[500];
2139  char *mapstext = NULL;
2140  int byletter;
2141  int basevalues, realcount = 0;
2142  struct_map_info *last_group = NULL;
2143 
2144  if (!generate_index)
2145  return strdup("");
2146 
2147  if (vars)
2148  for (basevalues = 0; vars[basevalues] != NULL; basevalues++)
2149  ;
2150  else
2151  basevalues = 0;
2152 
2153  idx_vars = malloc(sizeof(char *)*(basevalues+VARSADD));
2154  idx_vars[0] = "MAPCOUNT";
2155  memcpy(&idx_vars[1], vars, sizeof(char *)*basevalues);
2156  idx_vars[basevalues+VARSADD-1] = NULL;
2157 
2158  idx_values = malloc(sizeof(char *)*(basevalues+VARSADD-1));
2159  memcpy(&idx_values[1], values, sizeof(char *)*basevalues);
2160 
2161  string = NULL;
2162 
2163  idx_values[0] = count;
2164  /* wrong value, but in case the template needs to display something... */
2165  snprintf(count, sizeof(count), "%d", maps_list->count);
2166 
2167  idx_vars[basevalues+1] = "MAPNAME";
2168  idx_vars[basevalues+2] = "MAPPATH";
2169  idx_vars[basevalues+3] = "MAPHTML";
2170  idx_vars[basevalues+4] = NULL;
2171 
2172  qsort(maps_list->maps, maps_list->count, sizeof(const char *), sort_map_info);
2173 
2174  last_letter = '\0';
2175  str_letter[0] = '\0';
2176  str_letter[1] = '\0';
2177 
2178  strcpy(index_path, "/");
2179  strcat(index_path, dest);
2180 
2181  string = NULL;
2182  for (map = 0; map < maps_list->count; map++) {
2183  if (tolower(maps_list->maps[map]->name[0]) != last_letter) {
2184  if (mapstext != NULL) {
2185  idx_vars[basevalues+1] = "MAPS";
2186  idx_vars[basevalues+2] = "LETTER";
2187  idx_vars[basevalues+3] = "LETTERCOUNT";
2188  idx_vars[basevalues+4] = NULL;
2189  idx_values[basevalues+1] = mapstext;
2190  idx_values[basevalues+2] = str_letter;
2191  snprintf(lettercount, sizeof(lettercount), "%d", byletter);
2192  idx_values[basevalues+3] = lettercount;
2193  string = cat_template(string, do_template(template_letter, idx_vars, idx_values));
2194  free(mapstext);
2195  mapstext = NULL;
2196  idx_values[basevalues+2] = NULL;
2197  }
2198  last_letter = tolower(maps_list->maps[map]->name[0]);
2199  str_letter[0] = last_letter;
2200  byletter = 0;
2201  last_group = NULL;
2202  }
2203 
2204  if (last_group && last_group == maps_list->maps[map]->tiled_group)
2205  continue;
2206  else
2207  last_group = maps_list->maps[map]->tiled_group;
2208 
2209  realcount++;
2210  idx_vars[basevalues+1] = "MAPNAME";
2211  idx_vars[basevalues+2] = "MAPPATH";
2212  idx_vars[basevalues+3] = "MAPHTML";
2213  idx_values[basevalues+1] = last_group ? last_group->name : (maps_list->maps[map]->name ? maps_list->maps[map]->name : maps_list->maps[map]->path);
2214  relative_path(index_path, last_group ? last_group->path : maps_list->maps[map]->path, mappath);
2215  strcpy(maphtml, mappath);
2216  strcat(maphtml, ".html");
2217  idx_values[basevalues+2] = mappath;
2218  idx_values[basevalues+3] = maphtml;
2219  mapstext = cat_template(mapstext, do_template(template_map, idx_vars, idx_values));
2220  byletter++;
2221  }
2222  if (last_letter != '\0') {
2223  idx_vars[basevalues+1] = "MAPS";
2224  idx_vars[basevalues+2] = "LETTER";
2225  idx_vars[basevalues+3] = "LETTERCOUNT";
2226  idx_vars[basevalues+4] = NULL;
2227  idx_values[basevalues+1] = mapstext;
2228  idx_values[basevalues+2] = str_letter;
2229  snprintf(lettercount, sizeof(lettercount), "%d", byletter);
2230  idx_values[basevalues+3] = lettercount;
2231  string = cat_template(string, do_template(template_letter, idx_vars, idx_values));
2232  free(mapstext);
2233  mapstext = NULL;
2234  idx_values[basevalues+2] = NULL;
2235  }
2236 
2237  snprintf(count, sizeof(count), "%d", realcount);
2238  idx_values[basevalues+1] = string;
2239  idx_vars[basevalues+1] = "LETTERS";
2240  idx_vars[basevalues+2] = NULL;
2241  tmp = do_template(template_page, idx_vars, idx_values);
2242  free(string);
2243  free(idx_vars);
2244  free(idx_values);
2245  return tmp;
2246 }
2247 
2258  char *string;
2259  FILE *index;
2260  char html[500];
2261  const char *vars[] = { "REGIONNAME", "REGIONHTML", "REGIONLONGNAME", "REGIONDESC", NULL };
2262  const char *values[] = { reg->reg->name, html, NULL, NULL };
2263 
2264  printf("Generating map index for region %s...", reg->reg->name);
2265 
2266  values[2] = get_region_longname(reg->reg);
2267  values[3] = get_region_msg(reg->reg);
2268 
2269  strcpy(html, reg->reg->name);
2270  strcat(html, ".html");
2271 
2272  string = do_map_index(html, &reg->maps_list, region_template, region_letter_template, region_map_template, vars, values);
2273 
2274  strcpy(html, root);
2275  strcat(html, "/");
2276  strcat(html, reg->reg->name);
2277  strcat(html, ".html");
2278  index = fopen(html, "w+");
2279  fprintf(index, string);
2280  fclose(index);
2281  free(string);
2282 
2283  printf(" done.\n");
2284 
2285 }
2286 
2290 static void write_all_regions(void) {
2291  int reg;
2292 
2293  qsort(regions, region_count, sizeof(struct_region_info *), sort_region);
2294 
2295  for (reg = 0; reg < region_count; reg++)
2296  write_region_page(regions[reg]);
2297 }
2298 
2302 static void write_maps_index(void) {
2303  char index_path[500];
2304  char *tmp;
2305  FILE *index;
2306 
2307  printf("Generating global map index in maps.html...");
2308 
2309  tmp = do_map_index("maps.html", &maps_list, index_template, index_letter, index_map, NULL, NULL);
2310 
2311  strcpy(index_path, root);
2312  strcat(index_path, "/maps.html");
2313  index = fopen(index_path, "w+");
2314  fprintf(index, tmp);
2315  fclose(index);
2316  free(tmp);
2317 
2318  printf(" done.\n");
2319 }
2320 
2324 static void write_region_index(void) {
2325  char *txt;
2326  char *final;
2327  char count[10];
2329  int reg;
2330  char file[500];
2331  const char *vars[] = { "REGIONCOUNT", "REGIONFILE", "REGIONNAME", NULL };
2332  const char *values[] = { count, file, NULL };
2333  FILE *out;
2334 
2335  printf("Generating regions index in regions.html...");
2336 
2337  snprintf(count, sizeof(count), "%d", region_count);
2338  txt = NULL;
2339 
2340  for (reg = 0; reg < region_count; reg++) {
2341  region = regions[reg];
2342  snprintf(file, sizeof(file), "%s.html", region->reg->name);
2343  values[2] = get_region_longname(region->reg);
2344  txt = cat_template(txt, do_template(index_region_region_template, vars, values));
2345  }
2346  vars[1] = "REGIONS";
2347  values[1] = txt;
2348  vars[2] = NULL;
2349  final = do_template(index_region_template, vars, values);
2350  free(txt);
2351 
2352  strcpy(file, root);
2353  strcat(file, "/regions.html");
2354  out = fopen(file, "w+");
2355  fprintf(out, final);
2356  fclose(out);
2357  free(final);
2358 
2359  printf(" done.\n");
2360 }
2361 
2365 static void write_world_map(void) {
2366 #define SIZE 50
2367  int x, y;
2368  FILE *out;
2369  int wx, wy;
2370  char file[500];
2371  char *map = NULL;
2372  char *total;
2373  char *row = NULL;
2374  char mapleft[10], maptop[10], mapright[10], mapbottom[10];
2375  const char *vars[] = { NULL, NULL, "MAPLEFT", "MAPTOP", "MAPRIGHT", "MAPBOTTOM", NULL };
2376  const char *values[] = { NULL, NULL, mapleft, maptop, mapright, mapbottom, NULL };
2377  char name[100];
2378  char mappath[500], mapraw[500], mapregion[500];
2379  gdImagePtr pic;
2380  gdImagePtr small;
2381  gdFontPtr font;
2382  int region, color;
2383 
2384  if (!world_map)
2385  return;
2386 
2387  printf("Generating world map in world.html...");
2388  fflush(stdout);
2389 
2390  pic = gdImageCreateTrueColor(SIZE*30, SIZE*30);
2391 
2392  strcpy(file, root);
2393  strcat(file, "/world.html");
2394 
2395  wx = 100;
2396  wy = 100;
2397 
2398  for (y = 0; y < 30; y++) {
2399  for (x = 0; x < 30; x++) {
2400  values[0] = name;
2401  vars[0] = "MAPNAME";
2402  vars[1] = "MAPPATH";
2403  values[1] = mappath,
2404  snprintf(name, sizeof(name), "world_%d_%d", wx, wy);
2405  snprintf(mappath, sizeof(mappath), "world/%s.html", name);
2406  snprintf(mapleft, sizeof(mapleft), "%d", SIZE*x);
2407  snprintf(maptop, sizeof(maptop), "%d", SIZE*y);
2408  snprintf(mapright, sizeof(mapright), "%d", SIZE*(x+1)-1);
2409  snprintf(mapbottom, sizeof(mapbottom), "%d", SIZE*(y+1)-1);
2410 
2411  map = cat_template(map, do_template(world_map_template, vars, values));
2412 
2413  snprintf(mappath, sizeof(mappath), "%s/world/%s%s", root, name, output_extensions[output_format]);
2414 
2415  out = fopen(mappath, "rb");
2416  if (!out) {
2417  printf("\n warning: large pic not found for world_%d_%d", wx, wy);
2418  wx++;
2419  continue;
2420  }
2421  if (output_format == OF_PNG)
2422  small = gdImageCreateFromPng(out);
2423  else
2424  small = gdImageCreateFromJpeg(out);
2425  fclose(out);
2426  if (!small) {
2427  printf("\n warning: pic not found for world_%d_%d", wx, wy);
2428  wx++;
2429  continue;
2430  }
2431  gdImageCopyResized(pic, small, SIZE*x, SIZE*y, 0, 0, SIZE, SIZE, small->sx, small->sy);
2432  gdImageDestroy(small);
2433 
2434  wx++;
2435  }
2436  wy++;
2437  wx = 100;
2438  values[0] = map;
2439  vars[0] = "MAPS";
2440  vars[1] = NULL;
2441  row = cat_template(row, do_template(world_row_template, vars, values));
2442  free(map);
2443  map = NULL;
2444  }
2445  snprintf(mappath, sizeof(mappath), "world%s", output_extensions[output_format]);
2446  snprintf(mapraw, sizeof(mapraw), "world_raw%s", output_extensions[output_format]);
2447  snprintf(mapregion, sizeof(mapregion), "world_regions%s", output_extensions[output_format]);
2448 
2449  values[0] = row;
2450  vars[0] = "MAPS";
2451  values[1] = mappath;
2452  vars[1] = "WORLDMAP";
2453  values[2] = mapraw;
2454  vars[2] = "WORLDRAW";
2455  values[3] = mapregion;
2456  vars[3] = "WORLDREGIONS";
2457  vars[4] = NULL;
2458  total = do_template(world_template, vars, values);
2459  free(row);
2460  out = fopen(file, "w+");
2461  fprintf(out, total);
2462  free(total);
2463  fclose(out);
2464 
2465  snprintf(mappath, sizeof(mappath), "%s/world_raw%s", root, output_extensions[output_format]);
2466  out = fopen(mappath, "wb+");
2467  save_picture(out, pic);
2468  fclose(out);
2469 
2470  /* Write region names. */
2471  small = gdImageCreateTrueColor(SIZE*30, SIZE*30);
2472  font = gdFontGetGiant();
2473  color = gdImageColorAllocateAlpha(pic, 255, 0, 0, 20);
2474  for (region = 0; region < region_allocated; region++) {
2475  if (!regions[region]->is_world || regions[region]->sum == 0)
2476  continue;
2477 
2478  x = regions[region]->sum_x*SIZE/regions[region]->sum+SIZE/2-strlen(regions[region]->reg->name)*font->w/2;
2479  y = regions[region]->sum_y*SIZE/regions[region]->sum+SIZE/2-font->h/2;
2480  gdImageString(small, font, x, y, regions[region]->reg->name, color);
2481  gdImageString(pic, font, x, y, regions[region]->reg->name, color);
2482 
2483  /* For exit/road map, size isn't the same. */
2484  x = regions[region]->sum_x*50/regions[region]->sum+50/2-strlen(regions[region]->reg->name)*font->w/2;
2485  y = regions[region]->sum_y*50/regions[region]->sum+50/2-font->h/2;
2486  gdImageString(infomap, font, x, y, regions[region]->reg->name, color);
2487  }
2488 
2489  snprintf(mappath, sizeof(mappath), "%s/world_regions%s", root, output_extensions[output_format]);
2490  out = fopen(mappath, "wb+");
2491  save_picture(out, small);
2492  fclose(out);
2493  gdImageDestroy(small);
2494 
2495  snprintf(mappath, sizeof(mappath), "%s/world%s", root, output_extensions[output_format]);
2496  out = fopen(mappath, "wb+");
2497  save_picture(out, pic);
2498  fclose(out);
2499  gdImageDestroy(pic);
2500 
2501  printf(" done.\n");
2502 #undef SIZE
2503 }
2504 
2511 static void write_map_page(struct_map_info *map) {
2512  char *exits_text;
2513  char *exits_to;
2514  char *maplore;
2515  char *tmp;
2516  char *quests, *quest;
2517  char *monsters;
2518 
2519  char htmlpath[500]; /* Map file path. */
2520  char mappic[500]; /* Name of map's full size picture. */
2521  char mapsmallpic[500]; /* Name of map's small size picture. */
2522  char indexpath[500]; /* Relative path of full index. */
2523  char regionpath[500]; /* Path to region's filename. */
2524  char regionname[500]; /* Name of map's region. */
2525  char regionindexpath[500]; /* Path to region index file. */
2526  char worldmappath[500]; /* Path to world map. */
2527  char exit_path[500];
2528  char maplevel[5], minmonster[5], maxmonster[5];
2529  FILE *out;
2530  char questpath[500], questtemp[500];
2531  const char *quest_vars[] = { "NAME", "PATH", "TEXT", NULL };
2532  const char *quest_vals[] = { NULL, questpath, NULL, NULL };
2533  const char *q_vars[] = { "QUESTS", NULL };
2534  const char *q_vals[] = { NULL, NULL };
2535  const char *m_vars[] = { "NAME", NULL };
2536  const char *m_vals[] = { NULL, NULL };
2537  const char *vars[] = { "NAME", "MAPPATH", "MAPNAME", "MAPPIC", "MAPSMALLPIC", "MAPEXITFROM", "INDEXPATH", "REGIONPATH", "REGIONNAME", "REGIONINDEXPATH", "WORLDMAPPATH", "MAPLORE", "MAPEXITTO", "MAPLEVEL", "QUESTS", "MONSTERS", "MINMONSTER", "MAXMONSTER", NULL, NULL, NULL };
2538  const char *values[] = { map->path, htmlpath, map->name, mappic, mapsmallpic, "", indexpath, regionpath, regionname, regionindexpath, worldmappath, "", "", maplevel, NULL, "", minmonster, maxmonster, NULL, NULL, NULL };
2539  int vars_count = 0;
2540 
2541  while (vars[vars_count])
2542  vars_count++;
2543 
2544  snprintf(minmonster, sizeof(minmonster), "%d", map->min_monster);
2545  snprintf(maxmonster, sizeof(maxmonster), "%d", map->max_monster);
2546 
2547  relative_path(map->path, "/maps.html", indexpath);
2548  relative_path(map->path, "/world.html", worldmappath);
2549  relative_path(map->path, "/regions.html", regionindexpath);
2550 
2551  if (map->cfregion) {
2552  strcpy(regionname, get_region_longname(map->cfregion));
2553  strcpy(exit_path, "/");
2554  strcat(exit_path, map->cfregion->name);
2555  strcat(exit_path, ".html");
2556  relative_path(map->path, exit_path, regionpath);
2557  } else {
2558  regionpath[0]='\0';
2559  snprintf(regionname, sizeof(regionname), "(map was not processed)");
2560  }
2561 
2562  snprintf(mappic, sizeof(mappic), "%s%s", map->filename, output_extensions[output_format]);
2563  snprintf(mapsmallpic, sizeof(mapsmallpic), "%s.small%s", map->filename, output_extensions[output_format]);
2564 
2565  snprintf(htmlpath, sizeof(htmlpath), "%s%s.html", root, map->path);
2566  make_path_to_file(htmlpath);
2567 
2568  values[14] = "";
2569 
2570  snprintf(maplevel, sizeof(maplevel), "%d", map->level);
2571  if (map->lore && map->lore[0] != '\0') {
2572  values[11] = map->lore;
2573  maplore = do_template(map_lore_template, vars, values);
2574  } else {
2575  maplore = do_template(map_no_lore_template, vars, values);
2576  }
2577  values[11] = maplore;
2578 
2579  if (map->exits_from.count) {
2580  char *one_exit = NULL;
2581  int exit;
2582  char relative[500];
2583 
2584  vars[vars_count] = "EXITNAME";
2585  vars[vars_count+1] = "EXITFILE";
2586 
2587  qsort(map->exits_from.maps, map->exits_from.count, sizeof(const char *), sort_map_info);
2588  for (exit = 0; exit < map->exits_from.count; exit++) {
2589  relative_path(map->path, map->exits_from.maps[exit]->path, relative);
2590  values[vars_count] = map->exits_from.maps[exit]->name;
2591  strcat(relative, ".html");
2592  values[vars_count+1] = relative;
2593  one_exit = cat_template(one_exit, do_template(map_exit_template, vars, values));
2594  }
2595  vars[vars_count] = "EXIT";
2596  vars[vars_count+1] = NULL;
2597  values[vars_count] = one_exit;
2598  exits_text = do_template(map_with_exit_template, vars, values);
2599  free(one_exit);
2600  }
2601  else
2602  exits_text = do_template(map_no_exit_template, vars, values);
2603 
2604  values[5] = exits_text;
2605 
2606  if (map->exits_to.count) {
2607  char *one_exit = NULL;
2608  int exit;
2609  char relative[500];
2610 
2611  vars[vars_count] = "EXITNAME";
2612  vars[vars_count+1] = "EXITFILE";
2613 
2614  qsort(map->exits_to.maps, map->exits_to.count, sizeof(struct_map_info *), sort_map_info);
2615  for (exit = 0; exit < map->exits_to.count; exit++) {
2616  relative_path(map->path, map->exits_to.maps[exit]->path, relative);
2617  values[vars_count] = map->exits_to.maps[exit]->name;
2618  strcat(relative, ".html");
2619  values[vars_count+1] = relative;
2620  one_exit = cat_template(one_exit, do_template(map_exit_to_template, vars, values));
2621  }
2622  vars[vars_count] = "EXIT";
2623  vars[vars_count+1] = NULL;
2624  values[vars_count] = one_exit;
2625  exits_to = do_template(map_with_exit_to_template, vars, values);
2626  free(one_exit);
2627  } else
2628  exits_to = do_template(map_no_exit_to_template, vars, values);
2629 
2630  values[12] = exits_to;
2631 
2632  if (map->quests.count) {
2633  int q;
2634 
2635  quest = NULL;
2636  for (q = 0; q < map->quests.count; q++) {
2637  quest_vals[0] = map->quests.list[q]->quest->name;
2638  relative_path(map->path, "/quests.html", questtemp);
2639  snprintf(questpath, sizeof(questpath), "%s#quest_%d", questtemp, map->quests.list[q]->quest->number);
2640  quest_vals[2] = map->quests.list[q]->description;
2641  quest = cat_template(quest, do_template(map_one_quest_template, quest_vars, quest_vals));
2642  }
2643 
2644  q_vals[0] = quest;
2645  quests = do_template(map_with_quests_template, q_vars, q_vals);
2646  free(quest);
2647  quest = NULL;
2648  } else
2649  quests = strdup(map_no_quest_template);
2650  values[14] = quests;
2651 
2652  if (map->monsters.count) {
2653  int m;
2654 
2655  qsort(map->monsters.races, map->monsters.count, sizeof(struct_race *), sort_race);
2656 
2657  monsters = do_template(map_monster_before_template, vars, values);
2658  for (m = 0; m < map->monsters.count; m++) {
2659  m_vals[0] = map->monsters.races[m]->name;
2660  monsters = cat_template(monsters, do_template(map_monster_one_template, m_vars, m_vals));
2661  if (m != map->monsters.count-1)
2662  monsters = cat_template(monsters, do_template(map_monster_between_template, vars, values));
2663  }
2664  monsters = cat_template(monsters, do_template(map_monster_after_template, vars, values));
2665  } else
2666  monsters = do_template(map_no_monster_template, vars, values);
2667  values[15] = monsters;
2668 
2669  vars[vars_count] = NULL;
2670  out = fopen(htmlpath, "w+");
2671  tmp = do_template(map_template, vars, values);
2672  fprintf(out, tmp);
2673  fclose(out);
2674  free(tmp);
2675  free(exits_text);
2676  free(exits_to);
2677  free(maplore);
2678  free(quests);
2679  free(monsters);
2680 }
2681 
2683 static void fix_map_names(void) {
2684  int map;
2685 
2686  for (map = 0; map < maps_list.count; map++) {
2687  if (maps_list.maps[map]->name)
2688  continue;
2689  if (!maps_list.maps[map]->filename) {
2690  printf("map without path!\n");
2691  abort();
2692  }
2693  maps_list.maps[map]->name = strdup(maps_list.maps[map]->filename);
2694  }
2695 }
2696 
2703 static void fix_tiled_map(void) {
2704  int map, tile;
2705  char name[500];
2706  char *slash, *test;
2707  region *cfregion;
2708 
2709  for (map = 0; map < tiled_map_list.count; map++) {
2710  if (tiled_map_list.maps[map]->tiled_maps.count == 0) {
2711  printf("empty tiled map group!");
2712  abort();
2713  }
2714 
2715  snprintf(name, sizeof(name), "tiled_map_group_%d", map);
2716  tiled_map_list.maps[map]->filename = strdup(name);
2717 
2718  cfregion = NULL;
2719  test = NULL;
2720 
2721  for (tile = 0; tile < tiled_map_list.maps[map]->tiled_maps.count; tile++) {
2722  if (tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion == NULL)
2723  /* map not processed, ignore it. */
2724  continue;
2725 
2726  if (!cfregion)
2727  cfregion = tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion;
2728  else if (cfregion != tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion) {
2729  printf("*** warning: tiled maps %s and %s not in same region (%s and %s).\n",
2730  tiled_map_list.maps[map]->tiled_maps.maps[0]->path, tiled_map_list.maps[map]->tiled_maps.maps[tile]->path,
2731  tiled_map_list.maps[map]->tiled_maps.maps[0]->cfregion->name, tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion->name);
2732  cfregion = NULL;
2733  }
2734 
2735  if (strcmp(tiled_map_list.maps[map]->tiled_maps.maps[tile]->name, tiled_map_list.maps[map]->tiled_maps.maps[tile]->filename)) {
2736  /* map has a custom name, use it */
2737  if (!test)
2738  test = tiled_map_list.maps[map]->tiled_maps.maps[tile]->name;
2739  }
2740  }
2741 
2742  if (!test) {
2743  /* this can happen of course if only partial maps were processed, but well... */
2744  printf("*** warning: tiled map without any name. First map path %s\n", tiled_map_list.maps[map]->tiled_maps.maps[0]->path);
2745  test = name;
2746  }
2747 
2748  tiled_map_list.maps[map]->name = strdup(test);
2749  tiled_map_list.maps[map]->cfregion = cfregion;
2750 
2751  strncpy(name, tiled_map_list.maps[map]->tiled_maps.maps[0]->path, sizeof(name));
2752  slash = strrchr(name, '/');
2753  if (!slash)
2754  snprintf(name, sizeof(name), "/");
2755  else
2756  *(slash+1) = '\0';
2757  strncat(name, tiled_map_list.maps[map]->filename, sizeof(name));
2758  tiled_map_list.maps[map]->path = strdup(name);
2759  }
2760 }
2761 
2772 static void fix_exits_for_map(struct_map_info *current, struct_map_list *from, int is_from) {
2773  int map, max;
2774  struct_map_info *group;
2775 
2776  max = from->count-1;
2777  for (map = max; map >= 0; map--) {
2778  if (from->maps[map]->tiled_group) {
2779  group = from->maps[map]->tiled_group;
2780  if (map != max)
2781  from->maps[map] = from->maps[max];
2782  from->count--;
2783  max--;
2784  add_map(group, from);
2785  add_map(current->tiled_group ? current->tiled_group : current, is_from ? &group->exits_to : &group->exits_from);
2786  }
2787  }
2788 }
2789 
2791 static void fix_exits_to_tiled_maps(void) {
2792  int map, region, max;
2793  struct_map_info *group;
2794 
2795  for (map = 0; map < maps_list.count; map++) {
2796  fix_exits_for_map(maps_list.maps[map], &maps_list.maps[map]->exits_from, 1);
2797  fix_exits_for_map(maps_list.maps[map], &maps_list.maps[map]->exits_to, 0);
2798  }
2799 
2800  for (region = 0; region < region_count; region++) {
2801  max = regions[region]->maps_list.count-1;
2802  for (map = max; map >= 0; map--) {
2803  if (regions[region]->maps_list.maps[map]->tiled_group) {
2804  group = regions[region]->maps_list.maps[map]->tiled_group;
2805  if (map != max)
2806  regions[region]->maps_list.maps[map] = regions[region]->maps_list.maps[max];
2807  regions[region]->maps_list.count--;
2808  max--;
2809  add_map(group, &regions[region]->maps_list);
2810  }
2811  }
2812  }
2813 }
2814 
2819 static void fix_tiled_map_monsters(void) {
2820  int map, race, max;
2821  struct_map_info *group;
2822 
2823  for (race = 0; race < races.count; race++) {
2824  max = races.races[race]->origin.count-1;
2825  for (map = max; map >= 0; map--) {
2826  if (races.races[race]->origin.maps[map]->tiled_group) {
2827  group = races.races[race]->origin.maps[map]->tiled_group;
2828  if (map != max)
2829  races.races[race]->origin.maps[map] = races.races[race]->origin.maps[max];
2830  races.races[race]->origin.count--;
2831  max--;
2832  add_map(group, &races.races[race]->origin);
2833  }
2834  }
2835  }
2836 
2837  for (map = 0; map < maps_list.count; map++) {
2838  if (maps_list.maps[map]->tiled_group) {
2839  for (race = 0; race < maps_list.maps[map]->monsters.count; race++) {
2840  add_race_to_list(maps_list.maps[map]->monsters.races[race], &maps_list.maps[map]->tiled_group->monsters, 1);
2841  }
2842  }
2843  }
2844 }
2845 
2847 static void write_all_maps(void) {
2848  int map;
2849 
2850  printf("Writing map pages...");
2851 
2852  for (map = 0; map < maps_list.count; map++)
2853  if (!maps_list.maps[map]->tiled_group)
2854  write_map_page(maps_list.maps[map]);
2855 
2856  printf(" done.\n");
2857 }
2858 
2860  int test;
2861  char picpath[500];
2862  struct stat stats;
2863 
2864  snprintf(picpath, sizeof(picpath), "%s%s%s", root, map->path, output_extensions[output_format]);
2865  if (stat(picpath, &stats))
2866  return 1;
2867 
2868  snprintf(picpath, sizeof(picpath), "%s%s.small%s", root, map->path, output_extensions[output_format]);
2869  if (stat(picpath, &stats))
2870  return 1;
2871 
2872  for (test = 0; test < map->tiled_maps.count; test++) {
2873  if (map->tiled_maps.maps[test]->pic_was_done)
2874  return 1;
2875  }
2876 
2877  return 0;
2878 }
2879 
2892  int xmin = 0, xmax = 0, ymin = 0, ymax = 0, tiled, count, last;
2893  char picpath[500];
2894  gdImagePtr small, large, load;
2895  FILE *out;
2896  struct_map_info *current;
2897 
2898  if (!generate_pics)
2899  return;
2900 
2901  printf(" Generating composite map for %s...", map->name);
2902  fflush(stdout);
2903 
2904  if (!tiled_map_need_pic(map)) {
2905  printf(" already uptodate.\n");
2906  return;
2907  }
2908 
2909  count = map->tiled_maps.count;
2910  if (count == 0) {
2911  printf("Tiled map without tiled maps?\n");
2912  abort();
2913  }
2914  map->tiled_maps.maps[0]->processed = 1;
2915  map->tiled_maps.maps[0]->tiled_x_from = 0;
2916  map->tiled_maps.maps[0]->tiled_y_from = 0;
2917 
2918  while (count > 0) {
2919  last = count;
2920 
2921  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2922  current = map->tiled_maps.maps[tiled];
2923  if (current->processed != 1)
2924  continue;
2925 
2926  count--;
2927 
2928  if ((current->tiles[0]) && (current->tiles[0]->processed == 0)) {
2929  current->tiles[0]->processed = 1;
2930  current->tiles[0]->tiled_x_from = current->tiled_x_from;
2931  current->tiles[0]->tiled_y_from = current->tiled_y_from-current->tiles[0]->height;
2932  }
2933  if ((current->tiles[1]) && (current->tiles[1]->processed == 0)) {
2934  current->tiles[1]->processed = 1;
2935  current->tiles[1]->tiled_x_from = current->tiled_x_from+current->width;
2936  current->tiles[1]->tiled_y_from = current->tiled_y_from;
2937  }
2938  if ((current->tiles[2]) && (current->tiles[2]->processed == 0)) {
2939  current->tiles[2]->processed = 1;
2940  current->tiles[2]->tiled_x_from = current->tiled_x_from;
2941  current->tiles[2]->tiled_y_from = current->tiled_y_from+current->height;
2942  }
2943  if ((current->tiles[3]) && (current->tiles[3]->processed == 0)) {
2944  current->tiles[3]->processed = 1;
2945  current->tiles[3]->tiled_x_from = current->tiled_x_from-current->tiles[3]->width;
2946  current->tiles[3]->tiled_y_from = current->tiled_y_from;
2947  }
2948  }
2949 
2950  if (last == count) {
2951  printf("do_tiled_map_picture: didn't process any map in %s (%d left)??\n", map->path, last);
2952  abort();
2953  }
2954  }
2955 
2956  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2957  if (map->tiled_maps.maps[tiled]->tiled_x_from < xmin)
2958  xmin = map->tiled_maps.maps[tiled]->tiled_x_from;
2959  if (map->tiled_maps.maps[tiled]->tiled_y_from < ymin)
2960  ymin = map->tiled_maps.maps[tiled]->tiled_y_from;
2961  if (map->tiled_maps.maps[tiled]->tiled_x_from+map->tiled_maps.maps[tiled]->width > xmax)
2962  xmax = map->tiled_maps.maps[tiled]->tiled_x_from+map->tiled_maps.maps[tiled]->width;
2963  if (map->tiled_maps.maps[tiled]->tiled_y_from+map->tiled_maps.maps[tiled]->height > ymax)
2964  ymax = map->tiled_maps.maps[tiled]->tiled_y_from+map->tiled_maps.maps[tiled]->height;
2965  }
2966 
2967  large = gdImageCreateTrueColor(32*(xmax-xmin), 32*(ymax-ymin));
2968  small = gdImageCreateTrueColor(size_small*(xmax-xmin), size_small*(ymax-ymin));
2969 
2970  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2971  snprintf(picpath, sizeof(picpath), "%s%s%s", root, map->tiled_maps.maps[tiled]->path, output_extensions[output_format]);
2972 
2973  out = fopen(picpath, "rb");
2974  if (!out) {
2975  printf("\n do_tiled_map_picture: warning: pic file not found for %s (errno=%d)\n", map->tiled_maps.maps[tiled]->path, errno);
2976  continue;
2977  }
2978  if (output_format == OF_PNG)
2979  load = gdImageCreateFromPng(out);
2980  else
2981  load = gdImageCreateFromJpeg(out);
2982  fclose(out);
2983  if (!load) {
2984  printf("\n do_tiled_map_picture: warning: pic not found for %s\n", map->tiled_maps.maps[tiled]->path);
2985  continue;
2986  }
2987  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);
2988  gdImageDestroy(load);
2989 
2990  snprintf(picpath, sizeof(picpath), "%s%s.small%s", root, map->tiled_maps.maps[tiled]->path, output_extensions[output_format]);
2991  out = fopen(picpath, "rb");
2992  if (output_format == OF_PNG)
2993  load = gdImageCreateFromPng(out);
2994  else
2995  load = gdImageCreateFromJpeg(out);
2996  fclose(out);
2997  if (!load) {
2998  printf("\n do_tiled_map_picture: warning: small pic not found for %s\n", map->tiled_maps.maps[tiled]->path);
2999  continue;
3000  }
3001  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);
3002  gdImageDestroy(load);
3003  }
3004 
3005  snprintf(picpath, sizeof(picpath), "%s%s%s", root, map->path, output_extensions[output_format]);
3006  out = fopen(picpath, "wb+");
3007  save_picture(out, large);
3008  fclose(out);
3009 
3010  snprintf(picpath, sizeof(picpath), "%s%s.small%s", root, map->path, output_extensions[output_format]);
3011  out = fopen(picpath, "wb+");
3012  save_picture(out, small);
3013  fclose(out);
3014 
3015  gdImageDestroy(small);
3016  gdImageDestroy(large);
3017 
3018  printf(" done.\n");
3019 }
3020 
3023 
3024  do_tiled_map_picture(map);
3025 
3028  write_map_page(map);
3029 }
3030 
3032 static void write_tiled_maps(void) {
3033  int map;
3034 
3035  printf("Writing tiled map information...\n");
3036 
3037  for (map = 0; map < tiled_map_list.count; map++)
3038  write_tiled_map_page(tiled_map_list.maps[map]);
3039 
3040  printf(" done.\n");
3041 }
3042 
3044 static void write_maps_by_level(void) {
3045  int map;
3046  FILE *out;
3047  char name[500];
3048  char mappath[500];
3049  char *letters = NULL;
3050  char *maps = NULL;
3051  char *level = NULL;
3052  int lastlevel = -1;
3053  char strlevel[10];
3054  char strcount[10];
3055  const char *val_vars[] = { "LEVEL", "MAPS", NULL };
3056  const char *val_values[] = { strlevel, NULL, NULL };
3057  const char *map_vars[] = { "MAPNAME", "MAPPATH", NULL };
3058  const char *map_values[] = { NULL, mappath, NULL };
3059  const char *idx_vars[] = { "COUNT", "LEVELS", NULL };
3060  const char *idx_values[] = { strcount, NULL, NULL };
3061  int levelcount = 0;
3062  struct_map_info *last_tiled = NULL;
3063  struct_map_info *process;
3064 
3065  printf("Writing map index by level...");
3066 
3067  snprintf(name, sizeof(name), "%s/index_by_level.html", root);
3068 
3069  qsort(maps_list.maps, maps_list.count, sizeof(struct_map_info *), sort_map_info_by_level);
3070 
3071  for (map = 0; map < maps_list.count; map++) {
3072  process = maps_list.maps[map];
3073  if (maps_list.maps[map]->level != lastlevel) {
3074  if (maps) {
3075  snprintf(strlevel, sizeof(strlevel), "%d", lastlevel);
3076  val_values[1] = maps;
3077  letters = cat_template(letters, do_template(level_value_template, val_vars, val_values));
3078  free(maps);
3079  maps = NULL;
3080  }
3081  lastlevel = process->level;
3082  levelcount++;
3083  last_tiled = NULL;
3084  } else
3085  if (last_tiled && last_tiled == process->tiled_group)
3086  /* Group maps of same tiled group and level, but make them appear in different levels if applicable. */
3087  continue;
3088 
3089  if (process->tiled_group) {
3090  process = process->tiled_group;
3091  last_tiled = process;
3092  } else
3093  last_tiled = process->tiled_group;
3094 
3095  map_values[0] = process->name;
3096  snprintf(mappath, sizeof(mappath), "%s.html", process->path+1); /* don't want the leading / */
3097  maps = cat_template(maps, do_template(level_map_template, map_vars, map_values));
3098  }
3099 
3100  snprintf(strlevel, sizeof(strlevel), "%d", lastlevel);
3101  val_values[1] = maps;
3102  letters = cat_template(letters, do_template(level_value_template, val_vars, val_values));
3103  free(maps);
3104  maps = NULL;
3105 
3106  snprintf(strcount, sizeof(strcount), "%d", levelcount);
3107  idx_values[1] = letters;
3108  level = do_template(level_template, idx_vars, idx_values);
3109  free(letters);
3110 
3111  out = fopen(name, "w+");
3112  fprintf(out, level);
3113  fclose(out);
3114  free(level);
3115 
3116  printf(" done.\n");
3117 }
3118 
3122 static void write_equipment_index(void) {
3123  int item, map;
3124  FILE *out;
3125  char name[500];
3126 
3127  printf("Generating special equipment list..");
3128  fflush(stdout);
3129 
3130  qsort(special_equipment, equipment_count, sizeof(struct_equipment *), sort_equipment);
3131 
3132  snprintf(name, sizeof(name), "%s/items.html", root);
3133  out = fopen(name, "w+");
3134 
3135  fprintf(out, "<html><head><title>Item list</title></head></body><h1>Special items found in maps</h1>\n");
3136  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");
3137 
3138  for (item = 0; item < equipment_count; item++) {
3139  fprintf(out, "<tr><td>%s</td><td><ul>", special_equipment[item]->name);
3140 
3141  for (map = 0; map < special_equipment[item]->origin.count; map++)
3142  fprintf(out, "<li>%s</li>\n", special_equipment[item]->origin.maps[map]->path);
3143 
3144  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);
3145  }
3146  fprintf(out, "</body></html>\n");
3147  fclose(out);
3148 
3149  printf(" done.\n");
3150 }
3151 
3155 static void write_race_index(void) {
3156  int item, map;
3157  FILE *out;
3158  char name[500];
3159 
3160  printf("Generating monster list...");
3161  fflush(stdout);
3162 
3163  qsort(races.races, races.count, sizeof(struct_race *), sort_race);
3164 
3165  snprintf(name, sizeof(name), "%s/monsters.html", root);
3166  out = fopen(name, "w+");
3167 
3168  fprintf(out, "<html><head><title>Monster list</title></head></body><h1>Monsters found in maps</h1>\n");
3169  fprintf(out, "<table border=\"1\"><tr><th>Name</th><th>Count</th><th>Map(s)</th></tr>\n");
3170 
3171  for (item = 0; item < races.count; item++) {
3172  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);
3173 
3174  qsort(races.races[item]->origin.maps, races.races[item]->origin.count, sizeof(struct_map_info *), sort_map_info);
3175 
3176  for (map = 0; map < races.races[item]->origin.count; map++)
3177  fprintf(out, "<li>%s</li>\n", races.races[item]->origin.maps[map]->path);
3178 
3179  fprintf(out, "</ul></td></tr>\n");
3180  }
3181  fprintf(out, "</body></html>\n");
3182  fclose(out);
3183 
3184  printf(" done.\n");
3185 }
3186 
3188 static const char *ignore_path[] = {
3189  "/Info",
3190  "/editor",
3191  "/python",
3192  "/styles",
3193  "/templates",
3194  "/test",
3195  "/unlinked",
3196  NULL };
3197 
3199 static const char *ignore_name[] = {
3200  ".",
3201  "..",
3202  ".svn",
3203  "README",
3204  NULL };
3205 
3212 static void find_maps(const char *from) {
3213  struct dirent *file;
3214  struct stat statbuf;
3215  int status, ignore;
3216  char path[1024], full[1024];
3217  DIR *dir;
3218 
3219  for (ignore = 0; ignore_path[ignore] != NULL; ignore++) {
3220  if (strcmp(from, ignore_path[ignore]) == 0)
3221  return;
3222  }
3223 
3224  snprintf(path, sizeof(path), "%s/%s%s", settings.datadir, settings.mapdir, from);
3225  dir = opendir(path);
3226 
3227  if (dir) {
3228  for (file = readdir(dir); file; file = readdir(dir)) {
3229 
3230  for (ignore = 0; ignore_name[ignore] != NULL; ignore++) {
3231  if (strcmp(file->d_name, ignore_name[ignore]) == 0)
3232  break;
3233  }
3234  if (ignore_name[ignore] != NULL)
3235  continue;
3236 
3237  snprintf(full, sizeof(full), "%s/%s", path, file->d_name);
3238 
3239  status = stat(full, &statbuf);
3240  if ((status != -1) && (S_ISDIR(statbuf.st_mode))) {
3241  snprintf(full, sizeof(full), "%s/%s", from, file->d_name);
3242  find_maps(full);
3243  continue;
3244  }
3246  found_maps_allocated += 50;
3247  found_maps = realloc(found_maps, found_maps_allocated*sizeof(char *));
3248  }
3249  snprintf(full, sizeof(full), "%s/%s", from, file->d_name);
3250  found_maps[found_maps_count++] = strdup(full);
3251  }
3252  closedir(dir);
3253  }
3254 }
3255 
3257 static void dump_unused_maps(void) {
3258  FILE *dump;
3259  char path[1024];
3260  int index, found = 0;
3261 
3262  snprintf(path, sizeof(path), "%s/%s", root, "maps.unused");
3263  dump = fopen(path, "w+");
3264  if (dump == NULL) {
3265  printf("Unable to open file maps.unused!\n");
3266  return;
3267  }
3268  for (index = 0; index < found_maps_count; index++) {
3269  if (found_maps[index] != NULL) {
3270  fprintf(dump, "%s\n", found_maps[index]);
3271  free(found_maps[index]);
3272  found++;
3273  }
3274  }
3275  fclose(dump);
3276  printf("%d unused maps.\n", found);
3277 }
3278 
3280 static void write_world_info(void) {
3281  FILE *file;
3282  char path[MAX_BUF];
3283  int x, y;
3284  gdImagePtr elevationmap;
3285 
3286  if (!world_exit_info)
3287  return;
3288 
3289  printf("Saving exit/blocking/road information...");
3290  snprintf(path, sizeof(path), "%s/%s%s", root, "world_info", output_extensions[output_format]);
3291  file = fopen(path, "wb+");
3292  save_picture(file, infomap);
3293  fclose(file);
3294  printf("done.\n");
3295  gdImageDestroy(infomap);
3296  infomap = NULL;
3297 
3298  if (elevation_min == 0 || elevation_max == 0) {
3299  puts("Error: Could not save elevation world map due to not finding any minimum or maximum elevation.");
3300  return;
3301  }
3302 
3303  elevationmap = gdImageCreateTrueColor(30*50, 30*50);;
3304 
3305  for (x = 0; x < 30*50; x++) {
3306  for (y = 0; y < 30*50; y++) {
3307  gdImageSetPixel(elevationmap, x, y, get_elevation_color(elevation_info[x][y], elevationmap));
3308  }
3309  }
3310 
3311  printf("Saving elevation world map...");
3312  snprintf(path, sizeof(path), "%s/%s%s", root, "world_elevation", output_extensions[output_format]);
3313  file = fopen(path, "wb+");
3314  save_picture(file, elevationmap);
3315  fclose(file);
3316  printf("done.\n");
3317  gdImageDestroy(elevationmap);
3318  elevationmap = NULL;
3319 }
3320 
3322 static void write_regions_link(void) {
3323  FILE *file;
3324  char path[MAX_BUF];
3325  int link;
3326 
3327  if (!do_regions_link)
3328  return;
3329 
3330  printf("Writing regions link file...");
3331  snprintf(path, sizeof(path), "%s/%s", root, "region_links.dot");
3332  file = fopen(path, "wb+");
3333  fprintf(file, "digraph {\n");
3334  for (link = 0; link < regions_link_count; link++)
3335  fprintf(file, regions_link[link]);
3336  fprintf(file, "}\n");
3337  fclose(file);
3338  printf("done.\n");
3339 }
3340 
3349 static void write_slaying_map_name(FILE *file, struct_map_info *map) {
3350  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);
3351 }
3352 
3367 static void write_one_slaying_info(FILE *file, struct_slaying_info *info, int item, const char *with, const char *without) {
3368  int map;
3369 
3370  if (info->maps[item].count == 0) {
3371  if (without)
3372  fprintf(file, without);
3373  return;
3374  }
3375 
3376  qsort(info->maps[item].maps, info->maps[item].count, sizeof(const char *), sort_mapname);
3377 
3378  fprintf(file, with);
3379  fprintf(file, "<ul>\n");
3380  for (map = 0; map < info->maps[item].count; map++) {
3381  fprintf(file, "\t<li>");
3382  write_slaying_map_name(file, info->maps[item].maps[map]);
3383  fprintf(file, "</li>\n");
3384  }
3385  fprintf(file, "</ul>\n");
3386 }
3387 
3398 static int sort_slaying(const void *left, const void *right) {
3400  struct_slaying_info *r = *(struct_slaying_info **)right;
3401 
3402  return strcasecmp(l->slaying, r->slaying);
3403 }
3404 
3408 static void write_slaying_info(void) {
3409  FILE *file;
3410  char path[MAX_BUF];
3411  int lock;
3412  struct_slaying_info *info;
3413 
3414  printf("Writing slaying info file...");
3415 
3416  qsort(slaying_info, slaying_count, sizeof(struct_slaying_info *), sort_slaying);
3417 
3418  snprintf(path, sizeof(path), "%s/%s", root, "slaying_info.html");
3419  file = fopen(path, "wb+");
3420 
3421  fprintf(file, "<html>\n<head>\n<title>Slaying information</title>\n</head>\n<body>\n");
3422  fprintf(file, "<p>This is a list of various slaying fields on keys, containers, doors, detectors.</p>");
3423 
3424  for (lock = 0; lock < slaying_count; lock++) {
3425  info = slaying_info[lock];
3426  fprintf(file, "<h1>%s</h1>\n", info->slaying);
3427 
3428  if (info->maps[S_DOOR].count == 0 && info->maps[S_CONTAINER].count == 0 && info->maps[S_CONNECT].count == 0) {
3429  fprintf(file, "No door, container or detector matching this slaying.<br />\n");
3430  } else {
3431  write_one_slaying_info(file, info, S_DOOR, "Connected doors:\n", NULL);
3432  write_one_slaying_info(file, info, S_CONTAINER, "Matching containers:\n", NULL);
3433  write_one_slaying_info(file, info, S_CONNECT, "Detectors and such:\n", NULL);
3434  }
3435  write_one_slaying_info(file, info, S_KEY, "Matching keys:\n", "No key with this slaying.<br />\n");
3436  }
3437 
3438  fprintf(file, "</body>\n</html>\n");
3439 
3440  fclose(file);
3441  printf("done.\n");
3442 }
3443 
3447 static void write_npc_list(void) {
3448  FILE *file;
3449  char path[MAX_BUF];
3450  int map, npc;
3451 
3452  printf("Writing NPC info file...");
3453 
3454  qsort(slaying_info, slaying_count, sizeof(struct_slaying_info *), sort_slaying);
3455 
3456  snprintf(path, sizeof(path), "%s/%s", root, "npc_info.html");
3457  file = fopen(path, "wb+");
3458 
3459  fprintf(file, "<html>\n<head>\n<title>NPCs who have a special message</title>\n</head>\n<body>\n");
3460  fprintf(file, "<p>This is a list of NPCs having a special message.</p>");
3461  fprintf(file, "<ul>\n");
3462 
3463  for (map = 0; map < maps_list.count; map++) {
3464  if (maps_list.maps[map]->npcs.count == 0)
3465  continue;
3466  fprintf(file, "<li>%s</li>\n<ul>", maps_list.maps[map]->path);
3467  for (npc = 0; npc < maps_list.maps[map]->npcs.count; npc++) {
3468  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);
3469  }
3470  fprintf(file, "</ul>\n</li>\n");
3471  }
3472 
3473  fprintf(file, "</ul>\n");
3474  fprintf(file, "</body>\n</html>\n");
3475 
3476  fclose(file);
3477  printf("done.\n");
3478 }
3479 
3486 static void do_help(const char *program) {
3487  printf("Crossfire Mapper will generate pictures of maps, and create indexes for all maps and regions.\n\n");
3488  printf("Syntax: %s\n\n", program);
3489  printf("Optional arguments:\n");
3490  printf(" -nopics don't generate pictures.\n");
3491  printf(" -noindex don't generate global map index.\n");
3492  printf(" -root=<path> destination path. Default 'html'.\n");
3493  printf(" -limit=<number> stop processing after this number of maps, -1 to do all maps (default).\n");
3494  printf(" -showmaps outputs the name of maps as they are processed.\n");
3495  printf(" -jpg[=quality] generate jpg pictures, instead of default png. Quality should be 0-95, -1 for automatic.\n");
3496  printf(" -forcepics force to regenerate pics, even if pics's date is after map's.\n");
3497  printf(" -addmap=<map> adds a map to process. Path is relative to map's directory root.\n");
3498  printf(" -rawmaps generates maps pics without items on random (shop, treasure) tiles.\n");
3499  printf(" -warnnopath inform when an exit has no path set.\n");
3500  printf(" -listunusedmaps finds all unused maps in the maps directory.\n");
3501  printf(" -noworldmap don't write the world map in world.png.\n");
3502  printf(" -noregionslink don't generate regions relation file.\n");
3503  printf(" -regionslink generate regions relation file.\n");
3504  printf(" -noexitmap don't generate map of exits.\n");
3505  printf(" -exitmap generate map of exits.\n");
3506  printf(" -tileset=<number> use specified tileset to generate the pictures. Default 0 (standard).\n");
3507  printf("\n\n");
3508  exit(0);
3509 }
3510 
3519 static void do_parameters(int argc, char **argv) {
3520  int arg = 1;
3521  char path[500];
3522 
3523  root[0] = '\0';
3524 
3525  while (arg < argc) {
3526  if (strcmp(argv[arg], "-nopics") == 0)
3527  generate_pics = 0;
3528  else if (strcmp(argv[arg], "-noindex") == 0)
3529  generate_index = 0;
3530  else if (strncmp(argv[arg], "-root=", 6) == 0)
3531  strncpy(root, argv[arg]+6, 500);
3532  else if (strncmp(argv[arg], "-limit=", 7) == 0)
3533  map_limit = atoi(argv[arg]+7);
3534  else if (strcmp(argv[arg], "-showmaps") == 0)
3535  show_maps = 1;
3536  else if (strcmp(argv[arg], "-jpg") == 0) {
3538  if (argv[arg][4] == '=') {
3539  jpeg_quality = atoi(argv[arg]+5);
3540  if (jpeg_quality < 0)
3541  jpeg_quality = -1;
3542  }
3543  }
3544  else if (strcmp(argv[arg], "-forcepics") == 0)
3545  force_pics = 1;
3546  else if (strncmp(argv[arg], "-addmap=", 8) == 0) {
3547  if (*(argv[arg]+8) == '/')
3548  strncpy(path, argv[arg]+8, 500);
3549  else
3550  snprintf(path, 500, "/%s", argv[arg]+8);
3551  add_map(get_map_info(path), &maps_list);
3552  }
3553  else if (strcmp(argv[arg], "-rawmaps") == 0)
3554  rawmaps = 1;
3555  else if (strcmp(argv[arg], "-warnnopath") == 0)
3556  warn_no_path = 1;
3557  else if (strcmp(argv[arg], "-listunusedmaps") == 0)
3558  list_unused_maps = 1;
3559  else if (strcmp(argv[arg], "-noworldmap") == 0)
3560  world_map = 0;
3561  else if (strcmp(argv[arg], "-noregionslink") == 0)
3562  do_regions_link = 0;
3563  else if (strcmp(argv[arg], "-regionslink") == 0)
3564  do_regions_link = 1;
3565  else if (strcmp(argv[arg], "-noexitmap") == 0)
3566  world_exit_info = 0;
3567  else if (strcmp(argv[arg], "-exitmap") == 0)
3568  world_exit_info = 1;
3569  else if (strncmp(argv[arg], "-tileset=", 9) == 0) {
3570  tileset = atoi(argv[arg]+9);
3571  /* check of validity is done in main() as we need to actually have the sets loaded. */
3572  } else
3573  do_help(argv[0]);
3574  arg++;
3575  }
3576  if (!strlen(root))
3577  strcpy(root, "html");
3578  if (root[strlen(root)-1] == '/')
3579  root[strlen(root)-1] = '\0';
3580  if (map_limit < -1)
3581  map_limit = -1;
3582 }
3583 
3587 static void create_destination(void) {
3588  char dummy[502];
3589 
3590  strcpy(dummy, root);
3591  strcat(dummy, "/a");
3592  make_path_to_file(dummy);
3593 }
3594 
3603 static const char *yesno(int value) {
3604  return (value ? "yes" : "no");
3605 }
3606 
3607 int main(int argc, char **argv) {
3608  int current_map = 0, i;
3609  char max[50];
3610  region *dummy;
3611 
3612  init_map_list(&maps_list);
3613  init_map_list(&tiled_map_list);
3614  init_race_list(&races);
3615  pics_allocated = 0;
3616 
3617  do_parameters(argc, argv);
3618 
3619  printf("Initializing Crossfire data...\n");
3620 
3621  settings.debug = 0;
3622 
3623  init_globals();
3624  init_library();
3625  init_archetypes();
3626  init_artifacts();
3627  init_formulae();
3628  init_readable();
3629  init_regions();
3630 
3631  init_gods();
3633 
3634  /* Add a dummy region so unlinked maps can be identified. */
3635  dummy = get_region_struct();
3636  dummy->fallback = 1;
3637  dummy->name = add_string("unlinked");
3638  dummy->longname = add_string("This dummy region contains all maps without a region set.");
3639  dummy->longname = add_string("This dummy region contains all maps without a region set.");
3640  dummy->next = first_region;
3641  first_region = dummy;
3642 
3643  printf("\n\n done.\n\n");
3644 
3645  if (!is_valid_faceset(tileset)) {
3646  printf("Erreor: invalid tileset %d!\n", tileset);
3647  exit(1);
3648  }
3649 
3651  gdfaces = calloc(1, sizeof(gdImagePtr)*nrofpixmaps);
3652 
3653  read_template("templates/map.template", &map_template);
3654  read_template("templates/map_no_exit.template", &map_no_exit_template);
3655  read_template("templates/map_with_exit.template", &map_with_exit_template);
3656  read_template("templates/map_exit.template", &map_exit_template);
3657  read_template("templates/map_no_exit_to.template", &map_no_exit_to_template);
3658  read_template("templates/map_with_exit_to.template", &map_with_exit_to_template);
3659  read_template("templates/map_exit_to.template", &map_exit_to_template);
3660  read_template("templates/map_lore.template", &map_lore_template);
3661  read_template("templates/map_no_lore.template", &map_no_lore_template);
3662  read_template("templates/map_no_monster.template", &map_no_monster_template);
3663  read_template("templates/map_monster_before.template", &map_monster_before_template);
3664  read_template("templates/map_monster_between.template", &map_monster_between_template);
3665  read_template("templates/map_monster_one.template", &map_monster_one_template);
3666  read_template("templates/map_monster_after.template", &map_monster_after_template);
3667 
3668  read_template("templates/index.template", &index_template);
3669  read_template("templates/index_letter.template", &index_letter);
3670  read_template("templates/index_map.template", &index_map);
3671 
3672  read_template("templates/region.template", &region_template);
3673  read_template("templates/region_letter.template", &region_letter_template);
3674  read_template("templates/region_map.template", &region_map_template);
3675 
3676  read_template("templates/index_region.template", &index_region_template);
3677  read_template("templates/index_region_region.template", &index_region_region_template);
3678 
3679  read_template("templates/world.template", &world_template);
3680  read_template("templates/world_row.template", &world_row_template);
3681  read_template("templates/world_map.template", &world_map_template);
3682 
3683  read_template("templates/level.template", &level_template);
3684  read_template("templates/level_value.template", &level_value_template);
3685  read_template("templates/level_map.template", &level_map_template);
3686 
3687  read_template("templates/quests.template", &index_quest_template);
3688  read_template("templates/quests_quest.template", &quest_template);
3689  read_template("templates/quests_map.template", &quest_map_template);
3690 
3691  read_template("templates/map_with_quests.template", &map_with_quests_template);
3692  read_template("templates/map_one_quest.template", &map_one_quest_template);
3693  read_template("templates/map_no_quest.template", &map_no_quest_template);
3694 
3695  if (map_limit != -1)
3696  snprintf(max, sizeof(max), "%d", map_limit);
3697  else
3698  strcpy(max, "(none)");
3699  printf("Crossfire map browser generator\n");
3700  printf("-------------------------------\n\n");
3701  printf("Parameters:\n");
3702  printf(" path to write files: %s\n", root);
3703  printf(" maximum number of maps to process: %s\n", max);
3704  printf(" will generate map picture: %s\n", yesno(generate_pics));
3705  printf(" will always generate map picture: %s\n", yesno(force_pics));
3706  printf(" picture output format: %s\n", output_extensions[output_format]);
3707  if (output_format == OF_JPG)
3708  printf(" JPEG quality: %d\n", jpeg_quality);
3709  printf(" will generate map index: %s\n", yesno(generate_index));
3710  printf(" show map being processed: %s\n", yesno(show_maps));
3711  printf(" generate raw maps: %s\n", yesno(rawmaps));
3712  printf(" warn of exit without path: %s\n", yesno(warn_no_path));
3713  printf(" list unused maps: %s\n", yesno(list_unused_maps));
3714  printf(" generate world map: %s\n", yesno(world_map));
3715  printf(" generate exit map: %s\n", yesno(world_exit_info));
3716  printf(" generate regions link file: %s\n", yesno(do_regions_link));
3717  printf(" tileset: %s\n", facesets[tileset].fullname);
3718  printf("\n");
3719 
3720  if (list_unused_maps) {
3721  printf("listing all maps...");
3722  find_maps("");
3723  printf("done, %d maps found.\n", found_maps_count);
3724  qsort(found_maps, found_maps_count, sizeof(char *), sortbyname);
3725  }
3726 
3727  /* exit/blocking information. */
3728  infomap = gdImageCreateTrueColor(30*50, 30*50);
3729  color_unlinked_exit = gdImageColorResolve(infomap, 255, 0, 0);
3730  color_linked_exit = gdImageColorResolve(infomap, 255, 255, 255);
3731  color_road = gdImageColorResolve(infomap, 0, 255, 0);
3732  color_blocking = gdImageColorResolve(infomap, 0, 0, 255);
3733  color_slowing = gdImageColorResolve(infomap, 0, 0, 127);
3734  elevation_info = calloc(50*30, sizeof(int *));
3735  for (i = 0; i < 50*30; i++)
3736  elevation_info[i] = calloc(50*30, sizeof(int));
3737  elevation_min = 0;
3738  elevation_max = 0;
3739 
3740  printf("browsing maps...\n");
3741 
3743 
3744  while (current_map < maps_list.count) {
3745  process_map(maps_list.maps[current_map++]);
3746  if (current_map%100 == 0) {
3747  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);
3748  }
3749  if ((map_limit != -1) && (current_map == map_limit)) {
3750  printf(" --- map limit reached, stopping ---\n");
3751  break;
3752  }
3753  }
3754 
3755  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);
3756 
3757  if (list_unused_maps)
3758  dump_unused_maps();
3759 
3761  fix_map_names();
3762  fix_tiled_map();
3764 
3765  write_all_maps();
3766  write_maps_index();
3768  write_tiled_maps();
3769 
3772 
3773  write_world_map();
3774  write_world_info();
3775 
3778 
3780 
3782  write_race_index();
3783  write_npc_list();
3784 
3785  return 0;
3786 }
3787 
3789  object *tmp, *above = NULL;
3790  int x, y;
3791 
3792  if (m == NULL)
3793  return;
3794 
3795  for (x = 0; x < MAP_WIDTH(m); x++)
3796  for (y = 0; y < MAP_HEIGHT(m); y++)
3797  for (tmp = GET_MAP_OB(m, x, y); tmp != NULL; tmp = above) {
3798  above = tmp->above;
3799 
3800  if (tmp->inv) {
3801  object *invtmp, *invnext;
3802 
3803  for (invtmp = tmp->inv; invtmp != NULL; invtmp = invnext) {
3804  invnext = invtmp->below;
3805 
3806  if (QUERY_FLAG(invtmp, FLAG_AUTO_APPLY))
3807  auto_apply(invtmp);
3808  else if (invtmp->type == TREASURE && HAS_RANDOM_ITEMS(invtmp)) {
3809  while ((invtmp->stats.hp--) > 0)
3810  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3811  invtmp->randomitems = NULL;
3812  } else if (invtmp
3813  && invtmp->arch
3814  && invtmp->type != TREASURE
3815  && invtmp->type != SPELL
3816  && invtmp->type != CLASS
3817  && HAS_RANDOM_ITEMS(invtmp)) {
3818  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3819  /* Need to clear this so that we never try to create
3820  * treasure again for this object
3821  */
3822  invtmp->randomitems = NULL;
3823  }
3824  }
3825  /* This is really temporary - the code at the bottom will
3826  * also set randomitems to null. The problem is there are bunches
3827  * of maps/players already out there with items that have spells
3828  * which haven't had the randomitems set to null yet.
3829  * MSW 2004-05-13
3830  *
3831  * And if it's a spellbook, it's better to set randomitems to NULL too,
3832  * else you get two spells in the book ^_-
3833  * Ryo 2004-08-16
3834  */
3835  if (tmp->type == WAND
3836  || tmp->type == ROD
3837  || tmp->type == SCROLL
3838  || tmp->type == HORN
3839  || tmp->type == FIREWALL
3840  || tmp->type == POTION
3841  || tmp->type == ALTAR
3842  || tmp->type == SPELLBOOK)
3843  tmp->randomitems = NULL;
3844  }
3845 
3846  if (QUERY_FLAG(tmp, FLAG_AUTO_APPLY))
3847  auto_apply(tmp);
3848  else if ((tmp->type == TREASURE || (tmp->type == CONTAINER)) && HAS_RANDOM_ITEMS(tmp)) {
3849  while ((tmp->stats.hp--) > 0)
3850  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
3851  tmp->randomitems = NULL;
3852  } else if (tmp->type == TIMED_GATE) {
3853  object *head = tmp->head != NULL ? tmp->head : tmp;
3854 
3855  if (QUERY_FLAG(head, FLAG_IS_LINKED)) {
3856  tmp->speed = 0;
3857  update_ob_speed(tmp);
3858  }
3859  /* This function can be called everytime a map is loaded, even when
3860  * swapping back in. As such, we don't want to create the treasure
3861  * over and ove again, so after we generate the treasure, blank out
3862  * randomitems so if it is swapped in again, it won't make anything.
3863  * This is a problem for the above objects, because they have counters
3864  * which say how many times to make the treasure.
3865  */
3866  } else if (tmp
3867  && tmp->arch
3868  && tmp->type != PLAYER
3869  && tmp->type != TREASURE
3870  && tmp->type != SPELL
3871  && tmp->type != PLAYER_CHANGER
3872  && tmp->type != CLASS
3873  && HAS_RANDOM_ITEMS(tmp)) {
3874  create_treasure(tmp->randomitems, tmp, GT_APPLY, m->difficulty, 0);
3875  tmp->randomitems = NULL;
3876  }
3877  }
3878 
3879  for (x = 0; x < MAP_WIDTH(m); x++)
3880  for (y = 0; y < MAP_HEIGHT(m); y++)
3881  for (tmp = GET_MAP_OB(m, x, y); tmp != NULL; tmp = tmp->above)
3882  if (tmp->above
3883  && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL))
3884  check_trigger(tmp, tmp->above);
3885 }
3886 
3887 #ifndef DOXYGEN_SHOULD_SKIP_THIS
3888 
3893 void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *txt, const char *txt2) {
3894  fprintf(logfile, "%s\n", txt);
3895 }
3896 
3897 void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format, ...) {
3898  va_list ap;
3899 
3900  va_start(ap, old_format);
3901  vfprintf(logfile, old_format, ap);
3902  va_end(ap);
3903 }
3904 
3905 void ext_info_map(int color, const mapstruct *map, uint8 type, uint8 subtype, const char *str1, const char *str2) {
3906  fprintf(logfile, "ext_info_map: %s\n", str2);
3907 }
3908 
3909 void move_firewall(object *ob) {
3910 }
3911 
3912 void emergency_save(int x) {
3913 }
3914 
3915 void clean_tmp_files(void) {
3916 }
3917 
3918 void esrv_send_item(object *ob, object *obx) {
3919 }
3920 
3921 void dragon_ability_gain(object *ob, int x, int y) {
3922 }
3923 
3925 }
3926 
3927 object *find_skill_by_number(object *who, int skillno) {
3928  return NULL;
3929 }
3930 
3931 void esrv_del_item(player *pl, int tag) {
3932 }
3933 
3934 void esrv_update_item(int flags, object *pl, object *op) {
3935 }
3936 
3938 }
3939 
3940 void monster_check_apply(object *ob, object *obt) {
3941 }
3942 
3943 void trap_adjust(object *ob, int x) {
3944 }
3945 
3946 int execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix) {
3947  return 0;
3948 }
3949 
3950 int execute_global_event(int eventcode, ...) {
3951  return 0;
3952 }
3953 
3954 int auto_apply(object *op) {
3955  object *tmp = NULL, *tmp2;
3956  int i;
3957 
3958  switch (op->type) {
3959  case SHOP_FLOOR:
3960  if (!HAS_RANDOM_ITEMS(op))
3961  return 0;
3962  do {
3963  i = 10; /* let's give it 10 tries */
3964  while ((tmp = generate_treasure(op->randomitems, op->stats.exp ? (int)op->stats.exp : MAX(op->map->difficulty, 5))) == NULL && --i)
3965  ;
3966  if (tmp == NULL)
3967  return 0;
3968  if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)) {
3969  free_object(tmp);
3970  tmp = NULL;
3971  }
3972  } while (!tmp);
3973  tmp->x = op->x;
3974  tmp->y = op->y;
3975  SET_FLAG(tmp, FLAG_UNPAID);
3976  insert_ob_in_map(tmp, op->map, NULL, 0);
3978  identify(tmp);
3979  break;
3980 
3981  case TREASURE:
3982  if (QUERY_FLAG(op, FLAG_IS_A_TEMPLATE))
3983  return 0;
3984 
3985  while ((op->stats.hp--) > 0)
3986  create_treasure(op->randomitems, op, op->map ? GT_ENVIRONMENT : 0, op->stats.exp ? (int)op->stats.exp : op->map == NULL ? 14 : op->map->difficulty, 0);
3987 
3988  /* If we generated an object and put it in this object inventory,
3989  * move it to the parent object as the current object is about
3990  * to disappear. An example of this item is the random_ *stuff
3991  * that is put inside other objects.
3992  */
3993  for (tmp = op->inv; tmp; tmp = tmp2) {
3994  tmp2 = tmp->below;
3995  remove_ob(tmp);
3996  if (op->env)
3997  insert_ob_in_ob(tmp, op->env);
3998  else
3999  free_object(tmp);
4000  }
4001  remove_ob(op);
4002  free_object(op);
4003  break;
4004  }
4005  return tmp ? 1 : 0;
4006 }
4007 
4009 }
4010 
4011 #endif /* dummy DOXYGEN_SHOULD_SKIP_THIS */
struct struct_npc_info struct_npc_info
EXTERN FILE * logfile
Definition: global.h:220
struct_map_in_quest_list quests
Definition: mapper.c:276
struct struct_equipment struct_equipment
object * find_skill_by_number(object *who, int skillno)
Definition: mapper.c:3927
char path[HUGE_BUF]
Definition: map.h:384
static void free_equipment(struct_equipment *equip)
Definition: mapper.c:545
static void find_maps(const char *from)
Definition: mapper.c:3212
static int region_allocated
Definition: mapper.c:457
static int tiled_map_need_pic(struct_map_info *map)
Definition: mapper.c:2859
static int elevation_min
Definition: mapper.c:473
static char * map_exit_to_template
Definition: mapper.c:387
Definition: player.h:146
static char * level_map_template
Definition: mapper.c:409
archetype * find_archetype(const char *name)
Definition: arch.c:700
static void init_map_list(struct_map_list *list)
Definition: mapper.c:505
#define FLAG_DAMNED
Definition: define.h:614
#define FLAG_IS_FLOOR
Definition: define.h:599
#define FLAG_UNPAID
Definition: define.h:532
#define CHECK_INV
Definition: define.h:206
#define FLAG_IS_LINKED
Definition: define.h:612
struct_map_info * map
Definition: mapper.c:1152
#define S_MAX
Definition: mapper.c:488
static char * map_no_exit_to_template
Definition: mapper.c:385
static char * region_template
Definition: mapper.c:400
#define TELEPORTER
Definition: define.h:155
static int warn_no_path
Definition: mapper.c:445
static void process_map_lore(struct_map_info *map)
Definition: mapper.c:1297
face_info * faces
Definition: image.h:47
static char * region_letter_template
Definition: mapper.c:401
static int generate_index
Definition: mapper.c:369
static char * world_map_template
Definition: mapper.c:379
int tiled_y_from
Definition: mapper.c:286
void esrv_update_spells(player *pl)
Definition: mapper.c:3937
#define SET_FLAG(xyz, p)
Definition: define.h:510
static int sort_mapname(const void *left, const void *right)
Definition: mapper.c:1054
static char * map_lore_template
Definition: mapper.c:388
static char ** regions_link
Definition: mapper.c:478
struct struct_map_in_quest ** list
Definition: mapper.c:254
static struct_equipment ** special_equipment
Definition: mapper.c:305
static int tileset
Definition: mapper.c:375
void make_path_to_file(const char *filename)
Definition: porting.c:764
static int compare_map_info(const struct_map_info *left, const struct_map_info *right)
Definition: mapper.c:1082
struct_race_list monsters
Definition: mapper.c:280
#define WAND
Definition: define.h:291
static void write_tiled_maps(void)
Definition: mapper.c:3032
static void add_map_to_region(struct_map_info *map, region *reg)
Definition: mapper.c:1665
struct_map_list maps[S_MAX]
Definition: mapper.c:493
static int jpeg_quality
Definition: mapper.c:439
char * lore
Definition: mapper.c:271
struct_map_list tiled_maps
Definition: mapper.c:278
static char * cat_template(char *source, char *add)
Definition: mapper.c:876
#define FLAG_FRIENDLY
Definition: define.h:542
char * name
Definition: mapper.c:1159
static int equipment_allocated
Definition: mapper.c:309
static void add_slaying(struct_map_info *map, object *item)
Definition: mapper.c:1810
static struct_equipment * ensure_unique(struct_equipment *item)
Definition: mapper.c:559
char * create_pathname(const char *name, char *buf, size_t size)
Definition: map.c:114
static char * map_with_exit_template
Definition: mapper.c:383
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:64
mapstruct * ready_map_name(const char *name, int flags)
Definition: map.c:1809
int tiled_x_from
Definition: mapper.c:286
static void write_maps_index(void)
Definition: mapper.c:2302
static char * do_template(const char *template, const char **vars, const char **values)
Definition: mapper.c:947
Definition: mapper.c:426
static int rawmaps
Definition: mapper.c:442
void dragon_ability_gain(object *ob, int x, int y)
Definition: mapper.c:3921
static char * map_with_quests_template
Definition: mapper.c:416
struct treasureliststruct * randomitems
Definition: object.h:236
static void write_maps_by_level(void)
Definition: mapper.c:3044
#define MAP_HEIGHT(m)
Definition: map.h:99
static struct_slaying_info ** slaying_info
Definition: mapper.c:496
object clone
Definition: object.h:326
void set_darkness_map(mapstruct *m)
Definition: mapper.c:3924
sint16 invisible
Definition: object.h:211
struct_map_info * mainmap
Definition: mapper.c:1162
#define POTION
Definition: define.h:117
void monster_check_apply(object *ob, object *obt)
Definition: mapper.c:3940
struct_map_in_quest_list maps
Definition: mapper.c:1163
static void list_map(const char *path)
Definition: mapper.c:1642
const char * slaying
Definition: object.h:172
region * get_region_by_map(mapstruct *m)
Definition: region.c:85
#define IS_WEAPON(op)
Definition: define.h:449
static char * map_no_quest_template
Definition: mapper.c:415
static void init_npc_list(struct_npc_list *list)
Definition: mapper.c:1445
void init_archetypes(void)
Definition: arch.c:195
static gdImagePtr infomap
Definition: mapper.c:465
DIR * opendir(const char *)
Definition: win32.c:78
static void merge_tiled_maps(struct_map_info *map, int tile, struct_map_info *tiled_map)
Definition: mapper.c:1580
#define SCROLL
Definition: define.h:293
void init_globals(void)
Definition: init.c:263
static const char * output_extensions[]
Definition: mapper.c:430
sint8 fallback
Definition: map.h:316
int is_valid_faceset(int fsn)
Definition: image.c:575
static void save_picture(FILE *file, gdImagePtr pic)
Definition: mapper.c:1699
sint64 exp
Definition: living.h:88
static char * map_no_lore_template
Definition: mapper.c:389
uint32 in_memory
Definition: map.h:366
static const char * yesno(int value)
Definition: mapper.c:3603
static void do_help(const char *program)
Definition: mapper.c:3486
char * description
Definition: mapper.c:1160
struct obj * above
Definition: object.h:146
int count
Definition: mapper.c:315
void init_library(void)
Definition: init.c:201
int number
Definition: mapper.c:1161
static void relative_path(const char *from, const char *to, char *result)
Definition: mapper.c:1015
char * maplore
Definition: map.h:381
static void do_parameters(int argc, char **argv)
Definition: mapper.c:3519
static int sort_slaying(const void *left, const void *right)
Definition: mapper.c:3398
LogLevel debug
Definition: global.h:327
sint32 elevation
Definition: object.h:273
static object * small
sint16 x
Definition: object.h:179
static int color_unlinked_exit
Definition: mapper.c:466
static void write_npc_list(void)
Definition: mapper.c:3447
void get_multi_size(object *ob, int *sx, int *sy, int *hx, int *hy)
Definition: object.c:4066
const char * name
Definition: mapper.c:233
static struct struct_region_info ** regions
Definition: mapper.c:455
static void write_quests_page(void)
Definition: mapper.c:1370
struct struct_race_list struct_race_list
static void fix_tiled_map_monsters(void)
Definition: mapper.c:2819
static void process_map(struct_map_info *info)
Definition: mapper.c:1854
Definition: win32.h:128
static struct_race_list races
Definition: mapper.c:319
#define S_KEY
Definition: mapper.c:484
static int is_special_equipment(object *item)
Definition: mapper.c:513
const char * message
Definition: mapper.c:234
static int regions_link_count
Definition: mapper.c:479
int main(int argc, char **argv)
Definition: mapper.c:3607
struct struct_quest * quest
Definition: mapper.c:1154
Definition: object.h:321
static void dump_unused_maps(void)
Definition: mapper.c:3257
struct_map_list exits_to
Definition: mapper.c:275
#define PLAYER
Definition: define.h:113
static int slaying_allocated
Definition: mapper.c:498
static char * quest_map_template
Definition: mapper.c:413
sint16 hp
Definition: living.h:81
static void init_race_list(struct_race_list *list)
Definition: mapper.c:326
void init_formulae(void)
Definition: recipe.c:159
#define SPECIAL_KEY
Definition: define.h:133
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.c:499
static int color_linked_exit
Definition: mapper.c:467
#define MOVE_ALL
Definition: define.h:706
static void define_quest(const char *name, struct_map_info *mainmap, const char *description)
Definition: mapper.c:1278
output_format_type
Definition: mapper.c:424
region * reg
Definition: mapper.c:449
const char * get_region_longname(const region *r)
Definition: region.c:229
const char * name
Definition: map.h:299
static void add_map_to_quest(struct_map_info *map, const char *name, const char *description)
Definition: mapper.c:1226
uint16 number
Definition: face.h:43
static int color_slowing
Definition: mapper.c:470
char * name
Definition: map.h:349
static int sort_map_info(const void *left, const void *right)
Definition: mapper.c:1107
void esrv_update_item(int flags, object *pl, object *op)
Definition: mapper.c:3934
#define MAP_IN_MEMORY
Definition: map.h:151
static int sort_struct_map_in_quest(const void *left, const void *right)
Definition: mapper.c:1248
static void add_to_struct_map_in_quest_list(struct_map_in_quest_list *list, struct_map_in_quest *item)
Definition: mapper.c:1178
void remove_ob(object *op)
Definition: object.c:1515
static void write_map_page(struct_map_info *map)
Definition: mapper.c:2511
#define SIZE
#define SHOP_FLOOR
Definition: define.h:230
void clean_tmp_files(void)
Definition: mapper.c:3915
Definition: win32.h:138
static void fix_exits_to_tiled_maps(void)
Definition: mapper.c:2791
static char * map_monster_after_template
Definition: mapper.c:394
static int list_unused_maps
Definition: mapper.c:459
static char * level_value_template
Definition: mapper.c:408
const char * name_pl
Definition: object.h:168
static void write_slaying_info(void)
Definition: mapper.c:3408
struct_npc_list npcs
Definition: mapper.c:282
static char * index_template
Definition: mapper.c:396
static struct_map_info * create_map_info(void)
Definition: mapper.c:1541
#define S_CONNECT
Definition: mapper.c:487
static struct_map_list maps_list
Definition: mapper.c:291
static int region_count
Definition: mapper.c:456
static char * index_letter
Definition: mapper.c:397
static int created_pics
Definition: mapper.c:420
static int pics_allocated
Definition: mapper.c:364
static int is_road(object *item)
Definition: mapper.c:743
static void write_one_slaying_info(FILE *file, struct_slaying_info *info, int item, const char *with, const char *without)
Definition: mapper.c:3367
region * cfregion
Definition: mapper.c:272
static int color_road
Definition: mapper.c:468
static char root[500]
Definition: mapper.c:361
#define FLAG_UNAGGRESSIVE
Definition: define.h:568
struct mapdef * map
Definition: object.h:155
struct_npc_info ** npc
Definition: mapper.c:240
struct regiondef * next
Definition: map.h:298
struct struct_quest struct_quest
Definition: map.h:297
static struct_slaying_info * get_slaying_struct(const char *slaying)
Definition: mapper.c:1764
static char * index_region_template
Definition: mapper.c:404
struct struct_map_info * tiled_group
Definition: mapper.c:284
static int force_pics
Definition: mapper.c:368
#define HORN
Definition: define.h:147
static char * map_monster_before_template
Definition: mapper.c:391
region * get_region_struct(void)
Definition: region.c:336
void emergency_save(int x)
Definition: mapper.c:3912
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Definition: path.c:184
void identify(object *op)
Definition: item.c:1447
char * name
Definition: mapper.c:314
struct struct_map_info * tiles[4]
Definition: mapper.c:287
static char * map_monster_between_template
Definition: mapper.c:392
static void do_tiled_map_picture(struct_map_info *map)
Definition: mapper.c:2891
uint8 * data
Definition: image.h:34
const char * name
Definition: object.h:167
struct obj * env
Definition: object.h:151
#define SPELL
Definition: define.h:283
static char * map_monster_one_template
Definition: mapper.c:393
static void write_equipment_index(void)
Definition: mapper.c:3122
static void add_npc_to_map(struct_map_info *map, const object *npc)
Definition: mapper.c:1476
static int ** elevation_info
Definition: mapper.c:472
void ext_info_map(int color, const mapstruct *map, uint8 type, uint8 subtype, const char *str1, const char *str2)
Definition: mapper.c:3905
static int elevation_max
Definition: mapper.c:474
static char * index_region_region_template
Definition: mapper.c:405
struct obj * below
Definition: object.h:145
uint16 difficulty
Definition: map.h:364
#define EXIT_PATH(xyz)
Definition: define.h:748
char * tile_path[4]
Definition: map.h:382
char * name
Definition: mapper.c:298
#define FLAG_IS_A_TEMPLATE
Definition: define.h:671
static char * level_template
Definition: mapper.c:407
struct struct_npc_list struct_npc_list
static void replace_map(struct_map_info *find, struct_map_info *replace_by, struct_map_list *list)
Definition: mapper.c:1523
unsigned char uint8
Definition: global.h:75
static gdImagePtr * gdfaces
Definition: mapper.c:227
sint16 y
Definition: object.h:179
#define LOCKED_DOOR
Definition: define.h:132
sint8 item_power
Definition: object.h:213
static enum output_format_type output_format
Definition: mapper.c:436
static void check_slaying_inventory(struct_map_info *map, object *item)
Definition: mapper.c:1836
static void add_one_item(object *item, struct_map_info *map)
Definition: mapper.c:598
static char * world_template
Definition: mapper.c:377
static int world_map
Definition: mapper.c:373
static void fix_map_names(void)
Definition: mapper.c:2683
#define TRIGGER_PEDESTAL
Definition: define.h:144
int auto_apply(object *op)
Definition: mapper.c:3954
void read_client_images(void)
Definition: image.c:471
static object * large
#define MAX(x, y)
Definition: define.h:70
char d_name[_MAX_FNAME+1]
Definition: win32.h:132
void trap_adjust(object *ob, int x)
Definition: mapper.c:3943
static void add_monster(object *monster, struct_map_info *map)
Definition: mapper.c:708
float speed
Definition: object.h:181
void esrv_del_item(player *pl, int tag)
Definition: mapper.c:3931
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
static int quests_count
Definition: mapper.c:1168
const char * longname
Definition: map.h:312
#define CLEAR_FLAG(xyz, p)
Definition: define.h:512
static int sortbyname(const void *a, const void *b)
Definition: mapper.c:862
int execute_global_event(int eventcode,...)
Definition: mapper.c:3950
static char * index_quest_template
Definition: mapper.c:411
static void add_map_to_slaying(struct_slaying_info *info, int item, struct_map_info *map)
Definition: mapper.c:1798
#define TRIGGER_BUTTON
Definition: define.h:142
int min_monster
Definition: mapper.c:273
static int regions_link_allocated
Definition: mapper.c:480
static int size_small
Definition: mapper.c:370
static void add_region_link(mapstruct *source, mapstruct *dest, const char *linkname)
Definition: mapper.c:1715
#define EXIT
Definition: define.h:228
void init_readable(void)
Definition: readable.c:952
object * insert_ob_in_ob(object *op, object *where)
Definition: object.c:2510
static void create_destination(void)
Definition: mapper.c:3587
void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format,...)
Definition: mapper.c:3897
#define MAX_BUF
Definition: define.h:81
static int sort_race(const void *a, const void *b)
Definition: mapper.c:730
static int sort_region(const void *left, const void *right)
Definition: mapper.c:1142
#define IS_SHIELD(op)
Definition: define.h:456
static char * map_exit_template
Definition: mapper.c:384
object * insert_ob_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:1992
MoveType move_slow
Definition: object.h:282
char * filename
Definition: mapper.c:270
char * description
Definition: mapper.c:1153
struct struct_map_in_quest struct_map_in_quest
static void write_all_regions(void)
Definition: mapper.c:2290
void move_firewall(object *ob)
Definition: mapper.c:3909
#define tolower(C)
Definition: c_new.c:42
static void write_slaying_map_name(FILE *file, struct_map_info *map)
Definition: mapper.c:3349
void esrv_send_item(object *ob, object *obx)
Definition: mapper.c:3918
static int map_limit
Definition: mapper.c:371
#define CLASS
Definition: define.h:149
static char * map_template
Definition: mapper.c:381
struct_map_list maps_list
Definition: mapper.c:450
static const flag_definition flags[]
#define TIMED_GATE
Definition: define.h:138
#define MIN(x, y)
Definition: define.h:67
static char * region_map_template
Definition: mapper.c:402
Definition: mapper.c:425
static int sort_equipment(const void *a, const void *b)
Definition: mapper.c:661
const char * sstring
Definition: global.h:84
static char * map_no_monster_template
Definition: mapper.c:390
char * diff
Definition: mapper.c:301
#define FLAG_CURSED
Definition: define.h:613
const char * datadir
Definition: global.h:334
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
void get_ob_diff(StringBuffer *sb, object *op, object *op2)
#define FLAG_AUTO_APPLY
Definition: define.h:546
#define ALTAR
Definition: define.h:130
static void write_regions_link(void)
Definition: mapper.c:3322
struct struct_region_info struct_region_info
#define CONTAINER
Definition: define.h:306
face_sets facesets[MAX_FACE_SETS]
Definition: image.c:78
#define FIREWALL
Definition: define.h:204
struct struct_race ** races
Definition: mapper.c:247
static void init_struct_map_in_quest_list(struct_map_in_quest_list *list)
Definition: mapper.c:1172
living stats
Definition: object.h:219
static int slaying_count
Definition: mapper.c:497
static int do_regions_link
Definition: mapper.c:477
struct archt * arch
Definition: object.h:263
uint32 reset_time
Definition: map.h:353
#define MAP_WIDTH(m)
Definition: map.h:97
static int show_maps
Definition: mapper.c:372
static void write_world_info(void)
Definition: mapper.c:3280
static int equipment_count
Definition: mapper.c:307
int nrofpixmaps
Definition: image.c:76
static void check_equipment(object *item, struct_map_info *map)
Definition: mapper.c:642
static char * index_map
Definition: mapper.c:398
const char * mapdir
Definition: global.h:337
void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *txt, const char *txt2)
Definition: mapper.c:3893
struct Settings settings
Definition: init.c:48
static void write_all_maps(void)
Definition: mapper.c:2847
struct dirent * readdir(DIR *)
Definition: win32.c:116
void init_gods(void)
Definition: holy.c:63
void delete_map(mapstruct *m)
Definition: map.c:1745
int execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Definition: mapper.c:3946
static const char * ignore_path[]
Definition: mapper.c:3188
const char * msg
Definition: object.h:175
EXTERN char first_map_path[MAX_BUF]
Definition: global.h:229
void init_regions(void)
Definition: region.c:301
static void fix_tiled_map(void)
Definition: mapper.c:2703
static int get_elevation_color(int elevation, gdImagePtr elevationmap)
Definition: mapper.c:793
void update_ob_speed(object *op)
Definition: object.c:1008
static void do_exit_map(mapstruct *map)
Definition: mapper.c:808
sstring add_string(const char *str)
Definition: shstr.c:116
static struct_map_list tiled_map_list
Definition: mapper.c:294
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)
Definition: mapper.c:2122
static struct_equipment * get_equipment(void)
Definition: mapper.c:532
#define GET_MAP_OB(M, X, Y)
Definition: map.h:193
int strcasecmp(const char *s1, const char *s2)
Definition: porting.c:434
static void read_template(const char *name, char **buffer)
Definition: mapper.c:895
#define FLAG_MONSTER
Definition: define.h:541
#define TREASURE
Definition: define.h:116
static char * world_row_template
Definition: mapper.c:378
int max_monster
Definition: mapper.c:273
int closedir(DIR *)
Definition: win32.c:149
struct obj * inv
Definition: object.h:148
static char * map_one_quest_template
Definition: mapper.c:417
struct obj * head
Definition: object.h:154
#define S_ISDIR(x)
Definition: win32.h:80
#define SPELLBOOK
Definition: define.h:266
void fix_auto_apply(mapstruct *m)
Definition: mapper.c:4008
char * name
Definition: mapper.c:269
struct struct_race struct_race
static struct_race * get_race(const char *name)
Definition: mapper.c:679
#define ROD
Definition: define.h:115
static int world_exit_info
Definition: mapper.c:374
EXTERN region * first_region
Definition: global.h:192
static struct_map_info * create_tiled_map(void)
Definition: mapper.c:1562
MoveType move_block
Definition: object.h:278
static int color_blocking
Definition: mapper.c:469
struct struct_map_info ** maps
Definition: mapper.c:261
#define IS_ARMOR(op)
Definition: define.h:452
static char * map_no_exit_template
Definition: mapper.c:382
int check_trigger(object *op, object *cause)
Definition: button.c:525
static char * map_with_exit_to_template
Definition: mapper.c:386
int calc_item_power(const object *op, int flag)
Definition: item.c:264
struct_map_list origin
Definition: mapper.c:316
int get_face_fallback(int faceset, int imageno)
Definition: image.c:614
static int sort_map_info_by_level(const void *left, const void *right)
Definition: mapper.c:1123
object * generate_treasure(treasurelist *t, int difficulty)
Definition: treasure.c:524
static int found_maps_count
Definition: mapper.c:461
void free_object(object *ob)
Definition: object.c:1238
Definition: map.h:346
static void write_world_map(void)
Definition: mapper.c:2365
New_Face * face
Definition: object.h:183
struct_map_list origin
Definition: mapper.c:302
static char ** found_maps
Definition: mapper.c:460
static struct_map_info * get_map_info(const char *path)
Definition: mapper.c:1614
static void add_race_to_list(struct_race *race, struct_race_list *list, int check)
Definition: mapper.c:342
#define FLAG_NO_PICK
Definition: define.h:535
static void write_race_index(void)
Definition: mapper.c:3155
void do_auto_apply(mapstruct *m)
Definition: mapper.c:3788
static void write_region_page(struct_region_info *reg)
Definition: mapper.c:2257
static struct_npc_info * create_npc_info(const object *npc)
Definition: mapper.c:1458
#define IS_ARROW(op)
Definition: define.h:464
#define S_DOOR
Definition: mapper.c:483
sint16 level
Definition: object.h:202
struct_map_list exits_from
Definition: mapper.c:274
static int is_blocking(object *item)
Definition: mapper.c:779
static void fix_exits_for_map(struct_map_info *current, struct_map_list *from, int is_from)
Definition: mapper.c:2772
#define VARSADD
struct obj * more
Definition: object.h:153
static void write_tiled_map_page(struct_map_info *map)
Definition: mapper.c:3022
static struct_quest ** quests
Definition: mapper.c:1166
static char * quest_template
Definition: mapper.c:412
int pic_was_done
Definition: mapper.c:273
#define PLAYER_CHANGER
Definition: define.h:194
static void add_map(struct_map_info *info, struct_map_list *list)
Definition: mapper.c:1498
static int cached_pics
Definition: mapper.c:421
const char * name
Definition: object.h:322
#define S_CONTAINER
Definition: mapper.c:485
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:78
static int is_slaying(object *item)
Definition: mapper.c:1751
#define HAS_RANDOM_ITEMS(op)
Definition: define.h:470
uint8 type
Definition: object.h:189
const char * get_region_msg(const region *r)
Definition: region.c:250
static struct_quest * get_quest_info(const char *name)
Definition: mapper.c:1194
void init_artifacts(void)
Definition: treasure.c:1539
static int quests_allocated
Definition: mapper.c:1170
static int generate_pics
Definition: mapper.c:367
static void write_region_index(void)
Definition: mapper.c:2324
struct regiondef region
char * path
Definition: mapper.c:268
struct struct_map_info struct_map_info
static const char * ignore_name[]
Definition: mapper.c:3199
static int found_maps_allocated
Definition: mapper.c:462