Freeciv-3.4
Loading...
Searching...
No Matches
mapimg.c
Go to the documentation of this file.
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.
7
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****************************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdarg.h>
19
20#ifdef HAVE_MAPIMG_MAGICKWAND
21#ifdef FREECIV_MWAND7
22 #include <MagickWand/MagickWand.h>
23#else /* FREECIV_MWAND7 */
24 #include <wand/MagickWand.h>
25#endif /* FREECIV_MWAND7 */
26#endif /* HAVE_MAPIMG_MAGICKWAND */
27
28/* utility */
29#include "astring.h"
30#include "bitvector.h"
31#include "fc_cmdline.h"
32#include "fcintl.h"
33#include "log.h"
34#include "mem.h"
35#include "string_vector.h"
36#include "timing.h"
37
38/* common */
39#include "calendar.h"
40#include "connection.h"
41#include "fc_types.h"
42#include "game.h"
43#include "map.h"
44#include "rgbcolor.h"
45#include "terrain.h"
46#include "tile.h"
47#include "version.h"
48#include "player.h"
49
50#include "mapimg.h"
51
52/* Some magick for ImageMagick - the interface has changed:
53 ImageMagick-6.6.2-0: PixelGetNextIteratorRow(..., unsigned long *)
54 ImageMagick-6.6.2-1: PixelGetNextIteratorRow(..., size_t *)
55 Theoretically, "unsigned long" and "size_t" are pretty much the same but
56 in practice the compiler will complain bitterly.
57 (from Gem-0.93 ImageMAGICK plugin) */
58#ifndef MagickLibInterface
59# define MagickLibInterface 0
60#endif
61#ifndef MagickLibVersion
62# define MagickLibVersion 0
63#endif
64
65/* This won't catch ImageMagick>=6.6.2-0.
66 Another workaround: compile with "-fpermissive" */
67#if (MagickLibInterface > 3) || (MagickLibVersion >= 0x662)
68# define magickwand_size_t size_t
69#else
70# define magickwand_size_t unsigned long
71#endif
72
73/* == image colors == */
81
82static const struct rgbcolor *imgcolor_special(enum img_special imgcolor);
83static const struct rgbcolor *imgcolor_player(int plr_id);
84static const struct rgbcolor
85 *imgcolor_terrain(const struct terrain *pterrain);
86
87/* == topologies == */
88#define TILE_SIZE 6
89#define NUM_PIXEL TILE_SIZE * TILE_SIZE
90
92
93struct tile_shape {
96};
97
98struct img;
99
100typedef bv_pixel (*plot_func)(const struct tile *ptile,
101 const struct player *pplayer,
102 bool knowledge);
103typedef void (*base_coor_func)(struct img *pimg, int *base_x, int *base_y,
104 int x, int y);
105
106/* (isometric) rectangular topology */
107static struct tile_shape tile_rect = {
108 .x = {
109 0, 1, 2, 3, 4, 5,
110 0, 1, 2, 3, 4, 5,
111 0, 1, 2, 3, 4, 5,
112 0, 1, 2, 3, 4, 5,
113 0, 1, 2, 3, 4, 5,
114 0, 1, 2, 3, 4, 5
115 },
116 .y = {
117 0, 0, 0, 0, 0, 0,
118 1, 1, 1, 1, 1, 1,
119 2, 2, 2, 2, 2, 2,
120 3, 3, 3, 3, 3, 3,
121 4, 4, 4, 4, 4, 4,
122 5, 5, 5, 5, 5, 5
123 }
124};
125
126static bv_pixel pixel_tile_rect(const struct tile *ptile,
127 const struct player *pplayer,
128 bool knowledge);
129static bv_pixel pixel_city_rect(const struct tile *ptile,
130 const struct player *pplayer,
131 bool knowledge);
132static bv_pixel pixel_unit_rect(const struct tile *ptile,
133 const struct player *pplayer,
134 bool knowledge);
135static bv_pixel pixel_fogofwar_rect(const struct tile *ptile,
136 const struct player *pplayer,
137 bool knowledge);
138static bv_pixel pixel_border_rect(const struct tile *ptile,
139 const struct player *pplayer,
140 bool knowledge);
141static void base_coor_rect(struct img *pimg, int *base_x, int *base_y,
142 int x, int y);
143
144/* hexa topology */
145static struct tile_shape tile_hexa = {
146 .x = {
147 2, 3,
148 1, 2, 3, 4,
149 0, 1, 2, 3, 4, 5,
150 0, 1, 2, 3, 4, 5,
151 0, 1, 2, 3, 4, 5,
152 0, 1, 2, 3, 4, 5,
153 1, 2, 3, 4,
154 2, 3,
155 },
156 .y = {
157 0, 0,
158 1, 1, 1, 1,
159 2, 2, 2, 2, 2, 2,
160 3, 3, 3, 3, 3, 3,
161 4, 4, 4, 4, 4, 4,
162 5, 5, 5, 5, 5, 5,
163 6, 6, 6, 6,
164 7, 7,
165 }
166};
167
168static bv_pixel pixel_tile_hexa(const struct tile *ptile,
169 const struct player *pplayer,
170 bool knowledge);
171static bv_pixel pixel_city_hexa(const struct tile *ptile,
172 const struct player *pplayer,
173 bool knowledge);
174static bv_pixel pixel_unit_hexa(const struct tile *ptile,
175 const struct player *pplayer,
176 bool knowledge);
177static bv_pixel pixel_fogofwar_hexa(const struct tile *ptile,
178 const struct player *pplayer,
179 bool knowledge);
180static bv_pixel pixel_border_hexa(const struct tile *ptile,
181 const struct player *pplayer,
182 bool knowledge);
183static void base_coor_hexa(struct img *pimg, int *base_x, int *base_y,
184 int x, int y);
185
186/* isometric hexa topology */
187static struct tile_shape tile_isohexa = {
188 .x = {
189 2, 3, 4, 5,
190 1, 2, 3, 4, 5, 6,
191 0, 1, 2, 3, 4, 5, 6, 7,
192 0, 1, 2, 3, 4, 5, 6, 7,
193 1, 2, 3, 4, 5, 6,
194 2, 3, 4, 5
195 },
196 .y = {
197 0, 0, 0, 0,
198 1, 1, 1, 1, 1, 1,
199 2, 2, 2, 2, 2, 2, 2, 2,
200 3, 3, 3, 3, 3, 3, 3, 3,
201 4, 4, 4, 4, 4, 4,
202 5, 5, 5, 5
203 }
204};
205
206static bv_pixel pixel_tile_isohexa(const struct tile *ptile,
207 const struct player *pplayer,
208 bool knowledge);
209static bv_pixel pixel_city_isohexa(const struct tile *ptile,
210 const struct player *pplayer,
211 bool knowledge);
212static bv_pixel pixel_unit_isohexa(const struct tile *ptile,
213 const struct player *pplayer,
214 bool knowledge);
215static bv_pixel pixel_fogofwar_isohexa(const struct tile *ptile,
216 const struct player *pplayer,
217 bool knowledge);
218static bv_pixel pixel_border_isohexa(const struct tile *ptile,
219 const struct player *pplayer,
220 bool knowledge);
221static void base_coor_isohexa(struct img *pimg, int *base_x, int *base_y,
222 int x, int y);
223
224/* == map images == */
225
226#define ARG_PLRBV "plrbv"
227#define ARG_PLRID "plrid"
228#define ARG_PLRNAME "plrname"
229
230/* mapimg definition */
231#define SPECENUM_NAME mapdef_arg
232#define SPECENUM_VALUE0 MAPDEF_FORMAT
233#define SPECENUM_VALUE0NAME "format"
234#define SPECENUM_VALUE1 MAPDEF_MAP
235#define SPECENUM_VALUE1NAME "map"
236#define SPECENUM_VALUE2 MAPDEF_PLRBV
237#define SPECENUM_VALUE2NAME ARG_PLRBV
238#define SPECENUM_VALUE3 MAPDEF_PLRID
239#define SPECENUM_VALUE3NAME ARG_PLRID
240#define SPECENUM_VALUE4 MAPDEF_PLRNAME
241#define SPECENUM_VALUE4NAME ARG_PLRNAME
242#define SPECENUM_VALUE5 MAPDEF_SHOW
243#define SPECENUM_VALUE5NAME "show"
244#define SPECENUM_VALUE6 MAPDEF_TURNS
245#define SPECENUM_VALUE6NAME "turns"
246#define SPECENUM_VALUE7 MAPDEF_ZOOM
247#define SPECENUM_VALUE7NAME "zoom"
248#define SPECENUM_COUNT MAPDEF_COUNT
249#include "specenum_gen.h"
250
252
253/* image format */
254#define SPECENUM_NAME imageformat
255#define SPECENUM_BITWISE
256#define SPECENUM_VALUE0 IMGFORMAT_GIF
257#define SPECENUM_VALUE0NAME "gif"
258#define SPECENUM_VALUE1 IMGFORMAT_PNG
259#define SPECENUM_VALUE1NAME "png"
260#define SPECENUM_VALUE2 IMGFORMAT_PPM
261#define SPECENUM_VALUE2NAME "ppm"
262#define SPECENUM_VALUE3 IMGFORMAT_JPG
263#define SPECENUM_VALUE3NAME "jpg"
264#include "specenum_gen.h"
265
266/* image format */
267#define SPECENUM_NAME imagetool
268#define SPECENUM_VALUE0 IMGTOOL_PPM
269#define SPECENUM_VALUE0NAME "ppm"
270#define SPECENUM_VALUE1 IMGTOOL_MAGICKWAND
271#define SPECENUM_VALUE1NAME "magick"
272#include "specenum_gen.h"
273
274/* player definitions */
275#define SPECENUM_NAME show_player
276#define SPECENUM_VALUE0 SHOW_NONE
277#define SPECENUM_VALUE0NAME "none"
278#define SPECENUM_VALUE1 SHOW_EACH
279#define SPECENUM_VALUE1NAME "each"
280#define SPECENUM_VALUE2 SHOW_HUMAN
281#define SPECENUM_VALUE2NAME "human"
282#define SPECENUM_VALUE3 SHOW_ALL
283#define SPECENUM_VALUE3NAME "all"
284/* should be identical to MAPDEF_PLRNAME */
285#define SPECENUM_VALUE4 SHOW_PLRNAME
286#define SPECENUM_VALUE4NAME ARG_PLRNAME
287/* should be identical to MAPDEF_PLRID */
288#define SPECENUM_VALUE5 SHOW_PLRID
289#define SPECENUM_VALUE5NAME ARG_PLRID
290/* should be identical to MAPDEF_PLRBV */
291#define SPECENUM_VALUE6 SHOW_PLRBV
292#define SPECENUM_VALUE6NAME ARG_PLRBV
293#include "specenum_gen.h"
294
295#undef ARG_PLRBV
296#undef ARG_PLRID
297#undef ARG_PLRNAME
298
299/* map definition status */
300#define SPECENUM_NAME mapimg_status
301#define SPECENUM_VALUE0 MAPIMG_STATUS_UNKNOWN
302#define SPECENUM_VALUE0NAME _("not checked")
303#define SPECENUM_VALUE1 MAPIMG_STATUS_OK
304#define SPECENUM_VALUE1NAME _("OK")
305#define SPECENUM_VALUE2 MAPIMG_STATUS_ERROR
306#define SPECENUM_VALUE2NAME _("error")
307#include "specenum_gen.h"
308
309#define MAX_LEN_MAPARG MAX_LEN_MAPDEF
310#define MAX_NUM_MAPIMG 10
311
312static bool mapimg_test(int id);
313static bool mapimg_define_arg(struct mapdef *pmapdef, enum mapdef_arg arg,
314 const char *val, bool check);
315static bool mapimg_def2str(struct mapdef *pmapdef, char *str, size_t str_len);
316static bool mapimg_checkplayers(struct mapdef *pmapdef, bool recheck);
317static char *mapimg_generate_name(struct mapdef *pmapdef);
318
319/* == map definition == */
320struct mapdef {
326 int zoom;
327 int turns;
329 struct {
331 union {
332 char name[MAX_LEN_NAME]; /* used by SHOW_PLRNAME */
333 int id; /* used by SHOW_PLRID */
334 bv_player plrbv; /* used by SHOW_PLRBV */
335 };
336 bv_player checked_plrbv; /* player bitvector used for the image
337 * creation */
339
342};
343
344static struct mapdef *mapdef_new(bool colortest);
345static void mapdef_destroy(struct mapdef *pmapdef);
346
347/* List of map definitions. */
348#define SPECLIST_TAG mapdef
349#define SPECLIST_TYPE struct mapdef
350#include "speclist.h"
351
352#define mapdef_list_iterate(mapdef_list, pmapdef) \
353 TYPED_LIST_ITERATE(struct mapdef, mapdef_list, pmapdef)
354#define mapdef_list_iterate_end \
355 LIST_ITERATE_END
356
357/* == images == */
358struct mapdef;
359
360/* Some lengths used for the images created by the magickwand toolkit. */
361#define IMG_BORDER_HEIGHT 5
362#define IMG_BORDER_WIDTH IMG_BORDER_HEIGHT
363#define IMG_SPACER_HEIGHT 5
364#define IMG_LINE_HEIGHT 5
365#define IMG_TEXT_HEIGHT 12
366
367struct img {
368 struct mapdef *def; /* map definition */
369 int turn; /* save turn */
371
372 /* topology definition */
380
381 struct {
382 int x;
383 int y;
384 } mapsize; /* map size */
385 struct {
386 int x;
387 int y;
388 } imgsize; /* image size */
389 const struct rgbcolor **map;
390};
391
392static struct img *img_new(struct mapdef *mapdef, int topo, int wrap,
393 int xsize, int ysize);
394static void img_destroy(struct img *pimg);
395static inline void img_set_pixel(struct img *pimg, const int mindex,
396 const struct rgbcolor *pcolor);
397static inline int img_index(const int x, const int y,
398 const struct img *pimg);
399static const char *img_playerstr(const struct player *pplayer);
400static void img_plot(struct img *pimg, int x, int y,
401 const struct rgbcolor *pcolor, const bv_pixel pixel);
402static void img_plot_tile(struct img *pimg, const struct tile *ptile,
403 const struct rgbcolor *pcolor, const bv_pixel pixel);
404static bool img_save(const struct img *pimg, const char *mapimgfile,
405 const char *path);
406static bool img_save_ppm(const struct img *pimg, const char *mapimgfile);
407#ifdef HAVE_MAPIMG_MAGICKWAND
408static bool img_save_magickwand(const struct img *pimg,
409 const char *mapimgfile);
410#endif /* HAVE_MAPIMG_MAGICKWAND */
411static bool img_filename(const char *mapimgfile, enum imageformat format,
412 char *filename, size_t filename_len);
413static void img_createmap(struct img *pimg);
414
415/* == image toolkits == */
416typedef bool (*img_save_func)(const struct img *pimg,
417 const char *mapimgfile);
418
426
427#define GEN_TOOLKIT(_tool, _format_default, _formats, _save_func, _help) \
428 {_tool, _format_default, _formats, _save_func, _help},
429
430static struct toolkit img_toolkits[] = {
433 N_("Standard ppm files"))
434#ifdef HAVE_MAPIMG_MAGICKWAND
438 N_("ImageMagick"))
439#endif /* HAVE_MAPIMG_MAGICKWAND */
440};
441
443
444#ifdef HAVE_MAPIMG_MAGICKWAND
445 #define MAPIMG_DEFAULT_IMGFORMAT IMGFORMAT_GIF
446 #define MAPIMG_DEFAULT_IMGTOOL IMGTOOL_MAGICKWAND
447#else
448 #define MAPIMG_DEFAULT_IMGFORMAT IMGFORMAT_PPM
449 #define MAPIMG_DEFAULT_IMGTOOL IMGTOOL_PPM
450#endif /* HAVE_MAPIMG_MAGICKWAND */
451
452static const struct toolkit *img_toolkit_get(enum imagetool tool);
453
454#define img_toolkit_iterate(_toolkit) \
455 { \
456 int _i; \
457 for (_i = 0; _i < img_toolkits_count; _i++) { \
458 const struct toolkit *_toolkit = &img_toolkits[_i];
459
460#define img_toolkit_iterate_end \
461 } \
462 }
463
464/* == logging == */
465#define MAX_LEN_ERRORBUF 1024
466
467static char error_buffer[MAX_LEN_ERRORBUF] = "\0";
468static void mapimg_log(const char *file, const char *function, int line,
469 const char *format, ...)
471#define MAPIMG_LOG(format, ...) \
472 mapimg_log(__FILE__, __FUNCTION__, __FC_LINE__, format, ## __VA_ARGS__)
473#define MAPIMG_ASSERT_RET_VAL(cond, expr) \
474 fc_assert_action(cond, MAPIMG_LOG(_("internal error")); return (expr))
475
476/* == additional functions == */
477
478static int bvplayers_count(const struct mapdef *pmapdef);
479static const char *bvplayers_str(const bv_player plrbv);
480
481/* == map images data == */
482static struct {
483 bool init;
485
493} mapimg = { .init = FALSE };
494
495/*
496 * ==============================================
497 * map images (external functions)
498 * ==============================================
499 */
500
501/************************************************************************/
537
538/************************************************************************/
541void mapimg_reset(void)
542{
543 if (!mapimg_initialised()) {
544 return;
545 }
546
547 if (mapdef_list_size(mapimg.mapdef) > 0) {
552 }
553}
554
555/************************************************************************/
558void mapimg_free(void)
559{
560 if (!mapimg_initialised()) {
561 return;
562 }
563
564 mapimg_reset();
566
567 mapimg.init = FALSE;
568}
569
570/************************************************************************/
574{
575 if (!mapimg_initialised()) {
576 return 0;
577 }
578
579 return mapdef_list_size(mapimg.mapdef);
580}
581
582/************************************************************************/
585static const char *showname_help(enum show_player showplr)
586{
587 switch (showplr) {
588 case SHOW_NONE: return _("no players, only terrain");
589 case SHOW_EACH: return _("one image per player");
590 case SHOW_HUMAN: return _("one image per human player");
591 case SHOW_ALL: return _("all players on a single image");
592 case SHOW_PLRNAME: return _("just the player named with 'plrname'");
593 case SHOW_PLRID: return _("just the player specified with 'plrid'");
594 case SHOW_PLRBV: return _("one image per player in 'plrbv'");
595 }
596 fc_assert(0);
597 return "";
598}
599
600/************************************************************************/
603char *mapimg_help(const char *cmdname)
604{
605 enum imagetool tool;
606 enum show_player showplr;
607 enum mapimg_layer layer;
610 struct mapdef *pmapdef = mapdef_new(FALSE);
611 static struct astring help = ASTRING_INIT;
612
613 if (astr_len(&help) > 0) {
614 /* Help text was created already. */
615 return fc_strdup(astr_str(&help));
616 }
617
618 /* Possible 'format' settings (toolkit + format). */
619 for (tool = imagetool_begin(); tool != imagetool_end();
620 tool = imagetool_next(tool)) {
621 enum imageformat format;
622 const struct toolkit *toolkit = img_toolkit_get(tool);
623 const char *separator = "";
624
625 if (!toolkit) {
626 continue;
627 }
628
629 astr_add(&str_format, " - '%s': ", imagetool_name(tool));
630
631 for (format = imageformat_begin(); format != imageformat_end();
632 format = imageformat_next(format)) {
633 if (toolkit->formats & format) {
634 const char *name = imageformat_name(format);
635
636 if (name != nullptr) {
637 astr_add(&str_format, "%s'%s'", separator, name);
638 separator = ", ";
639 }
640 }
641 }
642
643 if (tool != imagetool_max()) {
644 astr_add(&str_format, "\n");
645 }
646 }
647
648 /* Possible 'show' settings. */
651 const char *nameptr = show_player_name(showplr);
652
653 if (nameptr != nullptr) {
654 char name[10];
655
656 fc_snprintf(name, sizeof(name), "'%s'", nameptr);
657 astr_add(&str_showplr, " - %-9s %s", name, showname_help(showplr));
658 if (showplr != show_player_max()) {
659 astr_add(&str_showplr, "\n");
660 }
661 }
662 }
663
664 /* Default values. */
667 "(%s|%s)", imagetool_name(pmapdef->tool),
668 imageformat_name(pmapdef->format));
671 "(%s)", show_player_name(pmapdef->player.show));
673 astr_set(&defaults[MAPDEF_TURNS], "(%d)", pmapdef->turns);
675 astr_set(&defaults[MAPDEF_ZOOM], "(%d)", pmapdef->zoom);
676
679 for (layer = mapimg_layer_begin(); layer != mapimg_layer_end();
680 layer = mapimg_layer_next(layer)) {
681 if (pmapdef->layers[layer]) {
682 astr_add(&defaults[MAPDEF_MAP], "%c", mapimg_layer_name(layer)[0]);
683 }
684 }
686
687 /* help text */
688 astr_set(&help,
689 /* TRANS: This is help for a server command, so keywords like
690 * "define" in the first column are server keywords that must not
691 * be translated. Do not translate keywords in single quotes, but
692 * strings in <angle brackets> should be translated. */
693 _("This command controls the creation of map images. Supported "
694 "arguments:\n"
695 " define <mapdef> - define a map image; returns numeric <id>\n"
696 " show <id>|all - list map image definitions or show a specific one\n"
697 " create <id>|all - manually save image(s) for current map state\n"
698 " delete <id>|all - delete map image definition(s)\n"
699 " colortest - create test image(s) showing all colors\n"
700 "\n"
701 "Multiple definitions can be active at once. "
702 "A definition <mapdef> consists of colon-separated options:\n"
703 "\n"
704 "option (default) description\n"
705 "\n"
706 "format=<[tool|]format> %-10s file format\n"
707 "show=<show> %-10s which players to show\n"
708 " plrname=<name> player name\n"
709 " plrid=<id> numeric player id\n"
710 " plrbv=<bit vector> see example; first char = id 0\n"
711 "turns=<turns> %-10s save image each <turns> turns\n"
712 " (0=no autosave, save with 'create')\n"
713 "zoom=<zoom> %-10s magnification factor (1-5)\n"
714 "map=<map> %-10s which map layers to draw\n"
715 "\n"
716 "<[tool|]format> = use image format <format>, optionally specifying "
717 "toolkit <tool>. The following toolkits and formats are compiled in:\n"
718 "%s\n"
719 "\n"
720 "<show> determines which players are represented and how many "
721 "images are saved by this definition:\n"
722 "%s\n"
723 "\n"
724 "<map> can contain one or more of the following layers:\n"
725 " - 'a' show area within borders of specified players\n"
726 " - 'b' show borders of specified players\n"
727 " - 'c' show cities of specified players\n"
728 " - 'f' show fog of war (single-player images only)\n"
729 " - 'k' show only player knowledge (single-player images only)\n"
730 " - 't' full display of terrain types\n"
731 " - 'u' show units of specified players\n"
732 "\n"
733 "Examples of <mapdef>:\n"
734 " 'zoom=1:map=tcub:show=all:format=ppm|ppm'\n"
735 " 'zoom=2:map=tcub:show=each:format=png'\n"
736 " 'zoom=1:map=tcub:show=plrname:plrname=Otto:format=gif'\n"
737 " 'zoom=3:map=cu:show=plrbv:plrbv=010011:format=jpg'\n"
738 " 'zoom=1:map=t:show=none:format=magick|jpg'"),
743
752
753 return fc_strdup(astr_str(&help));
754}
755
756/************************************************************************/
759const char *mapimg_error(void)
760{
761 return error_buffer;
762}
763
764/************************************************************************/
767#define NUM_MAX_MAPARGS 10
768#define NUM_MAX_MAPOPTS 2
769bool mapimg_define(const char *maparg, bool check)
770{
771 struct mapdef *pmapdef = nullptr;
773 int nmapargs, nmapopts, i;
774 bool ret = TRUE;
775 int count;
776
778
779 if (maparg == nullptr) {
780 MAPIMG_LOG(_("no map definition"));
781 return FALSE;
782 }
783
785 /* Too long map definition string */
786 MAPIMG_LOG(_("map definition string too long (max %d characters)"),
788 return FALSE;
789 }
790
791 count = mapimg_count();
792 if (count == MAX_NUM_MAPIMG) {
793 MAPIMG_LOG(_("maximum number of map definitions reached (%d)"),
795 return FALSE;
796 }
797
798 for (i = 0; i < count; i++) {
799 pmapdef = mapdef_list_get(mapimg.mapdef, i);
800 if (0 == fc_strcasecmp(pmapdef->maparg, maparg)) {
801 MAPIMG_LOG(_("duplicate of map image definition %d ('%s')"), i,
802 maparg);
803 return FALSE;
804 }
805 }
806
808
809 /* Get map options */
811
812 for (i = 0; i < nmapargs; i++) {
813 /* Split map options into variable and value */
815
816 if (nmapopts == 2) {
818
819 if (mapdef_arg_is_valid(arg)) {
820 /* If ret is FALSE an error message is set by mapimg_define_arg(). */
822 } else {
823 MAPIMG_LOG(_("unknown map option: '%s'"), mapargs[i]);
824 ret = FALSE;
825 }
826 } else {
827 MAPIMG_LOG(_("unknown map option: '%s'"), mapargs[i]);
828 ret = FALSE;
829 }
830
832
833 if (!ret) {
834 break;
835 }
836 }
838
839 /* sanity check */
840 switch (pmapdef->player.show) {
841 case SHOW_PLRNAME: /* display player given by name */
842 if (!BV_ISSET(pmapdef->args, MAPDEF_PLRNAME)) {
843 MAPIMG_LOG(_("'show=%s' but no player name 'plrname'"),
845 ret = FALSE;
846 }
847 break;
848 case SHOW_PLRID: /* display player given by id */
849 if (!BV_ISSET(pmapdef->args, MAPDEF_PLRID)) {
850 MAPIMG_LOG(_("'show=%s' but no player id 'plrid'"),
852 ret = FALSE;
853 }
854 break;
855 case SHOW_PLRBV: /* display players given by bitvector */
856 if (!BV_ISSET(pmapdef->args, MAPDEF_PLRBV)) {
857 MAPIMG_LOG(_("'show=%s' but no player bitvector 'plrbv'"),
859 ret = FALSE;
860 }
861 break;
862 case SHOW_NONE: /* no player on the map */
863 BV_CLR_ALL(pmapdef->player.checked_plrbv);
864 break;
865 case SHOW_ALL: /* show all players in one map */
866 BV_SET_ALL(pmapdef->player.checked_plrbv);
867 break;
868 case SHOW_EACH: /* one map for each player */
869 case SHOW_HUMAN: /* one map for each human player */
870 /* A loop for each player will be called at the time the image is
871 * created. */
872 BV_CLR_ALL(pmapdef->player.checked_plrbv);
873 break;
874 }
875
876 if (ret && !check) {
877 /* save map string */
879
880 /* add map definition */
882 } else {
884 }
885
886 return ret;
887}
888#undef NUM_MAX_MAPARGS
889#undef NUM_MAX_MAPOPTS
890
891/************************************************************************/
894#define NUM_MAX_FORMATARGS 2
895static bool mapimg_define_arg(struct mapdef *pmapdef, enum mapdef_arg arg,
896 const char *val, bool check)
897{
898 if (BV_ISSET(pmapdef->args, arg)) {
899 log_debug("Option '%s' for mapimg used more than once.",
900 mapdef_arg_name(arg));
901 }
902
903 /* This argument was used. */
904 BV_SET(pmapdef->args, arg);
905
906 switch (arg) {
907 case MAPDEF_FORMAT:
908 /* file format */
909 {
911 int nformatargs;
912 enum imageformat format;
913 enum imagetool tool;
914 bool error = TRUE;
915
916 /* get format options */
918
919 if (nformatargs == 2) {
922
924 const struct toolkit *toolkit = img_toolkit_get(tool);
925
926 if (toolkit && (toolkit->formats & format)) {
927 pmapdef->tool = tool;
928 pmapdef->format = format;
929
930 error = FALSE;
931 }
932 }
933 } else {
934 /* Only one argument to format. */
937 /* toolkit defined */
938 const struct toolkit *toolkit = img_toolkit_get(tool);
939
940 if (toolkit) {
941 pmapdef->tool = toolkit->tool;
942 pmapdef->format = toolkit->format_default;
943
944 error = FALSE;
945 }
946 } else {
948 if (imageformat_is_valid(format)) {
949 /* format defined */
951 if ((toolkit->formats & format)) {
952 pmapdef->tool = toolkit->tool;
953 pmapdef->format = toolkit->format_default;
954
955 error = FALSE;
956 break;
957 }
959 }
960 }
961 }
962
964
965 if (error) {
966 goto INVALID;
967 }
968 }
969 break;
970
971 case MAPDEF_MAP:
972 /* map definition */
973 {
974 int len = strlen(val), l;
975 enum mapimg_layer layer;
976 bool error;
977
978 for (layer = mapimg_layer_begin(); layer != mapimg_layer_end();
979 layer = mapimg_layer_next(layer)) {
980 pmapdef->layers[layer] = FALSE;
981 }
982
983 for (l = 0; l < len; l++) {
984 error = TRUE;
985 for (layer = mapimg_layer_begin(); layer != mapimg_layer_end();
986 layer = mapimg_layer_next(layer)) {
987 if (val[l] == mapimg_layer_name(layer)[0]) {
988 pmapdef->layers[layer] = TRUE;
989 error = FALSE;
990 break;
991 }
992 }
993
994 if (error) {
995 goto INVALID;
996 }
997 }
998 }
999 break;
1000
1001 case MAPDEF_PLRBV:
1002 /* player definition - bitvector */
1003 {
1004 int i;
1005
1006 if (strlen(val) < MAX_NUM_PLAYER_SLOTS + 1) {
1007 BV_CLR_ALL(pmapdef->player.plrbv);
1008 for (i = 0; i < strlen(val); i++) {
1009 if (!strchr("01", val[i])) {
1010 MAPIMG_LOG(_("invalid character in bitvector: '%c' (%s)"),
1011 val[i], val);
1012 return FALSE;
1013 } else if (val[i] == '1') {
1014 BV_SET(pmapdef->player.plrbv, i);
1015 }
1016 }
1017 } else {
1018 goto INVALID;
1019 }
1020 }
1021 break;
1022
1023 case MAPDEF_PLRID:
1024 /* player definition - player id; will be checked by mapimg_isvalid()
1025 * which calls mapimg_checkplayers() */
1026 {
1027 int plrid;
1028
1029 if (sscanf(val, "%d", &plrid) != 0) {
1031 MAPIMG_LOG(_("'plrid' should be between 0 and %d"),
1033 return FALSE;
1034 }
1035 pmapdef->player.id = plrid;
1036 } else {
1037 goto INVALID;
1038 }
1039 }
1040 break;
1041
1042 case MAPDEF_PLRNAME:
1043 /* player definition - player name; will be checked by mapimg_isvalid()
1044 * which calls mapimg_checkplayers() */
1045 {
1046 if (strlen(val) > sizeof(pmapdef->player.name)) {
1047 MAPIMG_LOG(_("player name too long: '%s' (max: %lu)"), val,
1048 (unsigned long) sizeof(pmapdef->player.name));
1049 return FALSE;
1050 } else {
1051 sz_strlcpy(pmapdef->player.name, val);
1052 }
1053 }
1054 break;
1055
1056 case MAPDEF_SHOW:
1057 /* player definition - basic definition */
1058 {
1059 enum show_player showplr;
1060
1063 pmapdef->player.show = showplr;
1064 } else {
1065 goto INVALID;
1066 }
1067 }
1068 break;
1069
1070 case MAPDEF_TURNS:
1071 /* save each <x> turns */
1072 {
1073 int turns;
1074
1075 if (sscanf(val, "%d", &turns) != 0) {
1076 if (turns < 0 || turns > 99) {
1077 MAPIMG_LOG(_("'turns' should be between 0 and 99"));
1078 return FALSE;
1079 } else {
1080 pmapdef->turns = turns;
1081 }
1082 } else {
1083 goto INVALID;
1084 }
1085 }
1086 break;
1087
1088 case MAPDEF_ZOOM:
1089 /* zoom factor */
1090 {
1091 int zoom;
1092
1093 if (sscanf(val, "%d", &zoom) != 0) {
1094 if (zoom < 1 || zoom > 5) {
1095 MAPIMG_LOG(_("'zoom' factor should be between 1 and 5"));
1096 return FALSE;
1097 } else {
1098 pmapdef->zoom = zoom;
1099 }
1100 } else {
1101 goto INVALID;
1102 }
1103 }
1104 break;
1105
1106 case MAPDEF_COUNT:
1108 break;
1109 }
1110
1111 return TRUE;
1112
1113 INVALID:
1114 MAPIMG_LOG(_("invalid value for option '%s': '%s'"),
1115 mapdef_arg_name(arg), val);
1116 return FALSE;
1117}
1118#undef NUM_MAX_FORMATARGS
1119
1120/************************************************************************/
1124struct mapdef *mapimg_isvalid(int id)
1125{
1126 struct mapdef *pmapdef = nullptr;
1127
1128 if (!mapimg_test(id)) {
1129 /* The error message is set in mapimg_test(). */
1130 return nullptr;
1131 }
1132
1133 pmapdef = mapdef_list_get(mapimg.mapdef, id);
1135
1136 switch (pmapdef->status) {
1138 MAPIMG_LOG(_("map definition not checked (game not started)"));
1139 return nullptr;
1141 MAPIMG_LOG(_("map definition deactivated: %s"), pmapdef->error);
1142 return nullptr;
1143 case MAPIMG_STATUS_OK:
1144 /* Nothing */
1145 break;
1146 }
1147
1148 return pmapdef;
1149}
1150
1151/************************************************************************/
1155{
1156 static struct strvec *format_list = nullptr;
1157
1158 if (format_list == nullptr) {
1159 enum imagetool tool;
1160
1162
1163 for (tool = imagetool_begin(); tool != imagetool_end();
1164 tool = imagetool_next(tool)) {
1165 enum imageformat format;
1166 const struct toolkit *toolkit = img_toolkit_get(tool);
1167
1168 if (!toolkit) {
1169 continue;
1170 }
1171
1172 for (format = imageformat_begin(); format != imageformat_end();
1173 format = imageformat_next(format)) {
1174 if (toolkit->formats & format) {
1175 char str_format[64];
1176
1177 fc_snprintf(str_format, sizeof(str_format), "%s|%s",
1180 }
1181 }
1182 }
1183 }
1184
1185 return format_list;
1186}
1187
1188/************************************************************************/
1192{
1193 static char default_format[64];
1194
1195 fc_snprintf(default_format, sizeof(default_format), "%s|%s",
1198
1199 return default_format;
1200}
1201
1202/************************************************************************/
1205bool mapimg_delete(int id)
1206{
1207 struct mapdef *pmapdef = nullptr;
1208
1209 if (!mapimg_test(id)) {
1210 /* The error message is set in mapimg_test(). */
1211 return FALSE;
1212 }
1213
1214 /* Delete map definition */
1215 pmapdef = mapdef_list_get(mapimg.mapdef, id);
1217
1218 return TRUE;
1219}
1220
1221/************************************************************************/
1224bool mapimg_show(int id, char *str, size_t str_len, bool detail)
1225{
1226 struct mapdef *pmapdef = nullptr;
1227
1228 if (!mapimg_test(id)) {
1229 /* The error message is set in mapimg_test(). */
1230 return FALSE;
1231 }
1232
1233 pmapdef = mapdef_list_get(mapimg.mapdef, id);
1234
1235 /* Clear string ... */
1237 str[0] = '\0';
1238
1239 if (detail) {
1240 cat_snprintf(str, str_len, _("Detailed information for map image "
1241 "definition %d\n"), id);
1242 if (pmapdef->status == MAPIMG_STATUS_ERROR) {
1243 cat_snprintf(str, str_len, _(" - status: %s (%s)\n"),
1244 mapimg_status_name(pmapdef->status), pmapdef->error);
1245 } else {
1246 cat_snprintf(str, str_len, _(" - status: %s\n"),
1247 mapimg_status_name(pmapdef->status));
1248 }
1249 cat_snprintf(str, str_len, _(" - file name string: %s\n"),
1251 cat_snprintf(str, str_len, _(" - image toolkit: %s\n"),
1252 imagetool_name(pmapdef->tool));
1253 cat_snprintf(str, str_len, _(" - image format: %s\n"),
1254 imageformat_name(pmapdef->format));
1255 cat_snprintf(str, str_len, _(" - zoom factor: %d\n"),
1256 pmapdef->zoom);
1257 cat_snprintf(str, str_len, _(" - show area within borders: %s\n"),
1258 pmapdef->layers[MAPIMG_LAYER_AREA] ? _("yes") : _("no"));
1259 cat_snprintf(str, str_len, _(" - show borders: %s\n"),
1260 pmapdef->layers[MAPIMG_LAYER_BORDERS] ? _("yes") : _("no"));
1261 cat_snprintf(str, str_len, _(" - show cities: %s\n"),
1262 pmapdef->layers[MAPIMG_LAYER_CITIES] ? _("yes") : _("no"));
1263 cat_snprintf(str, str_len, _(" - show fog of war: %s\n"),
1264 pmapdef->layers[MAPIMG_LAYER_FOGOFWAR] ? _("yes") : _("no"));
1265 cat_snprintf(str, str_len, _(" - show player knowledge: %s\n"),
1266 pmapdef->layers[MAPIMG_LAYER_KNOWLEDGE] ? _("yes") : _("no"));
1267 cat_snprintf(str, str_len, _(" - show terrain: %s\n"),
1268 pmapdef->layers[MAPIMG_LAYER_TERRAIN] ? _("full") :_("basic"));
1269 cat_snprintf(str, str_len, _(" - show units: %s\n"),
1270 pmapdef->layers[MAPIMG_LAYER_UNITS] ? _("yes") : _("no"));
1271 cat_snprintf(str, str_len, _(" - players included: %s"),
1272 show_player_name(pmapdef->player.show));
1273 switch (pmapdef->player.show) {
1274 case SHOW_NONE:
1275 case SHOW_HUMAN:
1276 case SHOW_EACH:
1277 case SHOW_ALL:
1278 /* nothing */
1279 break;
1280 case SHOW_PLRNAME:
1281 cat_snprintf(str, str_len, _("\n - player name: %s"),
1282 pmapdef->player.name);
1283 break;
1284 case SHOW_PLRID:
1285 cat_snprintf(str, str_len, _("\n - player id: %d"),
1286 pmapdef->player.id);
1287 break;
1288 case SHOW_PLRBV:
1289 cat_snprintf(str, str_len, _("\n - players: %s"),
1290 bvplayers_str(pmapdef->player.plrbv));
1291 break;
1292 }
1293 } else {
1294 char str_def[MAX_LEN_MAPDEF];
1296 if (pmapdef->status == MAPIMG_STATUS_ERROR) {
1297 cat_snprintf(str, str_len, "'%s' (%s: %s)", str_def,
1298 mapimg_status_name(pmapdef->status), pmapdef->error);
1299 } else {
1300 cat_snprintf(str, str_len, "'%s' (%s)", str_def,
1301 mapimg_status_name(pmapdef->status));
1302 }
1303 }
1304
1305 return TRUE;
1306}
1307
1308/************************************************************************/
1312bool mapimg_id2str(int id, char *str, size_t str_len)
1313{
1314 struct mapdef *pmapdef = nullptr;
1315
1316 if (!mapimg_test(id)) {
1317 /* The error message is set in mapimg_test(). */
1318 return FALSE;
1319 }
1320
1321 pmapdef = mapdef_list_get(mapimg.mapdef, id);
1322
1324}
1325
1326/************************************************************************/
1333bool mapimg_create(struct mapdef *pmapdef, bool force, const char *savename,
1334 const char *path)
1335{
1336 struct img *pimg;
1338 bool ret = TRUE;
1339#ifdef FREECIV_DEBUG
1340 struct timer *timer_cpu, *timer_user;
1341#endif
1342
1343 if (map_is_empty()) {
1344 MAPIMG_LOG(_("map not yet created"));
1345
1346 return FALSE;
1347 }
1348
1350
1351 if (pmapdef->status != MAPIMG_STATUS_OK) {
1352 MAPIMG_LOG(_("map definition not checked or error"));
1353 return FALSE;
1354 }
1355
1356 /* An image should be saved if:
1357 * - force is set to TRUE
1358 * - it is the first turn
1359 * - turns is set to a value not zero and the current turn can be devided
1360 * by this number */
1361 if (!force && game.info.turn != 1
1362 && !(pmapdef->turns != 0 && game.info.turn % pmapdef->turns == 0)) {
1363 return TRUE;
1364 }
1365
1366#ifdef FREECIV_DEBUG
1367 timer_cpu = timer_new(TIMER_CPU, TIMER_ACTIVE, "mapimg cpu");
1369 timer_user = timer_new(TIMER_USER, TIMER_ACTIVE, "mapimg user");
1371#endif /* FREECIV_DEBUG */
1372
1373 /* Create map */
1374 switch (pmapdef->player.show) {
1375 case SHOW_PLRNAME: /* display player given by name */
1376 case SHOW_PLRID: /* display player given by id */
1377 case SHOW_NONE: /* no player one the map */
1378 case SHOW_ALL: /* show all players in one map */
1379 case SHOW_PLRBV: /* display player(s) given by bitvector */
1382
1386 if (!img_save(pimg, mapimgfile, path)) {
1387 ret = FALSE;
1388 }
1390 break;
1391 case SHOW_EACH: /* one map for each player */
1392 case SHOW_HUMAN: /* one map for each human player */
1393 players_iterate(pplayer) {
1394 if (!pplayer->is_alive || (pmapdef->player.show == SHOW_HUMAN
1395 && !is_human(pplayer))) {
1396 /* no map image for dead players
1397 * or AI players if only human players should be shown */
1398 continue;
1399 }
1400
1401 BV_CLR_ALL(pmapdef->player.checked_plrbv);
1402 BV_SET(pmapdef->player.checked_plrbv, player_index(pplayer));
1403
1406
1410 if (!img_save(pimg, mapimgfile, path)) {
1411 ret = FALSE;
1412 }
1414
1415 if (!ret) {
1416 break;
1417 }
1419 break;
1420 }
1421
1422#ifdef FREECIV_DEBUG
1423 log_debug("Image generation time: %g seconds (%g apparent)",
1426
1429#endif /* FREECIV_DEBUG */
1430
1431 return ret;
1432}
1433
1434/************************************************************************/
1439bool mapimg_colortest(const char *savename, const char *path)
1440{
1441 struct img *pimg;
1442 const struct rgbcolor *pcolor;
1443 struct mapdef *pmapdef = mapdef_new(TRUE);
1446 int i, nat_x, nat_y;
1447 int max_playercolor = mapimg.mapimg_plrcolor_count();
1449 bool ret = TRUE;
1450 enum imagetool tool;
1451
1452#define SIZE_X 16
1453#define SIZE_Y 5
1454
1455 pimg = img_new(pmapdef, 0, 0, SIZE_X + 2,
1456 SIZE_Y * (max_playercolor / SIZE_X) + 2);
1457
1458 pixel = pimg->pixel_tile(nullptr, nullptr, FALSE);
1459
1461 for (i = 0; i < MAX(max_playercolor, max_terraincolor); i++) {
1462 nat_x = 1 + i % SIZE_X;
1463 nat_y = 1 + (i / SIZE_X) * SIZE_Y;
1464
1466 }
1467
1468 for (i = 0; i < MAX(max_playercolor, max_terraincolor); i++) {
1469 if (i >= max_playercolor) {
1470 break;
1471 }
1472
1473 nat_x = 1 + i % SIZE_X;
1474 nat_y = 2 + (i / SIZE_X) * SIZE_Y;
1475 pcolor = mapimg.mapimg_plrcolor_get(i);
1476
1478 }
1479
1481 for (i = 0; i < MAX(max_playercolor, max_terraincolor); i++) {
1482 nat_x = 1 + i % SIZE_X;
1483 nat_y = 3 + (i / SIZE_X) * SIZE_Y;
1484
1486 }
1487
1488 for (i = 0; i < MAX(max_playercolor, max_terraincolor); i++) {
1489 if (i >= max_terraincolor) {
1490 break;
1491 }
1492
1493 nat_x = 1 + i % SIZE_X;
1494 nat_y = 4 + (i / SIZE_X) * SIZE_Y;
1496
1498 }
1499
1500#undef SIZE_X
1501#undef SIZE_Y
1502
1503 for (tool = imagetool_begin(); tool != imagetool_end();
1505 enum imageformat format;
1506 const struct toolkit *toolkit = img_toolkit_get(tool);
1507
1508 if (!toolkit) {
1509 continue;
1510 }
1511
1512 /* Set the toolkit. */
1513 pmapdef->tool = tool;
1514
1515 for (format = imageformat_begin(); format != imageformat_end();
1516 format = imageformat_next(format)) {
1517 if (toolkit->formats & format) {
1518 char buf[128];
1519 const char *tname = imagetool_name(tool);
1520
1521 /* Set the image format. */
1522 pmapdef->format = format;
1523
1524 if (tname != nullptr) {
1525 fc_snprintf(buf, sizeof(buf), "colortest-%s", tname);
1526 } else {
1527 fc_snprintf(buf, sizeof(buf), "colortest");
1528 }
1529 /* filename for color test */
1531
1532 if (!img_save(pimg, mapimgfile, path)) {
1533 /* If one of the mapimg format/toolkit combination fail, return
1534 * FALSE, i.e. an error occurred. */
1535 ret = FALSE;
1536 }
1537 }
1538 }
1539 }
1540
1543
1544 return ret;
1545}
1546
1547/*
1548 * ==============================================
1549 * map images (internal functions)
1550 * ==============================================
1551 */
1552
1553/************************************************************************/
1557{
1558 return mapimg.init;
1559}
1560
1561/************************************************************************/
1565static bool mapimg_test(int id)
1566{
1568
1570 MAPIMG_LOG(_("no map definition with id %d"), id);
1571 return FALSE;
1572 }
1573
1574 return TRUE;
1575}
1576
1577/************************************************************************/
1580static bool mapimg_def2str(struct mapdef *pmapdef, char *str, size_t str_len)
1581{
1582 enum mapimg_layer layer;
1583 char buf[MAPIMG_LAYER_COUNT + 1];
1584 int i;
1585
1586 if (pmapdef->status != MAPIMG_STATUS_OK) {
1587 MAPIMG_LOG(_("map definition not checked or error"));
1588 fc_strlcpy(str, pmapdef->maparg, str_len);
1589 return FALSE;
1590 }
1591
1592 str[0] = '\0';
1593 cat_snprintf(str, str_len, "format=%s|%s:",
1594 imagetool_name(pmapdef->tool),
1595 imageformat_name(pmapdef->format));
1596 cat_snprintf(str, str_len, "turns=%d:", pmapdef->turns);
1597
1598 i = 0;
1599 for (layer = mapimg_layer_begin(); layer != mapimg_layer_end();
1600 layer = mapimg_layer_next(layer)) {
1601 if (pmapdef->layers[layer]) {
1602 buf[i++] = mapimg_layer_name(layer)[0];
1603 }
1604 }
1605 buf[i++] = '\0';
1606 cat_snprintf(str, str_len, "map=%s:", buf);
1607
1608 switch (pmapdef->player.show) {
1609 case SHOW_NONE:
1610 case SHOW_EACH:
1611 case SHOW_HUMAN:
1612 case SHOW_ALL:
1613 cat_snprintf(str, str_len, "show=%s:",
1614 show_player_name(pmapdef->player.show));
1615 break;
1616 case SHOW_PLRBV:
1618 cat_snprintf(str, str_len, "plrbv=%s:",
1619 bvplayers_str(pmapdef->player.plrbv));
1620 break;
1621 case SHOW_PLRNAME:
1623 cat_snprintf(str, str_len, "plrname=%s:", pmapdef->player.name);
1624 break;
1625 case SHOW_PLRID:
1627 cat_snprintf(str, str_len, "plrid=%d:", pmapdef->player.id);
1628 break;
1629 }
1630 cat_snprintf(str, str_len, "zoom=%d", pmapdef->zoom);
1631
1632 return TRUE;
1633}
1634
1635/************************************************************************/
1640static bool mapimg_checkplayers(struct mapdef *pmapdef, bool recheck)
1641{
1642 struct player *pplayer;
1643 enum m_pre_result result;
1644
1645 if (!recheck && pmapdef->status == MAPIMG_STATUS_ERROR) {
1646 return FALSE;
1647 }
1648
1649 /* game started - generate / check bitvector for players */
1650 switch (pmapdef->player.show) {
1651 case SHOW_NONE:
1652 /* nothing */
1653 break;
1654 case SHOW_PLRBV:
1655 pmapdef->player.checked_plrbv = pmapdef->player.plrbv;
1656 break;
1657 case SHOW_EACH:
1658 case SHOW_HUMAN:
1659 /* A map for each player will be created in a loop. */
1660 BV_CLR_ALL(pmapdef->player.checked_plrbv);
1661 break;
1662 case SHOW_ALL:
1663 BV_SET_ALL(pmapdef->player.checked_plrbv);
1664 break;
1665 case SHOW_PLRNAME:
1666 /* Display players as requested in the map definition */
1667 BV_CLR_ALL(pmapdef->player.checked_plrbv);
1668 pplayer = player_by_name_prefix(pmapdef->player.name, &result);
1669
1670 if (pplayer != nullptr) {
1671 BV_SET(pmapdef->player.checked_plrbv, player_index(pplayer));
1672 } else {
1673 pmapdef->status = MAPIMG_STATUS_ERROR;
1674 /* Save the error message in map definition. */
1675 fc_snprintf(pmapdef->error, sizeof(pmapdef->error),
1676 _("unknown player name: '%s'"), pmapdef->player.name);
1677 MAPIMG_LOG("%s", pmapdef->error);
1678 return FALSE;
1679 }
1680 break;
1681 case SHOW_PLRID:
1682 /* Display players as requested in the map definition */
1683 BV_CLR_ALL(pmapdef->player.checked_plrbv);
1684 pplayer = player_by_number(pmapdef->player.id);
1685
1686 if (pplayer != nullptr) {
1687 BV_SET(pmapdef->player.checked_plrbv, player_index(pplayer));
1688 } else {
1689 pmapdef->status = MAPIMG_STATUS_ERROR;
1690 /* Save the error message in map definition. */
1691 fc_snprintf(pmapdef->error, sizeof(pmapdef->error),
1692 _("invalid player id: %d"), pmapdef->player.id);
1693 MAPIMG_LOG("%s", pmapdef->error);
1694 return FALSE;
1695 }
1696 break;
1697 }
1698
1699 pmapdef->status = MAPIMG_STATUS_OK;
1700
1701 return TRUE;
1702}
1703
1704/************************************************************************/
1708static void mapimg_log(const char *file, const char *function, int line,
1709 const char *format, ...)
1710{
1711 va_list args;
1712
1713 va_start(args, format);
1714 fc_vsnprintf(error_buffer, sizeof(error_buffer), format, args);
1715 va_end(args);
1716
1717#ifdef FREECIV_DEBUG
1718 log_debug("In %s() [%s:%d]: %s", function, file, line, error_buffer);
1719#endif
1720}
1721
1722/************************************************************************/
1736{
1737 static char mapstr[256];
1739 enum mapimg_layer layer;
1740 int i, count = 0, plr_id = -1;
1741
1742 switch (pmapdef->player.show) {
1743 case SHOW_NONE:
1744 /* no player on the map */
1745 sz_strlcpy(str_show, "none");
1746 break;
1747 case SHOW_ALL:
1748 /* show all players in one map */
1749 sz_strlcpy(str_show, "all");
1750 break;
1751 case SHOW_PLRBV:
1752 case SHOW_PLRNAME:
1753 case SHOW_PLRID:
1754 case SHOW_HUMAN:
1755 case SHOW_EACH:
1756 /* one map for each selected player; iterate over all possible player ids
1757 * to generate unique strings even if civil wars occur */
1758 for (i = 0; i < MAX_NUM_PLAYER_SLOTS; i++) {
1759 str_show[i] = BV_ISSET(pmapdef->player.checked_plrbv, i) ? '1' : '0';
1760 if (BV_ISSET(pmapdef->player.checked_plrbv, i)) {
1761 count++;
1762 plr_id = i;
1763 }
1764 }
1766
1767 /* Return the option name if no player is selected or the player id if
1768 * there is only one player selected. */
1769 if (count == 0) {
1770 fc_snprintf(str_show, sizeof(str_show), "---%s",
1771 show_player_name(pmapdef->player.show));
1772 } else if (count == 1 && plr_id != -1) {
1773 fc_snprintf(str_show, sizeof(str_show), "%03d%s", plr_id,
1774 show_player_name(pmapdef->player.show));
1775 }
1776 break;
1777 }
1778
1779 fc_snprintf(mapstr, sizeof(mapstr), "M");
1780 for (layer = mapimg_layer_begin(); layer != mapimg_layer_end();
1781 layer = mapimg_layer_next(layer)) {
1782 if (pmapdef->layers[layer]) {
1783 const char *lname = mapimg_layer_name(layer);
1784
1785 if (lname != nullptr) {
1786 cat_snprintf(mapstr, sizeof(mapstr), "%s", lname);
1787 } else {
1788 cat_snprintf(mapstr, sizeof(mapstr), "-");
1789 }
1790 } else {
1791 cat_snprintf(mapstr, sizeof(mapstr), "-");
1792 }
1793 }
1794 cat_snprintf(mapstr, sizeof(mapstr), "Z%dP%s", pmapdef->zoom, str_show);
1795
1796 return mapstr;
1797}
1798
1799/*
1800 * ==============================================
1801 * map definitions (internal functions)
1802 * ==============================================
1803 */
1804
1805/************************************************************************/
1808static struct mapdef *mapdef_new(bool colortest)
1809{
1810 struct mapdef *pmapdef;
1811
1812 pmapdef = fc_malloc(sizeof(*pmapdef));
1813
1814 /* default values */
1815 pmapdef->maparg[0] = '\0';
1816 pmapdef->error[0] = '\0';
1820 pmapdef->zoom = 2;
1821 pmapdef->turns = 1;
1823 pmapdef->layers[MAPIMG_LAYER_CITIES] = TRUE;
1824 pmapdef->layers[MAPIMG_LAYER_UNITS] = TRUE;
1828 pmapdef->layers[MAPIMG_LAYER_AREA] = FALSE;
1829 pmapdef->player.show = SHOW_ALL;
1830 /* The union is not set at this point (player.id, player.name and
1831 * player.plrbv). */
1832 BV_CLR_ALL(pmapdef->player.checked_plrbv);
1833 BV_CLR_ALL(pmapdef->args);
1834 pmapdef->colortest = colortest;
1835
1836 return pmapdef;
1837}
1838
1839/************************************************************************/
1842static void mapdef_destroy(struct mapdef *pmapdef)
1843{
1844 if (pmapdef == nullptr) {
1845 return;
1846 }
1847
1848 free(pmapdef);
1849}
1850
1851/*
1852 * ==============================================
1853 * images (internal functions)
1854 * ==============================================
1855 */
1856
1857/************************************************************************/
1860static const struct toolkit *img_toolkit_get(enum imagetool tool)
1861{
1863 if (toolkit->tool == tool) {
1864 return toolkit;
1865 }
1867
1868 return nullptr;
1869}
1870
1871/************************************************************************/
1874static struct img *img_new(struct mapdef *mapdef, int topo, int wrap,
1875 int xsize, int ysize)
1876{
1877 struct img *pimg;
1878
1879 pimg = fc_malloc(sizeof(*pimg));
1880
1881 pimg->def = mapdef;
1882 pimg->turn = game.info.turn;
1883 fc_snprintf(pimg->title, sizeof(pimg->title),
1884 _("Turn: %4d - Year: %10s"), game.info.turn,
1885 calendar_text());
1886
1887 pimg->mapsize.x = xsize; /* x size of the map */
1888 pimg->mapsize.y = ysize; /* y size of the map */
1889
1890 pimg->imgsize.x = 0; /* x size of the map image */
1891 pimg->imgsize.y = 0; /* y size of the map image */
1892
1893 if (topo_has_flag(topo, TF_HEX)) {
1894 /* additional space for hex maps */
1895 pimg->imgsize.x += TILE_SIZE / 2;
1896 pimg->imgsize.y += TILE_SIZE / 2;
1897
1898 if (topo_has_flag(topo, TF_ISO)) {
1899 /* iso-hex */
1900 pimg->imgsize.x += (pimg->mapsize.x + pimg->mapsize.y / 2)
1901 * TILE_SIZE;
1902 pimg->imgsize.y += (pimg->mapsize.x + pimg->mapsize.y / 2)
1903 * TILE_SIZE;
1904
1905 /* magic for isohexa: change size if wrapping in only one direction */
1908 pimg->imgsize.y += (pimg->mapsize.x - pimg->mapsize.y / 2) / 2
1909 * TILE_SIZE;
1910 }
1911
1912 pimg->tileshape = &tile_isohexa;
1913
1914 pimg->pixel_tile = pixel_tile_isohexa;
1915 pimg->pixel_city = pixel_city_isohexa;
1916 pimg->pixel_unit = pixel_unit_isohexa;
1917 pimg->pixel_fogofwar = pixel_fogofwar_isohexa;
1918 pimg->pixel_border = pixel_border_isohexa;
1919
1920 pimg->base_coor = base_coor_isohexa;
1921 } else {
1922 /* hex */
1923 pimg->imgsize.x += pimg->mapsize.x * TILE_SIZE;
1924 pimg->imgsize.y += pimg->mapsize.y * TILE_SIZE;
1925
1926 pimg->tileshape = &tile_hexa;
1927
1928 pimg->pixel_tile = pixel_tile_hexa;
1929 pimg->pixel_city = pixel_city_hexa;
1930 pimg->pixel_unit = pixel_unit_hexa;
1931 pimg->pixel_fogofwar = pixel_fogofwar_hexa;
1932 pimg->pixel_border = pixel_border_hexa;
1933
1934 pimg->base_coor = base_coor_hexa;
1935 }
1936 } else {
1937 if (topo_has_flag(topo, TF_ISO)) {
1938 /* isometric rectangular */
1939 pimg->imgsize.x += (pimg->mapsize.x + pimg->mapsize.y / 2) * TILE_SIZE;
1940 pimg->imgsize.y += (pimg->mapsize.x + pimg->mapsize.y / 2) * TILE_SIZE;
1941 } else {
1942 /* rectangular */
1943 pimg->imgsize.x += pimg->mapsize.x * TILE_SIZE;
1944 pimg->imgsize.y += pimg->mapsize.y * TILE_SIZE;
1945 }
1946
1947 pimg->tileshape = &tile_rect;
1948
1949 pimg->pixel_tile = pixel_tile_rect;
1950 pimg->pixel_city = pixel_city_rect;
1951 pimg->pixel_unit = pixel_unit_rect;
1952 pimg->pixel_fogofwar = pixel_fogofwar_rect;
1953 pimg->pixel_border = pixel_border_rect;
1954
1955 pimg->base_coor = base_coor_rect;
1956 }
1957
1958 /* Here the map image is saved as an array of RGB color values. */
1959 pimg->map = fc_calloc(pimg->imgsize.x * pimg->imgsize.y,
1960 sizeof(*pimg->map));
1961 /* Initialise map. */
1962 memset(pimg->map, 0, pimg->imgsize.x * pimg->imgsize.y);
1963
1964 return pimg;
1965}
1966
1967/************************************************************************/
1970static void img_destroy(struct img *pimg)
1971{
1972 if (pimg != nullptr) {
1973 /* Do not free pimg->def */
1974 free(pimg->map);
1975 free(pimg);
1976 }
1977}
1978
1979/************************************************************************/
1982static inline void img_set_pixel(struct img *pimg, const int mindex,
1983 const struct rgbcolor *pcolor)
1984{
1985 if (mindex < 0 || mindex > pimg->imgsize.x * pimg->imgsize.y) {
1986 log_error("invalid index: 0 <= %d < %d", mindex,
1987 pimg->imgsize.x * pimg->imgsize.y);
1988 return;
1989 }
1990
1991 pimg->map[mindex] = pcolor;
1992}
1993
1994/************************************************************************/
1997static inline int img_index(const int x, const int y,
1998 const struct img *pimg)
1999{
2000 fc_assert_ret_val(x >= 0 && x < pimg->imgsize.x, -1);
2001 fc_assert_ret_val(y >= 0 && y < pimg->imgsize.y, -1);
2002
2003 return pimg->imgsize.x * y + x;
2004}
2005
2006/************************************************************************/
2010static void img_plot(struct img *pimg, int x, int y,
2011 const struct rgbcolor *pcolor, const bv_pixel pixel)
2012{
2013 int base_x, base_y, i, mindex;
2014
2015 if (!BV_ISSET_ANY(pixel)) {
2016 return;
2017 }
2018
2019 pimg->base_coor(pimg, &base_x, &base_y, x, y);
2020
2021 for (i = 0; i < NUM_PIXEL; i++) {
2022 if (BV_ISSET(pixel, i)) {
2023 mindex = img_index(base_x + pimg->tileshape->x[i],
2024 base_y + pimg->tileshape->y[i], pimg);
2026 }
2027 }
2028}
2029
2030/************************************************************************/
2033static void img_plot_tile(struct img *pimg, const struct tile *ptile,
2034 const struct rgbcolor *pcolor, const bv_pixel pixel)
2035{
2036 int x, y;
2037
2038 index_to_map_pos(&x, &y, tile_index(ptile));
2039
2040 img_plot(pimg, x, y, pcolor, pixel);
2041}
2042
2043/************************************************************************/
2046static bool img_save(const struct img *pimg, const char *mapimgfile,
2047 const char *path)
2048{
2049 enum imagetool tool = pimg->def->tool;
2050 const struct toolkit *toolkit = img_toolkit_get(tool);
2051 char tmpname[600];
2052
2053 if (!toolkit) {
2054 MAPIMG_LOG(_("toolkit not defined"));
2055 return FALSE;
2056 }
2057
2058 if (!path_is_absolute(mapimgfile) && path != nullptr && path[0] != '\0') {
2059 if (!make_dir(path, DIRMODE_DEFAULT)) {
2060 MAPIMG_LOG(_("can't create directory"));
2061 return FALSE;
2062 }
2063
2064 sz_strlcpy(tmpname, path);
2065 sz_strlcat(tmpname, "/");
2066 } else {
2067 tmpname[0] = '\0';
2068 }
2069
2071
2073
2074 return toolkit->img_save(pimg, tmpname);
2075}
2076
2077/************************************************************************/
2100#ifdef HAVE_MAPIMG_MAGICKWAND
2101#define SET_COLOR(str, pcolor) \
2102 fc_snprintf(str, sizeof(str), "rgb(%d,%d,%d)", \
2103 pcolor->r, pcolor->g, pcolor->b);
2104static bool img_save_magickwand(const struct img *pimg,
2105 const char *mapimgfile)
2106{
2107 const struct rgbcolor *pcolor = nullptr;
2108 struct player *pplr_now = nullptr, *pplr_only = nullptr;
2109 bool ret = TRUE;
2110 char imagefile[MAX_LEN_PATH];
2111 char str_color[32], comment[2048] = "", title[258];
2114 bool withplr = BV_ISSET_ANY(pimg->def->player.checked_plrbv);
2115
2116 if (!img_filename(mapimgfile, pimg->def->format, imagefile,
2117 sizeof(imagefile))) {
2118 MAPIMG_LOG(_("error generating the file name"));
2119 return FALSE;
2120 }
2121
2122 MagickWand *mw;
2124 PixelWand **pmw, *pw;
2125 DrawingWand *dw;
2126
2128
2129 mw = NewMagickWand();
2130 dw = NewDrawingWand();
2131 pw = NewPixelWand();
2132
2133 map_width = pimg->imgsize.x * pimg->def->zoom;
2134 map_height = pimg->imgsize.y * pimg->def->zoom;
2135
2139
2140 fc_snprintf(title, sizeof(title), "%s (%s)", pimg->title, mapimgfile);
2141
2145
2146 textoffset = 0;
2147 if (withplr) {
2148 if (bvplayers_count(pimg->def) == 1) {
2149 /* only one player */
2150 for (i = 0; i < player_slot_count(); i++) {
2151 if (BV_ISSET(pimg->def->player.checked_plrbv, i)) {
2153 break;
2154 }
2155 }
2156 }
2157
2158 if (pplr_only) {
2160
2162
2165
2166 /* Show the color of the selected player. */
2169 /* y coordinate */
2170 for (y = 0; y < IMG_TEXT_HEIGHT; y++) {
2172 /* x coordinate */
2173 for (x = 0; x < IMG_TEXT_HEIGHT; x++) {
2175 }
2177 }
2179 }
2180
2181 /* Show a line displaying the colors of alive players */
2184
2189 /* y coordinate */
2190 for (y = 0; y < IMG_LINE_HEIGHT; y++) {
2192
2193 /* x coordinate */
2194 for (x = plroffset; x < map_width; x++) {
2195 i = (x - plroffset) / plrwidth;
2197
2198 if (i > player_count() || pplr_now == nullptr || !pplr_now->is_alive) {
2199 continue;
2200 }
2201
2202 if (BV_ISSET(pimg->def->player.checked_plrbv, i)) {
2203 /* The selected player is alive - display it. */
2207 } else if (pplr_only != nullptr) {
2208 /* Display the state between pplr_only and pplr_now:
2209 * - if allied:
2210 * - show each second pixel
2211 * - if pplr_now does shares map with pplr_onlyus:
2212 * - show every other line of pixels
2213 * This results in the following patterns (# = color):
2214 * ###### # # # ######
2215 * # # # # # #
2216 * ###### # # # ######
2217 * # # # # # #
2218 * shared allied shared vision
2219 * vision + allied */
2220 if ((pplayers_allied(pplr_now, pplr_only) && (x + y) % 2 == 0)
2221 || (y % 2 == 0 && gives_shared_vision(pplr_now, pplr_only))) {
2225 }
2226 }
2227 }
2229 }
2231 }
2232
2233 /* Display the image name. */
2237 DrawSetFont(dw, "Times-New-Roman");
2241 (unsigned char *)title);
2242 MagickDrawImage(mw, dw);
2243
2244 /* Display the map. */
2249 : 0), map_width, map_height);
2250 /* y coordinate */
2251 for (y = 0; y < pimg->imgsize.y; y++) {
2252 /* zoom for y */
2253 for (yyy = 0; yyy < pimg->def->zoom; yyy++) {
2254
2256
2257 /* x coordinate */
2258 for (x = 0; x < pimg->imgsize.x; x++) {
2259 mindex = img_index(x, y, pimg);
2260 pcolor = pimg->map[mindex];
2261
2262 if (pcolor != nullptr) {
2264
2265 /* Zoom for x */
2266 for (xxx = 0; xxx < pimg->def->zoom; xxx++) {
2267 row = x * pimg->def->zoom + xxx;
2269 }
2270 }
2271 }
2273 }
2274 }
2276
2277 cat_snprintf(comment, sizeof(comment), "map definition: %s\n",
2278 pimg->def->maparg);
2279 if (BV_ISSET_ANY(pimg->def->player.checked_plrbv)) {
2280 players_iterate(pplayer) {
2281 if (!BV_ISSET(pimg->def->player.checked_plrbv, player_index(pplayer))) {
2282 continue;
2283 }
2284
2285 cat_snprintf(comment, sizeof(comment), "%s\n", img_playerstr(pplayer));
2287 }
2288 MagickCommentImage(mw, comment);
2289
2290 if (!MagickWriteImage(mw, imagefile)) {
2291 MAPIMG_LOG(_("error saving map image '%s'"), imagefile);
2292 ret = FALSE;
2293 } else {
2294 log_verbose("Map image saved as '%s'.", imagefile);
2295 }
2296
2300
2302
2303 return ret;
2304}
2305#undef SET_COLOR
2306#endif /* HAVE_MAPIMG_MAGICKWAND */
2307
2308/************************************************************************/
2311static bool img_save_ppm(const struct img *pimg, const char *mapimgfile)
2312{
2313 char ppmname[MAX_LEN_PATH];
2314 FILE *fp;
2315 int x, y, xxx, yyy, mindex;
2316 const struct rgbcolor *pcolor;
2317
2318 if (pimg->def->format != IMGFORMAT_PPM) {
2319 MAPIMG_LOG(_("the ppm toolkit can only create images in the ppm "
2320 "format"));
2321 return FALSE;
2322 }
2323
2325 MAPIMG_LOG(_("error generating the file name"));
2326 return FALSE;
2327 }
2328
2329 fp = fc_fopen(ppmname, "w");
2330 if (!fp) {
2331 MAPIMG_LOG(_("could not open file: %s"), ppmname);
2332 return FALSE;
2333 }
2334
2335 fprintf(fp, "P3\n");
2336 fprintf(fp, "# version:2\n");
2337 fprintf(fp, "# map definition: %s\n", pimg->def->maparg);
2338
2339 if (pimg->def->colortest) {
2340 fprintf(fp, "# color test\n");
2341 } else if (BV_ISSET_ANY(pimg->def->player.checked_plrbv)) {
2342 players_iterate(pplayer) {
2343 if (!BV_ISSET(pimg->def->player.checked_plrbv, player_index(pplayer))) {
2344 continue;
2345 }
2346
2347 fprintf(fp, "# %s\n", img_playerstr(pplayer));
2349 } else {
2350 fprintf(fp, "# no players\n");
2351 }
2352
2353 fprintf(fp, "%d %d\n", pimg->imgsize.x * pimg->def->zoom,
2354 pimg->imgsize.y * pimg->def->zoom);
2355 fprintf(fp, "255\n");
2356
2357 /* y coordinate */
2358 for (y = 0; y < pimg->imgsize.y; y++) {
2359 /* Zoom for y */
2360 for (yyy = 0; yyy < pimg->def->zoom; yyy++) {
2361 /* x coordinate */
2362 for (x = 0; x < pimg->imgsize.x; x++) {
2363 mindex = img_index(x, y, pimg);
2364 pcolor = pimg->map[mindex];
2365
2366 /* Zoom for x */
2367 for (xxx = 0; xxx < pimg->def->zoom; xxx++) {
2368 if (pcolor == nullptr) {
2370 }
2371 fprintf(fp, "%d %d %d\n", pcolor->r, pcolor->g, pcolor->b);
2372 }
2373 }
2374 }
2375 }
2376
2377 log_verbose("Map image saved as '%s'.", ppmname);
2378 fclose(fp);
2379
2380 return TRUE;
2381}
2382
2383/************************************************************************/
2386static bool img_filename(const char *mapimgfile, enum imageformat format,
2387 char *filename, size_t filename_len)
2388{
2390
2391 fc_snprintf(filename, filename_len, "%s.map.%s", mapimgfile,
2392 imageformat_name(format));
2393
2394 return TRUE;
2395}
2396
2397/************************************************************************/
2400static const char *img_playerstr(const struct player *pplayer)
2401{
2402 static char buf[512];
2403 const struct rgbcolor *pcolor = imgcolor_player(player_index(pplayer));
2404
2405 fc_snprintf(buf, sizeof(buf),
2406 "playerno:%d:color:(%3d, %3d, %3d):name:\"%s\"",
2407 player_number(pplayer), pcolor->r, pcolor->g, pcolor->b,
2408 player_name(pplayer));
2409
2410 return buf;
2411}
2412
2413/************************************************************************/
2417static void img_createmap(struct img *pimg)
2418{
2419 const struct rgbcolor *pcolor;
2421 int player_id;
2422 struct player *pplayer = nullptr;
2423 struct player *plr_tile = nullptr, *plr_city = nullptr, *plr_unit = nullptr;
2425 struct terrain *pterrain = nullptr;
2426 bool plr_knowledge = pimg->def->layers[MAPIMG_LAYER_KNOWLEDGE];
2427
2428 whole_map_iterate(&(wld.map), ptile) {
2429 if (bvplayers_count(pimg->def) == 1) {
2430 /* Only one player; get player id for 'known' and 'fogofwar' */
2432 if (BV_ISSET(pimg->def->player.checked_plrbv,
2434 pplayer = aplayer;
2435 tile_knowledge = mapimg.mapimg_tile_known(ptile, pplayer,
2437 break;
2438 }
2440 }
2441
2442 /* Known tiles */
2443 if (plr_knowledge && pplayer != nullptr && tile_knowledge == TILE_UNKNOWN) {
2444 /* Plot nothing iff tile is not known */
2445 continue;
2446 }
2447
2448 /* Terrain */
2449 pterrain = mapimg.mapimg_tile_terrain(ptile, pplayer, plr_knowledge);
2450 if (pimg->def->layers[MAPIMG_LAYER_TERRAIN]) {
2451 /* Full terrain */
2452 pixel = pimg->pixel_tile(ptile, pplayer, plr_knowledge);
2453 pcolor = imgcolor_terrain(pterrain);
2454 img_plot_tile(pimg, ptile, pcolor, pixel);
2455 } else {
2456 /* Basic terrain */
2457 pixel = pimg->pixel_tile(ptile, pplayer, plr_knowledge);
2458 if (is_ocean(pterrain)) {
2460 } else {
2462 }
2463 }
2464
2465 /* (Land) area within borders and borders */
2466 plr_tile = mapimg.mapimg_tile_owner(ptile, pplayer, plr_knowledge);
2467 if (game.info.borders > 0 && plr_tile != nullptr) {
2468 player_id = player_index(plr_tile);
2469 if (pimg->def->layers[MAPIMG_LAYER_AREA] && !is_ocean(pterrain)
2470 && BV_ISSET(pimg->def->player.checked_plrbv, player_id)) {
2471 /* The tile is land and inside the players borders */
2472 pixel = pimg->pixel_tile(ptile, pplayer, plr_knowledge);
2473 pcolor = imgcolor_player(player_id);
2474 img_plot_tile(pimg, ptile, pcolor, pixel);
2475 } else if (pimg->def->layers[MAPIMG_LAYER_BORDERS]
2476 && (BV_ISSET(pimg->def->player.checked_plrbv, player_id)
2477 || (plr_knowledge && pplayer != nullptr))) {
2478 /* Plot borders if player is selected or view range of the one
2479 * displayed player */
2480 pixel = pimg->pixel_border(ptile, pplayer, plr_knowledge);
2481 pcolor = imgcolor_player(player_id);
2482 img_plot_tile(pimg, ptile, pcolor, pixel);
2483 }
2484 }
2485
2486 /* Cities and units */
2487 plr_city = mapimg.mapimg_tile_city(ptile, pplayer, plr_knowledge);
2488 plr_unit = mapimg.mapimg_tile_unit(ptile, pplayer, plr_knowledge);
2489 if (pimg->def->layers[MAPIMG_LAYER_CITIES] && plr_city) {
2490 player_id = player_index(plr_city);
2491 if (BV_ISSET(pimg->def->player.checked_plrbv, player_id)
2492 || (plr_knowledge && pplayer != nullptr)) {
2493 /* Plot cities if player is selected or view range of the one
2494 * displayed player */
2495 pixel = pimg->pixel_city(ptile, pplayer, plr_knowledge);
2496 pcolor = imgcolor_player(player_id);
2497 img_plot_tile(pimg, ptile, pcolor, pixel);
2498 }
2499 } else if (pimg->def->layers[MAPIMG_LAYER_UNITS] && plr_unit) {
2500 player_id = player_index(plr_unit);
2501 if (BV_ISSET(pimg->def->player.checked_plrbv, player_id)
2502 || (plr_knowledge && pplayer != nullptr)) {
2503 /* Plot units if player is selected or view range of the one
2504 * displayed player */
2505 pixel = pimg->pixel_unit(ptile, pplayer, plr_knowledge);
2506 pcolor = imgcolor_player(player_id);
2507 img_plot_tile(pimg, ptile, pcolor, pixel);
2508 }
2509 }
2510
2511 /* Fogofwar; if only 1 player is plotted */
2512 if (game.info.fogofwar && pimg->def->layers[MAPIMG_LAYER_FOGOFWAR]
2513 && pplayer != nullptr
2515 pixel = pimg->pixel_fogofwar(ptile, pplayer, plr_knowledge);
2516 pcolor = nullptr;
2517 img_plot_tile(pimg, ptile, pcolor, pixel);
2518 }
2520}
2521
2522/*
2523 * ==============================================
2524 * topology (internal functions)
2525 * ==============================================
2526 * With these functions the pixels corresponding to the different elements
2527 * (tile, city, unit) for each map topology are defined.
2528 *
2529 * The bv_pixel_fogofwar_*() functions are special as they defines where
2530 * the color should be removed.
2531 *
2532 * The functions for a rectangular and an isometric rectangular topology
2533 * are identical.
2534 */
2535
2536/************************************************************************/
2544static bv_pixel pixel_tile_rect(const struct tile *ptile,
2545 const struct player *pplayer,
2546 bool knowledge)
2547{
2549
2551
2552 return pixel;
2553}
2554
2555/************************************************************************/
2563static bv_pixel pixel_city_rect(const struct tile *ptile,
2564 const struct player *pplayer,
2565 bool knowledge)
2566{
2568
2570 BV_SET(pixel, 7);
2571 BV_SET(pixel, 8);
2572 BV_SET(pixel, 9);
2573 BV_SET(pixel, 10);
2574 BV_SET(pixel, 13);
2575 BV_SET(pixel, 14);
2576 BV_SET(pixel, 15);
2577 BV_SET(pixel, 16);
2578 BV_SET(pixel, 19);
2579 BV_SET(pixel, 20);
2580 BV_SET(pixel, 21);
2581 BV_SET(pixel, 22);
2582 BV_SET(pixel, 21);
2583 BV_SET(pixel, 25);
2584 BV_SET(pixel, 26);
2585 BV_SET(pixel, 27);
2586 BV_SET(pixel, 28);
2587
2588 return pixel;
2589}
2590
2591/************************************************************************/
2599static bv_pixel pixel_unit_rect(const struct tile *ptile,
2600 const struct player *pplayer,
2601 bool knowledge)
2602{
2604
2606 BV_SET(pixel, 14);
2607 BV_SET(pixel, 15);
2608 BV_SET(pixel, 20);
2609 BV_SET(pixel, 21);
2610
2611 return pixel;
2612}
2613
2614/************************************************************************/
2622static bv_pixel pixel_fogofwar_rect(const struct tile *ptile,
2623 const struct player *pplayer,
2624 bool knowledge)
2625{
2627
2629
2630 BV_SET(pixel, 0);
2631 BV_SET(pixel, 2);
2632 BV_SET(pixel, 4);
2633 BV_SET(pixel, 7);
2634 BV_SET(pixel, 9);
2635 BV_SET(pixel, 11);
2636 BV_SET(pixel, 12);
2637 BV_SET(pixel, 14);
2638 BV_SET(pixel, 16);
2639 BV_SET(pixel, 19);
2640 BV_SET(pixel, 21);
2641 BV_SET(pixel, 23);
2642 BV_SET(pixel, 24);
2643 BV_SET(pixel, 26);
2644 BV_SET(pixel, 28);
2645 BV_SET(pixel, 31);
2646 BV_SET(pixel, 33);
2647 BV_SET(pixel, 35);
2648
2649 return pixel;
2650}
2651
2652/************************************************************************/
2664static bv_pixel pixel_border_rect(const struct tile *ptile,
2665 const struct player *pplayer,
2666 bool knowledge)
2667{
2669 struct tile *pnext;
2670 struct player *owner;
2671
2673
2674 fc_assert_ret_val(ptile != nullptr, pixel);
2675
2676 if (ptile == nullptr) {
2677 /* No tile */
2678 return pixel;
2679 }
2680
2681 owner = mapimg.mapimg_tile_owner(ptile, pplayer, knowledge);
2682 if (owner == nullptr) {
2683 /* No border */
2684 return pixel;
2685 }
2686
2687 pnext = mapstep(&(wld.map), ptile, DIR8_NORTH);
2688 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2690 && mapimg.mapimg_tile_owner(pnext, pplayer,
2691 knowledge) != owner)) {
2692 BV_SET(pixel, 0);
2693 BV_SET(pixel, 1);
2694 BV_SET(pixel, 2);
2695 BV_SET(pixel, 3);
2696 BV_SET(pixel, 4);
2697 BV_SET(pixel, 5);
2698 }
2699
2700 pnext = mapstep(&(wld.map), ptile, DIR8_EAST);
2701 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2703 && mapimg.mapimg_tile_owner(pnext, pplayer,
2704 knowledge) != owner)) {
2705 BV_SET(pixel, 5);
2706 BV_SET(pixel, 11);
2707 BV_SET(pixel, 17);
2708 BV_SET(pixel, 23);
2709 BV_SET(pixel, 29);
2710 BV_SET(pixel, 35);
2711 }
2712
2713 pnext = mapstep(&(wld.map), ptile, DIR8_SOUTH);
2714 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2716 && mapimg.mapimg_tile_owner(pnext, pplayer,
2717 knowledge) != owner)) {
2718 BV_SET(pixel, 30);
2719 BV_SET(pixel, 31);
2720 BV_SET(pixel, 32);
2721 BV_SET(pixel, 33);
2722 BV_SET(pixel, 34);
2723 BV_SET(pixel, 35);
2724 }
2725
2726 pnext = mapstep(&(wld.map), ptile, DIR8_WEST);
2727 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2729 && mapimg.mapimg_tile_owner(pnext, pplayer,
2730 knowledge) != owner)) {
2731 BV_SET(pixel, 0);
2732 BV_SET(pixel, 6);
2733 BV_SET(pixel, 12);
2734 BV_SET(pixel, 18);
2735 BV_SET(pixel, 24);
2736 BV_SET(pixel, 30);
2737 }
2738
2739 return pixel;
2740}
2741
2742/************************************************************************/
2745static void base_coor_rect(struct img *pimg, int *base_x, int *base_y,
2746 int x, int y)
2747{
2748 *base_x = x * TILE_SIZE;
2749 *base_y = y * TILE_SIZE;
2750}
2751
2752/************************************************************************/
2762static bv_pixel pixel_tile_hexa(const struct tile *ptile,
2763 const struct player *pplayer,
2764 bool knowledge)
2765{
2767
2769
2770 return pixel;
2771}
2772
2773/************************************************************************/
2783static bv_pixel pixel_city_hexa(const struct tile *ptile,
2784 const struct player *pplayer,
2785 bool knowledge)
2786{
2788
2790 BV_SET(pixel, 3);
2791 BV_SET(pixel, 4);
2792 BV_SET(pixel, 7);
2793 BV_SET(pixel, 8);
2794 BV_SET(pixel, 9);
2795 BV_SET(pixel, 10);
2796 BV_SET(pixel, 13);
2797 BV_SET(pixel, 14);
2798 BV_SET(pixel, 15);
2799 BV_SET(pixel, 16);
2800 BV_SET(pixel, 19);
2801 BV_SET(pixel, 20);
2802 BV_SET(pixel, 21);
2803 BV_SET(pixel, 22);
2804 BV_SET(pixel, 25);
2805 BV_SET(pixel, 26);
2806 BV_SET(pixel, 27);
2807 BV_SET(pixel, 28);
2808 BV_SET(pixel, 31);
2809 BV_SET(pixel, 32);
2810
2811 return pixel;
2812}
2813
2814/************************************************************************/
2824static bv_pixel pixel_unit_hexa(const struct tile *ptile,
2825 const struct player *pplayer,
2826 bool knowledge)
2827{
2829
2831 BV_SET(pixel, 14);
2832 BV_SET(pixel, 15);
2833 BV_SET(pixel, 20);
2834 BV_SET(pixel, 21);
2835
2836 return pixel;
2837}
2838
2839/************************************************************************/
2849static bv_pixel pixel_fogofwar_hexa(const struct tile *ptile,
2850 const struct player *pplayer,
2851 bool knowledge)
2852{
2854
2856 BV_SET(pixel, 0);
2857 BV_SET(pixel, 3);
2858 BV_SET(pixel, 5);
2859 BV_SET(pixel, 7);
2860 BV_SET(pixel, 9);
2861 BV_SET(pixel, 11);
2862 BV_SET(pixel, 13);
2863 BV_SET(pixel, 15);
2864 BV_SET(pixel, 17);
2865 BV_SET(pixel, 18);
2866 BV_SET(pixel, 20);
2867 BV_SET(pixel, 22);
2868 BV_SET(pixel, 24);
2869 BV_SET(pixel, 26);
2870 BV_SET(pixel, 28);
2871 BV_SET(pixel, 30);
2872 BV_SET(pixel, 32);
2873 BV_SET(pixel, 35);
2874
2875 return pixel;
2876}
2877
2878/************************************************************************/
2888static bv_pixel pixel_border_hexa(const struct tile *ptile,
2889 const struct player *pplayer,
2890 bool knowledge)
2891{
2893 struct tile *pnext;
2894 struct player *owner;
2895
2897
2898 fc_assert_ret_val(ptile != nullptr, pixel);
2899
2900 if (ptile == nullptr) {
2901 /* No tile */
2902 return pixel;
2903 }
2904
2905 owner = mapimg.mapimg_tile_owner(ptile, pplayer, knowledge);
2906 if (owner == nullptr) {
2907 /* No border */
2908 return pixel;
2909 }
2910
2911 pnext = mapstep(&(wld.map), ptile, DIR8_WEST);
2912 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2914 && mapimg.mapimg_tile_owner(pnext, pplayer,
2915 knowledge) != owner)) {
2916 BV_SET(pixel, 0);
2917 BV_SET(pixel, 2);
2918 BV_SET(pixel, 6);
2919 }
2920
2921 /* not used: DIR8_NORTHWEST */
2922
2923 pnext = mapstep(&(wld.map), ptile, DIR8_NORTH);
2924 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2926 && mapimg.mapimg_tile_owner(pnext, pplayer,
2927 knowledge) != owner)) {
2928 BV_SET(pixel, 1);
2929 BV_SET(pixel, 5);
2930 BV_SET(pixel, 11);
2931 }
2932
2933 pnext = mapstep(&(wld.map), ptile, DIR8_NORTHEAST);
2934 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2936 && mapimg.mapimg_tile_owner(pnext, pplayer,
2937 knowledge) != owner)) {
2938 BV_SET(pixel, 11);
2939 BV_SET(pixel, 17);
2940 BV_SET(pixel, 23);
2941 BV_SET(pixel, 29);
2942 }
2943
2944 pnext = mapstep(&(wld.map), ptile, DIR8_EAST);
2945 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2947 && mapimg.mapimg_tile_owner(pnext, pplayer,
2948 knowledge) != owner)) {
2949 BV_SET(pixel, 29);
2950 BV_SET(pixel, 33);
2951 BV_SET(pixel, 35);
2952 }
2953
2954 /* not used. DIR8_SOUTHEAST */
2955
2956 pnext = mapstep(&(wld.map), ptile, DIR8_SOUTH);
2957 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2959 && mapimg.mapimg_tile_owner(pnext, pplayer,
2960 knowledge) != owner)) {
2961 BV_SET(pixel, 24);
2962 BV_SET(pixel, 30);
2963 BV_SET(pixel, 34);
2964 }
2965
2966 pnext = mapstep(&(wld.map), ptile, DIR8_SOUTHWEST);
2967 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
2969 && mapimg.mapimg_tile_owner(pnext, pplayer,
2970 knowledge) != owner)) {
2971 BV_SET(pixel, 6);
2972 BV_SET(pixel, 12);
2973 BV_SET(pixel, 18);
2974 BV_SET(pixel, 24);
2975 }
2976
2977 return pixel;
2978}
2979
2980/************************************************************************/
2983static void base_coor_hexa(struct img *pimg, int *base_x, int *base_y,
2984 int x, int y)
2985{
2986 int nat_x, nat_y;
2987
2989
2990 *base_x = nat_x * TILE_SIZE + ((nat_y % 2) ? TILE_SIZE / 2 : 0);
2991 *base_y = nat_y * TILE_SIZE;
2992}
2993
2994/************************************************************************/
3002static bv_pixel pixel_tile_isohexa(const struct tile *ptile,
3003 const struct player *pplayer,
3004 bool knowledge)
3005{
3007
3009
3010 return pixel;
3011}
3012
3013/************************************************************************/
3021static bv_pixel pixel_city_isohexa(const struct tile *ptile,
3022 const struct player *pplayer,
3023 bool knowledge)
3024{
3026
3028 BV_SET(pixel, 5);
3029 BV_SET(pixel, 6);
3030 BV_SET(pixel, 7);
3031 BV_SET(pixel, 8);
3032 BV_SET(pixel, 11);
3033 BV_SET(pixel, 12);
3034 BV_SET(pixel, 13);
3035 BV_SET(pixel, 14);
3036 BV_SET(pixel, 15);
3037 BV_SET(pixel, 16);
3038 BV_SET(pixel, 19);
3039 BV_SET(pixel, 20);
3040 BV_SET(pixel, 21);
3041 BV_SET(pixel, 22);
3042 BV_SET(pixel, 23);
3043 BV_SET(pixel, 24);
3044 BV_SET(pixel, 27);
3045 BV_SET(pixel, 28);
3046 BV_SET(pixel, 29);
3047 BV_SET(pixel, 30);
3048
3049 return pixel;
3050}
3051
3052/************************************************************************/
3060static bv_pixel pixel_unit_isohexa(const struct tile *ptile,
3061 const struct player *pplayer,
3062 bool knowledge)
3063{
3065
3067 BV_SET(pixel, 13);
3068 BV_SET(pixel, 14);
3069 BV_SET(pixel, 21);
3070 BV_SET(pixel, 22);
3071
3072 return pixel;
3073}
3074
3075/************************************************************************/
3083static bv_pixel pixel_fogofwar_isohexa(const struct tile *ptile,
3084 const struct player *pplayer,
3085 bool knowledge)
3086{
3088
3090 BV_SET(pixel, 0);
3091 BV_SET(pixel, 1);
3092 BV_SET(pixel, 4);
3093 BV_SET(pixel, 7);
3094 BV_SET(pixel, 8);
3095 BV_SET(pixel, 12);
3096 BV_SET(pixel, 13);
3097 BV_SET(pixel, 16);
3098 BV_SET(pixel, 17);
3099 BV_SET(pixel, 18);
3100 BV_SET(pixel, 19);
3101 BV_SET(pixel, 22);
3102 BV_SET(pixel, 23);
3103 BV_SET(pixel, 27);
3104 BV_SET(pixel, 28);
3105 BV_SET(pixel, 31);
3106 BV_SET(pixel, 34);
3107 BV_SET(pixel, 35);
3108
3109 return pixel;
3110}
3111
3112/************************************************************************/
3125static bv_pixel pixel_border_isohexa(const struct tile *ptile,
3126 const struct player *pplayer,
3127 bool knowledge)
3128{
3130 struct tile *pnext;
3131 struct player *owner;
3132
3134
3135 fc_assert_ret_val(ptile != nullptr, pixel);
3136
3137 if (ptile == nullptr) {
3138 /* No tile */
3139 return pixel;
3140 }
3141
3142 owner = mapimg.mapimg_tile_owner(ptile, pplayer, knowledge);
3143 if (owner == nullptr) {
3144 /* No border */
3145 return pixel;
3146 }
3147
3148 pnext = mapstep(&(wld.map), ptile, DIR8_NORTH);
3149 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
3151 && mapimg.mapimg_tile_owner(pnext, pplayer,
3152 knowledge) != owner)) {
3153 BV_SET(pixel, 0);
3154 BV_SET(pixel, 1);
3155 BV_SET(pixel, 2);
3156 BV_SET(pixel, 3);
3157 }
3158
3159 /* not used: DIR8_NORTHEAST */
3160
3161 pnext = mapstep(&(wld.map), ptile, DIR8_EAST);
3162 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
3164 && mapimg.mapimg_tile_owner(pnext, pplayer,
3165 knowledge) != owner)) {
3166 BV_SET(pixel, 3);
3167 BV_SET(pixel, 9);
3168 BV_SET(pixel, 17);
3169 }
3170
3171 pnext = mapstep(&(wld.map), ptile, DIR8_SOUTHEAST);
3172 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
3174 && mapimg.mapimg_tile_owner(pnext, pplayer,
3175 knowledge) != owner)) {
3176 BV_SET(pixel, 25);
3177 BV_SET(pixel, 31);
3178 BV_SET(pixel, 35);
3179 }
3180
3181 pnext = mapstep(&(wld.map), ptile, DIR8_SOUTH);
3182 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
3184 && mapimg.mapimg_tile_owner(pnext, pplayer,
3185 knowledge) != owner)) {
3186 BV_SET(pixel, 32);
3187 BV_SET(pixel, 33);
3188 BV_SET(pixel, 34);
3189 BV_SET(pixel, 35);
3190 }
3191
3192 /* not used: DIR8_SOUTHWEST */
3193
3194 pnext = mapstep(&(wld.map), ptile, DIR8_WEST);
3195 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
3197 && mapimg.mapimg_tile_owner(pnext, pplayer,
3198 knowledge) != owner)) {
3199 BV_SET(pixel, 18);
3200 BV_SET(pixel, 26);
3201 BV_SET(pixel, 32);
3202 }
3203
3204 pnext = mapstep(&(wld.map), ptile, DIR8_NORTHWEST);
3205 if (!pnext || (mapimg.mapimg_tile_known(pnext, pplayer,
3207 && mapimg.mapimg_tile_owner(pnext, pplayer,
3208 knowledge) != owner)) {
3209 BV_SET(pixel, 0);
3210 BV_SET(pixel, 4);
3211 BV_SET(pixel, 10);
3212 }
3213
3214 return pixel;
3215}
3216
3217/************************************************************************/
3220static void base_coor_isohexa(struct img *pimg, int *base_x, int *base_y,
3221 int x, int y)
3222{
3223 /* magic for iso-hexa */
3224 y -= x / 2;
3225 y += (pimg->mapsize.x - 1)/2;
3226
3227 *base_x = x * TILE_SIZE;
3228 *base_y = y * TILE_SIZE + ((x % 2) ? 0 : TILE_SIZE / 2);
3229}
3230
3231/*
3232 * ==============================================
3233 * additional functions (internal functions)
3234 * ==============================================
3235 */
3236
3237/************************************************************************/
3240static const char *bvplayers_str(const bv_player plrbv)
3241{
3242 static char buf[MAX_NUM_PLAYER_SLOTS + 1];
3243 int i;
3244
3245 /* Don't print lots of unnecessary trailing zeroes */
3246 for (i = MAX_NUM_PLAYER_SLOTS-1; i >= 0; i--) {
3247 if (BV_ISSET(plrbv, i) || player_by_number(i)) {
3248 buf[i+1] = '\0';
3249 break;
3250 }
3251 }
3252
3253 for (; i >= 0; i--) {
3254 buf[i] = BV_ISSET(plrbv, i) ? '1' : '0';
3255 }
3256
3257 return buf;
3258}
3259
3260/************************************************************************/
3263static int bvplayers_count(const struct mapdef *pmapdef)
3264{
3265 int i, count = 0;
3266
3267 switch (pmapdef->player.show) {
3268 case SHOW_NONE: /* no player on the map */
3269 count = 0;
3270 break;
3271 case SHOW_HUMAN: /* one map for each human player */
3272 case SHOW_EACH: /* one map for each player */
3273 case SHOW_PLRNAME: /* the map of one selected player */
3274 case SHOW_PLRID:
3275 count = 1;
3276 break;
3277 case SHOW_PLRBV: /* map showing only players given by a bitvector */
3278 count = 0;
3279 for (i = 0; i < MAX_NUM_PLAYER_SLOTS; i++) {
3280 if (BV_ISSET(pmapdef->player.plrbv, i)) {
3281 count++;
3282 }
3283 }
3284 break;
3285 case SHOW_ALL: /* show all players in one map */
3286 count = player_count();
3287 break;
3288 }
3289
3290 return count;
3291}
3292
3293/*
3294 * ==============================================
3295 * image colors (internal functions)
3296 * ==============================================
3297 */
3298
3299/************************************************************************/
3303{
3304 static struct rgbcolor rgb_special[] = {
3305 { 255, 0, 0, nullptr}, /* IMGCOLOR_ERROR */
3306 /* FIXME: 'ocean' and 'ground' colors are also used in the overview; the
3307 * values are defined in colors.tilespec. */
3308 { 0, 0, 200, nullptr}, /* IMGCOLOR_OCEAN */
3309 { 0, 200, 0, nullptr}, /* IMGCOLOR_GROUND */
3310 { 0, 0, 0, nullptr}, /* IMGCOLOR_BACKGROUND */
3311 { 255, 255, 255, nullptr}, /* IMGCOLOR_TEXT */
3312 };
3313
3315 &rgb_special[0]);
3316
3317 return &rgb_special[imgcolor];
3318}
3319
3320/************************************************************************/
3325static const struct rgbcolor *imgcolor_player(int plr_id)
3326{
3327 struct player *pplayer = player_by_number(plr_id);
3328
3330 fc_assert_ret_val(pplayer->rgb != nullptr,
3332
3333 return pplayer->rgb;
3334}
3335
3336/************************************************************************/
3341static const struct rgbcolor
3342 *imgcolor_terrain(const struct terrain *pterrain)
3343{
3344 fc_assert_ret_val(pterrain != nullptr, imgcolor_special(IMGCOLOR_ERROR));
3345 fc_assert_ret_val(pterrain->rgb != nullptr, imgcolor_special(IMGCOLOR_ERROR));
3346
3347 return pterrain->rgb;
3348}
void astr_free(struct astring *astr)
Definition astring.c:148
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:251
void astr_init(struct astring *astr)
Definition astring.c:139
void astr_add(struct astring *astr, const char *format,...)
Definition astring.c:271
#define str
Definition astring.c:76
static size_t astr_len(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:101
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
#define ASTRING_INIT
Definition astring.h:44
#define BV_SET_ALL(bv)
Definition bitvector.h:107
#define BV_DEFINE(name, bits)
Definition bitvector.h:140
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define BV_ISSET_ANY(vec)
Definition bitvector.h:117
const char * calendar_text(void)
Definition calendar.c:142
struct canvas int int int int struct sprite *sprite struct canvas struct color * pcolor
Definition canvas_g.h:56
char * incite_cost
Definition comments.c:76
void free_tokens(char **tokens, size_t ntokens)
Definition fc_cmdline.c:203
int get_tokens(const char *str, char **tokens, size_t num_tokens, const char *delimiterset)
Definition fc_cmdline.c:166
#define MAX_NUM_PLAYER_SLOTS
Definition fc_types.h:32
#define MAX_LEN_NAME
Definition fc_types.h:67
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
int generate_save_name(const char *format, char *buf, int buflen, const char *reason)
Definition game.c:799
struct city * owner
Definition citydlg.c:226
const char * title
Definition repodlgs.c:1314
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:192
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
#define nat_x
#define nat_y
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:384
bool map_is_empty(void)
Definition map.c:148
#define topo_has_flag(topo, flag)
Definition map.h:42
#define MAP_TO_NATIVE_POS(pnat_x, pnat_y, map_x, map_y)
Definition map.h:176
#define wrap_has_flag(wrap, flag)
Definition map.h:45
#define whole_map_iterate(_map, _tile)
Definition map.h:573
#define whole_map_iterate_end
Definition map.h:582
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:229
static bv_pixel pixel_fogofwar_hexa(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:2849
#define NUM_PIXEL
Definition mapimg.c:89
static int bvplayers_count(const struct mapdef *pmapdef)
Definition mapimg.c:3263
static bv_pixel pixel_fogofwar_rect(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:2622
#define MAPIMG_DEFAULT_IMGFORMAT
Definition mapimg.c:448
static char error_buffer[MAX_LEN_ERRORBUF]
Definition mapimg.c:467
#define NUM_MAX_MAPARGS
Definition mapimg.c:767
bool mapimg_id2str(int id, char *str, size_t str_len)
Definition mapimg.c:1312
#define SIZE_X
void mapimg_free(void)
Definition mapimg.c:558
#define MAX_LEN_ERRORBUF
Definition mapimg.c:465
#define IMG_TEXT_HEIGHT
Definition mapimg.c:365
mapimg_tile_player_func mapimg_tile_owner
Definition mapimg.c:488
static bool mapimg_test(int id)
Definition mapimg.c:1565
bool(* img_save_func)(const struct img *pimg, const char *mapimgfile)
Definition mapimg.c:416
const char * mapimg_get_format_default(void)
Definition mapimg.c:1191
bool mapimg_initialised(void)
Definition mapimg.c:1556
static bool mapimg_def2str(struct mapdef *pmapdef, char *str, size_t str_len)
Definition mapimg.c:1580
static void base_coor_hexa(struct img *pimg, int *base_x, int *base_y, int x, int y)
Definition mapimg.c:2983
bool mapimg_colortest(const char *savename, const char *path)
Definition mapimg.c:1439
#define img_toolkit_iterate(_toolkit)
Definition mapimg.c:454
static struct img * img_new(struct mapdef *mapdef, int topo, int wrap, int xsize, int ysize)
Definition mapimg.c:1874
#define magickwand_size_t
Definition mapimg.c:70
static bv_pixel pixel_city_rect(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:2563
struct mapdef * mapimg_isvalid(int id)
Definition mapimg.c:1124
static bv_pixel pixel_border_hexa(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:2888
mapimg_tile_terrain_func mapimg_tile_terrain
Definition mapimg.c:487
bool init
Definition mapimg.c:483
mapimg_tile_player_func mapimg_tile_city
Definition mapimg.c:489
static struct mapdef * mapdef_new(bool colortest)
Definition mapimg.c:1808
static bool img_save_ppm(const struct img *pimg, const char *mapimgfile)
Definition mapimg.c:2311
static void img_destroy(struct img *pimg)
Definition mapimg.c:1970
#define IMG_BORDER_HEIGHT
Definition mapimg.c:361
#define IMG_SPACER_HEIGHT
Definition mapimg.c:363
bv_pixel(* plot_func)(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:100
mapimg_tile_player_func mapimg_tile_unit
Definition mapimg.c:490
#define TILE_SIZE
Definition mapimg.c:88
static void img_plot(struct img *pimg, int x, int y, const struct rgbcolor *pcolor, const bv_pixel pixel)
Definition mapimg.c:2010
static bool img_filename(const char *mapimgfile, enum imageformat format, char *filename, size_t filename_len)
Definition mapimg.c:2386
static const struct rgbcolor * imgcolor_terrain(const struct terrain *pterrain)
Definition mapimg.c:3342
static void img_createmap(struct img *pimg)
Definition mapimg.c:2417
static const char * showname_help(enum show_player showplr)
Definition mapimg.c:585
static void mapimg_log(const char *file, const char *function, int line, const char *format,...) fc__attribute((__format__(__printf__
Definition mapimg.c:1708
void mapimg_init(mapimg_tile_known_func mapimg_tile_known, mapimg_tile_terrain_func mapimg_tile_terrain, mapimg_tile_player_func mapimg_tile_owner, mapimg_tile_player_func mapimg_tile_city, mapimg_tile_player_func mapimg_tile_unit, mapimg_plrcolor_count_func mapimg_plrcolor_count, mapimg_plrcolor_get_func mapimg_plrcolor_get)
Definition mapimg.c:506
static bv_pixel pixel_border_rect(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:2664
#define mapdef_list_iterate_end
Definition mapimg.c:354
static int img_index(const int x, const int y, const struct img *pimg)
Definition mapimg.c:1997
static struct tile_shape tile_rect
Definition mapimg.c:107
#define MAX_NUM_MAPIMG
Definition mapimg.c:310
const struct strvec * mapimg_get_format_list(void)
Definition mapimg.c:1154
mapimg_tile_known_func mapimg_tile_known
Definition mapimg.c:486
static bool img_save(const struct img *pimg, const char *mapimgfile, const char *path)
Definition mapimg.c:2046
static struct @48 mapimg
static bv_pixel pixel_city_hexa(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:2783
static bv_pixel pixel_fogofwar_isohexa(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:3083
void(* base_coor_func)(struct img *pimg, int *base_x, int *base_y, int x, int y)
Definition mapimg.c:103
#define img_toolkit_iterate_end
Definition mapimg.c:460
mapimg_plrcolor_get_func mapimg_plrcolor_get
Definition mapimg.c:492
static bv_pixel pixel_tile_isohexa(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:3002
mapimg_plrcolor_count_func mapimg_plrcolor_count
Definition mapimg.c:491
bool mapimg_define(const char *maparg, bool check)
Definition mapimg.c:769
bool mapimg_delete(int id)
Definition mapimg.c:1205
static const struct rgbcolor * imgcolor_player(int plr_id)
Definition mapimg.c:3325
#define MAPIMG_DEFAULT_IMGTOOL
Definition mapimg.c:449
int mapimg_count(void)
Definition mapimg.c:573
#define SIZE_Y
#define MAPIMG_LOG(format,...)
Definition mapimg.c:471
#define NUM_MAX_MAPOPTS
Definition mapimg.c:768
#define IMG_BORDER_WIDTH
Definition mapimg.c:362
static bv_pixel pixel_tile_hexa(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:2762
static bv_pixel pixel_city_isohexa(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:3021
img_special
Definition mapimg.c:74
@ IMGCOLOR_OCEAN
Definition mapimg.c:76
@ IMGCOLOR_BACKGROUND
Definition mapimg.c:78
@ IMGCOLOR_TEXT
Definition mapimg.c:79
@ IMGCOLOR_GROUND
Definition mapimg.c:77
@ IMGCOLOR_ERROR
Definition mapimg.c:75
static void base_coor_rect(struct img *pimg, int *base_x, int *base_y, int x, int y)
Definition mapimg.c:2745
static struct tile_shape tile_hexa
Definition mapimg.c:145
#define MAPIMG_ASSERT_RET_VAL(cond, expr)
Definition mapimg.c:473
static char * mapimg_generate_name(struct mapdef *pmapdef)
Definition mapimg.c:1735
static bv_pixel pixel_unit_rect(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:2599
static bv_pixel pixel_unit_hexa(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:2824
static void img_plot_tile(struct img *pimg, const struct tile *ptile, const struct rgbcolor *pcolor, const bv_pixel pixel)
Definition mapimg.c:2033
static void base_coor_isohexa(struct img *pimg, int *base_x, int *base_y, int x, int y)
Definition mapimg.c:3220
static const int img_toolkits_count
Definition mapimg.c:442
static void mapdef_destroy(struct mapdef *pmapdef)
Definition mapimg.c:1842
bool mapimg_create(struct mapdef *pmapdef, bool force, const char *savename, const char *path)
Definition mapimg.c:1333
#define IMG_LINE_HEIGHT
Definition mapimg.c:364
static const struct rgbcolor * imgcolor_special(enum img_special imgcolor)
Definition mapimg.c:3302
static bv_pixel pixel_border_isohexa(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:3125
#define mapdef_list_iterate(mapdef_list, pmapdef)
Definition mapimg.c:352
#define MAX_LEN_MAPARG
Definition mapimg.c:309
const char * mapimg_error(void)
Definition mapimg.c:759
#define GEN_TOOLKIT(_tool, _format_default, _formats, _save_func, _help)
Definition mapimg.c:427
static const char * img_playerstr(const struct player *pplayer)
Definition mapimg.c:2400
static struct tile_shape tile_isohexa
Definition mapimg.c:187
void mapimg_reset(void)
Definition mapimg.c:541
bool mapimg_show(int id, char *str, size_t str_len, bool detail)
Definition mapimg.c:1224
static bool mapimg_define_arg(struct mapdef *pmapdef, enum mapdef_arg arg, const char *val, bool check)
Definition mapimg.c:895
static bool mapimg_checkplayers(struct mapdef *pmapdef, bool recheck)
Definition mapimg.c:1640
static const struct toolkit * img_toolkit_get(enum imagetool tool)
Definition mapimg.c:1860
static bv_pixel pixel_unit_isohexa(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:3060
static void img_set_pixel(struct img *pimg, const int mindex, const struct rgbcolor *pcolor)
Definition mapimg.c:1982
static bv_pixel pixel_tile_rect(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.c:2544
static struct toolkit img_toolkits[]
Definition mapimg.c:430
#define NUM_MAX_FORMATARGS
Definition mapimg.c:894
char * mapimg_help(const char *cmdname)
Definition mapimg.c:603
static const char * bvplayers_str(const bv_player plrbv)
Definition mapimg.c:3240
#define MAX_LEN_MAPDEF
Definition mapimg.h:65
struct rgbcolor *(* mapimg_plrcolor_get_func)(int)
Definition mapimg.h:104
int(* mapimg_plrcolor_count_func)(void)
Definition mapimg.h:103
enum known_type(* mapimg_tile_known_func)(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.h:91
struct terrain *(* mapimg_tile_terrain_func)(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.h:95
struct player *(* mapimg_tile_player_func)(const struct tile *ptile, const struct player *pplayer, bool knowledge)
Definition mapimg.h:99
#define fc_calloc(n, esz)
Definition mem.h:38
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
int len
Definition packhand.c:128
struct player * player_by_name_prefix(const char *name, enum m_pre_result *result)
Definition player.c:927
struct player * player_by_number(const int player_id)
Definition player.c:852
int player_count(void)
Definition player.c:819
int player_slot_count(void)
Definition player.c:420
int player_number(const struct player *pplayer)
Definition player.c:839
const char * player_name(const struct player *pplayer)
Definition player.c:900
int player_index(const struct player *pplayer)
Definition player.c:831
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1417
bool gives_shared_vision(const struct player *me, const struct player *them)
Definition player.c:1497
#define players_iterate_end
Definition player.h:542
#define players_iterate(_pplayer)
Definition player.h:537
#define is_human(plr)
Definition player.h:231
bool make_dir(const char *pathname, int mode)
Definition shared.c:1779
bool path_is_absolute(const char *filename)
Definition shared.c:1884
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define DIRMODE_DEFAULT
Definition shared.h:258
#define MAX(x, y)
Definition shared.h:54
#define MAX_LEN_PATH
Definition shared.h:32
m_pre_result
Definition shared.h:213
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
void strvec_append(struct strvec *psv, const char *string)
struct strvec * strvec_new(void)
struct packet_game_info info
Definition game.h:89
Definition mapimg.c:367
struct mapdef * def
Definition mapimg.c:368
struct img::@53 imgsize
struct img::@52 mapsize
struct tile_shape * tileshape
Definition mapimg.c:373
base_coor_func base_coor
Definition mapimg.c:379
plot_func pixel_tile
Definition mapimg.c:374
int y
Definition mapimg.c:383
plot_func pixel_city
Definition mapimg.c:375
int x
Definition mapimg.c:382
char title[MAX_LEN_MAPDEF]
Definition mapimg.c:370
const struct rgbcolor ** map
Definition mapimg.c:389
int turn
Definition mapimg.c:369
plot_func pixel_fogofwar
Definition mapimg.c:377
plot_func pixel_border
Definition mapimg.c:378
plot_func pixel_unit
Definition mapimg.c:376
enum mapimg_status status
Definition mapimg.c:323
char error[MAX_LEN_MAPDEF]
Definition mapimg.c:322
int zoom
Definition mapimg.c:326
bv_player checked_plrbv
Definition mapimg.c:336
bv_player plrbv
Definition mapimg.c:334
bv_mapdef_arg args
Definition mapimg.c:340
enum imageformat format
Definition mapimg.c:324
int id
Definition mapimg.c:333
int turns
Definition mapimg.c:327
enum show_player show
Definition mapimg.c:330
bool colortest
Definition mapimg.c:341
struct mapdef::@49 player
enum imagetool tool
Definition mapimg.c:325
bool layers[MAPIMG_LAYER_COUNT]
Definition mapimg.c:328
char name[MAX_LEN_NAME]
Definition mapimg.c:332
char maparg[MAX_LEN_MAPARG]
Definition mapimg.c:321
enum borders_mode borders
bool is_alive
Definition player.h:268
struct rgbcolor * rgb
Definition player.h:312
struct rgbcolor * rgb
Definition terrain.h:154
int y[NUM_PIXEL]
Definition mapimg.c:95
int x[NUM_PIXEL]
Definition mapimg.c:94
Definition tile.h:50
Definition timing.c:81
const img_save_func img_save
Definition mapimg.c:423
enum imagetool tool
Definition mapimg.c:420
const char * help
Definition mapimg.c:424
int formats
Definition mapimg.c:422
enum imageformat format_default
Definition mapimg.c:421
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
FILE * fc_fopen(const char *filename, const char *opentype)
Definition support.c:505
#define sz_strlcpy(dest, src)
Definition support.h:195
#define fc__attribute(x)
Definition support.h:99
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define bool
Definition support.h:71
#define sz_strlcat(dest, src)
Definition support.h:196
Terrain_type_id terrain_count(void)
Definition terrain.c:120
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:158
#define is_ocean(pterrain)
Definition terrain.h:194
#define tile_index(_pt_)
Definition tile.h:89
known_type
Definition tile.h:35
@ TILE_KNOWN_UNSEEN
Definition tile.h:37
@ TILE_UNKNOWN
Definition tile.h:36
void timer_destroy(struct timer *t)
Definition timing.c:208
void timer_start(struct timer *t)
Definition timing.c:263
struct timer * timer_new(enum timer_timetype type, enum timer_use use, const char *name)
Definition timing.c:160
double timer_read_seconds(struct timer *t)
Definition timing.c:379
@ TIMER_ACTIVE
Definition timing.h:46
@ TIMER_CPU
Definition timing.h:41
@ TIMER_USER
Definition timing.h:42
#define CURRENT_TOPOLOGY
#define MAP_NATIVE_WIDTH
#define CURRENT_WRAP
#define MAP_NATIVE_HEIGHT