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)
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 ****************************************************************************/
15 #include <fc_config.h>
20 #ifdef HAVE_MAPIMG_MAGICKWAND
21 #include <wand/MagickWand.h>
22 #endif /* HAVE_MAPIMG_MAGICKWAND */
26 #include "bitvector.h"
27 #include "fc_cmdline.h"
31 #include "string_vector.h"
36 #include "connection.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
57 #ifndef MagickLibVersion
58 # define MagickLibVersion 0
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
66 # define magickwand_size_t unsigned long
69 /* == image colors == */
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 == */
85 #define NUM_PIXEL TILE_SIZE * TILE_SIZE
87 BV_DEFINE(bv_pixel
, NUM_PIXEL
);
96 typedef bv_pixel (*plot_func
)(const struct tile
*ptile
,
97 const struct player
*pplayer
,
99 typedef void (*base_coor_func
)(struct img
*pimg
, int *base_x
, int *base_y
,
102 /* (isometric) rectangular topology */
103 static struct tile_shape tile_rect
= {
122 static bv_pixel
pixel_tile_rect(const struct tile
*ptile
,
123 const struct player
*pplayer
,
125 static bv_pixel
pixel_city_rect(const struct tile
*ptile
,
126 const struct player
*pplayer
,
128 static bv_pixel
pixel_unit_rect(const struct tile
*ptile
,
129 const struct player
*pplayer
,
131 static bv_pixel
pixel_fogofwar_rect(const struct tile
*ptile
,
132 const struct player
*pplayer
,
134 static bv_pixel
pixel_border_rect(const struct tile
*ptile
,
135 const struct player
*pplayer
,
137 static void base_coor_rect(struct img
*pimg
, int *base_x
, int *base_y
,
141 static struct tile_shape tile_hexa
= {
164 static bv_pixel
pixel_tile_hexa(const struct tile
*ptile
,
165 const struct player
*pplayer
,
167 static bv_pixel
pixel_city_hexa(const struct tile
*ptile
,
168 const struct player
*pplayer
,
170 static bv_pixel
pixel_unit_hexa(const struct tile
*ptile
,
171 const struct player
*pplayer
,
173 static bv_pixel
pixel_fogofwar_hexa(const struct tile
*ptile
,
174 const struct player
*pplayer
,
176 static bv_pixel
pixel_border_hexa(const struct tile
*ptile
,
177 const struct player
*pplayer
,
179 static void base_coor_hexa(struct img
*pimg
, int *base_x
, int *base_y
,
182 /* isometric hexa topology */
183 static struct tile_shape tile_isohexa
= {
187 0, 1, 2, 3, 4, 5, 6, 7,
188 0, 1, 2, 3, 4, 5, 6, 7,
195 2, 2, 2, 2, 2, 2, 2, 2,
196 3, 3, 3, 3, 3, 3, 3, 3,
202 static bv_pixel
pixel_tile_isohexa(const struct tile
*ptile
,
203 const struct player
*pplayer
,
205 static bv_pixel
pixel_city_isohexa(const struct tile
*ptile
,
206 const struct player
*pplayer
,
208 static bv_pixel
pixel_unit_isohexa(const struct tile
*ptile
,
209 const struct player
*pplayer
,
211 static bv_pixel
pixel_fogofwar_isohexa(const struct tile
*ptile
,
212 const struct player
*pplayer
,
214 static bv_pixel
pixel_border_isohexa(const struct tile
*ptile
,
215 const struct player
*pplayer
,
217 static void base_coor_isohexa(struct img
*pimg
, int *base_x
, int *base_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
);
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"
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"
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 == */
318 char maparg
[MAX_LEN_MAPARG
];
319 char error
[MAX_LEN_MAPDEF
];
320 enum mapimg_status status
;
321 enum imageformat format
;
325 bool layers
[MAPIMG_LAYER_COUNT
];
327 enum show_player show
;
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
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 \
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
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
;
381 } mapsize
; /* map size */
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
,
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
);
417 enum imageformat format_default
;
419 const img_save_func img_save
;
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
,
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
,
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
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) \
453 for (_i = 0; _i < img_toolkits_count; _i++) { \
454 const struct toolkit *_toolkit = &img_toolkits[_i];
456 #define img_toolkit_iterate_end \
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 == */
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
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()) {
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
;
534 /****************************************************************************
535 Reset the map image subsystem.
536 ****************************************************************************/
537 void mapimg_reset(void)
539 if (!mapimg_initialised()) {
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()) {
561 mapdef_list_destroy(mapimg
.mapdef
);
566 /****************************************************************************
567 Return the number of map image definitions.
568 ****************************************************************************/
569 int mapimg_count(void)
571 if (!mapimg_initialised()) {
575 return mapdef_list_size(mapimg
.mapdef
);
578 /****************************************************************************
579 Describe the 'show' settings.
580 ****************************************************************************/
581 static const char *showname_help(enum show_player 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'");
596 /****************************************************************************
597 Return a help string for the 'mapimg' command.
598 ****************************************************************************/
599 char *mapimg_help(void)
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
);
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
));
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
)) {
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
], ")");
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 "
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"
688 "Multiple definitions can be active at once. "
689 "A definition <mapdef> consists of colon-separated options:\n"
691 "option (default) description\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"
703 "<[tool|]format> = use image format <format>, optionally specifying "
704 "toolkit <tool>. The following toolkits and formats are compiled in:\n"
707 "<show> determines which players are represented and how many "
708 "images are saved by this definition:\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"
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)
751 /****************************************************************************
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
;
763 MAPIMG_ASSERT_RET_VAL(mapimg_initialised(), FALSE
);
765 if (maparg
== NULL
) {
766 MAPIMG_LOG(_("no map definition"));
770 if (strlen(maparg
) > MAX_LEN_MAPARG
) {
771 /* too long map definition string */
772 MAPIMG_LOG(_("map definition string too long (max %d characters)"),
777 if (mapimg_count() == MAX_NUM_MAPIMG
) {
778 MAPIMG_LOG(_("maximum number of map definitions reached (%d)"),
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
,
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
, "=");
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
);
807 MAPIMG_LOG(_("unknown map option: '%s'"), mapargs
[i
]);
811 MAPIMG_LOG(_("unknown map option: '%s'"), mapargs
[i
]);
815 free_tokens(mapopts
, nmapopts
);
821 free_tokens(mapargs
, nmapargs
);
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
));
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
));
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
));
846 case SHOW_NONE
: /* no player on the map */
847 BV_CLR_ALL(pmapdef
->player
.checked_plrbv
);
849 case SHOW_ALL
: /* show all players in one map */
850 BV_SET_ALL(pmapdef
->player
.checked_plrbv
);
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
856 BV_CLR_ALL(pmapdef
->player
.checked_plrbv
);
861 /* save map string */
862 fc_strlcpy(pmapdef
->maparg
, maparg
, MAX_LEN_MAPARG
);
864 /* add map definiton */
865 mapdef_list_append(mapimg
.mapdef
, pmapdef
);
867 mapdef_destroy(pmapdef
);
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
);
894 char *formatargs
[NUM_MAX_FORMATARGS
];
896 enum imageformat format
;
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
;
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
);
925 pmapdef
->tool
= toolkit
->tool
;
926 pmapdef
->format
= toolkit
->format_default
;
931 format
= imageformat_by_name(formatargs
[0], strcmp
);
932 if (imageformat_is_valid(format
)) {
934 img_toolkit_iterate(toolkit
) {
935 if ((toolkit
->formats
& format
)) {
936 pmapdef
->tool
= toolkit
->tool
;
937 pmapdef
->format
= toolkit
->format_default
;
942 } img_toolkit_iterate_end
;
947 free_tokens(formatargs
, nformatargs
);
958 int len
= strlen(val
), l
;
959 enum mapimg_layer layer
;
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
++) {
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
;
986 /* player definition - bitvector */
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)"),
997 } else if (val
[i
] == '1') {
998 BV_SET(pmapdef
->player
.plrbv
, i
);
1008 /* player definition - player id; will be checked by mapimg_isvalid()
1009 * which calls mapimg_checkplayers() */
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);
1019 pmapdef
->player
.id
= plrid
;
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
));
1035 sz_strlcpy(pmapdef
->player
.name
, val
);
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
;
1055 /* save each <x> turns */
1059 if (sscanf(val
, "%d", &turns
) != 0) {
1060 if (turns
< 0 || turns
> 99) {
1061 MAPIMG_LOG(_("'turns' should be between 0 and 99"));
1064 pmapdef
->turns
= turns
;
1077 if (sscanf(val
, "%d", &zoom
) != 0) {
1078 if (zoom
< 1 || zoom
> 5) {
1079 MAPIMG_LOG(_("'zoom' factor should be between 1 and 5"));
1082 pmapdef
->zoom
= zoom
;
1091 fc_assert_ret_val(arg
!= MAPDEF_COUNT
, FALSE
);
1098 MAPIMG_LOG(_("invalid value for option '%s': '%s'"),
1099 mapdef_arg_name(arg
), val
);
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(). */
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)"));
1125 case MAPIMG_STATUS_ERROR
:
1126 MAPIMG_LOG(_("map definition deactivated: %s"), pmapdef
->error
);
1129 case MAPIMG_STATUS_OK
:
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
);
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
);
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(). */
1199 /* delete map definition */
1200 pmapdef
= mapdef_list_get(mapimg
.mapdef
, id
);
1201 mapdef_list_remove(mapimg
.mapdef
, pmapdef
);
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(). */
1218 pmapdef
= mapdef_list_get(mapimg
.mapdef
, id
);
1220 /* Clear string ... */
1221 fc_assert_ret_val(str_len
> 0, FALSE
);
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
);
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"),
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
) {
1266 cat_snprintf(str
, str_len
, _("\n - player name: %s"),
1267 pmapdef
->player
.name
);
1270 cat_snprintf(str
, str_len
, _("\n - player id: %d"),
1271 pmapdef
->player
.id
);
1274 cat_snprintf(str
, str_len
, _("\n - players: %s"),
1275 bvplayers_str(pmapdef
->player
.plrbv
));
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
);
1285 cat_snprintf(str
, str_len
, "'%s' (%s)", str_def
,
1286 mapimg_status_name(pmapdef
->status
));
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(). */
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
,
1322 char mapimgfile
[MAX_LEN_PATH
];
1325 struct timer
*timer_cpu
, *timer_user
;
1328 if (map_is_empty()) {
1329 MAPIMG_LOG(_("map not yet created"));
1334 mapimg_checkplayers(pmapdef
, FALSE
);
1336 if (pmapdef
->status
!= MAPIMG_STATUS_OK
) {
1337 MAPIMG_LOG(_("map definition not checked or error"));
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
1346 if (!force
&& game
.info
.turn
!= 0
1347 && !(pmapdef
->turns
!= 0 && game
.info
.turn
% pmapdef
->turns
== 0)) {
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
);
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
, game
.map
.xsize
, game
.map
.ysize
);
1369 img_createmap(pimg
);
1370 if (!img_save(pimg
, mapimgfile
, path
)) {
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 && pplayer
->ai_controlled
)) {
1380 /* no map image for dead players
1381 * or AI players if only human players should be shown */
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
, game
.map
.xsize
, game
.map
.ysize
);
1392 img_createmap(pimg
);
1393 if (!img_save(pimg
, mapimgfile
, path
)) {
1401 } players_iterate_end
;
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
);
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
)
1425 const struct rgbcolor
*pcolor
;
1426 struct mapdef
*pmapdef
= mapdef_new(TRUE
);
1427 char mapimgfile
[MAX_LEN_PATH
];
1429 int i
, nat_x
, nat_y
;
1430 int max_playercolor
= mapimg
.mapimg_plrcolor_count();
1431 int max_terraincolor
= terrain_count();
1433 enum imagetool tool
;
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
) {
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
) {
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
);
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
);
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
) {
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. */
1520 mapdef_destroy(pmapdef
);
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)
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
);
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];
1564 if (pmapdef
->status
!= MAPIMG_STATUS_OK
) {
1565 MAPIMG_LOG(_("map definition not checked or error"));
1566 fc_strlcpy(str
, pmapdef
->maparg
, str_len
);
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
);
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];
1584 cat_snprintf(str
, str_len
, "map=%s:", buf
);
1586 switch (pmapdef
->player
.show
) {
1591 cat_snprintf(str
, str_len
, "show=%s:",
1592 show_player_name(pmapdef
->player
.show
));
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
));
1600 cat_snprintf(str
, str_len
, "show=%s:", show_player_name(SHOW_PLRNAME
));
1601 cat_snprintf(str
, str_len
, "plrname=%s:", pmapdef
->player
.name
);
1604 cat_snprintf(str
, str_len
, "show=%s:", show_player_name(SHOW_PLRID
));
1605 cat_snprintf(str
, str_len
, "plrid=%d:", pmapdef
->player
.id
);
1608 cat_snprintf(str
, str_len
, "zoom=%d", pmapdef
->zoom
);
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
) {
1627 /* game started - generate / check bitvector for players */
1628 switch (pmapdef
->player
.show
) {
1633 pmapdef
->player
.checked_plrbv
= pmapdef
->player
.plrbv
;
1637 /* A map for each player will be created in a loop. */
1638 BV_CLR_ALL(pmapdef
->player
.checked_plrbv
);
1641 BV_SET_ALL(pmapdef
->player
.checked_plrbv
);
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
));
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
);
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
));
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
);
1677 pmapdef
->status
= MAPIMG_STATUS_OK
;
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
, ...)
1691 va_start(args
, format
);
1692 fc_vsnprintf(error_buffer
, sizeof(error_buffer
), format
, args
);
1696 log_debug("In %s() [%s:%d]: %s", function
, file
, line
, error_buffer
);
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,
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
) {
1722 /* no player on the map */
1723 sz_strlcpy(str_show
, "none");
1726 /* show all players in one map */
1727 sz_strlcpy(str_show
, "all");
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
)) {
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. */
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
));
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
));
1763 cat_snprintf(mapstr
, sizeof(mapstr
), "-");
1766 cat_snprintf(mapstr
, sizeof(mapstr
), "Z%dP%s", pmapdef
->zoom
, str_show
);
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
;
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
1804 BV_CLR_ALL(pmapdef
->player
.checked_plrbv
);
1805 BV_CLR_ALL(pmapdef
->args
);
1806 pmapdef
->colortest
= colortest
;
1811 /****************************************************************************
1812 Destroy a map image definition.
1813 ****************************************************************************/
1814 static void mapdef_destroy(struct mapdef
*pmapdef
)
1816 if (pmapdef
== NULL
) {
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
) {
1838 } img_toolkit_iterate_end
;
1843 /****************************************************************************
1845 ****************************************************************************/
1846 static struct img
*img_new(struct mapdef
*mapdef
, int topo
, int xsize
, int ysize
)
1850 pimg
= fc_malloc(sizeof(*pimg
));
1853 pimg
->turn
= game
.info
.turn
;
1854 fc_snprintf(pimg
->title
, sizeof(pimg
->title
),
1855 _("Turn: %4d - Year: %10s"), game
.info
.turn
,
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
)) {
1871 pimg
->imgsize
.x
+= (pimg
->mapsize
.x
+ pimg
->mapsize
.y
/ 2)
1873 pimg
->imgsize
.y
+= (pimg
->mapsize
.x
+ pimg
->mapsize
.y
/ 2)
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
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
;
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
;
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
;
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
);
1938 /****************************************************************************
1940 ****************************************************************************/
1941 static void img_destroy(struct img
*pimg
)
1944 /* do not free pimg->def */
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
);
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
)) {
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
)
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
,
2019 enum imagetool tool
= pimg
->def
->tool
;
2020 const struct toolkit
*toolkit
= img_toolkit_get(tool
);
2024 MAPIMG_LOG(_("toolkit not defined"));
2028 if (!path_is_absolute(mapimgfile
) && path
!= NULL
) {
2031 sz_strlcpy(tmpname
, path
);
2032 if (tmpname
[0] != '\0') {
2033 sz_strlcat(tmpname
, "/");
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
2054 [+IMG_BORDER_HEIGHT]
2057 space (only if count(displayed players) > 0)
2058 [+IMG_SPACER_HEIGHT]
2059 player line (only if count(displayed players) > 0)
2062 [+IMG_SPACER_HEIGHT]
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
;
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"));
2093 PixelWand
**pmw
, *pw
;
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
);
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
);
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
);
2139 for (y
= 0; y
< IMG_TEXT_HEIGHT
; y
++) {
2140 pmw
= PixelGetNextIteratorRow(imw
, &plr_color_square
);
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
,
2159 for (y
= 0; y
< IMG_LINE_HEIGHT
; y
++) {
2160 pmw
= PixelGetNextIteratorRow(imw
, &map_width
);
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
) {
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:
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 * ###### # # # ######
2185 * ###### # # # ######
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
2217 + (withplr
? (IMG_LINE_HEIGHT
+ IMG_SPACER_HEIGHT
)
2218 : 0), map_width
, map_height
);
2220 for (y
= 0; y
< pimg
->imgsize
.y
; y
++) {
2222 for (yyy
= 0; yyy
< pimg
->def
->zoom
; yyy
++) {
2224 pmw
= PixelGetNextIteratorRow(imw
, &map_width
);
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
);
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",
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
))) {
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
);
2264 log_verbose("Map image saved as '%s'.", imagefile
);
2267 DestroyDrawingWand(dw
);
2268 DestroyPixelWand(pw
);
2269 DestroyMagickWand(mw
);
2271 MagickWandTerminus();
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
];
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 "
2294 if (!img_filename(mapimgfile
, IMGFORMAT_PPM
, ppmname
, sizeof(ppmname
))) {
2295 MAPIMG_LOG(_("error generating the file name"));
2299 fp
= fopen(ppmname
, "w");
2301 MAPIMG_LOG(_("could not open file: %s"), ppmname
);
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
))) {
2317 pcolor
= imgcolor_player(player_index(pplayer
));
2318 fprintf(fp
, "# %s\n", img_playerstr(pplayer
));
2319 } players_iterate_end
;
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");
2329 for (y
= 0; y
< pimg
->imgsize
.y
; y
++) {
2331 for (yyy
= 0; yyy
< pimg
->def
->zoom
; yyy
++) {
2333 for (x
= 0; x
< pimg
->imgsize
.x
; x
++) {
2334 mindex
= img_index(x
, y
, pimg
);
2335 pcolor
= pimg
->map
[mindex
];
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
);
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
));
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
));
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
;
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(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
))) {
2406 tile_knowledge
= mapimg
.mapimg_tile_known(ptile
, pplayer
,
2410 } players_iterate_end
;
2414 if (plr_knowledge
&& pplayer
!= NULL
&& tile_knowledge
== TILE_UNKNOWN
) {
2415 /* plot nothing iff tile is not known */
2420 pterrain
= mapimg
.mapimg_tile_terrain(ptile
, pplayer
, plr_knowledge
);
2421 if (pimg
->def
->layers
[MAPIMG_LAYER_TERRAIN
]) {
2423 pixel
= pimg
->pixel_tile(ptile
, pplayer
, plr_knowledge
);
2424 pcolor
= imgcolor_terrain(pterrain
);
2425 img_plot_tile(pimg
, ptile
, pcolor
, pixel
);
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
);
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
]
2485 && tile_knowledge
== TILE_KNOWN_UNSEEN
) {
2486 pixel
= pimg
->pixel_fogofwar(ptile
, pplayer
, plr_knowledge
);
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
2507 /****************************************************************************
2514 ****************************************************************************/
2515 static bv_pixel
pixel_tile_rect(const struct tile
*ptile
,
2516 const struct player
*pplayer
,
2526 /****************************************************************************
2533 ****************************************************************************/
2534 static bv_pixel
pixel_city_rect(const struct tile
*ptile
,
2535 const struct player
*pplayer
,
2562 /****************************************************************************
2569 ****************************************************************************/
2570 static bv_pixel
pixel_unit_rect(const struct tile
*ptile
,
2571 const struct player
*pplayer
,
2585 /****************************************************************************
2592 ****************************************************************************/
2593 static bv_pixel
pixel_fogofwar_rect(const struct tile
*ptile
,
2594 const struct player
*pplayer
,
2623 /****************************************************************************
2628 [W] 12 -- -- -- -- 17 [E]
2634 ****************************************************************************/
2635 static bv_pixel
pixel_border_rect(const struct tile
*ptile
,
2636 const struct player
*pplayer
,
2641 struct player
*owner
;
2645 fc_assert_ret_val(ptile
!= NULL
, pixel
);
2647 if (NULL
== ptile
) {
2652 owner
= mapimg
.mapimg_tile_owner(ptile
, pplayer
, knowledge
);
2653 if (NULL
== owner
) {
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
)) {
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
)) {
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
)) {
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
)) {
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
,
2719 *base_x
= x
* TILE_SIZE
;
2720 *base_y
= y
* TILE_SIZE
;
2723 /****************************************************************************
2732 ****************************************************************************/
2733 static bv_pixel
pixel_tile_hexa(const struct tile
*ptile
,
2734 const struct player
*pplayer
,
2744 /****************************************************************************
2753 ****************************************************************************/
2754 static bv_pixel
pixel_city_hexa(const struct tile
*ptile
,
2755 const struct player
*pplayer
,
2785 /****************************************************************************
2794 ****************************************************************************/
2795 static bv_pixel
pixel_unit_hexa(const struct tile
*ptile
,
2796 const struct player
*pplayer
,
2810 /****************************************************************************
2819 ****************************************************************************/
2820 static bv_pixel
pixel_fogofwar_hexa(const struct tile
*ptile
,
2821 const struct player
*pplayer
,
2849 /****************************************************************************
2853 [SW] 12 -- -- -- -- 17 [NE]
2858 ****************************************************************************/
2859 static bv_pixel
pixel_border_hexa(const struct tile
*ptile
,
2860 const struct player
*pplayer
,
2865 struct player
*owner
;
2869 fc_assert_ret_val(ptile
!= NULL
, pixel
);
2871 if (NULL
== ptile
) {
2876 owner
= mapimg
.mapimg_tile_owner(ptile
, pplayer
, knowledge
);
2877 if (NULL
== owner
) {
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
)) {
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
)) {
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
)) {
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
)) {
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
)) {
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
)) {
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
,
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 /****************************************************************************
2967 10 11 12 13 14 15 16 17
2968 18 19 20 21 22 23 24 25
2971 ****************************************************************************/
2972 static bv_pixel
pixel_tile_isohexa(const struct tile
*ptile
,
2973 const struct player
*pplayer
,
2983 /****************************************************************************
2986 -- 11 12 13 14 15 16 --
2987 -- 19 20 21 22 23 24 --
2990 ****************************************************************************/
2991 static bv_pixel
pixel_city_isohexa(const struct tile
*ptile
,
2992 const struct player
*pplayer
,
3022 /****************************************************************************
3025 -- -- -- 13 14 -- -- --
3026 -- -- -- 21 22 -- -- --
3029 ****************************************************************************/
3030 static bv_pixel
pixel_unit_isohexa(const struct tile
*ptile
,
3031 const struct player
*pplayer
,
3045 /****************************************************************************
3048 -- -- 12 13 -- -- 16 17
3049 18 19 -- -- 22 23 -- --
3052 ****************************************************************************/
3053 static bv_pixel
pixel_fogofwar_isohexa(const struct tile
*ptile
,
3054 const struct player
*pplayer
,
3082 /****************************************************************************
3088 10 -- -- -- -- -- -- 17
3089 18 -- -- -- -- -- -- 25
3091 [W] 32 33 34 35 [SE]
3094 ****************************************************************************/
3095 static bv_pixel
pixel_border_isohexa(const struct tile
*ptile
,
3096 const struct player
*pplayer
,
3101 struct player
*owner
;
3105 fc_assert_ret_val(ptile
!= NULL
, pixel
);
3107 if (NULL
== ptile
) {
3112 owner
= mapimg
.mapimg_tile_owner(ptile
, pplayer
, knowledge
);
3113 if (NULL
== owner
) {
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
)) {
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
)) {
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
)) {
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
)) {
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
)) {
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
)) {
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
,
3193 /* magic for iso-hexa */
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];
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
)) {
3223 for (; i
>= 0; i
--) {
3224 buf
[i
] = BV_ISSET(plrbv
, i
) ? '1' : '0';
3230 /****************************************************************************
3231 Return the number of players defined in a map image definition.
3232 ****************************************************************************/
3233 static int bvplayers_count(const struct mapdef
*pmapdef
)
3237 switch (pmapdef
->player
.show
) {
3238 case SHOW_NONE
: /* no player on the map */
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 */
3247 case SHOW_PLRBV
: /* map showing only players given by a bitvector */
3249 for (i
= 0; i
< MAX_NUM_PLAYER_SLOTS
; i
++) {
3250 if (BV_ISSET(pmapdef
->player
.plrbv
, i
)) {
3255 case SHOW_ALL
: /* show all players in one map */
3256 count
= player_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
),
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
;