Stop sharing requirement_unit_state_ereq().
[freeciv.git] / common / mapimg.c
blob0d689b0d2ddcdb0b21c211ef241ce4eaba7f9e83
1 /****************************************************************************
2 Freeciv - Copyright (C) 2010 - The Freeciv Team
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ****************************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <stdarg.h>
20 #ifdef HAVE_MAPIMG_MAGICKWAND
21 #include <wand/MagickWand.h>
22 #endif /* HAVE_MAPIMG_MAGICKWAND */
24 /* utility */
25 #include "astring.h"
26 #include "bitvector.h"
27 #include "fc_cmdline.h"
28 #include "fcintl.h"
29 #include "log.h"
30 #include "mem.h"
31 #include "string_vector.h"
32 #include "timing.h"
34 /* common */
35 #include "calendar.h"
36 #include "connection.h"
37 #include "fc_types.h"
38 #include "game.h"
39 #include "map.h"
40 #include "rgbcolor.h"
41 #include "terrain.h"
42 #include "tile.h"
43 #include "version.h"
44 #include "player.h"
46 #include "mapimg.h"
48 /* Some magick for ImageMagick - the interface has changed:
49 ImageMagick-6.6.2-0: PixelGetNextIteratorRow(..., unsigned long *)
50 ImageMagick-6.6.2-1: PixelGetNextIteratorRow(..., size_t *)
51 Theoretically, "unsigned long" and "size_t" are pretty much the same but
52 in practice the compiler will complain bitterly.
53 (from Gem-0.93 ImageMAGICK plugin) */
54 #ifndef MagickLibInterface
55 # define MagickLibInterface 0
56 #endif
57 #ifndef MagickLibVersion
58 # define MagickLibVersion 0
59 #endif
61 /* This won't catch ImageMagick>=6.6.2-0.
62 Another workaround: compile with "-fpermissive" */
63 #if (MagickLibInterface > 3) || (MagickLibVersion >= 0x662)
64 # define magickwand_size_t size_t
65 #else
66 # define magickwand_size_t unsigned long
67 #endif
69 /* == image colors == */
70 enum img_special {
71 IMGCOLOR_ERROR,
72 IMGCOLOR_OCEAN,
73 IMGCOLOR_GROUND,
74 IMGCOLOR_BACKGROUND,
75 IMGCOLOR_TEXT
78 static const struct rgbcolor *imgcolor_special(enum img_special imgcolor);
79 static const struct rgbcolor *imgcolor_player(int plr_id);
80 static const struct rgbcolor
81 *imgcolor_terrain(const struct terrain *pterrain);
83 /* == topologies == */
84 #define TILE_SIZE 6
85 #define NUM_PIXEL TILE_SIZE * TILE_SIZE
87 BV_DEFINE(bv_pixel, NUM_PIXEL);
89 struct tile_shape {
90 int x[NUM_PIXEL];
91 int y[NUM_PIXEL];
94 struct img;
96 typedef bv_pixel (*plot_func)(const struct tile *ptile,
97 const struct player *pplayer,
98 bool knowledge);
99 typedef void (*base_coor_func)(struct img *pimg, int *base_x, int *base_y,
100 int x, int y);
102 /* (isometric) rectangular topology */
103 static struct tile_shape tile_rect = {
104 .x = {
105 0, 1, 2, 3, 4, 5,
106 0, 1, 2, 3, 4, 5,
107 0, 1, 2, 3, 4, 5,
108 0, 1, 2, 3, 4, 5,
109 0, 1, 2, 3, 4, 5,
110 0, 1, 2, 3, 4, 5
112 .y = {
113 0, 0, 0, 0, 0, 0,
114 1, 1, 1, 1, 1, 1,
115 2, 2, 2, 2, 2, 2,
116 3, 3, 3, 3, 3, 3,
117 4, 4, 4, 4, 4, 4,
118 5, 5, 5, 5, 5, 5
122 static bv_pixel pixel_tile_rect(const struct tile *ptile,
123 const struct player *pplayer,
124 bool knowledge);
125 static bv_pixel pixel_city_rect(const struct tile *ptile,
126 const struct player *pplayer,
127 bool knowledge);
128 static bv_pixel pixel_unit_rect(const struct tile *ptile,
129 const struct player *pplayer,
130 bool knowledge);
131 static bv_pixel pixel_fogofwar_rect(const struct tile *ptile,
132 const struct player *pplayer,
133 bool knowledge);
134 static bv_pixel pixel_border_rect(const struct tile *ptile,
135 const struct player *pplayer,
136 bool knowledge);
137 static void base_coor_rect(struct img *pimg, int *base_x, int *base_y,
138 int x, int y);
140 /* hexa topology */
141 static struct tile_shape tile_hexa = {
142 .x = {
143 2, 3,
144 1, 2, 3, 4,
145 0, 1, 2, 3, 4, 5,
146 0, 1, 2, 3, 4, 5,
147 0, 1, 2, 3, 4, 5,
148 0, 1, 2, 3, 4, 5,
149 1, 2, 3, 4,
150 2, 3,
152 .y = {
153 0, 0,
154 1, 1, 1, 1,
155 2, 2, 2, 2, 2, 2,
156 3, 3, 3, 3, 3, 3,
157 4, 4, 4, 4, 4, 4,
158 5, 5, 5, 5, 5, 5,
159 6, 6, 6, 6,
160 7, 7,
164 static bv_pixel pixel_tile_hexa(const struct tile *ptile,
165 const struct player *pplayer,
166 bool knowledge);
167 static bv_pixel pixel_city_hexa(const struct tile *ptile,
168 const struct player *pplayer,
169 bool knowledge);
170 static bv_pixel pixel_unit_hexa(const struct tile *ptile,
171 const struct player *pplayer,
172 bool knowledge);
173 static bv_pixel pixel_fogofwar_hexa(const struct tile *ptile,
174 const struct player *pplayer,
175 bool knowledge);
176 static bv_pixel pixel_border_hexa(const struct tile *ptile,
177 const struct player *pplayer,
178 bool knowledge);
179 static void base_coor_hexa(struct img *pimg, int *base_x, int *base_y,
180 int x, int y);
182 /* isometric hexa topology */
183 static struct tile_shape tile_isohexa = {
184 .x = {
185 2, 3, 4, 5,
186 1, 2, 3, 4, 5, 6,
187 0, 1, 2, 3, 4, 5, 6, 7,
188 0, 1, 2, 3, 4, 5, 6, 7,
189 1, 2, 3, 4, 5, 6,
190 2, 3, 4, 5
192 .y = {
193 0, 0, 0, 0,
194 1, 1, 1, 1, 1, 1,
195 2, 2, 2, 2, 2, 2, 2, 2,
196 3, 3, 3, 3, 3, 3, 3, 3,
197 4, 4, 4, 4, 4, 4,
198 5, 5, 5, 5
202 static bv_pixel pixel_tile_isohexa(const struct tile *ptile,
203 const struct player *pplayer,
204 bool knowledge);
205 static bv_pixel pixel_city_isohexa(const struct tile *ptile,
206 const struct player *pplayer,
207 bool knowledge);
208 static bv_pixel pixel_unit_isohexa(const struct tile *ptile,
209 const struct player *pplayer,
210 bool knowledge);
211 static bv_pixel pixel_fogofwar_isohexa(const struct tile *ptile,
212 const struct player *pplayer,
213 bool knowledge);
214 static bv_pixel pixel_border_isohexa(const struct tile *ptile,
215 const struct player *pplayer,
216 bool knowledge);
217 static void base_coor_isohexa(struct img *pimg, int *base_x, int *base_y,
218 int x, int y);
220 /* == map images == */
222 #define ARG_PLRBV "plrbv"
223 #define ARG_PLRID "plrid"
224 #define ARG_PLRNAME "plrname"
226 /* mapimg definition */
227 #define SPECENUM_NAME mapdef_arg
228 #define SPECENUM_VALUE0 MAPDEF_FORMAT
229 #define SPECENUM_VALUE0NAME "format"
230 #define SPECENUM_VALUE1 MAPDEF_MAP
231 #define SPECENUM_VALUE1NAME "map"
232 #define SPECENUM_VALUE2 MAPDEF_PLRBV
233 #define SPECENUM_VALUE2NAME ARG_PLRBV
234 #define SPECENUM_VALUE3 MAPDEF_PLRID
235 #define SPECENUM_VALUE3NAME ARG_PLRID
236 #define SPECENUM_VALUE4 MAPDEF_PLRNAME
237 #define SPECENUM_VALUE4NAME ARG_PLRNAME
238 #define SPECENUM_VALUE5 MAPDEF_SHOW
239 #define SPECENUM_VALUE5NAME "show"
240 #define SPECENUM_VALUE6 MAPDEF_TURNS
241 #define SPECENUM_VALUE6NAME "turns"
242 #define SPECENUM_VALUE7 MAPDEF_ZOOM
243 #define SPECENUM_VALUE7NAME "zoom"
244 #define SPECENUM_COUNT MAPDEF_COUNT
245 #include "specenum_gen.h"
247 BV_DEFINE(bv_mapdef_arg, MAPDEF_COUNT);
249 /* image format */
250 #define SPECENUM_NAME imageformat
251 #define SPECENUM_BITWISE
252 #define SPECENUM_VALUE0 IMGFORMAT_GIF
253 #define SPECENUM_VALUE0NAME "gif"
254 #define SPECENUM_VALUE1 IMGFORMAT_PNG
255 #define SPECENUM_VALUE1NAME "png"
256 #define SPECENUM_VALUE2 IMGFORMAT_PPM
257 #define SPECENUM_VALUE2NAME "ppm"
258 #define SPECENUM_VALUE3 IMGFORMAT_JPG
259 #define SPECENUM_VALUE3NAME "jpg"
260 #include "specenum_gen.h"
262 /* image format */
263 #define SPECENUM_NAME imagetool
264 #define SPECENUM_VALUE0 IMGTOOL_PPM
265 #define SPECENUM_VALUE0NAME "ppm"
266 #define SPECENUM_VALUE1 IMGTOOL_MAGICKWAND
267 #define SPECENUM_VALUE1NAME "magick"
268 #include "specenum_gen.h"
270 /* player definitions */
271 #define SPECENUM_NAME show_player
272 #define SPECENUM_VALUE0 SHOW_NONE
273 #define SPECENUM_VALUE0NAME "none"
274 #define SPECENUM_VALUE1 SHOW_EACH
275 #define SPECENUM_VALUE1NAME "each"
276 #define SPECENUM_VALUE2 SHOW_HUMAN
277 #define SPECENUM_VALUE2NAME "human"
278 #define SPECENUM_VALUE3 SHOW_ALL
279 #define SPECENUM_VALUE3NAME "all"
280 /* should be identical to MAPDEF_PLRNAME */
281 #define SPECENUM_VALUE4 SHOW_PLRNAME
282 #define SPECENUM_VALUE4NAME ARG_PLRNAME
283 /* should be identical to MAPDEF_PLRID */
284 #define SPECENUM_VALUE5 SHOW_PLRID
285 #define SPECENUM_VALUE5NAME ARG_PLRID
286 /* should be identical to MAPDEF_PLRBV */
287 #define SPECENUM_VALUE6 SHOW_PLRBV
288 #define SPECENUM_VALUE6NAME ARG_PLRBV
289 #include "specenum_gen.h"
291 #undef ARG_PLRBV
292 #undef ARG_PLRID
293 #undef ARG_PLRNAME
295 /* map definition status */
296 #define SPECENUM_NAME mapimg_status
297 #define SPECENUM_VALUE0 MAPIMG_STATUS_UNKNOWN
298 #define SPECENUM_VALUE0NAME _("not checked")
299 #define SPECENUM_VALUE1 MAPIMG_STATUS_OK
300 #define SPECENUM_VALUE1NAME _("OK")
301 #define SPECENUM_VALUE2 MAPIMG_STATUS_ERROR
302 #define SPECENUM_VALUE2NAME _("error")
303 #include "specenum_gen.h"
305 #define MAX_LEN_MAPARG MAX_LEN_MAPDEF
306 #define MAX_NUM_MAPIMG 10
308 static inline bool mapimg_initialised(void);
309 static bool mapimg_test(int id);
310 static bool mapimg_define_arg(struct mapdef *pmapdef, enum mapdef_arg arg,
311 const char *val, bool check);
312 static bool mapimg_def2str(struct mapdef *pmapdef, char *str, size_t str_len);
313 static bool mapimg_checkplayers(struct mapdef *pmapdef, bool recheck);
314 static char *mapimg_generate_name(struct mapdef *pmapdef);
316 /* == map definition == */
317 struct mapdef {
318 char maparg[MAX_LEN_MAPARG];
319 char error[MAX_LEN_MAPDEF];
320 enum mapimg_status status;
321 enum imageformat format;
322 enum imagetool tool;
323 int zoom;
324 int turns;
325 bool layers[MAPIMG_LAYER_COUNT];
326 struct {
327 enum show_player show;
328 union {
329 char name[MAX_LEN_NAME]; /* used by SHOW_PLRNAME */
330 int id; /* used by SHOW_PLRID */
331 bv_player plrbv; /* used by SHOW_PLRBV */
333 bv_player checked_plrbv; /* player bitvector used for the image
334 * creation */
335 } player;
337 bv_mapdef_arg args;
338 bool colortest;
341 static struct mapdef *mapdef_new(bool colortest);
342 static void mapdef_destroy(struct mapdef *pmapdef);
344 /* List of map definitions. */
345 #define SPECLIST_TAG mapdef
346 #define SPECLIST_TYPE struct mapdef
347 #include "speclist.h"
349 #define mapdef_list_iterate(mapdef_list, pmapdef) \
350 TYPED_LIST_ITERATE(struct mapdef, mapdef_list, pmapdef)
351 #define mapdef_list_iterate_end \
352 LIST_ITERATE_END
354 /* == images == */
355 struct mapdef;
357 /* Some lengths used for the images created by the magickwand toolkit. */
358 #define IMG_BORDER_HEIGHT 5
359 #define IMG_BORDER_WIDTH IMG_BORDER_HEIGHT
360 #define IMG_SPACER_HEIGHT 5
361 #define IMG_LINE_HEIGHT 5
362 #define IMG_TEXT_HEIGHT 12
364 struct img {
365 struct mapdef *def; /* map definition */
366 int turn; /* save turn */
367 char title[MAX_LEN_MAPDEF];
369 /* topology definition */
370 struct tile_shape *tileshape;
371 plot_func pixel_tile;
372 plot_func pixel_city;
373 plot_func pixel_unit;
374 plot_func pixel_fogofwar;
375 plot_func pixel_border;
376 base_coor_func base_coor;
378 struct {
379 int x;
380 int y;
381 } mapsize; /* map size */
382 struct {
383 int x;
384 int y;
385 } imgsize; /* image size */
386 const struct rgbcolor **map;
389 static struct img *img_new(struct mapdef *mapdef, int topo, int xsize, int ysize);
390 static void img_destroy(struct img *pimg);
391 static inline void img_set_pixel(struct img *pimg, const int mindex,
392 const struct rgbcolor *pcolor);
393 static inline int img_index(const int x, const int y,
394 const struct img *pimg);
395 static const char *img_playerstr(const struct player *pplayer);
396 static void img_plot(struct img *pimg, int x, int y,
397 const struct rgbcolor *pcolor, const bv_pixel pixel);
398 static void img_plot_tile(struct img *pimg, const struct tile *ptile,
399 const struct rgbcolor *pcolor, const bv_pixel pixel);
400 static bool img_save(const struct img *pimg, const char *mapimgfile,
401 const char *path);
402 static bool img_save_ppm(const struct img *pimg, const char *mapimgfile);
403 #ifdef HAVE_MAPIMG_MAGICKWAND
404 static bool img_save_magickwand(const struct img *pimg,
405 const char *mapimgfile);
406 #endif /* HAVE_MAPIMG_MAGICKWAND */
407 static bool img_filename(const char *mapimgfile, enum imageformat format,
408 char *filename, size_t filename_len);
409 static void img_createmap(struct img *pimg);
411 /* == image toolkits == */
412 typedef bool (*img_save_func)(const struct img *pimg,
413 const char *mapimgfile);
415 struct toolkit {
416 enum imagetool tool;
417 enum imageformat format_default;
418 int formats;
419 const img_save_func img_save;
420 const char *help;
423 #define GEN_TOOLKIT(_tool, _format_default, _formats, _save_func, _help) \
424 {_tool, _format_default, _formats, _save_func, _help},
426 static struct toolkit img_toolkits[] = {
427 GEN_TOOLKIT(IMGTOOL_PPM, IMGFORMAT_PPM, IMGFORMAT_PPM,
428 img_save_ppm,
429 N_("Standard ppm files"))
430 #ifdef HAVE_MAPIMG_MAGICKWAND
431 GEN_TOOLKIT(IMGTOOL_MAGICKWAND, IMGFORMAT_GIF,
432 IMGFORMAT_GIF + IMGFORMAT_PNG + IMGFORMAT_PPM + IMGFORMAT_JPG,
433 img_save_magickwand,
434 N_("ImageMagick"))
435 #endif /* HAVE_MAPIMG_MAGICKWAND */
438 static const int img_toolkits_count = ARRAY_SIZE(img_toolkits);
440 #ifdef HAVE_MAPIMG_MAGICKWAND
441 #define MAPIMG_DEFAULT_IMGFORMAT IMGFORMAT_GIF
442 #define MAPIMG_DEFAULT_IMGTOOL IMGTOOL_MAGICKWAND
443 #else
444 #define MAPIMG_DEFAULT_IMGFORMAT IMGFORMAT_PPM
445 #define MAPIMG_DEFAULT_IMGTOOL IMGTOOL_PPM
446 #endif /* HAVE_MAPIMG_MAGICKWAND */
448 static const struct toolkit *img_toolkit_get(enum imagetool tool);
450 #define img_toolkit_iterate(_toolkit) \
452 int _i; \
453 for (_i = 0; _i < img_toolkits_count; _i++) { \
454 const struct toolkit *_toolkit = &img_toolkits[_i];
456 #define img_toolkit_iterate_end \
460 /* == logging == */
461 #define MAX_LEN_ERRORBUF 1024
463 static char error_buffer[MAX_LEN_ERRORBUF] = "\0";
464 static void mapimg_log(const char *file, const char *function, int line,
465 const char *format, ...)
466 fc__attribute((__format__(__printf__, 4, 5)));
467 #define MAPIMG_LOG(format, ...) \
468 mapimg_log(__FILE__, __FUNCTION__, __FC_LINE__, format, ## __VA_ARGS__)
469 #define MAPIMG_ASSERT_RET_VAL(cond, expr) \
470 fc_assert_action(cond, MAPIMG_LOG(_("internal error")); return (expr))
472 /* == additional functions == */
474 static int bvplayers_count(const struct mapdef *pmapdef);
475 static const char *bvplayers_str(const bv_player plrbv);
477 /* == map images data == */
478 static struct {
479 bool init;
480 struct mapdef_list *mapdef;
482 mapimg_tile_known_func mapimg_tile_known;
483 mapimg_tile_terrain_func mapimg_tile_terrain;
484 mapimg_tile_player_func mapimg_tile_owner;
485 mapimg_tile_player_func mapimg_tile_city;
486 mapimg_tile_player_func mapimg_tile_unit;
487 mapimg_plrcolor_count_func mapimg_plrcolor_count;
488 mapimg_plrcolor_get_func mapimg_plrcolor_get;
489 } mapimg = { .init = FALSE };
492 * ==============================================
493 * map images (external functions)
494 * ==============================================
497 /****************************************************************************
498 Initialisation of the map image subsystem. The arguments are used to
499 determine the map knowledge, the terrain type as well as the tile, city and
500 unit owner.
501 ****************************************************************************/
502 void mapimg_init(mapimg_tile_known_func mapimg_tile_known,
503 mapimg_tile_terrain_func mapimg_tile_terrain,
504 mapimg_tile_player_func mapimg_tile_owner,
505 mapimg_tile_player_func mapimg_tile_city,
506 mapimg_tile_player_func mapimg_tile_unit,
507 mapimg_plrcolor_count_func mapimg_plrcolor_count,
508 mapimg_plrcolor_get_func mapimg_plrcolor_get)
510 if (mapimg_initialised()) {
511 return;
514 mapimg.mapdef = mapdef_list_new();
516 fc_assert_ret(mapimg_tile_known != NULL);
517 mapimg.mapimg_tile_known = mapimg_tile_known;
518 fc_assert_ret(mapimg_tile_terrain != NULL);
519 mapimg.mapimg_tile_terrain = mapimg_tile_terrain;
520 fc_assert_ret(mapimg_tile_owner != NULL);
521 mapimg.mapimg_tile_owner = mapimg_tile_owner;
522 fc_assert_ret(mapimg_tile_city != NULL);
523 mapimg.mapimg_tile_city = mapimg_tile_city;
524 fc_assert_ret(mapimg_tile_unit != NULL);
525 mapimg.mapimg_tile_unit = mapimg_tile_unit;
526 fc_assert_ret(mapimg_plrcolor_count != NULL);
527 mapimg.mapimg_plrcolor_count = mapimg_plrcolor_count;
528 fc_assert_ret(mapimg_plrcolor_get != NULL);
529 mapimg.mapimg_plrcolor_get = mapimg_plrcolor_get;
531 mapimg.init = TRUE;
534 /****************************************************************************
535 Reset the map image subsystem.
536 ****************************************************************************/
537 void mapimg_reset(void)
539 if (!mapimg_initialised()) {
540 return;
543 if (mapdef_list_size(mapimg.mapdef) > 0) {
544 mapdef_list_iterate(mapimg.mapdef, pmapdef) {
545 mapdef_list_remove(mapimg.mapdef, pmapdef);
546 mapdef_destroy(pmapdef);
547 } mapdef_list_iterate_end;
551 /****************************************************************************
552 Free all memory allocated by the map image subsystem.
553 ****************************************************************************/
554 void mapimg_free(void)
556 if (!mapimg_initialised()) {
557 return;
560 mapimg_reset();
561 mapdef_list_destroy(mapimg.mapdef);
563 mapimg.init = FALSE;
566 /****************************************************************************
567 Return the number of map image definitions.
568 ****************************************************************************/
569 int mapimg_count(void)
571 if (!mapimg_initialised()) {
572 return 0;
575 return mapdef_list_size(mapimg.mapdef);
578 /****************************************************************************
579 Describe the 'show' settings.
580 ****************************************************************************/
581 static const char *showname_help(enum show_player showplr)
583 switch (showplr) {
584 case SHOW_NONE: return _("no players, only terrain");
585 case SHOW_EACH: return _("one image per player");
586 case SHOW_HUMAN: return _("one image per human player");
587 case SHOW_ALL: return _("all players on a single image");
588 case SHOW_PLRNAME: return _("just the player named with 'plrname'");
589 case SHOW_PLRID: return _("just the player specified with 'plrid'");
590 case SHOW_PLRBV: return _("one image per player in 'plrbv'");
592 fc_assert(0);
593 return "";
596 /****************************************************************************
597 Return a help string for the 'mapimg' command.
598 ****************************************************************************/
599 char *mapimg_help(void)
601 enum imagetool tool;
602 enum show_player showplr;
603 enum mapimg_layer layer;
604 struct astring defaults[MAPDEF_COUNT];
605 struct astring str_format = ASTRING_INIT, str_showplr = ASTRING_INIT;
606 struct mapdef *pmapdef = mapdef_new(FALSE);
607 static struct astring help = ASTRING_INIT;
609 if (astr_len(&help) > 0) {
610 /* Help text was created already. */
611 return fc_strdup(astr_str(&help));
614 /* Possible 'format' settings (toolkit + format). */
615 for (tool = imagetool_begin(); tool != imagetool_end();
616 tool = imagetool_next(tool)) {
617 enum imageformat format;
618 const struct toolkit *toolkit = img_toolkit_get(tool);
620 if (!toolkit) {
621 continue;
624 astr_add(&str_format, " - '%s': ", imagetool_name(tool));
626 const char *separator = "";
627 for (format = imageformat_begin(); format != imageformat_end();
628 format = imageformat_next(format)) {
629 if (toolkit->formats & format) {
630 astr_add(&str_format, "%s'%s'", separator, imageformat_name(format));
631 separator = ", ";
635 if (tool != imagetool_max()) {
636 astr_add(&str_format, "\n");
640 /* Possible 'show' settings. */
641 for (showplr = show_player_begin(); showplr != show_player_end();
642 showplr = show_player_next(showplr)) {
643 char name[10];
644 fc_snprintf(name, sizeof(name), "'%s'", show_player_name(showplr));
645 astr_add(&str_showplr, " - %-9s %s", name, showname_help(showplr));
646 if (showplr != show_player_max()) {
647 astr_add(&str_showplr, "\n");
651 /* Default values. */
652 astr_init(&defaults[MAPDEF_FORMAT]);
653 astr_set(&defaults[MAPDEF_FORMAT],
654 "(%s|%s)", imagetool_name(pmapdef->tool),
655 imageformat_name(pmapdef->format));
656 astr_init(&defaults[MAPDEF_SHOW]);
657 astr_set(&defaults[MAPDEF_SHOW],
658 "(%s)", show_player_name(pmapdef->player.show));
659 astr_init(&defaults[MAPDEF_TURNS]);
660 astr_set(&defaults[MAPDEF_TURNS], "(%d)", pmapdef->turns);
661 astr_init(&defaults[MAPDEF_ZOOM]);
662 astr_set(&defaults[MAPDEF_ZOOM], "(%d)", pmapdef->zoom);
664 astr_init(&defaults[MAPDEF_MAP]);
665 astr_set(&defaults[MAPDEF_MAP], "(");
666 for (layer = mapimg_layer_begin(); layer != mapimg_layer_end();
667 layer = mapimg_layer_next(layer)) {
668 if (pmapdef->layers[layer]) {
669 astr_add(&defaults[MAPDEF_MAP], "%c", mapimg_layer_name(layer)[0]);
672 astr_add(&defaults[MAPDEF_MAP], ")");
674 /* help text */
675 astr_set(&help,
676 /* TRANS: This is help for a server command, so keywords like
677 * "define" in the first column are server keywords that must not
678 * be translated. Do not translate keywords in single quotes, but
679 * strings in <angle brackets> should be translated. */
680 _("This command controls the creation of map images. Supported "
681 "arguments:\n"
682 " define <mapdef> - define a map image; returns numeric <id>\n"
683 " show <id>|all - list map image definitions or show a specific one\n"
684 " create <id>|all - manually save image(s) for current map state\n"
685 " delete <id>|all - delete map image definition(s)\n"
686 " colortest - create test image(s) showing all colors\n"
687 "\n"
688 "Multiple definitions can be active at once. "
689 "A definition <mapdef> consists of colon-separated options:\n"
690 "\n"
691 "option (default) description\n"
692 "\n"
693 "format=<[tool|]format> %-10s file format\n"
694 "show=<show> %-10s which players to show\n"
695 " plrname=<name> player name\n"
696 " plrid=<id> numeric player id\n"
697 " plrbv=<bit vector> see example; first char = id 0\n"
698 "turns=<turns> %-10s save image each <turns> turns\n"
699 " (0=no autosave, save with 'create')\n"
700 "zoom=<zoom> %-10s magnification factor (1-5)\n"
701 "map=<map> %-10s which map layers to draw\n"
702 "\n"
703 "<[tool|]format> = use image format <format>, optionally specifying "
704 "toolkit <tool>. The following toolkits and formats are compiled in:\n"
705 "%s\n"
706 "\n"
707 "<show> determines which players are represented and how many "
708 "images are saved by this definition:\n"
709 "%s\n"
710 "\n"
711 "<map> can contain one or more of the following layers:\n"
712 " - 'a' show area within borders of specified players\n"
713 " - 'b' show borders of specified players\n"
714 " - 'c' show cities of specified players\n"
715 " - 'f' show fog of war (single-player images only)\n"
716 " - 'k' show only player knowledge (single-player images only)\n"
717 " - 't' full display of terrain types\n"
718 " - 'u' show units of specified players\n"
719 "\n"
720 "Examples of <mapdef>:\n"
721 " 'zoom=1:map=tcub:show=all:format=ppm|ppm'\n"
722 " 'zoom=2:map=tcub:show=each:format=png'\n"
723 " 'zoom=1:map=tcub:show=plrname:plrname=Otto:format=gif'\n"
724 " 'zoom=3:map=cu:show=plrbv:plrbv=010011:format=jpg'\n"
725 " 'zoom=1:map=t:show=none:format=magick|jpg'"),
726 astr_str(&defaults[MAPDEF_FORMAT]), astr_str(&defaults[MAPDEF_SHOW]),
727 astr_str(&defaults[MAPDEF_TURNS]), astr_str(&defaults[MAPDEF_ZOOM]),
728 astr_str(&defaults[MAPDEF_MAP]),
729 astr_str(&str_format), astr_str(&str_showplr));
731 mapdef_destroy(pmapdef);
732 astr_free(&str_format);
733 astr_free(&str_showplr);
734 astr_free(&defaults[MAPDEF_FORMAT]);
735 astr_free(&defaults[MAPDEF_SHOW]);
736 astr_free(&defaults[MAPDEF_TURNS]);
737 astr_free(&defaults[MAPDEF_ZOOM]);
738 astr_free(&defaults[MAPDEF_MAP]);
740 return fc_strdup(astr_str(&help));
743 /****************************************************************************
744 Returns the last error.
745 ****************************************************************************/
746 const char *mapimg_error(void)
748 return error_buffer;
751 /****************************************************************************
752 Define on map image.
753 ****************************************************************************/
754 #define NUM_MAX_MAPARGS 10
755 #define NUM_MAX_MAPOPTS 2
756 bool mapimg_define(const char *maparg, bool check)
758 struct mapdef *pmapdef = NULL;
759 char *mapargs[NUM_MAX_MAPARGS], *mapopts[NUM_MAX_MAPOPTS];
760 int nmapargs, nmapopts, i;
761 bool ret = TRUE;
763 MAPIMG_ASSERT_RET_VAL(mapimg_initialised(), FALSE);
765 if (maparg == NULL) {
766 MAPIMG_LOG(_("no map definition"));
767 return FALSE;
770 if (strlen(maparg) > MAX_LEN_MAPARG) {
771 /* too long map definition string */
772 MAPIMG_LOG(_("map definition string too long (max %d characters)"),
773 MAX_LEN_MAPARG);
774 return FALSE;
777 if (mapimg_count() == MAX_NUM_MAPIMG) {
778 MAPIMG_LOG(_("maximum number of map definitions reached (%d)"),
779 MAX_NUM_MAPIMG);
780 return FALSE;
783 for (i = 0; i < mapimg_count(); i++) {
784 pmapdef = mapdef_list_get(mapimg.mapdef, i);
785 if (0 == fc_strcasecmp(pmapdef->maparg, maparg)) {
786 MAPIMG_LOG(_("duplicate of map image definition %d ('%s')"), i,
787 maparg);
788 return FALSE;
792 pmapdef = mapdef_new(FALSE);
794 /* get map options */
795 nmapargs = get_tokens(maparg, mapargs, NUM_MAX_MAPARGS, ":");
797 for (i = 0; i < nmapargs; i++) {
798 /* split map options into variable and value */
799 nmapopts = get_tokens(mapargs[i], mapopts, NUM_MAX_MAPOPTS, "=");
801 if (nmapopts == 2) {
802 enum mapdef_arg arg = mapdef_arg_by_name(mapopts[0], strcmp);
803 if (mapdef_arg_is_valid(arg)) {
804 /* If ret is FALSE an error message is set by mapimg_define_arg(). */
805 ret = mapimg_define_arg(pmapdef, arg, mapopts[1], check);
806 } else {
807 MAPIMG_LOG(_("unknown map option: '%s'"), mapargs[i]);
808 ret = FALSE;
810 } else {
811 MAPIMG_LOG(_("unknown map option: '%s'"), mapargs[i]);
812 ret = FALSE;
815 free_tokens(mapopts, nmapopts);
817 if (!ret) {
818 break;
821 free_tokens(mapargs, nmapargs);
823 /* sanity check */
824 switch (pmapdef->player.show) {
825 case SHOW_PLRNAME: /* display player given by name */
826 if (!BV_ISSET(pmapdef->args, MAPDEF_PLRNAME)) {
827 MAPIMG_LOG(_("'show=%s' but no player name 'plrname'"),
828 show_player_name(SHOW_PLRNAME));
829 ret = FALSE;
831 break;
832 case SHOW_PLRID: /* display player given by id */
833 if (!BV_ISSET(pmapdef->args, MAPDEF_PLRID)) {
834 MAPIMG_LOG(_("'show=%s' but no player id 'plrid'"),
835 show_player_name(SHOW_PLRID));
836 ret = FALSE;
838 break;
839 case SHOW_PLRBV: /* display players given by bitvector */
840 if (!BV_ISSET(pmapdef->args, MAPDEF_PLRBV)) {
841 MAPIMG_LOG(_("'show=%s' but no player bitvector 'plrbv'"),
842 show_player_name(SHOW_PLRBV));
843 ret = FALSE;
845 break;
846 case SHOW_NONE: /* no player on the map */
847 BV_CLR_ALL(pmapdef->player.checked_plrbv);
848 break;
849 case SHOW_ALL: /* show all players in one map */
850 BV_SET_ALL(pmapdef->player.checked_plrbv);
851 break;
852 case SHOW_EACH: /* one map for each player */
853 case SHOW_HUMAN: /* one map for each human player */
854 /* A loop for each player will be called at the time the image is
855 * created. */
856 BV_CLR_ALL(pmapdef->player.checked_plrbv);
857 break;
860 if (ret && !check) {
861 /* save map string */
862 fc_strlcpy(pmapdef->maparg, maparg, MAX_LEN_MAPARG);
864 /* add map definiton */
865 mapdef_list_append(mapimg.mapdef, pmapdef);
866 } else {
867 mapdef_destroy(pmapdef);
870 return ret;
872 #undef NUM_MAX_MAPARGS
873 #undef NUM_MAX_MAPOPTS
875 /****************************************************************************
876 Helper function for mapimg_define().
877 ****************************************************************************/
878 #define NUM_MAX_FORMATARGS 2
879 static bool mapimg_define_arg(struct mapdef *pmapdef, enum mapdef_arg arg,
880 const char *val, bool check)
882 if (BV_ISSET(pmapdef->args, arg)) {
883 log_debug("Option '%s' for mapimg used more than once.",
884 mapdef_arg_name(arg));
887 /* This argument was used. */
888 BV_SET(pmapdef->args, arg);
890 switch (arg) {
891 case MAPDEF_FORMAT:
892 /* file format */
894 char *formatargs[NUM_MAX_FORMATARGS];
895 int nformatargs;
896 enum imageformat format;
897 enum imagetool tool;
898 bool error = TRUE;
900 /* get format options */
901 nformatargs = get_tokens(val, formatargs, NUM_MAX_FORMATARGS, "|");
903 if (nformatargs == 2) {
904 tool = imagetool_by_name(formatargs[0], strcmp);
905 format = imageformat_by_name(formatargs[1], strcmp);
907 if (imageformat_is_valid(format) && imagetool_is_valid(tool)) {
908 const struct toolkit *toolkit = img_toolkit_get(tool);
910 if (toolkit && (toolkit->formats & format)) {
911 pmapdef->tool = tool;
912 pmapdef->format = format;
914 error = FALSE;
917 } else {
918 /* Only one argument to format. */
919 tool = imagetool_by_name(formatargs[0], strcmp);
920 if (imagetool_is_valid(tool)) {
921 /* toolkit defined */
922 const struct toolkit *toolkit = img_toolkit_get(tool);
924 if (toolkit) {
925 pmapdef->tool = toolkit->tool;
926 pmapdef->format = toolkit->format_default;
928 error = FALSE;
930 } else {
931 format = imageformat_by_name(formatargs[0], strcmp);
932 if (imageformat_is_valid(format)) {
933 /* format defined */
934 img_toolkit_iterate(toolkit) {
935 if ((toolkit->formats & format)) {
936 pmapdef->tool = toolkit->tool;
937 pmapdef->format = toolkit->format_default;
939 error = FALSE;
940 break;
942 } img_toolkit_iterate_end;
947 free_tokens(formatargs, nformatargs);
949 if (error) {
950 goto INVALID;
953 break;
955 case MAPDEF_MAP:
956 /* map definition */
958 int len = strlen(val), l;
959 enum mapimg_layer layer;
960 bool error;
962 for (layer = mapimg_layer_begin(); layer != mapimg_layer_end();
963 layer = mapimg_layer_next(layer)) {
964 pmapdef->layers[layer] = FALSE;
967 for (l = 0; l < len; l++) {
968 error = TRUE;
969 for (layer = mapimg_layer_begin(); layer != mapimg_layer_end();
970 layer = mapimg_layer_next(layer)) {
971 if (val[l] == mapimg_layer_name(layer)[0]) {
972 pmapdef->layers[layer] = TRUE;
973 error = FALSE;
974 break;
978 if (error) {
979 goto INVALID;
983 break;
985 case MAPDEF_PLRBV:
986 /* player definition - bitvector */
988 int i;
990 if (strlen(val) < MAX_NUM_PLAYER_SLOTS + 1) {
991 BV_CLR_ALL(pmapdef->player.plrbv);
992 for (i = 0; i < strlen(val); i++) {
993 if (!strchr("01", val[i])) {
994 MAPIMG_LOG(_("invalid character in bitvector: '%c' (%s)"),
995 val[i], val);
996 return FALSE;
997 } else if (val[i] == '1') {
998 BV_SET(pmapdef->player.plrbv, i);
1001 } else {
1002 goto INVALID;
1005 break;
1007 case MAPDEF_PLRID:
1008 /* player definition - player id; will be checked by mapimg_isvalid()
1009 * which calls mapimg_checkplayers() */
1011 int plrid;
1013 if (sscanf(val, "%d", &plrid) != 0) {
1014 if (plrid < 0 || plrid >= MAX_NUM_PLAYER_SLOTS) {
1015 MAPIMG_LOG(_("'plrid' should be between 0 and %d"),
1016 MAX_NUM_PLAYER_SLOTS-1);
1017 return FALSE;
1019 pmapdef->player.id = plrid;
1020 } else {
1021 goto INVALID;
1024 break;
1026 case MAPDEF_PLRNAME:
1027 /* player definition - player name; will be checked by mapimg_isvalid()
1028 * which calls mapimg_checkplayers() */
1030 if (strlen(val) > sizeof(pmapdef->player.name)) {
1031 MAPIMG_LOG(_("player name too long: '%s' (max: %lu)"), val,
1032 (unsigned long) sizeof(pmapdef->player.name));
1033 return FALSE;
1034 } else {
1035 sz_strlcpy(pmapdef->player.name, val);
1038 break;
1040 case MAPDEF_SHOW:
1041 /* player definition - basic definition */
1043 enum show_player showplr;
1045 showplr = show_player_by_name(val, strcmp);
1046 if (show_player_is_valid(showplr)) {
1047 pmapdef->player.show = showplr;
1048 } else {
1049 goto INVALID;
1052 break;
1054 case MAPDEF_TURNS:
1055 /* save each <x> turns */
1057 int turns;
1059 if (sscanf(val, "%d", &turns) != 0) {
1060 if (turns < 0 || turns > 99) {
1061 MAPIMG_LOG(_("'turns' should be between 0 and 99"));
1062 return FALSE;
1063 } else {
1064 pmapdef->turns = turns;
1066 } else {
1067 goto INVALID;
1070 break;
1072 case MAPDEF_ZOOM:
1073 /* zoom factor */
1075 int zoom;
1077 if (sscanf(val, "%d", &zoom) != 0) {
1078 if (zoom < 1 || zoom > 5) {
1079 MAPIMG_LOG(_("'zoom' factor should be between 1 and 5"));
1080 return FALSE;
1081 } else {
1082 pmapdef->zoom = zoom;
1084 } else {
1085 goto INVALID;
1088 break;
1090 case MAPDEF_COUNT:
1091 fc_assert_ret_val(arg != MAPDEF_COUNT, FALSE);
1092 break;
1095 return TRUE;
1097 INVALID:
1098 MAPIMG_LOG(_("invalid value for option '%s': '%s'"),
1099 mapdef_arg_name(arg), val);
1100 return FALSE;
1102 #undef NUM_MAX_FORMATARGS
1104 /****************************************************************************
1105 Check if a map image definition is valid. This function is a wrapper for
1106 mapimg_checkplayers().
1107 ****************************************************************************/
1108 struct mapdef *mapimg_isvalid(int id)
1110 struct mapdef *pmapdef = NULL;
1112 if (!mapimg_test(id)) {
1113 /* The error message is set in mapimg_test(). */
1114 return NULL;
1117 pmapdef = mapdef_list_get(mapimg.mapdef, id);
1118 mapimg_checkplayers(pmapdef, TRUE);
1120 switch (pmapdef->status) {
1121 case MAPIMG_STATUS_UNKNOWN:
1122 MAPIMG_LOG(_("map definition not checked (game not started)"));
1123 return NULL;
1124 break;
1125 case MAPIMG_STATUS_ERROR:
1126 MAPIMG_LOG(_("map definition deactivated: %s"), pmapdef->error);
1127 return NULL;
1128 break;
1129 case MAPIMG_STATUS_OK:
1130 /* nothing */
1131 break;
1134 return pmapdef;
1137 /****************************************************************************
1138 Return a list of all available tookits and formats for the client.
1139 ****************************************************************************/
1140 const struct strvec *mapimg_get_format_list(void)
1142 static struct strvec *format_list = NULL;
1144 if (NULL == format_list) {
1145 enum imagetool tool;
1147 format_list = strvec_new();
1149 for (tool = imagetool_begin(); tool != imagetool_end();
1150 tool = imagetool_next(tool)) {
1151 enum imageformat format;
1152 const struct toolkit *toolkit = img_toolkit_get(tool);
1154 if (!toolkit) {
1155 continue;
1158 for (format = imageformat_begin(); format != imageformat_end();
1159 format = imageformat_next(format)) {
1160 if (toolkit->formats & format) {
1161 char str_format[64];
1162 fc_snprintf(str_format, sizeof(str_format), "%s|%s",
1163 imagetool_name(tool), imageformat_name(format));
1164 strvec_append(format_list, str_format);
1170 return format_list;
1173 /****************************************************************************
1174 Return the default value of the tookit and the image format for the client.
1175 ****************************************************************************/
1176 const char *mapimg_get_format_default(void)
1178 static char default_format[64];
1180 fc_snprintf(default_format, sizeof(default_format), "%s|%s",
1181 imagetool_name(MAPIMG_DEFAULT_IMGTOOL),
1182 imageformat_name(MAPIMG_DEFAULT_IMGFORMAT));
1184 return default_format;
1187 /****************************************************************************
1188 Delete a map image definition.
1189 ****************************************************************************/
1190 bool mapimg_delete(int id)
1192 struct mapdef *pmapdef = NULL;
1194 if (!mapimg_test(id)) {
1195 /* The error message is set in mapimg_test(). */
1196 return FALSE;
1199 /* delete map definition */
1200 pmapdef = mapdef_list_get(mapimg.mapdef, id);
1201 mapdef_list_remove(mapimg.mapdef, pmapdef);
1203 return TRUE;
1206 /****************************************************************************
1207 Show a map image definition.
1208 ****************************************************************************/
1209 bool mapimg_show(int id, char *str, size_t str_len, bool detail)
1211 struct mapdef *pmapdef = NULL;
1213 if (!mapimg_test(id)) {
1214 /* The error message is set in mapimg_test(). */
1215 return FALSE;
1218 pmapdef = mapdef_list_get(mapimg.mapdef, id);
1220 /* Clear string ... */
1221 fc_assert_ret_val(str_len > 0, FALSE);
1222 str[0] = '\0';
1224 if (detail) {
1225 cat_snprintf(str, str_len, _("Detailed information for map image "
1226 "definition %d\n"), id);
1227 if (pmapdef->status == MAPIMG_STATUS_ERROR) {
1228 cat_snprintf(str, str_len, _(" - status: %s (%s)\n"),
1229 mapimg_status_name(pmapdef->status), pmapdef->error);
1230 } else {
1231 cat_snprintf(str, str_len, _(" - status: %s\n"),
1232 mapimg_status_name(pmapdef->status));
1234 cat_snprintf(str, str_len, _(" - file name string: %s\n"),
1235 mapimg_generate_name(pmapdef));
1236 cat_snprintf(str, str_len, _(" - image toolkit: %s\n"),
1237 imagetool_name(pmapdef->tool));
1238 cat_snprintf(str, str_len, _(" - image format: %s\n"),
1239 imageformat_name(pmapdef->format));
1240 cat_snprintf(str, str_len, _(" - zoom factor: %d\n"),
1241 pmapdef->zoom);
1242 cat_snprintf(str, str_len, _(" - show area within borders: %s\n"),
1243 pmapdef->layers[MAPIMG_LAYER_AREA] ? _("yes") : _("no"));
1244 cat_snprintf(str, str_len, _(" - show borders: %s\n"),
1245 pmapdef->layers[MAPIMG_LAYER_BORDERS] ? _("yes") : _("no"));
1246 cat_snprintf(str, str_len, _(" - show cities: %s\n"),
1247 pmapdef->layers[MAPIMG_LAYER_CITIES] ? _("yes") : _("no"));
1248 cat_snprintf(str, str_len, _(" - show fog of war: %s\n"),
1249 pmapdef->layers[MAPIMG_LAYER_FOGOFWAR] ? _("yes") : _("no"));
1250 cat_snprintf(str, str_len, _(" - show player knowledge: %s\n"),
1251 pmapdef->layers[MAPIMG_LAYER_KNOWLEDGE] ? _("yes") : _("no"));
1252 cat_snprintf(str, str_len, _(" - show terrain: %s\n"),
1253 pmapdef->layers[MAPIMG_LAYER_TERRAIN] ? _("full") :_("basic"));
1254 cat_snprintf(str, str_len, _(" - show units: %s\n"),
1255 pmapdef->layers[MAPIMG_LAYER_UNITS] ? _("yes") : _("no"));
1256 cat_snprintf(str, str_len, _(" - players included: %s"),
1257 show_player_name(pmapdef->player.show));
1258 switch (pmapdef->player.show) {
1259 case SHOW_NONE:
1260 case SHOW_HUMAN:
1261 case SHOW_EACH:
1262 case SHOW_ALL:
1263 /* nothing */
1264 break;
1265 case SHOW_PLRNAME:
1266 cat_snprintf(str, str_len, _("\n - player name: %s"),
1267 pmapdef->player.name);
1268 break;
1269 case SHOW_PLRID:
1270 cat_snprintf(str, str_len, _("\n - player id: %d"),
1271 pmapdef->player.id);
1272 break;
1273 case SHOW_PLRBV:
1274 cat_snprintf(str, str_len, _("\n - players: %s"),
1275 bvplayers_str(pmapdef->player.plrbv));
1276 break;
1278 } else {
1279 char str_def[MAX_LEN_MAPDEF];
1280 mapimg_def2str(pmapdef, str_def, sizeof(str_def));
1281 if (pmapdef->status == MAPIMG_STATUS_ERROR) {
1282 cat_snprintf(str, str_len, "'%s' (%s: %s)", str_def,
1283 mapimg_status_name(pmapdef->status), pmapdef->error);
1284 } else {
1285 cat_snprintf(str, str_len, "'%s' (%s)", str_def,
1286 mapimg_status_name(pmapdef->status));
1290 return TRUE;
1293 /****************************************************************************
1294 Return the map image definition 'id' as a mapdef string. This function is
1295 a wrapper for mapimg_def2str().
1296 ****************************************************************************/
1297 bool mapimg_id2str(int id, char *str, size_t str_len)
1299 struct mapdef *pmapdef = NULL;
1301 if (!mapimg_test(id)) {
1302 /* The error message is set in mapimg_test(). */
1303 return FALSE;
1306 pmapdef = mapdef_list_get(mapimg.mapdef, id);
1308 return mapimg_def2str(pmapdef, str, str_len);
1311 /****************************************************************************
1312 Create the requested map image. The filename is created as
1313 <basename as used for savegames>-<mapstr>.<mapext> where <mapstr>
1314 contains the map definition and <mapext> the selected image extension.
1315 If 'force' is FALSE, the image is only created if game.info.turn is a
1316 multiple of the map setting turns.
1317 ****************************************************************************/
1318 bool mapimg_create(struct mapdef *pmapdef, bool force, const char *savename,
1319 const char *path)
1321 struct img *pimg;
1322 char mapimgfile[MAX_LEN_PATH];
1323 bool ret = TRUE;
1324 #ifdef FREECIV_DEBUG
1325 struct timer *timer_cpu, *timer_user;
1326 #endif
1328 if (map_is_empty()) {
1329 MAPIMG_LOG(_("map not yet created"));
1331 return FALSE;
1334 mapimg_checkplayers(pmapdef, FALSE);
1336 if (pmapdef->status != MAPIMG_STATUS_OK) {
1337 MAPIMG_LOG(_("map definition not checked or error"));
1338 return FALSE;
1341 /* An image should be saved if:
1342 * - force is set to TRUE
1343 * - it is the first turn
1344 * - turns is set to a value not zero and the current turn can be devided
1345 * by this number */
1346 if (!force && game.info.turn != 1
1347 && !(pmapdef->turns != 0 && game.info.turn % pmapdef->turns == 0)) {
1348 return TRUE;
1351 #ifdef FREECIV_DEBUG
1352 timer_cpu = timer_new(TIMER_CPU, TIMER_ACTIVE);
1353 timer_start(timer_cpu);
1354 timer_user = timer_new(TIMER_USER, TIMER_ACTIVE);
1355 timer_start(timer_user);
1356 #endif /* FREECIV_DEBUG */
1358 /* create map */
1359 switch (pmapdef->player.show) {
1360 case SHOW_PLRNAME: /* display player given by name */
1361 case SHOW_PLRID: /* display player given by id */
1362 case SHOW_NONE: /* no player one the map */
1363 case SHOW_ALL: /* show all players in one map */
1364 case SHOW_PLRBV: /* display player(s) given by bitvector */
1365 generate_save_name(savename, mapimgfile, sizeof(mapimgfile),
1366 mapimg_generate_name(pmapdef));
1368 pimg = img_new(pmapdef, CURRENT_TOPOLOGY, wld.map.xsize, wld.map.ysize);
1369 img_createmap(pimg);
1370 if (!img_save(pimg, mapimgfile, path)) {
1371 ret = FALSE;
1373 img_destroy(pimg);
1374 break;
1375 case SHOW_EACH: /* one map for each player */
1376 case SHOW_HUMAN: /* one map for each human player */
1377 players_iterate(pplayer) {
1378 if (!pplayer->is_alive || (pmapdef->player.show == SHOW_HUMAN
1379 && !is_human(pplayer))) {
1380 /* no map image for dead players
1381 * or AI players if only human players should be shown */
1382 continue;
1385 BV_CLR_ALL(pmapdef->player.checked_plrbv);
1386 BV_SET(pmapdef->player.checked_plrbv, player_index(pplayer));
1388 generate_save_name(savename, mapimgfile, sizeof(mapimgfile),
1389 mapimg_generate_name(pmapdef));
1391 pimg = img_new(pmapdef, CURRENT_TOPOLOGY, wld.map.xsize, wld.map.ysize);
1392 img_createmap(pimg);
1393 if (!img_save(pimg, mapimgfile, path)) {
1394 ret = FALSE;
1396 img_destroy(pimg);
1398 if (!ret) {
1399 break;
1401 } players_iterate_end;
1402 break;
1405 #ifdef FREECIV_DEBUG
1406 log_debug("Image generation time: %g seconds (%g apparent)",
1407 timer_read_seconds(timer_cpu),
1408 timer_read_seconds(timer_user));
1410 timer_destroy(timer_cpu);
1411 timer_destroy(timer_user);
1412 #endif /* FREECIV_DEBUG */
1414 return ret;
1417 /****************************************************************************
1418 Create images which shows all map colors (playercolor, terrain colors). One
1419 image is created for each supported toolkit and image format. The filename
1420 will be <basename as used for savegames>-colortest-<tookit>.<format>.
1421 ****************************************************************************/
1422 bool mapimg_colortest(const char *savename, const char *path)
1424 struct img *pimg;
1425 const struct rgbcolor *pcolor;
1426 struct mapdef *pmapdef = mapdef_new(TRUE);
1427 char mapimgfile[MAX_LEN_PATH];
1428 bv_pixel pixel;
1429 int i, nat_x, nat_y;
1430 int max_playercolor = mapimg.mapimg_plrcolor_count();
1431 int max_terraincolor = terrain_count();
1432 bool ret = TRUE;
1433 enum imagetool tool;
1435 #define SIZE_X 16
1436 #define SIZE_Y 5
1438 pimg = img_new(pmapdef, 0, SIZE_X + 2,
1439 SIZE_Y * (max_playercolor / SIZE_X) + 2);
1441 pixel = pimg->pixel_tile(NULL, NULL, FALSE);
1443 pcolor = imgcolor_special(IMGCOLOR_OCEAN);
1444 for (i = 0; i < MAX(max_playercolor, max_terraincolor); i++) {
1445 nat_x = 1 + i % SIZE_X;
1446 nat_y = 1 + (i / SIZE_X) * SIZE_Y;
1448 img_plot(pimg, nat_x, nat_y, pcolor, pixel);
1451 for (i = 0; i < MAX(max_playercolor, max_terraincolor); i++) {
1452 if (i >= max_playercolor) {
1453 break;
1456 nat_x = 1 + i % SIZE_X;
1457 nat_y = 2 + (i / SIZE_X) * SIZE_Y;
1458 pcolor = mapimg.mapimg_plrcolor_get(i);
1460 img_plot(pimg, nat_x, nat_y, pcolor, pixel);
1463 pcolor = imgcolor_special(IMGCOLOR_GROUND);
1464 for (i = 0; i < MAX(max_playercolor, max_terraincolor); i++) {
1465 nat_x = 1 + i % SIZE_X;
1466 nat_y = 3 + (i / SIZE_X) * SIZE_Y;
1468 img_plot(pimg, nat_x, nat_y, pcolor, pixel);
1471 for (i = 0; i < MAX(max_playercolor, max_terraincolor); i++) {
1472 if (i >= max_terraincolor) {
1473 break;
1476 nat_x = 1 + i % SIZE_X;
1477 nat_y = 4 + (i / SIZE_X) * SIZE_Y;
1478 pcolor = imgcolor_terrain(terrain_by_number(i));
1480 img_plot(pimg, nat_x, nat_y, pcolor, pixel);
1483 #undef SIZE_X
1484 #undef SIZE_Y
1486 for (tool = imagetool_begin(); tool != imagetool_end();
1487 tool = imagetool_next(tool)) {
1488 enum imageformat format;
1489 const struct toolkit *toolkit = img_toolkit_get(tool);
1491 if (!toolkit) {
1492 continue;
1495 /* Set the toolkit. */
1496 pmapdef->tool = tool;
1498 for (format = imageformat_begin(); format != imageformat_end();
1499 format = imageformat_next(format)) {
1500 if (toolkit->formats & format) {
1501 char buf[128];
1503 /* Set the image format. */
1504 pmapdef->format = format;
1506 fc_snprintf(buf, sizeof(buf), "colortest-%s", imagetool_name(tool));
1507 /* filename for color test */
1508 generate_save_name(savename, mapimgfile, sizeof(mapimgfile), buf);
1510 if (!img_save(pimg, mapimgfile, path)) {
1511 /* If one of the mapimg format/toolkit combination fail, return
1512 * FALSE, i.e. an error occurred. */
1513 ret = FALSE;
1519 img_destroy(pimg);
1520 mapdef_destroy(pmapdef);
1522 return ret;
1526 * ==============================================
1527 * map images (internal functions)
1528 * ==============================================
1531 /****************************************************************************
1532 Check if the map image subsustem is initialised.
1533 ****************************************************************************/
1534 static inline bool mapimg_initialised(void)
1536 return mapimg.init;
1539 /****************************************************************************
1540 Check if the map image subsystem is initialised and the given ID is valid.
1541 In case of an error, the error message is saved via MAPIMG_LOG().
1542 ****************************************************************************/
1543 static bool mapimg_test(int id)
1545 MAPIMG_ASSERT_RET_VAL(mapimg_initialised(), FALSE);
1547 if (id < 0 || id >= mapimg_count()) {
1548 MAPIMG_LOG(_("no map definition with id %d"), id);
1549 return FALSE;
1552 return TRUE;
1555 /****************************************************************************
1556 Return a mapdef string for the map image definition given by 'pmapdef'.
1557 ****************************************************************************/
1558 static bool mapimg_def2str(struct mapdef *pmapdef, char *str, size_t str_len)
1560 enum mapimg_layer layer;
1561 char buf[MAPIMG_LAYER_COUNT + 1];
1562 int i;
1564 if (pmapdef->status != MAPIMG_STATUS_OK) {
1565 MAPIMG_LOG(_("map definition not checked or error"));
1566 fc_strlcpy(str, pmapdef->maparg, str_len);
1567 return FALSE;
1570 str[0] = '\0';
1571 cat_snprintf(str, str_len, "format=%s|%s:",
1572 imagetool_name(pmapdef->tool),
1573 imageformat_name(pmapdef->format));
1574 cat_snprintf(str, str_len, "turns=%d:", pmapdef->turns);
1576 i = 0;
1577 for (layer = mapimg_layer_begin(); layer != mapimg_layer_end();
1578 layer = mapimg_layer_next(layer)) {
1579 if (pmapdef->layers[layer]) {
1580 buf[i++] = mapimg_layer_name(layer)[0];
1583 buf[i++] = '\0';
1584 cat_snprintf(str, str_len, "map=%s:", buf);
1586 switch (pmapdef->player.show) {
1587 case SHOW_NONE:
1588 case SHOW_EACH:
1589 case SHOW_HUMAN:
1590 case SHOW_ALL:
1591 cat_snprintf(str, str_len, "show=%s:",
1592 show_player_name(pmapdef->player.show));
1593 break;
1594 case SHOW_PLRBV:
1595 cat_snprintf(str, str_len, "show=%s:", show_player_name(SHOW_PLRBV));
1596 cat_snprintf(str, str_len, "plrbv=%s:",
1597 bvplayers_str(pmapdef->player.plrbv));
1598 break;
1599 case SHOW_PLRNAME:
1600 cat_snprintf(str, str_len, "show=%s:", show_player_name(SHOW_PLRNAME));
1601 cat_snprintf(str, str_len, "plrname=%s:", pmapdef->player.name);
1602 break;
1603 case SHOW_PLRID:
1604 cat_snprintf(str, str_len, "show=%s:", show_player_name(SHOW_PLRID));
1605 cat_snprintf(str, str_len, "plrid=%d:", pmapdef->player.id);
1606 break;
1608 cat_snprintf(str, str_len, "zoom=%d", pmapdef->zoom);
1610 return TRUE;
1613 /****************************************************************************
1614 Check the player selection. This needs to be done befor _each_ image
1615 creationcall (see mapimg_create()) to test the the selection is still
1616 valid as players can be added or removed during the game.
1617 ****************************************************************************/
1618 static bool mapimg_checkplayers(struct mapdef *pmapdef, bool recheck)
1620 struct player *pplayer;
1621 enum m_pre_result result;
1623 if (!recheck && pmapdef->status == MAPIMG_STATUS_ERROR) {
1624 return FALSE;
1627 /* game started - generate / check bitvector for players */
1628 switch (pmapdef->player.show) {
1629 case SHOW_NONE:
1630 /* nothing */
1631 break;
1632 case SHOW_PLRBV:
1633 pmapdef->player.checked_plrbv = pmapdef->player.plrbv;
1634 break;
1635 case SHOW_EACH:
1636 case SHOW_HUMAN:
1637 /* A map for each player will be created in a loop. */
1638 BV_CLR_ALL(pmapdef->player.checked_plrbv);
1639 break;
1640 case SHOW_ALL:
1641 BV_SET_ALL(pmapdef->player.checked_plrbv);
1642 break;
1643 case SHOW_PLRNAME:
1644 /* display players as requested in the map definition */
1645 BV_CLR_ALL(pmapdef->player.checked_plrbv);
1646 pplayer = player_by_name_prefix(pmapdef->player.name, &result);
1648 if (pplayer != NULL) {
1649 BV_SET(pmapdef->player.checked_plrbv, player_index(pplayer));
1650 } else {
1651 pmapdef->status = MAPIMG_STATUS_ERROR;
1652 /* Save the error message in map definition. */
1653 fc_snprintf(pmapdef->error, sizeof(pmapdef->error),
1654 _("unknown player name: '%s'"), pmapdef->player.name);
1655 MAPIMG_LOG("%s", pmapdef->error);
1656 return FALSE;
1658 break;
1659 case SHOW_PLRID:
1660 /* display players as requested in the map definition */
1661 BV_CLR_ALL(pmapdef->player.checked_plrbv);
1662 pplayer = player_by_number(pmapdef->player.id);
1664 if (pplayer != NULL) {
1665 BV_SET(pmapdef->player.checked_plrbv, player_index(pplayer));
1666 } else {
1667 pmapdef->status = MAPIMG_STATUS_ERROR;
1668 /* Save the error message in map definition. */
1669 fc_snprintf(pmapdef->error, sizeof(pmapdef->error),
1670 _("invalid player id: %d"), pmapdef->player.id);
1671 MAPIMG_LOG("%s", pmapdef->error);
1672 return FALSE;
1674 break;
1677 pmapdef->status = MAPIMG_STATUS_OK;
1679 return TRUE;
1682 /****************************************************************************
1683 Edit the error_buffer.
1684 Strings should not have a terminating period.
1685 ****************************************************************************/
1686 static void mapimg_log(const char *file, const char *function, int line,
1687 const char *format, ...)
1689 va_list args;
1691 va_start(args, format);
1692 fc_vsnprintf(error_buffer, sizeof(error_buffer), format, args);
1693 va_end(args);
1695 #ifdef FREECIV_DEBUG
1696 log_debug("In %s() [%s:%d]: %s", function, file, line, error_buffer);
1697 #endif
1700 /****************************************************************************
1701 Generate an identifier for a map image.
1703 M<map options>Z<zoom factor>P<players>
1705 <map options> map options
1706 <zoom factor> zoom factor
1707 <players> player ID or vector of size MAX_NUM_PLAYER_SLOTS [0/1]
1709 For the player bitvector all MAX_NUM_PLAYER_SLOTS values are used due to
1710 the possibility of additional players during the game (civil war,
1711 barbarians).
1712 ****************************************************************************/
1713 static char *mapimg_generate_name(struct mapdef *pmapdef)
1715 static char mapstr[256];
1716 char str_show[MAX_NUM_PLAYER_SLOTS + 1];
1717 enum mapimg_layer layer;
1718 int i, count = 0, plr_id = -1;
1720 switch (pmapdef->player.show) {
1721 case SHOW_NONE:
1722 /* no player on the map */
1723 sz_strlcpy(str_show, "none");
1724 break;
1725 case SHOW_ALL:
1726 /* show all players in one map */
1727 sz_strlcpy(str_show, "all");
1728 break;
1729 case SHOW_PLRBV:
1730 case SHOW_PLRNAME:
1731 case SHOW_PLRID:
1732 case SHOW_HUMAN:
1733 case SHOW_EACH:
1734 /* one map for each selected player; iterate over all possible player ids
1735 * to generate unique strings even if civil wars occur */
1736 for (i = 0; i < MAX_NUM_PLAYER_SLOTS; i++) {
1737 str_show[i] = BV_ISSET(pmapdef->player.checked_plrbv, i) ? '1' : '0';
1738 if (BV_ISSET(pmapdef->player.checked_plrbv, i)) {
1739 count++;
1740 plr_id = i;
1743 str_show[MAX_NUM_PLAYER_SLOTS] = '\0';
1745 /* Return the option name if no player is selected or the player id if
1746 * there is only one player selected. */
1747 if (count == 0) {
1748 fc_snprintf(str_show, sizeof(str_show), "---%s",
1749 show_player_name(pmapdef->player.show));
1750 } else if (count == 1 && plr_id != -1) {
1751 fc_snprintf(str_show, sizeof(str_show), "%03d%s", plr_id,
1752 show_player_name(pmapdef->player.show));
1754 break;
1757 fc_snprintf(mapstr, sizeof(mapstr), "M");
1758 for (layer = mapimg_layer_begin(); layer != mapimg_layer_end();
1759 layer = mapimg_layer_next(layer)) {
1760 if (pmapdef->layers[layer]) {
1761 cat_snprintf(mapstr, sizeof(mapstr), "%s", mapimg_layer_name(layer));
1762 } else {
1763 cat_snprintf(mapstr, sizeof(mapstr), "-");
1766 cat_snprintf(mapstr, sizeof(mapstr), "Z%dP%s", pmapdef->zoom, str_show);
1768 return mapstr;
1772 * ==============================================
1773 * map definitions (internal functions)
1774 * ==============================================
1777 /****************************************************************************
1778 Create a new map image definition with default values.
1779 ****************************************************************************/
1780 static struct mapdef *mapdef_new(bool colortest)
1782 struct mapdef *pmapdef;
1784 pmapdef = fc_malloc(sizeof(*pmapdef));
1786 /* default values */
1787 pmapdef->maparg[0] = '\0';
1788 pmapdef->error[0] = '\0';
1789 pmapdef->status = MAPIMG_STATUS_UNKNOWN;
1790 pmapdef->format = MAPIMG_DEFAULT_IMGFORMAT;
1791 pmapdef->tool = MAPIMG_DEFAULT_IMGTOOL;
1792 pmapdef->zoom = 2;
1793 pmapdef->turns = 1;
1794 pmapdef->layers[MAPIMG_LAYER_TERRAIN] = FALSE;
1795 pmapdef->layers[MAPIMG_LAYER_CITIES] = TRUE;
1796 pmapdef->layers[MAPIMG_LAYER_UNITS] = TRUE;
1797 pmapdef->layers[MAPIMG_LAYER_BORDERS] = TRUE;
1798 pmapdef->layers[MAPIMG_LAYER_FOGOFWAR] = FALSE;
1799 pmapdef->layers[MAPIMG_LAYER_KNOWLEDGE] = TRUE;
1800 pmapdef->layers[MAPIMG_LAYER_AREA] = FALSE;
1801 pmapdef->player.show = SHOW_ALL;
1802 /* The union is not set at this point (player.id, player.name and
1803 * player.plrbv). */
1804 BV_CLR_ALL(pmapdef->player.checked_plrbv);
1805 BV_CLR_ALL(pmapdef->args);
1806 pmapdef->colortest = colortest;
1808 return pmapdef;
1811 /****************************************************************************
1812 Destroy a map image definition.
1813 ****************************************************************************/
1814 static void mapdef_destroy(struct mapdef *pmapdef)
1816 if (pmapdef == NULL) {
1817 return;
1820 free(pmapdef);
1824 * ==============================================
1825 * images (internal functions)
1826 * ==============================================
1829 /****************************************************************************
1830 Return the definition of the requested toolkit (or NULL).
1831 ****************************************************************************/
1832 static const struct toolkit *img_toolkit_get(enum imagetool tool)
1834 img_toolkit_iterate(toolkit) {
1835 if (toolkit->tool == tool) {
1836 return toolkit;
1838 } img_toolkit_iterate_end;
1840 return NULL;
1843 /****************************************************************************
1844 Create a new image.
1845 ****************************************************************************/
1846 static struct img *img_new(struct mapdef *mapdef, int topo, int xsize, int ysize)
1848 struct img *pimg;
1850 pimg = fc_malloc(sizeof(*pimg));
1852 pimg->def = mapdef;
1853 pimg->turn = game.info.turn;
1854 fc_snprintf(pimg->title, sizeof(pimg->title),
1855 _("Turn: %4d - Year: %10s"), game.info.turn,
1856 calendar_text());
1858 pimg->mapsize.x = xsize; /* x size of the map */
1859 pimg->mapsize.y = ysize; /* y size of the map */
1861 pimg->imgsize.x = 0; /* x size of the map image */
1862 pimg->imgsize.y = 0; /* y size of the map image */
1864 if (topo_has_flag(topo, TF_HEX)) {
1865 /* additional space for hex maps */
1866 pimg->imgsize.x += TILE_SIZE / 2;
1867 pimg->imgsize.y += TILE_SIZE / 2;
1869 if (topo_has_flag(topo, TF_ISO)) {
1870 /* iso-hex */
1871 pimg->imgsize.x += (pimg->mapsize.x + pimg->mapsize.y / 2)
1872 * TILE_SIZE;
1873 pimg->imgsize.y += (pimg->mapsize.x + pimg->mapsize.y / 2)
1874 * TILE_SIZE;
1876 /* magic for isohexa: change size if wrapping in only one direction */
1877 if ((topo_has_flag(topo, TF_WRAPX) && !topo_has_flag(topo, TF_WRAPY))
1878 || (!topo_has_flag(topo, TF_WRAPX) && topo_has_flag(topo, TF_WRAPY))) {
1879 pimg->imgsize.y += (pimg->mapsize.x - pimg->mapsize.y / 2) / 2
1880 * TILE_SIZE;
1883 pimg->tileshape = &tile_isohexa;
1885 pimg->pixel_tile = pixel_tile_isohexa;
1886 pimg->pixel_city = pixel_city_isohexa;
1887 pimg->pixel_unit = pixel_unit_isohexa;
1888 pimg->pixel_fogofwar = pixel_fogofwar_isohexa;
1889 pimg->pixel_border = pixel_border_isohexa;
1891 pimg->base_coor = base_coor_isohexa;
1892 } else {
1893 /* hex */
1894 pimg->imgsize.x += pimg->mapsize.x * TILE_SIZE;
1895 pimg->imgsize.y += pimg->mapsize.y * TILE_SIZE;
1897 pimg->tileshape = &tile_hexa;
1899 pimg->pixel_tile = pixel_tile_hexa;
1900 pimg->pixel_city = pixel_city_hexa;
1901 pimg->pixel_unit = pixel_unit_hexa;
1902 pimg->pixel_fogofwar = pixel_fogofwar_hexa;
1903 pimg->pixel_border = pixel_border_hexa;
1905 pimg->base_coor = base_coor_hexa;
1907 } else {
1908 if (topo_has_flag(topo, TF_ISO)) {
1909 /* isometric rectangular */
1910 pimg->imgsize.x += (pimg->mapsize.x + pimg->mapsize.y / 2) * TILE_SIZE;
1911 pimg->imgsize.y += (pimg->mapsize.x + pimg->mapsize.y / 2) * TILE_SIZE;
1912 } else {
1913 /* rectangular */
1914 pimg->imgsize.x += pimg->mapsize.x * TILE_SIZE;
1915 pimg->imgsize.y += pimg->mapsize.y * TILE_SIZE;
1918 pimg->tileshape = &tile_rect;
1920 pimg->pixel_tile = pixel_tile_rect;
1921 pimg->pixel_city = pixel_city_rect;
1922 pimg->pixel_unit = pixel_unit_rect;
1923 pimg->pixel_fogofwar = pixel_fogofwar_rect;
1924 pimg->pixel_border = pixel_border_rect;
1926 pimg->base_coor = base_coor_rect;
1929 /* Here the map image is saved as an array of RGB color values. */
1930 pimg->map = fc_calloc(pimg->imgsize.x * pimg->imgsize.y,
1931 sizeof(*pimg->map));
1932 /* Initialise map. */
1933 memset(pimg->map, 0, pimg->imgsize.x * pimg->imgsize.y);
1935 return pimg;
1938 /****************************************************************************
1939 Destroy a image.
1940 ****************************************************************************/
1941 static void img_destroy(struct img *pimg)
1943 if (pimg != NULL) {
1944 /* do not free pimg->def */
1945 free(pimg->map);
1946 free(pimg);
1950 /****************************************************************************
1951 Set the color of one pixel.
1952 ****************************************************************************/
1953 static inline void img_set_pixel(struct img *pimg, const int mindex,
1954 const struct rgbcolor *pcolor)
1956 if (mindex < 0 || mindex > pimg->imgsize.x * pimg->imgsize.y) {
1957 log_error("invalid index: 0 <= %d < %d", mindex,
1958 pimg->imgsize.x * pimg->imgsize.y);
1959 return;
1962 pimg->map[mindex] = pcolor;
1965 /****************************************************************************
1966 Get the index for an (x,y) image coordinate.
1967 ****************************************************************************/
1968 static inline int img_index(const int x, const int y,
1969 const struct img *pimg)
1971 fc_assert_ret_val(x >= 0 && x < pimg->imgsize.x, -1);
1972 fc_assert_ret_val(y >= 0 && y < pimg->imgsize.y, -1);
1974 return pimg->imgsize.x * y + x;
1977 /****************************************************************************
1978 Plot one tile at (x,y). Only the pixel of the tile set within 'pixel' are ploted.
1979 ****************************************************************************/
1980 static void img_plot(struct img *pimg, int x, int y,
1981 const struct rgbcolor *pcolor, const bv_pixel pixel)
1983 int base_x, base_y, i, mindex;
1985 if (!BV_ISSET_ANY(pixel)) {
1986 return;
1989 pimg->base_coor(pimg, &base_x, &base_y, x, y);
1991 for (i = 0; i < NUM_PIXEL; i++) {
1992 if (BV_ISSET(pixel, i)) {
1993 mindex = img_index(base_x + pimg->tileshape->x[i],
1994 base_y + pimg->tileshape->y[i], pimg);
1995 img_set_pixel(pimg, mindex, pcolor);
2000 /****************************************************************************
2001 Plot one tile. Only the pixel of the tile set within 'pixel' are ploted.
2002 ****************************************************************************/
2003 static void img_plot_tile(struct img *pimg, const struct tile *ptile,
2004 const struct rgbcolor *pcolor, const bv_pixel pixel)
2006 int x, y;
2008 index_to_map_pos(&x, &y, tile_index(ptile));
2010 img_plot(pimg, x, y, pcolor, pixel);
2013 /****************************************************************************
2014 Save an image as ppm file.
2015 ****************************************************************************/
2016 static bool img_save(const struct img *pimg, const char *mapimgfile,
2017 const char *path)
2019 enum imagetool tool = pimg->def->tool;
2020 const struct toolkit *toolkit = img_toolkit_get(tool);
2021 char tmpname[600];
2023 if (!toolkit) {
2024 MAPIMG_LOG(_("toolkit not defined"));
2025 return FALSE;
2028 if (!path_is_absolute(mapimgfile) && path != NULL) {
2029 make_dir(path);
2031 sz_strlcpy(tmpname, path);
2032 if (tmpname[0] != '\0') {
2033 sz_strlcat(tmpname, "/");
2035 } else {
2036 tmpname[0] = '\0';
2039 sz_strlcat(tmpname, mapimgfile);
2041 MAPIMG_ASSERT_RET_VAL(toolkit->img_save, FALSE);
2043 return toolkit->img_save(pimg, tmpname);
2046 /****************************************************************************
2047 Save an image using magickwand as toolkit. This allows different file
2048 formats.
2050 Image structure:
2052 [ 0]
2053 border
2054 [+IMG_BORDER_HEIGHT]
2055 title
2056 [+ IMG_TEXT_HEIGHT]
2057 space (only if count(displayed players) > 0)
2058 [+IMG_SPACER_HEIGHT]
2059 player line (only if count(displayed players) > 0)
2060 [+ IMG_LINE_HEIGHT]
2061 space
2062 [+IMG_SPACER_HEIGHT]
2064 [+ map_height]
2065 border
2066 [+IMG_BORDER_HEIGHT]
2068 ****************************************************************************/
2069 #ifdef HAVE_MAPIMG_MAGICKWAND
2070 #define SET_COLOR(str, pcolor) \
2071 fc_snprintf(str, sizeof(str), "rgb(%d,%d,%d)", \
2072 pcolor->r, pcolor->g, pcolor->b);
2073 static bool img_save_magickwand(const struct img *pimg,
2074 const char *mapimgfile)
2076 const struct rgbcolor *pcolor = NULL;
2077 struct player *pplr_now = NULL, *pplr_only = NULL;
2078 bool ret = TRUE;
2079 char imagefile[MAX_LEN_PATH];
2080 char str_color[32], comment[2048] = "", title[258];
2081 magickwand_size_t img_width, img_height, map_width, map_height;
2082 int x, y, xxx, yyy, row, i, mindex, plrwidth, plroffset, textoffset;
2083 bool withplr = BV_ISSET_ANY(pimg->def->player.checked_plrbv);
2085 if (!img_filename(mapimgfile, pimg->def->format, imagefile,
2086 sizeof(imagefile))) {
2087 MAPIMG_LOG(_("error generating the file name"));
2088 return FALSE;
2091 MagickWand *mw;
2092 PixelIterator *imw;
2093 PixelWand **pmw, *pw;
2094 DrawingWand *dw;
2096 MagickWandGenesis();
2098 mw = NewMagickWand();
2099 dw = NewDrawingWand();
2100 pw = NewPixelWand();
2102 map_width = pimg->imgsize.x * pimg->def->zoom;
2103 map_height = pimg->imgsize.y * pimg->def->zoom;
2105 img_width = map_width + 2 * IMG_BORDER_WIDTH;
2106 img_height = map_height + 2 * IMG_BORDER_HEIGHT + IMG_TEXT_HEIGHT
2107 + IMG_SPACER_HEIGHT + (withplr ? 2 * IMG_SPACER_HEIGHT : 0);
2109 fc_snprintf(title, sizeof(title), "%s (%s)", pimg->title, mapimgfile);
2111 SET_COLOR(str_color, imgcolor_special(IMGCOLOR_BACKGROUND));
2112 PixelSetColor(pw, str_color);
2113 MagickNewImage(mw, img_width, img_height, pw);
2115 textoffset = 0;
2116 if (withplr) {
2117 if (bvplayers_count(pimg->def) == 1) {
2118 /* only one player */
2119 for (i = 0; i < player_slot_count(); i++) {
2120 if (BV_ISSET(pimg->def->player.checked_plrbv, i)) {
2121 pplr_only = player_by_number(i);
2122 break;
2127 if (pplr_only) {
2128 magickwand_size_t plr_color_square = IMG_TEXT_HEIGHT;
2130 textoffset += IMG_TEXT_HEIGHT + IMG_BORDER_HEIGHT;
2132 pcolor = imgcolor_player(player_index(pplr_only));
2133 SET_COLOR(str_color, pcolor);
2135 /* Show the color of the selected player. */
2136 imw = NewPixelRegionIterator(mw, IMG_BORDER_WIDTH, IMG_BORDER_HEIGHT,
2137 IMG_TEXT_HEIGHT, IMG_TEXT_HEIGHT);
2138 /* y coordinate */
2139 for (y = 0; y < IMG_TEXT_HEIGHT; y++) {
2140 pmw = PixelGetNextIteratorRow(imw, &plr_color_square);
2141 /* x coordinate */
2142 for (x = 0; x < IMG_TEXT_HEIGHT; x++) {
2143 PixelSetColor(pmw[x], str_color);
2145 PixelSyncIterator(imw);
2147 DestroyPixelIterator(imw);
2150 /* Show a line displaying the colors of alive players */
2151 plrwidth = map_width / player_slot_count();
2152 plroffset = (map_width - plrwidth * player_slot_count()) / 2;
2154 imw = NewPixelRegionIterator(mw, IMG_BORDER_WIDTH,
2155 IMG_BORDER_HEIGHT + IMG_TEXT_HEIGHT
2156 + IMG_SPACER_HEIGHT, map_width,
2157 IMG_LINE_HEIGHT);
2158 /* y coordinate */
2159 for (y = 0; y < IMG_LINE_HEIGHT; y++) {
2160 pmw = PixelGetNextIteratorRow(imw, &map_width);
2162 /* x coordinate */
2163 for (x = plroffset; x < map_width; x++) {
2164 i = (x - plroffset) / plrwidth;
2165 pplr_now = player_by_number(i);
2167 if (i > player_count() || pplr_now == NULL || !pplr_now->is_alive) {
2168 continue;
2171 if (BV_ISSET(pimg->def->player.checked_plrbv, i)) {
2172 /* The selected player is alive - display it. */
2173 pcolor = imgcolor_player(i);
2174 SET_COLOR(str_color, pcolor);
2175 PixelSetColor(pmw[x], str_color);
2176 } else if (pplr_only != NULL) {
2177 /* Display the state between pplr_only and pplr_now:
2178 * - if allied:
2179 * - show each second pixel
2180 * - if pplr_now does shares map with pplr_onlyus:
2181 * - show every other line of pixels
2182 * This results in the following patterns (# = color):
2183 * ###### # # # ######
2184 * # # # # # #
2185 * ###### # # # ######
2186 * # # # # # #
2187 * shared allied shared vision
2188 * vision + allied */
2189 if ((pplayers_allied(pplr_now, pplr_only) && (x + y) % 2 == 0)
2190 || (y % 2 == 0 && gives_shared_vision(pplr_now, pplr_only))) {
2191 pcolor = imgcolor_player(i);
2192 SET_COLOR(str_color, pcolor);
2193 PixelSetColor(pmw[x], str_color);
2197 PixelSyncIterator(imw);
2199 DestroyPixelIterator(imw);
2202 /* Display the image name. */
2203 SET_COLOR(str_color, imgcolor_special(IMGCOLOR_TEXT));
2204 PixelSetColor(pw, str_color);
2205 DrawSetFillColor(dw, pw);
2206 DrawSetFont(dw, "Times-New-Roman");
2207 DrawSetFontSize(dw, IMG_TEXT_HEIGHT);
2208 DrawAnnotation(dw, IMG_BORDER_WIDTH + textoffset,
2209 IMG_TEXT_HEIGHT + IMG_BORDER_HEIGHT,
2210 (unsigned char *)title);
2211 MagickDrawImage(mw, dw);
2213 /* Display the map. */
2214 imw = NewPixelRegionIterator(mw, IMG_BORDER_WIDTH,
2215 IMG_BORDER_HEIGHT + IMG_TEXT_HEIGHT
2216 + IMG_SPACER_HEIGHT
2217 + (withplr ? (IMG_LINE_HEIGHT + IMG_SPACER_HEIGHT)
2218 : 0), map_width, map_height);
2219 /* y coordinate */
2220 for (y = 0; y < pimg->imgsize.y; y++) {
2221 /* zoom for y */
2222 for (yyy = 0; yyy < pimg->def->zoom; yyy++) {
2224 pmw = PixelGetNextIteratorRow(imw, &map_width);
2226 /* x coordinate */
2227 for (x = 0; x < pimg->imgsize.x; x++) {
2228 mindex = img_index(x, y, pimg);
2229 pcolor = pimg->map[mindex];
2231 if (pcolor != NULL) {
2232 SET_COLOR(str_color, pcolor);
2234 /* zoom for x */
2235 for (xxx = 0; xxx < pimg->def->zoom; xxx++) {
2236 row = x * pimg->def->zoom + xxx;
2237 PixelSetColor(pmw[row], str_color);
2241 PixelSyncIterator(imw);
2244 DestroyPixelIterator(imw);
2246 cat_snprintf(comment, sizeof(comment), "map definition: %s\n",
2247 pimg->def->maparg);
2248 if (BV_ISSET_ANY(pimg->def->player.checked_plrbv)) {
2249 players_iterate(pplayer) {
2250 if (!BV_ISSET(pimg->def->player.checked_plrbv, player_index(pplayer))) {
2251 continue;
2254 pcolor = imgcolor_player(player_index(pplayer));
2255 cat_snprintf(comment, sizeof(comment), "%s\n", img_playerstr(pplayer));
2256 } players_iterate_end;
2258 MagickCommentImage(mw, comment);
2260 if (!MagickWriteImage(mw, imagefile)) {
2261 MAPIMG_LOG(_("error saving map image '%s'"), imagefile);
2262 ret = FALSE;
2263 } else {
2264 log_verbose("Map image saved as '%s'.", imagefile);
2267 DestroyDrawingWand(dw);
2268 DestroyPixelWand(pw);
2269 DestroyMagickWand(mw);
2271 MagickWandTerminus();
2273 return ret;
2275 #undef SET_COLOR
2276 #endif /* HAVE_MAPIMG_MAGICKWAND */
2278 /****************************************************************************
2279 Save an image as ppm file (toolkit: ppm).
2280 ****************************************************************************/
2281 static bool img_save_ppm(const struct img *pimg, const char *mapimgfile)
2283 char ppmname[MAX_LEN_PATH];
2284 FILE *fp;
2285 int x, y, xxx, yyy, mindex;
2286 const struct rgbcolor *pcolor;
2288 if (pimg->def->format != IMGFORMAT_PPM) {
2289 MAPIMG_LOG(_("the ppm toolkit can only create images in the ppm "
2290 "format"));
2291 return FALSE;
2294 if (!img_filename(mapimgfile, IMGFORMAT_PPM, ppmname, sizeof(ppmname))) {
2295 MAPIMG_LOG(_("error generating the file name"));
2296 return FALSE;
2299 fp = fopen(ppmname, "w");
2300 if (!fp) {
2301 MAPIMG_LOG(_("could not open file: %s"), ppmname);
2302 return FALSE;
2305 fprintf(fp, "P3\n");
2306 fprintf(fp, "# version:2\n");
2307 fprintf(fp, "# map definition: %s\n", pimg->def->maparg);
2309 if (pimg->def->colortest) {
2310 fprintf(fp, "# color test\n");
2311 } else if (BV_ISSET_ANY(pimg->def->player.checked_plrbv)) {
2312 players_iterate(pplayer) {
2313 if (!BV_ISSET(pimg->def->player.checked_plrbv, player_index(pplayer))) {
2314 continue;
2317 pcolor = imgcolor_player(player_index(pplayer));
2318 fprintf(fp, "# %s\n", img_playerstr(pplayer));
2319 } players_iterate_end;
2320 } else {
2321 fprintf(fp, "# no players\n");
2324 fprintf(fp, "%d %d\n", pimg->imgsize.x * pimg->def->zoom,
2325 pimg->imgsize.y * pimg->def->zoom);
2326 fprintf(fp, "255\n");
2328 /* y coordinate */
2329 for (y = 0; y < pimg->imgsize.y; y++) {
2330 /* zoom for y */
2331 for (yyy = 0; yyy < pimg->def->zoom; yyy++) {
2332 /* x coordinate */
2333 for (x = 0; x < pimg->imgsize.x; x++) {
2334 mindex = img_index(x, y, pimg);
2335 pcolor = pimg->map[mindex];
2337 /* zoom for x */
2338 for (xxx = 0; xxx < pimg->def->zoom; xxx++) {
2339 if (pcolor == NULL) {
2340 pcolor = imgcolor_special(IMGCOLOR_BACKGROUND);
2342 fprintf(fp, "%d %d %d\n", pcolor->r, pcolor->g, pcolor->b);
2348 log_verbose("Map image saved as '%s'.", ppmname);
2349 fclose(fp);
2351 return TRUE;
2354 /****************************************************************************
2355 Generate the final filename.
2356 ****************************************************************************/
2357 static bool img_filename(const char *mapimgfile, enum imageformat format,
2358 char *filename, size_t filename_len)
2360 fc_assert_ret_val(imageformat_is_valid(format) , FALSE);
2362 fc_snprintf(filename, filename_len, "%s.map.%s", mapimgfile,
2363 imageformat_name(format));
2365 return TRUE;
2368 /****************************************************************************
2369 Return a definition string for the player.
2370 ****************************************************************************/
2371 static const char *img_playerstr(const struct player *pplayer)
2373 static char buf[512];
2374 const struct rgbcolor *pcolor = imgcolor_player(player_index(pplayer));
2376 fc_snprintf(buf, sizeof(buf),
2377 "playerno:%d:color:(%3d, %3d, %3d):name:\"%s\"",
2378 player_number(pplayer), pcolor->r, pcolor->g, pcolor->b,
2379 player_name(pplayer));
2381 return buf;
2384 /****************************************************************************
2385 Create the map considering the options (terrain, player(s), cities,
2386 units, borders, known, fogofwar, ...).
2387 ****************************************************************************/
2388 static void img_createmap(struct img *pimg)
2390 const struct rgbcolor *pcolor;
2391 bv_pixel pixel;
2392 int player_id;
2393 struct player *pplayer = NULL;
2394 struct player *plr_tile = NULL, *plr_city = NULL, *plr_unit = NULL;
2395 enum known_type tile_knowledge = TILE_UNKNOWN;
2396 struct terrain *pterrain = NULL;
2397 bool plr_knowledge = pimg->def->layers[MAPIMG_LAYER_KNOWLEDGE];
2399 whole_map_iterate(&(wld.map), ptile) {
2400 if (bvplayers_count(pimg->def) == 1) {
2401 /* only one player; get player id for 'known' and 'fogofwar' */
2402 players_iterate(aplayer) {
2403 if (BV_ISSET(pimg->def->player.checked_plrbv,
2404 player_index(aplayer))) {
2405 pplayer = aplayer;
2406 tile_knowledge = mapimg.mapimg_tile_known(ptile, pplayer,
2407 plr_knowledge);
2408 break;
2410 } players_iterate_end;
2413 /* known tiles */
2414 if (plr_knowledge && pplayer != NULL && tile_knowledge == TILE_UNKNOWN) {
2415 /* plot nothing iff tile is not known */
2416 continue;
2419 /* terrain */
2420 pterrain = mapimg.mapimg_tile_terrain(ptile, pplayer, plr_knowledge);
2421 if (pimg->def->layers[MAPIMG_LAYER_TERRAIN]) {
2422 /* full terrain */
2423 pixel = pimg->pixel_tile(ptile, pplayer, plr_knowledge);
2424 pcolor = imgcolor_terrain(pterrain);
2425 img_plot_tile(pimg, ptile, pcolor, pixel);
2426 } else {
2427 /* basic terrain */
2428 pixel = pimg->pixel_tile(ptile, pplayer, plr_knowledge);
2429 if (is_ocean(pterrain)) {
2430 img_plot_tile(pimg, ptile, imgcolor_special(IMGCOLOR_OCEAN), pixel);
2431 } else {
2432 img_plot_tile(pimg, ptile, imgcolor_special(IMGCOLOR_GROUND), pixel);
2436 /* (land) area within borders and borders */
2437 plr_tile = mapimg.mapimg_tile_owner(ptile, pplayer, plr_knowledge);
2438 if (game.info.borders > 0 && NULL != plr_tile) {
2439 player_id = player_index(plr_tile);
2440 if (pimg->def->layers[MAPIMG_LAYER_AREA] && !is_ocean(pterrain)
2441 && BV_ISSET(pimg->def->player.checked_plrbv, player_id)) {
2442 /* the tile is land and inside the players borders */
2443 pixel = pimg->pixel_tile(ptile, pplayer, plr_knowledge);
2444 pcolor = imgcolor_player(player_id);
2445 img_plot_tile(pimg, ptile, pcolor, pixel);
2446 } else if (pimg->def->layers[MAPIMG_LAYER_BORDERS]
2447 && (BV_ISSET(pimg->def->player.checked_plrbv, player_id)
2448 || (plr_knowledge && pplayer != NULL))) {
2449 /* plot borders if player is selected or view range of the one
2450 * displayed player */
2451 pixel = pimg->pixel_border(ptile, pplayer, plr_knowledge);
2452 pcolor = imgcolor_player(player_id);
2453 img_plot_tile(pimg, ptile, pcolor, pixel);
2457 /* cities and units */
2458 plr_city = mapimg.mapimg_tile_city(ptile, pplayer, plr_knowledge);
2459 plr_unit = mapimg.mapimg_tile_unit(ptile, pplayer, plr_knowledge);
2460 if (pimg->def->layers[MAPIMG_LAYER_CITIES] && plr_city) {
2461 player_id = player_index(plr_city);
2462 if (BV_ISSET(pimg->def->player.checked_plrbv, player_id)
2463 || (plr_knowledge && pplayer != NULL)) {
2464 /* plot cities if player is selected or view range of the one
2465 * displayed player */
2466 pixel = pimg->pixel_city(ptile, pplayer, plr_knowledge);
2467 pcolor = imgcolor_player(player_id);
2468 img_plot_tile(pimg, ptile, pcolor, pixel);
2470 } else if (pimg->def->layers[MAPIMG_LAYER_UNITS] && plr_unit) {
2471 player_id = player_index(plr_unit);
2472 if (BV_ISSET(pimg->def->player.checked_plrbv, player_id)
2473 || (plr_knowledge && pplayer != NULL)) {
2474 /* plot units if player is selected or view range of the one
2475 * displayed player */
2476 pixel = pimg->pixel_unit(ptile, pplayer, plr_knowledge);
2477 pcolor = imgcolor_player(player_id);
2478 img_plot_tile(pimg, ptile, pcolor, pixel);
2482 /* fogofwar; if only 1 player is plotted */
2483 if (game.info.fogofwar && pimg->def->layers[MAPIMG_LAYER_FOGOFWAR]
2484 && pplayer != NULL
2485 && tile_knowledge == TILE_KNOWN_UNSEEN) {
2486 pixel = pimg->pixel_fogofwar(ptile, pplayer, plr_knowledge);
2487 pcolor = NULL;
2488 img_plot_tile(pimg, ptile, pcolor, pixel);
2490 } whole_map_iterate_end;
2494 * ==============================================
2495 * topology (internal functions)
2496 * ==============================================
2497 * With these functions the pixels corresponding to the different elements
2498 * (tile, city, unit) for each map topology are defined.
2500 * The bv_pixel_fogofwar_*() functions are special as they defines where
2501 * the color should be removed.
2503 * The functions for a rectangular and an isometric rectangular topology
2504 * are identical.
2507 /****************************************************************************
2508 0 1 2 3 3 5
2509 6 7 8 9 10 11
2510 12 13 14 15 16 17
2511 18 19 20 21 22 23
2512 24 25 26 27 28 29
2513 30 31 32 33 34 35
2514 ****************************************************************************/
2515 static bv_pixel pixel_tile_rect(const struct tile *ptile,
2516 const struct player *pplayer,
2517 bool knowledge)
2519 bv_pixel pixel;
2521 BV_SET_ALL(pixel);
2523 return pixel;
2526 /****************************************************************************
2527 -- -- -- -- -- --
2528 -- 7 8 9 10 --
2529 -- 13 14 15 16 --
2530 -- 19 20 21 22 --
2531 -- 25 26 27 28 --
2532 -- -- -- -- -- --
2533 ****************************************************************************/
2534 static bv_pixel pixel_city_rect(const struct tile *ptile,
2535 const struct player *pplayer,
2536 bool knowledge)
2538 bv_pixel pixel;
2540 BV_CLR_ALL(pixel);
2541 BV_SET(pixel, 7);
2542 BV_SET(pixel, 8);
2543 BV_SET(pixel, 9);
2544 BV_SET(pixel, 10);
2545 BV_SET(pixel, 13);
2546 BV_SET(pixel, 14);
2547 BV_SET(pixel, 15);
2548 BV_SET(pixel, 16);
2549 BV_SET(pixel, 19);
2550 BV_SET(pixel, 20);
2551 BV_SET(pixel, 21);
2552 BV_SET(pixel, 22);
2553 BV_SET(pixel, 21);
2554 BV_SET(pixel, 25);
2555 BV_SET(pixel, 26);
2556 BV_SET(pixel, 27);
2557 BV_SET(pixel, 28);
2559 return pixel;
2562 /****************************************************************************
2563 -- -- -- -- -- --
2564 -- -- -- -- -- --
2565 -- -- 14 15 -- --
2566 -- -- 20 21 -- --
2567 -- -- -- -- -- --
2568 -- -- -- -- -- --
2569 ****************************************************************************/
2570 static bv_pixel pixel_unit_rect(const struct tile *ptile,
2571 const struct player *pplayer,
2572 bool knowledge)
2574 bv_pixel pixel;
2576 BV_CLR_ALL(pixel);
2577 BV_SET(pixel, 14);
2578 BV_SET(pixel, 15);
2579 BV_SET(pixel, 20);
2580 BV_SET(pixel, 21);
2582 return pixel;
2585 /****************************************************************************
2586 0 -- 2 -- 4 --
2587 -- 7 -- 9 -- 11
2588 12 -- 14 -- 16 --
2589 -- 19 -- 21 -- 23
2590 24 -- 26 -- 28 --
2591 -- 31 -- 33 -- 35
2592 ****************************************************************************/
2593 static bv_pixel pixel_fogofwar_rect(const struct tile *ptile,
2594 const struct player *pplayer,
2595 bool knowledge)
2597 bv_pixel pixel;
2599 BV_CLR_ALL(pixel);
2601 BV_SET(pixel, 0);
2602 BV_SET(pixel, 2);
2603 BV_SET(pixel, 4);
2604 BV_SET(pixel, 7);
2605 BV_SET(pixel, 9);
2606 BV_SET(pixel, 11);
2607 BV_SET(pixel, 12);
2608 BV_SET(pixel, 14);
2609 BV_SET(pixel, 16);
2610 BV_SET(pixel, 19);
2611 BV_SET(pixel, 21);
2612 BV_SET(pixel, 23);
2613 BV_SET(pixel, 24);
2614 BV_SET(pixel, 26);
2615 BV_SET(pixel, 28);
2616 BV_SET(pixel, 31);
2617 BV_SET(pixel, 33);
2618 BV_SET(pixel, 35);
2620 return pixel;
2623 /****************************************************************************
2626 0 1 2 3 3 5
2627 6 -- -- -- -- 11
2628 [W] 12 -- -- -- -- 17 [E]
2629 18 -- -- -- -- 23
2630 24 -- -- -- -- 29
2631 30 31 32 33 34 35
2634 ****************************************************************************/
2635 static bv_pixel pixel_border_rect(const struct tile *ptile,
2636 const struct player *pplayer,
2637 bool knowledge)
2639 bv_pixel pixel;
2640 struct tile *pnext;
2641 struct player *owner;
2643 BV_CLR_ALL(pixel);
2645 fc_assert_ret_val(ptile != NULL, pixel);
2647 if (NULL == ptile) {
2648 /* no tile */
2649 return pixel;
2652 owner = mapimg.mapimg_tile_owner(ptile, pplayer, knowledge);
2653 if (NULL == owner) {
2654 /* no border */
2655 return pixel;
2658 pnext = mapstep(ptile, DIR8_NORTH);
2659 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2660 knowledge) != TILE_UNKNOWN
2661 && mapimg.mapimg_tile_owner(pnext, pplayer,
2662 knowledge) != owner)) {
2663 BV_SET(pixel, 0);
2664 BV_SET(pixel, 1);
2665 BV_SET(pixel, 2);
2666 BV_SET(pixel, 3);
2667 BV_SET(pixel, 4);
2668 BV_SET(pixel, 5);
2671 pnext = mapstep(ptile, DIR8_EAST);
2672 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2673 knowledge) != TILE_UNKNOWN
2674 && mapimg.mapimg_tile_owner(pnext, pplayer,
2675 knowledge) != owner)) {
2676 BV_SET(pixel, 5);
2677 BV_SET(pixel, 11);
2678 BV_SET(pixel, 17);
2679 BV_SET(pixel, 23);
2680 BV_SET(pixel, 29);
2681 BV_SET(pixel, 35);
2684 pnext = mapstep(ptile, DIR8_SOUTH);
2685 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2686 knowledge) != TILE_UNKNOWN
2687 && mapimg.mapimg_tile_owner(pnext, pplayer,
2688 knowledge) != owner)) {
2689 BV_SET(pixel, 30);
2690 BV_SET(pixel, 31);
2691 BV_SET(pixel, 32);
2692 BV_SET(pixel, 33);
2693 BV_SET(pixel, 34);
2694 BV_SET(pixel, 35);
2697 pnext = mapstep(ptile, DIR8_WEST);
2698 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2699 knowledge) != TILE_UNKNOWN
2700 && mapimg.mapimg_tile_owner(pnext, pplayer,
2701 knowledge) != owner)) {
2702 BV_SET(pixel, 0);
2703 BV_SET(pixel, 6);
2704 BV_SET(pixel, 12);
2705 BV_SET(pixel, 18);
2706 BV_SET(pixel, 24);
2707 BV_SET(pixel, 30);
2710 return pixel;
2713 /****************************************************************************
2714 Base coordinates for the tiles on a (isometric) rectange topology,
2715 ****************************************************************************/
2716 static void base_coor_rect(struct img *pimg, int *base_x, int *base_y,
2717 int x, int y)
2719 *base_x = x * TILE_SIZE;
2720 *base_y = y * TILE_SIZE;
2723 /****************************************************************************
2725 2 3 4 5
2726 6 7 8 9 10 11
2727 12 13 14 15 16 17
2728 18 19 20 21 22 23
2729 24 25 26 27 28 29
2730 30 31 32 33
2731 34 35
2732 ****************************************************************************/
2733 static bv_pixel pixel_tile_hexa(const struct tile *ptile,
2734 const struct player *pplayer,
2735 bool knowledge)
2737 bv_pixel pixel;
2739 BV_SET_ALL(pixel);
2741 return pixel;
2744 /****************************************************************************
2745 -- --
2746 -- 3 4 --
2747 -- 7 8 9 10 --
2748 -- 13 14 15 16 --
2749 -- 19 20 21 22 --
2750 -- 25 26 27 28 --
2751 -- 31 32 --
2752 -- --
2753 ****************************************************************************/
2754 static bv_pixel pixel_city_hexa(const struct tile *ptile,
2755 const struct player *pplayer,
2756 bool knowledge)
2758 bv_pixel pixel;
2760 BV_CLR_ALL(pixel);
2761 BV_SET(pixel, 3);
2762 BV_SET(pixel, 4);
2763 BV_SET(pixel, 7);
2764 BV_SET(pixel, 8);
2765 BV_SET(pixel, 9);
2766 BV_SET(pixel, 10);
2767 BV_SET(pixel, 13);
2768 BV_SET(pixel, 14);
2769 BV_SET(pixel, 15);
2770 BV_SET(pixel, 16);
2771 BV_SET(pixel, 19);
2772 BV_SET(pixel, 20);
2773 BV_SET(pixel, 21);
2774 BV_SET(pixel, 22);
2775 BV_SET(pixel, 25);
2776 BV_SET(pixel, 26);
2777 BV_SET(pixel, 27);
2778 BV_SET(pixel, 28);
2779 BV_SET(pixel, 31);
2780 BV_SET(pixel, 32);
2782 return pixel;
2785 /****************************************************************************
2786 -- --
2787 -- -- -- --
2788 -- -- -- -- -- --
2789 -- -- 14 15 -- --
2790 -- -- 20 21 -- --
2791 -- -- -- -- -- --
2792 -- -- -- --
2793 -- --
2794 ****************************************************************************/
2795 static bv_pixel pixel_unit_hexa(const struct tile *ptile,
2796 const struct player *pplayer,
2797 bool knowledge)
2799 bv_pixel pixel;
2801 BV_CLR_ALL(pixel);
2802 BV_SET(pixel, 14);
2803 BV_SET(pixel, 15);
2804 BV_SET(pixel, 20);
2805 BV_SET(pixel, 21);
2807 return pixel;
2810 /****************************************************************************
2811 0 --
2812 -- 3 -- 5
2813 -- 7 -- 9 -- 11
2814 -- 13 -- 15 -- 17
2815 18 -- 20 -- 22 --
2816 24 -- 26 -- 28 --
2817 30 -- 32 --
2818 -- 35
2819 ****************************************************************************/
2820 static bv_pixel pixel_fogofwar_hexa(const struct tile *ptile,
2821 const struct player *pplayer,
2822 bool knowledge)
2824 bv_pixel pixel;
2826 BV_CLR_ALL(pixel);
2827 BV_SET(pixel, 0);
2828 BV_SET(pixel, 3);
2829 BV_SET(pixel, 5);
2830 BV_SET(pixel, 7);
2831 BV_SET(pixel, 9);
2832 BV_SET(pixel, 11);
2833 BV_SET(pixel, 13);
2834 BV_SET(pixel, 15);
2835 BV_SET(pixel, 17);
2836 BV_SET(pixel, 18);
2837 BV_SET(pixel, 20);
2838 BV_SET(pixel, 22);
2839 BV_SET(pixel, 24);
2840 BV_SET(pixel, 26);
2841 BV_SET(pixel, 28);
2842 BV_SET(pixel, 30);
2843 BV_SET(pixel, 32);
2844 BV_SET(pixel, 35);
2846 return pixel;
2849 /****************************************************************************
2850 [W] 0 1 [N]
2851 2 -- -- 5
2852 6 -- -- -- -- 11
2853 [SW] 12 -- -- -- -- 17 [NE]
2854 18 -- -- -- -- 23
2855 24 -- -- -- -- 29
2856 30 -- -- 33
2857 [S] 34 35 [E]
2858 ****************************************************************************/
2859 static bv_pixel pixel_border_hexa(const struct tile *ptile,
2860 const struct player *pplayer,
2861 bool knowledge)
2863 bv_pixel pixel;
2864 struct tile *pnext;
2865 struct player *owner;
2867 BV_CLR_ALL(pixel);
2869 fc_assert_ret_val(ptile != NULL, pixel);
2871 if (NULL == ptile) {
2872 /* no tile */
2873 return pixel;
2876 owner = mapimg.mapimg_tile_owner(ptile, pplayer, knowledge);
2877 if (NULL == owner) {
2878 /* no border */
2879 return pixel;
2882 pnext = mapstep(ptile, DIR8_WEST);
2883 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2884 knowledge) != TILE_UNKNOWN
2885 && mapimg.mapimg_tile_owner(pnext, pplayer,
2886 knowledge) != owner)) {
2887 BV_SET(pixel, 0);
2888 BV_SET(pixel, 2);
2889 BV_SET(pixel, 6);
2892 /* not used: DIR8_NORTHWEST */
2894 pnext = mapstep(ptile, DIR8_NORTH);
2895 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2896 knowledge) != TILE_UNKNOWN
2897 && mapimg.mapimg_tile_owner(pnext, pplayer,
2898 knowledge) != owner)) {
2899 BV_SET(pixel, 1);
2900 BV_SET(pixel, 5);
2901 BV_SET(pixel, 11);
2904 pnext = mapstep(ptile, DIR8_NORTHEAST);
2905 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2906 knowledge) != TILE_UNKNOWN
2907 && mapimg.mapimg_tile_owner(pnext, pplayer,
2908 knowledge) != owner)) {
2909 BV_SET(pixel, 11);
2910 BV_SET(pixel, 17);
2911 BV_SET(pixel, 23);
2912 BV_SET(pixel, 29);
2915 pnext = mapstep(ptile, DIR8_EAST);
2916 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2917 knowledge) != TILE_UNKNOWN
2918 && mapimg.mapimg_tile_owner(pnext, pplayer,
2919 knowledge) != owner)) {
2920 BV_SET(pixel, 29);
2921 BV_SET(pixel, 33);
2922 BV_SET(pixel, 35);
2925 /* not used. DIR8_SOUTHEAST */
2927 pnext = mapstep(ptile, DIR8_SOUTH);
2928 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2929 knowledge) != TILE_UNKNOWN
2930 && mapimg.mapimg_tile_owner(pnext, pplayer,
2931 knowledge) != owner)) {
2932 BV_SET(pixel, 24);
2933 BV_SET(pixel, 30);
2934 BV_SET(pixel, 34);
2937 pnext = mapstep(ptile, DIR8_SOUTHWEST);
2938 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2939 knowledge) != TILE_UNKNOWN
2940 && mapimg.mapimg_tile_owner(pnext, pplayer,
2941 knowledge) != owner)) {
2942 BV_SET(pixel, 6);
2943 BV_SET(pixel, 12);
2944 BV_SET(pixel, 18);
2945 BV_SET(pixel, 24);
2948 return pixel;
2951 /****************************************************************************
2952 Base coordinates for the tiles on a hexa topology,
2953 ****************************************************************************/
2954 static void base_coor_hexa(struct img *pimg, int *base_x, int *base_y,
2955 int x, int y)
2957 int nat_x, nat_y;
2958 MAP_TO_NATIVE_POS(&nat_x, &nat_y, x, y);
2960 *base_x = nat_x * TILE_SIZE + ((nat_y % 2) ? TILE_SIZE / 2 : 0);
2961 *base_y = nat_y * TILE_SIZE;
2964 /****************************************************************************
2965 0 1 2 3
2966 4 5 6 7 8 9
2967 10 11 12 13 14 15 16 17
2968 18 19 20 21 22 23 24 25
2969 26 27 28 29 30 31
2970 32 33 34 35
2971 ****************************************************************************/
2972 static bv_pixel pixel_tile_isohexa(const struct tile *ptile,
2973 const struct player *pplayer,
2974 bool knowledge)
2976 bv_pixel pixel;
2978 BV_SET_ALL(pixel);
2980 return pixel;
2983 /****************************************************************************
2984 -- -- -- --
2985 -- 5 6 7 8 --
2986 -- 11 12 13 14 15 16 --
2987 -- 19 20 21 22 23 24 --
2988 -- 27 28 29 30 --
2989 -- -- -- --
2990 ****************************************************************************/
2991 static bv_pixel pixel_city_isohexa(const struct tile *ptile,
2992 const struct player *pplayer,
2993 bool knowledge)
2995 bv_pixel pixel;
2997 BV_CLR_ALL(pixel);
2998 BV_SET(pixel, 5);
2999 BV_SET(pixel, 6);
3000 BV_SET(pixel, 7);
3001 BV_SET(pixel, 8);
3002 BV_SET(pixel, 11);
3003 BV_SET(pixel, 12);
3004 BV_SET(pixel, 13);
3005 BV_SET(pixel, 14);
3006 BV_SET(pixel, 15);
3007 BV_SET(pixel, 16);
3008 BV_SET(pixel, 19);
3009 BV_SET(pixel, 20);
3010 BV_SET(pixel, 21);
3011 BV_SET(pixel, 22);
3012 BV_SET(pixel, 23);
3013 BV_SET(pixel, 24);
3014 BV_SET(pixel, 27);
3015 BV_SET(pixel, 28);
3016 BV_SET(pixel, 29);
3017 BV_SET(pixel, 30);
3019 return pixel;
3022 /****************************************************************************
3023 -- -- -- --
3024 -- -- -- -- -- --
3025 -- -- -- 13 14 -- -- --
3026 -- -- -- 21 22 -- -- --
3027 -- -- -- -- -- --
3028 -- -- -- --
3029 ****************************************************************************/
3030 static bv_pixel pixel_unit_isohexa(const struct tile *ptile,
3031 const struct player *pplayer,
3032 bool knowledge)
3034 bv_pixel pixel;
3036 BV_CLR_ALL(pixel);
3037 BV_SET(pixel, 13);
3038 BV_SET(pixel, 14);
3039 BV_SET(pixel, 21);
3040 BV_SET(pixel, 22);
3042 return pixel;
3045 /****************************************************************************
3046 0 1 -- --
3047 4 -- -- 7 8 --
3048 -- -- 12 13 -- -- 16 17
3049 18 19 -- -- 22 23 -- --
3050 -- 27 28 -- -- 31
3051 -- -- 34 35
3052 ****************************************************************************/
3053 static bv_pixel pixel_fogofwar_isohexa(const struct tile *ptile,
3054 const struct player *pplayer,
3055 bool knowledge)
3057 bv_pixel pixel;
3059 BV_CLR_ALL(pixel);
3060 BV_SET(pixel, 0);
3061 BV_SET(pixel, 1);
3062 BV_SET(pixel, 4);
3063 BV_SET(pixel, 7);
3064 BV_SET(pixel, 8);
3065 BV_SET(pixel, 12);
3066 BV_SET(pixel, 13);
3067 BV_SET(pixel, 16);
3068 BV_SET(pixel, 17);
3069 BV_SET(pixel, 18);
3070 BV_SET(pixel, 19);
3071 BV_SET(pixel, 22);
3072 BV_SET(pixel, 23);
3073 BV_SET(pixel, 27);
3074 BV_SET(pixel, 28);
3075 BV_SET(pixel, 31);
3076 BV_SET(pixel, 34);
3077 BV_SET(pixel, 35);
3079 return pixel;
3082 /****************************************************************************
3086 [NW] 0 1 2 3 [E]
3087 4 -- -- -- -- 9
3088 10 -- -- -- -- -- -- 17
3089 18 -- -- -- -- -- -- 25
3090 26 -- -- -- -- 31
3091 [W] 32 33 34 35 [SE]
3094 ****************************************************************************/
3095 static bv_pixel pixel_border_isohexa(const struct tile *ptile,
3096 const struct player *pplayer,
3097 bool knowledge)
3099 bv_pixel pixel;
3100 struct tile *pnext;
3101 struct player *owner;
3103 BV_CLR_ALL(pixel);
3105 fc_assert_ret_val(ptile != NULL, pixel);
3107 if (NULL == ptile) {
3108 /* no tile */
3109 return pixel;
3112 owner = mapimg.mapimg_tile_owner(ptile, pplayer, knowledge);
3113 if (NULL == owner) {
3114 /* no border */
3115 return pixel;
3118 pnext = mapstep(ptile, DIR8_NORTH);
3119 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
3120 knowledge) != TILE_UNKNOWN
3121 && mapimg.mapimg_tile_owner(pnext, pplayer,
3122 knowledge) != owner)) {
3123 BV_SET(pixel, 0);
3124 BV_SET(pixel, 1);
3125 BV_SET(pixel, 2);
3126 BV_SET(pixel, 3);
3129 /* not used: DIR8_NORTHEAST */
3131 pnext = mapstep(ptile, DIR8_EAST);
3132 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
3133 knowledge) != TILE_UNKNOWN
3134 && mapimg.mapimg_tile_owner(pnext, pplayer,
3135 knowledge) != owner)) {
3136 BV_SET(pixel, 3);
3137 BV_SET(pixel, 9);
3138 BV_SET(pixel, 17);
3141 pnext = mapstep(ptile, DIR8_SOUTHEAST);
3142 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
3143 knowledge) != TILE_UNKNOWN
3144 && mapimg.mapimg_tile_owner(pnext, pplayer,
3145 knowledge) != owner)) {
3146 BV_SET(pixel, 25);
3147 BV_SET(pixel, 31);
3148 BV_SET(pixel, 35);
3151 pnext = mapstep(ptile, DIR8_SOUTH);
3152 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
3153 knowledge) != TILE_UNKNOWN
3154 && mapimg.mapimg_tile_owner(pnext, pplayer,
3155 knowledge) != owner)) {
3156 BV_SET(pixel, 32);
3157 BV_SET(pixel, 33);
3158 BV_SET(pixel, 34);
3159 BV_SET(pixel, 35);
3162 /* not used: DIR8_SOUTHWEST */
3164 pnext = mapstep(ptile, DIR8_WEST);
3165 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
3166 knowledge) != TILE_UNKNOWN
3167 && mapimg.mapimg_tile_owner(pnext, pplayer,
3168 knowledge) != owner)) {
3169 BV_SET(pixel, 18);
3170 BV_SET(pixel, 26);
3171 BV_SET(pixel, 32);
3174 pnext = mapstep(ptile, DIR8_NORTHWEST);
3175 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
3176 knowledge) != TILE_UNKNOWN
3177 && mapimg.mapimg_tile_owner(pnext, pplayer,
3178 knowledge) != owner)) {
3179 BV_SET(pixel, 0);
3180 BV_SET(pixel, 4);
3181 BV_SET(pixel, 10);
3184 return pixel;
3187 /****************************************************************************
3188 Base coordinates for the tiles on a isometric hexa topology,
3189 ****************************************************************************/
3190 static void base_coor_isohexa(struct img *pimg, int *base_x, int *base_y,
3191 int x, int y)
3193 /* magic for iso-hexa */
3194 y -= x / 2;
3195 y += (pimg->mapsize.x - 1)/2;
3197 *base_x = x * TILE_SIZE;
3198 *base_y = y * TILE_SIZE + ((x % 2) ? 0 : TILE_SIZE / 2);
3202 * ==============================================
3203 * additional functions (internal functions)
3204 * ==============================================
3207 /****************************************************************************
3208 Convert the player bitvector to a string.
3209 ****************************************************************************/
3210 static const char *bvplayers_str(const bv_player plrbv)
3212 static char buf[MAX_NUM_PLAYER_SLOTS + 1];
3213 int i;
3215 /* Don't print lots of unnecessary trailing zeroes */
3216 for (i = MAX_NUM_PLAYER_SLOTS-1; i >= 0; i--) {
3217 if (BV_ISSET(plrbv, i) || player_by_number(i)) {
3218 buf[i+1] = '\0';
3219 break;
3223 for (; i >= 0; i--) {
3224 buf[i] = BV_ISSET(plrbv, i) ? '1' : '0';
3227 return buf;
3230 /****************************************************************************
3231 Return the number of players defined in a map image definition.
3232 ****************************************************************************/
3233 static int bvplayers_count(const struct mapdef *pmapdef)
3235 int i, count = 0;
3237 switch (pmapdef->player.show) {
3238 case SHOW_NONE: /* no player on the map */
3239 count = 0;
3240 break;
3241 case SHOW_HUMAN: /* one map for each human player */
3242 case SHOW_EACH: /* one map for each player */
3243 case SHOW_PLRNAME: /* the map of one selected player */
3244 case SHOW_PLRID:
3245 count = 1;
3246 break;
3247 case SHOW_PLRBV: /* map showing only players given by a bitvector */
3248 count = 0;
3249 for (i = 0; i < MAX_NUM_PLAYER_SLOTS; i++) {
3250 if (BV_ISSET(pmapdef->player.plrbv, i)) {
3251 count++;
3254 break;
3255 case SHOW_ALL: /* show all players in one map */
3256 count = player_count();
3257 break;
3260 return count;
3264 * ==============================================
3265 * image colors (internal functions)
3266 * ==============================================
3269 /****************************************************************************
3270 Return rgbcolor for img_special
3271 ****************************************************************************/
3272 static const struct rgbcolor *imgcolor_special(enum img_special imgcolor)
3274 static struct rgbcolor rgb_special[] = {
3275 { 255, 0, 0, NULL}, /* IMGCOLOR_ERROR */
3276 /* FIXME: 'ocean' and 'ground' colors are also used in the overview; the
3277 * values are defined in colors.tilespec. */
3278 { 0, 0, 200, NULL}, /* IMGCOLOR_OCEAN */
3279 { 0, 200, 0, NULL}, /* IMGCOLOR_GROUND */
3280 { 0, 0, 0, NULL}, /* IMGCOLOR_BACKGROUND */
3281 { 255, 255, 255, NULL}, /* IMGCOLOR_TEXT */
3284 fc_assert_ret_val(imgcolor >= 0 && imgcolor < ARRAY_SIZE(rgb_special),
3285 &rgb_special[0]);
3287 return &rgb_special[imgcolor];
3290 /****************************************************************************
3291 Return rgbcolor for player.
3293 FIXME: nearly identical with get_player_color() in colors_common.c.
3294 ****************************************************************************/
3295 static const struct rgbcolor *imgcolor_player(int plr_id)
3297 struct player *pplayer = player_by_number(plr_id);
3299 fc_assert_ret_val(pplayer != NULL, imgcolor_special(IMGCOLOR_ERROR));
3300 fc_assert_ret_val(pplayer->rgb != NULL,
3301 imgcolor_special(IMGCOLOR_ERROR));
3303 return pplayer->rgb;
3306 /****************************************************************************
3307 Return rgbcolor for terrain.
3309 FIXME: nearly identical with get_terrain_color() in colors_common.c.
3310 ****************************************************************************/
3311 static const struct rgbcolor
3312 *imgcolor_terrain(const struct terrain *pterrain)
3314 fc_assert_ret_val(pterrain != NULL, imgcolor_special(IMGCOLOR_ERROR));
3315 fc_assert_ret_val(pterrain->rgb != NULL, imgcolor_special(IMGCOLOR_ERROR));
3317 return pterrain->rgb;